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