OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Implements the Chrome Extensions Debugger API. | 5 // Implements the Chrome Extensions Debugger API. |
6 | 6 |
7 #include "chrome/browser/extensions/api/debugger/debugger_api.h" | 7 #include "chrome/browser/extensions/api/debugger/debugger_api.h" |
8 | 8 |
9 #include <map> | 9 #include <map> |
10 #include <set> | 10 #include <set> |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
48 using content::WebContents; | 48 using content::WebContents; |
49 using extensions::api::debugger::Debuggee; | 49 using extensions::api::debugger::Debuggee; |
50 | 50 |
51 namespace keys = debugger_api_constants; | 51 namespace keys = debugger_api_constants; |
52 namespace Attach = extensions::api::debugger::Attach; | 52 namespace Attach = extensions::api::debugger::Attach; |
53 namespace Detach = extensions::api::debugger::Detach; | 53 namespace Detach = extensions::api::debugger::Detach; |
54 namespace OnDetach = extensions::api::debugger::OnDetach; | 54 namespace OnDetach = extensions::api::debugger::OnDetach; |
55 namespace OnEvent = extensions::api::debugger::OnEvent; | 55 namespace OnEvent = extensions::api::debugger::OnEvent; |
56 namespace SendCommand = extensions::api::debugger::SendCommand; | 56 namespace SendCommand = extensions::api::debugger::SendCommand; |
57 | 57 |
58 class ExtensionDevToolsClientHost; | |
59 | |
58 class ExtensionDevToolsInfoBarDelegate : public ConfirmInfoBarDelegate { | 60 class ExtensionDevToolsInfoBarDelegate : public ConfirmInfoBarDelegate { |
59 public: | 61 public: |
60 ExtensionDevToolsInfoBarDelegate( | 62 ExtensionDevToolsInfoBarDelegate( |
61 InfoBarTabHelper* infobar_helper, | 63 InfoBarTabHelper* infobar_helper, |
62 const std::string& client_name); | 64 const std::string& client_name, |
65 ExtensionDevToolsClientHost* client_host); | |
63 virtual ~ExtensionDevToolsInfoBarDelegate(); | 66 virtual ~ExtensionDevToolsInfoBarDelegate(); |
64 | 67 |
68 void DiscardClientHost(); | |
Matt Perry
2012/09/19 19:14:13
Please comment this method.
| |
69 | |
65 private: | 70 private: |
66 // ConfirmInfoBarDelegate: | 71 // ConfirmInfoBarDelegate: |
67 virtual bool ShouldExpire( | 72 virtual bool ShouldExpire( |
68 const content::LoadCommittedDetails& details) const OVERRIDE; | 73 const content::LoadCommittedDetails& details) const OVERRIDE; |
69 virtual int GetButtons() const OVERRIDE; | 74 virtual int GetButtons() const OVERRIDE; |
70 virtual Type GetInfoBarType() const OVERRIDE; | 75 virtual Type GetInfoBarType() const OVERRIDE; |
71 virtual string16 GetMessageText() const OVERRIDE; | 76 virtual string16 GetMessageText() const OVERRIDE; |
77 virtual void InfoBarDismissed() OVERRIDE; | |
78 virtual bool Cancel() OVERRIDE; | |
72 | 79 |
73 std::string client_name_; | 80 std::string client_name_; |
81 ExtensionDevToolsClientHost* client_host_; | |
74 DISALLOW_COPY_AND_ASSIGN(ExtensionDevToolsInfoBarDelegate); | 82 DISALLOW_COPY_AND_ASSIGN(ExtensionDevToolsInfoBarDelegate); |
75 }; | 83 }; |
76 | 84 |
77 class ExtensionDevToolsClientHost : public DevToolsClientHost, | 85 class ExtensionDevToolsClientHost : public DevToolsClientHost, |
78 public content::NotificationObserver { | 86 public content::NotificationObserver { |
79 public: | 87 public: |
80 ExtensionDevToolsClientHost(WebContents* web_contents, | 88 ExtensionDevToolsClientHost(WebContents* web_contents, |
81 const std::string& extension_id, | 89 const std::string& extension_id, |
82 const std::string& extension_name, | 90 const std::string& extension_name, |
83 int tab_id); | 91 int tab_id); |
84 | 92 |
85 ~ExtensionDevToolsClientHost(); | 93 ~ExtensionDevToolsClientHost(); |
86 | 94 |
87 bool MatchesContentsAndExtensionId(WebContents* web_contents, | 95 bool MatchesContentsAndExtensionId(WebContents* web_contents, |
88 const std::string& extension_id); | 96 const std::string& extension_id); |
89 void Close(); | 97 void Close(); |
90 void SendMessageToBackend(SendCommandDebuggerFunction* function, | 98 void SendMessageToBackend(SendCommandDebuggerFunction* function, |
91 const std::string& method, | 99 const std::string& method, |
92 SendCommand::Params::CommandParams* command_params); | 100 SendCommand::Params::CommandParams* command_params); |
101 void MarkAsReplaced(); | |
102 void MarkAsDismissed(); | |
Matt Perry
2012/09/19 19:14:13
All the methods above could use comments.
| |
93 | 103 |
94 // DevToolsClientHost interface | 104 // DevToolsClientHost interface |
95 virtual void InspectedContentsClosing() OVERRIDE; | 105 virtual void InspectedContentsClosing() OVERRIDE; |
96 virtual void DispatchOnInspectorFrontend(const std::string& message) OVERRIDE; | 106 virtual void DispatchOnInspectorFrontend(const std::string& message) OVERRIDE; |
97 virtual void ContentsReplaced(WebContents* web_contents) OVERRIDE; | 107 virtual void ContentsReplaced(WebContents* web_contents) OVERRIDE; |
98 virtual void FrameNavigating(const std::string& url) OVERRIDE {} | 108 virtual void FrameNavigating(const std::string& url) OVERRIDE {} |
99 | 109 |
100 private: | 110 private: |
101 void SendDetachedEvent(); | 111 void SendDetachedEvent(); |
102 | 112 |
103 // content::NotificationObserver implementation. | 113 // content::NotificationObserver implementation. |
104 virtual void Observe(int type, | 114 virtual void Observe(int type, |
105 const content::NotificationSource& source, | 115 const content::NotificationSource& source, |
106 const content::NotificationDetails& details); | 116 const content::NotificationDetails& details); |
107 | 117 |
108 WebContents* web_contents_; | 118 WebContents* web_contents_; |
109 std::string extension_id_; | 119 std::string extension_id_; |
110 int tab_id_; | 120 int tab_id_; |
111 content::NotificationRegistrar registrar_; | 121 content::NotificationRegistrar registrar_; |
112 int last_request_id_; | 122 int last_request_id_; |
113 typedef std::map<int, scoped_refptr<SendCommandDebuggerFunction> > | 123 typedef std::map<int, scoped_refptr<SendCommandDebuggerFunction> > |
114 PendingRequests; | 124 PendingRequests; |
115 PendingRequests pending_requests_; | 125 PendingRequests pending_requests_; |
116 ExtensionDevToolsInfoBarDelegate* infobar_delegate_; | 126 ExtensionDevToolsInfoBarDelegate* infobar_delegate_; |
127 OnDetach::Reason detach_reason_; | |
117 | 128 |
118 DISALLOW_COPY_AND_ASSIGN(ExtensionDevToolsClientHost); | 129 DISALLOW_COPY_AND_ASSIGN(ExtensionDevToolsClientHost); |
119 }; | 130 }; |
120 | 131 |
121 namespace { | 132 namespace { |
122 | 133 |
123 class AttachedClientHosts { | 134 class AttachedClientHosts { |
124 public: | 135 public: |
125 AttachedClientHosts() {} | 136 AttachedClientHosts() {} |
126 | 137 |
127 // Returns the singleton instance of this class | 138 // Returns the singleton instance of this class |
128 static AttachedClientHosts* GetInstance() { | 139 static AttachedClientHosts* GetInstance() { |
129 return Singleton<AttachedClientHosts>::get(); | 140 return Singleton<AttachedClientHosts>::get(); |
130 } | 141 } |
131 | 142 |
132 void Add(ExtensionDevToolsClientHost* client_host) { | 143 void Add(ExtensionDevToolsClientHost* client_host) { |
133 client_hosts_.insert(client_host); | 144 client_hosts_.insert(client_host); |
134 } | 145 } |
135 | 146 |
136 void Remove(ExtensionDevToolsClientHost* client_host) { | 147 void Remove(ExtensionDevToolsClientHost* client_host) { |
137 client_hosts_.erase(client_host); | 148 client_hosts_.erase(client_host); |
138 } | 149 } |
139 | 150 |
151 ExtensionDevToolsClientHost* AsExtensionDevToolsClientHost( | |
152 DevToolsClientHost* client_host) { | |
153 for (std::set<DevToolsClientHost*>::iterator it = client_hosts_.begin(); | |
154 it != client_hosts_.end(); ++it) { | |
155 if (client_host == *it) | |
156 return static_cast<ExtensionDevToolsClientHost*>(*it); | |
157 } | |
158 return NULL; | |
159 } | |
160 | |
140 ExtensionDevToolsClientHost* Lookup(WebContents* contents) { | 161 ExtensionDevToolsClientHost* Lookup(WebContents* contents) { |
141 for (std::set<DevToolsClientHost*>::iterator it = client_hosts_.begin(); | 162 for (std::set<DevToolsClientHost*>::iterator it = client_hosts_.begin(); |
142 it != client_hosts_.end(); ++it) { | 163 it != client_hosts_.end(); ++it) { |
143 DevToolsAgentHost* agent_host = | 164 DevToolsAgentHost* agent_host = |
144 DevToolsManager::GetInstance()->GetDevToolsAgentHostFor(*it); | 165 DevToolsManager::GetInstance()->GetDevToolsAgentHostFor(*it); |
145 if (!agent_host) | 166 if (!agent_host) |
146 continue; | 167 continue; |
147 content::RenderViewHost* rvh = | 168 content::RenderViewHost* rvh = |
148 DevToolsAgentHostRegistry::GetRenderViewHost(agent_host); | 169 DevToolsAgentHostRegistry::GetRenderViewHost(agent_host); |
149 if (rvh && WebContents::FromRenderViewHost(rvh) == contents) | 170 if (rvh && WebContents::FromRenderViewHost(rvh) == contents) |
(...skipping 10 matching lines...) Expand all Loading... | |
160 | 181 |
161 ExtensionDevToolsClientHost::ExtensionDevToolsClientHost( | 182 ExtensionDevToolsClientHost::ExtensionDevToolsClientHost( |
162 WebContents* web_contents, | 183 WebContents* web_contents, |
163 const std::string& extension_id, | 184 const std::string& extension_id, |
164 const std::string& extension_name, | 185 const std::string& extension_name, |
165 int tab_id) | 186 int tab_id) |
166 : web_contents_(web_contents), | 187 : web_contents_(web_contents), |
167 extension_id_(extension_id), | 188 extension_id_(extension_id), |
168 tab_id_(tab_id), | 189 tab_id_(tab_id), |
169 last_request_id_(0), | 190 last_request_id_(0), |
170 infobar_delegate_(NULL) { | 191 infobar_delegate_(NULL), |
192 detach_reason_(OnDetach::REASON_TARGET_CLOSED) { | |
171 AttachedClientHosts::GetInstance()->Add(this); | 193 AttachedClientHosts::GetInstance()->Add(this); |
172 | 194 |
173 // Detach from debugger when extension unloads. | 195 // Detach from debugger when extension unloads. |
174 Profile* profile = | 196 Profile* profile = |
175 Profile::FromBrowserContext(web_contents_->GetBrowserContext()); | 197 Profile::FromBrowserContext(web_contents_->GetBrowserContext()); |
176 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, | 198 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, |
177 content::Source<Profile>(profile)); | 199 content::Source<Profile>(profile)); |
178 | 200 |
179 // Attach to debugger and tell it we are ready. | 201 // Attach to debugger and tell it we are ready. |
180 DevToolsAgentHost* agent = DevToolsAgentHostRegistry::GetDevToolsAgentHost( | 202 DevToolsAgentHost* agent = DevToolsAgentHostRegistry::GetDevToolsAgentHost( |
181 web_contents_->GetRenderViewHost()); | 203 web_contents_->GetRenderViewHost()); |
182 DevToolsManager::GetInstance()->RegisterDevToolsClientHostFor(agent, this); | 204 DevToolsManager::GetInstance()->RegisterDevToolsClientHostFor(agent, this); |
183 | 205 |
184 InfoBarTabHelper* infobar_helper = | 206 InfoBarTabHelper* infobar_helper = |
185 TabContents::FromWebContents(web_contents_)->infobar_tab_helper(); | 207 TabContents::FromWebContents(web_contents_)->infobar_tab_helper(); |
186 infobar_delegate_ = | 208 infobar_delegate_ = new ExtensionDevToolsInfoBarDelegate(infobar_helper, |
187 new ExtensionDevToolsInfoBarDelegate(infobar_helper, extension_name); | 209 extension_name, |
210 this); | |
188 if (infobar_helper->AddInfoBar(infobar_delegate_)) { | 211 if (infobar_helper->AddInfoBar(infobar_delegate_)) { |
189 registrar_.Add(this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, | 212 registrar_.Add(this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, |
190 content::Source<InfoBarTabHelper>(infobar_helper)); | 213 content::Source<InfoBarTabHelper>(infobar_helper)); |
191 } else { | 214 } else { |
192 infobar_delegate_ = NULL; | 215 infobar_delegate_ = NULL; |
193 } | 216 } |
194 } | 217 } |
195 | 218 |
196 ExtensionDevToolsClientHost::~ExtensionDevToolsClientHost() { | 219 ExtensionDevToolsClientHost::~ExtensionDevToolsClientHost() { |
197 // Ensure calling RemoveInfoBar() below won't result in Observe() trying to | 220 // Ensure calling RemoveInfoBar() below won't result in Observe() trying to |
198 // Close() us. | 221 // Close() us. |
199 registrar_.RemoveAll(); | 222 registrar_.RemoveAll(); |
200 | 223 |
201 if (infobar_delegate_) { | 224 if (infobar_delegate_) { |
225 infobar_delegate_->DiscardClientHost(); | |
202 TabContents* tab_contents = TabContents::FromWebContents(web_contents_); | 226 TabContents* tab_contents = TabContents::FromWebContents(web_contents_); |
203 InfoBarTabHelper* helper = tab_contents->infobar_tab_helper(); | 227 InfoBarTabHelper* helper = tab_contents->infobar_tab_helper(); |
204 if (helper) | 228 if (helper) |
205 helper->RemoveInfoBar(infobar_delegate_); | 229 helper->RemoveInfoBar(infobar_delegate_); |
206 } | 230 } |
207 AttachedClientHosts::GetInstance()->Remove(this); | 231 AttachedClientHosts::GetInstance()->Remove(this); |
208 } | 232 } |
209 | 233 |
210 bool ExtensionDevToolsClientHost::MatchesContentsAndExtensionId( | 234 bool ExtensionDevToolsClientHost::MatchesContentsAndExtensionId( |
211 WebContents* web_contents, | 235 WebContents* web_contents, |
(...skipping 28 matching lines...) Expand all Loading... | |
240 if (command_params) { | 264 if (command_params) { |
241 protocol_request.Set("params", | 265 protocol_request.Set("params", |
242 command_params->additional_properties.DeepCopy()); | 266 command_params->additional_properties.DeepCopy()); |
243 } | 267 } |
244 | 268 |
245 std::string json_args; | 269 std::string json_args; |
246 base::JSONWriter::Write(&protocol_request, &json_args); | 270 base::JSONWriter::Write(&protocol_request, &json_args); |
247 DevToolsManager::GetInstance()->DispatchOnInspectorBackend(this, json_args); | 271 DevToolsManager::GetInstance()->DispatchOnInspectorBackend(this, json_args); |
248 } | 272 } |
249 | 273 |
274 void ExtensionDevToolsClientHost::MarkAsReplaced() { | |
275 detach_reason_ = OnDetach::REASON_REPLACED_WITH_DEVTOOLS; | |
276 } | |
277 | |
278 void ExtensionDevToolsClientHost::MarkAsDismissed() { | |
279 detach_reason_ = OnDetach::REASON_CANCELED_BY_USER; | |
280 } | |
281 | |
250 void ExtensionDevToolsClientHost::SendDetachedEvent() { | 282 void ExtensionDevToolsClientHost::SendDetachedEvent() { |
251 Profile* profile = | 283 Profile* profile = |
252 Profile::FromBrowserContext(web_contents_->GetBrowserContext()); | 284 Profile::FromBrowserContext(web_contents_->GetBrowserContext()); |
253 if (profile != NULL && profile->GetExtensionEventRouter()) { | 285 if (profile != NULL && profile->GetExtensionEventRouter()) { |
254 Debuggee debuggee; | 286 Debuggee debuggee; |
255 debuggee.tab_id = tab_id_; | 287 debuggee.tab_id = tab_id_; |
256 | 288 scoped_ptr<base::ListValue> args(OnDetach::Create(debuggee, |
257 scoped_ptr<base::ListValue> args(OnDetach::Create(debuggee)); | 289 detach_reason_)); |
258 profile->GetExtensionEventRouter()->DispatchEventToExtension( | 290 profile->GetExtensionEventRouter()->DispatchEventToExtension( |
259 extension_id_, keys::kOnDetach, args.Pass(), profile, GURL()); | 291 extension_id_, keys::kOnDetach, args.Pass(), profile, GURL()); |
260 } | 292 } |
261 } | 293 } |
262 | 294 |
263 void ExtensionDevToolsClientHost::Observe( | 295 void ExtensionDevToolsClientHost::Observe( |
264 int type, | 296 int type, |
265 const content::NotificationSource& source, | 297 const content::NotificationSource& source, |
266 const content::NotificationDetails& details) { | 298 const content::NotificationDetails& details) { |
267 if (type == chrome::NOTIFICATION_EXTENSION_UNLOADED) { | 299 if (type == chrome::NOTIFICATION_EXTENSION_UNLOADED) { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
315 if (!function) | 347 if (!function) |
316 return; | 348 return; |
317 | 349 |
318 function->SendResponseBody(dictionary); | 350 function->SendResponseBody(dictionary); |
319 pending_requests_.erase(id); | 351 pending_requests_.erase(id); |
320 } | 352 } |
321 } | 353 } |
322 | 354 |
323 ExtensionDevToolsInfoBarDelegate::ExtensionDevToolsInfoBarDelegate( | 355 ExtensionDevToolsInfoBarDelegate::ExtensionDevToolsInfoBarDelegate( |
324 InfoBarTabHelper* infobar_helper, | 356 InfoBarTabHelper* infobar_helper, |
325 const std::string& client_name) | 357 const std::string& client_name, |
358 ExtensionDevToolsClientHost* client_host) | |
326 : ConfirmInfoBarDelegate(infobar_helper), | 359 : ConfirmInfoBarDelegate(infobar_helper), |
327 client_name_(client_name) { | 360 client_name_(client_name), |
361 client_host_(client_host) { | |
328 } | 362 } |
329 | 363 |
330 ExtensionDevToolsInfoBarDelegate::~ExtensionDevToolsInfoBarDelegate() { | 364 ExtensionDevToolsInfoBarDelegate::~ExtensionDevToolsInfoBarDelegate() { |
331 } | 365 } |
332 | 366 |
367 void ExtensionDevToolsInfoBarDelegate::DiscardClientHost() { | |
368 client_host_ = NULL; | |
369 } | |
370 | |
333 bool ExtensionDevToolsInfoBarDelegate::ShouldExpire( | 371 bool ExtensionDevToolsInfoBarDelegate::ShouldExpire( |
334 const content::LoadCommittedDetails& details) const { | 372 const content::LoadCommittedDetails& details) const { |
335 return false; | 373 return false; |
336 } | 374 } |
337 | 375 |
338 int ExtensionDevToolsInfoBarDelegate::GetButtons() const { | 376 int ExtensionDevToolsInfoBarDelegate::GetButtons() const { |
339 return BUTTON_CANCEL; | 377 return BUTTON_CANCEL; |
340 } | 378 } |
341 | 379 |
342 InfoBarDelegate::Type ExtensionDevToolsInfoBarDelegate::GetInfoBarType() const { | 380 InfoBarDelegate::Type ExtensionDevToolsInfoBarDelegate::GetInfoBarType() const { |
343 return WARNING_TYPE; | 381 return WARNING_TYPE; |
344 } | 382 } |
345 | 383 |
346 string16 ExtensionDevToolsInfoBarDelegate::GetMessageText() const { | 384 string16 ExtensionDevToolsInfoBarDelegate::GetMessageText() const { |
347 return l10n_util::GetStringFUTF16(IDS_DEV_TOOLS_INFOBAR_LABEL, | 385 return l10n_util::GetStringFUTF16(IDS_DEV_TOOLS_INFOBAR_LABEL, |
348 UTF8ToUTF16(client_name_)); | 386 UTF8ToUTF16(client_name_)); |
349 } | 387 } |
350 | 388 |
389 void ExtensionDevToolsInfoBarDelegate::InfoBarDismissed() { | |
390 if (client_host_) | |
391 client_host_->MarkAsDismissed(); | |
392 } | |
393 | |
394 bool ExtensionDevToolsInfoBarDelegate::Cancel() { | |
395 if (client_host_) | |
396 client_host_->MarkAsDismissed(); | |
397 return true; | |
398 } | |
399 | |
351 DebuggerFunction::DebuggerFunction() | 400 DebuggerFunction::DebuggerFunction() |
352 : contents_(0), | 401 : contents_(0), |
353 tab_id_(0), | 402 tab_id_(0), |
354 client_host_(0) { | 403 client_host_(0) { |
355 } | 404 } |
356 | 405 |
357 bool DebuggerFunction::InitTabContents() { | 406 bool DebuggerFunction::InitTabContents() { |
358 // Find the TabContents that contains this tab id. | 407 // Find the TabContents that contains this tab id. |
359 contents_ = NULL; | 408 contents_ = NULL; |
360 TabContents* tab_contents = NULL; | 409 TabContents* tab_contents = NULL; |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
481 } | 530 } |
482 | 531 |
483 DictionaryValue* result_body; | 532 DictionaryValue* result_body; |
484 SendCommand::Results::Result result; | 533 SendCommand::Results::Result result; |
485 if (response->GetDictionary("result", &result_body)) | 534 if (response->GetDictionary("result", &result_body)) |
486 result.additional_properties.Swap(result_body); | 535 result.additional_properties.Swap(result_body); |
487 | 536 |
488 results_ = SendCommand::Results::Create(result); | 537 results_ = SendCommand::Results::Create(result); |
489 SendResponse(true); | 538 SendResponse(true); |
490 } | 539 } |
540 | |
541 // static | |
542 void DebuggerApi::MarkDevToolsClientHostAsReplaced( | |
543 DevToolsClientHost* client_host) { | |
544 ExtensionDevToolsClientHost* host = AttachedClientHosts::GetInstance()-> | |
545 AsExtensionDevToolsClientHost(client_host); | |
546 if (host) | |
547 host->MarkAsReplaced(); | |
548 } | |
OLD | NEW |