blob: 69b56b2320eceefc46fe4b5346293764a85baaa8 [file] [log] [blame]
license.botbf09a502008-08-24 00:55:551// Copyright (c) 2006-2008 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.
initial.commit09911bf2008-07-26 23:55:294
[email protected]037fce02009-01-22 01:42:155#include "build/build_config.h"
6
7#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:298#include <windows.h>
9#include <objidl.h>
10#include <mlang.h>
[email protected]037fce02009-01-22 01:42:1511#endif
initial.commit09911bf2008-07-26 23:55:2912
13#include "chrome/renderer/render_process.h"
14
15#include "base/basictypes.h"
16#include "base/command_line.h"
[email protected]037fce02009-01-22 01:42:1517#include "base/compiler_specific.h"
initial.commit09911bf2008-07-26 23:55:2918#include "base/message_loop.h"
19#include "base/histogram.h"
[email protected]8ee8189e2008-10-08 19:35:2120#include "base/path_service.h"
[email protected]037fce02009-01-22 01:42:1521#include "base/sys_info.h"
initial.commit09911bf2008-07-26 23:55:2922#include "chrome/browser/net/dns_global.h" // TODO(jar): DNS calls should be renderer specific, not including browser.
23#include "chrome/common/chrome_switches.h"
[email protected]8ee8189e2008-10-08 19:35:2124#include "chrome/common/chrome_paths.h"
initial.commit09911bf2008-07-26 23:55:2925#include "chrome/common/ipc_channel.h"
26#include "chrome/common/ipc_message_utils.h"
27#include "chrome/common/render_messages.h"
28#include "chrome/renderer/render_view.h"
29#include "webkit/glue/webkit_glue.h"
30
31//-----------------------------------------------------------------------------
32
initial.commit09911bf2008-07-26 23:55:2933bool RenderProcess::load_plugins_in_process_ = false;
34
35//-----------------------------------------------------------------------------
36
37RenderProcess::RenderProcess(const std::wstring& channel_name)
38 : render_thread_(channel_name),
[email protected]037fce02009-01-22 01:42:1539 ALLOW_THIS_IN_INITIALIZER_LIST(clearer_factory_(this)) {
40 for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i)
initial.commit09911bf2008-07-26 23:55:2941 shared_mem_cache_[i] = NULL;
42}
43
44RenderProcess::~RenderProcess() {
45 // We need to stop the RenderThread as the clearer_factory_
46 // member could be in use while the object itself is destroyed,
47 // as a result of the containing RenderProcess object being destroyed.
48 // This race condition causes a crash when the renderer process is shutting
49 // down.
50 render_thread_.Stop();
51 ClearSharedMemCache();
52}
53
54// static
55bool RenderProcess::GlobalInit(const std::wstring &channel_name) {
[email protected]037fce02009-01-22 01:42:1556#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:2957 // HACK: See http://b/issue?id=1024307 for rationale.
58 if (GetModuleHandle(L"LPK.DLL") == NULL) {
59 // Makes sure lpk.dll is loaded by gdi32 to make sure ExtTextOut() works
60 // when buffering into a EMF buffer for printing.
61 typedef BOOL (__stdcall *GdiInitializeLanguagePack)(int LoadedShapingDLLs);
62 GdiInitializeLanguagePack gdi_init_lpk =
63 reinterpret_cast<GdiInitializeLanguagePack>(GetProcAddress(
64 GetModuleHandle(L"GDI32.DLL"),
65 "GdiInitializeLanguagePack"));
66 DCHECK(gdi_init_lpk);
67 if (gdi_init_lpk) {
68 gdi_init_lpk(0);
69 }
70 }
[email protected]037fce02009-01-22 01:42:1571#endif
initial.commit09911bf2008-07-26 23:55:2972
[email protected]bb975362009-01-21 01:00:2273 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
initial.commit09911bf2008-07-26 23:55:2974 if (command_line.HasSwitch(switches::kJavaScriptFlags)) {
75 webkit_glue::SetJavaScriptFlags(
76 command_line.GetSwitchValue(switches::kJavaScriptFlags));
77 }
78 if (command_line.HasSwitch(switches::kPlaybackMode) ||
79 command_line.HasSwitch(switches::kRecordMode)) {
80 webkit_glue::SetRecordPlaybackMode(true);
81 }
82
83 if (command_line.HasSwitch(switches::kInProcessPlugins) ||
84 command_line.HasSwitch(switches::kSingleProcess))
85 load_plugins_in_process_ = true;
86
initial.commit09911bf2008-07-26 23:55:2987 if (command_line.HasSwitch(switches::kEnableWatchdog)) {
88 // TODO(JAR): Need to implement renderer IO msgloop watchdog.
89 }
90
91 if (command_line.HasSwitch(switches::kDumpHistogramsOnExit)) {
92 StatisticsRecorder::set_dump_on_exit(true);
93 }
94
[email protected]8ee8189e2008-10-08 19:35:2195 if (command_line.HasSwitch(switches::kGearsInRenderer)) {
[email protected]037fce02009-01-22 01:42:1596#if defined(OS_WIN)
[email protected]8ee8189e2008-10-08 19:35:2197 // Load gears.dll on startup so we can access it before the sandbox
98 // blocks us.
99 std::wstring path;
100 if (PathService::Get(chrome::FILE_GEARS_PLUGIN, &path))
101 LoadLibrary(path.c_str());
[email protected]037fce02009-01-22 01:42:15102#else
103 // TODO(port) Need to handle loading gears on non-Windows platforms
104 NOTIMPLEMENTED();
105#endif
[email protected]8ee8189e2008-10-08 19:35:21106 }
107
initial.commit09911bf2008-07-26 23:55:29108 ChildProcessFactory<RenderProcess> factory;
109 return ChildProcess::GlobalInit(channel_name, &factory);
110}
111
112// static
113void RenderProcess::GlobalCleanup() {
114 ChildProcess::GlobalCleanup();
initial.commit09911bf2008-07-26 23:55:29115}
116
117// static
118bool RenderProcess::ShouldLoadPluginsInProcess() {
119 return load_plugins_in_process_;
120}
121
122// static
[email protected]176aa482008-11-14 03:25:15123base::SharedMemory* RenderProcess::AllocSharedMemory(size_t size) {
initial.commit09911bf2008-07-26 23:55:29124 self()->clearer_factory_.RevokeAll();
125
[email protected]176aa482008-11-14 03:25:15126 base::SharedMemory* mem = self()->GetSharedMemFromCache(size);
initial.commit09911bf2008-07-26 23:55:29127 if (mem)
128 return mem;
129
130 // Round-up size to allocation granularity
[email protected]037fce02009-01-22 01:42:15131 size_t allocation_granularity = base::SysInfo::VMAllocationGranularity();
132 size = size / allocation_granularity + 1;
133 size = size * allocation_granularity;
initial.commit09911bf2008-07-26 23:55:29134
[email protected]176aa482008-11-14 03:25:15135 mem = new base::SharedMemory();
initial.commit09911bf2008-07-26 23:55:29136 if (!mem)
137 return NULL;
138 if (!mem->Create(L"", false, true, size)) {
139 delete mem;
140 return NULL;
141 }
142
143 return mem;
144}
145
146// static
[email protected]176aa482008-11-14 03:25:15147void RenderProcess::FreeSharedMemory(base::SharedMemory* mem) {
initial.commit09911bf2008-07-26 23:55:29148 if (self()->PutSharedMemInCache(mem)) {
149 self()->ScheduleCacheClearer();
150 return;
151 }
152 DeleteSharedMem(mem);
153}
154
155// static
[email protected]176aa482008-11-14 03:25:15156void RenderProcess::DeleteSharedMem(base::SharedMemory* mem) {
initial.commit09911bf2008-07-26 23:55:29157 delete mem;
158}
159
[email protected]176aa482008-11-14 03:25:15160base::SharedMemory* RenderProcess::GetSharedMemFromCache(size_t size) {
initial.commit09911bf2008-07-26 23:55:29161 // look for a cached object that is suitable for the requested size.
[email protected]037fce02009-01-22 01:42:15162 for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i) {
[email protected]176aa482008-11-14 03:25:15163 base::SharedMemory* mem = shared_mem_cache_[i];
initial.commit09911bf2008-07-26 23:55:29164 if (mem && mem->max_size() >= size) {
165 shared_mem_cache_[i] = NULL;
166 return mem;
167 }
168 }
169 return NULL;
170}
171
[email protected]176aa482008-11-14 03:25:15172bool RenderProcess::PutSharedMemInCache(base::SharedMemory* mem) {
initial.commit09911bf2008-07-26 23:55:29173 // simple algorithm:
174 // - look for an empty slot to store mem, or
175 // - if full, then replace any existing cache entry that is smaller than the
176 // given shared memory object.
[email protected]037fce02009-01-22 01:42:15177 for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i) {
initial.commit09911bf2008-07-26 23:55:29178 if (!shared_mem_cache_[i]) {
179 shared_mem_cache_[i] = mem;
180 return true;
181 }
182 }
[email protected]037fce02009-01-22 01:42:15183 for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i) {
[email protected]176aa482008-11-14 03:25:15184 base::SharedMemory* cached_mem = shared_mem_cache_[i];
initial.commit09911bf2008-07-26 23:55:29185 if (cached_mem->max_size() < mem->max_size()) {
186 shared_mem_cache_[i] = mem;
187 DeleteSharedMem(cached_mem);
188 return true;
189 }
190 }
191 return false;
192}
193
194void RenderProcess::ClearSharedMemCache() {
[email protected]037fce02009-01-22 01:42:15195 for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i) {
initial.commit09911bf2008-07-26 23:55:29196 if (shared_mem_cache_[i]) {
197 DeleteSharedMem(shared_mem_cache_[i]);
198 shared_mem_cache_[i] = NULL;
199 }
200 }
201}
202
203void RenderProcess::ScheduleCacheClearer() {
204 // If we already have a deferred clearer, then revoke it so we effectively
205 // delay cache clearing until idle for our desired interval.
206 clearer_factory_.RevokeAll();
207
208 MessageLoop::current()->PostDelayedTask(FROM_HERE,
209 clearer_factory_.NewRunnableMethod(&RenderProcess::ClearSharedMemCache),
210 5000 /* 5 seconds */);
211}
212
213void RenderProcess::Cleanup() {
214#ifndef NDEBUG
215 // log important leaked objects
216 webkit_glue::CheckForLeaks();
217#endif
218}