[email protected] | 9f76c1e | 2012-03-05 15:15:58 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | // Implements the Chrome Extensions Debugger API. |
| 6 | |
[email protected] | 1eb8f2f | 2012-07-12 02:04:49 | [diff] [blame] | 7 | #include "chrome/browser/extensions/api/debugger/debugger_api.h" |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 8 | |
[email protected] | ff31a8a | 2011-03-30 14:13:59 | [diff] [blame] | 9 | #include <map> |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 10 | #include <set> |
| 11 | |
[email protected] | 2fefdb3 | 2013-02-26 14:28:10 | [diff] [blame] | 12 | #include "base/command_line.h" |
[email protected] | ff31a8a | 2011-03-30 14:13:59 | [diff] [blame] | 13 | #include "base/json/json_reader.h" |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 14 | #include "base/json/json_writer.h" |
[email protected] | 752960d | 2012-07-23 19:06:11 | [diff] [blame] | 15 | #include "base/memory/scoped_ptr.h" |
[email protected] | 3b63f8f4 | 2011-03-28 01:54:15 | [diff] [blame] | 16 | #include "base/memory/singleton.h" |
[email protected] | 4edaf7ec | 2014-05-07 13:54:15 | [diff] [blame] | 17 | #include "base/scoped_observer.h" |
[email protected] | 06d503f | 2013-10-29 17:29:37 | [diff] [blame] | 18 | #include "base/stl_util.h" |
[email protected] | 3ea1b18 | 2013-02-08 22:38:41 | [diff] [blame] | 19 | #include "base/strings/string_number_conversions.h" |
[email protected] | 135cb80 | 2013-06-09 16:44:20 | [diff] [blame] | 20 | #include "base/strings/utf_string_conversions.h" |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 21 | #include "base/values.h" |
[email protected] | 49a01e64 | 2013-07-12 00:29:45 | [diff] [blame] | 22 | #include "chrome/browser/chrome_notification_types.h" |
[email protected] | 06d503f | 2013-10-29 17:29:37 | [diff] [blame] | 23 | #include "chrome/browser/devtools/devtools_target_impl.h" |
[email protected] | 1eb8f2f | 2012-07-12 02:04:49 | [diff] [blame] | 24 | #include "chrome/browser/extensions/api/debugger/debugger_api_constants.h" |
[email protected] | 2fefdb3 | 2013-02-26 14:28:10 | [diff] [blame] | 25 | #include "chrome/browser/extensions/extension_service.h" |
[email protected] | ac84431b | 2011-09-27 17:26:11 | [diff] [blame] | 26 | #include "chrome/browser/extensions/extension_tab_util.h" |
[email protected] | 4a8adfa0 | 2013-03-19 22:37:46 | [diff] [blame] | 27 | #include "chrome/browser/infobars/infobar_service.h" |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 28 | #include "chrome/browser/profiles/profile.h" |
[email protected] | 863f70a | 2012-01-27 02:05:50 | [diff] [blame] | 29 | #include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h" |
[email protected] | 2fefdb3 | 2013-02-26 14:28:10 | [diff] [blame] | 30 | #include "chrome/common/chrome_switches.h" |
[email protected] | af39f00 | 2014-08-22 10:18:18 | [diff] [blame] | 31 | #include "chrome/grit/generated_resources.h" |
[email protected] | f9b2160 | 2014-05-22 00:53:12 | [diff] [blame] | 32 | #include "components/infobars/core/confirm_infobar_delegate.h" |
[email protected] | 051655ad | 2014-04-18 15:09:41 | [diff] [blame] | 33 | #include "components/infobars/core/infobar.h" |
[email protected] | 98f6611 | 2012-12-25 12:59:36 | [diff] [blame] | 34 | #include "content/public/browser/devtools_agent_host.h" |
[email protected] | be3577e | 2013-06-26 21:42:33 | [diff] [blame] | 35 | #include "content/public/browser/devtools_http_handler.h" |
[email protected] | 1c3bd20 | 2011-12-23 05:48:24 | [diff] [blame] | 36 | #include "content/public/browser/notification_service.h" |
[email protected] | ad50def5 | 2011-10-19 23:17:07 | [diff] [blame] | 37 | #include "content/public/browser/notification_source.h" |
[email protected] | 2fefdb3 | 2013-02-26 14:28:10 | [diff] [blame] | 38 | #include "content/public/browser/render_process_host.h" |
[email protected] | 9c1662b | 2012-03-06 15:44:33 | [diff] [blame] | 39 | #include "content/public/browser/render_view_host.h" |
[email protected] | 2fefdb3 | 2013-02-26 14:28:10 | [diff] [blame] | 40 | #include "content/public/browser/render_widget_host.h" |
[email protected] | ef9572e | 2012-01-04 22:14:12 | [diff] [blame] | 41 | #include "content/public/browser/web_contents.h" |
[email protected] | 744c2a2 | 2012-03-15 18:42:04 | [diff] [blame] | 42 | #include "content/public/common/content_client.h" |
[email protected] | 3b366ae | 2013-05-17 21:16:58 | [diff] [blame] | 43 | #include "content/public/common/url_utils.h" |
[email protected] | 3442353 | 2013-11-21 18:13:10 | [diff] [blame] | 44 | #include "extensions/browser/event_router.h" |
[email protected] | 22401dc | 2014-03-21 01:38:57 | [diff] [blame] | 45 | #include "extensions/browser/extension_host.h" |
[email protected] | 4edaf7ec | 2014-05-07 13:54:15 | [diff] [blame] | 46 | #include "extensions/browser/extension_registry.h" |
| 47 | #include "extensions/browser/extension_registry_observer.h" |
[email protected] | 684a212a | 2014-06-27 17:14:50 | [diff] [blame] | 48 | #include "extensions/common/constants.h" |
[email protected] | e9f541a | 2012-11-19 21:52:31 | [diff] [blame] | 49 | #include "extensions/common/error_utils.h" |
[email protected] | e4452d3 | 2013-11-15 23:07:41 | [diff] [blame] | 50 | #include "extensions/common/extension.h" |
[email protected] | 684a212a | 2014-06-27 17:14:50 | [diff] [blame] | 51 | #include "extensions/common/manifest_constants.h" |
| 52 | #include "extensions/common/permissions/permissions_data.h" |
| 53 | #include "extensions/common/switches.h" |
[email protected] | c99c766 | 2011-12-23 12:05:37 | [diff] [blame] | 54 | #include "ui/base/l10n/l10n_util.h" |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 55 | |
[email protected] | 0e12d7d | 2011-12-01 16:21:44 | [diff] [blame] | 56 | using content::DevToolsAgentHost; |
[email protected] | be3577e | 2013-06-26 21:42:33 | [diff] [blame] | 57 | using content::DevToolsHttpHandler; |
[email protected] | 2fefdb3 | 2013-02-26 14:28:10 | [diff] [blame] | 58 | using content::RenderProcessHost; |
| 59 | using content::RenderViewHost; |
| 60 | using content::RenderWidgetHost; |
[email protected] | 7320a44e | 2012-05-22 17:01:11 | [diff] [blame] | 61 | using content::WebContents; |
[email protected] | 0e12d7d | 2011-12-01 16:21:44 | [diff] [blame] | 62 | |
[email protected] | 1eb8f2f | 2012-07-12 02:04:49 | [diff] [blame] | 63 | namespace keys = debugger_api_constants; |
[email protected] | 752960d | 2012-07-23 19:06:11 | [diff] [blame] | 64 | namespace Attach = extensions::api::debugger::Attach; |
| 65 | namespace Detach = extensions::api::debugger::Detach; |
| 66 | namespace OnDetach = extensions::api::debugger::OnDetach; |
| 67 | namespace OnEvent = extensions::api::debugger::OnEvent; |
| 68 | namespace SendCommand = extensions::api::debugger::SendCommand; |
[email protected] | ef9572e | 2012-01-04 22:14:12 | [diff] [blame] | 69 | |
[email protected] | 4edaf7ec | 2014-05-07 13:54:15 | [diff] [blame] | 70 | namespace extensions { |
| 71 | class ExtensionRegistry; |
[email protected] | 49c71ac | 2013-05-03 01:36:22 | [diff] [blame] | 72 | |
| 73 | // ExtensionDevToolsClientHost ------------------------------------------------ |
| 74 | |
[email protected] | b50452f | 2014-08-18 12:31:44 | [diff] [blame] | 75 | class ExtensionDevToolsClientHost : public content::DevToolsAgentHostClient, |
[email protected] | d32a9265 | 2014-05-09 11:06:15 | [diff] [blame] | 76 | public content::NotificationObserver, |
| 77 | public ExtensionRegistryObserver { |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 78 | public: |
[email protected] | 051655ad | 2014-04-18 15:09:41 | [diff] [blame] | 79 | ExtensionDevToolsClientHost(Profile* profile, |
| 80 | DevToolsAgentHost* agent_host, |
| 81 | const std::string& extension_id, |
| 82 | const std::string& extension_name, |
| 83 | const Debuggee& debuggee, |
| 84 | infobars::InfoBar* infobar); |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 85 | |
dcheng | ae36a4a | 2014-10-21 12:36:36 | [diff] [blame] | 86 | ~ExtensionDevToolsClientHost() override; |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 87 | |
[email protected] | ac3851f | 2013-04-05 15:51:59 | [diff] [blame] | 88 | const std::string& extension_id() { return extension_id_; } |
[email protected] | b50452f | 2014-08-18 12:31:44 | [diff] [blame] | 89 | DevToolsAgentHost* agent_host() { return agent_host_.get(); } |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 90 | void Close(); |
[email protected] | 4636c83 | 2013-01-11 02:10:11 | [diff] [blame] | 91 | void SendMessageToBackend(DebuggerSendCommandFunction* function, |
[email protected] | ac31010 | 2011-04-08 14:08:33 | [diff] [blame] | 92 | const std::string& method, |
[email protected] | 752960d | 2012-07-23 19:06:11 | [diff] [blame] | 93 | SendCommand::Params::CommandParams* command_params); |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 94 | |
[email protected] | b3b2607 | 2012-11-02 11:20:51 | [diff] [blame] | 95 | // Marks connection as to-be-terminated by the user. |
[email protected] | 87d8a63 | 2012-09-20 13:40:39 | [diff] [blame] | 96 | void MarkAsDismissed(); |
| 97 | |
[email protected] | b50452f | 2014-08-18 12:31:44 | [diff] [blame] | 98 | // DevToolsAgentHostClient interface. |
dcheng | ae36a4a | 2014-10-21 12:36:36 | [diff] [blame] | 99 | void AgentHostClosed(DevToolsAgentHost* agent_host, |
| 100 | bool replaced_with_another_client) override; |
| 101 | void DispatchProtocolMessage(DevToolsAgentHost* agent_host, |
| 102 | const std::string& message) override; |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 103 | |
| 104 | private: |
[email protected] | c99c766 | 2011-12-23 12:05:37 | [diff] [blame] | 105 | void SendDetachedEvent(); |
| 106 | |
[email protected] | 6c2381d | 2011-10-19 02:52:53 | [diff] [blame] | 107 | // content::NotificationObserver implementation. |
dcheng | ae36a4a | 2014-10-21 12:36:36 | [diff] [blame] | 108 | void Observe(int type, |
| 109 | const content::NotificationSource& source, |
| 110 | const content::NotificationDetails& details) override; |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 111 | |
[email protected] | d32a9265 | 2014-05-09 11:06:15 | [diff] [blame] | 112 | // ExtensionRegistryObserver implementation. |
dcheng | ae36a4a | 2014-10-21 12:36:36 | [diff] [blame] | 113 | void OnExtensionUnloaded(content::BrowserContext* browser_context, |
| 114 | const Extension* extension, |
| 115 | UnloadedExtensionInfo::Reason reason) override; |
[email protected] | 4edaf7ec | 2014-05-07 13:54:15 | [diff] [blame] | 116 | |
[email protected] | ac3851f | 2013-04-05 15:51:59 | [diff] [blame] | 117 | Profile* profile_; |
| 118 | scoped_refptr<DevToolsAgentHost> agent_host_; |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 119 | std::string extension_id_; |
[email protected] | 2fefdb3 | 2013-02-26 14:28:10 | [diff] [blame] | 120 | Debuggee debuggee_; |
[email protected] | 6c2381d | 2011-10-19 02:52:53 | [diff] [blame] | 121 | content::NotificationRegistrar registrar_; |
[email protected] | ff31a8a | 2011-03-30 14:13:59 | [diff] [blame] | 122 | int last_request_id_; |
[email protected] | 4636c83 | 2013-01-11 02:10:11 | [diff] [blame] | 123 | typedef std::map<int, scoped_refptr<DebuggerSendCommandFunction> > |
[email protected] | ff31a8a | 2011-03-30 14:13:59 | [diff] [blame] | 124 | PendingRequests; |
| 125 | PendingRequests pending_requests_; |
[email protected] | 051655ad | 2014-04-18 15:09:41 | [diff] [blame] | 126 | infobars::InfoBar* infobar_; |
rdevlin.cronin | 00f1fc2 | 2015-04-06 17:19:18 | [diff] [blame^] | 127 | api::debugger::DetachReason detach_reason_; |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 128 | |
[email protected] | 4edaf7ec | 2014-05-07 13:54:15 | [diff] [blame] | 129 | // Listen to extension unloaded notification. |
[email protected] | d32a9265 | 2014-05-09 11:06:15 | [diff] [blame] | 130 | ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver> |
[email protected] | 4edaf7ec | 2014-05-07 13:54:15 | [diff] [blame] | 131 | extension_registry_observer_; |
| 132 | |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 133 | DISALLOW_COPY_AND_ASSIGN(ExtensionDevToolsClientHost); |
| 134 | }; |
| 135 | |
[email protected] | 19bcf9d | 2013-07-18 22:00:59 | [diff] [blame] | 136 | // The member function declarations come after the other class declarations, so |
| 137 | // they can call members on them. |
| 138 | |
| 139 | |
| 140 | namespace { |
| 141 | |
| 142 | // Helpers -------------------------------------------------------------------- |
| 143 | |
| 144 | void CopyDebuggee(Debuggee* dst, const Debuggee& src) { |
| 145 | if (src.tab_id) |
| 146 | dst->tab_id.reset(new int(*src.tab_id)); |
| 147 | if (src.extension_id) |
| 148 | dst->extension_id.reset(new std::string(*src.extension_id)); |
| 149 | if (src.target_id) |
| 150 | dst->target_id.reset(new std::string(*src.target_id)); |
| 151 | } |
| 152 | |
[email protected] | 49c71ac | 2013-05-03 01:36:22 | [diff] [blame] | 153 | |
| 154 | // ExtensionDevToolsInfoBarDelegate ------------------------------------------- |
| 155 | |
[email protected] | da0ade7 | 2013-04-30 01:02:53 | [diff] [blame] | 156 | class ExtensionDevToolsInfoBarDelegate : public ConfirmInfoBarDelegate { |
| 157 | public: |
[email protected] | 39308cb | 2013-12-06 03:01:48 | [diff] [blame] | 158 | // Creates an extension dev tools infobar and delegate and adds the infobar to |
| 159 | // the InfoBarService associated with |rvh|. Returns the infobar if it was |
[email protected] | 19bcf9d | 2013-07-18 22:00:59 | [diff] [blame] | 160 | // successfully added. |
[email protected] | b3f957e6 | 2014-08-08 10:09:02 | [diff] [blame] | 161 | static infobars::InfoBar* Create(WebContents* web_contents, |
[email protected] | 051655ad | 2014-04-18 15:09:41 | [diff] [blame] | 162 | const std::string& client_name); |
[email protected] | da0ade7 | 2013-04-30 01:02:53 | [diff] [blame] | 163 | |
[email protected] | 28b05ef0 | 2013-07-10 22:28:32 | [diff] [blame] | 164 | void set_client_host(ExtensionDevToolsClientHost* client_host) { |
| 165 | client_host_ = client_host; |
| 166 | } |
[email protected] | da0ade7 | 2013-04-30 01:02:53 | [diff] [blame] | 167 | |
| 168 | private: |
[email protected] | 39308cb | 2013-12-06 03:01:48 | [diff] [blame] | 169 | explicit ExtensionDevToolsInfoBarDelegate(const std::string& client_name); |
dcheng | ae36a4a | 2014-10-21 12:36:36 | [diff] [blame] | 170 | ~ExtensionDevToolsInfoBarDelegate() override; |
[email protected] | da0ade7 | 2013-04-30 01:02:53 | [diff] [blame] | 171 | |
| 172 | // ConfirmInfoBarDelegate: |
dcheng | ae36a4a | 2014-10-21 12:36:36 | [diff] [blame] | 173 | Type GetInfoBarType() const override; |
pkasting | bdbf3b1 | 2015-02-24 00:18:27 | [diff] [blame] | 174 | void InfoBarDismissed() override; |
dcheng | ae36a4a | 2014-10-21 12:36:36 | [diff] [blame] | 175 | bool ShouldExpireInternal(const NavigationDetails& details) const override; |
| 176 | base::string16 GetMessageText() const override; |
| 177 | int GetButtons() const override; |
| 178 | bool Cancel() override; |
[email protected] | da0ade7 | 2013-04-30 01:02:53 | [diff] [blame] | 179 | |
| 180 | std::string client_name_; |
| 181 | ExtensionDevToolsClientHost* client_host_; |
[email protected] | 49c71ac | 2013-05-03 01:36:22 | [diff] [blame] | 182 | |
[email protected] | da0ade7 | 2013-04-30 01:02:53 | [diff] [blame] | 183 | DISALLOW_COPY_AND_ASSIGN(ExtensionDevToolsInfoBarDelegate); |
| 184 | }; |
| 185 | |
| 186 | // static |
[email protected] | 051655ad | 2014-04-18 15:09:41 | [diff] [blame] | 187 | infobars::InfoBar* ExtensionDevToolsInfoBarDelegate::Create( |
[email protected] | b3f957e6 | 2014-08-08 10:09:02 | [diff] [blame] | 188 | WebContents* web_contents, |
[email protected] | da0ade7 | 2013-04-30 01:02:53 | [diff] [blame] | 189 | const std::string& client_name) { |
[email protected] | da0ade7 | 2013-04-30 01:02:53 | [diff] [blame] | 190 | if (!web_contents) |
| 191 | return NULL; |
| 192 | |
| 193 | InfoBarService* infobar_service = |
| 194 | InfoBarService::FromWebContents(web_contents); |
| 195 | if (!infobar_service) |
| 196 | return NULL; |
| 197 | |
sdefresne | 316da45 | 2014-12-22 17:30:59 | [diff] [blame] | 198 | return infobar_service->AddInfoBar( |
| 199 | infobar_service->CreateConfirmInfoBar(scoped_ptr<ConfirmInfoBarDelegate>( |
[email protected] | 39308cb | 2013-12-06 03:01:48 | [diff] [blame] | 200 | new ExtensionDevToolsInfoBarDelegate(client_name)))); |
[email protected] | da0ade7 | 2013-04-30 01:02:53 | [diff] [blame] | 201 | } |
| 202 | |
[email protected] | da0ade7 | 2013-04-30 01:02:53 | [diff] [blame] | 203 | ExtensionDevToolsInfoBarDelegate::ExtensionDevToolsInfoBarDelegate( |
[email protected] | da0ade7 | 2013-04-30 01:02:53 | [diff] [blame] | 204 | const std::string& client_name) |
[email protected] | 39308cb | 2013-12-06 03:01:48 | [diff] [blame] | 205 | : ConfirmInfoBarDelegate(), |
[email protected] | da0ade7 | 2013-04-30 01:02:53 | [diff] [blame] | 206 | client_name_(client_name), |
| 207 | client_host_(NULL) { |
| 208 | } |
| 209 | |
| 210 | ExtensionDevToolsInfoBarDelegate::~ExtensionDevToolsInfoBarDelegate() { |
| 211 | } |
| 212 | |
[email protected] | 051655ad | 2014-04-18 15:09:41 | [diff] [blame] | 213 | infobars::InfoBarDelegate::Type |
| 214 | ExtensionDevToolsInfoBarDelegate::GetInfoBarType() const { |
[email protected] | da0ade7 | 2013-04-30 01:02:53 | [diff] [blame] | 215 | return WARNING_TYPE; |
| 216 | } |
| 217 | |
pkasting | bdbf3b1 | 2015-02-24 00:18:27 | [diff] [blame] | 218 | void ExtensionDevToolsInfoBarDelegate::InfoBarDismissed() { |
| 219 | if (client_host_) |
| 220 | client_host_->MarkAsDismissed(); |
| 221 | } |
| 222 | |
[email protected] | da0ade7 | 2013-04-30 01:02:53 | [diff] [blame] | 223 | bool ExtensionDevToolsInfoBarDelegate::ShouldExpireInternal( |
[email protected] | 5daf1d9 | 2014-04-04 15:52:13 | [diff] [blame] | 224 | const NavigationDetails& details) const { |
[email protected] | da0ade7 | 2013-04-30 01:02:53 | [diff] [blame] | 225 | return false; |
| 226 | } |
| 227 | |
[email protected] | 6a72a63 | 2013-12-12 22:22:00 | [diff] [blame] | 228 | base::string16 ExtensionDevToolsInfoBarDelegate::GetMessageText() const { |
[email protected] | da0ade7 | 2013-04-30 01:02:53 | [diff] [blame] | 229 | return l10n_util::GetStringFUTF16(IDS_DEV_TOOLS_INFOBAR_LABEL, |
[email protected] | 0433872 | 2013-12-24 23:18:05 | [diff] [blame] | 230 | base::UTF8ToUTF16(client_name_)); |
[email protected] | da0ade7 | 2013-04-30 01:02:53 | [diff] [blame] | 231 | } |
| 232 | |
[email protected] | d5a4c9ef | 2013-04-30 03:05:24 | [diff] [blame] | 233 | int ExtensionDevToolsInfoBarDelegate::GetButtons() const { |
| 234 | return BUTTON_CANCEL; |
[email protected] | da0ade7 | 2013-04-30 01:02:53 | [diff] [blame] | 235 | } |
| 236 | |
| 237 | bool ExtensionDevToolsInfoBarDelegate::Cancel() { |
[email protected] | 19bcf9d | 2013-07-18 22:00:59 | [diff] [blame] | 238 | InfoBarDismissed(); |
[email protected] | da0ade7 | 2013-04-30 01:02:53 | [diff] [blame] | 239 | return true; |
| 240 | } |
| 241 | |
[email protected] | 49c71ac | 2013-05-03 01:36:22 | [diff] [blame] | 242 | |
[email protected] | 49c71ac | 2013-05-03 01:36:22 | [diff] [blame] | 243 | // AttachedClientHosts -------------------------------------------------------- |
| 244 | |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 245 | class AttachedClientHosts { |
| 246 | public: |
[email protected] | 49c71ac | 2013-05-03 01:36:22 | [diff] [blame] | 247 | AttachedClientHosts(); |
[email protected] | 28b05ef0 | 2013-07-10 22:28:32 | [diff] [blame] | 248 | ~AttachedClientHosts(); |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 249 | |
[email protected] | 28b05ef0 | 2013-07-10 22:28:32 | [diff] [blame] | 250 | // Returns the singleton instance of this class. |
[email protected] | 49c71ac | 2013-05-03 01:36:22 | [diff] [blame] | 251 | static AttachedClientHosts* GetInstance(); |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 252 | |
[email protected] | 49c71ac | 2013-05-03 01:36:22 | [diff] [blame] | 253 | void Add(ExtensionDevToolsClientHost* client_host); |
| 254 | void Remove(ExtensionDevToolsClientHost* client_host); |
[email protected] | ac3851f | 2013-04-05 15:51:59 | [diff] [blame] | 255 | ExtensionDevToolsClientHost* Lookup(DevToolsAgentHost* agent_host, |
[email protected] | 49c71ac | 2013-05-03 01:36:22 | [diff] [blame] | 256 | const std::string& extension_id); |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 257 | |
| 258 | private: |
[email protected] | 28b05ef0 | 2013-07-10 22:28:32 | [diff] [blame] | 259 | typedef std::set<ExtensionDevToolsClientHost*> ClientHosts; |
| 260 | ClientHosts client_hosts_; |
[email protected] | 49c71ac | 2013-05-03 01:36:22 | [diff] [blame] | 261 | |
| 262 | DISALLOW_COPY_AND_ASSIGN(AttachedClientHosts); |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 263 | }; |
| 264 | |
[email protected] | 49c71ac | 2013-05-03 01:36:22 | [diff] [blame] | 265 | AttachedClientHosts::AttachedClientHosts() { |
| 266 | } |
| 267 | |
[email protected] | 28b05ef0 | 2013-07-10 22:28:32 | [diff] [blame] | 268 | AttachedClientHosts::~AttachedClientHosts() { |
| 269 | } |
[email protected] | 19bcf9d | 2013-07-18 22:00:59 | [diff] [blame] | 270 | |
[email protected] | 49c71ac | 2013-05-03 01:36:22 | [diff] [blame] | 271 | // static |
| 272 | AttachedClientHosts* AttachedClientHosts::GetInstance() { |
| 273 | return Singleton<AttachedClientHosts>::get(); |
| 274 | } |
| 275 | |
| 276 | void AttachedClientHosts::Add(ExtensionDevToolsClientHost* client_host) { |
| 277 | client_hosts_.insert(client_host); |
| 278 | } |
| 279 | |
| 280 | void AttachedClientHosts::Remove(ExtensionDevToolsClientHost* client_host) { |
| 281 | client_hosts_.erase(client_host); |
| 282 | } |
| 283 | |
| 284 | ExtensionDevToolsClientHost* AttachedClientHosts::Lookup( |
| 285 | DevToolsAgentHost* agent_host, |
| 286 | const std::string& extension_id) { |
[email protected] | 28b05ef0 | 2013-07-10 22:28:32 | [diff] [blame] | 287 | for (ClientHosts::iterator it = client_hosts_.begin(); |
[email protected] | 49c71ac | 2013-05-03 01:36:22 | [diff] [blame] | 288 | it != client_hosts_.end(); ++it) { |
| 289 | ExtensionDevToolsClientHost* client_host = *it; |
[email protected] | b50452f | 2014-08-18 12:31:44 | [diff] [blame] | 290 | if (client_host->agent_host() == agent_host && |
[email protected] | 49c71ac | 2013-05-03 01:36:22 | [diff] [blame] | 291 | client_host->extension_id() == extension_id) |
| 292 | return client_host; |
| 293 | } |
| 294 | return NULL; |
| 295 | } |
| 296 | |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 297 | } // namespace |
| 298 | |
[email protected] | 49c71ac | 2013-05-03 01:36:22 | [diff] [blame] | 299 | |
| 300 | // ExtensionDevToolsClientHost ------------------------------------------------ |
| 301 | |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 302 | ExtensionDevToolsClientHost::ExtensionDevToolsClientHost( |
[email protected] | ac3851f | 2013-04-05 15:51:59 | [diff] [blame] | 303 | Profile* profile, |
| 304 | DevToolsAgentHost* agent_host, |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 305 | const std::string& extension_id, |
[email protected] | c99c766 | 2011-12-23 12:05:37 | [diff] [blame] | 306 | const std::string& extension_name, |
[email protected] | 56cc3804 | 2013-04-03 04:42:47 | [diff] [blame] | 307 | const Debuggee& debuggee, |
[email protected] | 051655ad | 2014-04-18 15:09:41 | [diff] [blame] | 308 | infobars::InfoBar* infobar) |
[email protected] | ac3851f | 2013-04-05 15:51:59 | [diff] [blame] | 309 | : profile_(profile), |
| 310 | agent_host_(agent_host), |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 311 | extension_id_(extension_id), |
[email protected] | c99c766 | 2011-12-23 12:05:37 | [diff] [blame] | 312 | last_request_id_(0), |
[email protected] | 97efae6 | 2013-07-18 22:08:14 | [diff] [blame] | 313 | infobar_(infobar), |
rdevlin.cronin | 00f1fc2 | 2015-04-06 17:19:18 | [diff] [blame^] | 314 | detach_reason_(api::debugger::DETACH_REASON_TARGET_CLOSED), |
[email protected] | 4edaf7ec | 2014-05-07 13:54:15 | [diff] [blame] | 315 | extension_registry_observer_(this) { |
[email protected] | 28b05ef0 | 2013-07-10 22:28:32 | [diff] [blame] | 316 | CopyDebuggee(&debuggee_, debuggee); |
[email protected] | 2fefdb3 | 2013-02-26 14:28:10 | [diff] [blame] | 317 | |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 318 | AttachedClientHosts::GetInstance()->Add(this); |
| 319 | |
[email protected] | 4edaf7ec | 2014-05-07 13:54:15 | [diff] [blame] | 320 | // ExtensionRegistryObserver listen extension unloaded and detach debugger |
| 321 | // from there. |
[email protected] | d32a9265 | 2014-05-09 11:06:15 | [diff] [blame] | 322 | extension_registry_observer_.Add(ExtensionRegistry::Get(profile_)); |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 323 | |
[email protected] | 02ff8ad | 2013-04-12 13:54:35 | [diff] [blame] | 324 | // RVH-based agents disconnect from their clients when the app is terminating |
| 325 | // but shared worker-based agents do not. |
| 326 | // Disconnect explicitly to make sure that |this| observer is not leaked. |
| 327 | registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING, |
| 328 | content::NotificationService::AllSources()); |
| 329 | |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 330 | // Attach to debugger and tell it we are ready. |
[email protected] | b50452f | 2014-08-18 12:31:44 | [diff] [blame] | 331 | agent_host_->AttachClient(this); |
[email protected] | c99c766 | 2011-12-23 12:05:37 | [diff] [blame] | 332 | |
[email protected] | 97efae6 | 2013-07-18 22:08:14 | [diff] [blame] | 333 | if (infobar_) { |
[email protected] | 39308cb | 2013-12-06 03:01:48 | [diff] [blame] | 334 | static_cast<ExtensionDevToolsInfoBarDelegate*>( |
| 335 | infobar_->delegate())->set_client_host(this); |
[email protected] | 33fb320 | 2013-04-25 00:20:49 | [diff] [blame] | 336 | registrar_.Add( |
[email protected] | b3f957e6 | 2014-08-08 10:09:02 | [diff] [blame] | 337 | this, |
| 338 | chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, |
| 339 | content::Source<InfoBarService>( |
| 340 | InfoBarService::FromWebContents(agent_host_->GetWebContents()))); |
[email protected] | bde1160 | 2012-05-04 19:05:42 | [diff] [blame] | 341 | } |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 342 | } |
| 343 | |
| 344 | ExtensionDevToolsClientHost::~ExtensionDevToolsClientHost() { |
[email protected] | bde1160 | 2012-05-04 19:05:42 | [diff] [blame] | 345 | // Ensure calling RemoveInfoBar() below won't result in Observe() trying to |
| 346 | // Close() us. |
| 347 | registrar_.RemoveAll(); |
| 348 | |
[email protected] | 97efae6 | 2013-07-18 22:08:14 | [diff] [blame] | 349 | if (infobar_) { |
[email protected] | 39308cb | 2013-12-06 03:01:48 | [diff] [blame] | 350 | static_cast<ExtensionDevToolsInfoBarDelegate*>( |
| 351 | infobar_->delegate())->set_client_host(NULL); |
[email protected] | b3f957e6 | 2014-08-08 10:09:02 | [diff] [blame] | 352 | InfoBarService* infobar_service = |
| 353 | InfoBarService::FromWebContents(agent_host_->GetWebContents()); |
[email protected] | b44f1d3 | 2014-04-10 13:53:26 | [diff] [blame] | 354 | infobar_service->RemoveInfoBar(infobar_); |
[email protected] | c99c766 | 2011-12-23 12:05:37 | [diff] [blame] | 355 | } |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 356 | AttachedClientHosts::GetInstance()->Remove(this); |
| 357 | } |
| 358 | |
[email protected] | b50452f | 2014-08-18 12:31:44 | [diff] [blame] | 359 | // DevToolsAgentHostClient implementation. |
| 360 | void ExtensionDevToolsClientHost::AgentHostClosed( |
| 361 | DevToolsAgentHost* agent_host, bool replaced_with_another_client) { |
| 362 | DCHECK(agent_host == agent_host_.get()); |
| 363 | if (replaced_with_another_client) |
rdevlin.cronin | 00f1fc2 | 2015-04-06 17:19:18 | [diff] [blame^] | 364 | detach_reason_ = api::debugger::DETACH_REASON_REPLACED_WITH_DEVTOOLS; |
[email protected] | c99c766 | 2011-12-23 12:05:37 | [diff] [blame] | 365 | SendDetachedEvent(); |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 366 | delete this; |
| 367 | } |
| 368 | |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 369 | void ExtensionDevToolsClientHost::Close() { |
[email protected] | b50452f | 2014-08-18 12:31:44 | [diff] [blame] | 370 | agent_host_->DetachClient(); |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 371 | delete this; |
| 372 | } |
| 373 | |
| 374 | void ExtensionDevToolsClientHost::SendMessageToBackend( |
[email protected] | 4636c83 | 2013-01-11 02:10:11 | [diff] [blame] | 375 | DebuggerSendCommandFunction* function, |
[email protected] | ac31010 | 2011-04-08 14:08:33 | [diff] [blame] | 376 | const std::string& method, |
[email protected] | 752960d | 2012-07-23 19:06:11 | [diff] [blame] | 377 | SendCommand::Params::CommandParams* command_params) { |
[email protected] | aeca23f | 2013-06-21 22:34:41 | [diff] [blame] | 378 | base::DictionaryValue protocol_request; |
[email protected] | ff31a8a | 2011-03-30 14:13:59 | [diff] [blame] | 379 | int request_id = ++last_request_id_; |
| 380 | pending_requests_[request_id] = function; |
[email protected] | ac31010 | 2011-04-08 14:08:33 | [diff] [blame] | 381 | protocol_request.SetInteger("id", request_id); |
| 382 | protocol_request.SetString("method", method); |
[email protected] | 752960d | 2012-07-23 19:06:11 | [diff] [blame] | 383 | if (command_params) { |
| 384 | protocol_request.Set("params", |
| 385 | command_params->additional_properties.DeepCopy()); |
| 386 | } |
[email protected] | ff31a8a | 2011-03-30 14:13:59 | [diff] [blame] | 387 | |
| 388 | std::string json_args; |
[email protected] | 4abb460 | 2012-03-16 01:59:55 | [diff] [blame] | 389 | base::JSONWriter::Write(&protocol_request, &json_args); |
[email protected] | b50452f | 2014-08-18 12:31:44 | [diff] [blame] | 390 | agent_host_->DispatchProtocolMessage(json_args); |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 391 | } |
| 392 | |
[email protected] | 87d8a63 | 2012-09-20 13:40:39 | [diff] [blame] | 393 | void ExtensionDevToolsClientHost::MarkAsDismissed() { |
rdevlin.cronin | 00f1fc2 | 2015-04-06 17:19:18 | [diff] [blame^] | 394 | detach_reason_ = api::debugger::DETACH_REASON_CANCELED_BY_USER; |
[email protected] | 87d8a63 | 2012-09-20 13:40:39 | [diff] [blame] | 395 | } |
| 396 | |
[email protected] | c99c766 | 2011-12-23 12:05:37 | [diff] [blame] | 397 | void ExtensionDevToolsClientHost::SendDetachedEvent() { |
[email protected] | d32a9265 | 2014-05-09 11:06:15 | [diff] [blame] | 398 | if (!EventRouter::Get(profile_)) |
[email protected] | ac3851f | 2013-04-05 15:51:59 | [diff] [blame] | 399 | return; |
| 400 | |
| 401 | scoped_ptr<base::ListValue> args(OnDetach::Create(debuggee_, |
| 402 | detach_reason_)); |
[email protected] | d32a9265 | 2014-05-09 11:06:15 | [diff] [blame] | 403 | scoped_ptr<Event> event(new Event(OnDetach::kEventName, args.Pass())); |
[email protected] | 45fd9417 | 2013-11-13 03:29:52 | [diff] [blame] | 404 | event->restrict_to_browser_context = profile_; |
[email protected] | d32a9265 | 2014-05-09 11:06:15 | [diff] [blame] | 405 | EventRouter::Get(profile_) |
[email protected] | 9b448320 | 2014-04-18 10:26:40 | [diff] [blame] | 406 | ->DispatchEventToExtension(extension_id_, event.Pass()); |
[email protected] | c99c766 | 2011-12-23 12:05:37 | [diff] [blame] | 407 | } |
| 408 | |
[email protected] | 4edaf7ec | 2014-05-07 13:54:15 | [diff] [blame] | 409 | void ExtensionDevToolsClientHost::OnExtensionUnloaded( |
| 410 | content::BrowserContext* browser_context, |
[email protected] | d32a9265 | 2014-05-09 11:06:15 | [diff] [blame] | 411 | const Extension* extension, |
| 412 | UnloadedExtensionInfo::Reason reason) { |
[email protected] | 4edaf7ec | 2014-05-07 13:54:15 | [diff] [blame] | 413 | if (extension->id() == extension_id_) |
| 414 | Close(); |
| 415 | } |
| 416 | |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 417 | void ExtensionDevToolsClientHost::Observe( |
[email protected] | 43211582 | 2011-07-10 15:52:27 | [diff] [blame] | 418 | int type, |
[email protected] | 6c2381d | 2011-10-19 02:52:53 | [diff] [blame] | 419 | const content::NotificationSource& source, |
| 420 | const content::NotificationDetails& details) { |
[email protected] | 4edaf7ec | 2014-05-07 13:54:15 | [diff] [blame] | 421 | switch (type) { |
| 422 | case chrome::NOTIFICATION_APP_TERMINATING: |
[email protected] | 02ff8ad | 2013-04-12 13:54:35 | [diff] [blame] | 423 | Close(); |
[email protected] | 4edaf7ec | 2014-05-07 13:54:15 | [diff] [blame] | 424 | break; |
| 425 | case chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED: |
| 426 | if (content::Details<infobars::InfoBar::RemovedDetails>(details)->first == |
| 427 | infobar_) { |
| 428 | infobar_ = NULL; |
| 429 | SendDetachedEvent(); |
| 430 | Close(); |
| 431 | } |
| 432 | break; |
| 433 | default: |
| 434 | NOTREACHED(); |
[email protected] | bde1160 | 2012-05-04 19:05:42 | [diff] [blame] | 435 | } |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 436 | } |
| 437 | |
[email protected] | b50452f | 2014-08-18 12:31:44 | [diff] [blame] | 438 | void ExtensionDevToolsClientHost::DispatchProtocolMessage( |
| 439 | DevToolsAgentHost* agent_host, const std::string& message) { |
| 440 | DCHECK(agent_host == agent_host_.get()); |
[email protected] | d32a9265 | 2014-05-09 11:06:15 | [diff] [blame] | 441 | if (!EventRouter::Get(profile_)) |
[email protected] | ff31a8a | 2011-03-30 14:13:59 | [diff] [blame] | 442 | return; |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 443 | |
[email protected] | 5bcdd99d | 2013-12-23 18:28:30 | [diff] [blame] | 444 | scoped_ptr<base::Value> result(base::JSONReader::Read(message)); |
| 445 | if (!result->IsType(base::Value::TYPE_DICTIONARY)) |
[email protected] | ff31a8a | 2011-03-30 14:13:59 | [diff] [blame] | 446 | return; |
[email protected] | aeca23f | 2013-06-21 22:34:41 | [diff] [blame] | 447 | base::DictionaryValue* dictionary = |
| 448 | static_cast<base::DictionaryValue*>(result.get()); |
[email protected] | ff31a8a | 2011-03-30 14:13:59 | [diff] [blame] | 449 | |
[email protected] | ac31010 | 2011-04-08 14:08:33 | [diff] [blame] | 450 | int id; |
| 451 | if (!dictionary->GetInteger("id", &id)) { |
| 452 | std::string method_name; |
| 453 | if (!dictionary->GetString("method", &method_name)) |
[email protected] | 7d713ec | 2011-04-01 14:22:02 | [diff] [blame] | 454 | return; |
| 455 | |
[email protected] | 752960d | 2012-07-23 19:06:11 | [diff] [blame] | 456 | OnEvent::Params params; |
[email protected] | aeca23f | 2013-06-21 22:34:41 | [diff] [blame] | 457 | base::DictionaryValue* params_value; |
[email protected] | 752960d | 2012-07-23 19:06:11 | [diff] [blame] | 458 | if (dictionary->GetDictionary("params", ¶ms_value)) |
| 459 | params.additional_properties.Swap(params_value); |
| 460 | |
[email protected] | 5bcdd99d | 2013-12-23 18:28:30 | [diff] [blame] | 461 | scoped_ptr<base::ListValue> args( |
| 462 | OnEvent::Create(debuggee_, method_name, params)); |
[email protected] | d32a9265 | 2014-05-09 11:06:15 | [diff] [blame] | 463 | scoped_ptr<Event> event(new Event(OnEvent::kEventName, args.Pass())); |
[email protected] | 45fd9417 | 2013-11-13 03:29:52 | [diff] [blame] | 464 | event->restrict_to_browser_context = profile_; |
[email protected] | d32a9265 | 2014-05-09 11:06:15 | [diff] [blame] | 465 | EventRouter::Get(profile_) |
[email protected] | 9b448320 | 2014-04-18 10:26:40 | [diff] [blame] | 466 | ->DispatchEventToExtension(extension_id_, event.Pass()); |
[email protected] | ac31010 | 2011-04-08 14:08:33 | [diff] [blame] | 467 | } else { |
[email protected] | dc24976f | 2013-06-02 21:15:09 | [diff] [blame] | 468 | DebuggerSendCommandFunction* function = pending_requests_[id].get(); |
[email protected] | ac31010 | 2011-04-08 14:08:33 | [diff] [blame] | 469 | if (!function) |
| 470 | return; |
| 471 | |
| 472 | function->SendResponseBody(dictionary); |
| 473 | pending_requests_.erase(id); |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 474 | } |
| 475 | } |
| 476 | |
[email protected] | 49c71ac | 2013-05-03 01:36:22 | [diff] [blame] | 477 | |
| 478 | // DebuggerFunction ----------------------------------------------------------- |
| 479 | |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 480 | DebuggerFunction::DebuggerFunction() |
[email protected] | 19bcf9d | 2013-07-18 22:00:59 | [diff] [blame] | 481 | : client_host_(NULL) { |
[email protected] | ac3851f | 2013-04-05 15:51:59 | [diff] [blame] | 482 | } |
| 483 | |
| 484 | DebuggerFunction::~DebuggerFunction() { |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 485 | } |
| 486 | |
[email protected] | 2fefdb3 | 2013-02-26 14:28:10 | [diff] [blame] | 487 | void DebuggerFunction::FormatErrorMessage(const std::string& format) { |
[email protected] | 56cc3804 | 2013-04-03 04:42:47 | [diff] [blame] | 488 | if (debuggee_.tab_id) |
| 489 | error_ = ErrorUtils::FormatErrorMessage( |
| 490 | format, keys::kTabTargetType, base::IntToString(*debuggee_.tab_id)); |
| 491 | else if (debuggee_.extension_id) |
| 492 | error_ = ErrorUtils::FormatErrorMessage( |
| 493 | format, keys::kBackgroundPageTargetType, *debuggee_.extension_id); |
| 494 | else |
| 495 | error_ = ErrorUtils::FormatErrorMessage( |
| 496 | format, keys::kOpaqueTargetType, *debuggee_.target_id); |
[email protected] | 2fefdb3 | 2013-02-26 14:28:10 | [diff] [blame] | 497 | } |
| 498 | |
[email protected] | ac3851f | 2013-04-05 15:51:59 | [diff] [blame] | 499 | bool DebuggerFunction::InitAgentHost() { |
[email protected] | 2fefdb3 | 2013-02-26 14:28:10 | [diff] [blame] | 500 | if (debuggee_.tab_id) { |
| 501 | WebContents* web_contents = NULL; |
[email protected] | d32a9265 | 2014-05-09 11:06:15 | [diff] [blame] | 502 | bool result = ExtensionTabUtil::GetTabById(*debuggee_.tab_id, |
| 503 | GetProfile(), |
| 504 | include_incognito(), |
| 505 | NULL, |
| 506 | NULL, |
| 507 | &web_contents, |
| 508 | NULL); |
[email protected] | 56cc3804 | 2013-04-03 04:42:47 | [diff] [blame] | 509 | if (result && web_contents) { |
[email protected] | 684a212a | 2014-06-27 17:14:50 | [diff] [blame] | 510 | // TODO(rdevlin.cronin) This should definitely be GetLastCommittedURL(). |
| 511 | GURL url = web_contents->GetVisibleURL(); |
[email protected] | eba8f7d | 2014-07-28 22:09:23 | [diff] [blame] | 512 | if (PermissionsData::IsRestrictedUrl(url, url, extension(), &error_)) |
[email protected] | 56cc3804 | 2013-04-03 04:42:47 | [diff] [blame] | 513 | return false; |
[email protected] | 02a67fd | 2014-03-28 15:29:55 | [diff] [blame] | 514 | agent_host_ = DevToolsAgentHost::GetOrCreateFor(web_contents); |
[email protected] | 2fefdb3 | 2013-02-26 14:28:10 | [diff] [blame] | 515 | } |
[email protected] | 56cc3804 | 2013-04-03 04:42:47 | [diff] [blame] | 516 | } else if (debuggee_.extension_id) { |
[email protected] | d32a9265 | 2014-05-09 11:06:15 | [diff] [blame] | 517 | ExtensionHost* extension_host = |
reillyg | 0ea3fa90 | 2014-10-28 15:30:23 | [diff] [blame] | 518 | ProcessManager::Get(GetProfile()) |
[email protected] | 21a4008 | 2013-10-28 21:19:23 | [diff] [blame] | 519 | ->GetBackgroundHostForExtension(*debuggee_.extension_id); |
[email protected] | 56cc3804 | 2013-04-03 04:42:47 | [diff] [blame] | 520 | if (extension_host) { |
[email protected] | 684a212a | 2014-06-27 17:14:50 | [diff] [blame] | 521 | if (PermissionsData::IsRestrictedUrl(extension_host->GetURL(), |
| 522 | extension_host->GetURL(), |
[email protected] | eba8f7d | 2014-07-28 22:09:23 | [diff] [blame] | 523 | extension(), |
[email protected] | 684a212a | 2014-06-27 17:14:50 | [diff] [blame] | 524 | &error_)) { |
| 525 | return false; |
| 526 | } |
[email protected] | b3f957e6 | 2014-08-08 10:09:02 | [diff] [blame] | 527 | agent_host_ = |
| 528 | DevToolsAgentHost::GetOrCreateFor(extension_host->host_contents()); |
[email protected] | 30e246b | 2013-03-28 17:08:48 | [diff] [blame] | 529 | } |
[email protected] | 56cc3804 | 2013-04-03 04:42:47 | [diff] [blame] | 530 | } else if (debuggee_.target_id) { |
[email protected] | ac3851f | 2013-04-05 15:51:59 | [diff] [blame] | 531 | agent_host_ = DevToolsAgentHost::GetForId(*debuggee_.target_id); |
rob | 409bf9d6 | 2015-02-10 23:37:07 | [diff] [blame] | 532 | if (agent_host_.get()) { |
| 533 | if (PermissionsData::IsRestrictedUrl(agent_host_->GetURL(), |
| 534 | agent_host_->GetURL(), |
| 535 | extension(), |
| 536 | &error_)) { |
| 537 | agent_host_ = nullptr; |
| 538 | return false; |
| 539 | } |
| 540 | } |
[email protected] | 56cc3804 | 2013-04-03 04:42:47 | [diff] [blame] | 541 | } else { |
| 542 | error_ = keys::kInvalidTargetError; |
[email protected] | 4e023cd | 2013-03-28 15:04:12 | [diff] [blame] | 543 | return false; |
| 544 | } |
[email protected] | 30e246b | 2013-03-28 17:08:48 | [diff] [blame] | 545 | |
[email protected] | dc24976f | 2013-06-02 21:15:09 | [diff] [blame] | 546 | if (!agent_host_.get()) { |
[email protected] | 56cc3804 | 2013-04-03 04:42:47 | [diff] [blame] | 547 | FormatErrorMessage(keys::kNoTargetError); |
| 548 | return false; |
| 549 | } |
| 550 | return true; |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 551 | } |
| 552 | |
[email protected] | c7580b6 | 2011-10-26 08:46:30 | [diff] [blame] | 553 | bool DebuggerFunction::InitClientHost() { |
[email protected] | ac3851f | 2013-04-05 15:51:59 | [diff] [blame] | 554 | if (!InitAgentHost()) |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 555 | return false; |
| 556 | |
[email protected] | eba8f7d | 2014-07-28 22:09:23 | [diff] [blame] | 557 | client_host_ = AttachedClientHosts::GetInstance()->Lookup(agent_host_.get(), |
| 558 | extension()->id()); |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 559 | |
[email protected] | ac3851f | 2013-04-05 15:51:59 | [diff] [blame] | 560 | if (!client_host_) { |
[email protected] | 2fefdb3 | 2013-02-26 14:28:10 | [diff] [blame] | 561 | FormatErrorMessage(keys::kNotAttachedError); |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 562 | return false; |
| 563 | } |
| 564 | return true; |
| 565 | } |
| 566 | |
[email protected] | 49c71ac | 2013-05-03 01:36:22 | [diff] [blame] | 567 | |
| 568 | // DebuggerAttachFunction ----------------------------------------------------- |
| 569 | |
[email protected] | 28b05ef0 | 2013-07-10 22:28:32 | [diff] [blame] | 570 | DebuggerAttachFunction::DebuggerAttachFunction() { |
| 571 | } |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 572 | |
[email protected] | 28b05ef0 | 2013-07-10 22:28:32 | [diff] [blame] | 573 | DebuggerAttachFunction::~DebuggerAttachFunction() { |
| 574 | } |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 575 | |
[email protected] | a0c91a9f | 2014-05-03 03:41:43 | [diff] [blame] | 576 | bool DebuggerAttachFunction::RunAsync() { |
[email protected] | 752960d | 2012-07-23 19:06:11 | [diff] [blame] | 577 | scoped_ptr<Attach::Params> params(Attach::Params::Create(*args_)); |
| 578 | EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 579 | |
[email protected] | 28b05ef0 | 2013-07-10 22:28:32 | [diff] [blame] | 580 | CopyDebuggee(&debuggee_, params->target); |
[email protected] | ac3851f | 2013-04-05 15:51:59 | [diff] [blame] | 581 | if (!InitAgentHost()) |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 582 | return false; |
| 583 | |
[email protected] | be3577e | 2013-06-26 21:42:33 | [diff] [blame] | 584 | if (!DevToolsHttpHandler::IsSupportedProtocolVersion( |
| 585 | params->required_version)) { |
[email protected] | e9f541a | 2012-11-19 21:52:31 | [diff] [blame] | 586 | error_ = ErrorUtils::FormatErrorMessage( |
[email protected] | c7580b6 | 2011-10-26 08:46:30 | [diff] [blame] | 587 | keys::kProtocolVersionNotSupportedError, |
[email protected] | 752960d | 2012-07-23 19:06:11 | [diff] [blame] | 588 | params->required_version); |
[email protected] | c7580b6 | 2011-10-26 08:46:30 | [diff] [blame] | 589 | return false; |
| 590 | } |
| 591 | |
[email protected] | ac3851f | 2013-04-05 15:51:59 | [diff] [blame] | 592 | if (agent_host_->IsAttached()) { |
[email protected] | 2fefdb3 | 2013-02-26 14:28:10 | [diff] [blame] | 593 | FormatErrorMessage(keys::kAlreadyAttachedError); |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 594 | return false; |
| 595 | } |
| 596 | |
[email protected] | 051655ad | 2014-04-18 15:09:41 | [diff] [blame] | 597 | infobars::InfoBar* infobar = NULL; |
avi | 3ef9ec9e | 2014-12-22 22:50:17 | [diff] [blame] | 598 | if (!base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 599 | ::switches::kSilentDebuggerExtensionAPI)) { |
[email protected] | 56cc3804 | 2013-04-03 04:42:47 | [diff] [blame] | 600 | // Do not attach to the target if for any reason the infobar cannot be shown |
| 601 | // for this WebContents instance. |
[email protected] | 9f0fc9dc | 2013-07-24 21:31:56 | [diff] [blame] | 602 | infobar = ExtensionDevToolsInfoBarDelegate::Create( |
[email protected] | b3f957e6 | 2014-08-08 10:09:02 | [diff] [blame] | 603 | agent_host_->GetWebContents(), extension()->name()); |
[email protected] | 9f0fc9dc | 2013-07-24 21:31:56 | [diff] [blame] | 604 | if (!infobar) { |
[email protected] | 56cc3804 | 2013-04-03 04:42:47 | [diff] [blame] | 605 | error_ = ErrorUtils::FormatErrorMessage( |
| 606 | keys::kSilentDebuggingRequired, |
[email protected] | 684a212a | 2014-06-27 17:14:50 | [diff] [blame] | 607 | ::switches::kSilentDebuggerExtensionAPI); |
[email protected] | 56cc3804 | 2013-04-03 04:42:47 | [diff] [blame] | 608 | return false; |
| 609 | } |
| 610 | } |
| 611 | |
[email protected] | 21a4008 | 2013-10-28 21:19:23 | [diff] [blame] | 612 | new ExtensionDevToolsClientHost(GetProfile(), |
| 613 | agent_host_.get(), |
[email protected] | eba8f7d | 2014-07-28 22:09:23 | [diff] [blame] | 614 | extension()->id(), |
| 615 | extension()->name(), |
[email protected] | 21a4008 | 2013-10-28 21:19:23 | [diff] [blame] | 616 | debuggee_, |
| 617 | infobar); |
[email protected] | ff31a8a | 2011-03-30 14:13:59 | [diff] [blame] | 618 | SendResponse(true); |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 619 | return true; |
| 620 | } |
| 621 | |
[email protected] | 49c71ac | 2013-05-03 01:36:22 | [diff] [blame] | 622 | |
| 623 | // DebuggerDetachFunction ----------------------------------------------------- |
| 624 | |
[email protected] | 28b05ef0 | 2013-07-10 22:28:32 | [diff] [blame] | 625 | DebuggerDetachFunction::DebuggerDetachFunction() { |
| 626 | } |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 627 | |
[email protected] | 28b05ef0 | 2013-07-10 22:28:32 | [diff] [blame] | 628 | DebuggerDetachFunction::~DebuggerDetachFunction() { |
| 629 | } |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 630 | |
[email protected] | a0c91a9f | 2014-05-03 03:41:43 | [diff] [blame] | 631 | bool DebuggerDetachFunction::RunAsync() { |
[email protected] | 752960d | 2012-07-23 19:06:11 | [diff] [blame] | 632 | scoped_ptr<Detach::Params> params(Detach::Params::Create(*args_)); |
| 633 | EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 634 | |
[email protected] | 28b05ef0 | 2013-07-10 22:28:32 | [diff] [blame] | 635 | CopyDebuggee(&debuggee_, params->target); |
[email protected] | c7580b6 | 2011-10-26 08:46:30 | [diff] [blame] | 636 | if (!InitClientHost()) |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 637 | return false; |
| 638 | |
| 639 | client_host_->Close(); |
[email protected] | ff31a8a | 2011-03-30 14:13:59 | [diff] [blame] | 640 | SendResponse(true); |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 641 | return true; |
| 642 | } |
| 643 | |
[email protected] | 49c71ac | 2013-05-03 01:36:22 | [diff] [blame] | 644 | |
| 645 | // DebuggerSendCommandFunction ------------------------------------------------ |
| 646 | |
[email protected] | 28b05ef0 | 2013-07-10 22:28:32 | [diff] [blame] | 647 | DebuggerSendCommandFunction::DebuggerSendCommandFunction() { |
| 648 | } |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 649 | |
[email protected] | 28b05ef0 | 2013-07-10 22:28:32 | [diff] [blame] | 650 | DebuggerSendCommandFunction::~DebuggerSendCommandFunction() { |
| 651 | } |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 652 | |
[email protected] | a0c91a9f | 2014-05-03 03:41:43 | [diff] [blame] | 653 | bool DebuggerSendCommandFunction::RunAsync() { |
[email protected] | 752960d | 2012-07-23 19:06:11 | [diff] [blame] | 654 | scoped_ptr<SendCommand::Params> params(SendCommand::Params::Create(*args_)); |
| 655 | EXTENSION_FUNCTION_VALIDATE(params.get()); |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 656 | |
[email protected] | 28b05ef0 | 2013-07-10 22:28:32 | [diff] [blame] | 657 | CopyDebuggee(&debuggee_, params->target); |
[email protected] | c7580b6 | 2011-10-26 08:46:30 | [diff] [blame] | 658 | if (!InitClientHost()) |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 659 | return false; |
| 660 | |
[email protected] | 752960d | 2012-07-23 19:06:11 | [diff] [blame] | 661 | client_host_->SendMessageToBackend(this, params->method, |
| 662 | params->command_params.get()); |
[email protected] | 91ba331 | 2011-03-17 20:39:22 | [diff] [blame] | 663 | return true; |
| 664 | } |
[email protected] | ff31a8a | 2011-03-30 14:13:59 | [diff] [blame] | 665 | |
[email protected] | 4636c83 | 2013-01-11 02:10:11 | [diff] [blame] | 666 | void DebuggerSendCommandFunction::SendResponseBody( |
[email protected] | aeca23f | 2013-06-21 22:34:41 | [diff] [blame] | 667 | base::DictionaryValue* response) { |
[email protected] | 5bcdd99d | 2013-12-23 18:28:30 | [diff] [blame] | 668 | base::Value* error_body; |
[email protected] | 752960d | 2012-07-23 19:06:11 | [diff] [blame] | 669 | if (response->Get("error", &error_body)) { |
[email protected] | 4abb460 | 2012-03-16 01:59:55 | [diff] [blame] | 670 | base::JSONWriter::Write(error_body, &error_); |
[email protected] | ff31a8a | 2011-03-30 14:13:59 | [diff] [blame] | 671 | SendResponse(false); |
| 672 | return; |
| 673 | } |
| 674 | |
[email protected] | aeca23f | 2013-06-21 22:34:41 | [diff] [blame] | 675 | base::DictionaryValue* result_body; |
[email protected] | 752960d | 2012-07-23 19:06:11 | [diff] [blame] | 676 | SendCommand::Results::Result result; |
| 677 | if (response->GetDictionary("result", &result_body)) |
| 678 | result.additional_properties.Swap(result_body); |
| 679 | |
| 680 | results_ = SendCommand::Results::Create(result); |
[email protected] | ff31a8a | 2011-03-30 14:13:59 | [diff] [blame] | 681 | SendResponse(true); |
| 682 | } |
[email protected] | 56cc3804 | 2013-04-03 04:42:47 | [diff] [blame] | 683 | |
[email protected] | 49c71ac | 2013-05-03 01:36:22 | [diff] [blame] | 684 | |
| 685 | // DebuggerGetTargetsFunction ------------------------------------------------- |
| 686 | |
[email protected] | 28b05ef0 | 2013-07-10 22:28:32 | [diff] [blame] | 687 | namespace { |
[email protected] | 56cc3804 | 2013-04-03 04:42:47 | [diff] [blame] | 688 | |
[email protected] | 28b05ef0 | 2013-07-10 22:28:32 | [diff] [blame] | 689 | const char kTargetIdField[] = "id"; |
| 690 | const char kTargetTypeField[] = "type"; |
| 691 | const char kTargetTitleField[] = "title"; |
| 692 | const char kTargetAttachedField[] = "attached"; |
| 693 | const char kTargetUrlField[] = "url"; |
| 694 | const char kTargetFaviconUrlField[] = "faviconUrl"; |
| 695 | const char kTargetTypePage[] = "page"; |
| 696 | const char kTargetTypeBackgroundPage[] = "background_page"; |
| 697 | const char kTargetTypeWorker[] = "worker"; |
[email protected] | f80e0be6 | 2013-07-17 14:17:23 | [diff] [blame] | 698 | const char kTargetTypeOther[] = "other"; |
| 699 | const char kTargetTabIdField[] = "tabId"; |
| 700 | const char kTargetExtensionIdField[] = "extensionId"; |
[email protected] | 28b05ef0 | 2013-07-10 22:28:32 | [diff] [blame] | 701 | |
[email protected] | 06d503f | 2013-10-29 17:29:37 | [diff] [blame] | 702 | base::Value* SerializeTarget(const DevToolsTargetImpl& target) { |
[email protected] | 28b05ef0 | 2013-07-10 22:28:32 | [diff] [blame] | 703 | base::DictionaryValue* dictionary = new base::DictionaryValue(); |
| 704 | |
[email protected] | 06d503f | 2013-10-29 17:29:37 | [diff] [blame] | 705 | dictionary->SetString(kTargetIdField, target.GetId()); |
| 706 | dictionary->SetString(kTargetTitleField, target.GetTitle()); |
| 707 | dictionary->SetBoolean(kTargetAttachedField, target.IsAttached()); |
[email protected] | 657d273 | 2014-05-07 10:09:51 | [diff] [blame] | 708 | dictionary->SetString(kTargetUrlField, target.GetURL().spec()); |
[email protected] | 28b05ef0 | 2013-07-10 22:28:32 | [diff] [blame] | 709 | |
[email protected] | 06d503f | 2013-10-29 17:29:37 | [diff] [blame] | 710 | std::string type = target.GetType(); |
| 711 | if (type == kTargetTypePage) { |
| 712 | dictionary->SetInteger(kTargetTabIdField, target.GetTabId()); |
| 713 | } else if (type == kTargetTypeBackgroundPage) { |
| 714 | dictionary->SetString(kTargetExtensionIdField, target.GetExtensionId()); |
| 715 | } else if (type != kTargetTypeWorker) { |
| 716 | // DevToolsTargetImpl may support more types than the debugger API. |
| 717 | type = kTargetTypeOther; |
[email protected] | 28b05ef0 | 2013-07-10 22:28:32 | [diff] [blame] | 718 | } |
[email protected] | 06d503f | 2013-10-29 17:29:37 | [diff] [blame] | 719 | dictionary->SetString(kTargetTypeField, type); |
[email protected] | 28b05ef0 | 2013-07-10 22:28:32 | [diff] [blame] | 720 | |
[email protected] | 657d273 | 2014-05-07 10:09:51 | [diff] [blame] | 721 | GURL favicon_url = target.GetFaviconURL(); |
[email protected] | 06d503f | 2013-10-29 17:29:37 | [diff] [blame] | 722 | if (favicon_url.is_valid()) |
| 723 | dictionary->SetString(kTargetFaviconUrlField, favicon_url.spec()); |
[email protected] | 28b05ef0 | 2013-07-10 22:28:32 | [diff] [blame] | 724 | |
| 725 | return dictionary; |
| 726 | } |
| 727 | |
[email protected] | 4edaf7ec | 2014-05-07 13:54:15 | [diff] [blame] | 728 | } // namespace |
[email protected] | 28b05ef0 | 2013-07-10 22:28:32 | [diff] [blame] | 729 | |
| 730 | DebuggerGetTargetsFunction::DebuggerGetTargetsFunction() { |
| 731 | } |
| 732 | |
| 733 | DebuggerGetTargetsFunction::~DebuggerGetTargetsFunction() { |
| 734 | } |
[email protected] | 56cc3804 | 2013-04-03 04:42:47 | [diff] [blame] | 735 | |
[email protected] | a0c91a9f | 2014-05-03 03:41:43 | [diff] [blame] | 736 | bool DebuggerGetTargetsFunction::RunAsync() { |
[email protected] | 06d503f | 2013-10-29 17:29:37 | [diff] [blame] | 737 | DevToolsTargetImpl::EnumerateAllTargets( |
| 738 | base::Bind(&DebuggerGetTargetsFunction::SendTargetList, this)); |
[email protected] | 56cc3804 | 2013-04-03 04:42:47 | [diff] [blame] | 739 | return true; |
| 740 | } |
[email protected] | ac3851f | 2013-04-05 15:51:59 | [diff] [blame] | 741 | |
[email protected] | fe38b1e | 2013-10-02 23:43:34 | [diff] [blame] | 742 | void DebuggerGetTargetsFunction::SendTargetList( |
[email protected] | 06d503f | 2013-10-29 17:29:37 | [diff] [blame] | 743 | const std::vector<DevToolsTargetImpl*>& target_list) { |
| 744 | scoped_ptr<base::ListValue> result(new base::ListValue()); |
| 745 | for (size_t i = 0; i < target_list.size(); ++i) |
| 746 | result->Append(SerializeTarget(*target_list[i])); |
| 747 | STLDeleteContainerPointers(target_list.begin(), target_list.end()); |
| 748 | SetResult(result.release()); |
[email protected] | ac3851f | 2013-04-05 15:51:59 | [diff] [blame] | 749 | SendResponse(true); |
| 750 | } |
[email protected] | d32a9265 | 2014-05-09 11:06:15 | [diff] [blame] | 751 | |
| 752 | } // namespace extensions |