| Index: content/browser/devtools/shared_worker_devtools_manager.cc
 | 
| diff --git a/content/browser/devtools/worker_devtools_manager.cc b/content/browser/devtools/shared_worker_devtools_manager.cc
 | 
| similarity index 10%
 | 
| copy from content/browser/devtools/worker_devtools_manager.cc
 | 
| copy to content/browser/devtools/shared_worker_devtools_manager.cc
 | 
| index 62f77e785d6c18ff28f40158baf7aeaeb92cccdd..eac5114ca2d74855299848d01606ca758ef50ab3 100644
 | 
| --- a/content/browser/devtools/worker_devtools_manager.cc
 | 
| +++ b/content/browser/devtools/shared_worker_devtools_manager.cc
 | 
| @@ -1,446 +1,248 @@
 | 
| -// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 | 
| +// Copyright 2014 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/devtools/worker_devtools_manager.h"
 | 
| +#include "content/browser/devtools/shared_worker_devtools_manager.h"
 | 
|  
 | 
| -#include <list>
 | 
| -#include <map>
 | 
| -
 | 
| -#include "base/bind.h"
 | 
| -#include "base/lazy_instance.h"
 | 
|  #include "content/browser/devtools/devtools_manager_impl.h"
 | 
|  #include "content/browser/devtools/devtools_protocol.h"
 | 
|  #include "content/browser/devtools/devtools_protocol_constants.h"
 | 
|  #include "content/browser/devtools/ipc_devtools_agent_host.h"
 | 
| -#include "content/browser/devtools/worker_devtools_message_filter.h"
 | 
| -#include "content/browser/worker_host/worker_service_impl.h"
 | 
| +#include "content/browser/shared_worker/shared_worker_instance.h"
 | 
|  #include "content/common/devtools_messages.h"
 | 
|  #include "content/public/browser/browser_thread.h"
 | 
| -#include "content/public/browser/child_process_data.h"
 | 
| -#include "content/public/common/process_type.h"
 | 
| +#include "content/public/browser/render_process_host.h"
 | 
| +#include "content/public/browser/worker_service.h"
 | 
| +#include "ipc/ipc_listener.h"
 | 
|  
 | 
