Chromium版本:84.0.4113.0
一、入口
\src\chrome\app\chrome_exe_main_win.cc 源文件行:175
#if !defined(WIN_CONSOLE_APP)
int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prev, wchar_t*, int) {
#else
int main() {
HINSTANCE instance = GetModuleHandle(nullptr);
#endif
install_static::InitializeFromPrimaryModule();
SignalInitializeCrashReporting();
// Done here to ensure that OOMs that happen early in process initialization
// are correctly signaled to the OS.
base::EnableTerminationOnOutOfMemory();
// Initialize the CommandLine singleton from the environment.
base::CommandLine::Init(0, nullptr);
const base::CommandLine* command_line =
base::CommandLine::ForCurrentProcess();
const std::string process_type =
command_line->GetSwitchValueASCII(switches::kProcessType);
// Confirm that an explicit prefetch profile is used for all process types
// except for the browser process. Any new process type will have to assign
// itself a prefetch id. See kPrefetchArgument* constants in
// content_switches.cc for details.
DCHECK(process_type.empty() ||
HasValidWindowsPrefetchArgument(*command_line));
if (process_type == crash_reporter::switches::kCrashpadHandler) {
// Check if we should monitor the exit code of this process
std::unique_ptr<browser_watcher::ExitCodeWatcher> exit_code_watcher;
crash_reporter::SetupFallbackCrashHandling(*command_line);
// no-periodic-tasks is specified for self monitoring crashpad instances.
// This is to ensure we are a crashpad process monitoring the browser
// process and not another crashpad process.
if (!command_line->HasSwitch("no-periodic-tasks")) {
// Retrieve the client process from the command line
crashpad::InitialClientData initial_client_data;
if (initial_client_data.InitializeFromString(
command_line->GetSwitchValueASCII("initial-client-data"))) {
// Setup exit code watcher to monitor the parent process
HANDLE duplicate_handle = INVALID_HANDLE_VALUE;
if (DuplicateHandle(
::GetCurrentProcess(), initial_client_data.client_process(),
::GetCurrentProcess(), &duplicate_handle,
PROCESS_QUERY_INFORMATION, FALSE, DUPLICATE_SAME_ACCESS)) {
base::Process parent_process(duplicate_handle);
exit_code_watcher =
std::make_unique<browser_watcher::ExitCodeWatcher>();
if (exit_code_watcher->Initialize(std::move(parent_process))) {
exit_code_watcher->StartWatching();
}
}
}
}
// The handler process must always be passed the user data dir on the
// command line.
DCHECK(command_line->HasSwitch(switches::kUserDataDir));
base::FilePath user_data_dir =
command_line->GetSwitchValuePath(switches::kUserDataDir);
int crashpad_status = crash_reporter::RunAsCrashpadHandler(
*base::CommandLine::ForCurrentProcess(), user_data_dir,
switches::kProcessType, switches::kUserDataDir);
if (crashpad_status != 0 && exit_code_watcher) {
// Crashpad failed to initialize, explicitly stop the exit code watcher
// so the crashpad-handler process can exit with an error
exit_code_watcher->StopWatching();
}
return crashpad_status;
} else if (process_type == crash_reporter::switches::kFallbackCrashHandler) {
return RunFallbackCrashHandler(*command_line);
}
const base::TimeTicks exe_entry_point_ticks = base::TimeTicks::Now();
// Signal Chrome Elf that Chrome has begun to start.
SignalChromeElf();
// The exit manager is in charge of calling the dtors of singletons.
base::AtExitManager exit_manager;
// Only enable High DPI support for browser and GPU process.
if (process_type.empty() || process_type == switches::kGpuProcess)
base::win::EnableHighDPISupport();
if (AttemptFastNotify(*command_line))
return 0;
RemoveAppCompatFlagsEntry();
// Load and launch the chrome dll. *Everything* happens inside.
VLOG(1) << "About to load main DLL.";
MainDllLoader* loader = MakeMainDllLoader();
int rc = loader->Launch(instance, exe_entry_point_ticks);
loader->RelaunchChromeBrowserWithNewCommandLineIfNeeded();
delete loader;
// Process shutdown is hard and some process types have been crashing during
// shutdown. TerminateProcess is safer and faster.
if (process_type == switches::kUtilityProcess ||
process_type == switches::kPpapiPluginProcess) {
TerminateProcess(GetCurrentProcess(), rc);
}
return rc;
}
重点在行:96、97、98,源文件行:270、271、272。
MainDllLoader* loader = MakeMainDllLoader();
int rc = loader->Launch(instance, exe_entry_point_ticks);
loader->RelaunchChromeBrowserWithNewCommandLineIfNeeded();
\src\chrome\app\main_dll_loader_win.cc
MainDllLoader* MakeMainDllLoader() {
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
return new ChromeDllLoader();
#else
return new ChromiumDllLoader();
#endif
}
ChromeDllLoader和ChromiumDllLoader都继承自MainDllLoader
loader->Launch(instance, exe_entry_point_ticks)实际调用 int MainDllLoader::Launch(HINSTANCE instance, base::TimeTicks exe_entry_point_ticks)。
// Launching is a matter of loading the right dll and calling the entry point.
// Derived classes can add custom code in the OnBeforeLaunch callback.
int MainDllLoader::Launch(HINSTANCE instance,
base::TimeTicks exe_entry_point_ticks) {
const base::CommandLine& cmd_line = *base::CommandLine::ForCurrentProcess();
process_type_ = cmd_line.GetSwitchValueASCII(switches::kProcessType);
// Initialize the sandbox services.
sandbox::SandboxInterfaceInfo sandbox_info = {0};
const bool is_browser = process_type_.empty();
const bool is_sandboxed =
!cmd_line.HasSwitch(service_manager::switches::kNoSandbox);
if (is_browser || is_sandboxed) {
// For child processes that are running as --no-sandbox, don't initialize
// the sandbox info, otherwise they'll be treated as brokers (as if they
// were the browser).
content::InitializeSandboxInfo(&sandbox_info);
}
base::FilePath file;
dll_ = Load(&file);
if (!dll_)
return chrome::RESULT_CODE_MISSING_DATA;
if (!is_browser) {
// Set non-browser processes up to be killed by the system after the
// browser goes away. The browser uses the default shutdown order, which
// is 0x280. Note that lower numbers here denote "kill later" and higher
// numbers mean "kill sooner". This gets rid of most of those unsightly
// sad tabs on logout and shutdown.
::SetProcessShutdownParameters(kNonBrowserShutdownPriority - 1,
SHUTDOWN_NORETRY);
}
OnBeforeLaunch(cmd_line, process_type_, file);
DLL_MAIN chrome_main =
reinterpret_cast<DLL_MAIN>(::GetProcAddress(dll_, "ChromeMain"));
int rc = chrome_main(instance, &sandbox_info,
exe_entry_point_ticks.ToInternalValue());
return rc;
}
重点在行:36、37、38、39,源文件行:175、176、177、178。
DLL_MAIN chrome_main = reinterpret_cast<DLL_MAIN>(::GetProcAddress(dll_, "ChromeMain"));
int rc = chrome_main(instance, &sandbox_info,exe_entry_point_ticks.ToInternalValue());
二、ChromeMain
\src\chrome\app\chrome_main.cc 源文件行:49
#if defined(OS_WIN)
DLLEXPORT int __cdecl ChromeMain(HINSTANCE instance,
sandbox::SandboxInterfaceInfo* sandbox_info,
int64_t exe_entry_point_ticks) {
#elif defined(OS_POSIX)
int ChromeMain(int argc, const char** argv) {
int64_t exe_entry_point_ticks = 0;
#endif
#if defined(OS_WIN)
install_static::InitializeFromPrimaryModule();
#endif
ChromeMainDelegate chrome_main_delegate(
base::TimeTicks::FromInternalValue(exe_entry_point_ticks));
content::ContentMainParams params(&chrome_main_delegate);
#if defined(OS_WIN)
// The process should crash when going through abnormal termination, but we
// must be sure to reset this setting when ChromeMain returns normally.
auto crash_on_detach_resetter = base::ScopedClosureRunner(
base::BindOnce(&base::win::SetShouldCrashOnProcessDetach,
base::win::ShouldCrashOnProcessDetach()));
base::win::SetShouldCrashOnProcessDetach(true);
base::win::SetAbortBehaviorForCrashReporting();
params.instance = instance;
params.sandbox_info = sandbox_info;
// Pass chrome_elf's copy of DumpProcessWithoutCrash resolved via load-time
// dynamic linking.
base::debug::SetDumpWithoutCrashingFunction(&DumpProcessWithoutCrash);
// Verify that chrome_elf and this module (chrome.dll and chrome_child.dll)
// have the same version.
if (install_static::InstallDetails::Get().VersionMismatch())
base::debug::DumpWithoutCrashing();
#else
params.argc = argc;
params.argv = argv;
base::CommandLine::Init(params.argc, params.argv);
#endif // defined(OS_WIN)
base::CommandLine::Init(0, nullptr);
const base::CommandLine* command_line(base::CommandLine::ForCurrentProcess());
ALLOW_UNUSED_LOCAL(command_line);
#if defined(OS_MACOSX)
SetUpBundleOverrides();
#endif
// Start the sampling profiler as early as possible - namely, once the command
// line data is available. Allocated as an object on the stack to ensure that
// the destructor runs on shutdown, which is important to avoid the profiler
// thread's destruction racing with main thread destruction.
MainThreadStackSamplingProfiler scoped_sampling_profiler;
// Chrome-specific process modes.
#if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN)
if (command_line->HasSwitch(switches::kHeadless)) {
return headless::HeadlessShellMain(params);
}
#endif // defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN)
int rv = content::ContentMain(params);
return rv;
}
重点在行:14、15、16 ,源文件行:61。
ChromeMainDelegate chrome_main_delegate(
base::TimeTicks::FromInternalValue(exe_entry_point_ticks));
content::ContentMainParams params(&chrome_main_delegate);
还有在行63,源文件行:110。
int rv = content::ContentMain(params);
三、ContentMain
\src\content\app\content_main.cc 源文件行:12
int ContentMain(const ContentMainParams& params) {
ContentServiceManagerMainDelegate delegate(params);
service_manager::MainParams main_params(&delegate);
#if !defined(OS_WIN) && !defined(OS_ANDROID)
main_params.argc = params.argc;
main_params.argv = params.argv;
#endif
return service_manager::Main(main_params);
}
四、service_manager::Main
\src\services\service_manager\embedder\main.cc 源文件行:253
int Main(const MainParams& params) {
MainDelegate* delegate = params.delegate;
DCHECK(delegate);
int exit_code = -1;
base::debug::GlobalActivityTracker* tracker = nullptr;
ProcessType process_type = delegate->OverrideProcessType();
#if defined(OS_MACOSX)
std::unique_ptr<base::mac::ScopedNSAutoreleasePool> autorelease_pool;
#endif
// A flag to indicate whether Main() has been called before. On Android, we
// may re-run Main() without restarting the browser process. This flag
// prevents initializing things more than once.
static bool is_initialized = false;
#if !defined(OS_ANDROID)
DCHECK(!is_initialized);
#endif
if (!is_initialized) {
is_initialized = true;
#if defined(OS_MACOSX) && BUILDFLAG(USE_ALLOCATOR_SHIM)
base::allocator::InitializeAllocatorShim();
#endif
base::EnableTerminationOnOutOfMemory();
#if defined(OS_LINUX)
// The various desktop environments set this environment variable that
// allows the dbus client library to connect directly to the bus. When this
// variable is not set (test environments like xvfb-run), the dbus client
// library will fall back to auto-launch mode. Auto-launch is dangerous as
// it can cause hangs (crbug.com/715658) . This one line disables the dbus
// auto-launch, by clobbering the DBUS_SESSION_BUS_ADDRESS env variable if
// not already set. The old auto-launch behavior, if needed, can be restored
// by setting DBUS_SESSION_BUS_ADDRESS="autolaunch:" before launching
// chrome.
const int kNoOverrideIfAlreadySet = 0;
setenv("DBUS_SESSION_BUS_ADDRESS", "disabled:", kNoOverrideIfAlreadySet);
#endif
#if defined(OS_WIN)
base::win::RegisterInvalidParamHandler();
ui::win::CreateATLModuleIfNeeded();
#endif // defined(OS_WIN)
#if !defined(OS_ANDROID)
// On Android, the command line is initialized when library is loaded.
int argc = 0;
const char** argv = nullptr;
#if !defined(OS_WIN)
// argc/argv are ignored on Windows; see command_line.h for details.
argc = params.argc;
argv = params.argv;
#endif
base::CommandLine::Init(argc, argv);
#if defined(OS_POSIX)
PopulateFDsFromCommandLine();
#endif
base::EnableTerminationOnHeapCorruption();
SetProcessTitleFromCommandLine(argv);
#endif // !defined(OS_ANDROID)
// On Android setlocale() is not supported, and we don't override the signal
// handlers so we can get a stack trace when crashing.
#if defined(OS_POSIX) && !defined(OS_ANDROID)
// Set C library locale to make sure CommandLine can parse
// argument values in the correct encoding and to make sure
// generated file names (think downloads) are in the file system's
// encoding.
setlocale(LC_ALL, "");
// For numbers we never want the C library's locale sensitive
// conversion from number to string because the only thing it
// changes is the decimal separator which is not good enough for
// the UI and can be harmful elsewhere. User interface number
// conversions need to go through ICU. Other conversions need to
// be locale insensitive so we force the number locale back to the
// default, "C", locale.
setlocale(LC_NUMERIC, "C");
SetupSignalHandlers();
#endif
const auto& command_line = *base::CommandLine::ForCurrentProcess();
#if defined(OS_WIN)
base::win::SetupCRT(command_line);
#endif
MainDelegate::InitializeParams init_params;
#if defined(OS_MACOSX)
// We need this pool for all the objects created before we get to the event
// loop, but we don't want to leave them hanging around until the app quits.
// Each "main" needs to flush this pool right before it goes into its main
// event loop to get rid of the cruft.
autorelease_pool = std::make_unique<base::mac::ScopedNSAutoreleasePool>();
init_params.autorelease_pool = autorelease_pool.get();
InitializeMac();
#endif
mojo::core::Configuration mojo_config;
if (process_type == ProcessType::kDefault &&
command_line.GetSwitchValueASCII(switches::kProcessType) ==
switches::kProcessTypeServiceManager) {
mojo_config.is_broker_process = true;
}
mojo_config.max_message_num_bytes = kMaximumMojoMessageSize;
delegate->OverrideMojoConfiguration(&mojo_config);
mojo::core::Init(mojo_config);
ui::RegisterPathProvider();
tracker = base::debug::GlobalActivityTracker::Get();
exit_code = delegate->Initialize(init_params);
if (exit_code >= 0) {
if (tracker) {
tracker->SetProcessPhase(
base::debug::GlobalActivityTracker::PROCESS_LAUNCH_FAILED);
tracker->process_data().SetInt("exit-code", exit_code);
}
return exit_code;
}
// Note #1: the installed shared memory hooks require a live instance of
// mojo::core::ScopedIPCSupport to function, which is instantiated below by
// the process type's main function. However, some implementations of the
// service_manager::MainDelegate::Initialize() delegate method allocate
// shared memory, so the hooks cannot be installed before the Initialize()
// call above, or the shared memory allocation will simply fail.
//
// Note #2: some platforms can directly allocated shared memory in a
// sandboxed process. The defines below must be in sync with the
// implementation of mojo::NodeController::CreateSharedBuffer().
#if !defined(OS_MACOSX) && !defined(OS_NACL_SFI) && !defined(OS_FUCHSIA)
if (service_manager::IsUnsandboxedSandboxType(
service_manager::SandboxTypeFromCommandLine(command_line))) {
// Unsandboxed processes don't need shared memory brokering... because
// they're not sandboxed.
} else if (mojo_config.force_direct_shared_memory_allocation) {
// Don't bother with hooks if direct shared memory allocation has been
// requested.
} else {
// Sanity check, since installing the shared memory hooks in a broker
// process will lead to infinite recursion.
DCHECK(!mojo_config.is_broker_process);
// Otherwise, this is a sandboxed process that will need brokering to
// allocate shared memory.
mojo::SharedMemoryUtils::InstallBaseHooks();
}
#endif // !defined(OS_MACOSX) && !defined(OS_NACL_SFI) && !defined(OS_FUCHSIA)
#if defined(OS_WIN)
// Route stdio to parent console (if any) or create one.
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableLogging)) {
base::RouteStdioToConsole(true);
}
#endif
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
::switches::kTraceToConsole)) {
base::trace_event::TraceConfig trace_config =
tracing::GetConfigForTraceToConsole();
base::trace_event::TraceLog::GetInstance()->SetEnabled(
trace_config, base::trace_event::TraceLog::RECORDING_MODE);
}
}
const auto& command_line = *base::CommandLine::ForCurrentProcess();
if (process_type == ProcessType::kDefault) {
std::string type_switch =
command_line.GetSwitchValueASCII(switches::kProcessType);
if (type_switch == switches::kProcessTypeServiceManager) {
process_type = ProcessType::kServiceManager;
} else if (type_switch == switches::kProcessTypeService) {
process_type = ProcessType::kService;
} else {
process_type = ProcessType::kEmbedder;
}
}
switch (process_type) {
case ProcessType::kDefault:
NOTREACHED();
break;
case ProcessType::kServiceManager:
exit_code = RunServiceManager(delegate);
break;
case ProcessType::kService:
CommonSubprocessInit();
exit_code = RunService(delegate);
break;
case ProcessType::kEmbedder:
if (delegate->IsEmbedderSubprocess())
CommonSubprocessInit();
exit_code = delegate->RunEmbedderProcess();
break;
}
if (tracker) {
if (exit_code == 0) {
tracker->SetProcessPhaseIfEnabled(
base::debug::GlobalActivityTracker::PROCESS_EXITED_CLEANLY);
} else {
tracker->SetProcessPhaseIfEnabled(
base::debug::GlobalActivityTracker::PROCESS_EXITED_WITH_CODE);
tracker->process_data().SetInt("exit-code", exit_code);
}
}
#if defined(OS_MACOSX)
autorelease_pool.reset();
#endif
if (process_type == ProcessType::kEmbedder)
delegate->ShutDownEmbedderProcess();
return exit_code;
}
重点在行:2,源文件行:254。
MainDelegate* delegate = params.delegate;
还有在行:199、200、201、202、203、204, 源文件行:451、452、453、454、455、456。
case ProcessType::kEmbedder:
if (delegate->IsEmbedderSubprocess())
CommonSubprocessInit();
exit_code = delegate->RunEmbedderProcess();
break;
delegate->RunEmbedderProcess() 实际调用ContentServiceManagerMainDelegate::RunEmbedderProcess()经行窗口创建等过程。