diff options
author | kinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-29 04:35:00 +0000 |
---|---|---|
committer | kinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-29 04:35:00 +0000 |
commit | 7670d4336ccc74c75714b7f2d7faac63f424243b (patch) | |
tree | 99e30cfd3bce512226b1a4d04c274f60ea2a96de /content/renderer/service_worker | |
parent | 618bd5bd6df541678459acfafc765df101e116be (diff) | |
download | chromium_src-7670d4336ccc74c75714b7f2d7faac63f424243b.zip chromium_src-7670d4336ccc74c75714b7f2d7faac63f424243b.tar.gz chromium_src-7670d4336ccc74c75714b7f2d7faac63f424243b.tar.bz2 |
Initial child-process side plumbing for starting an embedded ServiceWorker context
Design assumptions (some assumptions can be tentative) for this CL:
* ServiceWorkerProvider is going to be embedded in all frame/document
* Browser process can tell which SWP is associated to which SW (if any),
via SWP registration process that is not added yet
* A newly created embedded worker context will always create its own shadow page
for its loading context
* A newly created embedded worker context stub will keep a ref to the embedding process
No browser-side implementation / blink plumbing yet.
This adds a new tiny dispatcher which listens messages
solely on the renderer thread.
BUG=313530
Review URL: https://codereview.chromium.org/54573002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@237873 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/renderer/service_worker')
5 files changed, 307 insertions, 0 deletions
diff --git a/content/renderer/service_worker/OWNERS b/content/renderer/service_worker/OWNERS new file mode 100644 index 0000000..633b8a4 --- /dev/null +++ b/content/renderer/service_worker/OWNERS @@ -0,0 +1,3 @@ +alecflett@chromium.org +kinuko@chromium.org +michaeln@chromium.org diff --git a/content/renderer/service_worker/embedded_worker_dispatcher.cc b/content/renderer/service_worker/embedded_worker_dispatcher.cc new file mode 100644 index 0000000..0aa4ab2 --- /dev/null +++ b/content/renderer/service_worker/embedded_worker_dispatcher.cc @@ -0,0 +1,94 @@ +// 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_dispatcher.h" + +#include "base/memory/scoped_ptr.h" +#include "base/strings/string16.h" +#include "base/strings/utf_string_conversions.h" +#include "content/child/child_process.h" +#include "content/child/scoped_child_process_reference.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/service_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" +#include "third_party/WebKit/public/web/WebEmbeddedWorkerStartData.h" +#include "webkit/child/worker_task_runner.h" +#include "webkit/common/user_agent/user_agent.h" + +namespace content { + +// A thin wrapper of WebEmbeddedWorker which also adds and releases process +// references automatically. +class EmbeddedWorkerDispatcher::WorkerWrapper { + public: + explicit WorkerWrapper(blink::WebEmbeddedWorker* worker) : worker_(worker) {} + ~WorkerWrapper() {} + + blink::WebEmbeddedWorker* worker() { return worker_.get(); } + + private: + ScopedChildProcessReference process_ref_; + scoped_ptr<blink::WebEmbeddedWorker> worker_; +}; + +EmbeddedWorkerDispatcher::EmbeddedWorkerDispatcher() : weak_factory_(this) {} + +EmbeddedWorkerDispatcher::~EmbeddedWorkerDispatcher() {} + +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_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +void EmbeddedWorkerDispatcher::WorkerContextDestroyed( + int embedded_worker_id) { + workers_.Remove(embedded_worker_id); +} + +void EmbeddedWorkerDispatcher::OnStartWorker( + int embedded_worker_id, + int64 service_worker_version_id, + const GURL& script_url) { + DCHECK(!workers_.Lookup(embedded_worker_id)); + scoped_ptr<WorkerWrapper> wrapper(new WorkerWrapper( + blink::WebEmbeddedWorker::create( + new ServiceWorkerContextClient( + embedded_worker_id, + service_worker_version_id, + script_url), + NULL))); + + blink::WebEmbeddedWorkerStartData start_data; + start_data.scriptURL = script_url; + start_data.userAgent = + base::UTF8ToUTF16(webkit_glue::GetUserAgent(script_url)); + + wrapper->worker()->startWorkerContext(start_data); + workers_.AddWithID(wrapper.release(), embedded_worker_id); +} + +void EmbeddedWorkerDispatcher::OnTerminateWorker(int embedded_worker_id) { + WorkerWrapper* wrapper = workers_.Lookup(embedded_worker_id); + if (!wrapper) { + LOG(WARNING) << "Got OnTerminateWorker for nonexistent worker"; + return; + } + + // This should eventually call WorkerContextDestroyed. (We may need to post + // a delayed task to forcibly abort the worker context if we find it + // necessary) + wrapper->worker()->terminateWorkerContext(); +} + +} // namespace content diff --git a/content/renderer/service_worker/embedded_worker_dispatcher.h b/content/renderer/service_worker/embedded_worker_dispatcher.h new file mode 100644 index 0000000..d4dd662 --- /dev/null +++ b/content/renderer/service_worker/embedded_worker_dispatcher.h @@ -0,0 +1,49 @@ +// 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_CHILD_SERVICE_WORKER_EMBEDDED_WORKER_DISPATCHER_H_ +#define CONTENT_CHILD_SERVICE_WORKER_EMBEDDED_WORKER_DISPATCHER_H_ + +#include "base/basictypes.h" +#include "base/id_map.h" +#include "base/memory/weak_ptr.h" +#include "ipc/ipc_listener.h" + +struct ServiceWorkerMsg_StartWorker_Params; +class GURL; + +namespace WebKit { +class WebEmbeddedWorker; +} + +namespace content { + +// A tiny dispatcher which handles embedded worker start/stop messages. +class EmbeddedWorkerDispatcher : public IPC::Listener { + public: + EmbeddedWorkerDispatcher(); + virtual ~EmbeddedWorkerDispatcher(); + + // IPC::Listener overrides. + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; + + void WorkerContextDestroyed(int embedded_worker_id); + + private: + class WorkerWrapper; + + void OnStartWorker(int embedded_worker_id, + int64 service_worker_version_id, + const GURL& script_url); + void OnTerminateWorker(int embedded_worker_id); + + IDMap<WorkerWrapper, IDMapOwnPointer> workers_; + base::WeakPtrFactory<EmbeddedWorkerDispatcher> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerDispatcher); +}; + +} // namespace content + +#endif // CONTENT_CHILD_SERVICE_WORKER_EMBEDDED_WORKER_DISPATCHER_H_ diff --git a/content/renderer/service_worker/service_worker_context_client.cc b/content/renderer/service_worker/service_worker_context_client.cc new file mode 100644 index 0000000..412ed67 --- /dev/null +++ b/content/renderer/service_worker/service_worker_context_client.cc @@ -0,0 +1,98 @@ +// 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/service_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/renderer/render_thread_impl.h" +#include "content/renderer/service_worker/embedded_worker_dispatcher.h" +#include "ipc/ipc_message_macros.h" +#include "third_party/WebKit/public/platform/WebString.h" +#include "webkit/child/worker_task_runner.h" + +using webkit_glue::WorkerTaskRunner; + +namespace content { + +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> >:: + Leaky g_worker_client_tls = LAZY_INSTANCE_INITIALIZER; + +void CallWorkerContextDestroyedOnMainThread(int embedded_worker_id) { + if (!RenderThreadImpl::current() || + !RenderThreadImpl::current()->embedded_worker_dispatcher()) + return; + RenderThreadImpl::current()->embedded_worker_dispatcher()-> + WorkerContextDestroyed(embedded_worker_id); +} + +} // namespace + +ServiceWorkerContextClient* +ServiceWorkerContextClient::ThreadSpecificInstance() { + return g_worker_client_tls.Pointer()->Get(); +} + +ServiceWorkerContextClient::ServiceWorkerContextClient( + int embedded_worker_id, + int64 service_worker_version_id, + const GURL& script_url) + : embedded_worker_id_(embedded_worker_id), + service_worker_version_id_(service_worker_version_id), + script_url_(script_url), + sender_(ChildThread::current()->thread_safe_sender()), + main_thread_proxy_(base::MessageLoopProxy::current()), + proxy_(NULL) { +} + +ServiceWorkerContextClient::~ServiceWorkerContextClient() { + DCHECK(g_worker_client_tls.Pointer()->Get() != NULL); + g_worker_client_tls.Pointer()->Set(NULL); +} + +bool ServiceWorkerContextClient::OnMessageReceived( + const IPC::Message& msg) { + NOTIMPLEMENTED(); + return false; +} + +void ServiceWorkerContextClient::workerContextFailedToStart() +{ + DCHECK(main_thread_proxy_->RunsTasksOnCurrentThread()); + DCHECK(!proxy_); + + RenderThreadImpl::current()->embedded_worker_dispatcher()-> + WorkerContextDestroyed(embedded_worker_id_); +} + +void ServiceWorkerContextClient::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. +} + +void ServiceWorkerContextClient::workerContextDestroyed() { + DCHECK_NE(0, WorkerTaskRunner::Instance()->CurrentWorkerId()); + proxy_ = NULL; + main_thread_proxy_->PostTask( + FROM_HERE, + base::Bind(&CallWorkerContextDestroyedOnMainThread, + embedded_worker_id_)); +} + +} // namespace content diff --git a/content/renderer/service_worker/service_worker_context_client.h b/content/renderer/service_worker/service_worker_context_client.h new file mode 100644 index 0000000..e59cc62 --- /dev/null +++ b/content/renderer/service_worker/service_worker_context_client.h @@ -0,0 +1,63 @@ +// 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_CHILD_SERVICE_WORKER_EMBEDDED_WORKER_CLIENT_H_ +#define CONTENT_CHILD_SERVICE_WORKER_EMBEDDED_WORKER_CLIENT_H_ + +#include "base/memory/ref_counted.h" +#include "base/strings/string16.h" +#include "ipc/ipc_listener.h" +#include "third_party/WebKit/public/web/WebServiceWorkerContextClient.h" +#include "url/gurl.h" + +namespace base { +class MessageLoopProxy; +} + +namespace content { + +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 + : public blink::WebServiceWorkerContextClient { + public: + // Returns a thread-specific client instance. This does NOT create a + // new instance. + static ServiceWorkerContextClient* ThreadSpecificInstance(); + + ServiceWorkerContextClient(int embedded_worker_id, + int64 service_worker_version_id, + const GURL& script_url); + + virtual ~ServiceWorkerContextClient(); + + bool OnMessageReceived(const IPC::Message& msg); + + // WebServiceWorkerContextClient overrides. + virtual void workerContextFailedToStart(); + virtual void workerContextStarted(blink::WebServiceWorkerContextProxy* proxy); + virtual void workerContextDestroyed(); + + // TODO: Implement DevTools related method overrides. + + int embedded_worker_id() const { return embedded_worker_id_; } + + private: + const int embedded_worker_id_; + const int64 service_worker_version_id_; + const GURL script_url_; + scoped_refptr<ThreadSafeSender> sender_; + scoped_refptr<base::MessageLoopProxy> main_thread_proxy_; + + blink::WebServiceWorkerContextProxy* proxy_; + + DISALLOW_COPY_AND_ASSIGN(ServiceWorkerContextClient); +}; + +} // namespace content + +#endif // CONTENT_CHILD_SERVICE_WORKER_EMBEDDED_WORKER_CLIENT_H_ |