summaryrefslogtreecommitdiffstats
path: root/chrome/renderer/render_process.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/renderer/render_process.cc')
-rw-r--r--chrome/renderer/render_process.cc298
1 files changed, 298 insertions, 0 deletions
diff --git a/chrome/renderer/render_process.cc b/chrome/renderer/render_process.cc
new file mode 100644
index 0000000..f5d72c8
--- /dev/null
+++ b/chrome/renderer/render_process.cc
@@ -0,0 +1,298 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "build/build_config.h"
+
+#if defined(OS_WIN)
+#include <windows.h>
+#include <objidl.h>
+#include <mlang.h>
+#endif
+
+#include "chrome/renderer/render_process.h"
+
+#include "base/basictypes.h"
+#include "base/command_line.h"
+#include "base/compiler_specific.h"
+#include "base/file_util.h"
+#include "base/message_loop.h"
+#include "base/histogram.h"
+#include "base/path_service.h"
+#include "base/sys_info.h"
+// TODO(jar): DNS calls should be renderer specific, not including browser.
+#include "chrome/browser/net/dns_global.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/render_messages.h"
+#include "chrome/common/nacl_types.h"
+#include "chrome/common/transport_dib.h"
+#include "chrome/renderer/render_view.h"
+#include "ipc/ipc_channel.h"
+#include "ipc/ipc_message_utils.h"
+#include "media/base/media.h"
+#include "media/base/media_switches.h"
+#include "native_client/src/trusted/plugin/nacl_entry_points.h"
+#include "webkit/glue/webkit_glue.h"
+
+#if defined(OS_MACOSX)
+#include "base/mac_util.h"
+#endif
+
+//-----------------------------------------------------------------------------
+
+RenderProcess::RenderProcess()
+ : ALLOW_THIS_IN_INITIALIZER_LIST(shared_mem_cache_cleaner_(
+ base::TimeDelta::FromSeconds(5),
+ this, &RenderProcess::ClearTransportDIBCache)),
+ sequence_number_(0) {
+ in_process_plugins_ = InProcessPlugins();
+ for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i)
+ shared_mem_cache_[i] = NULL;
+
+#if defined(OS_WIN)
+ // HACK: See http://b/issue?id=1024307 for rationale.
+ if (GetModuleHandle(L"LPK.DLL") == NULL) {
+ // Makes sure lpk.dll is loaded by gdi32 to make sure ExtTextOut() works
+ // when buffering into a EMF buffer for printing.
+ typedef BOOL (__stdcall *GdiInitializeLanguagePack)(int LoadedShapingDLLs);
+ GdiInitializeLanguagePack gdi_init_lpk =
+ reinterpret_cast<GdiInitializeLanguagePack>(GetProcAddress(
+ GetModuleHandle(L"GDI32.DLL"),
+ "GdiInitializeLanguagePack"));
+ DCHECK(gdi_init_lpk);
+ if (gdi_init_lpk) {
+ gdi_init_lpk(0);
+ }
+ }
+#endif
+
+ // Out of process dev tools rely upon auto break behavior.
+ webkit_glue::SetJavaScriptFlags(
+ L"--debugger-auto-break"
+ // Enable lazy in-memory profiling.
+ L" --prof --prof-lazy --logfile=* --compress-log");
+
+ const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ if (command_line.HasSwitch(switches::kJavaScriptFlags)) {
+ webkit_glue::SetJavaScriptFlags(
+ command_line.GetSwitchValue(switches::kJavaScriptFlags));
+ }
+
+ if (command_line.HasSwitch(switches::kEnableWatchdog)) {
+ // TODO(JAR): Need to implement renderer IO msgloop watchdog.
+ }
+
+ if (command_line.HasSwitch(switches::kDumpHistogramsOnExit)) {
+ StatisticsRecorder::set_dump_on_exit(true);
+ }
+
+#ifndef DISABLE_NACL
+ if (command_line.HasSwitch(switches::kInternalNaCl))
+ RegisterInternalNaClPlugin(RenderProcess::LaunchNaClProcess);
+#endif
+
+ if (!command_line.HasSwitch(switches::kDisableByteRangeSupport)) {
+ webkit_glue::SetMediaCacheEnabled(true);
+ }
+
+#if defined(OS_MACOSX)
+ FilePath bundle_path = mac_util::MainAppBundlePath();
+
+ initialized_media_library_ =
+ media::InitializeMediaLibrary(bundle_path.Append("Libraries"));
+#else
+ FilePath module_path;
+ initialized_media_library_ =
+ PathService::Get(base::DIR_MODULE, &module_path) &&
+ media::InitializeMediaLibrary(module_path);
+
+ // TODO(hclam): Add more checks here. Currently this is not used.
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableOpenMax)) {
+ media::InitializeOpenMaxLibrary(module_path);
+ }
+#endif
+}
+
+RenderProcess::~RenderProcess() {
+ // TODO(port): Try and limit what we pull in for our non-Win unit test bundle.
+#ifndef NDEBUG
+ // log important leaked objects
+ webkit_glue::CheckForLeaks();
+#endif
+
+ GetShutDownEvent()->Signal();
+ ClearTransportDIBCache();
+}
+
+bool RenderProcess::InProcessPlugins() {
+ const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+#if defined(OS_LINUX)
+ // Plugin processes require a UI message loop, and the Linux message loop
+ // implementation only allows one UI loop per process.
+ if (command_line.HasSwitch(switches::kInProcessPlugins))
+ NOTIMPLEMENTED() << ": in process plugins not supported on Linux";
+ return command_line.HasSwitch(switches::kInProcessPlugins);
+#else
+ return command_line.HasSwitch(switches::kInProcessPlugins) ||
+ command_line.HasSwitch(switches::kSingleProcess);
+#endif
+}
+
+bool RenderProcess::LaunchNaClProcess(const char* url,
+ int imc_fd,
+ nacl::Handle* imc_handle,
+ nacl::Handle* nacl_process_handle,
+ int* nacl_process_id) {
+ // TODO(gregoryd): nacl::FileDescriptor will be soon merged with
+ // base::FileDescriptor
+ nacl::FileDescriptor imc_descriptor;
+ base::ProcessHandle nacl_process;
+ if (!RenderThread::current()->Send(
+ new ViewHostMsg_LaunchNaCl(ASCIIToWide(url),
+ imc_fd,
+ &imc_descriptor,
+ &nacl_process,
+ reinterpret_cast<base::ProcessId*>(nacl_process_id)))) {
+ return false;
+ }
+ *imc_handle = nacl::ToNativeHandle(imc_descriptor);
+ *nacl_process_handle = nacl_process;
+ return true;
+}
+
+// -----------------------------------------------------------------------------
+// Platform specific code for dealing with bitmap transport...
+
+TransportDIB* RenderProcess::CreateTransportDIB(size_t size) {
+#if defined(OS_WIN) || defined(OS_LINUX)
+ // Windows and Linux create transport DIBs inside the renderer
+ return TransportDIB::Create(size, sequence_number_++);
+#elif defined(OS_MACOSX) // defined(OS_WIN) || defined(OS_LINUX)
+ // Mac creates transport DIBs in the browser, so we need to do a sync IPC to
+ // get one.
+ TransportDIB::Handle handle;
+ IPC::Message* msg = new ViewHostMsg_AllocTransportDIB(size, &handle);
+ if (!main_thread()->Send(msg))
+ return NULL;
+ if (handle.fd < 0)
+ return NULL;
+ return TransportDIB::Map(handle);
+#endif // defined(OS_MACOSX)
+}
+
+void RenderProcess::FreeTransportDIB(TransportDIB* dib) {
+ if (!dib)
+ return;
+
+#if defined(OS_MACOSX)
+ // On Mac we need to tell the browser that it can drop a reference to the
+ // shared memory.
+ IPC::Message* msg = new ViewHostMsg_FreeTransportDIB(dib->id());
+ main_thread()->Send(msg);
+#endif
+
+ delete dib;
+}
+
+// -----------------------------------------------------------------------------
+
+
+skia::PlatformCanvas* RenderProcess::GetDrawingCanvas(
+ TransportDIB** memory, const gfx::Rect& rect) {
+ int width = rect.width();
+ int height = rect.height();
+ const size_t stride = skia::PlatformCanvas::StrideForWidth(rect.width());
+#if defined(OS_LINUX)
+ const size_t max_size = base::SysInfo::MaxSharedMemorySize();
+#else
+ const size_t max_size = 0;
+#endif
+
+ // If the requested size is too big, reduce the height. Ideally we might like
+ // to reduce the width as well to make the size reduction more "balanced", but
+ // it rarely comes up in practice.
+ if ((max_size != 0) && (height * stride > max_size))
+ height = max_size / stride;
+
+ const size_t size = height * stride;
+
+ if (!GetTransportDIBFromCache(memory, size)) {
+ *memory = CreateTransportDIB(size);
+ if (!*memory)
+ return false;
+ }
+
+ return (*memory)->GetPlatformCanvas(width, height);
+}
+
+void RenderProcess::ReleaseTransportDIB(TransportDIB* mem) {
+ if (PutSharedMemInCache(mem)) {
+ shared_mem_cache_cleaner_.Reset();
+ return;
+ }
+
+ FreeTransportDIB(mem);
+}
+
+bool RenderProcess::GetTransportDIBFromCache(TransportDIB** mem,
+ size_t size) {
+ // look for a cached object that is suitable for the requested size.
+ for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i) {
+ if (shared_mem_cache_[i] &&
+ size <= shared_mem_cache_[i]->size()) {
+ *mem = shared_mem_cache_[i];
+ shared_mem_cache_[i] = NULL;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+int RenderProcess::FindFreeCacheSlot(size_t size) {
+ // simple algorithm:
+ // - look for an empty slot to store mem, or
+ // - if full, then replace smallest entry which is smaller than |size|
+ for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i) {
+ if (shared_mem_cache_[i] == NULL)
+ return i;
+ }
+
+ size_t smallest_size = size;
+ int smallest_index = -1;
+
+ for (size_t i = 1; i < arraysize(shared_mem_cache_); ++i) {
+ const size_t entry_size = shared_mem_cache_[i]->size();
+ if (entry_size < smallest_size) {
+ smallest_size = entry_size;
+ smallest_index = i;
+ }
+ }
+
+ if (smallest_index != -1) {
+ FreeTransportDIB(shared_mem_cache_[smallest_index]);
+ shared_mem_cache_[smallest_index] = NULL;
+ }
+
+ return smallest_index;
+}
+
+bool RenderProcess::PutSharedMemInCache(TransportDIB* mem) {
+ const int slot = FindFreeCacheSlot(mem->size());
+ if (slot == -1)
+ return false;
+
+ shared_mem_cache_[slot] = mem;
+ return true;
+}
+
+void RenderProcess::ClearTransportDIBCache() {
+ for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i) {
+ if (shared_mem_cache_[i]) {
+ FreeTransportDIB(shared_mem_cache_[i]);
+ shared_mem_cache_[i] = NULL;
+ }
+ }
+}