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