Enabling tests which should be fixed by r173829.
[chromium-blink-merge.git] / chrome / renderer / chrome_render_process_observer.cc
blobc1ab3478a12b937558a9718a5dbaa37f841d26e7
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.
5 #include "chrome/renderer/chrome_render_process_observer.h"
7 #include <limits>
8 #include <vector>
10 #include "base/allocator/allocator_extension.h"
11 #include "base/bind.h"
12 #include "base/command_line.h"
13 #include "base/file_util.h"
14 #include "base/message_loop.h"
15 #include "base/memory/weak_ptr.h"
16 #include "base/metrics/field_trial.h"
17 #include "base/metrics/histogram.h"
18 #include "base/metrics/statistics_recorder.h"
19 #include "base/native_library.h"
20 #include "base/path_service.h"
21 #include "base/process_util.h"
22 #include "base/threading/platform_thread.h"
23 #include "chrome/common/child_process_logging.h"
24 #include "chrome/common/chrome_paths.h"
25 #include "chrome/common/chrome_switches.h"
26 #include "chrome/common/extensions/extension_localization_peer.h"
27 #include "chrome/common/metrics/variations/variations_util.h"
28 #include "chrome/common/net/net_resource_provider.h"
29 #include "chrome/common/render_messages.h"
30 #include "chrome/renderer/chrome_content_renderer_client.h"
31 #include "chrome/renderer/content_settings_observer.h"
32 #include "chrome/renderer/security_filter_peer.h"
33 #include "content/public/common/resource_dispatcher_delegate.h"
34 #include "content/public/renderer/render_thread.h"
35 #include "content/public/renderer/render_view_visitor.h"
36 #include "content/public/renderer/render_view.h"
37 #include "crypto/nss_util.h"
38 #include "media/base/media_switches.h"
39 #include "net/base/net_errors.h"
40 #include "net/base/net_module.h"
41 #include "third_party/sqlite/sqlite3.h"
42 #include "third_party/WebKit/Source/WebKit/chromium/public/WebCache.h"
43 #include "third_party/WebKit/Source/WebKit/chromium/public/WebCrossOriginPreflightResultCache.h"
44 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
45 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFontCache.h"
46 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
47 #include "third_party/WebKit/Source/WebKit/chromium/public/WebRuntimeFeatures.h"
48 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
49 #include "v8/include/v8.h"
51 #if defined(OS_WIN)
52 #include "base/win/iat_patch_function.h"
53 #endif
55 #if defined(USE_TCMALLOC)
56 #include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h"
57 #endif
59 using WebKit::WebCache;
60 using WebKit::WebCrossOriginPreflightResultCache;
61 using WebKit::WebFontCache;
62 using WebKit::WebRuntimeFeatures;
63 using content::RenderThread;
65 namespace {
67 static const int kCacheStatsDelayMS = 2000;
69 class RendererResourceDelegate : public content::ResourceDispatcherDelegate {
70 public:
71 RendererResourceDelegate()
72 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
75 virtual webkit_glue::ResourceLoaderBridge::Peer* OnRequestComplete(
76 webkit_glue::ResourceLoaderBridge::Peer* current_peer,
77 ResourceType::Type resource_type,
78 int error_code) {
79 // Update the browser about our cache.
80 // Rate limit informing the host of our cache stats.
81 if (!weak_factory_.HasWeakPtrs()) {
82 MessageLoop::current()->PostDelayedTask(
83 FROM_HERE,
84 base::Bind(&RendererResourceDelegate::InformHostOfCacheStats,
85 weak_factory_.GetWeakPtr()),
86 base::TimeDelta::FromMilliseconds(kCacheStatsDelayMS));
89 if (error_code == net::ERR_ABORTED) {
90 return NULL;
93 // Resource canceled with a specific error are filtered.
94 return SecurityFilterPeer::CreateSecurityFilterPeerForDeniedRequest(
95 resource_type, current_peer, error_code);
98 virtual webkit_glue::ResourceLoaderBridge::Peer* OnReceivedResponse(
99 webkit_glue::ResourceLoaderBridge::Peer* current_peer,
100 const std::string& mime_type,
101 const GURL& url) {
102 return ExtensionLocalizationPeer::CreateExtensionLocalizationPeer(
103 current_peer, RenderThread::Get(), mime_type, url);
106 private:
107 void InformHostOfCacheStats() {
108 WebCache::UsageStats stats;
109 WebCache::getUsageStats(&stats);
110 RenderThread::Get()->Send(new ChromeViewHostMsg_UpdatedCacheStats(stats));
113 base::WeakPtrFactory<RendererResourceDelegate> weak_factory_;
115 DISALLOW_COPY_AND_ASSIGN(RendererResourceDelegate);
118 #if defined(OS_WIN)
119 static base::win::IATPatchFunction g_iat_patch_createdca;
120 HDC WINAPI CreateDCAPatch(LPCSTR driver_name,
121 LPCSTR device_name,
122 LPCSTR output,
123 const void* init_data) {
124 DCHECK(std::string("DISPLAY") == std::string(driver_name));
125 DCHECK(!device_name);
126 DCHECK(!output);
127 DCHECK(!init_data);
129 // CreateDC fails behind the sandbox, but not CreateCompatibleDC.
130 return CreateCompatibleDC(NULL);
133 static base::win::IATPatchFunction g_iat_patch_get_font_data;
134 DWORD WINAPI GetFontDataPatch(HDC hdc,
135 DWORD table,
136 DWORD offset,
137 LPVOID buffer,
138 DWORD length) {
139 int rv = GetFontData(hdc, table, offset, buffer, length);
140 if (rv == GDI_ERROR && hdc) {
141 HFONT font = static_cast<HFONT>(GetCurrentObject(hdc, OBJ_FONT));
143 LOGFONT logfont;
144 if (GetObject(font, sizeof(LOGFONT), &logfont)) {
145 std::vector<char> font_data;
146 RenderThread::Get()->PreCacheFont(logfont);
147 rv = GetFontData(hdc, table, offset, buffer, length);
148 RenderThread::Get()->ReleaseCachedFonts();
151 return rv;
153 #endif // OS_WIN
155 } // namespace
157 bool ChromeRenderProcessObserver::is_incognito_process_ = false;
159 ChromeRenderProcessObserver::ChromeRenderProcessObserver(
160 chrome::ChromeContentRendererClient* client)
161 : client_(client),
162 clear_cache_pending_(false) {
163 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
164 if (command_line.HasSwitch(switches::kEnableWatchdog)) {
165 // TODO(JAR): Need to implement renderer IO msgloop watchdog.
168 if (command_line.HasSwitch(switches::kDumpHistogramsOnExit)) {
169 base::StatisticsRecorder::set_dump_on_exit(true);
172 #if defined(TOOLKIT_VIEWS)
173 WebRuntimeFeatures::enableRequestAutocomplete(
174 command_line.HasSwitch(switches::kEnableInteractiveAutocomplete) ||
175 command_line.HasSwitch(switches::kEnableExperimentalWebKitFeatures));
176 #endif
178 RenderThread* thread = RenderThread::Get();
179 resource_delegate_.reset(new RendererResourceDelegate());
180 thread->SetResourceDispatcherDelegate(resource_delegate_.get());
182 // Configure modules that need access to resources.
183 net::NetModule::SetResourceProvider(chrome_common_net::NetResourceProvider);
185 #if defined(OS_WIN)
186 // Need to patch a few functions for font loading to work correctly.
187 FilePath pdf;
188 if (PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf) &&
189 file_util::PathExists(pdf)) {
190 g_iat_patch_createdca.Patch(
191 pdf.value().c_str(), "gdi32.dll", "CreateDCA", CreateDCAPatch);
192 g_iat_patch_get_font_data.Patch(
193 pdf.value().c_str(), "gdi32.dll", "GetFontData", GetFontDataPatch);
195 #endif
197 #if defined(OS_POSIX) && !defined(OS_MACOSX) && defined(USE_NSS)
198 // On platforms where we use system NSS shared libraries,
199 // initialize NSS now because it won't be able to load the .so's
200 // after we engage the sandbox.
201 if (!command_line.HasSwitch(switches::kSingleProcess))
202 crypto::InitNSSSafely();
203 #elif defined(OS_WIN)
204 // crypt32.dll is used to decode X509 certificates for Chromoting.
205 // Only load this library when the feature is enabled.
206 std::string error;
207 base::LoadNativeLibrary(FilePath(L"crypt32.dll"), &error);
208 #endif
209 // Setup initial set of crash dump data for Field Trials in this renderer.
210 chrome_variations::SetChildProcessLoggingVariationList();
213 ChromeRenderProcessObserver::~ChromeRenderProcessObserver() {
216 bool ChromeRenderProcessObserver::OnControlMessageReceived(
217 const IPC::Message& message) {
218 bool handled = true;
219 IPC_BEGIN_MESSAGE_MAP(ChromeRenderProcessObserver, message)
220 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetIsIncognitoProcess,
221 OnSetIsIncognitoProcess)
222 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetCacheCapacities, OnSetCacheCapacities)
223 IPC_MESSAGE_HANDLER(ChromeViewMsg_ClearCache, OnClearCache)
224 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetFieldTrialGroup, OnSetFieldTrialGroup)
225 IPC_MESSAGE_HANDLER(ChromeViewMsg_GetV8HeapStats, OnGetV8HeapStats)
226 IPC_MESSAGE_HANDLER(ChromeViewMsg_GetCacheResourceStats,
227 OnGetCacheResourceStats)
228 IPC_MESSAGE_HANDLER(ChromeViewMsg_PurgeMemory, OnPurgeMemory)
229 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetContentSettingRules,
230 OnSetContentSettingRules)
231 IPC_MESSAGE_HANDLER(ChromeViewMsg_ToggleWebKitSharedTimer,
232 OnToggleWebKitSharedTimer)
233 IPC_MESSAGE_UNHANDLED(handled = false)
234 IPC_END_MESSAGE_MAP()
235 return handled;
238 void ChromeRenderProcessObserver::OnSetIsIncognitoProcess(
239 bool is_incognito_process) {
240 is_incognito_process_ = is_incognito_process;
243 void ChromeRenderProcessObserver::OnSetContentSettingRules(
244 const RendererContentSettingRules& rules) {
245 content_setting_rules_ = rules;
248 void ChromeRenderProcessObserver::OnSetCacheCapacities(size_t min_dead_capacity,
249 size_t max_dead_capacity,
250 size_t capacity) {
251 WebCache::setCapacities(
252 min_dead_capacity, max_dead_capacity, capacity);
255 void ChromeRenderProcessObserver::OnClearCache(bool on_navigation) {
256 if (on_navigation) {
257 clear_cache_pending_ = true;
258 } else {
259 WebCache::clear();
263 void ChromeRenderProcessObserver::OnGetCacheResourceStats() {
264 WebCache::ResourceTypeStats stats;
265 WebCache::getResourceTypeStats(&stats);
266 RenderThread::Get()->Send(new ChromeViewHostMsg_ResourceTypeStats(stats));
269 void ChromeRenderProcessObserver::OnSetFieldTrialGroup(
270 const std::string& field_trial_name,
271 const std::string& group_name) {
272 base::FieldTrial* trial =
273 base::FieldTrialList::CreateFieldTrial(field_trial_name, group_name);
274 // Ensure the trial is marked as "used" by calling group() on it. This is
275 // needed to ensure the trial is properly reported in renderer crash reports.
276 trial->group();
277 chrome_variations::SetChildProcessLoggingVariationList();
280 void ChromeRenderProcessObserver::OnGetV8HeapStats() {
281 v8::HeapStatistics heap_stats;
282 v8::V8::GetHeapStatistics(&heap_stats);
283 RenderThread::Get()->Send(new ChromeViewHostMsg_V8HeapStats(
284 heap_stats.total_heap_size(), heap_stats.used_heap_size()));
287 void ChromeRenderProcessObserver::OnToggleWebKitSharedTimer(bool suspend) {
288 RenderThread::Get()->ToggleWebKitSharedTimer(suspend);
291 void ChromeRenderProcessObserver::OnPurgeMemory() {
292 RenderThread::Get()->EnsureWebKitInitialized();
294 // Clear the object cache (as much as possible; some live objects cannot be
295 // freed).
296 WebCache::clear();
298 // Clear the font/glyph cache.
299 WebFontCache::clear();
301 // Clear the Cross-Origin Preflight cache.
302 WebCrossOriginPreflightResultCache::clear();
304 // Release all freeable memory from the SQLite process-global page cache (a
305 // low-level object which backs the Connection-specific page caches).
306 while (sqlite3_release_memory(std::numeric_limits<int>::max()) > 0) {
309 v8::V8::LowMemoryNotification();
311 // Tell our allocator to release any free pages it's still holding.
312 base::allocator::ReleaseFreeMemory();
314 if (client_)
315 client_->OnPurgeMemory();
318 void ChromeRenderProcessObserver::ExecutePendingClearCache() {
319 if (clear_cache_pending_) {
320 clear_cache_pending_ = false;
321 WebCache::clear();
325 const RendererContentSettingRules*
326 ChromeRenderProcessObserver::content_setting_rules() const {
327 return &content_setting_rules_;