|  namespace content {
 | 
|  
 | 
| -// Called on the UI thread.
 | 
| -// static
 | 
| -scoped_refptr<DevToolsAgentHost> DevToolsAgentHost::GetForWorker(
 | 
| -    int worker_process_id,
 | 
| -    int worker_route_id) {
 | 
| -  return WorkerDevToolsManager::GetDevToolsAgentHostForWorker(
 | 
| -      worker_process_id,
 | 
| -      worker_route_id);
 | 
| -}
 | 
| -
 | 
|  namespace {
 | 
|  
 | 
| -typedef std::map<WorkerDevToolsManager::WorkerId,
 | 
| -                 WorkerDevToolsManager::WorkerDevToolsAgentHost*> AgentHosts;
 | 
| -base::LazyInstance<AgentHosts>::Leaky g_agent_map = LAZY_INSTANCE_INITIALIZER;
 | 
| -base::LazyInstance<AgentHosts>::Leaky g_orphan_map = LAZY_INSTANCE_INITIALIZER;
 | 
| +bool SendMessageToWorker(const SharedWorkerDevToolsManager::WorkerId& worker_id,
 | 
| +                         IPC::Message* message) {
 | 
| +  RenderProcessHost* host = RenderProcessHost::FromID(worker_id.first);
 | 
| +  if (!host) {
 | 
| +    delete message;
 | 
| +    return false;
 | 
| +  }
 | 
| +  message->set_routing_id(worker_id.second);
 | 
| +  host->Send(message);
 | 
| +  return true;
 | 
| +}
 | 
|  
 | 
|  }  // namespace
 | 
|  
 | 
| -struct WorkerDevToolsManager::TerminatedInspectedWorker {
 | 
| -  TerminatedInspectedWorker(WorkerId id,
 | 
| -                            const GURL& url,
 | 
| -                            const base::string16& name)
 | 
| -      : old_worker_id(id),
 | 
| -        worker_url(url),
 | 
| -        worker_name(name) {}
 | 
| -  WorkerId old_worker_id;
 | 
| -  GURL worker_url;
 | 
| -  base::string16 worker_name;
 | 
| -};
 | 
| -
 | 
| -
 | 
| -class WorkerDevToolsManager::WorkerDevToolsAgentHost
 | 
| -    : public IPCDevToolsAgentHost {
 | 
| +class SharedWorkerDevToolsManager::SharedWorkerDevToolsAgentHost
 | 
| +    : public IPCDevToolsAgentHost,
 | 
| +      public IPC::Listener {
 | 
|   public:
 | 
| -  explicit WorkerDevToolsAgentHost(WorkerId worker_id)
 | 
| -      : has_worker_id_(false) {
 | 
| -    SetWorkerId(worker_id, false);
 | 
| -  }
 | 
| -
 | 
| -  void SetWorkerId(WorkerId worker_id, bool reattach) {
 | 
| -    worker_id_ = worker_id;
 | 
| -    if (!has_worker_id_)
 | 
| -      AddRef();  //  Balanced in ResetWorkerId.
 | 
| -    has_worker_id_ = true;
 | 
| -    g_agent_map.Get()[worker_id_] = this;
 | 
| -
 | 
| -    BrowserThread::PostTask(
 | 
| -        BrowserThread::IO,
 | 
| -        FROM_HERE,
 | 
| -        base::Bind(
 | 
| -            &ConnectToWorker,
 | 
| -            worker_id.first,
 | 
| -            worker_id.second));
 | 
| -
 | 
| -    if (reattach)
 | 
| -      Reattach(state_);
 | 
| -  }
 | 
| -
 | 
| -  void ResetWorkerId() {
 | 
| -    g_agent_map.Get().erase(worker_id_);
 | 
| -    has_worker_id_ = false;
 | 
| -    Release();  //  Balanced in SetWorkerId.
 | 
| -  }
 | 
| -
 | 
| -  void SaveAgentRuntimeState(const std::string& state) {
 | 
| -    state_ = state;
 | 
| -  }
 | 
| -
 | 
| -  void ConnectionFailed() {
 | 
| -    NotifyCloseListener();
 | 
| -    // Object can be deleted here.
 | 
| -  }
 | 
| -
 | 
| - private:
 | 
| -  virtual ~WorkerDevToolsAgentHost();
 | 
| -
 | 
| -  static void ConnectToWorker(
 | 
| -      int worker_process_id,
 | 
| -      int worker_route_id) {
 | 
| -    WorkerDevToolsManager::GetInstance()->ConnectDevToolsAgentHostToWorker(
 | 
| -        worker_process_id, worker_route_id);
 | 
| -  }
 | 
| -
 | 
| -  static void ForwardToWorkerDevToolsAgent(
 | 
| -      int worker_process_id,
 | 
| -      int worker_route_id,
 | 
| -      IPC::Message* message) {
 | 
| -    WorkerDevToolsManager::GetInstance()->ForwardToWorkerDevToolsAgent(
 | 
| -        worker_process_id, worker_route_id, *message);
 | 
| +  explicit SharedWorkerDevToolsAgentHost(WorkerId worker_id)
 | 
| +      : worker_id_(worker_id), worker_attached_(true) {
 | 
| +    AddRef();
 | 
| +    if (RenderProcessHost* host = RenderProcessHost::FromID(worker_id_.first))
 | 
| +      host->AddRoute(worker_id_.second, this);
 | 
|    }
 | 
|  
 | 
|    // IPCDevToolsAgentHost implementation.
 | 
|    virtual void SendMessageToAgent(IPC::Message* message) OVERRIDE {
 | 
| -    if (!has_worker_id_) {
 | 
| -      delete message;
 | 
| -      return;
 | 
| -    }
 | 
| -    BrowserThread::PostTask(
 | 
| -        BrowserThread::IO, FROM_HERE,
 | 
| -        base::Bind(
 | 
| -            &WorkerDevToolsAgentHost::ForwardToWorkerDevToolsAgent,
 | 
| -            worker_id_.first,
 | 
| -            worker_id_.second,
 | 
| -            base::Owned(message)));
 | 
| +    if (worker_attached_)
 | 
| +      SendMessageToWorker(worker_id_, message);
 | 
|    }
 | 
| -
 | 
|    virtual void OnClientAttached() OVERRIDE {}
 | 
|    virtual void OnClientDetached() OVERRIDE {}
 | 
|  
 | 
| -  bool has_worker_id_;
 | 
| -  WorkerId worker_id_;
 | 
| -  std::string state_;
 | 
| -
 | 
| -  DISALLOW_COPY_AND_ASSIGN(WorkerDevToolsAgentHost);
 | 
| -};
 | 
| -
 | 
| -
 | 
| -class WorkerDevToolsManager::DetachedClientHosts {
 | 
| - public:
 | 
| -  static void WorkerReloaded(WorkerId old_id, WorkerId new_id) {
 | 
| +  // IPC::Listener implementation.
 | 
| +  virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE {
 | 
|      DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 | 
| -    AgentHosts::iterator it = g_orphan_map.Get().find(old_id);
 | 
| -    if (it != g_orphan_map.Get().end()) {
 | 
| -      it->second->SetWorkerId(new_id, true);
 | 
| -      g_orphan_map.Get().erase(old_id);
 | 
| -      return;
 | 
| -    }
 | 
| -    RemovePendingWorkerData(old_id);
 | 
| +    bool handled = true;
 | 
| +    IPC_BEGIN_MESSAGE_MAP(SharedWorkerDevToolsAgentHost, msg)
 | 
| +    IPC_MESSAGE_HANDLER(DevToolsClientMsg_DispatchOnInspectorFrontend,
 | 
| +                        OnDispatchOnInspectorFrontend)
 | 
| +    IPC_MESSAGE_HANDLER(DevToolsHostMsg_SaveAgentRuntimeState,
 | 
| +                        OnSaveAgentRuntimeState)
 | 
| +    IPC_MESSAGE_UNHANDLED(handled = false)
 | 
| +    IPC_END_MESSAGE_MAP()
 | 
| +    return handled;
 | 
| +  }
 | 
| +
 | 
| +  void ReattachToWorker(WorkerId worker_id) {
 | 
| +    CHECK(!worker_attached_);
 | 
| +    worker_attached_ = true;
 | 
| +    worker_id_ = worker_id;
 | 
| +    AddRef();
 | 
| +    if (RenderProcessHost* host = RenderProcessHost::FromID(worker_id_.first))
 | 
| +      host->AddRoute(worker_id_.second, this);
 | 
| +    Reattach(state_);
 | 
|    }
 | 
|  
 | 
| -  static void WorkerDestroyed(WorkerId id) {
 | 
| -    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 | 
| -    AgentHosts::iterator it = g_agent_map.Get().find(id);
 | 
| -    if (it == g_agent_map.Get().end()) {
 | 
| -      RemovePendingWorkerData(id);
 | 
| -      return;
 | 
| -    }
 | 
| -
 | 
| -    WorkerDevToolsAgentHost* agent = it->second;
 | 
| -    DevToolsManagerImpl* devtools_manager = DevToolsManagerImpl::GetInstance();
 | 
| -    if (!agent->IsAttached()) {
 | 
| -      // Agent has no client hosts -> delete it.
 | 
| -      RemovePendingWorkerData(id);
 | 
| -      return;
 | 
| -    }
 | 
| -
 | 
| -    // Client host is debugging this worker agent host.
 | 
| -    std::string notification = DevToolsProtocol::CreateNotification(
 | 
| -        devtools::Worker::disconnectedFromWorker::kName, NULL)->Serialize();
 | 
| -    devtools_manager->DispatchOnInspectorFrontend(agent, notification);
 | 
| -    g_orphan_map.Get()[id] = agent;
 | 
| -    agent->ResetWorkerId();
 | 
| +  void DetachFromWorker() {
 | 
| +    CHECK(worker_attached_);
 | 
| +    worker_attached_ = false;
 | 
| +    if (RenderProcessHost* host = RenderProcessHost::FromID(worker_id_.first))
 | 
| +      host->RemoveRoute(worker_id_.second);
 | 
| +    Release();
 | 
|    }
 | 
|  
 | 
| -  static void RemovePendingWorkerData(WorkerId id) {
 | 
| -    BrowserThread::PostTask(
 | 
| -        BrowserThread::IO, FROM_HERE,
 | 
| -        base::Bind(&RemoveInspectedWorkerDataOnIOThread, id));
 | 
| -  }
 | 
| +  WorkerId worker_id() const { return worker_id_; }
 | 
|  
 | 
|   private:
 | 
| -  DetachedClientHosts() {}
 | 
| -  ~DetachedClientHosts() {}
 | 
| +  virtual ~SharedWorkerDevToolsAgentHost() {
 | 
| +    CHECK(!worker_attached_);
 | 
| +    SharedWorkerDevToolsManager::GetInstance()->RemoveInspectedWorkerData(this);
 | 
| +  }
 | 
|  
 | 
| -  static void RemoveInspectedWorkerDataOnIOThread(WorkerId id) {
 | 
| -    WorkerDevToolsManager::GetInstance()->RemoveInspectedWorkerData(id);
 | 
| +  void OnDispatchOnInspectorFrontend(const std::string& message) {
 | 
| +    DevToolsManagerImpl::GetInstance()->DispatchOnInspectorFrontend(this,
 | 
| +                                                                    message);
 | 
|    }
 | 
| -};
 | 
|  
 | 
| -struct WorkerDevToolsManager::InspectedWorker {
 | 
| -  InspectedWorker(WorkerProcessHost* host, int route_id, const GURL& url,
 | 
| -                  const base::string16& name)
 | 
| -      : host(host),
 | 
| -        route_id(route_id),
 | 
| -        worker_url(url),
 | 
| -        worker_name(name) {}
 | 
| -  WorkerProcessHost* const host;
 | 
| -  int const route_id;
 | 
| -  GURL worker_url;
 | 
| -  base::string16 worker_name;
 | 
| +  void OnSaveAgentRuntimeState(const std::string& state) { state_ = state; }
 | 
| +
 | 
| +  WorkerId worker_id_;
 | 
| +  bool worker_attached_;
 | 
| +  std::string state_;
 | 
| +  DISALLOW_COPY_AND_ASSIGN(SharedWorkerDevToolsAgentHost);
 | 
|  };
 | 
|  
 | 
|  // static
 | 
| -WorkerDevToolsManager* WorkerDevToolsManager::GetInstance() {
 | 
| -  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 | 
| -  return Singleton<WorkerDevToolsManager>::get();
 | 
| +SharedWorkerDevToolsManager* SharedWorkerDevToolsManager::GetInstance() {
 | 
| +  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 | 
| +  return Singleton<SharedWorkerDevToolsManager>::get();
 | 
|  }
 | 
|  
 | 
| -// static
 | 
| -DevToolsAgentHost* WorkerDevToolsManager::GetDevToolsAgentHostForWorker(
 | 
| +DevToolsAgentHost* SharedWorkerDevToolsManager::GetDevToolsAgentHostForWorker(
 | 
|      int worker_process_id,
 | 
|      int worker_route_id) {
 | 
|    WorkerId id(worker_process_id, worker_route_id);
 | 
| -  AgentHosts::iterator it = g_agent_map.Get().find(id);
 | 
| -  if (it == g_agent_map.Get().end())
 | 
| -    return new WorkerDevToolsAgentHost(id);
 | 
| -  return it->second;
 | 
| -}
 | 
|  
 | 
| -WorkerDevToolsManager::WorkerDevToolsManager() {
 | 
| -}
 | 
| +  WorkerInfoMap::iterator it = workers_.find(id);
 | 
| +  if (it == workers_.end())
 | 
| +    return NULL;
 | 
|  
 | 
| -WorkerDevToolsManager::~WorkerDevToolsManager() {
 | 
| -}
 | 
| +  WorkerInfo* info = it->second;
 | 
| +  if (info->state() != WORKER_UNINSPECTED)
 | 
| +    return info->agent_host();
 | 
|  
 | 
| -bool WorkerDevToolsManager::WorkerCreated(
 | 
| -    WorkerProcessHost* worker,
 | 
| -    const WorkerProcessHost::WorkerInstance& instance) {
 | 
| -  for (TerminatedInspectedWorkers::iterator it = terminated_workers_.begin();
 | 
| -       it != terminated_workers_.end(); ++it) {
 | 
| -    if (instance.Matches(it->worker_url, it->worker_name,
 | 
| -                         instance.partition(),
 | 
| -                         instance.resource_context())) {
 | 
| -      WorkerId new_worker_id(worker->GetData().id, instance.worker_route_id());
 | 
| -      paused_workers_[new_worker_id] = it->old_worker_id;
 | 
| -      terminated_workers_.erase(it);
 | 
| -      return true;
 | 
| -    }
 | 
| -  }
 | 
| -  return false;
 | 
| +  SharedWorkerDevToolsAgentHost* agent_host =
 | 
| +      new SharedWorkerDevToolsAgentHost(id);
 | 
| +  info->set_agent_host(agent_host);
 | 
| +  info->set_state(WORKER_INSPECTED);
 | 
| +  return agent_host;
 | 
|  }
 | 
|  
 | 
| -void WorkerDevToolsManager::WorkerDestroyed(
 | 
| -    WorkerProcessHost* worker,
 | 
| -    int worker_route_id) {
 | 
| -  InspectedWorkersList::iterator it = FindInspectedWorker(
 | 
| -      worker->GetData().id,
 | 
| -      worker_route_id);
 | 
| -  if (it == inspected_workers_.end())
 | 
| -    return;
 | 
| -
 | 
| -  WorkerId worker_id(worker->GetData().id, worker_route_id);
 | 
| -  terminated_workers_.push_back(TerminatedInspectedWorker(
 | 
| -      worker_id,
 | 
| -      it->worker_url,
 | 
| -      it->worker_name));
 | 
| -  inspected_workers_.erase(it);
 | 
| -  BrowserThread::PostTask(
 | 
| -      BrowserThread::UI, FROM_HERE,
 | 
| -      base::Bind(&DetachedClientHosts::WorkerDestroyed, worker_id));
 | 
| -}
 | 
| +SharedWorkerDevToolsManager::SharedWorkerDevToolsManager() {}
 | 
|  
 | 
| -void WorkerDevToolsManager::WorkerContextStarted(WorkerProcessHost* process,
 | 
| -                                                 int worker_route_id) {
 | 
| -  WorkerId new_worker_id(process->GetData().id, worker_route_id);
 | 
| -  PausedWorkers::iterator it = paused_workers_.find(new_worker_id);
 | 
| -  if (it == paused_workers_.end())
 | 
| -    return;
 | 
| +SharedWorkerDevToolsManager::~SharedWorkerDevToolsManager() {}
 | 
|  
 | 
| -  BrowserThread::PostTask(
 | 
| -      BrowserThread::UI, FROM_HERE,
 | 
| -      base::Bind(
 | 
| -          &DetachedClientHosts::WorkerReloaded,
 | 
| -          it->second,
 | 
| -          new_worker_id));
 | 
| -  paused_workers_.erase(it);
 | 
| -}
 | 
| -
 | 
| -void WorkerDevToolsManager::RemoveInspectedWorkerData(
 | 
| -    const WorkerId& id) {
 | 
| -  for (TerminatedInspectedWorkers::iterator it = terminated_workers_.begin();
 | 
| -       it != terminated_workers_.end(); ++it) {
 | 
| -    if (it->old_worker_id == id) {
 | 
| -      terminated_workers_.erase(it);
 | 
| -      return;
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
| -  for (PausedWorkers::iterator it = paused_workers_.begin();
 | 
| -       it != paused_workers_.end(); ++it) {
 | 
| -    if (it->second == id) {
 | 
| -      SendResumeToWorker(it->first);
 | 
| -      paused_workers_.erase(it);
 | 
| -      return;
 | 
| -    }
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -WorkerDevToolsManager::InspectedWorkersList::iterator
 | 
| -WorkerDevToolsManager::FindInspectedWorker(
 | 
| -    int host_id, int route_id) {
 | 
| -  InspectedWorkersList::iterator it = inspected_workers_.begin();
 | 
| -  while (it != inspected_workers_.end()) {
 | 
| -    if (it->host->GetData().id == host_id && it->route_id == route_id)
 | 
| -      break;
 | 
| -    ++it;
 | 
| -  }
 | 
| -  return it;
 | 
| -}
 | 
| -
 | 
| -static WorkerProcessHost* FindWorkerProcess(int worker_process_id) {
 | 
| -  for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) {
 | 
| -    if (iter.GetData().id == worker_process_id)
 | 
| -      return *iter;
 | 
| -  }
 | 
| -  return NULL;
 | 
| -}
 | 
| -
 | 
| -void WorkerDevToolsManager::ConnectDevToolsAgentHostToWorker(
 | 
| +bool SharedWorkerDevToolsManager::WorkerCreated(
 | 
|      int worker_process_id,
 | 
| -    int worker_route_id) {
 | 
| -  if (WorkerProcessHost* process = FindWorkerProcess(worker_process_id)) {
 | 
| -    const WorkerProcessHost::Instances& instances = process->instances();
 | 
| -    for (WorkerProcessHost::Instances::const_iterator i = instances.begin();
 | 
| -         i != instances.end(); ++i) {
 | 
| -      if (i->worker_route_id() == worker_route_id) {
 | 
| -        DCHECK(FindInspectedWorker(worker_process_id, worker_route_id) ==
 | 
| -               inspected_workers_.end());
 | 
| -        inspected_workers_.push_back(
 | 
| -            InspectedWorker(process, worker_route_id, i->url(), i->name()));
 | 
| +    int worker_route_id,
 | 
| +    const SharedWorkerInstance& instance) {
 | 
| +  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 | 
| +  const WorkerId id(worker_process_id, worker_route_id);
 | 
| +  WorkerInfoMap::iterator it = FindExistingWorkerInfo(instance);
 | 
| +  if (it == workers_.end()) {
 | 
| +    scoped_ptr<WorkerInfo> info(new WorkerInfo(instance));
 | 
| +    workers_.set(id, info.Pass());
 | 
| +    return false;
 | 
| +  }
 | 
| +  DCHECK_EQ(WORKER_TERMINATED, it->second->state());
 | 
| +  scoped_ptr<WorkerInfo> info = workers_.take_and_erase(it);
 | 
| +  info->set_state(WORKER_PAUSED);
 | 
| +  workers_.set(id, info.Pass());
 | 
| +  return true;
 | 
| +}
 | 
| +
 | 
| +void SharedWorkerDevToolsManager::WorkerDestroyed(int worker_process_id,
 | 
| +                                                  int worker_route_id) {
 | 
| +  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 | 
| +  const WorkerId id(worker_process_id, worker_route_id);
 | 
| +  WorkerInfoMap::iterator it = workers_.find(id);
 | 
| +  DCHECK(it != workers_.end());
 | 
| +  WorkerInfo* info = it->second;
 | 
| +  switch (info->state()) {
 | 
| +    case WORKER_UNINSPECTED:
 | 
| +      workers_.erase(it);
 | 
| +      break;
 | 
| +    case WORKER_INSPECTED: {
 | 
| +      SharedWorkerDevToolsAgentHost* agent_host = info->agent_host();
 | 
| +      if (!agent_host->IsAttached()) {
 | 
| +        scoped_ptr<WorkerInfo> worker_info = workers_.take_and_erase(it);
 | 
| +        agent_host->DetachFromWorker();
 | 
|          return;
 | 
|        }
 | 
| +      info->set_state(WORKER_TERMINATED);
 | 
| +      // Client host is debugging this worker agent host.
 | 
| +      std::string notification =
 | 
| +          DevToolsProtocol::CreateNotification(
 | 
| +              devtools::Worker::disconnectedFromWorker::kName, NULL)
 | 
| +              ->Serialize();
 | 
| +      DevToolsManagerImpl::GetInstance()->DispatchOnInspectorFrontend(
 | 
| +          agent_host, notification);
 | 
| +      agent_host->DetachFromWorker();
 | 
| +      break;
 | 
|      }
 | 
| -  }
 | 
| -  NotifyConnectionFailedOnIOThread(worker_process_id, worker_route_id);
 | 
| -}
 | 
| -
 | 
| -void WorkerDevToolsManager::ForwardToDevToolsClient(
 | 
| -    int worker_process_id,
 | 
| -    int worker_route_id,
 | 
| -    const std::string& message) {
 | 
| -  if (FindInspectedWorker(worker_process_id, worker_route_id) ==
 | 
| -          inspected_workers_.end()) {
 | 
| +    case WORKER_TERMINATED:
 | 
|        NOTREACHED();
 | 
| -      return;
 | 
| +      break;
 | 
| +    case WORKER_PAUSED: {
 | 
| +      scoped_ptr<WorkerInfo> worker_info = workers_.take_and_erase(it);
 | 
| +      worker_info->set_state(WORKER_TERMINATED);
 | 
| +      const WorkerId old_id = worker_info->agent_host()->worker_id();
 | 
| +      workers_.set(old_id, worker_info.Pass());
 | 
| +      break;
 | 
| +    }
 | 
|    }
 | 
| -  BrowserThread::PostTask(
 | 
| -      BrowserThread::UI, FROM_HERE,
 | 
| -      base::Bind(
 | 
| -          &ForwardToDevToolsClientOnUIThread,
 | 
| -          worker_process_id,
 | 
| -          worker_route_id,
 | 
| -          message));
 | 
|  }
 | 
|  
 | 
| -void WorkerDevToolsManager::SaveAgentRuntimeState(int worker_process_id,
 | 
| -                                                  int worker_route_id,
 | 
| -                                                  const std::string& state) {
 | 
| -  BrowserThread::PostTask(
 | 
| -      BrowserThread::UI, FROM_HERE,
 | 
| -      base::Bind(
 | 
| -          &SaveAgentRuntimeStateOnUIThread,
 | 
| -          worker_process_id,
 | 
| -          worker_route_id,
 | 
| -          state));
 | 
| -}
 | 
| -
 | 
| -void WorkerDevToolsManager::ForwardToWorkerDevToolsAgent(
 | 
| -    int worker_process_id,
 | 
| -    int worker_route_id,
 | 
| -    const IPC::Message& message) {
 | 
| -  InspectedWorkersList::iterator it = FindInspectedWorker(
 | 
| -      worker_process_id,
 | 
| -      worker_route_id);
 | 
| -  if (it == inspected_workers_.end())
 | 
| -    return;
 | 
| -  IPC::Message* msg = new IPC::Message(message);
 | 
| -  msg->set_routing_id(worker_route_id);
 | 
| -  it->host->Send(msg);
 | 
| -}
 | 
| -
 | 
| -// static
 | 
| -void WorkerDevToolsManager::ForwardToDevToolsClientOnUIThread(
 | 
| -    int worker_process_id,
 | 
| -    int worker_route_id,
 | 
| -    const std::string& message) {
 | 
| -  AgentHosts::iterator it = g_agent_map.Get().find(WorkerId(worker_process_id,
 | 
| -                                                            worker_route_id));
 | 
| -  if (it == g_agent_map.Get().end())
 | 
| +void SharedWorkerDevToolsManager::WorkerContextStarted(int worker_process_id,
 | 
| +                                                       int worker_route_id) {
 | 
| +  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 | 
| +  const WorkerId id(worker_process_id, worker_route_id);
 | 
| +  WorkerInfoMap::iterator it = workers_.find(id);
 | 
| +  DCHECK(it != workers_.end());
 | 
| +  WorkerInfo* info = it->second;
 | 
| +  if (info->state() != WORKER_PAUSED)
 | 
|      return;
 | 
| -  DevToolsManagerImpl::GetInstance()->DispatchOnInspectorFrontend(it->second,
 | 
| -                                                                  message);
 | 
| +  info->agent_host()->ReattachToWorker(id);
 | 
| +  info->set_state(WORKER_INSPECTED);
 | 
|  }
 | 
|  
 | 
| -// static
 | 
| -void WorkerDevToolsManager::SaveAgentRuntimeStateOnUIThread(
 | 
| -    int worker_process_id,
 | 
| -    int worker_route_id,
 | 
| -    const std::string& state) {
 | 
| -  AgentHosts::iterator it = g_agent_map.Get().find(WorkerId(worker_process_id,
 | 
| -                                                            worker_route_id));
 | 
| -  if (it == g_agent_map.Get().end())
 | 
| +void SharedWorkerDevToolsManager::RemoveInspectedWorkerData(
 | 
| +    SharedWorkerDevToolsAgentHost* agent_host) {
 | 
| +  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 | 
| +  const WorkerId id(agent_host->worker_id());
 | 
| +  scoped_ptr<WorkerInfo> worker_info = workers_.take_and_erase(id);
 | 
| +  if (worker_info) {
 | 
| +    DCHECK_EQ(WORKER_TERMINATED, worker_info->state());
 | 
|      return;
 | 
| -  it->second->SaveAgentRuntimeState(state);
 | 
| -}
 | 
| -
 | 
| -// static
 | 
| -void WorkerDevToolsManager::NotifyConnectionFailedOnIOThread(
 | 
| -    int worker_process_id,
 | 
| -    int worker_route_id) {
 | 
| -  BrowserThread::PostTask(
 | 
| -      BrowserThread::UI, FROM_HERE,
 | 
| -      base::Bind(
 | 
| -          &WorkerDevToolsManager::NotifyConnectionFailedOnUIThread,
 | 
| -          worker_process_id,
 | 
| -          worker_route_id));
 | 
| -}
 | 
| -
 | 
| -// static
 | 
| -void WorkerDevToolsManager::NotifyConnectionFailedOnUIThread(
 | 
| -    int worker_process_id,
 | 
| -    int worker_route_id) {
 | 
| -  AgentHosts::iterator it = g_agent_map.Get().find(WorkerId(worker_process_id,
 | 
| -                                                            worker_route_id));
 | 
| -  if (it != g_agent_map.Get().end())
 | 
| -    it->second->ConnectionFailed();
 | 
| +  }
 | 
| +  for (WorkerInfoMap::iterator it = workers_.begin(); it != workers_.end();
 | 
| +       ++it) {
 | 
| +    if (it->second->agent_host() == agent_host) {
 | 
| +      DCHECK_EQ(WORKER_PAUSED, it->second->state());
 | 
| +      SendMessageToWorker(
 | 
| +          it->first,
 | 
| +          new DevToolsAgentMsg_ResumeWorkerContext(it->first.second));
 | 
| +      it->second->set_agent_host(NULL);
 | 
| +      it->second->set_state(WORKER_UNINSPECTED);
 | 
| +      return;
 | 
| +    }
 | 
| +  }
 | 
|  }
 | 
|  
 | 
| -// static
 | 
| -void WorkerDevToolsManager::SendResumeToWorker(const WorkerId& id) {
 | 
| -  if (WorkerProcessHost* process = FindWorkerProcess(id.first))
 | 
| -    process->Send(new DevToolsAgentMsg_ResumeWorkerContext(id.second));
 | 
| +SharedWorkerDevToolsManager::WorkerInfoMap::iterator
 | 
| +SharedWorkerDevToolsManager::FindExistingWorkerInfo(
 | 
| +    const SharedWorkerInstance& instance) {
 | 
| +  WorkerInfoMap::iterator it = workers_.begin();
 | 
| +  for (; it != workers_.end(); ++it) {
 | 
| +    if (it->second->instance().Matches(instance))
 | 
| +      break;
 | 
| +  }
 | 
| +  return it;
 | 
|  }
 | 
|  
 | 
| -WorkerDevToolsManager::WorkerDevToolsAgentHost::~WorkerDevToolsAgentHost() {
 | 
| -  DetachedClientHosts::RemovePendingWorkerData(worker_id_);
 | 
| -  g_agent_map.Get().erase(worker_id_);
 | 
| -  g_orphan_map.Get().erase(worker_id_);
 | 
| -}
 | 
| +void SharedWorkerDevToolsManager::ResetForTesting() { workers_.clear(); }
 | 
|  
 | 
|  }  // namespace content
 | 
| 
 |