Home | History | Annotate | Download | only in sessions
      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:
     33   SessionServiceTest() : window_bounds(0, 1, 2, 3), sync_save_count_(0){}
     34 
     35  protected:
     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
     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 
     61   virtual void TearDown() {
     62     helper_.set_service(NULL);
     63     path_deleter_.reset();
     64   }
     65 
     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 
     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.
     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 
    126   SessionService* service() { return helper_.service(); }
    127 
    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 
    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.
    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 
    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 
    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 
    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 
    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 
    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 
    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.
    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.
    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.
    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.
    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.
    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.
    579 TEST_F(SessionServiceTest, PinnedFalseWhenSetToFalse) {
    580   EXPECT_FALSE(CreateAndWriteSessionWithOneTab(false, true));
    581 }
    582 
    583 // Make sure application extension ids are persisted.
    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.
    605 TEST_F(SessionServiceTest, PinnedTrue) {
    606   EXPECT_TRUE(CreateAndWriteSessionWithOneTab(true, true));
    607 }
    608 
    609 class GetCurrentSessionCallbackHandler {
    610  public:
    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 
    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.
    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.
    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