diff options
-rw-r--r-- | chrome/browser/debugger/devtools_sanity_unittest.cc | 53 | ||||
-rw-r--r-- | content/browser/debugger/worker_devtools_manager.cc | 201 | ||||
-rw-r--r-- | content/browser/debugger/worker_devtools_manager.h | 44 | ||||
-rw-r--r-- | content/browser/debugger/worker_devtools_message_filter.cc | 6 | ||||
-rw-r--r-- | content/browser/debugger/worker_devtools_message_filter.h | 1 | ||||
-rw-r--r-- | content/browser/worker_host/worker_process_host.cc | 4 | ||||
-rw-r--r-- | content/browser/worker_host/worker_process_host.h | 6 | ||||
-rw-r--r-- | content/browser/worker_host/worker_service.cc | 28 | ||||
-rw-r--r-- | content/browser/worker_host/worker_service.h | 14 | ||||
-rw-r--r-- | content/browser/worker_host/worker_service_observer.h | 27 | ||||
-rw-r--r-- | content/common/devtools_messages.h | 7 | ||||
-rw-r--r-- | content/content_browser.gypi | 1 | ||||
-rw-r--r-- | content/worker/shared_worker_devtools_agent.cc | 12 | ||||
-rw-r--r-- | content/worker/shared_worker_devtools_agent.h | 2 |
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_; |