blob: 96310dafa7f2d58e726e12f842a84069e0b7e04e [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_manager.h"
#include "content/browser/devtools/protocol/network_handler.h"
#include "content/browser/devtools/service_worker_devtools_agent_host.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "ipc/ipc_listener.h"
namespace content {
// static
ServiceWorkerDevToolsManager* ServiceWorkerDevToolsManager::GetInstance() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return base::Singleton<ServiceWorkerDevToolsManager>::get();
}
ServiceWorkerDevToolsAgentHost*
ServiceWorkerDevToolsManager::GetDevToolsAgentHostForWorker(
int worker_process_id,
int worker_route_id) {
auto it = live_hosts_.find(WorkerId(worker_process_id, worker_route_id));
return it == live_hosts_.end() ? nullptr : it->second.get();
}
void ServiceWorkerDevToolsManager::AddAllAgentHosts(
ServiceWorkerDevToolsAgentHost::List* result) {
for (auto& it : live_hosts_)
result->push_back(it.second.get());
}
void ServiceWorkerDevToolsManager::AddAllAgentHostsForBrowserContext(
BrowserContext* browser_context,
ServiceWorkerDevToolsAgentHost::List* result) {
for (auto& it : live_hosts_) {
if (it.second->GetBrowserContext() == browser_context)
result->push_back(it.second.get());
}
}
void ServiceWorkerDevToolsManager::WorkerCreated(
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,
base::UnguessableToken* devtools_worker_token,
bool* pause_on_start) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
const WorkerId worker_id(worker_process_id, worker_route_id);
DCHECK(live_hosts_.find(worker_id) == live_hosts_.end());
auto it = std::find_if(
terminated_hosts_.begin(), terminated_hosts_.end(),
[&context, &version_id](ServiceWorkerDevToolsAgentHost* agent_host) {
return agent_host->Matches(context, version_id);
});
if (it == terminated_hosts_.end()) {
*devtools_worker_token = base::UnguessableToken::Create();
scoped_refptr<ServiceWorkerDevToolsAgentHost> host =
new ServiceWorkerDevToolsAgentHost(worker_process_id, worker_route_id,
context, context_weak, version_id,
url, scope, is_installed_version,
*devtools_worker_token);
live_hosts_[worker_id] = host;
*pause_on_start = debug_service_worker_on_start_;
for (auto& observer : observer_list_) {
bool should_pause_on_start = false;
observer.WorkerCreated(host.get(), &should_pause_on_start);
if (should_pause_on_start)
*pause_on_start = true;
}
return;
}
ServiceWorkerDevToolsAgentHost* agent_host = *it;
terminated_hosts_.erase(it);
live_hosts_[worker_id] = agent_host;
agent_host->WorkerRestarted(worker_process_id, worker_route_id);
*pause_on_start = agent_host->IsAttached();
*devtools_worker_token = agent_host->devtools_worker_token();
}
void ServiceWorkerDevToolsManager::WorkerReadyForInspection(
int worker_process_id,
int worker_route_id,
blink::mojom::DevToolsAgentAssociatedPtrInfo devtools_agent_ptr_info) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
const WorkerId worker_id(worker_process_id, worker_route_id);
auto it = live_hosts_.find(worker_id);
if (it == live_hosts_.end())
return;
scoped_refptr<ServiceWorkerDevToolsAgentHost> host = it->second;
host->WorkerReadyForInspection(std::move(devtools_agent_ptr_info));
// Bring up UI for the ones not picked by other clients.
if (debug_service_worker_on_start_ && !host->IsAttached())
host->Inspect();
}
void ServiceWorkerDevToolsManager::WorkerVersionInstalled(int worker_process_id,
int worker_route_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
const WorkerId worker_id(worker_process_id, worker_route_id);
auto it = live_hosts_.find(worker_id);
if (it == live_hosts_.end())
return;
scoped_refptr<ServiceWorkerDevToolsAgentHost> host = it->second;
host->WorkerVersionInstalled();
for (auto& observer : observer_list_)
observer.WorkerVersionInstalled(host.get());
}
void ServiceWorkerDevToolsManager::WorkerVersionDoomed(int worker_process_id,
int worker_route_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
const WorkerId worker_id(worker_process_id, worker_route_id);
auto it = live_hosts_.find(worker_id);
if (it == live_hosts_.end())
return;
scoped_refptr<ServiceWorkerDevToolsAgentHost> host = it->second;
host->WorkerVersionDoomed();
for (auto& observer : observer_list_)
observer.WorkerVersionDoomed(host.get());
}
void ServiceWorkerDevToolsManager::WorkerDestroyed(int worker_process_id,
int worker_route_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
const WorkerId worker_id(worker_process_id, worker_route_id);
auto it = live_hosts_.find(worker_id);
if (it == live_hosts_.end())
return;
scoped_refptr<ServiceWorkerDevToolsAgentHost> agent_host(it->second);
live_hosts_.erase(it);
terminated_hosts_.insert(agent_host.get());
agent_host->WorkerDestroyed();
for (auto& observer : observer_list_)
observer.WorkerDestroyed(agent_host.get());
}
void ServiceWorkerDevToolsManager::AgentHostDestroyed(
ServiceWorkerDevToolsAgentHost* agent_host) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
auto it = terminated_hosts_.find(agent_host);
// Might be missing during shutdown due to different
// destruction order of this manager, service workers
// and their agent hosts.
if (it != terminated_hosts_.end())
terminated_hosts_.erase(it);
}
void ServiceWorkerDevToolsManager::AddObserver(Observer* observer) {
observer_list_.AddObserver(observer);
}
void ServiceWorkerDevToolsManager::RemoveObserver(Observer* observer) {
observer_list_.RemoveObserver(observer);
}
void ServiceWorkerDevToolsManager::set_debug_service_worker_on_start(
bool debug_on_start) {
debug_service_worker_on_start_ = debug_on_start;
}
ServiceWorkerDevToolsManager::ServiceWorkerDevToolsManager()
: debug_service_worker_on_start_(false) {
}
ServiceWorkerDevToolsManager::~ServiceWorkerDevToolsManager() {
}
void ServiceWorkerDevToolsManager::NavigationPreloadRequestSent(
int worker_process_id,
int worker_route_id,
const std::string& request_id,
const network::ResourceRequest& request) {
const WorkerId worker_id(worker_process_id, worker_route_id);
auto it = live_hosts_.find(worker_id);
if (it == live_hosts_.end())
return;
for (auto* network : protocol::NetworkHandler::ForAgentHost(it->second.get()))
network->NavigationPreloadRequestSent(request_id, request);
}
void ServiceWorkerDevToolsManager::NavigationPreloadResponseReceived(
int worker_process_id,
int worker_route_id,
const std::string& request_id,
const GURL& url,
const network::ResourceResponseHead& head) {
const WorkerId worker_id(worker_process_id, worker_route_id);
auto it = live_hosts_.find(worker_id);
if (it == live_hosts_.end())
return;
for (auto* network : protocol::NetworkHandler::ForAgentHost(it->second.get()))
network->NavigationPreloadResponseReceived(request_id, url, head);
}
void ServiceWorkerDevToolsManager::NavigationPreloadCompleted(
int worker_process_id,
int worker_route_id,
const std::string& request_id,
const network::URLLoaderCompletionStatus& status) {
const WorkerId worker_id(worker_process_id, worker_route_id);
auto it = live_hosts_.find(worker_id);
if (it == live_hosts_.end())
return;
for (auto* network : protocol::NetworkHandler::ForAgentHost(it->second.get()))
network->NavigationPreloadCompleted(request_id, status);
}
} // namespace content