Add ICU message format support
[chromium-blink-merge.git] / chrome / browser / sessions / session_service_unittest.cc
blobc1a8f6b6f9d1ead998d852c4a3c31d04a4658848
1 // Copyright 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.
5 #include "base/bind.h"
6 #include "base/bind_helpers.h"
7 #include "base/files/file_util.h"
8 #include "base/files/scoped_temp_dir.h"
9 #include "base/location.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/memory/scoped_vector.h"
12 #include "base/run_loop.h"
13 #include "base/single_thread_task_runner.h"
14 #include "base/stl_util.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "base/synchronization/waitable_event.h"
18 #include "base/time/time.h"
19 #include "chrome/browser/browser_process.h"
20 #include "chrome/browser/chrome_notification_types.h"
21 #include "chrome/browser/defaults.h"
22 #include "chrome/browser/profiles/profile_manager.h"
23 #include "chrome/browser/sessions/session_service.h"
24 #include "chrome/browser/sessions/session_service_test_helper.h"
25 #include "chrome/common/chrome_paths.h"
26 #include "chrome/common/url_constants.h"
27 #include "chrome/test/base/browser_with_test_window_test.h"
28 #include "chrome/test/base/testing_browser_process.h"
29 #include "chrome/test/base/testing_profile.h"
30 #include "chrome/test/base/testing_profile_manager.h"
31 #include "components/sessions/serialized_navigation_entry_test_helper.h"
32 #include "components/sessions/session_command.h"
33 #include "components/sessions/session_types.h"
34 #include "content/public/browser/navigation_entry.h"
35 #include "content/public/browser/notification_observer.h"
36 #include "content/public/browser/notification_registrar.h"
37 #include "content/public/browser/notification_service.h"
38 #include "content/public/common/page_state.h"
39 #include "testing/gtest/include/gtest/gtest.h"
41 using content::NavigationEntry;
42 using sessions::SerializedNavigationEntry;
43 using sessions::SerializedNavigationEntryTestHelper;
45 class SessionServiceTest : public BrowserWithTestWindowTest,
46 public content::NotificationObserver {
47 public:
48 SessionServiceTest() : window_bounds(0, 1, 2, 3), sync_save_count_(0) {}
50 protected:
51 void SetUp() override {
52 BrowserWithTestWindowTest::SetUp();
54 profile_manager_.reset(
55 new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
56 ASSERT_TRUE(profile_manager_->SetUp());
58 std::string b = base::Int64ToString(base::Time::Now().ToInternalValue());
59 TestingProfile* profile = profile_manager_->CreateTestingProfile(b);
60 SessionService* session_service = new SessionService(profile);
61 path_ = profile->GetPath();
63 helper_.SetService(session_service);
65 service()->SetWindowType(window_id,
66 Browser::TYPE_TABBED,
67 SessionService::TYPE_NORMAL);
68 service()->SetWindowBounds(window_id,
69 window_bounds,
70 ui::SHOW_STATE_NORMAL);
73 // Upon notification, increment the sync_save_count variable
74 void Observe(int type,
75 const content::NotificationSource& source,
76 const content::NotificationDetails& details) override {
77 ASSERT_EQ(type, chrome::NOTIFICATION_SESSION_SERVICE_SAVED);
78 sync_save_count_++;
81 void TearDown() override {
82 helper_.SetService(NULL);
83 BrowserWithTestWindowTest::TearDown();
86 void UpdateNavigation(
87 const SessionID& window_id,
88 const SessionID& tab_id,
89 const SerializedNavigationEntry& navigation,
90 bool select) {
91 service()->UpdateTabNavigation(window_id, tab_id, navigation);
92 if (select) {
93 service()->SetSelectedNavigationIndex(
94 window_id, tab_id, navigation.index());
98 void ReadWindows(std::vector<sessions::SessionWindow*>* windows,
99 SessionID::id_type* active_window_id) {
100 // Forces closing the file.
101 helper_.SetService(NULL);
103 SessionService* session_service = new SessionService(path_);
104 helper_.SetService(session_service);
106 SessionID::id_type* non_null_active_window_id = active_window_id;
107 SessionID::id_type dummy_active_window_id = 0;
108 if (!non_null_active_window_id)
109 non_null_active_window_id = &dummy_active_window_id;
110 helper_.ReadWindows(windows, non_null_active_window_id);
113 // Configures the session service with one window with one tab and a single
114 // navigation. If |pinned_state| is true or |write_always| is true, the
115 // pinned state of the tab is updated. The session service is then recreated
116 // and the pinned state of the read back tab is returned.
117 bool CreateAndWriteSessionWithOneTab(bool pinned_state, bool write_always) {
118 SessionID tab_id;
119 SerializedNavigationEntry nav1 =
120 SerializedNavigationEntryTestHelper::CreateNavigation(
121 "http://google.com", "abc");
123 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
124 UpdateNavigation(window_id, tab_id, nav1, true);
126 if (pinned_state || write_always)
127 helper_.service()->SetPinnedState(window_id, tab_id, pinned_state);
129 ScopedVector<sessions::SessionWindow> windows;
130 ReadWindows(&(windows.get()), NULL);
132 EXPECT_EQ(1U, windows.size());
133 if (HasFatalFailure())
134 return false;
135 EXPECT_EQ(1U, windows[0]->tabs.size());
136 if (HasFatalFailure())
137 return false;
139 sessions::SessionTab* tab = windows[0]->tabs[0];
140 helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
142 return tab->pinned;
145 void CreateAndWriteSessionWithTwoWindows(
146 const SessionID& window2_id,
147 const SessionID& tab1_id,
148 const SessionID& tab2_id,
149 SerializedNavigationEntry* nav1,
150 SerializedNavigationEntry* nav2) {
151 *nav1 = SerializedNavigationEntryTestHelper::CreateNavigation(
152 "http://google.com", "abc");
153 *nav2 = SerializedNavigationEntryTestHelper::CreateNavigation(
154 "http://google2.com", "abcd");
156 helper_.PrepareTabInWindow(window_id, tab1_id, 0, true);
157 UpdateNavigation(window_id, tab1_id, *nav1, true);
159 const gfx::Rect window2_bounds(3, 4, 5, 6);
160 service()->SetWindowType(window2_id,
161 Browser::TYPE_TABBED,
162 SessionService::TYPE_NORMAL);
163 service()->SetWindowBounds(window2_id,
164 window2_bounds,
165 ui::SHOW_STATE_MAXIMIZED);
166 helper_.PrepareTabInWindow(window2_id, tab2_id, 0, true);
167 UpdateNavigation(window2_id, tab2_id, *nav2, true);
170 SessionService* service() { return helper_.service(); }
172 const gfx::Rect window_bounds;
174 SessionID window_id;
176 int sync_save_count_;
178 // Path used in testing.
179 base::ScopedTempDir temp_dir_;
180 base::FilePath path_;
182 SessionServiceTestHelper helper_;
183 scoped_ptr<TestingProfileManager> profile_manager_;
186 TEST_F(SessionServiceTest, Basic) {
187 SessionID tab_id;
188 ASSERT_NE(window_id.id(), tab_id.id());
190 SerializedNavigationEntry nav1 =
191 SerializedNavigationEntryTestHelper::CreateNavigation(
192 "http://google.com", "abc");
193 SerializedNavigationEntryTestHelper::SetOriginalRequestURL(
194 GURL("http://original.request.com"), &nav1);
196 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
197 UpdateNavigation(window_id, tab_id, nav1, true);
199 ScopedVector<sessions::SessionWindow> windows;
200 ReadWindows(&(windows.get()), NULL);
202 ASSERT_EQ(1U, windows.size());
203 ASSERT_TRUE(window_bounds == windows[0]->bounds);
204 ASSERT_EQ(0, windows[0]->selected_tab_index);
205 ASSERT_EQ(window_id.id(), windows[0]->window_id.id());
206 ASSERT_EQ(1U, windows[0]->tabs.size());
207 ASSERT_EQ(sessions::SessionWindow::TYPE_TABBED, windows[0]->type);
209 sessions::SessionTab* tab = windows[0]->tabs[0];
210 helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
212 helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
215 // Make sure we persist post entries.
216 TEST_F(SessionServiceTest, PersistPostData) {
217 SessionID tab_id;
218 ASSERT_NE(window_id.id(), tab_id.id());
220 SerializedNavigationEntry nav1 =
221 SerializedNavigationEntryTestHelper::CreateNavigation(
222 "http://google.com", "abc");
223 SerializedNavigationEntryTestHelper::SetHasPostData(true, &nav1);
225 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
226 UpdateNavigation(window_id, tab_id, nav1, true);
228 ScopedVector<sessions::SessionWindow> windows;
229 ReadWindows(&(windows.get()), NULL);
231 helper_.AssertSingleWindowWithSingleTab(windows.get(), 1);
234 TEST_F(SessionServiceTest, ClosingTabStaysClosed) {
235 SessionID tab_id;
236 SessionID tab2_id;
237 ASSERT_NE(tab_id.id(), tab2_id.id());
239 SerializedNavigationEntry nav1 =
240 SerializedNavigationEntryTestHelper::CreateNavigation(
241 "http://google.com", "abc");
242 SerializedNavigationEntry nav2 =
243 SerializedNavigationEntryTestHelper::CreateNavigation(
244 "http://google2.com", "abcd");
246 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
247 UpdateNavigation(window_id, tab_id, nav1, true);
249 helper_.PrepareTabInWindow(window_id, tab2_id, 1, false);
250 UpdateNavigation(window_id, tab2_id, nav2, true);
251 service()->TabClosed(window_id, tab2_id, false);
253 ScopedVector<sessions::SessionWindow> windows;
254 ReadWindows(&(windows.get()), NULL);
256 ASSERT_EQ(1U, windows.size());
257 ASSERT_EQ(0, windows[0]->selected_tab_index);
258 ASSERT_EQ(window_id.id(), windows[0]->window_id.id());
259 ASSERT_EQ(1U, windows[0]->tabs.size());
261 sessions::SessionTab* tab = windows[0]->tabs[0];
262 helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
264 helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
267 TEST_F(SessionServiceTest, Pruning) {
268 SessionID tab_id;
270 SerializedNavigationEntry nav1 =
271 SerializedNavigationEntryTestHelper::CreateNavigation(
272 "http://google.com", "abc");
273 SerializedNavigationEntry nav2 =
274 SerializedNavigationEntryTestHelper::CreateNavigation(
275 "http://google2.com", "abcd");
277 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
278 for (int i = 0; i < 6; ++i) {
279 SerializedNavigationEntry* nav = (i % 2) == 0 ? &nav1 : &nav2;
280 nav->set_index(i);
281 UpdateNavigation(window_id, tab_id, *nav, true);
283 service()->TabNavigationPathPrunedFromBack(window_id, tab_id, 3);
285 ScopedVector<sessions::SessionWindow> windows;
286 ReadWindows(&(windows.get()), NULL);
288 ASSERT_EQ(1U, windows.size());
289 ASSERT_EQ(0, windows[0]->selected_tab_index);
290 ASSERT_EQ(1U, windows[0]->tabs.size());
292 sessions::SessionTab* tab = windows[0]->tabs[0];
293 // We left the selected index at 5, then pruned. When rereading the
294 // index should get reset to last valid navigation, which is 2.
295 helper_.AssertTabEquals(window_id, tab_id, 0, 2, 3, *tab);
297 ASSERT_EQ(3u, tab->navigations.size());
298 helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
299 helper_.AssertNavigationEquals(nav2, tab->navigations[1]);
300 helper_.AssertNavigationEquals(nav1, tab->navigations[2]);
303 TEST_F(SessionServiceTest, TwoWindows) {
304 SessionID window2_id;
305 SessionID tab1_id;
306 SessionID tab2_id;
307 SerializedNavigationEntry nav1;
308 SerializedNavigationEntry nav2;
310 CreateAndWriteSessionWithTwoWindows(
311 window2_id, tab1_id, tab2_id, &nav1, &nav2);
313 ScopedVector<sessions::SessionWindow> windows;
314 ReadWindows(&(windows.get()), NULL);
316 ASSERT_EQ(2U, windows.size());
317 ASSERT_EQ(0, windows[0]->selected_tab_index);
318 ASSERT_EQ(0, windows[1]->selected_tab_index);
319 ASSERT_EQ(1U, windows[0]->tabs.size());
320 ASSERT_EQ(1U, windows[1]->tabs.size());
322 sessions::SessionTab* rt1;
323 sessions::SessionTab* rt2;
324 if (windows[0]->window_id.id() == window_id.id()) {
325 ASSERT_EQ(window2_id.id(), windows[1]->window_id.id());
326 ASSERT_EQ(ui::SHOW_STATE_NORMAL, windows[0]->show_state);
327 ASSERT_EQ(ui::SHOW_STATE_MAXIMIZED, windows[1]->show_state);
328 rt1 = windows[0]->tabs[0];
329 rt2 = windows[1]->tabs[0];
330 } else {
331 ASSERT_EQ(window2_id.id(), windows[0]->window_id.id());
332 ASSERT_EQ(window_id.id(), windows[1]->window_id.id());
333 ASSERT_EQ(ui::SHOW_STATE_MAXIMIZED, windows[0]->show_state);
334 ASSERT_EQ(ui::SHOW_STATE_NORMAL, windows[1]->show_state);
335 rt1 = windows[1]->tabs[0];
336 rt2 = windows[0]->tabs[0];
338 sessions::SessionTab* tab = rt1;
339 helper_.AssertTabEquals(window_id, tab1_id, 0, 0, 1, *tab);
340 helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
342 tab = rt2;
343 helper_.AssertTabEquals(window2_id, tab2_id, 0, 0, 1, *tab);
344 helper_.AssertNavigationEquals(nav2, tab->navigations[0]);
347 TEST_F(SessionServiceTest, WindowWithNoTabsGetsPruned) {
348 SessionID window2_id;
349 SessionID tab1_id;
350 SessionID tab2_id;
352 SerializedNavigationEntry nav1 =
353 SerializedNavigationEntryTestHelper::CreateNavigation(
354 "http://google.com", "abc");
356 helper_.PrepareTabInWindow(window_id, tab1_id, 0, true);
357 UpdateNavigation(window_id, tab1_id, nav1, true);
359 const gfx::Rect window2_bounds(3, 4, 5, 6);
360 service()->SetWindowType(window2_id,
361 Browser::TYPE_TABBED,
362 SessionService::TYPE_NORMAL);
363 service()->SetWindowBounds(window2_id,
364 window2_bounds,
365 ui::SHOW_STATE_NORMAL);
366 helper_.PrepareTabInWindow(window2_id, tab2_id, 0, true);
368 ScopedVector<sessions::SessionWindow> windows;
369 ReadWindows(&(windows.get()), NULL);
371 ASSERT_EQ(1U, windows.size());
372 ASSERT_EQ(0, windows[0]->selected_tab_index);
373 ASSERT_EQ(1U, windows[0]->tabs.size());
374 ASSERT_EQ(window_id.id(), windows[0]->window_id.id());
376 sessions::SessionTab* tab = windows[0]->tabs[0];
377 helper_.AssertTabEquals(window_id, tab1_id, 0, 0, 1, *tab);
378 helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
381 TEST_F(SessionServiceTest, ClosingWindowDoesntCloseTabs) {
382 SessionID tab_id;
383 SessionID tab2_id;
384 ASSERT_NE(tab_id.id(), tab2_id.id());
386 SerializedNavigationEntry nav1 =
387 SerializedNavigationEntryTestHelper::CreateNavigation(
388 "http://google.com", "abc");
389 SerializedNavigationEntry nav2 =
390 SerializedNavigationEntryTestHelper::CreateNavigation(
391 "http://google2.com", "abcd");
393 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
394 UpdateNavigation(window_id, tab_id, nav1, true);
396 helper_.PrepareTabInWindow(window_id, tab2_id, 1, false);
397 UpdateNavigation(window_id, tab2_id, nav2, true);
399 service()->WindowClosing(window_id);
401 ScopedVector<sessions::SessionWindow> windows;
402 ReadWindows(&(windows.get()), NULL);
404 ASSERT_EQ(1U, windows.size());
405 ASSERT_EQ(0, windows[0]->selected_tab_index);
406 ASSERT_EQ(window_id.id(), windows[0]->window_id.id());
407 ASSERT_EQ(2U, windows[0]->tabs.size());
409 sessions::SessionTab* tab = windows[0]->tabs[0];
410 helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
411 helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
413 tab = windows[0]->tabs[1];
414 helper_.AssertTabEquals(window_id, tab2_id, 1, 0, 1, *tab);
415 helper_.AssertNavigationEquals(nav2, tab->navigations[0]);
418 TEST_F(SessionServiceTest, LockingWindowRemembersAll) {
419 SessionID window2_id;
420 SessionID tab1_id;
421 SessionID tab2_id;
422 SerializedNavigationEntry nav1;
423 SerializedNavigationEntry nav2;
425 CreateAndWriteSessionWithTwoWindows(
426 window2_id, tab1_id, tab2_id, &nav1, &nav2);
428 ASSERT_TRUE(service()->profile() != NULL);
429 ASSERT_TRUE(g_browser_process->profile_manager() != NULL);
430 ProfileInfoCache& profile_info =
431 g_browser_process->profile_manager()->GetProfileInfoCache();
432 size_t profile_index = profile_info.GetIndexOfProfileWithPath(
433 service()->profile()->GetPath());
434 ASSERT_NE(std::string::npos, profile_index);
435 profile_info.SetProfileSigninRequiredAtIndex(profile_index, true);
437 service()->WindowClosing(window_id);
438 service()->WindowClosed(window_id);
439 service()->WindowClosing(window2_id);
440 service()->WindowClosed(window2_id);
442 ScopedVector<sessions::SessionWindow> windows;
443 ReadWindows(&(windows.get()), NULL);
445 ASSERT_EQ(2U, windows.size());
446 ASSERT_EQ(1U, windows[0]->tabs.size());
447 ASSERT_EQ(1U, windows[1]->tabs.size());
450 TEST_F(SessionServiceTest, WindowCloseCommittedAfterNavigate) {
451 SessionID window2_id;
452 SessionID tab_id;
453 SessionID tab2_id;
454 ASSERT_NE(window2_id.id(), window_id.id());
456 service()->SetWindowType(window2_id,
457 Browser::TYPE_TABBED,
458 SessionService::TYPE_NORMAL);
459 service()->SetWindowBounds(window2_id,
460 window_bounds,
461 ui::SHOW_STATE_NORMAL);
463 SerializedNavigationEntry nav1 =
464 SerializedNavigationEntryTestHelper::CreateNavigation(
465 "http://google.com", "abc");
466 SerializedNavigationEntry nav2 =
467 SerializedNavigationEntryTestHelper::CreateNavigation(
468 "http://google2.com", "abcd");
470 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
471 UpdateNavigation(window_id, tab_id, nav1, true);
473 helper_.PrepareTabInWindow(window2_id, tab2_id, 0, false);
474 UpdateNavigation(window2_id, tab2_id, nav2, true);
476 service()->WindowClosing(window2_id);
477 service()->TabClosed(window2_id, tab2_id, false);
478 service()->WindowClosed(window2_id);
480 ScopedVector<sessions::SessionWindow> windows;
481 ReadWindows(&(windows.get()), NULL);
483 ASSERT_EQ(1U, windows.size());
484 ASSERT_EQ(0, windows[0]->selected_tab_index);
485 ASSERT_EQ(window_id.id(), windows[0]->window_id.id());
486 ASSERT_EQ(1U, windows[0]->tabs.size());
488 sessions::SessionTab* tab = windows[0]->tabs[0];
489 helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
490 helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
493 // Makes sure we don't track popups.
494 TEST_F(SessionServiceTest, IgnorePopups) {
495 SessionID window2_id;
496 SessionID tab_id;
497 SessionID tab2_id;
498 ASSERT_NE(window2_id.id(), window_id.id());
500 service()->SetWindowType(window2_id,
501 Browser::TYPE_POPUP,
502 SessionService::TYPE_NORMAL);
503 service()->SetWindowBounds(window2_id,
504 window_bounds,
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<sessions::SessionWindow> windows;
521 ReadWindows(&(windows.get()), NULL);
523 ASSERT_EQ(1U, windows.size());
524 ASSERT_EQ(0, windows[0]->selected_tab_index);
525 ASSERT_EQ(window_id.id(), windows[0]->window_id.id());
526 ASSERT_EQ(1U, windows[0]->tabs.size());
528 sessions::SessionTab* tab = windows[0]->tabs[0];
529 helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
530 helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
533 TEST_F(SessionServiceTest, RemoveUnusedRestoreWindowsTest) {
534 ScopedVector<sessions::SessionWindow> windows_list;
535 windows_list.push_back(new sessions::SessionWindow());
536 windows_list.back()->type = sessions::SessionWindow::TYPE_TABBED;
537 windows_list.push_back(new sessions::SessionWindow());
538 windows_list.back()->type = sessions::SessionWindow::TYPE_POPUP;
540 service()->RemoveUnusedRestoreWindows(&(windows_list.get()));
541 ASSERT_EQ(1U, windows_list.size());
542 EXPECT_EQ(sessions::SessionWindow::TYPE_TABBED, windows_list[0]->type);
545 #if defined (OS_CHROMEOS)
546 // Makes sure we track apps. Only applicable on chromeos.
547 TEST_F(SessionServiceTest, RestoreApp) {
548 SessionID window2_id;
549 SessionID tab_id;
550 SessionID tab2_id;
551 ASSERT_NE(window2_id.id(), window_id.id());
553 service()->SetWindowType(window2_id,
554 Browser::TYPE_POPUP,
555 SessionService::TYPE_APP);
556 service()->SetWindowBounds(window2_id,
557 window_bounds,
558 ui::SHOW_STATE_NORMAL);
559 service()->SetWindowAppName(window2_id, "TestApp");
561 SerializedNavigationEntry nav1 =
562 SerializedNavigationEntryTestHelper::CreateNavigation(
563 "http://google.com", "abc");
564 SerializedNavigationEntry nav2 =
565 SerializedNavigationEntryTestHelper::CreateNavigation(
566 "http://google2.com", "abcd");
568 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
569 UpdateNavigation(window_id, tab_id, nav1, true);
571 helper_.PrepareTabInWindow(window2_id, tab2_id, 0, false);
572 UpdateNavigation(window2_id, tab2_id, nav2, true);
574 ScopedVector<sessions::SessionWindow> windows;
575 ReadWindows(&(windows.get()), NULL);
577 ASSERT_EQ(2U, windows.size());
578 int tabbed_index = windows[0]->type == sessions::SessionWindow::TYPE_TABBED ?
579 0 : 1;
580 int app_index = tabbed_index == 0 ? 1 : 0;
581 ASSERT_EQ(0, windows[tabbed_index]->selected_tab_index);
582 ASSERT_EQ(window_id.id(), windows[tabbed_index]->window_id.id());
583 ASSERT_EQ(1U, windows[tabbed_index]->tabs.size());
585 sessions::SessionTab* tab = windows[tabbed_index]->tabs[0];
586 helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
587 helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
589 ASSERT_EQ(0, windows[app_index]->selected_tab_index);
590 ASSERT_EQ(window2_id.id(), windows[app_index]->window_id.id());
591 ASSERT_EQ(1U, windows[app_index]->tabs.size());
592 ASSERT_TRUE(windows[app_index]->type == sessions::SessionWindow::TYPE_POPUP);
593 ASSERT_EQ("TestApp", windows[app_index]->app_name);
595 tab = windows[app_index]->tabs[0];
596 helper_.AssertTabEquals(window2_id, tab2_id, 0, 0, 1, *tab);
597 helper_.AssertNavigationEquals(nav2, tab->navigations[0]);
599 #endif // defined (OS_CHROMEOS)
601 // Tests pruning from the front.
602 TEST_F(SessionServiceTest, PruneFromFront) {
603 const std::string base_url("http://google.com/");
604 SessionID tab_id;
606 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
608 // Add 5 navigations, with the 4th selected.
609 for (int i = 0; i < 5; ++i) {
610 SerializedNavigationEntry nav =
611 SerializedNavigationEntryTestHelper::CreateNavigation(
612 base_url + base::IntToString(i), "a");
613 nav.set_index(i);
614 UpdateNavigation(window_id, tab_id, nav, (i == 3));
617 // Prune the first two navigations from the front.
618 helper_.service()->TabNavigationPathPrunedFromFront(window_id, tab_id, 2);
620 // Read back in.
621 ScopedVector<sessions::SessionWindow> windows;
622 ReadWindows(&(windows.get()), NULL);
624 ASSERT_EQ(1U, windows.size());
625 ASSERT_EQ(0, windows[0]->selected_tab_index);
626 ASSERT_EQ(window_id.id(), windows[0]->window_id.id());
627 ASSERT_EQ(1U, windows[0]->tabs.size());
629 // There shouldn't be an app id.
630 EXPECT_TRUE(windows[0]->tabs[0]->extension_app_id.empty());
632 // We should be left with three navigations, the 2nd selected.
633 sessions::SessionTab* tab = windows[0]->tabs[0];
634 ASSERT_EQ(1, tab->current_navigation_index);
635 EXPECT_EQ(3U, tab->navigations.size());
636 EXPECT_TRUE(GURL(base_url + base::IntToString(2)) ==
637 tab->navigations[0].virtual_url());
638 EXPECT_TRUE(GURL(base_url + base::IntToString(3)) ==
639 tab->navigations[1].virtual_url());
640 EXPECT_TRUE(GURL(base_url + base::IntToString(4)) ==
641 tab->navigations[2].virtual_url());
644 // Prunes from front so that we have no entries.
645 TEST_F(SessionServiceTest, PruneToEmpty) {
646 const std::string base_url("http://google.com/");
647 SessionID tab_id;
649 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
651 // Add 5 navigations, with the 4th selected.
652 for (int i = 0; i < 5; ++i) {
653 SerializedNavigationEntry nav =
654 SerializedNavigationEntryTestHelper::CreateNavigation(
655 base_url + base::IntToString(i), "a");
656 nav.set_index(i);
657 UpdateNavigation(window_id, tab_id, nav, (i == 3));
660 // Prune the first two navigations from the front.
661 helper_.service()->TabNavigationPathPrunedFromFront(window_id, tab_id, 5);
663 // Read back in.
664 ScopedVector<sessions::SessionWindow> windows;
665 ReadWindows(&(windows.get()), NULL);
667 ASSERT_EQ(0U, windows.size());
670 // Don't set the pinned state and make sure the pinned value is false.
671 TEST_F(SessionServiceTest, PinnedDefaultsToFalse) {
672 EXPECT_FALSE(CreateAndWriteSessionWithOneTab(false, false));
675 // Explicitly set the pinned state to false and make sure we get back false.
676 TEST_F(SessionServiceTest, PinnedFalseWhenSetToFalse) {
677 EXPECT_FALSE(CreateAndWriteSessionWithOneTab(false, true));
680 // Explicitly set the pinned state to true and make sure we get back true.
681 TEST_F(SessionServiceTest, PinnedTrue) {
682 EXPECT_TRUE(CreateAndWriteSessionWithOneTab(true, true));
685 // Make sure application extension ids are persisted.
686 TEST_F(SessionServiceTest, PersistApplicationExtensionID) {
687 SessionID tab_id;
688 ASSERT_NE(window_id.id(), tab_id.id());
689 std::string app_id("foo");
691 SerializedNavigationEntry nav1 =
692 SerializedNavigationEntryTestHelper::CreateNavigation(
693 "http://google.com", "abc");
695 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
696 UpdateNavigation(window_id, tab_id, nav1, true);
697 helper_.SetTabExtensionAppID(window_id, tab_id, app_id);
699 ScopedVector<sessions::SessionWindow> windows;
700 ReadWindows(&(windows.get()), NULL);
702 helper_.AssertSingleWindowWithSingleTab(windows.get(), 1);
703 EXPECT_TRUE(app_id == windows[0]->tabs[0]->extension_app_id);
706 // Check that user agent overrides are persisted.
707 TEST_F(SessionServiceTest, PersistUserAgentOverrides) {
708 SessionID tab_id;
709 ASSERT_NE(window_id.id(), tab_id.id());
710 std::string user_agent_override = "Mozilla/5.0 (X11; Linux x86_64) "
711 "AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.45 "
712 "Safari/535.19";
714 SerializedNavigationEntry nav1 =
715 SerializedNavigationEntryTestHelper::CreateNavigation(
716 "http://google.com", "abc");
717 SerializedNavigationEntryTestHelper::SetIsOverridingUserAgent(true, &nav1);
719 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
720 UpdateNavigation(window_id, tab_id, nav1, true);
721 helper_.SetTabUserAgentOverride(window_id, tab_id, user_agent_override);
723 ScopedVector<sessions::SessionWindow> windows;
724 ReadWindows(&(windows.get()), NULL);
725 helper_.AssertSingleWindowWithSingleTab(windows.get(), 1);
727 sessions::SessionTab* tab = windows[0]->tabs[0];
728 helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
729 helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
730 EXPECT_TRUE(user_agent_override == tab->user_agent_override);
733 // Test that the notification for SESSION_SERVICE_SAVED is working properly.
734 TEST_F(SessionServiceTest, SavedSessionNotification) {
735 content::NotificationRegistrar registrar_;
736 registrar_.Add(this, chrome::NOTIFICATION_SESSION_SERVICE_SAVED,
737 content::NotificationService::AllSources());
738 service()->GetBaseSessionServiceForTest()->Save();
739 EXPECT_EQ(sync_save_count_, 1);
742 // Makes sure a tab closed by a user gesture is not restored.
743 TEST_F(SessionServiceTest, CloseTabUserGesture) {
744 SessionID tab_id;
745 ASSERT_NE(window_id.id(), tab_id.id());
747 SerializedNavigationEntry nav1 =
748 SerializedNavigationEntryTestHelper::CreateNavigation(
749 "http://google.com", "abc");
751 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
752 UpdateNavigation(window_id, tab_id, nav1, true);
753 service()->TabClosed(window_id, tab_id, true);
755 ScopedVector<sessions::SessionWindow> windows;
756 ReadWindows(&(windows.get()), NULL);
758 ASSERT_TRUE(windows.empty());
761 // Verifies SetWindowBounds maps SHOW_STATE_DEFAULT to SHOW_STATE_NORMAL.
762 TEST_F(SessionServiceTest, DontPersistDefault) {
763 SessionID tab_id;
764 ASSERT_NE(window_id.id(), tab_id.id());
765 SerializedNavigationEntry nav1 =
766 SerializedNavigationEntryTestHelper::CreateNavigation(
767 "http://google.com", "abc");
768 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
769 UpdateNavigation(window_id, tab_id, nav1, true);
770 service()->SetWindowBounds(window_id,
771 window_bounds,
772 ui::SHOW_STATE_DEFAULT);
774 ScopedVector<sessions::SessionWindow> windows;
775 ReadWindows(&(windows.get()), NULL);
776 ASSERT_EQ(1U, windows.size());
777 EXPECT_EQ(ui::SHOW_STATE_NORMAL, windows[0]->show_state);
780 TEST_F(SessionServiceTest, KeepPostDataWithoutPasswords) {
781 SessionID tab_id;
782 ASSERT_NE(window_id.id(), tab_id.id());
784 // Create a page state representing a HTTP body without posted passwords.
785 content::PageState page_state =
786 content::PageState::CreateForTesting(GURL(), false, "data", NULL);
788 // Create a TabNavigation containing page_state and representing a POST
789 // request.
790 SerializedNavigationEntry nav1 =
791 SerializedNavigationEntryTestHelper::CreateNavigation(
792 "http://google.com", "title");
793 SerializedNavigationEntryTestHelper::SetEncodedPageState(
794 page_state.ToEncodedData(), &nav1);
795 SerializedNavigationEntryTestHelper::SetHasPostData(true, &nav1);
797 // Create a TabNavigation containing page_state and representing a normal
798 // request.
799 SerializedNavigationEntry nav2 =
800 SerializedNavigationEntryTestHelper::CreateNavigation(
801 "http://google.com/nopost", "title");
802 SerializedNavigationEntryTestHelper::SetEncodedPageState(
803 page_state.ToEncodedData(), &nav2);
804 nav2.set_index(1);
806 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
807 UpdateNavigation(window_id, tab_id, nav1, true);
808 UpdateNavigation(window_id, tab_id, nav2, true);
810 ScopedVector<sessions::SessionWindow> windows;
811 ReadWindows(&(windows.get()), NULL);
813 helper_.AssertSingleWindowWithSingleTab(windows.get(), 2);
815 // Expected: the page state of both navigations was saved and restored.
816 ASSERT_EQ(2u, windows[0]->tabs[0]->navigations.size());
817 helper_.AssertNavigationEquals(nav1, windows[0]->tabs[0]->navigations[0]);
818 helper_.AssertNavigationEquals(nav2, windows[0]->tabs[0]->navigations[1]);
821 TEST_F(SessionServiceTest, RemovePostDataWithPasswords) {
822 SessionID tab_id;
823 ASSERT_NE(window_id.id(), tab_id.id());
825 // Create a page state representing a HTTP body with posted passwords.
826 content::PageState page_state =
827 content::PageState::CreateForTesting(GURL(), true, "data", NULL);
829 // Create a TabNavigation containing page_state and representing a POST
830 // request with passwords.
831 SerializedNavigationEntry nav1 =
832 SerializedNavigationEntryTestHelper::CreateNavigation(
833 "http://google.com", "title");
834 SerializedNavigationEntryTestHelper::SetEncodedPageState(
835 page_state.ToEncodedData(), &nav1);
836 SerializedNavigationEntryTestHelper::SetHasPostData(true, &nav1);
837 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
838 UpdateNavigation(window_id, tab_id, nav1, true);
840 ScopedVector<sessions::SessionWindow> windows;
841 ReadWindows(&(windows.get()), NULL);
843 helper_.AssertSingleWindowWithSingleTab(windows.get(), 1);
845 // Expected: the HTTP body was removed from the page state of the POST
846 // navigation with passwords.
847 EXPECT_NE(page_state.ToEncodedData(),
848 windows[0]->tabs[0]->navigations[0].encoded_page_state());
851 TEST_F(SessionServiceTest, ReplacePendingNavigation) {
852 const std::string base_url("http://google.com/");
853 SessionID tab_id;
855 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
857 // Add 5 navigations, some with the same index
858 for (int i = 0; i < 5; ++i) {
859 SerializedNavigationEntry nav =
860 SerializedNavigationEntryTestHelper::CreateNavigation(
861 base_url + base::IntToString(i), "a");
862 nav.set_index(i / 2);
863 UpdateNavigation(window_id, tab_id, nav, true);
866 // Read back in.
867 ScopedVector<sessions::SessionWindow> windows;
868 ReadWindows(&(windows.get()), NULL);
870 // The ones with index 0, and 2 should have been replaced by 1 and 3.
871 ASSERT_EQ(1U, windows.size());
872 ASSERT_EQ(1U, windows[0]->tabs.size());
873 EXPECT_EQ(3U, windows[0]->tabs[0]->navigations.size());
874 EXPECT_EQ(GURL(base_url + base::IntToString(1)),
875 windows[0]->tabs[0]->navigations[0].virtual_url());
876 EXPECT_EQ(GURL(base_url + base::IntToString(3)),
877 windows[0]->tabs[0]->navigations[1].virtual_url());
878 EXPECT_EQ(GURL(base_url + base::IntToString(4)),
879 windows[0]->tabs[0]->navigations[2].virtual_url());
882 TEST_F(SessionServiceTest, ReplacePendingNavigationAndPrune) {
883 const std::string base_url("http://google.com/");
884 SessionID tab_id;
886 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
888 for (int i = 0; i < 5; ++i) {
889 SerializedNavigationEntry nav =
890 SerializedNavigationEntryTestHelper::CreateNavigation(
891 base_url + base::IntToString(i), "a");
892 nav.set_index(i);
893 UpdateNavigation(window_id, tab_id, nav, true);
896 // Prune all those navigations.
897 helper_.service()->TabNavigationPathPrunedFromFront(window_id, tab_id, 5);
899 // Add another navigation to replace the last one.
900 SerializedNavigationEntry nav =
901 SerializedNavigationEntryTestHelper::CreateNavigation(
902 base_url + base::IntToString(5), "a");
903 nav.set_index(4);
904 UpdateNavigation(window_id, tab_id, nav, true);
906 // Read back in.
907 ScopedVector<sessions::SessionWindow> windows;
908 ReadWindows(&(windows.get()), NULL);
910 // We should still have that last navigation at the end,
911 // even though it replaced one that was set before the prune.
912 ASSERT_EQ(1U, windows.size());
913 ASSERT_EQ(1U, windows[0]->tabs.size());
914 ASSERT_EQ(1U, windows[0]->tabs[0]->navigations.size());
915 EXPECT_EQ(GURL(base_url + base::IntToString(5)),
916 windows[0]->tabs[0]->navigations[0].virtual_url());
919 TEST_F(SessionServiceTest, RestoreActivation1) {
920 SessionID window2_id;
921 SessionID tab1_id;
922 SessionID tab2_id;
923 SerializedNavigationEntry nav1;
924 SerializedNavigationEntry nav2;
926 CreateAndWriteSessionWithTwoWindows(
927 window2_id, tab1_id, tab2_id, &nav1, &nav2);
929 service()->ScheduleCommand(
930 sessions::CreateSetActiveWindowCommand(window2_id).Pass());
931 service()->ScheduleCommand(
932 sessions::CreateSetActiveWindowCommand(window_id).Pass());
934 ScopedVector<sessions::SessionWindow> windows;
935 SessionID::id_type active_window_id = 0;
936 ReadWindows(&(windows.get()), &active_window_id);
937 EXPECT_EQ(window_id.id(), active_window_id);
940 // It's easier to have two separate tests with setup/teardown than to manualy
941 // reset the state for the different flavors of the test.
942 TEST_F(SessionServiceTest, RestoreActivation2) {
943 SessionID window2_id;
944 SessionID tab1_id;
945 SessionID tab2_id;
946 SerializedNavigationEntry nav1;
947 SerializedNavigationEntry nav2;
949 CreateAndWriteSessionWithTwoWindows(
950 window2_id, tab1_id, tab2_id, &nav1, &nav2);
952 service()->ScheduleCommand(
953 sessions::CreateSetActiveWindowCommand(window2_id).Pass());
954 service()->ScheduleCommand(
955 sessions::CreateSetActiveWindowCommand(window_id).Pass());
956 service()->ScheduleCommand(
957 sessions::CreateSetActiveWindowCommand(window2_id).Pass());
959 ScopedVector<sessions::SessionWindow> windows;
960 SessionID::id_type active_window_id = 0;
961 ReadWindows(&(windows.get()), &active_window_id);
962 EXPECT_EQ(window2_id.id(), active_window_id);
965 // Makes sure we don't track blacklisted URLs.
966 TEST_F(SessionServiceTest, IgnoreBlacklistedUrls) {
967 SessionID tab_id;
969 SerializedNavigationEntry nav1 =
970 SerializedNavigationEntryTestHelper::CreateNavigation(
971 "http://google.com", "abc");
972 SerializedNavigationEntry nav2 =
973 SerializedNavigationEntryTestHelper::CreateNavigation(
974 chrome::kChromeUIQuitURL, "quit");
975 SerializedNavigationEntry nav3 =
976 SerializedNavigationEntryTestHelper::CreateNavigation(
977 chrome::kChromeUIRestartURL, "restart");
979 helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
980 UpdateNavigation(window_id, tab_id, nav1, true);
981 UpdateNavigation(window_id, tab_id, nav2, true);
982 UpdateNavigation(window_id, tab_id, nav3, true);
984 ScopedVector<sessions::SessionWindow> windows;
985 ReadWindows(&(windows.get()), NULL);
987 ASSERT_EQ(1U, windows.size());
988 ASSERT_EQ(0, windows[0]->selected_tab_index);
989 ASSERT_EQ(window_id.id(), windows[0]->window_id.id());
990 ASSERT_EQ(1U, windows[0]->tabs.size());
992 sessions::SessionTab* tab = windows[0]->tabs[0];
993 helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
994 helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
997 // Functions used by GetSessionsAndDestroy.
998 namespace {
1000 void OnGotPreviousSession(ScopedVector<sessions::SessionWindow> windows,
1001 SessionID::id_type ignored_active_window) {
1002 FAIL() << "SessionService was destroyed, this shouldn't be reached.";
1005 void PostBackToThread(base::MessageLoop* message_loop,
1006 base::RunLoop* run_loop) {
1007 message_loop->task_runner()->PostTask(
1008 FROM_HERE, base::Bind(&base::RunLoop::Quit, base::Unretained(run_loop)));
1011 } // namespace
1013 // Verifies that SessionService::GetLastSession() works correctly if the
1014 // SessionService is deleted during processing. To verify the problematic case
1015 // does the following:
1016 // 1. Sends a task to the background thread that blocks.
1017 // 2. Asks SessionService for the last session commands. This is blocked by 1.
1018 // 3. Posts another task to the background thread, this too is blocked by 1.
1019 // 4. Deletes SessionService.
1020 // 5. Signals the semaphore that 2 and 3 are waiting on, allowing
1021 // GetLastSession() to continue.
1022 // 6. runs the message loop, this is quit when the task scheduled in 3 posts
1023 // back to the ui thread to quit the run loop.
1024 // The call to get the previous session should never be invoked because the
1025 // SessionService was destroyed before SessionService could process the results.
1026 TEST_F(SessionServiceTest, GetSessionsAndDestroy) {
1027 base::CancelableTaskTracker cancelable_task_tracker;
1028 base::RunLoop run_loop;
1029 base::WaitableEvent event(true, false);
1030 helper_.RunTaskOnBackendThread(FROM_HERE,
1031 base::Bind(&base::WaitableEvent::Wait,
1032 base::Unretained(&event)));
1033 service()->GetLastSession(base::Bind(&OnGotPreviousSession),
1034 &cancelable_task_tracker);
1035 helper_.RunTaskOnBackendThread(
1036 FROM_HERE,
1037 base::Bind(&PostBackToThread,
1038 base::Unretained(base::MessageLoop::current()),
1039 base::Unretained(&run_loop)));
1040 delete helper_.ReleaseService();
1041 event.Signal();
1042 run_loop.Run();