| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/resource_message_filter.h" | |
| 6 | |
| 7 #include "base/clipboard.h" | |
| 8 #include "base/gfx/native_widget_types.h" | |
| 9 #include "base/histogram.h" | |
| 10 #include "base/thread.h" | |
| 11 #include "chrome/browser/chrome_plugin_browsing_context.h" | |
| 12 #include "chrome/browser/chrome_thread.h" | |
| 13 #include "chrome/browser/net/dns_global.h" | |
| 14 #include "chrome/browser/printing/print_job_manager.h" | |
| 15 #include "chrome/browser/printing/printer_query.h" | |
| 16 #include "chrome/browser/profile.h" | |
| 17 #include "chrome/browser/plugin_service.h" | |
| 18 #include "chrome/browser/renderer_host/browser_render_process_host.h" | |
| 19 #include "chrome/browser/renderer_host/render_widget_helper.h" | |
| 20 #include "chrome/browser/spellchecker.h" | |
| 21 #include "chrome/common/chrome_plugin_lib.h" | |
| 22 #include "chrome/common/chrome_plugin_util.h" | |
| 23 #include "chrome/common/clipboard_service.h" | |
| 24 #include "chrome/common/notification_service.h" | |
| 25 #include "chrome/common/pref_names.h" | |
| 26 #include "chrome/common/pref_service.h" | |
| 27 #include "chrome/common/ipc_message_macros.h" | |
| 28 #include "chrome/common/render_messages.h" | |
| 29 #include "net/base/cookie_monster.h" | |
| 30 #include "net/base/mime_util.h" | |
| 31 #include "webkit/glue/webkit_glue.h" | |
| 32 #include "webkit/glue/webplugin.h" | |
| 33 | |
| 34 namespace { | |
| 35 | |
| 36 // Context menus are somewhat complicated. We need to intercept them here on | |
| 37 // the I/O thread to add any spelling suggestions to them. After that's done, | |
| 38 // we need to forward the modified message to the UI thread and the normal | |
| 39 // message forwarding isn't set up for sending modified messages. | |
| 40 // | |
| 41 // Therefore, this class dispatches the IPC message to the RenderProcessHost | |
| 42 // with the given ID (if possible) to emulate the normal dispatch. | |
| 43 class ContextMenuMessageDispatcher : public Task { | |
| 44 public: | |
| 45 ContextMenuMessageDispatcher( | |
| 46 int render_process_host_id, | |
| 47 const ViewHostMsg_ContextMenu& context_menu_message) | |
| 48 : render_process_host_id_(render_process_host_id), | |
| 49 context_menu_message_(context_menu_message) { | |
| 50 } | |
| 51 | |
| 52 void Run() { | |
| 53 RenderProcessHost* host = | |
| 54 RenderProcessHost::FromID(render_process_host_id_); | |
| 55 if (host) | |
| 56 host->OnMessageReceived(context_menu_message_); | |
| 57 } | |
| 58 | |
| 59 private: | |
| 60 int render_process_host_id_; | |
| 61 const ViewHostMsg_ContextMenu context_menu_message_; | |
| 62 | |
| 63 DISALLOW_COPY_AND_ASSIGN(ContextMenuMessageDispatcher); | |
| 64 }; | |
| 65 | |
| 66 // Completes a clipboard write initiated by the renderer. The write must be | |
| 67 // performed on the UI thread because the clipboard service from the IO thread | |
| 68 // cannot create windows so it cannot be the "owner" of the clipboard's | |
| 69 // contents. | |
| 70 class WriteClipboardTask : public Task { | |
| 71 public: | |
| 72 explicit WriteClipboardTask(Clipboard::ObjectMap* objects) | |
| 73 : objects_(objects) {} | |
| 74 ~WriteClipboardTask() {} | |
| 75 | |
| 76 void Run() { | |
| 77 g_browser_process->clipboard_service()->WriteObjects(*objects_.get()); | |
| 78 } | |
| 79 | |
| 80 private: | |
| 81 scoped_ptr<Clipboard::ObjectMap> objects_; | |
| 82 }; | |
| 83 | |
| 84 | |
| 85 } // namespace | |
| 86 | |
| 87 ResourceMessageFilter::ResourceMessageFilter( | |
| 88 ResourceDispatcherHost* resource_dispatcher_host, | |
| 89 PluginService* plugin_service, | |
| 90 printing::PrintJobManager* print_job_manager, | |
| 91 int render_process_host_id, | |
| 92 Profile* profile, | |
| 93 RenderWidgetHelper* render_widget_helper, | |
| 94 SpellChecker* spellchecker) | |
| 95 : channel_(NULL), | |
| 96 resource_dispatcher_host_(resource_dispatcher_host), | |
| 97 plugin_service_(plugin_service), | |
| 98 print_job_manager_(print_job_manager), | |
| 99 render_process_host_id_(render_process_host_id), | |
| 100 render_handle_(NULL), | |
| 101 request_context_(profile->GetRequestContext()), | |
| 102 profile_(profile), | |
| 103 render_widget_helper_(render_widget_helper), | |
| 104 spellchecker_(spellchecker), | |
| 105 ALLOW_THIS_IN_INITIALIZER_LIST(resolve_proxy_msg_helper_(this, NULL)) { | |
| 106 | |
| 107 DCHECK(request_context_.get()); | |
| 108 DCHECK(request_context_->cookie_store()); | |
| 109 } | |
| 110 | |
| 111 ResourceMessageFilter::~ResourceMessageFilter() { | |
| 112 if (render_handle_) | |
| 113 CloseHandle(render_handle_); | |
| 114 | |
| 115 // This function should be called on the IO thread. | |
| 116 DCHECK(MessageLoop::current() == | |
| 117 ChromeThread::GetMessageLoop(ChromeThread::IO)); | |
| 118 NotificationService::current()->RemoveObserver( | |
| 119 this, | |
| 120 NotificationType::SPELLCHECKER_REINITIALIZED, | |
| 121 Source<Profile>(static_cast<Profile*>(profile_))); | |
| 122 } | |
| 123 | |
| 124 // Called on the IPC thread: | |
| 125 void ResourceMessageFilter::OnFilterAdded(IPC::Channel* channel) { | |
| 126 channel_ = channel; | |
| 127 | |
| 128 // Add the observers to intercept | |
| 129 NotificationService::current()->AddObserver( | |
| 130 this, | |
| 131 NotificationType::SPELLCHECKER_REINITIALIZED, | |
| 132 Source<Profile>(static_cast<Profile*>(profile_))); | |
| 133 } | |
| 134 | |
| 135 // Called on the IPC thread: | |
| 136 void ResourceMessageFilter::OnChannelConnected(int32 peer_pid) { | |
| 137 DCHECK(!render_handle_); | |
| 138 render_handle_ = OpenProcess(PROCESS_DUP_HANDLE | PROCESS_TERMINATE, | |
| 139 FALSE, peer_pid); | |
| 140 DCHECK(render_handle_); | |
| 141 } | |
| 142 | |
| 143 // Called on the IPC thread: | |
| 144 void ResourceMessageFilter::OnChannelClosing() { | |
| 145 channel_ = NULL; | |
| 146 | |
| 147 // Unhook us from all pending network requests so they don't get sent to a | |
| 148 // deleted object. | |
| 149 resource_dispatcher_host_->CancelRequestsForProcess(render_process_host_id_); | |
| 150 } | |
| 151 | |
| 152 // Called on the IPC thread: | |
| 153 bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& message) { | |
| 154 bool handled = true; | |
| 155 bool msg_is_ok = true; | |
| 156 IPC_BEGIN_MESSAGE_MAP_EX(ResourceMessageFilter, message, msg_is_ok) | |
| 157 IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWindow, OnMsgCreateWindow) | |
| 158 IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWidget, OnMsgCreateWidget) | |
| 159 // TODO(brettw): we should get the view ID for this so the resource | |
| 160 // dispatcher can prioritize things based on the visible view. | |
| 161 IPC_MESSAGE_HANDLER(ViewHostMsg_RequestResource, OnRequestResource) | |
| 162 IPC_MESSAGE_HANDLER(ViewHostMsg_CancelRequest, OnCancelRequest) | |
| 163 IPC_MESSAGE_HANDLER(ViewHostMsg_ClosePage_ACK, OnClosePageACK) | |
| 164 IPC_MESSAGE_HANDLER(ViewHostMsg_DataReceived_ACK, OnDataReceivedACK) | |
| 165 IPC_MESSAGE_HANDLER(ViewHostMsg_UploadProgress_ACK, OnUploadProgressACK) | |
| 166 | |
| 167 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_SyncLoad, OnSyncLoad) | |
| 168 | |
| 169 IPC_MESSAGE_HANDLER(ViewHostMsg_SetCookie, OnSetCookie) | |
| 170 IPC_MESSAGE_HANDLER(ViewHostMsg_GetCookies, OnGetCookies) | |
| 171 IPC_MESSAGE_HANDLER(ViewHostMsg_GetDataDir, OnGetDataDir) | |
| 172 IPC_MESSAGE_HANDLER(ViewHostMsg_PluginMessage, OnPluginMessage) | |
| 173 IPC_MESSAGE_HANDLER(ViewHostMsg_PluginSyncMessage, OnPluginSyncMessage) | |
| 174 IPC_MESSAGE_HANDLER(ViewHostMsg_LoadFont, OnLoadFont) | |
| 175 IPC_MESSAGE_HANDLER(ViewHostMsg_GetScreenInfo, OnGetScreenInfo) | |
| 176 IPC_MESSAGE_HANDLER(ViewHostMsg_GetPlugins, OnGetPlugins) | |
| 177 IPC_MESSAGE_HANDLER(ViewHostMsg_GetPluginPath, OnGetPluginPath) | |
| 178 IPC_MESSAGE_HANDLER(ViewHostMsg_DownloadUrl, OnDownloadUrl) | |
| 179 IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_ContextMenu, | |
| 180 OnReceiveContextMenuMsg(message)) | |
| 181 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_OpenChannelToPlugin, | |
| 182 OnOpenChannelToPlugin) | |
| 183 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_SpellCheck, OnSpellCheck) | |
| 184 IPC_MESSAGE_HANDLER(ViewHostMsg_DnsPrefetch, OnDnsPrefetch) | |
| 185 IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_PaintRect, | |
| 186 render_widget_helper_->DidReceivePaintMsg(message)) | |
| 187 IPC_MESSAGE_HANDLER(ViewHostMsg_ClipboardWriteObjectsAsync, | |
| 188 OnClipboardWriteObjects) | |
| 189 IPC_MESSAGE_HANDLER(ViewHostMsg_ClipboardWriteObjectsSync, | |
| 190 OnClipboardWriteObjects) | |
| 191 IPC_MESSAGE_HANDLER(ViewHostMsg_ClipboardIsFormatAvailable, | |
| 192 OnClipboardIsFormatAvailable) | |
| 193 IPC_MESSAGE_HANDLER(ViewHostMsg_ClipboardReadText, OnClipboardReadText) | |
| 194 IPC_MESSAGE_HANDLER(ViewHostMsg_ClipboardReadAsciiText, | |
| 195 OnClipboardReadAsciiText) | |
| 196 IPC_MESSAGE_HANDLER(ViewHostMsg_ClipboardReadHTML, | |
| 197 OnClipboardReadHTML) | |
| 198 #if defined(OS_WIN) | |
| 199 IPC_MESSAGE_HANDLER(ViewHostMsg_GetWindowRect, OnGetWindowRect) | |
| 200 IPC_MESSAGE_HANDLER(ViewHostMsg_GetRootWindowRect, OnGetRootWindowRect) | |
| 201 IPC_MESSAGE_HANDLER(ViewHostMsg_GetRootWindowResizerRect, | |
| 202 OnGetRootWindowResizerRect) | |
| 203 #endif | |
| 204 IPC_MESSAGE_HANDLER(ViewHostMsg_GetMimeTypeFromExtension, | |
| 205 OnGetMimeTypeFromExtension) | |
| 206 IPC_MESSAGE_HANDLER(ViewHostMsg_GetMimeTypeFromFile, | |
| 207 OnGetMimeTypeFromFile) | |
| 208 IPC_MESSAGE_HANDLER(ViewHostMsg_GetPreferredExtensionForMimeType, | |
| 209 OnGetPreferredExtensionForMimeType) | |
| 210 IPC_MESSAGE_HANDLER(ViewHostMsg_GetCPBrowsingContext, | |
| 211 OnGetCPBrowsingContext) | |
| 212 IPC_MESSAGE_HANDLER(ViewHostMsg_DuplicateSection, OnDuplicateSection) | |
| 213 IPC_MESSAGE_HANDLER(ViewHostMsg_ResourceTypeStats, OnResourceTypeStats) | |
| 214 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ResolveProxy, OnResolveProxy) | |
| 215 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetDefaultPrintSettings, | |
| 216 OnGetDefaultPrintSettings) | |
| 217 #if defined(OS_WIN) | |
| 218 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ScriptedPrint, | |
| 219 OnScriptedPrint) | |
| 220 #endif | |
| 221 IPC_MESSAGE_UNHANDLED( | |
| 222 handled = false) | |
| 223 IPC_END_MESSAGE_MAP_EX() | |
| 224 | |
| 225 if (!msg_is_ok) { | |
| 226 BrowserRenderProcessHost::BadMessageTerminateProcess(message.type(), | |
| 227 render_handle_); | |
| 228 } | |
| 229 | |
| 230 return handled; | |
| 231 } | |
| 232 | |
| 233 void ResourceMessageFilter::OnReceiveContextMenuMsg(const IPC::Message& msg) { | |
| 234 void* iter = NULL; | |
| 235 ViewHostMsg_ContextMenu_Params params; | |
| 236 if (!IPC::ParamTraits<ViewHostMsg_ContextMenu_Params>:: | |
| 237 Read(&msg, &iter, ¶ms)) | |
| 238 return; | |
| 239 | |
| 240 // Fill in the dictionary suggestions if required. | |
| 241 if (!params.misspelled_word.empty() && | |
| 242 spellchecker_ != NULL && params.spellcheck_enabled) { | |
| 243 int misspell_location, misspell_length; | |
| 244 bool is_misspelled = !spellchecker_->SpellCheckWord( | |
| 245 params.misspelled_word.c_str(), | |
| 246 static_cast<int>(params.misspelled_word.length()), | |
| 247 &misspell_location, &misspell_length, | |
| 248 ¶ms.dictionary_suggestions); | |
| 249 | |
| 250 // If not misspelled, make the misspelled_word param empty. | |
| 251 if (!is_misspelled) | |
| 252 params.misspelled_word.clear(); | |
| 253 } | |
| 254 | |
| 255 // Create a new ViewHostMsg_ContextMenu message. | |
| 256 const ViewHostMsg_ContextMenu context_menu_message(msg.routing_id(), params); | |
| 257 render_widget_helper_->ui_loop()->PostTask(FROM_HERE, | |
| 258 new ContextMenuMessageDispatcher(render_process_host_id_, | |
| 259 context_menu_message)); | |
| 260 } | |
| 261 | |
| 262 // Called on the IPC thread: | |
| 263 bool ResourceMessageFilter::Send(IPC::Message* message) { | |
| 264 if (!channel_) { | |
| 265 delete message; | |
| 266 return false; | |
| 267 } | |
| 268 | |
| 269 return channel_->Send(message); | |
| 270 } | |
| 271 | |
| 272 void ResourceMessageFilter::OnMsgCreateWindow( | |
| 273 int opener_id, bool user_gesture, int* route_id, | |
| 274 ModalDialogEvent* modal_dialog_event) { | |
| 275 render_widget_helper_->CreateNewWindow(opener_id, | |
| 276 user_gesture, | |
| 277 render_handle_, | |
| 278 route_id, | |
| 279 modal_dialog_event); | |
| 280 } | |
| 281 | |
| 282 void ResourceMessageFilter::OnMsgCreateWidget(int opener_id, | |
| 283 bool activatable, | |
| 284 int* route_id) { | |
| 285 render_widget_helper_->CreateNewWidget(opener_id, activatable, route_id); | |
| 286 } | |
| 287 | |
| 288 void ResourceMessageFilter::OnRequestResource( | |
| 289 const IPC::Message& message, | |
| 290 int request_id, | |
| 291 const ViewHostMsg_Resource_Request& request) { | |
| 292 resource_dispatcher_host_->BeginRequest(this, | |
| 293 render_handle_, | |
| 294 render_process_host_id_, | |
| 295 message.routing_id(), | |
| 296 request_id, | |
| 297 request, | |
| 298 request_context_, | |
| 299 NULL); | |
| 300 } | |
| 301 | |
| 302 void ResourceMessageFilter::OnDataReceivedACK(int request_id) { | |
| 303 resource_dispatcher_host_->OnDataReceivedACK(render_process_host_id_, | |
| 304 request_id); | |
| 305 } | |
| 306 | |
| 307 void ResourceMessageFilter::OnUploadProgressACK(int request_id) { | |
| 308 resource_dispatcher_host_->OnUploadProgressACK(render_process_host_id_, | |
| 309 request_id); | |
| 310 } | |
| 311 | |
| 312 void ResourceMessageFilter::OnCancelRequest(int request_id) { | |
| 313 resource_dispatcher_host_->CancelRequest(render_process_host_id_, request_id, | |
| 314 true); | |
| 315 } | |
| 316 | |
| 317 void ResourceMessageFilter::OnClosePageACK(int new_render_process_host_id, | |
| 318 int new_request_id) { | |
| 319 resource_dispatcher_host_->OnClosePageACK(new_render_process_host_id, | |
| 320 new_request_id); | |
| 321 } | |
| 322 | |
| 323 void ResourceMessageFilter::OnSyncLoad( | |
| 324 int request_id, | |
| 325 const ViewHostMsg_Resource_Request& request, | |
| 326 IPC::Message* sync_result) { | |
| 327 resource_dispatcher_host_->BeginRequest(this, | |
| 328 render_handle_, | |
| 329 render_process_host_id_, | |
| 330 sync_result->routing_id(), | |
| 331 request_id, | |
| 332 request, | |
| 333 request_context_, | |
| 334 sync_result); | |
| 335 } | |
| 336 | |
| 337 void ResourceMessageFilter::OnSetCookie(const GURL& url, | |
| 338 const GURL& policy_url, | |
| 339 const std::string& cookie) { | |
| 340 if (request_context_->cookie_policy()->CanSetCookie(url, policy_url)) | |
| 341 request_context_->cookie_store()->SetCookie(url, cookie); | |
| 342 } | |
| 343 | |
| 344 void ResourceMessageFilter::OnGetCookies(const GURL& url, | |
| 345 const GURL& policy_url, | |
| 346 std::string* cookies) { | |
| 347 if (request_context_->cookie_policy()->CanGetCookies(url, policy_url)) | |
| 348 *cookies = request_context_->cookie_store()->GetCookies(url); | |
| 349 } | |
| 350 | |
| 351 void ResourceMessageFilter::OnGetDataDir(std::wstring* data_dir) { | |
| 352 *data_dir = plugin_service_->GetChromePluginDataDir().ToWStringHack(); | |
| 353 } | |
| 354 | |
| 355 void ResourceMessageFilter::OnPluginMessage(const FilePath& plugin_path, | |
| 356 const std::vector<uint8>& data) { | |
| 357 DCHECK(MessageLoop::current() == | |
| 358 ChromeThread::GetMessageLoop(ChromeThread::IO)); | |
| 359 | |
| 360 ChromePluginLib *chrome_plugin = ChromePluginLib::Find(plugin_path); | |
| 361 if (chrome_plugin) { | |
| 362 void *data_ptr = const_cast<void*>(reinterpret_cast<const void*>(&data[0])); | |
| 363 uint32 data_len = static_cast<uint32>(data.size()); | |
| 364 chrome_plugin->functions().on_message(data_ptr, data_len); | |
| 365 } | |
| 366 } | |
| 367 | |
| 368 void ResourceMessageFilter::OnPluginSyncMessage(const FilePath& plugin_path, | |
| 369 const std::vector<uint8>& data, | |
| 370 std::vector<uint8> *retval) { | |
| 371 DCHECK(MessageLoop::current() == | |
| 372 ChromeThread::GetMessageLoop(ChromeThread::IO)); | |
| 373 | |
| 374 ChromePluginLib *chrome_plugin = ChromePluginLib::Find(plugin_path); | |
| 375 if (chrome_plugin) { | |
| 376 void *data_ptr = const_cast<void*>(reinterpret_cast<const void*>(&data[0])); | |
| 377 uint32 data_len = static_cast<uint32>(data.size()); | |
| 378 void *retval_buffer = 0; | |
| 379 uint32 retval_size = 0; | |
| 380 chrome_plugin->functions().on_sync_message(data_ptr, data_len, | |
| 381 &retval_buffer, &retval_size); | |
| 382 if (retval_buffer) { | |
| 383 retval->resize(retval_size); | |
| 384 memcpy(&(retval->at(0)), retval_buffer, retval_size); | |
| 385 CPB_Free(retval_buffer); | |
| 386 } | |
| 387 } | |
| 388 } | |
| 389 | |
| 390 void ResourceMessageFilter::OnLoadFont(LOGFONT font) { | |
| 391 // If renderer is running in a sandbox, GetTextMetrics | |
| 392 // can sometimes fail. If a font has not been loaded | |
| 393 // previously, GetTextMetrics will try to load the font | |
| 394 // from the font file. However, the sandboxed renderer does | |
| 395 // not have permissions to access any font files and | |
| 396 // the call fails. So we make the browser pre-load the | |
| 397 // font for us by using a dummy call to GetTextMetrics of | |
| 398 // the same font. | |
| 399 | |
| 400 // Maintain a circular queue for the fonts and DCs to be cached. | |
| 401 // font_index maintains next available location in the queue. | |
| 402 static const int kFontCacheSize = 32; | |
| 403 static HFONT fonts[kFontCacheSize] = {0}; | |
| 404 static HDC hdcs[kFontCacheSize] = {0}; | |
| 405 static size_t font_index = 0; | |
| 406 | |
| 407 UMA_HISTOGRAM_COUNTS_100(L"Memory.CachedFontAndDC", | |
| 408 fonts[kFontCacheSize-1] ? kFontCacheSize : static_cast<int>(font_index)); | |
| 409 | |
| 410 HDC hdc = GetDC(NULL); | |
| 411 HFONT font_handle = CreateFontIndirect(&font); | |
| 412 DCHECK(NULL != font_handle); | |
| 413 | |
| 414 HGDIOBJ old_font = SelectObject(hdc, font_handle); | |
| 415 DCHECK(NULL != old_font); | |
| 416 | |
| 417 TEXTMETRIC tm; | |
| 418 BOOL ret = GetTextMetrics(hdc, &tm); | |
| 419 DCHECK(ret); | |
| 420 | |
| 421 if (fonts[font_index] || hdcs[font_index]) { | |
| 422 // We already have too many fonts, we will delete one and take it's place. | |
| 423 DeleteObject(fonts[font_index]); | |
| 424 ReleaseDC(NULL, hdcs[font_index]); | |
| 425 } | |
| 426 | |
| 427 fonts[font_index] = font_handle; | |
| 428 hdcs[font_index] = hdc; | |
| 429 font_index = (font_index + 1) % kFontCacheSize; | |
| 430 } | |
| 431 | |
| 432 void ResourceMessageFilter::OnGetScreenInfo( | |
| 433 gfx::NativeViewId window, webkit_glue::ScreenInfo* results) { | |
| 434 *results = webkit_glue::GetScreenInfoHelper(gfx::NativeViewFromId(window)); | |
| 435 } | |
| 436 | |
| 437 void ResourceMessageFilter::OnGetPlugins(bool refresh, | |
| 438 std::vector<WebPluginInfo>* plugins) { | |
| 439 plugin_service_->GetPlugins(refresh, plugins); | |
| 440 } | |
| 441 | |
| 442 void ResourceMessageFilter::OnGetPluginPath(const GURL& url, | |
| 443 const std::string& mime_type, | |
| 444 const std::string& clsid, | |
| 445 FilePath* filename, | |
| 446 std::string* url_mime_type) { | |
| 447 *filename = plugin_service_->GetPluginPath(url, mime_type, clsid, | |
| 448 url_mime_type); | |
| 449 } | |
| 450 | |
| 451 void ResourceMessageFilter::OnOpenChannelToPlugin(const GURL& url, | |
| 452 const std::string& mime_type, | |
| 453 const std::string& clsid, | |
| 454 const std::wstring& locale, | |
| 455 IPC::Message* reply_msg) { | |
| 456 plugin_service_->OpenChannelToPlugin(this, url, mime_type, clsid, | |
| 457 locale, reply_msg); | |
| 458 } | |
| 459 | |
| 460 void ResourceMessageFilter::OnDownloadUrl(const IPC::Message& message, | |
| 461 const GURL& url, | |
| 462 const GURL& referrer) { | |
| 463 resource_dispatcher_host_->BeginDownload(url, | |
| 464 referrer, | |
| 465 render_process_host_id_, | |
| 466 message.routing_id(), | |
| 467 request_context_); | |
| 468 } | |
| 469 | |
| 470 void ResourceMessageFilter::OnClipboardWriteObjects( | |
| 471 const Clipboard::ObjectMap& objects) { | |
| 472 // We cannot write directly from the IO thread, and cannot service the IPC | |
| 473 // on the UI thread. We'll copy the relevant data and get a handle to any | |
| 474 // shared memory so it doesn't go away when we resume the renderer, and post | |
| 475 // a task to perform the write on the UI thread. | |
| 476 Clipboard::ObjectMap* long_living_objects = new Clipboard::ObjectMap(objects);
| |
| 477 | |
| 478 // We pass the render_handle_ to assist the clipboard with using shared | |
| 479 // memory objects. render_handle_ is a handle to the process that would | |
| 480 // own any shared memory that might be in the object list. | |
| 481 Clipboard::DuplicateRemoteHandles(render_handle_, long_living_objects); | |
| 482 | |
| 483 render_widget_helper_->ui_loop()->PostTask(FROM_HERE, | |
| 484 new WriteClipboardTask(long_living_objects)); | |
| 485 } | |
| 486 | |
| 487 void ResourceMessageFilter::OnClipboardIsFormatAvailable(unsigned int format, | |
| 488 bool* result) { | |
| 489 DCHECK(result); | |
| 490 *result = GetClipboardService()->IsFormatAvailable(format); | |
| 491 } | |
| 492 | |
| 493 void ResourceMessageFilter::OnClipboardReadText(std::wstring* result) { | |
| 494 GetClipboardService()->ReadText(result); | |
| 495 } | |
| 496 | |
| 497 void ResourceMessageFilter::OnClipboardReadAsciiText(std::string* result) { | |
| 498 GetClipboardService()->ReadAsciiText(result); | |
| 499 } | |
| 500 | |
| 501 void ResourceMessageFilter::OnClipboardReadHTML(std::wstring* markup, | |
| 502 GURL* src_url) { | |
| 503 std::string src_url_str; | |
| 504 GetClipboardService()->ReadHTML(markup, &src_url_str); | |
| 505 *src_url = GURL(src_url_str); | |
| 506 } | |
| 507 | |
| 508 #if defined(OS_WIN) | |
| 509 | |
| 510 void ResourceMessageFilter::OnGetWindowRect(gfx::NativeViewId window_id, | |
| 511 gfx::Rect* rect) { | |
| 512 HWND window = gfx::NativeViewFromId(window_id); | |
| 513 RECT window_rect = {0}; | |
| 514 GetWindowRect(window, &window_rect); | |
| 515 *rect = window_rect; | |
| 516 } | |
| 517 | |
| 518 void ResourceMessageFilter::OnGetRootWindowRect(gfx::NativeViewId window_id, | |
| 519 gfx::Rect* rect) { | |
| 520 HWND window = gfx::NativeViewFromId(window_id); | |
| 521 RECT window_rect = {0}; | |
| 522 HWND root_window = ::GetAncestor(window, GA_ROOT); | |
| 523 GetWindowRect(root_window, &window_rect); | |
| 524 *rect = window_rect; | |
| 525 } | |
| 526 | |
| 527 void ResourceMessageFilter::OnGetRootWindowResizerRect(gfx::NativeViewId window, | |
| 528 gfx::Rect* rect) { | |
| 529 RECT window_rect = {0}; | |
| 530 *rect = window_rect; | |
| 531 } | |
| 532 | |
| 533 #endif // OS_WIN | |
| 534 | |
| 535 void ResourceMessageFilter::OnGetMimeTypeFromExtension( | |
| 536 const std::wstring& ext, std::string* mime_type) { | |
| 537 net::GetMimeTypeFromExtension(ext, mime_type); | |
| 538 } | |
| 539 | |
| 540 void ResourceMessageFilter::OnGetMimeTypeFromFile( | |
| 541 const std::wstring& file_path, std::string* mime_type) { | |
| 542 net::GetMimeTypeFromFile(file_path, mime_type); | |
| 543 } | |
| 544 | |
| 545 void ResourceMessageFilter::OnGetPreferredExtensionForMimeType( | |
| 546 const std::string& mime_type, std::wstring* ext) { | |
| 547 net::GetPreferredExtensionForMimeType(mime_type, ext); | |
| 548 } | |
| 549 | |
| 550 void ResourceMessageFilter::OnGetCPBrowsingContext(uint32* context) { | |
| 551 // Always allocate a new context when a plugin requests one, since it needs to | |
| 552 // be unique for that plugin instance. | |
| 553 *context = | |
| 554 CPBrowsingContextManager::Instance()->Allocate(request_context_.get()); | |
| 555 } | |
| 556 | |
| 557 void ResourceMessageFilter::OnDuplicateSection( | |
| 558 base::SharedMemoryHandle renderer_handle, | |
| 559 base::SharedMemoryHandle* browser_handle) { | |
| 560 // Duplicate the handle in this process right now so the memory is kept alive | |
| 561 // (even if it is not mapped) | |
| 562 base::SharedMemory shared_buf(renderer_handle, true, render_handle_); | |
| 563 shared_buf.GiveToProcess(GetCurrentProcess(), browser_handle); | |
| 564 } | |
| 565 | |
| 566 void ResourceMessageFilter::OnResourceTypeStats( | |
| 567 const CacheManager::ResourceTypeStats& stats) { | |
| 568 HISTOGRAM_COUNTS(L"WebCoreCache.ImagesSizeKB", | |
| 569 static_cast<int>(stats.images.size / 1024)); | |
| 570 HISTOGRAM_COUNTS(L"WebCoreCache.CSSStylesheetsSizeKB", | |
| 571 static_cast<int>(stats.css_stylesheets.size / 1024)); | |
| 572 HISTOGRAM_COUNTS(L"WebCoreCache.ScriptsSizeKB", | |
| 573 static_cast<int>(stats.scripts.size / 1024)); | |
| 574 HISTOGRAM_COUNTS(L"WebCoreCache.XSLStylesheetsSizeKB", | |
| 575 static_cast<int>(stats.xsl_stylesheets.size / 1024)); | |
| 576 HISTOGRAM_COUNTS(L"WebCoreCache.FontsSizeKB", | |
| 577 static_cast<int>(stats.fonts.size / 1024)); | |
| 578 } | |
| 579 | |
| 580 void ResourceMessageFilter::OnResolveProxy(const GURL& url, | |
| 581 IPC::Message* reply_msg) { | |
| 582 resolve_proxy_msg_helper_.Start(url, reply_msg); | |
| 583 } | |
| 584 | |
| 585 void ResourceMessageFilter::OnResolveProxyCompleted( | |
| 586 IPC::Message* reply_msg, | |
| 587 int result, | |
| 588 const std::string& proxy_list) { | |
| 589 ViewHostMsg_ResolveProxy::WriteReplyParams(reply_msg, result, proxy_list); | |
| 590 Send(reply_msg); | |
| 591 } | |
| 592 | |
| 593 void ResourceMessageFilter::OnGetDefaultPrintSettings(IPC::Message* reply_msg) { | |
| 594 scoped_refptr<printing::PrinterQuery> printer_query; | |
| 595 print_job_manager_->PopPrinterQuery(0, &printer_query); | |
| 596 if (!printer_query.get()) { | |
| 597 printer_query = new printing::PrinterQuery; | |
| 598 } | |
| 599 | |
| 600 CancelableTask* task = NewRunnableMethod( | |
| 601 this, | |
| 602 &ResourceMessageFilter::OnGetDefaultPrintSettingsReply, | |
| 603 printer_query, | |
| 604 reply_msg); | |
| 605 // Loads default settings. This is asynchronous, only the IPC message sender | |
| 606 // will hang until the settings are retrieved. | |
| 607 printer_query->GetSettings(printing::PrinterQuery::DEFAULTS, | |
| 608 NULL, | |
| 609 0, | |
| 610 task); | |
| 611 } | |
| 612 | |
| 613 void ResourceMessageFilter::OnGetDefaultPrintSettingsReply( | |
| 614 scoped_refptr<printing::PrinterQuery> printer_query, | |
| 615 IPC::Message* reply_msg) { | |
| 616 ViewMsg_Print_Params params; | |
| 617 if (printer_query->last_status() != printing::PrintingContext::OK) { | |
| 618 memset(¶ms, 0, sizeof(params)); | |
| 619 } else { | |
| 620 printer_query->settings().RenderParams(¶ms); | |
| 621 params.document_cookie = printer_query->cookie(); | |
| 622 } | |
| 623 ViewHostMsg_GetDefaultPrintSettings::WriteReplyParams(reply_msg, params); | |
| 624 Send(reply_msg); | |
| 625 // If user hasn't cancelled. | |
| 626 if (printer_query->cookie() && printer_query->settings().dpi()) { | |
| 627 print_job_manager_->QueuePrinterQuery(printer_query.get()); | |
| 628 } else { | |
| 629 printer_query->StopWorker(); | |
| 630 } | |
| 631 } | |
| 632 | |
| 633 #if defined(OS_WIN) | |
| 634 | |
| 635 void ResourceMessageFilter::OnScriptedPrint(gfx::NativeViewId host_window_id, | |
| 636 int cookie, | |
| 637 int expected_pages_count, | |
| 638 IPC::Message* reply_msg) { | |
| 639 HWND host_window = gfx::NativeViewFromId(host_window_id); | |
| 640 | |
| 641 scoped_refptr<printing::PrinterQuery> printer_query; | |
| 642 print_job_manager_->PopPrinterQuery(cookie, &printer_query); | |
| 643 if (!printer_query.get()) { | |
| 644 printer_query = new printing::PrinterQuery; | |
| 645 } | |
| 646 | |
| 647 CancelableTask* task = NewRunnableMethod( | |
| 648 this, | |
| 649 &ResourceMessageFilter::OnScriptedPrintReply, | |
| 650 printer_query, | |
| 651 reply_msg); | |
| 652 // Shows the Print... dialog box. This is asynchronous, only the IPC message | |
| 653 // sender will hang until the Print dialog is dismissed. | |
| 654 if (!host_window || !IsWindow(host_window)) { | |
| 655 // TODO(maruel): bug 1214347 Get the right browser window instead. | |
| 656 host_window = GetDesktopWindow(); | |
| 657 } else { | |
| 658 host_window = GetAncestor(host_window, GA_ROOTOWNER); | |
| 659 } | |
| 660 DCHECK(host_window); | |
| 661 printer_query->GetSettings(printing::PrinterQuery::ASK_USER, | |
| 662 host_window, | |
| 663 expected_pages_count, | |
| 664 task); | |
| 665 } | |
| 666 | |
| 667 void ResourceMessageFilter::OnScriptedPrintReply( | |
| 668 scoped_refptr<printing::PrinterQuery> printer_query, | |
| 669 IPC::Message* reply_msg) { | |
| 670 ViewMsg_PrintPages_Params params; | |
| 671 if (printer_query->last_status() != printing::PrintingContext::OK || | |
| 672 !printer_query->settings().dpi()) { | |
| 673 memset(¶ms, 0, sizeof(params)); | |
| 674 } else { | |
| 675 printer_query->settings().RenderParams(¶ms.params); | |
| 676 params.params.document_cookie = printer_query->cookie(); | |
| 677 params.pages = | |
| 678 printing::PageRange::GetPages(printer_query->settings().ranges); | |
| 679 } | |
| 680 ViewHostMsg_ScriptedPrint::WriteReplyParams(reply_msg, params); | |
| 681 Send(reply_msg); | |
| 682 if (params.params.dpi && params.params.document_cookie) { | |
| 683 print_job_manager_->QueuePrinterQuery(printer_query.get()); | |
| 684 } else { | |
| 685 printer_query->StopWorker(); | |
| 686 } | |
| 687 } | |
| 688 | |
| 689 #endif // OS_WIN | |
| 690 | |
| 691 // static | |
| 692 ClipboardService* ResourceMessageFilter::GetClipboardService() { | |
| 693 // We have a static instance of the clipboard service for use by all message | |
| 694 // filters. This instance lives for the life of the browser processes. | |
| 695 static ClipboardService* clipboard_service = new ClipboardService(); | |
| 696 | |
| 697 return clipboard_service; | |
| 698 } | |
| 699 | |
| 700 // Notes about SpellCheck. | |
| 701 // | |
| 702 // Spellchecking generally uses a fair amount of RAM. For this reason, we load | |
| 703 // the spellcheck dictionaries into the browser process, and all renderers ask | |
| 704 // the browsers to do SpellChecking. | |
| 705 // | |
| 706 // This filter should not try to initialize the spellchecker. It is up to the | |
| 707 // profile to initialize it when required, and send it here. If |spellchecker_| | |
| 708 // is made NULL, it corresponds to spellchecker turned off - i.e., all | |
| 709 // spellings are correct. | |
| 710 // | |
| 711 // Note: This is called in the IO thread. | |
| 712 void ResourceMessageFilter::OnSpellCheck(const std::wstring& word, | |
| 713 IPC::Message* reply_msg) { | |
| 714 int misspell_location = 0; | |
| 715 int misspell_length = 0; | |
| 716 | |
| 717 if (spellchecker_ != NULL) { | |
| 718 spellchecker_->SpellCheckWord(word.c_str(), | |
| 719 static_cast<int>(word.length()), | |
| 720 &misspell_location, &misspell_length, NULL); | |
| 721 } | |
| 722 | |
| 723 ViewHostMsg_SpellCheck::WriteReplyParams(reply_msg, misspell_location, | |
| 724 misspell_length); | |
| 725 Send(reply_msg); | |
| 726 return; | |
| 727 } | |
| 728 | |
| 729 void ResourceMessageFilter::Observe(NotificationType type, | |
| 730 const NotificationSource &source, | |
| 731 const NotificationDetails &details) { | |
| 732 if (type == NotificationType::SPELLCHECKER_REINITIALIZED) { | |
| 733 spellchecker_ = Details<SpellcheckerReinitializedDetails> | |
| 734 (details).ptr()->spellchecker; | |
| 735 } | |
| 736 } | |
| 737 | |
| 738 void ResourceMessageFilter::OnDnsPrefetch( | |
| 739 const std::vector<std::string>& hostnames) { | |
| 740 chrome_browser_net::DnsPrefetchList(hostnames); | |
| 741 } | |
| OLD | NEW |