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