• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "base/bind.h"
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"
37 
38 using content::NavigationEntry;
39 using sessions::SerializedNavigationEntry;
40 using sessions::SerializedNavigationEntryTestHelper;
41 
42 class SessionServiceTest : public BrowserWithTestWindowTest,
43                            public content::NotificationObserver {
44  public:
SessionServiceTest()45   SessionServiceTest() : window_bounds(0, 1, 2, 3), sync_save_count_(0) {}
46 
47  protected:
SetUp()48   virtual void SetUp() {
49     BrowserWithTestWindowTest::SetUp();
50 
51     profile_manager_.reset(
52         new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
53     ASSERT_TRUE(profile_manager_->SetUp());
54 
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();
59 
60     helper_.SetService(session_service);
61 
62     service()->SetWindowType(
63         window_id, Browser::TYPE_TABBED, SessionService::TYPE_NORMAL);
64     service()->SetWindowBounds(window_id,
65                                window_bounds,
66                                ui::SHOW_STATE_NORMAL);
67   }
68 
69   // Upon notification, increment the sync_save_count variable
Observe(int type,const content::NotificationSource & source,const content::NotificationDetails & details)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);
74     sync_save_count_++;
75   }
76 
TearDown()77   virtual void TearDown() {
78     helper_.SetService(NULL);
79     BrowserWithTestWindowTest::TearDown();
80   }
81 
UpdateNavigation(const SessionID & window_id,const SessionID & tab_id,const SerializedNavigationEntry & navigation,bool select)82   void UpdateNavigation(
83       const SessionID& window_id,
84       const SessionID& tab_id,
85       const SerializedNavigationEntry& navigation,
86       bool select) {
87     service()->UpdateTabNavigation(window_id, tab_id, navigation);
88     if (select) {
89       service()->SetSelectedNavigationIndex(
90           window_id, tab_id, navigation.index());
91     }
92   }
93 
ReadWindows(std::vector<SessionWindow * > * windows,SessionID::id_type * active_window_id)94   void ReadWindows(std::vector<SessionWindow*>* windows,
95                    SessionID::id_type* active_window_id) {
96     // Forces closing the file.
97     helper_.SetService(NULL);
98 
99     SessionService* session_service = new SessionService(path_);
100     helper_.SetService(session_service);
101 
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);
107   }
108 
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.
CreateAndWriteSessionWithOneTab(bool pinned_state,bool write_always)113   bool CreateAndWriteSessionWithOneTab(bool pinned_state, bool write_always) {
114     SessionID tab_id;
115     SerializedNavigationEntry nav1 =
116         SerializedNavigationEntryTestHelper::CreateNavigation(
117             "http://google.com", "abc");
118 
119     helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
120     UpdateNavigation(window_id, tab_id, nav1, true);
121 
122     if (pinned_state || write_always)
123       helper_.service()->SetPinnedState(window_id, tab_id, pinned_state);
124 
125     ScopedVector<SessionWindow> windows;
126     ReadWindows(&(windows.get()), NULL);
127 
128     EXPECT_EQ(1U, windows.size());
129     if (HasFatalFailure())
130       return false;
131     EXPECT_EQ(1U, windows[0]->tabs.size());
132     if (HasFatalFailure())
133       return false;
134 
135     SessionTab* tab = windows[0]->tabs[0];
136     helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
137 
138     return tab->pinned;
139   }
140 
CreateAndWriteSessionWithTwoWindows(const SessionID & window2_id,const SessionID & tab1_id,const SessionID & tab2_id,SerializedNavigationEntry * nav1,SerializedNavigationEntry * nav2)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");
151 
152     helper_.PrepareTabInWindow(window_id, tab1_id, 0, true);
153     UpdateNavigation(window_id, tab1_id, *nav1, true);
154 
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,
159                                window2_bounds,
160                                ui::SHOW_STATE_MAXIMIZED);
161     helper_.PrepareTabInWindow(window2_id, tab2_id, 0, true);
162     UpdateNavigation(window2_id, tab2_id, *nav2, true);
163   }
164 
service()165   SessionService* service() { return helper_.service(); }
166 
backend()167   SessionBackend* backend() { return helper_.backend(); }
168 
169   const gfx::Rect window_bounds;
170 
171   SessionID window_id;
172 
173   int sync_save_count_;
174 
175   // Path used in testing.
176   base::ScopedTempDir temp_dir_;
177   base::FilePath path_;
178 
179   SessionServiceTestHelper helper_;
180   scoped_ptr<TestingProfileManager> profile_manager_;
181 };
182 
TEST_F(SessionServiceTest,Basic)183 TEST_F(SessionServiceTest, Basic) {
184   SessionID tab_id;
185   ASSERT_NE(window_id.id(), tab_id.id());
186 
187   SerializedNavigationEntry nav1 =
188       SerializedNavigationEntryTestHelper::CreateNavigation(
189           "http://google.com", "abc");
190   SerializedNavigationEntryTestHelper::SetOriginalRequestURL(
191       GURL("http://original.request.com"), &nav1);
192 
193   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
194   UpdateNavigation(window_id, tab_id, nav1, true);
195 
196   ScopedVector<SessionWindow> windows;
197   ReadWindows(&(windows.get()), NULL);
198 
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);
205 
206   SessionTab* tab = windows[0]->tabs[0];
207   helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
208 
209   helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
210 }
211 
212 // Make sure we persist post entries.
TEST_F(SessionServiceTest,PersistPostData)213 TEST_F(SessionServiceTest, PersistPostData) {
214   SessionID tab_id;
215   ASSERT_NE(window_id.id(), tab_id.id());
216 
217   SerializedNavigationEntry nav1 =
218       SerializedNavigationEntryTestHelper::CreateNavigation(
219           "http://google.com", "abc");
220   SerializedNavigationEntryTestHelper::SetHasPostData(true, &nav1);
221 
222   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
223   UpdateNavigation(window_id, tab_id, nav1, true);
224 
225   ScopedVector<SessionWindow> windows;
226   ReadWindows(&(windows.get()), NULL);
227 
228   helper_.AssertSingleWindowWithSingleTab(windows.get(), 1);
229 }
230 
TEST_F(SessionServiceTest,ClosingTabStaysClosed)231 TEST_F(SessionServiceTest, ClosingTabStaysClosed) {
232   SessionID tab_id;
233   SessionID tab2_id;
234   ASSERT_NE(tab_id.id(), tab2_id.id());
235 
236   SerializedNavigationEntry nav1 =
237       SerializedNavigationEntryTestHelper::CreateNavigation(
238           "http://google.com", "abc");
239   SerializedNavigationEntry nav2 =
240       SerializedNavigationEntryTestHelper::CreateNavigation(
241           "http://google2.com", "abcd");
242 
243   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
244   UpdateNavigation(window_id, tab_id, nav1, true);
245 
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);
249 
250   ScopedVector<SessionWindow> windows;
251   ReadWindows(&(windows.get()), NULL);
252 
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());
257 
258   SessionTab* tab = windows[0]->tabs[0];
259   helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
260 
261   helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
262 }
263 
TEST_F(SessionServiceTest,Pruning)264 TEST_F(SessionServiceTest, Pruning) {
265   SessionID tab_id;
266 
267   SerializedNavigationEntry nav1 =
268       SerializedNavigationEntryTestHelper::CreateNavigation(
269           "http://google.com", "abc");
270   SerializedNavigationEntry nav2 =
271       SerializedNavigationEntryTestHelper::CreateNavigation(
272           "http://google2.com", "abcd");
273 
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;
277     nav->set_index(i);
278     UpdateNavigation(window_id, tab_id, *nav, true);
279   }
280   service()->TabNavigationPathPrunedFromBack(window_id, tab_id, 3);
281 
282   ScopedVector<SessionWindow> windows;
283   ReadWindows(&(windows.get()), NULL);
284 
285   ASSERT_EQ(1U, windows.size());
286   ASSERT_EQ(0, windows[0]->selected_tab_index);
287   ASSERT_EQ(1U, windows[0]->tabs.size());
288 
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);
293 
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]);
298 }
299 
TEST_F(SessionServiceTest,TwoWindows)300 TEST_F(SessionServiceTest, TwoWindows) {
301   SessionID window2_id;
302   SessionID tab1_id;
303   SessionID tab2_id;
304   SerializedNavigationEntry nav1;
305   SerializedNavigationEntry nav2;
306 
307   CreateAndWriteSessionWithTwoWindows(
308       window2_id, tab1_id, tab2_id, &nav1, &nav2);
309 
310   ScopedVector<SessionWindow> windows;
311   ReadWindows(&(windows.get()), NULL);
312 
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());
318 
319   SessionTab* rt1;
320   SessionTab* rt2;
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];
327   } else {
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];
334   }
335   SessionTab* tab = rt1;
336   helper_.AssertTabEquals(window_id, tab1_id, 0, 0, 1, *tab);
337   helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
338 
339   tab = rt2;
340   helper_.AssertTabEquals(window2_id, tab2_id, 0, 0, 1, *tab);
341   helper_.AssertNavigationEquals(nav2, tab->navigations[0]);
342 }
343 
TEST_F(SessionServiceTest,WindowWithNoTabsGetsPruned)344 TEST_F(SessionServiceTest, WindowWithNoTabsGetsPruned) {
345   SessionID window2_id;
346   SessionID tab1_id;
347   SessionID tab2_id;
348 
349   SerializedNavigationEntry nav1 =
350       SerializedNavigationEntryTestHelper::CreateNavigation(
351           "http://google.com", "abc");
352 
353   helper_.PrepareTabInWindow(window_id, tab1_id, 0, true);
354   UpdateNavigation(window_id, tab1_id, nav1, true);
355 
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,
360                              window2_bounds,
361                              ui::SHOW_STATE_NORMAL);
362   helper_.PrepareTabInWindow(window2_id, tab2_id, 0, true);
363 
364   ScopedVector<SessionWindow> windows;
365   ReadWindows(&(windows.get()), NULL);
366 
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());
371 
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]);
375 }
376 
TEST_F(SessionServiceTest,ClosingWindowDoesntCloseTabs)377 TEST_F(SessionServiceTest, ClosingWindowDoesntCloseTabs) {
378   SessionID tab_id;
379   SessionID tab2_id;
380   ASSERT_NE(tab_id.id(), tab2_id.id());
381 
382   SerializedNavigationEntry nav1 =
383       SerializedNavigationEntryTestHelper::CreateNavigation(
384           "http://google.com", "abc");
385   SerializedNavigationEntry nav2 =
386       SerializedNavigationEntryTestHelper::CreateNavigation(
387           "http://google2.com", "abcd");
388 
389   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
390   UpdateNavigation(window_id, tab_id, nav1, true);
391 
392   helper_.PrepareTabInWindow(window_id, tab2_id, 1, false);
393   UpdateNavigation(window_id, tab2_id, nav2, true);
394 
395   service()->WindowClosing(window_id);
396 
397   ScopedVector<SessionWindow> windows;
398   ReadWindows(&(windows.get()), NULL);
399 
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());
404 
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]);
408 
409   tab = windows[0]->tabs[1];
410   helper_.AssertTabEquals(window_id, tab2_id, 1, 0, 1, *tab);
411   helper_.AssertNavigationEquals(nav2, tab->navigations[0]);
412 }
413 
TEST_F(SessionServiceTest,LockingWindowRemembersAll)414 TEST_F(SessionServiceTest, LockingWindowRemembersAll) {
415   SessionID window2_id;
416   SessionID tab1_id;
417   SessionID tab2_id;
418   SerializedNavigationEntry nav1;
419   SerializedNavigationEntry nav2;
420 
421   CreateAndWriteSessionWithTwoWindows(
422       window2_id, tab1_id, tab2_id, &nav1, &nav2);
423 
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);
432 
433   service()->WindowClosing(window_id);
434   service()->WindowClosed(window_id);
435   service()->WindowClosing(window2_id);
436   service()->WindowClosed(window2_id);
437 
438   ScopedVector<SessionWindow> windows;
439   ReadWindows(&(windows.get()), NULL);
440 
441   ASSERT_EQ(2U, windows.size());
442   ASSERT_EQ(1U, windows[0]->tabs.size());
443   ASSERT_EQ(1U, windows[1]->tabs.size());
444 }
445 
TEST_F(SessionServiceTest,WindowCloseCommittedAfterNavigate)446 TEST_F(SessionServiceTest, WindowCloseCommittedAfterNavigate) {
447   SessionID window2_id;
448   SessionID tab_id;
449   SessionID tab2_id;
450   ASSERT_NE(window2_id.id(), window_id.id());
451 
452   service()->SetWindowType(
453       window2_id, Browser::TYPE_TABBED, SessionService::TYPE_NORMAL);
454   service()->SetWindowBounds(window2_id,
455                              window_bounds,
456                              ui::SHOW_STATE_NORMAL);
457 
458   SerializedNavigationEntry nav1 =
459       SerializedNavigationEntryTestHelper::CreateNavigation(
460           "http://google.com", "abc");
461   SerializedNavigationEntry nav2 =
462       SerializedNavigationEntryTestHelper::CreateNavigation(
463           "http://google2.com", "abcd");
464 
465   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
466   UpdateNavigation(window_id, tab_id, nav1, true);
467 
468   helper_.PrepareTabInWindow(window2_id, tab2_id, 0, false);
469   UpdateNavigation(window2_id, tab2_id, nav2, true);
470 
471   service()->WindowClosing(window2_id);
472   service()->TabClosed(window2_id, tab2_id, false);
473   service()->WindowClosed(window2_id);
474 
475   ScopedVector<SessionWindow> windows;
476   ReadWindows(&(windows.get()), NULL);
477 
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());
482 
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]);
486 }
487 
488 // Makes sure we don't track popups.
TEST_F(SessionServiceTest,IgnorePopups)489 TEST_F(SessionServiceTest, IgnorePopups) {
490   SessionID window2_id;
491   SessionID tab_id;
492   SessionID tab2_id;
493   ASSERT_NE(window2_id.id(), window_id.id());
494 
495   service()->SetWindowType(
496       window2_id, Browser::TYPE_POPUP, SessionService::TYPE_NORMAL);
497   service()->SetWindowBounds(window2_id,
498                              window_bounds,
499                              ui::SHOW_STATE_NORMAL);
500 
501   SerializedNavigationEntry nav1 =
502       SerializedNavigationEntryTestHelper::CreateNavigation(
503           "http://google.com", "abc");
504   SerializedNavigationEntry nav2 =
505       SerializedNavigationEntryTestHelper::CreateNavigation(
506           "http://google2.com", "abcd");
507 
508   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
509   UpdateNavigation(window_id, tab_id, nav1, true);
510 
511   helper_.PrepareTabInWindow(window2_id, tab2_id, 0, false);
512   UpdateNavigation(window2_id, tab2_id, nav2, true);
513 
514   ScopedVector<SessionWindow> windows;
515   ReadWindows(&(windows.get()), NULL);
516 
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());
521 
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]);
525 }
526 
527 #if defined (OS_CHROMEOS)
528 // Makes sure we track apps. Only applicable on chromeos.
TEST_F(SessionServiceTest,RestoreApp)529 TEST_F(SessionServiceTest, RestoreApp) {
530   SessionID window2_id;
531   SessionID tab_id;
532   SessionID tab2_id;
533   ASSERT_NE(window2_id.id(), window_id.id());
534 
535   service()->SetWindowType(
536       window2_id, Browser::TYPE_POPUP, SessionService::TYPE_APP);
537   service()->SetWindowBounds(window2_id,
538                              window_bounds,
539                              ui::SHOW_STATE_NORMAL);
540   service()->SetWindowAppName(window2_id, "TestApp");
541 
542   SerializedNavigationEntry nav1 =
543       SerializedNavigationEntryTestHelper::CreateNavigation(
544           "http://google.com", "abc");
545   SerializedNavigationEntry nav2 =
546       SerializedNavigationEntryTestHelper::CreateNavigation(
547           "http://google2.com", "abcd");
548 
549   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
550   UpdateNavigation(window_id, tab_id, nav1, true);
551 
552   helper_.PrepareTabInWindow(window2_id, tab2_id, 0, false);
553   UpdateNavigation(window2_id, tab2_id, nav2, true);
554 
555   ScopedVector<SessionWindow> windows;
556   ReadWindows(&(windows.get()), NULL);
557 
558   ASSERT_EQ(2U, windows.size());
559   int tabbed_index = windows[0]->type == Browser::TYPE_TABBED ?
560       0 : 1;
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());
565 
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]);
569 
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);
575 
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]);
579 }
580 #endif  // defined (OS_CHROMEOS)
581 
582 // Tests pruning from the front.
TEST_F(SessionServiceTest,PruneFromFront)583 TEST_F(SessionServiceTest, PruneFromFront) {
584   const std::string base_url("http://google.com/");
585   SessionID tab_id;
586 
587   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
588 
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");
594     nav.set_index(i);
595     UpdateNavigation(window_id, tab_id, nav, (i == 3));
596   }
597 
598   // Prune the first two navigations from the front.
599   helper_.service()->TabNavigationPathPrunedFromFront(window_id, tab_id, 2);
600 
601   // Read back in.
602   ScopedVector<SessionWindow> windows;
603   ReadWindows(&(windows.get()), NULL);
604 
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());
609 
610   // There shouldn't be an app id.
611   EXPECT_TRUE(windows[0]->tabs[0]->extension_app_id.empty());
612 
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());
623 }
624 
625 // Prunes from front so that we have no entries.
TEST_F(SessionServiceTest,PruneToEmpty)626 TEST_F(SessionServiceTest, PruneToEmpty) {
627   const std::string base_url("http://google.com/");
628   SessionID tab_id;
629 
630   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
631 
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");
637     nav.set_index(i);
638     UpdateNavigation(window_id, tab_id, nav, (i == 3));
639   }
640 
641   // Prune the first two navigations from the front.
642   helper_.service()->TabNavigationPathPrunedFromFront(window_id, tab_id, 5);
643 
644   // Read back in.
645   ScopedVector<SessionWindow> windows;
646   ReadWindows(&(windows.get()), NULL);
647 
648   ASSERT_EQ(0U, windows.size());
649 }
650 
651 // Don't set the pinned state and make sure the pinned value is false.
TEST_F(SessionServiceTest,PinnedDefaultsToFalse)652 TEST_F(SessionServiceTest, PinnedDefaultsToFalse) {
653   EXPECT_FALSE(CreateAndWriteSessionWithOneTab(false, false));
654 }
655 
656 // Explicitly set the pinned state to false and make sure we get back false.
TEST_F(SessionServiceTest,PinnedFalseWhenSetToFalse)657 TEST_F(SessionServiceTest, PinnedFalseWhenSetToFalse) {
658   EXPECT_FALSE(CreateAndWriteSessionWithOneTab(false, true));
659 }
660 
661 // Explicitly set the pinned state to true and make sure we get back true.
TEST_F(SessionServiceTest,PinnedTrue)662 TEST_F(SessionServiceTest, PinnedTrue) {
663   EXPECT_TRUE(CreateAndWriteSessionWithOneTab(true, true));
664 }
665 
666 // Make sure application extension ids are persisted.
TEST_F(SessionServiceTest,PersistApplicationExtensionID)667 TEST_F(SessionServiceTest, PersistApplicationExtensionID) {
668   SessionID tab_id;
669   ASSERT_NE(window_id.id(), tab_id.id());
670   std::string app_id("foo");
671 
672   SerializedNavigationEntry nav1 =
673       SerializedNavigationEntryTestHelper::CreateNavigation(
674           "http://google.com", "abc");
675 
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);
679 
680   ScopedVector<SessionWindow> windows;
681   ReadWindows(&(windows.get()), NULL);
682 
683   helper_.AssertSingleWindowWithSingleTab(windows.get(), 1);
684   EXPECT_TRUE(app_id == windows[0]->tabs[0]->extension_app_id);
685 }
686 
687 // Check that user agent overrides are persisted.
TEST_F(SessionServiceTest,PersistUserAgentOverrides)688 TEST_F(SessionServiceTest, PersistUserAgentOverrides) {
689   SessionID tab_id;
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 "
693       "Safari/535.19";
694 
695   SerializedNavigationEntry nav1 =
696       SerializedNavigationEntryTestHelper::CreateNavigation(
697           "http://google.com", "abc");
698   SerializedNavigationEntryTestHelper::SetIsOverridingUserAgent(true, &nav1);
699 
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);
703 
704   ScopedVector<SessionWindow> windows;
705   ReadWindows(&(windows.get()), NULL);
706   helper_.AssertSingleWindowWithSingleTab(windows.get(), 1);
707 
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);
712 }
713 
714 // Test that the notification for SESSION_SERVICE_SAVED is working properly.
TEST_F(SessionServiceTest,SavedSessionNotification)715 TEST_F(SessionServiceTest, SavedSessionNotification) {
716   content::NotificationRegistrar registrar_;
717   registrar_.Add(this, chrome::NOTIFICATION_SESSION_SERVICE_SAVED,
718                  content::NotificationService::AllSources());
719   service()->Save();
720   EXPECT_EQ(sync_save_count_, 1);
721 }
722 
723 // Makes sure a tab closed by a user gesture is not restored.
TEST_F(SessionServiceTest,CloseTabUserGesture)724 TEST_F(SessionServiceTest, CloseTabUserGesture) {
725   SessionID tab_id;
726   ASSERT_NE(window_id.id(), tab_id.id());
727 
728   SerializedNavigationEntry nav1 =
729       SerializedNavigationEntryTestHelper::CreateNavigation(
730           "http://google.com", "abc");
731 
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);
735 
736   ScopedVector<SessionWindow> windows;
737   ReadWindows(&(windows.get()), NULL);
738 
739   ASSERT_TRUE(windows.empty());
740 }
741 
742 // Verifies SetWindowBounds maps SHOW_STATE_DEFAULT to SHOW_STATE_NORMAL.
TEST_F(SessionServiceTest,DontPersistDefault)743 TEST_F(SessionServiceTest, DontPersistDefault) {
744   SessionID tab_id;
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,
752                              window_bounds,
753                              ui::SHOW_STATE_DEFAULT);
754 
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);
759 }
760 
TEST_F(SessionServiceTest,KeepPostDataWithoutPasswords)761 TEST_F(SessionServiceTest, KeepPostDataWithoutPasswords) {
762   SessionID tab_id;
763   ASSERT_NE(window_id.id(), tab_id.id());
764 
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);
768 
769   // Create a TabNavigation containing page_state and representing a POST
770   // request.
771   SerializedNavigationEntry nav1 =
772       SerializedNavigationEntryTestHelper::CreateNavigation(
773           "http://google.com", "title");
774   SerializedNavigationEntryTestHelper::SetPageState(page_state, &nav1);
775   SerializedNavigationEntryTestHelper::SetHasPostData(true, &nav1);
776 
777   // Create a TabNavigation containing page_state and representing a normal
778   // request.
779   SerializedNavigationEntry nav2 =
780       SerializedNavigationEntryTestHelper::CreateNavigation(
781           "http://google.com/nopost", "title");
782   SerializedNavigationEntryTestHelper::SetPageState(page_state, &nav2);
783   nav2.set_index(1);
784 
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);
788 
789   ScopedVector<SessionWindow> windows;
790   ReadWindows(&(windows.get()), NULL);
791 
792   helper_.AssertSingleWindowWithSingleTab(windows.get(), 2);
793 
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]);
798 }
799 
TEST_F(SessionServiceTest,RemovePostDataWithPasswords)800 TEST_F(SessionServiceTest, RemovePostDataWithPasswords) {
801   SessionID tab_id;
802   ASSERT_NE(window_id.id(), tab_id.id());
803 
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);
807 
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);
817 
818   ScopedVector<SessionWindow> windows;
819   ReadWindows(&(windows.get()), NULL);
820 
821   helper_.AssertSingleWindowWithSingleTab(windows.get(), 1);
822 
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());
826 }
827 
828 // This test is only applicable to chromeos.
829 #if defined(OS_CHROMEOS)
830 // Verifies migration of tab/window closed works.
TEST_F(SessionServiceTest,CanOpenV1TabClosed)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.
837   v1_file_path =
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");
841 
842   // Forces closing the file.
843   helper_.SetService(NULL);
844 
845   ASSERT_TRUE(base::CopyFile(v1_file_path, dest_file_path));
846 
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());
854 }
855 #endif  // defined(OS_CHROMEOS)
856 
TEST_F(SessionServiceTest,ReplacePendingNavigation)857 TEST_F(SessionServiceTest, ReplacePendingNavigation) {
858   const std::string base_url("http://google.com/");
859   SessionID tab_id;
860 
861   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
862 
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);
870   }
871 
872   // Read back in.
873   ScopedVector<SessionWindow> windows;
874   ReadWindows(&(windows.get()), NULL);
875 
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());
886 }
887 
TEST_F(SessionServiceTest,ReplacePendingNavigationAndPrune)888 TEST_F(SessionServiceTest, ReplacePendingNavigationAndPrune) {
889   const std::string base_url("http://google.com/");
890   SessionID tab_id;
891 
892   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
893 
894   for (int i = 0; i < 5; ++i) {
895     SerializedNavigationEntry nav =
896         SerializedNavigationEntryTestHelper::CreateNavigation(
897             base_url + base::IntToString(i), "a");
898     nav.set_index(i);
899     UpdateNavigation(window_id, tab_id, nav, true);
900   }
901 
902   // Prune all those navigations.
903   helper_.service()->TabNavigationPathPrunedFromFront(window_id, tab_id, 5);
904 
905   // Add another navigation to replace the last one.
906   SerializedNavigationEntry nav =
907       SerializedNavigationEntryTestHelper::CreateNavigation(
908         base_url + base::IntToString(5), "a");
909   nav.set_index(4);
910   UpdateNavigation(window_id, tab_id, nav, true);
911 
912   // Read back in.
913   ScopedVector<SessionWindow> windows;
914   ReadWindows(&(windows.get()), NULL);
915 
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());
923 }
924 
TEST_F(SessionServiceTest,RestoreActivation1)925 TEST_F(SessionServiceTest, RestoreActivation1) {
926   SessionID window2_id;
927   SessionID tab1_id;
928   SessionID tab2_id;
929   SerializedNavigationEntry nav1;
930   SerializedNavigationEntry nav2;
931 
932   CreateAndWriteSessionWithTwoWindows(
933       window2_id, tab1_id, tab2_id, &nav1, &nav2);
934 
935   service()->ScheduleCommand(
936       service()->CreateSetActiveWindowCommand(window2_id));
937   service()->ScheduleCommand(
938       service()->CreateSetActiveWindowCommand(window_id));
939 
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);
944 }
945 
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.
TEST_F(SessionServiceTest,RestoreActivation2)948 TEST_F(SessionServiceTest, RestoreActivation2) {
949   SessionID window2_id;
950   SessionID tab1_id;
951   SessionID tab2_id;
952   SerializedNavigationEntry nav1;
953   SerializedNavigationEntry nav2;
954 
955   CreateAndWriteSessionWithTwoWindows(
956       window2_id, tab1_id, tab2_id, &nav1, &nav2);
957 
958   service()->ScheduleCommand(
959       service()->CreateSetActiveWindowCommand(window2_id));
960   service()->ScheduleCommand(
961       service()->CreateSetActiveWindowCommand(window_id));
962   service()->ScheduleCommand(
963       service()->CreateSetActiveWindowCommand(window2_id));
964 
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);
969 }
970 
971 // Makes sure we don't track blacklisted URLs.
TEST_F(SessionServiceTest,IgnoreBlacklistedUrls)972 TEST_F(SessionServiceTest, IgnoreBlacklistedUrls) {
973   SessionID tab_id;
974 
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");
984 
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);
989 
990   ScopedVector<SessionWindow> windows;
991   ReadWindows(&(windows.get()), NULL);
992 
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());
997 
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]);
1001 }
1002