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