summaryrefslogtreecommitdiffstats
path: root/content/renderer/service_worker
diff options
context:
space:
mode:
authorkinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-29 04:35:00 +0000
committerkinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-29 04:35:00 +0000
commit7670d4336ccc74c75714b7f2d7faac63f424243b (patch)
tree99e30cfd3bce512226b1a4d04c274f60ea2a96de /content/renderer/service_worker
parent618bd5bd6df541678459acfafc765df101e116be (diff)
downloadchromium_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')
-rw-r--r--content/renderer/service_worker/OWNERS3
-rw-r--r--content/renderer/service_worker/embedded_worker_dispatcher.cc94
-rw-r--r--content/renderer/service_worker/embedded_worker_dispatcher.h49
-rw-r--r--content/renderer/service_worker/service_worker_context_client.cc98
-rw-r--r--content/renderer/service_worker/service_worker_context_client.h63
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_