[Cleanup] Used scoped pointers in KeyedServiceFactory's SetTestingFactory functions.
[chromium-blink-merge.git] / chrome / browser / sessions / persistent_tab_restore_service_unittest.cc
blobcadb88b41fee58a6bd3164e35bafbdefcce5d9aa
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/sessions/persistent_tab_restore_service.h"
7 #include <string>
9 #include "base/compiler_specific.h"
10 #include "base/strings/stringprintf.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "base/threading/sequenced_worker_pool.h"
13 #include "chrome/browser/chrome_notification_types.h"
14 #include "chrome/browser/sessions/session_service.h"
15 #include "chrome/browser/sessions/session_service_factory.h"
16 #include "chrome/browser/sessions/session_service_utils.h"
17 #include "chrome/browser/sessions/tab_restore_service_factory.h"
18 #include "chrome/browser/sessions/tab_restore_service_observer.h"
19 #include "chrome/common/url_constants.h"
20 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
21 #include "chrome/test/base/chrome_render_view_test.h"
22 #include "chrome/test/base/testing_profile.h"
23 #include "components/sessions/serialized_navigation_entry_test_helper.h"
24 #include "components/sessions/session_types.h"
25 #include "content/public/browser/browser_thread.h"
26 #include "content/public/browser/navigation_controller.h"
27 #include "content/public/browser/navigation_entry.h"
28 #include "content/public/browser/notification_service.h"
29 #include "content/public/browser/notification_types.h"
30 #include "content/public/browser/web_contents.h"
31 #include "content/public/test/render_view_test.h"
32 #include "content/public/test/test_utils.h"
33 #include "content/public/test/web_contents_tester.h"
34 #include "testing/gtest/include/gtest/gtest.h"
36 typedef TabRestoreService::Tab Tab;
37 typedef TabRestoreService::Window Window;
39 using content::NavigationEntry;
40 using content::WebContentsTester;
41 using sessions::SerializedNavigationEntry;
42 using sessions::SerializedNavigationEntryTestHelper;
44 // Create subclass that overrides TimeNow so that we can control the time used
45 // for closed tabs and windows.
46 class PersistentTabRestoreTimeFactory : public TabRestoreService::TimeFactory {
47 public:
48 PersistentTabRestoreTimeFactory() : time_(base::Time::Now()) {}
50 ~PersistentTabRestoreTimeFactory() override {}
52 base::Time TimeNow() override { return time_; }
54 private:
55 base::Time time_;
58 class PersistentTabRestoreServiceTest : public ChromeRenderViewHostTestHarness {
59 public:
60 PersistentTabRestoreServiceTest()
61 : url1_("http://1"),
62 url2_("http://2"),
63 url3_("http://3"),
64 user_agent_override_(
65 "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.19"
66 " (KHTML, like Gecko) Chrome/18.0.1025.45 Safari/535.19"),
67 time_factory_(NULL) {
70 ~PersistentTabRestoreServiceTest() override {}
72 protected:
73 enum {
74 kMaxEntries = TabRestoreServiceHelper::kMaxEntries,
77 // testing::Test:
78 void SetUp() override {
79 ChromeRenderViewHostTestHarness::SetUp();
80 time_factory_ = new PersistentTabRestoreTimeFactory();
81 service_.reset(new PersistentTabRestoreService(profile(), time_factory_));
84 void TearDown() override {
85 service_->Shutdown();
86 service_.reset();
87 delete time_factory_;
88 ChromeRenderViewHostTestHarness::TearDown();
91 TabRestoreService::Entries* mutable_entries() {
92 return service_->mutable_entries();
95 void PruneEntries() {
96 service_->PruneEntries();
99 void AddThreeNavigations() {
100 // Navigate to three URLs.
101 NavigateAndCommit(url1_);
102 NavigateAndCommit(url2_);
103 NavigateAndCommit(url3_);
106 void NavigateToIndex(int index) {
107 // Navigate back. We have to do this song and dance as NavigationController
108 // isn't happy if you navigate immediately while going back.
109 controller().GoToIndex(index);
110 WebContentsTester::For(web_contents())->CommitPendingNavigation();
113 void RecreateService() {
114 // Must set service to null first so that it is destroyed before the new
115 // one is created.
116 service_->Shutdown();
117 content::RunAllBlockingPoolTasksUntilIdle();
118 service_.reset();
119 service_.reset(new PersistentTabRestoreService(profile(), time_factory_));
120 SynchronousLoadTabsFromLastSession();
123 // Adds a window with one tab and url to the profile's session service.
124 // If |pinned| is true, the tab is marked as pinned in the session service.
125 void AddWindowWithOneTabToSessionService(bool pinned) {
126 SessionService* session_service =
127 SessionServiceFactory::GetForProfile(profile());
128 SessionID tab_id;
129 SessionID window_id;
130 session_service->SetWindowType(window_id,
131 Browser::TYPE_TABBED,
132 SessionService::TYPE_NORMAL);
133 session_service->SetTabWindow(window_id, tab_id);
134 session_service->SetTabIndexInWindow(window_id, tab_id, 0);
135 session_service->SetSelectedTabInWindow(window_id, 0);
136 if (pinned)
137 session_service->SetPinnedState(window_id, tab_id, true);
138 session_service->UpdateTabNavigation(
139 window_id, tab_id,
140 SerializedNavigationEntryTestHelper::CreateNavigation(
141 url1_.spec(), "title"));
144 // Creates a SessionService and assigns it to the Profile. The SessionService
145 // is configured with a single window with a single tab pointing at url1_ by
146 // way of AddWindowWithOneTabToSessionService. If |pinned| is true, the
147 // tab is marked as pinned in the session service.
148 void CreateSessionServiceWithOneWindow(bool pinned) {
149 scoped_ptr<SessionService> session_service(new SessionService(profile()));
150 SessionServiceFactory::SetForTestProfile(profile(), session_service.Pass());
152 AddWindowWithOneTabToSessionService(pinned);
154 // Set this, otherwise previous session won't be loaded.
155 profile()->set_last_session_exited_cleanly(false);
158 void SynchronousLoadTabsFromLastSession() {
159 // Ensures that the load is complete before continuing.
160 service_->LoadTabsFromLastSession();
161 content::RunAllBlockingPoolTasksUntilIdle();
164 GURL url1_;
165 GURL url2_;
166 GURL url3_;
167 std::string user_agent_override_;
168 scoped_ptr<PersistentTabRestoreService> service_;
169 PersistentTabRestoreTimeFactory* time_factory_;
172 namespace {
174 class TestTabRestoreServiceObserver : public TabRestoreServiceObserver {
175 public:
176 TestTabRestoreServiceObserver() : got_loaded_(false) {}
178 void clear_got_loaded() { got_loaded_ = false; }
179 bool got_loaded() const { return got_loaded_; }
181 // TabRestoreServiceObserver:
182 void TabRestoreServiceChanged(TabRestoreService* service) override {}
183 void TabRestoreServiceDestroyed(TabRestoreService* service) override {}
184 void TabRestoreServiceLoaded(TabRestoreService* service) override {
185 got_loaded_ = true;
188 private:
189 // Was TabRestoreServiceLoaded() invoked?
190 bool got_loaded_;
192 DISALLOW_COPY_AND_ASSIGN(TestTabRestoreServiceObserver);
195 } // namespace
197 TEST_F(PersistentTabRestoreServiceTest, Basic) {
198 AddThreeNavigations();
200 // Have the service record the tab.
201 service_->CreateHistoricalTab(web_contents(), -1);
203 // Make sure an entry was created.
204 ASSERT_EQ(1U, service_->entries().size());
206 // Make sure the entry matches.
207 TabRestoreService::Entry* entry = service_->entries().front();
208 ASSERT_EQ(TabRestoreService::TAB, entry->type);
209 Tab* tab = static_cast<Tab*>(entry);
210 EXPECT_FALSE(tab->pinned);
211 EXPECT_TRUE(tab->extension_app_id.empty());
212 ASSERT_EQ(3U, tab->navigations.size());
213 EXPECT_TRUE(url1_ == tab->navigations[0].virtual_url());
214 EXPECT_TRUE(url2_ == tab->navigations[1].virtual_url());
215 EXPECT_TRUE(url3_ == tab->navigations[2].virtual_url());
216 EXPECT_EQ("", tab->user_agent_override);
217 EXPECT_EQ(2, tab->current_navigation_index);
218 EXPECT_EQ(time_factory_->TimeNow().ToInternalValue(),
219 tab->timestamp.ToInternalValue());
221 NavigateToIndex(1);
223 // And check again, but set the user agent override this time.
224 web_contents()->SetUserAgentOverride(user_agent_override_);
225 service_->CreateHistoricalTab(web_contents(), -1);
227 // There should be two entries now.
228 ASSERT_EQ(2U, service_->entries().size());
230 // Make sure the entry matches.
231 entry = service_->entries().front();
232 ASSERT_EQ(TabRestoreService::TAB, entry->type);
233 tab = static_cast<Tab*>(entry);
234 EXPECT_FALSE(tab->pinned);
235 ASSERT_EQ(3U, tab->navigations.size());
236 EXPECT_EQ(url1_, tab->navigations[0].virtual_url());
237 EXPECT_EQ(url2_, tab->navigations[1].virtual_url());
238 EXPECT_EQ(url3_, tab->navigations[2].virtual_url());
239 EXPECT_EQ(user_agent_override_, tab->user_agent_override);
240 EXPECT_EQ(1, tab->current_navigation_index);
241 EXPECT_EQ(time_factory_->TimeNow().ToInternalValue(),
242 tab->timestamp.ToInternalValue());
245 // Make sure TabRestoreService doesn't create an entry for a tab with no
246 // navigations.
247 TEST_F(PersistentTabRestoreServiceTest, DontCreateEmptyTab) {
248 service_->CreateHistoricalTab(web_contents(), -1);
249 EXPECT_TRUE(service_->entries().empty());
252 // Tests restoring a single tab.
253 TEST_F(PersistentTabRestoreServiceTest, Restore) {
254 AddThreeNavigations();
256 // Have the service record the tab.
257 service_->CreateHistoricalTab(web_contents(), -1);
259 // Recreate the service and have it load the tabs.
260 RecreateService();
262 // One entry should be created.
263 ASSERT_EQ(1U, service_->entries().size());
265 // And verify the entry.
266 PersistentTabRestoreService::Entry* entry = service_->entries().front();
267 ASSERT_EQ(TabRestoreService::TAB, entry->type);
268 Tab* tab = static_cast<Tab*>(entry);
269 EXPECT_FALSE(tab->pinned);
270 ASSERT_EQ(3U, tab->navigations.size());
271 EXPECT_TRUE(url1_ == tab->navigations[0].virtual_url());
272 EXPECT_TRUE(url2_ == tab->navigations[1].virtual_url());
273 EXPECT_TRUE(url3_ == tab->navigations[2].virtual_url());
274 EXPECT_EQ(2, tab->current_navigation_index);
275 EXPECT_EQ(time_factory_->TimeNow().ToInternalValue(),
276 tab->timestamp.ToInternalValue());
279 // Tests restoring a single pinned tab.
280 TEST_F(PersistentTabRestoreServiceTest, RestorePinnedAndApp) {
281 AddThreeNavigations();
283 // Have the service record the tab.
284 service_->CreateHistoricalTab(web_contents(), -1);
286 // One entry should be created.
287 ASSERT_EQ(1U, service_->entries().size());
289 // We have to explicitly mark the tab as pinned as there is no browser for
290 // these tests.
291 TabRestoreService::Entry* entry = service_->entries().front();
292 ASSERT_EQ(TabRestoreService::TAB, entry->type);
293 Tab* tab = static_cast<Tab*>(entry);
294 tab->pinned = true;
295 const std::string extension_app_id("test");
296 tab->extension_app_id = extension_app_id;
298 // Recreate the service and have it load the tabs.
299 RecreateService();
301 // One entry should be created.
302 ASSERT_EQ(1U, service_->entries().size());
304 // And verify the entry.
305 entry = service_->entries().front();
306 ASSERT_EQ(TabRestoreService::TAB, entry->type);
307 tab = static_cast<Tab*>(entry);
308 EXPECT_TRUE(tab->pinned);
309 ASSERT_EQ(3U, tab->navigations.size());
310 EXPECT_TRUE(url1_ == tab->navigations[0].virtual_url());
311 EXPECT_TRUE(url2_ == tab->navigations[1].virtual_url());
312 EXPECT_TRUE(url3_ == tab->navigations[2].virtual_url());
313 EXPECT_EQ(2, tab->current_navigation_index);
314 EXPECT_TRUE(extension_app_id == tab->extension_app_id);
317 // Make sure we persist entries to disk that have post data.
318 TEST_F(PersistentTabRestoreServiceTest, DontPersistPostData) {
319 AddThreeNavigations();
320 controller().GetEntryAtIndex(0)->SetHasPostData(true);
321 controller().GetEntryAtIndex(1)->SetHasPostData(true);
322 controller().GetEntryAtIndex(2)->SetHasPostData(true);
324 // Have the service record the tab.
325 service_->CreateHistoricalTab(web_contents(), -1);
326 ASSERT_EQ(1U, service_->entries().size());
328 // Recreate the service and have it load the tabs.
329 RecreateService();
331 // One entry should be created.
332 ASSERT_EQ(1U, service_->entries().size());
334 const TabRestoreService::Entry* restored_entry = service_->entries().front();
335 ASSERT_EQ(TabRestoreService::TAB, restored_entry->type);
337 const Tab* restored_tab =
338 static_cast<const Tab*>(restored_entry);
339 // There should be 3 navs.
340 ASSERT_EQ(3U, restored_tab->navigations.size());
341 EXPECT_EQ(time_factory_->TimeNow().ToInternalValue(),
342 restored_tab->timestamp.ToInternalValue());
345 // Make sure we don't persist entries to disk that have post data. This
346 // differs from DontPersistPostData1 in that all the navigations have post
347 // data, so that nothing should be persisted.
348 TEST_F(PersistentTabRestoreServiceTest, DontLoadTwice) {
349 AddThreeNavigations();
351 // Have the service record the tab.
352 service_->CreateHistoricalTab(web_contents(), -1);
353 ASSERT_EQ(1U, service_->entries().size());
355 // Recreate the service and have it load the tabs.
356 RecreateService();
358 SynchronousLoadTabsFromLastSession();
360 // There should only be one entry.
361 ASSERT_EQ(1U, service_->entries().size());
364 // Makes sure we load the previous session as necessary.
365 TEST_F(PersistentTabRestoreServiceTest, LoadPreviousSession) {
366 CreateSessionServiceWithOneWindow(false);
368 SessionServiceFactory::GetForProfile(profile())->
369 MoveCurrentSessionToLastSession();
371 EXPECT_FALSE(service_->IsLoaded());
373 TestTabRestoreServiceObserver observer;
374 service_->AddObserver(&observer);
375 SynchronousLoadTabsFromLastSession();
376 EXPECT_TRUE(observer.got_loaded());
377 service_->RemoveObserver(&observer);
379 // Make sure we get back one entry with one tab whose url is url1.
380 ASSERT_EQ(1U, service_->entries().size());
381 TabRestoreService::Entry* entry2 = service_->entries().front();
382 ASSERT_EQ(TabRestoreService::WINDOW, entry2->type);
383 TabRestoreService::Window* window =
384 static_cast<TabRestoreService::Window*>(entry2);
385 ASSERT_EQ(1U, window->tabs.size());
386 EXPECT_EQ(0, window->timestamp.ToInternalValue());
387 EXPECT_EQ(0, window->selected_tab_index);
388 ASSERT_EQ(1U, window->tabs[0].navigations.size());
389 EXPECT_EQ(0, window->tabs[0].current_navigation_index);
390 EXPECT_EQ(0, window->tabs[0].timestamp.ToInternalValue());
391 EXPECT_TRUE(url1_ == window->tabs[0].navigations[0].virtual_url());
394 // Makes sure we don't attempt to load previous sessions after a restore.
395 TEST_F(PersistentTabRestoreServiceTest, DontLoadAfterRestore) {
396 CreateSessionServiceWithOneWindow(false);
398 SessionServiceFactory::GetForProfile(profile())->
399 MoveCurrentSessionToLastSession();
401 profile()->set_restored_last_session(true);
403 SynchronousLoadTabsFromLastSession();
405 // Because we restored a session PersistentTabRestoreService shouldn't load
406 // the tabs.
407 ASSERT_EQ(0U, service_->entries().size());
410 // Makes sure we don't attempt to load previous sessions after a clean exit.
411 TEST_F(PersistentTabRestoreServiceTest, DontLoadAfterCleanExit) {
412 CreateSessionServiceWithOneWindow(false);
414 SessionServiceFactory::GetForProfile(profile())->
415 MoveCurrentSessionToLastSession();
417 profile()->set_last_session_exited_cleanly(true);
419 SynchronousLoadTabsFromLastSession();
421 ASSERT_EQ(0U, service_->entries().size());
424 TEST_F(PersistentTabRestoreServiceTest, LoadPreviousSessionAndTabs) {
425 CreateSessionServiceWithOneWindow(false);
427 SessionServiceFactory::GetForProfile(profile())->
428 MoveCurrentSessionToLastSession();
430 AddThreeNavigations();
432 service_->CreateHistoricalTab(web_contents(), -1);
434 RecreateService();
436 // We should get back two entries, one from the previous session and one from
437 // the tab restore service. The previous session entry should be first.
438 ASSERT_EQ(2U, service_->entries().size());
439 // The first entry should come from the session service.
440 TabRestoreService::Entry* entry = service_->entries().front();
441 ASSERT_EQ(TabRestoreService::WINDOW, entry->type);
442 TabRestoreService::Window* window =
443 static_cast<TabRestoreService::Window*>(entry);
444 ASSERT_EQ(1U, window->tabs.size());
445 EXPECT_EQ(0, window->selected_tab_index);
446 EXPECT_EQ(0, window->timestamp.ToInternalValue());
447 ASSERT_EQ(1U, window->tabs[0].navigations.size());
448 EXPECT_EQ(0, window->tabs[0].current_navigation_index);
449 EXPECT_EQ(0, window->tabs[0].timestamp.ToInternalValue());
450 EXPECT_TRUE(url1_ == window->tabs[0].navigations[0].virtual_url());
452 // Then the closed tab.
453 entry = *(++service_->entries().begin());
454 ASSERT_EQ(TabRestoreService::TAB, entry->type);
455 Tab* tab = static_cast<Tab*>(entry);
456 ASSERT_FALSE(tab->pinned);
457 ASSERT_EQ(3U, tab->navigations.size());
458 EXPECT_EQ(2, tab->current_navigation_index);
459 EXPECT_EQ(time_factory_->TimeNow().ToInternalValue(),
460 tab->timestamp.ToInternalValue());
461 EXPECT_TRUE(url1_ == tab->navigations[0].virtual_url());
462 EXPECT_TRUE(url2_ == tab->navigations[1].virtual_url());
463 EXPECT_TRUE(url3_ == tab->navigations[2].virtual_url());
466 // Make sure pinned state is correctly loaded from session service.
467 TEST_F(PersistentTabRestoreServiceTest, LoadPreviousSessionAndTabsPinned) {
468 CreateSessionServiceWithOneWindow(true);
470 SessionServiceFactory::GetForProfile(profile())->
471 MoveCurrentSessionToLastSession();
473 AddThreeNavigations();
475 service_->CreateHistoricalTab(web_contents(), -1);
477 RecreateService();
479 // We should get back two entries, one from the previous session and one from
480 // the tab restore service. The previous session entry should be first.
481 ASSERT_EQ(2U, service_->entries().size());
482 // The first entry should come from the session service.
483 TabRestoreService::Entry* entry = service_->entries().front();
484 ASSERT_EQ(TabRestoreService::WINDOW, entry->type);
485 TabRestoreService::Window* window =
486 static_cast<TabRestoreService::Window*>(entry);
487 ASSERT_EQ(1U, window->tabs.size());
488 EXPECT_EQ(0, window->selected_tab_index);
489 EXPECT_TRUE(window->tabs[0].pinned);
490 ASSERT_EQ(1U, window->tabs[0].navigations.size());
491 EXPECT_EQ(0, window->tabs[0].current_navigation_index);
492 EXPECT_TRUE(url1_ == window->tabs[0].navigations[0].virtual_url());
494 // Then the closed tab.
495 entry = *(++service_->entries().begin());
496 ASSERT_EQ(TabRestoreService::TAB, entry->type);
497 Tab* tab = static_cast<Tab*>(entry);
498 ASSERT_FALSE(tab->pinned);
499 ASSERT_EQ(3U, tab->navigations.size());
500 EXPECT_EQ(2, tab->current_navigation_index);
501 EXPECT_TRUE(url1_ == tab->navigations[0].virtual_url());
502 EXPECT_TRUE(url2_ == tab->navigations[1].virtual_url());
503 EXPECT_TRUE(url3_ == tab->navigations[2].virtual_url());
506 // Creates kMaxEntries + 1 windows in the session service and makes sure we only
507 // get back kMaxEntries on restore.
508 TEST_F(PersistentTabRestoreServiceTest, ManyWindowsInSessionService) {
509 CreateSessionServiceWithOneWindow(false);
511 for (size_t i = 0; i < kMaxEntries; ++i)
512 AddWindowWithOneTabToSessionService(false);
514 SessionServiceFactory::GetForProfile(profile())->
515 MoveCurrentSessionToLastSession();
517 AddThreeNavigations();
519 service_->CreateHistoricalTab(web_contents(), -1);
521 RecreateService();
523 // We should get back kMaxEntries entries. We added more, but
524 // TabRestoreService only allows up to kMaxEntries.
525 ASSERT_EQ(kMaxEntries, service_->entries().size());
527 // The first entry should come from the session service.
528 TabRestoreService::Entry* entry = service_->entries().front();
529 ASSERT_EQ(TabRestoreService::WINDOW, entry->type);
530 TabRestoreService::Window* window =
531 static_cast<TabRestoreService::Window*>(entry);
532 ASSERT_EQ(1U, window->tabs.size());
533 EXPECT_EQ(0, window->selected_tab_index);
534 EXPECT_EQ(0, window->timestamp.ToInternalValue());
535 ASSERT_EQ(1U, window->tabs[0].navigations.size());
536 EXPECT_EQ(0, window->tabs[0].current_navigation_index);
537 EXPECT_EQ(0, window->tabs[0].timestamp.ToInternalValue());
538 EXPECT_TRUE(url1_ == window->tabs[0].navigations[0].virtual_url());
541 // Makes sure we restore timestamps correctly.
542 TEST_F(PersistentTabRestoreServiceTest, TimestampSurvivesRestore) {
543 base::Time tab_timestamp(base::Time::FromInternalValue(123456789));
545 AddThreeNavigations();
547 // Have the service record the tab.
548 service_->CreateHistoricalTab(web_contents(), -1);
550 // Make sure an entry was created.
551 ASSERT_EQ(1U, service_->entries().size());
553 // Make sure the entry matches.
554 std::vector<SerializedNavigationEntry> old_navigations;
556 // |entry|/|tab| doesn't survive after RecreateService().
557 TabRestoreService::Entry* entry = service_->entries().front();
558 ASSERT_EQ(TabRestoreService::TAB, entry->type);
559 Tab* tab = static_cast<Tab*>(entry);
560 tab->timestamp = tab_timestamp;
561 old_navigations = tab->navigations;
564 EXPECT_EQ(3U, old_navigations.size());
565 for (size_t i = 0; i < old_navigations.size(); ++i) {
566 EXPECT_FALSE(old_navigations[i].timestamp().is_null());
569 // Set this, otherwise previous session won't be loaded.
570 profile()->set_last_session_exited_cleanly(false);
572 RecreateService();
574 // One entry should be created.
575 ASSERT_EQ(1U, service_->entries().size());
577 // And verify the entry.
578 TabRestoreService::Entry* restored_entry = service_->entries().front();
579 ASSERT_EQ(TabRestoreService::TAB, restored_entry->type);
580 Tab* restored_tab =
581 static_cast<Tab*>(restored_entry);
582 EXPECT_EQ(tab_timestamp.ToInternalValue(),
583 restored_tab->timestamp.ToInternalValue());
584 ASSERT_EQ(old_navigations.size(), restored_tab->navigations.size());
585 for (size_t i = 0; i < restored_tab->navigations.size(); ++i) {
586 EXPECT_EQ(old_navigations[i].timestamp(),
587 restored_tab->navigations[i].timestamp());
591 // Makes sure we restore status codes correctly.
592 TEST_F(PersistentTabRestoreServiceTest, StatusCodesSurviveRestore) {
593 AddThreeNavigations();
595 // Have the service record the tab.
596 service_->CreateHistoricalTab(web_contents(), -1);
598 // Make sure an entry was created.
599 ASSERT_EQ(1U, service_->entries().size());
601 // Make sure the entry matches.
602 std::vector<sessions::SerializedNavigationEntry> old_navigations;
604 // |entry|/|tab| doesn't survive after RecreateService().
605 TabRestoreService::Entry* entry = service_->entries().front();
606 ASSERT_EQ(TabRestoreService::TAB, entry->type);
607 Tab* tab = static_cast<Tab*>(entry);
608 old_navigations = tab->navigations;
611 EXPECT_EQ(3U, old_navigations.size());
612 for (size_t i = 0; i < old_navigations.size(); ++i) {
613 EXPECT_EQ(200, old_navigations[i].http_status_code());
616 // Set this, otherwise previous session won't be loaded.
617 profile()->set_last_session_exited_cleanly(false);
619 RecreateService();
621 // One entry should be created.
622 ASSERT_EQ(1U, service_->entries().size());
624 // And verify the entry.
625 TabRestoreService::Entry* restored_entry = service_->entries().front();
626 ASSERT_EQ(TabRestoreService::TAB, restored_entry->type);
627 Tab* restored_tab =
628 static_cast<Tab*>(restored_entry);
629 ASSERT_EQ(old_navigations.size(), restored_tab->navigations.size());
630 for (size_t i = 0; i < restored_tab->navigations.size(); ++i) {
631 EXPECT_EQ(200, restored_tab->navigations[i].http_status_code());
635 TEST_F(PersistentTabRestoreServiceTest, PruneEntries) {
636 service_->ClearEntries();
637 ASSERT_TRUE(service_->entries().empty());
639 const size_t max_entries = kMaxEntries;
640 for (size_t i = 0; i < max_entries + 5; i++) {
641 SerializedNavigationEntry navigation =
642 SerializedNavigationEntryTestHelper::CreateNavigation(
643 base::StringPrintf("http://%d", static_cast<int>(i)),
644 base::StringPrintf("%d", static_cast<int>(i)));
646 Tab* tab = new Tab();
647 tab->navigations.push_back(navigation);
648 tab->current_navigation_index = 0;
650 mutable_entries()->push_back(tab);
653 // Only keep kMaxEntries around.
654 EXPECT_EQ(max_entries + 5, service_->entries().size());
655 PruneEntries();
656 EXPECT_EQ(max_entries, service_->entries().size());
657 // Pruning again does nothing.
658 PruneEntries();
659 EXPECT_EQ(max_entries, service_->entries().size());
661 // Prune older first.
662 const char kRecentUrl[] = "http://recent";
663 SerializedNavigationEntry navigation =
664 SerializedNavigationEntryTestHelper::CreateNavigation(kRecentUrl,
665 "Most recent");
666 Tab* tab = new Tab();
667 tab->navigations.push_back(navigation);
668 tab->current_navigation_index = 0;
669 mutable_entries()->push_front(tab);
670 EXPECT_EQ(max_entries + 1, service_->entries().size());
671 PruneEntries();
672 EXPECT_EQ(max_entries, service_->entries().size());
673 EXPECT_EQ(GURL(kRecentUrl),
674 static_cast<Tab*>(service_->entries().front())->
675 navigations[0].virtual_url());
677 // Ignore NTPs.
678 navigation = SerializedNavigationEntryTestHelper::CreateNavigation(
679 chrome::kChromeUINewTabURL, "New tab");
681 tab = new Tab();
682 tab->navigations.push_back(navigation);
683 tab->current_navigation_index = 0;
684 mutable_entries()->push_front(tab);
686 EXPECT_EQ(max_entries + 1, service_->entries().size());
687 PruneEntries();
688 EXPECT_EQ(max_entries, service_->entries().size());
689 EXPECT_EQ(GURL(kRecentUrl),
690 static_cast<Tab*>(service_->entries().front())->
691 navigations[0].virtual_url());
693 // Don't prune pinned NTPs.
694 tab = new Tab();
695 tab->pinned = true;
696 tab->current_navigation_index = 0;
697 tab->navigations.push_back(navigation);
698 mutable_entries()->push_front(tab);
699 EXPECT_EQ(max_entries + 1, service_->entries().size());
700 PruneEntries();
701 EXPECT_EQ(max_entries, service_->entries().size());
702 EXPECT_EQ(GURL(chrome::kChromeUINewTabURL),
703 static_cast<Tab*>(service_->entries().front())->
704 navigations[0].virtual_url());
706 // Don't prune NTPs that have multiple navigations.
707 // (Erase the last NTP first.)
708 delete service_->entries().front();
709 mutable_entries()->erase(mutable_entries()->begin());
710 tab = new Tab();
711 tab->current_navigation_index = 1;
712 tab->navigations.push_back(navigation);
713 tab->navigations.push_back(navigation);
714 mutable_entries()->push_front(tab);
715 EXPECT_EQ(max_entries, service_->entries().size());
716 PruneEntries();
717 EXPECT_EQ(max_entries, service_->entries().size());
718 EXPECT_EQ(GURL(chrome::kChromeUINewTabURL),
719 static_cast<Tab*>(service_->entries().front())->
720 navigations[1].virtual_url());
723 // Regression test for crbug.com/106082
724 TEST_F(PersistentTabRestoreServiceTest, PruneIsCalled) {
725 CreateSessionServiceWithOneWindow(false);
727 SessionServiceFactory::GetForProfile(profile())->
728 MoveCurrentSessionToLastSession();
730 profile()->set_restored_last_session(true);
732 const size_t max_entries = kMaxEntries;
733 for (size_t i = 0; i < max_entries + 5; i++) {
734 NavigateAndCommit(
735 GURL(base::StringPrintf("http://%d", static_cast<int>(i))));
736 service_->CreateHistoricalTab(web_contents(), -1);
739 EXPECT_EQ(max_entries, service_->entries().size());
740 // This should not crash.
741 SynchronousLoadTabsFromLastSession();
742 EXPECT_EQ(max_entries, service_->entries().size());
745 // Makes sure invoking LoadTabsFromLastSession() when the max number of entries
746 // have been added results in IsLoaded() returning true and notifies observers.
747 TEST_F(PersistentTabRestoreServiceTest, GoToLoadedWhenHaveMaxEntries) {
748 const size_t max_entries = kMaxEntries;
749 for (size_t i = 0; i < max_entries + 5; i++) {
750 NavigateAndCommit(
751 GURL(base::StringPrintf("http://%d", static_cast<int>(i))));
752 service_->CreateHistoricalTab(web_contents(), -1);
755 EXPECT_FALSE(service_->IsLoaded());
756 TestTabRestoreServiceObserver observer;
757 service_->AddObserver(&observer);
758 EXPECT_EQ(max_entries, service_->entries().size());
759 SynchronousLoadTabsFromLastSession();
760 EXPECT_TRUE(observer.got_loaded());
761 EXPECT_TRUE(service_->IsLoaded());
762 service_->RemoveObserver(&observer);