void ElectronBrowserClient::AppendExtraCommandLineSwitches()

in shell/browser/electron_browser_client.cc [500:645]


void ElectronBrowserClient::AppendExtraCommandLineSwitches(
    base::CommandLine* command_line,
    int process_id) {
  // Make sure we're about to launch a known executable
  {
    base::ThreadRestrictions::ScopedAllowIO allow_io;
    base::FilePath child_path;
    base::FilePath program =
        base::MakeAbsoluteFilePath(command_line->GetProgram());
#if defined(OS_MAC)
    auto renderer_child_path = content::ChildProcessHost::GetChildPath(
        content::ChildProcessHost::CHILD_RENDERER);
    auto gpu_child_path = content::ChildProcessHost::GetChildPath(
        content::ChildProcessHost::CHILD_GPU);
#if BUILDFLAG(ENABLE_PLUGINS)
    auto plugin_child_path = content::ChildProcessHost::GetChildPath(
        content::ChildProcessHost::CHILD_PLUGIN);
#endif
    if (program != renderer_child_path && program != gpu_child_path
#if BUILDFLAG(ENABLE_PLUGINS)
        && program != plugin_child_path
#endif
    ) {
      child_path = content::ChildProcessHost::GetChildPath(
          content::ChildProcessHost::CHILD_NORMAL);
      CHECK_EQ(program, child_path)
          << "Aborted from launching unexpected helper executable";
    }
#else
    if (!base::PathService::Get(content::CHILD_PROCESS_EXE, &child_path)) {
      CHECK(false) << "Unable to get child process binary name.";
    }
    SCOPED_CRASH_KEY_STRING256("ChildProcess", "child_process_exe",
                               child_path.AsUTF8Unsafe());
    SCOPED_CRASH_KEY_STRING256("ChildProcess", "program",
                               program.AsUTF8Unsafe());
    CHECK_EQ(program, child_path);
#endif
  }

  std::string process_type =
      command_line->GetSwitchValueASCII(::switches::kProcessType);

#if defined(OS_LINUX)
  bool enable_crash_reporter = false;
  if (crash_reporter::IsCrashpadEnabled()) {
    command_line->AppendSwitch(::switches::kEnableCrashpad);
    enable_crash_reporter = true;

    int fd;
    pid_t pid;

    if (crash_reporter::GetHandlerSocket(&fd, &pid)) {
      command_line->AppendSwitchASCII(
          crash_reporter::switches::kCrashpadHandlerPid,
          base::NumberToString(pid));
    }
  } else {
    enable_crash_reporter = breakpad::IsCrashReporterEnabled();
  }

  // Zygote Process gets booted before any JS runs, accessing GetClientId
  // will end up touching DIR_USER_DATA path provider and this will
  // configure default value because app.name from browser_init has
  // not run yet.
  if (enable_crash_reporter && process_type != ::switches::kZygoteProcess) {
    std::string switch_value =
        api::crash_reporter::GetClientId() + ",no_channel";
    command_line->AppendSwitchASCII(::switches::kEnableCrashReporter,
                                    switch_value);
    if (!crash_reporter::IsCrashpadEnabled()) {
      for (const auto& pair : api::crash_reporter::GetGlobalCrashKeys()) {
        if (!switch_value.empty())
          switch_value += ",";
        switch_value += pair.first;
        switch_value += "=";
        switch_value += pair.second;
      }
      command_line->AppendSwitchASCII(switches::kGlobalCrashKeys, switch_value);
    }
  }
#endif

  // The zygote process is booted before JS runs, so DIR_USER_DATA isn't usable
  // at that time. It doesn't need --user-data-dir to be correct anyway, since
  // the zygote itself doesn't access anything in that directory.
  if (process_type != ::switches::kZygoteProcess) {
    base::FilePath user_data_dir;
    if (base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir))
      command_line->AppendSwitchPath(::switches::kUserDataDir, user_data_dir);
  }

  if (process_type == ::switches::kUtilityProcess ||
      process_type == ::switches::kRendererProcess) {
    // Copy following switches to child process.
    static const char* const kCommonSwitchNames[] = {
        switches::kStandardSchemes,      switches::kEnableSandbox,
        switches::kSecureSchemes,        switches::kBypassCSPSchemes,
        switches::kCORSSchemes,          switches::kFetchSchemes,
        switches::kServiceWorkerSchemes, switches::kStreamingSchemes};
    command_line->CopySwitchesFrom(*base::CommandLine::ForCurrentProcess(),
                                   kCommonSwitchNames,
                                   base::size(kCommonSwitchNames));
  }

  if (process_type == ::switches::kRendererProcess) {
#if defined(OS_WIN)
    // Append --app-user-model-id.
    PWSTR current_app_id;
    if (SUCCEEDED(GetCurrentProcessExplicitAppUserModelID(&current_app_id))) {
      command_line->AppendSwitchNative(switches::kAppUserModelId,
                                       current_app_id);
      CoTaskMemFree(current_app_id);
    }
#endif

    if (delegate_) {
      auto app_path = static_cast<api::App*>(delegate_)->GetAppPath();
      command_line->AppendSwitchPath(switches::kAppPath, app_path);
    }

    auto env = base::Environment::Create();
    if (env->HasVar("ELECTRON_PROFILE_INIT_SCRIPTS")) {
      command_line->AppendSwitch("profile-electron-init");
    }

    // Extension background pages don't have WebContentsPreferences, but they
    // support WebSQL by default.
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
    content::RenderProcessHost* process =
        content::RenderProcessHost::FromID(process_id);
    if (extensions::ProcessMap::Get(process->GetBrowserContext())
            ->Contains(process_id))
      command_line->AppendSwitch(switches::kEnableWebSQL);
#endif

    content::WebContents* web_contents =
        GetWebContentsFromProcessID(process_id);
    if (web_contents) {
      auto* web_preferences = WebContentsPreferences::From(web_contents);
      if (web_preferences)
        web_preferences->AppendCommandLineSwitches(
            command_line, IsRendererSubFrame(process_id));
    }
  }
}