Add ICU message format support
[chromium-blink-merge.git] / chrome / browser / sessions / persistent_tab_restore_service_unittest.cc
blob912b1e76ea49f6b0a813f513755a9166ec6db28e
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/string_number_conversions.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/threading/sequenced_worker_pool.h"
14 #include "chrome/browser/chrome_notification_types.h"
15 #include "chrome/browser/sessions/session_service.h"
16 #include "chrome/browser/sessions/session_service_factory.h"
17 #include "chrome/browser/sessions/session_service_utils.h"
18 #include "chrome/browser/sessions/tab_restore_service_factory.h"
19 #include "chrome/browser/sessions/tab_restore_service_observer.h"
20 #include "chrome/common/url_constants.h"
21 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
22 #include "chrome/test/base/chrome_render_view_test.h"
23 #include "chrome/test/base/testing_profile.h"
24 #include "components/sessions/serialized_navigation_entry_test_helper.h"
25 #include "components/sessions/session_types.h"
26 #include "content/public/browser/browser_thread.h"
27 #include "content/public/browser/navigation_controller.h"
28 #include "content/public/browser/navigation_entry.h"
29 #include "content/public/browser/notification_service.h"
30 #include "content/public/browser/notification_types.h"
31 #include "content/public/browser/web_contents.h"
32 #include "content/public/test/render_view_test.h"
33 #include "content/public/test/test_utils.h"
34 #include "content/public/test/web_contents_tester.h"
35 #include "testing/gtest/include/gtest/gtest.h"
37 typedef TabRestoreService::Tab Tab;
38 typedef TabRestoreService::Window Window;
40 using content::NavigationEntry;
41 using content::WebContentsTester;
42 using sessions::SerializedNavigationEntry;
43 using sessions::SerializedNavigationEntryTestHelper;
45 // Create subclass that overrides TimeNow so that we can control the time used
46 // for closed tabs and windows.
47 class PersistentTabRestoreTimeFactory : public TabRestoreService::TimeFactory {
48 public:
49 PersistentTabRestoreTimeFactory() : time_(base::Time::Now()) {}
51 ~PersistentTabRestoreTimeFactory() override {}
53 base::Time TimeNow() override { return time_; }
55 private:
56 base::Time time_;
59 class PersistentTabRestoreServiceTest : public ChromeRenderViewHostTestHarness {
60 public:
61 PersistentTabRestoreServiceTest()
62 : url1_("http://1"),
63 url2_("http://2"),
64 url3_("http://3"),
65 user_agent_override_(
66 "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.19"
67 " (KHTML, like Gecko) Chrome/18.0.1025.45 Safari/535.19"),
68 time_factory_(NULL) {
71 ~PersistentTabRestoreServiceTest() override {}
73 protected:
74 enum {
75 kMaxEntries = TabRestoreServiceHelper::kMaxEntries,
78 // testing::Test:
79 void SetUp() override {
80 ChromeRenderViewHostTestHarness::SetUp();
81 time_factory_ = new PersistentTabRestoreTimeFactory();
82 service_.reset(new PersistentTabRestoreService(profile(), time_factory_));
85 void TearDown() override {
86 service_->Shutdown();
87 service_.reset();
88 delete time_factory_;
89 ChromeRenderViewHostTestHarness::TearDown();
92 TabRestoreService::Entries* mutable_entries() {
93 return service_->mutable_entries();
96 void PruneEntries() {
97 service_->PruneEntries();
100 void AddThreeNavigations() {
101 // Navigate to three URLs.
102 NavigateAndCommit(url1_);
103 NavigateAndCommit(url2_);
104 NavigateAndCommit(url3_);
107 void NavigateToIndex(int index) {
108 // Navigate back. We have to do this song and dance as NavigationController
109 // isn't happy if you navigate immediately while going back.
110 controller().GoToIndex(index);
111 WebContentsTester::For(web_contents())->CommitPendingNavigation();
114 void RecreateService() {
115 // Must set service to null first so that it is destroyed before the new
116 // one is created.
117 service_->Shutdown();
118 content::RunAllBlockingPoolTasksUntilIdle();
119 service_.reset();
120 service_.reset(new PersistentTabRestoreService(profile(), time_factory_));
121 SynchronousLoadTabsFromLastSession();
124 // Adds a window with one tab and url to the profile's session service.
125 // If |pinned| is true, the tab is marked as pinned in the session service.
126 void AddWindowWithOneTabToSessionService(bool pinned) {
127 SessionService* session_service =
128 SessionServiceFactory::GetForProfile(profile());
129 SessionID tab_id;
130 SessionID window_id;
131 session_service->SetWindowType(window_id,
132 Browser::TYPE_TABBED,
133 SessionService::TYPE_NORMAL);
134 session_service->SetTabWindow(window_id, tab_id);
135 session_service->SetTabIndexInWindow(window_id, tab_id, 0);
136 session_service->SetSelectedTabInWindow(window_id, 0);
137 if (pinned)
138 session_service->SetPinnedState(window_id, tab_id, true);
139 session_service->UpdateTabNavigation(
140 window_id, tab_id,
141 SerializedNavigationEntryTestHelper::CreateNavigation(
142 url1_.spec(), "title"));
145 // Creates a SessionService and assigns it to the Profile. The SessionService
146 // is configured with a single window with a single tab pointing at url1_ by
147 // way of AddWindowWithOneTabToSessionService. If |pinned| is true, the
148 // tab is marked as pinned in the session service.
149 void CreateSessionServiceWithOneWindow(bool pinned) {
150 scoped_ptr<SessionService> session_service(new SessionService(profile()));
151 SessionServiceFactory::SetForTestProfile(profile(), session_service.Pass());
153 AddWindowWithOneTabToSessionService(pinned);
155 // Set this, otherwise previous session won't be loaded.
156 profile()->set_last_session_exited_cleanly(false);
159 void SynchronousLoadTabsFromLastSession() {
160 // Ensures that the load is complete before continuing.
161 service_->LoadTabsFromLastSession();
162 content::RunAllBlockingPoolTasksUntilIdle();
165 GURL url1_;
166 GURL url2_;
167 GURL url3_;
168 std::string user_agent_override_;
169 scoped_ptr<PersistentTabRestoreService> service_;
170 PersistentTabRestoreTimeFactory* time_factory_;
173 namespace {
175 class TestTabRestoreServiceObserver : public TabRestoreServiceObserver {
176 public:
177 TestTabRestoreServiceObserver() : got_loaded_(false) {}
179 void clear_got_loaded() { got_loaded_ = false; }
180 bool got_loaded() const { return got_loaded_; }
182 // TabRestoreServiceObserver:
183 void TabRestoreServiceChanged(TabRestoreService* service) override {}
184 void TabRestoreServiceDestroyed(TabRestoreService* service) override {}
185 void TabRestoreServiceLoaded(TabRestoreService* service) override {
186 got_loaded_ = true;
189 private:
190 // Was TabRestoreServiceLoaded() invoked?
191 bool got_loaded_;
193 DISALLOW_COPY_AND_ASSIGN(TestTabRestoreServiceObserver);
196 } // namespace
198 TEST_F(PersistentTabRestoreServiceTest, Basic) {
199 AddThreeNavigations();
201 // Have the service record the tab.
202 service_->CreateHistoricalTab(web_contents(), -1);
204 // Make sure an entry was created.
205 ASSERT_EQ(1U, service_->entries().size());
207 // Make sure the entry matches.
208 TabRestoreService::Entry* entry = service_->entries().front();
209 ASSERT_EQ(TabRestoreService::TAB, entry->type);
210 Tab* tab = static_cast<Tab*>(entry);
211 EXPECT_FALSE(tab->pinned);
212 EXPECT_TRUE(tab->extension_app_id.empty());
213 ASSERT_EQ(3U, tab->navigations.size());
214 EXPECT_TRUE(url1_ == tab->navigations[0].virtual_url());
215 EXPECT_TRUE(url2_ == tab->navigations[1].virtual_url());
216 EXPECT_TRUE(url3_ == tab->navigations[2].virtual_url());
217 EXPECT_EQ("", tab->user_agent_override);
218 EXPECT_EQ(2, tab->current_navigation_index);
219 EXPECT_EQ(time_factory_->TimeNow().ToInternalValue(),
220 tab->timestamp.ToInternalValue());
222 NavigateToIndex(1);
224 // And check again, but set the user agent override this time.
225 web_contents()->SetUserAgentOverride(user_agent_override_);
226 service_->CreateHistoricalTab(web_contents(), -1);
228 // There should be two entries now.
229 ASSERT_EQ(2U, service_->entries().size());
231 // Make sure the entry matches.
232 entry = service_->entries().front();
233 ASSERT_EQ(TabRestoreService::TAB, entry->type);
234 tab = static_cast<Tab*>(entry);
235 EXPECT_FALSE(tab->pinned);
236 ASSERT_EQ(3U, tab->navigations.size());
237 EXPECT_EQ(url1_, tab->navigations[0].virtual_url());
238 EXPECT_EQ(url2_, tab->navigations[1].virtual_url());
239 EXPECT_EQ(url3_, tab->navigations[2].virtual_url());
240 EXPECT_EQ(user_agent_override_, tab->user_agent_override);
241 EXPECT_EQ(1, tab->current_navigation_index);
242 EXPECT_EQ(time_factory_->TimeNow().ToInternalValue(),
243 tab->timestamp.ToInternalValue());
246 // Make sure TabRestoreService doesn't create an entry for a tab with no
247 // navigations.
248 TEST_F(PersistentTabRestoreServiceTest, DontCreateEmptyTab) {
249 service_->CreateHistoricalTab(web_contents(), -1);
250 EXPECT_TRUE(service_->entries().empty());
253 // Tests restoring a single tab.
254 TEST_F(PersistentTabRestoreServiceTest, Restore) {
255 AddThreeNavigations();
257 // Have the service record the tab.
258 service_->CreateHistoricalTab(web_contents(), -1);
260 // Recreate the service and have it load the tabs.
261 RecreateService();
263 // One entry should be created.
264 ASSERT_EQ(1U, service_->entries().size());
266 // And verify the entry.
267 PersistentTabRestoreService::Entry* entry = service_->entries().front();
268 ASSERT_EQ(TabRestoreService::TAB, entry->type);
269 Tab* tab = static_cast<Tab*>(entry);
270 EXPECT_FALSE(tab->pinned);
271 ASSERT_EQ(3U, tab->navigations.size());
272 EXPECT_TRUE(url1_ == tab->navigations[0].virtual_url());
273 EXPECT_TRUE(url2_ == tab->navigations[1].virtual_url());
274 EXPECT_TRUE(url3_ == tab->navigations[2].virtual_url());
275 EXPECT_EQ(2, tab->current_navigation_index);
276 EXPECT_EQ(time_factory_->TimeNow().ToInternalValue(),
277 tab->timestamp.ToInternalValue());
280 // Tests restoring a single pinned tab.
281 TEST_F(PersistentTabRestoreServiceTest, RestorePinnedAndApp) {
282 AddThreeNavigations();
284 // Have the service record the tab.
285 service_->CreateHistoricalTab(web_contents(), -1);
287 // One entry should be created.
288 ASSERT_EQ(1U, service_->entries().size());
290 // We have to explicitly mark the tab as pinned as there is no browser for
291 // these tests.
292 TabRestoreService::Entry* entry = service_->entries().front();
293 ASSERT_EQ(TabRestoreService::TAB, entry->type);
294 Tab* tab = static_cast<Tab*>(entry);
295 tab->pinned = true;
296 const std::string extension_app_id("test");
297 tab->extension_app_id = extension_app_id;
299 // Recreate the service and have it load the tabs.
300 RecreateService();
302 // One entry should be created.
303 ASSERT_EQ(1U, service_->entries().size());
305 // And verify the entry.
306 entry = service_->entries().front();
307 ASSERT_EQ(TabRestoreService::TAB, entry->type);
308 tab = static_cast<Tab*>(entry);
309 EXPECT_TRUE(tab->pinned);
310 ASSERT_EQ(3U, tab->navigations.size());
311 EXPECT_TRUE(url1_ == tab->navigations[0].virtual_url());
312 EXPECT_TRUE(url2_ == tab->navigations[1].virtual_url());
313 EXPECT_TRUE(url3_ == tab->navigations[2].virtual_url());
314 EXPECT_EQ(2, tab->current_navigation_index);
315 EXPECT_TRUE(extension_app_id == tab->extension_app_id);
318 // Make sure we persist entries to disk that have post data.
319 TEST_F(PersistentTabRestoreServiceTest, DontPersistPostData) {
320 AddThreeNavigations();
321 controller().GetEntryAtIndex(0)->SetHasPostData(true);
322 controller().GetEntryAtIndex(1)->SetHasPostData(true);
323 controller().GetEntryAtIndex(2)->SetHasPostData(true);
325 // Have the service record the tab.
326 service_->CreateHistoricalTab(web_contents(), -1);
327 ASSERT_EQ(1U, service_->entries().size());
329 // Recreate the service and have it load the tabs.
330 RecreateService();
332 // One entry should be created.
333 ASSERT_EQ(1U, service_->entries().size());
335 const TabRestoreService::Entry* restored_entry = service_->entries().front();
336 ASSERT_EQ(TabRestoreService::TAB, restored_entry->type);
338 const Tab* restored_tab =
339 static_cast<const Tab*>(restored_entry);
340 // There should be 3 navs.
341 ASSERT_EQ(3U, restored_tab->navigations.size());
342 EXPECT_EQ(time_factory_->TimeNow().ToInternalValue(),
343 restored_tab->timestamp.ToInternalValue());
346 // Make sure we don't persist entries to disk that have post data. This
347 // differs from DontPersistPostData1 in that all the navigations have post
348 // data, so that nothing should be persisted.
349 TEST_F(PersistentTabRestoreServiceTest, DontLoadTwice) {
350 AddThreeNavigations();
352 // Have the service record the tab.
353 service_->CreateHistoricalTab(web_contents(), -1);
354 ASSERT_EQ(1U, service_->entries().size());
356 // Recreate the service and have it load the tabs.
357 RecreateService();
359 SynchronousLoadTabsFromLastSession();
361 // There should only be one entry.
362 ASSERT_EQ(1U, service_->entries().size());
365 // Makes sure we load the previous session as necessary.
366 TEST_F(PersistentTabRestoreServiceTest, LoadPreviousSession) {
367 CreateSessionServiceWithOneWindow(false);
369 SessionServiceFactory::GetForProfile(profile())->
370 MoveCurrentSessionToLastSession();
372 EXPECT_FALSE(service_->IsLoaded());
374 TestTabRestoreServiceObserver observer;
375 service_->AddObserver(&observer);
376 SynchronousLoadTabsFromLastSession();
377 EXPECT_TRUE(observer.got_loaded());
378 service_->RemoveObserver(&observer);
380 // Make sure we get back one entry with one tab whose url is url1.
381 ASSERT_EQ(1U, service_->entries().size());
382 TabRestoreService::Entry* entry2 = service_->entries().front();
383 ASSERT_EQ(TabRestoreService::WINDOW, entry2->type);
384 TabRestoreService::Window* window =
385 static_cast<TabRestoreService::Window*>(entry2);
386 ASSERT_EQ(1U, window->tabs.size());
387 EXPECT_EQ(0, window->timestamp.ToInternalValue());
388 EXPECT_EQ(0, window->selected_tab_index);
389 ASSERT_EQ(1U, window->tabs[0].navigations.size());
390 EXPECT_EQ(0, window->tabs[0].current_navigation_index);
391 EXPECT_EQ(0, window->tabs[0].timestamp.ToInternalValue());
392 EXPECT_TRUE(url1_ == window->tabs[0].navigations[0].virtual_url());
395 // Makes sure we don't attempt to load previous sessions after a restore.
396 TEST_F(PersistentTabRestoreServiceTest, DontLoadAfterRestore) {
397 CreateSessionServiceWithOneWindow(false);
399 SessionServiceFactory::GetForProfile(profile())->
400 MoveCurrentSessionToLastSession();
402 profile()->set_restored_last_session(true);
404 SynchronousLoadTabsFromLastSession();
406 // Because we restored a session PersistentTabRestoreService shouldn't load
407 // the tabs.
408 ASSERT_EQ(0U, service_->entries().size());
411 // Makes sure we don't attempt to load previous sessions after a clean exit.
412 TEST_F(PersistentTabRestoreServiceTest, DontLoadAfterCleanExit) {
413 CreateSessionServiceWithOneWindow(false);
415 SessionServiceFactory::GetForProfile(profile())->
416 MoveCurrentSessionToLastSession();
418 profile()->set_last_session_exited_cleanly(true);
420 SynchronousLoadTabsFromLastSession();
422 ASSERT_EQ(0U, service_->entries().size());
425 TEST_F(PersistentTabRestoreServiceTest, LoadPreviousSessionAndTabs) {
426 CreateSessionServiceWithOneWindow(false);
428 SessionServiceFactory::GetForProfile(profile())->
429 MoveCurrentSessionToLastSession();
431 AddThreeNavigations();
433 service_->CreateHistoricalTab(web_contents(), -1);
435 RecreateService();
437 // We should get back two entries, one from the previous session and one from
438 // the tab restore service. The previous session entry should be first.
439 ASSERT_EQ(2U, service_->entries().size());
440 // The first entry should come from the session service.
441 TabRestoreService::Entry* entry = service_->entries().front();
442 ASSERT_EQ(TabRestoreService::WINDOW, entry->type);
443 TabRestoreService::Window* window =
444 static_cast<TabRestoreService::Window*>(entry);
445 ASSERT_EQ(1U, window->tabs.size());
446 EXPECT_EQ(0, window->selected_tab_index);
447 EXPECT_EQ(0, window->timestamp.ToInternalValue());
448 ASSERT_EQ(1U, window->tabs[0].navigations.size());
449 EXPECT_EQ(0, window->tabs[0].current_navigation_index);
450 EXPECT_EQ(0, window->tabs[0].timestamp.ToInternalValue());
451 EXPECT_TRUE(url1_ == window->tabs[0].navigations[0].virtual_url());
453 // Then the closed tab.
454 entry = *(++service_->entries().begin());
455 ASSERT_EQ(TabRestoreService::TAB, entry->type);
456 Tab* tab = static_cast<Tab*>(entry);
457 ASSERT_FALSE(tab->pinned);
458 ASSERT_EQ(3U, tab->navigations.size());
459 EXPECT_EQ(2, tab->current_navigation_index);
460 EXPECT_EQ(time_factory_->TimeNow().ToInternalValue(),
461 tab->timestamp.ToInternalValue());
462 EXPECT_TRUE(url1_ == tab->navigations[0].virtual_url());
463 EXPECT_TRUE(url2_ == tab->navigations[1].virtual_url());
464 EXPECT_TRUE(url3_ == tab->navigations[2].virtual_url());
467 // Make sure pinned state is correctly loaded from session service.
468 TEST_F(PersistentTabRestoreServiceTest, LoadPreviousSessionAndTabsPinned) {
469 CreateSessionServiceWithOneWindow(true);
471 SessionServiceFactory::GetForProfile(profile())->
472 MoveCurrentSessionToLastSession();
474 AddThreeNavigations();
476 service_->CreateHistoricalTab(web_contents(), -1);
478 RecreateService();
480 // We should get back two entries, one from the previous session and one from
481 // the tab restore service. The previous session entry should be first.
482 ASSERT_EQ(2U, service_->entries().size());
483 // The first entry should come from the session service.
484 TabRestoreService::Entry* entry = service_->entries().front();
485 ASSERT_EQ(TabRestoreService::WINDOW, entry->type);
486 TabRestoreService::Window* window =
487 static_cast<TabRestoreService::Window*>(entry);
488 ASSERT_EQ(1U, window->tabs.size());
489 EXPECT_EQ(0, window->selected_tab_index);
490 EXPECT_TRUE(window->tabs[0].pinned);
491 ASSERT_EQ(1U, window->tabs[0].navigations.size());
492 EXPECT_EQ(0, window->tabs[0].current_navigation_index);
493 EXPECT_TRUE(url1_ == window->tabs[0].navigations[0].virtual_url());
495 // Then the closed tab.
496 entry = *(++service_->entries().begin());
497 ASSERT_EQ(TabRestoreService::TAB, entry->type);
498 Tab* tab = static_cast<Tab*>(entry);
499 ASSERT_FALSE(tab->pinned);
500 ASSERT_EQ(3U, tab->navigations.size());
501 EXPECT_EQ(2, tab->current_navigation_index);
502 EXPECT_TRUE(url1_ == tab->navigations[0].virtual_url());
503 EXPECT_TRUE(url2_ == tab->navigations[1].virtual_url());
504 EXPECT_TRUE(url3_ == tab->navigations[2].virtual_url());
507 // Creates kMaxEntries + 1 windows in the session service and makes sure we only
508 // get back kMaxEntries on restore.
509 TEST_F(PersistentTabRestoreServiceTest, ManyWindowsInSessionService) {
510 CreateSessionServiceWithOneWindow(false);
512 for (size_t i = 0; i < kMaxEntries; ++i)
513 AddWindowWithOneTabToSessionService(false);
515 SessionServiceFactory::GetForProfile(profile())->
516 MoveCurrentSessionToLastSession();
518 AddThreeNavigations();
520 service_->CreateHistoricalTab(web_contents(), -1);
522 RecreateService();
524 // We should get back kMaxEntries entries. We added more, but
525 // TabRestoreService only allows up to kMaxEntries.
526 ASSERT_EQ(kMaxEntries, service_->entries().size());
528 // The first entry should come from the session service.
529 TabRestoreService::Entry* entry = service_->entries().front();
530 ASSERT_EQ(TabRestoreService::WINDOW, entry->type);
531 TabRestoreService::Window* window =
532 static_cast<TabRestoreService::Window*>(entry);
533 ASSERT_EQ(1U, window->tabs.size());
534 EXPECT_EQ(0, window->selected_tab_index);
535 EXPECT_EQ(0, window->timestamp.ToInternalValue());
536 ASSERT_EQ(1U, window->tabs[0].navigations.size());
537 EXPECT_EQ(0, window->tabs[0].current_navigation_index);
538 EXPECT_EQ(0, window->tabs[0].timestamp.ToInternalValue());
539 EXPECT_TRUE(url1_ == window->tabs[0].navigations[0].virtual_url());
542 // Makes sure we restore timestamps correctly.
543 TEST_F(PersistentTabRestoreServiceTest, TimestampSurvivesRestore) {
544 base::Time tab_timestamp(base::Time::FromInternalValue(123456789));
546 AddThreeNavigations();
548 // Have the service record the tab.
549 service_->CreateHistoricalTab(web_contents(), -1);
551 // Make sure an entry was created.
552 ASSERT_EQ(1U, service_->entries().size());
554 // Make sure the entry matches.
555 std::vector<SerializedNavigationEntry> old_navigations;
557 // |entry|/|tab| doesn't survive after RecreateService().
558 TabRestoreService::Entry* entry = service_->entries().front();
559 ASSERT_EQ(TabRestoreService::TAB, entry->type);
560 Tab* tab = static_cast<Tab*>(entry);
561 tab->timestamp = tab_timestamp;
562 old_navigations = tab->navigations;
565 EXPECT_EQ(3U, old_navigations.size());
566 for (size_t i = 0; i < old_navigations.size(); ++i) {
567 EXPECT_FALSE(old_navigations[i].timestamp().is_null());
570 // Set this, otherwise previous session won't be loaded.
571 profile()->set_last_session_exited_cleanly(false);
573 RecreateService();
575 // One entry should be created.
576 ASSERT_EQ(1U, service_->entries().size());
578 // And verify the entry.
579 TabRestoreService::Entry* restored_entry = service_->entries().front();
580 ASSERT_EQ(TabRestoreService::TAB, restored_entry->type);
581 Tab* restored_tab =
582 static_cast<Tab*>(restored_entry);
583 EXPECT_EQ(tab_timestamp.ToInternalValue(),
584 restored_tab->timestamp.ToInternalValue());
585 ASSERT_EQ(old_navigations.size(), restored_tab->navigations.size());
586 for (size_t i = 0; i < restored_tab->navigations.size(); ++i) {
587 EXPECT_EQ(old_navigations[i].timestamp(),
588 restored_tab->navigations[i].timestamp());
592 // Makes sure we restore status codes correctly.
593 TEST_F(PersistentTabRestoreServiceTest, StatusCodesSurviveRestore) {
594 AddThreeNavigations();
596 // Have the service record the tab.
597 service_->CreateHistoricalTab(web_contents(), -1);
599 // Make sure an entry was created.
600 ASSERT_EQ(1U, service_->entries().size());
602 // Make sure the entry matches.
603 std::vector<sessions::SerializedNavigationEntry> old_navigations;
605 // |entry|/|tab| doesn't survive after RecreateService().
606 TabRestoreService::Entry* entry = service_->entries().front();
607 ASSERT_EQ(TabRestoreService::TAB, entry->type);
608 Tab* tab = static_cast<Tab*>(entry);
609 old_navigations = tab->navigations;
612 EXPECT_EQ(3U, old_navigations.size());
613 for (size_t i = 0; i < old_navigations.size(); ++i) {
614 EXPECT_EQ(200, old_navigations[i].http_status_code());
617 // Set this, otherwise previous session won't be loaded.
618 profile()->set_last_session_exited_cleanly(false);
620 RecreateService();
622 // One entry should be created.
623 ASSERT_EQ(1U, service_->entries().size());
625 // And verify the entry.
626 TabRestoreService::Entry* restored_entry = service_->entries().front();
627 ASSERT_EQ(TabRestoreService::TAB, restored_entry->type);
628 Tab* restored_tab =
629 static_cast<Tab*>(restored_entry);
630 ASSERT_EQ(old_navigations.size(), restored_tab->navigations.size());
631 for (size_t i = 0; i < restored_tab->navigations.size(); ++i) {
632 EXPECT_EQ(200, restored_tab->navigations[i].http_status_code());
636 TEST_F(PersistentTabRestoreServiceTest, PruneEntries) {
637 service_->ClearEntries();
638 ASSERT_TRUE(service_->entries().empty());
640 const size_t max_entries = kMaxEntries;
641 for (size_t i = 0; i < max_entries + 5; i++) {
642 SerializedNavigationEntry navigation =
643 SerializedNavigationEntryTestHelper::CreateNavigation(
644 base::StringPrintf("http://%d", static_cast<int>(i)),
645 base::SizeTToString(i));
647 Tab* tab = new Tab();
648 tab->navigations.push_back(navigation);
649 tab->current_navigation_index = 0;
651 mutable_entries()->push_back(tab);
654 // Only keep kMaxEntries around.
655 EXPECT_EQ(max_entries + 5, service_->entries().size());
656 PruneEntries();
657 EXPECT_EQ(max_entries, service_->entries().size());
658 // Pruning again does nothing.
659 PruneEntries();
660 EXPECT_EQ(max_entries, service_->entries().size());
662 // Prune older first.
663 const char kRecentUrl[] = "http://recent";
664 SerializedNavigationEntry navigation =
665 SerializedNavigationEntryTestHelper::CreateNavigation(kRecentUrl,
666 "Most recent");
667 Tab* tab = new Tab();
668 tab->navigations.push_back(navigation);
669 tab->current_navigation_index = 0;
670 mutable_entries()->push_front(tab);
671 EXPECT_EQ(max_entries + 1, service_->entries().size());
672 PruneEntries();
673 EXPECT_EQ(max_entries, service_->entries().size());
674 EXPECT_EQ(GURL(kRecentUrl),
675 static_cast<Tab*>(service_->entries().front())->
676 navigations[0].virtual_url());
678 // Ignore NTPs.
679 navigation = SerializedNavigationEntryTestHelper::CreateNavigation(
680 chrome::kChromeUINewTabURL, "New tab");
682 tab = new Tab();
683 tab->navigations.push_back(navigation);
684 tab->current_navigation_index = 0;
685 mutable_entries()->push_front(tab);
687 EXPECT_EQ(max_entries + 1, service_->entries().size());
688 PruneEntries();
689 EXPECT_EQ(max_entries, service_->entries().size());
690 EXPECT_EQ(GURL(kRecentUrl),
691 static_cast<Tab*>(service_->entries().front())->
692 navigations[0].virtual_url());
694 // Don't prune pinned NTPs.
695 tab = new Tab();
696 tab->pinned = true;
697 tab->current_navigation_index = 0;
698 tab->navigations.push_back(navigation);
699 mutable_entries()->push_front(tab);
700 EXPECT_EQ(max_entries + 1, service_->entries().size());
701 PruneEntries();
702 EXPECT_EQ(max_entries, service_->entries().size());
703 EXPECT_EQ(GURL(chrome::kChromeUINewTabURL),
704 static_cast<Tab*>(service_->entries().front())->
705 navigations[0].virtual_url());
707 // Don't prune NTPs that have multiple navigations.
708 // (Erase the last NTP first.)
709 delete service_->entries().front();
710 mutable_entries()->erase(mutable_entries()->begin());
711 tab = new Tab();
712 tab->current_navigation_index = 1;
713 tab->navigations.push_back(navigation);
714 tab->navigations.push_back(navigation);
715 mutable_entries()->push_front(tab);
716 EXPECT_EQ(max_entries, service_->entries().size());
717 PruneEntries();
718 EXPECT_EQ(max_entries, service_->entries().size());
719 EXPECT_EQ(GURL(chrome::kChromeUINewTabURL),
720 static_cast<Tab*>(service_->entries().front())->
721 navigations[1].virtual_url());
724 // Regression test for crbug.com/106082
725 TEST_F(PersistentTabRestoreServiceTest, PruneIsCalled) {
726 CreateSessionServiceWithOneWindow(false);
728 SessionServiceFactory::GetForProfile(profile())->
729 MoveCurrentSessionToLastSession();
731 profile()->set_restored_last_session(true);
733 const size_t max_entries = kMaxEntries;
734 for (size_t i = 0; i < max_entries + 5; i++) {
735 NavigateAndCommit(
736 GURL(base::StringPrintf("http://%d", static_cast<int>(i))));
737 service_->CreateHistoricalTab(web_contents(), -1);
740 EXPECT_EQ(max_entries, service_->entries().size());
741 // This should not crash.
742 SynchronousLoadTabsFromLastSession();
743 EXPECT_EQ(max_entries, service_->entries().size());
746 // Makes sure invoking LoadTabsFromLastSession() when the max number of entries
747 // have been added results in IsLoaded() returning true and notifies observers.
748 TEST_F(PersistentTabRestoreServiceTest, GoToLoadedWhenHaveMaxEntries) {
749 const size_t max_entries = kMaxEntries;
750 for (size_t i = 0; i < max_entries + 5; i++) {
751 NavigateAndCommit(
752 GURL(base::StringPrintf("http://%d", static_cast<int>(i))));
753 service_->CreateHistoricalTab(web_contents(), -1);
756 EXPECT_FALSE(service_->IsLoaded());
757 TestTabRestoreServiceObserver observer;
758 service_->AddObserver(&observer);
759 EXPECT_EQ(max_entries, service_->entries().size());
760 SynchronousLoadTabsFromLastSession();
761 EXPECT_TRUE(observer.got_loaded());
762 EXPECT_TRUE(service_->IsLoaded());
763 service_->RemoveObserver(&observer);