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();
#endif

  HandleTestParameters(*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

posted @   Bigben  阅读(298)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
历史上的今天:
2020-10-12 c++实用网址 书籍推荐 资源
点击右上角即可分享
微信分享提示