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