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> |
11 | 11 |
12 #include "base/json/json_reader.h" | 12 #include "base/json/json_reader.h" |
13 #include "base/json/json_writer.h" | 13 #include "base/json/json_writer.h" |
14 #include "base/memory/scoped_ptr.h" | |
14 #include "base/memory/singleton.h" | 15 #include "base/memory/singleton.h" |
15 #include "base/string_number_conversions.h" | 16 #include "base/string_number_conversions.h" |
16 #include "base/utf_string_conversions.h" | 17 #include "base/utf_string_conversions.h" |
17 #include "base/values.h" | 18 #include "base/values.h" |
18 #include "chrome/browser/extensions/api/debugger/debugger_api_constants.h" | 19 #include "chrome/browser/extensions/api/debugger/debugger_api_constants.h" |
19 #include "chrome/browser/extensions/extension_event_router.h" | 20 #include "chrome/browser/extensions/extension_event_router.h" |
20 #include "chrome/browser/extensions/extension_tab_util.h" | 21 #include "chrome/browser/extensions/extension_tab_util.h" |
21 #include "chrome/browser/infobars/infobar.h" | 22 #include "chrome/browser/infobars/infobar.h" |
22 #include "chrome/browser/infobars/infobar_tab_helper.h" | 23 #include "chrome/browser/infobars/infobar_tab_helper.h" |
23 #include "chrome/browser/profiles/profile.h" | 24 #include "chrome/browser/profiles/profile.h" |
24 #include "chrome/browser/tab_contents/confirm_infobar_delegate.h" | 25 #include "chrome/browser/tab_contents/confirm_infobar_delegate.h" |
25 #include "chrome/browser/ui/tab_contents/tab_contents.h" | 26 #include "chrome/browser/ui/tab_contents/tab_contents.h" |
26 #include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h" | 27 #include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h" |
27 #include "chrome/common/chrome_notification_types.h" | 28 #include "chrome/common/chrome_notification_types.h" |
29 #include "chrome/common/extensions/api/debugger.h" | |
28 #include "chrome/common/extensions/extension.h" | 30 #include "chrome/common/extensions/extension.h" |
29 #include "chrome/common/extensions/extension_error_utils.h" | 31 #include "chrome/common/extensions/extension_error_utils.h" |
30 #include "content/public/browser/devtools_agent_host_registry.h" | 32 #include "content/public/browser/devtools_agent_host_registry.h" |
31 #include "content/public/browser/devtools_client_host.h" | 33 #include "content/public/browser/devtools_client_host.h" |
32 #include "content/public/browser/devtools_manager.h" | 34 #include "content/public/browser/devtools_manager.h" |
33 #include "content/public/browser/notification_service.h" | 35 #include "content/public/browser/notification_service.h" |
34 #include "content/public/browser/notification_source.h" | 36 #include "content/public/browser/notification_source.h" |
35 #include "content/public/browser/render_view_host.h" | 37 #include "content/public/browser/render_view_host.h" |
36 #include "content/public/browser/web_contents.h" | 38 #include "content/public/browser/web_contents.h" |
37 #include "content/public/common/content_client.h" | 39 #include "content/public/common/content_client.h" |
38 #include "grit/generated_resources.h" | 40 #include "grit/generated_resources.h" |
39 #include "ui/base/l10n/l10n_util.h" | 41 #include "ui/base/l10n/l10n_util.h" |
40 #include "webkit/glue/webkit_glue.h" | 42 #include "webkit/glue/webkit_glue.h" |
41 | 43 |
42 using content::DevToolsAgentHost; | 44 using content::DevToolsAgentHost; |
43 using content::DevToolsAgentHostRegistry; | 45 using content::DevToolsAgentHostRegistry; |
44 using content::DevToolsClientHost; | 46 using content::DevToolsClientHost; |
45 using content::DevToolsManager; | 47 using content::DevToolsManager; |
46 using content::WebContents; | 48 using content::WebContents; |
49 using extensions::api::debugger::Debuggee; | |
47 | 50 |
48 namespace keys = debugger_api_constants; | 51 namespace keys = debugger_api_constants; |
52 namespace Attach = extensions::api::debugger::Attach; | |
53 namespace Detach = extensions::api::debugger::Detach; | |
54 namespace OnDetach = extensions::api::debugger::OnDetach; | |
55 namespace OnEvent = extensions::api::debugger::OnEvent; | |
56 namespace SendCommand = extensions::api::debugger::SendCommand; | |
49 | 57 |
50 class ExtensionDevToolsInfoBarDelegate : public ConfirmInfoBarDelegate { | 58 class ExtensionDevToolsInfoBarDelegate : public ConfirmInfoBarDelegate { |
51 public: | 59 public: |
52 ExtensionDevToolsInfoBarDelegate( | 60 ExtensionDevToolsInfoBarDelegate( |
53 InfoBarTabHelper* infobar_helper, | 61 InfoBarTabHelper* infobar_helper, |
54 const std::string& client_name); | 62 const std::string& client_name); |
55 virtual ~ExtensionDevToolsInfoBarDelegate(); | 63 virtual ~ExtensionDevToolsInfoBarDelegate(); |
56 | 64 |
57 private: | 65 private: |
58 // ConfirmInfoBarDelegate: | 66 // ConfirmInfoBarDelegate: |
(...skipping 15 matching lines...) Expand all Loading... | |
74 const std::string& extension_name, | 82 const std::string& extension_name, |
75 int tab_id); | 83 int tab_id); |
76 | 84 |
77 ~ExtensionDevToolsClientHost(); | 85 ~ExtensionDevToolsClientHost(); |
78 | 86 |
79 bool MatchesContentsAndExtensionId(WebContents* web_contents, | 87 bool MatchesContentsAndExtensionId(WebContents* web_contents, |
80 const std::string& extension_id); | 88 const std::string& extension_id); |
81 void Close(); | 89 void Close(); |
82 void SendMessageToBackend(SendCommandDebuggerFunction* function, | 90 void SendMessageToBackend(SendCommandDebuggerFunction* function, |
83 const std::string& method, | 91 const std::string& method, |
84 Value* params); | 92 SendCommand::Params::CommandParams* command_params); |
85 | 93 |
86 // DevToolsClientHost interface | 94 // DevToolsClientHost interface |
87 virtual void InspectedContentsClosing() OVERRIDE; | 95 virtual void InspectedContentsClosing() OVERRIDE; |
88 virtual void DispatchOnInspectorFrontend(const std::string& message) OVERRIDE; | 96 virtual void DispatchOnInspectorFrontend(const std::string& message) OVERRIDE; |
89 virtual void ContentsReplaced(WebContents* web_contents) OVERRIDE; | 97 virtual void ContentsReplaced(WebContents* web_contents) OVERRIDE; |
90 virtual void FrameNavigating(const std::string& url) OVERRIDE {} | 98 virtual void FrameNavigating(const std::string& url) OVERRIDE {} |
91 | 99 |
92 private: | 100 private: |
93 void SendDetachedEvent(); | 101 void SendDetachedEvent(); |
94 | 102 |
(...skipping 10 matching lines...) Expand all Loading... | |
105 typedef std::map<int, scoped_refptr<SendCommandDebuggerFunction> > | 113 typedef std::map<int, scoped_refptr<SendCommandDebuggerFunction> > |
106 PendingRequests; | 114 PendingRequests; |
107 PendingRequests pending_requests_; | 115 PendingRequests pending_requests_; |
108 ExtensionDevToolsInfoBarDelegate* infobar_delegate_; | 116 ExtensionDevToolsInfoBarDelegate* infobar_delegate_; |
109 | 117 |
110 DISALLOW_COPY_AND_ASSIGN(ExtensionDevToolsClientHost); | 118 DISALLOW_COPY_AND_ASSIGN(ExtensionDevToolsClientHost); |
111 }; | 119 }; |
112 | 120 |
113 namespace { | 121 namespace { |
114 | 122 |
115 static Value* CreateDebuggeeId(int tab_id) { | |
116 DictionaryValue* debuggeeId = new DictionaryValue(); | |
117 debuggeeId->SetInteger(keys::kTabIdKey, tab_id); | |
118 return debuggeeId; | |
119 } | |
120 | |
121 class AttachedClientHosts { | 123 class AttachedClientHosts { |
122 public: | 124 public: |
123 AttachedClientHosts() {} | 125 AttachedClientHosts() {} |
124 | 126 |
125 // Returns the singleton instance of this class | 127 // Returns the singleton instance of this class |
126 static AttachedClientHosts* GetInstance() { | 128 static AttachedClientHosts* GetInstance() { |
127 return Singleton<AttachedClientHosts>::get(); | 129 return Singleton<AttachedClientHosts>::get(); |
128 } | 130 } |
129 | 131 |
130 void Add(ExtensionDevToolsClientHost* client_host) { | 132 void Add(ExtensionDevToolsClientHost* client_host) { |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
222 } | 224 } |
223 | 225 |
224 void ExtensionDevToolsClientHost::Close() { | 226 void ExtensionDevToolsClientHost::Close() { |
225 DevToolsManager::GetInstance()->ClientHostClosing(this); | 227 DevToolsManager::GetInstance()->ClientHostClosing(this); |
226 delete this; | 228 delete this; |
227 } | 229 } |
228 | 230 |
229 void ExtensionDevToolsClientHost::SendMessageToBackend( | 231 void ExtensionDevToolsClientHost::SendMessageToBackend( |
230 SendCommandDebuggerFunction* function, | 232 SendCommandDebuggerFunction* function, |
231 const std::string& method, | 233 const std::string& method, |
232 Value* params) { | 234 SendCommand::Params::CommandParams* command_params) { |
233 DictionaryValue protocol_request; | 235 DictionaryValue protocol_request; |
234 int request_id = ++last_request_id_; | 236 int request_id = ++last_request_id_; |
235 pending_requests_[request_id] = function; | 237 pending_requests_[request_id] = function; |
236 protocol_request.SetInteger("id", request_id); | 238 protocol_request.SetInteger("id", request_id); |
237 protocol_request.SetString("method", method); | 239 protocol_request.SetString("method", method); |
238 if (params) | 240 if (command_params) { |
239 protocol_request.Set("params", params->DeepCopy()); | 241 protocol_request.Set("params", |
242 command_params->additional_properties.DeepCopy()); | |
243 } | |
240 | 244 |
241 std::string json_args; | 245 std::string json_args; |
242 base::JSONWriter::Write(&protocol_request, &json_args); | 246 base::JSONWriter::Write(&protocol_request, &json_args); |
243 DevToolsManager::GetInstance()->DispatchOnInspectorBackend(this, json_args); | 247 DevToolsManager::GetInstance()->DispatchOnInspectorBackend(this, json_args); |
244 } | 248 } |
245 | 249 |
246 void ExtensionDevToolsClientHost::SendDetachedEvent() { | 250 void ExtensionDevToolsClientHost::SendDetachedEvent() { |
247 Profile* profile = | 251 Profile* profile = |
248 Profile::FromBrowserContext(web_contents_->GetBrowserContext()); | 252 Profile::FromBrowserContext(web_contents_->GetBrowserContext()); |
249 if (profile != NULL && profile->GetExtensionEventRouter()) { | 253 if (profile != NULL && profile->GetExtensionEventRouter()) { |
250 ListValue args; | 254 Debuggee debuggee; |
251 args.Append(CreateDebuggeeId(tab_id_)); | 255 debuggee.tab_id = tab_id_; |
252 | 256 |
257 scoped_ptr<base::ListValue> args(OnDetach::Create(debuggee)); | |
not at google - send to devlin
2012/07/23 13:56:23
It occurs to me that we could get json schema comp
mitchellwrosen
2012/07/23 17:30:20
Good thought. With events landed perhaps that shou
| |
253 std::string json_args; | 258 std::string json_args; |
254 base::JSONWriter::Write(&args, &json_args); | 259 base::JSONWriter::Write(args.get(), &json_args); |
255 | 260 |
256 profile->GetExtensionEventRouter()->DispatchEventToExtension( | 261 profile->GetExtensionEventRouter()->DispatchEventToExtension( |
257 extension_id_, keys::kOnDetach, json_args, profile, GURL()); | 262 extension_id_, keys::kOnDetach, json_args, profile, GURL()); |
258 } | 263 } |
259 } | 264 } |
260 | 265 |
261 void ExtensionDevToolsClientHost::Observe( | 266 void ExtensionDevToolsClientHost::Observe( |
262 int type, | 267 int type, |
263 const content::NotificationSource& source, | 268 const content::NotificationSource& source, |
264 const content::NotificationDetails& details) { | 269 const content::NotificationDetails& details) { |
(...skipping 25 matching lines...) Expand all Loading... | |
290 if (!result->IsType(Value::TYPE_DICTIONARY)) | 295 if (!result->IsType(Value::TYPE_DICTIONARY)) |
291 return; | 296 return; |
292 DictionaryValue* dictionary = static_cast<DictionaryValue*>(result.get()); | 297 DictionaryValue* dictionary = static_cast<DictionaryValue*>(result.get()); |
293 | 298 |
294 int id; | 299 int id; |
295 if (!dictionary->GetInteger("id", &id)) { | 300 if (!dictionary->GetInteger("id", &id)) { |
296 std::string method_name; | 301 std::string method_name; |
297 if (!dictionary->GetString("method", &method_name)) | 302 if (!dictionary->GetString("method", &method_name)) |
298 return; | 303 return; |
299 | 304 |
300 ListValue args; | 305 Debuggee debuggee; |
301 args.Append(CreateDebuggeeId(tab_id_)); | 306 debuggee.tab_id = tab_id_; |
302 args.Append(Value::CreateStringValue(method_name)); | |
303 Value* params_value; | |
304 if (dictionary->Get("params", ¶ms_value)) | |
305 args.Append(params_value->DeepCopy()); | |
306 | 307 |
308 OnEvent::Params params; | |
309 DictionaryValue* params_value; | |
310 if (dictionary->GetDictionary("params", ¶ms_value)) | |
311 params.additional_properties.Swap(params_value); | |
312 | |
313 scoped_ptr<ListValue> args(OnEvent::Create(debuggee, method_name, params)); | |
307 std::string json_args; | 314 std::string json_args; |
308 base::JSONWriter::Write(&args, &json_args); | 315 base::JSONWriter::Write(args.get(), &json_args); |
309 | 316 |
310 profile->GetExtensionEventRouter()->DispatchEventToExtension( | 317 profile->GetExtensionEventRouter()->DispatchEventToExtension( |
311 extension_id_, keys::kOnEvent, json_args, profile, GURL()); | 318 extension_id_, keys::kOnEvent, json_args, profile, GURL()); |
312 } else { | 319 } else { |
313 SendCommandDebuggerFunction* function = pending_requests_[id]; | 320 SendCommandDebuggerFunction* function = pending_requests_[id]; |
314 if (!function) | 321 if (!function) |
315 return; | 322 return; |
316 | 323 |
317 function->SendResponseBody(dictionary); | 324 function->SendResponseBody(dictionary); |
318 pending_requests_.erase(id); | 325 pending_requests_.erase(id); |
(...skipping 28 matching lines...) Expand all Loading... | |
347 UTF8ToUTF16(client_name_)); | 354 UTF8ToUTF16(client_name_)); |
348 } | 355 } |
349 | 356 |
350 DebuggerFunction::DebuggerFunction() | 357 DebuggerFunction::DebuggerFunction() |
351 : contents_(0), | 358 : contents_(0), |
352 tab_id_(0), | 359 tab_id_(0), |
353 client_host_(0) { | 360 client_host_(0) { |
354 } | 361 } |
355 | 362 |
356 bool DebuggerFunction::InitTabContents() { | 363 bool DebuggerFunction::InitTabContents() { |
357 Value* debuggee; | |
358 EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &debuggee)); | |
359 | |
360 DictionaryValue* dict = static_cast<DictionaryValue*>(debuggee); | |
361 EXTENSION_FUNCTION_VALIDATE(dict->GetInteger(keys::kTabIdKey, &tab_id_)); | |
362 | |
363 // Find the TabContents that contains this tab id. | 364 // Find the TabContents that contains this tab id. |
364 contents_ = NULL; | 365 contents_ = NULL; |
365 TabContents* tab_contents = NULL; | 366 TabContents* tab_contents = NULL; |
366 bool result = ExtensionTabUtil::GetTabById( | 367 bool result = ExtensionTabUtil::GetTabById( |
367 tab_id_, profile(), include_incognito(), NULL, NULL, &tab_contents, NULL); | 368 tab_id_, profile(), include_incognito(), NULL, NULL, &tab_contents, NULL); |
368 if (!result || !tab_contents) { | 369 if (!result || !tab_contents) { |
369 error_ = ExtensionErrorUtils::FormatErrorMessage( | 370 error_ = ExtensionErrorUtils::FormatErrorMessage( |
370 keys::kNoTabError, | 371 keys::kNoTabError, |
371 base::IntToString(tab_id_)); | 372 base::IntToString(tab_id_)); |
372 return false; | 373 return false; |
(...skipping 27 matching lines...) Expand all Loading... | |
400 return false; | 401 return false; |
401 } | 402 } |
402 return true; | 403 return true; |
403 } | 404 } |
404 | 405 |
405 AttachDebuggerFunction::AttachDebuggerFunction() {} | 406 AttachDebuggerFunction::AttachDebuggerFunction() {} |
406 | 407 |
407 AttachDebuggerFunction::~AttachDebuggerFunction() {} | 408 AttachDebuggerFunction::~AttachDebuggerFunction() {} |
408 | 409 |
409 bool AttachDebuggerFunction::RunImpl() { | 410 bool AttachDebuggerFunction::RunImpl() { |
411 scoped_ptr<Attach::Params> params(Attach::Params::Create(*args_)); | |
412 EXTENSION_FUNCTION_VALIDATE(params.get()); | |
413 | |
414 tab_id_ = params->target.tab_id; | |
410 if (!InitTabContents()) | 415 if (!InitTabContents()) |
411 return false; | 416 return false; |
412 | 417 |
413 std::string version; | 418 if (!webkit_glue::IsInspectorProtocolVersionSupported( |
414 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &version)); | 419 params->required_version)) { |
415 | |
416 if (!webkit_glue::IsInspectorProtocolVersionSupported(version)) { | |
417 error_ = ExtensionErrorUtils::FormatErrorMessage( | 420 error_ = ExtensionErrorUtils::FormatErrorMessage( |
418 keys::kProtocolVersionNotSupportedError, | 421 keys::kProtocolVersionNotSupportedError, |
419 version); | 422 params->required_version); |
420 return false; | 423 return false; |
421 } | 424 } |
422 | 425 |
423 DevToolsAgentHost* agent = DevToolsAgentHostRegistry::GetDevToolsAgentHost( | 426 DevToolsAgentHost* agent = DevToolsAgentHostRegistry::GetDevToolsAgentHost( |
424 contents_->GetRenderViewHost()); | 427 contents_->GetRenderViewHost()); |
425 DevToolsClientHost* client_host = DevToolsManager::GetInstance()-> | 428 DevToolsClientHost* client_host = DevToolsManager::GetInstance()-> |
426 GetDevToolsClientHostFor(agent); | 429 GetDevToolsClientHostFor(agent); |
427 | 430 |
428 if (client_host != NULL) { | 431 if (client_host != NULL) { |
429 error_ = ExtensionErrorUtils::FormatErrorMessage( | 432 error_ = ExtensionErrorUtils::FormatErrorMessage( |
430 keys::kAlreadyAttachedError, | 433 keys::kAlreadyAttachedError, |
431 base::IntToString(tab_id_)); | 434 base::IntToString(tab_id_)); |
432 return false; | 435 return false; |
433 } | 436 } |
434 | 437 |
435 new ExtensionDevToolsClientHost(contents_, | 438 new ExtensionDevToolsClientHost(contents_, |
436 GetExtension()->id(), | 439 GetExtension()->id(), |
437 GetExtension()->name(), | 440 GetExtension()->name(), |
438 tab_id_); | 441 tab_id_); |
439 SendResponse(true); | 442 SendResponse(true); |
440 return true; | 443 return true; |
441 } | 444 } |
442 | 445 |
443 DetachDebuggerFunction::DetachDebuggerFunction() {} | 446 DetachDebuggerFunction::DetachDebuggerFunction() {} |
444 | 447 |
445 DetachDebuggerFunction::~DetachDebuggerFunction() {} | 448 DetachDebuggerFunction::~DetachDebuggerFunction() {} |
446 | 449 |
447 bool DetachDebuggerFunction::RunImpl() { | 450 bool DetachDebuggerFunction::RunImpl() { |
451 scoped_ptr<Detach::Params> params(Detach::Params::Create(*args_)); | |
452 EXTENSION_FUNCTION_VALIDATE(params.get()); | |
453 | |
454 tab_id_ = params->target.tab_id; | |
448 if (!InitClientHost()) | 455 if (!InitClientHost()) |
449 return false; | 456 return false; |
450 | 457 |
451 client_host_->Close(); | 458 client_host_->Close(); |
452 SendResponse(true); | 459 SendResponse(true); |
453 return true; | 460 return true; |
454 } | 461 } |
455 | 462 |
456 SendCommandDebuggerFunction::SendCommandDebuggerFunction() {} | 463 SendCommandDebuggerFunction::SendCommandDebuggerFunction() {} |
457 | 464 |
458 SendCommandDebuggerFunction::~SendCommandDebuggerFunction() {} | 465 SendCommandDebuggerFunction::~SendCommandDebuggerFunction() {} |
459 | 466 |
460 bool SendCommandDebuggerFunction::RunImpl() { | 467 bool SendCommandDebuggerFunction::RunImpl() { |
468 scoped_ptr<SendCommand::Params> params(SendCommand::Params::Create(*args_)); | |
469 EXTENSION_FUNCTION_VALIDATE(params.get()); | |
461 | 470 |
471 tab_id_ = params->target.tab_id; | |
462 if (!InitClientHost()) | 472 if (!InitClientHost()) |
463 return false; | 473 return false; |
464 | 474 |
465 std::string method; | 475 client_host_->SendMessageToBackend(this, params->method, |
466 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &method)); | 476 params->command_params.get()); |
467 | |
468 Value *params; | |
469 if (!args_->Get(2, ¶ms)) | |
470 params = NULL; | |
471 | |
472 client_host_->SendMessageToBackend(this, method, params); | |
473 return true; | 477 return true; |
474 } | 478 } |
475 | 479 |
476 void SendCommandDebuggerFunction::SendResponseBody( | 480 void SendCommandDebuggerFunction::SendResponseBody( |
477 DictionaryValue* dictionary) { | 481 DictionaryValue* dictionary) { |
not at google - send to devlin
2012/07/23 13:56:23
s/dictionary/response/
mitchellwrosen
2012/07/23 17:30:20
Done.
| |
478 Value* error_body; | 482 Value* error_body; |
479 if (dictionary->Get("error", &error_body)) { | 483 if (dictionary->Get("error", &error_body)) { |
480 base::JSONWriter::Write(error_body, &error_); | 484 base::JSONWriter::Write(error_body, &error_); |
481 SendResponse(false); | 485 SendResponse(false); |
482 return; | 486 return; |
483 } | 487 } |
484 | 488 |
485 Value* result_body; | 489 DictionaryValue* result_body; |
486 if (dictionary->Get("result", &result_body)) | 490 SendCommand::Results::Result result; |
487 SetResult(result_body->DeepCopy()); | 491 if (dictionary->GetDictionary("result", &result_body)) |
488 else | 492 result.additional_properties.Swap(result_body); |
489 SetResult(new DictionaryValue()); | 493 |
494 results_ = SendCommand::Results::Create(result); | |
490 SendResponse(true); | 495 SendResponse(true); |
491 } | 496 } |
OLD | NEW |