Commit 8d8c52b6 authored by Dmitry Gozman's avatar Dmitry Gozman Committed by Commit Bot

Reland "[DevTools] Switch shared worker inspection from routing id to SharedWorkerHost"

This is a reland of 0ea77a78
Original change's description:
> [DevTools] Switch shared worker inspection from routing id to SharedWorkerHost
>
> This is a preparation to replace routing id + legacy IPC with Mojo interface
> retrievable from SharedWorkerHost.
>
> Temporarily duplicated some code from WorkerDevToolsAgentHost, which
> makes it possible to migrate shared and service workers separately.
>
> Removed a test for WORKER_STATE manipulations altogether with the state itself.
>
> Bug: 776009
> Change-Id: Id884f4f5009eb70148251c94cae9629d5a1f6e8e
> Reviewed-on: https://chromium-review.googlesource.com/783110
> Commit-Queue: Dmitry Gozman <dgozman@chromium.org>
> Reviewed-by: Tsuyoshi Horo <horo@chromium.org>
> Reviewed-by: Alexei Filippov <alph@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#521277}

TBR=alph@chromium.org, horo@chromium.org

Bug: 776009
Change-Id: I0c0bbf56e5faf44fbf4cb7e12ea2b507c840fed2
Reviewed-on: https://chromium-review.googlesource.com/809466Reviewed-by: default avatarDmitry Gozman <dgozman@chromium.org>
Reviewed-by: default avatarTsuyoshi Horo <horo@chromium.org>
Commit-Queue: Dmitry Gozman <dgozman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#521901}
parent d8d7471e
......@@ -4,31 +4,48 @@
#include "content/browser/devtools/shared_worker_devtools_agent_host.h"
#include "content/browser/devtools/devtools_session.h"
#include "content/browser/devtools/protocol/inspector_handler.h"
#include "content/browser/devtools/protocol/network_handler.h"
#include "content/browser/devtools/protocol/protocol.h"
#include "content/browser/devtools/protocol/schema_handler.h"
#include "content/browser/devtools/shared_worker_devtools_manager.h"
#include "content/browser/shared_worker/shared_worker_host.h"
#include "content/browser/shared_worker/shared_worker_instance.h"
#include "content/browser/shared_worker/shared_worker_service_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
namespace content {
SharedWorkerDevToolsAgentHost::SharedWorkerDevToolsAgentHost(
WorkerId worker_id,
const SharedWorkerInstance& shared_worker)
: WorkerDevToolsAgentHost(shared_worker.devtools_worker_token(), worker_id),
shared_worker_(new SharedWorkerInstance(shared_worker)) {
SharedWorkerHost* worker_host)
: DevToolsAgentHostImpl(
worker_host->instance()->devtools_worker_token().ToString()),
worker_host_(worker_host),
instance_(new SharedWorkerInstance(*worker_host->instance())) {
NotifyCreated();
}
SharedWorkerDevToolsAgentHost::~SharedWorkerDevToolsAgentHost() {
SharedWorkerDevToolsManager::GetInstance()->AgentHostDestroyed(this);
}
BrowserContext* SharedWorkerDevToolsAgentHost::GetBrowserContext() {
RenderProcessHost* rph = GetProcess();
return rph ? rph->GetBrowserContext() : nullptr;
}
std::string SharedWorkerDevToolsAgentHost::GetType() {
return kTypeSharedWorker;
}
std::string SharedWorkerDevToolsAgentHost::GetTitle() {
return shared_worker_->name();
return instance_->name();
}
GURL SharedWorkerDevToolsAgentHost::GetURL() {
return shared_worker_->url();
return instance_->url();
}
bool SharedWorkerDevToolsAgentHost::Activate() {
......@@ -39,19 +56,128 @@ void SharedWorkerDevToolsAgentHost::Reload() {
}
bool SharedWorkerDevToolsAgentHost::Close() {
static_cast<SharedWorkerServiceImpl*>(SharedWorkerService::GetInstance())
->TerminateWorkerById(worker_id().first, worker_id().second);
if (worker_host_)
worker_host_->TerminateWorker();
return true;
}
bool SharedWorkerDevToolsAgentHost::Matches(
const SharedWorkerInstance& other) {
return shared_worker_->Matches(other);
void SharedWorkerDevToolsAgentHost::AttachSession(DevToolsSession* session) {
if (RenderProcessHost* host = GetProcess()) {
if (sessions().size() == 1)
host->AddRoute(worker_host_->route_id(), this);
session->SetRenderer(host, nullptr);
if (!waiting_ready_for_reattach_) {
host->Send(new DevToolsAgentMsg_Attach(worker_host_->route_id(),
session->session_id()));
}
}
session->SetFallThroughForNotFound(true);
session->AddHandler(std::make_unique<protocol::InspectorHandler>());
session->AddHandler(std::make_unique<protocol::NetworkHandler>(GetId()));
session->AddHandler(std::make_unique<protocol::SchemaHandler>());
}
SharedWorkerDevToolsAgentHost::~SharedWorkerDevToolsAgentHost() {
SharedWorkerDevToolsManager::GetInstance()->RemoveInspectedWorkerData(
worker_id());
void SharedWorkerDevToolsAgentHost::DetachSession(int session_id) {
if (RenderProcessHost* host = GetProcess()) {
host->Send(
new DevToolsAgentMsg_Detach(worker_host_->route_id(), session_id));
if (!sessions().size())
host->RemoveRoute(worker_host_->route_id());
}
}
bool SharedWorkerDevToolsAgentHost::DispatchProtocolMessage(
DevToolsSession* session,
const std::string& message) {
int call_id = 0;
std::string method;
if (session->Dispatch(message, &call_id, &method) !=
protocol::Response::kFallThrough) {
return true;
}
if (RenderProcessHost* host = GetProcess()) {
host->Send(new DevToolsAgentMsg_DispatchOnInspectorBackend(
worker_host_->route_id(), session->session_id(), call_id, method,
message));
session->waiting_messages()[call_id] = {method, message};
}
return true;
}
bool SharedWorkerDevToolsAgentHost::OnMessageReceived(const IPC::Message& msg) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(SharedWorkerDevToolsAgentHost, msg)
IPC_MESSAGE_HANDLER(DevToolsClientMsg_DispatchOnInspectorFrontend,
OnDispatchOnInspectorFrontend)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
bool SharedWorkerDevToolsAgentHost::Matches(SharedWorkerHost* worker_host) {
return instance_->Matches(*worker_host->instance());
}
void SharedWorkerDevToolsAgentHost::WorkerReadyForInspection() {
DCHECK(worker_host_);
if (!waiting_ready_for_reattach_)
return;
waiting_ready_for_reattach_ = false;
if (RenderProcessHost* host = GetProcess()) {
for (DevToolsSession* session : sessions()) {
host->Send(new DevToolsAgentMsg_Reattach(worker_host_->route_id(),
session->session_id(),
session->state_cookie()));
for (const auto& pair : session->waiting_messages()) {
int call_id = pair.first;
const DevToolsSession::Message& message = pair.second;
host->Send(new DevToolsAgentMsg_DispatchOnInspectorBackend(
worker_host_->route_id(), session->session_id(), call_id,
message.method, message.message));
}
}
}
}
bool SharedWorkerDevToolsAgentHost::WorkerRestarted(
SharedWorkerHost* worker_host) {
DCHECK(!worker_host_);
worker_host_ = worker_host;
if (RenderProcessHost* host = GetProcess()) {
if (sessions().size())
host->AddRoute(worker_host_->route_id(), this);
for (DevToolsSession* session : sessions())
session->SetRenderer(host, nullptr);
}
waiting_ready_for_reattach_ = IsAttached();
return waiting_ready_for_reattach_;
}
void SharedWorkerDevToolsAgentHost::WorkerDestroyed() {
DCHECK(worker_host_);
for (auto* inspector : protocol::InspectorHandler::ForAgentHost(this))
inspector->TargetCrashed();
for (DevToolsSession* session : sessions())
session->SetRenderer(nullptr, nullptr);
if (sessions().size()) {
if (RenderProcessHost* host = GetProcess())
host->RemoveRoute(worker_host_->route_id());
}
worker_host_ = nullptr;
}
RenderProcessHost* SharedWorkerDevToolsAgentHost::GetProcess() {
return worker_host_ ? RenderProcessHost::FromID(worker_host_->process_id())
: nullptr;
}
void SharedWorkerDevToolsAgentHost::OnDispatchOnInspectorFrontend(
const DevToolsMessageChunk& message) {
DevToolsSession* session = SessionById(message.session_id);
if (session)
session->ReceiveMessageChunk(message);
}
} // namespace content
......@@ -6,20 +6,24 @@
#define CONTENT_BROWSER_DEVTOOLS_SHARED_WORKER_DEVTOOLS_AGENT_HOST_H_
#include "base/macros.h"
#include "content/browser/devtools/worker_devtools_agent_host.h"
#include "content/browser/devtools/devtools_agent_host_impl.h"
#include "ipc/ipc_listener.h"
namespace content {
class SharedWorkerInstance;
class SharedWorkerHost;
class RenderProcessHost;
class SharedWorkerDevToolsAgentHost : public WorkerDevToolsAgentHost {
class SharedWorkerDevToolsAgentHost : public DevToolsAgentHostImpl,
public IPC::Listener {
public:
using List = std::vector<scoped_refptr<SharedWorkerDevToolsAgentHost>>;
SharedWorkerDevToolsAgentHost(WorkerId worker_id,
const SharedWorkerInstance& shared_worker);
explicit SharedWorkerDevToolsAgentHost(SharedWorkerHost* worker_host);
// DevToolsAgentHost override.
BrowserContext* GetBrowserContext() override;
std::string GetType() override;
std::string GetTitle() override;
GURL GetURL() override;
......@@ -27,13 +31,31 @@ class SharedWorkerDevToolsAgentHost : public WorkerDevToolsAgentHost {
void Reload() override;
bool Close() override;
bool Matches(const SharedWorkerInstance& other);
// DevToolsAgentHostImpl overrides.
void AttachSession(DevToolsSession* session) override;
void DetachSession(int session_id) override;
bool DispatchProtocolMessage(DevToolsSession* session,
const std::string& message) override;
// IPC::Listener implementation.
bool OnMessageReceived(const IPC::Message& msg) override;
bool Matches(SharedWorkerHost* worker_host);
void WorkerReadyForInspection();
// Returns whether the worker should be paused for reattach.
bool WorkerRestarted(SharedWorkerHost* worker_host);
void WorkerDestroyed();
private:
friend class SharedWorkerDevToolsManagerTest;
~SharedWorkerDevToolsAgentHost() override;
std::unique_ptr<SharedWorkerInstance> shared_worker_;
RenderProcessHost* GetProcess();
void OnDispatchOnInspectorFrontend(const DevToolsMessageChunk& message);
SharedWorkerHost* worker_host_;
std::unique_ptr<SharedWorkerInstance> instance_;
bool waiting_ready_for_reattach_ = false;
DISALLOW_COPY_AND_ASSIGN(SharedWorkerDevToolsAgentHost);
};
......
......@@ -5,7 +5,7 @@
#include "content/browser/devtools/shared_worker_devtools_manager.h"
#include "content/browser/devtools/shared_worker_devtools_agent_host.h"
#include "content/browser/shared_worker/shared_worker_instance.h"
#include "content/browser/shared_worker/shared_worker_host.h"
#include "content/public/browser/browser_thread.h"
namespace content {
......@@ -18,80 +18,61 @@ SharedWorkerDevToolsManager* SharedWorkerDevToolsManager::GetInstance() {
void SharedWorkerDevToolsManager::AddAllAgentHosts(
SharedWorkerDevToolsAgentHost::List* result) {
for (auto& worker : workers_) {
if (!worker.second->IsTerminated())
result->push_back(worker.second);
}
for (auto& it : live_hosts_)
result->push_back(it.second.get());
}
bool SharedWorkerDevToolsManager::WorkerCreated(
int worker_process_id,
int worker_route_id,
const SharedWorkerInstance& instance) {
bool SharedWorkerDevToolsManager::WorkerCreated(SharedWorkerHost* worker_host) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
const WorkerId id(worker_process_id, worker_route_id);
AgentHostMap::iterator it =
FindExistingWorkerAgentHost(instance);
if (it == workers_.end()) {
workers_[id] = new SharedWorkerDevToolsAgentHost(id, instance);
DCHECK(live_hosts_.find(worker_host) == live_hosts_.end());
auto it =
std::find_if(terminated_hosts_.begin(), terminated_hosts_.end(),
[&worker_host](SharedWorkerDevToolsAgentHost* agent_host) {
return agent_host->Matches(worker_host);
});
if (it == terminated_hosts_.end()) {
live_hosts_[worker_host] = new SharedWorkerDevToolsAgentHost(worker_host);
return false;
}
// Worker restarted.
SharedWorkerDevToolsAgentHost* agent_host = it->second;
agent_host->WorkerRestarted(id);
workers_.erase(it);
workers_[id] = agent_host;
return agent_host->IsAttached();
SharedWorkerDevToolsAgentHost* agent_host = *it;
terminated_hosts_.erase(it);
live_hosts_[worker_host] = agent_host;
return agent_host->WorkerRestarted(worker_host);
}
void SharedWorkerDevToolsManager::WorkerReadyForInspection(
int worker_process_id,
int worker_route_id) {
SharedWorkerHost* worker_host) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
const WorkerId id(worker_process_id, worker_route_id);
AgentHostMap::iterator it = workers_.find(id);
if (it == workers_.end() || it->second->IsTerminated())
return;
it->second->WorkerReadyForInspection();
live_hosts_[worker_host]->WorkerReadyForInspection();
}
void SharedWorkerDevToolsManager::WorkerDestroyed(
int worker_process_id,
int worker_route_id) {
SharedWorkerHost* worker_host) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
const WorkerId id(worker_process_id, worker_route_id);
AgentHostMap::iterator it = workers_.find(id);
if (it == workers_.end() || it->second->IsTerminated())
return;
scoped_refptr<SharedWorkerDevToolsAgentHost> agent_host(it->second);
scoped_refptr<SharedWorkerDevToolsAgentHost> agent_host =
live_hosts_[worker_host];
live_hosts_.erase(worker_host);
terminated_hosts_.insert(agent_host.get());
agent_host->WorkerDestroyed();
}
void SharedWorkerDevToolsManager::RemoveInspectedWorkerData(WorkerId id) {
void SharedWorkerDevToolsManager::AgentHostDestroyed(
SharedWorkerDevToolsAgentHost* agent_host) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
workers_.erase(id);
auto it = terminated_hosts_.find(agent_host);
// Might be missing during shutdown due to different
// destruction order of this manager, shared workers
// and their agent hosts.
if (it != terminated_hosts_.end())
terminated_hosts_.erase(it);
}
SharedWorkerDevToolsManager::SharedWorkerDevToolsManager() {
}
SharedWorkerDevToolsManager::~SharedWorkerDevToolsManager() {
}
SharedWorkerDevToolsManager::AgentHostMap::iterator
SharedWorkerDevToolsManager::FindExistingWorkerAgentHost(
const SharedWorkerInstance& instance) {
AgentHostMap::iterator it = workers_.begin();
for (; it != workers_.end(); ++it) {
if (it->second->Matches(instance))
break;
}
return it;
}
void SharedWorkerDevToolsManager::ResetForTesting() {
workers_.clear();
}
} // namespace content
......@@ -7,6 +7,7 @@
#include <map>
#include "base/containers/flat_set.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/singleton.h"
......@@ -15,14 +16,12 @@
namespace content {
class SharedWorkerDevToolsAgentHost;
class SharedWorkerInstance;
class SharedWorkerHost;
// Manages WorkerDevToolsAgentHost's for Shared Workers.
// This class lives on UI thread.
class CONTENT_EXPORT SharedWorkerDevToolsManager {
public:
using WorkerId = std::pair<int, int>;
// Returns the SharedWorkerDevToolsManager singleton.
static SharedWorkerDevToolsManager* GetInstance();
......@@ -31,12 +30,9 @@ class CONTENT_EXPORT SharedWorkerDevToolsManager {
// Returns true when the worker must be paused on start because a DevTool
// window for the same former SharedWorkerInstance is still opened.
bool WorkerCreated(int worker_process_id,
int worker_route_id,
const SharedWorkerInstance& instance);
void WorkerReadyForInspection(int worker_process_id, int worker_route_id);
void WorkerDestroyed(int worker_process_id, int worker_route_id);
void RemoveInspectedWorkerData(WorkerId id);
bool WorkerCreated(SharedWorkerHost* worker_host);
void WorkerReadyForInspection(SharedWorkerHost* worker_host);
void WorkerDestroyed(SharedWorkerHost* worker_host);
private:
friend struct base::DefaultSingletonTraits<SharedWorkerDevToolsManager>;
......@@ -45,18 +41,17 @@ class CONTENT_EXPORT SharedWorkerDevToolsManager {
FRIEND_TEST_ALL_PREFIXES(SharedWorkerDevToolsManagerTest, BasicTest);
FRIEND_TEST_ALL_PREFIXES(SharedWorkerDevToolsManagerTest, AttachTest);
using AgentHostMap = std::map<WorkerId, SharedWorkerDevToolsAgentHost*>;
SharedWorkerDevToolsManager();
~SharedWorkerDevToolsManager();
void AgentHostDestroyed(SharedWorkerDevToolsAgentHost* agent_host);
AgentHostMap::iterator FindExistingWorkerAgentHost(
const SharedWorkerInstance& instance);
// Resets to its initial state as if newly created.
void ResetForTesting();
// We retatin agent hosts as long as the shared worker is alive.
std::map<SharedWorkerHost*, scoped_refptr<SharedWorkerDevToolsAgentHost>>
live_hosts_;
// Clients may retain agent host for the terminated shared worker,
// and we reconnect them when shared worker is restarted.
base::flat_set<SharedWorkerDevToolsAgentHost*> terminated_hosts_;
AgentHostMap workers_;
DISALLOW_COPY_AND_ASSIGN(SharedWorkerDevToolsManager);
};
......
......@@ -70,10 +70,8 @@ SharedWorkerHost::SharedWorkerHost(
SharedWorkerHost::~SharedWorkerHost() {
UMA_HISTOGRAM_LONG_TIMES("SharedWorker.TimeToDeleted",
base::TimeTicks::Now() - creation_time_);
if (!closed_ && !termination_message_sent_) {
SharedWorkerDevToolsManager::GetInstance()->WorkerDestroyed(process_id_,
route_id_);
}
if (!closed_ && !termination_message_sent_)
SharedWorkerDevToolsManager::GetInstance()->WorkerDestroyed(this);
}
void SharedWorkerHost::Start(mojom::SharedWorkerFactoryPtr factory,
......@@ -127,11 +125,12 @@ void SharedWorkerHost::AllowIndexedDB(const GURL& url,
}
void SharedWorkerHost::TerminateWorker() {
// This can be called twice in tests while cleaning up all the workers.
if (termination_message_sent_)
return;
termination_message_sent_ = true;
if (!closed_) {
SharedWorkerDevToolsManager::GetInstance()->WorkerDestroyed(process_id_,
route_id_);
}
if (!closed_)
SharedWorkerDevToolsManager::GetInstance()->WorkerDestroyed(this);
worker_->Terminate();
// Now, we wait to observe OnWorkerConnectionLost.
}
......@@ -164,15 +163,13 @@ void SharedWorkerHost::OnContextClosed() {
// being sent to the worker (messages can still be sent from the worker,
// for exception reporting, etc).
closed_ = true;
if (!termination_message_sent_) {
SharedWorkerDevToolsManager::GetInstance()->WorkerDestroyed(process_id_,
route_id_);
}
if (!termination_message_sent_)
SharedWorkerDevToolsManager::GetInstance()->WorkerDestroyed(this);
}
void SharedWorkerHost::OnReadyForInspection() {
SharedWorkerDevToolsManager::GetInstance()->WorkerReadyForInspection(
process_id_, route_id_);
if (!closed_ && !termination_message_sent_)
SharedWorkerDevToolsManager::GetInstance()->WorkerReadyForInspection(this);
}
void SharedWorkerHost::OnScriptLoaded() {
......
......@@ -87,15 +87,6 @@ bool SharedWorkerServiceImpl::TerminateWorker(
return false;
}
bool SharedWorkerServiceImpl::TerminateWorkerById(int process_id,
int route_id) {
SharedWorkerHost* host = FindSharedWorkerHost(process_id, route_id);
if (!host || !host->instance())
return false;
host->TerminateWorker();
return true;
}
void SharedWorkerServiceImpl::TerminateAllWorkersForTesting(
base::OnceClosure callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
......@@ -210,13 +201,12 @@ void SharedWorkerServiceImpl::CreateWorker(
// Dev Tools will need to be modified to use something else as an identifier.
int worker_route_id = process_host->GetNextRoutingID();
bool pause_on_start =
SharedWorkerDevToolsManager::GetInstance()->WorkerCreated(
worker_process_id, worker_route_id, *instance);
auto host = std::make_unique<SharedWorkerHost>(
std::move(instance), worker_process_id, worker_route_id);
bool pause_on_start =
SharedWorkerDevToolsManager::GetInstance()->WorkerCreated(host.get());
// Get the factory used to instantiate the new shared worker instance in
// the target process.
mojom::SharedWorkerFactoryPtr factory;
......
......@@ -40,8 +40,6 @@ class CONTENT_EXPORT SharedWorkerServiceImpl : public SharedWorkerService {
StoragePartition* storage_partition,
ResourceContext* resource_context) override;
// Terminates the given worker. Returns true if the process was found.
bool TerminateWorkerById(int process_id, int route_id);
void TerminateAllWorkersForTesting(base::OnceClosure callback);
// Creates the worker if necessary or connects to an already existing worker.
......
......@@ -1203,7 +1203,6 @@ test("content_unittests") {
"../browser/devtools/devtools_http_handler_unittest.cc",
"../browser/devtools/devtools_manager_unittest.cc",
"../browser/devtools/protocol/tracing_handler_unittest.cc",
"../browser/devtools/shared_worker_devtools_manager_unittest.cc",
"../browser/dom_storage/dom_storage_area_unittest.cc",
"../browser/dom_storage/dom_storage_context_impl_unittest.cc",
"../browser/dom_storage/dom_storage_database_unittest.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