diff options
author | kinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-06 10:59:47 +0000 |
---|---|---|
committer | kinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-06 10:59:47 +0000 |
commit | ddbb5334852f62efa0f11245e5cb81684b1e57ac (patch) | |
tree | c06006b6df3acf0f1996e9ada4c3c00e0175ca48 | |
parent | 573878b5609fb6badae40e4a1bdef944b9d340dc (diff) | |
download | chromium_src-ddbb5334852f62efa0f11245e5cb81684b1e57ac.zip chromium_src-ddbb5334852f62efa0f11245e5cb81684b1e57ac.tar.gz chromium_src-ddbb5334852f62efa0f11245e5cb81684b1e57ac.tar.bz2 |
Add IPC stubs between browser and ServiceWorker's worker context in the child process
- Add ServiceWorkerHostMsg_WorkerStarted and ServiceWorkerHostMsg_WorkerStopped
that are sent from embedded worker to the browser process
- Add ServiceWorkerContextMsg_FetchEvent for messages from embedded worker
to the browser process
FetchEvent/FetchRequest code is a bit rough as it's meant to be
a placeholder. I can remove the part from this CL if it doesn't
look reay yet.
The new code uses new IPC class (ServiceWorkerContextMsg) for dispatching
messages specifically sent to the embedded workers's worker context,
which may feel a bit noisy. (Alternative suggestions welcome)
BUG=313530
R=alecflett@chromium.org, jochen@chromium.org, tsepez@chromium.org
Review URL: https://codereview.chromium.org/118103002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@243081 0039d316-1c4b-4281-b951-d872f2087c98
20 files changed, 337 insertions, 53 deletions
diff --git a/content/browser/service_worker/embedded_worker_instance.cc b/content/browser/service_worker/embedded_worker_instance.cc index 0799884..329b007 100644 --- a/content/browser/service_worker/embedded_worker_instance.cc +++ b/content/browser/service_worker/embedded_worker_instance.cc @@ -5,12 +5,13 @@ #include "content/browser/service_worker/embedded_worker_instance.h" #include "content/browser/service_worker/embedded_worker_registry.h" +#include "content/common/service_worker_messages.h" #include "url/gurl.h" namespace content { EmbeddedWorkerInstance::~EmbeddedWorkerInstance() { - registry_->RemoveWorker(embedded_worker_id_); + registry_->RemoveWorker(process_id_, embedded_worker_id_); } bool EmbeddedWorkerInstance::Start( @@ -40,6 +41,16 @@ bool EmbeddedWorkerInstance::Stop() { return success; } +bool EmbeddedWorkerInstance::SendFetchRequest( + const ServiceWorkerFetchRequest& request) { + DCHECK(status_ == RUNNING); + // TODO: Refine this code, the code around FetchEvent is currently very + // rough, mainly just for a placeholder for now. + return registry_->Send(process_id_, + new EmbeddedWorkerContextMsg_FetchEvent( + thread_id_, embedded_worker_id_, request)); +} + void EmbeddedWorkerInstance::AddProcessReference(int process_id) { ProcessRefMap::iterator found = process_refs_.find(process_id); if (found == process_refs_.end()) @@ -68,6 +79,9 @@ EmbeddedWorkerInstance::EmbeddedWorkerInstance( } void EmbeddedWorkerInstance::OnStarted(int thread_id) { + // Stop is requested before OnStarted is sent back from the worker. + if (status_ == STOPPING) + return; DCHECK(status_ == STARTING); status_ = RUNNING; thread_id_ = thread_id; diff --git a/content/browser/service_worker/embedded_worker_instance.h b/content/browser/service_worker/embedded_worker_instance.h index fb0fe19..5a992a2 100644 --- a/content/browser/service_worker/embedded_worker_instance.h +++ b/content/browser/service_worker/embedded_worker_instance.h @@ -19,6 +19,7 @@ class GURL; namespace content { class EmbeddedWorkerRegistry; +struct ServiceWorkerFetchRequest; // This gives an interface to control one EmbeddedWorker instance, which // may be 'in-waiting' or running in one of the child processes added by @@ -47,6 +48,11 @@ class CONTENT_EXPORT EmbeddedWorkerInstance { // IPC couldn't be sent to the worker. bool Stop(); + // Sends |request| to the embedded worker running in the child process. + // This returns false if sending IPC fails. + // It is invalid to call this while the worker is not in RUNNING status. + bool SendFetchRequest(const ServiceWorkerFetchRequest& request); + // Add or remove |process_id| to the internal process set where this // worker can be started. void AddProcessReference(int process_id); diff --git a/content/browser/service_worker/embedded_worker_instance_unittest.cc b/content/browser/service_worker/embedded_worker_instance_unittest.cc index 45b2f29..090d086 100644 --- a/content/browser/service_worker/embedded_worker_instance_unittest.cc +++ b/content/browser/service_worker/embedded_worker_instance_unittest.cc @@ -105,8 +105,8 @@ TEST_F(EmbeddedWorkerInstanceTest, StartAndStop) { // Verify that we've sent two messages to start and terminate the worker. const MessageList& messages = fake_sender.sent_messages(); ASSERT_EQ(2U, messages.size()); - ASSERT_EQ(ServiceWorkerMsg_StartWorker::ID, messages[0]->type()); - ASSERT_EQ(ServiceWorkerMsg_TerminateWorker::ID, messages[1]->type()); + ASSERT_EQ(EmbeddedWorkerMsg_StartWorker::ID, messages[0]->type()); + ASSERT_EQ(EmbeddedWorkerMsg_StopWorker::ID, messages[1]->type()); } TEST_F(EmbeddedWorkerInstanceTest, ChooseProcess) { diff --git a/content/browser/service_worker/embedded_worker_registry.cc b/content/browser/service_worker/embedded_worker_registry.cc index f8f0fbe..2147c4f 100644 --- a/content/browser/service_worker/embedded_worker_registry.cc +++ b/content/browser/service_worker/embedded_worker_registry.cc @@ -25,18 +25,13 @@ scoped_ptr<EmbeddedWorkerInstance> EmbeddedWorkerRegistry::CreateWorker() { return worker.Pass(); } -void EmbeddedWorkerRegistry::RemoveWorker(int embedded_worker_id) { - DCHECK(ContainsKey(worker_map_, embedded_worker_id)); - worker_map_.erase(embedded_worker_id); -} - bool EmbeddedWorkerRegistry::StartWorker( int process_id, int embedded_worker_id, int64 service_worker_version_id, const GURL& script_url) { return Send(process_id, - new ServiceWorkerMsg_StartWorker(embedded_worker_id, + new EmbeddedWorkerMsg_StartWorker(embedded_worker_id, service_worker_version_id, script_url)); } @@ -44,16 +39,49 @@ bool EmbeddedWorkerRegistry::StartWorker( bool EmbeddedWorkerRegistry::StopWorker(int process_id, int embedded_worker_id) { return Send(process_id, - new ServiceWorkerMsg_TerminateWorker(embedded_worker_id)); + new EmbeddedWorkerMsg_StopWorker(embedded_worker_id)); +} + +void EmbeddedWorkerRegistry::OnWorkerStarted( + int process_id, int thread_id, int embedded_worker_id) { + DCHECK(!ContainsKey(worker_process_map_, process_id)); + WorkerInstanceMap::iterator found = worker_map_.find(embedded_worker_id); + if (found == worker_map_.end()) { + LOG(ERROR) << "Worker " << embedded_worker_id << " not registered"; + return; + } + worker_process_map_[process_id] = embedded_worker_id; + DCHECK_EQ(found->second->process_id(), process_id); + found->second->OnStarted(thread_id); +} + +void EmbeddedWorkerRegistry::OnWorkerStopped( + int process_id, int embedded_worker_id) { + WorkerInstanceMap::iterator found = worker_map_.find(embedded_worker_id); + if (found == worker_map_.end()) { + LOG(ERROR) << "Worker " << embedded_worker_id << " not registered"; + return; + } + DCHECK_EQ(found->second->process_id(), process_id); + worker_process_map_.erase(process_id); + found->second->OnStopped(); } void EmbeddedWorkerRegistry::AddChildProcessSender( int process_id, IPC::Sender* sender) { process_sender_map_[process_id] = sender; + DCHECK(!ContainsKey(worker_process_map_, process_id)); } void EmbeddedWorkerRegistry::RemoveChildProcessSender(int process_id) { process_sender_map_.erase(process_id); + std::map<int, int>::iterator found = worker_process_map_.find(process_id); + if (found != worker_process_map_.end()) { + int embedded_worker_id = found->second; + DCHECK(ContainsKey(worker_map_, embedded_worker_id)); + worker_map_[embedded_worker_id]->OnStopped(); + worker_process_map_.erase(found); + } } EmbeddedWorkerRegistry::~EmbeddedWorkerRegistry() {} @@ -67,4 +95,11 @@ bool EmbeddedWorkerRegistry::Send(int process_id, IPC::Message* message) { return found->second->Send(message); } +void EmbeddedWorkerRegistry::RemoveWorker(int process_id, + int embedded_worker_id) { + DCHECK(ContainsKey(worker_map_, embedded_worker_id)); + worker_map_.erase(embedded_worker_id); + worker_process_map_.erase(process_id); +} + } // namespace content diff --git a/content/browser/service_worker/embedded_worker_registry.h b/content/browser/service_worker/embedded_worker_registry.h index 8860e37..ab6735f 100644 --- a/content/browser/service_worker/embedded_worker_registry.h +++ b/content/browser/service_worker/embedded_worker_registry.h @@ -39,7 +39,6 @@ class CONTENT_EXPORT EmbeddedWorkerRegistry // Creates and removes a new worker instance entry for bookkeeping. // This doesn't actually start or stop the worker. scoped_ptr<EmbeddedWorkerInstance> CreateWorker(); - void RemoveWorker(int embedded_worker_id); // Called from EmbeddedWorkerInstance, relayed to the child process. bool StartWorker(int process_id, @@ -49,24 +48,38 @@ class CONTENT_EXPORT EmbeddedWorkerRegistry bool StopWorker(int process_id, int embedded_worker_id); + // Called back from EmbeddedWorker in the child process, relayed via + // ServiceWorkerDispatcherHost. + void OnWorkerStarted(int process_id, int thread_id, int embedded_worker_id); + void OnWorkerStopped(int process_id, int embedded_worker_id); + // Keeps a map from process_id to sender information. void AddChildProcessSender(int process_id, IPC::Sender* sender); void RemoveChildProcessSender(int process_id); private: friend class base::RefCounted<EmbeddedWorkerRegistry>; + friend class EmbeddedWorkerInstance; + + typedef std::map<int, EmbeddedWorkerInstance*> WorkerInstanceMap; + typedef std::map<int, IPC::Sender*> ProcessToSenderMap; ~EmbeddedWorkerRegistry(); bool Send(int process_id, IPC::Message* message); - typedef std::map<int, EmbeddedWorkerInstance*> WorkerInstanceMap; - typedef std::map<int, IPC::Sender*> ProcessToSenderMap; + // RemoveWorker is called when EmbeddedWorkerInstance is destructed. + // |process_id| could be invalid (i.e. -1) if it's not running. + void RemoveWorker(int process_id, int embedded_worker_id); base::WeakPtr<ServiceWorkerContextCore> context_; WorkerInstanceMap worker_map_; ProcessToSenderMap process_sender_map_; + // Map from process_id to embedded_worker_id. + // This map only contains running workers. + std::map<int, int> worker_process_map_; + int next_embedded_worker_id_; DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerRegistry); diff --git a/content/browser/service_worker/service_worker_dispatcher_host.cc b/content/browser/service_worker/service_worker_dispatcher_host.cc index 92fe5e7..0ae3c82 100644 --- a/content/browser/service_worker/service_worker_dispatcher_host.cc +++ b/content/browser/service_worker/service_worker_dispatcher_host.cc @@ -61,9 +61,6 @@ void ServiceWorkerDispatcherHost::OnDestruct() const { bool ServiceWorkerDispatcherHost::OnMessageReceived( const IPC::Message& message, bool* message_was_ok) { - if (IPC_MESSAGE_CLASS(message) != ServiceWorkerMsgStart) - return false; - bool handled = true; IPC_BEGIN_MESSAGE_MAP_EX( ServiceWorkerDispatcherHost, message, *message_was_ok) @@ -75,6 +72,10 @@ bool ServiceWorkerDispatcherHost::OnMessageReceived( OnProviderCreated) IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ProviderDestroyed, OnProviderDestroyed) + IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerStarted, + OnWorkerStarted) + IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerStopped, + OnWorkerStopped) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() @@ -176,6 +177,21 @@ void ServiceWorkerDispatcherHost::RegistrationComplete( thread_id, request_id, registration_id)); } +void ServiceWorkerDispatcherHost::OnWorkerStarted( + int thread_id, int embedded_worker_id) { + if (!context_) + return; + context_->embedded_worker_registry()->OnWorkerStarted( + render_process_id_, thread_id, embedded_worker_id); +} + +void ServiceWorkerDispatcherHost::OnWorkerStopped(int embedded_worker_id) { + if (!context_) + return; + context_->embedded_worker_registry()->OnWorkerStopped( + render_process_id_, embedded_worker_id); +} + void ServiceWorkerDispatcherHost::UnregistrationComplete( int32 thread_id, int32 request_id, diff --git a/content/browser/service_worker/service_worker_dispatcher_host.h b/content/browser/service_worker/service_worker_dispatcher_host.h index be00801..4c42c6f 100644 --- a/content/browser/service_worker/service_worker_dispatcher_host.h +++ b/content/browser/service_worker/service_worker_dispatcher_host.h @@ -46,6 +46,9 @@ class CONTENT_EXPORT ServiceWorkerDispatcherHost : public BrowserMessageFilter { const GURL& pattern); void OnProviderCreated(int provider_id); void OnProviderDestroyed(int provider_id); + void OnWorkerStarted(int thread_id, + int embedded_worker_id); + void OnWorkerStopped(int embedded_worker_id); // Callbacks from ServiceWorkerContextCore void RegistrationComplete(int32 thread_id, diff --git a/content/common/service_worker_messages.h b/content/common/service_worker_messages.h index d2a5eb2..78beb73 100644 --- a/content/common/service_worker_messages.h +++ b/content/common/service_worker_messages.h @@ -5,11 +5,18 @@ // Message definition file, included multiple times, hence no include guard. #include "base/strings/string16.h" +#include "content/common/service_worker_types.h" #include "ipc/ipc_message_macros.h" #include "ipc/ipc_param_traits.h" #include "third_party/WebKit/public/platform/WebServiceWorkerError.h" #include "url/gurl.h" +IPC_STRUCT_TRAITS_BEGIN(content::ServiceWorkerFetchRequest) + IPC_STRUCT_TRAITS_MEMBER(url) + IPC_STRUCT_TRAITS_MEMBER(method) + IPC_STRUCT_TRAITS_MEMBER(headers) +IPC_STRUCT_TRAITS_END() + #undef IPC_MESSAGE_EXPORT #define IPC_MESSAGE_EXPORT CONTENT_EXPORT @@ -63,11 +70,33 @@ IPC_MESSAGE_CONTROL1(ServiceWorkerHostMsg_ProviderDestroyed, // For EmbeddedWorker related messages ------------------------------------- // Browser -> Renderer message to create a new embedded worker context. -IPC_MESSAGE_CONTROL3(ServiceWorkerMsg_StartWorker, +IPC_MESSAGE_CONTROL3(EmbeddedWorkerMsg_StartWorker, int /* embedded_worker_id */, int64 /* service_worker_version_id */, GURL /* script_url */) -// Browser -> Renderer message to terminate the embedded worker. -IPC_MESSAGE_CONTROL1(ServiceWorkerMsg_TerminateWorker, +// Browser -> Renderer message to stop (terminate) the embedded worker. +IPC_MESSAGE_CONTROL1(EmbeddedWorkerMsg_StopWorker, + int /* embedded_worker_id */) + +// Renderer -> Browser message to indicate that the worker is started. +IPC_MESSAGE_CONTROL2(EmbeddedWorkerHostMsg_WorkerStarted, + int /* thread_id */, + int /* embedded_worker_id */) + +// Renderer -> Browser message to indicate that the worker is stopped. +IPC_MESSAGE_CONTROL1(EmbeddedWorkerHostMsg_WorkerStopped, int /* embedded_worker_id */) + +// --------------------------------------------------------------------------- +// For EmbeddedWorkerContext related messages, which are directly sent from +// browser to the worker thread in the child process. We use a new message class +// for this for easier cross-thread message dispatching. + +#undef IPC_MESSAGE_START +#define IPC_MESSAGE_START EmbeddedWorkerContextMsgStart + +IPC_MESSAGE_CONTROL3(EmbeddedWorkerContextMsg_FetchEvent, + int /* thread_id */, + int /* embedded_worker_id */, + content::ServiceWorkerFetchRequest) diff --git a/content/common/service_worker_types.cc b/content/common/service_worker_types.cc new file mode 100644 index 0000000..c456752 --- /dev/null +++ b/content/common/service_worker_types.cc @@ -0,0 +1,22 @@ +// Copyright 2013 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/common/service_worker_types.h" + +namespace content { + +ServiceWorkerFetchRequest::ServiceWorkerFetchRequest() {} + +ServiceWorkerFetchRequest::ServiceWorkerFetchRequest( + const GURL& url, + const std::string& method, + const std::map<std::string, std::string>& headers) + : url(url), + method(method), + headers(headers) { +} + +ServiceWorkerFetchRequest::~ServiceWorkerFetchRequest() {} + +} // namespace content diff --git a/content/common/service_worker_types.h b/content/common/service_worker_types.h new file mode 100644 index 0000000..19a763f --- /dev/null +++ b/content/common/service_worker_types.h @@ -0,0 +1,38 @@ +// Copyright 2013 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_COMMON_SERVICE_WORKER_TYPES_H_ +#define CONTENT_COMMON_SERVICE_WORKER_TYPES_H_ + +#include <map> +#include <string> + +#include "base/basictypes.h" +#include "content/common/content_export.h" +#include "url/gurl.h" + +// This file is to have common definitions that are to be shared by +// browser and child process. + +namespace content { + +// To dispatch fetch request from browser to child process. +// TODO(kinuko): This struct will definitely need more fields and +// we'll probably want to have response struct/class too. +struct CONTENT_EXPORT ServiceWorkerFetchRequest { + ServiceWorkerFetchRequest(); + ServiceWorkerFetchRequest( + const GURL& url, + const std::string& method, + const std::map<std::string, std::string>& headers); + ~ServiceWorkerFetchRequest(); + + GURL url; + std::string method; + std::map<std::string, std::string> headers; +}; + +} // namespace content + +#endif // CONTENT_COMMON_SERVICE_WORKER_TYPES_H_ diff --git a/content/content_common.gypi b/content/content_common.gypi index 17c52ca..709feeb 100644 --- a/content/content_common.gypi +++ b/content/content_common.gypi @@ -318,7 +318,6 @@ 'common/message_router.cc', 'common/message_router.h', 'common/mime_registry_messages.h', - 'common/service_worker_messages.h', 'common/navigation_gesture.h', 'common/net/url_fetcher.cc', 'common/net/url_request_user_data.cc', @@ -375,6 +374,9 @@ 'common/sandbox_win.h', 'common/savable_url_schemes.cc', 'common/savable_url_schemes.h', + 'common/service_worker_messages.h', + 'common/service_worker_types.cc', + 'common/service_worker_types.h', 'common/set_process_title.cc', 'common/set_process_title.h', 'common/set_process_title_linux.cc', diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi index d8870cc..1d4ace4 100644 --- a/content/content_renderer.gypi +++ b/content/content_renderer.gypi @@ -481,10 +481,12 @@ 'renderer/savable_resources.h', 'renderer/scoped_clipboard_writer_glue.cc', 'renderer/scoped_clipboard_writer_glue.h', + 'renderer/service_worker/embedded_worker_context_client.cc', + 'renderer/service_worker/embedded_worker_context_client.h', + 'renderer/service_worker/embedded_worker_context_message_filter.cc', + 'renderer/service_worker/embedded_worker_context_message_filter.h', 'renderer/service_worker/embedded_worker_dispatcher.cc', 'renderer/service_worker/embedded_worker_dispatcher.h', - 'renderer/service_worker/service_worker_context_client.cc', - 'renderer/service_worker/service_worker_context_client.h', 'renderer/shared_memory_seqlock_reader.cc', 'renderer/shared_memory_seqlock_reader.h', 'renderer/shared_worker_repository.cc', diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 93e41b7..5e8db70 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc @@ -81,6 +81,7 @@ #include "content/renderer/render_process_impl.h" #include "content/renderer/render_view_impl.h" #include "content/renderer/renderer_webkitplatformsupport_impl.h" +#include "content/renderer/service_worker/embedded_worker_context_message_filter.h" #include "content/renderer/service_worker/embedded_worker_dispatcher.h" #include "content/renderer/skia_benchmarking_extension.h" #include "grit/content_resources.h" @@ -92,7 +93,6 @@ #include "media/filters/gpu_video_accelerator_factories.h" #include "net/base/net_errors.h" #include "net/base/net_util.h" -#include "third_party/skia/include/core/SkGraphics.h" #include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/web/WebColorName.h" #include "third_party/WebKit/public/web/WebDatabase.h" @@ -106,6 +106,7 @@ #include "third_party/WebKit/public/web/WebScriptController.h" #include "third_party/WebKit/public/web/WebSecurityPolicy.h" #include "third_party/WebKit/public/web/WebView.h" +#include "third_party/skia/include/core/SkGraphics.h" #include "ui/base/layout.h" #include "ui/base/ui_base_switches.h" #include "v8/include/v8.h" @@ -375,6 +376,8 @@ void RenderThreadImpl::Init() { AddFilter((new IndexedDBMessageFilter(thread_safe_sender()))->GetFilter()); + AddFilter((new EmbeddedWorkerContextMessageFilter())->GetFilter()); + GetContentClient()->renderer()->RenderThreadStarted(); const CommandLine& command_line = *CommandLine::ForCurrentProcess(); diff --git a/content/renderer/service_worker/service_worker_context_client.cc b/content/renderer/service_worker/embedded_worker_context_client.cc index 412ed67..a770fc4 100644 --- a/content/renderer/service_worker/service_worker_context_client.cc +++ b/content/renderer/service_worker/embedded_worker_context_client.cc @@ -2,13 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/renderer/service_worker/service_worker_context_client.h" +#include "content/renderer/service_worker/embedded_worker_context_client.h" #include "base/lazy_instance.h" #include "base/message_loop/message_loop_proxy.h" #include "base/pickle.h" #include "base/threading/thread_local.h" #include "content/child/thread_safe_sender.h" +#include "content/common/service_worker_messages.h" #include "content/renderer/render_thread_impl.h" #include "content/renderer/service_worker/embedded_worker_dispatcher.h" #include "ipc/ipc_message_macros.h" @@ -24,7 +25,7 @@ namespace { // For now client must be a per-thread instance. // TODO(kinuko): This needs to be refactored when we start using thread pool // or having multiple clients per one thread. -base::LazyInstance<base::ThreadLocalPointer<ServiceWorkerContextClient> >:: +base::LazyInstance<base::ThreadLocalPointer<EmbeddedWorkerContextClient> >:: Leaky g_worker_client_tls = LAZY_INSTANCE_INITIALIZER; void CallWorkerContextDestroyedOnMainThread(int embedded_worker_id) { @@ -37,12 +38,12 @@ void CallWorkerContextDestroyedOnMainThread(int embedded_worker_id) { } // namespace -ServiceWorkerContextClient* -ServiceWorkerContextClient::ThreadSpecificInstance() { +EmbeddedWorkerContextClient* +EmbeddedWorkerContextClient::ThreadSpecificInstance() { return g_worker_client_tls.Pointer()->Get(); } -ServiceWorkerContextClient::ServiceWorkerContextClient( +EmbeddedWorkerContextClient::EmbeddedWorkerContextClient( int embedded_worker_id, int64 service_worker_version_id, const GURL& script_url) @@ -54,19 +55,22 @@ ServiceWorkerContextClient::ServiceWorkerContextClient( proxy_(NULL) { } -ServiceWorkerContextClient::~ServiceWorkerContextClient() { +EmbeddedWorkerContextClient::~EmbeddedWorkerContextClient() { DCHECK(g_worker_client_tls.Pointer()->Get() != NULL); g_worker_client_tls.Pointer()->Set(NULL); } -bool ServiceWorkerContextClient::OnMessageReceived( +bool EmbeddedWorkerContextClient::OnMessageReceived( const IPC::Message& msg) { - NOTIMPLEMENTED(); - return false; + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(EmbeddedWorkerContextClient, msg) + IPC_MESSAGE_HANDLER(EmbeddedWorkerContextMsg_FetchEvent, OnFetchEvent) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; } -void ServiceWorkerContextClient::workerContextFailedToStart() -{ +void EmbeddedWorkerContextClient::workerContextFailedToStart() { DCHECK(main_thread_proxy_->RunsTasksOnCurrentThread()); DCHECK(!proxy_); @@ -74,19 +78,19 @@ void ServiceWorkerContextClient::workerContextFailedToStart() WorkerContextDestroyed(embedded_worker_id_); } -void ServiceWorkerContextClient::workerContextStarted( +void EmbeddedWorkerContextClient::workerContextStarted( blink::WebServiceWorkerContextProxy* proxy) { DCHECK_NE(0, WorkerTaskRunner::Instance()->CurrentWorkerId()); DCHECK(g_worker_client_tls.Pointer()->Get() == NULL); g_worker_client_tls.Pointer()->Set(this); proxy_ = proxy; - // TODO(kinuko): Send WorkerStarted message to the browser with the - // current thread ID so that the browser can start sending embedded worker - // messages directly to this client. + sender_->Send(new EmbeddedWorkerHostMsg_WorkerStarted( + WorkerTaskRunner::Instance()->CurrentWorkerId(), + embedded_worker_id_)); } -void ServiceWorkerContextClient::workerContextDestroyed() { +void EmbeddedWorkerContextClient::workerContextDestroyed() { DCHECK_NE(0, WorkerTaskRunner::Instance()->CurrentWorkerId()); proxy_ = NULL; main_thread_proxy_->PostTask( @@ -95,4 +99,13 @@ void ServiceWorkerContextClient::workerContextDestroyed() { embedded_worker_id_)); } +void EmbeddedWorkerContextClient::OnFetchEvent( + int thread_id, + int embedded_worker_id, + const ServiceWorkerFetchRequest& request) { + // TODO(kinuko): Implement. + // This is to call WebServiceWorkerContextProxy's dispatchFetchEvent method. + NOTIMPLEMENTED(); +} + } // namespace content diff --git a/content/renderer/service_worker/service_worker_context_client.h b/content/renderer/service_worker/embedded_worker_context_client.h index e59cc62..7f789714 100644 --- a/content/renderer/service_worker/service_worker_context_client.h +++ b/content/renderer/service_worker/embedded_worker_context_client.h @@ -17,23 +17,24 @@ class MessageLoopProxy; namespace content { +struct ServiceWorkerFetchRequest; class ThreadSafeSender; // This class provides access to/from an embedded worker's WorkerGlobalScope. // All methods other than the constructor (it's created on the main thread) // are called on the worker thread. -class ServiceWorkerContextClient +class EmbeddedWorkerContextClient : public blink::WebServiceWorkerContextClient { public: // Returns a thread-specific client instance. This does NOT create a // new instance. - static ServiceWorkerContextClient* ThreadSpecificInstance(); + static EmbeddedWorkerContextClient* ThreadSpecificInstance(); - ServiceWorkerContextClient(int embedded_worker_id, - int64 service_worker_version_id, - const GURL& script_url); + EmbeddedWorkerContextClient(int embedded_worker_id, + int64 service_worker_version_id, + const GURL& script_url); - virtual ~ServiceWorkerContextClient(); + virtual ~EmbeddedWorkerContextClient(); bool OnMessageReceived(const IPC::Message& msg); @@ -47,6 +48,10 @@ class ServiceWorkerContextClient int embedded_worker_id() const { return embedded_worker_id_; } private: + void OnFetchEvent(int thread_id, + int embedded_worker_id, + const ServiceWorkerFetchRequest& request); + const int embedded_worker_id_; const int64 service_worker_version_id_; const GURL script_url_; @@ -55,7 +60,7 @@ class ServiceWorkerContextClient blink::WebServiceWorkerContextProxy* proxy_; - DISALLOW_COPY_AND_ASSIGN(ServiceWorkerContextClient); + DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerContextClient); }; } // namespace content diff --git a/content/renderer/service_worker/embedded_worker_context_message_filter.cc b/content/renderer/service_worker/embedded_worker_context_message_filter.cc new file mode 100644 index 0000000..cbc141d --- /dev/null +++ b/content/renderer/service_worker/embedded_worker_context_message_filter.cc @@ -0,0 +1,48 @@ +// Copyright 2013 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/renderer/service_worker/embedded_worker_context_message_filter.h" + +#include "base/message_loop/message_loop_proxy.h" +#include "content/child/child_thread.h" +#include "content/child/thread_safe_sender.h" +#include "content/child/worker_thread_task_runner.h" +#include "content/renderer/service_worker/embedded_worker_context_client.h" +#include "ipc/ipc_message_macros.h" + +namespace content { + +EmbeddedWorkerContextMessageFilter::EmbeddedWorkerContextMessageFilter() + : main_thread_loop_proxy_(base::MessageLoopProxy::current()), + thread_safe_sender_(ChildThread::current()->thread_safe_sender()) {} + +EmbeddedWorkerContextMessageFilter::~EmbeddedWorkerContextMessageFilter() {} + +base::TaskRunner* +EmbeddedWorkerContextMessageFilter::OverrideTaskRunnerForMessage( + const IPC::Message& msg) { + if (IPC_MESSAGE_CLASS(msg) != EmbeddedWorkerContextMsgStart) + return NULL; + int ipc_thread_id = 0; + const bool success = PickleIterator(msg).ReadInt(&ipc_thread_id); + DCHECK(success); + if (!ipc_thread_id) + return main_thread_loop_proxy_.get(); + return new WorkerThreadTaskRunner(ipc_thread_id); +} + +bool EmbeddedWorkerContextMessageFilter::OnMessageReceived( + const IPC::Message& msg) { + if (IPC_MESSAGE_CLASS(msg) != EmbeddedWorkerContextMsgStart) + return false; + EmbeddedWorkerContextClient* client = + EmbeddedWorkerContextClient::ThreadSpecificInstance(); + if (!client) { + LOG(ERROR) << "Stray message is sent to nonexistent worker"; + return true; + } + return client->OnMessageReceived(msg); +} + +} // namespace content diff --git a/content/renderer/service_worker/embedded_worker_context_message_filter.h b/content/renderer/service_worker/embedded_worker_context_message_filter.h new file mode 100644 index 0000000..e3bffd2 --- /dev/null +++ b/content/renderer/service_worker/embedded_worker_context_message_filter.h @@ -0,0 +1,32 @@ +// Copyright 2013 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_RENDERER_SERVICE_WORKER_EMBEDDED_WORKER_CONTEXT_MESSAGE_FILTER_H_ +#define CONTENT_RENDERER_SERVICE_WORKER_EMBEDDED_WORKER_CONTEXT_MESSAGE_FILTER_H_ + +#include "content/child/child_message_filter.h" + +namespace content { + +class EmbeddedWorkerContextMessageFilter : public ChildMessageFilter { + public: + EmbeddedWorkerContextMessageFilter(); + + protected: + virtual ~EmbeddedWorkerContextMessageFilter(); + + // ChildMessageFilter implementation: + virtual base::TaskRunner* OverrideTaskRunnerForMessage( + const IPC::Message& msg) OVERRIDE; + virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE; + + scoped_refptr<base::MessageLoopProxy> main_thread_loop_proxy_; + scoped_refptr<ThreadSafeSender> thread_safe_sender_; + + DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerContextMessageFilter); +}; + +} // namespace content + +#endif // CONTENT_RENDERER_SERVICE_WORKER_EMBEDDED_WORKER_CONTEXT_MESSAGE_FILTER_H_ diff --git a/content/renderer/service_worker/embedded_worker_dispatcher.cc b/content/renderer/service_worker/embedded_worker_dispatcher.cc index 0aa4ab2..bbe72ab9 100644 --- a/content/renderer/service_worker/embedded_worker_dispatcher.cc +++ b/content/renderer/service_worker/embedded_worker_dispatcher.cc @@ -12,7 +12,7 @@ #include "content/child/thread_safe_sender.h" #include "content/common/service_worker_messages.h" #include "content/renderer/render_thread_impl.h" -#include "content/renderer/service_worker/service_worker_context_client.h" +#include "content/renderer/service_worker/embedded_worker_context_client.h" #include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/platform/WebURL.h" #include "third_party/WebKit/public/web/WebEmbeddedWorker.h" @@ -44,8 +44,8 @@ bool EmbeddedWorkerDispatcher::OnMessageReceived( const IPC::Message& message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(EmbeddedWorkerDispatcher, message) - IPC_MESSAGE_HANDLER(ServiceWorkerMsg_StartWorker, OnStartWorker) - IPC_MESSAGE_HANDLER(ServiceWorkerMsg_TerminateWorker, OnTerminateWorker) + IPC_MESSAGE_HANDLER(EmbeddedWorkerMsg_StartWorker, OnStartWorker) + IPC_MESSAGE_HANDLER(EmbeddedWorkerMsg_StopWorker, OnStopWorker) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; @@ -53,6 +53,8 @@ bool EmbeddedWorkerDispatcher::OnMessageReceived( void EmbeddedWorkerDispatcher::WorkerContextDestroyed( int embedded_worker_id) { + RenderThreadImpl::current()->thread_safe_sender()->Send( + new EmbeddedWorkerHostMsg_WorkerStopped(embedded_worker_id)); workers_.Remove(embedded_worker_id); } @@ -63,7 +65,7 @@ void EmbeddedWorkerDispatcher::OnStartWorker( DCHECK(!workers_.Lookup(embedded_worker_id)); scoped_ptr<WorkerWrapper> wrapper(new WorkerWrapper( blink::WebEmbeddedWorker::create( - new ServiceWorkerContextClient( + new EmbeddedWorkerContextClient( embedded_worker_id, service_worker_version_id, script_url), @@ -78,10 +80,10 @@ void EmbeddedWorkerDispatcher::OnStartWorker( workers_.AddWithID(wrapper.release(), embedded_worker_id); } -void EmbeddedWorkerDispatcher::OnTerminateWorker(int embedded_worker_id) { +void EmbeddedWorkerDispatcher::OnStopWorker(int embedded_worker_id) { WorkerWrapper* wrapper = workers_.Lookup(embedded_worker_id); if (!wrapper) { - LOG(WARNING) << "Got OnTerminateWorker for nonexistent worker"; + LOG(WARNING) << "Got OnStopWorker for nonexistent worker"; return; } diff --git a/content/renderer/service_worker/embedded_worker_dispatcher.h b/content/renderer/service_worker/embedded_worker_dispatcher.h index d4dd662..6b1ba84 100644 --- a/content/renderer/service_worker/embedded_worker_dispatcher.h +++ b/content/renderer/service_worker/embedded_worker_dispatcher.h @@ -36,7 +36,7 @@ class EmbeddedWorkerDispatcher : public IPC::Listener { void OnStartWorker(int embedded_worker_id, int64 service_worker_version_id, const GURL& script_url); - void OnTerminateWorker(int embedded_worker_id); + void OnStopWorker(int embedded_worker_id); IDMap<WorkerWrapper, IDMapOwnPointer> workers_; base::WeakPtrFactory<EmbeddedWorkerDispatcher> weak_factory_; diff --git a/ipc/ipc_message_start.h b/ipc/ipc_message_start.h index 7ce2bdd..e5b7c3d 100644 --- a/ipc/ipc_message_start.h +++ b/ipc/ipc_message_start.h @@ -92,6 +92,7 @@ enum IPCMessageStart { EncryptedMediaMsgStart, ServiceWorkerMsgStart, MessagePortMsgStart, + EmbeddedWorkerContextMsgStart, LastIPCMsgStart // Must come last. }; |