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 38using content::BrowserThread; 39using blink::WebCache; 40 41namespace { 42 43const uint32 kFilteredMessageClasses[] = { 44 ChromeMsgStart, 45}; 46 47} // namespace 48 49ChromeRenderMessageFilter::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 60ChromeRenderMessageFilter::~ChromeRenderMessageFilter() { 61} 62 63bool 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 91void 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 103void ChromeRenderMessageFilter::OnDnsPrefetch( 104 const std::vector<std::string>& hostnames) { 105 if (predictor_) 106 predictor_->DnsPrefetchList(hostnames); 107} 108 109void ChromeRenderMessageFilter::OnPreconnect(const GURL& url) { 110 if (predictor_) 111 predictor_->PreconnectUrl( 112 url, GURL(), chrome_browser_net::UrlInfo::MOUSE_OVER_MOTIVATED, 1); 113} 114 115void 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 135void ChromeRenderMessageFilter::OnUpdatedCacheStats( 136 const WebCache::UsageStats& stats) { 137 web_cache::WebCacheManager::GetInstance()->ObserveStats( 138 render_process_id_, stats); 139} 140 141void 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 167void 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 183void 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 198void 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 215void 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) 224void 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 243void 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 261void 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 269void 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) 309void 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 333void 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 345void 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) 360void ChromeRenderMessageFilter::OnIsCrashReportingEnabled(bool* enabled) { 361 *enabled = ChromeMetricsServiceAccessor::IsCrashReportingEnabled(); 362} 363#endif 364