• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/tab_proxy.h"
6 
7 #include <algorithm>
8 
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"
19 
TabProxy(AutomationMessageSender * sender,AutomationHandleTracker * tracker,int handle)20 TabProxy::TabProxy(AutomationMessageSender* sender,
21                    AutomationHandleTracker* tracker,
22                    int handle)
23     : AutomationResourceProxy(tracker, sender, handle) {
24 }
25 
GetTabTitle(std::wstring * title) const26 bool TabProxy::GetTabTitle(std::wstring* title) const {
27   if (!is_valid())
28     return false;
29 
30   if (!title) {
31     NOTREACHED();
32     return false;
33   }
34 
35   int tab_title_size_response = 0;
36 
37   bool succeeded = sender_->Send(
38       new AutomationMsg_TabTitle(handle_, &tab_title_size_response, title));
39   return succeeded;
40 }
41 
GetTabIndex(int * index) const42 bool TabProxy::GetTabIndex(int* index) const {
43   if (!is_valid())
44     return false;
45 
46   if (!index) {
47     NOTREACHED();
48     return false;
49   }
50 
51   return sender_->Send(new AutomationMsg_TabIndex(handle_, index));
52 }
53 
FindInPage(const std::wstring & search_string,FindInPageDirection forward,FindInPageCase match_case,bool find_next,int * ordinal)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;
61 
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);
67 
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;
79 }
80 
NavigateToURL(const GURL & url)81 AutomationMsg_NavigationResponseValues TabProxy::NavigateToURL(
82     const GURL& url) {
83   return NavigateToURLBlockUntilNavigationsComplete(url, 1);
84 }
85 
86 AutomationMsg_NavigationResponseValues
NavigateToURLBlockUntilNavigationsComplete(const GURL & url,int number_of_navigations)87     TabProxy::NavigateToURLBlockUntilNavigationsComplete(
88         const GURL& url, int number_of_navigations) {
89   if (!is_valid())
90     return AUTOMATION_MSG_NAVIGATION_ERROR;
91 
92   AutomationMsg_NavigationResponseValues navigate_response =
93       AUTOMATION_MSG_NAVIGATION_ERROR;
94 
95  sender_->Send(new AutomationMsg_NavigateToURLBlockUntilNavigationsComplete(
96       handle_, url, number_of_navigations, &navigate_response));
97 
98   return navigate_response;
99 }
100 
GoBack()101 AutomationMsg_NavigationResponseValues TabProxy::GoBack() {
102   return GoBackBlockUntilNavigationsComplete(1);
103 }
104 
105 AutomationMsg_NavigationResponseValues
GoBackBlockUntilNavigationsComplete(int number_of_navigations)106     TabProxy::GoBackBlockUntilNavigationsComplete(int number_of_navigations) {
107   if (!is_valid())
108     return AUTOMATION_MSG_NAVIGATION_ERROR;
109 
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;
115 }
116 
GoForward()117 AutomationMsg_NavigationResponseValues TabProxy::GoForward() {
118   return GoForwardBlockUntilNavigationsComplete(1);
119 }
120 
121 AutomationMsg_NavigationResponseValues
GoForwardBlockUntilNavigationsComplete(int number_of_navigations)122     TabProxy::GoForwardBlockUntilNavigationsComplete(
123         int number_of_navigations) {
124   if (!is_valid())
125     return AUTOMATION_MSG_NAVIGATION_ERROR;
126 
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;
132 }
133 
Reload()134 AutomationMsg_NavigationResponseValues TabProxy::Reload() {
135   if (!is_valid())
136     return AUTOMATION_MSG_NAVIGATION_ERROR;
137 
138   AutomationMsg_NavigationResponseValues navigate_response =
139       AUTOMATION_MSG_NAVIGATION_ERROR;
140   sender_->Send(new AutomationMsg_Reload(handle_, &navigate_response));
141   return navigate_response;
142 }
143 
GetCurrentURL(GURL * url) const144 bool TabProxy::GetCurrentURL(GURL* url) const {
145   if (!is_valid())
146     return false;
147 
148   if (!url) {
149     NOTREACHED();
150     return false;
151   }
152 
153   bool succeeded = false;
154   sender_->Send(new AutomationMsg_TabURL(handle_, &succeeded, url));
155   return succeeded;
156 }
157 
NavigateToURLAsync(const GURL & url)158 bool TabProxy::NavigateToURLAsync(const GURL& url) {
159   if (!is_valid())
160     return false;
161 
162   bool status = false;
163   sender_->Send(new AutomationMsg_NavigationAsync(handle_,
164                                                   url,
165                                                   &status));
166   return status;
167 }
168 
ExecuteAndExtractString(const std::wstring & frame_xpath,const std::wstring & jscript,std::wstring * string_value)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;
175 
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);
185     }
186   }
187   return succeeded;
188 }
189 
ExecuteAndExtractBool(const std::wstring & frame_xpath,const std::wstring & jscript,bool * bool_value)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;
196 
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;
205     }
206   }
207   return succeeded;
208 }
209 
ExecuteAndExtractInt(const std::wstring & frame_xpath,const std::wstring & jscript,int * int_value)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;
216 
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;
225     }
226   }
227   return succeeded;
228 }
229 
ExecuteAndExtractValue(const std::wstring & frame_xpath,const std::wstring & jscript)230 Value* TabProxy::ExecuteAndExtractValue(const std::wstring& frame_xpath,
231                                         const std::wstring& jscript) {
232   if (!is_valid())
233     return NULL;
234 
235   std::string json;
236   if (!sender_->Send(new AutomationMsg_DomOperation(handle_, frame_xpath,
237                                                     jscript, &json))) {
238     return NULL;
239   }
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("]");
244 
245   JSONStringValueSerializer deserializer(json);
246   return deserializer.Deserialize(NULL, NULL);
247 }
248 
GetCookies(const GURL & url,std::string * cookies)249 bool TabProxy::GetCookies(const GURL& url, std::string* cookies) {
250   if (!is_valid())
251     return false;
252 
253   int size = 0;
254   return sender_->Send(new AutomationMsg_GetCookies(url, handle_, &size,
255                                                     cookies));
256 }
257 
GetCookieByName(const GURL & url,const std::string & name,std::string * cookie)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;
264 
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();
272   }
273 
274   return true;
275 }
276 
Close()277 bool TabProxy::Close() {
278   return Close(false);
279 }
280 
Close(bool wait_until_closed)281 bool TabProxy::Close(bool wait_until_closed) {
282   if (!is_valid())
283     return false;
284 
285   bool succeeded = false;
286   sender_->Send(new AutomationMsg_CloseTab(handle_, wait_until_closed,
287                                            &succeeded));
288   return succeeded;
289 }
290 
291 #if defined(OS_WIN)
ProcessUnhandledAccelerator(const MSG & msg)292 bool TabProxy::ProcessUnhandledAccelerator(const MSG& msg) {
293   if (!is_valid())
294     return false;
295 
296   return sender_->Send(
297       new AutomationMsg_ProcessUnhandledAccelerator(handle_, msg));
298   // This message expects no response
299 }
300 
SetInitialFocus(bool reverse,bool restore_focus_to_view)301 bool TabProxy::SetInitialFocus(bool reverse, bool restore_focus_to_view) {
302   if (!is_valid())
303     return false;
304 
305   return sender_->Send(
306       new AutomationMsg_SetInitialFocus(handle_, reverse,
307                                         restore_focus_to_view));
308   // This message expects no response
309 }
310 
NavigateInExternalTab(const GURL & url,const GURL & referrer)311 AutomationMsg_NavigationResponseValues TabProxy::NavigateInExternalTab(
312     const GURL& url, const GURL& referrer) {
313   if (!is_valid())
314     return AUTOMATION_MSG_NAVIGATION_ERROR;
315 
316   AutomationMsg_NavigationResponseValues rv = AUTOMATION_MSG_NAVIGATION_ERROR;
317   sender_->Send(new AutomationMsg_NavigateInExternalTab(handle_, url,
318                                                         referrer, &rv));
319   return rv;
320 }
321 
NavigateExternalTabAtIndex(int index)322 AutomationMsg_NavigationResponseValues TabProxy::NavigateExternalTabAtIndex(
323     int index) {
324   if (!is_valid())
325     return AUTOMATION_MSG_NAVIGATION_ERROR;
326 
327   AutomationMsg_NavigationResponseValues rv = AUTOMATION_MSG_NAVIGATION_ERROR;
328   sender_->Send(new AutomationMsg_NavigateExternalTabAtIndex(handle_, index,
329                                                              &rv));
330   return rv;
331 }
332 
HandleMessageFromExternalHost(const std::string & message,const std::string & origin,const std::string & target)333 void TabProxy::HandleMessageFromExternalHost(const std::string& message,
334                                              const std::string& origin,
335                                              const std::string& target) {
336   if (!is_valid())
337     return;
338 
339   sender_->Send(
340       new AutomationMsg_HandleMessageFromExternalHost(
341           handle_, message, origin, target));
342 }
343 #endif  // defined(OS_WIN)
344 
PrintAsync()345 bool TabProxy::PrintAsync() {
346   if (!is_valid())
347     return false;
348 
349   return sender_->Send(new AutomationMsg_PrintAsync(handle_));
350 }
351 
WaitForInfoBarCount(size_t target_count)352 bool TabProxy::WaitForInfoBarCount(size_t target_count) {
353   if (!is_valid())
354     return false;
355 
356   bool success = false;
357   return sender_->Send(new AutomationMsg_WaitForInfoBarCount(
358       handle_, target_count, &success)) && success;
359 }
360 
OverrideEncoding(const std::string & encoding)361 bool TabProxy::OverrideEncoding(const std::string& encoding) {
362   if (!is_valid())
363     return false;
364 
365   bool succeeded = false;
366   sender_->Send(new AutomationMsg_OverrideEncoding(handle_, encoding,
367                                                    &succeeded));
368   return succeeded;
369 }
370 
371 #if defined(OS_WIN)
Reposition(HWND window,HWND window_insert_after,int left,int top,int width,int height,int flags,HWND parent_window)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));
386 }
387 
SendContextMenuCommand(int selected_command)388 void TabProxy::SendContextMenuCommand(int selected_command) {
389   sender_->Send(new AutomationMsg_ForwardContextMenuCommandToChrome(
390       handle_, selected_command));
391 }
392 
OnHostMoved()393 void TabProxy::OnHostMoved() {
394   sender_->Send(new AutomationMsg_BrowserMove(handle_));
395 }
396 #endif  // defined(OS_WIN)
397 
SelectAll()398 void TabProxy::SelectAll() {
399   sender_->Send(new AutomationMsg_SelectAll(handle_));
400 }
401 
Cut()402 void TabProxy::Cut() {
403   sender_->Send(new AutomationMsg_Cut(handle_));
404 }
405 
Copy()406 void TabProxy::Copy() {
407   sender_->Send(new AutomationMsg_Copy(handle_));
408 }
409 
Paste()410 void TabProxy::Paste() {
411   sender_->Send(new AutomationMsg_Paste(handle_));
412 }
413 
ReloadAsync()414 void TabProxy::ReloadAsync() {
415   sender_->Send(new AutomationMsg_ReloadAsync(handle_));
416 }
417 
StopAsync()418 void TabProxy::StopAsync() {
419   sender_->Send(new AutomationMsg_StopAsync(handle_));
420 }
421 
SaveAsAsync()422 void TabProxy::SaveAsAsync() {
423   sender_->Send(new AutomationMsg_SaveAsAsync(handle_));
424 }
425 
JavaScriptStressTestControl(int cmd,int param)426 void TabProxy::JavaScriptStressTestControl(int cmd, int param) {
427   if (!is_valid())
428     return;
429 
430   sender_->Send(new AutomationMsg_JavaScriptStressTestControl(
431       handle_, cmd, param));
432 }
433 
AddObserver(TabProxyDelegate * observer)434 void TabProxy::AddObserver(TabProxyDelegate* observer) {
435   base::AutoLock lock(list_lock_);
436   observers_list_.AddObserver(observer);
437 }
438 
RemoveObserver(TabProxyDelegate * observer)439 void TabProxy::RemoveObserver(TabProxyDelegate* observer) {
440   base::AutoLock lock(list_lock_);
441   observers_list_.RemoveObserver(observer);
442 }
443 
444 // Called on Channel background thread, if TabMessages filter is installed.
OnMessageReceived(const IPC::Message & message)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;
450 }
451 
OnChannelError()452 void TabProxy::OnChannelError() {
453   base::AutoLock lock(list_lock_);
454   FOR_EACH_OBSERVER(TabProxyDelegate, observers_list_, OnChannelError(this));
455 }
456 
~TabProxy()457 TabProxy::~TabProxy() {}
458 
FirstObjectAdded()459 void TabProxy::FirstObjectAdded() {
460   AddRef();
461 }
462 
LastObjectRemoved()463 void TabProxy::LastObjectRemoved() {
464   Release();
465 }
466