diff options
author | phajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-06 21:15:20 +0000 |
---|---|---|
committer | phajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-06 21:15:20 +0000 |
commit | 86671a3848e4fc1059ed815a7639de33e7404a07 (patch) | |
tree | adc25bab7c8ce2f263d93c22794d40e2db2b14ae /chrome/app/chrome_main_delegate.cc | |
parent | 72e446c065067905dc3ced8c3d2f4316f5a0f457 (diff) | |
download | chromium_src-86671a3848e4fc1059ed815a7639de33e7404a07.zip chromium_src-86671a3848e4fc1059ed815a7639de33e7404a07.tar.gz chromium_src-86671a3848e4fc1059ed815a7639de33e7404a07.tar.bz2 |
GTTF: Make browser_tests self-contained on Linux.
Windows will follow very soon, just proceeding in small steps.
Previously Linux browser_tests were launching chrome binary,
and Windows called PathService::Override for no reason.
Mac is going to be _much_ harder.
BUG=none
Review URL: http://codereview.chromium.org/8178004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@104364 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/app/chrome_main_delegate.cc')
-rw-r--r-- | chrome/app/chrome_main_delegate.cc | 715 |
1 files changed, 715 insertions, 0 deletions
diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc new file mode 100644 index 0000000..73e5331 --- /dev/null +++ b/chrome/app/chrome_main_delegate.cc @@ -0,0 +1,715 @@ +// 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 "chrome/app/chrome_main_delegate.h" + +#include "base/command_line.h" +#include "base/lazy_instance.h" +#include "base/message_loop.h" +#include "base/metrics/field_trial.h" +#include "base/metrics/stats_counters.h" +#include "base/path_service.h" +#include "base/process_util.h" +#include "base/stringprintf.h" +#include "base/utf_string_conversions.h" +#include "build/build_config.h" +#include "chrome/browser/chrome_content_browser_client.h" +#include "chrome/browser/defaults.h" +#include "chrome/browser/diagnostics/diagnostics_main.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/common/chrome_content_client.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/chrome_paths_internal.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/chrome_version_info.h" +#include "chrome/common/logging_chrome.h" +#include "chrome/common/profiling.h" +#include "chrome/common/url_constants.h" +#include "chrome/plugin/chrome_content_plugin_client.h" +#include "chrome/renderer/chrome_content_renderer_client.h" +#include "chrome/utility/chrome_content_utility_client.h" +#include "content/app/content_main.h" +#include "content/app/content_main_delegate.h" +#include "content/browser/renderer_host/render_process_host.h" +#include "content/common/content_client.h" +#include "content/common/content_counters.h" +#include "content/common/content_paths.h" +#include "content/common/content_switches.h" +#include "media/base/media.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/base/ui_base_switches.h" + +#if defined(OS_WIN) +#include <algorithm> +#include <atlbase.h> +#include <malloc.h> +#include "base/string_util.h" +#include "base/win/registry.h" +#include "chrome/browser/policy/policy_path_parser.h" +#include "policy/policy_constants.h" +#include "sandbox/src/sandbox.h" +#include "tools/memory_watcher/memory_watcher.h" +#endif + +#if defined(OS_MACOSX) +#include "base/mac/mac_util.h" +#include "base/mac/os_crash_dumps.h" +#include "chrome/app/breakpad_mac.h" +#include "chrome/app/chrome_main_mac.h" +#include "chrome/browser/mac/relauncher.h" +#include "chrome/common/chrome_paths_internal.h" +#include "chrome/common/mac/cfbundle_blocker.h" +#include "chrome/common/mac/objc_zombie.h" +#include "grit/chromium_strings.h" +#include "third_party/WebKit/Source/WebKit/mac/WebCoreSupport/WebSystemInterface.h" +#include "ui/base/l10n/l10n_util_mac.h" +#endif + +#if defined(OS_POSIX) +#include <locale.h> +#include <signal.h> +#endif + +#if defined(OS_POSIX) && !defined(OS_MACOSX) +#include "chrome/common/nacl_fork_delegate_linux.h" +#endif + +#if defined(OS_CHROMEOS) +#include "base/sys_info.h" +#include "chrome/browser/chromeos/boot_times_loader.h" +#endif + +#if defined(TOOLKIT_USES_GTK) +#include <gdk/gdk.h> +#include <glib.h> +#include <gtk/gtk.h> +#endif + +#if defined(USE_X11) +#include <stdlib.h> +#include <string.h> +#include "ui/base/x/x11_util.h" +#endif + +#if defined(USE_LINUX_BREAKPAD) +#include "chrome/app/breakpad_linux.h" +#endif + +base::LazyInstance<chrome::ChromeContentBrowserClient> + g_chrome_content_browser_client(base::LINKER_INITIALIZED); +base::LazyInstance<chrome::ChromeContentRendererClient> + g_chrome_content_renderer_client(base::LINKER_INITIALIZED); +base::LazyInstance<chrome::ChromeContentUtilityClient> + g_chrome_content_utility_client(base::LINKER_INITIALIZED); +base::LazyInstance<chrome::ChromeContentPluginClient> + g_chrome_content_plugin_client(base::LINKER_INITIALIZED); + +extern int NaClMain(const MainFunctionParams&); +extern int ServiceProcessMain(const MainFunctionParams&); + +namespace { + +#if defined(OS_WIN) +const wchar_t kProfilingDll[] = L"memory_watcher.dll"; + +// Load the memory profiling DLL. All it needs to be activated +// is to be loaded. Return true on success, false otherwise. +bool LoadMemoryProfiler() { + HMODULE prof_module = LoadLibrary(kProfilingDll); + return prof_module != NULL; +} + +// Early versions of Chrome incorrectly registered a chromehtml: URL handler, +// which gives us nothing but trouble. Avoid launching chrome this way since +// some apps fail to properly escape arguments. +bool HasDeprecatedArguments(const std::wstring& command_line) { + const wchar_t kChromeHtml[] = L"chromehtml:"; + std::wstring command_line_lower = command_line; + // We are only searching for ASCII characters so this is OK. + StringToLowerASCII(&command_line_lower); + std::wstring::size_type pos = command_line_lower.find(kChromeHtml); + return (pos != std::wstring::npos); +} + +// Checks if the registry key exists in the given hive and expands any +// variables in the string. +bool LoadUserDataDirPolicyFromRegistry(HKEY hive, + const std::wstring& key_name, + FilePath* user_data_dir) { + std::wstring value; + + base::win::RegKey hklm_policy_key(hive, policy::kRegistrySubKey, KEY_READ); + if (hklm_policy_key.ReadValue(key_name.c_str(), &value) == ERROR_SUCCESS) { + *user_data_dir = FilePath(policy::path_parser::ExpandPathVariables(value)); + return true; + } + return false; +} + +void CheckUserDataDirPolicy(FilePath* user_data_dir) { + DCHECK(user_data_dir); + // We are running as Chrome Frame if we were invoked with user-data-dir, + // chrome-frame, and automation-channel switches. + CommandLine* command_line = CommandLine::ForCurrentProcess(); + const bool is_chrome_frame = + !user_data_dir->empty() && + command_line->HasSwitch(switches::kChromeFrame) && + command_line->HasSwitch(switches::kAutomationClientChannelID); + + // In the case of Chrome Frame, the last path component of the user-data-dir + // provided on the command line must be preserved since it is specific to + // CF's host. + FilePath cf_host_dir; + if (is_chrome_frame) + cf_host_dir = user_data_dir->BaseName(); + + // Policy from the HKLM hive has precedence over HKCU so if we have one here + // we don't have to try to load HKCU. + const char* key_name_ascii = (is_chrome_frame ? policy::key::kGCFUserDataDir : + policy::key::kUserDataDir); + std::wstring key_name(ASCIIToWide(key_name_ascii)); + if (LoadUserDataDirPolicyFromRegistry(HKEY_LOCAL_MACHINE, key_name, + user_data_dir) || + LoadUserDataDirPolicyFromRegistry(HKEY_CURRENT_USER, key_name, + user_data_dir)) { + // A Group Policy value was loaded. Append the Chrome Frame host directory + // if relevant. + if (is_chrome_frame) + *user_data_dir = user_data_dir->Append(cf_host_dir); + } +} + +#endif // defined(OS_WIN) + +#if defined(OS_LINUX) +static void AdjustLinuxOOMScore(const std::string& process_type) { + // Browsers and zygotes should still be killable, but killed last. + const int kZygoteScore = 0; + // The minimum amount to bump a score by. This is large enough that + // even if it's translated into the old values, it will still go up + // by at least one. + const int kScoreBump = 100; + // This is the lowest score that renderers and extensions start with + // in the OomPriorityManager. + const int kRendererScore = chrome::kLowestRendererOomScore; + // For "miscellaneous" things, we want them after renderers, + // but before plugins. + const int kMiscScore = kRendererScore - kScoreBump; + // We want plugins to die after the renderers. + const int kPluginScore = kMiscScore - kScoreBump; + int score = -1; + + DCHECK(kMiscScore > 0); + DCHECK(kPluginScore > 0); + + if (process_type == switches::kPluginProcess || + process_type == switches::kPpapiPluginProcess) { + score = kPluginScore; + } else if (process_type == switches::kPpapiBrokerProcess) { + // The broker should be killed before the PPAPI plugin. + score = kPluginScore + kScoreBump; + } else if (process_type == switches::kUtilityProcess || + process_type == switches::kWorkerProcess || + process_type == switches::kGpuProcess || + process_type == switches::kServiceProcess) { + score = kMiscScore; +#ifndef DISABLE_NACL + } else if (process_type == switches::kNaClLoaderProcess) { + score = kPluginScore; +#endif + } else if (process_type == switches::kZygoteProcess || + process_type.empty()) { + // For zygotes and unlabeled process types, we want to still make + // them killable by the OOM killer. + score = kZygoteScore; + } else if (process_type == switches::kRendererProcess) { + LOG(WARNING) << "process type 'renderer' " + << "should be created through the zygote."; + // When debugging, this process type can end up being run directly, but + // this isn't the typical path for assigning the OOM score for it. Still, + // we want to assign a score that is somewhat representative for debugging. + score = kRendererScore; + } else { + NOTREACHED() << "Unknown process type"; + } + if (score > -1) + base::AdjustOOMScore(base::GetCurrentProcId(), score); +} +#endif // defined(OS_LINUX) + +// Enable the heap profiler if the appropriate command-line switch is +// present, bailing out of the app we can't. +void EnableHeapProfiler(const CommandLine& command_line) { +#if defined(OS_WIN) + if (command_line.HasSwitch(switches::kMemoryProfiling)) + if (!LoadMemoryProfiler()) + exit(-1); +#endif +} + +void InitializeChromeContentRendererClient() { + content::GetContentClient()->set_renderer( + &g_chrome_content_renderer_client.Get()); +} + +void InitializeChromeContentClient(const std::string& process_type) { + if (process_type.empty()) { + content::GetContentClient()->set_browser( + &g_chrome_content_browser_client.Get()); + } else if (process_type == switches::kPluginProcess) { + content::GetContentClient()->set_plugin( + &g_chrome_content_plugin_client.Get()); + } else if (process_type == switches::kRendererProcess) { + InitializeChromeContentRendererClient(); + } else if (process_type == switches::kUtilityProcess) { + content::GetContentClient()->set_utility( + &g_chrome_content_utility_client.Get()); + } +} + +// Returns true if this subprocess type needs the ResourceBundle initialized +// and resources loaded. +bool SubprocessNeedsResourceBundle(const std::string& process_type) { + return +#if defined(OS_WIN) || defined(OS_MACOSX) + // Windows needs resources for the default/null plugin. + // Mac needs them for the plugin process name. + process_type == switches::kPluginProcess || +#endif +#if defined(OS_POSIX) && !defined(OS_MACOSX) + // The zygote process opens the resources for the renderers. + process_type == switches::kZygoteProcess || +#endif +#if defined(OS_MACOSX) + // Mac needs them to for scrollbar related images. + process_type == switches::kWorkerProcess || +#endif + process_type == switches::kRendererProcess || + process_type == switches::kUtilityProcess; +} + +#if defined(OS_MACOSX) +// Update the name shown in Activity Monitor so users are less likely to ask +// why Chrome has so many processes. +void SetMacProcessName(const CommandLine& command_line) { + std::string process_type = + command_line.GetSwitchValueASCII(switches::kProcessType); + // Don't worry about the browser process, its gets the stock name. + int name_id = 0; + if (command_line.HasSwitch(switches::kExtensionProcess)) { + name_id = IDS_WORKER_APP_NAME; + } else if (process_type == switches::kRendererProcess) { + name_id = IDS_RENDERER_APP_NAME; + } else if (process_type == switches::kPluginProcess || + process_type == switches::kPpapiPluginProcess) { + name_id = IDS_PLUGIN_APP_NAME; + } else if (process_type == switches::kUtilityProcess) { + name_id = IDS_UTILITY_APP_NAME; + } + if (name_id) { + NSString* app_name = l10n_util::GetNSString(name_id); + base::mac::SetProcessName(base::mac::NSToCFCast(app_name)); + } +} + +#endif // defined(OS_MACOSX) + +#if defined(OS_POSIX) +// Check for --version and --product-version; return true if we encountered +// one of these switches and should exit now. +bool HandleVersionSwitches(const CommandLine& command_line) { + const chrome::VersionInfo version_info; + +#if !defined(OS_MACOSX) + if (command_line.HasSwitch(switches::kProductVersion)) { + printf("%s\n", version_info.Version().c_str()); + return true; + } +#endif + + if (command_line.HasSwitch(switches::kVersion)) { + printf("%s %s %s\n", + version_info.Name().c_str(), + version_info.Version().c_str(), + chrome::VersionInfo::GetVersionStringModifier().c_str()); + return true; + } + + return false; +} + +#if !defined(OS_MACOSX) && !defined(OS_CHROMEOS) +// Show the man page if --help or -h is on the command line. +void HandleHelpSwitches(const CommandLine& command_line) { + if (command_line.HasSwitch(switches::kHelp) || + command_line.HasSwitch(switches::kHelpShort)) { + FilePath binary(command_line.argv()[0]); + execlp("man", "man", binary.BaseName().value().c_str(), NULL); + PLOG(FATAL) << "execlp failed"; + } +} +#endif + +#endif // OS_POSIX + +struct MainFunction { + const char* name; + int (*function)(const MainFunctionParams&); +}; + +} // namespace + +ChromeMainDelegate::ChromeMainDelegate() { +} + +ChromeMainDelegate::~ChromeMainDelegate() { +} + +bool ChromeMainDelegate::BasicStartupComplete(int* exit_code) { +#if defined(OS_CHROMEOS) + chromeos::BootTimesLoader::Get()->SaveChromeMainStats(); +#endif + + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + +#if defined(OS_MACOSX) + // Give the browser process a longer treadmill, since crashes + // there have more impact. + const bool is_browser = !command_line.HasSwitch(switches::kProcessType); + ObjcEvilDoers::ZombieEnable(true, is_browser ? 10000 : 1000); + + SetUpBundleOverrides(); + chrome::common::mac::EnableCFBundleBlocker(); +#endif + + Profiling::ProcessStarted(); + +#if defined(OS_POSIX) + if (HandleVersionSwitches(command_line)) { + *exit_code = 0; + return true; // Got a --version switch; exit with a success error code. + } +#if !defined(OS_MACOSX) && !defined(OS_CHROMEOS) + // This will directly exit if the user asked for help. + HandleHelpSwitches(command_line); +#endif +#endif // OS_POSIX + + // If we are in diagnostics mode this is the end of the line. After the + // diagnostics are run the process will invariably exit. + if (command_line.HasSwitch(switches::kDiagnostics)) { + *exit_code = DiagnosticsMain(command_line); + return true; + } + +#if defined(OS_WIN) + // Must do this before any other usage of command line! + if (HasDeprecatedArguments(command_line.GetCommandLineString())) { + *exit_code = 1; + return true; + } +#endif + + if (!command_line.HasSwitch(switches::kProcessType) && + command_line.HasSwitch(switches::kEnableBenchmarking)) { + base::FieldTrial::EnableBenchmarking(); + } + return false; +} + +#if defined(OS_MACOSX) +void ChromeMainDelegate::InitMacCrashReporter(const CommandLine& command_line, + const std::string& process_type) { + // TODO(mark): Right now, InitCrashReporter() needs to be called after + // CommandLine::Init() and chrome::RegisterPathProvider(). Ideally, + // Breakpad initialization could occur sooner, preferably even before the + // framework dylib is even loaded, to catch potential early crashes. + InitCrashReporter(); + +#if defined(NDEBUG) + bool is_debug_build = false; +#else + bool is_debug_build = true; +#endif + + // Details on when we enable Apple's Crash reporter. + // + // Motivation: + // In debug mode it takes Apple's crash reporter eons to generate a crash + // dump. + // + // What we do: + // * We only pass crashes for foreground processes to Apple's Crash + // reporter. At the time of this writing, that means just the Browser + // process. + // * If Breakpad is enabled, it will pass browser crashes to Crash Reporter + // itself. + // * If Breakpad is disabled, we only turn on Crash Reporter for the + // Browser process in release mode. + if (!command_line.HasSwitch(switches::kDisableBreakpad)) { + bool disable_apple_crash_reporter = is_debug_build || + base::mac::IsBackgroundOnlyProcess(); + if (!IsCrashReporterEnabled() && disable_apple_crash_reporter) { + base::mac::DisableOSCrashDumps(); + } + } + + // Mac Chrome is packaged with a main app bundle and a helper app bundle. + // The main app bundle should only be used for the browser process, so it + // should never see a --type switch (switches::kProcessType). Likewise, + // the helper should always have a --type switch. + // + // This check is done this late so there is already a call to + // base::mac::IsBackgroundOnlyProcess(), so there is no change in + // startup/initialization order. + + // The helper's Info.plist marks it as a background only app. + if (base::mac::IsBackgroundOnlyProcess()) { + CHECK(command_line.HasSwitch(switches::kProcessType) && + !process_type.empty()) + << "Helper application requires --type."; + + // In addition, some helper flavors only work with certain process types. + FilePath executable; + if (PathService::Get(base::FILE_EXE, &executable) && + executable.value().size() >= 3) { + std::string last_three = + executable.value().substr(executable.value().size() - 3); + + if (last_three == " EH") { + CHECK(process_type == switches::kPluginProcess || + process_type == switches::kUtilityProcess) + << "Executable-heap process requires --type=" + << switches::kPluginProcess << " or " + << switches::kUtilityProcess << ", saw " << process_type; + } else if (last_three == " NP") { + CHECK_EQ(switches::kNaClLoaderProcess, process_type) + << "Non-PIE process requires --type=" + << switches::kNaClLoaderProcess << ", saw " << process_type; + } else { + CHECK(process_type != switches::kPluginProcess && + process_type != switches::kNaClLoaderProcess) + << "Non-executable-heap PIE process is intolerant of --type=" + << switches::kPluginProcess << " and " + << switches::kNaClLoaderProcess << ", saw " << process_type; + } + } + } else { + CHECK(!command_line.HasSwitch(switches::kProcessType) && + process_type.empty()) + << "Main application forbids --type, saw " << process_type; + } + + if (IsCrashReporterEnabled()) + InitCrashProcessInfo(); +} +#endif // defined(OS_MACOSX) + +void ChromeMainDelegate::PreSandboxStartup() { + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + std::string process_type = + command_line.GetSwitchValueASCII(switches::kProcessType); + + // Initialize the content client which that code uses to talk to Chrome. + content::SetContentClient(&chrome_content_client_); + InitializeChromeContentClient(process_type); + + // Initialize the Chrome path provider. + chrome::RegisterPathProvider(); + +#if defined(OS_MACOSX) + // On the Mac, the child executable lives at a predefined location within + // the app bundle's versioned directory. + PathService::Override(content::CHILD_PROCESS_EXE, + chrome::GetVersionedDirectory(). + Append(chrome::kHelperProcessExecutablePath)); + + InitMacCrashReporter(command_line, process_type); +#endif + + // Notice a user data directory override if any + FilePath user_data_dir = + command_line.GetSwitchValuePath(switches::kUserDataDir); +#if defined(OS_MACOSX) || defined(OS_WIN) + CheckUserDataDirPolicy(&user_data_dir); +#endif + if (!user_data_dir.empty()) + CHECK(PathService::Override(chrome::DIR_USER_DATA, user_data_dir)); + + startup_timer_.reset(new base::StatsScope<base::StatsCounterTimer> + (content::Counters::chrome_main())); + + // Enable the heap profiler as early as possible! + EnableHeapProfiler(command_line); + + // Enable Message Loop related state asap. + if (command_line.HasSwitch(switches::kMessageLoopHistogrammer)) + MessageLoop::EnableHistogrammer(true); + + // Single-process is an unsupported and not fully tested mode, so + // don't enable it for official Chrome builds. +#if !defined(GOOGLE_CHROME_BUILD) + if (command_line.HasSwitch(switches::kSingleProcess)) { + RenderProcessHost::set_run_renderer_in_process(true); +#if defined(OS_MACOSX) + // TODO(port-mac): This is from renderer_main_platform_delegate.cc. + // shess tried to refactor things appropriately, but it sprawled out + // of control because different platforms needed different styles of + // initialization. Try again once we understand the process + // architecture needed and where it should live. + InitWebCoreSystemInterface(); +#endif + + InitializeChromeContentRendererClient(); + } +#endif // GOOGLE_CHROME_BUILD + + logging::OldFileDeletionState file_state = + logging::APPEND_TO_OLD_LOG_FILE; + if (process_type.empty()) { + file_state = logging::DELETE_OLD_LOG_FILE; + } + logging::InitChromeLogging(command_line, file_state); + + // Register internal Chrome schemes so they'll be parsed correctly. This + // must happen before we process any URLs with the affected schemes, and + // must be done in all processes that work with these URLs (i.e. including + // renderers). + chrome::RegisterChromeSchemes(); + +#if defined(OS_WIN) + // TODO(darin): Kill this once http://crbug.com/52609 is fixed. + ResourceBundle::SetResourcesDataDLL(_AtlBaseModule.GetResourceInstance()); +#endif + + if (SubprocessNeedsResourceBundle(process_type)) { + // Initialize ResourceBundle which handles files loaded from external + // sources. The language should have been passed in to us from the + // browser process as a command line flag. + DCHECK(command_line.HasSwitch(switches::kLang) || + process_type == switches::kZygoteProcess); + + // TODO(markusheintz): The command line flag --lang is actually processed + // by the CommandLinePrefStore, and made available through the PrefService + // via the preference prefs::kApplicationLocale. The browser process uses + // the --lang flag to pass the value of the PrefService in here. Maybe + // this value could be passed in a different way. + const std::string locale = + command_line.GetSwitchValueASCII(switches::kLang); + const std::string loaded_locale = + ResourceBundle::InitSharedInstance(locale); + CHECK(!loaded_locale.empty()) << "Locale could not be found for " << + locale; + +#if defined(OS_MACOSX) + // Update the process name (need resources to get the strings, so + // only do this when ResourcesBundle has been initialized). + SetMacProcessName(command_line); +#endif // defined(OS_MACOSX) + } + +#if defined(USE_LINUX_BREAKPAD) + // Needs to be called after we have chrome::DIR_USER_DATA. BrowserMain + // sets this up for the browser process in a different manner. Zygotes + // need to call InitCrashReporter() in RunZygote(). + if (!process_type.empty() && process_type != switches::kZygoteProcess) + InitCrashReporter(); +#endif + +#if defined(OS_CHROMEOS) + // Read and cache ChromeOS version from file, + // to be used from inside the sandbox. + int32 major_version, minor_version, bugfix_version; + base::SysInfo::OperatingSystemVersionNumbers( + &major_version, &minor_version, &bugfix_version); +#endif +} + +void ChromeMainDelegate::SandboxInitialized(const std::string& process_type) { + startup_timer_->Stop(); // End of Startup Time Measurement. + + // Note: If you are adding a new process type below, be sure to adjust the + // AdjustLinuxOOMScore function too. +#if defined(OS_LINUX) + AdjustLinuxOOMScore(process_type); +#endif +} + +int ChromeMainDelegate::RunProcess( + const std::string& process_type, + const MainFunctionParams& main_function_params) { + static const MainFunction kMainFunctions[] = { + { switches::kServiceProcess, ServiceProcessMain }, +#if defined(OS_MACOSX) + { switches::kRelauncherProcess, + mac_relauncher::internal::RelauncherMain }, +#endif +#if !defined(DISABLE_NACL) + { switches::kNaClLoaderProcess, NaClMain }, +#endif // DISABLE_NACL + }; + + for (size_t i = 0; i < arraysize(kMainFunctions); ++i) { + if (process_type == kMainFunctions[i].name) + return kMainFunctions[i].function(main_function_params); + } + + NOTREACHED() << "Unknown process type: " << process_type; + return 1; +} + +void ChromeMainDelegate::ProcessExiting(const std::string& process_type) { + if (SubprocessNeedsResourceBundle(process_type)) + ResourceBundle::CleanupSharedInstance(); + + logging::CleanupChromeLogging(); +} + +#if defined(OS_MACOSX) +bool ChromeMainDelegate::ProcessRegistersWithSystemProcess( + const std::string& process_type) { + return process_type == switches::kNaClLoaderProcess; +} + +bool ChromeMainDelegate::ShouldSendMachPort(const std::string& process_type) { + return process_type != switches::kRelauncherProcess && + process_type != switches::kServiceProcess; +} + +bool ChromeMainDelegate::DelaySandboxInitialization( + const std::string& process_type) { + // NaClLoader does this in NaClMainPlatformDelegate::EnableSandbox(). + // No sandbox needed for relauncher. + return process_type == switches::kNaClLoaderProcess || + process_type == switches::kRelauncherProcess; +} +#elif defined(OS_POSIX) +ZygoteForkDelegate* ChromeMainDelegate::ZygoteStarting() { + // Each Renderer we spawn will re-attempt initialization of the media + // libraries, at which point failure will be detected and handled, so + // we do not need to cope with initialization failures here. + FilePath media_path; + if (PathService::Get(chrome::DIR_MEDIA_LIBS, &media_path)) + media::InitializeMediaLibrary(media_path); +#if defined(DISABLE_NACL) + return NULL; +#else + return new NaClForkDelegate(); +#endif +} + +void ChromeMainDelegate::ZygoteForked() { + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + std::string process_type = + command_line.GetSwitchValueASCII(switches::kProcessType); + +#if defined(USE_LINUX_BREAKPAD) + // Needs to be called after we have chrome::DIR_USER_DATA. BrowserMain sets + // this up for the browser process in a different manner. + InitCrashReporter(); +#endif + + InitializeChromeContentClient(process_type); +} +#endif // OS_MACOSX |