Home | History | Annotate | Download | only in renderer_host
      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/chrome_notification_types.h"
     13 #include "chrome/browser/content_settings/cookie_settings.h"
     14 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
     15 #include "chrome/browser/metrics/chrome_metrics_service_accessor.h"
     16 #include "chrome/browser/net/predictor.h"
     17 #include "chrome/browser/profiles/profile.h"
     18 #include "chrome/browser/profiles/profile_manager.h"
     19 #include "chrome/common/extensions/api/i18n/default_locale_handler.h"
     20 #include "chrome/common/render_messages.h"
     21 #include "components/web_cache/browser/web_cache_manager.h"
     22 #include "content/public/browser/notification_service.h"
     23 #include "content/public/browser/render_process_host.h"
     24 
     25 #if defined(ENABLE_EXTENSIONS)
     26 #include "extensions/browser/guest_view/web_view/web_view_permission_helper.h"
     27 #include "extensions/browser/guest_view/web_view/web_view_renderer_state.h"
     28 #endif
     29 
     30 #if defined(ENABLE_TASK_MANAGER)
     31 #include "chrome/browser/task_manager/task_manager.h"
     32 #endif
     33 
     34 #if defined(USE_TCMALLOC)
     35 #include "chrome/browser/browser_about_handler.h"
     36 #endif
     37 
     38 using content::BrowserThread;
     39 using blink::WebCache;
     40 
     41 namespace {
     42 
     43 const uint32 kFilteredMessageClasses[] = {
     44   ChromeMsgStart,
     45 };
     46 
     47 }  // namespace
     48 
     49 ChromeRenderMessageFilter::ChromeRenderMessageFilter(
     50     int render_process_id,
     51     Profile* profile)
     52     : BrowserMessageFilter(kFilteredMessageClasses,
     53                            arraysize(kFilteredMessageClasses)),
     54       render_process_id_(render_process_id),
     55       profile_(profile),
     56       predictor_(profile_->GetNetworkPredictor()),
     57       cookie_settings_(CookieSettings::Factory::GetForProfile(profile)) {
     58 }
     59 
     60 ChromeRenderMessageFilter::~ChromeRenderMessageFilter() {
     61 }
     62 
     63 bool ChromeRenderMessageFilter::OnMessageReceived(const IPC::Message& message) {
     64   bool handled = true;
     65   IPC_BEGIN_MESSAGE_MAP(ChromeRenderMessageFilter, message)
     66     IPC_MESSAGE_HANDLER(ChromeViewHostMsg_DnsPrefetch, OnDnsPrefetch)
     67     IPC_MESSAGE_HANDLER(ChromeViewHostMsg_Preconnect, OnPreconnect)
     68     IPC_MESSAGE_HANDLER(ChromeViewHostMsg_ResourceTypeStats,
     69                         OnResourceTypeStats)
     70     IPC_MESSAGE_HANDLER(ChromeViewHostMsg_UpdatedCacheStats,
     71                         OnUpdatedCacheStats)
     72     IPC_MESSAGE_HANDLER(ChromeViewHostMsg_V8HeapStats, OnV8HeapStats)
     73     IPC_MESSAGE_HANDLER(ChromeViewHostMsg_AllowDatabase, OnAllowDatabase)
     74     IPC_MESSAGE_HANDLER(ChromeViewHostMsg_AllowDOMStorage, OnAllowDOMStorage)
     75     IPC_MESSAGE_HANDLER_DELAY_REPLY(
     76         ChromeViewHostMsg_RequestFileSystemAccessSync,
     77         OnRequestFileSystemAccessSync)
     78     IPC_MESSAGE_HANDLER(ChromeViewHostMsg_RequestFileSystemAccessAsync,
     79                         OnRequestFileSystemAccessAsync)
     80     IPC_MESSAGE_HANDLER(ChromeViewHostMsg_AllowIndexedDB, OnAllowIndexedDB)
     81 #if defined(ENABLE_PLUGINS)
     82     IPC_MESSAGE_HANDLER(ChromeViewHostMsg_IsCrashReportingEnabled,
     83                         OnIsCrashReportingEnabled)
     84 #endif
     85     IPC_MESSAGE_UNHANDLED(handled = false)
     86   IPC_END_MESSAGE_MAP()
     87 
     88   return handled;
     89 }
     90 
     91 void ChromeRenderMessageFilter::OverrideThreadForMessage(
     92     const IPC::Message& message, BrowserThread::ID* thread) {
     93   switch (message.type()) {
     94     case ChromeViewHostMsg_ResourceTypeStats::ID:
     95     case ChromeViewHostMsg_UpdatedCacheStats::ID:
     96       *thread = BrowserThread::UI;
     97       break;
     98     default:
     99       break;
    100   }
    101 }
    102 
    103 void ChromeRenderMessageFilter::OnDnsPrefetch(
    104     const std::vector<std::string>& hostnames) {
    105   if (predictor_)
    106     predictor_->DnsPrefetchList(hostnames);
    107 }
    108 
    109 void ChromeRenderMessageFilter::OnPreconnect(const GURL& url) {
    110   if (predictor_)
    111     predictor_->PreconnectUrl(
    112         url, GURL(), chrome_browser_net::UrlInfo::MOUSE_OVER_MOTIVATED, 1);
    113 }
    114 
    115 void ChromeRenderMessageFilter::OnResourceTypeStats(
    116     const WebCache::ResourceTypeStats& stats) {
    117   LOCAL_HISTOGRAM_COUNTS("WebCoreCache.ImagesSizeKB",
    118                          static_cast<int>(stats.images.size / 1024));
    119   LOCAL_HISTOGRAM_COUNTS("WebCoreCache.CSSStylesheetsSizeKB",
    120                          static_cast<int>(stats.cssStyleSheets.size / 1024));
    121   LOCAL_HISTOGRAM_COUNTS("WebCoreCache.ScriptsSizeKB",
    122                          static_cast<int>(stats.scripts.size / 1024));
    123   LOCAL_HISTOGRAM_COUNTS("WebCoreCache.XSLStylesheetsSizeKB",
    124                          static_cast<int>(stats.xslStyleSheets.size / 1024));
    125   LOCAL_HISTOGRAM_COUNTS("WebCoreCache.FontsSizeKB",
    126                          static_cast<int>(stats.fonts.size / 1024));
    127 
    128   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    129 #if defined(ENABLE_TASK_MANAGER)
    130   TaskManager::GetInstance()->model()->NotifyResourceTypeStats(peer_pid(),
    131                                                                stats);
    132 #endif  // defined(ENABLE_TASK_MANAGER)
    133 }
    134 
    135 void ChromeRenderMessageFilter::OnUpdatedCacheStats(
    136     const WebCache::UsageStats& stats) {
    137   web_cache::WebCacheManager::GetInstance()->ObserveStats(
    138       render_process_id_, stats);
    139 }
    140 
    141 void ChromeRenderMessageFilter::OnV8HeapStats(int v8_memory_allocated,
    142                                               int v8_memory_used) {
    143   if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
    144     BrowserThread::PostTask(
    145         BrowserThread::UI, FROM_HERE,
    146         base::Bind(&ChromeRenderMessageFilter::OnV8HeapStats, this,
    147                    v8_memory_allocated, v8_memory_used));
    148     return;
    149   }
    150 
    151   base::ProcessId renderer_id = peer_pid();
    152 
    153 #if defined(ENABLE_TASK_MANAGER)
    154   TaskManager::GetInstance()->model()->NotifyV8HeapStats(
    155       renderer_id,
    156       static_cast<size_t>(v8_memory_allocated),
    157       static_cast<size_t>(v8_memory_used));
    158 #endif  // defined(ENABLE_TASK_MANAGER)
    159 
    160   V8HeapStatsDetails details(v8_memory_allocated, v8_memory_used);
    161   content::NotificationService::current()->Notify(
    162       chrome::NOTIFICATION_RENDERER_V8_HEAP_STATS_COMPUTED,
    163       content::Source<const base::ProcessId>(&renderer_id),
    164       content::Details<const V8HeapStatsDetails>(&details));
    165 }
    166 
    167 void ChromeRenderMessageFilter::OnAllowDatabase(
    168     int render_frame_id,
    169     const GURL& origin_url,
    170     const GURL& top_origin_url,
    171     const base::string16& name,
    172     const base::string16& display_name,
    173     bool* allowed) {
    174   *allowed =
    175       cookie_settings_->IsSettingCookieAllowed(origin_url, top_origin_url);
    176   BrowserThread::PostTask(
    177       BrowserThread::UI, FROM_HERE,
    178       base::Bind(&TabSpecificContentSettings::WebDatabaseAccessed,
    179                  render_process_id_, render_frame_id, origin_url, name,
    180                  display_name, !*allowed));
    181 }
    182 
    183 void ChromeRenderMessageFilter::OnAllowDOMStorage(int render_frame_id,
    184                                                   const GURL& origin_url,
    185                                                   const GURL& top_origin_url,
    186                                                   bool local,
    187                                                   bool* allowed) {
    188   *allowed =
    189       cookie_settings_->IsSettingCookieAllowed(origin_url, top_origin_url);
    190   // Record access to DOM storage for potential display in UI.
    191   BrowserThread::PostTask(
    192       BrowserThread::UI, FROM_HERE,
    193       base::Bind(&TabSpecificContentSettings::DOMStorageAccessed,
    194                  render_process_id_, render_frame_id, origin_url, local,
    195                  !*allowed));
    196 }
    197 
    198 void ChromeRenderMessageFilter::OnRequestFileSystemAccessSync(
    199     int render_frame_id,
    200     const GURL& origin_url,
    201     const GURL& top_origin_url,
    202     IPC::Message* reply_msg) {
    203   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    204   base::Callback<void(bool)> callback =
    205       base::Bind(&ChromeRenderMessageFilter::
    206                  OnRequestFileSystemAccessSyncResponse,
    207                  make_scoped_refptr(this),
    208                  reply_msg);
    209   OnRequestFileSystemAccess(render_frame_id,
    210                             origin_url,
    211                             top_origin_url,
    212                             callback);
    213 }
    214 
    215 void ChromeRenderMessageFilter::OnRequestFileSystemAccessSyncResponse(
    216     IPC::Message* reply_msg,
    217     bool allowed) {
    218   ChromeViewHostMsg_RequestFileSystemAccessSync::WriteReplyParams(reply_msg,
    219                                                                   allowed);
    220   Send(reply_msg);
    221 }
    222 
    223 #if defined(ENABLE_EXTENSIONS)
    224 void ChromeRenderMessageFilter::FileSystemAccessedSyncOnUIThread(
    225     int render_process_id,
    226     int render_frame_id,
    227     const GURL& url,
    228     bool blocked_by_policy,
    229     IPC::Message* reply_msg) {
    230   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    231   extensions::WebViewPermissionHelper* web_view_permission_helper =
    232       extensions::WebViewPermissionHelper::FromFrameID(
    233           render_process_id, render_frame_id);
    234   // Between the time the permission request is made and the time it is handled
    235   // by the UI thread, the extensions::WebViewPermissionHelper might be gone.
    236   if (!web_view_permission_helper)
    237     return;
    238   web_view_permission_helper->FileSystemAccessedSync(
    239       render_process_id, render_frame_id, url, blocked_by_policy, reply_msg);
    240 }
    241 #endif
    242 
    243 void ChromeRenderMessageFilter::OnRequestFileSystemAccessAsync(
    244     int render_frame_id,
    245     int request_id,
    246     const GURL& origin_url,
    247     const GURL& top_origin_url) {
    248   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    249   base::Callback<void(bool)> callback =
    250       base::Bind(&ChromeRenderMessageFilter::
    251                  OnRequestFileSystemAccessAsyncResponse,
    252                  make_scoped_refptr(this),
    253                  render_frame_id,
    254                  request_id);
    255   OnRequestFileSystemAccess(render_frame_id,
    256                             origin_url,
    257                             top_origin_url,
    258                             callback);
    259 }
    260 
    261 void ChromeRenderMessageFilter::OnRequestFileSystemAccessAsyncResponse(
    262     int render_frame_id,
    263     int request_id,
    264     bool allowed) {
    265   Send(new ChromeViewMsg_RequestFileSystemAccessAsyncResponse(
    266       render_frame_id, request_id, allowed));
    267 }
    268 
    269 void ChromeRenderMessageFilter::OnRequestFileSystemAccess(
    270     int render_frame_id,
    271     const GURL& origin_url,
    272     const GURL& top_origin_url,
    273     base::Callback<void(bool)> callback) {
    274   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    275 
    276   bool allowed =
    277       cookie_settings_->IsSettingCookieAllowed(origin_url, top_origin_url);
    278 
    279 #if defined(ENABLE_EXTENSIONS)
    280   bool is_web_view_guest = extensions::WebViewRendererState::GetInstance()
    281       ->IsGuest(render_process_id_);
    282   if (is_web_view_guest) {
    283     // Record access to file system for potential display in UI.
    284     BrowserThread::PostTask(
    285         BrowserThread::UI,
    286         FROM_HERE,
    287         base::Bind(&ChromeRenderMessageFilter::FileSystemAccessedOnUIThread,
    288                    render_process_id_,
    289                    render_frame_id,
    290                    origin_url,
    291                    allowed,
    292                    callback));
    293     return;
    294   }
    295 #endif
    296   callback.Run(allowed);
    297   // Record access to file system for potential display in UI.
    298   BrowserThread::PostTask(
    299       BrowserThread::UI,
    300       FROM_HERE,
    301       base::Bind(&TabSpecificContentSettings::FileSystemAccessed,
    302                  render_process_id_,
    303                  render_frame_id,
    304                  origin_url,
    305                  !allowed));
    306 }
    307 
    308 #if defined(ENABLE_EXTENSIONS)
    309 void ChromeRenderMessageFilter::FileSystemAccessedOnUIThread(
    310     int render_process_id,
    311     int render_frame_id,
    312     const GURL& url,
    313     bool allowed,
    314     base::Callback<void(bool)> callback) {
    315   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    316   extensions::WebViewPermissionHelper* web_view_permission_helper =
    317       extensions::WebViewPermissionHelper::FromFrameID(
    318           render_process_id, render_frame_id);
    319   // Between the time the permission request is made and the time it is handled
    320   // by the UI thread, the extensions::WebViewPermissionHelper might be gone.
    321   if (!web_view_permission_helper)
    322     return;
    323   web_view_permission_helper->RequestFileSystemPermission(
    324       url,
    325       allowed,
    326       base::Bind(&ChromeRenderMessageFilter::FileSystemAccessedResponse,
    327                  render_process_id,
    328                  render_frame_id,
    329                  url,
    330                  callback));
    331 }
    332 
    333 void ChromeRenderMessageFilter::FileSystemAccessedResponse(
    334     int render_process_id,
    335     int render_frame_id,
    336     const GURL& url,
    337     base::Callback<void(bool)> callback,
    338     bool allowed) {
    339   TabSpecificContentSettings::FileSystemAccessed(
    340       render_process_id, render_frame_id, url, !allowed);
    341   callback.Run(allowed);
    342 }
    343 #endif
    344 
    345 void ChromeRenderMessageFilter::OnAllowIndexedDB(int render_frame_id,
    346                                                  const GURL& origin_url,
    347                                                  const GURL& top_origin_url,
    348                                                  const base::string16& name,
    349                                                  bool* allowed) {
    350   *allowed =
    351       cookie_settings_->IsSettingCookieAllowed(origin_url, top_origin_url);
    352   BrowserThread::PostTask(
    353       BrowserThread::UI, FROM_HERE,
    354       base::Bind(&TabSpecificContentSettings::IndexedDBAccessed,
    355                  render_process_id_, render_frame_id, origin_url, name,
    356                  !*allowed));
    357 }
    358 
    359 #if defined(ENABLE_PLUGINS)
    360 void ChromeRenderMessageFilter::OnIsCrashReportingEnabled(bool* enabled) {
    361   *enabled = ChromeMetricsServiceAccessor::IsCrashReportingEnabled();
    362 }
    363 #endif
    364