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 |