chrome headless启动
1. D:\chromium110\chromium\src\chrome\app\chrome_exe_main_win.cc
#if !defined(WIN_CONSOLE_APP) ////////////非headless模式 int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prev, wchar_t*, int) { #else // !defined(WIN_CONSOLE_APP) ////////////headless模式 int main() { HINSTANCE instance = GetModuleHandle(nullptr); #endif // !defined(WIN_CONSOLE_APP) SetCwdForBrowserProcess(); install_static::InitializeFromPrimaryModule() // Initialize the CommandLine singleton from the environment. base::CommandLine::Init(0, nullptr); const base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); 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; if (AttemptFastNotify(*command_line)) return 0; // Load and launch the chrome dll. *Everything* happens inside. VLOG(1) << "About to load main DLL."; MainDllLoader* loader = MakeMainDllLoader(); 下面进入load,死循环中 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. TerminateCurrentProcessImmediately is safer and faster. if (process_type == switches::kUtilityProcess || process_type == switches::kPpapiPluginProcess) { base::Process::TerminateCurrentProcessImmediately(rc); } return rc; } 不停的读取消息 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 = {nullptr}; const bool is_browser = process_type_.empty(); // IsUnsandboxedSandboxType() can't be used here because its result can be // gated behind a feature flag, which are not yet initialized. const bool is_sandboxed = sandbox::policy::SandboxTypeFromCommandLine(cmd_line) != sandbox::mojom::Sandbox::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, IsExtensionPointDisableSet() ? sandbox::MITIGATION_EXTENSION_POINT_DISABLE : 0); } 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; } #if BUILDFLAG(IS_WIN) DLLEXPORT int __cdecl ChromeMain(HINSTANCE instance, sandbox::SandboxInterfaceInfo* sandbox_info, int64_t exe_entry_point_ticks) { #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) int ChromeMain(int argc, const char** argv) { int64_t exe_entry_point_ticks = 0; #else #error Unknown platform. #endif #if BUILDFLAG(IS_WIN) #if BUILDFLAG(USE_ALLOCATOR_SHIM) && BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) // Call this early on in order to configure heap workarounds. This must be // called from chrome.dll. This may be a NOP on some platforms. allocator_shim::ConfigurePartitionAlloc(); #endif install_static::InitializeFromPrimaryModule(); #endif // BUILDFLAG(IS_WIN) ChromeMainDelegate chrome_main_delegate( base::TimeTicks::FromInternalValue(exe_entry_point_ticks)); content::ContentMainParams params(&chrome_main_delegate); #if BUILDFLAG(IS_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 // BUILDFLAG(IS_WIN) base::CommandLine::Init(0, nullptr); [[maybe_unused]] base::CommandLine* command_line( base::CommandLine::ForCurrentProcess()); #if BUILDFLAG(IS_WIN) if (base::CommandLine::ForCurrentProcess()->HasSwitch( ::switches::kRaiseTimerFrequency)) { // Raise the timer interrupt frequency and leave it raised. timeBeginPeriod(1); } #endif #if BUILDFLAG(IS_MAC) 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 (headless::IsHeadlessMode()) { headless::SetUpCommandLine(command_line); } else { #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_MAC) || \ BUILDFLAG(IS_WIN) if (headless::IsOldHeadlessMode()) { #if BUILDFLAG(GOOGLE_CHROME_BRANDING) command_line->AppendSwitch(::headless::switches::kEnableCrashReporter); #endif return headless::HeadlessShellMain(std::move(params)); 、、、、、、、、、、、、、、、、、、、
D:\chromium110\chromium\src\headless\app\headless_shell.cc
int HeadlessShellMain(int argc, const char** argv) { base::CommandLine::Init(argc, argv); RunChildProcessIfNeeded(argc, argv); HeadlessBrowser::Options::Builder builder(argc, argv); #endif // BUILDFLAG(IS_WIN) base::CommandLine& command_line(*base::CommandLine::ForCurrentProcess()); #if BUILDFLAG(IS_MAC) command_line.AppendSwitch(os_crypt::switches::kUseMockKeychain); #endif #if BUILDFLAG(IS_FUCHSIA) // TODO(fuchsia): Remove this when GPU accelerated compositing is ready. command_line.AppendSwitch(::switches::kDisableGpu); #endif if (command_line.GetArgs().size() > 1) { LOG(ERROR) << "Multiple targets are not supported."; return EXIT_FAILURE; } if (!HandleCommandLineSwitches(command_line, builder)) return EXIT_FAILURE; HeadlessShell shell; return HeadlessBrowserMain( builder.Build(), base::BindOnce(&HeadlessShell::OnBrowserStart, base::Unretained(&shell))); } int HeadlessShellMain(const content::ContentMainParams& params) { #if BUILDFLAG(IS_WIN) return HeadlessShellMain(params.instance, params.sandbox_info);
到
int HeadlessShellMain(HINSTANCE instance, sandbox::SandboxInterfaceInfo* sandbox_info) { base::CommandLine::Init(0, nullptr); #if defined(HEADLESS_USE_CRASHPAD) std::string process_type = base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( ::switches::kProcessType); if (process_type == crash_reporter::switches::kCrashpadHandler) { return crash_reporter::RunAsCrashpadHandler( *base::CommandLine::ForCurrentProcess(), base::FilePath(), ::switches::kProcessType, switches::kUserDataDir); } #endif // defined(HEADLESS_USE_CRASHPAD) RunChildProcessIfNeeded(instance, sandbox_info);
到D:\chromium110\chromium\src\headless\app\headless_shell.cc
void RunChildProcessIfNeeded(int argc, const char** argv) { base::CommandLine::Init(argc, argv); HeadlessBrowser::Options::Builder builder(argc, argv); #endif // BUILDFLAG(IS_WIN) const base::CommandLine& command_line( *base::CommandLine::ForCurrentProcess()); if (!command_line.HasSwitch(::switches::kProcessType)) return; if (command_line.HasSwitch(switches::kUserAgent)) { std::string user_agent = command_line.GetSwitchValueASCII(switches::kUserAgent); #if 1 // dxf:agent, 2023-07-27,添加特殊标识 user_agent = user_agent.append(" Eversec"); #endif if (net::HttpUtil::IsValidHeaderValue(user_agent)) builder.SetUserAgent(user_agent); } int rc = RunContentMain(builder.Build(), base::OnceCallback<void(HeadlessBrowser*)>());
RunContentMain,到这里,headless的app实现完毕。下面进入了chromium的content层:
int RunContentMain( HeadlessBrowser::Options options, base::OnceCallback<void(HeadlessBrowser*)> on_browser_start_callback) { content::ContentMainParams params(nullptr); #if BUILDFLAG(IS_WIN) // Sandbox info has to be set and initialized. CHECK(options.sandbox_info); params.instance = options.instance; params.sandbox_info = std::move(options.sandbox_info); #elif !BUILDFLAG(IS_ANDROID) params.argc = options.argc; params.argv = options.argv; #endif // TODO(skyostil): Implement custom message pumps. DCHECK(!options.message_pump); auto browser = std::make_unique<HeadlessBrowserImpl>( std::move(on_browser_start_callback), std::move(options)); HeadlessContentMainDelegate delegate(std::move(browser)); params.delegate = &delegate; return content::ContentMain(std::move(params));
进入content模块,创建 runner,进入 RunContentProcess,执行 content_main_runner->Run(); 无限循环。取任务执行。
下面的代码显示了要启动几个进程
static const MainFunction kMainFunctions[] = {
#if BUILDFLAG(ENABLE_PPAPI)
{switches::kPpapiPluginProcess, PpapiPluginMain},
#endif // BUILDFLAG(ENABLE_PPAPI)
{switches::kUtilityProcess, UtilityMain},
{switches::kRendererProcess, RendererMain},
{switches::kGpuProcess, GpuMain},
};
// Run the FooMain() for a given process type. // Returns the exit code for this process. // This function must be marked with NO_STACK_PROTECTOR or it may crash on // return, see the --change-stack-guard-on-fork command line flag. int NO_STACK_PROTECTOR RunOtherNamedProcessTypeMain(const std::string& process_type, MainFunctionParams main_function_params, ContentMainDelegate* delegate) { #if BUILDFLAG(IS_WIN) if (delegate->ShouldHandleConsoleControlEvents()) InstallConsoleControlHandler(/*is_browser_process=*/false); #endif static const MainFunction kMainFunctions[] = { #if BUILDFLAG(ENABLE_PPAPI) {switches::kPpapiPluginProcess, PpapiPluginMain}, #endif // BUILDFLAG(ENABLE_PPAPI) {switches::kUtilityProcess, UtilityMain}, {switches::kRendererProcess, RendererMain}, {switches::kGpuProcess, GpuMain}, }; // The hang watcher needs to be started once the feature list is available // but before the IO thread is started. base::ScopedClosureRunner unregister_thread_closure; if (base::HangWatcher::IsEnabled()) { base::HangWatcher::CreateHangWatcherInstance(); unregister_thread_closure = base::HangWatcher::RegisterThread( base::HangWatcher::ThreadType::kMainThread); base::HangWatcher::GetInstance()->Start(); } for (size_t i = 0; i < std::size(kMainFunctions); ++i) { if (process_type == kMainFunctions[i].name) { auto exit_code = delegate->RunProcess(process_type, std::move(main_function_params)); if (absl::holds_alternative<int>(exit_code)) { DCHECK_GE(absl::get<int>(exit_code), 0); return absl::get<int>(exit_code); } return kMainFunctions[i].function( std::move(absl::get<MainFunctionParams>(exit_code))); } } #if BUILDFLAG(USE_ZYGOTE_HANDLE) // Zygote startup is special -- see RunZygote comments above // for why we don't use ZygoteMain directly. if (process_type == switches::kZygoteProcess) return RunZygote(delegate); #endif // BUILDFLAG(USE_ZYGOTE_HANDLE) // If it's a process we don't know about, the embedder should know. auto exit_code = delegate->RunProcess(process_type, std::move(main_function_params)); DCHECK(absl::holds_alternative<int>(exit_code)); DCHECK_GE(absl::get<int>(exit_code), 0); return absl::get<int>(exit_code); }
通过函数回调,有的走到 RendererMain的生成中:
int RendererMain(MainFunctionParams parameters)
里面也有loop
// It's not a memory leak since RenderThread has the same lifetime
// as a renderer process.
base::RunLoop run_loop;
new RenderThreadImpl(run_loop.QuitClosure(),
std::move(main_thread_scheduler));
// Multi-process mode. RenderThreadImpl::RenderThreadImpl( base::RepeatingClosure quit_closure, std::unique_ptr<blink::scheduler::WebThreadScheduler> scheduler) : ChildThreadImpl( std::move(quit_closure), Options::Builder() .ConnectToBrowser(true) .IPCTaskRunner(scheduler->DeprecatedDefaultTaskRunner()) .ExposesInterfacesToBrowser() .Build()), main_thread_scheduler_(std::move(scheduler)), client_id_(GetClientIdFromCommandLine()) { TRACE_EVENT0("startup", "RenderThreadImpl::Create"); Init(); } 到 void RenderThreadImpl::Init() 到 void RenderThreadImpl::InitializeWebKit(mojo::BinderMap* binders) void RenderThreadImpl::InitializeWebKit(mojo::BinderMap* binders) { DCHECK(!blink_platform_impl_); const base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); #ifdef ENABLE_VTUNE_JIT_INTERFACE if (command_line.HasSwitch(switches::kEnableVtune)) gin::Debug::SetJitCodeEventHandler(vTune::GetVtuneCodeEventHandler()); #endif blink_platform_impl_ = std::make_unique<RendererBlinkPlatformImpl>(main_thread_scheduler_.get()); // This, among other things, enables any feature marked "test" in // runtime_enabled_features. It is run before // SetRuntimeFeaturesDefaultsAndUpdateFromArgs() so that command line // arguments take precedence over (and can disable) "test" features. GetContentClient() ->renderer() ->SetRuntimeFeaturesDefaultsBeforeBlinkInitialization(); SetRuntimeFeaturesDefaultsAndUpdateFromArgs(command_line); blink::Initialize(blink_platform_impl_.get(), binders, main_thread_scheduler_.get()); v8::Isolate* isolate = blink::MainThreadIsolate(); isolate->SetAddCrashKeyCallback(AddCrashKey); if (!command_line.HasSwitch(switches::kDisableThreadedCompositing)) InitializeCompositorThread(); 这里有个 kDisableThreadedCompositing控制是否使用合成线程???????? --disable-threaded-compositing 禁用Web内容的多线程GPU合成。 到 void RenderThreadImpl::InitializeCompositorThread() { blink_platform_impl_->CreateAndSetCompositorThread(); compositor_task_runner_ = blink_platform_impl_->CompositorThreadTaskRunner(); compositor_task_runner_->PostTask(FROM_HERE, base::BindOnce(&base::DisallowBlocking)); GetContentClient()->renderer()->PostCompositorThreadCreated( compositor_task_runner_.get()); } 到 void Platform::CreateAndSetCompositorThread() { Thread::CreateAndSetCompositorThread(); } 到 void Thread::CreateAndSetCompositorThread() { DCHECK(!GetCompositorThread()); ThreadCreationParams params(ThreadType::kCompositorThread); params.base_thread_type = base::ThreadType::kCompositing; auto compositor_thread = std::make_unique<scheduler::CompositorThread>(params); compositor_thread->Init();..... 到 void NonMainThreadImpl::Init() { thread_->CreateScheduler();。。。。。。。接 thread_->StartAsync(); } 到 void NonMainThreadImpl::SimpleThreadImpl::CreateScheduler() { DCHECK(!non_main_thread_scheduler_); DCHECK(!default_task_runner_); DCHECK(sequence_manager_); non_main_thread_scheduler_ = thread_->CreateNonMainThreadScheduler(sequence_manager_.get()); 最终创建个全局的是否要用合成线程
namespace { scheduler::CompositorThreadSchedulerImpl* g_compositor_thread_scheduler = nullptr; } // namespace // static blink::CompositorThreadScheduler* ThreadScheduler::CompositorThreadScheduler() { return g_compositor_thread_scheduler; } namespace scheduler { CompositorThreadSchedulerImpl::CompositorThreadSchedulerImpl( base::sequence_manager::SequenceManager* sequence_manager) : NonMainThreadSchedulerBase(sequence_manager, TaskType::kCompositorThreadTaskQueueDefault), compositor_metrics_helper_(GetHelper().HasCPUTimingForEachTask()) { DCHECK(!g_compositor_thread_scheduler); g_compositor_thread_scheduler = this; }
BrowserMainLoop::PreMainMessageLoopRun()中进入 parts_->PreMainMessageLoopRun();
即 ChromeBrowserMainParts::PreMainMessageLoopRun() 进入 PreMainMessageLoopRunImpl
即 ChromeBrowserMainParts::PreMainMessageLoopRunImpl()
int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() {
// Now that the file thread has been started, start metrics.
StartMetricsRecording();// Do any initializating in the browser process that requires all threads
// running.
browser_process_->PreMainMessageLoopRun();// Record last shutdown time into a histogram.
browser_shutdown::ReadLastShutdownInfo();#if BUILDFLAG(IS_WIN)
// If the command line specifies 'uninstall' then we need to work here
// unless we detect another chrome browser running.
if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kUninstall)) {
return DoUninstallTasks(browser_util::IsBrowserAlreadyRunning());
}if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kHideIcons) ||
base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kShowIcons)) {
return ChromeBrowserMainPartsWin::HandleIconsCommands(
*base::CommandLine::ForCurrentProcess());
}ui::SelectFileDialog::SetFactory(new ChromeSelectFileDialogFactory());
#endif // BUILDFLAG(IS_WIN)if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kMakeDefaultBrowser)) {
bool is_managed = g_browser_process->local_state()->IsManagedPreference(
prefs::kDefaultBrowserSettingEnabled);
if (is_managed && !g_browser_process->local_state()->GetBoolean(
prefs::kDefaultBrowserSettingEnabled)) {
return static_cast<int>(chrome::RESULT_CODE_ACTION_DISALLOWED_BY_POLICY);
}return shell_integration::SetAsDefaultBrowser()
? static_cast<int>(content::RESULT_CODE_NORMAL_EXIT)
: static_cast<int>(chrome::RESULT_CODE_SHELL_INTEGRATION_FAILED);
}#if defined(USE_AURA)
// Make sure aura::Env has been initialized.
CHECK(aura::Env::GetInstance());
#endif // defined(USE_AURA)#if BUILDFLAG(ENABLE_PROCESS_SINGLETON)
if (!ChromeProcessSingleton::IsEarlySingletonFeatureEnabled()) {
// When another process is running, use that process instead of starting a
// new one. NotifyOtherProcess will currently give the other process up to
// 20 seconds to respond. Note that this needs to be done before we attempt
// to read the profile.
notify_result_ =
ChromeProcessSingleton::GetInstance()->NotifyOtherProcessOrCreate();
UMA_HISTOGRAM_ENUMERATION("Chrome.ProcessSingleton.NotifyResult",
notify_result_,
ProcessSingleton::kNumNotifyResults);
switch (notify_result_) {
case ProcessSingleton::PROCESS_NONE:
// No process already running, fall through to starting a new one.
ChromeProcessSingleton::GetInstance()->StartWatching();
g_browser_process->platform_part()
->PlatformSpecificCommandLineProcessing(
*base::CommandLine::ForCurrentProcess());
break;case ProcessSingleton::PROCESS_NOTIFIED:
printf("%s\n", base::SysWideToNativeMB(
base::UTF16ToWide(l10n_util::GetStringUTF16(
IDS_USED_EXISTING_BROWSER)))
.c_str());
return chrome::RESULT_CODE_NORMAL_EXIT_PROCESS_NOTIFIED;case ProcessSingleton::PROFILE_IN_USE:
return chrome::RESULT_CODE_PROFILE_IN_USE;case ProcessSingleton::LOCK_ERROR:
LOG(ERROR) << "Failed to create a ProcessSingleton for your profile "
"directory. This means that running multiple instances "
"would start multiple browser processes rather than "
"opening a new window in the existing process. Aborting "
"now to avoid profile corruption.";
return chrome::RESULT_CODE_PROFILE_IN_USE;
}
}
#endif // BUILDFLAG(ENABLE_PROCESS_SINGLETON)#if BUILDFLAG(IS_WIN)
// We must call DoUpgradeTasks now that we own the browser singleton to
// finish upgrade tasks (swap) and relaunch if necessary.
if (upgrade_util::DoUpgradeTasks(*base::CommandLine::ForCurrentProcess()))
return chrome::RESULT_CODE_NORMAL_EXIT_UPGRADE_RELAUNCHED;
#endif // BUILDFLAG(IS_WIN)#if !BUILDFLAG(IS_ANDROID) && BUILDFLAG(ENABLE_DOWNGRADE_PROCESSING)
// Begin relaunch processing immediately if User Data migration is required
// to handle a version downgrade.
if (downgrade_manager_.PrepareUserDataDirectoryForCurrentVersion(
user_data_dir_)) {
return chrome::RESULT_CODE_DOWNGRADE_AND_RELAUNCH;
}
downgrade_manager_.UpdateLastVersion(user_data_dir_);
#endif // !BUILDFLAG(IS_ANDROID) && BUILDFLAG(ENABLE_DOWNGRADE_PROCESSING)#if !BUILDFLAG(IS_CHROMEOS_ASH)
// Initialize the chrome browser cloud management controller after
// the browser process singleton is acquired to remove race conditions where
// multiple browser processes start simultaneously. The main
// initialization of browser_policy_connector is performed inside
// PreMainMessageLoopRun() so that policies can be applied as soon as
// possible.
//
// Note that this protects against multiple browser process starts in
// the same user data dir and not multiple starts across user data dirs.
browser_process_->browser_policy_connector()->InitCloudManagementController(
browser_process_->local_state(),
browser_process_->system_network_context_manager()
->GetSharedURLLoaderFactory());
#endif // !BUILDFLAG(IS_CHROMEOS_ASH)#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
// Wait for the chrome browser cloud management enrollment to finish.
// If enrollment is not mandatory, this function returns immediately.
// Abort the launch process if required enrollment fails.
if (!browser_process_->browser_policy_connector()
->chrome_browser_cloud_management_controller()
->WaitUntilPolicyEnrollmentFinished()) {
return chrome::RESULT_CODE_CLOUD_POLICY_ENROLLMENT_FAILED;
}
#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)#if BUILDFLAG(ENABLE_PROCESS_SINGLETON)
// Handle special early return paths (which couldn't be processed even earlier
// as they require the process singleton to be held) first.std::string try_chrome =
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kTryChromeAgain);// The TryChromeDialog may be aborted by a rendezvous from another browser
// process (e.g., a launch via Chrome's taskbar icon or some such). In this
// case, browser startup should continue without processing the original
// command line (the one with --try-chrome-again), but rather with the command
// line from the other process (handled in
// ProcessSingletonNotificationCallback thanks to the ProcessSingleton). The
// |process_command_line| variable is cleared in that particular case, leading
// to a bypass of the StartupBrowserCreator.
bool process_command_line = true;
if (!try_chrome.empty()) {
#if BUILDFLAG(IS_WIN)
// Setup.exe has determined that we need to run a retention experiment
// and has lauched chrome to show the experiment UI. It is guaranteed that
// no other Chrome is currently running as the process singleton was
// successfully grabbed above.
int try_chrome_int;
base::StringToInt(try_chrome, &try_chrome_int);
TryChromeDialog::Result answer = TryChromeDialog::Show(
try_chrome_int,
base::BindRepeating(
&ChromeProcessSingleton::SetModalDialogNotificationHandler,
base::Unretained(ChromeProcessSingleton::GetInstance())));
switch (answer) {
case TryChromeDialog::NOT_NOW:
return chrome::RESULT_CODE_NORMAL_EXIT_CANCEL;
case TryChromeDialog::OPEN_CHROME_WELCOME:
browser_creator_->set_welcome_back_page(true);
break;
case TryChromeDialog::OPEN_CHROME_DEFAULT:
break;
case TryChromeDialog::OPEN_CHROME_DEFER:
process_command_line = false;
break;
}
#else
// We don't support retention experiments on Mac or Linux.
return content::RESULT_CODE_NORMAL_EXIT;
#endif // BUILDFLAG(IS_WIN)
}
#endif // BUILDFLAG(ENABLE_PROCESS_SINGLETON)#if BUILDFLAG(IS_WIN)
// Check if there is any machine level Chrome installed on the current
// machine. If yes and the current Chrome process is user level, we do not
// allow the user level Chrome to run. So we notify the user and uninstall
// user level Chrome.
// Note this check needs to happen here (after the process singleton was
// obtained but before potentially creating the first run sentinel).
if (ChromeBrowserMainPartsWin::CheckMachineLevelInstall())
return chrome::RESULT_CODE_MACHINE_LEVEL_INSTALL_EXISTS;
#endif // BUILDFLAG(IS_WIN)// Desktop construction occurs here, (required before profile creation).
PreProfileInit();#if BUILDFLAG(ENABLE_NACL)
// NaClBrowserDelegateImpl is accessed inside CreateInitialProfile().
// So make sure to create it before that.
nacl::NaClBrowser::SetDelegate(std::make_unique<NaClBrowserDelegateImpl>(
browser_process_->profile_manager()));
#endif // BUILDFLAG(ENABLE_NACL)// This step is costly and is already measured in Startup.CreateFirstProfile
// and more directly Profile.CreateAndInitializeProfile.
StartupProfileInfo profile_info = CreateInitialProfile(
/*cur_dir=*/base::FilePath(), *base::CommandLine::ForCurrentProcess());if (profile_info.mode == StartupProfileMode::kError)
return content::RESULT_CODE_NORMAL_EXIT;#if !BUILDFLAG(IS_ANDROID)
// The first run sentinel must be created after the process singleton was
// grabbed (where enabled) and no early return paths were otherwise hit above.
first_run::CreateSentinelIfNeeded();
#endif // !BUILDFLAG(IS_ANDROID)#if BUILDFLAG(ENABLE_BACKGROUND_MODE)
// Autoload any profiles which are running background apps.
// TODO(rlp): Do this on a separate thread. See http://crbug.com/99075.
browser_process_->profile_manager()->AutoloadProfiles();
#endif // BUILDFLAG(ENABLE_BACKGROUND_MODE)
// Post-profile init ---------------------------------------------------------TranslateService::Initialize();
if (base::FeatureList::IsEnabled(features::kGeoLanguage) ||
base::FeatureList::IsEnabled(language::kExplicitLanguageAsk) ||
language::GetOverrideLanguageModel() ==
language::OverrideLanguageModel::GEO) {
language::GeoLanguageProvider::GetInstance()->StartUp(
browser_process_->local_state());
}// Needs to be done before PostProfileInit, since login manager on CrOS is
// called inside PostProfileInit.
content::WebUIControllerFactory::RegisterFactory(
ChromeWebUIControllerFactory::GetInstance());
RegisterChromeWebUIConfigs();
RegisterChromeUntrustedWebUIConfigs();#if BUILDFLAG(IS_ANDROID)
page_info::SetPageInfoClient(new ChromePageInfoClient());
#endif// Needs to be done before PostProfileInit, to allow connecting DevTools
// before WebUI for the CrOS login that can be called inside PostProfileInit
g_browser_process->CreateDevToolsProtocolHandler();
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
::switches::kAutoOpenDevToolsForTabs))
g_browser_process->CreateDevToolsAutoOpener();// Needs to be done before PostProfileInit, since the SODA Installer setup is
// called inside PostProfileInit and depends on it.
#if BUILDFLAG(ENABLE_COMPONENT_UPDATER)
if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableComponentUpdate)) {
component_updater::RegisterComponentsForUpdate();
}
#endif // BUILDFLAG(ENABLE_COMPONENT_UPDATER)// `profile` may be nullptr if the profile picker is shown.
Profile* profile = profile_info.profile;
// Call `PostProfileInit()`and set it up for profiles created later.
profile_init_manager_ = std::make_unique<ProfileInitManager>(this, profile);#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
// Execute first run specific code after the PrefService has been initialized
// and preferences have been registered since some of the import code depends
// on preferences.
if (first_run::IsChromeFirstRun()) {
// `profile` may be nullptr even on first run, for example when the
// "BrowserSignin" policy is set to "Force". If so, skip the auto import.
if (profile) {
first_run::AutoImport(profile, master_prefs_->import_bookmarks_path);
}// Note: This can pop-up the first run consent dialog on Linux & Mac.
first_run::DoPostImportTasks(master_prefs_->make_chrome_default_for_user);// The first run dialog is modal, and spins a RunLoop, which could receive
// a SIGTERM, and call chrome::AttemptExit(). Exit cleanly in that case.
if (browser_shutdown::IsTryingToQuit())
return content::RESULT_CODE_NORMAL_EXIT;
}
#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)#if BUILDFLAG(IS_WIN)
// Sets things up so that if we crash from this point on, a dialog will
// popup asking the user to restart chrome. It is done this late to avoid
// testing against a bunch of special cases that are taken care early on.
ChromeBrowserMainPartsWin::PrepareRestartOnCrashEnviroment(
*base::CommandLine::ForCurrentProcess());// Registers Chrome with the Windows Restart Manager, which will restore the
// Chrome session when the computer is restarted after a system update.
// This could be run as late as WM_QUERYENDSESSION for system update reboots,
// but should run on startup if extended to handle crashes/hangs/patches.
// Also, better to run once here than once for each HWND's WM_QUERYENDSESSION.
if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kBrowserTest)) {
ChromeBrowserMainPartsWin::RegisterApplicationRestart(
*base::CommandLine::ForCurrentProcess());
}
#endif // BUILDFLAG(IS_WIN)// Configure modules that need access to resources.
net::NetModule::SetResourceProvider(ChromeNetResourceProvider);
media::SetLocalizedStringProvider(ChromeMediaLocalizedStringProvider);#if !BUILDFLAG(IS_ANDROID)
// In unittest mode, this will do nothing. In normal mode, this will create
// the global IntranetRedirectDetector instance, which will promptly go to
// sleep for seven seconds (to avoid slowing startup), and wake up afterwards
// to see if it should do anything else.
//
// A simpler way of doing all this would be to have some function which could
// give the time elapsed since startup, and simply have this object check that
// when asked to initialize itself, but this doesn't seem to exist.
//
// This can't be created in the BrowserProcessImpl constructor because it
// needs to read prefs that get set after that runs.
browser_process_->intranet_redirect_detector();
#endif#if BUILDFLAG(ENABLE_PRINT_PREVIEW) && !defined(OFFICIAL_BUILD)
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDebugPrint)) {
base::FilePath path =
base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(
switches::kDebugPrint);
if (!path.empty())
printing::PrintedDocument::SetDebugDumpPath(path);
}
#endif // BUILDFLAG(ENABLE_PRINT_PREVIEW) && !defined(OFFICIAL_BUILD)#if BUILDFLAG(ENABLE_PRINTING)
printing::InitializeProcessForPrinting();
#endifHandleTestParameters(*base::CommandLine::ForCurrentProcess());
// This has to come before the first GetInstance() call. PreBrowserStart()
// seems like a reasonable place to put this, except on Android,
// OfflinePageInfoHandler::Register() below calls GetInstance().
// TODO(thestig): See if the Android code below can be moved to later.
sessions::ContentSerializedNavigationDriver::SetInstance(
ChromeSerializedNavigationDriver::GetInstance());#if BUILDFLAG(ENABLE_OFFLINE_PAGES)
offline_pages::OfflinePageInfoHandler::Register();
#endif#if BUILDFLAG(ENABLE_NACL)
nacl::NaClProcessHost::EarlyStartup();
#endif // BUILDFLAG(ENABLE_NACL)PreBrowserStart();
variations::VariationsService* variations_service =
browser_process_->variations_service();
// Only call PerformPreMainMessageLoopStartup() on VariationsService outside
// of integration (browser) tests.
if (!is_integration_test())
variations_service->PerformPreMainMessageLoopStartup();#if BUILDFLAG(IS_ANDROID)
// The profile picker is never shown on Android.
DCHECK_EQ(profile_info.mode, StartupProfileMode::kBrowserWindow);
DCHECK(profile);
// Just initialize the policy prefs service here. Variations seed fetching
// will be initialized when the app enters foreground mode.
variations_service->set_policy_pref_service(profile->GetPrefs());
#else
// We are in regular browser boot sequence. Open initial tabs and enter the
// main message loop.
std::vector<Profile*> last_opened_profiles;
#if !BUILDFLAG(IS_CHROMEOS_ASH)
// On ChromeOS multiple profiles doesn't apply, and will break if we load
// them this early as the cryptohome hasn't yet been mounted (which happens
// only once we log in). And if we're launching a web app, we don't want to
// restore the last opened profiles.
if (!base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kAppId)) {
last_opened_profiles =
g_browser_process->profile_manager()->GetLastOpenedProfiles();
}
#endif // BUILDFLAG(IS_CHROMEOS_ASH)// This step is costly and is already measured in
// Startup.StartupBrowserCreator_Start.
// See the comment above for an explanation of |process_command_line|.
const bool started =
#if BUILDFLAG(ENABLE_PROCESS_SINGLETON)
!process_command_line ||
#endif // BUILDFLAG(ENABLE_PROCESS_SINGLETON)
browser_creator_->Start(*base::CommandLine::ForCurrentProcess(),
base::FilePath(), profile_info,
last_opened_profiles);
if (started) {
// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
// of lacros-chrome is complete.
#if BUILDFLAG(IS_WIN) || (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS))
// Initialize autoupdate timer. Timer callback costs basically nothing
// when browser is not in persistent mode, so it's OK to let it ride on
// the main thread. This needs to be done here because we don't want
// to start the timer when Chrome is run inside a test harness.
browser_process_->StartAutoupdateTimer();
#endif // BUILDFLAG(IS_WIN) || (BUILDFLAG(IS_LINUX) ||
// BUILDFLAG(IS_CHROMEOS_LACROS))// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
// of lacros-chrome is complete.
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
// On Linux, the running exe will be updated if an upgrade becomes
// available while the browser is running. We need to save the last
// modified time of the exe, so we can compare to determine if there is
// an upgrade while the browser is kept alive by a persistent extension.
upgrade_util::SaveLastModifiedTimeOfExe();
#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)// Record now as the last successful chrome start.
if (ShouldRecordActiveUse(*base::CommandLine::ForCurrentProcess()))
GoogleUpdateSettings::SetLastRunTime();// Create the RunLoop for MainMessageLoopRun() to use and transfer
// ownership of the browser's lifetime to the BrowserProcess.
DCHECK(!GetMainRunLoopInstance());
GetMainRunLoopInstance() = std::make_unique<base::RunLoop>();
browser_process_->SetQuitClosure(
GetMainRunLoopInstance()->QuitWhenIdleClosure());
}
browser_creator_.reset();
#endif // !BUILDFLAG(IS_ANDROID)PostBrowserStart();
#if BUILDFLAG(ENABLE_DOWNGRADE_PROCESSING)
// Clean up old user data directory, snapshots and disk cache directory.
downgrade_manager_.DeleteMovedUserDataSoon(user_data_dir_);
#endif// This should be invoked as close as possible to the start of the browser's
// main loop, but before the end of PreMainMessageLoopRun in order for
// browser tests (which InterceptMainMessageLoopRun rather than
// MainMessageLoopRun) to be able to see its side-effect.
if (result_code_ <= 0)
RecordBrowserStartupTime();return result_code_;
}
进入 StartupProfileInfo CreateInitialProfile 设置usr date目录
ProfileManager::CreateAndInitializeProfile
BrowserContextDependencyManager::GetInstance()->CreateBrowserContextServices( this);
进入:BrowserContextDependencyManager::DoCreateBrowserContextServices
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
2020-10-12 c++实用网址 书籍推荐 资源