| 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/worker_devtools_manager.h" |
| 6 | 6 |
| 7 #include <list> | 7 #include <list> |
| 8 #include <map> | 8 #include <map> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/lazy_instance.h" | 11 #include "base/lazy_instance.h" |
| 12 #include "content/browser/devtools/devtools_agent_host.h" | 12 #include "content/browser/devtools/devtools_agent_host.h" |
| 13 #include "content/browser/devtools/devtools_manager_impl.h" | 13 #include "content/browser/devtools/devtools_manager_impl.h" |
| 14 #include "content/browser/devtools/worker_devtools_message_filter.h" | 14 #include "content/browser/devtools/worker_devtools_message_filter.h" |
| 15 #include "content/browser/worker_host/worker_service_impl.h" | 15 #include "content/browser/worker_host/worker_service_impl.h" |
| 16 #include "content/common/devtools_messages.h" | 16 #include "content/common/devtools_messages.h" |
| 17 #include "content/public/browser/browser_thread.h" | 17 #include "content/public/browser/browser_thread.h" |
| 18 #include "content/public/browser/child_process_data.h" | 18 #include "content/public/browser/child_process_data.h" |
| 19 #include "content/public/browser/devtools_agent_host_registry.h" | 19 #include "content/public/browser/devtools_agent_host_registry.h" |
| 20 #include "content/public/common/process_type.h" | 20 #include "content/public/common/process_type.h" |
| 21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDevToolsAgent.h" | 21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDevToolsAgent.h" |
| 22 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebCString.h
" | 22 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebCString.h
" |
| 23 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" | 23 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" |
| 24 | 24 |
| 25 using WebKit::WebDevToolsAgent; |
| 26 |
| 25 namespace content { | 27 namespace content { |
| 26 | 28 |
| 27 // Called on the UI thread. | 29 // Called on the UI thread. |
| 28 // static | 30 // static |
| 29 DevToolsAgentHost* DevToolsAgentHostRegistry::GetDevToolsAgentHostForWorker( | 31 DevToolsAgentHost* DevToolsAgentHostRegistry::GetDevToolsAgentHostForWorker( |
| 30 int worker_process_id, | 32 int worker_process_id, |
| 31 int worker_route_id) { | 33 int worker_route_id) { |
| 32 return WorkerDevToolsManager::GetDevToolsAgentHostForWorker( | 34 return WorkerDevToolsManager::GetDevToolsAgentHostForWorker( |
| 33 worker_process_id, | 35 worker_process_id, |
| 34 worker_route_id); | 36 worker_route_id); |
| 35 } | 37 } |
| 36 | 38 |
| 37 namespace { | 39 namespace { |
| 38 | 40 |
| 41 static WorkerDevToolsManager::WorkerId g_null_id = std::make_pair(-1, -1); |
| 42 |
| 39 typedef std::map<WorkerDevToolsManager::WorkerId, | 43 typedef std::map<WorkerDevToolsManager::WorkerId, |
| 40 WorkerDevToolsManager::WorkerDevToolsAgentHost*> AgentHosts; | 44 WorkerDevToolsManager::WorkerDevToolsAgentHost*> AgentHosts; |
| 41 typedef std::map<WorkerDevToolsManager::WorkerId, | |
| 42 int> OrphanHosts; | |
| 43 base::LazyInstance<AgentHosts>::Leaky g_agent_map = LAZY_INSTANCE_INITIALIZER; | 45 base::LazyInstance<AgentHosts>::Leaky g_agent_map = LAZY_INSTANCE_INITIALIZER; |
| 44 base::LazyInstance<OrphanHosts>::Leaky g_orphan_map = LAZY_INSTANCE_INITIALIZER; | 46 base::LazyInstance<AgentHosts>::Leaky g_orphan_map = LAZY_INSTANCE_INITIALIZER; |
| 45 | 47 |
| 46 } // namespace | 48 } // namespace |
| 47 | 49 |
| 48 struct WorkerDevToolsManager::TerminatedInspectedWorker { | 50 struct WorkerDevToolsManager::TerminatedInspectedWorker { |
| 49 TerminatedInspectedWorker(WorkerId id, const GURL& url, const string16& name) | 51 TerminatedInspectedWorker(WorkerId id, const GURL& url, const string16& name) |
| 50 : old_worker_id(id), | 52 : old_worker_id(id), |
| 51 worker_url(url), | 53 worker_url(url), |
| 52 worker_name(name) {} | 54 worker_name(name) {} |
| 53 WorkerId old_worker_id; | 55 WorkerId old_worker_id; |
| 54 GURL worker_url; | 56 GURL worker_url; |
| 55 string16 worker_name; | 57 string16 worker_name; |
| 56 }; | 58 }; |
| 57 | 59 |
| 58 | 60 |
| 59 class WorkerDevToolsManager::WorkerDevToolsAgentHost | 61 class WorkerDevToolsManager::WorkerDevToolsAgentHost |
| 60 : public DevToolsAgentHost { | 62 : public DevToolsAgentHost { |
| 61 public: | 63 public: |
| 62 explicit WorkerDevToolsAgentHost(WorkerId worker_id) | 64 explicit WorkerDevToolsAgentHost(WorkerId worker_id) { |
| 63 : worker_id_(worker_id) { | 65 SetWorkerId(worker_id, false); |
| 66 } |
| 67 |
| 68 void SetWorkerId(WorkerId worker_id, bool reattach) { |
| 69 worker_id_ = worker_id; |
| 64 g_agent_map.Get()[worker_id_] = this; | 70 g_agent_map.Get()[worker_id_] = this; |
| 71 |
| 65 BrowserThread::PostTask( | 72 BrowserThread::PostTask( |
| 66 BrowserThread::IO, | 73 BrowserThread::IO, |
| 67 FROM_HERE, | 74 FROM_HERE, |
| 68 base::Bind( | 75 base::Bind( |
| 69 &RegisterAgent, | 76 &ConnectToWorker, |
| 70 worker_id.first, | 77 worker_id.first, |
| 71 worker_id.second)); | 78 worker_id.second)); |
| 79 |
| 80 if (reattach) |
| 81 Reattach(state_); |
| 72 } | 82 } |
| 73 | 83 |
| 74 void WorkerDestroyed() { | 84 void ResetWorkerId() { |
| 75 NotifyCloseListener(); | 85 g_agent_map.Get().erase(worker_id_); |
| 86 worker_id_ = g_null_id; |
| 87 } |
| 88 |
| 89 virtual void Detach() { |
| 90 DevToolsAgentHost::Detach(); |
| 91 SelfDestruct(); |
| 92 } |
| 93 |
| 94 void SaveAgentRuntimeState(const std::string& state) { |
| 95 state_ = state; |
| 96 } |
| 97 |
| 98 void ConnectionFailed() { |
| 99 // Depending on whether we are connected or not, we should disconnect and |
| 100 // self-destruct. |
| 101 if (NotifyCloseListener()) |
| 102 return; // Detach will delete this instance. |
| 103 SelfDestruct(); |
| 104 } |
| 105 |
| 106 void SelfDestruct() { |
| 76 delete this; | 107 delete this; |
| 77 } | 108 } |
| 78 | 109 |
| 79 private: | 110 private: |
| 80 virtual ~WorkerDevToolsAgentHost() { | 111 virtual ~WorkerDevToolsAgentHost() { |
| 81 g_agent_map.Get().erase(worker_id_); | 112 g_agent_map.Get().erase(worker_id_); |
| 82 } | 113 } |
| 83 | 114 |
| 84 static void RegisterAgent( | 115 static void ConnectToWorker( |
| 85 int worker_process_id, | 116 int worker_process_id, |
| 86 int worker_route_id) { | 117 int worker_route_id) { |
| 87 WorkerDevToolsManager::GetInstance()->RegisterDevToolsAgentHostForWorker( | 118 WorkerDevToolsManager::GetInstance()->ConnectDevToolsAgentHostToWorker( |
| 88 worker_process_id, worker_route_id); | 119 worker_process_id, worker_route_id); |
| 89 } | 120 } |
| 90 | 121 |
| 91 static void ForwardToWorkerDevToolsAgent( | 122 static void ForwardToWorkerDevToolsAgent( |
| 92 int worker_process_id, | 123 int worker_process_id, |
| 93 int worker_route_id, | 124 int worker_route_id, |
| 94 IPC::Message* message) { | 125 IPC::Message* message) { |
| 95 WorkerDevToolsManager::GetInstance()->ForwardToWorkerDevToolsAgent( | 126 WorkerDevToolsManager::GetInstance()->ForwardToWorkerDevToolsAgent( |
| 96 worker_process_id, worker_route_id, *message); | 127 worker_process_id, worker_route_id, *message); |
| 97 } | 128 } |
| 98 | 129 |
| 99 // DevToolsAgentHost implementation. | 130 // DevToolsAgentHost implementation. |
| 100 virtual void SendMessageToAgent(IPC::Message* message) OVERRIDE { | 131 virtual void SendMessageToAgent(IPC::Message* message) OVERRIDE { |
| 132 if (worker_id_ == g_null_id) { |
| 133 delete message; |
| 134 return; |
| 135 } |
| 101 BrowserThread::PostTask( | 136 BrowserThread::PostTask( |
| 102 BrowserThread::IO, FROM_HERE, | 137 BrowserThread::IO, FROM_HERE, |
| 103 base::Bind( | 138 base::Bind( |
| 104 &WorkerDevToolsAgentHost::ForwardToWorkerDevToolsAgent, | 139 &WorkerDevToolsAgentHost::ForwardToWorkerDevToolsAgent, |
| 105 worker_id_.first, | 140 worker_id_.first, |
| 106 worker_id_.second, | 141 worker_id_.second, |
| 107 base::Owned(message))); | 142 base::Owned(message))); |
| 108 } | 143 } |
| 144 |
| 109 virtual void NotifyClientAttaching() OVERRIDE {} | 145 virtual void NotifyClientAttaching() OVERRIDE {} |
| 110 virtual void NotifyClientDetaching() OVERRIDE {} | 146 virtual void NotifyClientDetaching() OVERRIDE {} |
| 111 virtual int GetRenderProcessId() OVERRIDE { return -1; } | 147 virtual int GetRenderProcessId() OVERRIDE { return -1; } |
| 112 | 148 |
| 113 WorkerId worker_id_; | 149 WorkerId worker_id_; |
| 150 std::string state_; |
| 114 | 151 |
| 115 DISALLOW_COPY_AND_ASSIGN(WorkerDevToolsAgentHost); | 152 DISALLOW_COPY_AND_ASSIGN(WorkerDevToolsAgentHost); |
| 116 }; | 153 }; |
| 117 | 154 |
| 118 | 155 |
| 119 class WorkerDevToolsManager::DetachedClientHosts { | 156 class WorkerDevToolsManager::DetachedClientHosts { |
| 120 public: | 157 public: |
| 121 static void WorkerReloaded(WorkerId old_id, WorkerId new_id) { | 158 static void WorkerReloaded(WorkerId old_id, WorkerId new_id) { |
| 122 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 159 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 123 if (ReattachClient(old_id, new_id)) | 160 AgentHosts::iterator it = g_orphan_map.Get().find(old_id); |
| 161 if (it != g_orphan_map.Get().end()) { |
| 162 g_orphan_map.Get().erase(old_id); |
| 163 it->second->SetWorkerId(new_id, true); |
| 124 return; | 164 return; |
| 165 } |
| 125 RemovePendingWorkerData(old_id); | 166 RemovePendingWorkerData(old_id); |
| 126 } | 167 } |
| 127 | 168 |
| 128 static void WorkerDestroyed(WorkerId id) { | 169 static void WorkerDestroyed(WorkerId id) { |
| 129 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 170 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 130 AgentHosts::iterator it = g_agent_map.Get().find(id); | 171 AgentHosts::iterator it = g_agent_map.Get().find(id); |
| 131 if (it == g_agent_map.Get().end()) { | 172 if (it == g_agent_map.Get().end()) { |
| 132 RemovePendingWorkerData(id); | 173 RemovePendingWorkerData(id); |
| 133 return; | 174 return; |
| 134 } | 175 } |
| 176 |
| 135 WorkerDevToolsAgentHost* agent = it->second; | 177 WorkerDevToolsAgentHost* agent = it->second; |
| 136 DevToolsManagerImpl::GetInstance()->DispatchOnInspectorFrontend( | 178 DevToolsManagerImpl* devtools_manager = DevToolsManagerImpl::GetInstance(); |
| 137 agent, | 179 DevToolsClientHost* client_host = |
| 138 WebKit::WebDevToolsAgent::workerDisconnectedFromWorkerEvent().utf8()); | 180 devtools_manager->GetDevToolsClientHostFor(agent); |
| 139 int cookie = DevToolsManagerImpl::GetInstance()->DetachClientHost(agent); | 181 |
| 140 agent->WorkerDestroyed(); | 182 if (!client_host) { |
| 141 if (cookie == -1) { | 183 // Agent has no client hosts -> delete it. |
| 142 RemovePendingWorkerData(id); | 184 RemovePendingWorkerData(id); |
| 185 agent->SelfDestruct(); |
| 143 return; | 186 return; |
| 144 } | 187 } |
| 145 g_orphan_map.Get()[id] = cookie; | 188 |
| 189 // Client host is debugging this worker agent host. |
| 190 devtools_manager->DispatchOnInspectorFrontend( |
| 191 agent, |
| 192 WebDevToolsAgent::workerDisconnectedFromWorkerEvent().utf8()); |
| 193 g_orphan_map.Get()[id] = agent; |
| 194 agent->ResetWorkerId(); |
| 146 } | 195 } |
| 147 | 196 |
| 148 private: | 197 private: |
| 149 DetachedClientHosts() {} | 198 DetachedClientHosts() {} |
| 150 ~DetachedClientHosts() {} | 199 ~DetachedClientHosts() {} |
| 151 | 200 |
| 152 static bool ReattachClient(WorkerId old_id, WorkerId new_id) { | |
| 153 OrphanHosts::iterator it = g_orphan_map.Get().find(old_id); | |
| 154 if (it == g_orphan_map.Get().end()) | |
| 155 return false; | |
| 156 DevToolsAgentHost* agent = | |
| 157 WorkerDevToolsManager::GetDevToolsAgentHostForWorker( | |
| 158 new_id.first, | |
| 159 new_id.second); | |
| 160 DevToolsManagerImpl::GetInstance()->AttachClientHost( | |
| 161 it->second, | |
| 162 agent); | |
| 163 g_orphan_map.Get().erase(it); | |
| 164 return true; | |
| 165 } | |
| 166 | |
| 167 static void RemovePendingWorkerData(WorkerId id) { | 201 static void RemovePendingWorkerData(WorkerId id) { |
| 168 BrowserThread::PostTask( | 202 BrowserThread::PostTask( |
| 169 BrowserThread::IO, FROM_HERE, | 203 BrowserThread::IO, FROM_HERE, |
| 170 base::Bind(&RemoveInspectedWorkerDataOnIOThread, id)); | 204 base::Bind(&RemoveInspectedWorkerDataOnIOThread, id)); |
| 171 } | 205 } |
| 172 | 206 |
| 173 static void RemoveInspectedWorkerDataOnIOThread(WorkerId id) { | 207 static void RemoveInspectedWorkerDataOnIOThread(WorkerId id) { |
| 174 WorkerDevToolsManager::GetInstance()->RemoveInspectedWorkerData(id); | 208 WorkerDevToolsManager::GetInstance()->RemoveInspectedWorkerData(id); |
| 175 } | 209 } |
| 176 }; | 210 }; |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 298 } | 332 } |
| 299 | 333 |
| 300 static WorkerProcessHost* FindWorkerProcess(int worker_process_id) { | 334 static WorkerProcessHost* FindWorkerProcess(int worker_process_id) { |
| 301 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) { | 335 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) { |
| 302 if (iter.GetData().id == worker_process_id) | 336 if (iter.GetData().id == worker_process_id) |
| 303 return *iter; | 337 return *iter; |
| 304 } | 338 } |
| 305 return NULL; | 339 return NULL; |
| 306 } | 340 } |
| 307 | 341 |
| 308 void WorkerDevToolsManager::RegisterDevToolsAgentHostForWorker( | 342 void WorkerDevToolsManager::ConnectDevToolsAgentHostToWorker( |
| 309 int worker_process_id, | 343 int worker_process_id, |
| 310 int worker_route_id) { | 344 int worker_route_id) { |
| 311 if (WorkerProcessHost* process = FindWorkerProcess(worker_process_id)) { | 345 if (WorkerProcessHost* process = FindWorkerProcess(worker_process_id)) { |
| 312 const WorkerProcessHost::Instances& instances = process->instances(); | 346 const WorkerProcessHost::Instances& instances = process->instances(); |
| 313 for (WorkerProcessHost::Instances::const_iterator i = instances.begin(); | 347 for (WorkerProcessHost::Instances::const_iterator i = instances.begin(); |
| 314 i != instances.end(); ++i) { | 348 i != instances.end(); ++i) { |
| 315 if (i->worker_route_id() == worker_route_id) { | 349 if (i->worker_route_id() == worker_route_id) { |
| 316 DCHECK(FindInspectedWorker(worker_process_id, worker_route_id) == | 350 DCHECK(FindInspectedWorker(worker_process_id, worker_route_id) == |
| 317 inspected_workers_.end()); | 351 inspected_workers_.end()); |
| 318 inspected_workers_.push_back( | 352 inspected_workers_.push_back( |
| 319 InspectedWorker(process, worker_route_id, i->url(), i->name())); | 353 InspectedWorker(process, worker_route_id, i->url(), i->name())); |
| 320 return; | 354 return; |
| 321 } | 355 } |
| 322 } | 356 } |
| 323 } | 357 } |
| 324 NotifyWorkerDestroyedOnIOThread(worker_process_id, worker_route_id); | 358 NotifyConnectionFailedOnIOThread(worker_process_id, worker_route_id); |
| 325 } | 359 } |
| 326 | 360 |
| 327 void WorkerDevToolsManager::ForwardToDevToolsClient( | 361 void WorkerDevToolsManager::ForwardToDevToolsClient( |
| 328 int worker_process_id, | 362 int worker_process_id, |
| 329 int worker_route_id, | 363 int worker_route_id, |
| 330 const std::string& message) { | 364 const std::string& message) { |
| 331 if (FindInspectedWorker(worker_process_id, worker_route_id) == | 365 if (FindInspectedWorker(worker_process_id, worker_route_id) == |
| 332 inspected_workers_.end()) { | 366 inspected_workers_.end()) { |
| 333 NOTREACHED(); | 367 NOTREACHED(); |
| 334 return; | 368 return; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 383 | 417 |
| 384 // static | 418 // static |
| 385 void WorkerDevToolsManager::SaveAgentRuntimeStateOnUIThread( | 419 void WorkerDevToolsManager::SaveAgentRuntimeStateOnUIThread( |
| 386 int worker_process_id, | 420 int worker_process_id, |
| 387 int worker_route_id, | 421 int worker_route_id, |
| 388 const std::string& state) { | 422 const std::string& state) { |
| 389 AgentHosts::iterator it = g_agent_map.Get().find(WorkerId(worker_process_id, | 423 AgentHosts::iterator it = g_agent_map.Get().find(WorkerId(worker_process_id, |
| 390 worker_route_id)); | 424 worker_route_id)); |
| 391 if (it == g_agent_map.Get().end()) | 425 if (it == g_agent_map.Get().end()) |
| 392 return; | 426 return; |
| 393 DevToolsManagerImpl::GetInstance()->SaveAgentRuntimeState(it->second, state); | 427 it->second->SaveAgentRuntimeState(state); |
| 394 } | 428 } |
| 395 | 429 |
| 396 // static | 430 // static |
| 397 void WorkerDevToolsManager::NotifyWorkerDestroyedOnIOThread( | 431 void WorkerDevToolsManager::NotifyConnectionFailedOnIOThread( |
| 398 int worker_process_id, | 432 int worker_process_id, |
| 399 int worker_route_id) { | 433 int worker_route_id) { |
| 400 BrowserThread::PostTask( | 434 BrowserThread::PostTask( |
| 401 BrowserThread::UI, FROM_HERE, | 435 BrowserThread::UI, FROM_HERE, |
| 402 base::Bind( | 436 base::Bind( |
| 403 &WorkerDevToolsManager::NotifyWorkerDestroyedOnUIThread, | 437 &WorkerDevToolsManager::NotifyConnectionFailedOnUIThread, |
| 404 worker_process_id, | 438 worker_process_id, |
| 405 worker_route_id)); | 439 worker_route_id)); |
| 406 } | 440 } |
| 407 | 441 |
| 408 // static | 442 // static |
| 409 void WorkerDevToolsManager::NotifyWorkerDestroyedOnUIThread( | 443 void WorkerDevToolsManager::NotifyConnectionFailedOnUIThread( |
| 410 int worker_process_id, | 444 int worker_process_id, |
| 411 int worker_route_id) { | 445 int worker_route_id) { |
| 412 AgentHosts::iterator it = g_agent_map.Get().find(WorkerId(worker_process_id, | 446 AgentHosts::iterator it = g_agent_map.Get().find(WorkerId(worker_process_id, |
| 413 worker_route_id)); | 447 worker_route_id)); |
| 414 if (it != g_agent_map.Get().end()) | 448 if (it != g_agent_map.Get().end()) |
| 415 it->second->WorkerDestroyed(); | 449 it->second->ConnectionFailed(); |
| 416 } | 450 } |
| 417 | 451 |
| 418 // static | 452 // static |
| 419 void WorkerDevToolsManager::SendResumeToWorker(const WorkerId& id) { | 453 void WorkerDevToolsManager::SendResumeToWorker(const WorkerId& id) { |
| 420 if (WorkerProcessHost* process = FindWorkerProcess(id.first)) | 454 if (WorkerProcessHost* process = FindWorkerProcess(id.first)) |
| 421 process->Send(new DevToolsAgentMsg_ResumeWorkerContext(id.second)); | 455 process->Send(new DevToolsAgentMsg_ResumeWorkerContext(id.second)); |
| 422 } | 456 } |
| 423 | 457 |
| 424 } // namespace content | 458 } // namespace content |
| OLD | NEW |