chrome_render_message_filter.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
1// Copyright (c) 2012 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/renderer_host/chrome_render_message_filter.h"
6
7#include "base/bind.h"
8#include "base/command_line.h"
9#include "base/file_util.h"
10#include "base/metrics/histogram.h"
11#include "chrome/browser/automation/automation_resource_message_filter.h"
12#include "chrome/browser/browser_process.h"
13#include "chrome/browser/content_settings/cookie_settings.h"
14#include "chrome/browser/content_settings/tab_specific_content_settings.h"
15#include "chrome/browser/extensions/activity_log.h"
16#include "chrome/browser/extensions/api/messaging/message_service.h"
17#include "chrome/browser/extensions/event_router.h"
18#include "chrome/browser/extensions/extension_function_dispatcher.h"
19#include "chrome/browser/extensions/extension_info_map.h"
20#include "chrome/browser/extensions/extension_process_manager.h"
21#include "chrome/browser/extensions/extension_service.h"
22#include "chrome/browser/extensions/extension_system.h"
23#include "chrome/browser/nacl_host/nacl_infobar.h"
24#include "chrome/browser/nacl_host/nacl_process_host.h"
25#include "chrome/browser/nacl_host/pnacl_file_host.h"
26#include "chrome/browser/net/chrome_url_request_context.h"
27#include "chrome/browser/net/predictor.h"
28#include "chrome/browser/profiles/profile.h"
29#include "chrome/browser/task_manager/task_manager.h"
30#include "chrome/common/chrome_notification_types.h"
31#include "chrome/common/chrome_switches.h"
32#include "chrome/common/extensions/api/i18n/default_locale_handler.h"
33#include "chrome/common/extensions/extension.h"
34#include "chrome/common/extensions/extension_file_util.h"
35#include "chrome/common/extensions/extension_messages.h"
36#include "chrome/common/extensions/message_bundle.h"
37#include "chrome/common/render_messages.h"
38#include "chrome/common/url_constants.h"
39#include "content/public/browser/notification_service.h"
40#include "content/public/browser/render_process_host.h"
41#include "content/public/browser/resource_dispatcher_host.h"
42#include "content/public/common/process_type.h"
43#include "extensions/common/constants.h"
44#include "googleurl/src/gurl.h"
45#include "third_party/WebKit/Source/Platform/chromium/public/WebString.h"
46#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h"
47#include "webkit/plugins/npapi/plugin_list.h"
48
49#if defined(USE_TCMALLOC)
50#include "chrome/browser/browser_about_handler.h"
51#endif
52
53using content::BrowserThread;
54using extensions::APIPermission;
55using WebKit::WebCache;
56using WebKit::WebSecurityOrigin;
57
58namespace {
59
60void AddDOMActionToExtensionActivityLog(
61    Profile* profile,
62    const extensions::Extension* extension,
63    const GURL& url,
64    const string16& url_title,
65    const std::string& api_call,
66    scoped_ptr<ListValue> args,
67    const std::string& extra) {
68  // The ActivityLog can only be accessed from the main (UI) thread.  If we're
69  // running on the wrong thread, re-dispatch from the main thread.
70  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
71    BrowserThread::PostTask(BrowserThread::UI,
72                            FROM_HERE,
73                            base::Bind(&AddDOMActionToExtensionActivityLog,
74                                       profile,
75                                       extension,
76                                       url,
77                                       url_title,
78                                       api_call,
79                                       base::Passed(&args),
80                                       extra));
81  } else {
82    extensions::ActivityLog* activity_log =
83        extensions::ActivityLog::GetInstance(profile);
84    if (activity_log)
85      activity_log->LogDOMAction(extension, url, url_title,
86                                 api_call, args.get(), extra);
87  }
88}
89
90} // namespace
91
92ChromeRenderMessageFilter::ChromeRenderMessageFilter(
93    int render_process_id,
94    Profile* profile,
95    net::URLRequestContextGetter* request_context)
96    : render_process_id_(render_process_id),
97      profile_(profile),
98      off_the_record_(profile_->IsOffTheRecord()),
99      request_context_(request_context),
100      extension_info_map_(
101          extensions::ExtensionSystem::Get(profile)->info_map()),
102      cookie_settings_(CookieSettings::Factory::GetForProfile(profile)),
103      weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
104}
105
106ChromeRenderMessageFilter::~ChromeRenderMessageFilter() {
107}
108
109bool ChromeRenderMessageFilter::OnMessageReceived(const IPC::Message& message,
110                                                  bool* message_was_ok) {
111  bool handled = true;
112  IPC_BEGIN_MESSAGE_MAP_EX(ChromeRenderMessageFilter, message, *message_was_ok)
113#if !defined(DISABLE_NACL)
114    IPC_MESSAGE_HANDLER_DELAY_REPLY(ChromeViewHostMsg_LaunchNaCl, OnLaunchNaCl)
115    IPC_MESSAGE_HANDLER_DELAY_REPLY(ChromeViewHostMsg_GetReadonlyPnaclFD,
116                                    OnGetReadonlyPnaclFd)
117    IPC_MESSAGE_HANDLER_DELAY_REPLY(ChromeViewHostMsg_NaClCreateTemporaryFile,
118                                    OnNaClCreateTemporaryFile)
119    IPC_MESSAGE_HANDLER(ChromeViewHostMsg_NaClErrorStatus, OnNaClErrorStatus)
120#endif
121    IPC_MESSAGE_HANDLER(ChromeViewHostMsg_DnsPrefetch, OnDnsPrefetch)
122    IPC_MESSAGE_HANDLER(ChromeViewHostMsg_ResourceTypeStats,
123                        OnResourceTypeStats)
124    IPC_MESSAGE_HANDLER(ChromeViewHostMsg_UpdatedCacheStats,
125                        OnUpdatedCacheStats)
126    IPC_MESSAGE_HANDLER(ChromeViewHostMsg_FPS, OnFPS)
127    IPC_MESSAGE_HANDLER(ChromeViewHostMsg_V8HeapStats, OnV8HeapStats)
128    IPC_MESSAGE_HANDLER(ExtensionHostMsg_OpenChannelToExtension,
129                        OnOpenChannelToExtension)
130    IPC_MESSAGE_HANDLER(ExtensionHostMsg_OpenChannelToTab, OnOpenChannelToTab)
131    IPC_MESSAGE_HANDLER(ExtensionHostMsg_OpenChannelToNativeApp,
132                        OnOpenChannelToNativeApp)
133    IPC_MESSAGE_HANDLER_DELAY_REPLY(ExtensionHostMsg_GetMessageBundle,
134                                    OnGetExtensionMessageBundle)
135    IPC_MESSAGE_HANDLER(ExtensionHostMsg_AddListener, OnExtensionAddListener)
136    IPC_MESSAGE_HANDLER(ExtensionHostMsg_RemoveListener,
137                        OnExtensionRemoveListener)
138    IPC_MESSAGE_HANDLER(ExtensionHostMsg_AddLazyListener,
139                        OnExtensionAddLazyListener)
140    IPC_MESSAGE_HANDLER(ExtensionHostMsg_RemoveLazyListener,
141                        OnExtensionRemoveLazyListener)
142    IPC_MESSAGE_HANDLER(ExtensionHostMsg_AddFilteredListener,
143                        OnExtensionAddFilteredListener)
144    IPC_MESSAGE_HANDLER(ExtensionHostMsg_RemoveFilteredListener,
145                        OnExtensionRemoveFilteredListener)
146    IPC_MESSAGE_HANDLER(ExtensionHostMsg_CloseChannel, OnExtensionCloseChannel)
147    IPC_MESSAGE_HANDLER(ExtensionHostMsg_RequestForIOThread,
148                        OnExtensionRequestForIOThread)
149    IPC_MESSAGE_HANDLER(ExtensionHostMsg_ShouldSuspendAck,
150                        OnExtensionShouldSuspendAck)
151    IPC_MESSAGE_HANDLER(ExtensionHostMsg_GenerateUniqueID,
152                        OnExtensionGenerateUniqueID)
153    IPC_MESSAGE_HANDLER(ExtensionHostMsg_SuspendAck, OnExtensionSuspendAck)
154    IPC_MESSAGE_HANDLER(ExtensionHostMsg_ResumeRequests,
155                        OnExtensionResumeRequests);
156    IPC_MESSAGE_HANDLER(ExtensionHostMsg_AddDOMActionToActivityLog,
157                        OnAddDOMActionToExtensionActivityLog);
158    IPC_MESSAGE_HANDLER(ChromeViewHostMsg_AllowDatabase, OnAllowDatabase)
159    IPC_MESSAGE_HANDLER(ChromeViewHostMsg_AllowDOMStorage, OnAllowDOMStorage)
160    IPC_MESSAGE_HANDLER(ChromeViewHostMsg_AllowFileSystem, OnAllowFileSystem)
161    IPC_MESSAGE_HANDLER(ChromeViewHostMsg_AllowIndexedDB, OnAllowIndexedDB)
162    IPC_MESSAGE_HANDLER(ChromeViewHostMsg_CanTriggerClipboardRead,
163                        OnCanTriggerClipboardRead)
164    IPC_MESSAGE_HANDLER(ChromeViewHostMsg_CanTriggerClipboardWrite,
165                        OnCanTriggerClipboardWrite)
166    IPC_MESSAGE_UNHANDLED(handled = false)
167  IPC_END_MESSAGE_MAP()
168
169#if defined(ENABLE_AUTOMATION)
170  if ((message.type() == ChromeViewHostMsg_GetCookies::ID ||
171       message.type() == ChromeViewHostMsg_SetCookie::ID) &&
172    AutomationResourceMessageFilter::ShouldFilterCookieMessages(
173        render_process_id_, message.routing_id())) {
174    // ChromeFrame then we need to get/set cookies from the external host.
175    IPC_BEGIN_MESSAGE_MAP_EX(ChromeRenderMessageFilter, message,
176                             *message_was_ok)
177      IPC_MESSAGE_HANDLER_DELAY_REPLY(ChromeViewHostMsg_GetCookies,
178                                      OnGetCookies)
179      IPC_MESSAGE_HANDLER(ChromeViewHostMsg_SetCookie, OnSetCookie)
180    IPC_END_MESSAGE_MAP()
181    handled = true;
182  }
183#endif
184
185  return handled;
186}
187
188void ChromeRenderMessageFilter::OverrideThreadForMessage(
189    const IPC::Message& message, BrowserThread::ID* thread) {
190  switch (message.type()) {
191    case ChromeViewHostMsg_ResourceTypeStats::ID:
192    case ExtensionHostMsg_AddListener::ID:
193    case ExtensionHostMsg_RemoveListener::ID:
194    case ExtensionHostMsg_AddLazyListener::ID:
195    case ExtensionHostMsg_RemoveLazyListener::ID:
196    case ExtensionHostMsg_AddFilteredListener::ID:
197    case ExtensionHostMsg_RemoveFilteredListener::ID:
198    case ExtensionHostMsg_CloseChannel::ID:
199    case ExtensionHostMsg_ShouldSuspendAck::ID:
200    case ExtensionHostMsg_SuspendAck::ID:
201    case ChromeViewHostMsg_UpdatedCacheStats::ID:
202      *thread = BrowserThread::UI;
203      break;
204    default:
205      break;
206  }
207}
208
209net::HostResolver* ChromeRenderMessageFilter::GetHostResolver() {
210  return request_context_->GetURLRequestContext()->host_resolver();
211}
212
213#if !defined(DISABLE_NACL)
214void ChromeRenderMessageFilter::OnLaunchNaCl(
215    const nacl::NaClLaunchParams& launch_params,
216    IPC::Message* reply_msg) {
217  NaClProcessHost* host = new NaClProcessHost(
218      GURL(launch_params.manifest_url),
219      launch_params.render_view_id,
220      launch_params.permission_bits,
221      launch_params.uses_irt,
222      off_the_record_);
223  host->Launch(this, reply_msg, extension_info_map_);
224}
225
226void ChromeRenderMessageFilter::OnGetReadonlyPnaclFd(
227    const std::string& filename, IPC::Message* reply_msg) {
228  // This posts a task to another thread, but the renderer will
229  // block until the reply is sent.
230  pnacl_file_host::GetReadonlyPnaclFd(this, filename, reply_msg);
231}
232
233void ChromeRenderMessageFilter::OnNaClCreateTemporaryFile(
234    IPC::Message* reply_msg) {
235  pnacl_file_host::CreateTemporaryFile(this, reply_msg);
236}
237
238void ChromeRenderMessageFilter::OnNaClErrorStatus(int render_view_id,
239                                                  int error_id) {
240  // Currently there is only one kind of error status, for which
241  // we want to show the user an infobar.
242  ShowNaClInfobar(render_process_id_, render_view_id, error_id);
243}
244#endif
245
246void ChromeRenderMessageFilter::OnDnsPrefetch(
247    const std::vector<std::string>& hostnames) {
248  if (profile_->GetNetworkPredictor())
249    profile_->GetNetworkPredictor()->DnsPrefetchList(hostnames);
250}
251
252void ChromeRenderMessageFilter::OnResourceTypeStats(
253    const WebCache::ResourceTypeStats& stats) {
254  HISTOGRAM_COUNTS("WebCoreCache.ImagesSizeKB",
255                   static_cast<int>(stats.images.size / 1024));
256  HISTOGRAM_COUNTS("WebCoreCache.CSSStylesheetsSizeKB",
257                   static_cast<int>(stats.cssStyleSheets.size / 1024));
258  HISTOGRAM_COUNTS("WebCoreCache.ScriptsSizeKB",
259                   static_cast<int>(stats.scripts.size / 1024));
260  HISTOGRAM_COUNTS("WebCoreCache.XSLStylesheetsSizeKB",
261                   static_cast<int>(stats.xslStyleSheets.size / 1024));
262  HISTOGRAM_COUNTS("WebCoreCache.FontsSizeKB",
263                   static_cast<int>(stats.fonts.size / 1024));
264
265  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
266#if defined(ENABLE_TASK_MANAGER)
267  TaskManager::GetInstance()->model()->NotifyResourceTypeStats(
268      base::GetProcId(peer_handle()), stats);
269#endif  // defined(ENABLE_TASK_MANAGER)
270}
271
272void ChromeRenderMessageFilter::OnUpdatedCacheStats(
273    const WebCache::UsageStats& stats) {
274  WebCacheManager::GetInstance()->ObserveStats(render_process_id_, stats);
275}
276
277void ChromeRenderMessageFilter::OnFPS(int routing_id, float fps) {
278  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
279    BrowserThread::PostTask(
280        BrowserThread::UI, FROM_HERE,
281        base::Bind(
282            &ChromeRenderMessageFilter::OnFPS, this,
283            routing_id, fps));
284    return;
285  }
286
287  base::ProcessId renderer_id = base::GetProcId(peer_handle());
288
289#if defined(ENABLE_TASK_MANAGER)
290  TaskManager::GetInstance()->model()->NotifyFPS(
291      renderer_id, routing_id, fps);
292#endif  // defined(ENABLE_TASK_MANAGER)
293
294  FPSDetails details(routing_id, fps);
295  content::NotificationService::current()->Notify(
296      chrome::NOTIFICATION_RENDERER_FPS_COMPUTED,
297      content::Source<const base::ProcessId>(&renderer_id),
298      content::Details<const FPSDetails>(&details));
299}
300
301void ChromeRenderMessageFilter::OnV8HeapStats(int v8_memory_allocated,
302                                              int v8_memory_used) {
303  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
304    BrowserThread::PostTask(
305        BrowserThread::UI, FROM_HERE,
306        base::Bind(
307            &ChromeRenderMessageFilter::OnV8HeapStats, this,
308            v8_memory_allocated, v8_memory_used));
309    return;
310  }
311
312  base::ProcessId renderer_id = base::GetProcId(peer_handle());
313
314#if defined(ENABLE_TASK_MANAGER)
315  TaskManager::GetInstance()->model()->NotifyV8HeapStats(
316      renderer_id,
317      static_cast<size_t>(v8_memory_allocated),
318      static_cast<size_t>(v8_memory_used));
319#endif  // defined(ENABLE_TASK_MANAGER)
320
321  V8HeapStatsDetails details(v8_memory_allocated, v8_memory_used);
322  content::NotificationService::current()->Notify(
323      chrome::NOTIFICATION_RENDERER_V8_HEAP_STATS_COMPUTED,
324      content::Source<const base::ProcessId>(&renderer_id),
325      content::Details<const V8HeapStatsDetails>(&details));
326}
327
328void ChromeRenderMessageFilter::OnOpenChannelToExtension(
329    int routing_id, const std::string& source_extension_id,
330    const std::string& target_extension_id,
331    const std::string& channel_name, int* port_id) {
332  int port2_id;
333  extensions::MessageService::AllocatePortIdPair(port_id, &port2_id);
334
335  BrowserThread::PostTask(
336      BrowserThread::UI, FROM_HERE,
337      base::Bind(&ChromeRenderMessageFilter::OpenChannelToExtensionOnUIThread,
338                 this, render_process_id_, routing_id, port2_id,
339                 source_extension_id, target_extension_id, channel_name));
340}
341
342void ChromeRenderMessageFilter::OpenChannelToExtensionOnUIThread(
343    int source_process_id, int source_routing_id,
344    int receiver_port_id,
345    const std::string& source_extension_id,
346    const std::string& target_extension_id,
347    const std::string& channel_name) {
348  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
349  extensions::ExtensionSystem::Get(profile_)->message_service()->
350      OpenChannelToExtension(
351          source_process_id, source_routing_id, receiver_port_id,
352          source_extension_id, target_extension_id, channel_name);
353}
354
355void ChromeRenderMessageFilter::OnOpenChannelToNativeApp(
356    int routing_id,
357    const std::string& source_extension_id,
358    const std::string& native_app_name,
359    int* port_id) {
360  int port2_id;
361  extensions::MessageService::AllocatePortIdPair(port_id, &port2_id);
362
363  BrowserThread::PostTask(
364      BrowserThread::UI, FROM_HERE,
365      base::Bind(&ChromeRenderMessageFilter::OpenChannelToNativeAppOnUIThread,
366                 this, routing_id, port2_id, source_extension_id,
367                 native_app_name));
368}
369
370void ChromeRenderMessageFilter::OpenChannelToNativeAppOnUIThread(
371    int source_routing_id,
372    int receiver_port_id,
373    const std::string& source_extension_id,
374    const std::string& native_app_name) {
375  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
376  extensions::ExtensionSystem::Get(profile_)->message_service()->
377      OpenChannelToNativeApp(
378          render_process_id_, source_routing_id, receiver_port_id,
379          source_extension_id, native_app_name);
380}
381
382void ChromeRenderMessageFilter::OnOpenChannelToTab(
383    int routing_id, int tab_id, const std::string& extension_id,
384    const std::string& channel_name, int* port_id) {
385  int port2_id;
386  extensions::MessageService::AllocatePortIdPair(port_id, &port2_id);
387
388  BrowserThread::PostTask(
389      BrowserThread::UI, FROM_HERE,
390      base::Bind(&ChromeRenderMessageFilter::OpenChannelToTabOnUIThread, this,
391                 render_process_id_, routing_id, port2_id, tab_id, extension_id,
392                 channel_name));
393}
394
395void ChromeRenderMessageFilter::OpenChannelToTabOnUIThread(
396    int source_process_id, int source_routing_id,
397    int receiver_port_id,
398    int tab_id,
399    const std::string& extension_id,
400    const std::string& channel_name) {
401  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
402  extensions::ExtensionSystem::Get(profile_)->message_service()->
403      OpenChannelToTab(
404          source_process_id, source_routing_id, receiver_port_id,
405          tab_id, extension_id, channel_name);
406}
407
408void ChromeRenderMessageFilter::OnGetExtensionMessageBundle(
409    const std::string& extension_id, IPC::Message* reply_msg) {
410  const extensions::Extension* extension =
411      extension_info_map_->extensions().GetByID(extension_id);
412  base::FilePath extension_path;
413  std::string default_locale;
414  if (extension) {
415    extension_path = extension->path();
416    default_locale = extensions::LocaleInfo::GetDefaultLocale(extension);
417  }
418
419  BrowserThread::PostTask(
420      BrowserThread::FILE, FROM_HERE,
421      base::Bind(
422          &ChromeRenderMessageFilter::OnGetExtensionMessageBundleOnFileThread,
423          this, extension_path, extension_id, default_locale, reply_msg));
424}
425
426void ChromeRenderMessageFilter::OnGetExtensionMessageBundleOnFileThread(
427    const base::FilePath& extension_path,
428    const std::string& extension_id,
429    const std::string& default_locale,
430    IPC::Message* reply_msg) {
431  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
432
433  scoped_ptr<extensions::MessageBundle::SubstitutionMap> dictionary_map(
434      extension_file_util::LoadMessageBundleSubstitutionMap(
435          extension_path,
436          extension_id,
437          default_locale));
438
439  ExtensionHostMsg_GetMessageBundle::WriteReplyParams(
440      reply_msg, *dictionary_map);
441  Send(reply_msg);
442}
443
444void ChromeRenderMessageFilter::OnExtensionAddListener(
445    const std::string& extension_id,
446    const std::string& event_name) {
447  content::RenderProcessHost* process =
448      content::RenderProcessHost::FromID(render_process_id_);
449  if (!process ||
450      !extensions::ExtensionSystem::Get(profile_)->event_router())
451    return;
452
453  extensions::ExtensionSystem::Get(profile_)->event_router()->
454      AddEventListener(event_name, process, extension_id);
455}
456
457void ChromeRenderMessageFilter::OnExtensionRemoveListener(
458    const std::string& extension_id,
459    const std::string& event_name) {
460  content::RenderProcessHost* process =
461      content::RenderProcessHost::FromID(render_process_id_);
462  if (!process ||
463      !extensions::ExtensionSystem::Get(profile_)->event_router())
464    return;
465
466  extensions::ExtensionSystem::Get(profile_)->event_router()->
467      RemoveEventListener(event_name, process, extension_id);
468}
469
470void ChromeRenderMessageFilter::OnExtensionAddLazyListener(
471    const std::string& extension_id, const std::string& event_name) {
472  if (extensions::ExtensionSystem::Get(profile_)->event_router()) {
473    extensions::ExtensionSystem::Get(profile_)->event_router()->
474        AddLazyEventListener(event_name, extension_id);
475  }
476}
477
478void ChromeRenderMessageFilter::OnExtensionRemoveLazyListener(
479    const std::string& extension_id, const std::string& event_name) {
480  if (extensions::ExtensionSystem::Get(profile_)->event_router()) {
481    extensions::ExtensionSystem::Get(profile_)->event_router()->
482        RemoveLazyEventListener(event_name, extension_id);
483  }
484}
485
486void ChromeRenderMessageFilter::OnExtensionAddFilteredListener(
487    const std::string& extension_id,
488    const std::string& event_name,
489    const base::DictionaryValue& filter,
490    bool lazy) {
491  content::RenderProcessHost* process =
492      content::RenderProcessHost::FromID(render_process_id_);
493  if (!process ||
494      !extensions::ExtensionSystem::Get(profile_)->event_router())
495    return;
496
497  extensions::ExtensionSystem::Get(profile_)->event_router()->
498      AddFilteredEventListener(event_name, process, extension_id, filter, lazy);
499}
500
501void ChromeRenderMessageFilter::OnExtensionRemoveFilteredListener(
502    const std::string& extension_id,
503    const std::string& event_name,
504    const base::DictionaryValue& filter,
505    bool lazy) {
506  content::RenderProcessHost* process =
507      content::RenderProcessHost::FromID(render_process_id_);
508  if (!process ||
509      !extensions::ExtensionSystem::Get(profile_)->event_router())
510    return;
511
512  extensions::ExtensionSystem::Get(profile_)->event_router()->
513      RemoveFilteredEventListener(event_name, process, extension_id, filter,
514                                  lazy);
515}
516
517void ChromeRenderMessageFilter::OnExtensionCloseChannel(
518    int port_id,
519    const std::string& error_message) {
520  if (!content::RenderProcessHost::FromID(render_process_id_))
521    return;  // To guard against crash in browser_tests shutdown.
522
523  extensions::MessageService* message_service =
524      extensions::ExtensionSystem::Get(profile_)->message_service();
525  if (message_service)
526    message_service->CloseChannel(port_id, error_message);
527}
528
529void ChromeRenderMessageFilter::OnExtensionRequestForIOThread(
530    int routing_id,
531    const ExtensionHostMsg_Request_Params& params) {
532  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
533
534  ExtensionFunctionDispatcher::DispatchOnIOThread(
535      extension_info_map_, profile_, render_process_id_,
536      weak_ptr_factory_.GetWeakPtr(), routing_id, params);
537}
538
539void ChromeRenderMessageFilter::OnExtensionShouldSuspendAck(
540     const std::string& extension_id, int sequence_id) {
541  if (extensions::ExtensionSystem::Get(profile_)->process_manager()) {
542    extensions::ExtensionSystem::Get(profile_)->process_manager()->
543        OnShouldSuspendAck(extension_id, sequence_id);
544  }
545}
546
547void ChromeRenderMessageFilter::OnExtensionSuspendAck(
548     const std::string& extension_id) {
549  if (extensions::ExtensionSystem::Get(profile_)->process_manager()) {
550    extensions::ExtensionSystem::Get(profile_)->process_manager()->
551        OnSuspendAck(extension_id);
552  }
553}
554
555void ChromeRenderMessageFilter::OnExtensionGenerateUniqueID(int* unique_id) {
556  static int next_unique_id = 1;
557  *unique_id = next_unique_id++;
558}
559
560void ChromeRenderMessageFilter::OnExtensionResumeRequests(int route_id) {
561  content::ResourceDispatcherHost::Get()->ResumeBlockedRequestsForRoute(
562      render_process_id_, route_id);
563}
564
565void ChromeRenderMessageFilter::OnAddDOMActionToExtensionActivityLog(
566    const std::string& extension_id,
567    const ExtensionHostMsg_DOMAction_Params& params) {
568  const extensions::Extension* extension =
569      extension_info_map_->extensions().GetByID(extension_id);
570  scoped_ptr<ListValue> args(params.arguments.DeepCopy());
571  // The activity is recorded as a DOM action on the extension
572  // activity log.
573  AddDOMActionToExtensionActivityLog(profile_, extension,
574                                     params.url, params.url_title,
575                                     params.api_call, args.Pass(),
576                                     params.extra);
577}
578
579void ChromeRenderMessageFilter::OnAllowDatabase(int render_view_id,
580                                                const GURL& origin_url,
581                                                const GURL& top_origin_url,
582                                                const string16& name,
583                                                const string16& display_name,
584                                                bool* allowed) {
585  *allowed = cookie_settings_->IsSettingCookieAllowed(origin_url,
586                                                      top_origin_url);
587  BrowserThread::PostTask(
588      BrowserThread::UI, FROM_HERE,
589      base::Bind(
590          &TabSpecificContentSettings::WebDatabaseAccessed,
591          render_process_id_, render_view_id, origin_url, name, display_name,
592          !*allowed));
593}
594
595void ChromeRenderMessageFilter::OnAllowDOMStorage(int render_view_id,
596                                                  const GURL& origin_url,
597                                                  const GURL& top_origin_url,
598                                                  bool local,
599                                                  bool* allowed) {
600  *allowed = cookie_settings_->IsSettingCookieAllowed(origin_url,
601                                                      top_origin_url);
602  // Record access to DOM storage for potential display in UI.
603  BrowserThread::PostTask(
604      BrowserThread::UI, FROM_HERE,
605      base::Bind(
606          &TabSpecificContentSettings::DOMStorageAccessed,
607          render_process_id_, render_view_id, origin_url, local, !*allowed));
608}
609
610void ChromeRenderMessageFilter::OnAllowFileSystem(int render_view_id,
611                                                  const GURL& origin_url,
612                                                  const GURL& top_origin_url,
613                                                  bool* allowed) {
614  *allowed = cookie_settings_->IsSettingCookieAllowed(origin_url,
615                                                      top_origin_url);
616  // Record access to file system for potential display in UI.
617  BrowserThread::PostTask(
618      BrowserThread::UI, FROM_HERE,
619      base::Bind(
620          &TabSpecificContentSettings::FileSystemAccessed,
621          render_process_id_, render_view_id, origin_url, !*allowed));
622}
623
624void ChromeRenderMessageFilter::OnAllowIndexedDB(int render_view_id,
625                                                 const GURL& origin_url,
626                                                 const GURL& top_origin_url,
627                                                 const string16& name,
628                                                 bool* allowed) {
629  *allowed = cookie_settings_->IsSettingCookieAllowed(origin_url,
630                                                      top_origin_url);
631  BrowserThread::PostTask(
632      BrowserThread::UI, FROM_HERE,
633      base::Bind(
634          &TabSpecificContentSettings::IndexedDBAccessed,
635          render_process_id_, render_view_id, origin_url, name, !*allowed));
636}
637
638void ChromeRenderMessageFilter::OnCanTriggerClipboardRead(
639    const GURL& origin, bool* allowed) {
640  *allowed = extension_info_map_->SecurityOriginHasAPIPermission(
641      origin, render_process_id_, APIPermission::kClipboardRead);
642}
643
644void ChromeRenderMessageFilter::OnCanTriggerClipboardWrite(
645    const GURL& origin, bool* allowed) {
646  // Since all extensions could historically write to the clipboard, preserve it
647  // for compatibility.
648  *allowed = (origin.SchemeIs(extensions::kExtensionScheme) ||
649      extension_info_map_->SecurityOriginHasAPIPermission(
650          origin, render_process_id_, APIPermission::kClipboardWrite));
651}
652
653void ChromeRenderMessageFilter::OnGetCookies(
654    const GURL& url,
655    const GURL& first_party_for_cookies,
656    IPC::Message* reply_msg) {
657#if defined(ENABLE_AUTOMATION)
658  AutomationResourceMessageFilter::GetCookiesForUrl(
659      this, request_context_->GetURLRequestContext(), render_process_id_,
660      reply_msg, url);
661#endif
662}
663
664void ChromeRenderMessageFilter::OnSetCookie(const IPC::Message& message,
665                                            const GURL& url,
666                                            const GURL& first_party_for_cookies,
667                                            const std::string& cookie) {
668#if defined(ENABLE_AUTOMATION)
669  AutomationResourceMessageFilter::SetCookiesForUrl(
670      render_process_id_, message.routing_id(), url, cookie);
671#endif
672}
673