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