Allow overlapping sync and async startup requests
[chromium-blink-merge.git] / chrome / test / automation / tab_proxy.cc
blobfa1fb6ef5dc246d66d0e7465149c1a92ed43abbb
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/tab_proxy.h"
7 #include <algorithm>
9 #include "base/json/json_string_value_serializer.h"
10 #include "base/logging.h"
11 #include "base/strings/string16.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/threading/platform_thread.h"
14 #include "chrome/common/automation_constants.h"
15 #include "chrome/common/automation_messages.h"
16 #include "chrome/test/automation/automation_proxy.h"
17 #include "chrome/test/automation/browser_proxy.h"
18 #include "url/gurl.h"
20 TabProxy::TabProxy(AutomationMessageSender* sender,
21 AutomationHandleTracker* tracker,
22 int handle)
23 : AutomationResourceProxy(tracker, sender, handle) {
26 bool TabProxy::GetTabTitle(std::wstring* title) const {
27 if (!is_valid())
28 return false;
30 if (!title) {
31 NOTREACHED();
32 return false;
35 int tab_title_size_response = 0;
37 bool succeeded = sender_->Send(
38 new AutomationMsg_TabTitle(handle_, &tab_title_size_response, title));
39 return succeeded;
42 bool TabProxy::GetTabIndex(int* index) const {
43 if (!is_valid())
44 return false;
46 if (!index) {
47 NOTREACHED();
48 return false;
51 return sender_->Send(new AutomationMsg_TabIndex(handle_, index));
54 int TabProxy::FindInPage(const std::wstring& search_string,
55 FindInPageDirection forward,
56 FindInPageCase match_case,
57 bool find_next,
58 int* ordinal) {
59 if (!is_valid())
60 return -1;
62 AutomationMsg_Find_Params params;
63 params.search_string = WideToUTF16Hack(search_string);
64 params.find_next = find_next;
65 params.match_case = (match_case == CASE_SENSITIVE);
66 params.forward = (forward == FWD);
68 int matches = 0;
69 int ordinal2 = 0;
70 bool succeeded = sender_->Send(new AutomationMsg_Find(handle_,
71 params,
72 &ordinal2,
73 &matches));
74 if (!succeeded)
75 return -1;
76 if (ordinal)
77 *ordinal = ordinal2;
78 return matches;
81 AutomationMsg_NavigationResponseValues TabProxy::NavigateToURL(
82 const GURL& url) {
83 return NavigateToURLBlockUntilNavigationsComplete(url, 1);
86 AutomationMsg_NavigationResponseValues
87 TabProxy::NavigateToURLBlockUntilNavigationsComplete(
88 const GURL& url, int number_of_navigations) {
89 if (!is_valid())
90 return AUTOMATION_MSG_NAVIGATION_ERROR;
92 AutomationMsg_NavigationResponseValues navigate_response =
93 AUTOMATION_MSG_NAVIGATION_ERROR;
95 sender_->Send(new AutomationMsg_NavigateToURLBlockUntilNavigationsComplete(
96 handle_, url, number_of_navigations, &navigate_response));
98 return navigate_response;
101 AutomationMsg_NavigationResponseValues TabProxy::GoBack() {
102 return GoBackBlockUntilNavigationsComplete(1);
105 AutomationMsg_NavigationResponseValues
106 TabProxy::GoBackBlockUntilNavigationsComplete(int number_of_navigations) {
107 if (!is_valid())
108 return AUTOMATION_MSG_NAVIGATION_ERROR;
110 AutomationMsg_NavigationResponseValues navigate_response =
111 AUTOMATION_MSG_NAVIGATION_ERROR;
112 sender_->Send(new AutomationMsg_GoBackBlockUntilNavigationsComplete(
113 handle_, number_of_navigations, &navigate_response));
114 return navigate_response;
117 AutomationMsg_NavigationResponseValues TabProxy::GoForward() {
118 return GoForwardBlockUntilNavigationsComplete(1);
121 AutomationMsg_NavigationResponseValues
122 TabProxy::GoForwardBlockUntilNavigationsComplete(
123 int number_of_navigations) {
124 if (!is_valid())
125 return AUTOMATION_MSG_NAVIGATION_ERROR;
127 AutomationMsg_NavigationResponseValues navigate_response =
128 AUTOMATION_MSG_NAVIGATION_ERROR;
129 sender_->Send(new AutomationMsg_GoForwardBlockUntilNavigationsComplete(
130 handle_, number_of_navigations, &navigate_response));
131 return navigate_response;
134 AutomationMsg_NavigationResponseValues TabProxy::Reload() {
135 if (!is_valid())
136 return AUTOMATION_MSG_NAVIGATION_ERROR;
138 AutomationMsg_NavigationResponseValues navigate_response =
139 AUTOMATION_MSG_NAVIGATION_ERROR;
140 sender_->Send(new AutomationMsg_Reload(handle_, &navigate_response));
141 return navigate_response;
144 bool TabProxy::GetCurrentURL(GURL* url) const {
145 if (!is_valid())
146 return false;
148 if (!url) {
149 NOTREACHED();
150 return false;
153 bool succeeded = false;
154 sender_->Send(new AutomationMsg_TabURL(handle_, &succeeded, url));
155 return succeeded;
158 bool TabProxy::NavigateToURLAsync(const GURL& url) {
159 if (!is_valid())
160 return false;
162 bool status = false;
163 sender_->Send(new AutomationMsg_NavigationAsync(handle_,
164 url,
165 &status));
166 return status;
169 bool TabProxy::ExecuteAndExtractString(const std::wstring& frame_xpath,
170 const std::wstring& jscript,
171 std::wstring* string_value) {
172 scoped_ptr<Value> root(ExecuteAndExtractValue(frame_xpath, jscript));
173 if (root == NULL)
174 return false;
176 DCHECK(root->IsType(Value::TYPE_LIST));
177 Value* value = NULL;
178 bool succeeded = static_cast<ListValue*>(root.get())->Get(0, &value);
179 if (succeeded) {
180 string16 read_value;
181 succeeded = value->GetAsString(&read_value);
182 if (succeeded) {
183 // TODO(viettrungluu): remove conversion. (But should |jscript| be UTF-8?)
184 *string_value = UTF16ToWideHack(read_value);
187 return succeeded;
190 bool TabProxy::ExecuteAndExtractBool(const std::wstring& frame_xpath,
191 const std::wstring& jscript,
192 bool* bool_value) {
193 scoped_ptr<Value> root(ExecuteAndExtractValue(frame_xpath, jscript));
194 if (root == NULL)
195 return false;
197 bool read_value = false;
198 DCHECK(root->IsType(Value::TYPE_LIST));
199 Value* value = NULL;
200 bool succeeded = static_cast<ListValue*>(root.get())->Get(0, &value);
201 if (succeeded) {
202 succeeded = value->GetAsBoolean(&read_value);
203 if (succeeded) {
204 *bool_value = read_value;
207 return succeeded;
210 bool TabProxy::ExecuteAndExtractInt(const std::wstring& frame_xpath,
211 const std::wstring& jscript,
212 int* int_value) {
213 scoped_ptr<Value> root(ExecuteAndExtractValue(frame_xpath, jscript));
214 if (root == NULL)
215 return false;
217 int read_value = 0;
218 DCHECK(root->IsType(Value::TYPE_LIST));
219 Value* value = NULL;
220 bool succeeded = static_cast<ListValue*>(root.get())->Get(0, &value);
221 if (succeeded) {
222 succeeded = value->GetAsInteger(&read_value);
223 if (succeeded) {
224 *int_value = read_value;
227 return succeeded;
230 Value* TabProxy::ExecuteAndExtractValue(const std::wstring& frame_xpath,
231 const std::wstring& jscript) {
232 if (!is_valid())
233 return NULL;
235 std::string json;
236 if (!sender_->Send(new AutomationMsg_DomOperation(handle_, frame_xpath,
237 jscript, &json))) {
238 return NULL;
240 // Wrap |json| in an array before deserializing because valid JSON has an
241 // array or an object as the root.
242 json.insert(0, "[");
243 json.append("]");
245 JSONStringValueSerializer deserializer(json);
246 return deserializer.Deserialize(NULL, NULL);
249 bool TabProxy::GetCookies(const GURL& url, std::string* cookies) {
250 if (!is_valid())
251 return false;
253 int size = 0;
254 return sender_->Send(new AutomationMsg_GetCookies(url, handle_, &size,
255 cookies));
258 bool TabProxy::GetCookieByName(const GURL& url,
259 const std::string& name,
260 std::string* cookie) {
261 std::string cookies;
262 if (!GetCookies(url, &cookies))
263 return false;
265 std::string namestr = name + "=";
266 std::string::size_type idx = cookies.find(namestr);
267 if (idx != std::string::npos) {
268 cookies.erase(0, idx + namestr.length());
269 *cookie = cookies.substr(0, cookies.find(";"));
270 } else {
271 cookie->clear();
274 return true;
277 bool TabProxy::Close() {
278 return Close(false);
281 bool TabProxy::Close(bool wait_until_closed) {
282 if (!is_valid())
283 return false;
285 bool succeeded = false;
286 sender_->Send(new AutomationMsg_CloseTab(handle_, wait_until_closed,
287 &succeeded));
288 return succeeded;
291 #if defined(OS_WIN)
292 bool TabProxy::ProcessUnhandledAccelerator(const MSG& msg) {
293 if (!is_valid())
294 return false;
296 return sender_->Send(
297 new AutomationMsg_ProcessUnhandledAccelerator(handle_, msg));
298 // This message expects no response
301 bool TabProxy::SetInitialFocus(bool reverse, bool restore_focus_to_view) {
302 if (!is_valid())
303 return false;
305 return sender_->Send(
306 new AutomationMsg_SetInitialFocus(handle_, reverse,
307 restore_focus_to_view));
308 // This message expects no response
311 AutomationMsg_NavigationResponseValues TabProxy::NavigateInExternalTab(
312 const GURL& url, const GURL& referrer) {
313 if (!is_valid())
314 return AUTOMATION_MSG_NAVIGATION_ERROR;
316 AutomationMsg_NavigationResponseValues rv = AUTOMATION_MSG_NAVIGATION_ERROR;
317 sender_->Send(new AutomationMsg_NavigateInExternalTab(handle_, url,
318 referrer, &rv));
319 return rv;
322 AutomationMsg_NavigationResponseValues TabProxy::NavigateExternalTabAtIndex(
323 int index) {
324 if (!is_valid())
325 return AUTOMATION_MSG_NAVIGATION_ERROR;
327 AutomationMsg_NavigationResponseValues rv = AUTOMATION_MSG_NAVIGATION_ERROR;
328 sender_->Send(new AutomationMsg_NavigateExternalTabAtIndex(handle_, index,
329 &rv));
330 return rv;
333 void TabProxy::HandleMessageFromExternalHost(const std::string& message,
334 const std::string& origin,
335 const std::string& target) {
336 if (!is_valid())
337 return;
339 sender_->Send(
340 new AutomationMsg_HandleMessageFromExternalHost(
341 handle_, message, origin, target));
343 #endif // defined(OS_WIN)
345 bool TabProxy::PrintAsync() {
346 if (!is_valid())
347 return false;
349 return sender_->Send(new AutomationMsg_PrintAsync(handle_));
352 bool TabProxy::WaitForInfoBarCount(size_t target_count) {
353 if (!is_valid())
354 return false;
356 bool success = false;
357 return sender_->Send(new AutomationMsg_WaitForInfoBarCount(
358 handle_, target_count, &success)) && success;
361 bool TabProxy::OverrideEncoding(const std::string& encoding) {
362 if (!is_valid())
363 return false;
365 bool succeeded = false;
366 sender_->Send(new AutomationMsg_OverrideEncoding(handle_, encoding,
367 &succeeded));
368 return succeeded;
371 #if defined(OS_WIN)
372 void TabProxy::Reposition(HWND window, HWND window_insert_after, int left,
373 int top, int width, int height, int flags,
374 HWND parent_window) {
375 Reposition_Params params;
376 params.window = window;
377 params.window_insert_after = window_insert_after;
378 params.left = left;
379 params.top = top;
380 params.width = width;
381 params.height = height;
382 params.flags = flags;
383 params.set_parent = (::IsWindow(parent_window) ? true : false);
384 params.parent_window = parent_window;
385 sender_->Send(new AutomationMsg_TabReposition(handle_, params));
388 void TabProxy::SendContextMenuCommand(int selected_command) {
389 sender_->Send(new AutomationMsg_ForwardContextMenuCommandToChrome(
390 handle_, selected_command));
393 void TabProxy::OnHostMoved() {
394 sender_->Send(new AutomationMsg_BrowserMove(handle_));
396 #endif // defined(OS_WIN)
398 void TabProxy::SelectAll() {
399 sender_->Send(new AutomationMsg_SelectAll(handle_));
402 void TabProxy::Cut() {
403 sender_->Send(new AutomationMsg_Cut(handle_));
406 void TabProxy::Copy() {
407 sender_->Send(new AutomationMsg_Copy(handle_));
410 void TabProxy::Paste() {
411 sender_->Send(new AutomationMsg_Paste(handle_));
414 void TabProxy::ReloadAsync() {
415 sender_->Send(new AutomationMsg_ReloadAsync(handle_));
418 void TabProxy::StopAsync() {
419 sender_->Send(new AutomationMsg_StopAsync(handle_));
422 void TabProxy::SaveAsAsync() {
423 sender_->Send(new AutomationMsg_SaveAsAsync(handle_));
426 void TabProxy::JavaScriptStressTestControl(int cmd, int param) {
427 if (!is_valid())
428 return;
430 sender_->Send(new AutomationMsg_JavaScriptStressTestControl(
431 handle_, cmd, param));
434 void TabProxy::AddObserver(TabProxyDelegate* observer) {
435 base::AutoLock lock(list_lock_);
436 observers_list_.AddObserver(observer);
439 void TabProxy::RemoveObserver(TabProxyDelegate* observer) {
440 base::AutoLock lock(list_lock_);
441 observers_list_.RemoveObserver(observer);
444 // Called on Channel background thread, if TabMessages filter is installed.
445 bool TabProxy::OnMessageReceived(const IPC::Message& message) {
446 base::AutoLock lock(list_lock_);
447 FOR_EACH_OBSERVER(TabProxyDelegate, observers_list_,
448 OnMessageReceived(this, message));
449 return true;
452 void TabProxy::OnChannelError() {
453 base::AutoLock lock(list_lock_);
454 FOR_EACH_OBSERVER(TabProxyDelegate, observers_list_, OnChannelError(this));
457 TabProxy::~TabProxy() {}
459 void TabProxy::FirstObjectAdded() {
460 AddRef();
463 void TabProxy::LastObjectRemoved() {
464 Release();