DevTools: Merge WorkerInfo into EmbeddedWorkerDevToolsAgentHost

Fixes issues with EWDTAH lifetime. Now EWDTAH lives as long as there is a scoped_refptr referencing it or the worker is alive.

Split off https://codereview.chromium.org/349033009/

BUG=389454

Review URL: https://codereview.chromium.org/405603002

Cr-Commit-Position: refs/heads/master@{#288362}
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@288362 0039d316-1c4b-4281-b951-d872f2087c98
parent 3fb3f9ed
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/devtools/embedded_worker_devtools_agent_host.h"
#include "content/browser/devtools/devtools_manager_impl.h"
#include "content/browser/devtools/devtools_protocol.h"
#include "content/browser/devtools/devtools_protocol_constants.h"
#include "content/common/devtools_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
namespace content {
EmbeddedWorkerDevToolsAgentHost::EmbeddedWorkerDevToolsAgentHost(
WorkerId worker_id,
const SharedWorkerInstance& shared_worker)
: shared_worker_(new SharedWorkerInstance(shared_worker)),
state_(WORKER_UNINSPECTED),
worker_id_(worker_id) {
WorkerCreated();
}
EmbeddedWorkerDevToolsAgentHost::EmbeddedWorkerDevToolsAgentHost(
WorkerId worker_id,
const ServiceWorkerIdentifier& service_worker,
bool debug_service_worker_on_start)
: service_worker_(new ServiceWorkerIdentifier(service_worker)),
state_(WORKER_UNINSPECTED),
worker_id_(worker_id) {
if (debug_service_worker_on_start)
state_ = WORKER_PAUSED_FOR_DEBUG_ON_START;
WorkerCreated();
}
bool EmbeddedWorkerDevToolsAgentHost::IsWorker() const {
return true;
}
void EmbeddedWorkerDevToolsAgentHost::SendMessageToAgent(
IPC::Message* message_raw) {
scoped_ptr<IPC::Message> message(message_raw);
if (state_ != WORKER_INSPECTED)
return;
if (RenderProcessHost* host = RenderProcessHost::FromID(worker_id_.first)) {
message->set_routing_id(worker_id_.second);
host->Send(message.release());
}
}
void EmbeddedWorkerDevToolsAgentHost::Attach() {
if (state_ != WORKER_INSPECTED) {
state_ = WORKER_INSPECTED;
AttachToWorker();
}
IPCDevToolsAgentHost::Attach();
}
void EmbeddedWorkerDevToolsAgentHost::OnClientDetached() {
if (state_ == WORKER_INSPECTED) {
state_ = WORKER_UNINSPECTED;
DetachFromWorker();
} else if (state_ == WORKER_PAUSED_FOR_REATTACH) {
state_ = WORKER_UNINSPECTED;
}
}
bool EmbeddedWorkerDevToolsAgentHost::OnMessageReceived(
const IPC::Message& msg) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(EmbeddedWorkerDevToolsAgentHost, msg)
IPC_MESSAGE_HANDLER(DevToolsClientMsg_DispatchOnInspectorFrontend,
OnDispatchOnInspectorFrontend)
IPC_MESSAGE_HANDLER(DevToolsHostMsg_SaveAgentRuntimeState,
OnSaveAgentRuntimeState)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
void EmbeddedWorkerDevToolsAgentHost::WorkerContextStarted() {
if (state_ == WORKER_PAUSED_FOR_DEBUG_ON_START) {
RenderProcessHost* rph = RenderProcessHost::FromID(worker_id_.first);
DevToolsManagerImpl::GetInstance()->Inspect(rph->GetBrowserContext(), this);
} else if (state_ == WORKER_PAUSED_FOR_REATTACH) {
DCHECK(IsAttached());
state_ = WORKER_INSPECTED;
AttachToWorker();
Reattach(saved_agent_state_);
}
}
void EmbeddedWorkerDevToolsAgentHost::WorkerRestarted(WorkerId worker_id) {
DCHECK_EQ(WORKER_TERMINATED, state_);
state_ = IsAttached() ? WORKER_PAUSED_FOR_REATTACH : WORKER_UNINSPECTED;
worker_id_ = worker_id;
WorkerCreated();
}
void EmbeddedWorkerDevToolsAgentHost::WorkerDestroyed() {
DCHECK_NE(WORKER_TERMINATED, state_);
if (state_ == WORKER_INSPECTED) {
DCHECK(IsAttached());
// Client host is debugging this worker agent host.
std::string notification =
DevToolsProtocol::CreateNotification(
devtools::Worker::disconnectedFromWorker::kName, NULL)->Serialize();
DevToolsManagerImpl::GetInstance()->DispatchOnInspectorFrontend(
this, notification);
DetachFromWorker();
}
state_ = WORKER_TERMINATED;
Release(); // Balanced in WorkerCreated()
}
bool EmbeddedWorkerDevToolsAgentHost::Matches(
const SharedWorkerInstance& other) {
return shared_worker_ && shared_worker_->Matches(other);
}
bool EmbeddedWorkerDevToolsAgentHost::Matches(
const ServiceWorkerIdentifier& other) {
return service_worker_ && service_worker_->Matches(other);
}
EmbeddedWorkerDevToolsAgentHost::~EmbeddedWorkerDevToolsAgentHost() {
DCHECK_EQ(WORKER_TERMINATED, state_);
EmbeddedWorkerDevToolsManager::GetInstance()->RemoveInspectedWorkerData(
worker_id_);
}
void EmbeddedWorkerDevToolsAgentHost::AttachToWorker() {
if (RenderProcessHost* host = RenderProcessHost::FromID(worker_id_.first))
host->AddRoute(worker_id_.second, this);
}
void EmbeddedWorkerDevToolsAgentHost::DetachFromWorker() {
if (RenderProcessHost* host = RenderProcessHost::FromID(worker_id_.first))
host->RemoveRoute(worker_id_.second);
}
void EmbeddedWorkerDevToolsAgentHost::WorkerCreated() {
AddRef(); // Balanced in WorkerDestroyed()
}
void EmbeddedWorkerDevToolsAgentHost::OnDispatchOnInspectorFrontend(
const std::string& message) {
DevToolsManagerImpl::GetInstance()->DispatchOnInspectorFrontend(
this, message);
}
void EmbeddedWorkerDevToolsAgentHost::OnSaveAgentRuntimeState(
const std::string& state) {
saved_agent_state_ = state;
}
} // namespace content
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_DEVTOOLS_EMBEDDED_WORKER_DEVTOOLS_AGENT_HOST_H_
#define CONTENT_BROWSER_DEVTOOLS_EMBEDDED_WORKER_DEVTOOLS_AGENT_HOST_H_
#include "content/browser/devtools/embedded_worker_devtools_manager.h"
#include "content/browser/devtools/ipc_devtools_agent_host.h"
#include "ipc/ipc_listener.h"
namespace content {
class SharedWorkerInstance;
class EmbeddedWorkerDevToolsAgentHost : public IPCDevToolsAgentHost,
public IPC::Listener {
public:
typedef EmbeddedWorkerDevToolsManager::WorkerId WorkerId;
typedef EmbeddedWorkerDevToolsManager::ServiceWorkerIdentifier
ServiceWorkerIdentifier;
EmbeddedWorkerDevToolsAgentHost(WorkerId worker_id,
const SharedWorkerInstance& shared_worker);
EmbeddedWorkerDevToolsAgentHost(WorkerId worker_id,
const ServiceWorkerIdentifier& service_worker,
bool debug_service_worker_on_start);
// DevToolsAgentHost override.
virtual bool IsWorker() const OVERRIDE;
// IPCDevToolsAgentHost implementation.
virtual void SendMessageToAgent(IPC::Message* message) OVERRIDE;
virtual void Attach() OVERRIDE;
virtual void OnClientAttached() OVERRIDE {}
virtual void OnClientDetached() OVERRIDE;
// IPC::Listener implementation.
virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
void WorkerContextStarted();
void WorkerRestarted(WorkerId worker_id);
void WorkerDestroyed();
bool Matches(const SharedWorkerInstance& other);
bool Matches(const ServiceWorkerIdentifier& other);
private:
friend class EmbeddedWorkerDevToolsManagerTest;
virtual ~EmbeddedWorkerDevToolsAgentHost();
enum WorkerState {
WORKER_UNINSPECTED,
WORKER_INSPECTED,
WORKER_TERMINATED,
WORKER_PAUSED_FOR_DEBUG_ON_START,
WORKER_PAUSED_FOR_REATTACH,
};
void AttachToWorker();
void DetachFromWorker();
void WorkerCreated();
void OnDispatchOnInspectorFrontend(const std::string& message);
void OnSaveAgentRuntimeState(const std::string& state);
scoped_ptr<SharedWorkerInstance> shared_worker_;
scoped_ptr<ServiceWorkerIdentifier> service_worker_;
WorkerState state_;
WorkerId worker_id_;
std::string saved_agent_state_;
DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerDevToolsAgentHost);
};
} // namespace content
#endif // CONTENT_BROWSER_DEVTOOLS_EMBEDDED_WORKER_DEVTOOLS_AGENT_HOST_H_
......@@ -5,8 +5,9 @@
#ifndef CONTENT_BROWSER_DEVTOOLS_EMBEDDED_WORKER_DEVTOOLS_MANAGER_H_
#define CONTENT_BROWSER_DEVTOOLS_EMBEDDED_WORKER_DEVTOOLS_MANAGER_H_
#include <map>
#include "base/basictypes.h"
#include "base/containers/scoped_ptr_hash_map.h"
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_vector.h"
#include "base/memory/singleton.h"
......@@ -17,6 +18,7 @@
namespace content {
class DevToolsAgentHost;
class EmbeddedWorkerDevToolsAgentHost;
class ServiceWorkerContextCore;
// EmbeddedWorkerDevToolsManager is used instead of WorkerDevToolsManager when
......@@ -25,7 +27,6 @@ class ServiceWorkerContextCore;
class CONTENT_EXPORT EmbeddedWorkerDevToolsManager {
public:
typedef std::pair<int, int> WorkerId;
class EmbeddedWorkerDevToolsAgentHost;
class ServiceWorkerIdentifier {
public:
......@@ -73,60 +74,29 @@ class CONTENT_EXPORT EmbeddedWorkerDevToolsManager {
private:
friend struct DefaultSingletonTraits<EmbeddedWorkerDevToolsManager>;
friend class EmbeddedWorkerDevToolsAgentHost;
friend class EmbeddedWorkerDevToolsManagerTest;
FRIEND_TEST_ALL_PREFIXES(EmbeddedWorkerDevToolsManagerTest, BasicTest);
FRIEND_TEST_ALL_PREFIXES(EmbeddedWorkerDevToolsManagerTest, AttachTest);
enum WorkerState {
WORKER_UNINSPECTED,
WORKER_INSPECTED,
WORKER_TERMINATED,
WORKER_PAUSED_FOR_DEBUG_ON_START,
WORKER_PAUSED_FOR_REATTACH,
};
class WorkerInfo {
public:
// Creates WorkerInfo for SharedWorker.
explicit WorkerInfo(const SharedWorkerInstance& instance);
// Creates WorkerInfo for ServiceWorker.
explicit WorkerInfo(const ServiceWorkerIdentifier& service_worker_id);
~WorkerInfo();
WorkerState state() { return state_; }
void set_state(WorkerState new_state) { state_ = new_state; }
EmbeddedWorkerDevToolsAgentHost* agent_host() { return agent_host_; }
void set_agent_host(EmbeddedWorkerDevToolsAgentHost* agent_host) {
agent_host_ = agent_host;
}
bool Matches(const SharedWorkerInstance& other);
bool Matches(const ServiceWorkerIdentifier& other);
private:
scoped_ptr<SharedWorkerInstance> shared_worker_instance_;
scoped_ptr<ServiceWorkerIdentifier> service_worker_id_;
WorkerState state_;
EmbeddedWorkerDevToolsAgentHost* agent_host_;
};
typedef base::ScopedPtrHashMap<WorkerId, WorkerInfo> WorkerInfoMap;
typedef std::map<WorkerId, EmbeddedWorkerDevToolsAgentHost*> AgentHostMap;
EmbeddedWorkerDevToolsManager();
virtual ~EmbeddedWorkerDevToolsManager();
void RemoveInspectedWorkerData(EmbeddedWorkerDevToolsAgentHost* agent_host);
void RemoveInspectedWorkerData(WorkerId id);
WorkerInfoMap::iterator FindExistingSharedWorkerInfo(
AgentHostMap::iterator FindExistingSharedWorkerAgentHost(
const SharedWorkerInstance& instance);
WorkerInfoMap::iterator FindExistingServiceWorkerInfo(
AgentHostMap::iterator FindExistingServiceWorkerAgentHost(
const ServiceWorkerIdentifier& service_worker_id);
void MoveToPausedState(const WorkerId& id, const WorkerInfoMap::iterator& it);
void WorkerRestarted(const WorkerId& id, const AgentHostMap::iterator& it);
// Resets to its initial state as if newly created.
void ResetForTesting();
WorkerInfoMap workers_;
AgentHostMap workers_;
bool debug_service_worker_on_start_;
......
......@@ -443,6 +443,8 @@
'browser/devtools/forwarding_agent_host.h',
'browser/devtools/ipc_devtools_agent_host.cc',
'browser/devtools/ipc_devtools_agent_host.h',
'browser/devtools/embedded_worker_devtools_agent_host.cc',
'browser/devtools/embedded_worker_devtools_agent_host.h',
'browser/devtools/embedded_worker_devtools_manager.cc',
'browser/devtools/embedded_worker_devtools_manager.h',
'browser/devtools/render_view_devtools_agent_host.cc',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment