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