Home | History | Annotate | Download | only in integration
      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 "chrome/browser/sync/test/integration/sessions_helper.h"
      6 
      7 #include <algorithm>
      8 
      9 #include "base/stl_util.h"
     10 #include "base/test/test_timeouts.h"
     11 #include "base/time/time.h"
     12 #include "chrome/browser/profiles/profile.h"
     13 #include "chrome/browser/sync/glue/session_model_associator.h"
     14 #include "chrome/browser/sync/profile_sync_service.h"
     15 #include "chrome/browser/sync/profile_sync_service_factory.h"
     16 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
     17 #include "chrome/browser/sync/test/integration/sync_datatype_helper.h"
     18 #include "chrome/browser/sync/test/integration/sync_test.h"
     19 #include "chrome/browser/ui/singleton_tabs.h"
     20 #include "chrome/test/base/ui_test_utils.h"
     21 #include "url/gurl.h"
     22 
     23 using sync_datatype_helper::test;
     24 
     25 namespace sessions_helper {
     26 
     27 ScopedWindowMap::ScopedWindowMap() {
     28 }
     29 
     30 ScopedWindowMap::ScopedWindowMap(SessionWindowMap* windows) {
     31   Reset(windows);
     32 }
     33 
     34 ScopedWindowMap::~ScopedWindowMap() {
     35   STLDeleteContainerPairSecondPointers(windows_.begin(), windows_.end());
     36 }
     37 
     38 SessionWindowMap* ScopedWindowMap::GetMutable() {
     39   return &windows_;
     40 }
     41 
     42 const SessionWindowMap* ScopedWindowMap::Get() const {
     43   return &windows_;
     44 }
     45 
     46 void ScopedWindowMap::Reset(SessionWindowMap* windows) {
     47   STLDeleteContainerPairSecondPointers(windows_.begin(), windows_.end());
     48   windows_.clear();
     49   std::swap(*windows, windows_);
     50 }
     51 
     52 bool GetLocalSession(int index, const browser_sync::SyncedSession** session) {
     53   return ProfileSyncServiceFactory::GetInstance()->GetForProfile(
     54       test()->GetProfile(index))->GetSessionModelAssociatorDeprecated()->
     55           GetLocalSession(session);
     56 }
     57 
     58 bool ModelAssociatorHasTabWithUrl(int index, const GURL& url) {
     59   content::RunAllPendingInMessageLoop();
     60   const browser_sync::SyncedSession* local_session;
     61   if (!GetLocalSession(index, &local_session)) {
     62     return false;
     63   }
     64 
     65   if (local_session->windows.size() == 0) {
     66     DVLOG(1) << "Empty windows vector";
     67     return false;
     68   }
     69 
     70   int nav_index;
     71   sessions::SerializedNavigationEntry nav;
     72   for (SessionWindowMap::const_iterator it =
     73            local_session->windows.begin();
     74        it != local_session->windows.end(); ++it) {
     75     if (it->second->tabs.size() == 0) {
     76       DVLOG(1) << "Empty tabs vector";
     77       continue;
     78     }
     79     for (std::vector<SessionTab*>::const_iterator tab_it =
     80              it->second->tabs.begin();
     81          tab_it != it->second->tabs.end(); ++tab_it) {
     82       if ((*tab_it)->navigations.size() == 0) {
     83         DVLOG(1) << "Empty navigations vector";
     84         continue;
     85       }
     86       nav_index = (*tab_it)->current_navigation_index;
     87       nav = (*tab_it)->navigations[nav_index];
     88       if (nav.virtual_url() == url) {
     89         DVLOG(1) << "Found tab with url " << url.spec();
     90         DVLOG(1) << "Timestamp is " << nav.timestamp().ToInternalValue();
     91         if (nav.title().empty()) {
     92           DVLOG(1) << "Title empty -- tab hasn't finished loading yet";
     93           continue;
     94         }
     95         return true;
     96       }
     97     }
     98   }
     99   DVLOG(1) << "Could not find tab with url " << url.spec();
    100   return false;
    101 }
    102 
    103 bool OpenTab(int index, const GURL& url) {
    104   DVLOG(1) << "Opening tab: " << url.spec() << " using profile "
    105            << index << ".";
    106   chrome::ShowSingletonTab(test()->GetBrowser(index), url);
    107   return WaitForTabsToLoad(index, std::vector<GURL>(1, url));
    108 }
    109 
    110 bool OpenMultipleTabs(int index, const std::vector<GURL>& urls) {
    111   Browser* browser = test()->GetBrowser(index);
    112   for (std::vector<GURL>::const_iterator it = urls.begin();
    113        it != urls.end(); ++it) {
    114     DVLOG(1) << "Opening tab: " << it->spec() << " using profile " << index
    115              << ".";
    116     chrome::ShowSingletonTab(browser, *it);
    117   }
    118   return WaitForTabsToLoad(index, urls);
    119 }
    120 
    121 bool WaitForTabsToLoad(int index, const std::vector<GURL>& urls) {
    122   DVLOG(1) << "Waiting for session to propagate to associator.";
    123   base::TimeTicks start_time = base::TimeTicks::Now();
    124   base::TimeTicks end_time = start_time + TestTimeouts::action_max_timeout();
    125   bool found;
    126   for (std::vector<GURL>::const_iterator it = urls.begin();
    127        it != urls.end(); ++it) {
    128     found = false;
    129     while (!found) {
    130       found = ModelAssociatorHasTabWithUrl(index, *it);
    131       if (base::TimeTicks::Now() >= end_time) {
    132         LOG(ERROR) << "Failed to find all tabs after "
    133                    << TestTimeouts::action_max_timeout().InSecondsF()
    134                    << " seconds.";
    135         return false;
    136       }
    137       if (!found) {
    138         ProfileSyncServiceFactory::GetInstance()->GetForProfile(
    139             test()->GetProfile(index))->GetSessionModelAssociatorDeprecated()->
    140             BlockUntilLocalChangeForTest(TestTimeouts::action_max_timeout());
    141         content::RunMessageLoop();
    142       }
    143     }
    144   }
    145   return true;
    146 }
    147 
    148 bool GetLocalWindows(int index, SessionWindowMap* local_windows) {
    149   // The local session provided by GetLocalSession is owned, and has lifetime
    150   // controlled, by the model associator, so we must make our own copy.
    151   const browser_sync::SyncedSession* local_session;
    152   if (!GetLocalSession(index, &local_session)) {
    153     return false;
    154   }
    155   for (SessionWindowMap::const_iterator w = local_session->windows.begin();
    156        w != local_session->windows.end(); ++w) {
    157     const SessionWindow& window = *(w->second);
    158     SessionWindow* new_window = new SessionWindow();
    159     new_window->window_id.set_id(window.window_id.id());
    160     for (size_t t = 0; t < window.tabs.size(); ++t) {
    161       const SessionTab& tab = *window.tabs.at(t);
    162       SessionTab* new_tab = new SessionTab();
    163       new_tab->navigations.resize(tab.navigations.size());
    164       std::copy(tab.navigations.begin(), tab.navigations.end(),
    165                 new_tab->navigations.begin());
    166       new_window->tabs.push_back(new_tab);
    167     }
    168     (*local_windows)[new_window->window_id.id()] = new_window;
    169   }
    170 
    171   return true;
    172 }
    173 
    174 bool OpenTabAndGetLocalWindows(int index,
    175                                const GURL& url,
    176                                SessionWindowMap* local_windows) {
    177   if (!OpenTab(index, url)) {
    178     return false;
    179   }
    180   return GetLocalWindows(index, local_windows);
    181 }
    182 
    183 bool CheckInitialState(int index) {
    184   if (0 != GetNumWindows(index))
    185     return false;
    186   if (0 != GetNumForeignSessions(index))
    187     return false;
    188   return true;
    189 }
    190 
    191 int GetNumWindows(int index) {
    192   const browser_sync::SyncedSession* local_session;
    193   if (!GetLocalSession(index, &local_session)) {
    194     return 0;
    195   }
    196   return local_session->windows.size();
    197 }
    198 
    199 int GetNumForeignSessions(int index) {
    200   SyncedSessionVector sessions;
    201   if (!ProfileSyncServiceFactory::GetInstance()->GetForProfile(
    202           test()->GetProfile(index))->
    203           GetSessionModelAssociatorDeprecated()->GetAllForeignSessions(
    204               &sessions)) {
    205     return 0;
    206   }
    207   return sessions.size();
    208 }
    209 
    210 bool GetSessionData(int index, SyncedSessionVector* sessions) {
    211   if (!ProfileSyncServiceFactory::GetInstance()->GetForProfile(
    212           test()->GetProfile(index))->
    213           GetSessionModelAssociatorDeprecated()->GetAllForeignSessions(
    214               sessions)) {
    215     return false;
    216   }
    217   SortSyncedSessions(sessions);
    218   return true;
    219 }
    220 
    221 bool CompareSyncedSessions(const browser_sync::SyncedSession* lhs,
    222                            const browser_sync::SyncedSession* rhs) {
    223   if (!lhs ||
    224       !rhs ||
    225       lhs->windows.size() < 1 ||
    226       rhs->windows.size() < 1) {
    227     // Catchall for uncomparable data.
    228     return false;
    229   }
    230 
    231   return lhs->windows < rhs->windows;
    232 }
    233 
    234 void SortSyncedSessions(SyncedSessionVector* sessions) {
    235   std::sort(sessions->begin(), sessions->end(),
    236             CompareSyncedSessions);
    237 }
    238 
    239 bool NavigationEquals(const sessions::SerializedNavigationEntry& expected,
    240                       const sessions::SerializedNavigationEntry& actual) {
    241   if (expected.virtual_url() != actual.virtual_url()) {
    242     LOG(ERROR) << "Expected url " << expected.virtual_url()
    243                << ", actual " << actual.virtual_url();
    244     return false;
    245   }
    246   if (expected.referrer().url != actual.referrer().url) {
    247     LOG(ERROR) << "Expected referrer "
    248                << expected.referrer().url
    249                << ", actual "
    250                << actual.referrer().url;
    251     return false;
    252   }
    253   if (expected.title() != actual.title()) {
    254     LOG(ERROR) << "Expected title " << expected.title()
    255                << ", actual " << actual.title();
    256     return false;
    257   }
    258   if (expected.transition_type() != actual.transition_type()) {
    259     LOG(ERROR) << "Expected transition "
    260                << expected.transition_type()
    261                << ", actual "
    262                << actual.transition_type();
    263     return false;
    264   }
    265   return true;
    266 }
    267 
    268 bool WindowsMatch(const SessionWindowMap& win1,
    269                   const SessionWindowMap& win2) {
    270   SessionTab* client0_tab;
    271   SessionTab* client1_tab;
    272   if (win1.size() != win2.size())
    273     return false;
    274   for (SessionWindowMap::const_iterator i = win1.begin();
    275        i != win1.end(); ++i) {
    276     SessionWindowMap::const_iterator j = win2.find(i->first);
    277     if (j == win2.end())
    278       return false;
    279     if (i->second->tabs.size() != j->second->tabs.size())
    280       return false;
    281     for (size_t t = 0; t < i->second->tabs.size(); ++t) {
    282       client0_tab = i->second->tabs[t];
    283       client1_tab = j->second->tabs[t];
    284       for (size_t n = 0; n < client0_tab->navigations.size(); ++n) {
    285         if (!NavigationEquals(client0_tab->navigations[n],
    286                               client1_tab->navigations[n])) {
    287           return false;
    288         }
    289       }
    290     }
    291   }
    292 
    293   return true;
    294 }
    295 
    296 bool CheckForeignSessionsAgainst(
    297     int index,
    298     const std::vector<ScopedWindowMap>& windows) {
    299   SyncedSessionVector sessions;
    300   if (!GetSessionData(index, &sessions))
    301     return false;
    302   if ((size_t)(test()->num_clients()-1) != sessions.size())
    303     return false;
    304 
    305   int window_index = 0;
    306   for (size_t j = 0; j < sessions.size(); ++j, ++window_index) {
    307     if (window_index == index)
    308       window_index++;  // Skip self.
    309     if (!WindowsMatch(sessions[j]->windows,
    310                       *(windows[window_index].Get())))
    311       return false;
    312   }
    313 
    314   return true;
    315 }
    316 
    317 void DeleteForeignSession(int index, std::string session_tag) {
    318   ProfileSyncServiceFactory::GetInstance()->GetForProfile(
    319       test()->GetProfile(index))->
    320       GetSessionModelAssociatorDeprecated()->DeleteForeignSession(session_tag);
    321 }
    322 
    323 }  // namespace sessions_helper
    324