Allow overlapping sync and async startup requests
[chromium-blink-merge.git] / chrome / test / automation / browser_proxy.cc
blobbf1ad34fe88de677c9a1cc4da3ac7afc05d8e265
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.
5 #include "chrome/test/automation/browser_proxy.h"
7 #include <algorithm>
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"
20 using base::TimeDelta;
21 using base::TimeTicks;
23 bool BrowserProxy::ActivateTab(int tab_index) {
24 if (!is_valid())
25 return false;
27 int activate_tab_response = -1;
29 if (!sender_->Send(new AutomationMsg_ActivateTab(
30 handle_, tab_index, &activate_tab_response))) {
31 return false;
34 if (activate_tab_response >= 0)
35 return true;
37 return false;
40 bool BrowserProxy::BringToFront() {
41 if (!is_valid())
42 return false;
44 bool succeeded = false;
46 if (!sender_->Send(new AutomationMsg_BringBrowserToFront(
47 handle_, &succeeded))) {
48 return false;
51 return succeeded;
54 bool BrowserProxy::AppendTab(const GURL& tab_url) {
55 if (!is_valid())
56 return false;
58 int append_tab_response = -1;
60 sender_->Send(new AutomationMsg_AppendTab(handle_, tab_url,
61 &append_tab_response));
62 return append_tab_response >= 0;
65 bool BrowserProxy::GetActiveTabIndex(int* active_tab_index) const {
66 if (!is_valid())
67 return false;
69 if (!active_tab_index) {
70 NOTREACHED();
71 return false;
74 int active_tab_index_response = -1;
76 if (!sender_->Send(new AutomationMsg_ActiveTabIndex(
77 handle_, &active_tab_index_response))) {
78 return false;
81 if (active_tab_index_response >= 0) {
82 *active_tab_index = active_tab_index_response;
83 return true;
86 return false;
89 scoped_refptr<TabProxy> BrowserProxy::GetTab(int tab_index) const {
90 if (!is_valid())
91 return NULL;
93 int tab_handle = 0;
95 sender_->Send(new AutomationMsg_Tab(handle_, tab_index, &tab_handle));
96 if (!tab_handle)
97 return NULL;
99 TabProxy* tab = static_cast<TabProxy*>(tracker_->GetResource(tab_handle));
100 if (!tab) {
101 tab = new TabProxy(sender_, tracker_, tab_handle);
102 tab->AddRef();
105 // Since there is no scoped_refptr::attach.
106 scoped_refptr<TabProxy> result;
107 result.swap(&tab);
108 return result;
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);
118 bool BrowserProxy::GetTabCount(int* num_tabs) const {
119 if (!is_valid())
120 return false;
122 if (!num_tabs) {
123 NOTREACHED();
124 return false;
127 int tab_count_response = -1;
129 if (!sender_->Send(new AutomationMsg_TabCount(
130 handle_, &tab_count_response))) {
131 return false;
134 if (tab_count_response >= 0) {
135 *num_tabs = tab_count_response;
136 return true;
139 return false;
142 bool BrowserProxy::GetType(Browser::Type* type) const {
143 if (!is_valid())
144 return false;
146 if (!type) {
147 NOTREACHED();
148 return false;
151 int type_as_int;
152 if (!sender_->Send(new AutomationMsg_Type(handle_, &type_as_int)))
153 return false;
155 *type = static_cast<Browser::Type>(type_as_int);
156 return true;
159 bool BrowserProxy::ApplyAccelerator(int id) {
160 return RunCommandAsync(id);
163 bool BrowserProxy::WaitForTabCountToBecome(int count) {
164 bool success = false;
165 if (!sender_->Send(new AutomationMsg_WaitForTabCountToBecome(
166 handle_, count, &success))) {
167 return false;
170 return success;
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;
183 // If we get here, the active tab hasn't changed.
184 return false;
187 bool BrowserProxy::IsFindWindowFullyVisible(bool* is_visible) {
188 if (!is_valid())
189 return false;
191 if (!is_visible) {
192 NOTREACHED();
193 return false;
196 return sender_->Send(
197 new AutomationMsg_FindWindowVisibility(handle_, is_visible));
200 bool BrowserProxy::RunCommandAsync(int browser_command) const {
201 if (!is_valid())
202 return false;
204 bool result = false;
206 sender_->Send(new AutomationMsg_WindowExecuteCommandAsync(handle_,
207 browser_command,
208 &result));
210 return result;
213 bool BrowserProxy::RunCommand(int browser_command) const {
214 if (!is_valid())
215 return false;
217 bool result = false;
219 sender_->Send(new AutomationMsg_WindowExecuteCommand(handle_,
220 browser_command,
221 &result));
223 return result;
226 bool BrowserProxy::TerminateSession() {
227 if (!is_valid())
228 return false;
230 bool result = false;
232 sender_->Send(new AutomationMsg_TerminateSession(handle_, &result));
234 return result;
237 scoped_refptr<WindowProxy> BrowserProxy::GetWindow() const {
238 if (!is_valid())
239 return NULL;
241 bool handle_ok = false;
242 int window_handle = 0;
244 sender_->Send(new AutomationMsg_WindowForBrowser(handle_, &handle_ok,
245 &window_handle));
246 if (!handle_ok)
247 return NULL;
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();
256 // Since there is no scoped_refptr::attach.
257 scoped_refptr<WindowProxy> result;
258 result.swap(&window);
259 return result;
262 bool BrowserProxy::SendJSONRequest(const std::string& request,
263 int timeout_ms,
264 std::string* response) {
265 if (!is_valid())
266 return false;
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;
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\"}";
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;
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;
300 DictionaryValue* values_dict = static_cast<DictionaryValue*>(values.get());
302 Value* tabs_value;
303 if (!values_dict->Get("tabs", &tabs_value) ||
304 tabs_value->GetType() != Value::TYPE_LIST)
305 return false;
307 ListValue* tabs_list = static_cast<ListValue*>(tabs_value);
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;
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);
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);
329 if (i == 0)
330 *min_start_time = start_ms;
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);
336 std::sort(stop_times->begin(), stop_times->end());
337 return true;