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/automation_json_requests.h"
6
7#include "base/basictypes.h"
8#include "base/files/file_path.h"
9#include "base/format_macros.h"
10#include "base/json/json_reader.h"
11#include "base/json/json_string_value_serializer.h"
12#include "base/json/json_writer.h"
13#include "base/memory/scoped_ptr.h"
14#include "base/strings/stringprintf.h"
15#include "base/test/test_timeouts.h"
16#include "base/time/time.h"
17#include "base/values.h"
18#include "chrome/common/automation_messages.h"
19#include "chrome/test/automation/automation_proxy.h"
20
21using automation::Error;
22using automation::ErrorCode;
23using base::DictionaryValue;
24using base::ListValue;
25
26namespace {
27
28bool SendAutomationJSONRequest(AutomationMessageSender* sender,
29                               const DictionaryValue& request_dict,
30                               DictionaryValue* reply_dict,
31                               Error* error) {
32  std::string request, reply;
33  base::JSONWriter::Write(&request_dict, &request);
34  std::string command;
35  request_dict.GetString("command", &command);
36  LOG(INFO) << "Sending '" << command << "' command.";
37
38  base::Time before_sending = base::Time::Now();
39  bool success = false;
40  if (!SendAutomationJSONRequestWithDefaultTimeout(
41          sender, request, &reply, &success)) {
42    *error = Error(base::StringPrintf(
43        "Chrome did not respond to '%s'. Elapsed time was %" PRId64 " ms.",
44        command.c_str(),
45        (base::Time::Now() - before_sending).InMilliseconds()));
46    LOG(INFO) << error->message();
47    return false;
48  }
49  scoped_ptr<Value> value(
50      base::JSONReader::Read(reply, base::JSON_ALLOW_TRAILING_COMMAS));
51  if (!value.get() || !value->IsType(Value::TYPE_DICTIONARY)) {
52    *error = Error("JSON request did not return a dictionary");
53    LOG(ERROR) << "JSON request did not return dict: " << command << "\n";
54    return false;
55  }
56  DictionaryValue* dict = static_cast<DictionaryValue*>(value.get());
57  if (!success) {
58    std::string error_msg;
59    dict->GetString("error", &error_msg);
60    int int_code = automation::kUnknownError;
61    dict->GetInteger("code", &int_code);
62    ErrorCode code = static_cast<ErrorCode>(int_code);
63    *error = Error(code, error_msg);
64    LOG(INFO) << "JSON request failed: " << command << "\n"
65              << "    with error: " << error_msg;
66    return false;
67  }
68  reply_dict->MergeDictionary(dict);
69  return true;
70}
71
72}  // namespace
73
74WebKeyEvent::WebKeyEvent(automation::KeyEventTypes type,
75                         ui::KeyboardCode key_code,
76                         const std::string& unmodified_text,
77                         const std::string& modified_text,
78                         int modifiers)
79    : type(type),
80      key_code(key_code),
81      unmodified_text(unmodified_text),
82      modified_text(modified_text),
83      modifiers(modifiers) {}
84
85WebMouseEvent::WebMouseEvent(automation::MouseEventType type,
86                             automation::MouseButton button,
87                             int x,
88                             int y,
89                             int click_count,
90                             int modifiers)
91    : type(type),
92      button(button),
93      x(x),
94      y(y),
95      click_count(click_count),
96      modifiers(modifiers) {}
97
98// static
99WebViewId WebViewId::ForView(const AutomationId& view_id) {
100  WebViewId id;
101  id.old_style_ = false;
102  id.id_ = view_id;
103  return id;
104}
105
106// static
107WebViewId WebViewId::ForOldStyleTab(int tab_id) {
108  WebViewId id;
109  id.old_style_ = true;
110  id.tab_id_ = tab_id;
111  return id;
112}
113
114WebViewId::WebViewId() : old_style_(true) {}
115
116void WebViewId::UpdateDictionary(DictionaryValue* dict,
117                                 const std::string& view_id_key) const {
118  if (old_style_) {
119    dict->SetInteger("id", tab_id_);
120  } else {
121    dict->Set(view_id_key, id_.ToValue());
122  }
123}
124
125bool WebViewId::IsValid() const {
126  if (old_style_)
127    return tab_id_ != 0;
128  else
129    return id_.is_valid();
130}
131
132AutomationId WebViewId::GetId() const {
133  if (old_style_)
134    return AutomationId(AutomationId::kTypeTab, base::IntToString(tab_id_));
135  else
136    return id_;
137}
138
139bool WebViewId::IsTab() const {
140  return old_style_ || id_.type() == AutomationId::kTypeTab;
141}
142
143int WebViewId::tab_id() const {
144  return tab_id_;
145}
146
147bool WebViewId::old_style() const {
148  return old_style_;
149}
150
151// static
152WebViewLocator WebViewLocator::ForIndexPair(int browser_index, int tab_index) {
153  WebViewLocator locator;
154  locator.type_ = kTypeIndexPair;
155  locator.locator_.index_pair.browser_index = browser_index;
156  locator.locator_.index_pair.tab_index = tab_index;
157  return locator;
158}
159
160// static
161WebViewLocator WebViewLocator::ForViewId(const AutomationId& view_id) {
162  WebViewLocator locator;
163  locator.type_ = kTypeViewId;
164  locator.locator_.view_id = view_id;
165  return locator;
166}
167
168WebViewLocator::WebViewLocator() {}
169
170WebViewLocator::~WebViewLocator() {}
171
172void WebViewLocator::UpdateDictionary(
173    DictionaryValue* dict, const std::string& view_id_key) const {
174  if (type_ == kTypeIndexPair) {
175    dict->SetInteger("windex", locator_.index_pair.browser_index);
176    dict->SetInteger("tab_index", locator_.index_pair.tab_index);
177  } else if (type_ == kTypeViewId) {
178    dict->Set(view_id_key, locator_.view_id.ToValue());
179  }
180}
181
182int WebViewLocator::browser_index() const {
183  return locator_.index_pair.browser_index;
184}
185
186int WebViewLocator::tab_index() const {
187  return locator_.index_pair.tab_index;
188}
189
190WebViewLocator::Locator::Locator() {}
191
192WebViewLocator::Locator::~Locator() {}
193
194WebViewInfo::WebViewInfo(const WebViewId& view_id,
195                         const std::string& extension_id)
196    : view_id(view_id),
197      extension_id(extension_id) {}
198
199WebViewInfo::~WebViewInfo() {}
200
201bool SendAutomationJSONRequest(AutomationMessageSender* sender,
202                               const std::string& request,
203                               int timeout_ms,
204                               std::string* reply,
205                               bool* success) {
206  return sender->Send(new AutomationMsg_SendJSONRequest(
207      -1, request, reply, success), timeout_ms);
208}
209
210bool SendAutomationJSONRequestWithDefaultTimeout(
211    AutomationMessageSender* sender,
212    const std::string& request,
213    std::string* reply,
214    bool* success) {
215  return sender->Send(new AutomationMsg_SendJSONRequest(
216      -1, request, reply, success));
217}
218
219bool SendGetIndicesFromTabIdJSONRequest(
220    AutomationMessageSender* sender,
221    int tab_id,
222    int* browser_index,
223    int* tab_index,
224    Error* error) {
225  DictionaryValue request_dict;
226  request_dict.SetString("command", "GetIndicesFromTab");
227  request_dict.SetInteger("tab_id", tab_id);
228  DictionaryValue reply_dict;
229  if (!SendAutomationJSONRequest(sender, request_dict, &reply_dict, error))
230    return false;
231  if (!reply_dict.GetInteger("windex", browser_index))
232    return false;
233  if (!reply_dict.GetInteger("tab_index", tab_index))
234    return false;
235  return true;
236}
237
238bool SendGetIndicesFromTabHandleJSONRequest(
239    AutomationMessageSender* sender,
240    int tab_handle,
241    int* browser_index,
242    int* tab_index,
243    Error* error) {
244  DictionaryValue request_dict;
245  request_dict.SetString("command", "GetIndicesFromTab");
246  request_dict.SetInteger("tab_handle", tab_handle);
247  DictionaryValue reply_dict;
248  if (!SendAutomationJSONRequest(sender, request_dict, &reply_dict, error))
249    return false;
250  if (!reply_dict.GetInteger("windex", browser_index))
251    return false;
252  if (!reply_dict.GetInteger("tab_index", tab_index))
253    return false;
254  return true;
255}
256
257bool SendNavigateToURLJSONRequest(
258    AutomationMessageSender* sender,
259    const WebViewLocator& locator,
260    const std::string& url,
261    int navigation_count,
262    AutomationMsg_NavigationResponseValues* nav_response,
263    Error* error) {
264  DictionaryValue dict;
265  dict.SetString("command", "NavigateToURL");
266  locator.UpdateDictionary(&dict, "auto_id");
267  dict.SetString("url", url);
268  dict.SetInteger("navigation_count", navigation_count);
269  DictionaryValue reply_dict;
270  if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error))
271    return false;
272  // We don't expect a navigation result for asynchronous navigations.
273  if (navigation_count == 0)
274    return true;
275  int response = 0;
276  if (!reply_dict.GetInteger("result", &response))
277    return false;
278  *nav_response = static_cast<AutomationMsg_NavigationResponseValues>(response);
279  return true;
280}
281
282bool SendExecuteJavascriptJSONRequest(
283    AutomationMessageSender* sender,
284    const WebViewLocator& locator,
285    const std::string& frame_xpath,
286    const std::string& javascript,
287    scoped_ptr<Value>* result,
288    Error* error) {
289  DictionaryValue dict;
290  dict.SetString("command", "ExecuteJavascript");
291  locator.UpdateDictionary(&dict, "auto_id");
292  dict.SetString("frame_xpath", frame_xpath);
293  dict.SetString("javascript", javascript);
294  DictionaryValue reply_dict;
295  if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error))
296    return false;
297
298  std::string json;
299  if (!reply_dict.GetString("result", &json)) {
300    LOG(ERROR) << "Executed javascript but received no 'result'";
301    return false;
302  }
303  // Wrap |json| in an array before deserializing because valid JSON has an
304  // array or an object as the root.
305  json.insert(0, "[");
306  json.append("]");
307
308  JSONStringValueSerializer deserializer(json);
309  Value* value = deserializer.Deserialize(NULL, NULL);
310  if (!value || !value->IsType(Value::TYPE_LIST)) {
311    LOG(ERROR) << "Unable to deserialize returned JSON";
312    return false;
313  }
314  scoped_ptr<ListValue> list(static_cast<ListValue*>(value));
315  return list->Remove(0, result);
316}
317
318bool SendGoForwardJSONRequest(
319    AutomationMessageSender* sender,
320    const WebViewLocator& locator,
321    Error* error) {
322  DictionaryValue dict;
323  dict.SetString("command", "GoForward");
324  locator.UpdateDictionary(&dict, "auto_id");
325  DictionaryValue reply_dict;
326  return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
327}
328
329bool SendGoBackJSONRequest(
330    AutomationMessageSender* sender,
331    const WebViewLocator& locator,
332    Error* error) {
333  DictionaryValue dict;
334  dict.SetString("command", "GoBack");
335  locator.UpdateDictionary(&dict, "auto_id");
336  DictionaryValue reply_dict;
337  return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
338}
339
340bool SendReloadJSONRequest(
341    AutomationMessageSender* sender,
342    const WebViewLocator& locator,
343    Error* error) {
344  DictionaryValue dict;
345  dict.SetString("command", "Reload");
346  locator.UpdateDictionary(&dict, "auto_id");
347  DictionaryValue reply_dict;
348  return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
349}
350
351bool SendCaptureEntirePageJSONRequestDeprecated(
352    AutomationMessageSender* sender,
353    const WebViewLocator& locator,
354    const base::FilePath& path,
355    Error* error) {
356  DictionaryValue dict;
357  dict.SetString("command", "CaptureEntirePage");
358  locator.UpdateDictionary(&dict, "auto_id");
359  dict.SetString("path", path.value());
360  DictionaryValue reply_dict;
361
362  return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
363}
364
365#if !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS))
366bool SendHeapProfilerDumpJSONRequestDeprecated(
367    AutomationMessageSender* sender,
368    const WebViewLocator& locator,
369    const std::string& reason,
370    Error* error) {
371  DictionaryValue dict;
372  dict.SetString("command", "HeapProfilerDump");
373  dict.SetString("process_type", "renderer");
374  dict.SetString("reason", reason);
375  locator.UpdateDictionary(&dict, "auto_id");
376  DictionaryValue reply_dict;
377
378  return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
379}
380#endif  // !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS))
381
382bool SendGetCookiesJSONRequest(
383    AutomationMessageSender* sender,
384    const std::string& url,
385    scoped_ptr<ListValue>* cookies,
386    Error* error) {
387  DictionaryValue dict;
388  dict.SetString("command", "GetCookies");
389  dict.SetString("url", url);
390  DictionaryValue reply_dict;
391  if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error))
392    return false;
393  scoped_ptr<Value> cookies_value;
394  if (!reply_dict.Remove("cookies", &cookies_value))
395    return false;
396  if (!cookies_value->IsType(Value::TYPE_LIST))
397    return false;
398  cookies->reset(static_cast<ListValue*>(cookies_value.release()));
399  return true;
400}
401
402bool SendDeleteCookieJSONRequest(
403    AutomationMessageSender* sender,
404    const std::string& url,
405    const std::string& cookie_name,
406    Error* error) {
407  DictionaryValue dict;
408  dict.SetString("command", "DeleteCookie");
409  dict.SetString("url", url);
410  dict.SetString("name", cookie_name);
411  DictionaryValue reply_dict;
412  return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
413}
414
415bool SendSetCookieJSONRequest(
416    AutomationMessageSender* sender,
417    const std::string& url,
418    DictionaryValue* cookie_dict,
419    Error* error) {
420  DictionaryValue dict;
421  dict.SetString("command", "SetCookie");
422  dict.SetString("url", url);
423  dict.Set("cookie", cookie_dict->DeepCopy());
424  DictionaryValue reply_dict;
425  return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
426}
427
428bool SendGetTabIdsJSONRequest(
429    AutomationMessageSender* sender,
430    std::vector<WebViewInfo>* views,
431    Error* error) {
432  DictionaryValue dict;
433  dict.SetString("command", "GetTabIds");
434  DictionaryValue reply_dict;
435  if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error))
436    return false;
437  ListValue* id_list;
438  if (reply_dict.GetList("ids", &id_list)) {
439    for (size_t i = 0; i < id_list->GetSize(); ++i) {
440      int id;
441      if (!id_list->GetInteger(i, &id)) {
442        *error = Error("Returned id in 'tab_ids' is not an integer");
443        return false;
444      }
445      views->push_back(WebViewInfo(
446          WebViewId::ForOldStyleTab(id), std::string()));
447    }
448  }
449  return true;
450}
451
452bool SendGetWebViewsJSONRequest(
453    AutomationMessageSender* sender,
454    std::vector<WebViewInfo>* views,
455    Error* error) {
456  DictionaryValue dict;
457  dict.SetString("command", "GetViews");
458  DictionaryValue reply_dict;
459  if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error))
460    return false;
461  ListValue* views_list;
462  if (!reply_dict.GetList("views", &views_list)) {
463    *error = Error("Returned 'views' key is missing or invalid");
464    return false;
465  }
466  for (size_t i = 0; i < views_list->GetSize(); ++i) {
467    DictionaryValue* view_dict;
468    if (!views_list->GetDictionary(i, &view_dict)) {
469      *error = Error("Returned 'views' key contains non-dictionary values");
470      return false;
471    }
472    AutomationId view_id;
473    std::string error_msg;
474    if (!AutomationId::FromValueInDictionary(
475            view_dict, "auto_id", &view_id, &error_msg)) {
476      *error = Error(error_msg);
477      return false;
478    }
479    std::string extension_id;
480    view_dict->GetString("extension_id", &extension_id);
481    views->push_back(WebViewInfo(
482        WebViewId::ForView(view_id), extension_id));
483  }
484  return true;
485}
486
487bool SendIsTabIdValidJSONRequest(
488    AutomationMessageSender* sender,
489    const WebViewId& view_id,
490    bool* is_valid,
491    Error* error) {
492  DictionaryValue dict;
493  dict.SetString("command", "IsTabIdValid");
494  view_id.UpdateDictionary(&dict, "tab_id");
495  DictionaryValue reply_dict;
496  if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error))
497    return false;
498  return reply_dict.GetBoolean("is_valid", is_valid);
499}
500
501bool SendDoesAutomationObjectExistJSONRequest(
502    AutomationMessageSender* sender,
503    const WebViewId& view_id,
504    bool* does_exist,
505    Error* error) {
506  DictionaryValue dict;
507  dict.SetString("command", "DoesAutomationObjectExist");
508  view_id.UpdateDictionary(&dict, "auto_id");
509  DictionaryValue reply_dict;
510  if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error))
511    return false;
512  return reply_dict.GetBoolean("does_exist", does_exist);
513}
514
515bool SendCloseViewJSONRequest(
516    AutomationMessageSender* sender,
517    const WebViewLocator& locator,
518    Error* error) {
519  DictionaryValue dict;
520  dict.SetString("command", "CloseTab");
521  locator.UpdateDictionary(&dict, "auto_id");
522  DictionaryValue reply_dict;
523  return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
524}
525
526bool SendMouseMoveJSONRequestDeprecated(
527    AutomationMessageSender* sender,
528    const WebViewLocator& locator,
529    int x,
530    int y,
531    Error* error) {
532  DictionaryValue dict;
533  dict.SetString("command", "WebkitMouseMove");
534  locator.UpdateDictionary(&dict, "auto_id");
535  dict.SetInteger("x", x);
536  dict.SetInteger("y", y);
537  DictionaryValue reply_dict;
538  return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
539}
540
541bool SendMouseClickJSONRequestDeprecated(
542    AutomationMessageSender* sender,
543    const WebViewLocator& locator,
544    automation::MouseButton button,
545    int x,
546    int y,
547    Error* error) {
548  DictionaryValue dict;
549  dict.SetString("command", "WebkitMouseClick");
550  locator.UpdateDictionary(&dict, "auto_id");
551  dict.SetInteger("button", button);
552  dict.SetInteger("x", x);
553  dict.SetInteger("y", y);
554  DictionaryValue reply_dict;
555  return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
556}
557
558bool SendMouseDragJSONRequestDeprecated(
559    AutomationMessageSender* sender,
560    const WebViewLocator& locator,
561    int start_x,
562    int start_y,
563    int end_x,
564    int end_y,
565    Error* error) {
566  DictionaryValue dict;
567  dict.SetString("command", "WebkitMouseDrag");
568  locator.UpdateDictionary(&dict, "auto_id");
569  dict.SetInteger("start_x", start_x);
570  dict.SetInteger("start_y", start_y);
571  dict.SetInteger("end_x", end_x);
572  dict.SetInteger("end_y", end_y);
573  DictionaryValue reply_dict;
574  return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
575}
576
577bool SendMouseButtonDownJSONRequestDeprecated(
578    AutomationMessageSender* sender,
579    const WebViewLocator& locator,
580    int x,
581    int y,
582    Error* error) {
583  DictionaryValue dict;
584  dict.SetString("command", "WebkitMouseButtonDown");
585  locator.UpdateDictionary(&dict, "auto_id");
586  dict.SetInteger("x", x);
587  dict.SetInteger("y", y);
588  DictionaryValue reply_dict;
589  return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
590}
591
592bool SendMouseButtonUpJSONRequestDeprecated(
593    AutomationMessageSender* sender,
594    const WebViewLocator& locator,
595    int x,
596    int y,
597    Error* error)  {
598  DictionaryValue dict;
599  dict.SetString("command", "WebkitMouseButtonUp");
600  locator.UpdateDictionary(&dict, "auto_id");
601  dict.SetInteger("x", x);
602  dict.SetInteger("y", y);
603  DictionaryValue reply_dict;
604  return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
605}
606
607bool SendMouseDoubleClickJSONRequestDeprecated(
608    AutomationMessageSender* sender,
609    const WebViewLocator& locator,
610    int x,
611    int y,
612    Error* error)  {
613  DictionaryValue dict;
614  dict.SetString("command", "WebkitMouseDoubleClick");
615  locator.UpdateDictionary(&dict, "auto_id");
616  dict.SetInteger("x", x);
617  dict.SetInteger("y", y);
618  DictionaryValue reply_dict;
619  return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
620}
621
622bool SendWebKeyEventJSONRequest(
623    AutomationMessageSender* sender,
624    const WebViewLocator& locator,
625    const WebKeyEvent& key_event,
626    Error* error) {
627  DictionaryValue dict;
628  dict.SetString("command", "SendWebkitKeyEvent");
629  locator.UpdateDictionary(&dict, "auto_id");
630  dict.SetInteger("type", key_event.type);
631  dict.SetInteger("nativeKeyCode", key_event.key_code);
632  dict.SetInteger("windowsKeyCode", key_event.key_code);
633  dict.SetString("unmodifiedText", key_event.unmodified_text);
634  dict.SetString("text", key_event.modified_text);
635  dict.SetInteger("modifiers", key_event.modifiers);
636  dict.SetBoolean("isSystemKey", false);
637  DictionaryValue reply_dict;
638  return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
639}
640
641bool SendNativeKeyEventJSONRequest(
642    AutomationMessageSender* sender,
643    const WebViewLocator& locator,
644    ui::KeyboardCode key_code,
645    int modifiers,
646    Error* error) {
647  DictionaryValue dict;
648  dict.SetString("command", "SendOSLevelKeyEventToTab");
649  locator.UpdateDictionary(&dict, "auto_id");
650  dict.SetInteger("keyCode", key_code);
651  dict.SetInteger("modifiers", modifiers);
652  DictionaryValue reply_dict;
653  return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
654}
655
656bool SendWebMouseEventJSONRequestDeprecated(
657    AutomationMessageSender* sender,
658    const WebViewLocator& locator,
659    const WebMouseEvent& mouse_event,
660    automation::Error* error) {
661  DictionaryValue dict;
662  dict.SetString("command", "ProcessWebMouseEvent");
663  locator.UpdateDictionary(&dict, "auto_id");
664  dict.SetInteger("type", mouse_event.type);
665  dict.SetInteger("button", mouse_event.button);
666  dict.SetInteger("x", mouse_event.x);
667  dict.SetInteger("y", mouse_event.y);
668  dict.SetInteger("click_count", mouse_event.click_count);
669  dict.SetInteger("modifiers", mouse_event.modifiers);
670  DictionaryValue reply_dict;
671  return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
672}
673
674bool SendDragAndDropFilePathsJSONRequest(
675    AutomationMessageSender* sender,
676    const WebViewLocator& locator,
677    int x,
678    int y,
679    const std::vector<base::FilePath::StringType>& paths,
680    Error* error) {
681  DictionaryValue dict;
682  dict.SetString("command", "DragAndDropFilePaths");
683  locator.UpdateDictionary(&dict, "auto_id");
684  dict.SetInteger("x", x);
685  dict.SetInteger("y", y);
686
687  ListValue* list_value = new ListValue();
688  for (size_t path_index = 0; path_index < paths.size(); ++path_index) {
689    list_value->Append(new base::StringValue(paths[path_index]));
690  }
691  dict.Set("paths", list_value);
692
693  DictionaryValue reply_dict;
694  return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
695}
696
697bool SendSetViewBoundsJSONRequest(
698    AutomationMessageSender* sender,
699    const WebViewId& id,
700    int x,
701    int y,
702    int width,
703    int height,
704    automation::Error* error) {
705  DictionaryValue dict;
706  dict.SetString("command", "SetViewBounds");
707  id.UpdateDictionary(&dict, "auto_id");
708  dict.SetInteger("bounds.x", x);
709  dict.SetInteger("bounds.y", y);
710  dict.SetInteger("bounds.width", width);
711  dict.SetInteger("bounds.height", height);
712
713  DictionaryValue reply_dict;
714  return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
715}
716
717bool SendMaximizeJSONRequest(
718    AutomationMessageSender* sender,
719    const WebViewId& id,
720    automation::Error* error) {
721  DictionaryValue dict;
722  dict.SetString("command", "MaximizeView");
723  id.UpdateDictionary(&dict, "auto_id");
724
725  DictionaryValue reply_dict;
726  return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
727}
728
729bool SendGetAppModalDialogMessageJSONRequest(
730    AutomationMessageSender* sender,
731    std::string* message,
732    Error* error) {
733  DictionaryValue dict;
734  dict.SetString("command", "GetAppModalDialogMessage");
735  DictionaryValue reply_dict;
736  if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error))
737    return false;
738  return reply_dict.GetString("message", message);
739}
740
741bool SendAcceptOrDismissAppModalDialogJSONRequest(
742    AutomationMessageSender* sender,
743    bool accept,
744    Error* error) {
745  DictionaryValue dict;
746  dict.SetString("command", "AcceptOrDismissAppModalDialog");
747  dict.SetBoolean("accept", accept);
748  DictionaryValue reply_dict;
749  return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
750}
751
752bool SendAcceptPromptAppModalDialogJSONRequest(
753    AutomationMessageSender* sender,
754    const std::string& prompt_text,
755    Error* error) {
756  DictionaryValue dict;
757  dict.SetString("command", "AcceptOrDismissAppModalDialog");
758  dict.SetBoolean("accept", true);
759  dict.SetString("prompt_text", prompt_text);
760  DictionaryValue reply_dict;
761  return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
762}
763
764bool SendWaitForAllViewsToStopLoadingJSONRequestDeprecated(
765    AutomationMessageSender* sender,
766    Error* error) {
767  DictionaryValue dict;
768  dict.SetString("command", "WaitForAllTabsToStopLoading");
769  DictionaryValue reply_dict;
770  return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
771}
772
773bool SendGetChromeDriverAutomationVersion(
774    AutomationMessageSender* sender,
775    int* version,
776    Error* error) {
777  DictionaryValue dict;
778  dict.SetString("command", "GetChromeDriverAutomationVersion");
779  DictionaryValue reply_dict;
780  if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error))
781    return false;
782  return reply_dict.GetInteger("version", version);
783}
784
785bool SendInstallExtensionJSONRequest(
786    AutomationMessageSender* sender,
787    const base::FilePath& path,
788    bool with_ui,
789    std::string* extension_id,
790    Error* error) {
791  DictionaryValue dict;
792  dict.SetString("command", "InstallExtension");
793  dict.SetString("path", path.value());
794  dict.SetBoolean("with_ui", with_ui);
795  // TODO(kkania): Set correct auto_id instead of hardcoding windex.
796  dict.SetInteger("windex", 0);
797  dict.SetInteger("tab_index", 0);
798  DictionaryValue reply_dict;
799  if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error))
800    return false;
801  if (!reply_dict.GetString("id", extension_id)) {
802    *error = Error("Missing or invalid 'id'");
803    return false;
804  }
805  return true;
806}
807
808bool SendGetExtensionsInfoJSONRequest(
809    AutomationMessageSender* sender,
810    ListValue* extensions_list,
811    Error* error) {
812  DictionaryValue dict;
813  dict.SetString("command", "GetExtensionsInfo");
814  // TODO(kkania): Set correct auto_id instead of hardcoding windex.
815  dict.SetInteger("windex", 0);
816  DictionaryValue reply_dict;
817  if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error))
818    return false;
819  ListValue* extensions_list_swap;
820  if (!reply_dict.GetList("extensions", &extensions_list_swap)) {
821    *error = Error("Missing or invalid 'extensions'");
822    return false;
823  }
824  extensions_list->Swap(extensions_list_swap);
825  return true;
826}
827
828bool SendIsPageActionVisibleJSONRequest(
829    AutomationMessageSender* sender,
830    const WebViewId& tab_id,
831    const std::string& extension_id,
832    bool* is_visible,
833    Error* error) {
834  DictionaryValue dict;
835  dict.SetString("command", "IsPageActionVisible");
836  tab_id.UpdateDictionary(&dict, "auto_id");
837  dict.SetString("extension_id", extension_id);
838  // TODO(kkania): Set correct auto_id instead of hardcoding windex.
839  dict.SetInteger("windex", 0);
840  DictionaryValue reply_dict;
841  if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error))
842    return false;
843  if (!reply_dict.GetBoolean("is_visible", is_visible)) {
844    *error = Error("Missing or invalid 'is_visible'");
845    return false;
846  }
847  return true;
848}
849
850bool SendSetExtensionStateJSONRequest(
851    AutomationMessageSender* sender,
852    const std::string& extension_id,
853    bool enable,
854    bool allow_in_incognito,
855    Error* error) {
856  DictionaryValue dict;
857  dict.SetString("command", "SetExtensionStateById");
858  dict.SetString("id", extension_id);
859  dict.SetBoolean("enable", enable);
860  dict.SetBoolean("allow_in_incognito", allow_in_incognito);
861  // TODO(kkania): Set correct auto_id instead of hardcoding windex.
862  dict.SetInteger("windex", 0);
863  DictionaryValue reply_dict;
864  return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
865}
866
867bool SendClickExtensionButtonJSONRequest(
868    AutomationMessageSender* sender,
869    const std::string& extension_id,
870    bool browser_action,
871    Error* error) {
872  DictionaryValue dict;
873  if (browser_action)
874    dict.SetString("command", "TriggerBrowserActionById");
875  else
876    dict.SetString("command", "TriggerPageActionById");
877  dict.SetString("id", extension_id);
878  // TODO(kkania): Set correct auto_id instead of hardcoding windex.
879  dict.SetInteger("windex", 0);
880  dict.SetInteger("tab_index", 0);
881  DictionaryValue reply_dict;
882  return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
883}
884
885bool SendUninstallExtensionJSONRequest(
886    AutomationMessageSender* sender,
887    const std::string& extension_id,
888    Error* error) {
889  DictionaryValue dict;
890  dict.SetString("command", "UninstallExtensionById");
891  dict.SetString("id", extension_id);
892  // TODO(kkania): Set correct auto_id instead of hardcoding windex.
893  dict.SetInteger("windex", 0);
894  DictionaryValue reply_dict;
895  if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error))
896    return false;
897  bool success;
898  if (!reply_dict.GetBoolean("success", &success)) {
899    *error = Error("Missing or invalid 'success'");
900    return false;
901  }
902  if (!success) {
903    *error = Error("Extension uninstall not permitted");
904    return false;
905  }
906  return true;
907}
908
909bool SendSetLocalStatePreferenceJSONRequest(
910    AutomationMessageSender* sender,
911    const std::string& pref,
912    base::Value* value,
913    Error* error) {
914  DictionaryValue dict;
915  dict.SetString("command", "SetLocalStatePrefs");
916  dict.SetString("path", pref);
917  dict.Set("value", value);
918  DictionaryValue reply_dict;
919  return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
920}
921
922bool SendSetPreferenceJSONRequest(
923    AutomationMessageSender* sender,
924    const std::string& pref,
925    base::Value* value,
926    Error* error) {
927  DictionaryValue dict;
928  dict.SetString("command", "SetPrefs");
929  // TODO(kkania): Set correct auto_id instead of hardcoding windex.
930  dict.SetInteger("windex", 0);
931  dict.SetString("path", pref);
932  dict.Set("value", value);
933  DictionaryValue reply_dict;
934  return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
935}
936
937bool SendOverrideGeolocationJSONRequest(
938    AutomationMessageSender* sender,
939    const base::DictionaryValue* geolocation,
940    Error* error) {
941  scoped_ptr<DictionaryValue> dict(geolocation->DeepCopy());
942  dict->SetString("command", "OverrideGeoposition");
943  DictionaryValue reply_dict;
944  return SendAutomationJSONRequest(sender, *dict.get(), &reply_dict, error);
945}
946