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/common/url_constants.h"
24 #include "chrome/test/base/browser_with_test_window_test.h"
25 #include "chrome/test/base/testing_profile.h"
26 #include "components/sessions/serialized_navigation_entry_test_helper.h"
27 #include "content/public/browser/navigation_entry.h"
28 #include "content/public/browser/notification_observer.h"
29 #include "content/public/browser/notification_registrar.h"
30 #include "content/public/browser/notification_service.h"
31 #include "content/public/common/page_state.h"
32 #include "testing/gtest/include/gtest/gtest.h"
34 using content::NavigationEntry
;
35 using sessions::SerializedNavigationEntry
;
36 using sessions::SerializedNavigationEntryTestHelper
;
38 class SessionServiceTest
: public BrowserWithTestWindowTest
,
39 public content::NotificationObserver
{
41 SessionServiceTest() : window_bounds(0, 1, 2, 3), sync_save_count_(0) {}
44 virtual void SetUp() {
45 BrowserWithTestWindowTest::SetUp();
46 std::string b
= base::Int64ToString(base::Time::Now().ToInternalValue());
48 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
49 path_
= temp_dir_
.path().Append(FILE_PATH_LITERAL("SessionTestDirs"));
50 ASSERT_TRUE(base::CreateDirectory(path_
));
51 path_
= path_
.AppendASCII(b
);
53 SessionService
* session_service
= new SessionService(path_
);
54 helper_
.SetService(session_service
);
56 service()->SetWindowType(
57 window_id
, Browser::TYPE_TABBED
, SessionService::TYPE_NORMAL
);
58 service()->SetWindowBounds(window_id
,
60 ui::SHOW_STATE_NORMAL
);
63 // Upon notification, increment the sync_save_count variable
64 virtual void Observe(int type
,
65 const content::NotificationSource
& source
,
66 const content::NotificationDetails
& details
) OVERRIDE
{
67 ASSERT_EQ(type
, chrome::NOTIFICATION_SESSION_SERVICE_SAVED
);
71 virtual void TearDown() {
72 helper_
.SetService(NULL
);
73 BrowserWithTestWindowTest::TearDown();
76 void UpdateNavigation(
77 const SessionID
& window_id
,
78 const SessionID
& tab_id
,
79 const SerializedNavigationEntry
& navigation
,
81 service()->UpdateTabNavigation(window_id
, tab_id
, navigation
);
83 service()->SetSelectedNavigationIndex(
84 window_id
, tab_id
, navigation
.index());
88 void ReadWindows(std::vector
<SessionWindow
*>* windows
,
89 SessionID::id_type
* active_window_id
) {
90 // Forces closing the file.
91 helper_
.SetService(NULL
);
93 SessionService
* session_service
= new SessionService(path_
);
94 helper_
.SetService(session_service
);
96 SessionID::id_type
* non_null_active_window_id
= active_window_id
;
97 SessionID::id_type dummy_active_window_id
= 0;
98 if (!non_null_active_window_id
)
99 non_null_active_window_id
= &dummy_active_window_id
;
100 helper_
.ReadWindows(windows
, non_null_active_window_id
);
103 // Configures the session service with one window with one tab and a single
104 // navigation. If |pinned_state| is true or |write_always| is true, the
105 // pinned state of the tab is updated. The session service is then recreated
106 // and the pinned state of the read back tab is returned.
107 bool CreateAndWriteSessionWithOneTab(bool pinned_state
, bool write_always
) {
109 SerializedNavigationEntry nav1
=
110 SerializedNavigationEntryTestHelper::CreateNavigation(
111 "http://google.com", "abc");
113 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
114 UpdateNavigation(window_id
, tab_id
, nav1
, true);
116 if (pinned_state
|| write_always
)
117 helper_
.service()->SetPinnedState(window_id
, tab_id
, pinned_state
);
119 ScopedVector
<SessionWindow
> windows
;
120 ReadWindows(&(windows
.get()), NULL
);
122 EXPECT_EQ(1U, windows
.size());
123 if (HasFatalFailure())
125 EXPECT_EQ(1U, windows
[0]->tabs
.size());
126 if (HasFatalFailure())
129 SessionTab
* tab
= windows
[0]->tabs
[0];
130 helper_
.AssertTabEquals(window_id
, tab_id
, 0, 0, 1, *tab
);
135 void CreateAndWriteSessionWithTwoWindows(
136 const SessionID
& window2_id
,
137 const SessionID
& tab1_id
,
138 const SessionID
& tab2_id
,
139 SerializedNavigationEntry
* nav1
,
140 SerializedNavigationEntry
* nav2
) {
141 *nav1
= SerializedNavigationEntryTestHelper::CreateNavigation(
142 "http://google.com", "abc");
143 *nav2
= SerializedNavigationEntryTestHelper::CreateNavigation(
144 "http://google2.com", "abcd");
146 helper_
.PrepareTabInWindow(window_id
, tab1_id
, 0, true);
147 UpdateNavigation(window_id
, tab1_id
, *nav1
, true);
149 const gfx::Rect
window2_bounds(3, 4, 5, 6);
150 service()->SetWindowType(
151 window2_id
, Browser::TYPE_TABBED
, SessionService::TYPE_NORMAL
);
152 service()->SetWindowBounds(window2_id
,
154 ui::SHOW_STATE_MAXIMIZED
);
155 helper_
.PrepareTabInWindow(window2_id
, tab2_id
, 0, true);
156 UpdateNavigation(window2_id
, tab2_id
, *nav2
, true);
159 SessionService
* service() { return helper_
.service(); }
161 SessionBackend
* backend() { return helper_
.backend(); }
163 const gfx::Rect window_bounds
;
167 int sync_save_count_
;
169 // Path used in testing.
170 base::ScopedTempDir temp_dir_
;
171 base::FilePath path_
;
173 SessionServiceTestHelper helper_
;
176 TEST_F(SessionServiceTest
, Basic
) {
178 ASSERT_NE(window_id
.id(), tab_id
.id());
180 SerializedNavigationEntry nav1
=
181 SerializedNavigationEntryTestHelper::CreateNavigation(
182 "http://google.com", "abc");
183 SerializedNavigationEntryTestHelper::SetOriginalRequestURL(
184 GURL("http://original.request.com"), &nav1
);
186 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
187 UpdateNavigation(window_id
, tab_id
, nav1
, true);
189 ScopedVector
<SessionWindow
> windows
;
190 ReadWindows(&(windows
.get()), NULL
);
192 ASSERT_EQ(1U, windows
.size());
193 ASSERT_TRUE(window_bounds
== windows
[0]->bounds
);
194 ASSERT_EQ(0, windows
[0]->selected_tab_index
);
195 ASSERT_EQ(window_id
.id(), windows
[0]->window_id
.id());
196 ASSERT_EQ(1U, windows
[0]->tabs
.size());
197 ASSERT_EQ(Browser::TYPE_TABBED
, windows
[0]->type
);
199 SessionTab
* tab
= windows
[0]->tabs
[0];
200 helper_
.AssertTabEquals(window_id
, tab_id
, 0, 0, 1, *tab
);
202 helper_
.AssertNavigationEquals(nav1
, tab
->navigations
[0]);
205 // Make sure we persist post entries.
206 TEST_F(SessionServiceTest
, PersistPostData
) {
208 ASSERT_NE(window_id
.id(), tab_id
.id());
210 SerializedNavigationEntry nav1
=
211 SerializedNavigationEntryTestHelper::CreateNavigation(
212 "http://google.com", "abc");
213 SerializedNavigationEntryTestHelper::SetHasPostData(true, &nav1
);
215 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
216 UpdateNavigation(window_id
, tab_id
, nav1
, true);
218 ScopedVector
<SessionWindow
> windows
;
219 ReadWindows(&(windows
.get()), NULL
);
221 helper_
.AssertSingleWindowWithSingleTab(windows
.get(), 1);
224 TEST_F(SessionServiceTest
, ClosingTabStaysClosed
) {
227 ASSERT_NE(tab_id
.id(), tab2_id
.id());
229 SerializedNavigationEntry nav1
=
230 SerializedNavigationEntryTestHelper::CreateNavigation(
231 "http://google.com", "abc");
232 SerializedNavigationEntry nav2
=
233 SerializedNavigationEntryTestHelper::CreateNavigation(
234 "http://google2.com", "abcd");
236 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
237 UpdateNavigation(window_id
, tab_id
, nav1
, true);
239 helper_
.PrepareTabInWindow(window_id
, tab2_id
, 1, false);
240 UpdateNavigation(window_id
, tab2_id
, nav2
, true);
241 service()->TabClosed(window_id
, tab2_id
, false);
243 ScopedVector
<SessionWindow
> windows
;
244 ReadWindows(&(windows
.get()), NULL
);
246 ASSERT_EQ(1U, windows
.size());
247 ASSERT_EQ(0, windows
[0]->selected_tab_index
);
248 ASSERT_EQ(window_id
.id(), windows
[0]->window_id
.id());
249 ASSERT_EQ(1U, windows
[0]->tabs
.size());
251 SessionTab
* tab
= windows
[0]->tabs
[0];
252 helper_
.AssertTabEquals(window_id
, tab_id
, 0, 0, 1, *tab
);
254 helper_
.AssertNavigationEquals(nav1
, tab
->navigations
[0]);
257 TEST_F(SessionServiceTest
, Pruning
) {
260 SerializedNavigationEntry nav1
=
261 SerializedNavigationEntryTestHelper::CreateNavigation(
262 "http://google.com", "abc");
263 SerializedNavigationEntry nav2
=
264 SerializedNavigationEntryTestHelper::CreateNavigation(
265 "http://google2.com", "abcd");
267 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
268 for (int i
= 0; i
< 6; ++i
) {
269 SerializedNavigationEntry
* nav
= (i
% 2) == 0 ? &nav1
: &nav2
;
271 UpdateNavigation(window_id
, tab_id
, *nav
, true);
273 service()->TabNavigationPathPrunedFromBack(window_id
, tab_id
, 3);
275 ScopedVector
<SessionWindow
> windows
;
276 ReadWindows(&(windows
.get()), NULL
);
278 ASSERT_EQ(1U, windows
.size());
279 ASSERT_EQ(0, windows
[0]->selected_tab_index
);
280 ASSERT_EQ(1U, windows
[0]->tabs
.size());
282 SessionTab
* tab
= windows
[0]->tabs
[0];
283 // We left the selected index at 5, then pruned. When rereading the
284 // index should get reset to last valid navigation, which is 2.
285 helper_
.AssertTabEquals(window_id
, tab_id
, 0, 2, 3, *tab
);
287 ASSERT_EQ(3u, tab
->navigations
.size());
288 helper_
.AssertNavigationEquals(nav1
, tab
->navigations
[0]);
289 helper_
.AssertNavigationEquals(nav2
, tab
->navigations
[1]);
290 helper_
.AssertNavigationEquals(nav1
, tab
->navigations
[2]);
293 TEST_F(SessionServiceTest
, TwoWindows
) {
294 SessionID window2_id
;
297 SerializedNavigationEntry nav1
;
298 SerializedNavigationEntry nav2
;
300 CreateAndWriteSessionWithTwoWindows(
301 window2_id
, tab1_id
, tab2_id
, &nav1
, &nav2
);
303 ScopedVector
<SessionWindow
> windows
;
304 ReadWindows(&(windows
.get()), NULL
);
306 ASSERT_EQ(2U, windows
.size());
307 ASSERT_EQ(0, windows
[0]->selected_tab_index
);
308 ASSERT_EQ(0, windows
[1]->selected_tab_index
);
309 ASSERT_EQ(1U, windows
[0]->tabs
.size());
310 ASSERT_EQ(1U, windows
[1]->tabs
.size());
314 if (windows
[0]->window_id
.id() == window_id
.id()) {
315 ASSERT_EQ(window2_id
.id(), windows
[1]->window_id
.id());
316 ASSERT_EQ(ui::SHOW_STATE_NORMAL
, windows
[0]->show_state
);
317 ASSERT_EQ(ui::SHOW_STATE_MAXIMIZED
, windows
[1]->show_state
);
318 rt1
= windows
[0]->tabs
[0];
319 rt2
= windows
[1]->tabs
[0];
321 ASSERT_EQ(window2_id
.id(), windows
[0]->window_id
.id());
322 ASSERT_EQ(window_id
.id(), windows
[1]->window_id
.id());
323 ASSERT_EQ(ui::SHOW_STATE_MAXIMIZED
, windows
[0]->show_state
);
324 ASSERT_EQ(ui::SHOW_STATE_NORMAL
, windows
[1]->show_state
);
325 rt1
= windows
[1]->tabs
[0];
326 rt2
= windows
[0]->tabs
[0];
328 SessionTab
* tab
= rt1
;
329 helper_
.AssertTabEquals(window_id
, tab1_id
, 0, 0, 1, *tab
);
330 helper_
.AssertNavigationEquals(nav1
, tab
->navigations
[0]);
333 helper_
.AssertTabEquals(window2_id
, tab2_id
, 0, 0, 1, *tab
);
334 helper_
.AssertNavigationEquals(nav2
, tab
->navigations
[0]);
337 TEST_F(SessionServiceTest
, WindowWithNoTabsGetsPruned
) {
338 SessionID window2_id
;
342 SerializedNavigationEntry nav1
=
343 SerializedNavigationEntryTestHelper::CreateNavigation(
344 "http://google.com", "abc");
346 helper_
.PrepareTabInWindow(window_id
, tab1_id
, 0, true);
347 UpdateNavigation(window_id
, tab1_id
, nav1
, true);
349 const gfx::Rect
window2_bounds(3, 4, 5, 6);
350 service()->SetWindowType(
351 window2_id
, Browser::TYPE_TABBED
, SessionService::TYPE_NORMAL
);
352 service()->SetWindowBounds(window2_id
,
354 ui::SHOW_STATE_NORMAL
);
355 helper_
.PrepareTabInWindow(window2_id
, tab2_id
, 0, true);
357 ScopedVector
<SessionWindow
> windows
;
358 ReadWindows(&(windows
.get()), NULL
);
360 ASSERT_EQ(1U, windows
.size());
361 ASSERT_EQ(0, windows
[0]->selected_tab_index
);
362 ASSERT_EQ(1U, windows
[0]->tabs
.size());
363 ASSERT_EQ(window_id
.id(), windows
[0]->window_id
.id());
365 SessionTab
* tab
= windows
[0]->tabs
[0];
366 helper_
.AssertTabEquals(window_id
, tab1_id
, 0, 0, 1, *tab
);
367 helper_
.AssertNavigationEquals(nav1
, tab
->navigations
[0]);
370 TEST_F(SessionServiceTest
, ClosingWindowDoesntCloseTabs
) {
373 ASSERT_NE(tab_id
.id(), tab2_id
.id());
375 SerializedNavigationEntry nav1
=
376 SerializedNavigationEntryTestHelper::CreateNavigation(
377 "http://google.com", "abc");
378 SerializedNavigationEntry nav2
=
379 SerializedNavigationEntryTestHelper::CreateNavigation(
380 "http://google2.com", "abcd");
382 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
383 UpdateNavigation(window_id
, tab_id
, nav1
, true);
385 helper_
.PrepareTabInWindow(window_id
, tab2_id
, 1, false);
386 UpdateNavigation(window_id
, tab2_id
, nav2
, true);
388 service()->WindowClosing(window_id
);
390 ScopedVector
<SessionWindow
> windows
;
391 ReadWindows(&(windows
.get()), NULL
);
393 ASSERT_EQ(1U, windows
.size());
394 ASSERT_EQ(0, windows
[0]->selected_tab_index
);
395 ASSERT_EQ(window_id
.id(), windows
[0]->window_id
.id());
396 ASSERT_EQ(2U, windows
[0]->tabs
.size());
398 SessionTab
* tab
= windows
[0]->tabs
[0];
399 helper_
.AssertTabEquals(window_id
, tab_id
, 0, 0, 1, *tab
);
400 helper_
.AssertNavigationEquals(nav1
, tab
->navigations
[0]);
402 tab
= windows
[0]->tabs
[1];
403 helper_
.AssertTabEquals(window_id
, tab2_id
, 1, 0, 1, *tab
);
404 helper_
.AssertNavigationEquals(nav2
, tab
->navigations
[0]);
407 TEST_F(SessionServiceTest
, WindowCloseCommittedAfterNavigate
) {
408 SessionID window2_id
;
411 ASSERT_NE(window2_id
.id(), window_id
.id());
413 service()->SetWindowType(
414 window2_id
, Browser::TYPE_TABBED
, SessionService::TYPE_NORMAL
);
415 service()->SetWindowBounds(window2_id
,
417 ui::SHOW_STATE_NORMAL
);
419 SerializedNavigationEntry nav1
=
420 SerializedNavigationEntryTestHelper::CreateNavigation(
421 "http://google.com", "abc");
422 SerializedNavigationEntry nav2
=
423 SerializedNavigationEntryTestHelper::CreateNavigation(
424 "http://google2.com", "abcd");
426 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
427 UpdateNavigation(window_id
, tab_id
, nav1
, true);
429 helper_
.PrepareTabInWindow(window2_id
, tab2_id
, 0, false);
430 UpdateNavigation(window2_id
, tab2_id
, nav2
, true);
432 service()->WindowClosing(window2_id
);
433 service()->TabClosed(window2_id
, tab2_id
, false);
434 service()->WindowClosed(window2_id
);
436 ScopedVector
<SessionWindow
> windows
;
437 ReadWindows(&(windows
.get()), NULL
);
439 ASSERT_EQ(1U, windows
.size());
440 ASSERT_EQ(0, windows
[0]->selected_tab_index
);
441 ASSERT_EQ(window_id
.id(), windows
[0]->window_id
.id());
442 ASSERT_EQ(1U, windows
[0]->tabs
.size());
444 SessionTab
* tab
= windows
[0]->tabs
[0];
445 helper_
.AssertTabEquals(window_id
, tab_id
, 0, 0, 1, *tab
);
446 helper_
.AssertNavigationEquals(nav1
, tab
->navigations
[0]);
449 // Makes sure we don't track popups.
450 TEST_F(SessionServiceTest
, IgnorePopups
) {
451 if (browser_defaults::kRestorePopups
)
452 return; // This test is only applicable if popups aren't restored.
454 SessionID window2_id
;
457 ASSERT_NE(window2_id
.id(), window_id
.id());
459 service()->SetWindowType(
460 window2_id
, Browser::TYPE_POPUP
, SessionService::TYPE_NORMAL
);
461 service()->SetWindowBounds(window2_id
,
463 ui::SHOW_STATE_NORMAL
);
465 SerializedNavigationEntry nav1
=
466 SerializedNavigationEntryTestHelper::CreateNavigation(
467 "http://google.com", "abc");
468 SerializedNavigationEntry nav2
=
469 SerializedNavigationEntryTestHelper::CreateNavigation(
470 "http://google2.com", "abcd");
472 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
473 UpdateNavigation(window_id
, tab_id
, nav1
, true);
475 helper_
.PrepareTabInWindow(window2_id
, tab2_id
, 0, false);
476 UpdateNavigation(window2_id
, tab2_id
, nav2
, true);
478 ScopedVector
<SessionWindow
> windows
;
479 ReadWindows(&(windows
.get()), NULL
);
481 ASSERT_EQ(1U, windows
.size());
482 ASSERT_EQ(0, windows
[0]->selected_tab_index
);
483 ASSERT_EQ(window_id
.id(), windows
[0]->window_id
.id());
484 ASSERT_EQ(1U, windows
[0]->tabs
.size());
486 SessionTab
* tab
= windows
[0]->tabs
[0];
487 helper_
.AssertTabEquals(window_id
, tab_id
, 0, 0, 1, *tab
);
488 helper_
.AssertNavigationEquals(nav1
, tab
->navigations
[0]);
491 // Makes sure we track popups.
492 TEST_F(SessionServiceTest
, RestorePopup
) {
493 if (!browser_defaults::kRestorePopups
)
494 return; // This test is only applicable if popups are restored.
496 SessionID window2_id
;
499 ASSERT_NE(window2_id
.id(), window_id
.id());
501 service()->SetWindowType(
502 window2_id
, Browser::TYPE_POPUP
, SessionService::TYPE_NORMAL
);
503 service()->SetWindowBounds(window2_id
,
505 ui::SHOW_STATE_NORMAL
);
507 SerializedNavigationEntry nav1
=
508 SerializedNavigationEntryTestHelper::CreateNavigation(
509 "http://google.com", "abc");
510 SerializedNavigationEntry nav2
=
511 SerializedNavigationEntryTestHelper::CreateNavigation(
512 "http://google2.com", "abcd");
514 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
515 UpdateNavigation(window_id
, tab_id
, nav1
, true);
517 helper_
.PrepareTabInWindow(window2_id
, tab2_id
, 0, false);
518 UpdateNavigation(window2_id
, tab2_id
, nav2
, true);
520 ScopedVector
<SessionWindow
> windows
;
521 ReadWindows(&(windows
.get()), NULL
);
523 ASSERT_EQ(2U, windows
.size());
524 int tabbed_index
= windows
[0]->type
== Browser::TYPE_TABBED
?
526 int popup_index
= tabbed_index
== 0 ? 1 : 0;
527 ASSERT_EQ(0, windows
[tabbed_index
]->selected_tab_index
);
528 ASSERT_EQ(window_id
.id(), windows
[tabbed_index
]->window_id
.id());
529 ASSERT_EQ(1U, windows
[tabbed_index
]->tabs
.size());
531 SessionTab
* tab
= windows
[tabbed_index
]->tabs
[0];
532 helper_
.AssertTabEquals(window_id
, tab_id
, 0, 0, 1, *tab
);
533 helper_
.AssertNavigationEquals(nav1
, tab
->navigations
[0]);
535 ASSERT_EQ(0, windows
[popup_index
]->selected_tab_index
);
536 ASSERT_EQ(window2_id
.id(), windows
[popup_index
]->window_id
.id());
537 ASSERT_EQ(1U, windows
[popup_index
]->tabs
.size());
539 tab
= windows
[popup_index
]->tabs
[0];
540 helper_
.AssertTabEquals(window2_id
, tab2_id
, 0, 0, 1, *tab
);
541 helper_
.AssertNavigationEquals(nav2
, tab
->navigations
[0]);
544 #if defined (OS_CHROMEOS)
545 // Makes sure we track apps. Only applicable on chromeos.
546 TEST_F(SessionServiceTest
, RestoreApp
) {
547 SessionID window2_id
;
550 ASSERT_NE(window2_id
.id(), window_id
.id());
552 service()->SetWindowType(
553 window2_id
, Browser::TYPE_POPUP
, SessionService::TYPE_APP
);
554 service()->SetWindowBounds(window2_id
,
556 ui::SHOW_STATE_NORMAL
);
557 service()->SetWindowAppName(window2_id
, "TestApp");
559 SerializedNavigationEntry nav1
=
560 SerializedNavigationEntryTestHelper::CreateNavigation(
561 "http://google.com", "abc");
562 SerializedNavigationEntry nav2
=
563 SerializedNavigationEntryTestHelper::CreateNavigation(
564 "http://google2.com", "abcd");
566 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
567 UpdateNavigation(window_id
, tab_id
, nav1
, true);
569 helper_
.PrepareTabInWindow(window2_id
, tab2_id
, 0, false);
570 UpdateNavigation(window2_id
, tab2_id
, nav2
, true);
572 ScopedVector
<SessionWindow
> windows
;
573 ReadWindows(&(windows
.get()), NULL
);
575 ASSERT_EQ(2U, windows
.size());
576 int tabbed_index
= windows
[0]->type
== Browser::TYPE_TABBED
?
578 int app_index
= tabbed_index
== 0 ? 1 : 0;
579 ASSERT_EQ(0, windows
[tabbed_index
]->selected_tab_index
);
580 ASSERT_EQ(window_id
.id(), windows
[tabbed_index
]->window_id
.id());
581 ASSERT_EQ(1U, windows
[tabbed_index
]->tabs
.size());
583 SessionTab
* tab
= windows
[tabbed_index
]->tabs
[0];
584 helper_
.AssertTabEquals(window_id
, tab_id
, 0, 0, 1, *tab
);
585 helper_
.AssertNavigationEquals(nav1
, tab
->navigations
[0]);
587 ASSERT_EQ(0, windows
[app_index
]->selected_tab_index
);
588 ASSERT_EQ(window2_id
.id(), windows
[app_index
]->window_id
.id());
589 ASSERT_EQ(1U, windows
[app_index
]->tabs
.size());
590 ASSERT_TRUE(windows
[app_index
]->type
== Browser::TYPE_POPUP
);
591 ASSERT_EQ("TestApp", windows
[app_index
]->app_name
);
593 tab
= windows
[app_index
]->tabs
[0];
594 helper_
.AssertTabEquals(window2_id
, tab2_id
, 0, 0, 1, *tab
);
595 helper_
.AssertNavigationEquals(nav2
, tab
->navigations
[0]);
597 #endif // defined (OS_CHROMEOS)
599 // Tests pruning from the front.
600 TEST_F(SessionServiceTest
, PruneFromFront
) {
601 const std::string
base_url("http://google.com/");
604 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
606 // Add 5 navigations, with the 4th selected.
607 for (int i
= 0; i
< 5; ++i
) {
608 SerializedNavigationEntry nav
=
609 SerializedNavigationEntryTestHelper::CreateNavigation(
610 base_url
+ base::IntToString(i
), "a");
612 UpdateNavigation(window_id
, tab_id
, nav
, (i
== 3));
615 // Prune the first two navigations from the front.
616 helper_
.service()->TabNavigationPathPrunedFromFront(window_id
, tab_id
, 2);
619 ScopedVector
<SessionWindow
> windows
;
620 ReadWindows(&(windows
.get()), NULL
);
622 ASSERT_EQ(1U, windows
.size());
623 ASSERT_EQ(0, windows
[0]->selected_tab_index
);
624 ASSERT_EQ(window_id
.id(), windows
[0]->window_id
.id());
625 ASSERT_EQ(1U, windows
[0]->tabs
.size());
627 // There shouldn't be an app id.
628 EXPECT_TRUE(windows
[0]->tabs
[0]->extension_app_id
.empty());
630 // We should be left with three navigations, the 2nd selected.
631 SessionTab
* tab
= windows
[0]->tabs
[0];
632 ASSERT_EQ(1, tab
->current_navigation_index
);
633 EXPECT_EQ(3U, tab
->navigations
.size());
634 EXPECT_TRUE(GURL(base_url
+ base::IntToString(2)) ==
635 tab
->navigations
[0].virtual_url());
636 EXPECT_TRUE(GURL(base_url
+ base::IntToString(3)) ==
637 tab
->navigations
[1].virtual_url());
638 EXPECT_TRUE(GURL(base_url
+ base::IntToString(4)) ==
639 tab
->navigations
[2].virtual_url());
642 // Prunes from front so that we have no entries.
643 TEST_F(SessionServiceTest
, PruneToEmpty
) {
644 const std::string
base_url("http://google.com/");
647 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
649 // Add 5 navigations, with the 4th selected.
650 for (int i
= 0; i
< 5; ++i
) {
651 SerializedNavigationEntry nav
=
652 SerializedNavigationEntryTestHelper::CreateNavigation(
653 base_url
+ base::IntToString(i
), "a");
655 UpdateNavigation(window_id
, tab_id
, nav
, (i
== 3));
658 // Prune the first two navigations from the front.
659 helper_
.service()->TabNavigationPathPrunedFromFront(window_id
, tab_id
, 5);
662 ScopedVector
<SessionWindow
> windows
;
663 ReadWindows(&(windows
.get()), NULL
);
665 ASSERT_EQ(0U, windows
.size());
668 // Don't set the pinned state and make sure the pinned value is false.
669 TEST_F(SessionServiceTest
, PinnedDefaultsToFalse
) {
670 EXPECT_FALSE(CreateAndWriteSessionWithOneTab(false, false));
673 // Explicitly set the pinned state to false and make sure we get back false.
674 TEST_F(SessionServiceTest
, PinnedFalseWhenSetToFalse
) {
675 EXPECT_FALSE(CreateAndWriteSessionWithOneTab(false, true));
678 // Explicitly set the pinned state to true and make sure we get back true.
679 TEST_F(SessionServiceTest
, PinnedTrue
) {
680 EXPECT_TRUE(CreateAndWriteSessionWithOneTab(true, true));
683 // Make sure application extension ids are persisted.
684 TEST_F(SessionServiceTest
, PersistApplicationExtensionID
) {
686 ASSERT_NE(window_id
.id(), tab_id
.id());
687 std::string
app_id("foo");
689 SerializedNavigationEntry nav1
=
690 SerializedNavigationEntryTestHelper::CreateNavigation(
691 "http://google.com", "abc");
693 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
694 UpdateNavigation(window_id
, tab_id
, nav1
, true);
695 helper_
.SetTabExtensionAppID(window_id
, tab_id
, app_id
);
697 ScopedVector
<SessionWindow
> windows
;
698 ReadWindows(&(windows
.get()), NULL
);
700 helper_
.AssertSingleWindowWithSingleTab(windows
.get(), 1);
701 EXPECT_TRUE(app_id
== windows
[0]->tabs
[0]->extension_app_id
);
704 // Check that user agent overrides are persisted.
705 TEST_F(SessionServiceTest
, PersistUserAgentOverrides
) {
707 ASSERT_NE(window_id
.id(), tab_id
.id());
708 std::string user_agent_override
= "Mozilla/5.0 (X11; Linux x86_64) "
709 "AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.45 "
712 SerializedNavigationEntry nav1
=
713 SerializedNavigationEntryTestHelper::CreateNavigation(
714 "http://google.com", "abc");
715 SerializedNavigationEntryTestHelper::SetIsOverridingUserAgent(true, &nav1
);
717 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
718 UpdateNavigation(window_id
, tab_id
, nav1
, true);
719 helper_
.SetTabUserAgentOverride(window_id
, tab_id
, user_agent_override
);
721 ScopedVector
<SessionWindow
> windows
;
722 ReadWindows(&(windows
.get()), NULL
);
723 helper_
.AssertSingleWindowWithSingleTab(windows
.get(), 1);
725 SessionTab
* tab
= windows
[0]->tabs
[0];
726 helper_
.AssertTabEquals(window_id
, tab_id
, 0, 0, 1, *tab
);
727 helper_
.AssertNavigationEquals(nav1
, tab
->navigations
[0]);
728 EXPECT_TRUE(user_agent_override
== tab
->user_agent_override
);
731 // Test that the notification for SESSION_SERVICE_SAVED is working properly.
732 TEST_F(SessionServiceTest
, SavedSessionNotification
) {
733 content::NotificationRegistrar registrar_
;
734 registrar_
.Add(this, chrome::NOTIFICATION_SESSION_SERVICE_SAVED
,
735 content::NotificationService::AllSources());
737 EXPECT_EQ(sync_save_count_
, 1);
740 // Makes sure a tab closed by a user gesture is not restored.
741 TEST_F(SessionServiceTest
, CloseTabUserGesture
) {
743 ASSERT_NE(window_id
.id(), tab_id
.id());
745 SerializedNavigationEntry nav1
=
746 SerializedNavigationEntryTestHelper::CreateNavigation(
747 "http://google.com", "abc");
749 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
750 UpdateNavigation(window_id
, tab_id
, nav1
, true);
751 service()->TabClosed(window_id
, tab_id
, true);
753 ScopedVector
<SessionWindow
> windows
;
754 ReadWindows(&(windows
.get()), NULL
);
756 ASSERT_TRUE(windows
.empty());
759 // Verifies SetWindowBounds maps SHOW_STATE_DEFAULT to SHOW_STATE_NORMAL.
760 TEST_F(SessionServiceTest
, DontPersistDefault
) {
762 ASSERT_NE(window_id
.id(), tab_id
.id());
763 SerializedNavigationEntry nav1
=
764 SerializedNavigationEntryTestHelper::CreateNavigation(
765 "http://google.com", "abc");
766 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
767 UpdateNavigation(window_id
, tab_id
, nav1
, true);
768 service()->SetWindowBounds(window_id
,
770 ui::SHOW_STATE_DEFAULT
);
772 ScopedVector
<SessionWindow
> windows
;
773 ReadWindows(&(windows
.get()), NULL
);
774 ASSERT_EQ(1U, windows
.size());
775 EXPECT_EQ(ui::SHOW_STATE_NORMAL
, windows
[0]->show_state
);
778 TEST_F(SessionServiceTest
, KeepPostDataWithoutPasswords
) {
780 ASSERT_NE(window_id
.id(), tab_id
.id());
782 // Create a page state representing a HTTP body without posted passwords.
783 content::PageState page_state
=
784 content::PageState::CreateForTesting(GURL(), false, "data", NULL
);
786 // Create a TabNavigation containing page_state and representing a POST
788 SerializedNavigationEntry nav1
=
789 SerializedNavigationEntryTestHelper::CreateNavigation(
790 "http://google.com", "title");
791 SerializedNavigationEntryTestHelper::SetPageState(page_state
, &nav1
);
792 SerializedNavigationEntryTestHelper::SetHasPostData(true, &nav1
);
794 // Create a TabNavigation containing page_state and representing a normal
796 SerializedNavigationEntry nav2
=
797 SerializedNavigationEntryTestHelper::CreateNavigation(
798 "http://google.com/nopost", "title");
799 SerializedNavigationEntryTestHelper::SetPageState(page_state
, &nav2
);
802 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
803 UpdateNavigation(window_id
, tab_id
, nav1
, true);
804 UpdateNavigation(window_id
, tab_id
, nav2
, true);
806 ScopedVector
<SessionWindow
> windows
;
807 ReadWindows(&(windows
.get()), NULL
);
809 helper_
.AssertSingleWindowWithSingleTab(windows
.get(), 2);
811 // Expected: the page state of both navigations was saved and restored.
812 ASSERT_EQ(2u, windows
[0]->tabs
[0]->navigations
.size());
813 helper_
.AssertNavigationEquals(nav1
, windows
[0]->tabs
[0]->navigations
[0]);
814 helper_
.AssertNavigationEquals(nav2
, windows
[0]->tabs
[0]->navigations
[1]);
817 TEST_F(SessionServiceTest
, RemovePostDataWithPasswords
) {
819 ASSERT_NE(window_id
.id(), tab_id
.id());
821 // Create a page state representing a HTTP body with posted passwords.
822 content::PageState page_state
=
823 content::PageState::CreateForTesting(GURL(), true, "data", NULL
);
825 // Create a TabNavigation containing page_state and representing a POST
826 // request with passwords.
827 SerializedNavigationEntry nav1
=
828 SerializedNavigationEntryTestHelper::CreateNavigation(
829 "http://google.com", "title");
830 SerializedNavigationEntryTestHelper::SetPageState(page_state
, &nav1
);
831 SerializedNavigationEntryTestHelper::SetHasPostData(true, &nav1
);
832 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
833 UpdateNavigation(window_id
, tab_id
, nav1
, true);
835 ScopedVector
<SessionWindow
> windows
;
836 ReadWindows(&(windows
.get()), NULL
);
838 helper_
.AssertSingleWindowWithSingleTab(windows
.get(), 1);
840 // Expected: the HTTP body was removed from the page state of the POST
841 // navigation with passwords.
842 EXPECT_NE(page_state
, windows
[0]->tabs
[0]->navigations
[0].page_state());
845 // This test is only applicable to chromeos.
846 #if defined(OS_CHROMEOS)
847 // Verifies migration of tab/window closed works.
848 TEST_F(SessionServiceTest
, CanOpenV1TabClosed
) {
849 base::FilePath v1_file_path
;
850 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA
, &v1_file_path
));
851 // v1_session_file contains a tab closed command with the original id. The
852 // file was generated from ClosingTabStaysClosed. If we successfully processed
853 // the file we'll have one tab.
855 v1_file_path
.AppendASCII("sessions").AppendASCII("v1_session_file");
856 base::FilePath
dest_file_path(path_
);
857 dest_file_path
= dest_file_path
.AppendASCII("Current Session");
859 // Forces closing the file.
860 helper_
.SetService(NULL
);
862 ASSERT_TRUE(base::CopyFile(v1_file_path
, dest_file_path
));
864 SessionService
* session_service
= new SessionService(path_
);
865 helper_
.SetService(session_service
);
866 ScopedVector
<SessionWindow
> windows
;
867 SessionID::id_type active_window_id
= 0;
868 helper_
.ReadWindows(&(windows
.get()), &active_window_id
);
869 ASSERT_EQ(1u, windows
.size());
870 EXPECT_EQ(1u, windows
[0]->tabs
.size());
872 #endif // defined(OS_CHROMEOS)
874 TEST_F(SessionServiceTest
, ReplacePendingNavigation
) {
875 const std::string
base_url("http://google.com/");
878 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
880 // Add 5 navigations, some with the same index
881 for (int i
= 0; i
< 5; ++i
) {
882 SerializedNavigationEntry nav
=
883 SerializedNavigationEntryTestHelper::CreateNavigation(
884 base_url
+ base::IntToString(i
), "a");
885 nav
.set_index(i
/ 2);
886 UpdateNavigation(window_id
, tab_id
, nav
, true);
890 ScopedVector
<SessionWindow
> windows
;
891 ReadWindows(&(windows
.get()), NULL
);
893 // The ones with index 0, and 2 should have been replaced by 1 and 3.
894 ASSERT_EQ(1U, windows
.size());
895 ASSERT_EQ(1U, windows
[0]->tabs
.size());
896 EXPECT_EQ(3U, windows
[0]->tabs
[0]->navigations
.size());
897 EXPECT_EQ(GURL(base_url
+ base::IntToString(1)),
898 windows
[0]->tabs
[0]->navigations
[0].virtual_url());
899 EXPECT_EQ(GURL(base_url
+ base::IntToString(3)),
900 windows
[0]->tabs
[0]->navigations
[1].virtual_url());
901 EXPECT_EQ(GURL(base_url
+ base::IntToString(4)),
902 windows
[0]->tabs
[0]->navigations
[2].virtual_url());
905 TEST_F(SessionServiceTest
, ReplacePendingNavigationAndPrune
) {
906 const std::string
base_url("http://google.com/");
909 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
911 for (int i
= 0; i
< 5; ++i
) {
912 SerializedNavigationEntry nav
=
913 SerializedNavigationEntryTestHelper::CreateNavigation(
914 base_url
+ base::IntToString(i
), "a");
916 UpdateNavigation(window_id
, tab_id
, nav
, true);
919 // Prune all those navigations.
920 helper_
.service()->TabNavigationPathPrunedFromFront(window_id
, tab_id
, 5);
922 // Add another navigation to replace the last one.
923 SerializedNavigationEntry nav
=
924 SerializedNavigationEntryTestHelper::CreateNavigation(
925 base_url
+ base::IntToString(5), "a");
927 UpdateNavigation(window_id
, tab_id
, nav
, true);
930 ScopedVector
<SessionWindow
> windows
;
931 ReadWindows(&(windows
.get()), NULL
);
933 // We should still have that last navigation at the end,
934 // even though it replaced one that was set before the prune.
935 ASSERT_EQ(1U, windows
.size());
936 ASSERT_EQ(1U, windows
[0]->tabs
.size());
937 ASSERT_EQ(1U, windows
[0]->tabs
[0]->navigations
.size());
938 EXPECT_EQ(GURL(base_url
+ base::IntToString(5)),
939 windows
[0]->tabs
[0]->navigations
[0].virtual_url());
942 TEST_F(SessionServiceTest
, RestoreActivation1
) {
943 SessionID window2_id
;
946 SerializedNavigationEntry nav1
;
947 SerializedNavigationEntry nav2
;
949 CreateAndWriteSessionWithTwoWindows(
950 window2_id
, tab1_id
, tab2_id
, &nav1
, &nav2
);
952 service()->ScheduleCommand(
953 service()->CreateSetActiveWindowCommand(window2_id
));
954 service()->ScheduleCommand(
955 service()->CreateSetActiveWindowCommand(window_id
));
957 ScopedVector
<SessionWindow
> windows
;
958 SessionID::id_type active_window_id
= 0;
959 ReadWindows(&(windows
.get()), &active_window_id
);
960 EXPECT_EQ(window_id
.id(), active_window_id
);
963 // It's easier to have two separate tests with setup/teardown than to manualy
964 // reset the state for the different flavors of the test.
965 TEST_F(SessionServiceTest
, RestoreActivation2
) {
966 SessionID window2_id
;
969 SerializedNavigationEntry nav1
;
970 SerializedNavigationEntry nav2
;
972 CreateAndWriteSessionWithTwoWindows(
973 window2_id
, tab1_id
, tab2_id
, &nav1
, &nav2
);
975 service()->ScheduleCommand(
976 service()->CreateSetActiveWindowCommand(window2_id
));
977 service()->ScheduleCommand(
978 service()->CreateSetActiveWindowCommand(window_id
));
979 service()->ScheduleCommand(
980 service()->CreateSetActiveWindowCommand(window2_id
));
982 ScopedVector
<SessionWindow
> windows
;
983 SessionID::id_type active_window_id
= 0;
984 ReadWindows(&(windows
.get()), &active_window_id
);
985 EXPECT_EQ(window2_id
.id(), active_window_id
);
988 // Makes sure we don't track blacklisted URLs.
989 TEST_F(SessionServiceTest
, IgnoreBlacklistedUrls
) {
992 SerializedNavigationEntry nav1
=
993 SerializedNavigationEntryTestHelper::CreateNavigation(
994 "http://google.com", "abc");
995 SerializedNavigationEntry nav2
=
996 SerializedNavigationEntryTestHelper::CreateNavigation(
997 chrome::kChromeUIQuitURL
, "quit");
998 SerializedNavigationEntry nav3
=
999 SerializedNavigationEntryTestHelper::CreateNavigation(
1000 chrome::kChromeUIRestartURL
, "restart");
1002 helper_
.PrepareTabInWindow(window_id
, tab_id
, 0, true);
1003 UpdateNavigation(window_id
, tab_id
, nav1
, true);
1004 UpdateNavigation(window_id
, tab_id
, nav2
, true);
1005 UpdateNavigation(window_id
, tab_id
, nav3
, true);
1007 ScopedVector
<SessionWindow
> windows
;
1008 ReadWindows(&(windows
.get()), NULL
);
1010 ASSERT_EQ(1U, windows
.size());
1011 ASSERT_EQ(0, windows
[0]->selected_tab_index
);
1012 ASSERT_EQ(window_id
.id(), windows
[0]->window_id
.id());
1013 ASSERT_EQ(1U, windows
[0]->tabs
.size());
1015 SessionTab
* tab
= windows
[0]->tabs
[0];
1016 helper_
.AssertTabEquals(window_id
, tab_id
, 0, 0, 1, *tab
);
1017 helper_
.AssertNavigationEquals(nav1
, tab
->navigations
[0]);