Home | History | Annotate | Download | only in automation
      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 
     21 using automation::Error;
     22 using automation::ErrorCode;
     23 using base::DictionaryValue;
     24 using base::ListValue;
     25 
     26 namespace {
     27 
     28 bool 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 
     74 WebKeyEvent::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 
     85 WebMouseEvent::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
     99 WebViewId 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
    107 WebViewId WebViewId::ForOldStyleTab(int tab_id) {
    108   WebViewId id;
    109   id.old_style_ = true;
    110   id.tab_id_ = tab_id;
    111   return id;
    112 }
    113 
    114 WebViewId::WebViewId() : old_style_(true) {}
    115 
    116 void 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 
    125 bool WebViewId::IsValid() const {
    126   if (old_style_)
    127     return tab_id_ != 0;
    128   else
    129     return id_.is_valid();
    130 }
    131 
    132 AutomationId WebViewId::GetId() const {
    133   if (old_style_)
    134     return AutomationId(AutomationId::kTypeTab, base::IntToString(tab_id_));
    135   else
    136     return id_;
    137 }
    138 
    139 bool WebViewId::IsTab() const {
    140   return old_style_ || id_.type() == AutomationId::kTypeTab;
    141 }
    142 
    143 int WebViewId::tab_id() const {
    144   return tab_id_;
    145 }
    146 
    147 bool WebViewId::old_style() const {
    148   return old_style_;
    149 }
    150 
    151 // static
    152 WebViewLocator 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
    161 WebViewLocator 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 
    168 WebViewLocator::WebViewLocator() {}
    169 
    170 WebViewLocator::~WebViewLocator() {}
    171 
    172 void 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 
    182 int WebViewLocator::browser_index() const {
    183   return locator_.index_pair.browser_index;
    184 }
    185 
    186 int WebViewLocator::tab_index() const {
    187   return locator_.index_pair.tab_index;
    188 }
    189 
    190 WebViewLocator::Locator::Locator() {}
    191 
    192 WebViewLocator::Locator::~Locator() {}
    193 
    194 WebViewInfo::WebViewInfo(const WebViewId& view_id,
    195                          const std::string& extension_id)
    196     : view_id(view_id),
    197       extension_id(extension_id) {}
    198 
    199 WebViewInfo::~WebViewInfo() {}
    200 
    201 bool 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 
    210 bool 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 
    219 bool 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 
    238 bool 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 
    257 bool 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 
    282 bool 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 
    318 bool 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 
    329 bool 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 
    340 bool 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 
    351 bool 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))
    366 bool 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 
    382 bool 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 
    402 bool 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 
    415 bool 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 
    428 bool 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 
    452 bool 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 
    487 bool 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 
    501 bool 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 
    515 bool 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 
    526 bool 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 
    541 bool 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 
    558 bool 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 
    577 bool 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 
    592 bool 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 
    607 bool 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 
    622 bool 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 
    641 bool 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 
    656 bool 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 
    674 bool 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 
    697 bool 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 
    717 bool 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 
    729 bool 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 
    741 bool 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 
    752 bool 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 
    764 bool 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 
    773 bool 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 
    785 bool 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 
    808 bool 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 
    828 bool 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 
    850 bool 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 
    867 bool 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 
    885 bool 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 
    909 bool 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 
    922 bool 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 
    937 bool 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