Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / sessions / persistent_tab_restore_service_unittest.cc
bloba715fcd9b0e99a4ec7e24782b528b6b214408714
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 "base/compiler_specific.h"
8 #include "base/run_loop.h"
9 #include "base/strings/stringprintf.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/threading/sequenced_worker_pool.h"
12 #include "chrome/browser/chrome_notification_types.h"
13 #include "chrome/browser/sessions/session_service.h"
14 #include "chrome/browser/sessions/session_service_factory.h"
15 #include "chrome/browser/sessions/session_types.h"
16 #include "chrome/browser/sessions/tab_restore_service_factory.h"
17 #include "chrome/browser/sessions/tab_restore_service_observer.h"
18 #include "chrome/common/url_constants.h"
19 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
20 #include "chrome/test/base/chrome_render_view_test.h"
21 #include "chrome/test/base/testing_profile.h"
22 #include "components/sessions/serialized_navigation_entry_test_helper.h"
23 #include "content/public/browser/browser_thread.h"
24 #include "content/public/browser/navigation_controller.h"
25 #include "content/public/browser/navigation_entry.h"
26 #include "content/public/browser/notification_service.h"
27 #include "content/public/browser/notification_types.h"
28 #include "content/public/browser/web_contents.h"
29 #include "content/public/test/render_view_test.h"
30 #include "content/public/test/web_contents_tester.h"
31 #include "testing/gtest/include/gtest/gtest.h"
33 typedef TabRestoreService::Tab Tab;
34 typedef TabRestoreService::Window Window;
36 using content::NavigationEntry;
37 using content::WebContentsTester;
38 using sessions::SerializedNavigationEntry;
39 using sessions::SerializedNavigationEntryTestHelper;
41 // Create subclass that overrides TimeNow so that we can control the time used
42 // for closed tabs and windows.
43 class PersistentTabRestoreTimeFactory : public TabRestoreService::TimeFactory {
44 public:
45 PersistentTabRestoreTimeFactory() : time_(base::Time::Now()) {}
47 virtual ~PersistentTabRestoreTimeFactory() {}
49 virtual base::Time TimeNow() OVERRIDE {
50 return time_;
53 private:
54 base::Time time_;
57 class PersistentTabRestoreServiceTest : public ChromeRenderViewHostTestHarness {
58 public:
59 PersistentTabRestoreServiceTest()
60 : url1_("http://1"),
61 url2_("http://2"),
62 url3_("http://3"),
63 user_agent_override_(
64 "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.19"
65 " (KHTML, like Gecko) Chrome/18.0.1025.45 Safari/535.19"),
66 time_factory_(NULL) {
69 virtual ~PersistentTabRestoreServiceTest() {
72 protected:
73 enum {
74 kMaxEntries = TabRestoreServiceHelper::kMaxEntries,
77 // testing::Test:
78 virtual void SetUp() OVERRIDE {
79 ChromeRenderViewHostTestHarness::SetUp();
80 time_factory_ = new PersistentTabRestoreTimeFactory();
81 service_.reset(new PersistentTabRestoreService(profile(), time_factory_));
84 virtual 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::BrowserThread::GetBlockingPool()->FlushForTesting();
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(
131 window_id, Browser::TYPE_TABBED, SessionService::TYPE_NORMAL);
132 session_service->SetTabWindow(window_id, tab_id);
133 session_service->SetTabIndexInWindow(window_id, tab_id, 0);
134 session_service->SetSelectedTabInWindow(window_id, 0);
135 if (pinned)
136 session_service->SetPinnedState(window_id, tab_id, true);
137 session_service->UpdateTabNavigation(
138 window_id, tab_id,
139 SerializedNavigationEntryTestHelper::CreateNavigation(
140 url1_.spec(), "title"));
143 // Creates a SessionService and assigns it to the Profile. The SessionService
144 // is configured with a single window with a single tab pointing at url1_ by
145 // way of AddWindowWithOneTabToSessionService. If |pinned| is true, the
146 // tab is marked as pinned in the session service.
147 void CreateSessionServiceWithOneWindow(bool pinned) {
148 // The profile takes ownership of this.
149 SessionService* session_service = new SessionService(profile());
150 SessionServiceFactory::SetForTestProfile(profile(), session_service);
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::BrowserThread::GetBlockingPool()->FlushForTesting();
162 base::RunLoop().RunUntilIdle();
163 content::BrowserThread::GetBlockingPool()->FlushForTesting();
166 GURL url1_;
167 GURL url2_;
168 GURL url3_;
169 std::string user_agent_override_;
170 scoped_ptr<PersistentTabRestoreService> service_;
171 PersistentTabRestoreTimeFactory* time_factory_;
174 namespace {
176 class TestTabRestoreServiceObserver : public TabRestoreServiceObserver {
177 public:
178 TestTabRestoreServiceObserver() : got_loaded_(false) {}
180 void clear_got_loaded() { got_loaded_ = false; }
181 bool got_loaded() const { return got_loaded_; }
183 // TabRestoreServiceObserver:
184 virtual void TabRestoreServiceChanged(TabRestoreService* service) OVERRIDE {
186 virtual void TabRestoreServiceDestroyed(TabRestoreService* service) OVERRIDE {
188 virtual void TabRestoreServiceLoaded(TabRestoreService* service) OVERRIDE {
189 got_loaded_ = true;
192 private:
193 // Was TabRestoreServiceLoaded() invoked?
194 bool got_loaded_;
196 DISALLOW_COPY_AND_ASSIGN(TestTabRestoreServiceObserver);
199 } // namespace
201 TEST_F(PersistentTabRestoreServiceTest, Basic) {
202 AddThreeNavigations();
204 // Have the service record the tab.
205 service_->CreateHistoricalTab(web_contents(), -1);
207 // Make sure an entry was created.
208 ASSERT_EQ(1U, service_->entries().size());
210 // Make sure the entry matches.
211 TabRestoreService::Entry* entry = service_->entries().front();
212 ASSERT_EQ(TabRestoreService::TAB, entry->type);
213 Tab* tab = static_cast<Tab*>(entry);
214 EXPECT_FALSE(tab->pinned);
215 EXPECT_TRUE(tab->extension_app_id.empty());
216 ASSERT_EQ(3U, tab->navigations.size());
217 EXPECT_TRUE(url1_ == tab->navigations[0].virtual_url());
218 EXPECT_TRUE(url2_ == tab->navigations[1].virtual_url());
219 EXPECT_TRUE(url3_ == tab->navigations[2].virtual_url());
220 EXPECT_EQ("", tab->user_agent_override);
221 EXPECT_EQ(2, tab->current_navigation_index);
222 EXPECT_EQ(time_factory_->TimeNow().ToInternalValue(),
223 tab->timestamp.ToInternalValue());
225 NavigateToIndex(1);
227 // And check again, but set the user agent override this time.
228 web_contents()->SetUserAgentOverride(user_agent_override_);
229 service_->CreateHistoricalTab(web_contents(), -1);
231 // There should be two entries now.
232 ASSERT_EQ(2U, service_->entries().size());
234 // Make sure the entry matches.
235 entry = service_->entries().front();
236 ASSERT_EQ(TabRestoreService::TAB, entry->type);
237 tab = static_cast<Tab*>(entry);
238 EXPECT_FALSE(tab->pinned);
239 ASSERT_EQ(3U, tab->navigations.size());
240 EXPECT_EQ(url1_, tab->navigations[0].virtual_url());
241 EXPECT_EQ(url2_, tab->navigations[1].virtual_url());
242 EXPECT_EQ(url3_, tab->navigations[2].virtual_url());
243 EXPECT_EQ(user_agent_override_, tab->user_agent_override);
244 EXPECT_EQ(1, tab->current_navigation_index);
245 EXPECT_EQ(time_factory_->TimeNow().ToInternalValue(),
246 tab->timestamp.ToInternalValue());
249 // Make sure TabRestoreService doesn't create an entry for a tab with no
250 // navigations.
251 TEST_F(PersistentTabRestoreServiceTest, DontCreateEmptyTab) {
252 service_->CreateHistoricalTab(web_contents(), -1);
253 EXPECT_TRUE(service_->entries().empty());
256 // Tests restoring a single tab.
257 TEST_F(PersistentTabRestoreServiceTest, Restore) {
258 AddThreeNavigations();
260 // Have the service record the tab.
261 service_->CreateHistoricalTab(web_contents(), -1);
263 // Recreate the service and have it load the tabs.
264 RecreateService();
266 // One entry should be created.
267 ASSERT_EQ(1U, service_->entries().size());
269 // And verify the entry.
270 PersistentTabRestoreService::Entry* entry = service_->entries().front();
271 ASSERT_EQ(TabRestoreService::TAB, entry->type);
272 Tab* tab = static_cast<Tab*>(entry);
273 EXPECT_FALSE(tab->pinned);
274 ASSERT_EQ(3U, tab->navigations.size());
275 EXPECT_TRUE(url1_ == tab->navigations[0].virtual_url());
276 EXPECT_TRUE(url2_ == tab->navigations[1].virtual_url());
277 EXPECT_TRUE(url3_ == tab->navigations[2].virtual_url());
278 EXPECT_EQ(2, tab->current_navigation_index);
279 EXPECT_EQ(time_factory_->TimeNow().ToInternalValue(),
280 tab->timestamp.ToInternalValue());
283 // Tests restoring a single pinned tab.
284 TEST_F(PersistentTabRestoreServiceTest, RestorePinnedAndApp) {
285 AddThreeNavigations();
287 // Have the service record the tab.
288 service_->CreateHistoricalTab(web_contents(), -1);
290 // One entry should be created.
291 ASSERT_EQ(1U, service_->entries().size());
293 // We have to explicitly mark the tab as pinned as there is no browser for
294 // these tests.
295 TabRestoreService::Entry* entry = service_->entries().front();
296 ASSERT_EQ(TabRestoreService::TAB, entry->type);
297 Tab* tab = static_cast<Tab*>(entry);
298 tab->pinned = true;
299 const std::string extension_app_id("test");
300 tab->extension_app_id = extension_app_id;
302 // Recreate the service and have it load the tabs.
303 RecreateService();
305 // One entry should be created.
306 ASSERT_EQ(1U, service_->entries().size());
308 // And verify the entry.
309 entry = service_->entries().front();
310 ASSERT_EQ(TabRestoreService::TAB, entry->type);
311 tab = static_cast<Tab*>(entry);
312 EXPECT_TRUE(tab->pinned);
313 ASSERT_EQ(3U, tab->navigations.size());
314 EXPECT_TRUE(url1_ == tab->navigations[0].virtual_url());
315 EXPECT_TRUE(url2_ == tab->navigations[1].virtual_url());
316 EXPECT_TRUE(url3_ == tab->navigations[2].virtual_url());
317 EXPECT_EQ(2, tab->current_navigation_index);
318 EXPECT_TRUE(extension_app_id == tab->extension_app_id);
321 // Make sure we persist entries to disk that have post data.
322 TEST_F(PersistentTabRestoreServiceTest, DontPersistPostData) {
323 AddThreeNavigations();
324 controller().GetEntryAtIndex(0)->SetHasPostData(true);
325 controller().GetEntryAtIndex(1)->SetHasPostData(true);
326 controller().GetEntryAtIndex(2)->SetHasPostData(true);
328 // Have the service record the tab.
329 service_->CreateHistoricalTab(web_contents(), -1);
330 ASSERT_EQ(1U, service_->entries().size());
332 // Recreate the service and have it load the tabs.
333 RecreateService();
335 // One entry should be created.
336 ASSERT_EQ(1U, service_->entries().size());
338 const TabRestoreService::Entry* restored_entry = service_->entries().front();
339 ASSERT_EQ(TabRestoreService::TAB, restored_entry->type);
341 const Tab* restored_tab =
342 static_cast<const Tab*>(restored_entry);
343 // There should be 3 navs.
344 ASSERT_EQ(3U, restored_tab->navigations.size());
345 EXPECT_EQ(time_factory_->TimeNow().ToInternalValue(),
346 restored_tab->timestamp.ToInternalValue());
349 // Make sure we don't persist entries to disk that have post data. This
350 // differs from DontPersistPostData1 in that all the navigations have post
351 // data, so that nothing should be persisted.
352 TEST_F(PersistentTabRestoreServiceTest, DontLoadTwice) {
353 AddThreeNavigations();
355 // Have the service record the tab.
356 service_->CreateHistoricalTab(web_contents(), -1);
357 ASSERT_EQ(1U, service_->entries().size());
359 // Recreate the service and have it load the tabs.
360 RecreateService();
362 SynchronousLoadTabsFromLastSession();
364 // There should only be one entry.
365 ASSERT_EQ(1U, service_->entries().size());
368 // Makes sure we load the previous session as necessary.
369 TEST_F(PersistentTabRestoreServiceTest, LoadPreviousSession) {
370 CreateSessionServiceWithOneWindow(false);
372 SessionServiceFactory::GetForProfile(profile())->
373 MoveCurrentSessionToLastSession();
375 EXPECT_FALSE(service_->IsLoaded());
377 TestTabRestoreServiceObserver observer;
378 service_->AddObserver(&observer);
379 SynchronousLoadTabsFromLastSession();
380 EXPECT_TRUE(observer.got_loaded());
381 service_->RemoveObserver(&observer);
383 // Make sure we get back one entry with one tab whose url is url1.
384 ASSERT_EQ(1U, service_->entries().size());
385 TabRestoreService::Entry* entry2 = service_->entries().front();
386 ASSERT_EQ(TabRestoreService::WINDOW, entry2->type);
387 TabRestoreService::Window* window =
388 static_cast<TabRestoreService::Window*>(entry2);
389 ASSERT_EQ(1U, window->tabs.size());
390 EXPECT_EQ(0, window->timestamp.ToInternalValue());
391 EXPECT_EQ(0, window->selected_tab_index);
392 ASSERT_EQ(1U, window->tabs[0].navigations.size());
393 EXPECT_EQ(0, window->tabs[0].current_navigation_index);
394 EXPECT_EQ(0, window->tabs[0].timestamp.ToInternalValue());
395 EXPECT_TRUE(url1_ == window->tabs[0].navigations[0].virtual_url());
398 // Makes sure we don't attempt to load previous sessions after a restore.
399 TEST_F(PersistentTabRestoreServiceTest, DontLoadAfterRestore) {
400 CreateSessionServiceWithOneWindow(false);
402 SessionServiceFactory::GetForProfile(profile())->
403 MoveCurrentSessionToLastSession();
405 profile()->set_restored_last_session(true);
407 SynchronousLoadTabsFromLastSession();
409 // Because we restored a session PersistentTabRestoreService shouldn't load
410 // the tabs.
411 ASSERT_EQ(0U, service_->entries().size());
414 // Makes sure we don't attempt to load previous sessions after a clean exit.
415 TEST_F(PersistentTabRestoreServiceTest, DontLoadAfterCleanExit) {
416 CreateSessionServiceWithOneWindow(false);
418 SessionServiceFactory::GetForProfile(profile())->
419 MoveCurrentSessionToLastSession();
421 profile()->set_last_session_exited_cleanly(true);
423 SynchronousLoadTabsFromLastSession();
425 ASSERT_EQ(0U, service_->entries().size());
428 TEST_F(PersistentTabRestoreServiceTest, LoadPreviousSessionAndTabs) {
429 CreateSessionServiceWithOneWindow(false);
431 SessionServiceFactory::GetForProfile(profile())->
432 MoveCurrentSessionToLastSession();
434 AddThreeNavigations();
436 service_->CreateHistoricalTab(web_contents(), -1);
438 RecreateService();
440 // We should get back two entries, one from the previous session and one from
441 // the tab restore service. The previous session entry should be first.
442 ASSERT_EQ(2U, service_->entries().size());
443 // The first entry should come from the session service.
444 TabRestoreService::Entry* entry = service_->entries().front();
445 ASSERT_EQ(TabRestoreService::WINDOW, entry->type);
446 TabRestoreService::Window* window =
447 static_cast<TabRestoreService::Window*>(entry);
448 ASSERT_EQ(1U, window->tabs.size());
449 EXPECT_EQ(0, window->selected_tab_index);
450 EXPECT_EQ(0, window->timestamp.ToInternalValue());
451 ASSERT_EQ(1U, window->tabs[0].navigations.size());
452 EXPECT_EQ(0, window->tabs[0].current_navigation_index);
453 EXPECT_EQ(0, window->tabs[0].timestamp.ToInternalValue());
454 EXPECT_TRUE(url1_ == window->tabs[0].navigations[0].virtual_url());
456 // Then the closed tab.
457 entry = *(++service_->entries().begin());
458 ASSERT_EQ(TabRestoreService::TAB, entry->type);
459 Tab* tab = static_cast<Tab*>(entry);
460 ASSERT_FALSE(tab->pinned);
461 ASSERT_EQ(3U, tab->navigations.size());
462 EXPECT_EQ(2, tab->current_navigation_index);
463 EXPECT_EQ(time_factory_->TimeNow().ToInternalValue(),
464 tab->timestamp.ToInternalValue());
465 EXPECT_TRUE(url1_ == tab->navigations[0].virtual_url());
466 EXPECT_TRUE(url2_ == tab->navigations[1].virtual_url());
467 EXPECT_TRUE(url3_ == tab->navigations[2].virtual_url());
470 // Make sure pinned state is correctly loaded from session service.
471 TEST_F(PersistentTabRestoreServiceTest, LoadPreviousSessionAndTabsPinned) {
472 CreateSessionServiceWithOneWindow(true);
474 SessionServiceFactory::GetForProfile(profile())->
475 MoveCurrentSessionToLastSession();
477 AddThreeNavigations();
479 service_->CreateHistoricalTab(web_contents(), -1);
481 RecreateService();
483 // We should get back two entries, one from the previous session and one from
484 // the tab restore service. The previous session entry should be first.
485 ASSERT_EQ(2U, service_->entries().size());
486 // The first entry should come from the session service.
487 TabRestoreService::Entry* entry = service_->entries().front();
488 ASSERT_EQ(TabRestoreService::WINDOW, entry->type);
489 TabRestoreService::Window* window =
490 static_cast<TabRestoreService::Window*>(entry);
491 ASSERT_EQ(1U, window->tabs.size());
492 EXPECT_EQ(0, window->selected_tab_index);
493 EXPECT_TRUE(window->tabs[0].pinned);
494 ASSERT_EQ(1U, window->tabs[0].navigations.size());
495 EXPECT_EQ(0, window->tabs[0].current_navigation_index);
496 EXPECT_TRUE(url1_ == window->tabs[0].navigations[0].virtual_url());
498 // Then the closed tab.
499 entry = *(++service_->entries().begin());
500 ASSERT_EQ(TabRestoreService::TAB, entry->type);
501 Tab* tab = static_cast<Tab*>(entry);
502 ASSERT_FALSE(tab->pinned);
503 ASSERT_EQ(3U, tab->navigations.size());
504 EXPECT_EQ(2, tab->current_navigation_index);
505 EXPECT_TRUE(url1_ == tab->navigations[0].virtual_url());
506 EXPECT_TRUE(url2_ == tab->navigations[1].virtual_url());
507 EXPECT_TRUE(url3_ == tab->navigations[2].virtual_url());
510 // Creates kMaxEntries + 1 windows in the session service and makes sure we only
511 // get back kMaxEntries on restore.
512 TEST_F(PersistentTabRestoreServiceTest, ManyWindowsInSessionService) {
513 CreateSessionServiceWithOneWindow(false);
515 for (size_t i = 0; i < kMaxEntries; ++i)
516 AddWindowWithOneTabToSessionService(false);
518 SessionServiceFactory::GetForProfile(profile())->
519 MoveCurrentSessionToLastSession();
521 AddThreeNavigations();
523 service_->CreateHistoricalTab(web_contents(), -1);
525 RecreateService();
527 // We should get back kMaxEntries entries. We added more, but
528 // TabRestoreService only allows up to kMaxEntries.
529 ASSERT_EQ(kMaxEntries, service_->entries().size());
531 // The first entry should come from the session service.
532 TabRestoreService::Entry* entry = service_->entries().front();
533 ASSERT_EQ(TabRestoreService::WINDOW, entry->type);
534 TabRestoreService::Window* window =
535 static_cast<TabRestoreService::Window*>(entry);
536 ASSERT_EQ(1U, window->tabs.size());
537 EXPECT_EQ(0, window->selected_tab_index);
538 EXPECT_EQ(0, window->timestamp.ToInternalValue());
539 ASSERT_EQ(1U, window->tabs[0].navigations.size());
540 EXPECT_EQ(0, window->tabs[0].current_navigation_index);
541 EXPECT_EQ(0, window->tabs[0].timestamp.ToInternalValue());
542 EXPECT_TRUE(url1_ == window->tabs[0].navigations[0].virtual_url());
545 // Makes sure we restore timestamps correctly.
546 TEST_F(PersistentTabRestoreServiceTest, TimestampSurvivesRestore) {
547 base::Time tab_timestamp(base::Time::FromInternalValue(123456789));
549 AddThreeNavigations();
551 // Have the service record the tab.
552 service_->CreateHistoricalTab(web_contents(), -1);
554 // Make sure an entry was created.
555 ASSERT_EQ(1U, service_->entries().size());
557 // Make sure the entry matches.
558 std::vector<SerializedNavigationEntry> old_navigations;
560 // |entry|/|tab| doesn't survive after RecreateService().
561 TabRestoreService::Entry* entry = service_->entries().front();
562 ASSERT_EQ(TabRestoreService::TAB, entry->type);
563 Tab* tab = static_cast<Tab*>(entry);
564 tab->timestamp = tab_timestamp;
565 old_navigations = tab->navigations;
568 EXPECT_EQ(3U, old_navigations.size());
569 for (size_t i = 0; i < old_navigations.size(); ++i) {
570 EXPECT_FALSE(old_navigations[i].timestamp().is_null());
573 // Set this, otherwise previous session won't be loaded.
574 profile()->set_last_session_exited_cleanly(false);
576 RecreateService();
578 // One entry should be created.
579 ASSERT_EQ(1U, service_->entries().size());
581 // And verify the entry.
582 TabRestoreService::Entry* restored_entry = service_->entries().front();
583 ASSERT_EQ(TabRestoreService::TAB, restored_entry->type);
584 Tab* restored_tab =
585 static_cast<Tab*>(restored_entry);
586 EXPECT_EQ(tab_timestamp.ToInternalValue(),
587 restored_tab->timestamp.ToInternalValue());
588 ASSERT_EQ(old_navigations.size(), restored_tab->navigations.size());
589 for (size_t i = 0; i < restored_tab->navigations.size(); ++i) {
590 EXPECT_EQ(old_navigations[i].timestamp(),
591 restored_tab->navigations[i].timestamp());
595 // Makes sure we restore status codes correctly.
596 TEST_F(PersistentTabRestoreServiceTest, StatusCodesSurviveRestore) {
597 AddThreeNavigations();
599 // Have the service record the tab.
600 service_->CreateHistoricalTab(web_contents(), -1);
602 // Make sure an entry was created.
603 ASSERT_EQ(1U, service_->entries().size());
605 // Make sure the entry matches.
606 std::vector<sessions::SerializedNavigationEntry> old_navigations;
608 // |entry|/|tab| doesn't survive after RecreateService().
609 TabRestoreService::Entry* entry = service_->entries().front();
610 ASSERT_EQ(TabRestoreService::TAB, entry->type);
611 Tab* tab = static_cast<Tab*>(entry);
612 old_navigations = tab->navigations;
615 EXPECT_EQ(3U, old_navigations.size());
616 for (size_t i = 0; i < old_navigations.size(); ++i) {
617 EXPECT_EQ(200, old_navigations[i].http_status_code());
620 // Set this, otherwise previous session won't be loaded.
621 profile()->set_last_session_exited_cleanly(false);
623 RecreateService();
625 // One entry should be created.
626 ASSERT_EQ(1U, service_->entries().size());
628 // And verify the entry.
629 TabRestoreService::Entry* restored_entry = service_->entries().front();
630 ASSERT_EQ(TabRestoreService::TAB, restored_entry->type);
631 Tab* restored_tab =
632 static_cast<Tab*>(restored_entry);
633 ASSERT_EQ(old_navigations.size(), restored_tab->navigations.size());
634 for (size_t i = 0; i < restored_tab->navigations.size(); ++i) {
635 EXPECT_EQ(200, restored_tab->navigations[i].http_status_code());
639 TEST_F(PersistentTabRestoreServiceTest, PruneEntries) {
640 service_->ClearEntries();
641 ASSERT_TRUE(service_->entries().empty());
643 const size_t max_entries = kMaxEntries;
644 for (size_t i = 0; i < max_entries + 5; i++) {
645 SerializedNavigationEntry navigation =
646 SerializedNavigationEntryTestHelper::CreateNavigation(
647 base::StringPrintf("http://%d", static_cast<int>(i)),
648 base::StringPrintf("%d", static_cast<int>(i)));
650 Tab* tab = new Tab();
651 tab->navigations.push_back(navigation);
652 tab->current_navigation_index = 0;
654 mutable_entries()->push_back(tab);
657 // Only keep kMaxEntries around.
658 EXPECT_EQ(max_entries + 5, service_->entries().size());
659 PruneEntries();
660 EXPECT_EQ(max_entries, service_->entries().size());
661 // Pruning again does nothing.
662 PruneEntries();
663 EXPECT_EQ(max_entries, service_->entries().size());
665 // Prune older first.
666 const char kRecentUrl[] = "http://recent";
667 SerializedNavigationEntry navigation =
668 SerializedNavigationEntryTestHelper::CreateNavigation(kRecentUrl,
669 "Most recent");
670 Tab* tab = new Tab();
671 tab->navigations.push_back(navigation);
672 tab->current_navigation_index = 0;
673 mutable_entries()->push_front(tab);
674 EXPECT_EQ(max_entries + 1, service_->entries().size());
675 PruneEntries();
676 EXPECT_EQ(max_entries, service_->entries().size());
677 EXPECT_EQ(GURL(kRecentUrl),
678 static_cast<Tab*>(service_->entries().front())->
679 navigations[0].virtual_url());
681 // Ignore NTPs.
682 navigation = SerializedNavigationEntryTestHelper::CreateNavigation(
683 chrome::kChromeUINewTabURL, "New tab");
685 tab = new Tab();
686 tab->navigations.push_back(navigation);
687 tab->current_navigation_index = 0;
688 mutable_entries()->push_front(tab);
690 EXPECT_EQ(max_entries + 1, service_->entries().size());
691 PruneEntries();
692 EXPECT_EQ(max_entries, service_->entries().size());
693 EXPECT_EQ(GURL(kRecentUrl),
694 static_cast<Tab*>(service_->entries().front())->
695 navigations[0].virtual_url());
697 // Don't prune pinned NTPs.
698 tab = new Tab();
699 tab->pinned = true;
700 tab->current_navigation_index = 0;
701 tab->navigations.push_back(navigation);
702 mutable_entries()->push_front(tab);
703 EXPECT_EQ(max_entries + 1, service_->entries().size());
704 PruneEntries();
705 EXPECT_EQ(max_entries, service_->entries().size());
706 EXPECT_EQ(GURL(chrome::kChromeUINewTabURL),
707 static_cast<Tab*>(service_->entries().front())->
708 navigations[0].virtual_url());
710 // Don't prune NTPs that have multiple navigations.
711 // (Erase the last NTP first.)
712 delete service_->entries().front();
713 mutable_entries()->erase(mutable_entries()->begin());
714 tab = new Tab();
715 tab->current_navigation_index = 1;
716 tab->navigations.push_back(navigation);
717 tab->navigations.push_back(navigation);
718 mutable_entries()->push_front(tab);
719 EXPECT_EQ(max_entries, service_->entries().size());
720 PruneEntries();
721 EXPECT_EQ(max_entries, service_->entries().size());
722 EXPECT_EQ(GURL(chrome::kChromeUINewTabURL),
723 static_cast<Tab*>(service_->entries().front())->
724 navigations[1].virtual_url());
727 // Regression test for crbug.com/106082
728 TEST_F(PersistentTabRestoreServiceTest, PruneIsCalled) {
729 CreateSessionServiceWithOneWindow(false);
731 SessionServiceFactory::GetForProfile(profile())->
732 MoveCurrentSessionToLastSession();
734 profile()->set_restored_last_session(true);
736 const size_t max_entries = kMaxEntries;
737 for (size_t i = 0; i < max_entries + 5; i++) {
738 NavigateAndCommit(
739 GURL(base::StringPrintf("http://%d", static_cast<int>(i))));
740 service_->CreateHistoricalTab(web_contents(), -1);
743 EXPECT_EQ(max_entries, service_->entries().size());
744 // This should not crash.
745 SynchronousLoadTabsFromLastSession();
746 EXPECT_EQ(max_entries, service_->entries().size());
749 // Makes sure invoking LoadTabsFromLastSession() when the max number of entries
750 // have been added results in IsLoaded() returning true and notifies observers.
751 TEST_F(PersistentTabRestoreServiceTest, GoToLoadedWhenHaveMaxEntries) {
752 const size_t max_entries = kMaxEntries;
753 for (size_t i = 0; i < max_entries + 5; i++) {
754 NavigateAndCommit(
755 GURL(base::StringPrintf("http://%d", static_cast<int>(i))));
756 service_->CreateHistoricalTab(web_contents(), -1);
759 EXPECT_FALSE(service_->IsLoaded());
760 TestTabRestoreServiceObserver observer;
761 service_->AddObserver(&observer);
762 EXPECT_EQ(max_entries, service_->entries().size());
763 SynchronousLoadTabsFromLastSession();
764 EXPECT_TRUE(observer.got_loaded());
765 EXPECT_TRUE(service_->IsLoaded());
766 service_->RemoveObserver(&observer);