Index: content/browser/debugger/worker_devtools_manager_io.cc |
diff --git a/content/browser/debugger/worker_devtools_manager_io.cc b/content/browser/debugger/worker_devtools_manager_io.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..55fe5a4f8144f9c411b560072b0ac1b2d19d9e95 |
--- /dev/null |
+++ b/content/browser/debugger/worker_devtools_manager_io.cc |
@@ -0,0 +1,306 @@ |
+// 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_io.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" |
+ |
+namespace { |
+ |
+ |
pfeldman
2011/07/11 12:07:16
Blank line
yurys
2011/07/11 15:13:11
Done.
|
+void NotifyWorkerDevToolsClientClosingOnIOThread(int worker_process_host_id, |
+ int worker_route_id) { |
+ WorkerDevToolsManagerIO::GetInstance()->WorkerDevToolsClientClosing( |
+ worker_process_host_id, |
+ worker_route_id); |
+} |
+ |
+class WorkerDevToolsClients : public DevToolsClientHost::CloseListener { |
pfeldman
2011/07/11 12:07:16
ClientsUI ?
yurys
2011/07/11 15:13:11
Done.
|
+ public: |
+ static WorkerDevToolsClients* GetInstance() { |
+ static WorkerDevToolsClients* instance = new WorkerDevToolsClients(); |
+ return instance; |
+ } |
+ |
+ DevToolsClientHost* FindDevToolsClient(int worker_process_host_id, |
+ int worker_route_id) { |
+ WorkerIdToClientHostMap::iterator it = |
+ worker_id_to_client_host_.find(WorkerId(worker_process_host_id, |
+ worker_route_id)); |
+ if (it == worker_id_to_client_host_.end()) |
+ return NULL; |
+ return it->second; |
+ } |
+ |
+ bool FindWorkerInfo(DevToolsClientHost* client_host, |
+ int* host_id, |
+ int* route_id) { |
+ for (WorkerIdToClientHostMap::const_iterator it = |
+ worker_id_to_client_host_.begin(); |
+ it != worker_id_to_client_host_.end(); ++it) { |
+ if (it->second == client_host) { |
+ WorkerId id = it->first; |
+ *host_id = id.first; |
+ *route_id = id.second; |
+ return true; |
+ } |
+ } |
+ return false; |
+ } |
+ |
+ void RegisterDevToolsClientForWorker(int worker_process_host_id, |
+ int worker_route_id, |
+ DevToolsClientHost* client) { |
+ client->set_close_listener(this); |
+ WorkerId worker_id(worker_process_host_id, worker_route_id); |
+ worker_id_to_client_host_[worker_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) { |
+ WorkerId id = it->first; |
+ BrowserThread::PostTask( |
+ BrowserThread::IO, FROM_HERE, |
+ NewRunnableFunction(NotifyWorkerDevToolsClientClosingOnIOThread, |
+ id.first, id.second)); |
+ worker_id_to_client_host_.erase(it); |
+ return; |
+ } |
+ } |
+ } |
+ |
+ typedef std::pair<int, int> WorkerId; |
+ typedef std::map<WorkerId, DevToolsClientHost*> WorkerIdToClientHostMap; |
+ WorkerIdToClientHostMap worker_id_to_client_host_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(WorkerDevToolsClients); |
+}; |
+ |
+} // namespace |
+ |
+class WorkerDevToolsManagerIO::InspectedWorkersList { |
+ public: |
+ InspectedWorkersList() {} |
+ |
+ void AddInstance(WorkerProcessHost* host, int route_id) { |
+ DCHECK(!Contains(host->id(), route_id)); |
+ map_.push_back(Entry(host, route_id)); |
+ } |
+ |
+ bool Contains(int host_id, int route_id) { |
+ return FindHost(host_id, route_id) != NULL; |
+ } |
+ |
+ WorkerProcessHost* FindHost(int host_id, int route_id) { |
+ Entries::iterator it = FindEntry(host_id, route_id); |
+ if (it == map_.end()) |
+ return NULL; |
+ return it->host; |
+ } |
+ |
+ WorkerProcessHost* RemoveInstance(int host_id, int route_id) { |
+ Entries::iterator it = FindEntry(host_id, route_id); |
+ if (it == map_.end()) |
+ return NULL; |
+ WorkerProcessHost* host = it->host; |
+ map_.erase(it); |
+ return host; |
+ } |
+ |
+ void WorkerDevToolsMessageFilterClosing(int worker_process_host_id) { |
+ Entries::iterator it = map_.begin(); |
+ while (it != map_.end()) { |
+ if (it->host->id() == worker_process_host_id) |
+ it = map_.erase(it); |
+ else |
+ ++it; |
+ } |
+ } |
+ |
+ private: |
+ struct Entry { |
+ Entry(WorkerProcessHost* host, int route_id) |
+ : host(host), |
+ route_id(route_id) {} |
+ WorkerProcessHost* const host; |
+ int const route_id; |
+ }; |
+ typedef std::list<Entry> Entries; |
+ |
+ Entries::iterator FindEntry(int host_id, int route_id) { |
+ Entries::iterator it = map_.begin(); |
+ while (it != map_.end()) { |
+ if (it->host->id() == host_id && it->route_id == route_id) |
+ break; |
+ } |
+ return it; |
+ } |
+ |
+ Entries map_; |
+ DISALLOW_COPY_AND_ASSIGN(InspectedWorkersList); |
+}; |
+ |
+// static |
+WorkerDevToolsManagerIO* WorkerDevToolsManagerIO::GetInstance() { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ return Singleton<WorkerDevToolsManagerIO>::get(); |
+} |
+ |
+WorkerDevToolsManagerIO::WorkerDevToolsManagerIO() |
+ : inspected_workers_(new InspectedWorkersList()) { |
+} |
+ |
+WorkerDevToolsManagerIO::~WorkerDevToolsManagerIO() { |
+} |
+ |
+bool WorkerDevToolsManagerIO::ForwardToWorkerDevToolsAgentOnUIThread( |
+ DevToolsClientHost* from, |
+ const IPC::Message& message) { |
+ int worker_process_host_id; |
+ int worker_route_id; |
+ if (!WorkerDevToolsClients::GetInstance()->FindWorkerInfo( |
+ from, &worker_process_host_id, &worker_route_id)) |
+ return false; |
+ BrowserThread::PostTask( |
+ BrowserThread::IO, FROM_HERE, |
+ NewRunnableFunction( |
+ ForwardToWorkerDevToolsAgentOnIOThread, |
+ worker_process_host_id, |
+ worker_route_id, |
+ IPC::Message(message))); |
+ return true; |
+} |
+ |
+static void OpenDevToolsForWorkerOnUIThread(int worker_process_host_id, |
+ int worker_route_id) { |
+ Profile* profile = ProfileManager::GetDefaultProfile(); |
+ if (!profile) |
+ return; |
+ DevToolsWindow* window = DevToolsWindow::CreateDevToolsWindowForWorker( |
+ profile); |
+ window->Show(DEVTOOLS_TOGGLE_ACTION_NONE); |
+ WorkerDevToolsClients::GetInstance()->RegisterDevToolsClientForWorker( |
+ worker_process_host_id, worker_route_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 WorkerDevToolsManagerIO::OpenDevToolsForWorker(int worker_process_host_id, |
+ int worker_route_id) { |
+ WorkerProcessHost* host = FindWorkerProcessHostForWorker( |
+ worker_process_host_id, |
+ worker_route_id); |
+ if (!host) |
+ return; |
+ |
+ // DevTools client is already attached. |
+ if (inspected_workers_->Contains(worker_process_host_id, worker_route_id)) |
+ return; |
+ |
+ host->Send(new WorkerDevToolsAgentMsg_Attach(worker_route_id)); |
+ |
+ inspected_workers_->AddInstance(host, worker_route_id); |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, FROM_HERE, |
+ NewRunnableFunction( |
+ OpenDevToolsForWorkerOnUIThread, |
+ worker_process_host_id, |
+ worker_route_id)); |
+} |
+ |
+void WorkerDevToolsManagerIO::WorkerDevToolsClientClosing( |
+ int worker_process_host_id, |
+ int worker_route_id) { |
+ WorkerProcessHost* host = inspected_workers_->RemoveInstance( |
+ worker_process_host_id, worker_route_id); |
+ if (host) |
+ host->Send(new WorkerDevToolsAgentMsg_Detach(worker_route_id)); |
+} |
+ |
+static void ForwardToDevToolsClientOnUIThread( |
+ int worker_process_host_id, |
+ int worker_route_id, |
+ const IPC::Message& message) { |
+ DevToolsClientHost* client = WorkerDevToolsClients::GetInstance()-> |
+ FindDevToolsClient(worker_process_host_id, worker_route_id); |
+ if (client) |
+ client->SendMessageToClient(message); |
+} |
+ |
+void WorkerDevToolsManagerIO::ForwardToDevToolsClient( |
+ int worker_process_host_id, |
+ int worker_route_id, |
+ const IPC::Message& message) { |
+ if (!inspected_workers_->Contains(worker_process_host_id, worker_route_id)) { |
+ NOTREACHED(); |
+ return; |
+ } |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, FROM_HERE, |
+ NewRunnableFunction( |
+ ForwardToDevToolsClientOnUIThread, |
+ worker_process_host_id, |
+ worker_route_id, |
+ IPC::Message(message))); |
+} |
+ |
+void WorkerDevToolsManagerIO::WorkerProcessDestroying( |
+ int worker_process_host_id) { |
+ inspected_workers_->WorkerDevToolsMessageFilterClosing( |
+ worker_process_host_id); |
+} |
+ |
+void WorkerDevToolsManagerIO::ForwardToWorkerDevToolsAgentOnIOThread( |
+ int worker_process_host_id, |
+ int worker_route_id, |
+ const IPC::Message& message) { |
+ WorkerDevToolsManagerIO::GetInstance()->ForwardToWorkerDevToolsAgent( |
+ worker_process_host_id, worker_route_id, message); |
+} |
+ |
+void WorkerDevToolsManagerIO::ForwardToWorkerDevToolsAgent( |
+ int worker_process_host_id, |
+ int worker_route_id, |
+ const IPC::Message& message) { |
+ WorkerProcessHost* host = inspected_workers_->FindHost( |
+ worker_process_host_id, |
+ worker_route_id); |
+ if (!host) |
+ return; |
+ IPC::Message* msg = new IPC::Message(message); |
+ msg->set_routing_id(worker_route_id); |
+ host->Send(msg); |
+} |