- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / sessions / session_service_unittest.cc
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/chrome_notification_types.h"
17 #include "chrome/browser/defaults.h"
18 #include "chrome/browser/sessions/session_backend.h"
19 #include "chrome/browser/sessions/session_service.h"
20 #include "chrome/browser/sessions/session_service_test_helper.h"
21 #include "chrome/browser/sessions/session_types.h"
22 #include "chrome/common/chrome_paths.h"
23 #include "chrome/test/base/browser_with_test_window_test.h"
24 #include "chrome/test/base/testing_profile.h"
25 #include "components/sessions/serialized_navigation_entry_test_helper.h"
26 #include "content/public/browser/navigation_entry.h"
27 #include "content/public/browser/notification_observer.h"
28 #include "content/public/browser/notification_registrar.h"
29 #include "content/public/browser/notification_service.h"
30 #include "content/public/common/page_state.h"
31 #include "testing/gtest/include/gtest/gtest.h"
32
33 using content::NavigationEntry;
34 using sessions::SerializedNavigationEntry;
35 using sessions::SerializedNavigationEntryTestHelper;
36
37 class SessionServiceTest : public BrowserWithTestWindowTest,
38                            public content::NotificationObserver {
39  public:
40   SessionServiceTest() : window_bounds(0, 1, 2, 3), sync_save_count_(0) {}
41
42  protected:
43   virtual void SetUp() {
44     BrowserWithTestWindowTest::SetUp();
45     std::string b = base::Int64ToString(base::Time::Now().ToInternalValue());
46
47     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
48     path_ = temp_dir_.path().Append(FILE_PATH_LITERAL("SessionTestDirs"));
49     ASSERT_TRUE(file_util::CreateDirectory(path_));
50     path_ = path_.AppendASCII(b);
51
52     SessionService* session_service = new SessionService(path_);
53     helper_.SetService(session_service);
54
55     service()->SetWindowType(
56         window_id, Browser::TYPE_TABBED, SessionService::TYPE_NORMAL);
57     service()->SetWindowBounds(window_id,
58                                window_bounds,
59                                ui::SHOW_STATE_NORMAL);
60   }
61
62   // Upon notification, increment the sync_save_count variable
63   virtual void Observe(int type,
64                        const content::NotificationSource& source,
65                        const content::NotificationDetails& details) OVERRIDE {
66     ASSERT_EQ(type, chrome::NOTIFICATION_SESSION_SERVICE_SAVED);
67     sync_save_count_++;
68   }
69
70   virtual void TearDown() {
71     helper_.SetService(NULL);
72     BrowserWithTestWindowTest::TearDown();
73   }
74
75   void UpdateNavigation(
76       const SessionID& window_id,
77       const SessionID& tab_id,
78       const SerializedNavigationEntry& navigation,
79       bool select) {
80     service()->UpdateTabNavigation(window_id, tab_id, navigation);
81     if (select) {
82       service()->SetSelectedNavigationIndex(
83           window_id, tab_id, navigation.index());
84     }
85   }
86
87   void ReadWindows(std::vector<SessionWindow*>* windows,
88                    SessionID::id_type* active_window_id) {
89     // Forces closing the file.
90     helper_.SetService(NULL);
91
92     SessionService* session_service = new SessionService(path_);
93     helper_.SetService(session_service);
94
95     SessionID::id_type* non_null_active_window_id = active_window_id;
96     SessionID::id_type dummy_active_window_id = 0;
97     if (!non_null_active_window_id)
98       non_null_active_window_id = &dummy_active_window_id;
99     helper_.ReadWindows(windows, non_null_active_window_id);
100   }
101
102   // Configures the session service with one window with one tab and a single
103   // navigation. If |pinned_state| is true or |write_always| is true, the
104   // pinned state of the tab is updated. The session service is then recreated
105   // and the pinned state of the read back tab is returned.
106   bool CreateAndWriteSessionWithOneTab(bool pinned_state, bool write_always) {
107     SessionID tab_id;
108     SerializedNavigationEntry nav1 =
109         SerializedNavigationEntryTestHelper::CreateNavigation(
110             "http://google.com", "abc");
111
112     helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
113     UpdateNavigation(window_id, tab_id, nav1, true);
114
115     if (pinned_state || write_always)
116       helper_.service()->SetPinnedState(window_id, tab_id, pinned_state);
117
118     ScopedVector<SessionWindow> windows;
119     ReadWindows(&(windows.get()), NULL);
120
121     EXPECT_EQ(1U, windows.size());
122     if (HasFatalFailure())
123       return false;
124     EXPECT_EQ(1U, windows[0]->tabs.size());
125     if (HasFatalFailure())
126       return false;
127
128     SessionTab* tab = windows[0]->tabs[0];
129     helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
130
131     return tab->pinned;
132   }
133
134   void CreateAndWriteSessionWithTwoWindows(
135       const SessionID& window2_id,
136       const SessionID& tab1_id,
137       const SessionID& tab2_id,
138       SerializedNavigationEntry* nav1,
139       SerializedNavigationEntry* nav2) {
140     *nav1 = SerializedNavigationEntryTestHelper::CreateNavigation(
141         "http://google.com", "abc");
142     *nav2 = SerializedNavigationEntryTestHelper::CreateNavigation(
143         "http://google2.com", "abcd");
144
145     helper_.PrepareTabInWindow(window_id, tab1_id, 0, true);
146     UpdateNavigation(window_id, tab1_id, *nav1, true);
147
148     const gfx::Rect window2_bounds(3, 4, 5, 6);
149     service()->SetWindowType(
150         window2_id, Browser::TYPE_TABBED, SessionService::TYPE_NORMAL);
151     service()->SetWindowBounds(window2_id,
152                                window2_bounds,
153                                ui::SHOW_STATE_MAXIMIZED);
154     helper_.PrepareTabInWindow(window2_id, tab2_id, 0, true);
155     UpdateNavigation(window2_id, tab2_id, *nav2, true);
156   }
157
158   SessionService* service() { return helper_.service(); }
159
160   SessionBackend* backend() { return helper_.backend(); }
161
162   const gfx::Rect window_bounds;
163
164   SessionID window_id;
165
166   int sync_save_count_;
167
168   // Path used in testing.
169   base::ScopedTempDir temp_dir_;
170   base::FilePath path_;
171
172   SessionServiceTestHelper helper_;
173 };
174
175 TEST_F(SessionServiceTest, Basic) {
176   SessionID tab_id;
177   ASSERT_NE(window_id.id(), tab_id.id());
178
179   SerializedNavigationEntry nav1 =
180       SerializedNavigationEntryTestHelper::CreateNavigation(
181           "http://google.com", "abc");
182   SerializedNavigationEntryTestHelper::SetOriginalRequestURL(
183       GURL("http://original.request.com"), &nav1);
184
185   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
186   UpdateNavigation(window_id, tab_id, nav1, true);
187
188   ScopedVector<SessionWindow> windows;
189   ReadWindows(&(windows.get()), NULL);
190
191   ASSERT_EQ(1U, windows.size());
192   ASSERT_TRUE(window_bounds == windows[0]->bounds);
193   ASSERT_EQ(0, windows[0]->selected_tab_index);
194   ASSERT_EQ(window_id.id(), windows[0]->window_id.id());
195   ASSERT_EQ(1U, windows[0]->tabs.size());
196   ASSERT_EQ(Browser::TYPE_TABBED, windows[0]->type);
197
198   SessionTab* tab = windows[0]->tabs[0];
199   helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
200
201   helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
202 }
203
204 // Make sure we persist post entries.
205 TEST_F(SessionServiceTest, PersistPostData) {
206   SessionID tab_id;
207   ASSERT_NE(window_id.id(), tab_id.id());
208
209   SerializedNavigationEntry nav1 =
210       SerializedNavigationEntryTestHelper::CreateNavigation(
211           "http://google.com", "abc");
212   SerializedNavigationEntryTestHelper::SetHasPostData(true, &nav1);
213
214   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
215   UpdateNavigation(window_id, tab_id, nav1, true);
216
217   ScopedVector<SessionWindow> windows;
218   ReadWindows(&(windows.get()), NULL);
219
220   helper_.AssertSingleWindowWithSingleTab(windows.get(), 1);
221 }
222
223 TEST_F(SessionServiceTest, ClosingTabStaysClosed) {
224   SessionID tab_id;
225   SessionID tab2_id;
226   ASSERT_NE(tab_id.id(), tab2_id.id());
227
228   SerializedNavigationEntry nav1 =
229       SerializedNavigationEntryTestHelper::CreateNavigation(
230           "http://google.com", "abc");
231   SerializedNavigationEntry nav2 =
232       SerializedNavigationEntryTestHelper::CreateNavigation(
233           "http://google2.com", "abcd");
234
235   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
236   UpdateNavigation(window_id, tab_id, nav1, true);
237
238   helper_.PrepareTabInWindow(window_id, tab2_id, 1, false);
239   UpdateNavigation(window_id, tab2_id, nav2, true);
240   service()->TabClosed(window_id, tab2_id, false);
241
242   ScopedVector<SessionWindow> windows;
243   ReadWindows(&(windows.get()), NULL);
244
245   ASSERT_EQ(1U, windows.size());
246   ASSERT_EQ(0, windows[0]->selected_tab_index);
247   ASSERT_EQ(window_id.id(), windows[0]->window_id.id());
248   ASSERT_EQ(1U, windows[0]->tabs.size());
249
250   SessionTab* tab = windows[0]->tabs[0];
251   helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
252
253   helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
254 }
255
256 TEST_F(SessionServiceTest, Pruning) {
257   SessionID tab_id;
258
259   SerializedNavigationEntry nav1 =
260       SerializedNavigationEntryTestHelper::CreateNavigation(
261           "http://google.com", "abc");
262   SerializedNavigationEntry nav2 =
263       SerializedNavigationEntryTestHelper::CreateNavigation(
264           "http://google2.com", "abcd");
265
266   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
267   for (int i = 0; i < 6; ++i) {
268     SerializedNavigationEntry* nav = (i % 2) == 0 ? &nav1 : &nav2;
269     nav->set_index(i);
270     UpdateNavigation(window_id, tab_id, *nav, true);
271   }
272   service()->TabNavigationPathPrunedFromBack(window_id, tab_id, 3);
273
274   ScopedVector<SessionWindow> windows;
275   ReadWindows(&(windows.get()), NULL);
276
277   ASSERT_EQ(1U, windows.size());
278   ASSERT_EQ(0, windows[0]->selected_tab_index);
279   ASSERT_EQ(1U, windows[0]->tabs.size());
280
281   SessionTab* tab = windows[0]->tabs[0];
282   // We left the selected index at 5, then pruned. When rereading the
283   // index should get reset to last valid navigation, which is 2.
284   helper_.AssertTabEquals(window_id, tab_id, 0, 2, 3, *tab);
285
286   ASSERT_EQ(3u, tab->navigations.size());
287   helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
288   helper_.AssertNavigationEquals(nav2, tab->navigations[1]);
289   helper_.AssertNavigationEquals(nav1, tab->navigations[2]);
290 }
291
292 TEST_F(SessionServiceTest, TwoWindows) {
293   SessionID window2_id;
294   SessionID tab1_id;
295   SessionID tab2_id;
296   SerializedNavigationEntry nav1;
297   SerializedNavigationEntry nav2;
298
299   CreateAndWriteSessionWithTwoWindows(
300       window2_id, tab1_id, tab2_id, &nav1, &nav2);
301
302   ScopedVector<SessionWindow> windows;
303   ReadWindows(&(windows.get()), NULL);
304
305   ASSERT_EQ(2U, windows.size());
306   ASSERT_EQ(0, windows[0]->selected_tab_index);
307   ASSERT_EQ(0, windows[1]->selected_tab_index);
308   ASSERT_EQ(1U, windows[0]->tabs.size());
309   ASSERT_EQ(1U, windows[1]->tabs.size());
310
311   SessionTab* rt1;
312   SessionTab* rt2;
313   if (windows[0]->window_id.id() == window_id.id()) {
314     ASSERT_EQ(window2_id.id(), windows[1]->window_id.id());
315     ASSERT_EQ(ui::SHOW_STATE_NORMAL, windows[0]->show_state);
316     ASSERT_EQ(ui::SHOW_STATE_MAXIMIZED, windows[1]->show_state);
317     rt1 = windows[0]->tabs[0];
318     rt2 = windows[1]->tabs[0];
319   } else {
320     ASSERT_EQ(window2_id.id(), windows[0]->window_id.id());
321     ASSERT_EQ(window_id.id(), windows[1]->window_id.id());
322     ASSERT_EQ(ui::SHOW_STATE_MAXIMIZED, windows[0]->show_state);
323     ASSERT_EQ(ui::SHOW_STATE_NORMAL, windows[1]->show_state);
324     rt1 = windows[1]->tabs[0];
325     rt2 = windows[0]->tabs[0];
326   }
327   SessionTab* tab = rt1;
328   helper_.AssertTabEquals(window_id, tab1_id, 0, 0, 1, *tab);
329   helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
330
331   tab = rt2;
332   helper_.AssertTabEquals(window2_id, tab2_id, 0, 0, 1, *tab);
333   helper_.AssertNavigationEquals(nav2, tab->navigations[0]);
334 }
335
336 TEST_F(SessionServiceTest, WindowWithNoTabsGetsPruned) {
337   SessionID window2_id;
338   SessionID tab1_id;
339   SessionID tab2_id;
340
341   SerializedNavigationEntry nav1 =
342       SerializedNavigationEntryTestHelper::CreateNavigation(
343           "http://google.com", "abc");
344
345   helper_.PrepareTabInWindow(window_id, tab1_id, 0, true);
346   UpdateNavigation(window_id, tab1_id, nav1, true);
347
348   const gfx::Rect window2_bounds(3, 4, 5, 6);
349   service()->SetWindowType(
350       window2_id, Browser::TYPE_TABBED, SessionService::TYPE_NORMAL);
351   service()->SetWindowBounds(window2_id,
352                              window2_bounds,
353                              ui::SHOW_STATE_NORMAL);
354   helper_.PrepareTabInWindow(window2_id, tab2_id, 0, true);
355
356   ScopedVector<SessionWindow> windows;
357   ReadWindows(&(windows.get()), NULL);
358
359   ASSERT_EQ(1U, windows.size());
360   ASSERT_EQ(0, windows[0]->selected_tab_index);
361   ASSERT_EQ(1U, windows[0]->tabs.size());
362   ASSERT_EQ(window_id.id(), windows[0]->window_id.id());
363
364   SessionTab* tab = windows[0]->tabs[0];
365   helper_.AssertTabEquals(window_id, tab1_id, 0, 0, 1, *tab);
366   helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
367 }
368
369 TEST_F(SessionServiceTest, ClosingWindowDoesntCloseTabs) {
370   SessionID tab_id;
371   SessionID tab2_id;
372   ASSERT_NE(tab_id.id(), tab2_id.id());
373
374   SerializedNavigationEntry nav1 =
375       SerializedNavigationEntryTestHelper::CreateNavigation(
376           "http://google.com", "abc");
377   SerializedNavigationEntry nav2 =
378       SerializedNavigationEntryTestHelper::CreateNavigation(
379           "http://google2.com", "abcd");
380
381   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
382   UpdateNavigation(window_id, tab_id, nav1, true);
383
384   helper_.PrepareTabInWindow(window_id, tab2_id, 1, false);
385   UpdateNavigation(window_id, tab2_id, nav2, true);
386
387   service()->WindowClosing(window_id);
388
389   ScopedVector<SessionWindow> windows;
390   ReadWindows(&(windows.get()), NULL);
391
392   ASSERT_EQ(1U, windows.size());
393   ASSERT_EQ(0, windows[0]->selected_tab_index);
394   ASSERT_EQ(window_id.id(), windows[0]->window_id.id());
395   ASSERT_EQ(2U, windows[0]->tabs.size());
396
397   SessionTab* tab = windows[0]->tabs[0];
398   helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
399   helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
400
401   tab = windows[0]->tabs[1];
402   helper_.AssertTabEquals(window_id, tab2_id, 1, 0, 1, *tab);
403   helper_.AssertNavigationEquals(nav2, tab->navigations[0]);
404 }
405
406 TEST_F(SessionServiceTest, WindowCloseCommittedAfterNavigate) {
407   SessionID window2_id;
408   SessionID tab_id;
409   SessionID tab2_id;
410   ASSERT_NE(window2_id.id(), window_id.id());
411
412   service()->SetWindowType(
413       window2_id, Browser::TYPE_TABBED, SessionService::TYPE_NORMAL);
414   service()->SetWindowBounds(window2_id,
415                              window_bounds,
416                              ui::SHOW_STATE_NORMAL);
417
418   SerializedNavigationEntry nav1 =
419       SerializedNavigationEntryTestHelper::CreateNavigation(
420           "http://google.com", "abc");
421   SerializedNavigationEntry nav2 =
422       SerializedNavigationEntryTestHelper::CreateNavigation(
423           "http://google2.com", "abcd");
424
425   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
426   UpdateNavigation(window_id, tab_id, nav1, true);
427
428   helper_.PrepareTabInWindow(window2_id, tab2_id, 0, false);
429   UpdateNavigation(window2_id, tab2_id, nav2, true);
430
431   service()->WindowClosing(window2_id);
432   service()->TabClosed(window2_id, tab2_id, false);
433   service()->WindowClosed(window2_id);
434
435   ScopedVector<SessionWindow> windows;
436   ReadWindows(&(windows.get()), NULL);
437
438   ASSERT_EQ(1U, windows.size());
439   ASSERT_EQ(0, windows[0]->selected_tab_index);
440   ASSERT_EQ(window_id.id(), windows[0]->window_id.id());
441   ASSERT_EQ(1U, windows[0]->tabs.size());
442
443   SessionTab* tab = windows[0]->tabs[0];
444   helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
445   helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
446 }
447
448 // Makes sure we don't track popups.
449 TEST_F(SessionServiceTest, IgnorePopups) {
450   if (browser_defaults::kRestorePopups)
451     return;  // This test is only applicable if popups aren't restored.
452
453   SessionID window2_id;
454   SessionID tab_id;
455   SessionID tab2_id;
456   ASSERT_NE(window2_id.id(), window_id.id());
457
458   service()->SetWindowType(
459       window2_id, Browser::TYPE_POPUP, SessionService::TYPE_NORMAL);
460   service()->SetWindowBounds(window2_id,
461                              window_bounds,
462                              ui::SHOW_STATE_NORMAL);
463
464   SerializedNavigationEntry nav1 =
465       SerializedNavigationEntryTestHelper::CreateNavigation(
466           "http://google.com", "abc");
467   SerializedNavigationEntry nav2 =
468       SerializedNavigationEntryTestHelper::CreateNavigation(
469           "http://google2.com", "abcd");
470
471   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
472   UpdateNavigation(window_id, tab_id, nav1, true);
473
474   helper_.PrepareTabInWindow(window2_id, tab2_id, 0, false);
475   UpdateNavigation(window2_id, tab2_id, nav2, true);
476
477   ScopedVector<SessionWindow> windows;
478   ReadWindows(&(windows.get()), NULL);
479
480   ASSERT_EQ(1U, windows.size());
481   ASSERT_EQ(0, windows[0]->selected_tab_index);
482   ASSERT_EQ(window_id.id(), windows[0]->window_id.id());
483   ASSERT_EQ(1U, windows[0]->tabs.size());
484
485   SessionTab* tab = windows[0]->tabs[0];
486   helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
487   helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
488 }
489
490 // Makes sure we track popups.
491 TEST_F(SessionServiceTest, RestorePopup) {
492   if (!browser_defaults::kRestorePopups)
493     return;  // This test is only applicable if popups are restored.
494
495   SessionID window2_id;
496   SessionID tab_id;
497   SessionID tab2_id;
498   ASSERT_NE(window2_id.id(), window_id.id());
499
500   service()->SetWindowType(
501       window2_id, Browser::TYPE_POPUP, SessionService::TYPE_NORMAL);
502   service()->SetWindowBounds(window2_id,
503                              window_bounds,
504                              ui::SHOW_STATE_NORMAL);
505
506   SerializedNavigationEntry nav1 =
507       SerializedNavigationEntryTestHelper::CreateNavigation(
508           "http://google.com", "abc");
509   SerializedNavigationEntry nav2 =
510       SerializedNavigationEntryTestHelper::CreateNavigation(
511           "http://google2.com", "abcd");
512
513   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
514   UpdateNavigation(window_id, tab_id, nav1, true);
515
516   helper_.PrepareTabInWindow(window2_id, tab2_id, 0, false);
517   UpdateNavigation(window2_id, tab2_id, nav2, true);
518
519   ScopedVector<SessionWindow> windows;
520   ReadWindows(&(windows.get()), NULL);
521
522   ASSERT_EQ(2U, windows.size());
523   int tabbed_index = windows[0]->type == Browser::TYPE_TABBED ?
524       0 : 1;
525   int popup_index = tabbed_index == 0 ? 1 : 0;
526   ASSERT_EQ(0, windows[tabbed_index]->selected_tab_index);
527   ASSERT_EQ(window_id.id(), windows[tabbed_index]->window_id.id());
528   ASSERT_EQ(1U, windows[tabbed_index]->tabs.size());
529
530   SessionTab* tab = windows[tabbed_index]->tabs[0];
531   helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
532   helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
533
534   ASSERT_EQ(0, windows[popup_index]->selected_tab_index);
535   ASSERT_EQ(window2_id.id(), windows[popup_index]->window_id.id());
536   ASSERT_EQ(1U, windows[popup_index]->tabs.size());
537
538   tab = windows[popup_index]->tabs[0];
539   helper_.AssertTabEquals(window2_id, tab2_id, 0, 0, 1, *tab);
540   helper_.AssertNavigationEquals(nav2, tab->navigations[0]);
541 }
542
543 #if defined (OS_CHROMEOS)
544 // Makes sure we track apps. Only applicable on chromeos.
545 TEST_F(SessionServiceTest, RestoreApp) {
546   SessionID window2_id;
547   SessionID tab_id;
548   SessionID tab2_id;
549   ASSERT_NE(window2_id.id(), window_id.id());
550
551   service()->SetWindowType(
552       window2_id, Browser::TYPE_POPUP, SessionService::TYPE_APP);
553   service()->SetWindowBounds(window2_id,
554                              window_bounds,
555                              ui::SHOW_STATE_NORMAL);
556   service()->SetWindowAppName(window2_id, "TestApp");
557
558   SerializedNavigationEntry nav1 =
559       SerializedNavigationEntryTestHelper::CreateNavigation(
560           "http://google.com", "abc");
561   SerializedNavigationEntry nav2 =
562       SerializedNavigationEntryTestHelper::CreateNavigation(
563           "http://google2.com", "abcd");
564
565   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
566   UpdateNavigation(window_id, tab_id, nav1, true);
567
568   helper_.PrepareTabInWindow(window2_id, tab2_id, 0, false);
569   UpdateNavigation(window2_id, tab2_id, nav2, true);
570
571   ScopedVector<SessionWindow> windows;
572   ReadWindows(&(windows.get()), NULL);
573
574   ASSERT_EQ(2U, windows.size());
575   int tabbed_index = windows[0]->type == Browser::TYPE_TABBED ?
576       0 : 1;
577   int app_index = tabbed_index == 0 ? 1 : 0;
578   ASSERT_EQ(0, windows[tabbed_index]->selected_tab_index);
579   ASSERT_EQ(window_id.id(), windows[tabbed_index]->window_id.id());
580   ASSERT_EQ(1U, windows[tabbed_index]->tabs.size());
581
582   SessionTab* tab = windows[tabbed_index]->tabs[0];
583   helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
584   helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
585
586   ASSERT_EQ(0, windows[app_index]->selected_tab_index);
587   ASSERT_EQ(window2_id.id(), windows[app_index]->window_id.id());
588   ASSERT_EQ(1U, windows[app_index]->tabs.size());
589   ASSERT_TRUE(windows[app_index]->type == Browser::TYPE_POPUP);
590   ASSERT_EQ("TestApp", windows[app_index]->app_name);
591
592   tab = windows[app_index]->tabs[0];
593   helper_.AssertTabEquals(window2_id, tab2_id, 0, 0, 1, *tab);
594   helper_.AssertNavigationEquals(nav2, tab->navigations[0]);
595 }
596 #endif  // defined (OS_CHROMEOS)
597
598 // Tests pruning from the front.
599 TEST_F(SessionServiceTest, PruneFromFront) {
600   const std::string base_url("http://google.com/");
601   SessionID tab_id;
602
603   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
604
605   // Add 5 navigations, with the 4th selected.
606   for (int i = 0; i < 5; ++i) {
607     SerializedNavigationEntry nav =
608         SerializedNavigationEntryTestHelper::CreateNavigation(
609             base_url + base::IntToString(i), "a");
610     nav.set_index(i);
611     UpdateNavigation(window_id, tab_id, nav, (i == 3));
612   }
613
614   // Prune the first two navigations from the front.
615   helper_.service()->TabNavigationPathPrunedFromFront(window_id, tab_id, 2);
616
617   // Read back in.
618   ScopedVector<SessionWindow> windows;
619   ReadWindows(&(windows.get()), NULL);
620
621   ASSERT_EQ(1U, windows.size());
622   ASSERT_EQ(0, windows[0]->selected_tab_index);
623   ASSERT_EQ(window_id.id(), windows[0]->window_id.id());
624   ASSERT_EQ(1U, windows[0]->tabs.size());
625
626   // There shouldn't be an app id.
627   EXPECT_TRUE(windows[0]->tabs[0]->extension_app_id.empty());
628
629   // We should be left with three navigations, the 2nd selected.
630   SessionTab* tab = windows[0]->tabs[0];
631   ASSERT_EQ(1, tab->current_navigation_index);
632   EXPECT_EQ(3U, tab->navigations.size());
633   EXPECT_TRUE(GURL(base_url + base::IntToString(2)) ==
634               tab->navigations[0].virtual_url());
635   EXPECT_TRUE(GURL(base_url + base::IntToString(3)) ==
636               tab->navigations[1].virtual_url());
637   EXPECT_TRUE(GURL(base_url + base::IntToString(4)) ==
638               tab->navigations[2].virtual_url());
639 }
640
641 // Prunes from front so that we have no entries.
642 TEST_F(SessionServiceTest, PruneToEmpty) {
643   const std::string base_url("http://google.com/");
644   SessionID tab_id;
645
646   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
647
648   // Add 5 navigations, with the 4th selected.
649   for (int i = 0; i < 5; ++i) {
650     SerializedNavigationEntry nav =
651         SerializedNavigationEntryTestHelper::CreateNavigation(
652             base_url + base::IntToString(i), "a");
653     nav.set_index(i);
654     UpdateNavigation(window_id, tab_id, nav, (i == 3));
655   }
656
657   // Prune the first two navigations from the front.
658   helper_.service()->TabNavigationPathPrunedFromFront(window_id, tab_id, 5);
659
660   // Read back in.
661   ScopedVector<SessionWindow> windows;
662   ReadWindows(&(windows.get()), NULL);
663
664   ASSERT_EQ(0U, windows.size());
665 }
666
667 // Don't set the pinned state and make sure the pinned value is false.
668 TEST_F(SessionServiceTest, PinnedDefaultsToFalse) {
669   EXPECT_FALSE(CreateAndWriteSessionWithOneTab(false, false));
670 }
671
672 // Explicitly set the pinned state to false and make sure we get back false.
673 TEST_F(SessionServiceTest, PinnedFalseWhenSetToFalse) {
674   EXPECT_FALSE(CreateAndWriteSessionWithOneTab(false, true));
675 }
676
677 // Explicitly set the pinned state to true and make sure we get back true.
678 TEST_F(SessionServiceTest, PinnedTrue) {
679   EXPECT_TRUE(CreateAndWriteSessionWithOneTab(true, true));
680 }
681
682 // Make sure application extension ids are persisted.
683 TEST_F(SessionServiceTest, PersistApplicationExtensionID) {
684   SessionID tab_id;
685   ASSERT_NE(window_id.id(), tab_id.id());
686   std::string app_id("foo");
687
688   SerializedNavigationEntry nav1 =
689       SerializedNavigationEntryTestHelper::CreateNavigation(
690           "http://google.com", "abc");
691
692   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
693   UpdateNavigation(window_id, tab_id, nav1, true);
694   helper_.SetTabExtensionAppID(window_id, tab_id, app_id);
695
696   ScopedVector<SessionWindow> windows;
697   ReadWindows(&(windows.get()), NULL);
698
699   helper_.AssertSingleWindowWithSingleTab(windows.get(), 1);
700   EXPECT_TRUE(app_id == windows[0]->tabs[0]->extension_app_id);
701 }
702
703 // Check that user agent overrides are persisted.
704 TEST_F(SessionServiceTest, PersistUserAgentOverrides) {
705   SessionID tab_id;
706   ASSERT_NE(window_id.id(), tab_id.id());
707   std::string user_agent_override = "Mozilla/5.0 (X11; Linux x86_64) "
708       "AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.45 "
709       "Safari/535.19";
710
711   SerializedNavigationEntry nav1 =
712       SerializedNavigationEntryTestHelper::CreateNavigation(
713           "http://google.com", "abc");
714   SerializedNavigationEntryTestHelper::SetIsOverridingUserAgent(true, &nav1);
715
716   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
717   UpdateNavigation(window_id, tab_id, nav1, true);
718   helper_.SetTabUserAgentOverride(window_id, tab_id, user_agent_override);
719
720   ScopedVector<SessionWindow> windows;
721   ReadWindows(&(windows.get()), NULL);
722   helper_.AssertSingleWindowWithSingleTab(windows.get(), 1);
723
724   SessionTab* tab = windows[0]->tabs[0];
725   helper_.AssertTabEquals(window_id, tab_id, 0, 0, 1, *tab);
726   helper_.AssertNavigationEquals(nav1, tab->navigations[0]);
727   EXPECT_TRUE(user_agent_override == tab->user_agent_override);
728 }
729
730 // Test that the notification for SESSION_SERVICE_SAVED is working properly.
731 TEST_F(SessionServiceTest, SavedSessionNotification) {
732   content::NotificationRegistrar registrar_;
733   registrar_.Add(this, chrome::NOTIFICATION_SESSION_SERVICE_SAVED,
734                  content::NotificationService::AllSources());
735   service()->Save();
736   EXPECT_EQ(sync_save_count_, 1);
737 }
738
739 // Makes sure a tab closed by a user gesture is not restored.
740 TEST_F(SessionServiceTest, CloseTabUserGesture) {
741   SessionID tab_id;
742   ASSERT_NE(window_id.id(), tab_id.id());
743
744   SerializedNavigationEntry nav1 =
745       SerializedNavigationEntryTestHelper::CreateNavigation(
746           "http://google.com", "abc");
747
748   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
749   UpdateNavigation(window_id, tab_id, nav1, true);
750   service()->TabClosed(window_id, tab_id, true);
751
752   ScopedVector<SessionWindow> windows;
753   ReadWindows(&(windows.get()), NULL);
754
755   ASSERT_TRUE(windows.empty());
756 }
757
758 // Verifies SetWindowBounds maps SHOW_STATE_DEFAULT to SHOW_STATE_NORMAL.
759 TEST_F(SessionServiceTest, DontPersistDefault) {
760   SessionID tab_id;
761   ASSERT_NE(window_id.id(), tab_id.id());
762   SerializedNavigationEntry nav1 =
763       SerializedNavigationEntryTestHelper::CreateNavigation(
764           "http://google.com", "abc");
765   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
766   UpdateNavigation(window_id, tab_id, nav1, true);
767   service()->SetWindowBounds(window_id,
768                              window_bounds,
769                              ui::SHOW_STATE_DEFAULT);
770
771   ScopedVector<SessionWindow> windows;
772   ReadWindows(&(windows.get()), NULL);
773   ASSERT_EQ(1U, windows.size());
774   EXPECT_EQ(ui::SHOW_STATE_NORMAL, windows[0]->show_state);
775 }
776
777 TEST_F(SessionServiceTest, KeepPostDataWithoutPasswords) {
778   SessionID tab_id;
779   ASSERT_NE(window_id.id(), tab_id.id());
780
781   // Create a page state representing a HTTP body without posted passwords.
782   content::PageState page_state =
783       content::PageState::CreateForTesting(GURL(), false, "data", NULL);
784
785   // Create a TabNavigation containing page_state and representing a POST
786   // request.
787   SerializedNavigationEntry nav1 =
788       SerializedNavigationEntryTestHelper::CreateNavigation(
789           "http://google.com", "title");
790   SerializedNavigationEntryTestHelper::SetPageState(page_state, &nav1);
791   SerializedNavigationEntryTestHelper::SetHasPostData(true, &nav1);
792
793   // Create a TabNavigation containing page_state and representing a normal
794   // request.
795   SerializedNavigationEntry nav2 =
796       SerializedNavigationEntryTestHelper::CreateNavigation(
797           "http://google.com/nopost", "title");
798   SerializedNavigationEntryTestHelper::SetPageState(page_state, &nav2);
799   nav2.set_index(1);
800
801   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
802   UpdateNavigation(window_id, tab_id, nav1, true);
803   UpdateNavigation(window_id, tab_id, nav2, true);
804
805   ScopedVector<SessionWindow> windows;
806   ReadWindows(&(windows.get()), NULL);
807
808   helper_.AssertSingleWindowWithSingleTab(windows.get(), 2);
809
810   // Expected: the page state of both navigations was saved and restored.
811   ASSERT_EQ(2u, windows[0]->tabs[0]->navigations.size());
812   helper_.AssertNavigationEquals(nav1, windows[0]->tabs[0]->navigations[0]);
813   helper_.AssertNavigationEquals(nav2, windows[0]->tabs[0]->navigations[1]);
814 }
815
816 TEST_F(SessionServiceTest, RemovePostDataWithPasswords) {
817   SessionID tab_id;
818   ASSERT_NE(window_id.id(), tab_id.id());
819
820   // Create a page state representing a HTTP body with posted passwords.
821   content::PageState page_state =
822       content::PageState::CreateForTesting(GURL(), true, "data", NULL);
823
824   // Create a TabNavigation containing page_state and representing a POST
825   // request with passwords.
826   SerializedNavigationEntry nav1 =
827       SerializedNavigationEntryTestHelper::CreateNavigation(
828           "http://google.com", "title");
829   SerializedNavigationEntryTestHelper::SetPageState(page_state, &nav1);
830   SerializedNavigationEntryTestHelper::SetHasPostData(true, &nav1);
831   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
832   UpdateNavigation(window_id, tab_id, nav1, true);
833
834   ScopedVector<SessionWindow> windows;
835   ReadWindows(&(windows.get()), NULL);
836
837   helper_.AssertSingleWindowWithSingleTab(windows.get(), 1);
838
839   // Expected: the HTTP body was removed from the page state of the POST
840   // navigation with passwords.
841   EXPECT_NE(page_state, windows[0]->tabs[0]->navigations[0].page_state());
842 }
843
844 // This test is only applicable to chromeos.
845 #if defined(OS_CHROMEOS)
846 // Verifies migration of tab/window closed works.
847 TEST_F(SessionServiceTest, CanOpenV1TabClosed) {
848   base::FilePath v1_file_path;
849   ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &v1_file_path));
850   // v1_session_file contains a tab closed command with the original id. The
851   // file was generated from ClosingTabStaysClosed. If we successfully processed
852   // the file we'll have one tab.
853   v1_file_path =
854       v1_file_path.AppendASCII("sessions").AppendASCII("v1_session_file");
855   base::FilePath dest_file_path(path_);
856   dest_file_path = dest_file_path.AppendASCII("Current Session");
857
858   // Forces closing the file.
859   helper_.SetService(NULL);
860
861   ASSERT_TRUE(base::CopyFile(v1_file_path, dest_file_path));
862
863   SessionService* session_service = new SessionService(path_);
864   helper_.SetService(session_service);
865   ScopedVector<SessionWindow> windows;
866   SessionID::id_type active_window_id = 0;
867   helper_.ReadWindows(&(windows.get()), &active_window_id);
868   ASSERT_EQ(1u, windows.size());
869   EXPECT_EQ(1u, windows[0]->tabs.size());
870 }
871 #endif  // defined(OS_CHROMEOS)
872
873 TEST_F(SessionServiceTest, ReplacePendingNavigation) {
874   const std::string base_url("http://google.com/");
875   SessionID tab_id;
876
877   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
878
879   // Add 5 navigations, some with the same index
880   for (int i = 0; i < 5; ++i) {
881     SerializedNavigationEntry nav =
882         SerializedNavigationEntryTestHelper::CreateNavigation(
883             base_url + base::IntToString(i), "a");
884     nav.set_index(i / 2);
885     UpdateNavigation(window_id, tab_id, nav, true);
886   }
887
888   // Read back in.
889   ScopedVector<SessionWindow> windows;
890   ReadWindows(&(windows.get()), NULL);
891
892   // The ones with index 0, and 2 should have been replaced by 1 and 3.
893   ASSERT_EQ(1U, windows.size());
894   ASSERT_EQ(1U, windows[0]->tabs.size());
895   EXPECT_EQ(3U, windows[0]->tabs[0]->navigations.size());
896   EXPECT_EQ(GURL(base_url + base::IntToString(1)),
897             windows[0]->tabs[0]->navigations[0].virtual_url());
898   EXPECT_EQ(GURL(base_url + base::IntToString(3)),
899             windows[0]->tabs[0]->navigations[1].virtual_url());
900   EXPECT_EQ(GURL(base_url + base::IntToString(4)),
901             windows[0]->tabs[0]->navigations[2].virtual_url());
902 }
903
904 TEST_F(SessionServiceTest, ReplacePendingNavigationAndPrune) {
905   const std::string base_url("http://google.com/");
906   SessionID tab_id;
907
908   helper_.PrepareTabInWindow(window_id, tab_id, 0, true);
909
910   for (int i = 0; i < 5; ++i) {
911     SerializedNavigationEntry nav =
912         SerializedNavigationEntryTestHelper::CreateNavigation(
913             base_url + base::IntToString(i), "a");
914     nav.set_index(i);
915     UpdateNavigation(window_id, tab_id, nav, true);
916   }
917
918   // Prune all those navigations.
919   helper_.service()->TabNavigationPathPrunedFromFront(window_id, tab_id, 5);
920
921   // Add another navigation to replace the last one.
922   SerializedNavigationEntry nav =
923       SerializedNavigationEntryTestHelper::CreateNavigation(
924         base_url + base::IntToString(5), "a");
925   nav.set_index(4);
926   UpdateNavigation(window_id, tab_id, nav, true);
927
928   // Read back in.
929   ScopedVector<SessionWindow> windows;
930   ReadWindows(&(windows.get()), NULL);
931
932   // We should still have that last navigation at the end,
933   // even though it replaced one that was set before the prune.
934   ASSERT_EQ(1U, windows.size());
935   ASSERT_EQ(1U, windows[0]->tabs.size());
936   ASSERT_EQ(1U, windows[0]->tabs[0]->navigations.size());
937   EXPECT_EQ(GURL(base_url + base::IntToString(5)),
938             windows[0]->tabs[0]->navigations[0].virtual_url());
939 }
940
941 TEST_F(SessionServiceTest, RestoreActivation1) {
942   SessionID window2_id;
943   SessionID tab1_id;
944   SessionID tab2_id;
945   SerializedNavigationEntry nav1;
946   SerializedNavigationEntry nav2;
947
948   CreateAndWriteSessionWithTwoWindows(
949       window2_id, tab1_id, tab2_id, &nav1, &nav2);
950
951   service()->ScheduleCommand(
952       service()->CreateSetActiveWindowCommand(window2_id));
953   service()->ScheduleCommand(
954       service()->CreateSetActiveWindowCommand(window_id));
955
956   ScopedVector<SessionWindow> windows;
957   SessionID::id_type active_window_id = 0;
958   ReadWindows(&(windows.get()), &active_window_id);
959   EXPECT_EQ(window_id.id(), active_window_id);
960 }
961
962 // It's easier to have two separate tests with setup/teardown than to manualy
963 // reset the state for the different flavors of the test.
964 TEST_F(SessionServiceTest, RestoreActivation2) {
965   SessionID window2_id;
966   SessionID tab1_id;
967   SessionID tab2_id;
968   SerializedNavigationEntry nav1;
969   SerializedNavigationEntry nav2;
970
971   CreateAndWriteSessionWithTwoWindows(
972       window2_id, tab1_id, tab2_id, &nav1, &nav2);
973
974   service()->ScheduleCommand(
975       service()->CreateSetActiveWindowCommand(window2_id));
976   service()->ScheduleCommand(
977       service()->CreateSetActiveWindowCommand(window_id));
978   service()->ScheduleCommand(
979       service()->CreateSetActiveWindowCommand(window2_id));
980
981   ScopedVector<SessionWindow> windows;
982   SessionID::id_type active_window_id = 0;
983   ReadWindows(&(windows.get()), &active_window_id);
984   EXPECT_EQ(window2_id.id(), active_window_id);
985 }