chrome_render_message_filter.cc revision 116680a4aac90f2aa7413d9095a592090648e557
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/browser/renderer_host/web_cache_manager.h"
20#include "chrome/common/extensions/api/i18n/default_locale_handler.h"
21#include "chrome/common/render_messages.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 "chrome/browser/guest_view/web_view/web_view_permission_helper.h"
27#include "chrome/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  HISTOGRAM_COUNTS("WebCoreCache.ImagesSizeKB",
118                   static_cast<int>(stats.images.size / 1024));
119  HISTOGRAM_COUNTS("WebCoreCache.CSSStylesheetsSizeKB",
120                   static_cast<int>(stats.cssStyleSheets.size / 1024));
121  HISTOGRAM_COUNTS("WebCoreCache.ScriptsSizeKB",
122                   static_cast<int>(stats.scripts.size / 1024));
123  HISTOGRAM_COUNTS("WebCoreCache.XSLStylesheetsSizeKB",
124                   static_cast<int>(stats.xslStyleSheets.size / 1024));
125  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  WebCacheManager::GetInstance()->ObserveStats(render_process_id_, stats);
138}
139
140void ChromeRenderMessageFilter::OnV8HeapStats(int v8_memory_allocated,
141                                              int v8_memory_used) {
142  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
143    BrowserThread::PostTask(
144        BrowserThread::UI, FROM_HERE,
145        base::Bind(&ChromeRenderMessageFilter::OnV8HeapStats, this,
146                   v8_memory_allocated, v8_memory_used));
147    return;
148  }
149
150  base::ProcessId renderer_id = peer_pid();
151
152#if defined(ENABLE_TASK_MANAGER)
153  TaskManager::GetInstance()->model()->NotifyV8HeapStats(
154      renderer_id,
155      static_cast<size_t>(v8_memory_allocated),
156      static_cast<size_t>(v8_memory_used));
157#endif  // defined(ENABLE_TASK_MANAGER)
158
159  V8HeapStatsDetails details(v8_memory_allocated, v8_memory_used);
160  content::NotificationService::current()->Notify(
161      chrome::NOTIFICATION_RENDERER_V8_HEAP_STATS_COMPUTED,
162      content::Source<const base::ProcessId>(&renderer_id),
163      content::Details<const V8HeapStatsDetails>(&details));
164}
165
166void ChromeRenderMessageFilter::OnAllowDatabase(
167    int render_frame_id,
168    const GURL& origin_url,
169    const GURL& top_origin_url,
170    const base::string16& name,
171    const base::string16& display_name,
172    bool* allowed) {
173  *allowed =
174      cookie_settings_->IsSettingCookieAllowed(origin_url, top_origin_url);
175  BrowserThread::PostTask(
176      BrowserThread::UI, FROM_HERE,
177      base::Bind(&TabSpecificContentSettings::WebDatabaseAccessed,
178                 render_process_id_, render_frame_id, origin_url, name,
179                 display_name, !*allowed));
180}
181
182void ChromeRenderMessageFilter::OnAllowDOMStorage(int render_frame_id,
183                                                  const GURL& origin_url,
184                                                  const GURL& top_origin_url,
185                                                  bool local,
186                                                  bool* allowed) {
187  *allowed =
188      cookie_settings_->IsSettingCookieAllowed(origin_url, top_origin_url);
189  // Record access to DOM storage for potential display in UI.
190  BrowserThread::PostTask(
191      BrowserThread::UI, FROM_HERE,
192      base::Bind(&TabSpecificContentSettings::DOMStorageAccessed,
193                 render_process_id_, render_frame_id, origin_url, local,
194                 !*allowed));
195}
196
197void ChromeRenderMessageFilter::OnRequestFileSystemAccessSync(
198    int render_frame_id,
199    const GURL& origin_url,
200    const GURL& top_origin_url,
201    IPC::Message* reply_msg) {
202  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
203  base::Callback<void(bool)> callback =
204      base::Bind(&ChromeRenderMessageFilter::
205                 OnRequestFileSystemAccessSyncResponse,
206                 make_scoped_refptr(this),
207                 reply_msg);
208  OnRequestFileSystemAccess(render_frame_id,
209                            origin_url,
210                            top_origin_url,
211                            callback);
212}
213
214void ChromeRenderMessageFilter::OnRequestFileSystemAccessSyncResponse(
215    IPC::Message* reply_msg,
216    bool allowed) {
217  ChromeViewHostMsg_RequestFileSystemAccessSync::WriteReplyParams(reply_msg,
218                                                                  allowed);
219  Send(reply_msg);
220}
221
222#if defined(ENABLE_EXTENSIONS)
223void ChromeRenderMessageFilter::FileSystemAccessedSyncOnUIThread(
224    int render_process_id,
225    int render_frame_id,
226    const GURL& url,
227    bool blocked_by_policy,
228    IPC::Message* reply_msg) {
229  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
230  WebViewPermissionHelper* web_view_permission_helper =
231      WebViewPermissionHelper::FromFrameID(render_process_id, render_frame_id);
232  web_view_permission_helper->FileSystemAccessedSync(render_process_id,
233                                                     render_frame_id,
234                                                     url,
235                                                     blocked_by_policy,
236                                                     reply_msg);
237}
238#endif
239
240void ChromeRenderMessageFilter::OnRequestFileSystemAccessAsync(
241    int render_frame_id,
242    int request_id,
243    const GURL& origin_url,
244    const GURL& top_origin_url) {
245  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
246  base::Callback<void(bool)> callback =
247      base::Bind(&ChromeRenderMessageFilter::
248                 OnRequestFileSystemAccessAsyncResponse,
249                 make_scoped_refptr(this),
250                 render_frame_id,
251                 request_id);
252  OnRequestFileSystemAccess(render_frame_id,
253                            origin_url,
254                            top_origin_url,
255                            callback);
256}
257
258void ChromeRenderMessageFilter::OnRequestFileSystemAccessAsyncResponse(
259    int render_frame_id,
260    int request_id,
261    bool allowed) {
262  Send(new ChromeViewMsg_RequestFileSystemAccessAsyncResponse(
263      render_frame_id, request_id, allowed));
264}
265
266void ChromeRenderMessageFilter::OnRequestFileSystemAccess(
267    int render_frame_id,
268    const GURL& origin_url,
269    const GURL& top_origin_url,
270    base::Callback<void(bool)> callback) {
271  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
272
273  bool allowed =
274      cookie_settings_->IsSettingCookieAllowed(origin_url, top_origin_url);
275
276#if defined(ENABLE_EXTENSIONS)
277  bool is_web_view_guest =
278      WebViewRendererState::GetInstance()->IsGuest(render_process_id_);
279  if (is_web_view_guest) {
280    // Record access to file system for potential display in UI.
281    BrowserThread::PostTask(
282        BrowserThread::UI,
283        FROM_HERE,
284        base::Bind(&ChromeRenderMessageFilter::FileSystemAccessedOnUIThread,
285                   render_process_id_,
286                   render_frame_id,
287                   origin_url,
288                   allowed,
289                   callback));
290    return;
291  }
292#endif
293  callback.Run(allowed);
294  // Record access to file system for potential display in UI.
295  BrowserThread::PostTask(
296      BrowserThread::UI,
297      FROM_HERE,
298      base::Bind(&TabSpecificContentSettings::FileSystemAccessed,
299                 render_process_id_,
300                 render_frame_id,
301                 origin_url,
302                 !allowed));
303}
304
305#if defined(ENABLE_EXTENSIONS)
306void ChromeRenderMessageFilter::FileSystemAccessedOnUIThread(
307    int render_process_id,
308    int render_frame_id,
309    const GURL& url,
310    bool allowed,
311    base::Callback<void(bool)> callback) {
312  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
313  WebViewPermissionHelper* web_view_permission_helper =
314      WebViewPermissionHelper::FromFrameID(render_process_id, render_frame_id);
315  web_view_permission_helper->RequestFileSystemPermission(
316      url,
317      allowed,
318      base::Bind(&ChromeRenderMessageFilter::FileSystemAccessedResponse,
319                 render_process_id,
320                 render_frame_id,
321                 url,
322                 callback));
323}
324
325void ChromeRenderMessageFilter::FileSystemAccessedResponse(
326    int render_process_id,
327    int render_frame_id,
328    const GURL& url,
329    base::Callback<void(bool)> callback,
330    bool allowed) {
331  TabSpecificContentSettings::FileSystemAccessed(
332      render_process_id, render_frame_id, url, !allowed);
333  callback.Run(allowed);
334}
335#endif
336
337void ChromeRenderMessageFilter::OnAllowIndexedDB(int render_frame_id,
338                                                 const GURL& origin_url,
339                                                 const GURL& top_origin_url,
340                                                 const base::string16& name,
341                                                 bool* allowed) {
342  *allowed =
343      cookie_settings_->IsSettingCookieAllowed(origin_url, top_origin_url);
344  BrowserThread::PostTask(
345      BrowserThread::UI, FROM_HERE,
346      base::Bind(&TabSpecificContentSettings::IndexedDBAccessed,
347                 render_process_id_, render_frame_id, origin_url, name,
348                 !*allowed));
349}
350
351#if defined(ENABLE_PLUGINS)
352void ChromeRenderMessageFilter::OnIsCrashReportingEnabled(bool* enabled) {
353  *enabled = ChromeMetricsServiceAccessor::IsCrashReportingEnabled();
354}
355#endif
356