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