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