diff options
author | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-12-21 20:03:24 +0000 |
---|---|---|
committer | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-12-21 20:03:24 +0000 |
commit | 6541227a9c1aa7a492dd1b671ef9bca26236b8e7 (patch) | |
tree | 8fe17eb6198b90237e117a809b3c9f55318973a2 /chrome | |
parent | 523d40835e4524c5e2ee2d4b8cfe1d7ca765f686 (diff) | |
download | chromium_src-6541227a9c1aa7a492dd1b671ef9bca26236b8e7.zip chromium_src-6541227a9c1aa7a492dd1b671ef9bca26236b8e7.tar.gz chromium_src-6541227a9c1aa7a492dd1b671ef9bca26236b8e7.tar.bz2 |
Create a message filter for message port and worker messages. This allows a nice cleanup of getting rid of the notifications when RenderMessageFilter and WorkerProcessHost go away. SafeBrowsingResourceHandler doesn't need it anymore as well, since it now overrides OnRequestClosed() which does the same thing.
Review URL: http://codereview.chromium.org/6055002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@69862 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
24 files changed, 1130 insertions, 1350 deletions
diff --git a/chrome/browser/browser_child_process_host.h b/chrome/browser/browser_child_process_host.h index 7524018..f917a4d 100644 --- a/chrome/browser/browser_child_process_host.h +++ b/chrome/browser/browser_child_process_host.h @@ -116,6 +116,10 @@ class BrowserChildProcessHost : public ChildProcessHost, // the host list. Calls ChildProcessHost::ForceShutdown virtual void ForceShutdown(); + ResourceDispatcherHost* resource_dispatcher_host() { + return resource_dispatcher_host_; + } + private: void Initialize(ResourceMessageFilter::URLRequestContextOverride* url_request_context_override); diff --git a/chrome/browser/renderer_host/browser_render_process_host.cc b/chrome/browser/renderer_host/browser_render_process_host.cc index c9e63385..c018061 100644 --- a/chrome/browser/renderer_host/browser_render_process_host.cc +++ b/chrome/browser/renderer_host/browser_render_process_host.cc @@ -16,6 +16,7 @@ #endif #include "app/app_switches.h" +#include "base/callback.h" #include "base/command_line.h" #include "base/logging.h" #include "base/metrics/field_trial.h" @@ -66,6 +67,7 @@ #include "chrome/browser/spellcheck_host.h" #include "chrome/browser/metrics/user_metrics.h" #include "chrome/browser/visitedlink/visitedlink_master.h" +#include "chrome/browser/worker_host/worker_message_filter.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/child_process_info.h" @@ -462,6 +464,13 @@ void BrowserRenderProcessHost::CreateMessageFilters() { socket_stream_dispatcher_host->set_url_request_context_override( url_request_context_override); channel_->AddFilter(socket_stream_dispatcher_host); + + channel_->AddFilter(new WorkerMessageFilter( + id(), + profile()->GetRequestContext(), + g_browser_process->resource_dispatcher_host(), + NewCallbackWithReturnValue( + widget_helper_.get(), &RenderWidgetHelper::GetNextRoutingID))); } int BrowserRenderProcessHost::GetNextRoutingID() { diff --git a/chrome/browser/renderer_host/render_message_filter.cc b/chrome/browser/renderer_host/render_message_filter.cc index 453e5c5..2bda4a6 100644 --- a/chrome/browser/renderer_host/render_message_filter.cc +++ b/chrome/browser/renderer_host/render_message_filter.cc @@ -44,8 +44,6 @@ #include "chrome/browser/renderer_host/render_widget_helper.h" #include "chrome/browser/spellchecker_platform_engine.h" #include "chrome/browser/task_manager/task_manager.h" -#include "chrome/browser/worker_host/message_port_dispatcher.h" -#include "chrome/browser/worker_host/worker_service.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/extension_file_util.h" #include "chrome/common/extensions/extension_message_bundle.h" @@ -245,8 +243,6 @@ RenderMessageFilter::RenderMessageFilter( profile->GetDesktopNotificationService()->prefs_cache()), host_zoom_map_(profile->GetHostZoomMap()), off_the_record_(profile->IsOffTheRecord()), - next_route_id_callback_(NewCallbackWithReturnValue( - render_widget_helper, &RenderWidgetHelper::GetNextRoutingID)), webkit_context_(profile->GetWebKitContext()), render_process_id_(render_process_id) { request_context_ = profile_->GetRequestContext(); @@ -264,183 +260,139 @@ RenderMessageFilter::RenderMessageFilter( RenderMessageFilter::~RenderMessageFilter() { // This function should be called on the IO thread. DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - - // Let interested observers know we are being deleted. - NotificationService::current()->Notify( - NotificationType::RESOURCE_MESSAGE_FILTER_SHUTDOWN, - Source<RenderMessageFilter>(this), - NotificationService::NoDetails()); -} - -// Called on the IPC thread: -void RenderMessageFilter::OnChannelConnected(int32 peer_pid) { - BrowserMessageFilter::OnChannelConnected(peer_pid); - - WorkerService::GetInstance()->Initialize(resource_dispatcher_host_); -} - -void RenderMessageFilter::OnChannelError() { - BrowserMessageFilter::OnChannelError(); - - NotificationService::current()->Notify( - NotificationType::RESOURCE_MESSAGE_FILTER_SHUTDOWN, - Source<RenderMessageFilter>(this), - NotificationService::NoDetails()); } // Called on the IPC thread: bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message, bool* message_was_ok) { - MessagePortDispatcher* mp_dispatcher = MessagePortDispatcher::GetInstance(); - bool handled = mp_dispatcher->OnMessageReceived( - message, this, next_route_id_callback(), message_was_ok); - - if (!handled) { - handled = true; - IPC_BEGIN_MESSAGE_MAP_EX(RenderMessageFilter, message, *message_was_ok) - // On Linux we need to dispatch these messages to the UI2 thread - // because we cannot make X calls from the IO thread. Mac - // doesn't have windowed plug-ins so we handle the messages in - // the UI thread. On Windows, we intercept the messages and - // handle them directly. + bool handled = true; + IPC_BEGIN_MESSAGE_MAP_EX(RenderMessageFilter, message, *message_was_ok) + // On Linux we need to dispatch these messages to the UI2 thread + // because we cannot make X calls from the IO thread. Mac + // doesn't have windowed plug-ins so we handle the messages in + // the UI thread. On Windows, we intercept the messages and + // handle them directly. #if !defined(OS_MACOSX) - IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetScreenInfo, - OnGetScreenInfo) - IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetWindowRect, - OnGetWindowRect) - IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetRootWindowRect, - OnGetRootWindowRect) + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetScreenInfo, OnGetScreenInfo) + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetWindowRect, OnGetWindowRect) + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetRootWindowRect, + OnGetRootWindowRect) #endif - IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWindow, OnMsgCreateWindow) - IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWidget, OnMsgCreateWidget) - IPC_MESSAGE_HANDLER(ViewHostMsg_CreateFullscreenWidget, - OnMsgCreateFullscreenWidget) - IPC_MESSAGE_HANDLER(ViewHostMsg_SetCookie, OnSetCookie) - IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetCookies, OnGetCookies) - IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetRawCookies, - OnGetRawCookies) - IPC_MESSAGE_HANDLER(ViewHostMsg_DeleteCookie, OnDeleteCookie) - IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_CookiesEnabled, - OnCookiesEnabled) + IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWindow, OnMsgCreateWindow) + IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWidget, OnMsgCreateWidget) + IPC_MESSAGE_HANDLER(ViewHostMsg_CreateFullscreenWidget, + OnMsgCreateFullscreenWidget) + IPC_MESSAGE_HANDLER(ViewHostMsg_SetCookie, OnSetCookie) + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetCookies, OnGetCookies) + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetRawCookies, OnGetRawCookies) + IPC_MESSAGE_HANDLER(ViewHostMsg_DeleteCookie, OnDeleteCookie) + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_CookiesEnabled, + OnCookiesEnabled) #if defined(OS_MACOSX) - IPC_MESSAGE_HANDLER(ViewHostMsg_LoadFont, OnLoadFont) + IPC_MESSAGE_HANDLER(ViewHostMsg_LoadFont, OnLoadFont) #endif #if defined(OS_WIN) // This hack is Windows-specific. - IPC_MESSAGE_HANDLER(ViewHostMsg_PreCacheFont, OnPreCacheFont) + IPC_MESSAGE_HANDLER(ViewHostMsg_PreCacheFont, OnPreCacheFont) #endif - IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetPlugins, OnGetPlugins) - IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetPluginInfo, - OnGetPluginInfo) - IPC_MESSAGE_HANDLER(ViewHostMsg_DownloadUrl, OnDownloadUrl) - IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_ContextMenu, - OnReceiveContextMenuMsg(message)) - IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_OpenChannelToPlugin, - OnOpenChannelToPlugin) - IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_OpenChannelToPepperPlugin, - OnOpenChannelToPepperPlugin) - IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_LaunchNaCl, OnLaunchNaCl) - IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWorker, OnCreateWorker) - IPC_MESSAGE_HANDLER(ViewHostMsg_LookupSharedWorker, OnLookupSharedWorker) - IPC_MESSAGE_HANDLER(ViewHostMsg_DocumentDetached, OnDocumentDetached) - IPC_MESSAGE_HANDLER(ViewHostMsg_CancelCreateDedicatedWorker, - OnCancelCreateDedicatedWorker) - IPC_MESSAGE_HANDLER(ViewHostMsg_ForwardToWorker, - OnForwardToWorker) - IPC_MESSAGE_HANDLER(ViewHostMsg_SpellChecker_PlatformCheckSpelling, - OnPlatformCheckSpelling) - IPC_MESSAGE_HANDLER(ViewHostMsg_SpellChecker_PlatformFillSuggestionList, - OnPlatformFillSuggestionList) - IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetDocumentTag, - OnGetDocumentTag) - IPC_MESSAGE_HANDLER(ViewHostMsg_DocumentWithTagClosed, - OnDocumentWithTagClosed) - IPC_MESSAGE_HANDLER(ViewHostMsg_ShowSpellingPanel, OnShowSpellingPanel) - IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateSpellingPanelWithMisspelledWord, - OnUpdateSpellingPanelWithMisspelledWord) - IPC_MESSAGE_HANDLER(ViewHostMsg_DnsPrefetch, OnDnsPrefetch) - IPC_MESSAGE_HANDLER(ViewHostMsg_RendererHistograms, - OnRendererHistograms) - IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_UpdateRect, - render_widget_helper_->DidReceiveUpdateMsg(message)) - IPC_MESSAGE_HANDLER(ViewHostMsg_ClipboardWriteObjectsAsync, - OnClipboardWriteObjectsAsync) - IPC_MESSAGE_HANDLER(ViewHostMsg_ClipboardWriteObjectsSync, - OnClipboardWriteObjectsSync) - IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ClipboardIsFormatAvailable, - OnClipboardIsFormatAvailable) - IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ClipboardReadText, - OnClipboardReadText) - IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ClipboardReadAsciiText, - OnClipboardReadAsciiText) - IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ClipboardReadHTML, - OnClipboardReadHTML) + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetPlugins, OnGetPlugins) + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetPluginInfo, OnGetPluginInfo) + IPC_MESSAGE_HANDLER(ViewHostMsg_DownloadUrl, OnDownloadUrl) + IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_ContextMenu, + OnReceiveContextMenuMsg(message)) + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_OpenChannelToPlugin, + OnOpenChannelToPlugin) + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_OpenChannelToPepperPlugin, + OnOpenChannelToPepperPlugin) + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_LaunchNaCl, OnLaunchNaCl) + IPC_MESSAGE_HANDLER(ViewHostMsg_SpellChecker_PlatformCheckSpelling, + OnPlatformCheckSpelling) + IPC_MESSAGE_HANDLER(ViewHostMsg_SpellChecker_PlatformFillSuggestionList, + OnPlatformFillSuggestionList) + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetDocumentTag, + OnGetDocumentTag) + IPC_MESSAGE_HANDLER(ViewHostMsg_DocumentWithTagClosed, + OnDocumentWithTagClosed) + IPC_MESSAGE_HANDLER(ViewHostMsg_ShowSpellingPanel, OnShowSpellingPanel) + IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateSpellingPanelWithMisspelledWord, + OnUpdateSpellingPanelWithMisspelledWord) + IPC_MESSAGE_HANDLER(ViewHostMsg_DnsPrefetch, OnDnsPrefetch) + IPC_MESSAGE_HANDLER(ViewHostMsg_RendererHistograms, OnRendererHistograms) + IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_UpdateRect, + render_widget_helper_->DidReceiveUpdateMsg(message)) + IPC_MESSAGE_HANDLER(ViewHostMsg_ClipboardWriteObjectsAsync, + OnClipboardWriteObjectsAsync) + IPC_MESSAGE_HANDLER(ViewHostMsg_ClipboardWriteObjectsSync, + OnClipboardWriteObjectsSync) + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ClipboardIsFormatAvailable, + OnClipboardIsFormatAvailable) + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ClipboardReadText, + OnClipboardReadText) + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ClipboardReadAsciiText, + OnClipboardReadAsciiText) + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ClipboardReadHTML, + OnClipboardReadHTML) #if defined(OS_MACOSX) - IPC_MESSAGE_HANDLER(ViewHostMsg_ClipboardFindPboardWriteStringAsync, - OnClipboardFindPboardWriteString) + IPC_MESSAGE_HANDLER(ViewHostMsg_ClipboardFindPboardWriteStringAsync, + OnClipboardFindPboardWriteString) #endif - IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ClipboardReadAvailableTypes, - OnClipboardReadAvailableTypes) - IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ClipboardReadData, - OnClipboardReadData) - IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ClipboardReadFilenames, - OnClipboardReadFilenames) - IPC_MESSAGE_HANDLER(ViewHostMsg_CheckNotificationPermission, - OnCheckNotificationPermission) - IPC_MESSAGE_HANDLER(ViewHostMsg_RevealFolderInOS, OnRevealFolderInOS) - IPC_MESSAGE_HANDLER(ViewHostMsg_GetCPBrowsingContext, - OnGetCPBrowsingContext) + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ClipboardReadAvailableTypes, + OnClipboardReadAvailableTypes) + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ClipboardReadData, + OnClipboardReadData) + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ClipboardReadFilenames, + OnClipboardReadFilenames) + IPC_MESSAGE_HANDLER(ViewHostMsg_CheckNotificationPermission, + OnCheckNotificationPermission) + IPC_MESSAGE_HANDLER(ViewHostMsg_RevealFolderInOS, OnRevealFolderInOS) + IPC_MESSAGE_HANDLER(ViewHostMsg_GetCPBrowsingContext, + OnGetCPBrowsingContext) #if defined(OS_WIN) - IPC_MESSAGE_HANDLER(ViewHostMsg_DuplicateSection, OnDuplicateSection) + IPC_MESSAGE_HANDLER(ViewHostMsg_DuplicateSection, OnDuplicateSection) #endif #if defined(OS_POSIX) - IPC_MESSAGE_HANDLER(ViewHostMsg_AllocateSharedMemoryBuffer, - OnAllocateSharedMemoryBuffer) + IPC_MESSAGE_HANDLER(ViewHostMsg_AllocateSharedMemoryBuffer, + OnAllocateSharedMemoryBuffer) #endif #if defined(OS_POSIX) && !defined(OS_MACOSX) - IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_AllocateTempFileForPrinting, - OnAllocateTempFileForPrinting) - IPC_MESSAGE_HANDLER(ViewHostMsg_TempFileForPrintingWritten, - OnTempFileForPrintingWritten) + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_AllocateTempFileForPrinting, + OnAllocateTempFileForPrinting) + IPC_MESSAGE_HANDLER(ViewHostMsg_TempFileForPrintingWritten, + OnTempFileForPrintingWritten) #endif - IPC_MESSAGE_HANDLER(ViewHostMsg_ResourceTypeStats, OnResourceTypeStats) - IPC_MESSAGE_HANDLER(ViewHostMsg_V8HeapStats, OnV8HeapStats) - IPC_MESSAGE_HANDLER(ViewHostMsg_DidZoomURL, OnDidZoomURL) - IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ResolveProxy, OnResolveProxy) - IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetDefaultPrintSettings, - OnGetDefaultPrintSettings) - IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ScriptedPrint, - OnScriptedPrint) + IPC_MESSAGE_HANDLER(ViewHostMsg_ResourceTypeStats, OnResourceTypeStats) + IPC_MESSAGE_HANDLER(ViewHostMsg_V8HeapStats, OnV8HeapStats) + IPC_MESSAGE_HANDLER(ViewHostMsg_DidZoomURL, OnDidZoomURL) + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ResolveProxy, OnResolveProxy) + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetDefaultPrintSettings, + OnGetDefaultPrintSettings) + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ScriptedPrint, OnScriptedPrint) #if defined(OS_MACOSX) - IPC_MESSAGE_HANDLER(ViewHostMsg_AllocTransportDIB, - OnAllocTransportDIB) - IPC_MESSAGE_HANDLER(ViewHostMsg_FreeTransportDIB, - OnFreeTransportDIB) + IPC_MESSAGE_HANDLER(ViewHostMsg_AllocTransportDIB, OnAllocTransportDIB) + IPC_MESSAGE_HANDLER(ViewHostMsg_FreeTransportDIB, OnFreeTransportDIB) #endif - IPC_MESSAGE_HANDLER(ViewHostMsg_OpenChannelToExtension, - OnOpenChannelToExtension) - IPC_MESSAGE_HANDLER(ViewHostMsg_OpenChannelToTab, OnOpenChannelToTab) - IPC_MESSAGE_HANDLER(ViewHostMsg_CloseCurrentConnections, - OnCloseCurrentConnections) - IPC_MESSAGE_HANDLER(ViewHostMsg_SetCacheMode, OnSetCacheMode) - IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ClearCache, OnClearCache) - IPC_MESSAGE_HANDLER(ViewHostMsg_DidGenerateCacheableMetadata, - OnCacheableMetadataAvailable) - IPC_MESSAGE_HANDLER(ViewHostMsg_EnableSpdy, OnEnableSpdy) - IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_Keygen, OnKeygen) - IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetExtensionMessageBundle, - OnGetExtensionMessageBundle) + IPC_MESSAGE_HANDLER(ViewHostMsg_OpenChannelToExtension, + OnOpenChannelToExtension) + IPC_MESSAGE_HANDLER(ViewHostMsg_OpenChannelToTab, OnOpenChannelToTab) + IPC_MESSAGE_HANDLER(ViewHostMsg_CloseCurrentConnections, + OnCloseCurrentConnections) + IPC_MESSAGE_HANDLER(ViewHostMsg_SetCacheMode, OnSetCacheMode) + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ClearCache, OnClearCache) + IPC_MESSAGE_HANDLER(ViewHostMsg_DidGenerateCacheableMetadata, + OnCacheableMetadataAvailable) + IPC_MESSAGE_HANDLER(ViewHostMsg_EnableSpdy, OnEnableSpdy) + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_Keygen, OnKeygen) + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetExtensionMessageBundle, + OnGetExtensionMessageBundle) #if defined(USE_TCMALLOC) - IPC_MESSAGE_HANDLER(ViewHostMsg_RendererTcmalloc, OnRendererTcmalloc) + IPC_MESSAGE_HANDLER(ViewHostMsg_RendererTcmalloc, OnRendererTcmalloc) #endif - IPC_MESSAGE_HANDLER(ViewHostMsg_EstablishGpuChannel, - OnEstablishGpuChannel) - IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_SynchronizeGpu, - OnSynchronizeGpu) - IPC_MESSAGE_HANDLER(ViewHostMsg_AsyncOpenFile, OnAsyncOpenFile) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP_EX() - } + IPC_MESSAGE_HANDLER(ViewHostMsg_EstablishGpuChannel, OnEstablishGpuChannel) + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_SynchronizeGpu, + OnSynchronizeGpu) + IPC_MESSAGE_HANDLER(ViewHostMsg_AsyncOpenFile, OnAsyncOpenFile) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP_EX() return handled; } @@ -771,50 +723,6 @@ void RenderMessageFilter::OnLaunchNaCl( host->Launch(this, channel_descriptor, reply_msg); } -void RenderMessageFilter::OnCreateWorker( - const ViewHostMsg_CreateWorker_Params& params, int* route_id) { - *route_id = params.route_id != MSG_ROUTING_NONE ? - params.route_id : render_widget_helper_->GetNextRoutingID(); - if (params.is_shared) - WorkerService::GetInstance()->CreateSharedWorker( - params.url, off_the_record(), params.name, - params.document_id, render_process_id_, params.render_view_route_id, - this, *route_id, params.script_resource_appcache_id, - static_cast<ChromeURLRequestContext*>( - request_context_->GetURLRequestContext())); - else - WorkerService::GetInstance()->CreateDedicatedWorker( - params.url, off_the_record(), - params.document_id, render_process_id_, params.render_view_route_id, - this, *route_id, render_process_id_, params.parent_appcache_host_id, - static_cast<ChromeURLRequestContext*>( - request_context_->GetURLRequestContext())); -} - -void RenderMessageFilter::OnLookupSharedWorker( - const ViewHostMsg_CreateWorker_Params& params, bool* exists, int* route_id, - bool* url_mismatch) { - *route_id = render_widget_helper_->GetNextRoutingID(); - *exists = WorkerService::GetInstance()->LookupSharedWorker( - params.url, params.name, off_the_record(), params.document_id, - render_process_id_, params.render_view_route_id, this, *route_id, - url_mismatch); -} - -void RenderMessageFilter::OnDocumentDetached(unsigned long long document_id) { - // Notify the WorkerService that the passed document was detached so any - // associated shared workers can be shut down. - WorkerService::GetInstance()->DocumentDetached(this, document_id); -} - -void RenderMessageFilter::OnCancelCreateDedicatedWorker(int route_id) { - WorkerService::GetInstance()->CancelCreateDedicatedWorker(this, route_id); -} - -void RenderMessageFilter::OnForwardToWorker(const IPC::Message& message) { - WorkerService::GetInstance()->ForwardMessage(message, this); -} - void RenderMessageFilter::OnDownloadUrl(const IPC::Message& message, const GURL& url, const GURL& referrer) { diff --git a/chrome/browser/renderer_host/render_message_filter.h b/chrome/browser/renderer_host/render_message_filter.h index 5c988b8..98e8402 100644 --- a/chrome/browser/renderer_host/render_message_filter.h +++ b/chrome/browser/renderer_host/render_message_filter.h @@ -15,7 +15,6 @@ #include "app/clipboard/clipboard.h" #include "app/surface/transport_dib.h" -#include "base/callback.h" #include "base/file_path.h" #include "base/linked_ptr.h" #include "base/string16.h" @@ -75,8 +74,6 @@ class RenderMessageFilter : public BrowserMessageFilter, RenderWidgetHelper* render_widget_helper); // BrowserMessageFilter methods: - virtual void OnChannelConnected(int32 peer_pid); - virtual void OnChannelError(); virtual bool OnMessageReceived(const IPC::Message& message, bool* message_was_ok); virtual void OnDestruct() const; @@ -86,9 +83,6 @@ class RenderMessageFilter : public BrowserMessageFilter, return resource_dispatcher_host_; } bool off_the_record() { return off_the_record_; } - CallbackWithReturnValue<int>::Type* next_route_id_callback() { - return next_route_id_callback_.get(); - } // Returns either the extension URLRequestContext or regular URLRequestContext // depending on whether |url| is an extension URL. @@ -170,15 +164,6 @@ class RenderMessageFilter : public BrowserMessageFilter, void OnLaunchNaCl(const std::wstring& url, int channel_descriptor, IPC::Message* reply_msg); - void OnCreateWorker(const ViewHostMsg_CreateWorker_Params& params, - int* route_id); - void OnLookupSharedWorker(const ViewHostMsg_CreateWorker_Params& params, - bool* exists, - int* route_id, - bool* url_error); - void OnDocumentDetached(unsigned long long document_id); - void OnCancelCreateDedicatedWorker(int route_id); - void OnForwardToWorker(const IPC::Message& msg); void OnDownloadUrl(const IPC::Message& message, const GURL& url, const GURL& referrer); @@ -424,9 +409,6 @@ class RenderMessageFilter : public BrowserMessageFilter, // A list of all Ppapi plugin processes for this renderer. std::vector<linked_ptr<PpapiPluginProcessHost> > ppapi_plugin_hosts_; - // A callback to create a routing id for the associated renderer process. - scoped_ptr<CallbackWithReturnValue<int>::Type> next_route_id_callback_; - scoped_refptr<WebKitContext> webkit_context_; int render_process_id_; diff --git a/chrome/browser/renderer_host/render_widget_host.cc b/chrome/browser/renderer_host/render_widget_host.cc index b4bb0e2..f530697 100644 --- a/chrome/browser/renderer_host/render_widget_host.cc +++ b/chrome/browser/renderer_host/render_widget_host.cc @@ -391,8 +391,7 @@ BackingStore* RenderWidgetHost::GetBackingStore(bool force_create) { IPC::Message msg; TimeDelta max_delay = TimeDelta::FromMilliseconds(kPaintMsgTimeoutMS); if (process_->WaitForUpdateMsg(routing_id_, max_delay, &msg)) { - ViewHostMsg_UpdateRect::Dispatch( - &msg, this, &RenderWidgetHost::OnMsgUpdateRect); + OnMessageReceived(msg); backing_store = BackingStoreManager::GetBackingStore(this, current_size_); } } @@ -427,10 +426,8 @@ void RenderWidgetHost::ScheduleComposite() { // We always block on response because we do not have a backing store. IPC::Message msg; TimeDelta max_delay = TimeDelta::FromMilliseconds(kPaintMsgTimeoutMS); - if (process_->WaitForUpdateMsg(routing_id_, max_delay, &msg)) { - ViewHostMsg_UpdateRect::Dispatch( - &msg, this, &RenderWidgetHost::OnMsgUpdateRect); - } + if (process_->WaitForUpdateMsg(routing_id_, max_delay, &msg)) + OnMessageReceived(msg); } void RenderWidgetHost::StartHangMonitorTimeout(TimeDelta delay) { diff --git a/chrome/browser/renderer_host/resource_dispatcher_host.cc b/chrome/browser/renderer_host/resource_dispatcher_host.cc index 1d073d3..cad4560 100644 --- a/chrome/browser/renderer_host/resource_dispatcher_host.cc +++ b/chrome/browser/renderer_host/resource_dispatcher_host.cc @@ -1518,20 +1518,14 @@ bool ResourceDispatcherHost::RenderViewForRequest( // If the request is from the worker process, find a tab that owns the worker. if (info->process_type() == ChildProcessInfo::WORKER_PROCESS) { - const WorkerProcessHost::WorkerInstance* worker_instance = - WorkerService::GetInstance()->FindWorkerInstance(info->child_id()); - if (!worker_instance) { + // Need to display some related UI for this network request - pick an + // arbitrary parent to do so. + if (!WorkerService::GetInstance()->GetRendererForWorker( + info->child_id(), render_process_host_id, render_view_host_id)) { *render_process_host_id = -1; *render_view_host_id = -1; return false; } - DCHECK(!worker_instance->worker_document_set()->IsEmpty()); - const WorkerDocumentSet::DocumentInfoSet& parents = - worker_instance->worker_document_set()->documents(); - // Need to display some related UI for this network request - pick an - // arbitrary parent to do so. - *render_process_host_id = parents.begin()->renderer_id(); - *render_view_host_id = parents.begin()->render_view_route_id(); } else { *render_process_host_id = info->child_id(); *render_view_host_id = info->route_id(); diff --git a/chrome/browser/renderer_host/resource_request_details.cc b/chrome/browser/renderer_host/resource_request_details.cc index 6facdd6..07183d4 100644 --- a/chrome/browser/renderer_host/resource_request_details.cc +++ b/chrome/browser/renderer_host/resource_request_details.cc @@ -4,6 +4,8 @@ #include "chrome/browser/renderer_host/resource_request_details.h" +#include "chrome/browser/worker_host/worker_service.h" + ResourceRequestDetails::ResourceRequestDetails(const net::URLRequest* request, int cert_id) : url_(request->url()), @@ -25,18 +27,13 @@ ResourceRequestDetails::ResourceRequestDetails(const net::URLRequest* request, // If request is from the worker process on behalf of a renderer, use // the renderer process id, since it consumes the notification response // such as ssl state etc. - const WorkerProcessHost::WorkerInstance* worker_instance = - WorkerService::GetInstance()->FindWorkerInstance(info->child_id()); - if (worker_instance) { - DCHECK(!worker_instance->worker_document_set()->IsEmpty()); - const WorkerDocumentSet::DocumentInfoSet& parents = - worker_instance->worker_document_set()->documents(); - // TODO(atwilson): need to notify all associated renderers in the case - // of ssl state change (http://crbug.com/25357). For now, just notify - // the first one (works for dedicated workers and shared workers with - // a single process). - origin_child_id_ = parents.begin()->renderer_id(); - } else { + // TODO(atwilson): need to notify all associated renderers in the case + // of ssl state change (http://crbug.com/25357). For now, just notify + // the first one (works for dedicated workers and shared workers with + // a single process). + int temp; + if (!WorkerService::GetInstance()->GetRendererForWorker( + info->child_id(), &origin_child_id_, &temp)) { origin_child_id_ = info->child_id(); } } diff --git a/chrome/browser/renderer_host/safe_browsing_resource_handler.cc b/chrome/browser/renderer_host/safe_browsing_resource_handler.cc index d73f24b0..237cad8 100644 --- a/chrome/browser/renderer_host/safe_browsing_resource_handler.cc +++ b/chrome/browser/renderer_host/safe_browsing_resource_handler.cc @@ -6,10 +6,8 @@ #include "base/logging.h" #include "chrome/browser/renderer_host/global_request_id.h" -#include "chrome/browser/renderer_host/render_message_filter.h" #include "chrome/browser/renderer_host/resource_dispatcher_host.h" #include "chrome/browser/renderer_host/resource_message_filter.h" -#include "chrome/common/notification_service.h" #include "chrome/common/resource_response.h" #include "net/base/net_errors.h" #include "net/base/io_buffer.h" @@ -38,8 +36,6 @@ SafeBrowsingResourceHandler::SafeBrowsingResourceHandler( safe_browsing_(safe_browsing), rdh_(resource_dispatcher_host), resource_type_(resource_type) { - registrar_.Add(this, NotificationType::RESOURCE_MESSAGE_FILTER_SHUTDOWN, - NotificationService::AllSources()); } SafeBrowsingResourceHandler::~SafeBrowsingResourceHandler() { @@ -204,15 +200,6 @@ void SafeBrowsingResourceHandler::OnBlockingPageComplete(bool proceed) { Release(); // Balances the AddRef() in StartDisplayingBlockingPage(). } -void SafeBrowsingResourceHandler::Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - if (Source<ResourceMessageFilter>(source).ptr()->child_id() == - render_process_host_id_) { - Shutdown(); - } -} - void SafeBrowsingResourceHandler::Shutdown() { if (state_ == STATE_CHECKING_URL) { timer_.Stop(); diff --git a/chrome/browser/renderer_host/safe_browsing_resource_handler.h b/chrome/browser/renderer_host/safe_browsing_resource_handler.h index e679fdc..724297f 100644 --- a/chrome/browser/renderer_host/safe_browsing_resource_handler.h +++ b/chrome/browser/renderer_host/safe_browsing_resource_handler.h @@ -13,8 +13,6 @@ #include "base/timer.h" #include "chrome/browser/renderer_host/resource_handler.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" -#include "chrome/common/notification_observer.h" -#include "chrome/common/notification_registrar.h" class ResourceDispatcherHost; @@ -41,8 +39,7 @@ class ResourceDispatcherHost; // If on the other hand the URL was decided to be safe, the request is // resumed. class SafeBrowsingResourceHandler : public ResourceHandler, - public SafeBrowsingService::Client, - public NotificationObserver { + public SafeBrowsingService::Client { public: SafeBrowsingResourceHandler(ResourceHandler* handler, int render_process_host_id, @@ -74,11 +71,6 @@ class SafeBrowsingResourceHandler : public ResourceHandler, // the user has decided to proceed with the current request, or go back. virtual void OnBlockingPageComplete(bool proceed); - // NotificationObserver interface. - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details); - private: // Describes what phase of the check a handler is in. enum State { @@ -145,7 +137,6 @@ class SafeBrowsingResourceHandler : public ResourceHandler, int deferred_request_id_; scoped_refptr<ResourceResponse> deferred_redirect_response_; - NotificationRegistrar registrar_; scoped_refptr<ResourceHandler> next_handler_; int render_process_host_id_; int render_view_id_; diff --git a/chrome/browser/worker_host/message_port_dispatcher.cc b/chrome/browser/worker_host/message_port_dispatcher.cc deleted file mode 100644 index 1be8369..0000000 --- a/chrome/browser/worker_host/message_port_dispatcher.cc +++ /dev/null @@ -1,291 +0,0 @@ -// 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/message_port_dispatcher.h" - -#include "base/callback.h" -#include "base/singleton.h" -#include "chrome/browser/renderer_host/render_message_filter.h" -#include "chrome/browser/worker_host/worker_process_host.h" -#include "chrome/common/notification_service.h" -#include "chrome/common/worker_messages.h" - -struct MessagePortDispatcher::MessagePort { - // sender and route_id are what we need to send messages to the port. - IPC::Message::Sender* sender; - int route_id; - // A function pointer to generate a new route id for the sender above. - // Owned by "sender" above, so don't delete. - CallbackWithReturnValue<int>::Type* next_routing_id; - // A globally unique id for this message port. - int message_port_id; - // The globally unique id of the entangled message port. - int entangled_message_port_id; - // If true, all messages to this message port are queued and not delivered. - bool queue_messages; - QueuedMessages queued_messages; -}; - -MessagePortDispatcher* MessagePortDispatcher::GetInstance() { - return Singleton<MessagePortDispatcher>::get(); -} - -MessagePortDispatcher::MessagePortDispatcher() - : next_message_port_id_(0), - sender_(NULL), - next_routing_id_(NULL) { - // Receive a notification if a message filter or WorkerProcessHost is deleted. - registrar_.Add(this, NotificationType::RESOURCE_MESSAGE_FILTER_SHUTDOWN, - NotificationService::AllSources()); - - registrar_.Add(this, NotificationType::WORKER_PROCESS_HOST_SHUTDOWN, - NotificationService::AllSources()); -} - -MessagePortDispatcher::~MessagePortDispatcher() { -} - -bool MessagePortDispatcher::OnMessageReceived( - const IPC::Message& message, - IPC::Message::Sender* sender, - CallbackWithReturnValue<int>::Type* next_routing_id, - bool* message_was_ok) { - sender_ = sender; - next_routing_id_ = next_routing_id; - - bool handled = true; - *message_was_ok = true; - - IPC_BEGIN_MESSAGE_MAP_EX(MessagePortDispatcher, message, *message_was_ok) - IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_CreateMessagePort, OnCreate) - IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_DestroyMessagePort, OnDestroy) - IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_Entangle, OnEntangle) - IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_PostMessage, OnPostMessage) - IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_QueueMessages, OnQueueMessages) - IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_SendQueuedMessages, - OnSendQueuedMessages) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP_EX() - - sender_ = NULL; - next_routing_id_ = NULL; - - return handled; -} - -void MessagePortDispatcher::UpdateMessagePort( - int message_port_id, - IPC::Message::Sender* sender, - int routing_id, - CallbackWithReturnValue<int>::Type* next_routing_id) { - if (!message_ports_.count(message_port_id)) { - NOTREACHED(); - return; - } - - MessagePort& port = message_ports_[message_port_id]; - port.sender = sender; - port.route_id = routing_id; - port.next_routing_id = next_routing_id; -} - -bool MessagePortDispatcher::Send(IPC::Message* message) { - return sender_->Send(message); -} - -void MessagePortDispatcher::OnCreate(int *route_id, - int* message_port_id) { - *message_port_id = ++next_message_port_id_; - *route_id = next_routing_id_->Run(); - - MessagePort port; - port.sender = sender_; - port.route_id = *route_id; - port.next_routing_id = next_routing_id_; - port.message_port_id = *message_port_id; - port.entangled_message_port_id = MSG_ROUTING_NONE; - port.queue_messages = false; - message_ports_[*message_port_id] = port; -} - -void MessagePortDispatcher::OnDestroy(int message_port_id) { - if (!message_ports_.count(message_port_id)) { - NOTREACHED(); - return; - } - - DCHECK(message_ports_[message_port_id].queued_messages.empty()); - Erase(message_port_id); -} - -void MessagePortDispatcher::OnEntangle(int local_message_port_id, - int remote_message_port_id) { - if (!message_ports_.count(local_message_port_id) || - !message_ports_.count(remote_message_port_id)) { - NOTREACHED(); - return; - } - - DCHECK(message_ports_[remote_message_port_id].entangled_message_port_id == - MSG_ROUTING_NONE); - message_ports_[remote_message_port_id].entangled_message_port_id = - local_message_port_id; -} - -void MessagePortDispatcher::OnPostMessage( - int sender_message_port_id, - const string16& message, - const std::vector<int>& sent_message_port_ids) { - if (!message_ports_.count(sender_message_port_id)) { - NOTREACHED(); - return; - } - - int entangled_message_port_id = - message_ports_[sender_message_port_id].entangled_message_port_id; - if (entangled_message_port_id == MSG_ROUTING_NONE) - return; // Process could have crashed. - - if (!message_ports_.count(entangled_message_port_id)) { - NOTREACHED(); - return; - } - - PostMessageTo(entangled_message_port_id, message, sent_message_port_ids); -} - -void MessagePortDispatcher::PostMessageTo( - int message_port_id, - const string16& message, - const std::vector<int>& sent_message_port_ids) { - if (!message_ports_.count(message_port_id)) { - NOTREACHED(); - return; - } - for (size_t i = 0; i < sent_message_port_ids.size(); ++i) { - if (!message_ports_.count(sent_message_port_ids[i])) { - NOTREACHED(); - return; - } - } - - MessagePort& entangled_port = message_ports_[message_port_id]; - - std::vector<MessagePort*> sent_ports(sent_message_port_ids.size()); - for (size_t i = 0; i < sent_message_port_ids.size(); ++i) { - sent_ports[i] = &message_ports_[sent_message_port_ids[i]]; - sent_ports[i]->queue_messages = true; - } - - if (entangled_port.queue_messages) { - entangled_port.queued_messages.push_back( - std::make_pair(message, sent_message_port_ids)); - } else { - // If a message port was sent around, the new location will need a routing - // id. Instead of having the created port send us a sync message to get it, - // send along with the message. - std::vector<int> new_routing_ids(sent_message_port_ids.size()); - for (size_t i = 0; i < sent_message_port_ids.size(); ++i) { - new_routing_ids[i] = entangled_port.next_routing_id->Run(); - sent_ports[i]->sender = entangled_port.sender; - - // Update the entry for the sent port as it can be in a different process. - sent_ports[i]->route_id = new_routing_ids[i]; - } - - if (entangled_port.sender) { - // Now send the message to the entangled port. - IPC::Message* ipc_msg = new WorkerProcessMsg_Message( - entangled_port.route_id, message, sent_message_port_ids, - new_routing_ids); - entangled_port.sender->Send(ipc_msg); - } - } -} - -void MessagePortDispatcher::OnQueueMessages(int message_port_id) { - if (!message_ports_.count(message_port_id)) { - NOTREACHED(); - return; - } - - MessagePort& port = message_ports_[message_port_id]; - if (port.sender) { - port.sender->Send(new WorkerProcessMsg_MessagesQueued(port.route_id)); - port.queue_messages = true; - port.sender = NULL; - } -} - -void MessagePortDispatcher::OnSendQueuedMessages( - int message_port_id, - const QueuedMessages& queued_messages) { - if (!message_ports_.count(message_port_id)) { - NOTREACHED(); - return; - } - - // Send the queued messages to the port again. This time they'll reach the - // new location. - MessagePort& port = message_ports_[message_port_id]; - port.queue_messages = false; - port.queued_messages.insert(port.queued_messages.begin(), - queued_messages.begin(), - queued_messages.end()); - SendQueuedMessagesIfPossible(message_port_id); -} - -void MessagePortDispatcher::SendQueuedMessagesIfPossible(int message_port_id) { - if (!message_ports_.count(message_port_id)) { - NOTREACHED(); - return; - } - - MessagePort& port = message_ports_[message_port_id]; - if (port.queue_messages || !port.sender) - return; - - for (QueuedMessages::iterator iter = port.queued_messages.begin(); - iter != port.queued_messages.end(); ++iter) { - PostMessageTo(message_port_id, iter->first, iter->second); - } - port.queued_messages.clear(); -} - -void MessagePortDispatcher::Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - IPC::Message::Sender* sender = NULL; - if (type.value == NotificationType::RESOURCE_MESSAGE_FILTER_SHUTDOWN) { - sender = Source<RenderMessageFilter>(source).ptr(); - } else if (type.value == NotificationType::WORKER_PROCESS_HOST_SHUTDOWN) { - sender = Source<WorkerProcessHost>(source).ptr(); - } else { - NOTREACHED(); - } - - // Check if the (possibly) crashed process had any message ports. - for (MessagePorts::iterator iter = message_ports_.begin(); - iter != message_ports_.end();) { - MessagePorts::iterator cur_item = iter++; - if (cur_item->second.sender == sender) { - Erase(cur_item->first); - } - } -} - -void MessagePortDispatcher::Erase(int message_port_id) { - MessagePorts::iterator erase_item = message_ports_.find(message_port_id); - DCHECK(erase_item != message_ports_.end()); - - int entangled_id = erase_item->second.entangled_message_port_id; - if (entangled_id != MSG_ROUTING_NONE) { - // Do the disentanglement (and be paranoid about the other side existing - // just in case something unusual happened during entanglement). - if (message_ports_.count(entangled_id)) { - message_ports_[entangled_id].entangled_message_port_id = MSG_ROUTING_NONE; - } - } - message_ports_.erase(erase_item); -} diff --git a/chrome/browser/worker_host/message_port_dispatcher.h b/chrome/browser/worker_host/message_port_dispatcher.h deleted file mode 100644 index 4c71283..0000000 --- a/chrome/browser/worker_host/message_port_dispatcher.h +++ /dev/null @@ -1,93 +0,0 @@ -// 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_MESSAGE_PORT_DISPATCHER_H_ -#define CHROME_BROWSER_WORKER_HOST_MESSAGE_PORT_DISPATCHER_H_ -#pragma once - -#include <map> -#include <utility> -#include <vector> - -#include "base/basictypes.h" -#include "base/callback.h" -#include "base/singleton.h" -#include "base/string16.h" -#include "base/task.h" -#include "chrome/common/notification_observer.h" -#include "chrome/common/notification_registrar.h" -#include "ipc/ipc_message.h" - -class MessagePortDispatcher : public NotificationObserver { - public: - typedef std::vector<std::pair<string16, std::vector<int> > > QueuedMessages; - - // Returns the MessagePortDispatcher singleton. - static MessagePortDispatcher* GetInstance(); - - bool OnMessageReceived(const IPC::Message& message, - IPC::Message::Sender* sender, - CallbackWithReturnValue<int>::Type* next_routing_id, - bool* message_was_ok); - - // Updates the information needed to reach a message port when it's sent to a - // (possibly different) process. - void UpdateMessagePort( - int message_port_id, - IPC::Message::Sender* sender, - int routing_id, - CallbackWithReturnValue<int>::Type* next_routing_id); - - // Attempts to send the queued messages for a message port. - void SendQueuedMessagesIfPossible(int message_port_id); - - bool Send(IPC::Message* message); - - private: - friend struct DefaultSingletonTraits<MessagePortDispatcher>; - - MessagePortDispatcher(); - ~MessagePortDispatcher(); - - // Message handlers. - void OnCreate(int* route_id, int* message_port_id); - void OnDestroy(int message_port_id); - void OnEntangle(int local_message_port_id, int remote_message_port_id); - void OnPostMessage(int sender_message_port_id, - const string16& message, - const std::vector<int>& sent_message_port_ids); - void OnQueueMessages(int message_port_id); - void OnSendQueuedMessages(int message_port_id, - const QueuedMessages& queued_messages); - - void PostMessageTo(int message_port_id, - const string16& message, - const std::vector<int>& sent_message_port_ids); - - // NotificationObserver interface. - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details); - - // Handles the details of removing a message port id. Before calling this, - // verify that the message port id exists. - void Erase(int message_port_id); - - struct MessagePort; - typedef std::map<int, MessagePort> MessagePorts; - MessagePorts message_ports_; - - // We need globally unique identifiers for each message port. - int next_message_port_id_; - - // Valid only during IPC message dispatching. - IPC::Message::Sender* sender_; - CallbackWithReturnValue<int>::Type* next_routing_id_; - - NotificationRegistrar registrar_; - - DISALLOW_COPY_AND_ASSIGN(MessagePortDispatcher); -}; - -#endif // CHROME_BROWSER_WORKER_HOST_MESSAGE_PORT_DISPATCHER_H_ diff --git a/chrome/browser/worker_host/message_port_service.cc b/chrome/browser/worker_host/message_port_service.cc new file mode 100644 index 0000000..6638e71 --- /dev/null +++ b/chrome/browser/worker_host/message_port_service.cc @@ -0,0 +1,236 @@ +// 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/message_port_service.h" + +#include "chrome/browser/worker_host/worker_message_filter.h" +#include "chrome/common/worker_messages.h" + +struct MessagePortService::MessagePort { + // |filter| and |route_id| are what we need to send messages to the port. + // |filter| is just a weak pointer since we get notified when its process has + // gone away and remove it. + WorkerMessageFilter* filter; + int route_id; + // A globally unique id for this message port. + int message_port_id; + // The globally unique id of the entangled message port. + int entangled_message_port_id; + // If true, all messages to this message port are queued and not delivered. + bool queue_messages; + QueuedMessages queued_messages; +}; + +MessagePortService* MessagePortService::GetInstance() { + return Singleton<MessagePortService>::get(); +} + +MessagePortService::MessagePortService() + : next_message_port_id_(0) { +} + +MessagePortService::~MessagePortService() { +} + +void MessagePortService::UpdateMessagePort( + int message_port_id, + WorkerMessageFilter* filter, + int routing_id) { + if (!message_ports_.count(message_port_id)) { + NOTREACHED(); + return; + } + + MessagePort& port = message_ports_[message_port_id]; + port.filter = filter; + port.route_id = routing_id; +} + +void MessagePortService::OnWorkerMessageFilterClosing( + WorkerMessageFilter* filter) { + // Check if the (possibly) crashed process had any message ports. + for (MessagePorts::iterator iter = message_ports_.begin(); + iter != message_ports_.end();) { + MessagePorts::iterator cur_item = iter++; + if (cur_item->second.filter == filter) { + Erase(cur_item->first); + } + } +} + +void MessagePortService::Create(int route_id, + WorkerMessageFilter* filter, + int* message_port_id) { + *message_port_id = ++next_message_port_id_; + + MessagePort port; + port.filter = filter; + port.route_id = route_id; + port.message_port_id = *message_port_id; + port.entangled_message_port_id = MSG_ROUTING_NONE; + port.queue_messages = false; + message_ports_[*message_port_id] = port; +} + +void MessagePortService::Destroy(int message_port_id) { + if (!message_ports_.count(message_port_id)) { + NOTREACHED(); + return; + } + + DCHECK(message_ports_[message_port_id].queued_messages.empty()); + Erase(message_port_id); +} + +void MessagePortService::Entangle(int local_message_port_id, + int remote_message_port_id) { + if (!message_ports_.count(local_message_port_id) || + !message_ports_.count(remote_message_port_id)) { + NOTREACHED(); + return; + } + + DCHECK(message_ports_[remote_message_port_id].entangled_message_port_id == + MSG_ROUTING_NONE); + message_ports_[remote_message_port_id].entangled_message_port_id = + local_message_port_id; +} + +void MessagePortService::PostMessage( + int sender_message_port_id, + const string16& message, + const std::vector<int>& sent_message_port_ids) { + if (!message_ports_.count(sender_message_port_id)) { + NOTREACHED(); + return; + } + + int entangled_message_port_id = + message_ports_[sender_message_port_id].entangled_message_port_id; + if (entangled_message_port_id == MSG_ROUTING_NONE) + return; // Process could have crashed. + + if (!message_ports_.count(entangled_message_port_id)) { + NOTREACHED(); + return; + } + + PostMessageTo(entangled_message_port_id, message, sent_message_port_ids); +} + +void MessagePortService::PostMessageTo( + int message_port_id, + const string16& message, + const std::vector<int>& sent_message_port_ids) { + if (!message_ports_.count(message_port_id)) { + NOTREACHED(); + return; + } + for (size_t i = 0; i < sent_message_port_ids.size(); ++i) { + if (!message_ports_.count(sent_message_port_ids[i])) { + NOTREACHED(); + return; + } + } + + MessagePort& entangled_port = message_ports_[message_port_id]; + + std::vector<MessagePort*> sent_ports(sent_message_port_ids.size()); + for (size_t i = 0; i < sent_message_port_ids.size(); ++i) { + sent_ports[i] = &message_ports_[sent_message_port_ids[i]]; + sent_ports[i]->queue_messages = true; + } + + if (entangled_port.queue_messages) { + entangled_port.queued_messages.push_back( + std::make_pair(message, sent_message_port_ids)); + return; + } + + if (!entangled_port.filter) { + NOTREACHED(); + return; + } + + // If a message port was sent around, the new location will need a routing + // id. Instead of having the created port send us a sync message to get it, + // send along with the message. + std::vector<int> new_routing_ids(sent_message_port_ids.size()); + for (size_t i = 0; i < sent_message_port_ids.size(); ++i) { + new_routing_ids[i] = entangled_port.filter->GetNextRoutingID(); + sent_ports[i]->filter = entangled_port.filter; + + // Update the entry for the sent port as it can be in a different process. + sent_ports[i]->route_id = new_routing_ids[i]; + } + + // Now send the message to the entangled port. + entangled_port.filter->Send(new WorkerProcessMsg_Message( + entangled_port.route_id, message, sent_message_port_ids, + new_routing_ids)); +} + +void MessagePortService::QueueMessages(int message_port_id) { + if (!message_ports_.count(message_port_id)) { + NOTREACHED(); + return; + } + + MessagePort& port = message_ports_[message_port_id]; + if (port.filter) { + port.filter->Send(new WorkerProcessMsg_MessagesQueued(port.route_id)); + port.queue_messages = true; + port.filter = NULL; + } +} + +void MessagePortService::SendQueuedMessages( + int message_port_id, + const QueuedMessages& queued_messages) { + if (!message_ports_.count(message_port_id)) { + NOTREACHED(); + return; + } + + // Send the queued messages to the port again. This time they'll reach the + // new location. + MessagePort& port = message_ports_[message_port_id]; + port.queue_messages = false; + port.queued_messages.insert(port.queued_messages.begin(), + queued_messages.begin(), + queued_messages.end()); + SendQueuedMessagesIfPossible(message_port_id); +} + +void MessagePortService::SendQueuedMessagesIfPossible(int message_port_id) { + if (!message_ports_.count(message_port_id)) { + NOTREACHED(); + return; + } + + MessagePort& port = message_ports_[message_port_id]; + if (port.queue_messages || !port.filter) + return; + + for (QueuedMessages::iterator iter = port.queued_messages.begin(); + iter != port.queued_messages.end(); ++iter) { + PostMessageTo(message_port_id, iter->first, iter->second); + } + port.queued_messages.clear(); +} + +void MessagePortService::Erase(int message_port_id) { + MessagePorts::iterator erase_item = message_ports_.find(message_port_id); + DCHECK(erase_item != message_ports_.end()); + + int entangled_id = erase_item->second.entangled_message_port_id; + if (entangled_id != MSG_ROUTING_NONE) { + // Do the disentanglement (and be paranoid about the other side existing + // just in case something unusual happened during entanglement). + if (message_ports_.count(entangled_id)) { + message_ports_[entangled_id].entangled_message_port_id = MSG_ROUTING_NONE; + } + } + message_ports_.erase(erase_item); +} diff --git a/chrome/browser/worker_host/message_port_service.h b/chrome/browser/worker_host/message_port_service.h new file mode 100644 index 0000000..9c30b6e --- /dev/null +++ b/chrome/browser/worker_host/message_port_service.h @@ -0,0 +1,75 @@ +// 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_MESSAGE_PORT_SERVICE_H_ +#define CHROME_BROWSER_WORKER_HOST_MESSAGE_PORT_SERVICE_H_ +#pragma once + +#include <map> +#include <utility> +#include <vector> + +#include "base/basictypes.h" +#include "base/singleton.h" +#include "base/string16.h" +#include "base/task.h" +#include "ipc/ipc_message.h" + +class WorkerMessageFilter; + +class MessagePortService { + public: + typedef std::vector<std::pair<string16, std::vector<int> > > QueuedMessages; + + // Returns the MessagePortService singleton. + static MessagePortService* GetInstance(); + + // These methods correspond to the message port related IPCs. + void Create(int route_id, WorkerMessageFilter* filter, int* message_port_id); + void Destroy(int message_port_id); + void Entangle(int local_message_port_id, int remote_message_port_id); + void PostMessage(int sender_message_port_id, + const string16& message, + const std::vector<int>& sent_message_port_ids); + void QueueMessages(int message_port_id); + void SendQueuedMessages(int message_port_id, + const QueuedMessages& queued_messages); + + // Updates the information needed to reach a message port when it's sent to a + // (possibly different) process. + void UpdateMessagePort( + int message_port_id, + WorkerMessageFilter* filter, + int routing_id); + + void OnWorkerMessageFilterClosing(WorkerMessageFilter* filter); + + // Attempts to send the queued messages for a message port. + void SendQueuedMessagesIfPossible(int message_port_id); + + private: + friend struct DefaultSingletonTraits<MessagePortService>; + + MessagePortService(); + ~MessagePortService(); + + void PostMessageTo(int message_port_id, + const string16& message, + const std::vector<int>& sent_message_port_ids); + + // Handles the details of removing a message port id. Before calling this, + // verify that the message port id exists. + void Erase(int message_port_id); + + struct MessagePort; + typedef std::map<int, MessagePort> MessagePorts; + MessagePorts message_ports_; + + // We need globally unique identifiers for each message port. + int next_message_port_id_; + + DISALLOW_COPY_AND_ASSIGN(MessagePortService); +}; + +#endif // CHROME_BROWSER_WORKER_HOST_MESSAGE_PORT_SERVICE_H_ diff --git a/chrome/browser/worker_host/worker_document_set.cc b/chrome/browser/worker_host/worker_document_set.cc index 3588bb1..0b3c634 100644 --- a/chrome/browser/worker_host/worker_document_set.cc +++ b/chrome/browser/worker_host/worker_document_set.cc @@ -4,32 +4,34 @@ #include "chrome/browser/worker_host/worker_document_set.h" +#include "base/logging.h" + WorkerDocumentSet::WorkerDocumentSet() { } -void WorkerDocumentSet::Add(IPC::Message::Sender* parent, +void WorkerDocumentSet::Add(WorkerMessageFilter* parent, unsigned long long document_id, - int renderer_id, - int render_view_route_id) { - DocumentInfo info(parent, document_id, renderer_id, render_view_route_id); + int render_process_id, + int render_view_id) { + DocumentInfo info(parent, document_id, render_process_id, render_view_id); document_set_.insert(info); } -bool WorkerDocumentSet::Contains(IPC::Message::Sender* parent, +bool WorkerDocumentSet::Contains(WorkerMessageFilter* parent, unsigned long long document_id) const { for (DocumentInfoSet::const_iterator i = document_set_.begin(); i != document_set_.end(); ++i) { - if (i->sender() == parent && i->document_id() == document_id) + if (i->filter() == parent && i->document_id() == document_id) return true; } return false; } -void WorkerDocumentSet::Remove(IPC::Message::Sender* parent, +void WorkerDocumentSet::Remove(WorkerMessageFilter* parent, unsigned long long document_id) { for (DocumentInfoSet::iterator i = document_set_.begin(); i != document_set_.end(); i++) { - if (i->sender() == parent && i->document_id() == document_id) { + if (i->filter() == parent && i->document_id() == document_id) { document_set_.erase(i); break; } @@ -38,14 +40,14 @@ void WorkerDocumentSet::Remove(IPC::Message::Sender* parent, DCHECK(!Contains(parent, document_id)); } -void WorkerDocumentSet::RemoveAll(IPC::Message::Sender* parent) { +void WorkerDocumentSet::RemoveAll(WorkerMessageFilter* parent) { for (DocumentInfoSet::iterator i = document_set_.begin(); i != document_set_.end();) { // Note this idiom is somewhat tricky - calling document_set_.erase(iter) // invalidates any iterators that point to the element being removed, so // bump the iterator beyond the item being removed before calling erase. - if (i->sender() == parent) { + if (i->filter() == parent) { DocumentInfoSet::iterator item_to_delete = i++; document_set_.erase(item_to_delete); } else { @@ -55,12 +57,13 @@ void WorkerDocumentSet::RemoveAll(IPC::Message::Sender* parent) { } WorkerDocumentSet::DocumentInfo::DocumentInfo( - IPC::Message::Sender* sender, unsigned long long document_id, - int renderer_id, int render_view_route_id) - : sender_(sender), + WorkerMessageFilter* filter, unsigned long long document_id, + int render_process_id, int render_view_id) + : filter_(filter), document_id_(document_id), - renderer_id_(renderer_id), - render_view_route_id_(render_view_route_id) { + render_process_id_(render_process_id), + render_view_id_(render_view_id) { } -WorkerDocumentSet::~WorkerDocumentSet() {} +WorkerDocumentSet::~WorkerDocumentSet() { +} diff --git a/chrome/browser/worker_host/worker_document_set.h b/chrome/browser/worker_host/worker_document_set.h index 7894fc4..49da2b6 100644 --- a/chrome/browser/worker_host/worker_document_set.h +++ b/chrome/browser/worker_host/worker_document_set.h @@ -10,7 +10,8 @@ #include "base/basictypes.h" #include "base/ref_counted.h" -#include "ipc/ipc_message.h" + +class WorkerMessageFilter; // The WorkerDocumentSet tracks all of the DOM documents associated with a // set of workers. With nested workers, multiple workers can share the same @@ -23,53 +24,53 @@ class WorkerDocumentSet : public base::RefCounted<WorkerDocumentSet> { // The information we track for each document class DocumentInfo { public: - DocumentInfo(IPC::Message::Sender* sender, unsigned long long document_id, - int renderer_id, int render_view_route_id); - IPC::Message::Sender* sender() const { return sender_; } + DocumentInfo(WorkerMessageFilter* filter, unsigned long long document_id, + int renderer_process_id, int render_view_id); + WorkerMessageFilter* filter() const { return filter_; } unsigned long long document_id() const { return document_id_; } - int renderer_id() const { return renderer_id_; } - int render_view_route_id() const { return render_view_route_id_; } + int render_process_id() const { return render_process_id_; } + int render_view_id() const { return render_view_id_; } // Define operator "<", which is used to determine uniqueness within // the set. bool operator <(const DocumentInfo& other) const { // Items are identical if the sender and document_id are identical, // otherwise create an arbitrary stable ordering based on the document - // id/sender. - if (sender() == other.sender()) { + // id/filter. + if (filter() == other.filter()) { return document_id() < other.document_id(); } else { - return reinterpret_cast<unsigned long long>(sender()) < - reinterpret_cast<unsigned long long>(other.sender()); + return reinterpret_cast<unsigned long long>(filter()) < + reinterpret_cast<unsigned long long>(other.filter()); } } private: - IPC::Message::Sender* sender_; + WorkerMessageFilter* filter_; unsigned long long document_id_; - int renderer_id_; - int render_view_route_id_; + int render_process_id_; + int render_view_id_; }; // Adds a document to a shared worker's document set. Also includes the - // associated renderer_id the document is associated with, to enable + // associated render_process_id the document is associated with, to enable // communication with the parent tab for things like http auth dialogs. - void Add(IPC::Message::Sender* parent, + void Add(WorkerMessageFilter* parent, unsigned long long document_id, - int renderer_id, - int render_view_route_id); + int render_process_id, + int render_view_id); // Checks to see if a document is in a shared worker's document set. - bool Contains(IPC::Message::Sender* parent, + bool Contains(WorkerMessageFilter* parent, unsigned long long document_id) const; // Removes a specific document from a worker's document set when that document // is detached. - void Remove(IPC::Message::Sender* parent, unsigned long long document_id); + void Remove(WorkerMessageFilter* parent, unsigned long long document_id); // Invoked when a render process exits, to remove all associated documents // from a worker's document set. - void RemoveAll(IPC::Message::Sender* parent); + void RemoveAll(WorkerMessageFilter* parent); bool IsEmpty() const { return document_set_.empty(); } diff --git a/chrome/browser/worker_host/worker_message_filter.cc b/chrome/browser/worker_host/worker_message_filter.cc new file mode 100644 index 0000000..b598202 --- /dev/null +++ b/chrome/browser/worker_host/worker_message_filter.cc @@ -0,0 +1,116 @@ +// Copyright (c) 2010 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_message_filter.h" + +#include "chrome/browser/net/chrome_url_request_context.h" +#include "chrome/browser/worker_host/message_port_service.h" +#include "chrome/browser/worker_host/worker_service.h" +#include "chrome/common/net/url_request_context_getter.h" +#include "chrome/common/render_messages.h" +#include "chrome/common/render_messages_params.h" +#include "chrome/common/worker_messages.h" + +WorkerMessageFilter::WorkerMessageFilter( + int render_process_id, + URLRequestContextGetter* request_context, + ResourceDispatcherHost* resource_dispatcher_host, + CallbackWithReturnValue<int>::Type* next_routing_id) + : render_process_id_(render_process_id), + request_context_(request_context), + resource_dispatcher_host_(resource_dispatcher_host), + next_routing_id_(next_routing_id) { +} + +WorkerMessageFilter::~WorkerMessageFilter() { +} + +void WorkerMessageFilter::OnChannelClosing() { + BrowserMessageFilter::OnChannelClosing(); + + MessagePortService::GetInstance()->OnWorkerMessageFilterClosing(this); + WorkerService::GetInstance()->OnWorkerMessageFilterClosing(this); +} + +bool WorkerMessageFilter::OnMessageReceived(const IPC::Message& message, + bool* message_was_ok) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP_EX(WorkerMessageFilter, message, *message_was_ok) + // Worker messages. + // Only sent from renderer for now, until we have nested workers. + IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWorker, OnCreateWorker) + // Only sent from renderer for now, until we have nested workers. + IPC_MESSAGE_HANDLER(ViewHostMsg_LookupSharedWorker, OnLookupSharedWorker) + IPC_MESSAGE_HANDLER(ViewHostMsg_CancelCreateDedicatedWorker, + OnCancelCreateDedicatedWorker) + IPC_MESSAGE_HANDLER(ViewHostMsg_ForwardToWorker, OnForwardToWorker) + // Only sent from renderer. + IPC_MESSAGE_HANDLER(ViewHostMsg_DocumentDetached, OnDocumentDetached) + // Message Port related messages. + IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_CreateMessagePort, + OnCreateMessagePort) + IPC_MESSAGE_FORWARD(WorkerProcessHostMsg_DestroyMessagePort, + MessagePortService::GetInstance(), + MessagePortService::Destroy) + IPC_MESSAGE_FORWARD(WorkerProcessHostMsg_Entangle, + MessagePortService::GetInstance(), + MessagePortService::Entangle) + IPC_MESSAGE_FORWARD(WorkerProcessHostMsg_PostMessage, + MessagePortService::GetInstance(), + MessagePortService::PostMessage) + IPC_MESSAGE_FORWARD(WorkerProcessHostMsg_QueueMessages, + MessagePortService::GetInstance(), + MessagePortService::QueueMessages) + IPC_MESSAGE_FORWARD(WorkerProcessHostMsg_SendQueuedMessages, + MessagePortService::GetInstance(), + MessagePortService::SendQueuedMessages) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP_EX() + + return handled; +} + +int WorkerMessageFilter::GetNextRoutingID() { + return next_routing_id_->Run(); +} + +void WorkerMessageFilter::OnCreateWorker( + const ViewHostMsg_CreateWorker_Params& params, + int* route_id) { + *route_id = params.route_id != MSG_ROUTING_NONE ? + params.route_id : next_routing_id_->Run(); + WorkerService::GetInstance()->CreateWorker( + params, *route_id, this, request_context_); +} + +void WorkerMessageFilter::OnLookupSharedWorker( + const ViewHostMsg_CreateWorker_Params& params, + bool* exists, + int* route_id, + bool* url_error) { + *route_id = next_routing_id_->Run(); + + bool off_the_record = static_cast<ChromeURLRequestContext*>( + request_context_->GetURLRequestContext())->is_off_the_record(); + WorkerService::GetInstance()->LookupSharedWorker( + params, *route_id, this, off_the_record, exists, url_error); +} + +void WorkerMessageFilter::OnCancelCreateDedicatedWorker(int route_id) { + WorkerService::GetInstance()->CancelCreateDedicatedWorker(route_id, this); +} + +void WorkerMessageFilter::OnForwardToWorker(const IPC::Message& message) { + WorkerService::GetInstance()->ForwardToWorker(message, this); +} + +void WorkerMessageFilter::OnDocumentDetached(unsigned long long document_id) { + WorkerService::GetInstance()->DocumentDetached(document_id, this); +} + +void WorkerMessageFilter::OnCreateMessagePort(int *route_id, + int* message_port_id) { + *route_id = next_routing_id_->Run(); + MessagePortService::GetInstance()->Create(*route_id, this, message_port_id); +} diff --git a/chrome/browser/worker_host/worker_message_filter.h b/chrome/browser/worker_host/worker_message_filter.h new file mode 100644 index 0000000..2e32dab --- /dev/null +++ b/chrome/browser/worker_host/worker_message_filter.h @@ -0,0 +1,62 @@ +// Copyright (c) 2010 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_MESSAGE_FILTER_H_ +#define CHROME_BROWSER_WORKER_HOST_WORKER_MESSAGE_FILTER_H_ + +#include "base/callback.h" +#include "chrome/browser/browser_message_filter.h" + +class ResourceDispatcherHost; +class URLRequestContextGetter; +struct ViewHostMsg_CreateWorker_Params; + +class WorkerMessageFilter : public BrowserMessageFilter { + public: + // |next_routing_id| is owned by this object. It can be used up until + // OnChannelClosing. + WorkerMessageFilter( + int render_process_id, + URLRequestContextGetter* request_context, + ResourceDispatcherHost* resource_dispatcher_host, + CallbackWithReturnValue<int>::Type* next_routing_id); + + // BrowserMessageFilter implementation. + virtual void OnChannelClosing(); + virtual bool OnMessageReceived(const IPC::Message& message, + bool* message_was_ok); + + int GetNextRoutingID(); + int render_process_id() const { return render_process_id_; } + ResourceDispatcherHost* resource_dispatcher_host() const { + return resource_dispatcher_host_; + } + + private: + ~WorkerMessageFilter(); + + // Message handlers. + void OnCreateWorker(const ViewHostMsg_CreateWorker_Params& params, + int* route_id); + void OnLookupSharedWorker(const ViewHostMsg_CreateWorker_Params& params, + bool* exists, + int* route_id, + bool* url_error); + void OnCancelCreateDedicatedWorker(int route_id); + void OnForwardToWorker(const IPC::Message& message); + void OnDocumentDetached(unsigned long long document_id); + void OnCreateMessagePort(int* route_id, int* message_port_id); + + int render_process_id_; + scoped_refptr<URLRequestContextGetter> request_context_; + ResourceDispatcherHost* resource_dispatcher_host_; + + // This is guaranteed to be valid until OnChannelClosing is closed, and it's + // not used after. + scoped_ptr<CallbackWithReturnValue<int>::Type> next_routing_id_; + + DISALLOW_IMPLICIT_CONSTRUCTORS(WorkerMessageFilter); +}; + +#endif // CHROME_BROWSER_WORKER_HOST_WORKER_MESSAGE_FILTER_H_ diff --git a/chrome/browser/worker_host/worker_process_host.cc b/chrome/browser/worker_host/worker_process_host.cc index 7c58421..cc3e9e2 100644 --- a/chrome/browser/worker_host/worker_process_host.cc +++ b/chrome/browser/worker_host/worker_process_host.cc @@ -19,20 +19,18 @@ #include "chrome/browser/file_system/file_system_dispatcher_host.h" #include "chrome/browser/mime_registry_message_filter.h" #include "chrome/browser/net/chrome_url_request_context.h" -#include "chrome/browser/profiles/profile.h" #include "chrome/browser/renderer_host/blob_message_filter.h" #include "chrome/browser/renderer_host/database_message_filter.h" #include "chrome/browser/renderer_host/file_utilities_message_filter.h" -#include "chrome/browser/renderer_host/render_message_filter.h" #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/renderer_host/render_view_host_delegate.h" #include "chrome/browser/renderer_host/render_view_host_notification_task.h" #include "chrome/browser/renderer_host/socket_stream_dispatcher_host.h" -#include "chrome/browser/worker_host/message_port_dispatcher.h" +#include "chrome/browser/worker_host/message_port_service.h" +#include "chrome/browser/worker_host/worker_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/notification_service.h" #include "chrome/common/render_messages.h" #include "chrome/common/render_messages_params.h" #include "chrome/common/result_codes.h" @@ -91,20 +89,12 @@ class WorkerCrashTask : public Task { WorkerProcessHost::WorkerProcessHost( ResourceDispatcherHost* resource_dispatcher_host, - ChromeURLRequestContext *request_context) + URLRequestContextGetter* request_context) : BrowserChildProcessHost(WORKER_PROCESS, resource_dispatcher_host), request_context_(request_context) { - next_route_id_callback_.reset(NewCallbackWithReturnValue( - WorkerService::GetInstance(), &WorkerService::next_worker_route_id)); } WorkerProcessHost::~WorkerProcessHost() { - // Let interested observers know we are being deleted. - NotificationService::current()->Notify( - NotificationType::WORKER_PROCESS_HOST_SHUTDOWN, - Source<WorkerProcessHost>(this), - NotificationService::NoDetails()); - // If we crashed, tell the RenderViewHosts. for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) { const WorkerDocumentSet::DocumentInfoSet& parents = @@ -113,15 +103,15 @@ WorkerProcessHost::~WorkerProcessHost() { parents.begin(); parent_iter != parents.end(); ++parent_iter) { BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, - new WorkerCrashTask(parent_iter->renderer_id(), - parent_iter->render_view_route_id())); + new WorkerCrashTask(parent_iter->render_process_id(), + parent_iter->render_view_id())); } } ChildProcessSecurityPolicy::GetInstance()->Remove(id()); } -bool WorkerProcessHost::Init() { +bool WorkerProcessHost::Init(int render_process_id) { if (!CreateChannel()) return false; @@ -195,7 +185,7 @@ bool WorkerProcessHost::Init() { // requests them. ChildProcessSecurityPolicy::GetInstance()->GrantPermissionsForFile( id(), - request_context_->file_system_context()-> + GetChromeURLRequestContext()->file_system_context()-> path_manager()->base_path(), base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_CREATE | @@ -210,26 +200,35 @@ bool WorkerProcessHost::Init() { base::PLATFORM_FILE_WRITE_ATTRIBUTES); } - CreateMessageFilters(); + CreateMessageFilters(render_process_id); return true; } -void WorkerProcessHost::CreateMessageFilters() { - AddFilter(new AppCacheDispatcherHost(request_context_, id())); - AddFilter(new FileSystemDispatcherHost(request_context_)); +void WorkerProcessHost::CreateMessageFilters(int render_process_id) { + ChromeURLRequestContext* chrome_url_context = GetChromeURLRequestContext(); + + worker_message_filter_= new WorkerMessageFilter( + render_process_id, + request_context_, + resource_dispatcher_host(), + NewCallbackWithReturnValue( + WorkerService::GetInstance(), &WorkerService::next_worker_route_id)); + AddFilter(worker_message_filter_); + AddFilter(new AppCacheDispatcherHost(chrome_url_context, id())); + AddFilter(new FileSystemDispatcherHost(chrome_url_context)); AddFilter(new FileUtilitiesMessageFilter(id())); AddFilter( - new BlobMessageFilter(id(), request_context_->blob_storage_context())); + new BlobMessageFilter(id(), chrome_url_context->blob_storage_context())); AddFilter(new MimeRegistryMessageFilter()); AddFilter(new DatabaseMessageFilter( - request_context_->database_tracker(), - request_context_->host_content_settings_map())); + chrome_url_context->database_tracker(), + chrome_url_context->host_content_settings_map())); SocketStreamDispatcherHost* socket_stream_dispatcher_host = new SocketStreamDispatcherHost(); socket_stream_dispatcher_host->set_url_request_context_override( - new URLRequestContextOverride(request_context_)); + new URLRequestContextOverride(chrome_url_context)); AddFilter(socket_stream_dispatcher_host); } @@ -251,22 +250,21 @@ void WorkerProcessHost::CreateWorker(const WorkerInstance& instance) { UpdateTitle(); - // Walk all pending senders and let them know the worker has been created + // Walk all pending filters and let them know the worker has been created // (could be more than one in the case where we had to queue up worker // creation because the worker process limit was reached). - for (WorkerInstance::SenderList::const_iterator i = - instance.senders().begin(); - i != instance.senders().end(); ++i) { + for (WorkerInstance::FilterList::const_iterator i = + instance.filters().begin(); + i != instance.filters().end(); ++i) { i->first->Send(new ViewMsg_WorkerCreated(i->second)); } } bool WorkerProcessHost::FilterMessage(const IPC::Message& message, - IPC::Message::Sender* sender) { + WorkerMessageFilter* filter) { for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) { - if (!i->closed() && i->HasSender(sender, message.routing_id())) { - RelayMessage( - message, this, i->worker_route_id(), next_route_id_callback_.get()); + if (!i->closed() && i->HasFilter(filter, message.routing_id())) { + RelayMessage(message, worker_message_filter_, i->worker_route_id()); return true; } } @@ -274,42 +272,18 @@ bool WorkerProcessHost::FilterMessage(const IPC::Message& message, return false; } -// Sent to notify the browser process when a worker context invokes close(), so -// no new connections are sent to shared workers. -void WorkerProcessHost::OnWorkerContextClosed(int worker_route_id) { - for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) { - if (i->worker_route_id() == worker_route_id) { - // Set the closed flag - this will stop any further messages from - // being sent to the worker (messages can still be sent from the worker, - // for exception reporting, etc). - i->set_closed(true); - break; - } - } +void WorkerProcessHost::OnProcessLaunched() { } void WorkerProcessHost::OnMessageReceived(const IPC::Message& message) { bool msg_is_ok = true; - bool handled = - MessagePortDispatcher::GetInstance()->OnMessageReceived( - message, this, next_route_id_callback_.get(), &msg_is_ok); - - if (!handled) { - handled = true; - IPC_BEGIN_MESSAGE_MAP_EX(WorkerProcessHost, message, msg_is_ok) - IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWorker, OnCreateWorker) - IPC_MESSAGE_HANDLER(ViewHostMsg_LookupSharedWorker, OnLookupSharedWorker) - IPC_MESSAGE_HANDLER(ViewHostMsg_CancelCreateDedicatedWorker, - OnCancelCreateDedicatedWorker) - IPC_MESSAGE_HANDLER(WorkerHostMsg_WorkerContextClosed, - OnWorkerContextClosed); - IPC_MESSAGE_HANDLER(ViewHostMsg_ForwardToWorker, - OnForwardToWorker) - IPC_MESSAGE_HANDLER_DELAY_REPLY(WorkerProcessHostMsg_AllowDatabase, - OnAllowDatabase) - IPC_MESSAGE_UNHANDLED(handled = false) + bool handled = true; + IPC_BEGIN_MESSAGE_MAP_EX(WorkerProcessHost, message, msg_is_ok) + IPC_MESSAGE_HANDLER(WorkerHostMsg_WorkerContextClosed, + OnWorkerContextClosed) + IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_AllowDatabase, OnAllowDatabase) + IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP_EX() - } if (!msg_is_ok) { NOTREACHED(); @@ -324,10 +298,8 @@ void WorkerProcessHost::OnMessageReceived(const IPC::Message& message) { if (!i->shared()) { // Don't relay messages from shared workers (all communication is via // the message port). - WorkerInstance::SenderInfo info = i->GetSender(); - CallbackWithReturnValue<int>::Type* next_route_id = - GetNextRouteIdCallback(info.first); - RelayMessage(message, info.first, info.second, next_route_id); + WorkerInstance::FilterInfo info = i->GetFilter(); + RelayMessage(message, info.first, info.second); } if (message.type() == WorkerHostMsg_WorkerContextDestroyed::ID) { @@ -339,31 +311,53 @@ void WorkerProcessHost::OnMessageReceived(const IPC::Message& message) { } } -void WorkerProcessHost::OnProcessLaunched() { +// Sent to notify the browser process when a worker context invokes close(), so +// no new connections are sent to shared workers. +void WorkerProcessHost::OnWorkerContextClosed(int worker_route_id) { + for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) { + if (i->worker_route_id() == worker_route_id) { + // Set the closed flag - this will stop any further messages from + // being sent to the worker (messages can still be sent from the worker, + // for exception reporting, etc). + i->set_closed(true); + break; + } + } } -CallbackWithReturnValue<int>::Type* WorkerProcessHost::GetNextRouteIdCallback( - IPC::Message::Sender* sender) { - // We don't keep callbacks for senders associated with workers, so figure out - // what kind of sender this is, and cast it to the correct class to get the - // callback. - for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); - !iter.Done(); ++iter) { - WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); - if (static_cast<IPC::Message::Sender*>(worker) == sender) - return worker->next_route_id_callback_.get(); - } +void WorkerProcessHost::OnAllowDatabase(int worker_route_id, + const GURL& url, + const string16& name, + const string16& display_name, + unsigned long estimated_size, + bool* result) { + ContentSetting content_setting = GetChromeURLRequestContext()-> + host_content_settings_map()->GetContentSetting( + url, CONTENT_SETTINGS_TYPE_COOKIES, ""); - // Must be a RenderMessageFilter. - return static_cast<RenderMessageFilter*>(sender)->next_route_id_callback(); + *result = content_setting != CONTENT_SETTING_BLOCK; + + // Find the worker instance and forward the message to all attached documents. + for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) { + if (i->worker_route_id() != worker_route_id) + continue; + const WorkerDocumentSet::DocumentInfoSet& documents = + i->worker_document_set()->documents(); + for (WorkerDocumentSet::DocumentInfoSet::const_iterator doc = + documents.begin(); doc != documents.end(); ++doc) { + CallRenderViewHostContentSettingsDelegate( + doc->render_process_id(), doc->render_view_id(), + &RenderViewHostDelegate::ContentSettings::OnWebDatabaseAccessed, + url, name, display_name, estimated_size, !*result); + } + break; + } } void WorkerProcessHost::RelayMessage( const IPC::Message& message, - IPC::Message::Sender* sender, - int route_id, - CallbackWithReturnValue<int>::Type* next_route_id) { - + WorkerMessageFilter* filter, + int route_id) { if (message.type() == WorkerMsg_PostMessage::ID) { // We want to send the receiver a routing id for the new channel, so // crack the message first. @@ -378,19 +372,19 @@ void WorkerProcessHost::RelayMessage( return; for (size_t i = 0; i < sent_message_port_ids.size(); ++i) { - new_routing_ids[i] = next_route_id->Run(); - MessagePortDispatcher::GetInstance()->UpdateMessagePort( - sent_message_port_ids[i], sender, new_routing_ids[i], next_route_id); + new_routing_ids[i] = filter->GetNextRoutingID(); + MessagePortService::GetInstance()->UpdateMessagePort( + sent_message_port_ids[i], filter, new_routing_ids[i]); } - sender->Send(new WorkerMsg_PostMessage( + filter->Send(new WorkerMsg_PostMessage( route_id, msg, sent_message_port_ids, new_routing_ids)); // Send any queued messages to the sent message ports. We can only do this // after sending the above message, since it's the one that sets up the // message port route which the queued messages are sent to. for (size_t i = 0; i < sent_message_port_ids.size(); ++i) { - MessagePortDispatcher::GetInstance()-> + MessagePortService::GetInstance()-> SendQueuedMessagesIfPossible(sent_message_port_ids[i]); } } else if (message.type() == WorkerMsg_Connect::ID) { @@ -401,35 +395,35 @@ void WorkerProcessHost::RelayMessage( &message, &sent_message_port_id, &new_routing_id)) { return; } - new_routing_id = next_route_id->Run(); - MessagePortDispatcher::GetInstance()->UpdateMessagePort( - sent_message_port_id, sender, new_routing_id, next_route_id); + new_routing_id = filter->GetNextRoutingID(); + MessagePortService::GetInstance()->UpdateMessagePort( + sent_message_port_id, filter, new_routing_id); // Resend the message with the new routing id. - sender->Send(new WorkerMsg_Connect( + filter->Send(new WorkerMsg_Connect( route_id, sent_message_port_id, new_routing_id)); // Send any queued messages for the sent port. - MessagePortDispatcher::GetInstance()->SendQueuedMessagesIfPossible( + MessagePortService::GetInstance()->SendQueuedMessagesIfPossible( sent_message_port_id); } else { IPC::Message* new_message = new IPC::Message(message); new_message->set_routing_id(route_id); - sender->Send(new_message); + filter->Send(new_message); return; } } -void WorkerProcessHost::SenderShutdown(IPC::Message::Sender* sender) { +void WorkerProcessHost::FilterShutdown(WorkerMessageFilter* filter) { for (Instances::iterator i = instances_.begin(); i != instances_.end();) { bool shutdown = false; - i->RemoveSenders(sender); + i->RemoveFilters(filter); if (i->shared()) { - i->worker_document_set()->RemoveAll(sender); + i->worker_document_set()->RemoveAll(filter); if (i->worker_document_set()->IsEmpty()) { shutdown = true; } - } else if (i->NumSenders() == 0) { + } else if (i->NumFilters() == 0) { shutdown = true; } if (shutdown) { @@ -456,8 +450,7 @@ void WorkerProcessHost::UpdateTitle() { // Check if it's an extension-created worker, in which case we want to use // the name of the extension. - std::string extension_name = static_cast<ChromeURLRequestContext*>( - Profile::GetDefaultRequestContext()->GetURLRequestContext())-> + std::string extension_name = GetChromeURLRequestContext()-> extension_info_map()->GetNameForExtension(title); if (!extension_name.empty()) { titles.insert(extension_name); @@ -481,96 +474,19 @@ void WorkerProcessHost::UpdateTitle() { set_name(ASCIIToWide(display_title)); } -void WorkerProcessHost::OnLookupSharedWorker( - const ViewHostMsg_CreateWorker_Params& params, - bool* exists, - int* route_id, - bool* url_mismatch) { - *route_id = WorkerService::GetInstance()->next_worker_route_id(); - // TODO(atwilson): Add code to pass in the current worker's document set for - // these nested workers. Code below will not work for SharedWorkers as it - // only looks at a single parent. - DCHECK(instances_.front().worker_document_set()->documents().size() == 1); - WorkerDocumentSet::DocumentInfoSet::const_iterator first_parent = - instances_.front().worker_document_set()->documents().begin(); - *exists = WorkerService::GetInstance()->LookupSharedWorker( - params.url, params.name, instances_.front().off_the_record(), - params.document_id, first_parent->renderer_id(), - first_parent->render_view_route_id(), this, *route_id, url_mismatch); -} - -void WorkerProcessHost::OnCreateWorker( - const ViewHostMsg_CreateWorker_Params& params, int* route_id) { - DCHECK(instances_.size() == 1); // Only called when one process per worker. - // TODO(atwilson): Add code to pass in the current worker's document set for - // these nested workers. Code below will not work for SharedWorkers as it - // only looks at a single parent. - DCHECK(instances_.front().worker_document_set()->documents().size() == 1); - WorkerDocumentSet::DocumentInfoSet::const_iterator first_parent = - instances_.front().worker_document_set()->documents().begin(); - *route_id = params.route_id == MSG_ROUTING_NONE ? - WorkerService::GetInstance()->next_worker_route_id() : params.route_id; - - if (params.is_shared) - WorkerService::GetInstance()->CreateSharedWorker( - params.url, instances_.front().off_the_record(), - params.name, params.document_id, first_parent->renderer_id(), - first_parent->render_view_route_id(), this, *route_id, - params.script_resource_appcache_id, request_context_); - else - WorkerService::GetInstance()->CreateDedicatedWorker( - params.url, instances_.front().off_the_record(), - params.document_id, first_parent->renderer_id(), - first_parent->render_view_route_id(), this, *route_id, - id(), params.parent_appcache_host_id, request_context_); -} - -void WorkerProcessHost::OnCancelCreateDedicatedWorker(int route_id) { - WorkerService::GetInstance()->CancelCreateDedicatedWorker(this, route_id); -} - -void WorkerProcessHost::OnForwardToWorker(const IPC::Message& message) { - WorkerService::GetInstance()->ForwardMessage(message, this); -} - -void WorkerProcessHost::OnAllowDatabase(const GURL& url, - const string16& name, - const string16& display_name, - unsigned long estimated_size, - IPC::Message* reply_msg) { - ContentSetting content_setting = - request_context_->host_content_settings_map()->GetContentSetting( - url, CONTENT_SETTINGS_TYPE_COOKIES, ""); - - bool allowed = content_setting != CONTENT_SETTING_BLOCK; - - // Find the worker instance and forward the message to all attached documents. - for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) { - if (i->worker_route_id() != reply_msg->routing_id()) - continue; - const WorkerDocumentSet::DocumentInfoSet& documents = - i->worker_document_set()->documents(); - for (WorkerDocumentSet::DocumentInfoSet::const_iterator doc = - documents.begin(); doc != documents.end(); ++doc) { - CallRenderViewHostContentSettingsDelegate( - doc->renderer_id(), doc->render_view_route_id(), - &RenderViewHostDelegate::ContentSettings::OnWebDatabaseAccessed, - url, name, display_name, estimated_size, !allowed); - } - break; - } - WorkerProcessHostMsg_AllowDatabase::WriteReplyParams(reply_msg, allowed); - Send(reply_msg); +ChromeURLRequestContext* WorkerProcessHost::GetChromeURLRequestContext() { + return static_cast<ChromeURLRequestContext*>( + request_context_->GetURLRequestContext()); } -void WorkerProcessHost::DocumentDetached(IPC::Message::Sender* parent, +void WorkerProcessHost::DocumentDetached(WorkerMessageFilter* filter, unsigned long long document_id) { // Walk all instances and remove the document from their document set. for (Instances::iterator i = instances_.begin(); i != instances_.end();) { if (!i->shared()) { ++i; } else { - i->worker_document_set()->Remove(parent, document_id); + i->worker_document_set()->Remove(filter, document_id); if (i->worker_document_set()->IsEmpty()) { // This worker has no more associated documents - shut it down. Send(new WorkerMsg_TerminateWorkerContext(i->worker_route_id())); @@ -591,7 +507,7 @@ WorkerProcessHost::WorkerInstance::WorkerInstance( int parent_process_id, int parent_appcache_host_id, int64 main_resource_appcache_id, - ChromeURLRequestContext* request_context) + URLRequestContextGetter* request_context) : url_(url), shared_(shared), off_the_record_(off_the_record), @@ -603,8 +519,6 @@ WorkerProcessHost::WorkerInstance::WorkerInstance( main_resource_appcache_id_(main_resource_appcache_id), request_context_(request_context), worker_document_set_(new WorkerDocumentSet()) { - DCHECK(!request_context || - (off_the_record == request_context->is_off_the_record())); } WorkerProcessHost::WorkerInstance::~WorkerInstance() { @@ -635,65 +549,65 @@ bool WorkerProcessHost::WorkerInstance::Matches( return name_ == match_name; } -void WorkerProcessHost::WorkerInstance::AddSender(IPC::Message::Sender* sender, - int sender_route_id) { - if (!HasSender(sender, sender_route_id)) { - SenderInfo info(sender, sender_route_id); - senders_.push_back(info); +void WorkerProcessHost::WorkerInstance::AddFilter(WorkerMessageFilter* filter, + int route_id) { + if (!HasFilter(filter, route_id)) { + FilterInfo info(filter, route_id); + filters_.push_back(info); } - // Only shared workers can have more than one associated sender. - DCHECK(shared_ || senders_.size() == 1); + // Only shared workers can have more than one associated filter. + DCHECK(shared_ || filters_.size() == 1); } -void WorkerProcessHost::WorkerInstance::RemoveSender( - IPC::Message::Sender* sender, int sender_route_id) { - for (SenderList::iterator i = senders_.begin(); i != senders_.end();) { - if (i->first == sender && i->second == sender_route_id) - i = senders_.erase(i); +void WorkerProcessHost::WorkerInstance::RemoveFilter( + WorkerMessageFilter* filter, int route_id) { + for (FilterList::iterator i = filters_.begin(); i != filters_.end();) { + if (i->first == filter && i->second == route_id) + i = filters_.erase(i); else ++i; } - // Should not be duplicate copies in the sender set. - DCHECK(!HasSender(sender, sender_route_id)); + // Should not be duplicate copies in the filter set. + DCHECK(!HasFilter(filter, route_id)); } -void WorkerProcessHost::WorkerInstance::RemoveSenders( - IPC::Message::Sender* sender) { - for (SenderList::iterator i = senders_.begin(); i != senders_.end();) { - if (i->first == sender) - i = senders_.erase(i); +void WorkerProcessHost::WorkerInstance::RemoveFilters( + WorkerMessageFilter* filter) { + for (FilterList::iterator i = filters_.begin(); i != filters_.end();) { + if (i->first == filter) + i = filters_.erase(i); else ++i; } } -bool WorkerProcessHost::WorkerInstance::HasSender( - IPC::Message::Sender* sender, int sender_route_id) const { - for (SenderList::const_iterator i = senders_.begin(); i != senders_.end(); +bool WorkerProcessHost::WorkerInstance::HasFilter( + WorkerMessageFilter* filter, int route_id) const { + for (FilterList::const_iterator i = filters_.begin(); i != filters_.end(); ++i) { - if (i->first == sender && i->second == sender_route_id) + if (i->first == filter && i->second == route_id) return true; } return false; } bool WorkerProcessHost::WorkerInstance::RendererIsParent( - int renderer_id, int render_view_route_id) const { + int render_process_id, int render_view_id) const { const WorkerDocumentSet::DocumentInfoSet& parents = worker_document_set()->documents(); for (WorkerDocumentSet::DocumentInfoSet::const_iterator parent_iter = parents.begin(); parent_iter != parents.end(); ++parent_iter) { - if (parent_iter->renderer_id() == renderer_id && - parent_iter->render_view_route_id() == render_view_route_id) { + if (parent_iter->render_process_id() == render_process_id && + parent_iter->render_view_id() == render_view_id) { return true; } } return false; } -WorkerProcessHost::WorkerInstance::SenderInfo -WorkerProcessHost::WorkerInstance::GetSender() const { - DCHECK(NumSenders() == 1); - return *senders_.begin(); +WorkerProcessHost::WorkerInstance::FilterInfo +WorkerProcessHost::WorkerInstance::GetFilter() const { + DCHECK(NumFilters() == 1); + return *filters_.begin(); } diff --git a/chrome/browser/worker_host/worker_process_host.h b/chrome/browser/worker_host/worker_process_host.h index 39aad8e..150da93 100644 --- a/chrome/browser/worker_host/worker_process_host.h +++ b/chrome/browser/worker_host/worker_process_host.h @@ -9,26 +9,19 @@ #include <list> #include "base/basictypes.h" -#include "base/callback.h" #include "base/file_path.h" #include "chrome/browser/browser_child_process_host.h" #include "chrome/browser/net/chrome_url_request_context.h" #include "chrome/browser/worker_host/worker_document_set.h" #include "googleurl/src/gurl.h" -class ChromeURLRequestContext; -class ChromeURLRequestContextGetter; -namespace webkit_database { -class DatabaseTracker; -} // namespace webkit_database - -struct ViewHostMsg_CreateWorker_Params; +class URLRequestContextGetter; // The WorkerProcessHost is the interface that represents the browser side of // the browser <-> worker communication channel. There will be one // WorkerProcessHost per worker process. Currently each worker runs in its own // process, but that may change. However, we do assume [by storing a -// ChromeURLRequestContext] that a WorkerProcessHost serves a single Profile. +// URLRequestContext] that a WorkerProcessHost serves a single Profile. class WorkerProcessHost : public BrowserChildProcessHost { public: @@ -44,24 +37,24 @@ class WorkerProcessHost : public BrowserChildProcessHost { int parent_process_id, int parent_appcache_host_id, int64 main_resource_appcache_id, - ChromeURLRequestContext* request_context); + URLRequestContextGetter* request_context); ~WorkerInstance(); // Unique identifier for a worker client. - typedef std::pair<IPC::Message::Sender*, int> SenderInfo; + typedef std::pair<WorkerMessageFilter*, int> FilterInfo; - // APIs to manage the sender list for a given instance. - void AddSender(IPC::Message::Sender* sender, int sender_route_id); - void RemoveSender(IPC::Message::Sender* sender, int sender_route_id); - void RemoveSenders(IPC::Message::Sender* sender); - bool HasSender(IPC::Message::Sender* sender, int sender_route_id) const; - bool RendererIsParent(int renderer_id, int render_view_route_id) const; - int NumSenders() const { return senders_.size(); } - // Returns the single sender (must only be one). - SenderInfo GetSender() const; + // APIs to manage the filter list for a given instance. + void AddFilter(WorkerMessageFilter* filter, int route_id); + void RemoveFilter(WorkerMessageFilter* filter, int route_id); + void RemoveFilters(WorkerMessageFilter* filter); + bool HasFilter(WorkerMessageFilter* filter, int route_id) const; + bool RendererIsParent(int render_process_id, int render_view_id) const; + int NumFilters() const { return filters_.size(); } + // Returns the single filter (must only be one). + FilterInfo GetFilter() const; - typedef std::list<SenderInfo> SenderList; - const SenderList& senders() const { return senders_; } + typedef std::list<FilterInfo> FilterList; + const FilterList& filters() const { return filters_; } // Checks if this WorkerInstance matches the passed url/name params // (per the comparison algorithm in the WebWorkers spec). This API only @@ -92,12 +85,12 @@ class WorkerProcessHost : public BrowserChildProcessHost { WorkerDocumentSet* worker_document_set() const { return worker_document_set_; } - ChromeURLRequestContext* request_context() const { + URLRequestContextGetter* request_context() const { return request_context_; } private: - // Set of all senders (clients) associated with this worker. + // Set of all filters (clients) associated with this worker. GURL url_; bool shared_; bool off_the_record_; @@ -107,34 +100,36 @@ class WorkerProcessHost : public BrowserChildProcessHost { int parent_process_id_; int parent_appcache_host_id_; int64 main_resource_appcache_id_; - scoped_refptr<ChromeURLRequestContext> request_context_; - SenderList senders_; + scoped_refptr<URLRequestContextGetter> request_context_; + FilterList filters_; scoped_refptr<WorkerDocumentSet> worker_document_set_; }; WorkerProcessHost( ResourceDispatcherHost* resource_dispatcher_host, - ChromeURLRequestContext* request_context); + URLRequestContextGetter* request_context); ~WorkerProcessHost(); // Starts the process. Returns true iff it succeeded. - bool Init(); + // |render_process_id| is the renderer process responsible for starting this + // worker. + bool Init(int render_process_id); // Creates a worker object in the process. void CreateWorker(const WorkerInstance& instance); // Returns true iff the given message from a renderer process was forwarded to // the worker. - bool FilterMessage(const IPC::Message& message, IPC::Message::Sender* sender); + bool FilterMessage(const IPC::Message& message, WorkerMessageFilter* filter); - void SenderShutdown(IPC::Message::Sender* sender); + void FilterShutdown(WorkerMessageFilter* filter); // Shuts down any shared workers that are no longer referenced by active // documents. - void DocumentDetached(IPC::Message::Sender* sender, + void DocumentDetached(WorkerMessageFilter* filter, unsigned long long document_id); - ChromeURLRequestContext* request_context() const { + URLRequestContextGetter* request_context() const { return request_context_; } @@ -146,61 +141,45 @@ class WorkerProcessHost : public BrowserChildProcessHost { Instances& mutable_instances() { return instances_; } private: - // IPC::Channel::Listener implementation: - // Called when a message arrives from the worker process. - virtual void OnMessageReceived(const IPC::Message& message); - - // Creates and adds the message filters. - void CreateMessageFilters(); - // Called when the process has been launched successfully. virtual void OnProcessLaunched(); - // Called when the app invokes close() from within worker context. - void OnWorkerContextClosed(int worker_route_id); + // Creates and adds the message filters. + void CreateMessageFilters(int render_process_id); - // Called if a worker tries to connect to a shared worker. - void OnLookupSharedWorker(const ViewHostMsg_CreateWorker_Params& params, - bool* exists, - int* route_id, - bool* url_error); + // IPC::Channel::Listener implementation: + // Called when a message arrives from the worker process. + virtual void OnMessageReceived(const IPC::Message& message); - // Given a Sender, returns the callback that generates a new routing id. - static CallbackWithReturnValue<int>::Type* GetNextRouteIdCallback( - IPC::Message::Sender* sender); + void OnWorkerContextClosed(int worker_route_id); + void OnAllowDatabase(int worker_route_id, + const GURL& url, + const string16& name, + const string16& display_name, + unsigned long estimated_size, + bool* result); // Relays a message to the given endpoint. Takes care of parsing the message // if it contains a message port and sending it a valid route id. static void RelayMessage(const IPC::Message& message, - IPC::Message::Sender* sender, - int route_id, - CallbackWithReturnValue<int>::Type* next_route_id); + WorkerMessageFilter* filter, + int route_id); virtual bool CanShutdown(); // Updates the title shown in the task manager. void UpdateTitle(); - void OnCreateWorker(const ViewHostMsg_CreateWorker_Params& params, - int* route_id); - void OnCancelCreateDedicatedWorker(int route_id); - void OnForwardToWorker(const IPC::Message& message); - - // Checks the content settings whether access to web databases is enabled and - // relays the WebDatabaseAccessed message to all documents attached to a - // worker. - void OnAllowDatabase(const GURL& url, - const string16& name, - const string16& display_name, - unsigned long estimated_size, - IPC::Message* reply_msg); + ChromeURLRequestContext* GetChromeURLRequestContext(); Instances instances_; - scoped_refptr<ChromeURLRequestContext> request_context_; + scoped_refptr<URLRequestContextGetter> request_context_; - // A callback to create a routing id for the associated worker process. - scoped_ptr<CallbackWithReturnValue<int>::Type> next_route_id_callback_; + // A reference to the filter associated with this worker process. We need to + // keep this around since we'll use it when forward messages to the worker + // process. + scoped_refptr<WorkerMessageFilter> worker_message_filter_; DISALLOW_COPY_AND_ASSIGN(WorkerProcessHost); }; diff --git a/chrome/browser/worker_host/worker_service.cc b/chrome/browser/worker_host/worker_service.cc index e623db1..cea298d 100644 --- a/chrome/browser/worker_host/worker_service.cc +++ b/chrome/browser/worker_host/worker_service.cc @@ -11,13 +11,11 @@ #include "base/sys_info.h" #include "base/thread.h" #include "chrome/browser/content_settings/host_content_settings_map.h" -#include "chrome/browser/plugin_service.h" -#include "chrome/browser/renderer_host/render_message_filter.h" -#include "chrome/browser/renderer_host/render_process_host.h" +#include "chrome/browser/worker_host/worker_message_filter.h" #include "chrome/browser/worker_host/worker_process_host.h" #include "chrome/common/chrome_switches.h" -#include "chrome/common/notification_service.h" #include "chrome/common/render_messages.h" +#include "chrome/common/render_messages_params.h" #include "chrome/common/worker_messages.h" #include "net/base/registry_controlled_domain.h" @@ -29,97 +27,205 @@ WorkerService* WorkerService::GetInstance() { return Singleton<WorkerService>::get(); } -WorkerService::WorkerService() - : next_worker_route_id_(0), - resource_dispatcher_host_(NULL) { - // Receive a notification if a message filter or WorkerProcessHost is deleted. - registrar_.Add(this, NotificationType::RESOURCE_MESSAGE_FILTER_SHUTDOWN, - NotificationService::AllSources()); - - registrar_.Add(this, NotificationType::WORKER_PROCESS_HOST_SHUTDOWN, - NotificationService::AllSources()); -} - -void WorkerService::Initialize(ResourceDispatcherHost* rdh) { - resource_dispatcher_host_ = rdh; +WorkerService::WorkerService() : next_worker_route_id_(0) { } WorkerService::~WorkerService() { } -bool WorkerService::CreateDedicatedWorker( - const GURL& url, - bool is_off_the_record, - unsigned long long document_id, - int renderer_pid, - int render_view_route_id, - IPC::Message::Sender* sender, - int sender_route_id, - int parent_process_id, - int parent_appcache_host_id, - ChromeURLRequestContext* request_context) { - return CreateWorker(url, false, is_off_the_record, string16(), - document_id, renderer_pid, render_view_route_id, - sender, sender_route_id, - parent_process_id, parent_appcache_host_id, 0, - request_context); -} +void WorkerService::OnWorkerMessageFilterClosing(WorkerMessageFilter* filter) { + for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); + !iter.Done(); ++iter) { + WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); + worker->FilterShutdown(filter); + } + + // See if that process had any queued workers. + for (WorkerProcessHost::Instances::iterator i = queued_workers_.begin(); + i != queued_workers_.end();) { + i->RemoveFilters(filter); + if (i->NumFilters() == 0) { + i = queued_workers_.erase(i); + } else { + ++i; + } + } -bool WorkerService::CreateSharedWorker( - const GURL& url, - bool is_off_the_record, - const string16& name, - unsigned long long document_id, - int renderer_pid, - int render_view_route_id, - IPC::Message::Sender* sender, - int sender_route_id, - int64 main_resource_appcache_id, - ChromeURLRequestContext* request_context) { - return CreateWorker(url, true, is_off_the_record, name, - document_id, renderer_pid, render_view_route_id, - sender, sender_route_id, - 0, 0, main_resource_appcache_id, - request_context); + // Also, see if that process had any pending shared workers. + for (WorkerProcessHost::Instances::iterator iter = + pending_shared_workers_.begin(); + iter != pending_shared_workers_.end(); ) { + iter->worker_document_set()->RemoveAll(filter); + if (iter->worker_document_set()->IsEmpty()) { + iter = pending_shared_workers_.erase(iter); + } else { + ++iter; + } + } + + // Either a worker proceess has shut down, in which case we can start one of + // the queued workers, or a renderer has shut down, in which case it doesn't + // affect anything. We call this function in both scenarios because then we + // don't have to keep track which filters are from worker processes. + TryStartingQueuedWorker(); } -bool WorkerService::CreateWorker( - const GURL& url, - bool is_shared, - bool off_the_record, - const string16& name, - unsigned long long document_id, - int renderer_id, - int render_view_route_id, - IPC::Message::Sender* sender, - int sender_route_id, - int parent_process_id, - int parent_appcache_host_id, - int64 main_resource_appcache_id, - ChromeURLRequestContext* request_context) { +void WorkerService::CreateWorker(const ViewHostMsg_CreateWorker_Params& params, + int route_id, + WorkerMessageFilter* filter, + URLRequestContextGetter* request_context) { + + ChromeURLRequestContext* context = static_cast<ChromeURLRequestContext*>( + request_context->GetURLRequestContext()); + // 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. - WorkerProcessHost::WorkerInstance instance(url, - is_shared, - off_the_record, - name, - next_worker_route_id(), - parent_process_id, - parent_appcache_host_id, - main_resource_appcache_id, - request_context); - instance.AddSender(sender, sender_route_id); + WorkerProcessHost::WorkerInstance instance( + params.url, + params.is_shared, + context->is_off_the_record(), + params.name, + next_worker_route_id(), + params.is_shared ? 0 : filter->render_process_id(), + params.is_shared ? 0 : params.parent_appcache_host_id, + params.is_shared ? params.script_resource_appcache_id : 0, + request_context); + instance.AddFilter(filter, route_id); instance.worker_document_set()->Add( - sender, document_id, renderer_id, render_view_route_id); + filter, params.document_id, filter->render_process_id(), + params.render_view_route_id); + + CreateWorkerFromInstance(instance); +} + +void WorkerService::LookupSharedWorker( + const ViewHostMsg_CreateWorker_Params& params, + int route_id, + WorkerMessageFilter* filter, + bool off_the_record, + bool* exists, + bool* url_mismatch) { + + *exists = true; + WorkerProcessHost::WorkerInstance* instance = FindSharedWorkerInstance( + params.url, params.name, off_the_record); + + if (!instance) { + // If no worker instance currently exists, we need to create a pending + // instance - this is to make sure that any subsequent lookups passing a + // mismatched URL get the appropriate url_mismatch error at lookup time. + // Having named shared workers was a Really Bad Idea due to details like + // this. + instance = CreatePendingInstance(params.url, params.name, off_the_record); + *exists = false; + } + + // Make sure the passed-in instance matches the URL - if not, return an + // error. + if (params.url != instance->url()) { + *url_mismatch = true; + *exists = false; + } else { + *url_mismatch = false; + // Add our route ID to the existing instance so we can send messages to it. + instance->AddFilter(filter, route_id); + + // Add the passed filter/document_id to the worker instance. + // TODO(atwilson): This won't work if the message is from a worker process. + // We don't support that yet though (this message is only sent from + // renderers) but when we do, we'll need to add code to pass in the current + // worker's document set for nested workers. + instance->worker_document_set()->Add( + filter, params.document_id, filter->render_process_id(), + params.render_view_route_id); + } +} + +void WorkerService::CancelCreateDedicatedWorker( + int route_id, + WorkerMessageFilter* filter) { + for (WorkerProcessHost::Instances::iterator i = queued_workers_.begin(); + i != queued_workers_.end(); ++i) { + if (i->HasFilter(filter, route_id)) { + DCHECK(!i->shared()); + queued_workers_.erase(i); + return; + } + } + + // There could be a race condition where the WebWorkerProxy told us to cancel + // the worker right as we sent it a message say it's been created. Look at + // the running workers. + for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); + !iter.Done(); ++iter) { + WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); + for (WorkerProcessHost::Instances::const_iterator instance = + worker->instances().begin(); + instance != worker->instances().end(); ++instance) { + if (instance->HasFilter(filter, route_id)) { + // Fake a worker destroyed message so that WorkerProcessHost cleans up + // properly. + WorkerHostMsg_WorkerContextDestroyed message(route_id); + ForwardToWorker(message, filter); + return; + } + } + } + + DCHECK(false) << "Couldn't find worker to cancel"; +} + +void WorkerService::ForwardToWorker(const IPC::Message& message, + WorkerMessageFilter* filter) { + for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); + !iter.Done(); ++iter) { + WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); + if (worker->FilterMessage(message, filter)) + return; + } + + // TODO(jabdelmalek): tell filter that callee is gone +} + +void WorkerService::DocumentDetached(unsigned long long document_id, + WorkerMessageFilter* filter) { + // Any associated shared workers can be shut down. + for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); + !iter.Done(); ++iter) { + WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); + worker->DocumentDetached(filter, document_id); + } - return CreateWorkerFromInstance(instance); + // Remove any queued shared workers for this document. + for (WorkerProcessHost::Instances::iterator iter = queued_workers_.begin(); + iter != queued_workers_.end();) { + if (iter->shared()) { + iter->worker_document_set()->Remove(filter, document_id); + if (iter->worker_document_set()->IsEmpty()) { + iter = queued_workers_.erase(iter); + continue; + } + } + ++iter; + } + + // Remove the document from any pending shared workers. + for (WorkerProcessHost::Instances::iterator iter = + pending_shared_workers_.begin(); + iter != pending_shared_workers_.end(); ) { + iter->worker_document_set()->Remove(filter, document_id); + if (iter->worker_document_set()->IsEmpty()) { + iter = pending_shared_workers_.erase(iter); + } else { + ++iter; + } + } } bool WorkerService::CreateWorkerFromInstance( WorkerProcessHost::WorkerInstance instance) { - // TODO(michaeln): We need to ensure that a process is working // on behalf of a single profile. The process sharing logic below // does not ensure that. Consider making WorkerService a per profile @@ -145,17 +251,17 @@ bool WorkerService::CreateWorkerFromInstance( WorkerProcessHost::WorkerInstance* existing_instance = FindSharedWorkerInstance( instance.url(), instance.name(), instance.off_the_record()); - WorkerProcessHost::WorkerInstance::SenderInfo sender_info = - instance.GetSender(); + WorkerProcessHost::WorkerInstance::FilterInfo filter_info = + instance.GetFilter(); // If this worker is already running, no need to create a new copy. Just // inform the caller that the worker has been created. if (existing_instance) { - // Walk the worker's sender list to see if this client is listed. If not, + // Walk the worker's filter list to see if this client is listed. If not, // then it means that the worker started by the client already exited so // we should not attach to this new one (http://crbug.com/29243). - if (!existing_instance->HasSender(sender_info.first, sender_info.second)) + if (!existing_instance->HasFilter(filter_info.first, filter_info.second)) return false; - sender_info.first->Send(new ViewMsg_WorkerCreated(sender_info.second)); + filter_info.first->Send(new ViewMsg_WorkerCreated(filter_info.second)); return true; } @@ -163,38 +269,38 @@ bool WorkerService::CreateWorkerFromInstance( WorkerProcessHost::WorkerInstance* pending = FindPendingInstance( instance.url(), instance.name(), instance.off_the_record()); // If there's no instance *and* no pending instance (or there is a pending - // instance but it does not contain our sender info), then it means the + // instance but it does not contain our filter info), then it means the // worker started up and exited already. Log a warning because this should // be a very rare occurrence and is probably a bug, but it *can* happen so // handle it gracefully. if (!pending || - !pending->HasSender(sender_info.first, sender_info.second)) { + !pending->HasFilter(filter_info.first, filter_info.second)) { DLOG(WARNING) << "Pending worker already exited"; return false; } - // Assign the accumulated document set and sender list for this pending + // Assign the accumulated document set and filter list for this pending // worker to the new instance. DCHECK(!pending->worker_document_set()->IsEmpty()); instance.ShareDocumentSet(*pending); - for (WorkerProcessHost::WorkerInstance::SenderList::const_iterator i = - pending->senders().begin(); - i != pending->senders().end(); ++i) { - instance.AddSender(i->first, i->second); + for (WorkerProcessHost::WorkerInstance::FilterList::const_iterator i = + pending->filters().begin(); + i != pending->filters().end(); ++i) { + instance.AddFilter(i->first, i->second); } RemovePendingInstances( instance.url(), instance.name(), instance.off_the_record()); - // Remove any queued instances of this worker and copy over the sender to + // Remove any queued instances of this worker and copy over the filter to // this instance. for (WorkerProcessHost::Instances::iterator iter = queued_workers_.begin(); iter != queued_workers_.end();) { if (iter->Matches(instance.url(), instance.name(), instance.off_the_record())) { - DCHECK(iter->NumSenders() == 1); - WorkerProcessHost::WorkerInstance::SenderInfo sender_info = - iter->GetSender(); - instance.AddSender(sender_info.first, sender_info.second); + DCHECK(iter->NumFilters() == 1); + WorkerProcessHost::WorkerInstance::FilterInfo filter_info = + iter->GetFilter(); + instance.AddFilter(filter_info.first, filter_info.second); iter = queued_workers_.erase(iter); } else { ++iter; @@ -203,9 +309,15 @@ bool WorkerService::CreateWorkerFromInstance( } if (!worker) { - worker = new WorkerProcessHost(resource_dispatcher_host_, - instance.request_context()); - if (!worker->Init()) { + WorkerMessageFilter* first_filter = instance.filters().begin()->first; + worker = new WorkerProcessHost( + first_filter->resource_dispatcher_host(), + instance.request_context()); + // TODO(atwilson): This won't work if the message is from a worker process. + // We don't support that yet though (this message is only sent from + // renderers) but when we do, we'll need to add code to pass in the current + // worker's document set for nested workers. + if (!worker->Init(first_filter->render_process_id())) { delete worker; return false; } @@ -219,127 +331,6 @@ bool WorkerService::CreateWorkerFromInstance( return true; } -bool WorkerService::LookupSharedWorker( - const GURL &url, - const string16& name, - bool off_the_record, - unsigned long long document_id, - int renderer_id, - int render_view_route_id, - IPC::Message::Sender* sender, - int sender_route_id, - bool* url_mismatch) { - bool found_instance = true; - WorkerProcessHost::WorkerInstance* instance = - FindSharedWorkerInstance(url, name, off_the_record); - - if (!instance) { - // If no worker instance currently exists, we need to create a pending - // instance - this is to make sure that any subsequent lookups passing a - // mismatched URL get the appropriate url_mismatch error at lookup time. - // Having named shared workers was a Really Bad Idea due to details like - // this. - instance = CreatePendingInstance(url, name, off_the_record); - found_instance = false; - } - - // Make sure the passed-in instance matches the URL - if not, return an - // error. - if (url != instance->url()) { - *url_mismatch = true; - return false; - } else { - *url_mismatch = false; - } - - // Add our route ID to the existing instance so we can send messages to it. - instance->AddSender(sender, sender_route_id); - - // Add the passed sender/document_id to the worker instance. - instance->worker_document_set()->Add( - sender, document_id, renderer_id, render_view_route_id); - return found_instance; -} - -void WorkerService::DocumentDetached(IPC::Message::Sender* sender, - unsigned long long document_id) { - for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); - !iter.Done(); ++iter) { - WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); - worker->DocumentDetached(sender, document_id); - } - - // Remove any queued shared workers for this document. - for (WorkerProcessHost::Instances::iterator iter = queued_workers_.begin(); - iter != queued_workers_.end();) { - if (iter->shared()) { - iter->worker_document_set()->Remove(sender, document_id); - if (iter->worker_document_set()->IsEmpty()) { - iter = queued_workers_.erase(iter); - continue; - } - } - ++iter; - } - - // Remove the document from any pending shared workers. - for (WorkerProcessHost::Instances::iterator iter = - pending_shared_workers_.begin(); - iter != pending_shared_workers_.end(); ) { - iter->worker_document_set()->Remove(sender, document_id); - if (iter->worker_document_set()->IsEmpty()) { - iter = pending_shared_workers_.erase(iter); - } else { - ++iter; - } - } -} - -void WorkerService::CancelCreateDedicatedWorker(IPC::Message::Sender* sender, - int sender_route_id) { - for (WorkerProcessHost::Instances::iterator i = queued_workers_.begin(); - i != queued_workers_.end(); ++i) { - if (i->HasSender(sender, sender_route_id)) { - DCHECK(!i->shared()); - queued_workers_.erase(i); - return; - } - } - - // There could be a race condition where the WebWorkerProxy told us to cancel - // the worker right as we sent it a message say it's been created. Look at - // the running workers. - for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); - !iter.Done(); ++iter) { - WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); - for (WorkerProcessHost::Instances::const_iterator instance = - worker->instances().begin(); - instance != worker->instances().end(); ++instance) { - if (instance->HasSender(sender, sender_route_id)) { - // Fake a worker destroyed message so that WorkerProcessHost cleans up - // properly. - WorkerHostMsg_WorkerContextDestroyed msg(sender_route_id); - ForwardMessage(msg, sender); - return; - } - } - } - - DCHECK(false) << "Couldn't find worker to cancel"; -} - -void WorkerService::ForwardMessage(const IPC::Message& message, - IPC::Message::Sender* sender) { - for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); - !iter.Done(); ++iter) { - WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); - if (worker->FilterMessage(message, sender)) - return; - } - - // TODO(jabdelmalek): tell sender that callee is gone -} - WorkerProcessHost* WorkerService::GetProcessForDomain(const GURL& url) { int num_processes = 0; std::string domain = @@ -398,8 +389,8 @@ bool WorkerService::CanCreateWorkerProcess( parents.begin(); parent_iter != parents.end(); ++parent_iter) { bool hit_total_worker_limit = false; - if (TabCanCreateWorkerProcess(parent_iter->renderer_id(), - parent_iter->render_view_route_id(), + if (TabCanCreateWorkerProcess(parent_iter->render_process_id(), + parent_iter->render_view_id(), &hit_total_worker_limit)) { return true; } @@ -413,8 +404,8 @@ bool WorkerService::CanCreateWorkerProcess( return false; } -bool WorkerService::TabCanCreateWorkerProcess(int renderer_id, - int render_view_route_id, +bool WorkerService::TabCanCreateWorkerProcess(int render_process_id, + int render_view_id, bool* hit_total_worker_limit) { int total_workers = 0; int workers_per_tab = 0; @@ -430,7 +421,7 @@ bool WorkerService::TabCanCreateWorkerProcess(int renderer_id, *hit_total_worker_limit = true; return false; } - if (cur_instance->RendererIsParent(renderer_id, render_view_route_id)) { + if (cur_instance->RendererIsParent(render_process_id, render_view_id)) { workers_per_tab++; if (workers_per_tab >= kMaxWorkersPerTabWhenSeparate) return false; @@ -441,53 +432,7 @@ bool WorkerService::TabCanCreateWorkerProcess(int renderer_id, return true; } -void WorkerService::Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - if (type.value == NotificationType::RESOURCE_MESSAGE_FILTER_SHUTDOWN) { - RenderMessageFilter* sender = Source<RenderMessageFilter>(source).ptr(); - SenderShutdown(sender); - } else if (type.value == NotificationType::WORKER_PROCESS_HOST_SHUTDOWN) { - WorkerProcessHost* sender = Source<WorkerProcessHost>(source).ptr(); - SenderShutdown(sender); - WorkerProcessDestroyed(sender); - } else { - NOTREACHED(); - } -} - -void WorkerService::SenderShutdown(IPC::Message::Sender* sender) { - for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); - !iter.Done(); ++iter) { - WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); - worker->SenderShutdown(sender); - } - - // See if that render process had any queued workers. - for (WorkerProcessHost::Instances::iterator i = queued_workers_.begin(); - i != queued_workers_.end();) { - i->RemoveSenders(sender); - if (i->NumSenders() == 0) { - i = queued_workers_.erase(i); - } else { - ++i; - } - } - - // Also, see if that render process had any pending shared workers. - for (WorkerProcessHost::Instances::iterator iter = - pending_shared_workers_.begin(); - iter != pending_shared_workers_.end(); ) { - iter->worker_document_set()->RemoveAll(sender); - if (iter->worker_document_set()->IsEmpty()) { - iter = pending_shared_workers_.erase(iter); - } else { - ++iter; - } - } -} - -void WorkerService::WorkerProcessDestroyed(WorkerProcessHost* process) { +void WorkerService::TryStartingQueuedWorker() { if (queued_workers_.empty()) return; @@ -510,6 +455,30 @@ void WorkerService::WorkerProcessDestroyed(WorkerProcessHost* process) { } } +bool WorkerService::GetRendererForWorker(int worker_process_id, + int* render_process_id, + int* render_view_id) const { + for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); + !iter.Done(); ++iter) { + if (iter->id() != worker_process_id) + continue; + + // This code assumes one worker per process, see function comment in header! + WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); + WorkerProcessHost::Instances::const_iterator first_instance = + worker->instances().begin(); + if (first_instance == worker->instances().end()) + return false; + + WorkerDocumentSet::DocumentInfoSet::const_iterator info = + first_instance->worker_document_set()->documents().begin(); + *render_process_id = info->render_process_id(); + *render_view_id = info->render_view_id(); + return true; + } + return false; +} + const WorkerProcessHost::WorkerInstance* WorkerService::FindWorkerInstance( int worker_process_id) { for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); diff --git a/chrome/browser/worker_host/worker_service.h b/chrome/browser/worker_host/worker_service.h index 994d11f..7c39d57 100644 --- a/chrome/browser/worker_host/worker_service.h +++ b/chrome/browser/worker_host/worker_service.h @@ -11,83 +11,50 @@ #include "base/basictypes.h" #include "base/singleton.h" #include "chrome/browser/worker_host/worker_process_host.h" -#include "chrome/common/notification_registrar.h" #include "googleurl/src/gurl.h" #include "ipc/ipc_message.h" -class ChromeURLRequestContext; -class ResourceDispatcherHost; +class URLRequestContextGetter; +struct ViewHostMsg_CreateWorker_Params; -class WorkerService : public NotificationObserver { +// A singelton for managing HTML5 web workers. +class WorkerService { public: // Returns the WorkerService singleton. static WorkerService* GetInstance(); - // Initialize the WorkerService. OK to be called multiple times. - void Initialize(ResourceDispatcherHost* rdh); - - // Creates a decidated worker. Returns true on success. - bool CreateDedicatedWorker(const GURL &url, - bool is_off_the_record, - unsigned long long document_id, - int renderer_pid, - int render_view_route_id, - IPC::Message::Sender* sender, - int sender_route_id, - int parent_process_id, - int parent_appcache_host_id, - ChromeURLRequestContext* request_context); - - // Creates a shared worker. Returns true on success. - bool CreateSharedWorker(const GURL &url, - bool is_off_the_record, - const string16& name, - unsigned long long document_id, - int renderer_pid, - int render_view_route_id, - IPC::Message::Sender* sender, - int sender_route_id, - int64 main_resource_appcache_id, - ChromeURLRequestContext* request_context); - - // Validates the passed URL and checks for the existence of matching shared - // worker. Returns true if the url was found, and sets the url_mismatch out - // param to true/false depending on whether there's a url mismatch with an - // existing shared worker with the same name. - bool LookupSharedWorker(const GURL &url, - const string16& name, + // These methods correspond to worker related IPCs. + void CreateWorker(const ViewHostMsg_CreateWorker_Params& params, + int route_id, + WorkerMessageFilter* filter, + URLRequestContextGetter* request_context); + void LookupSharedWorker(const ViewHostMsg_CreateWorker_Params& params, + int route_id, + WorkerMessageFilter* filter, bool off_the_record, - unsigned long long document_id, - int renderer_pid, - int render_view_route_id, - IPC::Message::Sender* sender, - int sender_route_id, - bool* url_mismatch); - - // Notification from the renderer that a given document has detached, so any - // associated shared workers can be shut down. - void DocumentDetached(IPC::Message::Sender* sender, - unsigned long long document_id); - - // Cancel creation of a dedicated worker that hasn't started yet. - void CancelCreateDedicatedWorker(IPC::Message::Sender* sender, - int sender_route_id); - - // Called by the worker creator when a message arrives that should be - // forwarded to the worker process. - void ForwardMessage(const IPC::Message& message, - IPC::Message::Sender* sender); + bool* exists, + bool* url_error); + void CancelCreateDedicatedWorker(int route_id, WorkerMessageFilter* filter); + void ForwardToWorker(const IPC::Message& message, + WorkerMessageFilter* filter); + void DocumentDetached(unsigned long long document_id, + WorkerMessageFilter* filter); + + void OnWorkerMessageFilterClosing(WorkerMessageFilter* filter); int next_worker_route_id() { return ++next_worker_route_id_; } + // Given a worker's process id, return the IDs of the renderer process and + // render view that created it. For shared workers, this returns the first + // parent. // TODO(dimich): This code assumes there is 1 worker per worker process, which // is how it is today until V8 can run in separate threads. + bool GetRendererForWorker(int worker_process_id, + int* render_process_id, + int* render_view_id) const; const WorkerProcessHost::WorkerInstance* FindWorkerInstance( int worker_process_id); - WorkerProcessHost::WorkerInstance* FindSharedWorkerInstance( - const GURL& url, const string16& name, bool off_the_record); - // Used when multiple workers can run in the same process. static const int kMaxWorkerProcessesWhenSharing; @@ -101,20 +68,6 @@ class WorkerService : public NotificationObserver { WorkerService(); ~WorkerService(); - bool CreateWorker(const GURL &url, - bool is_shared, - bool is_off_the_record, - const string16& name, - unsigned long long document_id, - int renderer_pid, - int render_view_route_id, - IPC::Message::Sender* sender, - int sender_route_id, - int parent_process_id, - int parent_appcache_host_id, - int64 main_resource_appcache_id, - ChromeURLRequestContext* request_context); - // Given a WorkerInstance, create an associated worker process. bool CreateWorkerFromInstance(WorkerProcessHost::WorkerInstance instance); @@ -139,18 +92,10 @@ class WorkerService : public NotificationObserver { // worker process based on the process limit when we're using a strategy of // one worker per process. bool TabCanCreateWorkerProcess( - int renderer_id, int render_view_route_id, bool* hit_total_worker_limit); + int render_process_id, int render_route_id, bool* hit_total_worker_limit); - // NotificationObserver interface. - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details); - - // Notifies us that a process that's talking to a worker has shut down. - void SenderShutdown(IPC::Message::Sender* sender); - - // Notifies us that a worker process has closed. - void WorkerProcessDestroyed(WorkerProcessHost* process); + // Tries to see if any of the queued workers can be created. + void TryStartingQueuedWorker(); // APIs for manipulating our set of pending shared worker instances. WorkerProcessHost::WorkerInstance* CreatePendingInstance( @@ -160,9 +105,11 @@ class WorkerService : public NotificationObserver { void RemovePendingInstances( const GURL& url, const string16& name, bool off_the_record); + WorkerProcessHost::WorkerInstance* FindSharedWorkerInstance( + const GURL& url, const string16& name, bool off_the_record); + NotificationRegistrar registrar_; int next_worker_route_id_; - ResourceDispatcherHost* resource_dispatcher_host_; WorkerProcessHost::Instances queued_workers_; diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index b5fabe1..cfe644b 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -3489,10 +3489,12 @@ 'browser/web_applications/web_app.h', 'browser/web_resource/web_resource_service.h', 'browser/web_resource/web_resource_service.cc', - 'browser/worker_host/message_port_dispatcher.cc', - 'browser/worker_host/message_port_dispatcher.h', + 'browser/worker_host/message_port_service.cc', + 'browser/worker_host/message_port_service.h', 'browser/worker_host/worker_document_set.cc', 'browser/worker_host/worker_document_set.h', + 'browser/worker_host/worker_message_filter.cc', + 'browser/worker_host/worker_message_filter.h', 'browser/worker_host/worker_process_host.cc', 'browser/worker_host/worker_process_host.h', 'browser/worker_host/worker_service.cc', diff --git a/chrome/common/notification_type.h b/chrome/common/notification_type.h index 8564063..d27f2f8 100644 --- a/chrome/common/notification_type.h +++ b/chrome/common/notification_type.h @@ -183,16 +183,6 @@ class NotificationType { // change. There are no details. SSL_INTERNAL_STATE_CHANGED, - // Lets resource handlers and other interested observers know when the - // message filter is being deleted and can no longer be used. This will - // also get sent if the renderer crashes (and in that case, it'll be sent - // twice). - RESOURCE_MESSAGE_FILTER_SHUTDOWN, - - // Lets interested observers know when a WorkerProcessHost is being deleted - // and can no longer be used. - WORKER_PROCESS_HOST_SHUTDOWN, - // Views ------------------------------------------------------------------- // Notification that a view was removed from a view hierarchy. The source diff --git a/chrome/common/worker_messages_internal.h b/chrome/common/worker_messages_internal.h index d1ef439..e661f67 100644 --- a/chrome/common/worker_messages_internal.h +++ b/chrome/common/worker_messages_internal.h @@ -76,12 +76,13 @@ IPC_MESSAGE_CONTROL2(WorkerProcessHostMsg_SendQueuedMessages, // Sent by the worker process to check whether access to web databases is // granted by content settings. -IPC_SYNC_MESSAGE_ROUTED4_1(WorkerProcessHostMsg_AllowDatabase, - GURL /* origin url */, - string16 /* database name */, - string16 /* database display name */, - unsigned long /* estimated size */, - bool /* result */) +IPC_SYNC_MESSAGE_CONTROL5_1(WorkerProcessHostMsg_AllowDatabase, + int /* worker_route_id */, + GURL /* origin url */, + string16 /* database name */, + string16 /* database display name */, + unsigned long /* estimated size */, + bool /* result */) //----------------------------------------------------------------------------- // Worker messages |