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