• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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/file_util.h"
6 #include "base/memory/scoped_ptr.h"
7 #include "base/memory/scoped_vector.h"
8 #include "base/memory/scoped_temp_dir.h"
9 #include "base/path_service.h"
10 #include "base/stl_util-inl.h"
11 #include "base/string_number_conversions.h"
12 #include "base/time.h"
13 #include "base/utf_string_conversions.h"
14 #include "chrome/browser/defaults.h"
15 #include "chrome/browser/sessions/session_backend.h"
16 #include "chrome/browser/sessions/session_service.h"
17 #include "chrome/browser/sessions/session_service_test_helper.h"
18 #include "chrome/browser/sessions/session_types.h"
19 #include "chrome/common/chrome_paths.h"
20 #include "chrome/test/browser_with_test_window_test.h"
21 #include "chrome/test/file_test_utils.h"
22 #include "chrome/test/testing_profile.h"
23 #include "content/browser/tab_contents/navigation_entry.h"
24 #include "content/common/notification_observer.h"
25 #include "content/common/notification_registrar.h"
26 #include "content/common/notification_service.h"
27 #include "content/common/notification_type.h"
28 #include "testing/gtest/include/gtest/gtest.h"
29 
30 class SessionServiceTest : public BrowserWithTestWindowTest,
31                            public NotificationObserver {
32  public:
SessionServiceTest()33   SessionServiceTest() : window_bounds(0, 1, 2, 3), sync_save_count_(0){}
34 
35  protected:
SetUp()36   virtual void SetUp() {
37     BrowserWithTestWindowTest::SetUp();
38     std::string b = base::Int64ToString(base::Time::Now().ToInternalValue());
39 
40     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
41     path_ = temp_dir_.path().Append(FILE_PATH_LITERAL("SessionTestDirs"));
42     file_util::CreateDirectory(path_);
43     path_deleter_.reset(new FileAutoDeleter(path_));
44     path_ = path_.AppendASCII(b);
45 
46     SessionService* session_service = new SessionService(path_);
47     helper_.set_service(session_service);
48 
49     service()->SetWindowType(window_id, Browser::TYPE_NORMAL);
50     service()->SetWindowBounds(window_id, window_bounds, false);
51   }
52 
53   // Upon notification, increment the sync_save_count variable
Observe(NotificationType type,const NotificationSource & source,const NotificationDetails & details)54   void Observe(NotificationType type,
55                const NotificationSource& source,
56                const NotificationDetails& details) {
57     ASSERT_EQ(type.value, NotificationType::SESSION_SERVICE_SAVED);
58     sync_save_count_++;
59   }
60 
TearDown()61   virtual void TearDown() {
62     helper_.set_service(NULL);
63     path_deleter_.reset();
64   }
65 
UpdateNavigation(const SessionID & window_id,const SessionID & tab_id,const TabNavigation & navigation,int index,bool select)66   void UpdateNavigation(const SessionID& window_id,
67                         const SessionID& tab_id,
68                         const TabNavigation& navigation,
69                         int index,
70                         bool select) {
71     NavigationEntry entry;
72     entry.set_url(navigation.virtual_url());
73     entry.set_referrer(navigation.referrer());
74     entry.set_title(navigation.title());
75     entry.set_content_state(navigation.state());
76     entry.set_transition_type(navigation.transition());
77     entry.set_has_post_data(
78         navigation.type_mask() & TabNavigation::HAS_POST_DATA);
79     service()->UpdateTabNavigation(window_id, tab_id, index, entry);
80     if (select)
81       service()->SetSelectedNavigationIndex(window_id, tab_id, index);
82   }
83 
ReadWindows(std::vector<SessionWindow * > * windows)84   void ReadWindows(std::vector<SessionWindow*>* windows) {
85     // Forces closing the file.
86     helper_.set_service(NULL);
87 
88     SessionService* session_service = new SessionService(path_);
89     helper_.set_service(session_service);
90     helper_.ReadWindows(windows);
91   }
92 
93   // Configures the session service with one window with one tab and a single
94   // navigation. If |pinned_state| is true or |write_always| is true, the
95   // pinned state of the tab is updated. The session service is then recreated
96   // and the pinned state of the read back tab is returned.
CreateAndWriteSessionWithOneTab(bool pinned_state,bool write_always)97   bool CreateAndWriteSessionWithOneTab(bool pinned_state, bool write_always) {
98     SessionID tab_id;
99     TabNavigation nav1(0, GURL("http://google.com"),
100                        GURL("http://www.referrer.com"),
101                        ASCIIToUTF16("abc"), "def",
102                        PageTransition::QUALIFIER_MASK);
103 
104     helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
105     UpdateNavigation(window_id, tab_id, nav1, 0, true);
106 
107     if (pinned_state || write_always)
108       helper_.service()->SetPinnedState(window_id, tab_id, pinned_state);
109 
110     ScopedVector<SessionWindow> windows;
111     ReadWindows(&(windows.get()));
112 
113     EXPECT_EQ(1U, windows->size());
114     if (HasFatalFailure())
115       return false;
116     EXPECT_EQ(1U, windows[0]->tabs.size());
117     if (HasFatalFailure())
118       return false;
119 
120     SessionTab* tab = windows[0]->tabs[0];
121     helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
122 
123     return tab->pinned;
124   }
125 
service()126   SessionService* service() { return helper_.service(); }
127 
backend()128   SessionBackend* backend() { return helper_.backend(); }
129 
130   const gfx::Rect window_bounds;
131 
132   SessionID window_id;
133 
134   int sync_save_count_;
135 
136   // Path used in testing.
137   ScopedTempDir temp_dir_;
138   FilePath path_;
139   scoped_ptr<FileAutoDeleter> path_deleter_;
140 
141   SessionServiceTestHelper helper_;
142 };
143 
TEST_F(SessionServiceTest,Basic)144 TEST_F(SessionServiceTest, Basic) {
145   SessionID tab_id;
146   ASSERT_NE(window_id.id(), tab_id.id());
147 
148   TabNavigation nav1(0, GURL("http://google.com"),
149                      GURL("http://www.referrer.com"),
150                      ASCIIToUTF16("abc"), "def",
151                      PageTransition::QUALIFIER_MASK);
152 
153   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
154   UpdateNavigation(window_id, tab_id, nav1, 0, true);
155 
156   ScopedVector<SessionWindow> windows;
157   ReadWindows(&(windows.get()));
158 
159   ASSERT_EQ(1U, windows->size());
160   ASSERT_TRUE(window_bounds == windows[0]->bounds);
161   ASSERT_EQ(0, windows[0]->selected_tab_index);
162   ASSERT_EQ(window_id.id(), windows[0]->window_id.id());
163   ASSERT_EQ(1U, windows[0]->tabs.size());
164   ASSERT_EQ(Browser::TYPE_NORMAL, windows[0]->type);
165 
166   SessionTab* tab = windows[0]->tabs[0];
167   helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
168 
169   helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
170 }
171 
172 // Make sure we persist post entries.
TEST_F(SessionServiceTest,PersistPostData)173 TEST_F(SessionServiceTest, PersistPostData) {
174   SessionID tab_id;
175   ASSERT_NE(window_id.id(), tab_id.id());
176 
177   TabNavigation nav1(0, GURL("http://google.com"), GURL(),
178                      ASCIIToUTF16("abc"), std::string(),
179                      PageTransition::QUALIFIER_MASK);
180   nav1.set_type_mask(TabNavigation::HAS_POST_DATA);
181 
182   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
183   UpdateNavigation(window_id, tab_id, nav1, 0, true);
184 
185   ScopedVector<SessionWindow> windows;
186   ReadWindows(&(windows.get()));
187 
188   helper_.AssertSingleWindowWithSingleTab(windows.get(), 1);
189 }
190 
TEST_F(SessionServiceTest,ClosingTabStaysClosed)191 TEST_F(SessionServiceTest, ClosingTabStaysClosed) {
192   SessionID tab_id;
193   SessionID tab2_id;
194   ASSERT_NE(tab_id.id(), tab2_id.id());
195 
196   TabNavigation nav1(0, GURL("http://google.com"), GURL(),
197                      ASCIIToUTF16("abc"), "def",
198                      PageTransition::QUALIFIER_MASK);
199   TabNavigation nav2(0, GURL("http://google2.com"), GURL(),
200                      ASCIIToUTF16("abcd"), "defg",
201                      PageTransition::AUTO_BOOKMARK);
202 
203   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
204   UpdateNavigation(window_id, tab_id, nav1, 0, true);
205 
206   helper_.PrepareTabInWindow(window_id, tab2_id, 1, false);
207   UpdateNavigation(window_id, tab2_id, nav2, 0, true);
208   service()->TabClosed(window_id, tab2_id, false);
209 
210   ScopedVector<SessionWindow> windows;
211   ReadWindows(&(windows.get()));
212 
213   ASSERT_EQ(1U, windows->size());
214   ASSERT_EQ(0, windows[0]->selected_tab_index);
215   ASSERT_EQ(window_id.id(), windows[0]->window_id.id());
216   ASSERT_EQ(1U, windows[0]->tabs.size());
217 
218   SessionTab* tab = windows[0]->tabs[0];
219   helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
220 
221   helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
222 }
223 
TEST_F(SessionServiceTest,Pruning)224 TEST_F(SessionServiceTest, Pruning) {
225   SessionID tab_id;
226 
227   TabNavigation nav1(0, GURL("http://google.com"), GURL(),
228                      ASCIIToUTF16("abc"), "def",
229                      PageTransition::QUALIFIER_MASK);
230   TabNavigation nav2(0, GURL("http://google2.com"), GURL(),
231                      ASCIIToUTF16("abcd"), "defg",
232                      PageTransition::AUTO_BOOKMARK);
233 
234   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
235   for (int i = 0; i < 6; ++i) {
236     TabNavigation& nav = (i % 2) == 0 ? nav1 : nav2;
237     UpdateNavigation(window_id, tab_id, nav, i, true);
238   }
239   service()->TabNavigationPathPrunedFromBack(window_id, tab_id, 3);
240 
241   ScopedVector<SessionWindow> windows;
242   ReadWindows(&(windows.get()));
243 
244   ASSERT_EQ(1U, windows->size());
245   ASSERT_EQ(0, windows[0]->selected_tab_index);
246   ASSERT_EQ(1U, windows[0]->tabs.size());
247 
248   SessionTab* tab = windows[0]->tabs[0];
249   // We left the selected index at 5, then pruned. When rereading the
250   // index should get reset to last valid navigation, which is 2.
251   helper_.AssertTabEquals(window_id, tab_id, 0, 2, 3, *tab);
252 
253   helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
254   helper_.AssertNavigationEquals(nav2, tab->navigations[1]);
255   helper_.AssertNavigationEquals(nav1, tab->navigations[2]);
256 }
257 
TEST_F(SessionServiceTest,TwoWindows)258 TEST_F(SessionServiceTest, TwoWindows) {
259   SessionID window2_id;
260   SessionID tab1_id;
261   SessionID tab2_id;
262 
263   TabNavigation nav1(0, GURL("http://google.com"), GURL(),
264                      ASCIIToUTF16("abc"), "def",
265                      PageTransition::QUALIFIER_MASK);
266   TabNavigation nav2(0, GURL("http://google2.com"), GURL(),
267                      ASCIIToUTF16("abcd"), "defg",
268                      PageTransition::AUTO_BOOKMARK);
269 
270   helper_.PrepareTabInWindow(window_id, tab1_id, 0, true);
271   UpdateNavigation(window_id, tab1_id, nav1, 0, true);
272 
273   const gfx::Rect window2_bounds(3, 4, 5, 6);
274   service()->SetWindowType(window2_id, Browser::TYPE_NORMAL);
275   service()->SetWindowBounds(window2_id, window2_bounds, true);
276   helper_.PrepareTabInWindow(window2_id, tab2_id, 0, true);
277   UpdateNavigation(window2_id, tab2_id, nav2, 0, true);
278 
279   ScopedVector<SessionWindow> windows;
280   ReadWindows(&(windows.get()));
281 
282   ASSERT_EQ(2U, windows->size());
283   ASSERT_EQ(0, windows[0]->selected_tab_index);
284   ASSERT_EQ(0, windows[1]->selected_tab_index);
285   ASSERT_EQ(1U, windows[0]->tabs.size());
286   ASSERT_EQ(1U, windows[1]->tabs.size());
287 
288   SessionTab* rt1;
289   SessionTab* rt2;
290   if (windows[0]->window_id.id() == window_id.id()) {
291     ASSERT_EQ(window2_id.id(), windows[1]->window_id.id());
292     ASSERT_FALSE(windows[0]->is_maximized);
293     ASSERT_TRUE(windows[1]->is_maximized);
294     rt1 = windows[0]->tabs[0];
295     rt2 = windows[1]->tabs[0];
296   } else {
297     ASSERT_EQ(window2_id.id(), windows[0]->window_id.id());
298     ASSERT_EQ(window_id.id(), windows[1]->window_id.id());
299     ASSERT_TRUE(windows[0]->is_maximized);
300     ASSERT_FALSE(windows[1]->is_maximized);
301     rt1 = windows[1]->tabs[0];
302     rt2 = windows[0]->tabs[0];
303   }
304   SessionTab* tab = rt1;
305   helper_.AssertTabEquals(window_id, tab1_id, 0, 0, 1, *tab);
306   helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
307 
308   tab = rt2;
309   helper_.AssertTabEquals(window2_id, tab2_id, 0, 0, 1, *tab);
310   helper_.AssertNavigationEquals(nav2, tab->navigations[0]);
311 }
312 
TEST_F(SessionServiceTest,WindowWithNoTabsGetsPruned)313 TEST_F(SessionServiceTest, WindowWithNoTabsGetsPruned) {
314   SessionID window2_id;
315   SessionID tab1_id;
316   SessionID tab2_id;
317 
318   TabNavigation nav1(0, GURL("http://google.com"), GURL(),
319                      ASCIIToUTF16("abc"), "def",
320                      PageTransition::QUALIFIER_MASK);
321 
322   helper_.PrepareTabInWindow(window_id, tab1_id, 0, true);
323   UpdateNavigation(window_id, tab1_id, nav1, 0, true);
324 
325   const gfx::Rect window2_bounds(3, 4, 5, 6);
326   service()->SetWindowType(window2_id, Browser::TYPE_NORMAL);
327   service()->SetWindowBounds(window2_id, window2_bounds, false);
328   helper_.PrepareTabInWindow(window2_id, tab2_id, 0, true);
329 
330   ScopedVector<SessionWindow> windows;
331   ReadWindows(&(windows.get()));
332 
333   ASSERT_EQ(1U, windows->size());
334   ASSERT_EQ(0, windows[0]->selected_tab_index);
335   ASSERT_EQ(1U, windows[0]->tabs.size());
336   ASSERT_EQ(window_id.id(), windows[0]->window_id.id());
337 
338   SessionTab* tab = windows[0]->tabs[0];
339   helper_.AssertTabEquals(window_id, tab1_id, 0, 0, 1, *tab);
340   helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
341 }
342 
TEST_F(SessionServiceTest,ClosingWindowDoesntCloseTabs)343 TEST_F(SessionServiceTest, ClosingWindowDoesntCloseTabs) {
344   SessionID tab_id;
345   SessionID tab2_id;
346   ASSERT_NE(tab_id.id(), tab2_id.id());
347 
348   TabNavigation nav1(0, GURL("http://google.com"), GURL(),
349                      ASCIIToUTF16("abc"), "def",
350                      PageTransition::QUALIFIER_MASK);
351   TabNavigation nav2(0, GURL("http://google2.com"), GURL(),
352                      ASCIIToUTF16("abcd"), "defg",
353                      PageTransition::AUTO_BOOKMARK);
354 
355   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
356   UpdateNavigation(window_id, tab_id, nav1, 0, true);
357 
358   helper_.PrepareTabInWindow(window_id, tab2_id, 1, false);
359   UpdateNavigation(window_id, tab2_id, nav2, 0, true);
360 
361   service()->WindowClosing(window_id);
362 
363   ScopedVector<SessionWindow> windows;
364   ReadWindows(&(windows.get()));
365 
366   ASSERT_EQ(1U, windows->size());
367   ASSERT_EQ(0, windows[0]->selected_tab_index);
368   ASSERT_EQ(window_id.id(), windows[0]->window_id.id());
369   ASSERT_EQ(2U, windows[0]->tabs.size());
370 
371   SessionTab* tab = windows[0]->tabs[0];
372   helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
373   helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
374 
375   tab = windows[0]->tabs[1];
376   helper_.AssertTabEquals(window_id, tab2_id, 1, 0, 1, *tab);
377   helper_.AssertNavigationEquals(nav2, tab->navigations[0]);
378 }
379 
TEST_F(SessionServiceTest,WindowCloseCommittedAfterNavigate)380 TEST_F(SessionServiceTest, WindowCloseCommittedAfterNavigate) {
381   SessionID window2_id;
382   SessionID tab_id;
383   SessionID tab2_id;
384   ASSERT_NE(window2_id.id(), window_id.id());
385 
386   service()->SetWindowType(window2_id, Browser::TYPE_NORMAL);
387   service()->SetWindowBounds(window2_id, window_bounds, false);
388 
389   TabNavigation nav1(0, GURL("http://google.com"), GURL(),
390                      ASCIIToUTF16("abc"), "def",
391                      PageTransition::QUALIFIER_MASK);
392   TabNavigation nav2(0, GURL("http://google2.com"), GURL(),
393                      ASCIIToUTF16("abcd"), "defg",
394                      PageTransition::AUTO_BOOKMARK);
395 
396   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
397   UpdateNavigation(window_id, tab_id, nav1, 0, true);
398 
399   helper_.PrepareTabInWindow(window2_id, tab2_id, 0, false);
400   UpdateNavigation(window2_id, tab2_id, nav2, 0, true);
401 
402   service()->WindowClosing(window2_id);
403   service()->TabClosed(window2_id, tab2_id, false);
404   service()->WindowClosed(window2_id);
405 
406   ScopedVector<SessionWindow> windows;
407   ReadWindows(&(windows.get()));
408 
409   ASSERT_EQ(1U, windows->size());
410   ASSERT_EQ(0, windows[0]->selected_tab_index);
411   ASSERT_EQ(window_id.id(), windows[0]->window_id.id());
412   ASSERT_EQ(1U, windows[0]->tabs.size());
413 
414   SessionTab* tab = windows[0]->tabs[0];
415   helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
416   helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
417 }
418 
419 // Makes sure we don't track popups.
TEST_F(SessionServiceTest,IgnorePopups)420 TEST_F(SessionServiceTest, IgnorePopups) {
421   if (browser_defaults::kRestorePopups)
422     return;  // This test is only applicable if popups aren't restored.
423 
424   SessionID window2_id;
425   SessionID tab_id;
426   SessionID tab2_id;
427   ASSERT_NE(window2_id.id(), window_id.id());
428 
429   service()->SetWindowType(window2_id, Browser::TYPE_POPUP);
430   service()->SetWindowBounds(window2_id, window_bounds, false);
431 
432   TabNavigation nav1(0, GURL("http://google.com"), GURL(),
433                      ASCIIToUTF16("abc"), "def",
434                      PageTransition::QUALIFIER_MASK);
435   TabNavigation nav2(0, GURL("http://google2.com"), GURL(),
436                      ASCIIToUTF16("abcd"), "defg",
437                      PageTransition::AUTO_BOOKMARK);
438 
439   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
440   UpdateNavigation(window_id, tab_id, nav1, 0, true);
441 
442   helper_.PrepareTabInWindow(window2_id, tab2_id, 0, false);
443   UpdateNavigation(window2_id, tab2_id, nav2, 0, true);
444 
445   ScopedVector<SessionWindow> windows;
446   ReadWindows(&(windows.get()));
447 
448   ASSERT_EQ(1U, windows->size());
449   ASSERT_EQ(0, windows[0]->selected_tab_index);
450   ASSERT_EQ(window_id.id(), windows[0]->window_id.id());
451   ASSERT_EQ(1U, windows[0]->tabs.size());
452 
453   SessionTab* tab = windows[0]->tabs[0];
454   helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
455   helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
456 }
457 
458 // Makes sure we track popups.
TEST_F(SessionServiceTest,RestorePopup)459 TEST_F(SessionServiceTest, RestorePopup) {
460   if (!browser_defaults::kRestorePopups)
461     return;  // This test is only applicable if popups are restored.
462 
463   SessionID window2_id;
464   SessionID tab_id;
465   SessionID tab2_id;
466   ASSERT_NE(window2_id.id(), window_id.id());
467 
468   service()->SetWindowType(window2_id, Browser::TYPE_POPUP);
469   service()->SetWindowBounds(window2_id, window_bounds, false);
470 
471   TabNavigation nav1(0, GURL("http://google.com"), GURL(),
472                      ASCIIToUTF16("abc"), "def",
473                      PageTransition::QUALIFIER_MASK);
474   TabNavigation nav2(0, GURL("http://google2.com"), GURL(),
475                      ASCIIToUTF16("abcd"), "defg",
476                      PageTransition::AUTO_BOOKMARK);
477 
478   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
479   UpdateNavigation(window_id, tab_id, nav1, 0, true);
480 
481   helper_.PrepareTabInWindow(window2_id, tab2_id, 0, false);
482   UpdateNavigation(window2_id, tab2_id, nav2, 0, true);
483 
484   ScopedVector<SessionWindow> windows;
485   ReadWindows(&(windows.get()));
486 
487   ASSERT_EQ(2U, windows->size());
488   int normal_index = windows[0]->type == Browser::TYPE_NORMAL ?
489       0 : 1;
490   int popup_index = normal_index == 0 ? 1 : 0;
491   ASSERT_EQ(0, windows[normal_index]->selected_tab_index);
492   ASSERT_EQ(window_id.id(), windows[normal_index]->window_id.id());
493   ASSERT_EQ(1U, windows[normal_index]->tabs.size());
494 
495   SessionTab* tab = windows[normal_index]->tabs[0];
496   helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
497   helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
498 
499   ASSERT_EQ(0, windows[popup_index]->selected_tab_index);
500   ASSERT_EQ(window2_id.id(), windows[popup_index]->window_id.id());
501   ASSERT_EQ(1U, windows[popup_index]->tabs.size());
502 
503   tab = windows[popup_index]->tabs[0];
504   helper_.AssertTabEquals(window2_id, tab2_id, 0, 0, 1, *tab);
505   helper_.AssertNavigationEquals(nav2, tab->navigations[0]);
506 }
507 
508 // Tests pruning from the front.
TEST_F(SessionServiceTest,PruneFromFront)509 TEST_F(SessionServiceTest, PruneFromFront) {
510   const std::string base_url("http://google.com/");
511   SessionID tab_id;
512 
513   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
514 
515   // Add 5 navigations, with the 4th selected.
516   for (int i = 0; i < 5; ++i) {
517     TabNavigation nav(0, GURL(base_url + base::IntToString(i)), GURL(),
518                       ASCIIToUTF16("a"), "b", PageTransition::QUALIFIER_MASK);
519     UpdateNavigation(window_id, tab_id, nav, i, (i == 3));
520   }
521 
522   // Prune the first two navigations from the front.
523   helper_.service()->TabNavigationPathPrunedFromFront(window_id, tab_id, 2);
524 
525   // Read back in.
526   ScopedVector<SessionWindow> windows;
527   ReadWindows(&(windows.get()));
528 
529   ASSERT_EQ(1U, windows->size());
530   ASSERT_EQ(0, windows[0]->selected_tab_index);
531   ASSERT_EQ(window_id.id(), windows[0]->window_id.id());
532   ASSERT_EQ(1U, windows[0]->tabs.size());
533 
534   // There shouldn't be an app id.
535   EXPECT_TRUE(windows[0]->tabs[0]->extension_app_id.empty());
536 
537   // We should be left with three navigations, the 2nd selected.
538   SessionTab* tab = windows[0]->tabs[0];
539   ASSERT_EQ(1, tab->current_navigation_index);
540   EXPECT_EQ(3U, tab->navigations.size());
541   EXPECT_TRUE(GURL(base_url + base::IntToString(2)) ==
542               tab->navigations[0].virtual_url());
543   EXPECT_TRUE(GURL(base_url + base::IntToString(3)) ==
544               tab->navigations[1].virtual_url());
545   EXPECT_TRUE(GURL(base_url + base::IntToString(4)) ==
546               tab->navigations[2].virtual_url());
547 }
548 
549 // Prunes from front so that we have no entries.
TEST_F(SessionServiceTest,PruneToEmpty)550 TEST_F(SessionServiceTest, PruneToEmpty) {
551   const std::string base_url("http://google.com/");
552   SessionID tab_id;
553 
554   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
555 
556   // Add 5 navigations, with the 4th selected.
557   for (int i = 0; i < 5; ++i) {
558     TabNavigation nav(0, GURL(base_url + base::IntToString(i)), GURL(),
559                       ASCIIToUTF16("a"), "b", PageTransition::QUALIFIER_MASK);
560     UpdateNavigation(window_id, tab_id, nav, i, (i == 3));
561   }
562 
563   // Prune the first two navigations from the front.
564   helper_.service()->TabNavigationPathPrunedFromFront(window_id, tab_id, 5);
565 
566   // Read back in.
567   ScopedVector<SessionWindow> windows;
568   ReadWindows(&(windows.get()));
569 
570   ASSERT_EQ(0U, windows->size());
571 }
572 
573 // Don't set the pinned state and make sure the pinned value is false.
TEST_F(SessionServiceTest,PinnedDefaultsToFalse)574 TEST_F(SessionServiceTest, PinnedDefaultsToFalse) {
575   EXPECT_FALSE(CreateAndWriteSessionWithOneTab(false, false));
576 }
577 
578 // Explicitly set the pinned state to false and make sure we get back false.
TEST_F(SessionServiceTest,PinnedFalseWhenSetToFalse)579 TEST_F(SessionServiceTest, PinnedFalseWhenSetToFalse) {
580   EXPECT_FALSE(CreateAndWriteSessionWithOneTab(false, true));
581 }
582 
583 // Make sure application extension ids are persisted.
TEST_F(SessionServiceTest,PersistApplicationExtensionID)584 TEST_F(SessionServiceTest, PersistApplicationExtensionID) {
585   SessionID tab_id;
586   ASSERT_NE(window_id.id(), tab_id.id());
587   std::string app_id("foo");
588 
589   TabNavigation nav1(0, GURL("http://google.com"), GURL(),
590                      ASCIIToUTF16("abc"), std::string(),
591                      PageTransition::QUALIFIER_MASK);
592 
593   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
594   UpdateNavigation(window_id, tab_id, nav1, 0, true);
595   helper_.SetTabExtensionAppID(window_id, tab_id, app_id);
596 
597   ScopedVector<SessionWindow> windows;
598   ReadWindows(&(windows.get()));
599 
600   helper_.AssertSingleWindowWithSingleTab(windows.get(), 1);
601   EXPECT_TRUE(app_id == windows[0]->tabs[0]->extension_app_id);
602 }
603 
604 // Explicitly set the pinned state to true and make sure we get back true.
TEST_F(SessionServiceTest,PinnedTrue)605 TEST_F(SessionServiceTest, PinnedTrue) {
606   EXPECT_TRUE(CreateAndWriteSessionWithOneTab(true, true));
607 }
608 
609 class GetCurrentSessionCallbackHandler {
610  public:
OnGotSession(int handle,std::vector<SessionWindow * > * windows)611   void OnGotSession(int handle, std::vector<SessionWindow*>* windows) {
612     EXPECT_EQ(1U, windows->size());
613     EXPECT_EQ(2U, (*windows)[0]->tabs.size());
614     EXPECT_EQ(2U, (*windows)[0]->tabs[0]->navigations.size());
615     EXPECT_EQ(GURL("http://bar/1"),
616               (*windows)[0]->tabs[0]->navigations[0].virtual_url());
617     EXPECT_EQ(GURL("http://bar/2"),
618               (*windows)[0]->tabs[0]->navigations[1].virtual_url());
619     EXPECT_EQ(2U, (*windows)[0]->tabs[1]->navigations.size());
620     EXPECT_EQ(GURL("http://foo/1"),
621               (*windows)[0]->tabs[1]->navigations[0].virtual_url());
622     EXPECT_EQ(GURL("http://foo/2"),
623               (*windows)[0]->tabs[1]->navigations[1].virtual_url());
624   }
625 };
626 
TEST_F(SessionServiceTest,GetCurrentSession)627 TEST_F(SessionServiceTest, GetCurrentSession) {
628   AddTab(browser(), GURL("http://foo/1"));
629   NavigateAndCommitActiveTab(GURL("http://foo/2"));
630   AddTab(browser(), GURL("http://bar/1"));
631   NavigateAndCommitActiveTab(GURL("http://bar/2"));
632 
633   CancelableRequestConsumer consumer;
634   GetCurrentSessionCallbackHandler handler;
635   service()->GetCurrentSession(&consumer,
636       NewCallback(&handler, &GetCurrentSessionCallbackHandler::OnGotSession));
637 }
638 
639 // Test that the notification for SESSION_SERVICE_SAVED is working properly.
TEST_F(SessionServiceTest,SavedSessionNotification)640 TEST_F(SessionServiceTest, SavedSessionNotification) {
641   NotificationRegistrar registrar_;
642   registrar_.Add(this, NotificationType::SESSION_SERVICE_SAVED,
643                  NotificationService::AllSources());
644   service()->Save();
645   EXPECT_EQ(sync_save_count_, 1);
646 }
647 
648 // Makes sure a tab closed by a user gesture is not restored.
TEST_F(SessionServiceTest,CloseTabUserGesture)649 TEST_F(SessionServiceTest, CloseTabUserGesture) {
650   SessionID tab_id;
651   ASSERT_NE(window_id.id(), tab_id.id());
652 
653   TabNavigation nav1(0, GURL("http://google.com"),
654                      GURL("http://www.referrer.com"),
655                      ASCIIToUTF16("abc"), "def",
656                      PageTransition::QUALIFIER_MASK);
657 
658   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
659   UpdateNavigation(window_id, tab_id, nav1, 0, true);
660   service()->TabClosed(window_id, tab_id, true);
661 
662   ScopedVector<SessionWindow> windows;
663   ReadWindows(&(windows.get()));
664 
665   ASSERT_TRUE(windows->empty());
666 }
667