// 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/devtools_manager.h" #include "content/browser/devtools/ipc_devtools_agent_host.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 "content/public/browser/worker_service.h" #include "ipc/ipc_listener.h" namespace content { ServiceWorkerDevToolsManager::ServiceWorkerIdentifier::ServiceWorkerIdentifier( const ServiceWorkerContextCore* context, base::WeakPtr context_weak, int64 version_id, const GURL& url) : context_(context), context_weak_(context_weak), version_id_(version_id), url_(url) { } ServiceWorkerDevToolsManager::ServiceWorkerIdentifier::ServiceWorkerIdentifier( const ServiceWorkerIdentifier& other) : context_(other.context_), context_weak_(other.context_weak_), version_id_(other.version_id_), url_(other.url_) { } ServiceWorkerDevToolsManager:: ServiceWorkerIdentifier::~ServiceWorkerIdentifier() { } bool ServiceWorkerDevToolsManager::ServiceWorkerIdentifier::Matches( const ServiceWorkerIdentifier& other) const { return context_ == other.context_ && version_id_ == other.version_id_; } // static ServiceWorkerDevToolsManager* ServiceWorkerDevToolsManager::GetInstance() { DCHECK_CURRENTLY_ON(BrowserThread::UI); return Singleton::get(); } DevToolsAgentHostImpl* ServiceWorkerDevToolsManager::GetDevToolsAgentHostForWorker( int worker_process_id, int worker_route_id) { AgentHostMap::iterator it = workers_.find( WorkerId(worker_process_id, worker_route_id)); return it == workers_.end() ? NULL : it->second; } void ServiceWorkerDevToolsManager::AddAllAgentHosts( ServiceWorkerDevToolsAgentHost::List* result) { for (auto& worker : workers_) { if (!worker.second->IsTerminated()) result->push_back(worker.second); } } bool ServiceWorkerDevToolsManager::WorkerCreated( int worker_process_id, int worker_route_id, const ServiceWorkerIdentifier& service_worker_id) { DCHECK_CURRENTLY_ON(BrowserThread::UI); const WorkerId id(worker_process_id, worker_route_id); AgentHostMap::iterator it = FindExistingWorkerAgentHost(service_worker_id); if (it == workers_.end()) { scoped_refptr host = new ServiceWorkerDevToolsAgentHost( id, service_worker_id); workers_[id] = host.get(); FOR_EACH_OBSERVER(Observer, observer_list_, WorkerCreated(host.get())); DevToolsManager::GetInstance()->AgentHostChanged(host.get()); if (debug_service_worker_on_start_) host->PauseForDebugOnStart(); return host->IsPausedForDebugOnStart(); } // Worker was restarted. ServiceWorkerDevToolsAgentHost* agent_host = it->second; agent_host->WorkerRestarted(id); workers_.erase(it); workers_[id] = agent_host; DevToolsManager::GetInstance()->AgentHostChanged(agent_host); return it->second->IsAttached(); } void ServiceWorkerDevToolsManager::WorkerReadyForInspection( int worker_process_id, int worker_route_id) { DCHECK_CURRENTLY_ON(BrowserThread::UI); const WorkerId id(worker_process_id, worker_route_id); AgentHostMap::iterator it = workers_.find(id); DCHECK(it != workers_.end()); scoped_refptr host = it->second; host->WorkerReadyForInspection(); FOR_EACH_OBSERVER(Observer, observer_list_, WorkerReadyForInspection(host.get())); // Then bring up UI for the ones not picked by other clients. if (host->IsPausedForDebugOnStart() && !host->IsAttached()) { host->Inspect(RenderProcessHost::FromID(worker_process_id)-> GetBrowserContext()); } } void ServiceWorkerDevToolsManager::WorkerStopIgnored(int worker_process_id, int worker_route_id) { DCHECK_CURRENTLY_ON(BrowserThread::UI); // TODO(pfeldman): Show a console message to tell the user that UA didn't // terminate the worker because devtools is attached. } void ServiceWorkerDevToolsManager::WorkerDestroyed(int worker_process_id, int worker_route_id) { DCHECK_CURRENTLY_ON(BrowserThread::UI); const WorkerId id(worker_process_id, worker_route_id); AgentHostMap::iterator it = workers_.find(id); DCHECK(it != workers_.end()); scoped_refptr agent_host(it->second); agent_host->WorkerDestroyed(); DevToolsManager::GetInstance()->AgentHostChanged(agent_host); FOR_EACH_OBSERVER(Observer, observer_list_, WorkerDestroyed(it->second)); } void ServiceWorkerDevToolsManager::RemoveInspectedWorkerData(WorkerId id) { DCHECK_CURRENTLY_ON(BrowserThread::UI); workers_.erase(id); } void ServiceWorkerDevToolsManager::AddObserver(Observer* observer) { observer_list_.AddObserver(observer); } void ServiceWorkerDevToolsManager::RemoveObserver(Observer* observer) { observer_list_.RemoveObserver(observer); } ServiceWorkerDevToolsManager::ServiceWorkerDevToolsManager() : debug_service_worker_on_start_(false) { } ServiceWorkerDevToolsManager::~ServiceWorkerDevToolsManager() { } ServiceWorkerDevToolsManager::AgentHostMap::iterator ServiceWorkerDevToolsManager::FindExistingWorkerAgentHost( const ServiceWorkerIdentifier& service_worker_id) { AgentHostMap::iterator it = workers_.begin(); for (; it != workers_.end(); ++it) { if (static_cast( it->second)->Matches(service_worker_id)) break; } return it; } void ServiceWorkerDevToolsManager::ResetForTesting() { workers_.clear(); } } // namespace content