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/browser_process.h"
17 #include "chrome/browser/chrome_notification_types.h"
18 #include "chrome/browser/defaults.h"
19 #include "chrome/browser/profiles/profile_manager.h"
20 #include "chrome/browser/sessions/session_backend.h"
21 #include "chrome/browser/sessions/session_service.h"
22 #include "chrome/browser/sessions/session_service_test_helper.h"
23 #include "chrome/browser/sessions/session_types.h"
24 #include "chrome/common/chrome_paths.h"
25 #include "chrome/common/url_constants.h"
26 #include "chrome/test/base/browser_with_test_window_test.h"
27 #include "chrome/test/base/testing_browser_process.h"
28 #include "chrome/test/base/testing_profile.h"
29 #include "chrome/test/base/testing_profile_manager.h"
30 #include "components/sessions/serialized_navigation_entry_test_helper.h"
31 #include "content/public/browser/navigation_entry.h"
32 #include "content/public/browser/notification_observer.h"
33 #include "content/public/browser/notification_registrar.h"
34 #include "content/public/browser/notification_service.h"
35 #include "content/public/common/page_state.h"
36 #include "testing/gtest/include/gtest/gtest.h"
38 using content::NavigationEntry
;
39 using sessions::SerializedNavigationEntry
;
40 using sessions::SerializedNavigationEntryTestHelper
;
42 class SessionServiceTest
: public BrowserWithTestWindowTest
,
43 public content::NotificationObserver
{
45 SessionServiceTest() : window_bounds(0, 1, 2, 3), sync_save_count_(0) {}
48 virtual void SetUp() {
49 BrowserWithTestWindowTest::SetUp();
51 profile_manager_
.reset(
52 new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
53 ASSERT_TRUE(profile_manager_
->SetUp());
55 std::string b
= base::Int64ToString(base::Time::Now().ToInternalValue());
56 TestingProfile
* profile
= profile_manager_
->CreateTestingProfile(b
);
57 SessionService
* session_service
= new SessionService(profile
);
58 path_
= profile
->GetPath();
60 helper_
.SetService(session_service
);
62 service()->SetWindowType(
63 window_id
, Browser::TYPE_TABBED
, SessionService::TYPE_NORMAL
);
64 service()->SetWindowBounds(window_id
,
66 ui::SHOW_STATE_NORMAL
);
69 // Upon notification, increment the sync_save_count variable
70 virtual void Observe(int type
,
71 const content::NotificationSource
& source
,
72 const content::NotificationDetails
& details
) OVERRIDE
{
73 ASSERT_EQ(type
, chrome::NOTIFICATION_SESSION_SERVICE_SAVED
);
77 virtual void TearDown() {
78 helper_
.SetService(NULL
);
79 BrowserWithTestWindowTest::TearDown();
82 void UpdateNavigation(
83 const SessionID
& window_id
,
84 const SessionID
& tab_id
,
85 const SerializedNavigationEntry
& navigation
,
87 service()->UpdateTabNavigation(window_id
, tab_id
, navigation
);
89 service()->SetSelectedNavigationIndex(
90 window_id
, tab_id
, navigation
.index());
94 void ReadWindows(std::vector
<SessionWindow
*>* windows
,
95 SessionID::id_type
* active_window_id
) {
96 // Forces closing the file.
97 helper_
.SetService(NULL
);
99 SessionService
* session_service
= new SessionService(path_
);
100 helper_
.SetService(session_service
);
102 SessionID::id_type
* non_null_active_window_id
= active_window_id
;
103 SessionID::id_type dummy_active_window_id
= 0;
104 if (!non_null_active_window_id
)
105 non_null_active_window_id
= &dummy_active_window_id
;
106 helper_
.ReadWindows(windows
, non_null_active_window_id
);
109 // Configures the session service with one window with one tab and a single
110 // navigation. If |pinned_state| is true or |write_always| is true, the
111 // pinned state of the tab is updated. The session service is then recreated
112 // and the pinned state of the read back tab is returned.
113 bool CreateAndWriteSessionWithOneTab(bool pinned_state
, bool write_always
) {
115 SerializedNavigationEntry nav1
=
116 SerializedNavigationEntryTestHelper::CreateNavigation(
117 "http://google.com", "abc");
119 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
120 UpdateNavigation(window_id
, tab_id
, nav1
, true);
122 if (pinned_state
|| write_always
)
123 helper_
.service()->SetPinnedState(window_id
, tab_id
, pinned_state
);
125 ScopedVector
<SessionWindow
> windows
;
126 ReadWindows(&(windows
.get()), NULL
);
128 EXPECT_EQ(1U, windows
.size());
129 if (HasFatalFailure())
131 EXPECT_EQ(1U, windows
[0]->tabs
.size());
132 if (HasFatalFailure())
135 SessionTab
* tab
= windows
[0]->tabs
[0];
136 helper_
.AssertTabEquals(window_id
, tab_id
, 0, 0, 1, *tab
);
141 void CreateAndWriteSessionWithTwoWindows(
142 const SessionID
& window2_id
,
143 const SessionID
& tab1_id
,
144 const SessionID
& tab2_id
,
145 SerializedNavigationEntry
* nav1
,
146 SerializedNavigationEntry
* nav2
) {
147 *nav1
= SerializedNavigationEntryTestHelper::CreateNavigation(
148 "http://google.com", "abc");
149 *nav2
= SerializedNavigationEntryTestHelper::CreateNavigation(
150 "http://google2.com", "abcd");
152 helper_
.PrepareTabInWindow(window_id
, tab1_id
, 0, true);
153 UpdateNavigation(window_id
, tab1_id
, *nav1
, true);
155 const gfx::Rect
window2_bounds(3, 4, 5, 6);
156 service()->SetWindowType(
157 window2_id
, Browser::TYPE_TABBED
, SessionService::TYPE_NORMAL
);
158 service()->SetWindowBounds(window2_id
,
160 ui::SHOW_STATE_MAXIMIZED
);
161 helper_
.PrepareTabInWindow(window2_id
, tab2_id
, 0, true);
162 UpdateNavigation(window2_id
, tab2_id
, *nav2
, true);
165 SessionService
* service() { return helper_
.service(); }
167 SessionBackend
* backend() { return helper_
.backend(); }
169 const gfx::Rect window_bounds
;
173 int sync_save_count_
;
175 // Path used in testing.
176 base::ScopedTempDir temp_dir_
;
177 base::FilePath path_
;
179 SessionServiceTestHelper helper_
;
180 scoped_ptr
<TestingProfileManager
> profile_manager_
;
183 TEST_F(SessionServiceTest
, Basic
) {
185 ASSERT_NE(window_id
.id(), tab_id
.id());
187 SerializedNavigationEntry nav1
=
188 SerializedNavigationEntryTestHelper::CreateNavigation(
189 "http://google.com", "abc");
190 SerializedNavigationEntryTestHelper::SetOriginalRequestURL(
191 GURL("http://original.request.com"), &nav1
);
193 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
194 UpdateNavigation(window_id
, tab_id
, nav1
, true);
196 ScopedVector
<SessionWindow
> windows
;
197 ReadWindows(&(windows
.get()), NULL
);
199 ASSERT_EQ(1U, windows
.size());
200 ASSERT_TRUE(window_bounds
== windows
[0]->bounds
);
201 ASSERT_EQ(0, windows
[0]->selected_tab_index
);
202 ASSERT_EQ(window_id
.id(), windows
[0]->window_id
.id());
203 ASSERT_EQ(1U, windows
[0]->tabs
.size());
204 ASSERT_EQ(Browser::TYPE_TABBED
, windows
[0]->type
);
206 SessionTab
* tab
= windows
[0]->tabs
[0];
207 helper_
.AssertTabEquals(window_id
, tab_id
, 0, 0, 1, *tab
);
209 helper_
.AssertNavigationEquals(nav1
, tab
->navigations
[0]);
212 // Make sure we persist post entries.
213 TEST_F(SessionServiceTest
, PersistPostData
) {
215 ASSERT_NE(window_id
.id(), tab_id
.id());
217 SerializedNavigationEntry nav1
=
218 SerializedNavigationEntryTestHelper::CreateNavigation(
219 "http://google.com", "abc");
220 SerializedNavigationEntryTestHelper::SetHasPostData(true, &nav1
);
222 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
223 UpdateNavigation(window_id
, tab_id
, nav1
, true);
225 ScopedVector
<SessionWindow
> windows
;
226 ReadWindows(&(windows
.get()), NULL
);
228 helper_
.AssertSingleWindowWithSingleTab(windows
.get(), 1);
231 TEST_F(SessionServiceTest
, ClosingTabStaysClosed
) {
234 ASSERT_NE(tab_id
.id(), tab2_id
.id());
236 SerializedNavigationEntry nav1
=
237 SerializedNavigationEntryTestHelper::CreateNavigation(
238 "http://google.com", "abc");
239 SerializedNavigationEntry nav2
=
240 SerializedNavigationEntryTestHelper::CreateNavigation(
241 "http://google2.com", "abcd");
243 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
244 UpdateNavigation(window_id
, tab_id
, nav1
, true);
246 helper_
.PrepareTabInWindow(window_id
, tab2_id
, 1, false);
247 UpdateNavigation(window_id
, tab2_id
, nav2
, true);
248 service()->TabClosed(window_id
, tab2_id
, false);
250 ScopedVector
<SessionWindow
> windows
;
251 ReadWindows(&(windows
.get()), NULL
);
253 ASSERT_EQ(1U, windows
.size());
254 ASSERT_EQ(0, windows
[0]->selected_tab_index
);
255 ASSERT_EQ(window_id
.id(), windows
[0]->window_id
.id());
256 ASSERT_EQ(1U, windows
[0]->tabs
.size());
258 SessionTab
* tab
= windows
[0]->tabs
[0];
259 helper_
.AssertTabEquals(window_id
, tab_id
, 0, 0, 1, *tab
);
261 helper_
.AssertNavigationEquals(nav1
, tab
->navigations
[0]);
264 TEST_F(SessionServiceTest
, Pruning
) {
267 SerializedNavigationEntry nav1
=
268 SerializedNavigationEntryTestHelper::CreateNavigation(
269 "http://google.com", "abc");
270 SerializedNavigationEntry nav2
=
271 SerializedNavigationEntryTestHelper::CreateNavigation(
272 "http://google2.com", "abcd");
274 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
275 for (int i
= 0; i
< 6; ++i
) {
276 SerializedNavigationEntry
* nav
= (i
% 2) == 0 ? &nav1
: &nav2
;
278 UpdateNavigation(window_id
, tab_id
, *nav
, true);
280 service()->TabNavigationPathPrunedFromBack(window_id
, tab_id
, 3);
282 ScopedVector
<SessionWindow
> windows
;
283 ReadWindows(&(windows
.get()), NULL
);
285 ASSERT_EQ(1U, windows
.size());
286 ASSERT_EQ(0, windows
[0]->selected_tab_index
);
287 ASSERT_EQ(1U, windows
[0]->tabs
.size());
289 SessionTab
* tab
= windows
[0]->tabs
[0];
290 // We left the selected index at 5, then pruned. When rereading the
291 // index should get reset to last valid navigation, which is 2.
292 helper_
.AssertTabEquals(window_id
, tab_id
, 0, 2, 3, *tab
);
294 ASSERT_EQ(3u, tab
->navigations
.size());
295 helper_
.AssertNavigationEquals(nav1
, tab
->navigations
[0]);
296 helper_
.AssertNavigationEquals(nav2
, tab
->navigations
[1]);
297 helper_
.AssertNavigationEquals(nav1
, tab
->navigations
[2]);
300 TEST_F(SessionServiceTest
, TwoWindows
) {
301 SessionID window2_id
;
304 SerializedNavigationEntry nav1
;
305 SerializedNavigationEntry nav2
;
307 CreateAndWriteSessionWithTwoWindows(
308 window2_id
, tab1_id
, tab2_id
, &nav1
, &nav2
);
310 ScopedVector
<SessionWindow
> windows
;
311 ReadWindows(&(windows
.get()), NULL
);
313 ASSERT_EQ(2U, windows
.size());
314 ASSERT_EQ(0, windows
[0]->selected_tab_index
);
315 ASSERT_EQ(0, windows
[1]->selected_tab_index
);
316 ASSERT_EQ(1U, windows
[0]->tabs
.size());
317 ASSERT_EQ(1U, windows
[1]->tabs
.size());
321 if (windows
[0]->window_id
.id() == window_id
.id()) {
322 ASSERT_EQ(window2_id
.id(), windows
[1]->window_id
.id());
323 ASSERT_EQ(ui::SHOW_STATE_NORMAL
, windows
[0]->show_state
);
324 ASSERT_EQ(ui::SHOW_STATE_MAXIMIZED
, windows
[1]->show_state
);
325 rt1
= windows
[0]->tabs
[0];
326 rt2
= windows
[1]->tabs
[0];
328 ASSERT_EQ(window2_id
.id(), windows
[0]->window_id
.id());
329 ASSERT_EQ(window_id
.id(), windows
[1]->window_id
.id());
330 ASSERT_EQ(ui::SHOW_STATE_MAXIMIZED
, windows
[0]->show_state
);
331 ASSERT_EQ(ui::SHOW_STATE_NORMAL
, windows
[1]->show_state
);
332 rt1
= windows
[1]->tabs
[0];
333 rt2
= windows
[0]->tabs
[0];
335 SessionTab
* tab
= rt1
;
336 helper_
.AssertTabEquals(window_id
, tab1_id
, 0, 0, 1, *tab
);
337 helper_
.AssertNavigationEquals(nav1
, tab
->navigations
[0]);
340 helper_
.AssertTabEquals(window2_id
, tab2_id
, 0, 0, 1, *tab
);
341 helper_
.AssertNavigationEquals(nav2
, tab
->navigations
[0]);
344 TEST_F(SessionServiceTest
, WindowWithNoTabsGetsPruned
) {
345 SessionID window2_id
;
349 SerializedNavigationEntry nav1
=
350 SerializedNavigationEntryTestHelper::CreateNavigation(
351 "http://google.com", "abc");
353 helper_
.PrepareTabInWindow(window_id
, tab1_id
, 0, true);
354 UpdateNavigation(window_id
, tab1_id
, nav1
, true);
356 const gfx::Rect
window2_bounds(3, 4, 5, 6);
357 service()->SetWindowType(
358 window2_id
, Browser::TYPE_TABBED
, SessionService::TYPE_NORMAL
);
359 service()->SetWindowBounds(window2_id
,
361 ui::SHOW_STATE_NORMAL
);
362 helper_
.PrepareTabInWindow(window2_id
, tab2_id
, 0, true);
364 ScopedVector
<SessionWindow
> windows
;
365 ReadWindows(&(windows
.get()), NULL
);
367 ASSERT_EQ(1U, windows
.size());
368 ASSERT_EQ(0, windows
[0]->selected_tab_index
);
369 ASSERT_EQ(1U, windows
[0]->tabs
.size());
370 ASSERT_EQ(window_id
.id(), windows
[0]->window_id
.id());
372 SessionTab
* tab
= windows
[0]->tabs
[0];
373 helper_
.AssertTabEquals(window_id
, tab1_id
, 0, 0, 1, *tab
);
374 helper_
.AssertNavigationEquals(nav1
, tab
->navigations
[0]);
377 TEST_F(SessionServiceTest
, ClosingWindowDoesntCloseTabs
) {
380 ASSERT_NE(tab_id
.id(), tab2_id
.id());
382 SerializedNavigationEntry nav1
=
383 SerializedNavigationEntryTestHelper::CreateNavigation(
384 "http://google.com", "abc");
385 SerializedNavigationEntry nav2
=
386 SerializedNavigationEntryTestHelper::CreateNavigation(
387 "http://google2.com", "abcd");
389 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
390 UpdateNavigation(window_id
, tab_id
, nav1
, true);
392 helper_
.PrepareTabInWindow(window_id
, tab2_id
, 1, false);
393 UpdateNavigation(window_id
, tab2_id
, nav2
, true);
395 service()->WindowClosing(window_id
);
397 ScopedVector
<SessionWindow
> windows
;
398 ReadWindows(&(windows
.get()), NULL
);
400 ASSERT_EQ(1U, windows
.size());
401 ASSERT_EQ(0, windows
[0]->selected_tab_index
);
402 ASSERT_EQ(window_id
.id(), windows
[0]->window_id
.id());
403 ASSERT_EQ(2U, windows
[0]->tabs
.size());
405 SessionTab
* tab
= windows
[0]->tabs
[0];
406 helper_
.AssertTabEquals(window_id
, tab_id
, 0, 0, 1, *tab
);
407 helper_
.AssertNavigationEquals(nav1
, tab
->navigations
[0]);
409 tab
= windows
[0]->tabs
[1];
410 helper_
.AssertTabEquals(window_id
, tab2_id
, 1, 0, 1, *tab
);
411 helper_
.AssertNavigationEquals(nav2
, tab
->navigations
[0]);
414 TEST_F(SessionServiceTest
, LockingWindowRemembersAll
) {
415 SessionID window2_id
;
418 SerializedNavigationEntry nav1
;
419 SerializedNavigationEntry nav2
;
421 CreateAndWriteSessionWithTwoWindows(
422 window2_id
, tab1_id
, tab2_id
, &nav1
, &nav2
);
424 ASSERT_TRUE(service()->profile() != NULL
);
425 ASSERT_TRUE(g_browser_process
->profile_manager() != NULL
);
426 ProfileInfoCache
& profile_info
=
427 g_browser_process
->profile_manager()->GetProfileInfoCache();
428 size_t profile_index
= profile_info
.GetIndexOfProfileWithPath(
429 service()->profile()->GetPath());
430 ASSERT_NE(std::string::npos
, profile_index
);
431 profile_info
.SetProfileSigninRequiredAtIndex(profile_index
, true);
433 service()->WindowClosing(window_id
);
434 service()->WindowClosed(window_id
);
435 service()->WindowClosing(window2_id
);
436 service()->WindowClosed(window2_id
);
438 ScopedVector
<SessionWindow
> windows
;
439 ReadWindows(&(windows
.get()), NULL
);
441 ASSERT_EQ(2U, windows
.size());
442 ASSERT_EQ(1U, windows
[0]->tabs
.size());
443 ASSERT_EQ(1U, windows
[1]->tabs
.size());
446 TEST_F(SessionServiceTest
, WindowCloseCommittedAfterNavigate
) {
447 SessionID window2_id
;
450 ASSERT_NE(window2_id
.id(), window_id
.id());
452 service()->SetWindowType(
453 window2_id
, Browser::TYPE_TABBED
, SessionService::TYPE_NORMAL
);
454 service()->SetWindowBounds(window2_id
,
456 ui::SHOW_STATE_NORMAL
);
458 SerializedNavigationEntry nav1
=
459 SerializedNavigationEntryTestHelper::CreateNavigation(
460 "http://google.com", "abc");
461 SerializedNavigationEntry nav2
=
462 SerializedNavigationEntryTestHelper::CreateNavigation(
463 "http://google2.com", "abcd");
465 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
466 UpdateNavigation(window_id
, tab_id
, nav1
, true);
468 helper_
.PrepareTabInWindow(window2_id
, tab2_id
, 0, false);
469 UpdateNavigation(window2_id
, tab2_id
, nav2
, true);
471 service()->WindowClosing(window2_id
);
472 service()->TabClosed(window2_id
, tab2_id
, false);
473 service()->WindowClosed(window2_id
);
475 ScopedVector
<SessionWindow
> windows
;
476 ReadWindows(&(windows
.get()), NULL
);
478 ASSERT_EQ(1U, windows
.size());
479 ASSERT_EQ(0, windows
[0]->selected_tab_index
);
480 ASSERT_EQ(window_id
.id(), windows
[0]->window_id
.id());
481 ASSERT_EQ(1U, windows
[0]->tabs
.size());
483 SessionTab
* tab
= windows
[0]->tabs
[0];
484 helper_
.AssertTabEquals(window_id
, tab_id
, 0, 0, 1, *tab
);
485 helper_
.AssertNavigationEquals(nav1
, tab
->navigations
[0]);
488 // Makes sure we don't track popups.
489 TEST_F(SessionServiceTest
, IgnorePopups
) {
490 SessionID window2_id
;
493 ASSERT_NE(window2_id
.id(), window_id
.id());
495 service()->SetWindowType(
496 window2_id
, Browser::TYPE_POPUP
, SessionService::TYPE_NORMAL
);
497 service()->SetWindowBounds(window2_id
,
499 ui::SHOW_STATE_NORMAL
);
501 SerializedNavigationEntry nav1
=
502 SerializedNavigationEntryTestHelper::CreateNavigation(
503 "http://google.com", "abc");
504 SerializedNavigationEntry nav2
=
505 SerializedNavigationEntryTestHelper::CreateNavigation(
506 "http://google2.com", "abcd");
508 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
509 UpdateNavigation(window_id
, tab_id
, nav1
, true);
511 helper_
.PrepareTabInWindow(window2_id
, tab2_id
, 0, false);
512 UpdateNavigation(window2_id
, tab2_id
, nav2
, true);
514 ScopedVector
<SessionWindow
> windows
;
515 ReadWindows(&(windows
.get()), NULL
);
517 ASSERT_EQ(1U, windows
.size());
518 ASSERT_EQ(0, windows
[0]->selected_tab_index
);
519 ASSERT_EQ(window_id
.id(), windows
[0]->window_id
.id());
520 ASSERT_EQ(1U, windows
[0]->tabs
.size());
522 SessionTab
* tab
= windows
[0]->tabs
[0];
523 helper_
.AssertTabEquals(window_id
, tab_id
, 0, 0, 1, *tab
);
524 helper_
.AssertNavigationEquals(nav1
, tab
->navigations
[0]);
527 #if defined (OS_CHROMEOS)
528 // Makes sure we track apps. Only applicable on chromeos.
529 TEST_F(SessionServiceTest
, RestoreApp
) {
530 SessionID window2_id
;
533 ASSERT_NE(window2_id
.id(), window_id
.id());
535 service()->SetWindowType(
536 window2_id
, Browser::TYPE_POPUP
, SessionService::TYPE_APP
);
537 service()->SetWindowBounds(window2_id
,
539 ui::SHOW_STATE_NORMAL
);
540 service()->SetWindowAppName(window2_id
, "TestApp");
542 SerializedNavigationEntry nav1
=
543 SerializedNavigationEntryTestHelper::CreateNavigation(
544 "http://google.com", "abc");
545 SerializedNavigationEntry nav2
=
546 SerializedNavigationEntryTestHelper::CreateNavigation(
547 "http://google2.com", "abcd");
549 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
550 UpdateNavigation(window_id
, tab_id
, nav1
, true);
552 helper_
.PrepareTabInWindow(window2_id
, tab2_id
, 0, false);
553 UpdateNavigation(window2_id
, tab2_id
, nav2
, true);
555 ScopedVector
<SessionWindow
> windows
;
556 ReadWindows(&(windows
.get()), NULL
);
558 ASSERT_EQ(2U, windows
.size());
559 int tabbed_index
= windows
[0]->type
== Browser::TYPE_TABBED
?
561 int app_index
= tabbed_index
== 0 ? 1 : 0;
562 ASSERT_EQ(0, windows
[tabbed_index
]->selected_tab_index
);
563 ASSERT_EQ(window_id
.id(), windows
[tabbed_index
]->window_id
.id());
564 ASSERT_EQ(1U, windows
[tabbed_index
]->tabs
.size());
566 SessionTab
* tab
= windows
[tabbed_index
]->tabs
[0];
567 helper_
.AssertTabEquals(window_id
, tab_id
, 0, 0, 1, *tab
);
568 helper_
.AssertNavigationEquals(nav1
, tab
->navigations
[0]);
570 ASSERT_EQ(0, windows
[app_index
]->selected_tab_index
);
571 ASSERT_EQ(window2_id
.id(), windows
[app_index
]->window_id
.id());
572 ASSERT_EQ(1U, windows
[app_index
]->tabs
.size());
573 ASSERT_TRUE(windows
[app_index
]->type
== Browser::TYPE_POPUP
);
574 ASSERT_EQ("TestApp", windows
[app_index
]->app_name
);
576 tab
= windows
[app_index
]->tabs
[0];
577 helper_
.AssertTabEquals(window2_id
, tab2_id
, 0, 0, 1, *tab
);
578 helper_
.AssertNavigationEquals(nav2
, tab
->navigations
[0]);
580 #endif // defined (OS_CHROMEOS)
582 // Tests pruning from the front.
583 TEST_F(SessionServiceTest
, PruneFromFront
) {
584 const std::string
base_url("http://google.com/");
587 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
589 // Add 5 navigations, with the 4th selected.
590 for (int i
= 0; i
< 5; ++i
) {
591 SerializedNavigationEntry nav
=
592 SerializedNavigationEntryTestHelper::CreateNavigation(
593 base_url
+ base::IntToString(i
), "a");
595 UpdateNavigation(window_id
, tab_id
, nav
, (i
== 3));
598 // Prune the first two navigations from the front.
599 helper_
.service()->TabNavigationPathPrunedFromFront(window_id
, tab_id
, 2);
602 ScopedVector
<SessionWindow
> windows
;
603 ReadWindows(&(windows
.get()), NULL
);
605 ASSERT_EQ(1U, windows
.size());
606 ASSERT_EQ(0, windows
[0]->selected_tab_index
);
607 ASSERT_EQ(window_id
.id(), windows
[0]->window_id
.id());
608 ASSERT_EQ(1U, windows
[0]->tabs
.size());
610 // There shouldn't be an app id.
611 EXPECT_TRUE(windows
[0]->tabs
[0]->extension_app_id
.empty());
613 // We should be left with three navigations, the 2nd selected.
614 SessionTab
* tab
= windows
[0]->tabs
[0];
615 ASSERT_EQ(1, tab
->current_navigation_index
);
616 EXPECT_EQ(3U, tab
->navigations
.size());
617 EXPECT_TRUE(GURL(base_url
+ base::IntToString(2)) ==
618 tab
->navigations
[0].virtual_url());
619 EXPECT_TRUE(GURL(base_url
+ base::IntToString(3)) ==
620 tab
->navigations
[1].virtual_url());
621 EXPECT_TRUE(GURL(base_url
+ base::IntToString(4)) ==
622 tab
->navigations
[2].virtual_url());
625 // Prunes from front so that we have no entries.
626 TEST_F(SessionServiceTest
, PruneToEmpty
) {
627 const std::string
base_url("http://google.com/");
630 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
632 // Add 5 navigations, with the 4th selected.
633 for (int i
= 0; i
< 5; ++i
) {
634 SerializedNavigationEntry nav
=
635 SerializedNavigationEntryTestHelper::CreateNavigation(
636 base_url
+ base::IntToString(i
), "a");
638 UpdateNavigation(window_id
, tab_id
, nav
, (i
== 3));
641 // Prune the first two navigations from the front.
642 helper_
.service()->TabNavigationPathPrunedFromFront(window_id
, tab_id
, 5);
645 ScopedVector
<SessionWindow
> windows
;
646 ReadWindows(&(windows
.get()), NULL
);
648 ASSERT_EQ(0U, windows
.size());
651 // Don't set the pinned state and make sure the pinned value is false.
652 TEST_F(SessionServiceTest
, PinnedDefaultsToFalse
) {
653 EXPECT_FALSE(CreateAndWriteSessionWithOneTab(false, false));
656 // Explicitly set the pinned state to false and make sure we get back false.
657 TEST_F(SessionServiceTest
, PinnedFalseWhenSetToFalse
) {
658 EXPECT_FALSE(CreateAndWriteSessionWithOneTab(false, true));
661 // Explicitly set the pinned state to true and make sure we get back true.
662 TEST_F(SessionServiceTest
, PinnedTrue
) {
663 EXPECT_TRUE(CreateAndWriteSessionWithOneTab(true, true));
666 // Make sure application extension ids are persisted.
667 TEST_F(SessionServiceTest
, PersistApplicationExtensionID
) {
669 ASSERT_NE(window_id
.id(), tab_id
.id());
670 std::string
app_id("foo");
672 SerializedNavigationEntry nav1
=
673 SerializedNavigationEntryTestHelper::CreateNavigation(
674 "http://google.com", "abc");
676 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
677 UpdateNavigation(window_id
, tab_id
, nav1
, true);
678 helper_
.SetTabExtensionAppID(window_id
, tab_id
, app_id
);
680 ScopedVector
<SessionWindow
> windows
;
681 ReadWindows(&(windows
.get()), NULL
);
683 helper_
.AssertSingleWindowWithSingleTab(windows
.get(), 1);
684 EXPECT_TRUE(app_id
== windows
[0]->tabs
[0]->extension_app_id
);
687 // Check that user agent overrides are persisted.
688 TEST_F(SessionServiceTest
, PersistUserAgentOverrides
) {
690 ASSERT_NE(window_id
.id(), tab_id
.id());
691 std::string user_agent_override
= "Mozilla/5.0 (X11; Linux x86_64) "
692 "AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.45 "
695 SerializedNavigationEntry nav1
=
696 SerializedNavigationEntryTestHelper::CreateNavigation(
697 "http://google.com", "abc");
698 SerializedNavigationEntryTestHelper::SetIsOverridingUserAgent(true, &nav1
);
700 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
701 UpdateNavigation(window_id
, tab_id
, nav1
, true);
702 helper_
.SetTabUserAgentOverride(window_id
, tab_id
, user_agent_override
);
704 ScopedVector
<SessionWindow
> windows
;
705 ReadWindows(&(windows
.get()), NULL
);
706 helper_
.AssertSingleWindowWithSingleTab(windows
.get(), 1);
708 SessionTab
* tab
= windows
[0]->tabs
[0];
709 helper_
.AssertTabEquals(window_id
, tab_id
, 0, 0, 1, *tab
);
710 helper_
.AssertNavigationEquals(nav1
, tab
->navigations
[0]);
711 EXPECT_TRUE(user_agent_override
== tab
->user_agent_override
);
714 // Test that the notification for SESSION_SERVICE_SAVED is working properly.
715 TEST_F(SessionServiceTest
, SavedSessionNotification
) {
716 content::NotificationRegistrar registrar_
;
717 registrar_
.Add(this, chrome::NOTIFICATION_SESSION_SERVICE_SAVED
,
718 content::NotificationService::AllSources());
720 EXPECT_EQ(sync_save_count_
, 1);
723 // Makes sure a tab closed by a user gesture is not restored.
724 TEST_F(SessionServiceTest
, CloseTabUserGesture
) {
726 ASSERT_NE(window_id
.id(), tab_id
.id());
728 SerializedNavigationEntry nav1
=
729 SerializedNavigationEntryTestHelper::CreateNavigation(
730 "http://google.com", "abc");
732 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
733 UpdateNavigation(window_id
, tab_id
, nav1
, true);
734 service()->TabClosed(window_id
, tab_id
, true);
736 ScopedVector
<SessionWindow
> windows
;
737 ReadWindows(&(windows
.get()), NULL
);
739 ASSERT_TRUE(windows
.empty());
742 // Verifies SetWindowBounds maps SHOW_STATE_DEFAULT to SHOW_STATE_NORMAL.
743 TEST_F(SessionServiceTest
, DontPersistDefault
) {
745 ASSERT_NE(window_id
.id(), tab_id
.id());
746 SerializedNavigationEntry nav1
=
747 SerializedNavigationEntryTestHelper::CreateNavigation(
748 "http://google.com", "abc");
749 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
750 UpdateNavigation(window_id
, tab_id
, nav1
, true);
751 service()->SetWindowBounds(window_id
,
753 ui::SHOW_STATE_DEFAULT
);
755 ScopedVector
<SessionWindow
> windows
;
756 ReadWindows(&(windows
.get()), NULL
);
757 ASSERT_EQ(1U, windows
.size());
758 EXPECT_EQ(ui::SHOW_STATE_NORMAL
, windows
[0]->show_state
);
761 TEST_F(SessionServiceTest
, KeepPostDataWithoutPasswords
) {
763 ASSERT_NE(window_id
.id(), tab_id
.id());
765 // Create a page state representing a HTTP body without posted passwords.
766 content::PageState page_state
=
767 content::PageState::CreateForTesting(GURL(), false, "data", NULL
);
769 // Create a TabNavigation containing page_state and representing a POST
771 SerializedNavigationEntry nav1
=
772 SerializedNavigationEntryTestHelper::CreateNavigation(
773 "http://google.com", "title");
774 SerializedNavigationEntryTestHelper::SetPageState(page_state
, &nav1
);
775 SerializedNavigationEntryTestHelper::SetHasPostData(true, &nav1
);
777 // Create a TabNavigation containing page_state and representing a normal
779 SerializedNavigationEntry nav2
=
780 SerializedNavigationEntryTestHelper::CreateNavigation(
781 "http://google.com/nopost", "title");
782 SerializedNavigationEntryTestHelper::SetPageState(page_state
, &nav2
);
785 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
786 UpdateNavigation(window_id
, tab_id
, nav1
, true);
787 UpdateNavigation(window_id
, tab_id
, nav2
, true);
789 ScopedVector
<SessionWindow
> windows
;
790 ReadWindows(&(windows
.get()), NULL
);
792 helper_
.AssertSingleWindowWithSingleTab(windows
.get(), 2);
794 // Expected: the page state of both navigations was saved and restored.
795 ASSERT_EQ(2u, windows
[0]->tabs
[0]->navigations
.size());
796 helper_
.AssertNavigationEquals(nav1
, windows
[0]->tabs
[0]->navigations
[0]);
797 helper_
.AssertNavigationEquals(nav2
, windows
[0]->tabs
[0]->navigations
[1]);
800 TEST_F(SessionServiceTest
, RemovePostDataWithPasswords
) {
802 ASSERT_NE(window_id
.id(), tab_id
.id());
804 // Create a page state representing a HTTP body with posted passwords.
805 content::PageState page_state
=
806 content::PageState::CreateForTesting(GURL(), true, "data", NULL
);
808 // Create a TabNavigation containing page_state and representing a POST
809 // request with passwords.
810 SerializedNavigationEntry nav1
=
811 SerializedNavigationEntryTestHelper::CreateNavigation(
812 "http://google.com", "title");
813 SerializedNavigationEntryTestHelper::SetPageState(page_state
, &nav1
);
814 SerializedNavigationEntryTestHelper::SetHasPostData(true, &nav1
);
815 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
816 UpdateNavigation(window_id
, tab_id
, nav1
, true);
818 ScopedVector
<SessionWindow
> windows
;
819 ReadWindows(&(windows
.get()), NULL
);
821 helper_
.AssertSingleWindowWithSingleTab(windows
.get(), 1);
823 // Expected: the HTTP body was removed from the page state of the POST
824 // navigation with passwords.
825 EXPECT_NE(page_state
, windows
[0]->tabs
[0]->navigations
[0].page_state());
828 // This test is only applicable to chromeos.
829 #if defined(OS_CHROMEOS)
830 // Verifies migration of tab/window closed works.
831 TEST_F(SessionServiceTest
, CanOpenV1TabClosed
) {
832 base::FilePath v1_file_path
;
833 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA
, &v1_file_path
));
834 // v1_session_file contains a tab closed command with the original id. The
835 // file was generated from ClosingTabStaysClosed. If we successfully processed
836 // the file we'll have one tab.
838 v1_file_path
.AppendASCII("sessions").AppendASCII("v1_session_file");
839 base::FilePath
dest_file_path(path_
);
840 dest_file_path
= dest_file_path
.AppendASCII("Current Session");
842 // Forces closing the file.
843 helper_
.SetService(NULL
);
845 ASSERT_TRUE(base::CopyFile(v1_file_path
, dest_file_path
));
847 SessionService
* session_service
= new SessionService(path_
);
848 helper_
.SetService(session_service
);
849 ScopedVector
<SessionWindow
> windows
;
850 SessionID::id_type active_window_id
= 0;
851 helper_
.ReadWindows(&(windows
.get()), &active_window_id
);
852 ASSERT_EQ(1u, windows
.size());
853 EXPECT_EQ(1u, windows
[0]->tabs
.size());
855 #endif // defined(OS_CHROMEOS)
857 TEST_F(SessionServiceTest
, ReplacePendingNavigation
) {
858 const std::string
base_url("http://google.com/");
861 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
863 // Add 5 navigations, some with the same index
864 for (int i
= 0; i
< 5; ++i
) {
865 SerializedNavigationEntry nav
=
866 SerializedNavigationEntryTestHelper::CreateNavigation(
867 base_url
+ base::IntToString(i
), "a");
868 nav
.set_index(i
/ 2);
869 UpdateNavigation(window_id
, tab_id
, nav
, true);
873 ScopedVector
<SessionWindow
> windows
;
874 ReadWindows(&(windows
.get()), NULL
);
876 // The ones with index 0, and 2 should have been replaced by 1 and 3.
877 ASSERT_EQ(1U, windows
.size());
878 ASSERT_EQ(1U, windows
[0]->tabs
.size());
879 EXPECT_EQ(3U, windows
[0]->tabs
[0]->navigations
.size());
880 EXPECT_EQ(GURL(base_url
+ base::IntToString(1)),
881 windows
[0]->tabs
[0]->navigations
[0].virtual_url());
882 EXPECT_EQ(GURL(base_url
+ base::IntToString(3)),
883 windows
[0]->tabs
[0]->navigations
[1].virtual_url());
884 EXPECT_EQ(GURL(base_url
+ base::IntToString(4)),
885 windows
[0]->tabs
[0]->navigations
[2].virtual_url());
888 TEST_F(SessionServiceTest
, ReplacePendingNavigationAndPrune
) {
889 const std::string
base_url("http://google.com/");
892 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
894 for (int i
= 0; i
< 5; ++i
) {
895 SerializedNavigationEntry nav
=
896 SerializedNavigationEntryTestHelper::CreateNavigation(
897 base_url
+ base::IntToString(i
), "a");
899 UpdateNavigation(window_id
, tab_id
, nav
, true);
902 // Prune all those navigations.
903 helper_
.service()->TabNavigationPathPrunedFromFront(window_id
, tab_id
, 5);
905 // Add another navigation to replace the last one.
906 SerializedNavigationEntry nav
=
907 SerializedNavigationEntryTestHelper::CreateNavigation(
908 base_url
+ base::IntToString(5), "a");
910 UpdateNavigation(window_id
, tab_id
, nav
, true);
913 ScopedVector
<SessionWindow
> windows
;
914 ReadWindows(&(windows
.get()), NULL
);
916 // We should still have that last navigation at the end,
917 // even though it replaced one that was set before the prune.
918 ASSERT_EQ(1U, windows
.size());
919 ASSERT_EQ(1U, windows
[0]->tabs
.size());
920 ASSERT_EQ(1U, windows
[0]->tabs
[0]->navigations
.size());
921 EXPECT_EQ(GURL(base_url
+ base::IntToString(5)),
922 windows
[0]->tabs
[0]->navigations
[0].virtual_url());
925 TEST_F(SessionServiceTest
, RestoreActivation1
) {
926 SessionID window2_id
;
929 SerializedNavigationEntry nav1
;
930 SerializedNavigationEntry nav2
;
932 CreateAndWriteSessionWithTwoWindows(
933 window2_id
, tab1_id
, tab2_id
, &nav1
, &nav2
);
935 service()->ScheduleCommand(
936 service()->CreateSetActiveWindowCommand(window2_id
));
937 service()->ScheduleCommand(
938 service()->CreateSetActiveWindowCommand(window_id
));
940 ScopedVector
<SessionWindow
> windows
;
941 SessionID::id_type active_window_id
= 0;
942 ReadWindows(&(windows
.get()), &active_window_id
);
943 EXPECT_EQ(window_id
.id(), active_window_id
);
946 // It's easier to have two separate tests with setup/teardown than to manualy
947 // reset the state for the different flavors of the test.
948 TEST_F(SessionServiceTest
, RestoreActivation2
) {
949 SessionID window2_id
;
952 SerializedNavigationEntry nav1
;
953 SerializedNavigationEntry nav2
;
955 CreateAndWriteSessionWithTwoWindows(
956 window2_id
, tab1_id
, tab2_id
, &nav1
, &nav2
);
958 service()->ScheduleCommand(
959 service()->CreateSetActiveWindowCommand(window2_id
));
960 service()->ScheduleCommand(
961 service()->CreateSetActiveWindowCommand(window_id
));
962 service()->ScheduleCommand(
963 service()->CreateSetActiveWindowCommand(window2_id
));
965 ScopedVector
<SessionWindow
> windows
;
966 SessionID::id_type active_window_id
= 0;
967 ReadWindows(&(windows
.get()), &active_window_id
);
968 EXPECT_EQ(window2_id
.id(), active_window_id
);
971 // Makes sure we don't track blacklisted URLs.
972 TEST_F(SessionServiceTest
, IgnoreBlacklistedUrls
) {
975 SerializedNavigationEntry nav1
=
976 SerializedNavigationEntryTestHelper::CreateNavigation(
977 "http://google.com", "abc");
978 SerializedNavigationEntry nav2
=
979 SerializedNavigationEntryTestHelper::CreateNavigation(
980 chrome::kChromeUIQuitURL
, "quit");
981 SerializedNavigationEntry nav3
=
982 SerializedNavigationEntryTestHelper::CreateNavigation(
983 chrome::kChromeUIRestartURL
, "restart");
985 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
986 UpdateNavigation(window_id
, tab_id
, nav1
, true);
987 UpdateNavigation(window_id
, tab_id
, nav2
, true);
988 UpdateNavigation(window_id
, tab_id
, nav3
, true);
990 ScopedVector
<SessionWindow
> windows
;
991 ReadWindows(&(windows
.get()), NULL
);
993 ASSERT_EQ(1U, windows
.size());
994 ASSERT_EQ(0, windows
[0]->selected_tab_index
);
995 ASSERT_EQ(window_id
.id(), windows
[0]->window_id
.id());
996 ASSERT_EQ(1U, windows
[0]->tabs
.size());
998 SessionTab
* tab
= windows
[0]->tabs
[0];
999 helper_
.AssertTabEquals(window_id
, tab_id
, 0, 0, 1, *tab
);
1000 helper_
.AssertNavigationEquals(nav1
, tab
->navigations
[0]);