Support shared workers as debug targets for chrome.debugger API
BUG=226014
Review URL: https://chromiumcodereview.appspot.com/13517002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@192569 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/extensions/api/debugger/debugger_api.cc b/chrome/browser/extensions/api/debugger/debugger_api.cc
index a503a75..b41d28a 100644
--- a/chrome/browser/extensions/api/debugger/debugger_api.cc
+++ b/chrome/browser/extensions/api/debugger/debugger_api.cc
@@ -42,6 +42,7 @@
#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/browser/worker_service.h"
#include "content/public/common/content_client.h"
#include "content/public/common/url_constants.h"
#include "extensions/common/error_utils.h"
@@ -56,6 +57,7 @@
using content::RenderViewHost;
using content::RenderWidgetHost;
using content::WebContents;
+using content::WorkerService;
using extensions::ErrorUtils;
namespace keys = debugger_api_constants;
@@ -72,7 +74,7 @@
// Creates an extension dev tools delegate and adds it to |infobar_service|.
// Returns a pointer to the delegate if it was successfully added.
static ExtensionDevToolsInfoBarDelegate* Create(
- WebContents* web_contents,
+ RenderViewHost* rvh,
const std::string& client_name);
// Associates DevToolsClientHost with this infobar delegate.
@@ -105,7 +107,8 @@
public content::NotificationObserver {
public:
ExtensionDevToolsClientHost(
- WebContents* web_contents,
+ Profile* profile,
+ DevToolsAgentHost* agent_host,
const std::string& extension_id,
const std::string& extension_name,
const Debuggee& debuggee,
@@ -113,8 +116,7 @@
virtual ~ExtensionDevToolsClientHost();
- bool MatchesContentsAndExtensionId(WebContents* web_contents,
- const std::string& extension_id);
+ const std::string& extension_id() { return extension_id_; }
void Close();
void SendMessageToBackend(DebuggerSendCommandFunction* function,
const std::string& method,
@@ -136,7 +138,8 @@
const content::NotificationSource& source,
const content::NotificationDetails& details) OVERRIDE;
- WebContents* web_contents_;
+ Profile* profile_;
+ scoped_refptr<DevToolsAgentHost> agent_host_;
std::string extension_id_;
Debuggee debuggee_;
content::NotificationRegistrar registrar_;
@@ -169,22 +172,22 @@
client_hosts_.erase(client_host);
}
- ExtensionDevToolsClientHost* Lookup(WebContents* contents) {
- for (std::set<DevToolsClientHost*>::iterator it = client_hosts_.begin();
+ ExtensionDevToolsClientHost* Lookup(DevToolsAgentHost* agent_host,
+ const std::string& extension_id) {
+ DevToolsManager* manager = DevToolsManager::GetInstance();
+ for (ClientHostSet::iterator it = client_hosts_.begin();
it != client_hosts_.end(); ++it) {
- DevToolsAgentHost* agent_host =
- DevToolsManager::GetInstance()->GetDevToolsAgentHostFor(*it);
- if (!agent_host)
- continue;
- content::RenderViewHost* rvh = agent_host->GetRenderViewHost();
- if (rvh && WebContents::FromRenderViewHost(rvh) == contents)
- return static_cast<ExtensionDevToolsClientHost*>(*it);
+ ExtensionDevToolsClientHost* client_host = *it;
+ if (manager->GetDevToolsAgentHostFor(client_host) == agent_host &&
+ client_host->extension_id() == extension_id)
+ return client_host;
}
return NULL;
}
private:
- std::set<DevToolsClientHost*> client_hosts_;
+ typedef std::set<ExtensionDevToolsClientHost*> ClientHostSet;
+ ClientHostSet client_hosts_;
};
static extensions::ExtensionHost* GetExtensionBackgroundHost(
@@ -213,6 +216,7 @@
static const char kTargetTypePage[] = "page";
static const char kTargetTypeBackgroundPage[] = "background_page";
+static const char kTargetTypeWorker[] = "worker";
static base::Value* SerializePageInfo(RenderViewHost* rvh) {
WebContents* web_contents = WebContents::FromRenderViewHost(rvh);
@@ -237,8 +241,7 @@
} else {
// This RenderViewHost belongs to a regular page.
dictionary->SetString(kTargetTypeField, kTargetTypePage);
- dictionary->SetString(kTargetTitleField,
- UTF16ToUTF8(net::EscapeForHTML(web_contents->GetTitle())));
+ dictionary->SetString(kTargetTitleField, web_contents->GetTitle());
content::NavigationController& controller = web_contents->GetController();
content::NavigationEntry* entry = controller.GetActiveEntry();
@@ -251,6 +254,21 @@
return dictionary;
}
+static base::Value* SerializeWorkerInfo(
+ const WorkerService::WorkerInfo& worker) {
+ base::DictionaryValue* dictionary = new base::DictionaryValue;
+
+ scoped_refptr<DevToolsAgentHost> agent(DevToolsAgentHost::GetForWorker(
+ worker.process_id, worker.route_id));
+ dictionary->SetString(kTargetIdField, agent->GetId());
+ dictionary->SetString(kTargetTypeField, kTargetTypeWorker);
+ dictionary->SetString(kTargetTitleField, worker.name);
+ dictionary->SetString(kTargetUrlField, worker.url.spec());
+ dictionary->SetBoolean(kTargetAttachedField, agent->IsAttached());
+
+ return dictionary;
+}
+
} // namespace
static void CopyDebuggee(Debuggee & dst, const Debuggee& src) {
@@ -263,12 +281,14 @@
}
ExtensionDevToolsClientHost::ExtensionDevToolsClientHost(
- WebContents* web_contents,
+ Profile* profile,
+ DevToolsAgentHost* agent_host,
const std::string& extension_id,
const std::string& extension_name,
const Debuggee& debuggee,
ExtensionDevToolsInfoBarDelegate* infobar_delegate)
- : web_contents_(web_contents),
+ : profile_(profile),
+ agent_host_(agent_host),
extension_id_(extension_id),
last_request_id_(0),
infobar_delegate_(infobar_delegate),
@@ -278,15 +298,12 @@
AttachedClientHosts::GetInstance()->Add(this);
// Detach from debugger when extension unloads.
- Profile* profile =
- Profile::FromBrowserContext(web_contents_->GetBrowserContext());
registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
- content::Source<Profile>(profile));
+ content::Source<Profile>(profile_));
// Attach to debugger and tell it we are ready.
- scoped_refptr<DevToolsAgentHost> agent(DevToolsAgentHost::GetOrCreateFor(
- web_contents_->GetRenderViewHost()));
- DevToolsManager::GetInstance()->RegisterDevToolsClientHostFor(agent, this);
+ DevToolsManager::GetInstance()->
+ RegisterDevToolsClientHostFor(agent_host_, this);
if (infobar_delegate_) {
infobar_delegate_->AttachClientHost(this);
@@ -309,12 +326,6 @@
AttachedClientHosts::GetInstance()->Remove(this);
}
-bool ExtensionDevToolsClientHost::MatchesContentsAndExtensionId(
- WebContents* web_contents,
- const std::string& extension_id) {
- return web_contents == web_contents_ && extension_id_ == extension_id;
-}
-
// DevToolsClientHost interface
void ExtensionDevToolsClientHost::InspectedContentsClosing() {
SendDetachedEvent();
@@ -354,18 +365,16 @@
}
void ExtensionDevToolsClientHost::SendDetachedEvent() {
- Profile* profile =
- Profile::FromBrowserContext(web_contents_->GetBrowserContext());
- if (profile != NULL &&
- extensions::ExtensionSystem::Get(profile)->event_router()) {
- scoped_ptr<base::ListValue> args(OnDetach::Create(debuggee_,
- detach_reason_));
- scoped_ptr<extensions::Event> event(new extensions::Event(
- keys::kOnDetach, args.Pass()));
- event->restrict_to_profile = profile;
- extensions::ExtensionSystem::Get(profile)->event_router()->
- DispatchEventToExtension(extension_id_, event.Pass());
- }
+ if (!extensions::ExtensionSystem::Get(profile_)->event_router())
+ return;
+
+ scoped_ptr<base::ListValue> args(OnDetach::Create(debuggee_,
+ detach_reason_));
+ scoped_ptr<extensions::Event> event(new extensions::Event(
+ keys::kOnDetach, args.Pass()));
+ event->restrict_to_profile = profile_;
+ extensions::ExtensionSystem::Get(profile_)->event_router()->
+ DispatchEventToExtension(extension_id_, event.Pass());
}
void ExtensionDevToolsClientHost::Observe(
@@ -391,10 +400,7 @@
void ExtensionDevToolsClientHost::DispatchOnInspectorFrontend(
const std::string& message) {
- Profile* profile =
- Profile::FromBrowserContext(web_contents_->GetBrowserContext());
- if (profile == NULL ||
- !extensions::ExtensionSystem::Get(profile)->event_router())
+ if (!extensions::ExtensionSystem::Get(profile_)->event_router())
return;
scoped_ptr<Value> result(base::JSONReader::Read(message));
@@ -416,8 +422,8 @@
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;
- extensions::ExtensionSystem::Get(profile)->event_router()->
+ event->restrict_to_profile = profile_;
+ extensions::ExtensionSystem::Get(profile_)->event_router()->
DispatchEventToExtension(extension_id_, event.Pass());
} else {
DebuggerSendCommandFunction* function = pending_requests_[id];
@@ -431,12 +437,20 @@
// static
ExtensionDevToolsInfoBarDelegate* ExtensionDevToolsInfoBarDelegate::Create(
- WebContents* web_contents,
+ RenderViewHost* rvh,
const std::string& client_name) {
+ if (!rvh)
+ return NULL;
+
+ WebContents* web_contents = WebContents::FromRenderViewHost(rvh);
+ if (!web_contents)
+ return NULL;
+
InfoBarService* infobar_service =
InfoBarService::FromWebContents(web_contents);
if (!infobar_service)
return NULL;
+
return static_cast<ExtensionDevToolsInfoBarDelegate*>(
infobar_service->AddInfoBar(scoped_ptr<InfoBarDelegate>(
new ExtensionDevToolsInfoBarDelegate(infobar_service, client_name))));
@@ -492,8 +506,10 @@
}
DebuggerFunction::DebuggerFunction()
- : contents_(0),
- client_host_(0) {
+ : client_host_(0) {
+}
+
+DebuggerFunction::~DebuggerFunction() {
}
void DebuggerFunction::FormatErrorMessage(const std::string& format) {
@@ -508,7 +524,7 @@
format, keys::kOpaqueTargetType, *debuggee_.target_id);
}
-bool DebuggerFunction::InitWebContents() {
+bool DebuggerFunction::InitAgentHost() {
if (debuggee_.tab_id) {
WebContents* web_contents = NULL;
bool result = ExtensionTabUtil::GetTabById(
@@ -521,29 +537,25 @@
web_contents->GetURL().scheme());
return false;
}
- contents_ = web_contents;
+ agent_host_ = DevToolsAgentHost::GetOrCreateFor(
+ web_contents->GetRenderViewHost());
}
} else if (debuggee_.extension_id) {
extensions::ExtensionHost* extension_host =
extensions::ExtensionSystem::Get(profile())->process_manager()->
GetBackgroundHostForExtension(*debuggee_.extension_id);
if (extension_host) {
- contents_ = WebContents::FromRenderViewHost(
+ agent_host_ = DevToolsAgentHost::GetOrCreateFor(
extension_host->render_view_host());
}
} else if (debuggee_.target_id) {
- DevToolsAgentHost* agent_host =
- DevToolsAgentHost::GetForId(*debuggee_.target_id);
- if (agent_host) {
- contents_ = WebContents::FromRenderViewHost(
- agent_host->GetRenderViewHost());
- }
+ agent_host_ = DevToolsAgentHost::GetForId(*debuggee_.target_id);
} else {
error_ = keys::kInvalidTargetError;
return false;
}
- if (!contents_) {
+ if (!agent_host_) {
FormatErrorMessage(keys::kNoTargetError);
return false;
}
@@ -551,15 +563,13 @@
}
bool DebuggerFunction::InitClientHost() {
- if (!InitWebContents())
+ if (!InitAgentHost())
return false;
- // Don't fetch rvh from the contents since it'll be wrong upon navigation.
- client_host_ = AttachedClientHosts::GetInstance()->Lookup(contents_);
+ client_host_ = AttachedClientHosts::GetInstance()->
+ Lookup(agent_host_, GetExtension()->id());
- if (!client_host_ ||
- !client_host_->MatchesContentsAndExtensionId(contents_,
- GetExtension()->id())) {
+ if (!client_host_) {
FormatErrorMessage(keys::kNotAttachedError);
return false;
}
@@ -575,7 +585,7 @@
EXTENSION_FUNCTION_VALIDATE(params.get());
CopyDebuggee(debuggee_, params->target);
- if (!InitWebContents())
+ if (!InitAgentHost())
return false;
if (!webkit_glue::IsInspectorProtocolVersionSupported(
@@ -586,9 +596,7 @@
return false;
}
- scoped_refptr<DevToolsAgentHost> agent(DevToolsAgentHost::GetOrCreateFor(
- contents_->GetRenderViewHost()));
- if (agent->IsAttached()) {
+ if (agent_host_->IsAttached()) {
FormatErrorMessage(keys::kAlreadyAttachedError);
return false;
}
@@ -600,7 +608,7 @@
// Do not attach to the target if for any reason the infobar cannot be shown
// for this WebContents instance.
infobar_delegate = ExtensionDevToolsInfoBarDelegate::Create(
- contents_, GetExtension()->name());
+ agent_host_->GetRenderViewHost(), GetExtension()->name());
if (!infobar_delegate) {
error_ = ErrorUtils::FormatErrorMessage(
keys::kSilentDebuggingRequired,
@@ -609,7 +617,8 @@
}
}
- new ExtensionDevToolsClientHost(contents_,
+ new ExtensionDevToolsClientHost(profile(),
+ agent_host_,
GetExtension()->id(),
GetExtension()->name(),
debuggee_,
@@ -675,7 +684,7 @@
DebuggerGetTargetsFunction::~DebuggerGetTargetsFunction() {}
bool DebuggerGetTargetsFunction::RunImpl() {
- base::ListValue* results_list = new ListValue();
+ base::ListValue* results_list = new base::ListValue();
std::vector<RenderViewHost*> rvh_list =
DevToolsAgentHost::GetValidRenderViewHosts();
@@ -686,7 +695,27 @@
results_list->Append(value);
}
- SetResult(results_list);
- SendResponse(true);
+ BrowserThread::PostTaskAndReply(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&DebuggerGetTargetsFunction::CollectWorkerInfo,
+ this,
+ results_list),
+ base::Bind(&DebuggerGetTargetsFunction::SendTargetList,
+ this,
+ results_list));
return true;
}
+
+void DebuggerGetTargetsFunction::CollectWorkerInfo(base::ListValue* list) {
+ std::vector<WorkerService::WorkerInfo> worker_info =
+ WorkerService::GetInstance()->GetWorkers();
+
+ for (size_t i = 0; i < worker_info.size(); ++i)
+ list->Append(SerializeWorkerInfo(worker_info[i]));
+}
+
+void DebuggerGetTargetsFunction::SendTargetList(base::ListValue* list) {
+ SetResult(list);
+ SendResponse(true);
+}