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