Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(52)

Side by Side Diff: chrome/browser/extensions/api/debugger/debugger_api.cc

Issue 10803043: Refactor chrome.debugger api to use the JSON schema compiler. Also modified the (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Small change Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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)
Matt Tytel 2012/07/20 21:26:53 nit: People prefer wrapping in {} if the whole sta
mitchellwrosen 2012/07/21 00:18:02 Done.
239 protocol_request.Set("params", params->DeepCopy()); 241 protocol_request.Set("params",
242 command_params->additional_properties.DeepCopy());
240 243
241 std::string json_args; 244 std::string json_args;
242 base::JSONWriter::Write(&protocol_request, &json_args); 245 base::JSONWriter::Write(&protocol_request, &json_args);
243 DevToolsManager::GetInstance()->DispatchOnInspectorBackend(this, json_args); 246 DevToolsManager::GetInstance()->DispatchOnInspectorBackend(this, json_args);
244 } 247 }
245 248
246 void ExtensionDevToolsClientHost::SendDetachedEvent() { 249 void ExtensionDevToolsClientHost::SendDetachedEvent() {
247 Profile* profile = 250 Profile* profile =
248 Profile::FromBrowserContext(web_contents_->GetBrowserContext()); 251 Profile::FromBrowserContext(web_contents_->GetBrowserContext());
249 if (profile != NULL && profile->GetExtensionEventRouter()) { 252 if (profile != NULL && profile->GetExtensionEventRouter()) {
250 ListValue args; 253 Debuggee debuggee;
251 args.Append(CreateDebuggeeId(tab_id_)); 254 debuggee.tab_id = tab_id_;
252 255
256 scoped_ptr<base::ListValue> args(OnDetach::Create(debuggee));
253 std::string json_args; 257 std::string json_args;
254 base::JSONWriter::Write(&args, &json_args); 258 base::JSONWriter::Write(args.get(), &json_args);
255 259
256 profile->GetExtensionEventRouter()->DispatchEventToExtension( 260 profile->GetExtensionEventRouter()->DispatchEventToExtension(
257 extension_id_, keys::kOnDetach, json_args, profile, GURL()); 261 extension_id_, keys::kOnDetach, json_args, profile, GURL());
258 } 262 }
259 } 263 }
260 264
261 void ExtensionDevToolsClientHost::Observe( 265 void ExtensionDevToolsClientHost::Observe(
262 int type, 266 int type,
263 const content::NotificationSource& source, 267 const content::NotificationSource& source,
264 const content::NotificationDetails& details) { 268 const content::NotificationDetails& details) {
(...skipping 14 matching lines...) Expand all
279 } 283 }
280 } 284 }
281 285
282 void ExtensionDevToolsClientHost::DispatchOnInspectorFrontend( 286 void ExtensionDevToolsClientHost::DispatchOnInspectorFrontend(
283 const std::string& message) { 287 const std::string& message) {
284 Profile* profile = 288 Profile* profile =
285 Profile::FromBrowserContext(web_contents_->GetBrowserContext()); 289 Profile::FromBrowserContext(web_contents_->GetBrowserContext());
286 if (profile == NULL || !profile->GetExtensionEventRouter()) 290 if (profile == NULL || !profile->GetExtensionEventRouter())
287 return; 291 return;
288 292
289 scoped_ptr<Value> result(base::JSONReader::Read(message)); 293 scoped_ptr<Value> result_value(base::JSONReader::Read(message));
290 if (!result->IsType(Value::TYPE_DICTIONARY)) 294 if (!result_value->IsType(Value::TYPE_DICTIONARY))
291 return; 295 return;
292 DictionaryValue* dictionary = static_cast<DictionaryValue*>(result.get()); 296 SendCommand::Results::Result result;
297 result.additional_properties.Swap(
298 static_cast<DictionaryValue*>(result_value.get()));
293 299
294 int id; 300 int id;
295 if (!dictionary->GetInteger("id", &id)) { 301 if (!result.additional_properties.GetInteger("id", &id)) {
296 std::string method_name; 302 std::string method_name;
297 if (!dictionary->GetString("method", &method_name)) 303 if (!result.additional_properties.GetString("method", &method_name))
298 return; 304 return;
299 305
300 ListValue args; 306 Debuggee debuggee;
301 args.Append(CreateDebuggeeId(tab_id_)); 307 debuggee.tab_id = tab_id_;
302 args.Append(Value::CreateStringValue(method_name)); 308
309 std::string method = method_name;
Matt Tytel 2012/07/20 21:26:54 Got an extra string here I think.
mitchellwrosen 2012/07/21 00:18:02 Done.
310
311 OnEvent::Params params;
303 Value* params_value; 312 Value* params_value;
304 if (dictionary->Get("params", &params_value)) 313 if (result.additional_properties.Get("params", &params_value))
305 args.Append(params_value->DeepCopy()); 314 params.additional_properties.Swap(
315 static_cast<DictionaryValue*>(params_value));
306 316
317 scoped_ptr<ListValue> args(OnEvent::Create(debuggee, method, params));
307 std::string json_args; 318 std::string json_args;
308 base::JSONWriter::Write(&args, &json_args); 319 base::JSONWriter::Write(args.get(), &json_args);
309 320
310 profile->GetExtensionEventRouter()->DispatchEventToExtension( 321 profile->GetExtensionEventRouter()->DispatchEventToExtension(
311 extension_id_, keys::kOnEvent, json_args, profile, GURL()); 322 extension_id_, keys::kOnEvent, json_args, profile, GURL());
312 } else { 323 } else {
313 SendCommandDebuggerFunction* function = pending_requests_[id]; 324 SendCommandDebuggerFunction* function = pending_requests_[id];
314 if (!function) 325 if (!function)
315 return; 326 return;
316 327
317 function->SendResponseBody(dictionary); 328 function->SendResponseBody(result);
318 pending_requests_.erase(id); 329 pending_requests_.erase(id);
319 } 330 }
320 } 331 }
321 332
322 ExtensionDevToolsInfoBarDelegate::ExtensionDevToolsInfoBarDelegate( 333 ExtensionDevToolsInfoBarDelegate::ExtensionDevToolsInfoBarDelegate(
323 InfoBarTabHelper* infobar_helper, 334 InfoBarTabHelper* infobar_helper,
324 const std::string& client_name) 335 const std::string& client_name)
325 : ConfirmInfoBarDelegate(infobar_helper), 336 : ConfirmInfoBarDelegate(infobar_helper),
326 client_name_(client_name) { 337 client_name_(client_name) {
327 } 338 }
(...skipping 19 matching lines...) Expand all
347 UTF8ToUTF16(client_name_)); 358 UTF8ToUTF16(client_name_));
348 } 359 }
349 360
350 DebuggerFunction::DebuggerFunction() 361 DebuggerFunction::DebuggerFunction()
351 : contents_(0), 362 : contents_(0),
352 tab_id_(0), 363 tab_id_(0),
353 client_host_(0) { 364 client_host_(0) {
354 } 365 }
355 366
356 bool DebuggerFunction::InitTabContents() { 367 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. 368 // Find the TabContents that contains this tab id.
364 contents_ = NULL; 369 contents_ = NULL;
365 TabContents* tab_contents = NULL; 370 TabContents* tab_contents = NULL;
366 bool result = ExtensionTabUtil::GetTabById( 371 bool result = ExtensionTabUtil::GetTabById(
367 tab_id_, profile(), include_incognito(), NULL, NULL, &tab_contents, NULL); 372 tab_id_, profile(), include_incognito(), NULL, NULL, &tab_contents, NULL);
368 if (!result || !tab_contents) { 373 if (!result || !tab_contents) {
369 error_ = ExtensionErrorUtils::FormatErrorMessage( 374 error_ = ExtensionErrorUtils::FormatErrorMessage(
370 keys::kNoTabError, 375 keys::kNoTabError,
371 base::IntToString(tab_id_)); 376 base::IntToString(tab_id_));
372 return false; 377 return false;
(...skipping 27 matching lines...) Expand all
400 return false; 405 return false;
401 } 406 }
402 return true; 407 return true;
403 } 408 }
404 409
405 AttachDebuggerFunction::AttachDebuggerFunction() {} 410 AttachDebuggerFunction::AttachDebuggerFunction() {}
406 411
407 AttachDebuggerFunction::~AttachDebuggerFunction() {} 412 AttachDebuggerFunction::~AttachDebuggerFunction() {}
408 413
409 bool AttachDebuggerFunction::RunImpl() { 414 bool AttachDebuggerFunction::RunImpl() {
415 scoped_ptr<Attach::Params> params(Attach::Params::Create(*args_));
416 EXTENSION_FUNCTION_VALIDATE(params.get());
417
418 tab_id_ = params->target.tab_id;
410 if (!InitTabContents()) 419 if (!InitTabContents())
411 return false; 420 return false;
412 421
413 std::string version; 422 if (!webkit_glue::IsInspectorProtocolVersionSupported(
414 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &version)); 423 params->required_version)) {
415
416 if (!webkit_glue::IsInspectorProtocolVersionSupported(version)) {
417 error_ = ExtensionErrorUtils::FormatErrorMessage( 424 error_ = ExtensionErrorUtils::FormatErrorMessage(
418 keys::kProtocolVersionNotSupportedError, 425 keys::kProtocolVersionNotSupportedError,
419 version); 426 params->required_version);
420 return false; 427 return false;
421 } 428 }
422 429
423 DevToolsAgentHost* agent = DevToolsAgentHostRegistry::GetDevToolsAgentHost( 430 DevToolsAgentHost* agent = DevToolsAgentHostRegistry::GetDevToolsAgentHost(
424 contents_->GetRenderViewHost()); 431 contents_->GetRenderViewHost());
425 DevToolsClientHost* client_host = DevToolsManager::GetInstance()-> 432 DevToolsClientHost* client_host = DevToolsManager::GetInstance()->
426 GetDevToolsClientHostFor(agent); 433 GetDevToolsClientHostFor(agent);
427 434
428 if (client_host != NULL) { 435 if (client_host != NULL) {
429 error_ = ExtensionErrorUtils::FormatErrorMessage( 436 error_ = ExtensionErrorUtils::FormatErrorMessage(
430 keys::kAlreadyAttachedError, 437 keys::kAlreadyAttachedError,
431 base::IntToString(tab_id_)); 438 base::IntToString(tab_id_));
432 return false; 439 return false;
433 } 440 }
434 441
435 new ExtensionDevToolsClientHost(contents_, 442 new ExtensionDevToolsClientHost(contents_,
436 GetExtension()->id(), 443 GetExtension()->id(),
437 GetExtension()->name(), 444 GetExtension()->name(),
438 tab_id_); 445 tab_id_);
439 SendResponse(true); 446 SendResponse(true);
440 return true; 447 return true;
441 } 448 }
442 449
443 DetachDebuggerFunction::DetachDebuggerFunction() {} 450 DetachDebuggerFunction::DetachDebuggerFunction() {}
444 451
445 DetachDebuggerFunction::~DetachDebuggerFunction() {} 452 DetachDebuggerFunction::~DetachDebuggerFunction() {}
446 453
447 bool DetachDebuggerFunction::RunImpl() { 454 bool DetachDebuggerFunction::RunImpl() {
455 scoped_ptr<Detach::Params> params(Detach::Params::Create(*args_));
456 EXTENSION_FUNCTION_VALIDATE(params.get());
457
458 tab_id_ = params->target.tab_id;
448 if (!InitClientHost()) 459 if (!InitClientHost())
449 return false; 460 return false;
450 461
451 client_host_->Close(); 462 client_host_->Close();
452 SendResponse(true); 463 SendResponse(true);
453 return true; 464 return true;
454 } 465 }
455 466
456 SendCommandDebuggerFunction::SendCommandDebuggerFunction() {} 467 SendCommandDebuggerFunction::SendCommandDebuggerFunction() {}
457 468
458 SendCommandDebuggerFunction::~SendCommandDebuggerFunction() {} 469 SendCommandDebuggerFunction::~SendCommandDebuggerFunction() {}
459 470
460 bool SendCommandDebuggerFunction::RunImpl() { 471 bool SendCommandDebuggerFunction::RunImpl() {
472 scoped_ptr<SendCommand::Params> params(SendCommand::Params::Create(*args_));
473 EXTENSION_FUNCTION_VALIDATE(params.get());
461 474
475 tab_id_ = params->target.tab_id;
462 if (!InitClientHost()) 476 if (!InitClientHost())
463 return false; 477 return false;
464 478
465 std::string method; 479 client_host_->SendMessageToBackend(this, params->method,
466 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &method)); 480 params->command_params.get());
467
468 Value *params;
469 if (!args_->Get(2, &params))
470 params = NULL;
471
472 client_host_->SendMessageToBackend(this, method, params);
473 return true; 481 return true;
474 } 482 }
475 483
476 void SendCommandDebuggerFunction::SendResponseBody( 484 void SendCommandDebuggerFunction::SendResponseBody(
477 DictionaryValue* dictionary) { 485 const SendCommand::Results::Result& result) {
478 Value* error_body; 486 Value* error_body;
479 if (dictionary->Get("error", &error_body)) { 487 if (result.additional_properties.Get("error", &error_body)) {
480 base::JSONWriter::Write(error_body, &error_); 488 base::JSONWriter::Write(error_body, &error_);
481 SendResponse(false); 489 SendResponse(false);
482 return; 490 return;
483 } 491 }
484 492
485 Value* result_body; 493 results_ = SendCommand::Results::Create(result);
Matt Tytel 2012/07/20 21:26:54 Not positive, but I think you may still need to pu
486 if (dictionary->Get("result", &result_body))
487 SetResult(result_body->DeepCopy());
488 else
489 SetResult(new DictionaryValue());
490 SendResponse(true); 494 SendResponse(true);
491 } 495 }
OLDNEW
« no previous file with comments | « chrome/browser/extensions/api/debugger/debugger_api.h ('k') | chrome/browser/extensions/api/debugger/debugger_api_constants.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698