| Index: chrome/renderer/renderer_main.cc
|
| ===================================================================
|
| --- chrome/renderer/renderer_main.cc (revision 81952)
|
| +++ chrome/renderer/renderer_main.cc (working copy)
|
| @@ -1,372 +0,0 @@
|
| -// 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 "chrome/common/chrome_constants.h"
|
| -#include "chrome/common/chrome_counters.h"
|
| -#include "chrome/common/chrome_switches.h"
|
| -#include "chrome/common/logging_chrome.h"
|
| -#include "chrome/common/net/net_resource_provider.h"
|
| -#include "chrome/common/pepper_plugin_registry.h"
|
| -#include "chrome/renderer/renderer_main_platform_delegate.h"
|
| -#include "content/common/main_function_params.h"
|
| -#include "content/common/hi_res_timer_manager.h"
|
| -#include "content/renderer/render_process_impl.h"
|
| -#include "content/renderer/render_thread.h"
|
| -#include "grit/generated_resources.h"
|
| -#include "net/base/net_module.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
|
| -
|
| - // Configure modules that need access to resources.
|
| - net::NetModule::SetResourceProvider(chrome_common_net::NetResourceProvider);
|
| -
|
| - // 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(chrome::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;
|
| -}
|
|
|