Chromium Code Reviews| OLD | NEW | 
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "content/browser/devtools/worker_devtools_manager.h" | 5 #include "content/browser/devtools/shared_worker_devtools_manager.h" | 
| 6 | 6 | 
| 7 #include <list> | |
| 8 #include <map> | |
| 9 | |
| 10 #include "base/bind.h" | |
| 11 #include "base/lazy_instance.h" | 7 #include "base/lazy_instance.h" | 
| 8 #include "base/logging.h" | |
| 9 #include "base/memory/singleton.h" | |
| 
 
kinuko
2014/03/24 12:24:02
nit: we already have this in .h
 
horo
2014/03/25 06:28:17
Done.
 
 | |
| 12 #include "content/browser/devtools/devtools_manager_impl.h" | 10 #include "content/browser/devtools/devtools_manager_impl.h" | 
| 13 #include "content/browser/devtools/devtools_protocol.h" | 11 #include "content/browser/devtools/devtools_protocol.h" | 
| 14 #include "content/browser/devtools/devtools_protocol_constants.h" | 12 #include "content/browser/devtools/devtools_protocol_constants.h" | 
| 15 #include "content/browser/devtools/ipc_devtools_agent_host.h" | 13 #include "content/browser/devtools/ipc_devtools_agent_host.h" | 
| 16 #include "content/browser/devtools/worker_devtools_message_filter.h" | 14 #include "content/browser/shared_worker/shared_worker_instance.h" | 
| 17 #include "content/browser/worker_host/worker_service_impl.h" | |
| 18 #include "content/common/devtools_messages.h" | 15 #include "content/common/devtools_messages.h" | 
| 19 #include "content/public/browser/browser_thread.h" | 16 #include "content/public/browser/browser_thread.h" | 
| 20 #include "content/public/browser/child_process_data.h" | 17 #include "content/public/browser/render_process_host.h" | 
| 21 #include "content/public/common/process_type.h" | 18 #include "content/public/browser/worker_service.h" | 
| 19 #include "ipc/ipc_listener.h" | |
| 22 | 20 | 
| 23 namespace content { | 21 namespace content { | 
| 24 | 22 | 
| 25 // Called on the UI thread. | |
| 26 // static | |
| 27 scoped_refptr<DevToolsAgentHost> DevToolsAgentHost::GetForWorker( | |
| 28 int worker_process_id, | |
| 29 int worker_route_id) { | |
| 30 return WorkerDevToolsManager::GetDevToolsAgentHostForWorker( | |
| 31 worker_process_id, | |
| 32 worker_route_id); | |
| 33 } | |
| 34 | |
| 35 namespace { | 23 namespace { | 
| 36 | 24 | 
| 37 typedef std::map<WorkerDevToolsManager::WorkerId, | 25 typedef std::map<SharedWorkerDevToolsManager::WorkerId, | 
| 38 WorkerDevToolsManager::WorkerDevToolsAgentHost*> AgentHosts; | 26 SharedWorkerDevToolsManager::SharedWorkerDevToolsAgentHost*> | 
| 27 AgentHosts; | |
| 39 base::LazyInstance<AgentHosts>::Leaky g_agent_map = LAZY_INSTANCE_INITIALIZER; | 28 base::LazyInstance<AgentHosts>::Leaky g_agent_map = LAZY_INSTANCE_INITIALIZER; | 
| 40 base::LazyInstance<AgentHosts>::Leaky g_orphan_map = LAZY_INSTANCE_INITIALIZER; | 29 base::LazyInstance<AgentHosts>::Leaky g_orphan_map = LAZY_INSTANCE_INITIALIZER; | 
| 41 | 30 | 
| 31 bool SendMessageToWorker(const SharedWorkerDevToolsManager::WorkerId& worker_id, | |
| 32 IPC::Message* message) { | |
| 33 RenderProcessHost* host = RenderProcessHost::FromID(worker_id.first); | |
| 34 if (!host) { | |
| 35 delete message; | |
| 36 return false; | |
| 37 } | |
| 38 message->set_routing_id(worker_id.second); | |
| 39 host->Send(message); | |
| 40 return true; | |
| 41 } | |
| 42 | |
| 42 } // namespace | 43 } // namespace | 
| 43 | 44 | 
| 44 struct WorkerDevToolsManager::TerminatedInspectedWorker { | 45 class SharedWorkerDevToolsManager::SharedWorkerDevToolsAgentHost | 
| 45 TerminatedInspectedWorker(WorkerId id, | 46 : public IPCDevToolsAgentHost, | 
| 46 const GURL& url, | 47 public IPC::Listener { | 
| 47 const base::string16& name) | 48 public: | 
| 48 : old_worker_id(id), | 49 SharedWorkerDevToolsAgentHost(WorkerId worker_id) | 
| 49 worker_url(url), | 50 : has_worker_id_(false) { | 
| 50 worker_name(name) {} | 51 SetWorkerId(worker_id, false); | 
| 
 
kinuko
2014/03/24 12:24:02
nit: can you add '/* reattach */' comment after 'f
 
horo
2014/03/25 06:28:17
Done.
 
 | |
| 51 WorkerId old_worker_id; | 52 } | 
| 53 // IPCDevToolsAgentHost implementation. | |
| 54 virtual void SendMessageToAgent(IPC::Message* message) OVERRIDE { | |
| 55 SendMessageToWorker(worker_id_, message); | |
| 56 } | |
| 57 virtual void OnClientAttached() OVERRIDE {} | |
| 58 virtual void OnClientDetached() OVERRIDE {} | |
| 59 | |
| 60 // IPC::Listener implementation. | |
| 61 virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE { | |
| 62 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 63 bool handled = true; | |
| 64 IPC_BEGIN_MESSAGE_MAP(SharedWorkerDevToolsAgentHost, msg) | |
| 65 IPC_MESSAGE_HANDLER(DevToolsClientMsg_DispatchOnInspectorFrontend, | |
| 66 OnDispatchOnInspectorFrontend) | |
| 67 IPC_MESSAGE_HANDLER(DevToolsHostMsg_SaveAgentRuntimeState, | |
| 68 OnSaveAgentRumtimeState) | |
| 
 
kinuko
2014/03/24 12:24:02
typo: Rumtime -> Runtime
 
horo
2014/03/25 06:28:17
Done.
 
 | |
| 69 IPC_MESSAGE_UNHANDLED(handled = false) | |
| 70 IPC_END_MESSAGE_MAP() | |
| 71 return handled; | |
| 72 } | |
| 73 | |
| 74 void OnDispatchOnInspectorFrontend(const std::string& message) { | |
| 75 DevToolsManagerImpl::GetInstance()->DispatchOnInspectorFrontend(this, | |
| 76 message); | |
| 
 
kinuko
2014/03/24 12:24:02
indent is off
 
horo
2014/03/25 06:28:17
Done.
 
 | |
| 77 } | |
| 
 
kinuko
2014/03/24 12:24:02
nit: please have an empty line between methods unl
 
horo
2014/03/25 06:28:17
Done.
Moved to private.
 
 | |
| 78 void OnSaveAgentRumtimeState(const std::string& state) { | |
| 79 SaveAgentRuntimeState(state); | |
| 
 
kinuko
2014/03/24 12:24:02
nit: as far as this is the only place we call it,
 
horo
2014/03/25 06:28:17
Done.
 
 | |
| 80 } | |
| 81 | |
| 82 void SetWorkerId(WorkerId worker_id, bool reattach) { | |
| 83 if (!SharedWorkerDevToolsManager::GetInstance() | |
| 84 ->ConnectDevToolsAgentHostToWorker(worker_id)) { | |
| 85 NotifyCloseListener(); | |
| 86 return; | |
| 87 } | |
| 88 worker_id_ = worker_id; | |
| 89 if (!has_worker_id_) { | |
| 90 AddRef(); // Balanced in ResetWorkerId. | |
| 91 } | |
| 
 
kinuko
2014/03/24 12:24:02
nit: no need of { } for single-line body
 
horo
2014/03/25 06:28:17
Done.
 
 | |
| 92 has_worker_id_ = true; | |
| 93 g_agent_map.Get()[worker_id_] = this; | |
| 94 | |
| 95 if (RenderProcessHost* host = RenderProcessHost::FromID(worker_id_.first)) | |
| 96 host->AddRoute(worker_id_.second, this); | |
| 97 | |
| 98 if (reattach) | |
| 99 Reattach(state_); | |
| 100 } | |
| 101 | |
| 102 void ResetWorkerId() { | |
| 103 CHECK(has_worker_id_); | |
| 104 g_agent_map.Get().erase(worker_id_); | |
| 105 has_worker_id_ = false; | |
| 106 if (RenderProcessHost* host = RenderProcessHost::FromID(worker_id_.first)) | |
| 107 host->RemoveRoute(worker_id_.second); | |
| 108 Release(); // Balanced in SetWorkerId. | |
| 109 } | |
| 110 | |
| 111 void SaveAgentRuntimeState(const std::string& state) { state_ = state; } | |
| 112 | |
| 113 private: | |
| 114 virtual ~SharedWorkerDevToolsAgentHost() { | |
| 115 if (has_worker_id_) { | |
| 
 
kinuko
2014/03/24 12:24:02
Could we reach here other without going through Re
 
horo
2014/03/25 06:28:17
Done.
We should call RemoveInspectedWorkerData and
 
 | |
| 116 SharedWorkerDevToolsManager::GetInstance()->RemoveInspectedWorkerData( | |
| 117 worker_id_); | |
| 118 g_agent_map.Get().erase(worker_id_); | |
| 119 g_orphan_map.Get().erase(worker_id_); | |
| 120 if (RenderProcessHost* host = | |
| 121 RenderProcessHost::FromID(worker_id_.first)) { | |
| 122 host->RemoveRoute(worker_id_.second); | |
| 123 } | |
| 124 } | |
| 125 } | |
| 
 
kinuko
2014/03/24 12:24:02
nit: can we have one empty line here?
 
horo
2014/03/25 06:28:17
Done.
 
 | |
| 126 bool has_worker_id_; | |
| 127 WorkerId worker_id_; | |
| 128 std::string state_; | |
| 129 DISALLOW_COPY_AND_ASSIGN(SharedWorkerDevToolsAgentHost); | |
| 130 }; | |
| 131 | |
| 132 struct SharedWorkerDevToolsManager::WorkerInfo { | |
| 133 WorkerInfo(WorkerId id, const GURL& url, const base::string16& name) | |
| 134 : worker_id(id), worker_url(url), worker_name(name) {} | |
| 135 WorkerId worker_id; | |
| 52 GURL worker_url; | 136 GURL worker_url; | 
| 53 base::string16 worker_name; | 137 base::string16 worker_name; | 
| 54 }; | 138 }; | 
| 55 | 139 | 
| 56 | |
| 57 class WorkerDevToolsManager::WorkerDevToolsAgentHost | |
| 58 : public IPCDevToolsAgentHost { | |
| 59 public: | |
| 60 explicit WorkerDevToolsAgentHost(WorkerId worker_id) | |
| 61 : has_worker_id_(false) { | |
| 62 SetWorkerId(worker_id, false); | |
| 63 } | |
| 64 | |
| 65 void SetWorkerId(WorkerId worker_id, bool reattach) { | |
| 66 worker_id_ = worker_id; | |
| 67 if (!has_worker_id_) | |
| 68 AddRef(); // Balanced in ResetWorkerId. | |
| 69 has_worker_id_ = true; | |
| 70 g_agent_map.Get()[worker_id_] = this; | |
| 71 | |
| 72 BrowserThread::PostTask( | |
| 73 BrowserThread::IO, | |
| 74 FROM_HERE, | |
| 75 base::Bind( | |
| 76 &ConnectToWorker, | |
| 77 worker_id.first, | |
| 78 worker_id.second)); | |
| 79 | |
| 80 if (reattach) | |
| 81 Reattach(state_); | |
| 82 } | |
| 83 | |
| 84 void ResetWorkerId() { | |
| 85 g_agent_map.Get().erase(worker_id_); | |
| 86 has_worker_id_ = false; | |
| 87 Release(); // Balanced in SetWorkerId. | |
| 88 } | |
| 89 | |
| 90 void SaveAgentRuntimeState(const std::string& state) { | |
| 91 state_ = state; | |
| 92 } | |
| 93 | |
| 94 void ConnectionFailed() { | |
| 95 NotifyCloseListener(); | |
| 96 // Object can be deleted here. | |
| 97 } | |
| 98 | |
| 99 private: | |
| 100 virtual ~WorkerDevToolsAgentHost(); | |
| 101 | |
| 102 static void ConnectToWorker( | |
| 103 int worker_process_id, | |
| 104 int worker_route_id) { | |
| 105 WorkerDevToolsManager::GetInstance()->ConnectDevToolsAgentHostToWorker( | |
| 106 worker_process_id, worker_route_id); | |
| 107 } | |
| 108 | |
| 109 static void ForwardToWorkerDevToolsAgent( | |
| 110 int worker_process_id, | |
| 111 int worker_route_id, | |
| 112 IPC::Message* message) { | |
| 113 WorkerDevToolsManager::GetInstance()->ForwardToWorkerDevToolsAgent( | |
| 114 worker_process_id, worker_route_id, *message); | |
| 115 } | |
| 116 | |
| 117 // IPCDevToolsAgentHost implementation. | |
| 118 virtual void SendMessageToAgent(IPC::Message* message) OVERRIDE { | |
| 119 if (!has_worker_id_) { | |
| 120 delete message; | |
| 121 return; | |
| 122 } | |
| 123 BrowserThread::PostTask( | |
| 124 BrowserThread::IO, FROM_HERE, | |
| 125 base::Bind( | |
| 126 &WorkerDevToolsAgentHost::ForwardToWorkerDevToolsAgent, | |
| 127 worker_id_.first, | |
| 128 worker_id_.second, | |
| 129 base::Owned(message))); | |
| 130 } | |
| 131 | |
| 132 virtual void OnClientAttached() OVERRIDE {} | |
| 133 virtual void OnClientDetached() OVERRIDE {} | |
| 134 | |
| 135 bool has_worker_id_; | |
| 136 WorkerId worker_id_; | |
| 137 std::string state_; | |
| 138 | |
| 139 DISALLOW_COPY_AND_ASSIGN(WorkerDevToolsAgentHost); | |
| 140 }; | |
| 141 | |
| 142 | |
| 143 class WorkerDevToolsManager::DetachedClientHosts { | |
| 144 public: | |
| 145 static void WorkerReloaded(WorkerId old_id, WorkerId new_id) { | |
| 146 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 147 AgentHosts::iterator it = g_orphan_map.Get().find(old_id); | |
| 148 if (it != g_orphan_map.Get().end()) { | |
| 149 it->second->SetWorkerId(new_id, true); | |
| 150 g_orphan_map.Get().erase(old_id); | |
| 151 return; | |
| 152 } | |
| 153 RemovePendingWorkerData(old_id); | |
| 154 } | |
| 155 | |
| 156 static void WorkerDestroyed(WorkerId id) { | |
| 157 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 158 AgentHosts::iterator it = g_agent_map.Get().find(id); | |
| 159 if (it == g_agent_map.Get().end()) { | |
| 160 RemovePendingWorkerData(id); | |
| 161 return; | |
| 162 } | |
| 163 | |
| 164 WorkerDevToolsAgentHost* agent = it->second; | |
| 165 DevToolsManagerImpl* devtools_manager = DevToolsManagerImpl::GetInstance(); | |
| 166 if (!agent->IsAttached()) { | |
| 167 // Agent has no client hosts -> delete it. | |
| 168 RemovePendingWorkerData(id); | |
| 169 return; | |
| 170 } | |
| 171 | |
| 172 // Client host is debugging this worker agent host. | |
| 173 std::string notification = DevToolsProtocol::CreateNotification( | |
| 174 devtools::Worker::disconnectedFromWorker::kName, NULL)->Serialize(); | |
| 175 devtools_manager->DispatchOnInspectorFrontend(agent, notification); | |
| 176 g_orphan_map.Get()[id] = agent; | |
| 177 agent->ResetWorkerId(); | |
| 178 } | |
| 179 | |
| 180 static void RemovePendingWorkerData(WorkerId id) { | |
| 181 BrowserThread::PostTask( | |
| 182 BrowserThread::IO, FROM_HERE, | |
| 183 base::Bind(&RemoveInspectedWorkerDataOnIOThread, id)); | |
| 184 } | |
| 185 | |
| 186 private: | |
| 187 DetachedClientHosts() {} | |
| 188 ~DetachedClientHosts() {} | |
| 189 | |
| 190 static void RemoveInspectedWorkerDataOnIOThread(WorkerId id) { | |
| 191 WorkerDevToolsManager::GetInstance()->RemoveInspectedWorkerData(id); | |
| 192 } | |
| 193 }; | |
| 194 | |
| 195 struct WorkerDevToolsManager::InspectedWorker { | |
| 196 InspectedWorker(WorkerProcessHost* host, int route_id, const GURL& url, | |
| 197 const base::string16& name) | |
| 198 : host(host), | |
| 199 route_id(route_id), | |
| 200 worker_url(url), | |
| 201 worker_name(name) {} | |
| 202 WorkerProcessHost* const host; | |
| 203 int const route_id; | |
| 204 GURL worker_url; | |
| 205 base::string16 worker_name; | |
| 206 }; | |
| 207 | |
| 208 // static | 140 // static | 
| 209 WorkerDevToolsManager* WorkerDevToolsManager::GetInstance() { | 141 SharedWorkerDevToolsManager* SharedWorkerDevToolsManager::GetInstance() { | 
| 210 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 142 DCHECK(WorkerService::EmbeddedSharedWorkerEnabled()); | 
| 211 return Singleton<WorkerDevToolsManager>::get(); | 143 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
| 144 return Singleton<SharedWorkerDevToolsManager>::get(); | |
| 212 } | 145 } | 
| 213 | 146 | 
| 214 // static | 147 // static | 
| 215 DevToolsAgentHost* WorkerDevToolsManager::GetDevToolsAgentHostForWorker( | 148 DevToolsAgentHost* SharedWorkerDevToolsManager::GetDevToolsAgentHostForWorker( | 
| 216 int worker_process_id, | 149 int worker_process_id, | 
| 217 int worker_route_id) { | 150 int worker_route_id) { | 
| 151 DCHECK(WorkerService::EmbeddedSharedWorkerEnabled()); | |
| 218 WorkerId id(worker_process_id, worker_route_id); | 152 WorkerId id(worker_process_id, worker_route_id); | 
| 219 AgentHosts::iterator it = g_agent_map.Get().find(id); | 153 AgentHosts::iterator it = g_agent_map.Get().find(id); | 
| 220 if (it == g_agent_map.Get().end()) | 154 if (it == g_agent_map.Get().end()) | 
| 221 return new WorkerDevToolsAgentHost(id); | 155 return new SharedWorkerDevToolsAgentHost(id); | 
| 
 
kinuko
2014/03/24 12:24:02
It looks we could return a new refptr without stor
 
horo
2014/03/25 06:28:17
It is OK.
When ConnectDevToolsAgentHostToWorker fa
 
 | |
| 222 return it->second; | 156 return it->second; | 
| 223 } | 157 } | 
| 224 | 158 | 
| 225 WorkerDevToolsManager::WorkerDevToolsManager() { | 159 // static | 
| 226 } | 160 bool SharedWorkerDevToolsManager::HasDevToolsAgentHostForWorker( | 
| 227 | 161 int worker_process_id, | 
| 228 WorkerDevToolsManager::~WorkerDevToolsManager() { | |
| 229 } | |
| 230 | |
| 231 void WorkerDevToolsManager::WorkerCreated( | |
| 232 WorkerProcessHost* worker, | |
| 233 const WorkerProcessHost::WorkerInstance& instance) { | |
| 234 for (TerminatedInspectedWorkers::iterator it = terminated_workers_.begin(); | |
| 235 it != terminated_workers_.end(); ++it) { | |
| 236 if (instance.Matches(it->worker_url, it->worker_name, | |
| 237 instance.partition(), | |
| 238 instance.resource_context())) { | |
| 239 worker->Send(new DevToolsAgentMsg_PauseWorkerContextOnStart( | |
| 240 instance.worker_route_id())); | |
| 241 WorkerId new_worker_id(worker->GetData().id, instance.worker_route_id()); | |
| 242 paused_workers_[new_worker_id] = it->old_worker_id; | |
| 243 terminated_workers_.erase(it); | |
| 244 return; | |
| 245 } | |
| 246 } | |
| 247 } | |
| 248 | |
| 249 void WorkerDevToolsManager::WorkerDestroyed( | |
| 250 WorkerProcessHost* worker, | |
| 251 int worker_route_id) { | 162 int worker_route_id) { | 
| 252 InspectedWorkersList::iterator it = FindInspectedWorker( | 163 DCHECK(WorkerService::EmbeddedSharedWorkerEnabled()); | 
| 253 worker->GetData().id, | 164 WorkerId id(worker_process_id, worker_route_id); | 
| 254 worker_route_id); | 165 return g_agent_map.Get().find(id) != g_agent_map.Get().end(); | 
| 166 } | |
| 167 | |
| 168 SharedWorkerDevToolsManager::SharedWorkerDevToolsManager() {} | |
| 169 | |
| 170 SharedWorkerDevToolsManager::~SharedWorkerDevToolsManager() {} | |
| 171 | |
| 172 void SharedWorkerDevToolsManager::WorkerCreated(int worker_process_id, | |
| 173 int worker_route_id, | |
| 174 const GURL& url, | |
| 175 const base::string16& name) { | |
| 176 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 177 const WorkerId id(worker_process_id, worker_route_id); | |
| 178 WorkerInfoMap::iterator it = FindTerminatedWorker(url, name); | |
| 179 if (it != terminated_workers_.end()) { | |
| 180 scoped_ptr<WorkerInfo> info = terminated_workers_.take_and_erase(it); | |
| 181 WorkerId old_id = info->worker_id; | |
| 182 AgentHosts::iterator orphan_agent_host_it = g_orphan_map.Get().find(old_id); | |
| 183 if (orphan_agent_host_it != g_orphan_map.Get().end()) { | |
| 184 g_agent_map.Get()[id] = orphan_agent_host_it->second; | |
| 185 } | |
| 186 paused_workers_.set(id, info.Pass()); | |
| 187 SendMessageToWorker( | |
| 188 id, new DevToolsAgentMsg_PauseWorkerContextOnStart(worker_route_id)); | |
| 189 } else { | |
| 190 scoped_ptr<WorkerInfo> info(new WorkerInfo(id, url, name)); | |
| 191 uninspected_workers_.set(id, info.Pass()); | |
| 192 } | |
| 193 } | |
| 194 | |
| 195 void SharedWorkerDevToolsManager::WorkerDestroyed(int worker_process_id, | |
| 196 int worker_route_id) { | |
| 197 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 198 const WorkerId id(worker_process_id, worker_route_id); | |
| 199 if (uninspected_workers_.erase(id)) | |
| 200 return; | |
| 201 WorkerInfoMap::iterator it = inspected_workers_.find(id); | |
| 255 if (it == inspected_workers_.end()) | 202 if (it == inspected_workers_.end()) | 
| 256 return; | 203 return; | 
| 257 | 204 scoped_ptr<WorkerInfo> info = inspected_workers_.take_and_erase(it); | 
| 258 WorkerId worker_id(worker->GetData().id, worker_route_id); | 205 | 
| 259 terminated_workers_.push_back(TerminatedInspectedWorker( | 206 AgentHosts::iterator agent_host_it = g_agent_map.Get().find(id); | 
| 260 worker_id, | 207 if (agent_host_it == g_agent_map.Get().end()) | 
| 261 it->worker_url, | 208 return; | 
| 262 it->worker_name)); | 209 | 
| 263 inspected_workers_.erase(it); | 210 if (!agent_host_it->second->IsAttached()) { | 
| 264 BrowserThread::PostTask( | 211 RemoveInspectedWorkerData(id); | 
| 265 BrowserThread::UI, FROM_HERE, | 212 agent_host_it->second->ResetWorkerId(); | 
| 266 base::Bind(&DetachedClientHosts::WorkerDestroyed, worker_id)); | 213 return; | 
| 267 } | 214 } | 
| 268 | 215 | 
| 269 void WorkerDevToolsManager::WorkerContextStarted(WorkerProcessHost* process, | 216 // Client host is debugging this worker agent host. | 
| 270 int worker_route_id) { | 217 std::string notification = | 
| 271 WorkerId new_worker_id(process->GetData().id, worker_route_id); | 218 DevToolsProtocol::CreateNotification( | 
| 272 PausedWorkers::iterator it = paused_workers_.find(new_worker_id); | 219 devtools::Worker::disconnectedFromWorker::kName, NULL)->Serialize(); | 
| 220 DevToolsManagerImpl::GetInstance()->DispatchOnInspectorFrontend( | |
| 221 agent_host_it->second, notification); | |
| 222 terminated_workers_.set(id, info.Pass()); | |
| 223 g_orphan_map.Get()[id] = agent_host_it->second; | |
| 224 agent_host_it->second->ResetWorkerId(); | |
| 225 } | |
| 226 | |
| 227 void SharedWorkerDevToolsManager::WorkerContextStarted(int worker_process_id, | |
| 228 int worker_route_id) { | |
| 229 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 230 const WorkerId id(worker_process_id, worker_route_id); | |
| 231 WorkerInfoMap::iterator it = paused_workers_.find(id); | |
| 273 if (it == paused_workers_.end()) | 232 if (it == paused_workers_.end()) | 
| 274 return; | 233 return; | 
| 275 | 234 scoped_ptr<WorkerInfo> info = paused_workers_.take_and_erase(it); | 
| 276 BrowserThread::PostTask( | 235 const WorkerId old_id(info->worker_id); | 
| 277 BrowserThread::UI, FROM_HERE, | 236 info->worker_id = id; | 
| 278 base::Bind( | 237 uninspected_workers_.set(id, info.Pass()); | 
| 279 &DetachedClientHosts::WorkerReloaded, | 238 | 
| 280 it->second, | 239 AgentHosts::iterator orphan_agent_host_it = g_orphan_map.Get().find(old_id); | 
| 281 new_worker_id)); | 240 if (orphan_agent_host_it == g_orphan_map.Get().end()) | 
| 282 paused_workers_.erase(it); | 241 return; | 
| 283 } | 242 orphan_agent_host_it->second->SetWorkerId(id, true); | 
| 284 | 243 g_orphan_map.Get().erase(old_id); | 
| 285 void WorkerDevToolsManager::RemoveInspectedWorkerData( | 244 g_agent_map.Get().erase(old_id); | 
| 286 const WorkerId& id) { | 245 } | 
| 287 for (TerminatedInspectedWorkers::iterator it = terminated_workers_.begin(); | 246 | 
| 288 it != terminated_workers_.end(); ++it) { | 247 bool SharedWorkerDevToolsManager::ConnectDevToolsAgentHostToWorker( | 
| 289 if (it->old_worker_id == id) { | 248 const WorkerId& worker_id) { | 
| 290 terminated_workers_.erase(it); | 249 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
| 291 return; | 250 WorkerInfoMap::iterator it = uninspected_workers_.find(worker_id); | 
| 292 } | 251 if (it == uninspected_workers_.end()) | 
| 293 } | 252 return false; | 
| 294 | 253 inspected_workers_.set(worker_id, uninspected_workers_.take_and_erase(it)); | 
| 295 for (PausedWorkers::iterator it = paused_workers_.begin(); | 254 return true; | 
| 296 it != paused_workers_.end(); ++it) { | 255 } | 
| 297 if (it->second == id) { | 256 | 
| 298 SendResumeToWorker(it->first); | 257 void SharedWorkerDevToolsManager::RemoveInspectedWorkerData( | 
| 258 const WorkerId& worker_id) { | |
| 259 if (terminated_workers_.erase(worker_id)) | |
| 260 return; | |
| 261 | |
| 262 for (WorkerInfoMap::iterator it = paused_workers_.begin(); | |
| 263 it != paused_workers_.end(); | |
| 264 ++it) { | |
| 265 if (it->second->worker_id == worker_id) { | |
| 266 SendMessageToWorker( | |
| 267 it->first, | |
| 268 new DevToolsAgentMsg_ResumeWorkerContext(it->first.second)); | |
| 299 paused_workers_.erase(it); | 269 paused_workers_.erase(it); | 
| 300 return; | 270 return; | 
| 301 } | 271 } | 
| 302 } | 272 } | 
| 303 } | 273 } | 
| 304 | 274 | 
| 305 WorkerDevToolsManager::InspectedWorkersList::iterator | 275 SharedWorkerDevToolsManager::WorkerInfoMap::iterator | 
| 306 WorkerDevToolsManager::FindInspectedWorker( | 276 SharedWorkerDevToolsManager::FindTerminatedWorker(const GURL& url, | 
| 307 int host_id, int route_id) { | 277 const base::string16& name) { | 
| 308 InspectedWorkersList::iterator it = inspected_workers_.begin(); | 278 WorkerInfoMap::iterator it = terminated_workers_.begin(); | 
| 309 while (it != inspected_workers_.end()) { | 279 for (; it != terminated_workers_.end(); ++it) { | 
| 310 if (it->host->GetData().id == host_id && it->route_id == route_id) | 280 if (SharedWorkerInstance::UrlNameMatches(it->second->worker_url, | 
| 281 it->second->worker_name, | |
| 282 url, | |
| 283 name)) { | |
| 311 break; | 284 break; | 
| 312 ++it; | 285 } | 
| 313 } | 286 } | 
| 314 return it; | 287 return it; | 
| 315 } | 288 } | 
| 316 | 289 | 
| 317 static WorkerProcessHost* FindWorkerProcess(int worker_process_id) { | |
| 318 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) { | |
| 319 if (iter.GetData().id == worker_process_id) | |
| 320 return *iter; | |
| 321 } | |
| 322 return NULL; | |
| 323 } | |
| 324 | |
| 325 void WorkerDevToolsManager::ConnectDevToolsAgentHostToWorker( | |
| 326 int worker_process_id, | |
| 327 int worker_route_id) { | |
| 328 if (WorkerProcessHost* process = FindWorkerProcess(worker_process_id)) { | |
| 329 const WorkerProcessHost::Instances& instances = process->instances(); | |
| 330 for (WorkerProcessHost::Instances::const_iterator i = instances.begin(); | |
| 331 i != instances.end(); ++i) { | |
| 332 if (i->worker_route_id() == worker_route_id) { | |
| 333 DCHECK(FindInspectedWorker(worker_process_id, worker_route_id) == | |
| 334 inspected_workers_.end()); | |
| 335 inspected_workers_.push_back( | |
| 336 InspectedWorker(process, worker_route_id, i->url(), i->name())); | |
| 337 return; | |
| 338 } | |
| 339 } | |
| 340 } | |
| 341 NotifyConnectionFailedOnIOThread(worker_process_id, worker_route_id); | |
| 342 } | |
| 343 | |
| 344 void WorkerDevToolsManager::ForwardToDevToolsClient( | |
| 345 int worker_process_id, | |
| 346 int worker_route_id, | |
| 347 const std::string& message) { | |
| 348 if (FindInspectedWorker(worker_process_id, worker_route_id) == | |
| 349 inspected_workers_.end()) { | |
| 350 NOTREACHED(); | |
| 351 return; | |
| 352 } | |
| 353 BrowserThread::PostTask( | |
| 354 BrowserThread::UI, FROM_HERE, | |
| 355 base::Bind( | |
| 356 &ForwardToDevToolsClientOnUIThread, | |
| 357 worker_process_id, | |
| 358 worker_route_id, | |
| 359 message)); | |
| 360 } | |
| 361 | |
| 362 void WorkerDevToolsManager::SaveAgentRuntimeState(int worker_process_id, | |
| 363 int worker_route_id, | |
| 364 const std::string& state) { | |
| 365 BrowserThread::PostTask( | |
| 366 BrowserThread::UI, FROM_HERE, | |
| 367 base::Bind( | |
| 368 &SaveAgentRuntimeStateOnUIThread, | |
| 369 worker_process_id, | |
| 370 worker_route_id, | |
| 371 state)); | |
| 372 } | |
| 373 | |
| 374 void WorkerDevToolsManager::ForwardToWorkerDevToolsAgent( | |
| 375 int worker_process_id, | |
| 376 int worker_route_id, | |
| 377 const IPC::Message& message) { | |
| 378 InspectedWorkersList::iterator it = FindInspectedWorker( | |
| 379 worker_process_id, | |
| 380 worker_route_id); | |
| 381 if (it == inspected_workers_.end()) | |
| 382 return; | |
| 383 IPC::Message* msg = new IPC::Message(message); | |
| 384 msg->set_routing_id(worker_route_id); | |
| 385 it->host->Send(msg); | |
| 386 } | |
| 387 | |
| 388 // static | |
| 389 void WorkerDevToolsManager::ForwardToDevToolsClientOnUIThread( | |
| 390 int worker_process_id, | |
| 391 int worker_route_id, | |
| 392 const std::string& message) { | |
| 393 AgentHosts::iterator it = g_agent_map.Get().find(WorkerId(worker_process_id, | |
| 394 worker_route_id)); | |
| 395 if (it == g_agent_map.Get().end()) | |
| 396 return; | |
| 397 DevToolsManagerImpl::GetInstance()->DispatchOnInspectorFrontend(it->second, | |
| 398 message); | |
| 399 } | |
| 400 | |
| 401 // static | |
| 402 void WorkerDevToolsManager::SaveAgentRuntimeStateOnUIThread( | |
| 403 int worker_process_id, | |
| 404 int worker_route_id, | |
| 405 const std::string& state) { | |
| 406 AgentHosts::iterator it = g_agent_map.Get().find(WorkerId(worker_process_id, | |
| 407 worker_route_id)); | |
| 408 if (it == g_agent_map.Get().end()) | |
| 409 return; | |
| 410 it->second->SaveAgentRuntimeState(state); | |
| 411 } | |
| 412 | |
| 413 // static | |
| 414 void WorkerDevToolsManager::NotifyConnectionFailedOnIOThread( | |
| 415 int worker_process_id, | |
| 416 int worker_route_id) { | |
| 417 BrowserThread::PostTask( | |
| 418 BrowserThread::UI, FROM_HERE, | |
| 419 base::Bind( | |
| 420 &WorkerDevToolsManager::NotifyConnectionFailedOnUIThread, | |
| 421 worker_process_id, | |
| 422 worker_route_id)); | |
| 423 } | |
| 424 | |
| 425 // static | |
| 426 void WorkerDevToolsManager::NotifyConnectionFailedOnUIThread( | |
| 427 int worker_process_id, | |
| 428 int worker_route_id) { | |
| 429 AgentHosts::iterator it = g_agent_map.Get().find(WorkerId(worker_process_id, | |
| 430 worker_route_id)); | |
| 431 if (it != g_agent_map.Get().end()) | |
| 432 it->second->ConnectionFailed(); | |
| 433 } | |
| 434 | |
| 435 // static | |
| 436 void WorkerDevToolsManager::SendResumeToWorker(const WorkerId& id) { | |
| 437 if (WorkerProcessHost* process = FindWorkerProcess(id.first)) | |
| 438 process->Send(new DevToolsAgentMsg_ResumeWorkerContext(id.second)); | |
| 439 } | |
| 440 | |
| 441 WorkerDevToolsManager::WorkerDevToolsAgentHost::~WorkerDevToolsAgentHost() { | |
| 442 DetachedClientHosts::RemovePendingWorkerData(worker_id_); | |
| 443 g_agent_map.Get().erase(worker_id_); | |
| 444 g_orphan_map.Get().erase(worker_id_); | |
| 445 } | |
| 446 | |
| 447 } // namespace content | 290 } // namespace content | 
| OLD | NEW |