diff options
author | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-04 00:39:56 +0000 |
---|---|---|
committer | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-04 00:39:56 +0000 |
commit | eb47a137b7ce84a6df0ccc9550c75b6bec60eb68 (patch) | |
tree | 7f6c4e1d169bf60465a0b642a4434a239aaf0f6d /chrome/browser | |
parent | 0ff03ae3f1bf6f877a4aa32263f6418f2c5797d2 (diff) | |
download | chromium_src-eb47a137b7ce84a6df0ccc9550c75b6bec60eb68.zip chromium_src-eb47a137b7ce84a6df0ccc9550c75b6bec60eb68.tar.gz chromium_src-eb47a137b7ce84a6df0ccc9550c75b6bec60eb68.tar.bz2 |
Initial checkin of the out of process worker implementation.
WebWorkerClient/WebWorker are parallel interfaces of WebCore::{WorkerObjectProxy, WorkerContextProxy} that use Chrome data types. When WebKit requests a WorkerObjectProxy, we create an instance of WebWorkerClientImpl. This class creates an object that implements a Chromium version of WorkerObjectProxy (i.e. with Chrome data types) through WebViewDelegate. That object is a WebWorkerProxy and talks over IPC to a WebWorker object in the worker process. The WebWorker object creates the actual WebCore::Worker object using another class in glue: WebWorkerImpl.
When the WebCore::Worker object running in the worker process wants to talk back to the code running in the renderer, it talks to WebWorkerImpl which implements WebCore::WorkerObjectProxy. WebWorkerImpl converts the data types to Chrome compatible ones, and then calls the WebWorkerClient version which does IPC to get to the renderer process. This ends up at WebWorkerProxy, which calls WebWorkerClientImpl (the original class).
In future changes, sandboxing, multiple worker processes etc will be added. Note that I also had to make two small changes to WebKit, since WorkerMessagingProxy couldn't be created as is for the nested worker case. I'll either check it in myself or work with Jian to do so.
Review URL: http://codereview.chromium.org/27157
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@10847 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/browser.scons | 4 | ||||
-rw-r--r-- | chrome/browser/browser.vcproj | 20 | ||||
-rw-r--r-- | chrome/browser/renderer_host/resource_message_filter.cc | 17 | ||||
-rw-r--r-- | chrome/browser/renderer_host/resource_message_filter.h | 2 | ||||
-rw-r--r-- | chrome/browser/worker_host/worker_process_host.cc | 99 | ||||
-rw-r--r-- | chrome/browser/worker_host/worker_process_host.h | 56 | ||||
-rw-r--r-- | chrome/browser/worker_host/worker_service.cc | 73 | ||||
-rw-r--r-- | chrome/browser/worker_host/worker_service.h | 52 |
8 files changed, 323 insertions, 0 deletions
diff --git a/chrome/browser/browser.scons b/chrome/browser/browser.scons index 64d190f..bb765f6 100644 --- a/chrome/browser/browser.scons +++ b/chrome/browser/browser.scons @@ -648,6 +648,10 @@ input_files = ChromeFileList([ 'plugin_installer.h', 'toolbar_model.cc', 'toolbar_model.h', + 'worker_host/worker_process_host.cc', + 'worker_host/worker_process_host.h', + 'worker_host/worker_service.cc', + 'worker_host/worker_service.h', ]) if not env.Bit('windows'): diff --git a/chrome/browser/browser.vcproj b/chrome/browser/browser.vcproj index 2b032b6..9c63f9c 100644 --- a/chrome/browser/browser.vcproj +++ b/chrome/browser/browser.vcproj @@ -2386,6 +2386,26 @@ > </File> </Filter> + <Filter + Name="Worker Host" + > + <File + RelativePath=".\worker_host\worker_process_host.cc" + > + </File> + <File + RelativePath=".\worker_host\worker_process_host.h" + > + </File> + <File + RelativePath=".\worker_host\worker_service.cc" + > + </File> + <File + RelativePath=".\worker_host\worker_service.h" + > + </File> + </Filter> <File RelativePath=".\browser_trial.cc" > diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc index bf6c8b9..edec4d7 100644 --- a/chrome/browser/renderer_host/resource_message_filter.cc +++ b/chrome/browser/renderer_host/resource_message_filter.cc @@ -22,6 +22,7 @@ #include "chrome/browser/renderer_host/browser_render_process_host.h" #include "chrome/browser/renderer_host/render_widget_helper.h" #include "chrome/browser/spellchecker.h" +#include "chrome/browser/worker_host/worker_service.h" #include "chrome/common/chrome_plugin_lib.h" #include "chrome/common/chrome_plugin_util.h" #include "chrome/common/notification_service.h" @@ -123,6 +124,8 @@ ResourceMessageFilter::ResourceMessageFilter( } ResourceMessageFilter::~ResourceMessageFilter() { + WorkerService::GetInstance()->RendererShutdown(this); + if (render_handle_) base::CloseProcessHandle(render_handle_); @@ -201,6 +204,10 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& message) { OnReceiveContextMenuMsg(message)) IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_OpenChannelToPlugin, OnOpenChannelToPlugin) + IPC_MESSAGE_HANDLER(ViewHostMsg_CreateDedicatedWorker, + OnCreateDedicatedWorker) + IPC_MESSAGE_HANDLER(ViewHostMsg_ForwardToWorker, + OnForwardToWorker) IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_SpellCheck, OnSpellCheck) IPC_MESSAGE_HANDLER(ViewHostMsg_DnsPrefetch, OnDnsPrefetch) IPC_MESSAGE_HANDLER(ViewHostMsg_RendererHistograms, @@ -492,6 +499,16 @@ void ResourceMessageFilter::OnOpenChannelToPlugin(const GURL& url, locale, reply_msg); } +void ResourceMessageFilter::OnCreateDedicatedWorker(const GURL& url, + int* route_id) { + *route_id = render_widget_helper_->GetNextRoutingID(); + WorkerService::GetInstance()->CreateDedicatedWorker(url, this, *route_id); +} + +void ResourceMessageFilter::OnForwardToWorker(const IPC::Message& message) { + WorkerService::GetInstance()->ForwardMessage(message); +} + void ResourceMessageFilter::OnDownloadUrl(const IPC::Message& message, const GURL& url, const GURL& referrer) { diff --git a/chrome/browser/renderer_host/resource_message_filter.h b/chrome/browser/renderer_host/resource_message_filter.h index 537c937..b131488 100644 --- a/chrome/browser/renderer_host/resource_message_filter.h +++ b/chrome/browser/renderer_host/resource_message_filter.h @@ -143,6 +143,8 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter, const std::string& clsid, const std::wstring& locale, IPC::Message* reply_msg); + void OnCreateDedicatedWorker(const GURL& url, int* route_id); + void OnForwardToWorker(const IPC::Message& msg); void OnDownloadUrl(const IPC::Message& message, const GURL& url, const GURL& referrer); diff --git a/chrome/browser/worker_host/worker_process_host.cc b/chrome/browser/worker_host/worker_process_host.cc new file mode 100644 index 0000000..3b713fd --- /dev/null +++ b/chrome/browser/worker_host/worker_process_host.cc @@ -0,0 +1,99 @@ +// Copyright (c) 2009 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 "chrome/browser/worker_host/worker_process_host.h" + +#include "base/command_line.h" +#include "base/debug_util.h" +#include "base/logging.h" +#include "base/path_service.h" +#include "base/process_util.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/renderer_host/resource_message_filter.h" +#include "chrome/browser/worker_host/worker_service.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/debug_flags.h" +#include "chrome/common/process_watcher.h" +#include "chrome/common/render_messages.h" +#include "chrome/common/worker_messages.h" + + +WorkerProcessHost::WorkerProcessHost(MessageLoop* main_message_loop) + : ChildProcessHost(WORKER_PROCESS, main_message_loop) { +} + +WorkerProcessHost::~WorkerProcessHost() { +} + +bool WorkerProcessHost::Init() { + // TODO(jabdelmalek): figure out what to set as the title. + set_name(L"TBD"); + + if (!CreateChannel()) + return false; + + std::wstring exe_path; + if (!PathService::Get(base::FILE_EXE, &exe_path)) + return false; + + CommandLine cmd_line(exe_path); + + // TODO(jabdelmalek): factor out common code from renderer/plugin that does + // sandboxing and command line copying and reuse here. + cmd_line.AppendSwitchWithValue(switches::kProcessType, + switches::kWorkerProcess); + cmd_line.AppendSwitchWithValue(switches::kProcessChannelID, channel_id()); + base::ProcessHandle handle; + if (!base::LaunchApp(cmd_line, false, false, &handle)) + return false; + SetHandle(handle); + + return true; +} + +void WorkerProcessHost::CreateWorker(const GURL& url, + int worker_route_id, + int renderer_route_id, + ResourceMessageFilter* filter) { + WorkerInstance instance; + instance.worker_route_id = worker_route_id; + instance.renderer_route_id = renderer_route_id; + instance.filter = filter; + instances_.push_back(instance); + Send(new WorkerProcessMsg_CreateWorker(url, worker_route_id)); +} + +bool WorkerProcessHost::FilterMessage(const IPC::Message& message) { + for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) { + if (i->renderer_route_id == message.routing_id()) { + IPC::Message* new_message = new IPC::Message(message); + new_message->set_routing_id(i->worker_route_id); + Send(new_message); + return true; + } + } + + return false; +} + +void WorkerProcessHost::OnMessageReceived(const IPC::Message& message) { + for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) { + if (i->worker_route_id == message.routing_id()) { + IPC::Message* new_message = new IPC::Message(message); + new_message->set_routing_id(i->renderer_route_id); + i->filter->Send(new_message); + break; + } + } +} + +void WorkerProcessHost::RendererShutdown(ResourceMessageFilter* filter) { + for (Instances::iterator i = instances_.begin(); i != instances_.end();) { + if (i->filter == filter) { + i = instances_.erase(i); + } else { + ++i; + } + } +} diff --git a/chrome/browser/worker_host/worker_process_host.h b/chrome/browser/worker_host/worker_process_host.h new file mode 100644 index 0000000..40da66f --- /dev/null +++ b/chrome/browser/worker_host/worker_process_host.h @@ -0,0 +1,56 @@ +// Copyright (c) 2009 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 CHROME_BROWSER_WORKER_HOST_WORKER_PROCESS_HOST_H_ +#define CHROME_BROWSER_WORKER_HOST_WORKER_PROCESS_HOST_H_ + +#include <list> + +#include "base/basictypes.h" +#include "base/scoped_ptr.h" +#include "chrome/common/child_process_host.h" +#include "chrome/common/ipc_channel.h" +#include "googleurl/src/gurl.h" + +class ResourceMessageFilter; + +class WorkerProcessHost : public ChildProcessHost { + public: + WorkerProcessHost(MessageLoop* main_message_loop); + ~WorkerProcessHost(); + + // Starts the process. Returns true iff it succeeded. + bool Init(); + + // Creates a worker object in the process. + void CreateWorker(const GURL& url, + int worker_route_id, + int renderer_route_id, + ResourceMessageFilter* filter); + + // Returns true iff the given message from a renderer process was forwarded to + // the worker. + bool FilterMessage(const IPC::Message& message); + + void RendererShutdown(ResourceMessageFilter* filter); + + private: + // Called when a message arrives from the worker process. + void OnMessageReceived(const IPC::Message& message); + + // Contains information about each worker instance, needed to forward messages + // between the renderer and worker processes. + struct WorkerInstance { + int worker_route_id; + int renderer_route_id; + ResourceMessageFilter* filter; + }; + + typedef std::list<WorkerInstance> Instances; + Instances instances_; + + DISALLOW_COPY_AND_ASSIGN(WorkerProcessHost); +}; + +#endif // CHROME_BROWSER_WORKER_HOST_WORKER_PROCESS_HOST_H_ diff --git a/chrome/browser/worker_host/worker_service.cc b/chrome/browser/worker_host/worker_service.cc new file mode 100644 index 0000000..cdbf69c --- /dev/null +++ b/chrome/browser/worker_host/worker_service.cc @@ -0,0 +1,73 @@ +// Copyright (c) 2009 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 "chrome/browser/worker_host/worker_service.h" + +#include "base/singleton.h" +#include "base/thread.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/plugin_service.h" +#include "chrome/browser/worker_host/worker_process_host.h" +#include "chrome/browser/renderer_host/render_process_host.h" +#include "chrome/browser/renderer_host/resource_message_filter.h" + +WorkerService* WorkerService::GetInstance() { + return Singleton<WorkerService>::get(); +} + +WorkerService::WorkerService() : next_worker_route_id_(0) { +} + +WorkerService::~WorkerService() { +} + +bool WorkerService::CreateDedicatedWorker(const GURL &url, + ResourceMessageFilter* filter, + int renderer_route_id) { + WorkerProcessHost* worker = NULL; + // One worker process for quick bringup! + for (ChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); + !iter.Done(); ++iter) { + worker = static_cast<WorkerProcessHost*>(*iter); + break; + } + + if (!worker) { + // TODO(jabdelmalek): there has to be a better way to get the main message + // loop than to go through PluginService. + worker = new WorkerProcessHost( + PluginService::GetInstance()->main_message_loop()); + if (!worker->Init()) { + delete worker; + return false; + } + } + + // Generate a unique route id for the browser-worker communication that's + // unique among all worker processes. That way when the worker process sends + // a wrapped IPC message through us, we know which WorkerProcessHost to give + // it to. + worker->CreateWorker(url, ++next_worker_route_id_, renderer_route_id, filter); + + return true; +} + +void WorkerService::ForwardMessage(const IPC::Message& message) { + for (ChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); + !iter.Done(); ++iter) { + WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); + if (worker->FilterMessage(message)) + return; + } + + // TODO(jabdelmalek): tell sender that callee is gone +} + +void WorkerService::RendererShutdown(ResourceMessageFilter* filter) { + for (ChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); + !iter.Done(); ++iter) { + WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); + worker->RendererShutdown(filter); + } +} diff --git a/chrome/browser/worker_host/worker_service.h b/chrome/browser/worker_host/worker_service.h new file mode 100644 index 0000000..7f7b282 --- /dev/null +++ b/chrome/browser/worker_host/worker_service.h @@ -0,0 +1,52 @@ +// Copyright (c) 2009 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 CHROME_BROWSER_WORKER_HOST__WORKER_SERVICE_H_ +#define CHROME_BROWSER_WORKER_HOST__WORKER_SERVICE_H_ + +#include <list> + +#include "base/basictypes.h" +#include "base/hash_tables.h" +#include "base/singleton.h" +#include "googleurl/src/gurl.h" + +namespace IPC { +class Message; +} + +class MessageLoop; +class WorkerProcessHost; +class ResourceMessageFilter; + +class WorkerService { + public: + // Returns the WorkerService singleton. + static WorkerService* GetInstance(); + + // Creates a dedicated worker. Returns true on success. + bool CreateDedicatedWorker(const GURL &url, + ResourceMessageFilter* filter, + int renderer_route_id); + + // Called by ResourceMessageFilter when a message from the renderer comes that + // should be forwarded to the worker process. + void ForwardMessage(const IPC::Message& message); + + // Called by ResourceMessageFilter when it's destructed so that all the + // WorkerProcessHost objects can remove their pointers to it. + void RendererShutdown(ResourceMessageFilter* filter); + + private: + friend struct DefaultSingletonTraits<WorkerService>; + + WorkerService(); + ~WorkerService(); + + int next_worker_route_id_; + + DISALLOW_COPY_AND_ASSIGN(WorkerService); +}; + +#endif // CHROME_BROWSER_WORKER_HOST__WORKER_SERVICE_H_ |