Chromium Code Reviews| Index: chrome/browser/extensions/api/debugger/debugger_api.cc |
| diff --git a/chrome/browser/extensions/api/debugger/debugger_api.cc b/chrome/browser/extensions/api/debugger/debugger_api.cc |
| index 66a2b2898ad53a001de61ecbb5944351f1c2cb31..f85b2fcfdc5977dd4502753093cccf3d1971228a 100644 |
| --- a/chrome/browser/extensions/api/debugger/debugger_api.cc |
| +++ b/chrome/browser/extensions/api/debugger/debugger_api.cc |
| @@ -9,6 +9,7 @@ |
| #include <map> |
| #include <set> |
| +#include "base/command_line.h" |
| #include "base/json/json_reader.h" |
| #include "base/json/json_writer.h" |
| #include "base/memory/scoped_ptr.h" |
| @@ -20,20 +21,23 @@ |
| #include "chrome/browser/api/infobars/infobar_service.h" |
| #include "chrome/browser/extensions/api/debugger/debugger_api_constants.h" |
| #include "chrome/browser/extensions/event_router.h" |
| +#include "chrome/browser/extensions/extension_service.h" |
| #include "chrome/browser/extensions/extension_system.h" |
| #include "chrome/browser/extensions/extension_tab_util.h" |
| #include "chrome/browser/infobars/infobar.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h" |
| #include "chrome/common/chrome_notification_types.h" |
| -#include "chrome/common/extensions/api/debugger.h" |
| +#include "chrome/common/chrome_switches.h" |
| #include "chrome/common/extensions/extension.h" |
| #include "content/public/browser/devtools_agent_host.h" |
| #include "content/public/browser/devtools_client_host.h" |
| #include "content/public/browser/devtools_manager.h" |
| #include "content/public/browser/notification_service.h" |
| #include "content/public/browser/notification_source.h" |
| +#include "content/public/browser/render_process_host.h" |
| #include "content/public/browser/render_view_host.h" |
| +#include "content/public/browser/render_widget_host.h" |
| #include "content/public/browser/web_contents.h" |
| #include "content/public/common/content_client.h" |
| #include "content/public/common/url_constants.h" |
| @@ -45,8 +49,10 @@ |
| using content::DevToolsAgentHost; |
| using content::DevToolsClientHost; |
| using content::DevToolsManager; |
| +using content::RenderProcessHost; |
| +using content::RenderViewHost; |
| +using content::RenderWidgetHost; |
| using content::WebContents; |
| -using extensions::api::debugger::Debuggee; |
| using extensions::ErrorUtils; |
| namespace keys = debugger_api_constants; |
| @@ -98,7 +104,7 @@ class ExtensionDevToolsClientHost : public DevToolsClientHost, |
| ExtensionDevToolsClientHost(WebContents* web_contents, |
| const std::string& extension_id, |
| const std::string& extension_name, |
| - int tab_id); |
| + const Debuggee& debuggee); |
| virtual ~ExtensionDevToolsClientHost(); |
| @@ -127,7 +133,7 @@ class ExtensionDevToolsClientHost : public DevToolsClientHost, |
| WebContents* web_contents_; |
| std::string extension_id_; |
| - int tab_id_; |
| + Debuggee debuggee_; |
| content::NotificationRegistrar registrar_; |
| int last_request_id_; |
| typedef std::map<int, scoped_refptr<DebuggerSendCommandFunction> > |
| @@ -178,17 +184,25 @@ class AttachedClientHosts { |
| } // namespace |
| +static void CopyDebuggee(Debuggee & dst, const Debuggee& src) { |
| + if (src.tab_id) |
| + dst.tab_id.reset(new int(*src.tab_id)); |
| + if (src.extension_id) |
| + dst.extension_id.reset(new std::string(*src.extension_id)); |
| +} |
| + |
| ExtensionDevToolsClientHost::ExtensionDevToolsClientHost( |
| WebContents* web_contents, |
| const std::string& extension_id, |
| const std::string& extension_name, |
| - int tab_id) |
| + const Debuggee& debuggee) |
| : web_contents_(web_contents), |
| extension_id_(extension_id), |
| - tab_id_(tab_id), |
| last_request_id_(0), |
| infobar_delegate_(NULL), |
| detach_reason_(OnDetach::REASON_TARGET_CLOSED) { |
| + CopyDebuggee(debuggee_, debuggee); |
| + |
| AttachedClientHosts::GetInstance()->Add(this); |
| // Detach from debugger when extension unloads. |
| @@ -202,14 +216,16 @@ ExtensionDevToolsClientHost::ExtensionDevToolsClientHost( |
| web_contents_->GetRenderViewHost())); |
| DevToolsManager::GetInstance()->RegisterDevToolsClientHostFor(agent, this); |
| - InfoBarService* infobar_service = |
| - InfoBarService::FromWebContents(web_contents_); |
| - infobar_delegate_ = ExtensionDevToolsInfoBarDelegate::Create(infobar_service, |
| - extension_name, |
| - this); |
| - if (infobar_delegate_) { |
| - registrar_.Add(this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, |
| - content::Source<InfoBarService>(infobar_service)); |
| + if (!CommandLine::ForCurrentProcess()-> |
| + HasSwitch(switches::kExtensionDebuggingSilent)) { |
| + InfoBarService* infobar_service = |
| + InfoBarService::FromWebContents(web_contents_); |
| + infobar_delegate_ = ExtensionDevToolsInfoBarDelegate::Create( |
| + infobar_service, extension_name, this); |
| + if (infobar_delegate_) { |
| + registrar_.Add(this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, |
| + content::Source<InfoBarService>(infobar_service)); |
| + } |
| } |
| } |
| @@ -277,9 +293,7 @@ void ExtensionDevToolsClientHost::SendDetachedEvent() { |
| Profile::FromBrowserContext(web_contents_->GetBrowserContext()); |
| if (profile != NULL && |
| extensions::ExtensionSystem::Get(profile)->event_router()) { |
| - Debuggee debuggee; |
| - debuggee.tab_id = tab_id_; |
| - scoped_ptr<base::ListValue> args(OnDetach::Create(debuggee, |
| + scoped_ptr<base::ListValue> args(OnDetach::Create(debuggee_, |
| detach_reason_)); |
| scoped_ptr<extensions::Event> event(new extensions::Event( |
| keys::kOnDetach, args.Pass())); |
| @@ -329,15 +343,12 @@ void ExtensionDevToolsClientHost::DispatchOnInspectorFrontend( |
| if (!dictionary->GetString("method", &method_name)) |
| return; |
| - Debuggee debuggee; |
| - debuggee.tab_id = tab_id_; |
| - |
| OnEvent::Params params; |
| DictionaryValue* params_value; |
| if (dictionary->GetDictionary("params", ¶ms_value)) |
| params.additional_properties.Swap(params_value); |
| - scoped_ptr<ListValue> args(OnEvent::Create(debuggee, method_name, params)); |
| + scoped_ptr<ListValue> args(OnEvent::Create(debuggee_, method_name, params)); |
| scoped_ptr<extensions::Event> event(new extensions::Event( |
| keys::kOnEvent, args.Pass())); |
| event->restrict_to_profile = profile; |
| @@ -411,32 +422,101 @@ bool ExtensionDevToolsInfoBarDelegate::Cancel() { |
| DebuggerFunction::DebuggerFunction() |
| : contents_(0), |
| - tab_id_(0), |
| client_host_(0) { |
| } |
| +void DebuggerFunction::FormatErrorMessage(const std::string& format) { |
| + error_ = ErrorUtils::FormatErrorMessage( |
| + format, |
| + debuggee_.tab_id ? |
| + keys::kTabTargetType : |
| + keys::kExtensionTargetType, |
| + debuggee_.tab_id ? |
| + base::IntToString(*debuggee_.tab_id) : |
| + *debuggee_.extension_id); |
| +} |
| + |
| +static WebContents* FindWebContentsForExtension( |
|
Matt Perry
2013/02/20 19:52:01
There can be multiple WebContents for an extension
Vladislav Kaznacheev
2013/02/21 09:39:09
Thanks for the pointer! Done.
On 2013/02/20 19:52:
|
| + const extensions::Extension* extension) { |
| + for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator()); |
| + !it.IsAtEnd(); it.Advance()) { |
| + RenderProcessHost* render_process_host = it.GetCurrentValue(); |
| + DCHECK(render_process_host); |
| + |
| + // Ignore processes that don't have a connection, such as crashed tabs. |
| + if (!render_process_host->HasConnection()) |
| + continue; |
| + |
| + RenderProcessHost::RenderWidgetHostsIterator rwit( |
| + render_process_host->GetRenderWidgetHostsIterator()); |
| + for (; !rwit.IsAtEnd(); rwit.Advance()) { |
| + const RenderWidgetHost* widget = rwit.GetCurrentValue(); |
| + DCHECK(widget); |
| + if (!widget || !widget->IsRenderView()) |
| + continue; |
| + |
| + RenderViewHost* rvh = |
| + RenderViewHost::From(const_cast<RenderWidgetHost*>(widget)); |
| + |
| + WebContents* web_contents = WebContents::FromRenderViewHost(rvh); |
| + if (web_contents) { |
| + GURL url = web_contents->GetURL(); |
| + if (url.host() == extension->id()) { |
| + return web_contents; |
| + } |
| + } |
| + } |
| + } |
| + return NULL; |
| +} |
| + |
| bool DebuggerFunction::InitWebContents() { |
| // Find the WebContents that contains this tab id. |
| contents_ = NULL; |
| - WebContents* web_contents = NULL; |
| - bool result = ExtensionTabUtil::GetTabById( |
| - tab_id_, profile(), include_incognito(), NULL, NULL, &web_contents, NULL); |
| - if (!result || !web_contents) { |
| - error_ = ErrorUtils::FormatErrorMessage( |
| - keys::kNoTabError, |
| - base::IntToString(tab_id_)); |
| - return false; |
| + if (debuggee_.tab_id) { |
| + WebContents* web_contents = NULL; |
| + bool result = ExtensionTabUtil::GetTabById( |
| + *debuggee_.tab_id, profile(), include_incognito(), NULL, NULL, |
| + &web_contents, NULL); |
| + if (!result || !web_contents) { |
| + FormatErrorMessage(keys::kNoTargetError); |
| + return false; |
| + } |
| + contents_ = web_contents; |
| + |
| + if (content::HasWebUIScheme(contents_->GetURL())) { |
| + error_ = ErrorUtils::FormatErrorMessage( |
| + keys::kAttachToWebUIError, |
| + contents_->GetURL().scheme()); |
| + return false; |
| + } |
| + |
| + return true; |
| } |
| - contents_ = web_contents; |
| - if (content::HasWebUIScheme(contents_->GetURL())) { |
| - error_ = ErrorUtils::FormatErrorMessage( |
| - keys::kAttachToWebUIError, |
| - contents_->GetURL().scheme()); |
| + if (debuggee_.extension_id) { |
| + if (!CommandLine::ForCurrentProcess()-> |
| + HasSwitch(switches::kExtensionDebuggingSilent)) { |
| + error_ = ErrorUtils::FormatErrorMessage( |
| + keys::kSilentDebuggingRequired, |
| + switches::kExtensionDebuggingSilent); |
| + return false; |
| + } |
| + |
| + const extensions::Extension* extension = profile()->GetExtensionService()-> |
| + extensions()->GetByID(*debuggee_.extension_id); |
| + if (extension) { |
| + contents_ = FindWebContentsForExtension(extension); |
| + if (contents_) |
| + return true; |
| + } |
| + |
| + FormatErrorMessage(keys::kNoTargetError); |
| return false; |
| } |
| - return true; |
| + error_ = keys::kInvalidTargetError; |
| + return false; |
| } |
| bool DebuggerFunction::InitClientHost() { |
| @@ -449,9 +529,7 @@ bool DebuggerFunction::InitClientHost() { |
| if (!client_host_ || |
| !client_host_->MatchesContentsAndExtensionId(contents_, |
| GetExtension()->id())) { |
| - error_ = ErrorUtils::FormatErrorMessage( |
| - keys::kNotAttachedError, |
| - base::IntToString(tab_id_)); |
| + FormatErrorMessage(keys::kNotAttachedError); |
| return false; |
| } |
| return true; |
| @@ -465,7 +543,7 @@ bool DebuggerAttachFunction::RunImpl() { |
| scoped_ptr<Attach::Params> params(Attach::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params.get()); |
| - tab_id_ = params->target.tab_id; |
| + CopyDebuggee(debuggee_, params->target); |
| if (!InitWebContents()) |
| return false; |
| @@ -483,16 +561,14 @@ bool DebuggerAttachFunction::RunImpl() { |
| GetDevToolsClientHostFor(agent); |
| if (client_host != NULL) { |
| - error_ = ErrorUtils::FormatErrorMessage( |
| - keys::kAlreadyAttachedError, |
| - base::IntToString(tab_id_)); |
| + FormatErrorMessage(keys::kAlreadyAttachedError); |
| return false; |
| } |
| new ExtensionDevToolsClientHost(contents_, |
| GetExtension()->id(), |
| GetExtension()->name(), |
| - tab_id_); |
| + debuggee_); |
| SendResponse(true); |
| return true; |
| } |
| @@ -505,7 +581,7 @@ bool DebuggerDetachFunction::RunImpl() { |
| scoped_ptr<Detach::Params> params(Detach::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params.get()); |
| - tab_id_ = params->target.tab_id; |
| + CopyDebuggee(debuggee_, params->target); |
| if (!InitClientHost()) |
| return false; |
| @@ -522,7 +598,7 @@ bool DebuggerSendCommandFunction::RunImpl() { |
| scoped_ptr<SendCommand::Params> params(SendCommand::Params::Create(*args_)); |
| EXTENSION_FUNCTION_VALIDATE(params.get()); |
| - tab_id_ = params->target.tab_id; |
| + CopyDebuggee(debuggee_, params->target); |
| if (!InitClientHost()) |
| return false; |