diff options
Diffstat (limited to 'chrome')
39 files changed, 1322 insertions, 63 deletions
diff --git a/chrome/SConscript b/chrome/SConscript index 28d8de1..d6a3e78 100644 --- a/chrome/SConscript +++ b/chrome/SConscript @@ -142,6 +142,7 @@ if env.Bit('windows'): env_dll.Append( LIBS = [ 'plugin', + 'worker', ] ) @@ -293,6 +294,7 @@ p = env.ChromeMSVSProject('app/chrome_dll.vcproj', '$BASE_DIR/build/base.vcproj', '$WEBKIT_DIR/build/WebCore/WebCore.vcproj', '$CHROME_DIR/plugin/plugin.vcproj', + '$CHROME_DIR/worker/worker.vcproj', '$LIBJPEG_DIR/libjpeg.vcproj', '$BZIP2_DIR/bzip2.vcproj', '$NET_DIR/build/net.vcproj', diff --git a/chrome/app/chrome_dll_main.cc b/chrome/app/chrome_dll_main.cc index 6f77924..1e3e428 100644 --- a/chrome/app/chrome_dll_main.cc +++ b/chrome/app/chrome_dll_main.cc @@ -55,6 +55,7 @@ extern int BrowserMain(const MainFunctionParams&); extern int RendererMain(const MainFunctionParams&); extern int PluginMain(const MainFunctionParams&); +extern int WorkerMain(const MainFunctionParams&); #if defined(OS_WIN) // TODO(erikkay): isn't this already defined somewhere? @@ -370,6 +371,10 @@ int ChromeMain(int argc, const char** argv) { #if defined(OS_WIN) rv = PluginMain(main_params); #endif + } else if (process_type == switches::kWorkerProcess) { +#if defined(OS_WIN) + rv = WorkerMain(main_params); +#endif } else if (process_type.empty()) { ScopedOleInitializer ole_initializer; rv = BrowserMain(main_params); 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_ diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index fbf1155..c361074 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -955,6 +955,10 @@ 'browser/views/toolbar_view.h', 'browser/views/user_data_dir_dialog.cc', 'browser/views/user_data_dir_dialog.h', + 'browser/worker_host/worker_process_host.cc', + 'browser/worker_host/worker_process_host.h', + 'browser/worker_host/worker_service.cc', + 'browser/worker_host/worker_service.h', 'browser/webdata/web_data_service.cc', 'browser/webdata/web_data_service.h', 'browser/webdata/web_data_service_win.cc', diff --git a/chrome/chrome.sln b/chrome/chrome.sln index d9678c6..099f905 100644 --- a/chrome/chrome.sln +++ b/chrome/chrome.sln @@ -165,6 +165,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "chrome_dll", "app\chrome_dl {C0334F9A-1168-4101-9DD8-C30FB252D435} = {C0334F9A-1168-4101-9DD8-C30FB252D435} {C564F145-9172-42C3-BFCB-6014CA97DBCD} = {C564F145-9172-42C3-BFCB-6014CA97DBCD} {C66B126D-0ECE-4CA2-B6DC-FA780AFBBF09} = {C66B126D-0ECE-4CA2-B6DC-FA780AFBBF09} + {C78D02D0-A366-4EC6-A248-AA8E64C4BA18} = {C78D02D0-A366-4EC6-A248-AA8E64C4BA18} {CD9CA56E-4E94-444C-87D4-58CA1E6F300D} = {CD9CA56E-4E94-444C-87D4-58CA1E6F300D} {D5E8DCB2-9C61-446F-8BEE-B18CA0E0936E} = {D5E8DCB2-9C61-446F-8BEE-B18CA0E0936E} {D703D7A0-EDC1-4FE6-9E22-56154155B24E} = {D703D7A0-EDC1-4FE6-9E22-56154155B24E} @@ -1346,6 +1347,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WebKit", "..\webkit\build\W {2F7EDFA2-EE27-4D83-8454-9EFBD5779203} = {2F7EDFA2-EE27-4D83-8454-9EFBD5779203} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "worker", "worker\worker.vcproj", "{C78D02D0-A366-4EC6-A248-AA8E64C4BA18}" + ProjectSection(WebsiteProperties) = preProject + Debug.AspNetCompiler.Debug = "True" + Release.AspNetCompiler.Debug = "False" + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Mixed Platforms = Debug|Mixed Platforms @@ -2328,6 +2335,14 @@ Global {C70D3509-57C4-4326-90C1-2EC0AE34848D}.Release|Mixed Platforms.Build.0 = Release|Win32 {C70D3509-57C4-4326-90C1-2EC0AE34848D}.Release|Win32.ActiveCfg = Release|Win32 {C70D3509-57C4-4326-90C1-2EC0AE34848D}.Release|Win32.Build.0 = Release|Win32 + {C78D02D0-A366-4EC6-A248-AA8E64C4BA18}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {C78D02D0-A366-4EC6-A248-AA8E64C4BA18}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {C78D02D0-A366-4EC6-A248-AA8E64C4BA18}.Debug|Win32.ActiveCfg = Debug|Win32 + {C78D02D0-A366-4EC6-A248-AA8E64C4BA18}.Debug|Win32.Build.0 = Debug|Win32 + {C78D02D0-A366-4EC6-A248-AA8E64C4BA18}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {C78D02D0-A366-4EC6-A248-AA8E64C4BA18}.Release|Mixed Platforms.Build.0 = Release|Win32 + {C78D02D0-A366-4EC6-A248-AA8E64C4BA18}.Release|Win32.ActiveCfg = Release|Win32 + {C78D02D0-A366-4EC6-A248-AA8E64C4BA18}.Release|Win32.Build.0 = Release|Win32 {C8C6183C-B03C-11DD-B471-DFD256D89593}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {C8C6183C-B03C-11DD-B471-DFD256D89593}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {C8C6183C-B03C-11DD-B471-DFD256D89593}.Debug|Win32.ActiveCfg = Debug|Win32 @@ -2758,6 +2773,7 @@ Global {C564F145-9172-42C3-BFCB-6014CA97DBCD} = {EF78C1F9-AA17-4CA5-B6CB-39B37A73A3DA} {C66B126D-0ECE-4CA2-B6DC-FA780AFBBF09} = {CB43561E-A6F8-49E2-96A2-3F2BA1FFF21E} {C70D3509-57C4-4326-90C1-2EC0AE34848D} = {2325D8C4-8EF5-42AC-8900-492225750DE4} + {C78D02D0-A366-4EC6-A248-AA8E64C4BA18} = {97555540-8163-4D0F-BCAC-EFA0FFED3453} {C8C6183C-B03C-11DD-B471-DFD256D89593} = {1174D37F-6ABB-45DA-81B3-C631281273B7} {C9E0BD1D-B175-4A91-8380-3FDC81FAB9D7} = {1174D37F-6ABB-45DA-81B3-C631281273B7} {CAB69303-0F02-4C68-A12E-FFE55DB52526} = {2325D8C4-8EF5-42AC-8900-492225750DE4} diff --git a/chrome/common/child_process_host.cc b/chrome/common/child_process_host.cc index 66d3ebf..15d8daa 100644 --- a/chrome/common/child_process_host.cc +++ b/chrome/common/child_process_host.cc @@ -154,18 +154,20 @@ void ChildProcessHost::ListenerHook::OnChannelError() { ChildProcessHost::Iterator::Iterator() : all_(true) { - iterator_ = Singleton<ChildProcessList>::get()->begin(); DCHECK(MessageLoop::current() == ChromeThread::GetMessageLoop(ChromeThread::IO)) << "ChildProcessInfo::Iterator must be used on the IO thread."; + iterator_ = Singleton<ChildProcessList>::get()->begin(); } ChildProcessHost::Iterator::Iterator(ProcessType type) : all_(false), type_(type) { - iterator_ = Singleton<ChildProcessList>::get()->begin(); DCHECK(MessageLoop::current() == ChromeThread::GetMessageLoop(ChromeThread::IO)) << "ChildProcessInfo::Iterator must be used on the IO thread."; + iterator_ = Singleton<ChildProcessList>::get()->begin(); + if (!Done() && (*iterator_)->type() != type_) + iterator_++; } ChildProcessInfo* ChildProcessHost::Iterator::operator++() { diff --git a/chrome/common/child_thread.cc b/chrome/common/child_thread.cc index bad15a6..ff73a7f 100644 --- a/chrome/common/child_thread.cc +++ b/chrome/common/child_thread.cc @@ -11,6 +11,9 @@ #include "chrome/common/ipc_logging.h" #include "webkit/glue/webkit_glue.h" +// V8 needs a 1MB stack size. +const size_t ChildThread::kV8StackSize = 1024 * 1024; + ChildThread::ChildThread(Thread::Options options) : Thread("Chrome_ChildThread"), owner_loop_(MessageLoop::current()), diff --git a/chrome/common/child_thread.h b/chrome/common/child_thread.h index 5b13ab7..f97964c 100644 --- a/chrome/common/child_thread.h +++ b/chrome/common/child_thread.h @@ -37,6 +37,9 @@ class ChildThread : public IPC::Channel::Listener, void SetChannelName(const std::wstring& name) { channel_name_ = name; } protected: + // The required stack size if V8 runs on a thread. + static const size_t kV8StackSize; + virtual void OnControlMessageReceived(const IPC::Message& msg) { } // Returns the one child thread. diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index 53c7910..cf47946 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc @@ -74,9 +74,12 @@ const wchar_t kRendererProcess[] = L"renderer"; // Path to the exe to run for the renderer subprocess const wchar_t kRendererPath[] = L"renderer-path"; -// Causes the process to run as plugin host +// Causes the process to run as a plugin subprocess. const wchar_t kPluginProcess[] = L"plugin"; +// Causes the process to run as a worker subprocess. +const wchar_t kWorkerProcess[] = L"worker"; + // Runs the renderer and plugins in the same process as the browser const wchar_t kSingleProcess[] = L"single-process"; diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index 93841cd..578fc71 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h @@ -30,6 +30,7 @@ extern const wchar_t kBrowserStartRenderersManually[]; extern const wchar_t kRendererProcess[]; extern const wchar_t kRendererPath[]; extern const wchar_t kPluginProcess[]; +extern const wchar_t kWorkerProcess[]; extern const wchar_t kSingleProcess[]; extern const wchar_t kProcessPerTab[]; extern const wchar_t kProcessPerSite[]; diff --git a/chrome/common/common.scons b/chrome/common/common.scons index 86b43a9..7ebad2e 100644 --- a/chrome/common/common.scons +++ b/chrome/common/common.scons @@ -101,6 +101,8 @@ input_files = ChromeFileList([ 'plugin_messages_internal.h', 'render_messages.h', 'render_messages_internal.h', + 'worker_messages.h', + 'worker_messages_internal.h', ]), 'accessibility.h', 'animation.cc', diff --git a/chrome/common/common.vcproj b/chrome/common/common.vcproj index d91438c..e409d1d 100644 --- a/chrome/common/common.vcproj +++ b/chrome/common/common.vcproj @@ -300,6 +300,14 @@ RelativePath=".\render_messages_internal.h" > </File> + <File + RelativePath=".\worker_messages.h" + > + </File> + <File + RelativePath=".\worker_messages_internal.h" + > + </File> </Filter> <Filter Name="extensions" diff --git a/chrome/common/ipc_message_utils.h b/chrome/common/ipc_message_utils.h index 8f813f6..61243f5 100644 --- a/chrome/common/ipc_message_utils.h +++ b/chrome/common/ipc_message_utils.h @@ -11,6 +11,7 @@ #include "base/file_path.h" #include "base/string_util.h" +#include "base/string16.h" #include "base/tuple.h" #if defined(OS_POSIX) #include "chrome/common/file_descriptor_set_posix.h" @@ -56,6 +57,10 @@ enum IPCMessageStart { TestMsgStart, DevToolsAgentMsgStart, DevToolsClientMsgStart, + WorkerProcessMsgStart, + WorkerProcessHostMsgStart, + WorkerMsgStart, + WorkerHostMsgStart, // NOTE: When you add a new message class, also update // IPCStatusView::IPCStatusView to ensure logging works. // NOTE: this enum is used by IPC_MESSAGE_MACRO to generate a unique message @@ -492,6 +497,7 @@ struct ParamTraits<std::map<K, V> > { } }; + template <> struct ParamTraits<std::wstring> { typedef std::wstring param_type; @@ -506,6 +512,34 @@ struct ParamTraits<std::wstring> { } }; + +// If WCHAR_T_IS_UTF16 is defined, then string16 is a std::wstring so we don't +// need this trait. +#if !defined(WCHAR_T_IS_UTF16) + +template <> +struct ParamTraits<string16> { + typedef string16 param_type; + static void Write(Message* m, const param_type& p) { + m->WriteData(reinterpret_cast<const char*>(p.data()), + static_cast<int>(p.size() * sizeof(char16))); + } + static bool Read(const Message* m, void** iter, param_type* r) { + const char *data; + int data_size = 0; + if (!m->ReadData(iter, &data, &data_size)) + return false; + r->assign(reinterpret_cast<const char16*>(data), + data_size / sizeof(char16)); + return true; + } + static void Log(const param_type& p, std::wstring* l) { + l->append(UTF16ToWide(p)); + } +}; + +#endif + template <> struct ParamTraits<GURL> { typedef GURL param_type; @@ -893,6 +927,66 @@ struct ParamTraits<LogData> { } }; + +template <> +struct ParamTraits<webkit_glue::WebApplicationInfo> { + typedef webkit_glue::WebApplicationInfo param_type; + static void Write(Message* m, const param_type& p); + static bool Read(const Message* m, void** iter, param_type* r); + static void Log(const param_type& p, std::wstring* l); +}; + + +#if defined(OS_WIN) +template<> +struct ParamTraits<TransportDIB::Id> { + typedef TransportDIB::Id param_type; + static void Write(Message* m, const param_type& p) { + WriteParam(m, p.handle); + WriteParam(m, p.sequence_num); + } + static bool Read(const Message* m, void** iter, param_type* r) { + return (ReadParam(m, iter, &r->handle) && + ReadParam(m, iter, &r->sequence_num)); + } + static void Log(const param_type& p, std::wstring* l) { + l->append(L"TransportDIB("); + LogParam(p.handle, l); + l->append(L", "); + LogParam(p.sequence_num, l); + l->append(L")"); + } +}; +#endif + +template<typename A> +struct ParamTraits<Maybe<A> > { + typedef struct Maybe<A> param_type; + static void Write(Message* m, const param_type& p) { + WriteParam(m, p.valid); + if (p.valid) + WriteParam(m, p.value); + } + static bool Read(const Message* m, void** iter, param_type* r) { + if (!ReadParam(m, iter, &r->valid)) + return false; + + if (r->valid) + return ReadParam(m, iter, &r->value); + return true; + } + static void Log(const param_type& p, std::wstring* l) { + if (p.valid) { + l->append(L"Just "); + ParamTraits<A>::Log(p.value, l); + } else { + l->append(L"Nothing"); + } + + } +}; + + template <> struct ParamTraits<Message> { static void Write(Message* m, const Message& p) { @@ -914,6 +1008,7 @@ struct ParamTraits<Message> { } }; + template <> struct ParamTraits<Tuple0> { typedef Tuple0 param_type; @@ -1070,62 +1165,6 @@ struct ParamTraits< Tuple6<A, B, C, D, E, F> > { } }; -#if defined(OS_WIN) -template<> -struct ParamTraits<TransportDIB::Id> { - typedef TransportDIB::Id param_type; - static void Write(Message* m, const param_type& p) { - WriteParam(m, p.handle); - WriteParam(m, p.sequence_num); - } - static bool Read(const Message* m, void** iter, param_type* r) { - return (ReadParam(m, iter, &r->handle) && - ReadParam(m, iter, &r->sequence_num)); - } - static void Log(const param_type& p, std::wstring* l) { - l->append(L"TransportDIB("); - LogParam(p.handle, l); - l->append(L", "); - LogParam(p.sequence_num, l); - l->append(L")"); - } -}; -#endif - -template<typename A> -struct ParamTraits<Maybe<A> > { - typedef struct Maybe<A> param_type; - static void Write(Message* m, const param_type& p) { - WriteParam(m, p.valid); - if (p.valid) - WriteParam(m, p.value); - } - static bool Read(const Message* m, void** iter, param_type* r) { - if (!ReadParam(m, iter, &r->valid)) - return false; - - if (r->valid) - return ReadParam(m, iter, &r->value); - return true; - } - static void Log(const param_type& p, std::wstring* l) { - if (p.valid) { - l->append(L"Just "); - ParamTraits<A>::Log(p.value, l); - } else { - l->append(L"Nothing"); - } - - } -}; - -template <> -struct ParamTraits<webkit_glue::WebApplicationInfo> { - typedef webkit_glue::WebApplicationInfo param_type; - static void Write(Message* m, const param_type& p); - static bool Read(const Message* m, void** iter, param_type* r); - static void Log(const param_type& p, std::wstring* l); -}; //----------------------------------------------------------------------------- diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index 41b18a6..af42627 100644 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -1196,4 +1196,16 @@ IPC_BEGIN_MESSAGES(ViewHost) TransportDIB::Id /* DIB id */) #endif + // A renderer sends this to the browser process when it wants to create a + // worker. The browser will create the worker process if necessary, and + // will return the route id on success. On error returns MSG_ROUTING_NONE. + IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_CreateDedicatedWorker, + GURL /* url */, + int /* route_id */) + + // Wraps an IPC message that's destined to the worker on the renderer->browser + // hop. + IPC_MESSAGE_CONTROL1(ViewHostMsg_ForwardToWorker, + IPC::Message /* message */) + IPC_END_MESSAGES(ViewHost) diff --git a/chrome/common/worker_messages.h b/chrome/common/worker_messages.h new file mode 100644 index 0000000..e1f64a5 --- /dev/null +++ b/chrome/common/worker_messages.h @@ -0,0 +1,21 @@ +// 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. + +// Defines messages between the browser and worker process, as well as between +// the renderer and worker process. + +#ifndef CHROME_COMMON_WORKER_MESSAGES_H_ +#define CHROME_COMMON_WORKER_MESSAGES_H_ + +#include <string> + +#include "base/basictypes.h" +#include "chrome/common/ipc_message_utils.h" + + +#define MESSAGES_INTERNAL_FILE "chrome/common/worker_messages_internal.h" +#include "chrome/common/ipc_message_macros.h" + +#endif // CHROME_COMMON_WORKER_MESSAGES_H_ + diff --git a/chrome/common/worker_messages_internal.h b/chrome/common/worker_messages_internal.h new file mode 100644 index 0000000..7691c79 --- /dev/null +++ b/chrome/common/worker_messages_internal.h @@ -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 "base/string16.h" +#include "chrome/common/ipc_message_macros.h" +#include "googleurl/src/gurl.h" + + +//----------------------------------------------------------------------------- +// WorkerProcess messages +// These are messages sent from the browser to the worker process. +IPC_BEGIN_MESSAGES(WorkerProcess) + IPC_MESSAGE_CONTROL2(WorkerProcessMsg_CreateWorker, + GURL /* url */, + int /* route_id */) +IPC_END_MESSAGES(WorkerProcess) + + +//----------------------------------------------------------------------------- +// WorkerProcessHost messages +// These are messages sent from the worker process to the browser process. + +// No messages being sent in this direction for now. +//IPC_BEGIN_MESSAGES(WorkerProcessHost) +//IPC_END_MESSAGES(WorkerProcessHost) + +//----------------------------------------------------------------------------- +// Worker messages +// These are messages sent from the renderer process to the worker process. +IPC_BEGIN_MESSAGES(Worker) + IPC_MESSAGE_ROUTED3(WorkerMsg_StartWorkerContext, + GURL /* url */, + string16 /* user_agent */, + string16 /* source_code */) + + IPC_MESSAGE_ROUTED0(WorkerMsg_TerminateWorkerContext) + + IPC_MESSAGE_ROUTED1(WorkerMsg_PostMessageToWorkerContext, + string16 /* message */) + + IPC_MESSAGE_ROUTED0(WorkerMsg_WorkerObjectDestroyed) +IPC_END_MESSAGES(Worker) + + +//----------------------------------------------------------------------------- +// WorkerHost messages +// These are messages sent from the worker process to the renderer process. +IPC_BEGIN_MESSAGES(WorkerHost) + IPC_MESSAGE_ROUTED1(WorkerHostMsg_PostMessageToWorkerObject, + string16 /* message */) + + IPC_MESSAGE_ROUTED3(WorkerHostMsg_PostExceptionToWorkerObject, + string16 /* error_message */, + int /* line_number */, + string16 /* source_url*/) + + IPC_MESSAGE_ROUTED6(WorkerHostMsg_PostConsoleMessageToWorkerObject, + int /* destination */, + int /* source */, + int /* level */, + string16 /* message */, + int /* line_number */, + string16 /* source_url */) + + IPC_MESSAGE_ROUTED1(WorkerHostMsg_ConfirmMessageFromWorkerObject, + bool /* bool has_pending_activity */) + + IPC_MESSAGE_ROUTED1(WorkerHostMsg_ReportPendingActivity, + bool /* bool has_pending_activity */) + + IPC_MESSAGE_ROUTED0(WorkerHostMsg_WorkerContextDestroyed) +IPC_END_MESSAGES(WorkerHost) diff --git a/chrome/renderer/render_thread.cc b/chrome/renderer/render_thread.cc index 1870c00..f244092 100644 --- a/chrome/renderer/render_thread.cc +++ b/chrome/renderer/render_thread.cc @@ -40,8 +40,6 @@ static const unsigned int kCacheStatsDelayMS = 2000 /* milliseconds */; -// V8 needs a 1MB stack size. -static const size_t kStackSize = 1024 * 1024; //----------------------------------------------------------------------------- // Methods below are only called on the owner's thread: @@ -51,13 +49,13 @@ static const size_t kStackSize = 1024 * 1024; RenderThread::RenderThread() : ChildThread( base::Thread::Options(RenderProcess::InProcessPlugins() ? - MessageLoop::TYPE_UI : MessageLoop::TYPE_DEFAULT, kStackSize)) { + MessageLoop::TYPE_UI : MessageLoop::TYPE_DEFAULT, kV8StackSize)) { } RenderThread::RenderThread(const std::wstring& channel_name) : ChildThread( base::Thread::Options(RenderProcess::InProcessPlugins() ? - MessageLoop::TYPE_UI : MessageLoop::TYPE_DEFAULT, kStackSize)) { + MessageLoop::TYPE_UI : MessageLoop::TYPE_DEFAULT, kV8StackSize)) { SetChannelName(channel_name); } diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index 59ba2c9..461f99c 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -36,6 +36,7 @@ #include "chrome/renderer/visitedlink_slave.h" #include "chrome/renderer/webmediaplayer_delegate_impl.h" #include "chrome/renderer/webplugin_delegate_proxy.h" +#include "chrome/renderer/webworker_proxy.h" #include "grit/generated_resources.h" #include "grit/renderer_resources.h" #include "net/base/escape.h" @@ -1973,6 +1974,16 @@ void RenderView::OnMissingPluginStatus(WebPluginDelegate* delegate, #endif } +WebWorker* RenderView::CreateWebWorker(WebWorkerClient* client) { +#if defined(OS_WIN) + return new WebWorkerProxy(this, client); +#else + // TODO(port): out of process workers + NOTIMPLEMENTED(); + return NULL; +#endif +} + void RenderView::OpenURL(WebView* webview, const GURL& url, const GURL& referrer, WindowOpenDisposition disposition) { diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index 3ce6c3c..1c0078c 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -239,6 +239,7 @@ class RenderView : public RenderWidget, const std::string& mime_type, const std::string& clsid, std::string* actual_mime_type); + virtual WebWorker* CreateWebWorker(WebWorkerClient* client); virtual webkit_glue::WebMediaPlayerDelegate* CreateMediaPlayerDelegate(); virtual void OnMissingPluginStatus(WebPluginDelegate* delegate, int status); virtual void OpenURL(WebView* webview, const GURL& url, diff --git a/chrome/renderer/renderer.scons b/chrome/renderer/renderer.scons index e8dfddd..62b6d57 100644 --- a/chrome/renderer/renderer.scons +++ b/chrome/renderer/renderer.scons @@ -108,6 +108,8 @@ input_files = ChromeFileList([ 'webmediaplayer_delegate_impl.h', 'webplugin_delegate_proxy.cc', 'webplugin_delegate_proxy.h', + 'webworker_proxy.cc', + 'webworker_proxy.h', ]) if not env.Bit('windows'): diff --git a/chrome/renderer/renderer.vcproj b/chrome/renderer/renderer.vcproj index 908f55d..a566716f 100644 --- a/chrome/renderer/renderer.vcproj +++ b/chrome/renderer/renderer.vcproj @@ -393,6 +393,14 @@ RelativePath=".\webplugin_delegate_proxy.h" > </File> + <File + RelativePath=".\webworker_proxy.cc" + > + </File> + <File + RelativePath=".\webworker_proxy.h" + > + </File> </Files> <Globals> </Globals> diff --git a/chrome/renderer/webworker_proxy.cc b/chrome/renderer/webworker_proxy.cc new file mode 100644 index 0000000..c271e40 --- /dev/null +++ b/chrome/renderer/webworker_proxy.cc @@ -0,0 +1,92 @@ +// 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/renderer/webworker_proxy.h" + +#include "chrome/common/render_messages.h" +#include "chrome/common/worker_messages.h" +#include "chrome/renderer/render_thread.h" +#include "webkit/glue/webworkerclient.h" + +WebWorkerProxy::WebWorkerProxy( + IPC::Message::Sender* sender, WebWorkerClient* client) + : sender_(sender), + route_id_(MSG_ROUTING_NONE), + client_(client) { +} + +WebWorkerProxy::~WebWorkerProxy() { +} + +void WebWorkerProxy::StartWorkerContext( + const GURL& script_url, + const string16& user_agent, + const string16& source_code) { + sender_->Send( + new ViewHostMsg_CreateDedicatedWorker(script_url, &route_id_)); + if (route_id_ == MSG_ROUTING_NONE) + return; + + RenderThread::current()->AddRoute(route_id_, this); + Send(new WorkerMsg_StartWorkerContext( + route_id_, script_url, user_agent, source_code)); +} + +void WebWorkerProxy::TerminateWorkerContext() { + if (route_id_ != MSG_ROUTING_NONE) { + Send(new WorkerMsg_TerminateWorkerContext(route_id_)); + RenderThread::current()->RemoveRoute(route_id_); + route_id_ = MSG_ROUTING_NONE; + } +} + +void WebWorkerProxy::PostMessageToWorkerContext( + const string16& message) { + Send(new WorkerMsg_PostMessageToWorkerContext(route_id_, message)); +} + +void WebWorkerProxy::WorkerObjectDestroyed() { + client_ = NULL; + Send(new WorkerMsg_WorkerObjectDestroyed(route_id_)); +} + +bool WebWorkerProxy::Send(IPC::Message* message) { + if (route_id_ == MSG_ROUTING_NONE) { + delete message; + return false; + } + + // For now we proxy all messages to the worker process through the browser. + // Revisit if we find this slow. + // TODO(jabdelmalek): handle sync messages if we need them. + IPC::Message* wrapped_msg = new ViewHostMsg_ForwardToWorker(*message); + delete message; + return sender_->Send(wrapped_msg); +} + +void WebWorkerProxy::OnMessageReceived(const IPC::Message& message) { + if (!client_) + return; + + IPC_BEGIN_MESSAGE_MAP(WebWorkerProxy, message) + IPC_MESSAGE_FORWARD(WorkerHostMsg_PostMessageToWorkerObject, + client_, + WebWorkerClient::PostMessageToWorkerObject) + IPC_MESSAGE_FORWARD(WorkerHostMsg_PostExceptionToWorkerObject, + client_, + WebWorkerClient::PostExceptionToWorkerObject) + IPC_MESSAGE_FORWARD(WorkerHostMsg_PostConsoleMessageToWorkerObject, + client_, + WebWorkerClient::PostConsoleMessageToWorkerObject) + IPC_MESSAGE_FORWARD(WorkerHostMsg_ConfirmMessageFromWorkerObject, + client_, + WebWorkerClient::ConfirmMessageFromWorkerObject) + IPC_MESSAGE_FORWARD(WorkerHostMsg_ReportPendingActivity, + client_, + WebWorkerClient::ReportPendingActivity) + IPC_MESSAGE_FORWARD(WorkerHostMsg_WorkerContextDestroyed, + client_, + WebWorkerClient::WorkerContextDestroyed) + IPC_END_MESSAGE_MAP() +} diff --git a/chrome/renderer/webworker_proxy.h b/chrome/renderer/webworker_proxy.h new file mode 100644 index 0000000..019ff0d --- /dev/null +++ b/chrome/renderer/webworker_proxy.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_RENDERER_WEBWORKER_PROXY_H_ +#define CHROME_RENDERER_WEBWORKER_PROXY_H_ + +#include "base/basictypes.h" +#include "chrome/common/ipc_channel.h" +#include "webkit/glue/webworker.h" + +class GURL; +class RenderView; + +namespace IPC { +class Message; +} + +// This class provides an implementation of WebWorker that the renderer provides +// to the glue. This class converts function calls to IPC messages that are +// dispatched in the worker process by WebWorkerClientProxy. It also receives +// IPC messages from WebWorkerClientProxy which it converts to function calls to +// WebWorkerClient. +class WebWorkerProxy : public WebWorker, + public IPC::Channel::Listener { + public: + WebWorkerProxy(IPC::Message::Sender* sender, WebWorkerClient* client); + virtual ~WebWorkerProxy(); + + // WebWorker implementation. + // These functions are called by WebKit (after the data types have been + // converted by glue code). + virtual void StartWorkerContext(const GURL& script_url, + const string16& user_agent, + const string16& source_code); + virtual void TerminateWorkerContext(); + virtual void PostMessageToWorkerContext(const string16& message); + virtual void WorkerObjectDestroyed(); + + // IPC::Channel::Listener implementation. + void OnMessageReceived(const IPC::Message& message); + + private: + bool Send(IPC::Message* message); + + IPC::Message::Sender* sender_; + int route_id_; + + // Used to communicate to the WebCore::Worker object in response to IPC + // messages. + WebWorkerClient* client_; + + DISALLOW_COPY_AND_ASSIGN(WebWorkerProxy); +}; + +#endif // CHROME_RENDERER_WEBWORKER_PROXY_H_ diff --git a/chrome/worker/webworkerclient_proxy.cc b/chrome/worker/webworkerclient_proxy.cc new file mode 100644 index 0000000..84cb2ed --- /dev/null +++ b/chrome/worker/webworkerclient_proxy.cc @@ -0,0 +1,95 @@ +// 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/worker/webworkerclient_proxy.h" + +#include "chrome/common/ipc_logging.h" +#include "chrome/common/worker_messages.h" +#include "chrome/worker/worker_process.h" +#include "chrome/worker/worker_thread.h" +#include "webkit/glue/webworker.h" + + +WebWorkerClientProxy::WebWorkerClientProxy(const GURL& url, int route_id) + : url_(url), + route_id_(route_id), + started_worker_(false), + ALLOW_THIS_IN_INITIALIZER_LIST(impl_(WebWorker::Create(this))) { + WorkerThread::current()->AddRoute(route_id_, this); + WorkerProcess::current()->AddRefProcess(); +} + +WebWorkerClientProxy::~WebWorkerClientProxy() { + WorkerThread::current()->RemoveRoute(route_id_); + WorkerProcess::current()->ReleaseProcess(); +} + +void WebWorkerClientProxy::PostMessageToWorkerObject(const string16& message) { + Send(new WorkerHostMsg_PostMessageToWorkerObject(route_id_, message)); +} + +void WebWorkerClientProxy::PostExceptionToWorkerObject( + const string16& error_message, + int line_number, + const string16& source_url) { + Send(new WorkerHostMsg_PostExceptionToWorkerObject( + route_id_, error_message, line_number, source_url)); +} + +void WebWorkerClientProxy::PostConsoleMessageToWorkerObject( + int destination, + int source, + int level, + const string16& message, + int line_number, + const string16& source_url) { + Send(new WorkerHostMsg_PostConsoleMessageToWorkerObject( + route_id_, destination, source, level,message, line_number, source_url)); +} + +void WebWorkerClientProxy::ConfirmMessageFromWorkerObject(bool has_pending_activity) { + Send(new WorkerHostMsg_ConfirmMessageFromWorkerObject( + route_id_, has_pending_activity)); +} + +void WebWorkerClientProxy::ReportPendingActivity(bool has_pending_activity) { + Send(new WorkerHostMsg_ReportPendingActivity( + route_id_, has_pending_activity)); +} + +void WebWorkerClientProxy::WorkerContextDestroyed() { + Send(new WorkerHostMsg_WorkerContextDestroyed(route_id_)); +} + +bool WebWorkerClientProxy::Send(IPC::Message* message) { + return WorkerThread::current()->Send(message); +} + +void WebWorkerClientProxy::OnMessageReceived(const IPC::Message& message) { + if (!started_worker_ && + message.type() != WorkerMsg_StartWorkerContext::ID) { + queued_messages_.push_back(new IPC::Message(message)); + return; + } + + WebWorker* worker = impl_.get(); + IPC_BEGIN_MESSAGE_MAP(WebWorkerClientProxy, message) + IPC_MESSAGE_FORWARD(WorkerMsg_StartWorkerContext, worker, + WebWorker::StartWorkerContext) + IPC_MESSAGE_FORWARD(WorkerMsg_TerminateWorkerContext, worker, + WebWorker::TerminateWorkerContext) + IPC_MESSAGE_FORWARD(WorkerMsg_PostMessageToWorkerContext, worker, + WebWorker::PostMessageToWorkerContext) + IPC_MESSAGE_FORWARD(WorkerMsg_WorkerObjectDestroyed, worker, + WebWorker::WorkerObjectDestroyed) + IPC_END_MESSAGE_MAP() + + if (message.type() == WorkerMsg_StartWorkerContext::ID) { + started_worker_ = true; + for (size_t i = 0; i < queued_messages_.size(); ++i) + OnMessageReceived(*queued_messages_[i]); + + queued_messages_.clear(); + } +} diff --git a/chrome/worker/webworkerclient_proxy.h b/chrome/worker/webworkerclient_proxy.h new file mode 100644 index 0000000..c744023 --- /dev/null +++ b/chrome/worker/webworkerclient_proxy.h @@ -0,0 +1,68 @@ +// 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_WORKER_WEBWORKERCLIENT_PROXY_H_ +#define CHROME_WORKER_WEBWORKERCLIENT_PROXY_H_ + +#include <vector> + +#include "base/basictypes.h" +#include "base/scoped_ptr.h" +#include "chrome/common/ipc_channel.h" +#include "googleurl/src/gurl.h" +#include "webkit/glue/webworkerclient.h" + +class WebWorker; + +// This class receives IPCs from the renderer and calls the WebCore::Worker +// implementation (after the data types have been converted by glue code). It +// is also called by the worker code and converts these function calls into +// IPCs that are sent to the renderer, where they're converted back to function +// calls by WebWorkerProxy. +class WebWorkerClientProxy : public WebWorkerClient, + public IPC::Channel::Listener { + public: + WebWorkerClientProxy (const GURL& url, int route_id); + ~WebWorkerClientProxy (); + + // WebWorkerClient implementation. + void PostMessageToWorkerObject(const string16& message); + void PostExceptionToWorkerObject( + const string16& error_message, + int line_number, + const string16& source_url); + void PostConsoleMessageToWorkerObject( + int destination, + int source, + int level, + const string16& message, + int line_number, + const string16& source_url); + void ConfirmMessageFromWorkerObject(bool has_pending_activity); + void ReportPendingActivity(bool has_pending_activity); + void WorkerContextDestroyed(); + + // IPC::Channel::Listener implementation. + void OnMessageReceived(const IPC::Message& message); + + private: + bool Send(IPC::Message* message); + + // The source url for this worker. + GURL url_; + + int route_id_; + + // Whether we've received StartWorkerContext message. + bool started_worker_; + + scoped_ptr<WebWorker> impl_; + + // Stores messages that arrived before the StartWorkerContext message. + std::vector<IPC::Message*> queued_messages_; + + DISALLOW_COPY_AND_ASSIGN(WebWorkerClientProxy); +}; + +#endif // CHROME_WORKER_WEBWORKERCLIENT_PROXY_H_ diff --git a/chrome/worker/worker.scons b/chrome/worker/worker.scons new file mode 100644 index 0000000..e00c413 --- /dev/null +++ b/chrome/worker/worker.scons @@ -0,0 +1,102 @@ +# 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. + +Import('env') + +env = env.Clone() + +env.SConscript([ +# '$NPAPI_DIR/using_npapi.scons', +# '$SKIA_DIR/using_skia.scons', +], {'env':env}) + +env.Prepend( + CPPPATH = [ + '$CHROME_SRC_DIR', + ], +) + +if env.Bit('windows'): + env.Prepend( + CPPPATH = [ + '$CHROME_DIR/tools/build/win', + ], + ) + +input_files = ChromeFileList([ + 'webworkerclient_proxy.cc', + 'webworkerclient_proxy.h', + 'worker_main.cc', + 'worker_process.cc', + 'worker_process.h', + 'worker_thread.cc', + 'worker_thread.h', + '$CHROME_DIR/tools/build/win/precompiled$OBJSUFFIX', + '$CHROME_DIR/tools/build/win/precompiled.h', +]) + +if not env.Bit('windows'): + input_files.Remove( + '$CHROME_DIR/tools/build/win/precompiled$OBJSUFFIX', + ) + +if env.Bit('posix'): + # TODO(port) + input_files.Remove( + 'webworker.cc', + 'worker_main.cc', + 'worker_process.cc', + 'worker_thread.cc', + ) + +env.ChromeLibrary('worker', input_files) + +p = env.ChromeMSVSProject('worker.vcproj', + dest='$CHROME_SRC_DIR/chrome/worker/worker.vcproj', + guid='{C78D02D0-A366-4ec6-A248-AA8E64C4BA18}', + keyword='Win32Proj', + # TODO(sgk): when we can intuit the hierarchy + # from the built targets. + #buildtargets=TODO, + files=input_files, + local_directory_prefix='./', + tools=[ + 'VCPreBuildEventTool', + 'VCCustomBuildTool', + 'VCXMLDataGeneratorTool', + 'VCWebServiceProxyGeneratorTool', + 'VCMIDLTool', + 'VCCLCompilerTool', + 'VCManagedResourceCompilerTool', + 'VCResourceCompilerTool', + 'VCPreLinkEventTool', + 'VCLibrarianTool', + 'VCALinkTool', + 'VCXDCMakeTool', + 'VCBscMakeTool', + 'VCFxCopTool', + 'VCPostBuildEventTool', + ], + ConfigurationType='4') + + +p.AddConfig('Debug|Win32', + InheritedPropertySheets=[ + '$(SolutionDir)../build/common.vsprops', + '$(SolutionDir)../build/debug.vsprops', + '../tools/build/win/precompiled.vsprops', + ]) + +p.AddConfig('Release|Win32', + InheritedPropertySheets=[ + '$(SolutionDir)../build/common.vsprops', + '$(SolutionDir)../build/release.vsprops', + ]) + +p.AddFileConfig('../tools/build/win/precompiled.cc', + 'Debug|Win32', + tools=[ + MSVSTool('VCCLCompilerTool', + UsePrecompiledHeader='1'), + ]) diff --git a/chrome/worker/worker.vcproj b/chrome/worker/worker.vcproj new file mode 100644 index 0000000..ba82a39 --- /dev/null +++ b/chrome/worker/worker.vcproj @@ -0,0 +1,171 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="worker"
+ ProjectGUID="{C78D02D0-A366-4EC6-A248-AA8E64C4BA18}"
+ RootNamespace="worker"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\debug.vsprops;..\tools\build\win\precompiled.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\release.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\tools\build\win\precompiled.cc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\tools\build\win\precompiled.h"
+ >
+ </File>
+ <File
+ RelativePath=".\webworkerclient_proxy.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\webworkerclient_proxy.h"
+ >
+ </File>
+ <File
+ RelativePath=".\worker_main.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\worker_process.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\worker_process.h"
+ >
+ </File>
+ <File
+ RelativePath=".\worker_thread.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\worker_thread.h"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/chrome/worker/worker_main.cc b/chrome/worker/worker_main.cc new file mode 100644 index 0000000..b3c4256 --- /dev/null +++ b/chrome/worker/worker_main.cc @@ -0,0 +1,39 @@ +// 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 "base/command_line.h" +#include "base/message_loop.h" +#include "base/string_util.h" +#include "base/system_monitor.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/logging_chrome.h" +#include "chrome/common/main_function_params.h" +#include "chrome/common/win_util.h" +#include "chrome/worker/worker_process.h" +#include "sandbox/src/sandbox.h" + +// Mainline routine for running as the worker process. +int WorkerMain(const MainFunctionParams& parameters) { + const CommandLine& parsed_command_line = parameters.command_line_; + + // The main thread of the render process. + MessageLoopForIO main_message_loop; + std::wstring app_name = chrome::kBrowserAppName; + PlatformThread::SetName(WideToASCII(app_name + L"_WorkerMain").c_str()); + + // Initialize the SystemMonitor + base::SystemMonitor::Start(); + + // TODO(jabdelmalek): refactor sandboxing code from renderer so that the + // workers are sandboxed. + + WorkerProcess worker_process; + + // Load the accelerator table from the browser executable and tell the + // message loop to use it when translating messages. + MessageLoop::current()->Run(); + + return 0; +} diff --git a/chrome/worker/worker_process.cc b/chrome/worker/worker_process.cc new file mode 100644 index 0000000..4d319e3 --- /dev/null +++ b/chrome/worker/worker_process.cc @@ -0,0 +1,14 @@ +// 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/worker/worker_process.h" + +#include "chrome/worker/worker_thread.h" + +WorkerProcess::WorkerProcess() + : ChildProcess(new WorkerThread()) { +} + +WorkerProcess::~WorkerProcess() { +} diff --git a/chrome/worker/worker_process.h b/chrome/worker/worker_process.h new file mode 100644 index 0000000..da76781 --- /dev/null +++ b/chrome/worker/worker_process.h @@ -0,0 +1,28 @@ +// 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_WORKER_WORKER_PROCESS_H_ +#define CHROME_WORKER_WORKER_PROCESS_H_ + +#include "chrome/common/child_process.h" + +// Represents the worker end of the renderer<->worker connection. The +// opposite end is the WorkerProcessHost. This is a singleton object for +// each worker process. +class WorkerProcess : public ChildProcess { + public: + WorkerProcess(); + virtual ~WorkerProcess(); + + // Returns a pointer to the PluginProcess singleton instance. + static WorkerProcess* current() { + return static_cast<WorkerProcess*>(ChildProcess::current()); + } + + private: + + DISALLOW_COPY_AND_ASSIGN(WorkerProcess); +}; + +#endif // CHROME_WORKER_WORKER_PROCESS_H_ diff --git a/chrome/worker/worker_thread.cc b/chrome/worker/worker_thread.cc new file mode 100644 index 0000000..daba38b --- /dev/null +++ b/chrome/worker/worker_thread.cc @@ -0,0 +1,26 @@ +// 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/worker/worker_thread.h" + +#include "chrome/common/worker_messages.h" +#include "chrome/worker/webworkerclient_proxy.h" +#include "chrome/worker/worker_process.h" + +WorkerThread::WorkerThread() + : ChildThread(base::Thread::Options(MessageLoop::TYPE_DEFAULT, kV8StackSize)) { +} + +WorkerThread::~WorkerThread() { +} + +void WorkerThread::OnControlMessageReceived(const IPC::Message& msg) { + IPC_BEGIN_MESSAGE_MAP(WorkerThread, msg) + IPC_MESSAGE_HANDLER(WorkerProcessMsg_CreateWorker, OnCreateWorker) + IPC_END_MESSAGE_MAP() +} + +void WorkerThread::OnCreateWorker(const GURL& url, int route_id) { + WebWorkerClientProxy* worker = new WebWorkerClientProxy(url, route_id); +} diff --git a/chrome/worker/worker_thread.h b/chrome/worker/worker_thread.h new file mode 100644 index 0000000..25ae2f2 --- /dev/null +++ b/chrome/worker/worker_thread.h @@ -0,0 +1,31 @@ +// 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_WORKER_WORKER_THREAD_H_ +#define CHROME_WORKER_WORKER_THREAD_H_ + +#include "base/thread.h" +#include "chrome/common/child_thread.h" + +class GURL; + +class WorkerThread : public ChildThread { + public: + WorkerThread(); + ~WorkerThread(); + + // Returns the one worker thread. + static WorkerThread* current() { + return static_cast<WorkerThread*>(ChildThread::current()); + } + + private: + virtual void OnControlMessageReceived(const IPC::Message& msg); + + void OnCreateWorker(const GURL& url, int route_id); + + DISALLOW_COPY_AND_ASSIGN(WorkerThread); +}; + +#endif // CHROME_WORKER_WORKER_THREAD_H_ |