summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/debugger/devtools_sanity_unittest.cc53
-rw-r--r--content/browser/debugger/worker_devtools_manager.cc201
-rw-r--r--content/browser/debugger/worker_devtools_manager.h44
-rw-r--r--content/browser/debugger/worker_devtools_message_filter.cc6
-rw-r--r--content/browser/debugger/worker_devtools_message_filter.h1
-rw-r--r--content/browser/worker_host/worker_process_host.cc4
-rw-r--r--content/browser/worker_host/worker_process_host.h6
-rw-r--r--content/browser/worker_host/worker_service.cc28
-rw-r--r--content/browser/worker_host/worker_service.h14
-rw-r--r--content/browser/worker_host/worker_service_observer.h27
-rw-r--r--content/common/devtools_messages.h7
-rw-r--r--content/content_browser.gypi1
-rw-r--r--content/worker/shared_worker_devtools_agent.cc12
-rw-r--r--content/worker/shared_worker_devtools_agent.h2
14 files changed, 349 insertions, 57 deletions
diff --git a/chrome/browser/debugger/devtools_sanity_unittest.cc b/chrome/browser/debugger/devtools_sanity_unittest.cc
index a03b59d..d0f28f1 100644
--- a/chrome/browser/debugger/devtools_sanity_unittest.cc
+++ b/chrome/browser/debugger/devtools_sanity_unittest.cc
@@ -24,6 +24,8 @@
#include "content/browser/renderer_host/render_view_host.h"
#include "content/browser/tab_contents/tab_contents.h"
#include "content/browser/worker_host/worker_process_host.h"
+#include "content/browser/worker_host/worker_service.h"
+#include "content/browser/worker_host/worker_service_observer.h"
#include "content/common/notification_registrar.h"
#include "content/common/notification_service.h"
#include "net/test/test_server.h"
@@ -267,10 +269,37 @@ class WorkerDevToolsSanityTest : public InProcessBrowserTest {
protected:
struct WorkerData : public base::RefCountedThreadSafe<WorkerData> {
- WorkerData() : worker_process_id(0), worker_route_id(0), valid(false) {}
+ WorkerData() : worker_process_id(0), worker_route_id(0) {}
int worker_process_id;
int worker_route_id;
- bool valid;
+ };
+
+ class WorkerCreationObserver : public WorkerServiceObserver {
+ public:
+ explicit WorkerCreationObserver(WorkerData* worker_data)
+ : worker_data_(worker_data) {
+ }
+
+ private:
+ virtual ~WorkerCreationObserver() {}
+
+ virtual void WorkerCreated (
+ WorkerProcessHost* process,
+ const WorkerProcessHost::WorkerInstance& instance) OVERRIDE {
+ worker_data_->worker_process_id = process->id();
+ worker_data_->worker_route_id = instance.worker_route_id();
+ WorkerService::GetInstance()->RemoveObserver(this);
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ new MessageLoop::QuitTask);
+ delete this;
+ }
+ virtual void WorkerDestroyed(
+ WorkerProcessHost*,
+ const WorkerProcessHost::WorkerInstance&) OVERRIDE {}
+ virtual void WorkerContextStarted(
+ WorkerProcessHost*,
+ int worker_route_id) OVERRIDE {}
+ scoped_refptr<WorkerData> worker_data_;
};
void RunTest(const char* test_name, const char* test_page) {
@@ -284,8 +313,7 @@ class WorkerDevToolsSanityTest : public InProcessBrowserTest {
}
static void WaitForFirstSharedWorkerOnIOThread(
- scoped_refptr<WorkerData> worker_data,
- int attempt) {
+ scoped_refptr<WorkerData> worker_data) {
BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS);
for (; !iter.Done(); ++iter) {
WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter);
@@ -296,30 +324,21 @@ class WorkerDevToolsSanityTest : public InProcessBrowserTest {
continue;
worker_data->worker_process_id = worker->id();
worker_data->worker_route_id = i->worker_route_id();
- worker_data->valid = true;
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
new MessageLoop::QuitTask);
return;
}
}
- if (attempt > TestTimeouts::action_timeout_ms() /
- TestTimeouts::tiny_timeout_ms())
- FAIL() << "Shared worker not found.";
- MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- NewRunnableFunction(
- &WaitForFirstSharedWorkerOnIOThread,
- worker_data,
- attempt + 1),
- TestTimeouts::tiny_timeout_ms());
+
+ WorkerService::GetInstance()->AddObserver(
+ new WorkerCreationObserver(worker_data.get()));
}
void OpenDevToolsWindowForFirstSharedWorker() {
scoped_refptr<WorkerData> worker_data(new WorkerData());
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, NewRunnableFunction(
- &WaitForFirstSharedWorkerOnIOThread, worker_data, 1));
+ &WaitForFirstSharedWorkerOnIOThread, worker_data));
ui_test_utils::RunMessageLoop();
- ASSERT_TRUE(worker_data->valid);
Profile* profile = browser()->profile();
window_ = DevToolsWindow::CreateDevToolsWindowForWorker(profile);
diff --git a/content/browser/debugger/worker_devtools_manager.cc b/content/browser/debugger/worker_devtools_manager.cc
index 5bd8071..b270030 100644
--- a/content/browser/debugger/worker_devtools_manager.cc
+++ b/content/browser/debugger/worker_devtools_manager.cc
@@ -13,16 +13,13 @@
#include "content/browser/debugger/devtools_manager.h"
#include "content/browser/debugger/worker_devtools_message_filter.h"
#include "content/browser/worker_host/worker_process_host.h"
+#include "content/browser/worker_host/worker_service.h"
#include "content/common/content_notification_types.h"
#include "content/common/devtools_messages.h"
#include "content/common/notification_observer.h"
#include "content/common/notification_registrar.h"
#include "content/common/notification_service.h"
-namespace {
-typedef std::pair<int, int> WorkerId;
-}
-
class WorkerDevToolsManager::AgentHosts : private NotificationObserver {
public:
static void Add(WorkerId id, WorkerDevToolsAgentHost* host) {
@@ -75,6 +72,17 @@ WorkerDevToolsManager::AgentHosts*
WorkerDevToolsManager::AgentHosts::instance_ = NULL;
+struct WorkerDevToolsManager::TerminatedInspectedWorker {
+ TerminatedInspectedWorker(WorkerId id, const GURL& url, const string16& name)
+ : old_worker_id(id),
+ worker_url(url),
+ worker_name(name) {}
+ WorkerId old_worker_id;
+ GURL worker_url;
+ string16 worker_name;
+};
+
+
class WorkerDevToolsManager::WorkerDevToolsAgentHost
: public DevToolsAgentHost {
public:
@@ -133,6 +141,77 @@ class WorkerDevToolsManager::WorkerDevToolsAgentHost
DISALLOW_COPY_AND_ASSIGN(WorkerDevToolsAgentHost);
};
+
+class WorkerDevToolsManager::DetachedClientHosts {
+ public:
+ static void WorkerReloaded(WorkerId old_id, WorkerId new_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ if (instance_ && instance_->ReattachClient(old_id, new_id))
+ return;
+ RemovePendingWorkerData(old_id);
+ }
+
+ static void WorkerDestroyed(WorkerId id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ WorkerDevToolsAgentHost* agent = AgentHosts::GetAgentHost(id);
+ if (!agent) {
+ RemovePendingWorkerData(id);
+ return;
+ }
+ int cookie = DevToolsManager::GetInstance()->DetachClientHost(agent);
+ if (cookie == -1) {
+ RemovePendingWorkerData(id);
+ return;
+ }
+ if (!instance_)
+ new DetachedClientHosts();
+ instance_->worker_id_to_cookie_[id] = cookie;
+ }
+
+ private:
+ DetachedClientHosts() {
+ instance_ = this;
+ }
+ ~DetachedClientHosts() {
+ instance_ = NULL;
+ }
+
+ bool ReattachClient(WorkerId old_id, WorkerId new_id) {
+ WorkerIdToCookieMap::iterator it = worker_id_to_cookie_.find(old_id);
+ if (it == worker_id_to_cookie_.end())
+ return false;
+ DevToolsAgentHost* agent =
+ WorkerDevToolsManager::GetDevToolsAgentHostForWorker(
+ new_id.first,
+ new_id.second);
+ DevToolsManager::GetInstance()->AttachClientHost(
+ it->second,
+ agent);
+ worker_id_to_cookie_.erase(it);
+ if (worker_id_to_cookie_.empty())
+ delete this;
+ return true;
+ }
+
+ static void RemovePendingWorkerData(WorkerId id) {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ NewRunnableFunction(RemoveInspectedWorkerDataOnIOThread, id));
+ }
+
+ static void RemoveInspectedWorkerDataOnIOThread(WorkerId id) {
+ WorkerDevToolsManager::GetInstance()->RemoveInspectedWorkerData(id);
+ }
+
+ static DetachedClientHosts* instance_;
+ typedef std::map<WorkerId, int> WorkerIdToCookieMap;
+ WorkerIdToCookieMap worker_id_to_cookie_;
+};
+
+WorkerDevToolsManager::DetachedClientHosts*
+ WorkerDevToolsManager::DetachedClientHosts::instance_ = NULL;
+
+
void WorkerDevToolsManager::AgentHosts::Observe(int type,
const NotificationSource&,
const NotificationDetails&) {
@@ -163,26 +242,12 @@ class WorkerDevToolsManager::InspectedWorkersList {
return it->host;
}
- WorkerProcessHost* RemoveInstance(int host_id, int route_id) {
+ bool RemoveInstance(int host_id, int route_id) {
Entries::iterator it = FindEntry(host_id, route_id);
if (it == map_.end())
- return NULL;
- WorkerProcessHost* host = it->host;
+ return false;
map_.erase(it);
- return host;
- }
-
- void WorkerDevToolsMessageFilterClosing(int worker_process_id) {
- Entries::iterator it = map_.begin();
- while (it != map_.end()) {
- if (it->host->id() == worker_process_id) {
- NotifyWorkerDestroyedOnIOThread(
- it->host->id(),
- it->route_id);
- it = map_.erase(it);
- } else
- ++it;
- }
+ return true;
}
private:
@@ -228,11 +293,87 @@ DevToolsAgentHost* WorkerDevToolsManager::GetDevToolsAgentHostForWorker(
WorkerDevToolsManager::WorkerDevToolsManager()
: inspected_workers_(new InspectedWorkersList()) {
+ WorkerService::GetInstance()->AddObserver(this);
}
WorkerDevToolsManager::~WorkerDevToolsManager() {
}
+void 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.resource_context())) {
+ worker->Send(new DevToolsAgentMsg_PauseWorkerContextOnStart(
+ instance.worker_route_id()));
+ WorkerId new_worker_id(worker->id(), instance.worker_route_id());
+ paused_workers_[new_worker_id] = it->old_worker_id;
+ terminated_workers_.erase(it);
+ return;
+ }
+ }
+}
+
+void WorkerDevToolsManager::WorkerDestroyed(
+ WorkerProcessHost* worker,
+ const WorkerProcessHost::WorkerInstance& instance) {
+ if (!instance.shared())
+ return;
+ if (!inspected_workers_->RemoveInstance(worker->id(),
+ instance.worker_route_id())) {
+ return;
+ }
+
+ WorkerId worker_id(worker->id(), instance.worker_route_id());
+ terminated_workers_.push_back(TerminatedInspectedWorker(
+ worker_id,
+ instance.url(),
+ instance.name()));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ NewRunnableFunction(
+ DetachedClientHosts::WorkerDestroyed,
+ worker_id));
+}
+
+void WorkerDevToolsManager::WorkerContextStarted(WorkerProcessHost* process,
+ int worker_route_id) {
+ WorkerId new_worker_id(process->id(), worker_route_id);
+ PausedWorkers::iterator it = paused_workers_.find(new_worker_id);
+ if (it == paused_workers_.end())
+ return;
+
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ NewRunnableFunction(
+ 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;
+ }
+ }
+}
+
static WorkerProcessHost* FindWorkerProcessHostForWorker(
int worker_process_id,
int worker_route_id) {
@@ -293,12 +434,6 @@ void WorkerDevToolsManager::SaveAgentRuntimeState(int worker_process_id,
state));
}
-void WorkerDevToolsManager::WorkerProcessDestroying(
- int worker_process_id) {
- inspected_workers_->WorkerDevToolsMessageFilterClosing(
- worker_process_id);
-}
-
void WorkerDevToolsManager::ForwardToWorkerDevToolsAgent(
int worker_process_id,
int worker_route_id,
@@ -360,3 +495,15 @@ void WorkerDevToolsManager::NotifyWorkerDestroyedOnUIThread(
if (host)
host->WorkerDestroyed();
}
+
+// static
+void WorkerDevToolsManager::SendResumeToWorker(const WorkerId& id) {
+ BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS);
+ for (; !iter.Done(); ++iter) {
+ if (iter->id() == id.first) {
+ iter->Send(new DevToolsAgentMsg_ResumeWorkerContext(id.second));
+ return;
+ }
+ }
+}
+
diff --git a/content/browser/debugger/worker_devtools_manager.h b/content/browser/debugger/worker_devtools_manager.h
index d25f092..2255aa2 100644
--- a/content/browser/debugger/worker_devtools_manager.h
+++ b/content/browser/debugger/worker_devtools_manager.h
@@ -6,12 +6,14 @@
#define CONTENT_BROWSER_DEBUGGER_WORKER_DEVTOOLS_MANAGER_H_
#pragma once
+#include <list>
#include <string>
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/singleton.h"
#include "content/common/content_export.h"
+#include "content/browser/worker_host/worker_service_observer.h"
namespace IPC {
class Message;
@@ -20,7 +22,7 @@ class DevToolsAgentHost;
class WorkerDevToolsMessageFilter;
// All methods are supposed to be called on the IO thread.
-class WorkerDevToolsManager {
+class WorkerDevToolsManager : private WorkerServiceObserver {
public:
// Returns the WorkerDevToolsManager singleton.
static WorkerDevToolsManager* GetInstance();
@@ -30,7 +32,6 @@ class WorkerDevToolsManager {
int worker_process_id,
int worker_route_id);
- void WorkerProcessDestroying(int worker_process_host_id);
void ForwardToDevToolsClient(int worker_process_id,
int worker_route_id,
const IPC::Message& message);
@@ -39,11 +40,25 @@ class WorkerDevToolsManager {
const std::string& state);
private:
friend struct DefaultSingletonTraits<WorkerDevToolsManager>;
+ typedef std::pair<int, int> WorkerId;
class AgentHosts;
+ class DetachedClientHosts;
class WorkerDevToolsAgentHost;
WorkerDevToolsManager();
- ~WorkerDevToolsManager();
+ virtual ~WorkerDevToolsManager();
+
+ // WorkerServiceOberver implementation.
+ virtual void WorkerCreated(
+ WorkerProcessHost* process,
+ const WorkerProcessHost::WorkerInstance& instance) OVERRIDE;
+ virtual void WorkerDestroyed(
+ WorkerProcessHost* process,
+ const WorkerProcessHost::WorkerInstance& instance) OVERRIDE;
+ virtual void WorkerContextStarted(WorkerProcessHost* process,
+ int worker_route_id) OVERRIDE;
+
+ void RemoveInspectedWorkerData(const WorkerId& id);
void RegisterDevToolsAgentHostForWorker(int worker_process_id,
int worker_route_id);
@@ -62,10 +77,33 @@ class WorkerDevToolsManager {
int worker_route_id);
static void NotifyWorkerDestroyedOnUIThread(int worker_process_id,
int worker_route_id);
+ static void SendResumeToWorker(const WorkerId& id);
class InspectedWorkersList;
scoped_ptr<InspectedWorkersList> inspected_workers_;
+ struct TerminatedInspectedWorker;
+ typedef std::list<TerminatedInspectedWorker> TerminatedInspectedWorkers;
+ // List of terminated workers for which there may be a devtools client on
+ // the UI thread. Worker entry is added into this list when inspected worker
+ // is terminated and will be removed in one of two cases:
+ // - shared worker with the same URL and name is started(in wich case we will
+ // try to reattach existing DevTools client to the new worker).
+ // - DevTools client which was inspecting terminated worker is closed on the
+ // UI thread and and WorkerDevToolsManager is notified about that on the IO
+ // thread.
+ TerminatedInspectedWorkers terminated_workers_;
+
+ typedef std::map<WorkerId, WorkerId> PausedWorkers;
+ // Map from old to new worker id for the inspected workers that have been
+ // terminated and started again in paused state. Worker data will be removed
+ // from this list in one of two cases:
+ // - DevTools client is closed on the UI thread, WorkerDevToolsManager was
+ // notified about that on the IO thread and sent "resume" message to the
+ // worker.
+ // - Existing DevTools client was reattached to the new worker.
+ PausedWorkers paused_workers_;
+
DISALLOW_COPY_AND_ASSIGN(WorkerDevToolsManager);
};
diff --git a/content/browser/debugger/worker_devtools_message_filter.cc b/content/browser/debugger/worker_devtools_message_filter.cc
index cc18bcc..3d1795f 100644
--- a/content/browser/debugger/worker_devtools_message_filter.cc
+++ b/content/browser/debugger/worker_devtools_message_filter.cc
@@ -18,12 +18,6 @@ WorkerDevToolsMessageFilter::WorkerDevToolsMessageFilter(
WorkerDevToolsMessageFilter::~WorkerDevToolsMessageFilter() {
}
-void WorkerDevToolsMessageFilter::OnChannelClosing() {
- BrowserMessageFilter::OnChannelClosing();
- WorkerDevToolsManager::GetInstance()->WorkerProcessDestroying(
- worker_process_host_id_);
-}
-
bool WorkerDevToolsMessageFilter::OnMessageReceived(
const IPC::Message& message,
bool* message_was_ok) {
diff --git a/content/browser/debugger/worker_devtools_message_filter.h b/content/browser/debugger/worker_devtools_message_filter.h
index 8fed10d..453d9b3 100644
--- a/content/browser/debugger/worker_devtools_message_filter.h
+++ b/content/browser/debugger/worker_devtools_message_filter.h
@@ -17,7 +17,6 @@ class WorkerDevToolsMessageFilter : public BrowserMessageFilter {
virtual ~WorkerDevToolsMessageFilter();
// BrowserMessageFilter implementation.
- virtual void OnChannelClosing();
virtual bool OnMessageReceived(const IPC::Message& message,
bool* message_was_ok);
// Message handlers.
diff --git a/content/browser/worker_host/worker_process_host.cc b/content/browser/worker_host/worker_process_host.cc
index e8dbb67..4cccb2d 100644
--- a/content/browser/worker_host/worker_process_host.cc
+++ b/content/browser/worker_host/worker_process_host.cc
@@ -110,6 +110,7 @@ WorkerProcessHost::~WorkerProcessHost() {
new WorkerCrashTask(parent_iter->render_process_id(),
parent_iter->render_view_id()));
}
+ WorkerService::GetInstance()->NotifyWorkerDestroyed(this, *i);
}
ChildProcessSecurityPolicy::GetInstance()->Remove(id());
@@ -344,6 +345,7 @@ bool WorkerProcessHost::OnMessageReceived(const IPC::Message& message) {
}
if (message.type() == WorkerHostMsg_WorkerContextDestroyed::ID) {
+ WorkerService::GetInstance()->NotifyWorkerDestroyed(this, *i);
instances_.erase(i);
UpdateTitle();
}
@@ -438,6 +440,8 @@ void WorkerProcessHost::RelayMessage(
IPC::Message* new_message = new IPC::Message(message);
new_message->set_routing_id(route_id);
filter->Send(new_message);
+ if (message.type() == WorkerMsg_StartWorkerContext::ID)
+ WorkerService::GetInstance()->NotifyWorkerContextStarted(this, route_id);
return;
}
}
diff --git a/content/browser/worker_host/worker_process_host.h b/content/browser/worker_host/worker_process_host.h
index 733e55a..008a595 100644
--- a/content/browser/worker_host/worker_process_host.h
+++ b/content/browser/worker_host/worker_process_host.h
@@ -175,9 +175,9 @@ class WorkerProcessHost : public BrowserChildProcessHost {
// Relays a message to the given endpoint. Takes care of parsing the message
// if it contains a message port and sending it a valid route id.
- static void RelayMessage(const IPC::Message& message,
- WorkerMessageFilter* filter,
- int route_id);
+ void RelayMessage(const IPC::Message& message,
+ WorkerMessageFilter* filter,
+ int route_id);
virtual bool CanShutdown();
diff --git a/content/browser/worker_host/worker_service.cc b/content/browser/worker_host/worker_service.cc
index f5ac739..0b4e3f2 100644
--- a/content/browser/worker_host/worker_service.cc
+++ b/content/browser/worker_host/worker_service.cc
@@ -13,6 +13,7 @@
#include "content/browser/resource_context.h"
#include "content/browser/worker_host/worker_message_filter.h"
#include "content/browser/worker_host/worker_process_host.h"
+#include "content/browser/worker_host/worker_service_observer.h"
#include "content/common/content_switches.h"
#include "content/common/view_messages.h"
#include "content/common/worker_messages.h"
@@ -31,6 +32,8 @@ WorkerService::WorkerService() : next_worker_route_id_(0) {
}
WorkerService::~WorkerService() {
+ // The observers in observers_ can't be used here because they might be
+ // gone already.
}
void WorkerService::OnWorkerMessageFilterClosing(WorkerMessageFilter* filter) {
@@ -323,6 +326,8 @@ bool WorkerService::CreateWorkerFromInstance(
// DCHECK(worker->request_context() == instance.request_context());
worker->CreateWorker(instance);
+ FOR_EACH_OBSERVER(WorkerServiceObserver, observers_,
+ WorkerCreated(worker, instance));
return true;
}
@@ -489,6 +494,29 @@ const WorkerProcessHost::WorkerInstance* WorkerService::FindWorkerInstance(
return NULL;
}
+void WorkerService::AddObserver(WorkerServiceObserver* observer) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ observers_.AddObserver(observer);
+}
+
+void WorkerService::RemoveObserver(WorkerServiceObserver* observer) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ observers_.RemoveObserver(observer);
+}
+
+void WorkerService::NotifyWorkerDestroyed(
+ WorkerProcessHost* process,
+ const WorkerProcessHost::WorkerInstance& instance) {
+ FOR_EACH_OBSERVER(WorkerServiceObserver, observers_,
+ WorkerDestroyed(process, instance));
+}
+
+void WorkerService::NotifyWorkerContextStarted(WorkerProcessHost* process,
+ int worker_route_id) {
+ FOR_EACH_OBSERVER(WorkerServiceObserver, observers_,
+ WorkerContextStarted(process, worker_route_id));
+}
+
WorkerProcessHost::WorkerInstance*
WorkerService::FindSharedWorkerInstance(
const GURL& url,
diff --git a/content/browser/worker_host/worker_service.h b/content/browser/worker_host/worker_service.h
index 4c3367c..c9f8464 100644
--- a/content/browser/worker_host/worker_service.h
+++ b/content/browser/worker_host/worker_service.h
@@ -8,6 +8,7 @@
#include "base/basictypes.h"
#include "base/memory/singleton.h"
+#include "base/observer_list.h"
#include "base/threading/non_thread_safe.h"
#include "content/browser/worker_host/worker_process_host.h"
#include "content/common/content_export.h"
@@ -20,6 +21,7 @@ class ResourceContext;
namespace net {
class URLRequestContextGetter;
} // namespace net
+class WorkerServiceObserver;
struct ViewHostMsg_CreateWorker_Params;
// A singleton for managing HTML5 web workers.
@@ -60,6 +62,16 @@ class WorkerService {
const WorkerProcessHost::WorkerInstance* FindWorkerInstance(
int worker_process_id);
+ void AddObserver(WorkerServiceObserver* observer);
+ void RemoveObserver(WorkerServiceObserver* observer);
+
+ void NotifyWorkerDestroyed(
+ WorkerProcessHost* process,
+ const WorkerProcessHost::WorkerInstance& instance);
+ void NotifyWorkerContextStarted(
+ WorkerProcessHost* process,
+ int worker_route_id);
+
// Used when multiple workers can run in the same process.
static const int kMaxWorkerProcessesWhenSharing;
@@ -131,6 +143,8 @@ class WorkerService {
// URL mismatches when two pages launch shared workers simultaneously.
WorkerProcessHost::Instances pending_shared_workers_;
+ ObserverList<WorkerServiceObserver> observers_;
+
DISALLOW_COPY_AND_ASSIGN(WorkerService);
};
diff --git a/content/browser/worker_host/worker_service_observer.h b/content/browser/worker_host/worker_service_observer.h
new file mode 100644
index 0000000..8ee4514
--- /dev/null
+++ b/content/browser/worker_host/worker_service_observer.h
@@ -0,0 +1,27 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_WORKER_HOST_WORKER_SERVICE_OBSERVER_H_
+#define CONTENT_BROWSER_WORKER_HOST_WORKER_SERVICE_OBSERVER_H_
+#pragma once
+
+#include "content/browser/worker_host/worker_process_host.h"
+
+class WorkerServiceObserver {
+ public:
+ virtual void WorkerCreated(
+ WorkerProcessHost* process,
+ const WorkerProcessHost::WorkerInstance& instance) = 0;
+ virtual void WorkerDestroyed(
+ WorkerProcessHost* process,
+ const WorkerProcessHost::WorkerInstance& instance) = 0;
+ virtual void WorkerContextStarted(
+ WorkerProcessHost* process,
+ int worker_route_id) = 0;
+
+ protected:
+ virtual ~WorkerServiceObserver() {}
+};
+
+#endif // CONTENT_BROWSER_WORKER_HOST_WORKER_SERVICE_OBSERVER_H_
diff --git a/content/common/devtools_messages.h b/content/common/devtools_messages.h
index 57a234c..5c2af90 100644
--- a/content/common/devtools_messages.h
+++ b/content/common/devtools_messages.h
@@ -94,6 +94,13 @@ IPC_MESSAGE_ROUTED2(DevToolsAgentMsg_InspectElement,
int /* x */,
int /* y */)
+// Notifies worker devtools agent that it should pause worker context
+// when it starts and wait until either DevTools client is attached or
+// explicit resume notification is received.
+IPC_MESSAGE_ROUTED0(DevToolsAgentMsg_PauseWorkerContextOnStart)
+
+// Worker DevTools agent should resume worker execution.
+IPC_MESSAGE_ROUTED0(DevToolsAgentMsg_ResumeWorkerContext)
//-----------------------------------------------------------------------------
// These are messages sent from the browser to the renderer.
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index e229f7f..7bf2a59 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -535,6 +535,7 @@
'browser/worker_host/worker_process_host.h',
'browser/worker_host/worker_service.cc',
'browser/worker_host/worker_service.h',
+ 'browser/worker_host/worker_service_observer.h',
'browser/zygote_host_linux.cc',
'browser/zygote_host_linux.h',
'browser/zygote_main_linux.cc',
diff --git a/content/worker/shared_worker_devtools_agent.cc b/content/worker/shared_worker_devtools_agent.cc
index 3ba7444..702105d 100644
--- a/content/worker/shared_worker_devtools_agent.cc
+++ b/content/worker/shared_worker_devtools_agent.cc
@@ -32,6 +32,10 @@ bool SharedWorkerDevToolsAgent::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(DevToolsAgentMsg_Detach, OnDetach)
IPC_MESSAGE_HANDLER(DevToolsAgentMsg_DispatchOnInspectorBackend,
OnDispatchOnInspectorBackend)
+ IPC_MESSAGE_HANDLER(DevToolsAgentMsg_PauseWorkerContextOnStart,
+ OnPauseWorkerContextOnStart)
+ IPC_MESSAGE_HANDLER(DevToolsAgentMsg_ResumeWorkerContext,
+ OnResumeWorkerContext)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -68,6 +72,14 @@ void SharedWorkerDevToolsAgent::OnDispatchOnInspectorBackend(
webworker_->dispatchDevToolsMessage(WebString::fromUTF8(message));
}
+void SharedWorkerDevToolsAgent::OnPauseWorkerContextOnStart() {
+ webworker_->pauseWorkerContextOnStart();
+}
+
+void SharedWorkerDevToolsAgent::OnResumeWorkerContext() {
+ webworker_->resumeWorkerContext();
+}
+
bool SharedWorkerDevToolsAgent::Send(IPC::Message* message) {
return WorkerThread::current()->Send(message);
}
diff --git a/content/worker/shared_worker_devtools_agent.h b/content/worker/shared_worker_devtools_agent.h
index 22f5dac6..a1f92db 100644
--- a/content/worker/shared_worker_devtools_agent.h
+++ b/content/worker/shared_worker_devtools_agent.h
@@ -34,6 +34,8 @@ class SharedWorkerDevToolsAgent {
void OnReattach(const std::string&);
void OnDetach();
void OnDispatchOnInspectorBackend(const std::string& message);
+ void OnPauseWorkerContextOnStart();
+ void OnResumeWorkerContext();
bool Send(IPC::Message* message);
const int route_id_;