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