diff options
47 files changed, 1757 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_ diff --git a/webkit/glue/glue.vcproj b/webkit/glue/glue.vcproj index 4ce48b8..34a6b0b 100644 --- a/webkit/glue/glue.vcproj +++ b/webkit/glue/glue.vcproj @@ -249,6 +249,14 @@ >
</File>
<File
+ RelativePath=".\webworker.h"
+ >
+ </File>
+ <File
+ RelativePath=".\webworkerclient.h"
+ >
+ </File>
+ <File
RelativePath=".\window_open_disposition.h"
>
</File>
@@ -700,6 +708,22 @@ RelativePath=".\webwidget_impl.h"
>
</File>
+ <File
+ RelativePath=".\webworker_impl.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\webworker_impl.h"
+ >
+ </File>
+ <File
+ RelativePath=".\webworkerclient_impl.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\webworkerclient_impl.h"
+ >
+ </File>
</Filter>
<Filter
Name="Plugins"
diff --git a/webkit/glue/webview_delegate.h b/webkit/glue/webview_delegate.h index 7ef577a..59d4d95 100644 --- a/webkit/glue/webview_delegate.h +++ b/webkit/glue/webview_delegate.h @@ -54,6 +54,8 @@ class WebRequest; class WebResponse; class WebView; class WebWidget; +class WebWorker; +class WebWorkerClient; enum WebNavigationType { WebNavigationTypeLinkClicked, @@ -127,6 +129,11 @@ class WebViewDelegate : virtual public WebWidgetDelegate { return NULL; } + // This method is called when the renderer creates a worker object. + virtual WebWorker* CreateWebWorker(WebWorkerClient* client) { + return NULL; + } + // Called when a WebMediaPlayerDelegate is needed. virtual webkit_glue::WebMediaPlayerDelegate* CreateMediaPlayerDelegate() { return NULL; diff --git a/webkit/glue/webworker.h b/webkit/glue/webworker.h new file mode 100644 index 0000000..302fa24 --- /dev/null +++ b/webkit/glue/webworker.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 WEBKIT_GLUE_WEBWORKER_H_ +#define WEBKIT_GLUE_WEBWORKER_H_ + +#include "base/string16.h" + +class GURL; +class WebWorkerClient; + +// This is a version of the WebCore::WorkerContextProxy interface that uses +// Chrome data types. +class WebWorker { + public: + virtual ~WebWorker() { } + + // Creates a WebWorker object that wraps around the WebKit code that implements + // web workers. + static WebWorker* Create(WebWorkerClient* client); + + virtual void StartWorkerContext(const GURL& script_url, + const string16& user_agent, + const string16& source_code) = 0; + virtual void TerminateWorkerContext() = 0; + virtual void PostMessageToWorkerContext(const string16& message) = 0; + virtual void WorkerObjectDestroyed() = 0; +}; + +#endif // #ifndef WEBKIT_GLUE_WEBWORKER_H_ diff --git a/webkit/glue/webworker_impl.cc b/webkit/glue/webworker_impl.cc new file mode 100644 index 0000000..3bb5d20 --- /dev/null +++ b/webkit/glue/webworker_impl.cc @@ -0,0 +1,91 @@ +// 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 "config.h" + +#include "base/compiler_specific.h" +#include "webkit/glue/glue_util.h" +#include "webkit/glue/webworkerclient.h" +#include "webkit/glue/webworker_impl.h" + +#if ENABLE(WORKERS) + + +WebWorker* WebWorker::Create(WebWorkerClient* client) { + return new WebWorkerImpl(client); +} + + +WebWorkerImpl::WebWorkerImpl(WebWorkerClient* client) : client_(client) { +} + +WebWorkerImpl::~WebWorkerImpl() { +} + +void WebWorkerImpl::StartWorkerContext(const GURL& script_url, + const string16& user_agent, + const string16& source_code) { + // TODO(jianli): implement WorkerContextProxy here (i.e. create WorkerThread + // etc). The WebKit code uses worker_object_proxy_ when it wants to talk to + // code running in the renderer process. +} + +void WebWorkerImpl::TerminateWorkerContext() { +} + +void WebWorkerImpl::PostMessageToWorkerContext(const string16& message) { +} + +void WebWorkerImpl::WorkerObjectDestroyed() { +} + +void WebWorkerImpl::postMessageToWorkerObject(const WebCore::String& message) { + client_->PostMessageToWorkerObject(webkit_glue::StringToString16(message)); +} + +void WebWorkerImpl::postExceptionToWorkerObject( + const WebCore::String& errorMessage, + int lineNumber, + const WebCore::String& sourceURL) { + client_->PostExceptionToWorkerObject( + webkit_glue::StringToString16(errorMessage), + lineNumber, + webkit_glue::StringToString16(sourceURL)); +} + +void WebWorkerImpl::postConsoleMessageToWorkerObject( + WebCore::MessageDestination destination, + WebCore::MessageSource source, + WebCore::MessageLevel level, + const WebCore::String& message, + int lineNumber, + const WebCore::String& sourceURL) { + client_->PostConsoleMessageToWorkerObject( + destination, + source, + level, + webkit_glue::StringToString16(message), + lineNumber, + webkit_glue::StringToString16(sourceURL)); +} + +void WebWorkerImpl::confirmMessageFromWorkerObject(bool hasPendingActivity) { + client_->ConfirmMessageFromWorkerObject(hasPendingActivity); +} + +void WebWorkerImpl::reportPendingActivity(bool hasPendingActivity) { + client_->ReportPendingActivity(hasPendingActivity); +} + +void WebWorkerImpl::workerContextDestroyed() { + client_->WorkerContextDestroyed(); +} + +#else + +WebWorker* WebWorker::Create(WebWorkerClient* client) { + return NULL; +} + +#endif diff --git a/webkit/glue/webworker_impl.h b/webkit/glue/webworker_impl.h new file mode 100644 index 0000000..9903cea --- /dev/null +++ b/webkit/glue/webworker_impl.h @@ -0,0 +1,57 @@ +// 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 WEBKIT_GLUE_WEBWORKER_IMPL_H_ +#define WEBKIT_GLUE_WEBWORKER_IMPL_H_ + +#include "webkit/glue/webworker.h" + +#if ENABLE(WORKERS) + +#include "ScriptExecutionContext.h" +#include "WorkerObjectProxy.h" + +// This class is used by the worker process code to talk to the WebCore::Worker +// implementation. It can't use it directly since it uses WebKit types, so this +// class converts the data types. When the WebCore::Worker object wants to call +// WebCore::WorkerObjectProxy, this class will conver to Chrome data types first +// and then call the supplied WebWorkerClient. +class WebWorkerImpl: public WebCore::WorkerObjectProxy, + public WebWorker { + public: + WebWorkerImpl(WebWorkerClient* client); + virtual ~WebWorkerImpl(); + + // WebCore::WorkerObjectProxy implementation. + void postMessageToWorkerObject(const WebCore::String& message); + void postExceptionToWorkerObject(const WebCore::String& errorMessage, + int lineNumber, + const WebCore::String& sourceURL); + void postConsoleMessageToWorkerObject(WebCore::MessageDestination destination, + WebCore::MessageSource source, + WebCore::MessageLevel level, + const WebCore::String& message, + int lineNumber, + const WebCore::String& sourceURL); + void confirmMessageFromWorkerObject(bool hasPendingActivity); + void reportPendingActivity(bool hasPendingActivity); + void workerContextDestroyed(); + + // WebWorker implementation. + void StartWorkerContext(const GURL& script_url, + const string16& user_agent, + const string16& source_code); + void TerminateWorkerContext(); + void PostMessageToWorkerContext(const string16& message); + void WorkerObjectDestroyed(); + + private: + WebWorkerClient* client_; + + DISALLOW_COPY_AND_ASSIGN(WebWorkerImpl); +}; + +#endif + +#endif // WEBKIT_GLUE_WEBWORKER_IMPL_H_ diff --git a/webkit/glue/webworkerclient.h b/webkit/glue/webworkerclient.h new file mode 100644 index 0000000..aaa56b8 --- /dev/null +++ b/webkit/glue/webworkerclient.h @@ -0,0 +1,36 @@ +// 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 WEBKIT_GLUE_WEBWORKERCLIENT_H_ +#define WEBKIT_GLUE_WEBWORKERCLIENT_H_ + +#include "base/string16.h" + +// This is a version of the WebCore::WorkerObjectProxy interface that uses +// Chrome data types. +class WebWorkerClient { + public: + virtual ~WebWorkerClient() { } + + virtual void PostMessageToWorkerObject(const string16& message) = 0; + virtual void PostExceptionToWorkerObject( + const string16& error_message, + int line_number, + const string16& source_url) = 0; + // destination, source, and level are the int values of the corresponding + // WebKit enums. This avoids duplicating the enums and having to stay up to + // date. + virtual void PostConsoleMessageToWorkerObject( + int destination, + int source, + int level, + const string16& message, + int line_number, + const string16& source_url) = 0; + virtual void ConfirmMessageFromWorkerObject(bool has_pending_activity) = 0; + virtual void ReportPendingActivity(bool has_pending_activity) = 0; + virtual void WorkerContextDestroyed() = 0; +}; + +#endif // #ifndef WEBKIT_GLUE_WEBWORKERCLIENT_H_ diff --git a/webkit/glue/webworkerclient_impl.cc b/webkit/glue/webworkerclient_impl.cc new file mode 100644 index 0000000..d140681 --- /dev/null +++ b/webkit/glue/webworkerclient_impl.cc @@ -0,0 +1,128 @@ +// 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 "config.h" + +#if ENABLE(WORKERS) + +#include "base/compiler_specific.h" + +#include "Frame.h" +#include "FrameLoaderClient.h" +#include "WorkerMessagingProxy.h" +#include "Worker.h" + +#undef LOG + +#include "webkit/glue/webworkerclient_impl.h" + +#include "webkit/glue/glue_util.h" +#include "webkit/glue/webframeloaderclient_impl.h" +#include "webkit/glue/webframe_impl.h" +#include "webkit/glue/webview_delegate.h" +#include "webkit/glue/webview_impl.h" +#include "webkit/glue/webworker.h" + + +// When WebKit creates a WorkerContextProxy object, we check if we're in the +// renderer or worker process. If the latter, then we just use +// WebCore::WorkerMessagingProxy. +// +// If we're in the renderer process, then we need use the glue provided +// WebWorker object to talk to the worker process over IPC. The worker process +// talks to WebCore::Worker* using WorkerObjectProxy, which we implement on +// WebWorkerClientImpl. +WebCore::WorkerContextProxy* WebCore::WorkerContextProxy::create( + WebCore::Worker* worker) { + if (!worker->scriptExecutionContext()->isDocument()) + return new WebCore::WorkerMessagingProxy(worker); + + WebWorkerClientImpl* proxy = new WebWorkerClientImpl(worker); + + // Get to the RenderView, so that we can tell the browser to create a + // worker process if necessary. + WebCore::Document* document = static_cast<WebCore::Document*>( + worker->scriptExecutionContext()); + WebFrameLoaderClient* frame_loader_client = + static_cast<WebFrameLoaderClient*>(document->frame()->loader()->client()); + WebViewDelegate* webview_delegate = + frame_loader_client->webframe()->webview_impl()->delegate(); + WebWorker* webworker = webview_delegate->CreateWebWorker(proxy); + proxy->set_webworker(webworker); + return proxy; +} + + +WebWorkerClientImpl::WebWorkerClientImpl(WebCore::Worker* worker) + : worker_(worker) { +} + +WebWorkerClientImpl::~WebWorkerClientImpl() { +} + +void WebWorkerClientImpl::set_webworker(WebWorker* webworker) { + webworker_.reset(webworker); +} + +void WebWorkerClientImpl::startWorkerContext( + const WebCore::KURL& scriptURL, + const WebCore::String& userAgent, + const WebCore::String& sourceCode) { + webworker_->StartWorkerContext(webkit_glue::KURLToGURL(scriptURL), + webkit_glue::StringToString16(userAgent), + webkit_glue::StringToString16(sourceCode)); +} + +void WebWorkerClientImpl::terminateWorkerContext() { + webworker_->TerminateWorkerContext(); +} + +void WebWorkerClientImpl::postMessageToWorkerContext( + const WebCore::String& message) { + webworker_->PostMessageToWorkerContext( + webkit_glue::StringToString16(message)); +} + +bool WebWorkerClientImpl::hasPendingActivity() const { + // TODO(jianli): we should use the same logic from WorkerMessagingProxy + // here, so that we don't do a synchronous IPC. + // Until then, always return true. + return true; +} + +void WebWorkerClientImpl::workerObjectDestroyed() { + webworker_->WorkerObjectDestroyed(); +} + +void WebWorkerClientImpl::PostMessageToWorkerObject(const string16& message) { + // TODO(jianli): this method, and the ones below, need to implement + // WorkerObjectProxy. +} + +void WebWorkerClientImpl::PostExceptionToWorkerObject( + const string16& error_message, + int line_number, + const string16& source_url) { +} + +void WebWorkerClientImpl::PostConsoleMessageToWorkerObject( + int destination, + int source, + int level, + const string16& message, + int line_number, + const string16& source_url) { +} + +void WebWorkerClientImpl::ConfirmMessageFromWorkerObject(bool has_pending_activity) { +} + +void WebWorkerClientImpl::ReportPendingActivity(bool has_pending_activity) { +} + +void WebWorkerClientImpl::WorkerContextDestroyed() { + delete this; +} + +#endif diff --git a/webkit/glue/webworkerclient_impl.h b/webkit/glue/webworkerclient_impl.h new file mode 100644 index 0000000..fc93a3c --- /dev/null +++ b/webkit/glue/webworkerclient_impl.h @@ -0,0 +1,61 @@ +// 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 WEBKIT_GLUE_WEBWORKERCLIENT_IMPL_H_ +#define WEBKIT_GLUE_WEBWORKERCLIENT_IMPL_H_ + +#if ENABLE(WORKERS) + +#include "base/scoped_ptr.h" +#include "webkit/glue/webworkerclient.h" + +#include "WorkerContextProxy.h" + +class WebWorker; + +// The purpose of this class is to provide a WorkerContextProxy +// implementation that we can give to WebKit. Internally, it converts the +// data types to Chrome compatible ones so that renderer code can use it over +// IPC. +class WebWorkerClientImpl : public WebCore::WorkerContextProxy, + public WebWorkerClient { + public: + WebWorkerClientImpl(WebCore::Worker* worker); + + void set_webworker(WebWorker* webworker); + + // WebCore::WorkerContextProxy implementation + void startWorkerContext(const WebCore::KURL& scriptURL, + const WebCore::String& userAgent, + const WebCore::String& sourceCode); + void terminateWorkerContext(); + void postMessageToWorkerContext(const WebCore::String& message); + bool hasPendingActivity() const; + void workerObjectDestroyed(); + + // 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(); + + private: + virtual ~WebWorkerClientImpl(); + + WebCore::Worker* worker_; + scoped_ptr<WebWorker> webworker_; +}; + +#endif + +#endif // WEBKIT_GLUE_WEBWORKERCLIENT_IMPL_H_ |