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 @ 2023-10-12 17:31  Bigben  阅读(154)  评论(0编辑  收藏  举报