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/browser/automation/automation_provider_json.h"
      6 
      7 #include "base/json/json_writer.h"
      8 #include "base/json/string_escape.h"
      9 #include "base/values.h"
     10 #include "chrome/browser/autocomplete/autocomplete_match.h"
     11 #include "chrome/browser/automation/automation_provider.h"
     12 #include "chrome/browser/automation/automation_util.h"
     13 #include "chrome/browser/extensions/extension_service.h"
     14 #include "chrome/browser/extensions/extension_system.h"
     15 #include "chrome/browser/profiles/profile.h"
     16 #include "chrome/common/automation_id.h"
     17 #include "chrome/common/automation_messages.h"
     18 #include "chrome/common/extensions/extension.h"
     19 #include "content/public/browser/web_contents.h"
     20 
     21 using automation::Error;
     22 using automation::ErrorCode;
     23 using content::WebContents;
     24 
     25 AutomationJSONReply::AutomationJSONReply(AutomationProvider* provider,
     26                                          IPC::Message* reply_message)
     27   : provider_(provider),
     28     message_(reply_message) {
     29 }
     30 
     31 AutomationJSONReply::~AutomationJSONReply() {
     32   DCHECK(!message_) << "JSON automation request not replied!";
     33 }
     34 
     35 void AutomationJSONReply::SendSuccess(const Value* value) {
     36   DCHECK(message_) << "Resending reply for JSON automation request";
     37   std::string json_string = "{}";
     38   if (value)
     39     base::JSONWriter::Write(value, &json_string);
     40   AutomationMsg_SendJSONRequest::WriteReplyParams(
     41       message_, json_string, true);
     42   provider_->Send(message_);
     43   message_ = NULL;
     44 }
     45 
     46 void AutomationJSONReply::SendError(const std::string& error_message) {
     47   SendError(Error(error_message));
     48 }
     49 
     50 void AutomationJSONReply::SendErrorCode(ErrorCode code) {
     51   SendError(Error(code));
     52 }
     53 
     54 void AutomationJSONReply::SendError(const Error& error) {
     55   DCHECK(message_) << "Resending reply for JSON automation request";
     56 
     57   base::DictionaryValue dict;
     58   dict.SetString("error", error.message());
     59   dict.SetInteger("code", error.code());
     60   std::string json;
     61   base::JSONWriter::Write(&dict, &json);
     62 
     63   AutomationMsg_SendJSONRequest::WriteReplyParams(message_, json, false);
     64   provider_->Send(message_);
     65   message_ = NULL;
     66 }
     67 
     68 bool GetBrowserFromJSONArgs(
     69     DictionaryValue* args,
     70     Browser** browser,
     71     std::string* error) {
     72   if (args->HasKey("auto_id")) {
     73     AutomationId id;
     74     if (!GetAutomationIdFromJSONArgs(args, "auto_id", &id, error))
     75       return false;
     76     WebContents* tab;
     77     if (!automation_util::GetTabForId(id, &tab)) {
     78       *error = "'auto_id' does not refer to an open tab";
     79       return false;
     80     }
     81     Browser* container = automation_util::GetBrowserForTab(tab);
     82     if (!container) {
     83       *error = "tab does not belong to an open browser";
     84       return false;
     85     }
     86     *browser = container;
     87   } else {
     88     int browser_index;
     89     if (!args->GetInteger("windex", &browser_index)) {
     90       *error = "'windex' missing or invalid";
     91       return false;
     92     }
     93     *browser = automation_util::GetBrowserAt(browser_index);
     94     if (!*browser) {
     95       *error = "Cannot locate browser from given index";
     96       return false;
     97     }
     98   }
     99   return true;
    100 }
    101 
    102 bool GetTabFromJSONArgs(
    103     DictionaryValue* args,
    104     WebContents** tab,
    105     std::string* error) {
    106   if (args->HasKey("auto_id")) {
    107     AutomationId id;
    108     if (!GetAutomationIdFromJSONArgs(args, "auto_id", &id, error))
    109       return false;
    110     if (!automation_util::GetTabForId(id, tab)) {
    111       *error = "'auto_id' does not refer to an open tab";
    112       return false;
    113     }
    114   } else {
    115     int browser_index, tab_index;
    116     if (!args->GetInteger("windex", &browser_index)) {
    117       *error = "'windex' missing or invalid";
    118       return false;
    119     }
    120     if (!args->GetInteger("tab_index", &tab_index)) {
    121       *error = "'tab_index' missing or invalid";
    122       return false;
    123     }
    124     *tab = automation_util::GetWebContentsAt(browser_index, tab_index);
    125     if (!*tab) {
    126       *error = "Cannot locate tab from given indices";
    127       return false;
    128     }
    129   }
    130   return true;
    131 }
    132 
    133 bool GetBrowserAndTabFromJSONArgs(
    134     DictionaryValue* args,
    135     Browser** browser,
    136     WebContents** tab,
    137     std::string* error) {
    138   return GetBrowserFromJSONArgs(args, browser, error) &&
    139          GetTabFromJSONArgs(args, tab, error);
    140 }
    141 
    142 bool GetAutomationIdFromJSONArgs(
    143     DictionaryValue* args,
    144     const std::string& key,
    145     AutomationId* id,
    146     std::string* error) {
    147   Value* id_value;
    148   if (!args->Get(key, &id_value)) {
    149     *error = base::StringPrintf("Missing parameter '%s'", key.c_str());
    150     return false;
    151   }
    152   return AutomationId::FromValue(id_value, id, error);
    153 }
    154 
    155 bool GetRenderViewFromJSONArgs(
    156     DictionaryValue* args,
    157     Profile* profile,
    158     content::RenderViewHost** rvh,
    159     std::string* error) {
    160   Value* id_value;
    161   if (args->Get("auto_id", &id_value)) {
    162     AutomationId id;
    163     if (!AutomationId::FromValue(id_value, &id, error))
    164       return false;
    165     if (!automation_util::GetRenderViewForId(id, profile, rvh)) {
    166       *error = "ID does not correspond to an open view";
    167       return false;
    168     }
    169   } else {
    170     // If the render view id is not specified, check for browser/tab indices.
    171     WebContents* tab = NULL;
    172     if (!GetTabFromJSONArgs(args, &tab, error))
    173       return false;
    174     *rvh = tab->GetRenderViewHost();
    175   }
    176   return true;
    177 }
    178 
    179 namespace {
    180 
    181 bool GetExtensionFromJSONArgsHelper(
    182     base::DictionaryValue* args,
    183     const std::string& key,
    184     Profile* profile,
    185     bool include_disabled,
    186     const extensions::Extension** extension,
    187     std::string* error) {
    188   std::string id;
    189   if (!args->GetString(key, &id)) {
    190     *error = base::StringPrintf("Missing or invalid key: %s", key.c_str());
    191     return false;
    192   }
    193   ExtensionService* service = extensions::ExtensionSystem::Get(profile)->
    194       extension_service();
    195   if (!service) {
    196     *error = "No extensions service.";
    197     return false;
    198   }
    199   if (!service->GetInstalledExtension(id)) {
    200     // The extension ID does not correspond to any extension, whether crashed
    201     // or not.
    202     *error = base::StringPrintf("Extension %s is not installed.",
    203                                 id.c_str());
    204     return false;
    205   }
    206   const extensions::Extension* installed_extension =
    207       service->GetExtensionById(id, include_disabled);
    208   if (!installed_extension) {
    209     *error = "Extension is disabled or has crashed.";
    210     return false;
    211   }
    212   *extension = installed_extension;
    213   return true;
    214 }
    215 
    216 }  // namespace
    217 
    218 bool GetExtensionFromJSONArgs(
    219     base::DictionaryValue* args,
    220     const std::string& key,
    221     Profile* profile,
    222     const extensions::Extension** extension,
    223     std::string* error) {
    224   return GetExtensionFromJSONArgsHelper(
    225       args, key, profile, true /* include_disabled */, extension, error);
    226 }
    227 
    228 bool GetEnabledExtensionFromJSONArgs(
    229     base::DictionaryValue* args,
    230     const std::string& key,
    231     Profile* profile,
    232     const extensions::Extension** extension,
    233     std::string* error) {
    234   return GetExtensionFromJSONArgsHelper(
    235       args, key, profile, false /* include_disabled */, extension, error);
    236 }
    237