blob: 94d353e31c319bc162d3498165518db5297821f1 [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"
[email protected]f09c7182009-03-10 12:54:0422// TODO(jar): DNS calls should be renderer specific, not including browser.
23#include "chrome/browser/net/dns_global.h"
initial.commit09911bf2008-07-26 23:55:2924#include "chrome/common/chrome_switches.h"
[email protected]8ee8189e2008-10-08 19:35:2125#include "chrome/common/chrome_paths.h"
[email protected]82e5ee82009-04-03 02:29:4526#include "chrome/common/ipc_channel.h"
27#include "chrome/common/ipc_message_utils.h"
initial.commit09911bf2008-07-26 23:55:2928#include "chrome/common/render_messages.h"
[email protected]e68e62fa2009-02-20 02:00:0429#include "chrome/common/transport_dib.h"
initial.commit09911bf2008-07-26 23:55:2930#include "chrome/renderer/render_view.h"
[email protected]10000d62009-04-18 00:36:2231#include "media/base/media.h"
initial.commit09911bf2008-07-26 23:55:2932#include "webkit/glue/webkit_glue.h"
33
[email protected]bf557e12009-02-25 20:50:2934//-----------------------------------------------------------------------------
initial.commit09911bf2008-07-26 23:55:2935
[email protected]8930d472009-02-21 08:05:2836RenderProcess::RenderProcess()
37 : ChildProcess(new RenderThread()),
[email protected]514e7112009-02-20 05:23:3638 ALLOW_THIS_IN_INITIALIZER_LIST(shared_mem_cache_cleaner_(
39 base::TimeDelta::FromSeconds(5),
40 this, &RenderProcess::ClearTransportDIBCache)),
41 sequence_number_(0) {
[email protected]8930d472009-02-21 08:05:2842 Init();
43}
44
45RenderProcess::RenderProcess(const std::wstring& channel_name)
46 : ChildProcess(new RenderThread(channel_name)),
47 ALLOW_THIS_IN_INITIALIZER_LIST(shared_mem_cache_cleaner_(
48 base::TimeDelta::FromSeconds(5),
49 this, &RenderProcess::ClearTransportDIBCache)),
50 sequence_number_(0) {
51 Init();
initial.commit09911bf2008-07-26 23:55:2952}
53
54RenderProcess::~RenderProcess() {
[email protected]8930d472009-02-21 08:05:2855 // TODO(port)
56 // Try and limit what we pull in for our non-Win unit test bundle
57#ifndef NDEBUG
58 // log important leaked objects
59 webkit_glue::CheckForLeaks();
60#endif
61
62 GetShutDownEvent()->Signal();
63
initial.commit09911bf2008-07-26 23:55:2964 // We need to stop the RenderThread as the clearer_factory_
65 // member could be in use while the object itself is destroyed,
66 // as a result of the containing RenderProcess object being destroyed.
67 // This race condition causes a crash when the renderer process is shutting
68 // down.
[email protected]8930d472009-02-21 08:05:2869 child_thread()->Stop();
[email protected]e68e62fa2009-02-20 02:00:0470 ClearTransportDIBCache();
initial.commit09911bf2008-07-26 23:55:2971}
72
[email protected]8930d472009-02-21 08:05:2873void RenderProcess::Init() {
74 in_process_plugins_ = InProcessPlugins();
[email protected]8930d472009-02-21 08:05:2875 for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i)
76 shared_mem_cache_[i] = NULL;
77
[email protected]037fce02009-01-22 01:42:1578#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:2979 // HACK: See http://b/issue?id=1024307 for rationale.
80 if (GetModuleHandle(L"LPK.DLL") == NULL) {
81 // Makes sure lpk.dll is loaded by gdi32 to make sure ExtTextOut() works
82 // when buffering into a EMF buffer for printing.
83 typedef BOOL (__stdcall *GdiInitializeLanguagePack)(int LoadedShapingDLLs);
84 GdiInitializeLanguagePack gdi_init_lpk =
85 reinterpret_cast<GdiInitializeLanguagePack>(GetProcAddress(
86 GetModuleHandle(L"GDI32.DLL"),
87 "GdiInitializeLanguagePack"));
88 DCHECK(gdi_init_lpk);
89 if (gdi_init_lpk) {
90 gdi_init_lpk(0);
91 }
92 }
[email protected]037fce02009-01-22 01:42:1593#endif
initial.commit09911bf2008-07-26 23:55:2994
[email protected]bb975362009-01-21 01:00:2295 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
initial.commit09911bf2008-07-26 23:55:2996 if (command_line.HasSwitch(switches::kJavaScriptFlags)) {
97 webkit_glue::SetJavaScriptFlags(
98 command_line.GetSwitchValue(switches::kJavaScriptFlags));
99 }
initial.commit09911bf2008-07-26 23:55:29100
[email protected]2ef9c452009-05-13 13:03:14101 if (!command_line.HasSwitch(switches::kDisableOutOfProcessDevTools)) {
102 // Out of process dev tools rely upon auto break behavior.
103 webkit_glue::SetJavaScriptFlags(L"--debugger-auto-break");
104 }
105
initial.commit09911bf2008-07-26 23:55:29106 if (command_line.HasSwitch(switches::kEnableWatchdog)) {
107 // TODO(JAR): Need to implement renderer IO msgloop watchdog.
108 }
109
110 if (command_line.HasSwitch(switches::kDumpHistogramsOnExit)) {
111 StatisticsRecorder::set_dump_on_exit(true);
112 }
113
[email protected]10000d62009-04-18 00:36:22114 FilePath module_path;
115 if (PathService::Get(base::DIR_MODULE, &module_path)) {
116 if (media::InitializeMediaLibrary(module_path)) {
117 webkit_glue::SetMediaPlayerAvailable(true);
118 }
[email protected]c3e28172009-02-11 23:38:32119 }
initial.commit09911bf2008-07-26 23:55:29120}
121
[email protected]8930d472009-02-21 08:05:28122bool RenderProcess::InProcessPlugins() {
123 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
[email protected]0e2f8752009-04-27 20:34:31124#if defined(OS_LINUX)
125 // Plugin processes require a UI message loop, and the Linux message loop
126 // implementation only allows one UI loop per process.
127 if (command_line.HasSwitch(switches::kInProcessPlugins))
128 NOTIMPLEMENTED() << ": in process plugins not supported on Linux";
129 return command_line.HasSwitch(switches::kInProcessPlugins);
130#else
[email protected]8930d472009-02-21 08:05:28131 return command_line.HasSwitch(switches::kInProcessPlugins) ||
132 command_line.HasSwitch(switches::kSingleProcess);
[email protected]0e2f8752009-04-27 20:34:31133#endif
initial.commit09911bf2008-07-26 23:55:29134}
135
[email protected]e68e62fa2009-02-20 02:00:04136// -----------------------------------------------------------------------------
137// Platform specific code for dealing with bitmap transport...
138
139// -----------------------------------------------------------------------------
140// Create a platform canvas object which renders into the given transport
141// memory.
142// -----------------------------------------------------------------------------
143static skia::PlatformCanvas* CanvasFromTransportDIB(
144 TransportDIB* dib, const gfx::Rect& rect) {
145#if defined(OS_WIN)
146 return new skia::PlatformCanvas(rect.width(), rect.height(), true,
147 dib->handle());
148#elif defined(OS_LINUX) || defined(OS_MACOSX)
149 return new skia::PlatformCanvas(rect.width(), rect.height(), true,
150 reinterpret_cast<uint8_t*>(dib->memory()));
151#endif
152}
153
154TransportDIB* RenderProcess::CreateTransportDIB(size_t size) {
155#if defined(OS_WIN) || defined(OS_LINUX)
156 // Windows and Linux create transport DIBs inside the renderer
157 return TransportDIB::Create(size, sequence_number_++);
158#elif defined(OS_MACOSX) // defined(OS_WIN) || defined(OS_LINUX)
159 // Mac creates transport DIBs in the browser, so we need to do a sync IPC to
160 // get one.
[email protected]2749885f2009-03-05 21:40:11161 TransportDIB::Handle handle;
162 IPC::Message* msg = new ViewHostMsg_AllocTransportDIB(size, &handle);
[email protected]8930d472009-02-21 08:05:28163 if (!child_thread()->Send(msg))
[email protected]e68e62fa2009-02-20 02:00:04164 return NULL;
[email protected]2749885f2009-03-05 21:40:11165 if (handle.fd < 0)
[email protected]e68e62fa2009-02-20 02:00:04166 return NULL;
[email protected]2749885f2009-03-05 21:40:11167 return TransportDIB::Map(handle);
[email protected]e68e62fa2009-02-20 02:00:04168#endif // defined(OS_MACOSX)
169}
170
171void RenderProcess::FreeTransportDIB(TransportDIB* dib) {
172 if (!dib)
173 return;
174
175#if defined(OS_MACOSX)
176 // On Mac we need to tell the browser that it can drop a reference to the
177 // shared memory.
178 IPC::Message* msg = new ViewHostMsg_FreeTransportDIB(dib->id());
[email protected]8930d472009-02-21 08:05:28179 child_thread()->Send(msg);
[email protected]e68e62fa2009-02-20 02:00:04180#endif
181
182 delete dib;
183}
184
185// -----------------------------------------------------------------------------
186
187
[email protected]e68e62fa2009-02-20 02:00:04188skia::PlatformCanvas* RenderProcess::GetDrawingCanvas(
189 TransportDIB** memory, const gfx::Rect& rect) {
190 const size_t stride = skia::PlatformCanvas::StrideForWidth(rect.width());
191 const size_t size = stride * rect.height();
initial.commit09911bf2008-07-26 23:55:29192
[email protected]8930d472009-02-21 08:05:28193 if (!GetTransportDIBFromCache(memory, size)) {
194 *memory = CreateTransportDIB(size);
[email protected]e68e62fa2009-02-20 02:00:04195 if (!*memory)
196 return false;
initial.commit09911bf2008-07-26 23:55:29197 }
198
[email protected]e68e62fa2009-02-20 02:00:04199 return CanvasFromTransportDIB(*memory, rect);
initial.commit09911bf2008-07-26 23:55:29200}
201
[email protected]e68e62fa2009-02-20 02:00:04202void RenderProcess::ReleaseTransportDIB(TransportDIB* mem) {
[email protected]8930d472009-02-21 08:05:28203 if (PutSharedMemInCache(mem)) {
204 shared_mem_cache_cleaner_.Reset();
initial.commit09911bf2008-07-26 23:55:29205 return;
206 }
[email protected]e68e62fa2009-02-20 02:00:04207
[email protected]8930d472009-02-21 08:05:28208 FreeTransportDIB(mem);
initial.commit09911bf2008-07-26 23:55:29209}
210
[email protected]e68e62fa2009-02-20 02:00:04211bool RenderProcess::GetTransportDIBFromCache(TransportDIB** mem,
212 size_t size) {
initial.commit09911bf2008-07-26 23:55:29213 // look for a cached object that is suitable for the requested size.
[email protected]037fce02009-01-22 01:42:15214 for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i) {
[email protected]e68e62fa2009-02-20 02:00:04215 if (shared_mem_cache_[i] &&
216 size <= shared_mem_cache_[i]->size()) {
217 *mem = shared_mem_cache_[i];
initial.commit09911bf2008-07-26 23:55:29218 shared_mem_cache_[i] = NULL;
[email protected]e68e62fa2009-02-20 02:00:04219 return true;
initial.commit09911bf2008-07-26 23:55:29220 }
221 }
initial.commit09911bf2008-07-26 23:55:29222
initial.commit09911bf2008-07-26 23:55:29223 return false;
224}
225
[email protected]e68e62fa2009-02-20 02:00:04226int RenderProcess::FindFreeCacheSlot(size_t size) {
227 // simple algorithm:
228 // - look for an empty slot to store mem, or
229 // - if full, then replace smallest entry which is smaller than |size|
230 for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i) {
231 if (shared_mem_cache_[i] == NULL)
232 return i;
233 }
234
235 size_t smallest_size = size;
236 int smallest_index = -1;
237
238 for (size_t i = 1; i < arraysize(shared_mem_cache_); ++i) {
239 const size_t entry_size = shared_mem_cache_[i]->size();
240 if (entry_size < smallest_size) {
241 smallest_size = entry_size;
242 smallest_index = i;
243 }
244 }
245
246 if (smallest_index != -1) {
247 FreeTransportDIB(shared_mem_cache_[smallest_index]);
248 shared_mem_cache_[smallest_index] = NULL;
249 }
250
251 return smallest_index;
252}
253
254bool RenderProcess::PutSharedMemInCache(TransportDIB* mem) {
255 const int slot = FindFreeCacheSlot(mem->size());
256 if (slot == -1)
257 return false;
258
259 shared_mem_cache_[slot] = mem;
260 return true;
261}
262
263void RenderProcess::ClearTransportDIBCache() {
[email protected]037fce02009-01-22 01:42:15264 for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i) {
initial.commit09911bf2008-07-26 23:55:29265 if (shared_mem_cache_[i]) {
[email protected]e68e62fa2009-02-20 02:00:04266 FreeTransportDIB(shared_mem_cache_[i]);
initial.commit09911bf2008-07-26 23:55:29267 shared_mem_cache_[i] = NULL;
268 }
269 }
270}