Fixed service side implementation of glTexStorage2DEXT to only initialize the number of
[chromium-blink-merge.git] / chrome / renderer / chrome_render_process_observer.cc
blobbf3389fff175cae4e16fa781f6eb8a0dd7edcb0e
1 // Copyright (c) 2011 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 "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/file_util.h"
10 #include "base/message_loop.h"
11 #include "base/memory/weak_ptr.h"
12 #include "base/metrics/field_trial.h"
13 #include "base/metrics/histogram.h"
14 #include "base/native_library.h"
15 #include "base/path_service.h"
16 #include "base/process_util.h"
17 #include "base/threading/platform_thread.h"
18 #include "chrome/common/chrome_paths.h"
19 #include "chrome/common/chrome_switches.h"
20 #include "chrome/common/extensions/extension_localization_peer.h"
21 #include "chrome/common/net/net_resource_provider.h"
22 #include "chrome/common/render_messages.h"
23 #include "chrome/renderer/chrome_content_renderer_client.h"
24 #include "chrome/renderer/content_settings_observer.h"
25 #include "chrome/renderer/security_filter_peer.h"
26 #include "content/public/common/resource_dispatcher_delegate.h"
27 #include "content/public/renderer/render_thread.h"
28 #include "content/public/renderer/render_view_visitor.h"
29 #include "content/public/renderer/render_view.h"
30 #include "crypto/nss_util.h"
31 #include "media/base/media.h"
32 #include "media/base/media_switches.h"
33 #include "net/base/net_errors.h"
34 #include "net/base/net_module.h"
35 #include "third_party/sqlite/sqlite3.h"
36 #include "third_party/tcmalloc/chromium/src/google/heap-profiler.h"
37 #include "third_party/tcmalloc/chromium/src/google/malloc_extension.h"
38 #include "third_party/WebKit/Source/WebKit/chromium/public/WebCache.h"
39 #include "third_party/WebKit/Source/WebKit/chromium/public/WebCrossOriginPreflightResultCache.h"
40 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
41 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFontCache.h"
42 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
43 #include "third_party/WebKit/Source/WebKit/chromium/public/WebRuntimeFeatures.h"
44 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
45 #include "v8/include/v8.h"
47 #if defined(OS_WIN)
48 #include "base/win/iat_patch_function.h"
49 #endif
51 using WebKit::WebCache;
52 using WebKit::WebCrossOriginPreflightResultCache;
53 using WebKit::WebFontCache;
54 using WebKit::WebRuntimeFeatures;
55 using content::RenderThread;
57 namespace {
59 static const unsigned int kCacheStatsDelayMS = 2000 /* milliseconds */;
61 class RendererResourceDelegate : public content::ResourceDispatcherDelegate {
62 public:
63 RendererResourceDelegate()
64 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
67 virtual webkit_glue::ResourceLoaderBridge::Peer* OnRequestComplete(
68 webkit_glue::ResourceLoaderBridge::Peer* current_peer,
69 ResourceType::Type resource_type,
70 const net::URLRequestStatus& status) {
71 // Update the browser about our cache.
72 // Rate limit informing the host of our cache stats.
73 if (!weak_factory_.HasWeakPtrs()) {
74 MessageLoop::current()->PostDelayedTask(
75 FROM_HERE,
76 base::Bind(&RendererResourceDelegate::InformHostOfCacheStats,
77 weak_factory_.GetWeakPtr()),
78 kCacheStatsDelayMS);
81 if (status.status() != net::URLRequestStatus::CANCELED ||
82 status.error() == net::ERR_ABORTED) {
83 return NULL;
86 // Resource canceled with a specific error are filtered.
87 return SecurityFilterPeer::CreateSecurityFilterPeerForDeniedRequest(
88 resource_type, current_peer, status.error());
91 virtual webkit_glue::ResourceLoaderBridge::Peer* OnReceivedResponse(
92 webkit_glue::ResourceLoaderBridge::Peer* current_peer,
93 const std::string& mime_type,
94 const GURL& url) {
95 return ExtensionLocalizationPeer::CreateExtensionLocalizationPeer(
96 current_peer, RenderThread::Get(), mime_type, url);
99 private:
100 void InformHostOfCacheStats() {
101 WebCache::UsageStats stats;
102 WebCache::getUsageStats(&stats);
103 RenderThread::Get()->Send(new ChromeViewHostMsg_UpdatedCacheStats(stats));
106 base::WeakPtrFactory<RendererResourceDelegate> weak_factory_;
108 DISALLOW_COPY_AND_ASSIGN(RendererResourceDelegate);
111 #if defined(OS_WIN)
112 static base::win::IATPatchFunction g_iat_patch_createdca;
113 HDC WINAPI CreateDCAPatch(LPCSTR driver_name,
114 LPCSTR device_name,
115 LPCSTR output,
116 const void* init_data) {
117 DCHECK(std::string("DISPLAY") == std::string(driver_name));
118 DCHECK(!device_name);
119 DCHECK(!output);
120 DCHECK(!init_data);
122 // CreateDC fails behind the sandbox, but not CreateCompatibleDC.
123 return CreateCompatibleDC(NULL);
126 static base::win::IATPatchFunction g_iat_patch_get_font_data;
127 DWORD WINAPI GetFontDataPatch(HDC hdc,
128 DWORD table,
129 DWORD offset,
130 LPVOID buffer,
131 DWORD length) {
132 int rv = GetFontData(hdc, table, offset, buffer, length);
133 if (rv == GDI_ERROR && hdc) {
134 HFONT font = static_cast<HFONT>(GetCurrentObject(hdc, OBJ_FONT));
136 LOGFONT logfont;
137 if (GetObject(font, sizeof(LOGFONT), &logfont)) {
138 std::vector<char> font_data;
139 RenderThread::Get()->PreCacheFont(logfont);
140 rv = GetFontData(hdc, table, offset, buffer, length);
141 RenderThread::Get()->ReleaseCachedFonts();
144 return rv;
146 #endif // OS_WIN
148 #if defined(OS_POSIX)
149 class SuicideOnChannelErrorFilter : public IPC::ChannelProxy::MessageFilter {
150 void OnChannelError() {
151 // On POSIX, at least, one can install an unload handler which loops
152 // forever and leave behind a renderer process which eats 100% CPU forever.
154 // This is because the terminate signals (ViewMsg_ShouldClose and the error
155 // from the IPC channel) are routed to the main message loop but never
156 // processed (because that message loop is stuck in V8).
158 // One could make the browser SIGKILL the renderers, but that leaves open a
159 // large window where a browser failure (or a user, manually terminating
160 // the browser because "it's stuck") will leave behind a process eating all
161 // the CPU.
163 // So, we install a filter on the channel so that we can process this event
164 // here and kill the process.
166 _exit(0);
169 #endif // OS_POSIX
171 } // namespace
173 bool ChromeRenderProcessObserver::is_incognito_process_ = false;
175 ChromeRenderProcessObserver::ChromeRenderProcessObserver(
176 chrome::ChromeContentRendererClient* client)
177 : client_(client),
178 clear_cache_pending_(false) {
179 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
180 if (command_line.HasSwitch(switches::kEnableWatchdog)) {
181 // TODO(JAR): Need to implement renderer IO msgloop watchdog.
184 if (command_line.HasSwitch(switches::kDumpHistogramsOnExit)) {
185 base::StatisticsRecorder::set_dump_on_exit(true);
188 RenderThread* thread = RenderThread::Get();
189 resource_delegate_.reset(new RendererResourceDelegate());
190 thread->SetResourceDispatcherDelegate(resource_delegate_.get());
192 #if defined(OS_POSIX)
193 thread->AddFilter(new SuicideOnChannelErrorFilter());
194 #endif
196 // Configure modules that need access to resources.
197 net::NetModule::SetResourceProvider(chrome_common_net::NetResourceProvider);
199 #if defined(OS_WIN)
200 // Need to patch a few functions for font loading to work correctly.
201 FilePath pdf;
202 if (PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf) &&
203 file_util::PathExists(pdf)) {
204 g_iat_patch_createdca.Patch(
205 pdf.value().c_str(), "gdi32.dll", "CreateDCA", CreateDCAPatch);
206 g_iat_patch_get_font_data.Patch(
207 pdf.value().c_str(), "gdi32.dll", "GetFontData", GetFontDataPatch);
209 #endif
211 #if defined(OS_POSIX) && !defined(OS_MACOSX) && defined(USE_NSS)
212 // Remoting requires NSS to function properly.
213 if (!command_line.HasSwitch(switches::kSingleProcess)) {
214 // We are going to fork to engage the sandbox and we have not loaded
215 // any security modules so it is safe to disable the fork check in NSS.
216 crypto::DisableNSSForkCheck();
217 crypto::ForceNSSNoDBInit();
218 crypto::EnsureNSSInit();
220 #elif defined(OS_WIN)
221 // crypt32.dll is used to decode X509 certificates for Chromoting.
222 // Only load this library when the feature is enabled.
223 std::string error;
224 base::LoadNativeLibrary(FilePath(L"crypt32.dll"), &error);
225 #endif
227 // Note that under Linux, the media library will normally already have
228 // been initialized by the Zygote before this instance became a Renderer.
229 FilePath media_path;
230 PathService::Get(chrome::DIR_MEDIA_LIBS, &media_path);
231 if (!media_path.empty())
232 media::InitializeMediaLibrary(media_path);
235 ChromeRenderProcessObserver::~ChromeRenderProcessObserver() {
238 bool ChromeRenderProcessObserver::OnControlMessageReceived(
239 const IPC::Message& message) {
240 bool handled = true;
241 IPC_BEGIN_MESSAGE_MAP(ChromeRenderProcessObserver, message)
242 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetIsIncognitoProcess,
243 OnSetIsIncognitoProcess)
244 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetCacheCapacities, OnSetCacheCapacities)
245 IPC_MESSAGE_HANDLER(ChromeViewMsg_ClearCache, OnClearCache)
246 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetFieldTrialGroup, OnSetFieldTrialGroup)
247 #if defined(USE_TCMALLOC)
248 IPC_MESSAGE_HANDLER(ChromeViewMsg_GetRendererTcmalloc,
249 OnGetRendererTcmalloc)
250 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetTcmallocHeapProfiling,
251 OnSetTcmallocHeapProfiling)
252 IPC_MESSAGE_HANDLER(ChromeViewMsg_WriteTcmallocHeapProfile,
253 OnWriteTcmallocHeapProfile)
254 #endif
255 IPC_MESSAGE_HANDLER(ChromeViewMsg_GetV8HeapStats, OnGetV8HeapStats)
256 IPC_MESSAGE_HANDLER(ChromeViewMsg_GetCacheResourceStats,
257 OnGetCacheResourceStats)
258 IPC_MESSAGE_HANDLER(ChromeViewMsg_PurgeMemory, OnPurgeMemory)
259 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetContentSettingRules,
260 OnSetContentSettingRules)
261 IPC_MESSAGE_UNHANDLED(handled = false)
262 IPC_END_MESSAGE_MAP()
263 return handled;
266 void ChromeRenderProcessObserver::WebKitInitialized() {
267 WebRuntimeFeatures::enableMediaPlayer(media::IsMediaLibraryInitialized());
270 void ChromeRenderProcessObserver::OnSetIsIncognitoProcess(
271 bool is_incognito_process) {
272 is_incognito_process_ = is_incognito_process;
275 void ChromeRenderProcessObserver::OnSetContentSettingRules(
276 const RendererContentSettingRules& rules) {
277 content_setting_rules_ = rules;
280 void ChromeRenderProcessObserver::OnSetCacheCapacities(size_t min_dead_capacity,
281 size_t max_dead_capacity,
282 size_t capacity) {
283 WebCache::setCapacities(
284 min_dead_capacity, max_dead_capacity, capacity);
287 void ChromeRenderProcessObserver::OnClearCache(bool on_navigation) {
288 if (on_navigation) {
289 clear_cache_pending_ = true;
290 } else {
291 WebCache::clear();
295 void ChromeRenderProcessObserver::OnGetCacheResourceStats() {
296 WebCache::ResourceTypeStats stats;
297 WebCache::getResourceTypeStats(&stats);
298 RenderThread::Get()->Send(new ChromeViewHostMsg_ResourceTypeStats(stats));
301 #if defined(USE_TCMALLOC)
302 void ChromeRenderProcessObserver::OnGetRendererTcmalloc() {
303 std::string result;
304 char buffer[1024 * 32];
305 MallocExtension::instance()->GetStats(buffer, sizeof(buffer));
306 result.append(buffer);
307 RenderThread::Get()->Send(new ChromeViewHostMsg_RendererTcmalloc(result));
310 void ChromeRenderProcessObserver::OnSetTcmallocHeapProfiling(
311 bool profiling, const std::string& filename_prefix) {
312 #if !defined(OS_WIN)
313 // TODO(stevenjb): Create MallocExtension wrappers for HeapProfile functions.
314 if (profiling)
315 HeapProfilerStart(filename_prefix.c_str());
316 else
317 HeapProfilerStop();
318 #endif
321 void ChromeRenderProcessObserver::OnWriteTcmallocHeapProfile(
322 const FilePath::StringType& filename) {
323 #if !defined(OS_WIN)
324 // TODO(stevenjb): Create MallocExtension wrappers for HeapProfile functions.
325 if (!IsHeapProfilerRunning())
326 return;
327 char* profile = GetHeapProfile();
328 if (!profile) {
329 LOG(WARNING) << "Unable to get heap profile.";
330 return;
332 // The render process can not write to a file, so copy the result into
333 // a string and pass it to the handler (which runs on the browser host).
334 std::string result(profile);
335 delete profile;
336 RenderThread::Get()->Send(
337 new ChromeViewHostMsg_WriteTcmallocHeapProfile_ACK(filename, result));
338 #endif
341 #endif
343 void ChromeRenderProcessObserver::OnSetFieldTrialGroup(
344 const std::string& field_trial_name,
345 const std::string& group_name) {
346 base::FieldTrialList::CreateFieldTrial(field_trial_name, group_name);
349 void ChromeRenderProcessObserver::OnGetV8HeapStats() {
350 v8::HeapStatistics heap_stats;
351 v8::V8::GetHeapStatistics(&heap_stats);
352 RenderThread::Get()->Send(new ChromeViewHostMsg_V8HeapStats(
353 heap_stats.total_heap_size(), heap_stats.used_heap_size()));
356 void ChromeRenderProcessObserver::OnPurgeMemory() {
357 // Clear the object cache (as much as possible; some live objects cannot be
358 // freed).
359 WebCache::clear();
361 // Clear the font/glyph cache.
362 WebFontCache::clear();
364 // Clear the Cross-Origin Preflight cache.
365 WebCrossOriginPreflightResultCache::clear();
367 // Release all freeable memory from the SQLite process-global page cache (a
368 // low-level object which backs the Connection-specific page caches).
369 while (sqlite3_release_memory(std::numeric_limits<int>::max()) > 0) {
372 v8::V8::LowMemoryNotification();
374 #if !defined(OS_MACOSX) && defined(USE_TCMALLOC)
375 // Tell tcmalloc to release any free pages it's still holding.
376 MallocExtension::instance()->ReleaseFreeMemory();
377 #endif
379 if (client_)
380 client_->OnPurgeMemory();
383 void ChromeRenderProcessObserver::ExecutePendingClearCache() {
384 if (clear_cache_pending_) {
385 clear_cache_pending_ = false;
386 WebCache::clear();
390 const RendererContentSettingRules*
391 ChromeRenderProcessObserver::content_setting_rules() const {
392 return &content_setting_rules_;