chrome_render_message_filter.cc revision 6e8cce623b6e4fe0c9e4af605d675dd9d0338c38
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  extensions::WebViewPermissionHelper* web_view_permission_helper =
231      extensions::WebViewPermissionHelper::FromFrameID(
232          render_process_id, render_frame_id);
233  // Between the time the permission request is made and the time it is handled
234  // by the UI thread, the extensions::WebViewPermissionHelper might be gone.
235  if (!web_view_permission_helper)
236    return;
237  web_view_permission_helper->FileSystemAccessedSync(
238      render_process_id, render_frame_id, url, blocked_by_policy, reply_msg);
239}
240#endif
241
242void ChromeRenderMessageFilter::OnRequestFileSystemAccessAsync(
243    int render_frame_id,
244    int request_id,
245    const GURL& origin_url,
246    const GURL& top_origin_url) {
247  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
248  base::Callback<void(bool)> callback =
249      base::Bind(&ChromeRenderMessageFilter::
250                 OnRequestFileSystemAccessAsyncResponse,
251                 make_scoped_refptr(this),
252                 render_frame_id,
253                 request_id);
254  OnRequestFileSystemAccess(render_frame_id,
255                            origin_url,
256                            top_origin_url,
257                            callback);
258}
259
260void ChromeRenderMessageFilter::OnRequestFileSystemAccessAsyncResponse(
261    int render_frame_id,
262    int request_id,
263    bool allowed) {
264  Send(new ChromeViewMsg_RequestFileSystemAccessAsyncResponse(
265      render_frame_id, request_id, allowed));
266}
267
268void ChromeRenderMessageFilter::OnRequestFileSystemAccess(
269    int render_frame_id,
270    const GURL& origin_url,
271    const GURL& top_origin_url,
272    base::Callback<void(bool)> callback) {
273  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
274
275  bool allowed =
276      cookie_settings_->IsSettingCookieAllowed(origin_url, top_origin_url);
277
278#if defined(ENABLE_EXTENSIONS)
279  bool is_web_view_guest = extensions::WebViewRendererState::GetInstance()
280      ->IsGuest(render_process_id_);
281  if (is_web_view_guest) {
282    // Record access to file system for potential display in UI.
283    BrowserThread::PostTask(
284        BrowserThread::UI,
285        FROM_HERE,
286        base::Bind(&ChromeRenderMessageFilter::FileSystemAccessedOnUIThread,
287                   render_process_id_,
288                   render_frame_id,
289                   origin_url,
290                   allowed,
291                   callback));
292    return;
293  }
294#endif
295  callback.Run(allowed);
296  // Record access to file system for potential display in UI.
297  BrowserThread::PostTask(
298      BrowserThread::UI,
299      FROM_HERE,
300      base::Bind(&TabSpecificContentSettings::FileSystemAccessed,
301                 render_process_id_,
302                 render_frame_id,
303                 origin_url,
304                 !allowed));
305}
306
307#if defined(ENABLE_EXTENSIONS)
308void ChromeRenderMessageFilter::FileSystemAccessedOnUIThread(
309    int render_process_id,
310    int render_frame_id,
311    const GURL& url,
312    bool allowed,
313    base::Callback<void(bool)> callback) {
314  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
315  extensions::WebViewPermissionHelper* web_view_permission_helper =
316      extensions::WebViewPermissionHelper::FromFrameID(
317          render_process_id, render_frame_id);
318  // Between the time the permission request is made and the time it is handled
319  // by the UI thread, the extensions::WebViewPermissionHelper might be gone.
320  if (!web_view_permission_helper)
321    return;
322  web_view_permission_helper->RequestFileSystemPermission(
323      url,
324      allowed,
325      base::Bind(&ChromeRenderMessageFilter::FileSystemAccessedResponse,
326                 render_process_id,
327                 render_frame_id,
328                 url,
329                 callback));
330}
331
332void ChromeRenderMessageFilter::FileSystemAccessedResponse(
333    int render_process_id,
334    int render_frame_id,
335    const GURL& url,
336    base::Callback<void(bool)> callback,
337    bool allowed) {
338  TabSpecificContentSettings::FileSystemAccessed(
339      render_process_id, render_frame_id, url, !allowed);
340  callback.Run(allowed);
341}
342#endif
343
344void ChromeRenderMessageFilter::OnAllowIndexedDB(int render_frame_id,
345                                                 const GURL& origin_url,
346                                                 const GURL& top_origin_url,
347                                                 const base::string16& name,
348                                                 bool* allowed) {
349  *allowed =
350      cookie_settings_->IsSettingCookieAllowed(origin_url, top_origin_url);
351  BrowserThread::PostTask(
352      BrowserThread::UI, FROM_HERE,
353      base::Bind(&TabSpecificContentSettings::IndexedDBAccessed,
354                 render_process_id_, render_frame_id, origin_url, name,
355                 !*allowed));
356}
357
358#if defined(ENABLE_PLUGINS)
359void ChromeRenderMessageFilter::OnIsCrashReportingEnabled(bool* enabled) {
360  *enabled = ChromeMetricsServiceAccessor::IsCrashReportingEnabled();
361}
362#endif
363