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/test/automation/browser_proxy.h" 6 7 #include <algorithm> 8 9 #include "base/json/json_reader.h" 10 #include "base/logging.h" 11 #include "base/threading/platform_thread.h" 12 #include "base/time/time.h" 13 #include "chrome/common/automation_constants.h" 14 #include "chrome/common/automation_messages.h" 15 #include "chrome/test/automation/automation_proxy.h" 16 #include "chrome/test/automation/tab_proxy.h" 17 #include "chrome/test/automation/window_proxy.h" 18 #include "ui/gfx/point.h" 19 20 using base::TimeDelta; 21 using base::TimeTicks; 22 23 bool BrowserProxy::ActivateTab(int tab_index) { 24 if (!is_valid()) 25 return false; 26 27 int activate_tab_response = -1; 28 29 if (!sender_->Send(new AutomationMsg_ActivateTab( 30 handle_, tab_index, &activate_tab_response))) { 31 return false; 32 } 33 34 if (activate_tab_response >= 0) 35 return true; 36 37 return false; 38 } 39 40 bool BrowserProxy::BringToFront() { 41 if (!is_valid()) 42 return false; 43 44 bool succeeded = false; 45 46 if (!sender_->Send(new AutomationMsg_BringBrowserToFront( 47 handle_, &succeeded))) { 48 return false; 49 } 50 51 return succeeded; 52 } 53 54 bool BrowserProxy::AppendTab(const GURL& tab_url) { 55 if (!is_valid()) 56 return false; 57 58 int append_tab_response = -1; 59 60 sender_->Send(new AutomationMsg_AppendTab(handle_, tab_url, 61 &append_tab_response)); 62 return append_tab_response >= 0; 63 } 64 65 bool BrowserProxy::GetActiveTabIndex(int* active_tab_index) const { 66 if (!is_valid()) 67 return false; 68 69 if (!active_tab_index) { 70 NOTREACHED(); 71 return false; 72 } 73 74 int active_tab_index_response = -1; 75 76 if (!sender_->Send(new AutomationMsg_ActiveTabIndex( 77 handle_, &active_tab_index_response))) { 78 return false; 79 } 80 81 if (active_tab_index_response >= 0) { 82 *active_tab_index = active_tab_index_response; 83 return true; 84 } 85 86 return false; 87 } 88 89 scoped_refptr<TabProxy> BrowserProxy::GetTab(int tab_index) const { 90 if (!is_valid()) 91 return NULL; 92 93 int tab_handle = 0; 94 95 sender_->Send(new AutomationMsg_Tab(handle_, tab_index, &tab_handle)); 96 if (!tab_handle) 97 return NULL; 98 99 TabProxy* tab = static_cast<TabProxy*>(tracker_->GetResource(tab_handle)); 100 if (!tab) { 101 tab = new TabProxy(sender_, tracker_, tab_handle); 102 tab->AddRef(); 103 } 104 105 // Since there is no scoped_refptr::attach. 106 scoped_refptr<TabProxy> result; 107 result.swap(&tab); 108 return result; 109 } 110 111 scoped_refptr<TabProxy> BrowserProxy::GetActiveTab() const { 112 int active_tab_index; 113 if (!GetActiveTabIndex(&active_tab_index)) 114 return NULL; 115 return GetTab(active_tab_index); 116 } 117 118 bool BrowserProxy::GetTabCount(int* num_tabs) const { 119 if (!is_valid()) 120 return false; 121 122 if (!num_tabs) { 123 NOTREACHED(); 124 return false; 125 } 126 127 int tab_count_response = -1; 128 129 if (!sender_->Send(new AutomationMsg_TabCount( 130 handle_, &tab_count_response))) { 131 return false; 132 } 133 134 if (tab_count_response >= 0) { 135 *num_tabs = tab_count_response; 136 return true; 137 } 138 139 return false; 140 } 141 142 bool BrowserProxy::GetType(Browser::Type* type) const { 143 if (!is_valid()) 144 return false; 145 146 if (!type) { 147 NOTREACHED(); 148 return false; 149 } 150 151 int type_as_int; 152 if (!sender_->Send(new AutomationMsg_Type(handle_, &type_as_int))) 153 return false; 154 155 *type = static_cast<Browser::Type>(type_as_int); 156 return true; 157 } 158 159 bool BrowserProxy::ApplyAccelerator(int id) { 160 return RunCommandAsync(id); 161 } 162 163 bool BrowserProxy::WaitForTabCountToBecome(int count) { 164 bool success = false; 165 if (!sender_->Send(new AutomationMsg_WaitForTabCountToBecome( 166 handle_, count, &success))) { 167 return false; 168 } 169 170 return success; 171 } 172 173 bool BrowserProxy::WaitForTabToBecomeActive(int tab, 174 base::TimeDelta wait_timeout) { 175 const TimeTicks start = TimeTicks::Now(); 176 while (TimeTicks::Now() - start < wait_timeout) { 177 base::PlatformThread::Sleep( 178 base::TimeDelta::FromMilliseconds(automation::kSleepTime)); 179 int active_tab; 180 if (GetActiveTabIndex(&active_tab) && active_tab == tab) 181 return true; 182 } 183 // If we get here, the active tab hasn't changed. 184 return false; 185 } 186 187 bool BrowserProxy::IsFindWindowFullyVisible(bool* is_visible) { 188 if (!is_valid()) 189 return false; 190 191 if (!is_visible) { 192 NOTREACHED(); 193 return false; 194 } 195 196 return sender_->Send( 197 new AutomationMsg_FindWindowVisibility(handle_, is_visible)); 198 } 199 200 bool BrowserProxy::RunCommandAsync(int browser_command) const { 201 if (!is_valid()) 202 return false; 203 204 bool result = false; 205 206 sender_->Send(new AutomationMsg_WindowExecuteCommandAsync(handle_, 207 browser_command, 208 &result)); 209 210 return result; 211 } 212 213 bool BrowserProxy::RunCommand(int browser_command) const { 214 if (!is_valid()) 215 return false; 216 217 bool result = false; 218 219 sender_->Send(new AutomationMsg_WindowExecuteCommand(handle_, 220 browser_command, 221 &result)); 222 223 return result; 224 } 225 226 bool BrowserProxy::TerminateSession() { 227 if (!is_valid()) 228 return false; 229 230 bool result = false; 231 232 sender_->Send(new AutomationMsg_TerminateSession(handle_, &result)); 233 234 return result; 235 } 236 237 scoped_refptr<WindowProxy> BrowserProxy::GetWindow() const { 238 if (!is_valid()) 239 return NULL; 240 241 bool handle_ok = false; 242 int window_handle = 0; 243 244 sender_->Send(new AutomationMsg_WindowForBrowser(handle_, &handle_ok, 245 &window_handle)); 246 if (!handle_ok) 247 return NULL; 248 249 WindowProxy* window = 250 static_cast<WindowProxy*>(tracker_->GetResource(window_handle)); 251 if (!window) { 252 window = new WindowProxy(sender_, tracker_, window_handle); 253 window->AddRef(); 254 } 255 256 // Since there is no scoped_refptr::attach. 257 scoped_refptr<WindowProxy> result; 258 result.swap(&window); 259 return result; 260 } 261 262 bool BrowserProxy::SendJSONRequest(const std::string& request, 263 int timeout_ms, 264 std::string* response) { 265 if (!is_valid()) 266 return false; 267 268 bool result = false; 269 if (!sender_->Send( 270 new AutomationMsg_SendJSONRequestWithBrowserHandle(handle_, 271 request, 272 response, 273 &result), 274 timeout_ms)) 275 return false; 276 return result; 277 } 278 279 bool BrowserProxy::GetInitialLoadTimes(base::TimeDelta timeout, 280 float* min_start_time, 281 float* max_stop_time, 282 std::vector<float>* stop_times) { 283 std::string json_response; 284 const char* kJSONCommand = "{\"command\": \"GetInitialLoadTimes\"}"; 285 286 *max_stop_time = 0; 287 *min_start_time = -1; 288 if (!SendJSONRequest( 289 kJSONCommand, timeout.InMilliseconds(), &json_response)) { 290 // Older browser versions do not support GetInitialLoadTimes. 291 // Fail gracefully and do not record them in this case. 292 return false; 293 } 294 std::string error; 295 scoped_ptr<Value> values(base::JSONReader::ReadAndReturnError( 296 json_response, base::JSON_ALLOW_TRAILING_COMMAS, NULL, &error)); 297 if (!error.empty() || values->GetType() != Value::TYPE_DICTIONARY) 298 return false; 299 300 DictionaryValue* values_dict = static_cast<DictionaryValue*>(values.get()); 301 302 Value* tabs_value; 303 if (!values_dict->Get("tabs", &tabs_value) || 304 tabs_value->GetType() != Value::TYPE_LIST) 305 return false; 306 307 ListValue* tabs_list = static_cast<ListValue*>(tabs_value); 308 309 for (size_t i = 0; i < tabs_list->GetSize(); i++) { 310 float stop_ms = 0; 311 float start_ms = 0; 312 Value* tab_value; 313 DictionaryValue* tab_dict; 314 315 if (!tabs_list->Get(i, &tab_value) || 316 tab_value->GetType() != Value::TYPE_DICTIONARY) 317 return false; 318 tab_dict = static_cast<DictionaryValue*>(tab_value); 319 320 double temp; 321 if (!tab_dict->GetDouble("load_start_ms", &temp)) 322 return false; 323 start_ms = static_cast<float>(temp); 324 // load_stop_ms can only be null if WaitForInitialLoads did not run. 325 if (!tab_dict->GetDouble("load_stop_ms", &temp)) 326 return false; 327 stop_ms = static_cast<float>(temp); 328 329 if (i == 0) 330 *min_start_time = start_ms; 331 332 *min_start_time = std::min(start_ms, *min_start_time); 333 *max_stop_time = std::max(stop_ms, *max_stop_time); 334 stop_times->push_back(stop_ms); 335 } 336 std::sort(stop_times->begin(), stop_times->end()); 337 return true; 338 } 339