chrome_render_message_filter.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
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