Chromium Code Reviews| Index: content/browser/debugger/worker_devtools_manager.cc |
| diff --git a/content/browser/debugger/worker_devtools_manager.cc b/content/browser/debugger/worker_devtools_manager.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..6c59684033ac5b4b3b315c2f5e63806340845bea |
| --- /dev/null |
| +++ b/content/browser/debugger/worker_devtools_manager.cc |
| @@ -0,0 +1,298 @@ |
| +// Copyright (c) 2011 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/debugger/worker_devtools_manager.h" |
| + |
| +#include <list> |
| + |
| +#include "base/tuple.h" |
| +#include "chrome/browser/profiles/profile_manager.h" |
| +#include "content/browser/browser_thread.h" |
| +#include "content/browser/debugger/devtools_manager.h" |
| +#include "content/browser/debugger/devtools_window.h" |
| +#include "content/browser/debugger/worker_devtools_message_filter.h" |
| +#include "content/browser/worker_host/worker_process_host.h" |
| +#include "content/common/devtools_messages.h" |
| + |
| +class WorkerDevToolsManager::DevToolsWorkerIds { |
|
pfeldman
2011/07/08 09:17:17
IdsIOMap
yurys
2011/07/08 15:35:53
Done.
|
| + public: |
| + DevToolsWorkerIds() : next_id_(1) {} |
| + |
| + int CreateDevToolsId(WorkerProcessHost* host, int route_id) { |
| + DCHECK(-1 == FindDevToolsId(host->id(), route_id)); |
| + int devtools_id = next_id_++; |
| + map_.push_back(Entry(host, route_id, devtools_id)); |
| + return devtools_id; |
| + } |
| + |
| + int FindDevToolsId(int worker_process_host_id, int route_id) { |
| + for (IdMap::iterator it = map_.begin(); |
| + it != map_.end(); ++it) { |
|
pfeldman
2011/07/08 09:17:17
Does it fit one line?
yurys
2011/07/08 15:35:53
Done.
|
| + if (it->a->id() == worker_process_host_id && it->b == route_id) |
|
pfeldman
2011/07/08 09:17:17
it-a-id? do we want a struct?
yurys
2011/07/08 15:35:53
Done.
|
| + return it->c; |
| + } |
| + return -1; |
| + } |
| + |
| + bool FindWorkerInfo( |
| + int devtools_id, |
|
pfeldman
2011/07/08 09:17:17
why line break?
yurys
2011/07/08 15:35:53
Doesn't fit on 1 line.
|
| + WorkerProcessHost** host, |
| + int* route_id) { |
| + for (IdMap::iterator it = map_.begin(); |
|
pfeldman
2011/07/08 09:17:17
ditto
yurys
2011/07/08 15:35:53
Done.
|
| + it != map_.end(); ++it) { |
| + if (it->c == devtools_id) { |
| + *host = it->a; |
| + *route_id = it->b; |
| + return true; |
| + } |
| + } |
| + return false; |
| + } |
| + |
| + bool TakeWorkerInfo( |
| + int devtools_id, |
| + WorkerProcessHost** host, |
| + int* route_id) { |
| + for (IdMap::iterator it = map_.begin(); |
| + it != map_.end(); ++it) { |
| + if (it->c == devtools_id) { |
| + *host = it->a; |
| + *route_id = it->b; |
| + map_.erase(it); |
| + return true; |
| + } |
| + } |
| + return false; |
| + } |
| + |
| + void WorkerDevToolsMessageFilterClosing(int worker_process_host_id) { |
| + IdMap::iterator it = map_.begin(); |
| + while (it != map_.end()) { |
| + if (it->a->id() == worker_process_host_id) |
| + it = map_.erase(it); |
| + else |
| + ++it; |
| + } |
| + } |
| + |
| + private: |
| + int next_id_; |
| + typedef Tuple3<WorkerProcessHost*, int, int> Entry; |
| + typedef std::list<Entry> IdMap; |
| + IdMap map_; |
| + DISALLOW_COPY_AND_ASSIGN(DevToolsWorkerIds); |
| +}; |
| + |
| +namespace { |
| + |
| +void ForwardToWorkerDevToolsAgentOnIOThread( |
| + int worker_devtools_id, |
| + const IPC::Message& message) { |
| + WorkerDevToolsManager::GetInstance()->ForwardToWorkerDevToolsAgent( |
| + worker_devtools_id, message); |
| +} |
| + |
| +void NotifyWorkerDevToolsClientClosingOnIOThread(int worker_devtools_id) { |
| + WorkerDevToolsManager::GetInstance()->WorkerDevToolsClientClosing( |
|
pfeldman
2011/07/08 09:17:17
WorkerDevToolsManagerIO
yurys
2011/07/08 15:35:53
Done.
|
| + worker_devtools_id); |
| +} |
| + |
| +class WorkerDevToolsClients : public DevToolsClientHost::CloseListener { |
|
pfeldman
2011/07/08 09:17:17
Can Clients be merged with the Ids?
yurys
2011/07/08 15:35:53
No, they live on different threads.
|
| + public: |
| + static WorkerDevToolsClients* GetInstance() { |
| + static WorkerDevToolsClients* instance = new WorkerDevToolsClients(); |
| + return instance; |
| + } |
| + |
| + DevToolsClientHost* FindDevToolsClient(int worker_devtools_id) { |
| + WorkerIdToClientHostMap::iterator it = |
| + worker_id_to_client_host_.find(worker_devtools_id); |
| + if (it == worker_id_to_client_host_.end()) |
| + return NULL; |
| + return it->second; |
| + } |
| + |
| + int FindWorkerDevToolsId(DevToolsClientHost* client_host) { |
| + for (WorkerIdToClientHostMap::const_iterator it = |
| + worker_id_to_client_host_.begin(); |
| + it != worker_id_to_client_host_.end(); ++it) { |
| + if (it->second == client_host) |
| + return it->first; |
| + } |
| + return -1; |
| + } |
| + |
| + void RegisterDevToolsClientForWorker( |
| + int worker_devtools_id, |
| + DevToolsClientHost* client) { |
| + client->set_close_listener(this); |
| + worker_id_to_client_host_[worker_devtools_id] = client; |
| + } |
| + |
| + private: |
| + WorkerDevToolsClients() {} |
| + virtual ~WorkerDevToolsClients() {} |
| + |
| + virtual void ClientHostClosing(DevToolsClientHost* host) { |
| + WorkerIdToClientHostMap::iterator it = worker_id_to_client_host_.begin(); |
| + for (; it != worker_id_to_client_host_.end(); ++it) { |
| + if (it->second == host) { |
| + BrowserThread::PostTask( |
| + BrowserThread::IO, FROM_HERE, |
| + NewRunnableFunction(NotifyWorkerDevToolsClientClosingOnIOThread, |
| + it->first)); |
| + worker_id_to_client_host_.erase(it); |
| + return; |
| + } |
| + } |
| + } |
| + |
| + typedef std::map<int, DevToolsClientHost*> WorkerIdToClientHostMap; |
| + WorkerIdToClientHostMap worker_id_to_client_host_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(WorkerDevToolsClients); |
| +}; |
| + |
| +} // namespace |
| + |
| +// static |
| +WorkerDevToolsManager* WorkerDevToolsManager::GetInstance() { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + return Singleton<WorkerDevToolsManager>::get(); |
| +} |
| + |
| +WorkerDevToolsManager::WorkerDevToolsManager() |
| + : devtools_worker_ids_(new DevToolsWorkerIds()) { |
| +} |
| + |
| +WorkerDevToolsManager::~WorkerDevToolsManager() { |
| +} |
| + |
| + |
| +bool WorkerDevToolsManager::ForwardToWorkerDevToolsAgent( |
| + DevToolsClientHost* from, |
| + const IPC::Message& message) { |
| + int worker_devtools_id = WorkerDevToolsClients::GetInstance()-> |
| + FindWorkerDevToolsId(from); |
| + if (worker_devtools_id == -1) |
| + return false; |
| + BrowserThread::PostTask( |
| + BrowserThread::IO, FROM_HERE, |
| + NewRunnableFunction( |
| + ForwardToWorkerDevToolsAgentOnIOThread, |
| + worker_devtools_id, |
| + IPC::Message(message))); |
| + return true; |
| +} |
| + |
| +static void OpenDevToolsForWorkerOnUIThread( |
| + int worker_devtools_id) { |
| + Profile* profile = ProfileManager::GetDefaultProfile(); |
| + if (!profile) |
| + return; |
| + DevToolsWindow* window = DevToolsWindow::CreateDevToolsWindow(profile); |
| + window->Show(DEVTOOLS_TOGGLE_ACTION_NONE); |
| + WorkerDevToolsClients::GetInstance()->RegisterDevToolsClientForWorker( |
| + worker_devtools_id, window); |
| +} |
| + |
| +static WorkerProcessHost* FindWorkerProcessHostForWorker( |
| + int worker_process_host_id, |
| + int worker_route_id) { |
| + BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); |
| + for (; !iter.Done(); ++iter) { |
| + if (iter->id() != worker_process_host_id) |
| + continue; |
| + WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); |
| + const WorkerProcessHost::Instances& instances = worker->instances(); |
| + for (WorkerProcessHost::Instances::const_iterator i = instances.begin(); |
| + i != instances.end(); ++i) { |
| + if (i->shared() && i->worker_route_id() == worker_route_id) |
| + return worker; |
| + } |
| + return NULL; |
| + } |
| + return NULL; |
| +} |
| + |
| +void WorkerDevToolsManager::OpenDevToolsForWorker(int worker_process_host_id, |
| + int worker_route_id) { |
| + WorkerProcessHost* host = FindWorkerProcessHostForWorker( |
| + worker_process_host_id, |
| + worker_route_id); |
| + if (!host) |
| + return; |
| + |
| + int devtools_id = devtools_worker_ids_->FindDevToolsId( |
| + worker_process_host_id, worker_route_id); |
| + // DevTools client is already attached. |
| + if (devtools_id != -1) |
| + return; |
| + |
| + host->Send(new WorkerDevToolsAgentMsg_Attach(worker_route_id)); |
| + |
| + devtools_id = devtools_worker_ids_->CreateDevToolsId( |
| + host, worker_route_id); |
| + BrowserThread::PostTask( |
| + BrowserThread::UI, FROM_HERE, |
| + NewRunnableFunction( |
| + OpenDevToolsForWorkerOnUIThread, |
| + devtools_id)); |
| +} |
| + |
| +void WorkerDevToolsManager::WorkerDevToolsClientClosing( |
| + int worker_devtools_id) { |
| + WorkerProcessHost* host; |
| + int route_id; |
| + if (!devtools_worker_ids_->TakeWorkerInfo( |
| + worker_devtools_id, &host, &route_id)) |
| + return; |
| + host->Send(new WorkerDevToolsAgentMsg_Detach(route_id)); |
| +} |
| + |
| +static void ForwardToDevToolsClientOnUIThread( |
| + int worker_devtools_id, |
| + const IPC::Message& message) { |
| + DevToolsClientHost* client = WorkerDevToolsClients::GetInstance()-> |
| + FindDevToolsClient(worker_devtools_id); |
| + if (client) |
| + client->SendMessageToClient(message); |
| +} |
| + |
| +void WorkerDevToolsManager::ForwardToDevToolsClient( |
| + int worker_process_host_id, |
| + int worker_route_id, |
| + const IPC::Message& message) { |
| + int devtools_id = devtools_worker_ids_->FindDevToolsId( |
| + worker_process_host_id, worker_route_id); |
| + DCHECK(devtools_id != -1); |
| + if (devtools_id == -1) |
| + return; |
| + BrowserThread::PostTask( |
| + BrowserThread::UI, FROM_HERE, |
| + NewRunnableFunction( |
| + ForwardToDevToolsClientOnUIThread, |
| + devtools_id, |
| + IPC::Message(message))); |
| +} |
| + |
| +void WorkerDevToolsManager::ForwardToWorkerDevToolsAgent( |
| + int worker_devtools_id, |
| + const IPC::Message& message) { |
| + WorkerProcessHost* host; |
| + int route_id; |
| + if (!devtools_worker_ids_->FindWorkerInfo( |
| + worker_devtools_id, &host, &route_id)) |
| + return; |
| + IPC::Message* msg = new IPC::Message(message); |
| + msg->set_routing_id(route_id); |
| + host->Send(msg); |
| +} |
| + |
| +void WorkerDevToolsManager::WorkerProcessDestroying( |
| + int worker_process_host_id) { |
| + devtools_worker_ids_->WorkerDevToolsMessageFilterClosing( |
| + worker_process_host_id); |
| +} |
| + |