1 // Copyright (c) 2012 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.
6 #include "base/bind_helpers.h"
7 #include "base/file_util.h"
8 #include "base/files/scoped_temp_dir.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/memory/scoped_vector.h"
11 #include "base/path_service.h"
12 #include "base/stl_util.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/time/time.h"
16 #include "chrome/browser/chrome_notification_types.h"
17 #include "chrome/browser/defaults.h"
18 #include "chrome/browser/sessions/session_backend.h"
19 #include "chrome/browser/sessions/session_service.h"
20 #include "chrome/browser/sessions/session_service_test_helper.h"
21 #include "chrome/browser/sessions/session_types.h"
22 #include "chrome/common/chrome_paths.h"
23 #include "chrome/test/base/browser_with_test_window_test.h"
24 #include "chrome/test/base/testing_profile.h"
25 #include "components/sessions/serialized_navigation_entry_test_helper.h"
26 #include "content/public/browser/navigation_entry.h"
27 #include "content/public/browser/notification_observer.h"
28 #include "content/public/browser/notification_registrar.h"
29 #include "content/public/browser/notification_service.h"
30 #include "content/public/common/page_state.h"
31 #include "testing/gtest/include/gtest/gtest.h"
33 using content::NavigationEntry;
34 using sessions::SerializedNavigationEntry;
35 using sessions::SerializedNavigationEntryTestHelper;
37 class SessionServiceTest : public BrowserWithTestWindowTest,
38 public content::NotificationObserver {
40 SessionServiceTest() : window_bounds(0, 1, 2, 3), sync_save_count_(0) {}
43 virtual void SetUp() {
44 BrowserWithTestWindowTest::SetUp();
45 std::string b = base::Int64ToString(base::Time::Now().ToInternalValue());
47 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
48 path_ = temp_dir_.path().Append(FILE_PATH_LITERAL("SessionTestDirs"));
49 ASSERT_TRUE(file_util::CreateDirectory(path_));
50 path_ = path_.AppendASCII(b);
52 SessionService* session_service = new SessionService(path_);
53 helper_.SetService(session_service);
55 service()->SetWindowType(
56 window_id, Browser::TYPE_TABBED, SessionService::TYPE_NORMAL);
57 service()->SetWindowBounds(window_id,
59 ui::SHOW_STATE_NORMAL);
62 // Upon notification, increment the sync_save_count variable
63 virtual void Observe(int type,
64 const content::NotificationSource& source,
65 const content::NotificationDetails& details) OVERRIDE {
66 ASSERT_EQ(type, chrome::NOTIFICATION_SESSION_SERVICE_SAVED);
70 virtual void TearDown() {
71 helper_.SetService(NULL);
72 BrowserWithTestWindowTest::TearDown();
75 void UpdateNavigation(
76 const SessionID& window_id,
77 const SessionID& tab_id,
78 const SerializedNavigationEntry& navigation,
80 service()->UpdateTabNavigation(window_id, tab_id, navigation);
82 service()->SetSelectedNavigationIndex(
83 window_id, tab_id, navigation.index());
87 void ReadWindows(std::vector<SessionWindow*>* windows,
88 SessionID::id_type* active_window_id) {
89 // Forces closing the file.
90 helper_.SetService(NULL);
92 SessionService* session_service = new SessionService(path_);
93 helper_.SetService(session_service);
95 SessionID::id_type* non_null_active_window_id = active_window_id;
96 SessionID::id_type dummy_active_window_id = 0;
97 if (!non_null_active_window_id)
98 non_null_active_window_id = &dummy_active_window_id;
99 helper_.ReadWindows(windows, non_null_active_window_id);
102 // Configures the session service with one window with one tab and a single
103 // navigation. If |pinned_state| is true or |write_always| is true, the
104 // pinned state of the tab is updated. The session service is then recreated
105 // and the pinned state of the read back tab is returned.
106 bool CreateAndWriteSessionWithOneTab(bool pinned_state, bool write_always) {
108 SerializedNavigationEntry nav1 =
109 SerializedNavigationEntryTestHelper::CreateNavigation(
110 "http://google.com", "abc");
112 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
113 UpdateNavigation(window_id, tab_id, nav1, true);
115 if (pinned_state || write_always)
116 helper_.service()->SetPinnedState(window_id, tab_id, pinned_state);
118 ScopedVector<SessionWindow> windows;
119 ReadWindows(&(windows.get()), NULL);
121 EXPECT_EQ(1U, windows.size());
122 if (HasFatalFailure())
124 EXPECT_EQ(1U, windows[0]->tabs.size());
125 if (HasFatalFailure())
128 SessionTab* tab = windows[0]->tabs[0];
129 helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
134 void CreateAndWriteSessionWithTwoWindows(
135 const SessionID& window2_id,
136 const SessionID& tab1_id,
137 const SessionID& tab2_id,
138 SerializedNavigationEntry* nav1,
139 SerializedNavigationEntry* nav2) {
140 *nav1 = SerializedNavigationEntryTestHelper::CreateNavigation(
141 "http://google.com", "abc");
142 *nav2 = SerializedNavigationEntryTestHelper::CreateNavigation(
143 "http://google2.com", "abcd");
145 helper_.PrepareTabInWindow(window_id, tab1_id, 0, true);
146 UpdateNavigation(window_id, tab1_id, *nav1, true);
148 const gfx::Rect window2_bounds(3, 4, 5, 6);
149 service()->SetWindowType(
150 window2_id, Browser::TYPE_TABBED, SessionService::TYPE_NORMAL);
151 service()->SetWindowBounds(window2_id,
153 ui::SHOW_STATE_MAXIMIZED);
154 helper_.PrepareTabInWindow(window2_id, tab2_id, 0, true);
155 UpdateNavigation(window2_id, tab2_id, *nav2, true);
158 SessionService* service() { return helper_.service(); }
160 SessionBackend* backend() { return helper_.backend(); }
162 const gfx::Rect window_bounds;
166 int sync_save_count_;
168 // Path used in testing.
169 base::ScopedTempDir temp_dir_;
170 base::FilePath path_;
172 SessionServiceTestHelper helper_;
175 TEST_F(SessionServiceTest, Basic) {
177 ASSERT_NE(window_id.id(), tab_id.id());
179 SerializedNavigationEntry nav1 =
180 SerializedNavigationEntryTestHelper::CreateNavigation(
181 "http://google.com", "abc");
182 SerializedNavigationEntryTestHelper::SetOriginalRequestURL(
183 GURL("http://original.request.com"), &nav1);
185 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
186 UpdateNavigation(window_id, tab_id, nav1, true);
188 ScopedVector<SessionWindow> windows;
189 ReadWindows(&(windows.get()), NULL);
191 ASSERT_EQ(1U, windows.size());
192 ASSERT_TRUE(window_bounds == windows[0]->bounds);
193 ASSERT_EQ(0, windows[0]->selected_tab_index);
194 ASSERT_EQ(window_id.id(), windows[0]->window_id.id());
195 ASSERT_EQ(1U, windows[0]->tabs.size());
196 ASSERT_EQ(Browser::TYPE_TABBED, windows[0]->type);
198 SessionTab* tab = windows[0]->tabs[0];
199 helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
201 helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
204 // Make sure we persist post entries.
205 TEST_F(SessionServiceTest, PersistPostData) {
207 ASSERT_NE(window_id.id(), tab_id.id());
209 SerializedNavigationEntry nav1 =
210 SerializedNavigationEntryTestHelper::CreateNavigation(
211 "http://google.com", "abc");
212 SerializedNavigationEntryTestHelper::SetHasPostData(true, &nav1);
214 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
215 UpdateNavigation(window_id, tab_id, nav1, true);
217 ScopedVector<SessionWindow> windows;
218 ReadWindows(&(windows.get()), NULL);
220 helper_.AssertSingleWindowWithSingleTab(windows.get(), 1);
223 TEST_F(SessionServiceTest, ClosingTabStaysClosed) {
226 ASSERT_NE(tab_id.id(), tab2_id.id());
228 SerializedNavigationEntry nav1 =
229 SerializedNavigationEntryTestHelper::CreateNavigation(
230 "http://google.com", "abc");
231 SerializedNavigationEntry nav2 =
232 SerializedNavigationEntryTestHelper::CreateNavigation(
233 "http://google2.com", "abcd");
235 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
236 UpdateNavigation(window_id, tab_id, nav1, true);
238 helper_.PrepareTabInWindow(window_id, tab2_id, 1, false);
239 UpdateNavigation(window_id, tab2_id, nav2, true);
240 service()->TabClosed(window_id, tab2_id, false);
242 ScopedVector<SessionWindow> windows;
243 ReadWindows(&(windows.get()), NULL);
245 ASSERT_EQ(1U, windows.size());
246 ASSERT_EQ(0, windows[0]->selected_tab_index);
247 ASSERT_EQ(window_id.id(), windows[0]->window_id.id());
248 ASSERT_EQ(1U, windows[0]->tabs.size());
250 SessionTab* tab = windows[0]->tabs[0];
251 helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
253 helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
256 TEST_F(SessionServiceTest, Pruning) {
259 SerializedNavigationEntry nav1 =
260 SerializedNavigationEntryTestHelper::CreateNavigation(
261 "http://google.com", "abc");
262 SerializedNavigationEntry nav2 =
263 SerializedNavigationEntryTestHelper::CreateNavigation(
264 "http://google2.com", "abcd");
266 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
267 for (int i = 0; i < 6; ++i) {
268 SerializedNavigationEntry* nav = (i % 2) == 0 ? &nav1 : &nav2;
270 UpdateNavigation(window_id, tab_id, *nav, true);
272 service()->TabNavigationPathPrunedFromBack(window_id, tab_id, 3);
274 ScopedVector<SessionWindow> windows;
275 ReadWindows(&(windows.get()), NULL);
277 ASSERT_EQ(1U, windows.size());
278 ASSERT_EQ(0, windows[0]->selected_tab_index);
279 ASSERT_EQ(1U, windows[0]->tabs.size());
281 SessionTab* tab = windows[0]->tabs[0];
282 // We left the selected index at 5, then pruned. When rereading the
283 // index should get reset to last valid navigation, which is 2.
284 helper_.AssertTabEquals(window_id, tab_id, 0, 2, 3, *tab);
286 ASSERT_EQ(3u, tab->navigations.size());
287 helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
288 helper_.AssertNavigationEquals(nav2, tab->navigations[1]);
289 helper_.AssertNavigationEquals(nav1, tab->navigations[2]);
292 TEST_F(SessionServiceTest, TwoWindows) {
293 SessionID window2_id;
296 SerializedNavigationEntry nav1;
297 SerializedNavigationEntry nav2;
299 CreateAndWriteSessionWithTwoWindows(
300 window2_id, tab1_id, tab2_id, &nav1, &nav2);
302 ScopedVector<SessionWindow> windows;
303 ReadWindows(&(windows.get()), NULL);
305 ASSERT_EQ(2U, windows.size());
306 ASSERT_EQ(0, windows[0]->selected_tab_index);
307 ASSERT_EQ(0, windows[1]->selected_tab_index);
308 ASSERT_EQ(1U, windows[0]->tabs.size());
309 ASSERT_EQ(1U, windows[1]->tabs.size());
313 if (windows[0]->window_id.id() == window_id.id()) {
314 ASSERT_EQ(window2_id.id(), windows[1]->window_id.id());
315 ASSERT_EQ(ui::SHOW_STATE_NORMAL, windows[0]->show_state);
316 ASSERT_EQ(ui::SHOW_STATE_MAXIMIZED, windows[1]->show_state);
317 rt1 = windows[0]->tabs[0];
318 rt2 = windows[1]->tabs[0];
320 ASSERT_EQ(window2_id.id(), windows[0]->window_id.id());
321 ASSERT_EQ(window_id.id(), windows[1]->window_id.id());
322 ASSERT_EQ(ui::SHOW_STATE_MAXIMIZED, windows[0]->show_state);
323 ASSERT_EQ(ui::SHOW_STATE_NORMAL, windows[1]->show_state);
324 rt1 = windows[1]->tabs[0];
325 rt2 = windows[0]->tabs[0];
327 SessionTab* tab = rt1;
328 helper_.AssertTabEquals(window_id, tab1_id, 0, 0, 1, *tab);
329 helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
332 helper_.AssertTabEquals(window2_id, tab2_id, 0, 0, 1, *tab);
333 helper_.AssertNavigationEquals(nav2, tab->navigations[0]);
336 TEST_F(SessionServiceTest, WindowWithNoTabsGetsPruned) {
337 SessionID window2_id;
341 SerializedNavigationEntry nav1 =
342 SerializedNavigationEntryTestHelper::CreateNavigation(
343 "http://google.com", "abc");
345 helper_.PrepareTabInWindow(window_id, tab1_id, 0, true);
346 UpdateNavigation(window_id, tab1_id, nav1, true);
348 const gfx::Rect window2_bounds(3, 4, 5, 6);
349 service()->SetWindowType(
350 window2_id, Browser::TYPE_TABBED, SessionService::TYPE_NORMAL);
351 service()->SetWindowBounds(window2_id,
353 ui::SHOW_STATE_NORMAL);
354 helper_.PrepareTabInWindow(window2_id, tab2_id, 0, true);
356 ScopedVector<SessionWindow> windows;
357 ReadWindows(&(windows.get()), NULL);
359 ASSERT_EQ(1U, windows.size());
360 ASSERT_EQ(0, windows[0]->selected_tab_index);
361 ASSERT_EQ(1U, windows[0]->tabs.size());
362 ASSERT_EQ(window_id.id(), windows[0]->window_id.id());
364 SessionTab* tab = windows[0]->tabs[0];
365 helper_.AssertTabEquals(window_id, tab1_id, 0, 0, 1, *tab);
366 helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
369 TEST_F(SessionServiceTest, ClosingWindowDoesntCloseTabs) {
372 ASSERT_NE(tab_id.id(), tab2_id.id());
374 SerializedNavigationEntry nav1 =
375 SerializedNavigationEntryTestHelper::CreateNavigation(
376 "http://google.com", "abc");
377 SerializedNavigationEntry nav2 =
378 SerializedNavigationEntryTestHelper::CreateNavigation(
379 "http://google2.com", "abcd");
381 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
382 UpdateNavigation(window_id, tab_id, nav1, true);
384 helper_.PrepareTabInWindow(window_id, tab2_id, 1, false);
385 UpdateNavigation(window_id, tab2_id, nav2, true);
387 service()->WindowClosing(window_id);
389 ScopedVector<SessionWindow> windows;
390 ReadWindows(&(windows.get()), NULL);
392 ASSERT_EQ(1U, windows.size());
393 ASSERT_EQ(0, windows[0]->selected_tab_index);
394 ASSERT_EQ(window_id.id(), windows[0]->window_id.id());
395 ASSERT_EQ(2U, windows[0]->tabs.size());
397 SessionTab* tab = windows[0]->tabs[0];
398 helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
399 helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
401 tab = windows[0]->tabs[1];
402 helper_.AssertTabEquals(window_id, tab2_id, 1, 0, 1, *tab);
403 helper_.AssertNavigationEquals(nav2, tab->navigations[0]);
406 TEST_F(SessionServiceTest, WindowCloseCommittedAfterNavigate) {
407 SessionID window2_id;
410 ASSERT_NE(window2_id.id(), window_id.id());
412 service()->SetWindowType(
413 window2_id, Browser::TYPE_TABBED, SessionService::TYPE_NORMAL);
414 service()->SetWindowBounds(window2_id,
416 ui::SHOW_STATE_NORMAL);
418 SerializedNavigationEntry nav1 =
419 SerializedNavigationEntryTestHelper::CreateNavigation(
420 "http://google.com", "abc");
421 SerializedNavigationEntry nav2 =
422 SerializedNavigationEntryTestHelper::CreateNavigation(
423 "http://google2.com", "abcd");
425 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
426 UpdateNavigation(window_id, tab_id, nav1, true);
428 helper_.PrepareTabInWindow(window2_id, tab2_id, 0, false);
429 UpdateNavigation(window2_id, tab2_id, nav2, true);
431 service()->WindowClosing(window2_id);
432 service()->TabClosed(window2_id, tab2_id, false);
433 service()->WindowClosed(window2_id);
435 ScopedVector<SessionWindow> windows;
436 ReadWindows(&(windows.get()), NULL);
438 ASSERT_EQ(1U, windows.size());
439 ASSERT_EQ(0, windows[0]->selected_tab_index);
440 ASSERT_EQ(window_id.id(), windows[0]->window_id.id());
441 ASSERT_EQ(1U, windows[0]->tabs.size());
443 SessionTab* tab = windows[0]->tabs[0];
444 helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
445 helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
448 // Makes sure we don't track popups.
449 TEST_F(SessionServiceTest, IgnorePopups) {
450 if (browser_defaults::kRestorePopups)
451 return; // This test is only applicable if popups aren't restored.
453 SessionID window2_id;
456 ASSERT_NE(window2_id.id(), window_id.id());
458 service()->SetWindowType(
459 window2_id, Browser::TYPE_POPUP, SessionService::TYPE_NORMAL);
460 service()->SetWindowBounds(window2_id,
462 ui::SHOW_STATE_NORMAL);
464 SerializedNavigationEntry nav1 =
465 SerializedNavigationEntryTestHelper::CreateNavigation(
466 "http://google.com", "abc");
467 SerializedNavigationEntry nav2 =
468 SerializedNavigationEntryTestHelper::CreateNavigation(
469 "http://google2.com", "abcd");
471 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
472 UpdateNavigation(window_id, tab_id, nav1, true);
474 helper_.PrepareTabInWindow(window2_id, tab2_id, 0, false);
475 UpdateNavigation(window2_id, tab2_id, nav2, true);
477 ScopedVector<SessionWindow> windows;
478 ReadWindows(&(windows.get()), NULL);
480 ASSERT_EQ(1U, windows.size());
481 ASSERT_EQ(0, windows[0]->selected_tab_index);
482 ASSERT_EQ(window_id.id(), windows[0]->window_id.id());
483 ASSERT_EQ(1U, windows[0]->tabs.size());
485 SessionTab* tab = windows[0]->tabs[0];
486 helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
487 helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
490 // Makes sure we track popups.
491 TEST_F(SessionServiceTest, RestorePopup) {
492 if (!browser_defaults::kRestorePopups)
493 return; // This test is only applicable if popups are restored.
495 SessionID window2_id;
498 ASSERT_NE(window2_id.id(), window_id.id());
500 service()->SetWindowType(
501 window2_id, Browser::TYPE_POPUP, SessionService::TYPE_NORMAL);
502 service()->SetWindowBounds(window2_id,
504 ui::SHOW_STATE_NORMAL);
506 SerializedNavigationEntry nav1 =
507 SerializedNavigationEntryTestHelper::CreateNavigation(
508 "http://google.com", "abc");
509 SerializedNavigationEntry nav2 =
510 SerializedNavigationEntryTestHelper::CreateNavigation(
511 "http://google2.com", "abcd");
513 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
514 UpdateNavigation(window_id, tab_id, nav1, true);
516 helper_.PrepareTabInWindow(window2_id, tab2_id, 0, false);
517 UpdateNavigation(window2_id, tab2_id, nav2, true);
519 ScopedVector<SessionWindow> windows;
520 ReadWindows(&(windows.get()), NULL);
522 ASSERT_EQ(2U, windows.size());
523 int tabbed_index = windows[0]->type == Browser::TYPE_TABBED ?
525 int popup_index = tabbed_index == 0 ? 1 : 0;
526 ASSERT_EQ(0, windows[tabbed_index]->selected_tab_index);
527 ASSERT_EQ(window_id.id(), windows[tabbed_index]->window_id.id());
528 ASSERT_EQ(1U, windows[tabbed_index]->tabs.size());
530 SessionTab* tab = windows[tabbed_index]->tabs[0];
531 helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
532 helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
534 ASSERT_EQ(0, windows[popup_index]->selected_tab_index);
535 ASSERT_EQ(window2_id.id(), windows[popup_index]->window_id.id());
536 ASSERT_EQ(1U, windows[popup_index]->tabs.size());
538 tab = windows[popup_index]->tabs[0];
539 helper_.AssertTabEquals(window2_id, tab2_id, 0, 0, 1, *tab);
540 helper_.AssertNavigationEquals(nav2, tab->navigations[0]);
543 #if defined (OS_CHROMEOS)
544 // Makes sure we track apps. Only applicable on chromeos.
545 TEST_F(SessionServiceTest, RestoreApp) {
546 SessionID window2_id;
549 ASSERT_NE(window2_id.id(), window_id.id());
551 service()->SetWindowType(
552 window2_id, Browser::TYPE_POPUP, SessionService::TYPE_APP);
553 service()->SetWindowBounds(window2_id,
555 ui::SHOW_STATE_NORMAL);
556 service()->SetWindowAppName(window2_id, "TestApp");
558 SerializedNavigationEntry nav1 =
559 SerializedNavigationEntryTestHelper::CreateNavigation(
560 "http://google.com", "abc");
561 SerializedNavigationEntry nav2 =
562 SerializedNavigationEntryTestHelper::CreateNavigation(
563 "http://google2.com", "abcd");
565 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
566 UpdateNavigation(window_id, tab_id, nav1, true);
568 helper_.PrepareTabInWindow(window2_id, tab2_id, 0, false);
569 UpdateNavigation(window2_id, tab2_id, nav2, true);
571 ScopedVector<SessionWindow> windows;
572 ReadWindows(&(windows.get()), NULL);
574 ASSERT_EQ(2U, windows.size());
575 int tabbed_index = windows[0]->type == Browser::TYPE_TABBED ?
577 int app_index = tabbed_index == 0 ? 1 : 0;
578 ASSERT_EQ(0, windows[tabbed_index]->selected_tab_index);
579 ASSERT_EQ(window_id.id(), windows[tabbed_index]->window_id.id());
580 ASSERT_EQ(1U, windows[tabbed_index]->tabs.size());
582 SessionTab* tab = windows[tabbed_index]->tabs[0];
583 helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
584 helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
586 ASSERT_EQ(0, windows[app_index]->selected_tab_index);
587 ASSERT_EQ(window2_id.id(), windows[app_index]->window_id.id());
588 ASSERT_EQ(1U, windows[app_index]->tabs.size());
589 ASSERT_TRUE(windows[app_index]->type == Browser::TYPE_POPUP);
590 ASSERT_EQ("TestApp", windows[app_index]->app_name);
592 tab = windows[app_index]->tabs[0];
593 helper_.AssertTabEquals(window2_id, tab2_id, 0, 0, 1, *tab);
594 helper_.AssertNavigationEquals(nav2, tab->navigations[0]);
596 #endif // defined (OS_CHROMEOS)
598 // Tests pruning from the front.
599 TEST_F(SessionServiceTest, PruneFromFront) {
600 const std::string base_url("http://google.com/");
603 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
605 // Add 5 navigations, with the 4th selected.
606 for (int i = 0; i < 5; ++i) {
607 SerializedNavigationEntry nav =
608 SerializedNavigationEntryTestHelper::CreateNavigation(
609 base_url + base::IntToString(i), "a");
611 UpdateNavigation(window_id, tab_id, nav, (i == 3));
614 // Prune the first two navigations from the front.
615 helper_.service()->TabNavigationPathPrunedFromFront(window_id, tab_id, 2);
618 ScopedVector<SessionWindow> windows;
619 ReadWindows(&(windows.get()), NULL);
621 ASSERT_EQ(1U, windows.size());
622 ASSERT_EQ(0, windows[0]->selected_tab_index);
623 ASSERT_EQ(window_id.id(), windows[0]->window_id.id());
624 ASSERT_EQ(1U, windows[0]->tabs.size());
626 // There shouldn't be an app id.
627 EXPECT_TRUE(windows[0]->tabs[0]->extension_app_id.empty());
629 // We should be left with three navigations, the 2nd selected.
630 SessionTab* tab = windows[0]->tabs[0];
631 ASSERT_EQ(1, tab->current_navigation_index);
632 EXPECT_EQ(3U, tab->navigations.size());
633 EXPECT_TRUE(GURL(base_url + base::IntToString(2)) ==
634 tab->navigations[0].virtual_url());
635 EXPECT_TRUE(GURL(base_url + base::IntToString(3)) ==
636 tab->navigations[1].virtual_url());
637 EXPECT_TRUE(GURL(base_url + base::IntToString(4)) ==
638 tab->navigations[2].virtual_url());
641 // Prunes from front so that we have no entries.
642 TEST_F(SessionServiceTest, PruneToEmpty) {
643 const std::string base_url("http://google.com/");
646 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
648 // Add 5 navigations, with the 4th selected.
649 for (int i = 0; i < 5; ++i) {
650 SerializedNavigationEntry nav =
651 SerializedNavigationEntryTestHelper::CreateNavigation(
652 base_url + base::IntToString(i), "a");
654 UpdateNavigation(window_id, tab_id, nav, (i == 3));
657 // Prune the first two navigations from the front.
658 helper_.service()->TabNavigationPathPrunedFromFront(window_id, tab_id, 5);
661 ScopedVector<SessionWindow> windows;
662 ReadWindows(&(windows.get()), NULL);
664 ASSERT_EQ(0U, windows.size());
667 // Don't set the pinned state and make sure the pinned value is false.
668 TEST_F(SessionServiceTest, PinnedDefaultsToFalse) {
669 EXPECT_FALSE(CreateAndWriteSessionWithOneTab(false, false));
672 // Explicitly set the pinned state to false and make sure we get back false.
673 TEST_F(SessionServiceTest, PinnedFalseWhenSetToFalse) {
674 EXPECT_FALSE(CreateAndWriteSessionWithOneTab(false, true));
677 // Explicitly set the pinned state to true and make sure we get back true.
678 TEST_F(SessionServiceTest, PinnedTrue) {
679 EXPECT_TRUE(CreateAndWriteSessionWithOneTab(true, true));
682 // Make sure application extension ids are persisted.
683 TEST_F(SessionServiceTest, PersistApplicationExtensionID) {
685 ASSERT_NE(window_id.id(), tab_id.id());
686 std::string app_id("foo");
688 SerializedNavigationEntry nav1 =
689 SerializedNavigationEntryTestHelper::CreateNavigation(
690 "http://google.com", "abc");
692 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
693 UpdateNavigation(window_id, tab_id, nav1, true);
694 helper_.SetTabExtensionAppID(window_id, tab_id, app_id);
696 ScopedVector<SessionWindow> windows;
697 ReadWindows(&(windows.get()), NULL);
699 helper_.AssertSingleWindowWithSingleTab(windows.get(), 1);
700 EXPECT_TRUE(app_id == windows[0]->tabs[0]->extension_app_id);
703 // Check that user agent overrides are persisted.
704 TEST_F(SessionServiceTest, PersistUserAgentOverrides) {
706 ASSERT_NE(window_id.id(), tab_id.id());
707 std::string user_agent_override = "Mozilla/5.0 (X11; Linux x86_64) "
708 "AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.45 "
711 SerializedNavigationEntry nav1 =
712 SerializedNavigationEntryTestHelper::CreateNavigation(
713 "http://google.com", "abc");
714 SerializedNavigationEntryTestHelper::SetIsOverridingUserAgent(true, &nav1);
716 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
717 UpdateNavigation(window_id, tab_id, nav1, true);
718 helper_.SetTabUserAgentOverride(window_id, tab_id, user_agent_override);
720 ScopedVector<SessionWindow> windows;
721 ReadWindows(&(windows.get()), NULL);
722 helper_.AssertSingleWindowWithSingleTab(windows.get(), 1);
724 SessionTab* tab = windows[0]->tabs[0];
725 helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
726 helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
727 EXPECT_TRUE(user_agent_override == tab->user_agent_override);
730 // Test that the notification for SESSION_SERVICE_SAVED is working properly.
731 TEST_F(SessionServiceTest, SavedSessionNotification) {
732 content::NotificationRegistrar registrar_;
733 registrar_.Add(this, chrome::NOTIFICATION_SESSION_SERVICE_SAVED,
734 content::NotificationService::AllSources());
736 EXPECT_EQ(sync_save_count_, 1);
739 // Makes sure a tab closed by a user gesture is not restored.
740 TEST_F(SessionServiceTest, CloseTabUserGesture) {
742 ASSERT_NE(window_id.id(), tab_id.id());
744 SerializedNavigationEntry nav1 =
745 SerializedNavigationEntryTestHelper::CreateNavigation(
746 "http://google.com", "abc");
748 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
749 UpdateNavigation(window_id, tab_id, nav1, true);
750 service()->TabClosed(window_id, tab_id, true);
752 ScopedVector<SessionWindow> windows;
753 ReadWindows(&(windows.get()), NULL);
755 ASSERT_TRUE(windows.empty());
758 // Verifies SetWindowBounds maps SHOW_STATE_DEFAULT to SHOW_STATE_NORMAL.
759 TEST_F(SessionServiceTest, DontPersistDefault) {
761 ASSERT_NE(window_id.id(), tab_id.id());
762 SerializedNavigationEntry nav1 =
763 SerializedNavigationEntryTestHelper::CreateNavigation(
764 "http://google.com", "abc");
765 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
766 UpdateNavigation(window_id, tab_id, nav1, true);
767 service()->SetWindowBounds(window_id,
769 ui::SHOW_STATE_DEFAULT);
771 ScopedVector<SessionWindow> windows;
772 ReadWindows(&(windows.get()), NULL);
773 ASSERT_EQ(1U, windows.size());
774 EXPECT_EQ(ui::SHOW_STATE_NORMAL, windows[0]->show_state);
777 TEST_F(SessionServiceTest, KeepPostDataWithoutPasswords) {
779 ASSERT_NE(window_id.id(), tab_id.id());
781 // Create a page state representing a HTTP body without posted passwords.
782 content::PageState page_state =
783 content::PageState::CreateForTesting(GURL(), false, "data", NULL);
785 // Create a TabNavigation containing page_state and representing a POST
787 SerializedNavigationEntry nav1 =
788 SerializedNavigationEntryTestHelper::CreateNavigation(
789 "http://google.com", "title");
790 SerializedNavigationEntryTestHelper::SetPageState(page_state, &nav1);
791 SerializedNavigationEntryTestHelper::SetHasPostData(true, &nav1);
793 // Create a TabNavigation containing page_state and representing a normal
795 SerializedNavigationEntry nav2 =
796 SerializedNavigationEntryTestHelper::CreateNavigation(
797 "http://google.com/nopost", "title");
798 SerializedNavigationEntryTestHelper::SetPageState(page_state, &nav2);
801 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
802 UpdateNavigation(window_id, tab_id, nav1, true);
803 UpdateNavigation(window_id, tab_id, nav2, true);
805 ScopedVector<SessionWindow> windows;
806 ReadWindows(&(windows.get()), NULL);
808 helper_.AssertSingleWindowWithSingleTab(windows.get(), 2);
810 // Expected: the page state of both navigations was saved and restored.
811 ASSERT_EQ(2u, windows[0]->tabs[0]->navigations.size());
812 helper_.AssertNavigationEquals(nav1, windows[0]->tabs[0]->navigations[0]);
813 helper_.AssertNavigationEquals(nav2, windows[0]->tabs[0]->navigations[1]);
816 TEST_F(SessionServiceTest, RemovePostDataWithPasswords) {
818 ASSERT_NE(window_id.id(), tab_id.id());
820 // Create a page state representing a HTTP body with posted passwords.
821 content::PageState page_state =
822 content::PageState::CreateForTesting(GURL(), true, "data", NULL);
824 // Create a TabNavigation containing page_state and representing a POST
825 // request with passwords.
826 SerializedNavigationEntry nav1 =
827 SerializedNavigationEntryTestHelper::CreateNavigation(
828 "http://google.com", "title");
829 SerializedNavigationEntryTestHelper::SetPageState(page_state, &nav1);
830 SerializedNavigationEntryTestHelper::SetHasPostData(true, &nav1);
831 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
832 UpdateNavigation(window_id, tab_id, nav1, true);
834 ScopedVector<SessionWindow> windows;
835 ReadWindows(&(windows.get()), NULL);
837 helper_.AssertSingleWindowWithSingleTab(windows.get(), 1);
839 // Expected: the HTTP body was removed from the page state of the POST
840 // navigation with passwords.
841 EXPECT_NE(page_state, windows[0]->tabs[0]->navigations[0].page_state());
844 // This test is only applicable to chromeos.
845 #if defined(OS_CHROMEOS)
846 // Verifies migration of tab/window closed works.
847 TEST_F(SessionServiceTest, CanOpenV1TabClosed) {
848 base::FilePath v1_file_path;
849 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &v1_file_path));
850 // v1_session_file contains a tab closed command with the original id. The
851 // file was generated from ClosingTabStaysClosed. If we successfully processed
852 // the file we'll have one tab.
854 v1_file_path.AppendASCII("sessions").AppendASCII("v1_session_file");
855 base::FilePath dest_file_path(path_);
856 dest_file_path = dest_file_path.AppendASCII("Current Session");
858 // Forces closing the file.
859 helper_.SetService(NULL);
861 ASSERT_TRUE(base::CopyFile(v1_file_path, dest_file_path));
863 SessionService* session_service = new SessionService(path_);
864 helper_.SetService(session_service);
865 ScopedVector<SessionWindow> windows;
866 SessionID::id_type active_window_id = 0;
867 helper_.ReadWindows(&(windows.get()), &active_window_id);
868 ASSERT_EQ(1u, windows.size());
869 EXPECT_EQ(1u, windows[0]->tabs.size());
871 #endif // defined(OS_CHROMEOS)
873 TEST_F(SessionServiceTest, ReplacePendingNavigation) {
874 const std::string base_url("http://google.com/");
877 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
879 // Add 5 navigations, some with the same index
880 for (int i = 0; i < 5; ++i) {
881 SerializedNavigationEntry nav =
882 SerializedNavigationEntryTestHelper::CreateNavigation(
883 base_url + base::IntToString(i), "a");
884 nav.set_index(i / 2);
885 UpdateNavigation(window_id, tab_id, nav, true);
889 ScopedVector<SessionWindow> windows;
890 ReadWindows(&(windows.get()), NULL);
892 // The ones with index 0, and 2 should have been replaced by 1 and 3.
893 ASSERT_EQ(1U, windows.size());
894 ASSERT_EQ(1U, windows[0]->tabs.size());
895 EXPECT_EQ(3U, windows[0]->tabs[0]->navigations.size());
896 EXPECT_EQ(GURL(base_url + base::IntToString(1)),
897 windows[0]->tabs[0]->navigations[0].virtual_url());
898 EXPECT_EQ(GURL(base_url + base::IntToString(3)),
899 windows[0]->tabs[0]->navigations[1].virtual_url());
900 EXPECT_EQ(GURL(base_url + base::IntToString(4)),
901 windows[0]->tabs[0]->navigations[2].virtual_url());
904 TEST_F(SessionServiceTest, ReplacePendingNavigationAndPrune) {
905 const std::string base_url("http://google.com/");
908 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
910 for (int i = 0; i < 5; ++i) {
911 SerializedNavigationEntry nav =
912 SerializedNavigationEntryTestHelper::CreateNavigation(
913 base_url + base::IntToString(i), "a");
915 UpdateNavigation(window_id, tab_id, nav, true);
918 // Prune all those navigations.
919 helper_.service()->TabNavigationPathPrunedFromFront(window_id, tab_id, 5);
921 // Add another navigation to replace the last one.
922 SerializedNavigationEntry nav =
923 SerializedNavigationEntryTestHelper::CreateNavigation(
924 base_url + base::IntToString(5), "a");
926 UpdateNavigation(window_id, tab_id, nav, true);
929 ScopedVector<SessionWindow> windows;
930 ReadWindows(&(windows.get()), NULL);
932 // We should still have that last navigation at the end,
933 // even though it replaced one that was set before the prune.
934 ASSERT_EQ(1U, windows.size());
935 ASSERT_EQ(1U, windows[0]->tabs.size());
936 ASSERT_EQ(1U, windows[0]->tabs[0]->navigations.size());
937 EXPECT_EQ(GURL(base_url + base::IntToString(5)),
938 windows[0]->tabs[0]->navigations[0].virtual_url());
941 TEST_F(SessionServiceTest, RestoreActivation1) {
942 SessionID window2_id;
945 SerializedNavigationEntry nav1;
946 SerializedNavigationEntry nav2;
948 CreateAndWriteSessionWithTwoWindows(
949 window2_id, tab1_id, tab2_id, &nav1, &nav2);
951 service()->ScheduleCommand(
952 service()->CreateSetActiveWindowCommand(window2_id));
953 service()->ScheduleCommand(
954 service()->CreateSetActiveWindowCommand(window_id));
956 ScopedVector<SessionWindow> windows;
957 SessionID::id_type active_window_id = 0;
958 ReadWindows(&(windows.get()), &active_window_id);
959 EXPECT_EQ(window_id.id(), active_window_id);
962 // It's easier to have two separate tests with setup/teardown than to manualy
963 // reset the state for the different flavors of the test.
964 TEST_F(SessionServiceTest, RestoreActivation2) {
965 SessionID window2_id;
968 SerializedNavigationEntry nav1;
969 SerializedNavigationEntry nav2;
971 CreateAndWriteSessionWithTwoWindows(
972 window2_id, tab1_id, tab2_id, &nav1, &nav2);
974 service()->ScheduleCommand(
975 service()->CreateSetActiveWindowCommand(window2_id));
976 service()->ScheduleCommand(
977 service()->CreateSetActiveWindowCommand(window_id));
978 service()->ScheduleCommand(
979 service()->CreateSetActiveWindowCommand(window2_id));
981 ScopedVector<SessionWindow> windows;
982 SessionID::id_type active_window_id = 0;
983 ReadWindows(&(windows.get()), &active_window_id);
984 EXPECT_EQ(window2_id.id(), active_window_id);