summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-18 17:30:35 +0000
committerjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-18 17:30:35 +0000
commitbf2ecb42b2821b9609ce5736d8218c730011d7db (patch)
treede6abdf6c894199554631b9ca75405b026198588 /content
parent253b073edfdab221f0c71caf5c92759705d04170 (diff)
downloadchromium_src-bf2ecb42b2821b9609ce5736d8218c730011d7db.zip
chromium_src-bf2ecb42b2821b9609ce5736d8218c730011d7db.tar.gz
chromium_src-bf2ecb42b2821b9609ce5736d8218c730011d7db.tar.bz2
Move renderer_main and renderer_glue to content.
Review URL: http://codereview.chromium.org/6878002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@81962 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r--content/common/content_counters.cc35
-rw-r--r--content/common/content_counters.h30
-rw-r--r--content/common/content_switches.cc21
-rw-r--r--content/common/content_switches.h6
-rw-r--r--content/content_common.gypi2
-rw-r--r--content/content_renderer.gypi7
-rw-r--r--content/renderer/DEPS1
-rw-r--r--content/renderer/renderer_glue.cc267
-rw-r--r--content/renderer/renderer_main.cc364
-rw-r--r--content/renderer/renderer_main_platform_delegate.h40
-rw-r--r--content/renderer/renderer_main_platform_delegate_linux.cc52
-rw-r--r--content/renderer/renderer_main_platform_delegate_mac.mm58
-rw-r--r--content/renderer/renderer_main_platform_delegate_win.cc140
13 files changed, 1023 insertions, 0 deletions
diff --git a/content/common/content_counters.cc b/content/common/content_counters.cc
new file mode 100644
index 0000000..1718568
--- /dev/null
+++ b/content/common/content_counters.cc
@@ -0,0 +1,35 @@
+// Copyright (c) 2011 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 "content/common/content_counters.h"
+
+#include "base/metrics/stats_counters.h"
+
+namespace content {
+
+using base::StatsCounterTimer;
+using base::StatsRate;
+
+// Note: We use the construct-on-first-use pattern here, because we don't
+// want to fight with any static initializer ordering problems later.
+// The downside of this is that the objects don't ever get cleaned up.
+// But they are small and this is okay.
+
+// Note: Because these are constructed on-first-use, there is a slight
+// race condition - two threads could initialize the same counter.
+// If this happened, the stats table would still work just fine;
+// we'd leak the extraneous StatsCounter object once, and that
+// would be it. But these are small objects, so this is ok.
+
+StatsCounterTimer& Counters::chrome_main() {
+ static StatsCounterTimer* ctr = new StatsCounterTimer("Chrome.Init");
+ return *ctr;
+}
+
+StatsCounterTimer& Counters::renderer_main() {
+ static StatsCounterTimer* ctr = new StatsCounterTimer("Chrome.RendererInit");
+ return *ctr;
+}
+
+} // namespace content
diff --git a/content/common/content_counters.h b/content/common/content_counters.h
new file mode 100644
index 0000000..16dc638
--- /dev/null
+++ b/content/common/content_counters.h
@@ -0,0 +1,30 @@
+// Copyright (c) 2011 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.
+
+// Counters used within the browser.
+
+#ifndef CONTENT_COMMON_CONTENT_COUNTERS_H_
+#define CONTENT_COMMON_CONTENT_COUNTERS_H_
+#pragma once
+
+namespace base {
+class StatsCounter;
+class StatsCounterTimer;
+class StatsRate;
+}
+
+namespace content {
+
+class Counters {
+ public:
+ // The amount of time spent in chrome initialization.
+ static base::StatsCounterTimer& chrome_main();
+
+ // The amount of time spent in renderer initialization.
+ static base::StatsCounterTimer& renderer_main();
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_CONTENT_COUNTERS_H_
diff --git a/content/common/content_switches.cc b/content/common/content_switches.cc
index 9e64cb7..b6e64e6 100644
--- a/content/common/content_switches.cc
+++ b/content/common/content_switches.cc
@@ -182,6 +182,18 @@ const char kExtraPluginDir[] = "extra-plugin-dir";
// Causes the process to run as an extension subprocess.
const char kExtensionProcess[] = "extension";
+// Some field tests may rendomized in the browser, and the randomly selected
+// outcome needs to be propagated to the renderer. For instance, this is used
+// to modify histograms recorded in the renderer, or to get the renderer to
+// also set of its state (initialize, or not initialize components) to match the
+// experiment(s).
+// The argument is a string-ized list of experiment names, and the associated
+// value that was randomly selected. In the recent implementetaion, the
+// persistent representation generated by field_trial.cc and later decoded, is a
+// list of name and value pairs, separated by slashes. See field trial.cc for
+// current details.
+const char kForceFieldTestNameAndValue[] = "force-fieldtest";
+
// Extra command line options for launching the GPU process (normally used
// for debugging). Use like renderer-cmd-prefix.
const char kGpuLauncher[] = "gpu-launcher";
@@ -302,6 +314,9 @@ const char kProfileImportProcess[] = "profile-import";
// Register Pepper plugins (see pepper_plugin_registry.cc for its format).
const char kRegisterPepperPlugins[] = "register-pepper-plugins";
+// Causes the renderer process to throw an assertion on launch.
+const char kRendererAssertTest[] = "renderer-assert-test";
+
// On POSIX only: the contents of this flag are prepended to the renderer
// command line. Useful values might be "valgrind" or "xterm -e gdb --args".
const char kRendererCmdPrefix[] = "renderer-cmd-prefix";
@@ -380,4 +395,10 @@ const char kZygoteCmdPrefix[] = "zygote-cmd-prefix";
// Causes the process to run as a renderer zygote.
const char kZygoteProcess[] = "zygote";
+
+#if !defined(OFFICIAL_BUILD)
+// Causes the renderer process to throw an assertion on launch.
+const char kRendererCheckFalseTest[] = "renderer-check-false-test";
+#endif
+
} // namespace switches
diff --git a/content/common/content_switches.h b/content/common/content_switches.h
index 761b35b..f5b756c 100644
--- a/content/common/content_switches.h
+++ b/content/common/content_switches.h
@@ -62,6 +62,7 @@ extern const char kExperimentalLocationFeatures[];
// TODO(jam): this doesn't belong in content.
extern const char kExtensionProcess[];
extern const char kExtraPluginDir[];
+extern const char kForceFieldTestNameAndValue[];
extern const char kGpuLauncher[];
extern const char kGpuProcess[];
extern const char kGpuStartupDialog[];
@@ -97,6 +98,7 @@ extern const char kProcessType[];
extern const char kProfileImportProcess[];
extern const char kRecordMode[];
extern const char kRegisterPepperPlugins[];
+extern const char kRendererAssertTest[];
extern const char kRendererCmdPrefix[];
extern const char kRendererCrashTest[];
extern const char kRendererProcess[];
@@ -121,6 +123,10 @@ extern const char kWorkerProcess[];
extern const char kZygoteCmdPrefix[];
extern const char kZygoteProcess[];
+#if !defined(OFFICIAL_BUILD)
+extern const char kRendererCheckFalseTest[];
+#endif
+
} // namespace switches
#endif // CONTENT_COMMON_CONTENT_SWITCHES_H_
diff --git a/content/content_common.gypi b/content/content_common.gypi
index 6a427c6..743b74a 100644
--- a/content/content_common.gypi
+++ b/content/content_common.gypi
@@ -54,6 +54,8 @@
'common/content_client.h',
'common/content_constants.cc',
'common/content_constants.h',
+ 'common/content_counters.cc',
+ 'common/content_counters.h',
'common/content_paths.cc',
'common/content_paths.h',
'common/content_switches.cc',
diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi
index 4eff5e7..dcc304e 100644
--- a/content/content_renderer.gypi
+++ b/content/content_renderer.gypi
@@ -15,6 +15,7 @@
'../skia/skia.gyp:skia',
'../third_party/ffmpeg/ffmpeg.gyp:ffmpeg',
'../third_party/icu/icu.gyp:icuuc',
+ '../third_party/icu/icu.gyp:icui18n',
'../third_party/libjingle/libjingle.gyp:libjingle',
'../third_party/libjingle/libjingle.gyp:libjingle_p2p',
'../third_party/npapi/npapi.gyp:npapi',
@@ -105,6 +106,12 @@
'renderer/render_widget_fullscreen_pepper.h',
'renderer/renderer_gl_context.cc',
'renderer/renderer_gl_context.h',
+ 'renderer/renderer_glue.cc',
+ 'renderer/renderer_main.cc',
+ 'renderer/renderer_main_platform_delegate.h',
+ 'renderer/renderer_main_platform_delegate_linux.cc',
+ 'renderer/renderer_main_platform_delegate_mac.mm',
+ 'renderer/renderer_main_platform_delegate_win.cc',
'renderer/renderer_sandbox_support_linux.cc',
'renderer/renderer_sandbox_support_linux.h',
'renderer/renderer_webapplicationcachehost_impl.cc',
diff --git a/content/renderer/DEPS b/content/renderer/DEPS
index 378d848..730495c 100644
--- a/content/renderer/DEPS
+++ b/content/renderer/DEPS
@@ -7,6 +7,7 @@ include_rules = [
"-chrome/renderer/spellchecker",
"+content/plugin", # For shared npruntime proxying code.
+ "+third_party/mach_override",
"+third_party/tcmalloc",
"+v8/include",
]
diff --git a/content/renderer/renderer_glue.cc b/content/renderer/renderer_glue.cc
new file mode 100644
index 0000000..58ec602
--- /dev/null
+++ b/content/renderer/renderer_glue.cc
@@ -0,0 +1,267 @@
+// Copyright (c) 2011 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.
+
+// This file provides the embedder's side of random webkit glue functions.
+
+#include "build/build_config.h"
+
+#if defined(OS_WIN)
+#include <windows.h>
+#endif
+
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/memory/ref_counted.h"
+#include "base/string_util.h"
+#include "chrome/common/url_constants.h"
+#include "content/common/clipboard_messages.h"
+#include "content/common/content_switches.h"
+#include "content/common/socket_stream_dispatcher.h"
+#include "content/common/view_messages.h"
+#include "content/plugin/npobject_util.h"
+#include "content/renderer/render_thread.h"
+#include "googleurl/src/url_util.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebKit.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebKitClient.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/clipboard/clipboard.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "webkit/glue/scoped_clipboard_writer_glue.h"
+#include "webkit/glue/webkit_glue.h"
+#include "webkit/glue/websocketstreamhandle_bridge.h"
+
+#if defined(OS_LINUX)
+#include "content/renderer/renderer_sandbox_support_linux.h"
+#endif
+
+// This definition of WriteBitmapFromPixels uses shared memory to communicate
+// across processes.
+void ScopedClipboardWriterGlue::WriteBitmapFromPixels(const void* pixels,
+ const gfx::Size& size) {
+ // Do not try to write a bitmap more than once
+ if (shared_buf_)
+ return;
+
+ uint32 buf_size = 4 * size.width() * size.height();
+
+ // Allocate a shared memory buffer to hold the bitmap bits.
+#if defined(OS_POSIX)
+ // On POSIX, we need to ask the browser to create the shared memory for us,
+ // since this is blocked by the sandbox.
+ base::SharedMemoryHandle shared_mem_handle;
+ ViewHostMsg_AllocateSharedMemoryBuffer *msg =
+ new ViewHostMsg_AllocateSharedMemoryBuffer(buf_size,
+ &shared_mem_handle);
+ if (RenderThread::current()->Send(msg)) {
+ if (base::SharedMemory::IsHandleValid(shared_mem_handle)) {
+ shared_buf_ = new base::SharedMemory(shared_mem_handle, false);
+ if (!shared_buf_ || !shared_buf_->Map(buf_size)) {
+ NOTREACHED() << "Map failed";
+ return;
+ }
+ } else {
+ NOTREACHED() << "Browser failed to allocate shared memory";
+ return;
+ }
+ } else {
+ NOTREACHED() << "Browser allocation request message failed";
+ return;
+ }
+#else // !OS_POSIX
+ shared_buf_ = new base::SharedMemory;
+ if (!shared_buf_->CreateAndMapAnonymous(buf_size)) {
+ NOTREACHED();
+ return;
+ }
+#endif
+
+ // Copy the bits into shared memory
+ memcpy(shared_buf_->memory(), pixels, buf_size);
+ shared_buf_->Unmap();
+
+ ui::Clipboard::ObjectMapParam size_param;
+ const char* size_data = reinterpret_cast<const char*>(&size);
+ for (size_t i = 0; i < sizeof(gfx::Size); ++i)
+ size_param.push_back(size_data[i]);
+
+ ui::Clipboard::ObjectMapParams params;
+
+ // The first parameter is replaced on the receiving end with a pointer to
+ // a shared memory object containing the bitmap. We reserve space for it here.
+ ui::Clipboard::ObjectMapParam place_holder_param;
+ params.push_back(place_holder_param);
+ params.push_back(size_param);
+ objects_[ui::Clipboard::CBF_SMBITMAP] = params;
+}
+
+// Define a destructor that makes IPCs to flush the contents to the
+// system clipboard.
+ScopedClipboardWriterGlue::~ScopedClipboardWriterGlue() {
+ if (objects_.empty())
+ return;
+
+ if (shared_buf_) {
+ RenderThread::current()->Send(
+ new ClipboardHostMsg_WriteObjectsSync(objects_,
+ shared_buf_->handle()));
+ delete shared_buf_;
+ return;
+ }
+
+ RenderThread::current()->Send(
+ new ClipboardHostMsg_WriteObjectsAsync(objects_));
+}
+
+namespace webkit_glue {
+
+void AppendToLog(const char* file, int line, const char* msg) {
+ logging::LogMessage(file, line).stream() << msg;
+}
+
+base::StringPiece GetDataResource(int resource_id) {
+ return ResourceBundle::GetSharedInstance().GetRawDataResource(resource_id);
+}
+
+#if defined(OS_WIN)
+HCURSOR LoadCursor(int cursor_id) {
+ return ResourceBundle::GetSharedInstance().LoadCursor(cursor_id);
+}
+#endif
+
+// Clipboard glue
+
+ui::Clipboard* ClipboardGetClipboard() {
+ return NULL;
+}
+
+bool ClipboardIsFormatAvailable(const ui::Clipboard::FormatType& format,
+ ui::Clipboard::Buffer buffer) {
+ bool result;
+ RenderThread::current()->Send(
+ new ClipboardHostMsg_IsFormatAvailable(format, buffer, &result));
+ return result;
+}
+
+void ClipboardReadAvailableTypes(ui::Clipboard::Buffer buffer,
+ std::vector<string16>* types,
+ bool* contains_filenames) {
+ RenderThread::current()->Send(new ClipboardHostMsg_ReadAvailableTypes(
+ buffer, types, contains_filenames));
+}
+
+void ClipboardReadText(ui::Clipboard::Buffer buffer, string16* result) {
+ RenderThread::current()->Send(new ClipboardHostMsg_ReadText(buffer, result));
+}
+
+void ClipboardReadAsciiText(ui::Clipboard::Buffer buffer, std::string* result) {
+ RenderThread::current()->Send(
+ new ClipboardHostMsg_ReadAsciiText(buffer, result));
+}
+
+void ClipboardReadHTML(ui::Clipboard::Buffer buffer, string16* markup,
+ GURL* url) {
+ RenderThread::current()->Send(
+ new ClipboardHostMsg_ReadHTML(buffer, markup, url));
+}
+
+void ClipboardReadImage(ui::Clipboard::Buffer buffer, std::string* data) {
+ RenderThread::current()->Send(new ClipboardHostMsg_ReadImage(buffer, data));
+}
+
+bool ClipboardReadData(ui::Clipboard::Buffer buffer, const string16& type,
+ string16* data, string16* metadata) {
+ bool result = false;
+ RenderThread::current()->Send(new ClipboardHostMsg_ReadData(
+ buffer, type, &result, data, metadata));
+ return result;
+}
+
+bool ClipboardReadFilenames(ui::Clipboard::Buffer buffer,
+ std::vector<string16>* filenames) {
+ bool result;
+ RenderThread::current()->Send(new ClipboardHostMsg_ReadFilenames(
+ buffer, &result, filenames));
+ return result;
+}
+
+void GetPlugins(bool refresh,
+ std::vector<webkit::npapi::WebPluginInfo>* plugins) {
+ if (!RenderThread::current()->plugin_refresh_allowed())
+ refresh = false;
+ RenderThread::current()->Send(new ViewHostMsg_GetPlugins(refresh, plugins));
+}
+
+bool IsProtocolSupportedForMedia(const GURL& url) {
+ // If new protocol is to be added here, we need to make sure the response is
+ // validated accordingly in the media engine.
+ if (url.SchemeIsFile() || url.SchemeIs(chrome::kHttpScheme) ||
+ url.SchemeIs(chrome::kHttpsScheme) ||
+ url.SchemeIs(chrome::kDataScheme) ||
+ url.SchemeIs(chrome::kExtensionScheme) ||
+ url.SchemeIs(chrome::kFileSystemScheme) ||
+ url.SchemeIs(chrome::kBlobScheme))
+ return true;
+ return false;
+}
+
+// static factory function
+ResourceLoaderBridge* ResourceLoaderBridge::Create(
+ const ResourceLoaderBridge::RequestInfo& request_info) {
+ return ChildThread::current()->CreateBridge(request_info);
+}
+
+// static factory function
+WebSocketStreamHandleBridge* WebSocketStreamHandleBridge::Create(
+ WebKit::WebSocketStreamHandle* handle,
+ WebSocketStreamHandleDelegate* delegate) {
+ SocketStreamDispatcher* dispatcher =
+ ChildThread::current()->socket_stream_dispatcher();
+ return dispatcher->CreateBridge(handle, delegate);
+}
+
+void CloseCurrentConnections() {
+ RenderThread::current()->CloseCurrentConnections();
+}
+
+void SetCacheMode(bool enabled) {
+ RenderThread::current()->SetCacheMode(enabled);
+}
+
+void ClearCache(bool preserve_ssl_host_info) {
+ RenderThread::current()->ClearCache(preserve_ssl_host_info);
+}
+
+void ClearHostResolverCache() {
+ RenderThread::current()->ClearHostResolverCache();
+}
+
+void ClearPredictorCache() {
+ RenderThread::current()->ClearPredictorCache();
+}
+
+bool IsSingleProcess() {
+ return CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess);
+}
+
+void EnableSpdy(bool enable) {
+ RenderThread::current()->EnableSpdy(enable);
+}
+
+#if defined(OS_LINUX)
+int MatchFontWithFallback(const std::string& face, bool bold,
+ bool italic, int charset) {
+ return renderer_sandbox_support::MatchFontWithFallback(
+ face, bold, italic, charset);
+}
+
+bool GetFontTable(int fd, uint32_t table, uint8_t* output,
+ size_t* output_length) {
+ return renderer_sandbox_support::GetFontTable(
+ fd, table, output, output_length);
+}
+#endif
+
+} // namespace webkit_glue
diff --git a/content/renderer/renderer_main.cc b/content/renderer/renderer_main.cc
new file mode 100644
index 0000000..f6dc81b
--- /dev/null
+++ b/content/renderer/renderer_main.cc
@@ -0,0 +1,364 @@
+// Copyright (c) 2011 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.
+
+#if defined(OS_MACOSX)
+#include <signal.h>
+#include <unistd.h>
+#endif // OS_MACOSX
+
+#include "base/command_line.h"
+#include "base/debug/trace_event.h"
+#include "base/i18n/rtl.h"
+#include "base/mac/scoped_nsautorelease_pool.h"
+#include "base/memory/ref_counted.h"
+#include "base/metrics/field_trial.h"
+#include "base/message_loop.h"
+#include "base/metrics/histogram.h"
+#include "base/metrics/stats_counters.h"
+#include "base/path_service.h"
+#include "base/process_util.h"
+#include "base/string_util.h"
+#include "base/threading/platform_thread.h"
+#include "base/time.h"
+#include "content/common/content_counters.h"
+#include "content/common/content_switches.h"
+#include "content/common/main_function_params.h"
+#include "content/common/hi_res_timer_manager.h"
+#include "content/common/pepper_plugin_registry.h"
+#include "content/renderer/render_process_impl.h"
+#include "content/renderer/render_thread.h"
+#include "content/renderer/renderer_main_platform_delegate.h"
+#include "ui/base/system_monitor/system_monitor.h"
+#include "ui/base/ui_base_switches.h"
+
+#if defined(OS_MACOSX)
+#include <Carbon/Carbon.h> // TISCreateInputSourceList
+
+#include "base/eintr_wrapper.h"
+#include "base/sys_info.h"
+#include "chrome/app/breakpad_mac.h"
+#include "third_party/mach_override/mach_override.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
+#endif // OS_MACOSX
+
+#if defined(OS_MACOSX)
+namespace {
+
+CFArrayRef ChromeTISCreateInputSourceList(
+ CFDictionaryRef properties,
+ Boolean includeAllInstalled) {
+ CFTypeRef values[] = { CFSTR("") };
+ return CFArrayCreate(
+ kCFAllocatorDefault, values, arraysize(values), &kCFTypeArrayCallBacks);
+}
+
+void InstallFrameworkHacks() {
+ int32 os_major, os_minor, os_bugfix;
+ base::SysInfo::OperatingSystemVersionNumbers(
+ &os_major, &os_minor, &os_bugfix);
+
+ // See http://crbug.com/31225
+ // TODO: Don't do this on newer OS X revisions that have a fix for
+ // http://openradar.appspot.com/radar?id=1156410
+ if (os_major == 10 && os_minor >= 6) {
+ // Chinese Handwriting was introduced in 10.6. Since doing this override
+ // regresses page cycler memory usage on 10.5, don't do the unnecessary
+ // override there.
+ mach_error_t err = mach_override_ptr(
+ (void*)&TISCreateInputSourceList,
+ (void*)&ChromeTISCreateInputSourceList,
+ NULL);
+ CHECK_EQ(err_none, err);
+ }
+}
+
+// TODO(viettrungluu): crbug.com/28547: The following signal handling is needed,
+// as a stopgap, to avoid leaking due to not releasing Breakpad properly.
+// Without this problem, this could all be eliminated. Remove when Breakpad is
+// fixed?
+// TODO(viettrungluu): Code taken from browser_main.cc (with a bit of editing).
+// The code should be properly shared (or this code should be eliminated).
+int g_shutdown_pipe_write_fd = -1;
+
+void SIGTERMHandler(int signal) {
+ RAW_CHECK(signal == SIGTERM);
+ RAW_LOG(INFO, "Handling SIGTERM in renderer.");
+
+ // Reinstall the default handler. We had one shot at graceful shutdown.
+ struct sigaction action;
+ memset(&action, 0, sizeof(action));
+ action.sa_handler = SIG_DFL;
+ CHECK(sigaction(signal, &action, NULL) == 0);
+
+ RAW_CHECK(g_shutdown_pipe_write_fd != -1);
+ size_t bytes_written = 0;
+ do {
+ int rv = HANDLE_EINTR(
+ write(g_shutdown_pipe_write_fd,
+ reinterpret_cast<const char*>(&signal) + bytes_written,
+ sizeof(signal) - bytes_written));
+ RAW_CHECK(rv >= 0);
+ bytes_written += rv;
+ } while (bytes_written < sizeof(signal));
+
+ RAW_LOG(INFO, "Wrote signal to shutdown pipe.");
+}
+
+class ShutdownDetector : public base::PlatformThread::Delegate {
+ public:
+ explicit ShutdownDetector(int shutdown_fd) : shutdown_fd_(shutdown_fd) {
+ CHECK(shutdown_fd_ != -1);
+ }
+
+ virtual void ThreadMain() {
+ int signal;
+ size_t bytes_read = 0;
+ ssize_t ret;
+ do {
+ ret = HANDLE_EINTR(
+ read(shutdown_fd_,
+ reinterpret_cast<char*>(&signal) + bytes_read,
+ sizeof(signal) - bytes_read));
+ if (ret < 0) {
+ NOTREACHED() << "Unexpected error: " << strerror(errno);
+ break;
+ } else if (ret == 0) {
+ NOTREACHED() << "Unexpected closure of shutdown pipe.";
+ break;
+ }
+ bytes_read += ret;
+ } while (bytes_read < sizeof(signal));
+
+ if (bytes_read == sizeof(signal))
+ VLOG(1) << "Handling shutdown for signal " << signal << ".";
+ else
+ VLOG(1) << "Handling shutdown for unknown signal.";
+
+ // Clean up Breakpad if necessary.
+ if (IsCrashReporterEnabled()) {
+ VLOG(1) << "Cleaning up Breakpad.";
+ DestructCrashReporter();
+ } else {
+ VLOG(1) << "Breakpad not enabled; no clean-up needed.";
+ }
+
+ // Something went seriously wrong, so get out.
+ if (bytes_read != sizeof(signal)) {
+ LOG(WARNING) << "Failed to get signal. Quitting ungracefully.";
+ _exit(1);
+ }
+
+ // Re-raise the signal.
+ kill(getpid(), signal);
+
+ // The signal may be handled on another thread. Give that a chance to
+ // happen.
+ sleep(3);
+
+ // We really should be dead by now. For whatever reason, we're not. Exit
+ // immediately, with the exit status set to the signal number with bit 8
+ // set. On the systems that we care about, this exit status is what is
+ // normally used to indicate an exit by this signal's default handler.
+ // This mechanism isn't a de jure standard, but even in the worst case, it
+ // should at least result in an immediate exit.
+ LOG(WARNING) << "Still here, exiting really ungracefully.";
+ _exit(signal | (1 << 7));
+ }
+
+ private:
+ const int shutdown_fd_;
+
+ DISALLOW_COPY_AND_ASSIGN(ShutdownDetector);
+};
+
+} // namespace
+#endif // OS_MACOSX
+
+// This function provides some ways to test crash and assertion handling
+// behavior of the renderer.
+static void HandleRendererErrorTestParameters(const CommandLine& command_line) {
+ // This parameter causes an assertion.
+ if (command_line.HasSwitch(switches::kRendererAssertTest)) {
+ DCHECK(false);
+ }
+
+
+#if !defined(OFFICIAL_BUILD)
+ // This parameter causes an assertion too.
+ if (command_line.HasSwitch(switches::kRendererCheckFalseTest)) {
+ CHECK(false);
+ }
+#endif // !defined(OFFICIAL_BUILD)
+
+
+ // This parameter causes a null pointer crash (crash reporter trigger).
+ if (command_line.HasSwitch(switches::kRendererCrashTest)) {
+ int* bad_pointer = NULL;
+ *bad_pointer = 0;
+ }
+
+ if (command_line.HasSwitch(switches::kRendererStartupDialog)) {
+ ChildProcess::WaitForDebugger("Renderer");
+ }
+}
+
+// This is a simplified version of the browser Jankometer, which measures
+// the processing time of tasks on the render thread.
+class RendererMessageLoopObserver : public MessageLoop::TaskObserver {
+ public:
+ RendererMessageLoopObserver()
+ : process_times_(base::Histogram::FactoryGet(
+ "Chrome.ProcMsgL RenderThread",
+ 1, 3600000, 50, base::Histogram::kUmaTargetedHistogramFlag)) {}
+ virtual ~RendererMessageLoopObserver() {}
+
+ virtual void WillProcessTask(const Task* task) {
+ begin_process_message_ = base::TimeTicks::Now();
+ }
+
+ virtual void DidProcessTask(const Task* task) {
+ if (begin_process_message_ != base::TimeTicks())
+ process_times_->AddTime(base::TimeTicks::Now() - begin_process_message_);
+ }
+
+ private:
+ base::TimeTicks begin_process_message_;
+ base::Histogram* const process_times_;
+ DISALLOW_COPY_AND_ASSIGN(RendererMessageLoopObserver);
+};
+
+// mainline routine for running as the Renderer process
+int RendererMain(const MainFunctionParams& parameters) {
+ TRACE_EVENT_BEGIN("RendererMain", 0, "");
+
+ const CommandLine& parsed_command_line = parameters.command_line_;
+ base::mac::ScopedNSAutoreleasePool* pool = parameters.autorelease_pool_;
+
+#if defined(OS_MACOSX)
+ // TODO(viettrungluu): Code taken from browser_main.cc.
+ int pipefd[2];
+ int ret = pipe(pipefd);
+ if (ret < 0) {
+ PLOG(DFATAL) << "Failed to create pipe";
+ } else {
+ int shutdown_pipe_read_fd = pipefd[0];
+ g_shutdown_pipe_write_fd = pipefd[1];
+ const size_t kShutdownDetectorThreadStackSize = 4096;
+ if (!base::PlatformThread::CreateNonJoinable(
+ kShutdownDetectorThreadStackSize,
+ new ShutdownDetector(shutdown_pipe_read_fd))) {
+ LOG(DFATAL) << "Failed to create shutdown detector task.";
+ }
+ }
+
+ // crbug.com/28547: When Breakpad is in use, handle SIGTERM to avoid leaking
+ // Mach ports.
+ struct sigaction action;
+ memset(&action, 0, sizeof(action));
+ action.sa_handler = SIGTERMHandler;
+ CHECK(sigaction(SIGTERM, &action, NULL) == 0);
+
+ InstallFrameworkHacks();
+#endif // OS_MACOSX
+
+#if defined(OS_CHROMEOS)
+ // As Zygote process starts up earlier than browser process gets its own
+ // locale (at login time for Chrome OS), we have to set the ICU default
+ // locale for renderer process here.
+ // ICU locale will be used for fallback font selection etc.
+ if (parsed_command_line.HasSwitch(switches::kLang)) {
+ const std::string locale =
+ parsed_command_line.GetSwitchValueASCII(switches::kLang);
+ base::i18n::SetICUDefaultLocale(locale);
+ }
+#endif
+
+ // This function allows pausing execution using the --renderer-startup-dialog
+ // flag allowing us to attach a debugger.
+ // Do not move this function down since that would mean we can't easily debug
+ // whatever occurs before it.
+ HandleRendererErrorTestParameters(parsed_command_line);
+
+ RendererMainPlatformDelegate platform(parameters);
+
+ base::StatsScope<base::StatsCounterTimer>
+ startup_timer(content::Counters::renderer_main());
+
+ RendererMessageLoopObserver task_observer;
+#if defined(OS_MACOSX)
+ // As long as we use Cocoa in the renderer (for the forseeable future as of
+ // now; see http://crbug.com/13890 for info) we need to have a UI loop.
+ MessageLoop main_message_loop(MessageLoop::TYPE_UI);
+#else
+ // The main message loop of the renderer services doesn't have IO or UI tasks,
+ // unless in-process-plugins is used.
+ MessageLoop main_message_loop(RenderProcessImpl::InProcessPlugins() ?
+ MessageLoop::TYPE_UI : MessageLoop::TYPE_DEFAULT);
+#endif
+ main_message_loop.AddTaskObserver(&task_observer);
+
+ base::PlatformThread::SetName("CrRendererMain");
+
+ ui::SystemMonitor system_monitor;
+ HighResolutionTimerManager hi_res_timer_manager;
+
+ platform.PlatformInitialize();
+
+ bool no_sandbox = parsed_command_line.HasSwitch(switches::kNoSandbox);
+ platform.InitSandboxTests(no_sandbox);
+
+ // Initialize histogram statistics gathering system.
+ // Don't create StatisticsRecorder in the single process mode.
+ scoped_ptr<base::StatisticsRecorder> statistics;
+ if (!base::StatisticsRecorder::IsActive()) {
+ statistics.reset(new base::StatisticsRecorder());
+ }
+
+ // Initialize statistical testing infrastructure.
+ base::FieldTrialList field_trial;
+ // Ensure any field trials in browser are reflected into renderer.
+ if (parsed_command_line.HasSwitch(switches::kForceFieldTestNameAndValue)) {
+ std::string persistent = parsed_command_line.GetSwitchValueASCII(
+ switches::kForceFieldTestNameAndValue);
+ bool ret = field_trial.CreateTrialsInChildProcess(persistent);
+ DCHECK(ret);
+ }
+
+ // Load pepper plugins before engaging the sandbox.
+ PepperPluginRegistry::GetInstance();
+
+ {
+#if !defined(OS_LINUX)
+ // TODO(markus): Check if it is OK to unconditionally move this
+ // instruction down.
+ RenderProcessImpl render_process;
+ render_process.set_main_thread(new RenderThread());
+#endif
+ bool run_loop = true;
+ if (!no_sandbox) {
+ run_loop = platform.EnableSandbox();
+ } else {
+ LOG(ERROR) << "Running without renderer sandbox";
+ }
+#if defined(OS_LINUX)
+ RenderProcessImpl render_process;
+ render_process.set_main_thread(new RenderThread());
+#endif
+
+ platform.RunSandboxTests();
+
+ startup_timer.Stop(); // End of Startup Time Measurement.
+
+ if (run_loop) {
+ if (pool)
+ pool->Recycle();
+ TRACE_EVENT_BEGIN("RendererMain.START_MSG_LOOP", 0, 0);
+ MessageLoop::current()->Run();
+ TRACE_EVENT_END("RendererMain.START_MSG_LOOP", 0, 0);
+ }
+ }
+ platform.PlatformUninitialize();
+ TRACE_EVENT_END("RendererMain", 0, "");
+ return 0;
+}
diff --git a/content/renderer/renderer_main_platform_delegate.h b/content/renderer/renderer_main_platform_delegate.h
new file mode 100644
index 0000000..c57e90e
--- /dev/null
+++ b/content/renderer/renderer_main_platform_delegate.h
@@ -0,0 +1,40 @@
+// Copyright (c) 2009 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.
+
+#ifndef CHROME_RENDERER_RENDERER_MAIN_PLATFORM_DELEGATE_H_
+#define CHROME_RENDERER_RENDERER_MAIN_PLATFORM_DELEGATE_H_
+#pragma once
+
+#include "content/common/main_function_params.h"
+
+class RendererMainPlatformDelegate {
+ public:
+ explicit RendererMainPlatformDelegate(const MainFunctionParams& parameters);
+ ~RendererMainPlatformDelegate();
+
+ // Called first thing and last thing in the process' lifecycle, i.e. before
+ // the sandbox is enabled.
+ void PlatformInitialize();
+ void PlatformUninitialize();
+
+ // Gives us an opportunity to initialize state used for tests before enabling
+ // the sandbox.
+ bool InitSandboxTests(bool no_sandbox);
+
+ // Initiate Lockdown, returns true on success.
+ bool EnableSandbox();
+
+ // Runs Sandbox tests.
+ void RunSandboxTests();
+
+ private:
+ const MainFunctionParams& parameters_;
+#if defined(OS_WIN)
+ HMODULE sandbox_test_module_;
+#endif
+
+ DISALLOW_COPY_AND_ASSIGN(RendererMainPlatformDelegate);
+};
+
+#endif // CHROME_RENDERER_RENDERER_MAIN_PLATFORM_DELEGATE_H_
diff --git a/content/renderer/renderer_main_platform_delegate_linux.cc b/content/renderer/renderer_main_platform_delegate_linux.cc
new file mode 100644
index 0000000..b20caf9
--- /dev/null
+++ b/content/renderer/renderer_main_platform_delegate_linux.cc
@@ -0,0 +1,52 @@
+// Copyright (c) 2009 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 "content/renderer/renderer_main_platform_delegate.h"
+
+#include "base/command_line.h"
+#include "content/common/content_switches.h"
+#include "seccompsandbox/sandbox.h"
+
+RendererMainPlatformDelegate::RendererMainPlatformDelegate(
+ const MainFunctionParams& parameters)
+ : parameters_(parameters) {
+}
+
+RendererMainPlatformDelegate::~RendererMainPlatformDelegate() {
+}
+
+void RendererMainPlatformDelegate::PlatformInitialize() {
+}
+
+void RendererMainPlatformDelegate::PlatformUninitialize() {
+}
+
+bool RendererMainPlatformDelegate::InitSandboxTests(bool no_sandbox) {
+ // The sandbox is started in the zygote process: zygote_main_linux.cc
+ // http://code.google.com/p/chromium/wiki/LinuxSUIDSandbox
+ return true;
+}
+
+bool RendererMainPlatformDelegate::EnableSandbox() {
+ // The setuid sandbox is started in the zygote process: zygote_main_linux.cc
+ // http://code.google.com/p/chromium/wiki/LinuxSUIDSandbox
+ //
+ // The seccomp sandbox is started in the renderer.
+ // http://code.google.com/p/seccompsandbox/
+#if defined(ARCH_CPU_X86_FAMILY) && !defined(CHROMIUM_SELINUX) && \
+ !defined(__clang__)
+ // N.b. SupportsSeccompSandbox() returns a cached result, as we already
+ // called it earlier in the zygote. Thus, it is OK for us to not pass in
+ // a file descriptor for "/proc".
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableSeccompSandbox) && SupportsSeccompSandbox(-1))
+ StartSeccompSandbox();
+#endif
+ return true;
+}
+
+void RendererMainPlatformDelegate::RunSandboxTests() {
+ // The sandbox is started in the zygote process: zygote_main_linux.cc
+ // http://code.google.com/p/chromium/wiki/LinuxSUIDSandbox
+}
diff --git a/content/renderer/renderer_main_platform_delegate_mac.mm b/content/renderer/renderer_main_platform_delegate_mac.mm
new file mode 100644
index 0000000..86edec7
--- /dev/null
+++ b/content/renderer/renderer_main_platform_delegate_mac.mm
@@ -0,0 +1,58 @@
+// Copyright (c) 2009 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 "content/renderer/renderer_main_platform_delegate.h"
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/command_line.h"
+#import "content/common/chrome_application_mac.h"
+#include "content/common/content_switches.h"
+#include "content/common/sandbox_mac.h"
+#include "third_party/WebKit/Source/WebKit/mac/WebCoreSupport/WebSystemInterface.h"
+
+RendererMainPlatformDelegate::RendererMainPlatformDelegate(
+ const MainFunctionParams& parameters)
+ : parameters_(parameters) {
+}
+
+RendererMainPlatformDelegate::~RendererMainPlatformDelegate() {
+}
+
+// TODO(mac-port): Any code needed to initialize a process for purposes of
+// running a renderer needs to also be reflected in chrome_main.cc for
+// --single-process support.
+void RendererMainPlatformDelegate::PlatformInitialize() {
+ // Initialize NSApplication using the custom subclass. Without this call,
+ // drawing of native UI elements (e.g. buttons) in WebKit will explode.
+ [CrApplication sharedApplication];
+
+ // Load WebKit system interfaces.
+ InitWebCoreSystemInterface();
+
+ if (![NSThread isMultiThreaded]) {
+ NSString* string = @"";
+ [NSThread detachNewThreadSelector:@selector(length)
+ toTarget:string
+ withObject:nil];
+ }
+}
+
+void RendererMainPlatformDelegate::PlatformUninitialize() {
+}
+
+bool RendererMainPlatformDelegate::InitSandboxTests(bool no_sandbox) {
+ return true;
+}
+
+bool RendererMainPlatformDelegate::EnableSandbox() {
+ CommandLine* parsed_command_line = CommandLine::ForCurrentProcess();
+ SandboxInitWrapper sandbox_wrapper;
+ return sandbox_wrapper.InitializeSandbox(*parsed_command_line,
+ switches::kRendererProcess);
+}
+
+void RendererMainPlatformDelegate::RunSandboxTests() {
+ // TODO(port): Run sandbox unit test here.
+}
diff --git a/content/renderer/renderer_main_platform_delegate_win.cc b/content/renderer/renderer_main_platform_delegate_win.cc
new file mode 100644
index 0000000..50a8059
--- /dev/null
+++ b/content/renderer/renderer_main_platform_delegate_win.cc
@@ -0,0 +1,140 @@
+// Copyright (c) 2011 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 "content/renderer/renderer_main_platform_delegate.h"
+
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/common/content_switches.h"
+#include "content/common/injection_test_dll.h"
+#include "sandbox/src/sandbox.h"
+#include "unicode/timezone.h"
+
+namespace {
+
+// In order to have Theme support, we need to connect to the theme service.
+// This needs to be done before we lock down the renderer. Officially this
+// can be done with OpenThemeData() but it fails unless you pass a valid
+// window at least the first time. Interestingly, the very act of creating a
+// window also sets the connection to the theme service.
+void EnableThemeSupportForRenderer(bool no_sandbox) {
+ HWINSTA current = NULL;
+ HWINSTA winsta0 = NULL;
+
+ if (!no_sandbox) {
+ current = ::GetProcessWindowStation();
+ winsta0 = ::OpenWindowStationW(L"WinSta0", FALSE, GENERIC_READ);
+ if (!winsta0 || !::SetProcessWindowStation(winsta0)) {
+ // Could not set the alternate window station. There is a possibility
+ // that the theme wont be correctly initialized on XP.
+ NOTREACHED() << "Unable to switch to WinSt0";
+ }
+ }
+
+ HWND window = ::CreateWindowExW(0, L"Static", L"", WS_POPUP | WS_DISABLED,
+ CW_USEDEFAULT, 0, 0, 0, HWND_MESSAGE, NULL,
+ ::GetModuleHandleA(NULL), NULL);
+ if (!window) {
+ DLOG(WARNING) << "failed to enable theme support";
+ } else {
+ ::DestroyWindow(window);
+ }
+
+ if (!no_sandbox) {
+ // Revert the window station.
+ if (!current || !::SetProcessWindowStation(current)) {
+ // We failed to switch back to the secure window station. This might
+ // confuse the renderer enough that we should kill it now.
+ LOG(FATAL) << "Failed to restore alternate window station";
+ }
+
+ if (!::CloseWindowStation(winsta0)) {
+ // We might be leaking a winsta0 handle. This is a security risk, but
+ // since we allow fail over to no desktop protection in low memory
+ // condition, this is not a big risk.
+ NOTREACHED();
+ }
+ }
+}
+
+} // namespace
+
+RendererMainPlatformDelegate::RendererMainPlatformDelegate(
+ const MainFunctionParams& parameters)
+ : parameters_(parameters),
+ sandbox_test_module_(NULL) {
+}
+
+RendererMainPlatformDelegate::~RendererMainPlatformDelegate() {
+}
+
+void RendererMainPlatformDelegate::PlatformInitialize() {
+ // Be mindful of what resources you acquire here. They can be used by
+ // malicious code if the renderer gets compromised.
+ const CommandLine& command_line = parameters_.command_line_;
+ bool no_sandbox = command_line.HasSwitch(switches::kNoSandbox);
+ EnableThemeSupportForRenderer(no_sandbox);
+
+ if (!no_sandbox) {
+ // ICU DateFormat class (used in base/time_format.cc) needs to get the
+ // Olson timezone ID by accessing the registry keys under
+ // HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones.
+ // After TimeZone::createDefault is called once here, the timezone ID is
+ // cached and there's no more need to access the registry. If the sandbox
+ // is disabled, we don't have to make this dummy call.
+ scoped_ptr<icu::TimeZone> zone(icu::TimeZone::createDefault());
+ }
+}
+
+void RendererMainPlatformDelegate::PlatformUninitialize() {
+}
+
+bool RendererMainPlatformDelegate::InitSandboxTests(bool no_sandbox) {
+ const CommandLine& command_line = parameters_.command_line_;
+
+ DVLOG(1) << "Started renderer with " << command_line.command_line_string();
+
+ sandbox::TargetServices* target_services =
+ parameters_.sandbox_info_.TargetServices();
+
+ if (target_services && !no_sandbox) {
+ std::wstring test_dll_name =
+ command_line.GetSwitchValueNative(switches::kTestSandbox);
+ if (!test_dll_name.empty()) {
+ sandbox_test_module_ = LoadLibrary(test_dll_name.c_str());
+ DCHECK(sandbox_test_module_);
+ if (!sandbox_test_module_) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+bool RendererMainPlatformDelegate::EnableSandbox() {
+ sandbox::TargetServices* target_services =
+ parameters_.sandbox_info_.TargetServices();
+
+ if (target_services) {
+ target_services->LowerToken();
+ return true;
+ }
+ return false;
+}
+
+void RendererMainPlatformDelegate::RunSandboxTests() {
+ if (sandbox_test_module_) {
+ RunRendererTests run_security_tests =
+ reinterpret_cast<RunRendererTests>(GetProcAddress(sandbox_test_module_,
+ kRenderTestCall));
+ DCHECK(run_security_tests);
+ if (run_security_tests) {
+ int test_count = 0;
+ DVLOG(1) << "Running renderer security tests";
+ BOOL result = run_security_tests(&test_count);
+ CHECK(result) << "Test number " << test_count << " has failed.";
+ }
+ }
+}