chrome_main_delegate.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
1// Copyright (c) 2012 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. 4 5#include "chrome/app/chrome_main_delegate.h" 6 7#include "base/command_line.h" 8#include "base/lazy_instance.h" 9#include "base/message_loop.h" 10#include "base/metrics/stats_counters.h" 11#include "base/path_service.h" 12#include "base/process_util.h" 13#include "base/strings/stringprintf.h" 14#include "base/strings/utf_string_conversions.h" 15#include "build/build_config.h" 16#include "chrome/browser/chrome_content_browser_client.h" 17#include "chrome/browser/defaults.h" 18#include "chrome/browser/diagnostics/diagnostics_main.h" 19#include "chrome/browser/policy/policy_path_parser.h" 20#include "chrome/common/chrome_constants.h" 21#include "chrome/common/chrome_content_client.h" 22#include "chrome/common/chrome_paths.h" 23#include "chrome/common/chrome_paths_internal.h" 24#include "chrome/common/chrome_switches.h" 25#include "chrome/common/chrome_version_info.h" 26#include "chrome/common/logging_chrome.h" 27#include "chrome/common/profiling.h" 28#include "chrome/common/startup_metric_utils.h" 29#include "chrome/common/url_constants.h" 30#include "chrome/plugin/chrome_content_plugin_client.h" 31#include "chrome/renderer/chrome_content_renderer_client.h" 32#include "chrome/utility/chrome_content_utility_client.h" 33#include "components/nacl/common/nacl_switches.h" 34#include "content/public/common/content_client.h" 35#include "content/public/common/content_paths.h" 36#include "ui/base/ui_base_switches.h" 37 38#if defined(OS_WIN) 39#include <algorithm> 40#include <atlbase.h> 41#include <malloc.h> 42#include "base/strings/string_util.h" 43#include "sandbox/win/src/sandbox.h" 44#include "tools/memory_watcher/memory_watcher.h" 45#include "ui/base/resource/resource_bundle_win.h" 46#endif 47 48#if defined(OS_MACOSX) 49#include "base/mac/mac_util.h" 50#include "base/mac/os_crash_dumps.h" 51#include "chrome/app/breakpad_mac.h" 52#include "chrome/app/chrome_main_mac.h" 53#include "chrome/browser/mac/relauncher.h" 54#include "chrome/common/chrome_paths_internal.h" 55#include "chrome/common/mac/cfbundle_blocker.h" 56#include "chrome/common/mac/objc_zombie.h" 57#include "grit/chromium_strings.h" 58#include "ui/base/l10n/l10n_util_mac.h" 59#endif 60 61#if defined(OS_POSIX) 62#include <locale.h> 63#include <signal.h> 64#endif 65 66#if !defined(DISABLE_NACL) && defined(OS_LINUX) 67#include "chrome/app/nacl_fork_delegate_linux.h" 68#include "chrome/common/nacl_paths.h" 69#endif 70 71#if defined(OS_CHROMEOS) 72#include "base/sys_info.h" 73#include "chrome/browser/chromeos/boot_times_loader.h" 74#include "chromeos/chromeos_paths.h" 75#endif 76 77#if defined(OS_ANDROID) 78#include "chrome/common/descriptors_android.h" 79#endif 80 81#if defined(USE_X11) 82#include <stdlib.h> 83#include <string.h> 84#include "ui/base/x/x11_util.h" 85#endif 86 87#if defined(USE_LINUX_BREAKPAD) 88#include "chrome/app/breakpad_linux.h" 89#endif 90 91base::LazyInstance<chrome::ChromeContentBrowserClient> 92 g_chrome_content_browser_client = LAZY_INSTANCE_INITIALIZER; 93base::LazyInstance<chrome::ChromeContentRendererClient> 94 g_chrome_content_renderer_client = LAZY_INSTANCE_INITIALIZER; 95base::LazyInstance<chrome::ChromeContentUtilityClient> 96 g_chrome_content_utility_client = LAZY_INSTANCE_INITIALIZER; 97base::LazyInstance<chrome::ChromeContentPluginClient> 98 g_chrome_content_plugin_client = LAZY_INSTANCE_INITIALIZER; 99 100extern int NaClMain(const content::MainFunctionParams&); 101extern int ServiceProcessMain(const content::MainFunctionParams&); 102 103namespace { 104 105#if defined(OS_WIN) 106const wchar_t kProfilingDll[] = L"memory_watcher.dll"; 107 108// Load the memory profiling DLL. All it needs to be activated 109// is to be loaded. Return true on success, false otherwise. 110bool LoadMemoryProfiler() { 111 HMODULE prof_module = LoadLibrary(kProfilingDll); 112 return prof_module != NULL; 113} 114 115// Early versions of Chrome incorrectly registered a chromehtml: URL handler, 116// which gives us nothing but trouble. Avoid launching chrome this way since 117// some apps fail to properly escape arguments. 118bool HasDeprecatedArguments(const std::wstring& command_line) { 119 const wchar_t kChromeHtml[] = L"chromehtml:"; 120 std::wstring command_line_lower = command_line; 121 // We are only searching for ASCII characters so this is OK. 122 StringToLowerASCII(&command_line_lower); 123 std::wstring::size_type pos = command_line_lower.find(kChromeHtml); 124 return (pos != std::wstring::npos); 125} 126 127// If we try to access a path that is not currently available, we want the call 128// to fail rather than show an error dialog. 129void SuppressWindowsErrorDialogs() { 130 UINT new_flags = SEM_FAILCRITICALERRORS | 131 SEM_NOOPENFILEERRORBOX; 132 133 // Preserve existing error mode. 134 UINT existing_flags = SetErrorMode(new_flags); 135 SetErrorMode(existing_flags | new_flags); 136} 137 138#endif // defined(OS_WIN) 139 140#if defined(OS_LINUX) 141static void AdjustLinuxOOMScore(const std::string& process_type) { 142 // Browsers and zygotes should still be killable, but killed last. 143 const int kZygoteScore = 0; 144 // The minimum amount to bump a score by. This is large enough that 145 // even if it's translated into the old values, it will still go up 146 // by at least one. 147 const int kScoreBump = 100; 148 // This is the lowest score that renderers and extensions start with 149 // in the OomPriorityManager. 150 const int kRendererScore = chrome::kLowestRendererOomScore; 151 // For "miscellaneous" things, we want them after renderers, 152 // but before plugins. 153 const int kMiscScore = kRendererScore - kScoreBump; 154 // We want plugins to die after the renderers. 155 const int kPluginScore = kMiscScore - kScoreBump; 156 int score = -1; 157 158 DCHECK(kMiscScore > 0); 159 DCHECK(kPluginScore > 0); 160 161 if (process_type == switches::kPluginProcess || 162 process_type == switches::kPpapiPluginProcess) { 163 score = kPluginScore; 164 } else if (process_type == switches::kPpapiBrokerProcess) { 165 // The broker should be killed before the PPAPI plugin. 166 score = kPluginScore + kScoreBump; 167 } else if (process_type == switches::kUtilityProcess || 168 process_type == switches::kWorkerProcess || 169 process_type == switches::kGpuProcess || 170 process_type == switches::kServiceProcess) { 171 score = kMiscScore; 172#ifndef DISABLE_NACL 173 } else if (process_type == switches::kNaClLoaderProcess) { 174 score = kPluginScore; 175#endif 176 } else if (process_type == switches::kZygoteProcess || 177 process_type.empty()) { 178 // For zygotes and unlabeled process types, we want to still make 179 // them killable by the OOM killer. 180 score = kZygoteScore; 181 } else if (process_type == switches::kRendererProcess) { 182 LOG(WARNING) << "process type 'renderer' " 183 << "should be created through the zygote."; 184 // When debugging, this process type can end up being run directly, but 185 // this isn't the typical path for assigning the OOM score for it. Still, 186 // we want to assign a score that is somewhat representative for debugging. 187 score = kRendererScore; 188 } else { 189 NOTREACHED() << "Unknown process type"; 190 } 191 if (score > -1) 192 base::AdjustOOMScore(base::GetCurrentProcId(), score); 193} 194#endif // defined(OS_LINUX) 195 196// Enable the heap profiler if the appropriate command-line switch is 197// present, bailing out of the app we can't. 198void EnableHeapProfiler(const CommandLine& command_line) { 199#if defined(OS_WIN) 200 if (command_line.HasSwitch(switches::kMemoryProfiling)) 201 if (!LoadMemoryProfiler()) 202 exit(-1); 203#endif 204} 205 206// Returns true if this subprocess type needs the ResourceBundle initialized 207// and resources loaded. 208bool SubprocessNeedsResourceBundle(const std::string& process_type) { 209 return 210#if defined(OS_WIN) || defined(OS_MACOSX) 211 // Windows needs resources for the default/null plugin. 212 // Mac needs them for the plugin process name. 213 process_type == switches::kPluginProcess || 214#endif 215#if defined(OS_POSIX) && !defined(OS_MACOSX) 216 // The zygote process opens the resources for the renderers. 217 process_type == switches::kZygoteProcess || 218#endif 219#if defined(OS_MACOSX) 220 // Mac needs them too for scrollbar related images and for sandbox 221 // profiles. 222 process_type == switches::kWorkerProcess || 223 process_type == switches::kNaClLoaderProcess || 224 process_type == switches::kPpapiPluginProcess || 225 process_type == switches::kPpapiBrokerProcess || 226 process_type == switches::kGpuProcess || 227#endif 228 process_type == switches::kRendererProcess || 229 process_type == switches::kUtilityProcess; 230} 231 232#if defined(OS_MACOSX) 233// Update the name shown in Activity Monitor so users are less likely to ask 234// why Chrome has so many processes. 235void SetMacProcessName(const CommandLine& command_line) { 236 std::string process_type = 237 command_line.GetSwitchValueASCII(switches::kProcessType); 238 // Don't worry about the browser process, its gets the stock name. 239 int name_id = 0; 240 if (command_line.HasSwitch(switches::kExtensionProcess)) { 241 name_id = IDS_WORKER_APP_NAME; 242 } else if (process_type == switches::kRendererProcess) { 243 name_id = IDS_RENDERER_APP_NAME; 244 } else if (process_type == switches::kPluginProcess || 245 process_type == switches::kPpapiPluginProcess) { 246 name_id = IDS_PLUGIN_APP_NAME; 247 } else if (process_type == switches::kUtilityProcess) { 248 name_id = IDS_UTILITY_APP_NAME; 249 } 250 if (name_id) { 251 NSString* app_name = l10n_util::GetNSString(name_id); 252 base::mac::SetProcessName(base::mac::NSToCFCast(app_name)); 253 } 254} 255 256#endif // defined(OS_MACOSX) 257 258#if defined(OS_POSIX) 259// Check for --version and --product-version; return true if we encountered 260// one of these switches and should exit now. 261bool HandleVersionSwitches(const CommandLine& command_line) { 262 const chrome::VersionInfo version_info; 263 264#if !defined(OS_MACOSX) 265 if (command_line.HasSwitch(switches::kProductVersion)) { 266 printf("%s\n", version_info.Version().c_str()); 267 return true; 268 } 269#endif 270 271 if (command_line.HasSwitch(switches::kVersion)) { 272 printf("%s %s %s\n", 273 version_info.Name().c_str(), 274 version_info.Version().c_str(), 275 chrome::VersionInfo::GetVersionStringModifier().c_str()); 276 return true; 277 } 278 279 return false; 280} 281 282#if !defined(OS_MACOSX) && !defined(OS_CHROMEOS) 283// Show the man page if --help or -h is on the command line. 284void HandleHelpSwitches(const CommandLine& command_line) { 285 if (command_line.HasSwitch(switches::kHelp) || 286 command_line.HasSwitch(switches::kHelpShort)) { 287 base::FilePath binary(command_line.argv()[0]); 288 execlp("man", "man", binary.BaseName().value().c_str(), NULL); 289 PLOG(FATAL) << "execlp failed"; 290 } 291} 292#endif 293 294#if !defined(OS_MACOSX) 295void SIGTERMProfilingShutdown(int signal) { 296 Profiling::Stop(); 297 struct sigaction sigact; 298 memset(&sigact, 0, sizeof(sigact)); 299 sigact.sa_handler = SIG_DFL; 300 CHECK(sigaction(SIGTERM, &sigact, NULL) == 0); 301 raise(signal); 302} 303 304void SetUpProfilingShutdownHandler() { 305 struct sigaction sigact; 306 sigact.sa_handler = SIGTERMProfilingShutdown; 307 sigact.sa_flags = SA_RESETHAND; 308 sigemptyset(&sigact.sa_mask); 309 CHECK(sigaction(SIGTERM, &sigact, NULL) == 0); 310} 311#endif 312 313#endif // OS_POSIX 314 315struct MainFunction { 316 const char* name; 317 int (*function)(const content::MainFunctionParams&); 318}; 319 320} // namespace 321 322ChromeMainDelegate::ChromeMainDelegate() { 323 startup_metric_utils::RecordMainEntryPointTime(); 324} 325 326ChromeMainDelegate::~ChromeMainDelegate() { 327} 328 329bool ChromeMainDelegate::BasicStartupComplete(int* exit_code) { 330#if defined(OS_CHROMEOS) 331 chromeos::BootTimesLoader::Get()->SaveChromeMainStats(); 332#endif 333 334 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 335 336#if defined(OS_MACOSX) 337 // Give the browser process a longer treadmill, since crashes 338 // there have more impact. 339 const bool is_browser = !command_line.HasSwitch(switches::kProcessType); 340 ObjcEvilDoers::ZombieEnable(true, is_browser ? 10000 : 1000); 341 342 SetUpBundleOverrides(); 343 chrome::common::mac::EnableCFBundleBlocker(); 344#endif 345 346 Profiling::ProcessStarted(); 347 348#if defined(OS_POSIX) 349 if (HandleVersionSwitches(command_line)) { 350 *exit_code = 0; 351 return true; // Got a --version switch; exit with a success error code. 352 } 353#if !defined(OS_MACOSX) && !defined(OS_CHROMEOS) 354 // This will directly exit if the user asked for help. 355 HandleHelpSwitches(command_line); 356#endif 357#endif // OS_POSIX 358 359 // No support for ANDROID yet as DiagnosticsMain needs wchar support. 360#if !defined(OS_ANDROID) 361 // If we are in diagnostics mode this is the end of the line. After the 362 // diagnostics are run the process will invariably exit. 363 if (command_line.HasSwitch(switches::kDiagnostics)) { 364 *exit_code = DiagnosticsMain(command_line); 365 return true; 366 } 367#endif 368 369#if defined(OS_WIN) 370 // Must do this before any other usage of command line! 371 if (HasDeprecatedArguments(command_line.GetCommandLineString())) { 372 *exit_code = 1; 373 return true; 374 } 375#endif 376 377 content::SetContentClient(&chrome_content_client_); 378 379 return false; 380} 381 382#if defined(OS_MACOSX) 383void ChromeMainDelegate::InitMacCrashReporter(const CommandLine& command_line, 384 const std::string& process_type) { 385 // TODO(mark): Right now, InitCrashReporter() needs to be called after 386 // CommandLine::Init() and chrome::RegisterPathProvider(). Ideally, 387 // Breakpad initialization could occur sooner, preferably even before the 388 // framework dylib is even loaded, to catch potential early crashes. 389 InitCrashReporter(); 390 391#if defined(NDEBUG) 392 bool is_debug_build = false; 393#else 394 bool is_debug_build = true; 395#endif 396 397 // Details on when we enable Apple's Crash reporter. 398 // 399 // Motivation: 400 // In debug mode it takes Apple's crash reporter eons to generate a crash 401 // dump. 402 // 403 // What we do: 404 // * We only pass crashes for foreground processes to Apple's Crash 405 // reporter. At the time of this writing, that means just the Browser 406 // process. 407 // * If Breakpad is enabled, it will pass browser crashes to Crash Reporter 408 // itself. 409 // * If Breakpad is disabled, we only turn on Crash Reporter for the 410 // Browser process in release mode. 411 if (!command_line.HasSwitch(switches::kDisableBreakpad)) { 412 bool disable_apple_crash_reporter = is_debug_build || 413 base::mac::IsBackgroundOnlyProcess(); 414 if (!IsCrashReporterEnabled() && disable_apple_crash_reporter) { 415 base::mac::DisableOSCrashDumps(); 416 } 417 } 418 419 // Mac Chrome is packaged with a main app bundle and a helper app bundle. 420 // The main app bundle should only be used for the browser process, so it 421 // should never see a --type switch (switches::kProcessType). Likewise, 422 // the helper should always have a --type switch. 423 // 424 // This check is done this late so there is already a call to 425 // base::mac::IsBackgroundOnlyProcess(), so there is no change in 426 // startup/initialization order. 427 428 // The helper's Info.plist marks it as a background only app. 429 if (base::mac::IsBackgroundOnlyProcess()) { 430 CHECK(command_line.HasSwitch(switches::kProcessType) && 431 !process_type.empty()) 432 << "Helper application requires --type."; 433 434 // In addition, some helper flavors only work with certain process types. 435 base::FilePath executable; 436 if (PathService::Get(base::FILE_EXE, &executable) && 437 executable.value().size() >= 3) { 438 std::string last_three = 439 executable.value().substr(executable.value().size() - 3); 440 441 if (last_three == " EH") { 442 CHECK(process_type == switches::kPluginProcess || 443 process_type == switches::kUtilityProcess) 444 << "Executable-heap process requires --type=" 445 << switches::kPluginProcess << " or " 446 << switches::kUtilityProcess << ", saw " << process_type; 447 } else if (last_three == " NP") { 448 CHECK_EQ(switches::kNaClLoaderProcess, process_type) 449 << "Non-PIE process requires --type=" 450 << switches::kNaClLoaderProcess << ", saw " << process_type; 451 } else { 452 CHECK(process_type != switches::kPluginProcess && 453 process_type != switches::kNaClLoaderProcess) 454 << "Non-executable-heap PIE process is intolerant of --type=" 455 << switches::kPluginProcess << " and " 456 << switches::kNaClLoaderProcess << ", saw " << process_type; 457 } 458 } 459 } else { 460 CHECK(!command_line.HasSwitch(switches::kProcessType) && 461 process_type.empty()) 462 << "Main application forbids --type, saw " << process_type; 463 } 464 465 if (IsCrashReporterEnabled()) 466 InitCrashProcessInfo(); 467} 468#endif // defined(OS_MACOSX) 469 470void ChromeMainDelegate::PreSandboxStartup() { 471 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 472 std::string process_type = 473 command_line.GetSwitchValueASCII(switches::kProcessType); 474 475 chrome::RegisterPathProvider(); 476#if defined(OS_CHROMEOS) 477 chromeos::RegisterPathProvider(); 478#endif 479#if !defined(DISABLE_NACL) && defined(OS_LINUX) 480 nacl::RegisterPathProvider(); 481#endif 482 483#if defined(OS_MACOSX) 484 // On the Mac, the child executable lives at a predefined location within 485 // the app bundle's versioned directory. 486 PathService::Override(content::CHILD_PROCESS_EXE, 487 chrome::GetVersionedDirectory(). 488 Append(chrome::kHelperProcessExecutablePath)); 489 490 InitMacCrashReporter(command_line, process_type); 491#endif 492 493 // Notice a user data directory override if any 494 base::FilePath user_data_dir = 495 command_line.GetSwitchValuePath(switches::kUserDataDir); 496#if defined(OS_MACOSX) || defined(OS_WIN) 497 policy::path_parser::CheckUserDataDirPolicy(&user_data_dir); 498#endif 499 if (!user_data_dir.empty()) { 500 CHECK(PathService::OverrideAndCreateIfNeeded( 501 chrome::DIR_USER_DATA, 502 user_data_dir, 503 chrome::ProcessNeedsProfileDir(process_type))); 504 } 505 506 stats_counter_timer_.reset(new base::StatsCounterTimer("Chrome.Init")); 507 startup_timer_.reset(new base::StatsScope<base::StatsCounterTimer> 508 (*stats_counter_timer_)); 509 510 // Enable the heap profiler as early as possible! 511 EnableHeapProfiler(command_line); 512 513 // Enable Message Loop related state asap. 514 if (command_line.HasSwitch(switches::kMessageLoopHistogrammer)) 515 base::MessageLoop::EnableHistogrammer(true); 516 517#if !defined(OS_ANDROID) 518 // Android does InitLogging when library is loaded. Skip here. 519 logging::OldFileDeletionState file_state = 520 logging::APPEND_TO_OLD_LOG_FILE; 521 if (process_type.empty()) { 522 file_state = logging::DELETE_OLD_LOG_FILE; 523 } 524 logging::InitChromeLogging(command_line, file_state); 525#endif 526 527#if defined(OS_WIN) 528 // TODO(darin): Kill this once http://crbug.com/52609 is fixed. 529 ui::SetResourcesDataDLL(_AtlBaseModule.GetResourceInstance()); 530#endif 531 532 if (SubprocessNeedsResourceBundle(process_type)) { 533 // Initialize ResourceBundle which handles files loaded from external 534 // sources. The language should have been passed in to us from the 535 // browser process as a command line flag. 536#if defined(DISABLE_NACL) 537 DCHECK(command_line.HasSwitch(switches::kLang) || 538 process_type == switches::kZygoteProcess || 539 process_type == switches::kGpuProcess || 540 process_type == switches::kPpapiBrokerProcess || 541 process_type == switches::kPpapiPluginProcess); 542#else 543 DCHECK(command_line.HasSwitch(switches::kLang) || 544 process_type == switches::kZygoteProcess || 545 process_type == switches::kGpuProcess || 546 process_type == switches::kNaClLoaderProcess || 547 process_type == switches::kPpapiBrokerProcess || 548 process_type == switches::kPpapiPluginProcess); 549#endif 550 551 // TODO(markusheintz): The command line flag --lang is actually processed 552 // by the CommandLinePrefStore, and made available through the PrefService 553 // via the preference prefs::kApplicationLocale. The browser process uses 554 // the --lang flag to pass the value of the PrefService in here. Maybe 555 // this value could be passed in a different way. 556 const std::string locale = 557 command_line.GetSwitchValueASCII(switches::kLang); 558#if defined(OS_ANDROID) 559 // The renderer sandbox prevents us from accessing our .pak files directly. 560 // Therefore file descriptors to the .pak files that we need are passed in 561 // at process creation time. 562 int locale_pak_fd = base::GlobalDescriptors::GetInstance()->MaybeGet( 563 kAndroidLocalePakDescriptor); 564 CHECK(locale_pak_fd != -1); 565 ResourceBundle::InitSharedInstanceWithPakFile(locale_pak_fd, false); 566 567 int extra_pak_keys[] = { 568 kAndroidChromePakDescriptor, 569 kAndroidChrome100PercentPakDescriptor, 570 kAndroidUIResourcesPakDescriptor, 571 }; 572 for (size_t i = 0; i < arraysize(extra_pak_keys); ++i) { 573 int pak_fd = 574 base::GlobalDescriptors::GetInstance()->MaybeGet(extra_pak_keys[i]); 575 CHECK(pak_fd != -1); 576 ResourceBundle::GetSharedInstance().AddDataPackFromFile( 577 pak_fd, ui::SCALE_FACTOR_100P); 578 } 579 580 const std::string loaded_locale = locale; 581#else 582 const std::string loaded_locale = 583 ResourceBundle::InitSharedInstanceWithLocale(locale, NULL); 584 585 base::FilePath resources_pack_path; 586 PathService::Get(chrome::FILE_RESOURCES_PACK, &resources_pack_path); 587 ResourceBundle::GetSharedInstance().AddDataPackFromPath( 588 resources_pack_path, ui::SCALE_FACTOR_NONE); 589#endif 590 CHECK(!loaded_locale.empty()) << "Locale could not be found for " << 591 locale; 592 593#if defined(OS_MACOSX) 594 // Update the process name (need resources to get the strings, so 595 // only do this when ResourcesBundle has been initialized). 596 SetMacProcessName(command_line); 597#endif // defined(OS_MACOSX) 598 } 599 600#if defined(USE_LINUX_BREAKPAD) 601 // Needs to be called after we have chrome::DIR_USER_DATA. BrowserMain 602 // sets this up for the browser process in a different manner. Zygotes 603 // need to call InitCrashReporter() in RunZygote(). 604 if (!process_type.empty() && process_type != switches::kZygoteProcess) { 605#if defined(OS_ANDROID) 606 InitNonBrowserCrashReporterForAndroid(); 607#else 608 InitCrashReporter(); 609#endif 610 } 611#endif 612 613#if defined(OS_CHROMEOS) 614 // Read and cache ChromeOS version from file, 615 // to be used from inside the sandbox. 616 int32 major_version, minor_version, bugfix_version; 617 base::SysInfo::OperatingSystemVersionNumbers( 618 &major_version, &minor_version, &bugfix_version); 619#endif 620} 621 622void ChromeMainDelegate::SandboxInitialized(const std::string& process_type) { 623 startup_timer_->Stop(); // End of Startup Time Measurement. 624 625 // Note: If you are adding a new process type below, be sure to adjust the 626 // AdjustLinuxOOMScore function too. 627#if defined(OS_LINUX) 628 AdjustLinuxOOMScore(process_type); 629#endif 630#if defined(OS_WIN) 631 SuppressWindowsErrorDialogs(); 632#endif 633} 634 635int ChromeMainDelegate::RunProcess( 636 const std::string& process_type, 637 const content::MainFunctionParams& main_function_params) { 638 // ANDROID doesn't support "service", so no ServiceProcessMain, and arraysize 639 // doesn't support empty array. So we comment out the block for Android. 640#if !defined(OS_ANDROID) 641 static const MainFunction kMainFunctions[] = { 642 { switches::kServiceProcess, ServiceProcessMain }, 643#if defined(OS_MACOSX) 644 { switches::kRelauncherProcess, 645 mac_relauncher::internal::RelauncherMain }, 646#endif 647 // TODO(scottmg): http://crbug.com/237249 NaCl -> child. 648#if !defined(DISABLE_NACL) 649 { switches::kNaClLoaderProcess, NaClMain }, 650#endif // DISABLE_NACL 651 }; 652 653 for (size_t i = 0; i < arraysize(kMainFunctions); ++i) { 654 if (process_type == kMainFunctions[i].name) 655 return kMainFunctions[i].function(main_function_params); 656 } 657#endif 658 659 return -1; 660} 661 662void ChromeMainDelegate::ProcessExiting(const std::string& process_type) { 663 if (SubprocessNeedsResourceBundle(process_type)) 664 ResourceBundle::CleanupSharedInstance(); 665#if !defined(OS_ANDROID) 666 logging::CleanupChromeLogging(); 667#else 668 // Android doesn't use InitChromeLogging, so we close the log file manually. 669 logging::CloseLogFile(); 670#endif // !defined(OS_ANDROID) 671} 672 673#if defined(OS_MACOSX) 674bool ChromeMainDelegate::ProcessRegistersWithSystemProcess( 675 const std::string& process_type) { 676 return process_type == switches::kNaClLoaderProcess; 677} 678 679bool ChromeMainDelegate::ShouldSendMachPort(const std::string& process_type) { 680 return process_type != switches::kRelauncherProcess && 681 process_type != switches::kServiceProcess; 682} 683 684bool ChromeMainDelegate::DelaySandboxInitialization( 685 const std::string& process_type) { 686 // NaClLoader does this in NaClMainPlatformDelegate::EnableSandbox(). 687 // No sandbox needed for relauncher. 688 return process_type == switches::kNaClLoaderProcess || 689 process_type == switches::kRelauncherProcess; 690} 691#elif defined(OS_POSIX) && !defined(OS_ANDROID) 692content::ZygoteForkDelegate* ChromeMainDelegate::ZygoteStarting() { 693#if defined(DISABLE_NACL) 694 return NULL; 695#else 696 return new NaClForkDelegate(); 697#endif 698} 699 700void ChromeMainDelegate::ZygoteForked() { 701 Profiling::ProcessStarted(); 702 if (Profiling::BeingProfiled()) { 703 base::debug::RestartProfilingAfterFork(); 704 SetUpProfilingShutdownHandler(); 705 } 706 707#if defined(USE_LINUX_BREAKPAD) 708 // Needs to be called after we have chrome::DIR_USER_DATA. BrowserMain sets 709 // this up for the browser process in a different manner. 710 InitCrashReporter(); 711#endif 712} 713 714#endif // OS_MACOSX 715 716content::ContentBrowserClient* 717 ChromeMainDelegate::CreateContentBrowserClient() { 718 return &g_chrome_content_browser_client.Get(); 719} 720 721content::ContentPluginClient* ChromeMainDelegate::CreateContentPluginClient() { 722 // TODO(scottmg): http://crbug.com/237249 This will have to be split out into 723 // browser and child parts. 724 return &g_chrome_content_plugin_client.Get(); 725} 726 727content::ContentRendererClient* 728 ChromeMainDelegate::CreateContentRendererClient() { 729 return &g_chrome_content_renderer_client.Get(); 730} 731 732content::ContentUtilityClient* 733 ChromeMainDelegate::CreateContentUtilityClient() { 734 return &g_chrome_content_utility_client.Get(); 735} 736