| // 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/renderer_host/resource_message_filter.h" |
| |
| #include "app/clipboard/clipboard.h" |
| #include "base/callback.h" |
| #include "base/command_line.h" |
| #if defined(OS_POSIX) |
| #include "base/file_descriptor_posix.h" |
| #endif |
| #include "base/file_util.h" |
| #include "base/histogram.h" |
| #include "base/process_util.h" |
| #include "base/thread.h" |
| #include "base/utf_string_conversions.h" |
| #include "base/worker_pool.h" |
| #include "chrome/browser/appcache/appcache_dispatcher_host.h" |
| #include "chrome/browser/browser_about_handler.h" |
| #include "chrome/browser/child_process_security_policy.h" |
| #include "chrome/browser/chrome_plugin_browsing_context.h" |
| #include "chrome/browser/chrome_thread.h" |
| #include "chrome/browser/clipboard_dispatcher.h" |
| #include "chrome/browser/download/download_file.h" |
| #include "chrome/browser/extensions/extension_message_service.h" |
| #include "chrome/browser/geolocation/geolocation_permission_context.h" |
| #include "chrome/browser/geolocation/geolocation_dispatcher_host.h" |
| #include "chrome/browser/gpu_process_host.h" |
| #include "chrome/browser/host_zoom_map.h" |
| #include "chrome/browser/in_process_webkit/dom_storage_dispatcher_host.h" |
| #include "chrome/browser/in_process_webkit/indexed_db_dispatcher_host.h" |
| #include "chrome/browser/metrics/histogram_synchronizer.h" |
| #include "chrome/browser/nacl_host/nacl_process_host.h" |
| #include "chrome/browser/net/chrome_url_request_context.h" |
| #include "chrome/browser/net/predictor_api.h" |
| #include "chrome/browser/notifications/desktop_notification_service.h" |
| #include "chrome/browser/notifications/notifications_prefs_cache.h" |
| #include "chrome/browser/plugin_service.h" |
| #include "chrome/browser/pref_service.h" |
| #include "chrome/browser/printing/print_job_manager.h" |
| #include "chrome/browser/printing/printer_query.h" |
| #include "chrome/browser/profile.h" |
| #include "chrome/browser/renderer_host/audio_renderer_host.h" |
| #include "chrome/browser/renderer_host/browser_render_process_host.h" |
| #include "chrome/browser/renderer_host/database_dispatcher_host.h" |
| #include "chrome/browser/renderer_host/render_view_host_notification_task.h" |
| #include "chrome/browser/renderer_host/render_widget_helper.h" |
| #include "chrome/browser/spellchecker_platform_engine.h" |
| #include "chrome/browser/task_manager.h" |
| #include "chrome/browser/worker_host/message_port_dispatcher.h" |
| #include "chrome/browser/worker_host/worker_service.h" |
| #include "chrome/common/child_process_host.h" |
| #include "chrome/common/chrome_plugin_lib.h" |
| #include "chrome/common/chrome_plugin_util.h" |
| #include "chrome/common/chrome_switches.h" |
| #include "chrome/common/extensions/extension_constants.h" |
| #include "chrome/common/extensions/extension_file_util.h" |
| #include "chrome/common/extensions/extension_message_bundle.h" |
| #if defined(OS_MACOSX) |
| #include "chrome/common/font_descriptor_mac.h" |
| #include "chrome/common/font_loader_mac.h" |
| #endif |
| #include "chrome/common/notification_service.h" |
| #include "chrome/common/pref_names.h" |
| #include "chrome/common/render_messages.h" |
| #include "chrome/common/url_constants.h" |
| #include "chrome/common/worker_messages.h" |
| #include "gfx/native_widget_types.h" |
| #include "net/base/cookie_monster.h" |
| #include "net/base/file_stream.h" |
| #include "net/base/keygen_handler.h" |
| #include "net/base/load_flags.h" |
| #include "net/base/mime_util.h" |
| #include "net/base/net_errors.h" |
| #include "net/disk_cache/disk_cache.h" |
| #include "net/http/http_cache.h" |
| #include "net/http/http_transaction_factory.h" |
| #include "net/url_request/url_request_context.h" |
| #include "third_party/WebKit/WebKit/chromium/public/WebNotificationPresenter.h" |
| #include "webkit/glue/plugins/plugin_list.h" |
| #include "webkit/glue/plugins/webplugin.h" |
| #include "webkit/glue/webkit_glue.h" |
| |
| using WebKit::WebCache; |
| |
| namespace { |
| |
| // Context menus are somewhat complicated. We need to intercept them here on |
| // the I/O thread to add any spelling suggestions to them. After that's done, |
| // we need to forward the modified message to the UI thread and the normal |
| // message forwarding isn't set up for sending modified messages. |
| // |
| // Therefore, this class dispatches the IPC message to the RenderProcessHost |
| // with the given ID (if possible) to emulate the normal dispatch. |
| class ContextMenuMessageDispatcher : public Task { |
| public: |
| ContextMenuMessageDispatcher( |
| int render_process_id, |
| const ViewHostMsg_ContextMenu& context_menu_message) |
| : render_process_id_(render_process_id), |
| context_menu_message_(context_menu_message) { |
| } |
| |
| void Run() { |
| RenderProcessHost* host = |
| RenderProcessHost::FromID(render_process_id_); |
| if (host) |
| host->OnMessageReceived(context_menu_message_); |
| } |
| |
| private: |
| int render_process_id_; |
| const ViewHostMsg_ContextMenu context_menu_message_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ContextMenuMessageDispatcher); |
| }; |
| |
| // Completes a clipboard write initiated by the renderer. The write must be |
| // performed on the UI thread because the clipboard service from the IO thread |
| // cannot create windows so it cannot be the "owner" of the clipboard's |
| // contents. |
| class WriteClipboardTask : public Task { |
| public: |
| explicit WriteClipboardTask(Clipboard::ObjectMap* objects) |
| : objects_(objects) {} |
| ~WriteClipboardTask() {} |
| |
| void Run() { |
| g_browser_process->clipboard()->WriteObjects(*objects_.get()); |
| } |
| |
| private: |
| scoped_ptr<Clipboard::ObjectMap> objects_; |
| }; |
| |
| void RenderParamsFromPrintSettings(const printing::PrintSettings& settings, |
| ViewMsg_Print_Params* params) { |
| DCHECK(params); |
| #if defined(OS_WIN) || defined(OS_MACOSX) |
| params->page_size = settings.page_setup_device_units().physical_size(); |
| params->printable_size.SetSize( |
| settings.page_setup_device_units().content_area().width(), |
| settings.page_setup_device_units().content_area().height()); |
| params->margin_top = settings.page_setup_device_units().content_area().x(); |
| params->margin_left = settings.page_setup_device_units().content_area().y(); |
| params->dpi = settings.dpi(); |
| // Currently hardcoded at 1.25. See PrintSettings' constructor. |
| params->min_shrink = settings.min_shrink; |
| // Currently hardcoded at 2.0. See PrintSettings' constructor. |
| params->max_shrink = settings.max_shrink; |
| // Currently hardcoded at 72dpi. See PrintSettings' constructor. |
| params->desired_dpi = settings.desired_dpi; |
| // Always use an invalid cookie. |
| params->document_cookie = 0; |
| params->selection_only = settings.selection_only; |
| #else |
| NOTIMPLEMENTED(); |
| #endif |
| } |
| |
| class SetCookieCompletion : public net::CompletionCallback { |
| public: |
| SetCookieCompletion(int render_process_id, |
| int render_view_id, |
| const GURL& url, |
| const std::string& cookie_line, |
| ChromeURLRequestContext* context) |
| : render_process_id_(render_process_id), |
| render_view_id_(render_view_id), |
| url_(url), |
| cookie_line_(cookie_line), |
| context_(context) { |
| } |
| |
| virtual void RunWithParams(const Tuple1<int>& params) { |
| int result = params.a; |
| bool blocked_by_policy = true; |
| if (result == net::OK || |
| result == net::OK_FOR_SESSION_ONLY) { |
| blocked_by_policy = false; |
| net::CookieOptions options; |
| if (result == net::OK_FOR_SESSION_ONLY) |
| options.set_force_session(); |
| context_->cookie_store()->SetCookieWithOptions(url_, cookie_line_, |
| options); |
| } |
| if (!context_->IsExternal()) { |
| CallRenderViewHostContentSettingsDelegate( |
| render_process_id_, render_view_id_, |
| &RenderViewHostDelegate::ContentSettings::OnCookieAccessed, |
| url_, cookie_line_, blocked_by_policy); |
| } |
| delete this; |
| } |
| |
| private: |
| int render_process_id_; |
| int render_view_id_; |
| GURL url_; |
| std::string cookie_line_; |
| scoped_refptr<ChromeURLRequestContext> context_; |
| }; |
| |
| class GetCookiesCompletion : public net::CompletionCallback { |
| public: |
| GetCookiesCompletion(const GURL& url, IPC::Message* reply_msg, |
| ResourceMessageFilter* filter, |
| URLRequestContext* context) |
| : url_(url), |
| reply_msg_(reply_msg), |
| filter_(filter), |
| context_(context) { |
| } |
| |
| virtual void RunWithParams(const Tuple1<int>& params) { |
| int result = params.a; |
| std::string cookies; |
| if (result == net::OK) |
| cookies = context_->cookie_store()->GetCookies(url_); |
| ViewHostMsg_GetCookies::WriteReplyParams(reply_msg_, cookies); |
| filter_->Send(reply_msg_); |
| delete this; |
| } |
| |
| private: |
| GURL url_; |
| IPC::Message* reply_msg_; |
| scoped_refptr<ResourceMessageFilter> filter_; |
| scoped_refptr<URLRequestContext> context_; |
| }; |
| |
| class GetRawCookiesCompletion : public net::CompletionCallback { |
| public: |
| GetRawCookiesCompletion(const GURL& url, IPC::Message* reply_msg, |
| ResourceMessageFilter* filter, |
| URLRequestContext* context) |
| : url_(url), |
| reply_msg_(reply_msg), |
| filter_(filter), |
| context_(context) { |
| } |
| |
| virtual void RunWithParams(const Tuple1<int>& params) { |
| // Ignore the policy result. We only waited on the policy result so that |
| // any pending 'set-cookie' requests could be flushed. The intent of |
| // querying the raw cookies is to reveal the contents of the cookie DB, so |
| // it important that we don't read the cookie db ahead of pending writes. |
| |
| net::CookieMonster* cookie_monster = |
| context_->cookie_store()->GetCookieMonster(); |
| net::CookieMonster::CookieList cookie_list = |
| cookie_monster->GetAllCookiesForURL(url_); |
| |
| std::vector<webkit_glue::WebCookie> cookies; |
| for (size_t i = 0; i < cookie_list.size(); ++i) { |
| // TODO(darin): url.host() is not necessarily the domain of the cookie. |
| // We need a different API on CookieMonster to provide the domain info. |
| // See http://crbug.com/34315. |
| cookies.push_back( |
| webkit_glue::WebCookie(cookie_list[i].first, cookie_list[i].second)); |
| } |
| |
| ViewHostMsg_GetRawCookies::WriteReplyParams(reply_msg_, cookies); |
| filter_->Send(reply_msg_); |
| delete this; |
| } |
| |
| private: |
| GURL url_; |
| IPC::Message* reply_msg_; |
| scoped_refptr<ResourceMessageFilter> filter_; |
| scoped_refptr<URLRequestContext> context_; |
| }; |
| |
| class ClearCacheCompletion : public net::CompletionCallback { |
| public: |
| ClearCacheCompletion(IPC::Message* reply_msg, |
| ResourceMessageFilter* filter) |
| : reply_msg_(reply_msg), |
| filter_(filter) { |
| } |
| |
| virtual void RunWithParams(const Tuple1<int>& params) { |
| ViewHostMsg_ClearCache::WriteReplyParams(reply_msg_, params.a); |
| filter_->Send(reply_msg_); |
| delete this; |
| } |
| |
| private: |
| IPC::Message* reply_msg_; |
| scoped_refptr<ResourceMessageFilter> filter_; |
| }; |
| |
| void WriteFileSize(IPC::Message* reply_msg, |
| const file_util::FileInfo& file_info) { |
| ViewHostMsg_GetFileSize::WriteReplyParams(reply_msg, file_info.size); |
| } |
| |
| void WriteFileModificationTime(IPC::Message* reply_msg, |
| const file_util::FileInfo& file_info) { |
| ViewHostMsg_GetFileModificationTime::WriteReplyParams( |
| reply_msg, file_info.last_modified); |
| } |
| |
| } // namespace |
| |
| ResourceMessageFilter::ResourceMessageFilter( |
| ResourceDispatcherHost* resource_dispatcher_host, |
| int child_id, |
| AudioRendererHost* audio_renderer_host, |
| PluginService* plugin_service, |
| printing::PrintJobManager* print_job_manager, |
| Profile* profile, |
| RenderWidgetHelper* render_widget_helper, |
| URLRequestContextGetter* request_context) |
| : Receiver(RENDER_PROCESS, child_id), |
| channel_(NULL), |
| resource_dispatcher_host_(resource_dispatcher_host), |
| plugin_service_(plugin_service), |
| print_job_manager_(print_job_manager), |
| profile_(profile), |
| ALLOW_THIS_IN_INITIALIZER_LIST(resolve_proxy_msg_helper_(this, NULL)), |
| request_context_(request_context), |
| media_request_context_(profile->GetRequestContextForMedia()), |
| extensions_request_context_(profile->GetRequestContextForExtensions()), |
| extensions_message_service_(profile->GetExtensionMessageService()), |
| render_widget_helper_(render_widget_helper), |
| audio_renderer_host_(audio_renderer_host), |
| appcache_dispatcher_host_( |
| new AppCacheDispatcherHost(profile->GetRequestContext())), |
| ALLOW_THIS_IN_INITIALIZER_LIST(dom_storage_dispatcher_host_( |
| new DOMStorageDispatcherHost(this, profile->GetWebKitContext()))), |
| ALLOW_THIS_IN_INITIALIZER_LIST(indexed_db_dispatcher_host_( |
| new IndexedDBDispatcherHost(this, profile->GetWebKitContext()))), |
| ALLOW_THIS_IN_INITIALIZER_LIST(db_dispatcher_host_( |
| new DatabaseDispatcherHost(profile->GetDatabaseTracker(), this, |
| profile->GetHostContentSettingsMap()))), |
| notification_prefs_( |
| profile->GetDesktopNotificationService()->prefs_cache()), |
| host_zoom_map_(profile->GetHostZoomMap()), |
| off_the_record_(profile->IsOffTheRecord()), |
| next_route_id_callback_(NewCallbackWithReturnValue( |
| render_widget_helper, &RenderWidgetHelper::GetNextRoutingID)), |
| ALLOW_THIS_IN_INITIALIZER_LIST(geolocation_dispatcher_host_( |
| GeolocationDispatcherHost::New( |
| this->id(), profile->GetGeolocationPermissionContext()))) { |
| DCHECK(request_context_); |
| DCHECK(media_request_context_); |
| DCHECK(audio_renderer_host_.get()); |
| DCHECK(appcache_dispatcher_host_.get()); |
| DCHECK(dom_storage_dispatcher_host_.get()); |
| |
| render_widget_helper_->Init(id(), resource_dispatcher_host_); |
| #if defined(OS_CHROMEOS) |
| cloud_print_enabled_ = true; |
| #else |
| cloud_print_enabled_ = CommandLine::ForCurrentProcess()->HasSwitch( |
| switches::kEnableCloudPrint); |
| #endif |
| } |
| |
| ResourceMessageFilter::~ResourceMessageFilter() { |
| // This function should be called on the IO thread. |
| DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); |
| |
| // Tell the DOM Storage dispatcher host to stop sending messages via us. |
| dom_storage_dispatcher_host_->Shutdown(); |
| |
| // Tell the Indexed DB dispatcher host to stop sending messages via us. |
| indexed_db_dispatcher_host_->Shutdown(); |
| |
| // Shut down the database dispatcher host. |
| db_dispatcher_host_->Shutdown(); |
| |
| // Let interested observers know we are being deleted. |
| NotificationService::current()->Notify( |
| NotificationType::RESOURCE_MESSAGE_FILTER_SHUTDOWN, |
| Source<ResourceMessageFilter>(this), |
| NotificationService::NoDetails()); |
| |
| if (handle()) |
| base::CloseProcessHandle(handle()); |
| } |
| |
| // Called on the IPC thread: |
| void ResourceMessageFilter::OnFilterAdded(IPC::Channel* channel) { |
| channel_ = channel; |
| } |
| |
| // Called on the IPC thread: |
| void ResourceMessageFilter::OnChannelConnected(int32 peer_pid) { |
| DCHECK(!handle()) << " " << handle(); |
| DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); |
| |
| base::ProcessHandle peer_handle; |
| if (!base::OpenProcessHandle(peer_pid, &peer_handle)) { |
| NOTREACHED(); |
| } |
| set_handle(peer_handle); |
| |
| // Hook AudioRendererHost to this object after channel is connected so it can |
| // this object for sending messages. |
| audio_renderer_host_->IPCChannelConnected(id(), handle(), this); |
| |
| WorkerService::GetInstance()->Initialize(resource_dispatcher_host_); |
| appcache_dispatcher_host_->Initialize(this); |
| dom_storage_dispatcher_host_->Init(id(), handle()); |
| indexed_db_dispatcher_host_->Init(id(), handle()); |
| db_dispatcher_host_->Init(handle()); |
| } |
| |
| void ResourceMessageFilter::OnChannelError() { |
| NotificationService::current()->Notify( |
| NotificationType::RESOURCE_MESSAGE_FILTER_SHUTDOWN, |
| Source<ResourceMessageFilter>(this), |
| NotificationService::NoDetails()); |
| } |
| |
| // Called on the IPC thread: |
| void ResourceMessageFilter::OnChannelClosing() { |
| channel_ = NULL; |
| |
| // Unhook us from all pending network requests so they don't get sent to a |
| // deleted object. |
| resource_dispatcher_host_->CancelRequestsForProcess(id()); |
| |
| // Unhook AudioRendererHost. |
| audio_renderer_host_->IPCChannelClosing(); |
| } |
| |
| // Called on the IPC thread: |
| bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& msg) { |
| MessagePortDispatcher* mp_dispatcher = MessagePortDispatcher::GetInstance(); |
| bool msg_is_ok = true; |
| bool handled = |
| resource_dispatcher_host_->OnMessageReceived(msg, this, &msg_is_ok) || |
| appcache_dispatcher_host_->OnMessageReceived(msg, &msg_is_ok) || |
| dom_storage_dispatcher_host_->OnMessageReceived(msg, &msg_is_ok) || |
| indexed_db_dispatcher_host_->OnMessageReceived(msg) || |
| audio_renderer_host_->OnMessageReceived(msg, &msg_is_ok) || |
| db_dispatcher_host_->OnMessageReceived(msg, &msg_is_ok) || |
| mp_dispatcher->OnMessageReceived( |
| msg, this, next_route_id_callback(), &msg_is_ok) || |
| geolocation_dispatcher_host_->OnMessageReceived(msg, &msg_is_ok); |
| |
| if (!handled) { |
| DCHECK(msg_is_ok); // It should have been marked handled if it wasn't OK. |
| handled = true; |
| IPC_BEGIN_MESSAGE_MAP_EX(ResourceMessageFilter, msg, msg_is_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) |
| #endif |
| |
| IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWindow, OnMsgCreateWindow) |
| IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWidget, OnMsgCreateWidget) |
| 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(ViewHostMsg_GetCookiesEnabled, OnGetCookiesEnabled) |
| #if defined(OS_MACOSX) |
| IPC_MESSAGE_HANDLER(ViewHostMsg_LoadFont, OnLoadFont) |
| #endif |
| #if defined(OS_WIN) // This hack is Windows-specific. |
| IPC_MESSAGE_HANDLER(ViewHostMsg_PreCacheFont, OnPreCacheFont) |
| #endif |
| IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetPlugins, OnGetPlugins) |
| IPC_MESSAGE_HANDLER(ViewHostMsg_GetPluginPath, OnGetPluginPath) |
| IPC_MESSAGE_HANDLER(ViewHostMsg_DownloadUrl, OnDownloadUrl) |
| IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_ContextMenu, |
| OnReceiveContextMenuMsg(msg)) |
| IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_OpenChannelToPlugin, |
| OnOpenChannelToPlugin) |
| 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(msg)) |
| 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) |
| #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_GetMimeTypeFromExtension, |
| OnGetMimeTypeFromExtension) |
| IPC_MESSAGE_HANDLER(ViewHostMsg_GetMimeTypeFromFile, |
| OnGetMimeTypeFromFile) |
| IPC_MESSAGE_HANDLER(ViewHostMsg_GetPreferredExtensionForMimeType, |
| OnGetPreferredExtensionForMimeType) |
| IPC_MESSAGE_HANDLER(ViewHostMsg_GetCPBrowsingContext, |
| OnGetCPBrowsingContext) |
| #if defined(OS_WIN) |
| IPC_MESSAGE_HANDLER(ViewHostMsg_DuplicateSection, OnDuplicateSection) |
| #endif |
| #if defined(OS_MACOSX) |
| IPC_MESSAGE_HANDLER(ViewHostMsg_AllocatePDFTransport, |
| OnAllocateSharedMemoryBuffer) |
| #endif |
| #if defined(OS_POSIX) |
| 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) |
| #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) |
| #if defined(OS_WIN) || defined(OS_MACOSX) |
| IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ScriptedPrint, |
| OnScriptedPrint) |
| #endif |
| #if defined(OS_MACOSX) |
| 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_DELAY_REPLY(ViewHostMsg_GetFileSize, OnGetFileSize) |
| IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetFileModificationTime, |
| OnGetFileModificationTime) |
| IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_OpenFile, OnOpenFile) |
| 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) |
| #endif |
| IPC_MESSAGE_HANDLER(ViewHostMsg_EstablishGpuChannel, |
| OnEstablishGpuChannel) |
| IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_SynchronizeGpu, |
| OnSynchronizeGpu) |
| IPC_MESSAGE_UNHANDLED( |
| handled = false) |
| IPC_END_MESSAGE_MAP_EX() |
| } |
| |
| if (!msg_is_ok) |
| BrowserRenderProcessHost::BadMessageTerminateProcess(msg.type(), handle()); |
| |
| return handled; |
| } |
| |
| void ResourceMessageFilter::OnDestruct() { |
| ChromeThread::DeleteOnIOThread::Destruct(this); |
| } |
| |
| void ResourceMessageFilter::OnReceiveContextMenuMsg(const IPC::Message& msg) { |
| void* iter = NULL; |
| ContextMenuParams params; |
| if (!IPC::ParamTraits<ContextMenuParams>::Read(&msg, &iter, ¶ms)) |
| return; |
| |
| // Create a new ViewHostMsg_ContextMenu message. |
| const ViewHostMsg_ContextMenu context_menu_message(msg.routing_id(), params); |
| ChromeThread::PostTask( |
| ChromeThread::UI, FROM_HERE, |
| new ContextMenuMessageDispatcher(id(), context_menu_message)); |
| } |
| |
| // Called on the IPC thread: |
| bool ResourceMessageFilter::Send(IPC::Message* message) { |
| if (!channel_) { |
| delete message; |
| return false; |
| } |
| |
| return channel_->Send(message); |
| } |
| |
| URLRequestContext* ResourceMessageFilter::GetRequestContext( |
| uint32 request_id, |
| const ViewHostMsg_Resource_Request& request_data) { |
| URLRequestContextGetter* request_context = request_context_; |
| // If the request has resource type of ResourceType::MEDIA, we use a request |
| // context specific to media for handling it because these resources have |
| // specific needs for caching. |
| if (request_data.resource_type == ResourceType::MEDIA) |
| request_context = media_request_context_; |
| return request_context->GetURLRequestContext(); |
| } |
| |
| void ResourceMessageFilter::OnMsgCreateWindow( |
| const ViewHostMsg_CreateWindow_Params& params, |
| int* route_id, int64* cloned_session_storage_namespace_id) { |
| *cloned_session_storage_namespace_id = dom_storage_dispatcher_host_-> |
| CloneSessionStorage(params.session_storage_namespace_id); |
| render_widget_helper_->CreateNewWindow(params.opener_id, |
| params.user_gesture, |
| params.window_container_type, |
| params.frame_name, |
| handle(), |
| route_id); |
| } |
| |
| void ResourceMessageFilter::OnMsgCreateWidget(int opener_id, |
| WebKit::WebPopupType popup_type, |
| int* route_id) { |
| render_widget_helper_->CreateNewWidget(opener_id, popup_type, route_id); |
| } |
| |
| void ResourceMessageFilter::OnSetCookie(const IPC::Message& message, |
| const GURL& url, |
| const GURL& first_party_for_cookies, |
| const std::string& cookie) { |
| ChromeURLRequestContext* context = GetRequestContextForURL(url); |
| |
| SetCookieCompletion* callback = |
| new SetCookieCompletion(id(), message.routing_id(), url, cookie, context); |
| |
| int policy = net::OK; |
| if (context->cookie_policy()) { |
| policy = context->cookie_policy()->CanSetCookie( |
| url, first_party_for_cookies, cookie, callback); |
| if (policy == net::ERR_IO_PENDING) |
| return; |
| } |
| callback->Run(policy); |
| } |
| |
| void ResourceMessageFilter::OnGetCookies(const GURL& url, |
| const GURL& first_party_for_cookies, |
| IPC::Message* reply_msg) { |
| URLRequestContext* context = GetRequestContextForURL(url); |
| |
| GetCookiesCompletion* callback = |
| new GetCookiesCompletion(url, reply_msg, this, context); |
| |
| int policy = net::OK; |
| if (context->cookie_policy()) { |
| policy = context->cookie_policy()->CanGetCookies( |
| url, first_party_for_cookies, callback); |
| if (policy == net::ERR_IO_PENDING) { |
| Send(new ViewMsg_SignalCookiePromptEvent()); |
| return; |
| } |
| } |
| callback->Run(policy); |
| } |
| |
| void ResourceMessageFilter::OnGetRawCookies( |
| const GURL& url, |
| const GURL& first_party_for_cookies, |
| IPC::Message* reply_msg) { |
| |
| ChromeURLRequestContext* context = GetRequestContextForURL(url); |
| |
| // Only return raw cookies to trusted renderers or if this request is |
| // not targeted to an an external host like ChromeFrame. |
| // TODO(ananta) We need to support retreiving raw cookies from external |
| // hosts. |
| if (!ChildProcessSecurityPolicy::GetInstance()->CanReadRawCookies(id()) || |
| context->IsExternal()) { |
| ViewHostMsg_GetRawCookies::WriteReplyParams( |
| reply_msg, |
| std::vector<webkit_glue::WebCookie>()); |
| Send(reply_msg); |
| return; |
| } |
| |
| GetRawCookiesCompletion* callback = |
| new GetRawCookiesCompletion(url, reply_msg, this, context); |
| |
| // We check policy here to avoid sending back cookies that would not normally |
| // be applied to outbound requests for the given URL. Since this cookie info |
| // is visible in the developer tools, it is helpful to make it match reality. |
| int policy = net::OK; |
| if (context->cookie_policy()) { |
| policy = context->cookie_policy()->CanGetCookies( |
| url, first_party_for_cookies, callback); |
| if (policy == net::ERR_IO_PENDING) { |
| Send(new ViewMsg_SignalCookiePromptEvent()); |
| return; |
| } |
| } |
| callback->Run(policy); |
| } |
| |
| void ResourceMessageFilter::OnDeleteCookie(const GURL& url, |
| const std::string& cookie_name) { |
| URLRequestContext* context = GetRequestContextForURL(url); |
| context->cookie_store()->DeleteCookie(url, cookie_name); |
| } |
| |
| void ResourceMessageFilter::OnGetCookiesEnabled( |
| const GURL& url, |
| const GURL& first_party_for_cookies, |
| bool* enabled) { |
| *enabled = GetRequestContextForURL(url)->AreCookiesEnabled(); |
| } |
| |
| #if defined(OS_MACOSX) |
| void ResourceMessageFilter::OnLoadFont(const FontDescriptor& font, |
| uint32* handle_size, |
| base::SharedMemoryHandle* handle) { |
| base::SharedMemory font_data; |
| uint32 font_data_size = 0; |
| bool ok = FontLoader::LoadFontIntoBuffer(font.nsFont(), &font_data, |
| &font_data_size); |
| if (!ok || font_data_size == 0) { |
| LOG(ERROR) << "Couldn't load font data for " << font.font_name << |
| " ok=" << ok << " font_data_size=" << font_data_size; |
| *handle_size = 0; |
| *handle = base::SharedMemory::NULLHandle(); |
| return; |
| } |
| |
| *handle_size = font_data_size; |
| font_data.GiveToProcess(base::GetCurrentProcessHandle(), handle); |
| } |
| #endif // OS_MACOSX |
| |
| #if defined(OS_WIN) // This hack is Windows-specific. |
| void ResourceMessageFilter::OnPreCacheFont(LOGFONT font) { |
| ChildProcessHost::PreCacheFont(font); |
| } |
| #endif // OS_WIN |
| |
| void ResourceMessageFilter::OnGetPlugins(bool refresh, |
| IPC::Message* reply_msg) { |
| ChromeThread::PostTask( |
| ChromeThread::FILE, FROM_HERE, |
| NewRunnableMethod( |
| this, &ResourceMessageFilter::OnGetPluginsOnFileThread, refresh, |
| reply_msg)); |
| } |
| |
| void ResourceMessageFilter::OnGetPluginsOnFileThread( |
| bool refresh, IPC::Message* reply_msg) { |
| DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
| std::vector<WebPluginInfo> plugins; |
| NPAPI::PluginList::Singleton()->GetEnabledPlugins(refresh, &plugins); |
| ViewHostMsg_GetPlugins::WriteReplyParams(reply_msg, plugins); |
| ChromeThread::PostTask( |
| ChromeThread::IO, FROM_HERE, |
| NewRunnableMethod(this, &ResourceMessageFilter::Send, reply_msg)); |
| } |
| |
| void ResourceMessageFilter::OnGetPluginPath(const GURL& url, |
| const GURL& policy_url, |
| const std::string& mime_type, |
| FilePath* filename, |
| std::string* url_mime_type) { |
| *filename = plugin_service_->GetPluginPath( |
| url, policy_url, mime_type, url_mime_type); |
| } |
| |
| void ResourceMessageFilter::OnOpenChannelToPlugin(const GURL& url, |
| const std::string& mime_type, |
| const std::wstring& locale, |
| IPC::Message* reply_msg) { |
| plugin_service_->OpenChannelToPlugin( |
| this, url, mime_type, locale, reply_msg); |
| } |
| |
| void ResourceMessageFilter::OnLaunchNaCl( |
| const std::wstring& url, int channel_descriptor, IPC::Message* reply_msg) { |
| NaClProcessHost* host = new NaClProcessHost(resource_dispatcher_host_, url); |
| host->Launch(this, channel_descriptor, reply_msg); |
| } |
| |
| void ResourceMessageFilter::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, 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, id(), params.render_view_route_id, this, *route_id, |
| id(), params.parent_appcache_host_id, |
| static_cast<ChromeURLRequestContext*>( |
| request_context_->GetURLRequestContext())); |
| } |
| |
| void ResourceMessageFilter::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, id(), |
| params.render_view_route_id, this, *route_id, url_mismatch); |
| } |
| |
| void ResourceMessageFilter::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 ResourceMessageFilter::OnCancelCreateDedicatedWorker(int route_id) { |
| WorkerService::GetInstance()->CancelCreateDedicatedWorker(this, route_id); |
| } |
| |
| void ResourceMessageFilter::OnForwardToWorker(const IPC::Message& message) { |
| WorkerService::GetInstance()->ForwardMessage(message, this); |
| } |
| |
| void ResourceMessageFilter::OnDownloadUrl(const IPC::Message& message, |
| const GURL& url, |
| const GURL& referrer) { |
| URLRequestContext* context = request_context_->GetURLRequestContext(); |
| |
| // Don't show "Save As" UI. |
| bool prompt_for_save_location = false; |
| resource_dispatcher_host_->BeginDownload(url, |
| referrer, |
| DownloadSaveInfo(), |
| prompt_for_save_location, |
| id(), |
| message.routing_id(), |
| context); |
| } |
| |
| void ResourceMessageFilter::OnClipboardWriteObjectsSync( |
| const Clipboard::ObjectMap& objects, |
| base::SharedMemoryHandle bitmap_handle) { |
| DCHECK(base::SharedMemory::IsHandleValid(bitmap_handle)) |
| << "Bad bitmap handle"; |
| // We cannot write directly from the IO thread, and cannot service the IPC |
| // on the UI thread. We'll copy the relevant data and get a handle to any |
| // shared memory so it doesn't go away when we resume the renderer, and post |
| // a task to perform the write on the UI thread. |
| Clipboard::ObjectMap* long_living_objects = new Clipboard::ObjectMap(objects); |
| |
| // Splice the shared memory handle into the clipboard data. |
| Clipboard::ReplaceSharedMemHandle(long_living_objects, bitmap_handle, |
| handle()); |
| |
| ChromeThread::PostTask( |
| ChromeThread::UI, |
| FROM_HERE, |
| new WriteClipboardTask(long_living_objects)); |
| } |
| |
| void ResourceMessageFilter::OnClipboardWriteObjectsAsync( |
| const Clipboard::ObjectMap& objects) { |
| // We cannot write directly from the IO thread, and cannot service the IPC |
| // on the UI thread. We'll copy the relevant data and post a task to preform |
| // the write on the UI thread. |
| Clipboard::ObjectMap* long_living_objects = new Clipboard::ObjectMap(objects); |
| |
| // This async message doesn't support shared-memory based bitmaps; they must |
| // be removed otherwise we might dereference a rubbish pointer. |
| long_living_objects->erase(Clipboard::CBF_SMBITMAP); |
| |
| ChromeThread::PostTask( |
| ChromeThread::UI, |
| FROM_HERE, |
| new WriteClipboardTask(long_living_objects)); |
| } |
| |
| #if !defined(USE_X11) |
| // On non-X11 platforms, clipboard actions can be performed on the IO thread. |
| // On X11, since the clipboard is linked with GTK, we either have to do this |
| // with GTK on the UI thread, or with Xlib on the BACKGROUND_X11 thread. In an |
| // ideal world, we would do the latter. However, for now we're going to |
| // terminate these calls on the UI thread. This risks deadlock in the case of |
| // plugins, but it's better than crashing which is what doing on the IO thread |
| // gives us. |
| // |
| // See resource_message_filter_gtk.cc for the Linux implementation of these |
| // functions. |
| |
| void ResourceMessageFilter::OnClipboardIsFormatAvailable( |
| Clipboard::FormatType format, Clipboard::Buffer buffer, |
| IPC::Message* reply) { |
| const bool result = GetClipboard()->IsFormatAvailable(format, buffer); |
| ViewHostMsg_ClipboardIsFormatAvailable::WriteReplyParams(reply, result); |
| Send(reply); |
| } |
| |
| void ResourceMessageFilter::OnClipboardReadText(Clipboard::Buffer buffer, |
| IPC::Message* reply) { |
| string16 result; |
| GetClipboard()->ReadText(buffer, &result); |
| ViewHostMsg_ClipboardReadText::WriteReplyParams(reply, result); |
| Send(reply); |
| } |
| |
| void ResourceMessageFilter::OnClipboardReadAsciiText(Clipboard::Buffer buffer, |
| IPC::Message* reply) { |
| std::string result; |
| GetClipboard()->ReadAsciiText(buffer, &result); |
| ViewHostMsg_ClipboardReadAsciiText::WriteReplyParams(reply, result); |
| Send(reply); |
| } |
| |
| void ResourceMessageFilter::OnClipboardReadHTML(Clipboard::Buffer buffer, |
| IPC::Message* reply) { |
| std::string src_url_str; |
| string16 markup; |
| GetClipboard()->ReadHTML(buffer, &markup, &src_url_str); |
| const GURL src_url = GURL(src_url_str); |
| |
| ViewHostMsg_ClipboardReadHTML::WriteReplyParams(reply, markup, src_url); |
| Send(reply); |
| } |
| |
| void ResourceMessageFilter::OnClipboardReadAvailableTypes( |
| Clipboard::Buffer buffer, IPC::Message* reply) { |
| std::vector<string16> types; |
| bool contains_filenames = false; |
| bool result = ClipboardDispatcher::ReadAvailableTypes( |
| buffer, &types, &contains_filenames); |
| ViewHostMsg_ClipboardReadAvailableTypes::WriteReplyParams( |
| reply, result, types, contains_filenames); |
| Send(reply); |
| } |
| |
| void ResourceMessageFilter::OnClipboardReadData( |
| Clipboard::Buffer buffer, const string16& type, IPC::Message* reply) { |
| string16 data; |
| string16 metadata; |
| bool result = ClipboardDispatcher::ReadData(buffer, type, &data, &metadata); |
| ViewHostMsg_ClipboardReadData::WriteReplyParams( |
| reply, result, data, metadata); |
| Send(reply); |
| } |
| |
| void ResourceMessageFilter::OnClipboardReadFilenames( |
| Clipboard::Buffer buffer, IPC::Message* reply) { |
| std::vector<string16> filenames; |
| bool result = ClipboardDispatcher::ReadFilenames(buffer, &filenames); |
| ViewHostMsg_ClipboardReadFilenames::WriteReplyParams( |
| reply, result, filenames); |
| Send(reply); |
| } |
| |
| #endif |
| |
| void ResourceMessageFilter::OnCheckNotificationPermission( |
| const GURL& source_url, int* result) { |
| *result = WebKit::WebNotificationPresenter::PermissionNotAllowed; |
| |
| ChromeURLRequestContext* context = GetRequestContextForURL(source_url); |
| if (context->CheckURLAccessToExtensionPermission(source_url, |
| Extension::kNotificationPermission)) { |
| *result = WebKit::WebNotificationPresenter::PermissionAllowed; |
| return; |
| } |
| |
| // Fall back to the regular notification preferences, which works on an |
| // origin basis. |
| *result = notification_prefs_->HasPermission(source_url.GetOrigin()); |
| } |
| |
| void ResourceMessageFilter::OnGetMimeTypeFromExtension( |
| const FilePath::StringType& ext, std::string* mime_type) { |
| net::GetMimeTypeFromExtension(ext, mime_type); |
| } |
| |
| void ResourceMessageFilter::OnGetMimeTypeFromFile( |
| const FilePath& file_path, std::string* mime_type) { |
| net::GetMimeTypeFromFile(file_path, mime_type); |
| } |
| |
| void ResourceMessageFilter::OnGetPreferredExtensionForMimeType( |
| const std::string& mime_type, FilePath::StringType* ext) { |
| net::GetPreferredExtensionForMimeType(mime_type, ext); |
| } |
| |
| void ResourceMessageFilter::OnGetCPBrowsingContext(uint32* context) { |
| // Always allocate a new context when a plugin requests one, since it needs to |
| // be unique for that plugin instance. |
| *context = CPBrowsingContextManager::Instance()->Allocate( |
| request_context_->GetURLRequestContext()); |
| } |
| |
| #if defined(OS_WIN) |
| void ResourceMessageFilter::OnDuplicateSection( |
| base::SharedMemoryHandle renderer_handle, |
| base::SharedMemoryHandle* browser_handle) { |
| // Duplicate the handle in this process right now so the memory is kept alive |
| // (even if it is not mapped) |
| base::SharedMemory shared_buf(renderer_handle, true, handle()); |
| shared_buf.GiveToProcess(base::GetCurrentProcessHandle(), browser_handle); |
| } |
| #endif |
| |
| #if defined(OS_POSIX) |
| void ResourceMessageFilter::OnAllocateSharedMemoryBuffer( |
| uint32 buffer_size, |
| base::SharedMemoryHandle* handle) { |
| base::SharedMemory shared_buf; |
| shared_buf.Create(L"", false, false, buffer_size); |
| if (!shared_buf.Map(buffer_size)) { |
| *handle = base::SharedMemory::NULLHandle(); |
| NOTREACHED() << "Cannot map shared memory buffer"; |
| return; |
| } |
| shared_buf.GiveToProcess(base::GetCurrentProcessHandle(), handle); |
| } |
| #endif |
| |
| void ResourceMessageFilter::OnResourceTypeStats( |
| const WebCache::ResourceTypeStats& stats) { |
| HISTOGRAM_COUNTS("WebCoreCache.ImagesSizeKB", |
| static_cast<int>(stats.images.size / 1024)); |
| HISTOGRAM_COUNTS("WebCoreCache.CSSStylesheetsSizeKB", |
| static_cast<int>(stats.cssStyleSheets.size / 1024)); |
| HISTOGRAM_COUNTS("WebCoreCache.ScriptsSizeKB", |
| static_cast<int>(stats.scripts.size / 1024)); |
| HISTOGRAM_COUNTS("WebCoreCache.XSLStylesheetsSizeKB", |
| static_cast<int>(stats.xslStyleSheets.size / 1024)); |
| HISTOGRAM_COUNTS("WebCoreCache.FontsSizeKB", |
| static_cast<int>(stats.fonts.size / 1024)); |
| // We need to notify the TaskManager of these statistics from the UI |
| // thread. |
| ChromeThread::PostTask( |
| ChromeThread::UI, FROM_HERE, |
| NewRunnableFunction( |
| &ResourceMessageFilter::OnResourceTypeStatsOnUIThread, |
| stats, |
| base::GetProcId(handle()))); |
| } |
| |
| void ResourceMessageFilter::OnResourceTypeStatsOnUIThread( |
| WebCache::ResourceTypeStats stats, base::ProcessId renderer_id) { |
| DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
| TaskManager::GetInstance()->model()->NotifyResourceTypeStats( |
| renderer_id, stats); |
| } |
| |
| |
| void ResourceMessageFilter::OnV8HeapStats(int v8_memory_allocated, |
| int v8_memory_used) { |
| ChromeThread::PostTask( |
| ChromeThread::UI, FROM_HERE, |
| NewRunnableFunction(&ResourceMessageFilter::OnV8HeapStatsOnUIThread, |
| v8_memory_allocated, |
| v8_memory_used, |
| base::GetProcId(handle()))); |
| } |
| |
| // static |
| void ResourceMessageFilter::OnV8HeapStatsOnUIThread( |
| int v8_memory_allocated, int v8_memory_used, base::ProcessId renderer_id) { |
| DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
| TaskManager::GetInstance()->model()->NotifyV8HeapStats( |
| renderer_id, |
| static_cast<size_t>(v8_memory_allocated), |
| static_cast<size_t>(v8_memory_used)); |
| } |
| |
| void ResourceMessageFilter::OnDidZoomURL(const GURL& url, |
| int zoom_level) { |
| ChromeThread::PostTask(ChromeThread::UI, FROM_HERE, |
| NewRunnableMethod(this, |
| &ResourceMessageFilter::UpdateHostZoomLevelsOnUIThread, |
| url, zoom_level)); |
| } |
| |
| void ResourceMessageFilter::UpdateHostZoomLevelsOnUIThread( |
| const GURL& url, |
| int zoom_level) { |
| DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
| host_zoom_map_->SetZoomLevel(url, zoom_level); |
| |
| // Notify renderers from this profile. |
| for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator()); |
| !i.IsAtEnd(); i.Advance()) { |
| RenderProcessHost* render_process_host = i.GetCurrentValue(); |
| if (render_process_host->profile() == profile_) { |
| render_process_host->Send( |
| new ViewMsg_SetZoomLevelForCurrentURL(url, zoom_level)); |
| } |
| } |
| } |
| |
| void ResourceMessageFilter::OnResolveProxy(const GURL& url, |
| IPC::Message* reply_msg) { |
| resolve_proxy_msg_helper_.Start(url, reply_msg); |
| } |
| |
| void ResourceMessageFilter::OnResolveProxyCompleted( |
| IPC::Message* reply_msg, |
| int result, |
| const std::string& proxy_list) { |
| ViewHostMsg_ResolveProxy::WriteReplyParams(reply_msg, result, proxy_list); |
| Send(reply_msg); |
| } |
| |
| void ResourceMessageFilter::OnGetDefaultPrintSettings(IPC::Message* reply_msg) { |
| scoped_refptr<printing::PrinterQuery> printer_query; |
| print_job_manager_->PopPrinterQuery(0, &printer_query); |
| if (!printer_query.get()) { |
| printer_query = new printing::PrinterQuery; |
| } |
| |
| CancelableTask* task = NewRunnableMethod( |
| this, |
| &ResourceMessageFilter::OnGetDefaultPrintSettingsReply, |
| printer_query, |
| reply_msg); |
| // Loads default settings. This is asynchronous, only the IPC message sender |
| // will hang until the settings are retrieved. |
| printer_query->GetSettings(printing::PrinterQuery::DEFAULTS, |
| NULL, |
| 0, |
| false, |
| true, |
| task); |
| } |
| |
| void ResourceMessageFilter::OnGetDefaultPrintSettingsReply( |
| scoped_refptr<printing::PrinterQuery> printer_query, |
| IPC::Message* reply_msg) { |
| ViewMsg_Print_Params params; |
| if (printer_query->last_status() != printing::PrintingContext::OK) { |
| memset(¶ms, 0, sizeof(params)); |
| } else { |
| RenderParamsFromPrintSettings(printer_query->settings(), ¶ms); |
| params.document_cookie = printer_query->cookie(); |
| } |
| ViewHostMsg_GetDefaultPrintSettings::WriteReplyParams(reply_msg, params); |
| Send(reply_msg); |
| // If user hasn't cancelled. |
| if (printer_query->cookie() && printer_query->settings().dpi()) { |
| print_job_manager_->QueuePrinterQuery(printer_query.get()); |
| } else { |
| printer_query->StopWorker(); |
| } |
| } |
| |
| #if defined(OS_WIN) || defined(OS_MACOSX) |
| |
| void ResourceMessageFilter::OnScriptedPrint( |
| const ViewHostMsg_ScriptedPrint_Params& params, |
| IPC::Message* reply_msg) { |
| gfx::NativeView host_view = |
| gfx::NativeViewFromIdInBrowser(params.host_window_id); |
| |
| scoped_refptr<printing::PrinterQuery> printer_query; |
| print_job_manager_->PopPrinterQuery(params.cookie, &printer_query); |
| if (!printer_query.get()) { |
| printer_query = new printing::PrinterQuery; |
| } |
| |
| CancelableTask* task = NewRunnableMethod( |
| this, |
| &ResourceMessageFilter::OnScriptedPrintReply, |
| printer_query, |
| params.routing_id, |
| reply_msg); |
| |
| printer_query->GetSettings(printing::PrinterQuery::ASK_USER, |
| host_view, |
| params.expected_pages_count, |
| params.has_selection, |
| params.use_overlays, |
| task); |
| } |
| |
| void ResourceMessageFilter::OnScriptedPrintReply( |
| scoped_refptr<printing::PrinterQuery> printer_query, |
| int routing_id, |
| IPC::Message* reply_msg) { |
| ViewMsg_PrintPages_Params params; |
| if (printer_query->last_status() != printing::PrintingContext::OK || |
| !printer_query->settings().dpi()) { |
| memset(¶ms, 0, sizeof(params)); |
| } else { |
| RenderParamsFromPrintSettings(printer_query->settings(), ¶ms.params); |
| params.params.document_cookie = printer_query->cookie(); |
| params.pages = |
| printing::PageRange::GetPages(printer_query->settings().ranges); |
| } |
| ViewHostMsg_ScriptedPrint::WriteReplyParams(reply_msg, params); |
| Send(reply_msg); |
| if (params.params.dpi && params.params.document_cookie) { |
| print_job_manager_->QueuePrinterQuery(printer_query.get()); |
| } else { |
| printer_query->StopWorker(); |
| } |
| } |
| |
| #endif // OS_WIN || OS_MACOSX |
| |
| // static |
| Clipboard* ResourceMessageFilter::GetClipboard() { |
| // We have a static instance of the clipboard service for use by all message |
| // filters. This instance lives for the life of the browser processes. |
| static Clipboard* clipboard = new Clipboard; |
| |
| return clipboard; |
| } |
| |
| ChromeURLRequestContext* ResourceMessageFilter::GetRequestContextForURL( |
| const GURL& url) { |
| DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); |
| URLRequestContextGetter* context_getter = |
| url.SchemeIs(chrome::kExtensionScheme) ? |
| extensions_request_context_ : request_context_; |
| return static_cast<ChromeURLRequestContext*>( |
| context_getter->GetURLRequestContext()); |
| } |
| |
| void ResourceMessageFilter::OnPlatformCheckSpelling(const string16& word, |
| int tag, |
| bool* correct) { |
| *correct = SpellCheckerPlatform::CheckSpelling(word, tag); |
| } |
| |
| void ResourceMessageFilter::OnPlatformFillSuggestionList( |
| const string16& word, |
| std::vector<string16>* suggestions) { |
| SpellCheckerPlatform::FillSuggestionList(word, suggestions); |
| } |
| |
| void ResourceMessageFilter::OnGetDocumentTag(IPC::Message* reply_msg) { |
| int tag = SpellCheckerPlatform::GetDocumentTag(); |
| ViewHostMsg_GetDocumentTag::WriteReplyParams(reply_msg, tag); |
| Send(reply_msg); |
| return; |
| } |
| |
| void ResourceMessageFilter::OnDocumentWithTagClosed(int tag) { |
| SpellCheckerPlatform::CloseDocumentWithTag(tag); |
| } |
| |
| void ResourceMessageFilter::OnShowSpellingPanel(bool show) { |
| SpellCheckerPlatform::ShowSpellingPanel(show); |
| } |
| |
| void ResourceMessageFilter::OnUpdateSpellingPanelWithMisspelledWord( |
| const string16& word) { |
| SpellCheckerPlatform::UpdateSpellingPanelWithMisspelledWord(word); |
| } |
| |
| void ResourceMessageFilter::OnDnsPrefetch( |
| const std::vector<std::string>& hostnames) { |
| chrome_browser_net::DnsPrefetchList(hostnames); |
| } |
| |
| void ResourceMessageFilter::OnRendererHistograms( |
| int sequence_number, |
| const std::vector<std::string>& histograms) { |
| HistogramSynchronizer::DeserializeHistogramList(sequence_number, histograms); |
| } |
| |
| #if defined(OS_MACOSX) |
| void ResourceMessageFilter::OnAllocTransportDIB( |
| size_t size, bool cache_in_browser, TransportDIB::Handle* handle) { |
| render_widget_helper_->AllocTransportDIB(size, cache_in_browser, handle); |
| } |
| |
| void ResourceMessageFilter::OnFreeTransportDIB( |
| TransportDIB::Id dib_id) { |
| render_widget_helper_->FreeTransportDIB(dib_id); |
| } |
| #endif |
| |
| void ResourceMessageFilter::OnOpenChannelToExtension( |
| int routing_id, const std::string& source_extension_id, |
| const std::string& target_extension_id, |
| const std::string& channel_name, int* port_id) { |
| if (extensions_message_service_.get()) { |
| *port_id = extensions_message_service_-> |
| OpenChannelToExtension(routing_id, source_extension_id, |
| target_extension_id, channel_name, this); |
| } else { |
| *port_id = -1; |
| } |
| } |
| |
| void ResourceMessageFilter::OnOpenChannelToTab( |
| int routing_id, int tab_id, const std::string& extension_id, |
| const std::string& channel_name, int* port_id) { |
| if (extensions_message_service_.get()) { |
| *port_id = extensions_message_service_-> |
| OpenChannelToTab(routing_id, tab_id, extension_id, channel_name, this); |
| } else { |
| *port_id = -1; |
| } |
| } |
| |
| bool ResourceMessageFilter::CheckBenchmarkingEnabled() const { |
| static bool checked = false; |
| static bool result = false; |
| if (!checked) { |
| const CommandLine& command_line = *CommandLine::ForCurrentProcess(); |
| result = command_line.HasSwitch(switches::kEnableBenchmarking); |
| checked = true; |
| } |
| return result; |
| } |
| |
| void ResourceMessageFilter::OnCloseCurrentConnections() { |
| // This function is disabled unless the user has enabled |
| // benchmarking extensions. |
| if (!CheckBenchmarkingEnabled()) |
| return; |
| request_context_->GetURLRequestContext()-> |
| http_transaction_factory()->GetCache()->CloseCurrentConnections(); |
| } |
| |
| void ResourceMessageFilter::OnSetCacheMode(bool enabled) { |
| // This function is disabled unless the user has enabled |
| // benchmarking extensions. |
| if (!CheckBenchmarkingEnabled()) |
| return; |
| |
| net::HttpCache::Mode mode = enabled ? |
| net::HttpCache::NORMAL : net::HttpCache::DISABLE; |
| net::HttpCache* http_cache = request_context_->GetURLRequestContext()-> |
| http_transaction_factory()->GetCache(); |
| http_cache->set_mode(mode); |
| } |
| |
| void ResourceMessageFilter::OnClearCache(IPC::Message* reply_msg) { |
| // This function is disabled unless the user has enabled |
| // benchmarking extensions. |
| int rv = -1; |
| if (CheckBenchmarkingEnabled()) { |
| disk_cache::Backend* backend = request_context_->GetURLRequestContext()-> |
| http_transaction_factory()->GetCache()->GetCurrentBackend(); |
| if (backend) { |
| ClearCacheCompletion* callback = |
| new ClearCacheCompletion(reply_msg, this); |
| rv = backend->DoomAllEntries(callback); |
| if (rv == net::ERR_IO_PENDING) { |
| // The callback will send the reply. |
| return; |
| } |
| // Completed synchronously, no need for the callback. |
| delete callback; |
| } |
| } |
| ViewHostMsg_ClearCache::WriteReplyParams(reply_msg, rv); |
| Send(reply_msg); |
| } |
| |
| bool ResourceMessageFilter::CheckPreparsedJsCachingEnabled() const { |
| static bool checked = false; |
| static bool result = false; |
| if (!checked) { |
| const CommandLine& command_line = *CommandLine::ForCurrentProcess(); |
| result = command_line.HasSwitch(switches::kEnablePreparsedJsCaching); |
| checked = true; |
| } |
| return result; |
| } |
| |
| void ResourceMessageFilter::OnCacheableMetadataAvailable( |
| const GURL& url, |
| double expected_response_time, |
| const std::vector<char>& data) { |
| if (!CheckPreparsedJsCachingEnabled()) |
| return; |
| |
| net::HttpCache* cache = request_context_->GetURLRequestContext()-> |
| http_transaction_factory()->GetCache(); |
| DCHECK(cache); |
| |
| scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(data.size()); |
| memcpy(buf->data(), &data.front(), data.size()); |
| cache->WriteMetadata( |
| url, base::Time::FromDoubleT(expected_response_time), buf, data.size()); |
| } |
| |
| void ResourceMessageFilter::OnGetFileSize(const FilePath& path, |
| IPC::Message* reply_msg) { |
| // Get file size only when the child process has been granted permission to |
| // upload the file. |
| if (!ChildProcessSecurityPolicy::GetInstance()->CanUploadFile(id(), path)) { |
| ViewHostMsg_GetFileSize::WriteReplyParams( |
| reply_msg, static_cast<int64>(-1)); |
| Send(reply_msg); |
| return; |
| } |
| |
| // Getting file size could take long time if it lives on a network share, |
| // so run it on FILE thread. |
| ChromeThread::PostTask( |
| ChromeThread::FILE, FROM_HERE, |
| NewRunnableMethod( |
| this, &ResourceMessageFilter::OnGetFileInfoOnFileThread, path, |
| reply_msg, &WriteFileSize)); |
| } |
| |
| void ResourceMessageFilter::OnGetFileModificationTime(const FilePath& path, |
| IPC::Message* reply_msg) { |
| // Get file modification time only when the child process has been granted |
| // permission to upload the file. |
| if (!ChildProcessSecurityPolicy::GetInstance()->CanUploadFile(id(), path)) { |
| ViewHostMsg_GetFileModificationTime::WriteReplyParams(reply_msg, |
| base::Time()); |
| Send(reply_msg); |
| return; |
| } |
| |
| // Getting file modification time could take a long time if it lives on a |
| // network share, so run it on the FILE thread. |
| ChromeThread::PostTask( |
| ChromeThread::FILE, FROM_HERE, |
| NewRunnableMethod( |
| this, &ResourceMessageFilter::OnGetFileInfoOnFileThread, |
| path, reply_msg, &WriteFileModificationTime)); |
| } |
| |
| void ResourceMessageFilter::OnGetFileInfoOnFileThread( |
| const FilePath& path, |
| IPC::Message* reply_msg, |
| FileInfoWriteFunc write_func) { |
| DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
| |
| file_util::FileInfo file_info; |
| file_info.size = 0; |
| file_util::GetFileInfo(path, &file_info); |
| |
| (*write_func)(reply_msg, file_info); |
| |
| ChromeThread::PostTask( |
| ChromeThread::IO, FROM_HERE, |
| NewRunnableMethod(this, &ResourceMessageFilter::Send, reply_msg)); |
| } |
| |
| void ResourceMessageFilter::OnOpenFile(const FilePath& path, |
| int mode, |
| IPC::Message* reply_msg) { |
| // Open the file only when the child process has been granted permission to |
| // upload the file. |
| // TODO(jianli): Do we need separate permission to control opening the file? |
| if (!ChildProcessSecurityPolicy::GetInstance()->CanUploadFile(id(), path)) { |
| ViewHostMsg_OpenFile::WriteReplyParams( |
| reply_msg, |
| #if defined(OS_WIN) |
| base::kInvalidPlatformFileValue |
| #elif defined(OS_POSIX) |
| base::FileDescriptor(base::kInvalidPlatformFileValue, true) |
| #endif |
| ); |
| Send(reply_msg); |
| return; |
| } |
| |
| // Opening the file could take a long time if it lives on a network share, |
| // so run it on the FILE thread. |
| ChromeThread::PostTask( |
| ChromeThread::FILE, FROM_HERE, |
| NewRunnableMethod( |
| this, &ResourceMessageFilter::OnOpenFileOnFileThread, |
| path, mode, reply_msg)); |
| } |
| |
| void ResourceMessageFilter::OnOpenFileOnFileThread(const FilePath& path, |
| int mode, |
| IPC::Message* reply_msg) { |
| DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
| |
| base::PlatformFile file_handle = base::CreatePlatformFile( |
| path, |
| (mode == 0) ? (base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ) |
| : (base::PLATFORM_FILE_CREATE_ALWAYS | |
| base::PLATFORM_FILE_WRITE), |
| NULL); |
| |
| base::PlatformFile target_file_handle; |
| #if defined(OS_WIN) |
| // Duplicate the file handle so that the renderer process can access the file. |
| if (!DuplicateHandle(GetCurrentProcess(), file_handle, |
| handle(), &target_file_handle, 0, false, |
| DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { |
| // file_handle is closed whether or not DuplicateHandle succeeds. |
| target_file_handle = INVALID_HANDLE_VALUE; |
| } |
| #else |
| target_file_handle = file_handle; |
| #endif |
| |
| ViewHostMsg_OpenFile::WriteReplyParams( |
| reply_msg, |
| #if defined(OS_WIN) |
| target_file_handle |
| #elif defined(OS_POSIX) |
| base::FileDescriptor(target_file_handle, true) |
| #endif |
| ); |
| |
| ChromeThread::PostTask( |
| ChromeThread::IO, FROM_HERE, |
| NewRunnableMethod(this, &ResourceMessageFilter::Send, reply_msg)); |
| } |
| |
| void ResourceMessageFilter::OnKeygen(uint32 key_size_index, |
| const std::string& challenge_string, |
| const GURL& url, |
| IPC::Message* reply_msg) { |
| // Map displayed strings indicating level of keysecurity in the <keygen> |
| // menu to the key size in bits. (See SSLKeyGeneratorChromium.cpp in WebCore.) |
| int key_size_in_bits; |
| switch (key_size_index) { |
| case 0: |
| key_size_in_bits = 2048; |
| break; |
| case 1: |
| key_size_in_bits = 1024; |
| break; |
| default: |
| DCHECK(false) << "Illegal key_size_index " << key_size_index; |
| ViewHostMsg_Keygen::WriteReplyParams(reply_msg, std::string()); |
| Send(reply_msg); |
| return; |
| } |
| |
| LOG(INFO) << "Dispatching keygen task to worker pool."; |
| // Dispatch to worker pool, so we do not block the IO thread. |
| if (!WorkerPool::PostTask( |
| FROM_HERE, |
| NewRunnableMethod( |
| this, &ResourceMessageFilter::OnKeygenOnWorkerThread, |
| key_size_in_bits, challenge_string, reply_msg), |
| true)) { |
| NOTREACHED() << "Failed to dispatch keygen task to worker pool"; |
| ViewHostMsg_Keygen::WriteReplyParams(reply_msg, std::string()); |
| Send(reply_msg); |
| return; |
| } |
| } |
| |
| void ResourceMessageFilter::OnKeygenOnWorkerThread( |
| int key_size_in_bits, |
| const std::string& challenge_string, |
| IPC::Message* reply_msg) { |
| DCHECK(reply_msg); |
| // Verify we are on a worker thread. |
| DCHECK(!MessageLoop::current()); |
| |
| // Generate a signed public key and challenge, then send it back. |
| net::KeygenHandler keygen_handler(key_size_in_bits, challenge_string); |
| |
| ViewHostMsg_Keygen::WriteReplyParams( |
| reply_msg, |
| keygen_handler.GenKeyAndSignChallenge()); |
| |
| ChromeThread::PostTask( |
| ChromeThread::IO, FROM_HERE, |
| NewRunnableMethod(this, &ResourceMessageFilter::Send, reply_msg)); |
| } |
| |
| #if defined(USE_TCMALLOC) |
| void ResourceMessageFilter::OnRendererTcmalloc(base::ProcessId pid, |
| const std::string& output) { |
| ChromeThread::PostTask( |
| ChromeThread::UI, FROM_HERE, |
| NewRunnableFunction(AboutTcmallocRendererCallback, pid, output)); |
| } |
| #endif |
| |
| void ResourceMessageFilter::OnEstablishGpuChannel() { |
| GpuProcessHost::Get()->EstablishGpuChannel(id(), this); |
| } |
| |
| void ResourceMessageFilter::OnSynchronizeGpu(IPC::Message* reply) { |
| // We handle this message (and the other GPU process messages) here |
| // rather than handing the message to the GpuProcessHost for |
| // dispatch so that we can use the DELAY_REPLY macro to synthesize |
| // the reply message, and also send down a "this" pointer so that |
| // the GPU process host can send the reply later. |
| GpuProcessHost::Get()->Synchronize(reply, this); |
| } |
| |
| void ResourceMessageFilter::OnGetExtensionMessageBundle( |
| const std::string& extension_id, IPC::Message* reply_msg) { |
| ChromeURLRequestContext* context = static_cast<ChromeURLRequestContext*>( |
| request_context_->GetURLRequestContext()); |
| |
| FilePath extension_path = context->GetPathForExtension(extension_id); |
| std::string default_locale = |
| context->GetDefaultLocaleForExtension(extension_id); |
| |
| ChromeThread::PostTask( |
| ChromeThread::FILE, FROM_HERE, |
| NewRunnableMethod( |
| this, &ResourceMessageFilter::OnGetExtensionMessageBundleOnFileThread, |
| extension_path, extension_id, default_locale, reply_msg)); |
| } |
| |
| void ResourceMessageFilter::OnGetExtensionMessageBundleOnFileThread( |
| const FilePath& extension_path, |
| const std::string& extension_id, |
| const std::string& default_locale, |
| IPC::Message* reply_msg) { |
| DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
| |
| std::map<std::string, std::string> dictionary_map; |
| if (!default_locale.empty()) { |
| // Touch disk only if extension is localized. |
| std::string error; |
| scoped_ptr<ExtensionMessageBundle> bundle( |
| extension_file_util::LoadExtensionMessageBundle( |
| extension_path, default_locale, &error)); |
| |
| if (bundle.get()) |
| dictionary_map = *bundle->dictionary(); |
| } |
| |
| // Add @@extension_id reserved message here, so it's available to |
| // non-localized extensions too. |
| dictionary_map.insert( |
| std::make_pair(ExtensionMessageBundle::kExtensionIdKey, extension_id)); |
| |
| ViewHostMsg_GetExtensionMessageBundle::WriteReplyParams( |
| reply_msg, dictionary_map); |
| |
| ChromeThread::PostTask( |
| ChromeThread::IO, FROM_HERE, |
| NewRunnableMethod(this, &ResourceMessageFilter::Send, reply_msg)); |
| } |