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