blob: b4886cc9754467affaa50996de3a554344681d5a [file] [log] [blame]
// 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/service_worker_devtools_agent_host.h"
#include "base/strings/stringprintf.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/service_worker_devtools_manager.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
namespace content {
namespace {
void TerminateServiceWorkerOnIO(
base::WeakPtr<ServiceWorkerContextCore> context_weak,
int64_t version_id) {
if (ServiceWorkerContextCore* context = context_weak.get()) {
if (ServiceWorkerVersion* version = context->GetLiveVersion(version_id))
version->StopWorker(base::DoNothing());
}
}
void SetDevToolsAttachedOnIO(
base::WeakPtr<ServiceWorkerContextCore> context_weak,
int64_t version_id,
bool attached) {
if (ServiceWorkerContextCore* context = context_weak.get()) {
if (ServiceWorkerVersion* version = context->GetLiveVersion(version_id))
version->SetDevToolsAttached(attached);
}
}
} // namespace
ServiceWorkerDevToolsAgentHost::ServiceWorkerDevToolsAgentHost(
int worker_process_id,
int worker_route_id,
const ServiceWorkerContextCore* context,
base::WeakPtr<ServiceWorkerContextCore> context_weak,
int64_t version_id,
const GURL& url,
const GURL& scope,
bool is_installed_version,
const base::UnguessableToken& devtools_worker_token)
: DevToolsAgentHostImpl(devtools_worker_token.ToString()),
state_(WORKER_NOT_READY),
devtools_worker_token_(devtools_worker_token),
worker_process_id_(worker_process_id),
worker_route_id_(worker_route_id),
context_(context),
context_weak_(context_weak),
version_id_(version_id),
url_(url),
scope_(scope),
version_installed_time_(is_installed_version ? base::Time::Now()
: base::Time()) {
NotifyCreated();
}
BrowserContext* ServiceWorkerDevToolsAgentHost::GetBrowserContext() {
RenderProcessHost* rph = RenderProcessHost::FromID(worker_process_id_);
return rph ? rph->GetBrowserContext() : nullptr;
}
std::string ServiceWorkerDevToolsAgentHost::GetType() {
return kTypeServiceWorker;
}
std::string ServiceWorkerDevToolsAgentHost::GetTitle() {
return "Service Worker " + url_.spec();
}
GURL ServiceWorkerDevToolsAgentHost::GetURL() {
return url_;
}
bool ServiceWorkerDevToolsAgentHost::Activate() {
return false;
}
void ServiceWorkerDevToolsAgentHost::Reload() {
}
bool ServiceWorkerDevToolsAgentHost::Close() {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(&TerminateServiceWorkerOnIO, context_weak_, version_id_));
return true;
}
void ServiceWorkerDevToolsAgentHost::WorkerVersionInstalled() {
version_installed_time_ = base::Time::Now();
}
void ServiceWorkerDevToolsAgentHost::WorkerVersionDoomed() {
version_doomed_time_ = base::Time::Now();
}
bool ServiceWorkerDevToolsAgentHost::Matches(
const ServiceWorkerContextCore* context,
int64_t version_id) {
return context_ == context && version_id_ == version_id;
}
ServiceWorkerDevToolsAgentHost::~ServiceWorkerDevToolsAgentHost() {
ServiceWorkerDevToolsManager::GetInstance()->AgentHostDestroyed(this);
}
bool ServiceWorkerDevToolsAgentHost::AttachSession(DevToolsSession* session) {
if (state_ == WORKER_READY) {
if (sessions().size() == 1) {
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
base::BindOnce(&SetDevToolsAttachedOnIO,
context_weak_, version_id_, true));
}
session->SetRenderer(worker_process_id_, nullptr);
session->AttachToAgent(agent_ptr_);
}
session->AddHandler(base::WrapUnique(new protocol::InspectorHandler()));
session->AddHandler(base::WrapUnique(new protocol::NetworkHandler(GetId())));
session->AddHandler(base::WrapUnique(new protocol::SchemaHandler()));
return true;
}
void ServiceWorkerDevToolsAgentHost::DetachSession(DevToolsSession* session) {
// Destroying session automatically detaches in renderer.
if (state_ == WORKER_READY && sessions().empty()) {
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
base::BindOnce(&SetDevToolsAttachedOnIO,
context_weak_, version_id_, false));
}
}
void ServiceWorkerDevToolsAgentHost::DispatchProtocolMessage(
DevToolsSession* session,
const std::string& message) {
session->DispatchProtocolMessage(message);
}
void ServiceWorkerDevToolsAgentHost::WorkerReadyForInspection(
blink::mojom::DevToolsAgentAssociatedPtrInfo devtools_agent_ptr_info) {
DCHECK_EQ(WORKER_NOT_READY, state_);
state_ = WORKER_READY;
agent_ptr_.Bind(std::move(devtools_agent_ptr_info));
if (!sessions().empty()) {
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
base::BindOnce(&SetDevToolsAttachedOnIO,
context_weak_, version_id_, true));
}
for (DevToolsSession* session : sessions()) {
session->SetRenderer(worker_process_id_, nullptr);
session->AttachToAgent(agent_ptr_);
}
}
void ServiceWorkerDevToolsAgentHost::WorkerRestarted(int worker_process_id,
int worker_route_id) {
DCHECK_EQ(WORKER_TERMINATED, state_);
state_ = WORKER_NOT_READY;
worker_process_id_ = worker_process_id;
worker_route_id_ = worker_route_id;
for (auto* inspector : protocol::InspectorHandler::ForAgentHost(this))
inspector->TargetReloadedAfterCrash();
for (DevToolsSession* session : sessions())
session->SetRenderer(worker_process_id_, nullptr);
}
void ServiceWorkerDevToolsAgentHost::WorkerDestroyed() {
DCHECK_NE(WORKER_TERMINATED, state_);
state_ = WORKER_TERMINATED;
agent_ptr_.reset();
for (auto* inspector : protocol::InspectorHandler::ForAgentHost(this))
inspector->TargetCrashed();
for (DevToolsSession* session : sessions())
session->SetRenderer(-1, nullptr);
}
} // namespace content