1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Use of this source code is governed by a BSD-style license that can be
3ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// found in the LICENSE file.
4ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
5ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Implements the Chrome Extensions Debugger API.
6ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
7ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/extensions/extension_debugger_api.h"
8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
9ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include <map>
10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include <set>
11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/json/json_reader.h"
13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/json/json_writer.h"
14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/singleton.h"
15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/string_number_conversions.h"
16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/values.h"
17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/debugger/devtools_client_host.h"
18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/debugger/devtools_manager.h"
19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/extensions/extension_debugger_api_constants.h"
20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/extensions/extension_event_router.h"
21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/extensions/extension_tabs_module.h"
22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/profiles/profile.h"
23ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/common/devtools_messages.h"
25ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/common/extensions/extension.h"
26ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/common/extensions/extension_error_utils.h"
27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/browser/tab_contents/tab_contents.h"
28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_service.h"
29ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennamespace keys = extension_debugger_api_constants;
31ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass ExtensionDevToolsClientHost : public DevToolsClientHost,
33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                    public NotificationObserver {
34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen public:
35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ExtensionDevToolsClientHost(TabContents* tab_contents,
36ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                              const std::string& extension_id,
37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                              int tab_id);
38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ~ExtensionDevToolsClientHost();
40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  bool MatchesContentsAndExtensionId(TabContents* tab_contents,
42ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                     const std::string& extension_id);
43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void Close();
44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void SendMessageToBackend(SendRequestDebuggerFunction* function,
45ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                            const std::string& method,
46ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                            Value* params);
47ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // DevToolsClientHost interface
49ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual void InspectedTabClosing();
50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual void SendMessageToClient(const IPC::Message& msg);
51ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual void TabReplaced(TabContentsWrapper* tab_contents);
52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual void FrameNavigating(const std::string& url) {}
53ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
54ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen private:
55ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // NotificationObserver implementation.
56ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual void Observe(NotificationType type,
57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                       const NotificationSource& source,
58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                       const NotificationDetails& details);
59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void OnDispatchOnInspectorFrontend(const std::string& data);
60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  TabContents* tab_contents_;
62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string extension_id_;
63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int tab_id_;
64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  NotificationRegistrar registrar_;
65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int last_request_id_;
66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  typedef std::map<int, scoped_refptr<SendRequestDebuggerFunction> >
67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      PendingRequests;
68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  PendingRequests pending_requests_;
69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DISALLOW_COPY_AND_ASSIGN(ExtensionDevToolsClientHost);
71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen};
72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennamespace {
74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass AttachedClientHosts {
76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen public:
77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  AttachedClientHosts() {}
78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Returns the singleton instance of this class
80ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  static AttachedClientHosts* GetInstance() {
81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return Singleton<AttachedClientHosts>::get();
82ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
83ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
84ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void Add(ExtensionDevToolsClientHost* client_host) {
85ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    client_hosts_.insert(client_host);
86ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
87ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
88ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void Remove(ExtensionDevToolsClientHost* client_host) {
89ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    client_hosts_.erase(client_host);
90ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
91ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
92ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ExtensionDevToolsClientHost* Lookup(RenderViewHost* rvh) {
93ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DevToolsClientHost* client_host =
94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        DevToolsManager::GetInstance()->GetDevToolsClientHostFor(rvh);
95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    std::set<DevToolsClientHost*>::iterator it =
96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        client_hosts_.find(client_host);
97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (it == client_hosts_.end())
98ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return NULL;
99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return static_cast<ExtensionDevToolsClientHost*>(client_host);
100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen private:
103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::set<DevToolsClientHost*> client_hosts_;
104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen};
105ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}  // namespace
107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenExtensionDevToolsClientHost::ExtensionDevToolsClientHost(
109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    TabContents* tab_contents,
110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const std::string& extension_id,
111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    int tab_id)
112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    : tab_contents_(tab_contents),
113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      extension_id_(extension_id),
114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      tab_id_(tab_id),
115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      last_request_id_(0) {
116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  AttachedClientHosts::GetInstance()->Add(this);
117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Detach from debugger when extension unloads.
119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                 Source<Profile>(tab_contents_->profile()));
121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Attach to debugger and tell it we are ready.
123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DevToolsManager::GetInstance()->RegisterDevToolsClientHostFor(
124ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      tab_contents_->render_view_host(),
125ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      this);
126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DevToolsManager::GetInstance()->ForwardToDevToolsAgent(
127ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      this,
128ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      DevToolsAgentMsg_FrontendLoaded());
129ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenExtensionDevToolsClientHost::~ExtensionDevToolsClientHost() {
132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  AttachedClientHosts::GetInstance()->Remove(this);
133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool ExtensionDevToolsClientHost::MatchesContentsAndExtensionId(
136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    TabContents* tab_contents,
137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const std::string& extension_id) {
138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return tab_contents == tab_contents_ && extension_id_ == extension_id;
139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// DevToolsClientHost interface
142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionDevToolsClientHost::InspectedTabClosing() {
143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Tell extension that this client host has been detached.
144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  Profile* profile = tab_contents_->profile();
145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (profile != NULL && profile->GetExtensionEventRouter()) {
146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ListValue args;
147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    args.Append(Value::CreateIntegerValue(tab_id_));
148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
149ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    std::string json_args;
150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    base::JSONWriter::Write(&args, false, &json_args);
151ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
152ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    profile->GetExtensionEventRouter()->DispatchEventToExtension(
153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        extension_id_, keys::kOnDetach, json_args, profile, GURL());
154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  delete this;
156ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
157ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
158ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionDevToolsClientHost::SendMessageToClient(
159ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const IPC::Message& msg) {
160ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  IPC_BEGIN_MESSAGE_MAP(ExtensionDevToolsClientHost, msg)
161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    IPC_MESSAGE_HANDLER(DevToolsClientMsg_DispatchOnInspectorFrontend,
162ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                        OnDispatchOnInspectorFrontend);
163ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    IPC_MESSAGE_UNHANDLED_ERROR()
164ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  IPC_END_MESSAGE_MAP()
165ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
166ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
167ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionDevToolsClientHost::TabReplaced(
168ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    TabContentsWrapper* tab_contents) {
169ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  tab_contents_ = tab_contents->tab_contents();
170ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
171ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
172ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionDevToolsClientHost::Close() {
173ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DevToolsClientHost::NotifyCloseListener();
174ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  delete this;
175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
176ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionDevToolsClientHost::SendMessageToBackend(
178ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    SendRequestDebuggerFunction* function,
179ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const std::string& method,
180ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    Value* params) {
181ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DictionaryValue protocol_request;
182ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int request_id = ++last_request_id_;
183ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  pending_requests_[request_id] = function;
184ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  protocol_request.SetInteger("id", request_id);
185ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  protocol_request.SetString("method", method);
186ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (params)
187ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    protocol_request.Set("params", params->DeepCopy());
188ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
189ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string json_args;
190ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  base::JSONWriter::Write(&protocol_request, false, &json_args);
191ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DevToolsManager::GetInstance()->ForwardToDevToolsAgent(
192ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      this,
193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      DevToolsAgentMsg_DispatchOnInspectorBackend(json_args));
194ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
196ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionDevToolsClientHost::Observe(
197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    NotificationType type,
198ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const NotificationSource& source,
199ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const NotificationDetails& details) {
200ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(type == NotificationType::EXTENSION_UNLOADED);
201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  Close();
202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
204ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionDevToolsClientHost::OnDispatchOnInspectorFrontend(
205ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const std::string& data) {
206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  Profile* profile = tab_contents_->profile();
207ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (profile == NULL || !profile->GetExtensionEventRouter())
208ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
210ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  scoped_ptr<Value> result(base::JSONReader::Read(data, false));
211ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!result->IsType(Value::TYPE_DICTIONARY))
212ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
213ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DictionaryValue* dictionary = static_cast<DictionaryValue*>(result.get());
214ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int id;
216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!dictionary->GetInteger("id", &id)) {
217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    std::string method_name;
218ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!dictionary->GetString("method", &method_name))
219ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return;
220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
221ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ListValue args;
222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    args.Append(Value::CreateIntegerValue(tab_id_));
223ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    args.Append(Value::CreateStringValue(method_name));
224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    Value* params_value;
225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (dictionary->Get("params", &params_value))
226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      args.Append(params_value->DeepCopy());
227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
228ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    std::string json_args;
229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    base::JSONWriter::Write(&args, false, &json_args);
230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    profile->GetExtensionEventRouter()->DispatchEventToExtension(
232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        extension_id_, keys::kOnEvent, json_args, profile, GURL());
233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else {
234ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    SendRequestDebuggerFunction* function = pending_requests_[id];
235ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!function)
236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return;
237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
238ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    function->SendResponseBody(dictionary);
239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    pending_requests_.erase(id);
240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
243ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenDebuggerFunction::DebuggerFunction()
244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    : contents_(0),
245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      client_host_(0) {
246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
247ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
248ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool DebuggerFunction::InitTabContents(int tab_id) {
249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Find the TabContents that contains this tab id.
250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  contents_ = NULL;
251ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  TabContentsWrapper* wrapper = NULL;
252ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  bool result = ExtensionTabUtil::GetTabById(
253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      tab_id, profile(), include_incognito(), NULL, NULL, &wrapper, NULL);
254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!result || !wrapper) {
255ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    error_ = error_ = ExtensionErrorUtils::FormatErrorMessage(
256ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        keys::kNoTabError,
257ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        base::IntToString(tab_id));
258ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
259ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
260ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  contents_ = wrapper->tab_contents();
261ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return true;
262ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
263ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
264ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool DebuggerFunction::InitClientHost(int tab_id) {
265ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!InitTabContents(tab_id))
266ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
267ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
268ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  RenderViewHost* rvh = contents_->render_view_host();
269ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  client_host_ = AttachedClientHosts::GetInstance()->Lookup(rvh);
270ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
271ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!client_host_ ||
272ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      !client_host_->MatchesContentsAndExtensionId(contents_,
273ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                                   GetExtension()->id())) {
274ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    error_ = ExtensionErrorUtils::FormatErrorMessage(
275ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        keys::kNotAttachedError,
276ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        base::IntToString(tab_id));
277ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
278ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
279ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return true;
280ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
281ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
282ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenAttachDebuggerFunction::AttachDebuggerFunction() {}
283ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
284ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenAttachDebuggerFunction::~AttachDebuggerFunction() {}
285ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
286ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool AttachDebuggerFunction::RunImpl() {
287ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int tab_id;
288ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &tab_id));
289ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
290ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!InitTabContents(tab_id))
291ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
292ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
293ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DevToolsClientHost* client_host = DevToolsManager::GetInstance()->
294ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      GetDevToolsClientHostFor(contents_->render_view_host());
295ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
296ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (client_host != NULL) {
297ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    error_ = ExtensionErrorUtils::FormatErrorMessage(
298ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        keys::kAlreadyAttachedError,
299ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        base::IntToString(tab_id));
300ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
301ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
302ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
303ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  new ExtensionDevToolsClientHost(contents_, GetExtension()->id(), tab_id);
304ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SendResponse(true);
305ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return true;
306ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
307ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
308ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenDetachDebuggerFunction::DetachDebuggerFunction() {}
309ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
310ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenDetachDebuggerFunction::~DetachDebuggerFunction() {}
311ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
312ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool DetachDebuggerFunction::RunImpl() {
313ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int tab_id;
314ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &tab_id));
315ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
316ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!InitClientHost(tab_id))
317ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
318ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
319ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  client_host_->Close();
320ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SendResponse(true);
321ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return true;
322ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
323ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
324ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenSendRequestDebuggerFunction::SendRequestDebuggerFunction() {}
325ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
326ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenSendRequestDebuggerFunction::~SendRequestDebuggerFunction() {}
327ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
328ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool SendRequestDebuggerFunction::RunImpl() {
329ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int tab_id;
330ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &tab_id));
331ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
332ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!InitClientHost(tab_id))
333ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
334ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
335ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string method;
336ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &method));
337ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
338ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  Value *params;
339ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!args_->Get(2, &params))
340ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    params = NULL;
341ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
342ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  client_host_->SendMessageToBackend(this, method, params);
343ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return true;
344ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
345ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
346ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SendRequestDebuggerFunction::SendResponseBody(
347ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DictionaryValue* dictionary) {
348ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  Value* error_body;
349ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (dictionary->Get("error", &error_body)) {
350ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    base::JSONWriter::Write(error_body, false, &error_);
351ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    SendResponse(false);
352ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
353ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
354ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
355ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  Value* result_body;
356ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (dictionary->Get("result", &result_body))
357ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    result_.reset(result_body->DeepCopy());
358ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  else
359ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    result_.reset(new DictionaryValue());
360ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SendResponse(true);
361ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
362