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