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