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_messages.h"
17#include "content/public/browser/web_contents.h"
18#include "extensions/common/extension.h"
19
20using content::WebContents;
21
22AutomationJSONReply::AutomationJSONReply(AutomationProvider* provider,
23                                         IPC::Message* reply_message)
24  : provider_(provider),
25    message_(reply_message) {
26}
27
28AutomationJSONReply::~AutomationJSONReply() {
29  DCHECK(!message_) << "JSON automation request not replied!";
30}
31
32void AutomationJSONReply::SendSuccess(const Value* value) {
33  DCHECK(message_) << "Resending reply for JSON automation request";
34  std::string json_string = "{}";
35  if (value)
36    base::JSONWriter::Write(value, &json_string);
37  AutomationMsg_SendJSONRequest::WriteReplyParams(
38      message_, json_string, true);
39  provider_->Send(message_);
40  message_ = NULL;
41}
42
43void AutomationJSONReply::SendError(const std::string& error_message) {
44  DCHECK(message_) << "Resending reply for JSON automation request";
45
46  base::DictionaryValue dict;
47  dict.SetString("error", error_message);
48  std::string json;
49  base::JSONWriter::Write(&dict, &json);
50
51  AutomationMsg_SendJSONRequest::WriteReplyParams(message_, json, false);
52  provider_->Send(message_);
53  message_ = NULL;
54}
55
56bool GetBrowserFromJSONArgs(
57    DictionaryValue* args,
58    Browser** browser,
59    std::string* error) {
60  int browser_index;
61  if (!args->GetInteger("windex", &browser_index)) {
62    *error = "'windex' missing or invalid";
63    return false;
64  }
65  *browser = automation_util::GetBrowserAt(browser_index);
66  if (!*browser) {
67    *error = "Cannot locate browser from given index";
68    return false;
69  }
70  return true;
71}
72
73bool GetTabFromJSONArgs(
74    DictionaryValue* args,
75    WebContents** tab,
76    std::string* error) {
77  int browser_index, tab_index;
78  if (!args->GetInteger("windex", &browser_index)) {
79    *error = "'windex' missing or invalid";
80    return false;
81  }
82  if (!args->GetInteger("tab_index", &tab_index)) {
83    *error = "'tab_index' missing or invalid";
84    return false;
85  }
86  *tab = automation_util::GetWebContentsAt(browser_index, tab_index);
87  if (!*tab) {
88    *error = "Cannot locate tab from given indices";
89    return false;
90  }
91  return true;
92}
93
94bool GetBrowserAndTabFromJSONArgs(
95    DictionaryValue* args,
96    Browser** browser,
97    WebContents** tab,
98    std::string* error) {
99  return GetBrowserFromJSONArgs(args, browser, error) &&
100         GetTabFromJSONArgs(args, tab, error);
101}
102
103bool GetRenderViewFromJSONArgs(
104    DictionaryValue* args,
105    Profile* profile,
106    content::RenderViewHost** rvh,
107    std::string* error) {
108  WebContents* tab = NULL;
109  if (!GetTabFromJSONArgs(args, &tab, error))
110    return false;
111  *rvh = tab->GetRenderViewHost();
112  return true;
113}
114
115namespace {
116
117bool GetExtensionFromJSONArgsHelper(
118    base::DictionaryValue* args,
119    const std::string& key,
120    Profile* profile,
121    bool include_disabled,
122    const extensions::Extension** extension,
123    std::string* error) {
124  std::string id;
125  if (!args->GetString(key, &id)) {
126    *error = base::StringPrintf("Missing or invalid key: %s", key.c_str());
127    return false;
128  }
129  ExtensionService* service = extensions::ExtensionSystem::Get(profile)->
130      extension_service();
131  if (!service) {
132    *error = "No extensions service.";
133    return false;
134  }
135  if (!service->GetInstalledExtension(id)) {
136    // The extension ID does not correspond to any extension, whether crashed
137    // or not.
138    *error = base::StringPrintf("Extension %s is not installed.",
139                                id.c_str());
140    return false;
141  }
142  const extensions::Extension* installed_extension =
143      service->GetExtensionById(id, include_disabled);
144  if (!installed_extension) {
145    *error = "Extension is disabled or has crashed.";
146    return false;
147  }
148  *extension = installed_extension;
149  return true;
150}
151
152}  // namespace
153
154bool GetExtensionFromJSONArgs(
155    base::DictionaryValue* args,
156    const std::string& key,
157    Profile* profile,
158    const extensions::Extension** extension,
159    std::string* error) {
160  return GetExtensionFromJSONArgsHelper(
161      args, key, profile, true /* include_disabled */, extension, error);
162}
163
164bool GetEnabledExtensionFromJSONArgs(
165    base::DictionaryValue* args,
166    const std::string& key,
167    Profile* profile,
168    const extensions::Extension** extension,
169    std::string* error) {
170  return GetExtensionFromJSONArgsHelper(
171      args, key, profile, false /* include_disabled */, extension, error);
172}
173