[M120 Migration]Fix for crash during chrome exit
[platform/framework/web/chromium-efl.git] / chrome / browser / chrome_browser_main.cc
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/chrome_browser_main.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include <memory>
11 #include <set>
12 #include <string>
13 #include <tuple>
14 #include <utility>
15 #include <vector>
16
17 #include "base/at_exit.h"
18 #include "base/base_switches.h"
19 #include "base/command_line.h"
20 #include "base/debug/crash_logging.h"
21 #include "base/debug/debugger.h"
22 #include "base/debug/leak_annotations.h"
23 #include "base/feature_list.h"
24 #include "base/files/file_path.h"
25 #include "base/files/file_util.h"
26 #include "base/functional/bind.h"
27 #include "base/logging.h"
28 #include "base/memory/ptr_util.h"
29 #include "base/memory/raw_ptr.h"
30 #include "base/memory/scoped_refptr.h"
31 #include "base/metrics/field_trial.h"
32 #include "base/metrics/histogram_functions.h"
33 #include "base/metrics/histogram_macros.h"
34 #include "base/no_destructor.h"
35 #include "base/path_service.h"
36 #include "base/run_loop.h"
37 #include "base/strings/string_number_conversions.h"
38 #include "base/strings/string_piece.h"
39 #include "base/strings/sys_string_conversions.h"
40 #include "base/strings/utf_string_conversions.h"
41 #include "base/system/sys_info.h"
42 #include "base/task/current_thread.h"
43 #include "base/task/single_thread_task_runner.h"
44 #include "base/task/thread_pool.h"
45 #include "base/threading/hang_watcher.h"
46 #include "base/threading/platform_thread.h"
47 #include "base/time/default_tick_clock.h"
48 #include "base/time/time.h"
49 #include "base/trace_event/trace_event.h"
50 #include "base/values.h"
51 #include "build/branding_buildflags.h"
52 #include "build/build_config.h"
53 #include "build/chromeos_buildflags.h"
54 #include "cc/base/switches.h"
55 #include "chrome/browser/about_flags.h"
56 #include "chrome/browser/active_use_util.h"
57 #include "chrome/browser/after_startup_task_utils.h"
58 #include "chrome/browser/browser_features.h"
59 #include "chrome/browser/browser_process.h"
60 #include "chrome/browser/browser_process_impl.h"
61 #include "chrome/browser/browser_process_platform_part.h"
62 #include "chrome/browser/buildflags.h"
63 #include "chrome/browser/chrome_browser_field_trials.h"
64 #include "chrome/browser/chrome_browser_main_extra_parts.h"
65 #include "chrome/browser/defaults.h"
66 #include "chrome/browser/enterprise/browser_management/management_service_factory.h"
67 #include "chrome/browser/extensions/component_loader.h"
68 #include "chrome/browser/first_run/first_run.h"
69 #include "chrome/browser/language/url_language_histogram_factory.h"
70 #include "chrome/browser/lifetime/application_lifetime.h"
71 #include "chrome/browser/lifetime/browser_shutdown.h"
72 #include "chrome/browser/media/router/chrome_media_router_factory.h"
73 #include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
74 #include "chrome/browser/media/webrtc/webrtc_log_util.h"
75 #include "chrome/browser/metrics/chrome_feature_list_creator.h"
76 #include "chrome/browser/metrics/chrome_metrics_service_accessor.h"
77 #include "chrome/browser/metrics/expired_histograms_array.h"
78 #include "chrome/browser/metrics/shutdown_watcher_helper.h"
79 #include "chrome/browser/nacl_host/nacl_browser_delegate_impl.h"
80 #include "chrome/browser/net/system_network_context_manager.h"
81 #include "chrome/browser/policy/chrome_browser_policy_connector.h"
82 #include "chrome/browser/prefs/chrome_command_line_pref_store.h"
83 #include "chrome/browser/prefs/chrome_pref_service_factory.h"
84 #include "chrome/browser/privacy_budget/active_sampling.h"
85 #include "chrome/browser/profiles/profile.h"
86 #include "chrome/browser/profiles/profile_attributes_entry.h"
87 #include "chrome/browser/profiles/profile_attributes_storage.h"
88 #include "chrome/browser/profiles/profile_manager.h"
89 #include "chrome/browser/profiles/profile_manager_observer.h"
90 #include "chrome/browser/profiles/profiles_state.h"
91 #include "chrome/browser/sessions/chrome_serialized_navigation_driver.h"
92 #include "chrome/browser/shell_integration.h"
93 #include "chrome/browser/startup_data.h"
94 #include "chrome/browser/tracing/background_tracing_field_trial.h"
95 #include "chrome/browser/tracing/trace_event_system_stats_monitor.h"
96 #include "chrome/browser/translate/chrome_translate_client.h"
97 #include "chrome/browser/translate/translate_service.h"
98 #include "chrome/browser/ui/actions/chrome_actions.h"
99 #include "chrome/browser/ui/color/chrome_color_mixers.h"
100 #include "chrome/browser/ui/javascript_dialogs/chrome_javascript_app_modal_dialog_view_factory.h"
101 #include "chrome/browser/ui/profiles/profile_error_dialog.h"
102 #include "chrome/browser/ui/startup/bad_flags_prompt.h"
103 #include "chrome/browser/ui/startup/startup_browser_creator.h"
104 #include "chrome/browser/ui/webui/chrome_untrusted_web_ui_configs.h"
105 #include "chrome/browser/ui/webui/chrome_web_ui_configs.h"
106 #include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h"
107 #include "chrome/common/buildflags.h"
108 #include "chrome/common/channel_info.h"
109 #include "chrome/common/chrome_constants.h"
110 #include "chrome/common/chrome_features.h"
111 #include "chrome/common/chrome_paths.h"
112 #include "chrome/common/chrome_result_codes.h"
113 #include "chrome/common/chrome_switches.h"
114 #include "chrome/common/crash_keys.h"
115 #include "chrome/common/env_vars.h"
116 #include "chrome/common/logging_chrome.h"
117 #include "chrome/common/media/media_resource_provider.h"
118 #include "chrome/common/net/net_resource_provider.h"
119 #include "chrome/common/pref_names.h"
120 #include "chrome/common/profiler/thread_profiler.h"
121 #include "chrome/common/profiler/thread_profiler_configuration.h"
122 #include "chrome/common/profiler/unwind_util.h"
123 #include "chrome/grit/branded_strings.h"
124 #include "chrome/grit/generated_resources.h"
125 #include "chrome/installer/util/google_update_settings.h"
126 #include "components/color/color_mixers.h"
127 #include "components/device_event_log/device_event_log.h"
128 #include "components/embedder_support/origin_trials/component_updater_utils.h"
129 #include "components/embedder_support/origin_trials/origin_trials_settings_storage.h"
130 #include "components/embedder_support/switches.h"
131 #include "components/flags_ui/pref_service_flags_storage.h"
132 #include "components/google/core/common/google_util.h"
133 #include "components/keyed_service/content/browser_context_dependency_manager.h"
134 #include "components/language/content/browser/geo_language_provider.h"
135 #include "components/language/core/browser/language_usage_metrics.h"
136 #include "components/language/core/browser/pref_names.h"
137 #include "components/language/core/common/language_experiments.h"
138 #include "components/language/core/common/language_util.h"
139 #include "components/metrics/call_stack_profile_metrics_provider.h"
140 #include "components/metrics/call_stack_profile_params.h"
141 #include "components/metrics/content/subprocess_metrics_provider.h"
142 #include "components/metrics/expired_histogram_util.h"
143 #include "components/metrics/metrics_reporting_default_state.h"
144 #include "components/metrics/metrics_service.h"
145 #include "components/metrics/metrics_shutdown.h"
146 #include "components/metrics/persistent_histograms.h"
147 #include "components/metrics_services_manager/metrics_services_manager.h"
148 #include "components/nacl/browser/nacl_browser.h"
149 #include "components/nacl/common/buildflags.h"
150 #include "components/offline_pages/buildflags/buildflags.h"
151 #include "components/policy/core/common/management/management_service.h"
152 #include "components/prefs/json_pref_store.h"
153 #include "components/prefs/pref_registry_simple.h"
154 #include "components/prefs/pref_service.h"
155 #include "components/prefs/pref_value_store.h"
156 #include "components/site_isolation/site_isolation_policy.h"
157 #include "components/spellcheck/spellcheck_buildflags.h"
158 #include "components/startup_metric_utils/browser/startup_metric_utils.h"
159 #include "components/tracing/common/background_tracing_utils.h"
160 #include "components/tracing/common/tracing_switches.h"
161 #include "components/translate/core/browser/translate_download_manager.h"
162 #include "components/translate/core/browser/translate_metrics_logger_impl.h"
163 #include "components/variations/field_trial_config/field_trial_util.h"
164 #include "components/variations/pref_names.h"
165 #include "components/variations/service/variations_service.h"
166 #include "components/variations/synthetic_trial_registry.h"
167 #include "components/variations/synthetic_trials_active_group_id_provider.h"
168 #include "components/variations/variations_associated_data.h"
169 #include "components/variations/variations_crash_keys.h"
170 #include "components/variations/variations_ids_provider.h"
171 #include "components/variations/variations_switches.h"
172 #include "components/version_info/version_info.h"
173 #include "content/public/browser/browser_context.h"
174 #include "content/public/browser/browser_task_traits.h"
175 #include "content/public/browser/browser_thread.h"
176 #include "content/public/browser/first_party_sets_handler.h"
177 #include "content/public/browser/render_process_host.h"
178 #include "content/public/browser/site_instance.h"
179 #include "content/public/common/content_client.h"
180 #include "content/public/common/content_features.h"
181 #include "content/public/common/content_switches.h"
182 #include "content/public/common/main_function_params.h"
183 #include "content/public/common/profiling.h"
184 #include "extensions/buildflags/buildflags.h"
185 #include "media/audio/audio_manager.h"
186 #include "media/base/localized_strings.h"
187 #include "media/media_buildflags.h"
188 #include "net/base/net_module.h"
189 #include "net/cookies/cookie_monster.h"
190 #include "net/http/http_network_layer.h"
191 #include "net/http/http_stream_factory.h"
192 #include "ppapi/buildflags/buildflags.h"
193 #include "printing/buildflags/buildflags.h"
194 #include "rlz/buildflags/buildflags.h"
195 #include "services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.h"
196 #include "third_party/blink/public/common/origin_trials/origin_trials_settings_provider.h"
197 #include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h"
198 #include "third_party/blink/public/common/switches.h"
199 #include "ui/base/l10n/l10n_util.h"
200 #include "ui/base/resource/resource_bundle.h"
201 #include "ui/color/color_provider_manager.h"
202
203 #if BUILDFLAG(ENABLE_COMPONENT_UPDATER)
204 #include "chrome/browser/component_updater/registration.h"
205 #endif  // BUILDFLAG(ENABLE_COMPONENT_UPDATER)
206
207 #if BUILDFLAG(IS_ANDROID)
208 #include "chrome/browser/flags/android/chrome_feature_list.h"
209 #include "chrome/browser/share/share_history.h"
210 #include "chrome/browser/ui/page_info/chrome_page_info_client.h"
211 #include "ui/base/resource/resource_bundle_android.h"
212 #else
213 #include "chrome/browser/profiles/delete_profile_helper.h"
214 #include "chrome/browser/resource_coordinator/tab_manager.h"
215 #include "chrome/browser/resources_integrity.h"
216 #include "chrome/browser/ui/browser.h"
217 #include "chrome/browser/ui/browser_finder.h"
218 #include "chrome/browser/ui/uma_browsing_activity_observer.h"
219 #include "chrome/browser/upgrade_detector/upgrade_detector.h"
220 #include "chrome/browser/usb/web_usb_detector.h"
221 #include "components/soda/soda_installer.h"
222 #endif  // BUILDFLAG(IS_ANDROID)
223
224 #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
225 #include "chrome/browser/first_run/upgrade_util.h"
226 #endif  // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
227
228 #if BUILDFLAG(IS_CHROMEOS)
229 #include "base/process/process.h"
230 #include "base/task/task_traits.h"
231 #include "components/crash/core/app/breakpad_linux.h"
232 #endif  // BUILDFLAG(IS_CHROMEOS)
233
234 #if BUILDFLAG(IS_CHROMEOS_ASH)
235 #include "ash/components/arc/metrics/stability_metrics_manager.h"
236 #include "ash/constants/ash_features.h"
237 #include "ash/constants/ash_switches.h"
238 #include "chrome/browser/ash/profiles/profile_helper.h"
239 #include "chrome/browser/ash/settings/cros_settings.h"
240 #include "chrome/browser/ash/settings/hardware_data_usage_controller.h"
241 #include "chrome/browser/ash/settings/stats_reporting_controller.h"
242 #include "chromeos/ash/components/settings/cros_settings_names.h"
243 #else
244 #include "components/enterprise/browser/controller/chrome_browser_cloud_management_controller.h"
245 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
246
247 // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
248 // of lacros-chrome is complete.
249 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
250 #include "chrome/browser/first_run/upgrade_util_linux.h"
251 #endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
252
253 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
254 #include "components/crash/core/app/crashpad.h"
255 #endif
256
257 #if BUILDFLAG(IS_MAC)
258 #include <Security/Security.h>
259
260 #if defined(ARCH_CPU_X86_64)
261 #include "base/mac/mac_util.h"
262 #include "base/threading/platform_thread.h"
263 #endif  // defined(ARCH_CPU_X86_64)
264
265 #include "chrome/browser/app_controller_mac.h"
266 #include "chrome/browser/mac/keystone_glue.h"
267 #include "chrome/browser/ui/ui_features.h"
268 #endif  // BUILDFLAG(IS_MAC)
269
270 #if BUILDFLAG(IS_WIN)
271 #include "base/trace_event/trace_event_etw_export_win.h"
272 #include "base/win/win_util.h"
273 #include "chrome/browser/chrome_browser_main_win.h"
274 #include "chrome/browser/first_run/upgrade_util_win.h"
275 #include "chrome/browser/notifications/win/notification_launch_id.h"
276 #include "chrome/browser/ui/network_profile_bubble.h"
277 #include "chrome/browser/win/browser_util.h"
278 #include "chrome/browser/win/chrome_select_file_dialog_factory.h"
279 #include "chrome/browser/win/parental_controls.h"
280 #include "chrome/install_static/install_util.h"
281 #include "ui/shell_dialogs/select_file_dialog.h"
282 #endif  // BUILDFLAG(IS_WIN)
283
284 // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
285 // of lacros-chrome is complete.
286 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || \
287     BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_FUCHSIA)
288 #include "chrome/browser/metrics/desktop_session_duration/desktop_session_duration_tracker.h"
289 #include "chrome/browser/metrics/desktop_session_duration/touch_mode_stats_tracker.h"
290 #include "chrome/browser/profiles/profile_activity_metrics_recorder.h"
291 #include "ui/base/pointer/touch_ui_controller.h"
292 #endif
293
294 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
295 #include "chrome/browser/headless/headless_mode_metrics.h"  // nogncheck
296 #include "chrome/browser/headless/headless_mode_util.h"     // nogncheck
297 #include "components/headless/select_file_dialog/headless_select_file_dialog.h"
298 #include "ui/gfx/switches.h"
299 #endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
300
301 #if BUILDFLAG(ENABLE_PROCESS_SINGLETON)
302 #include "chrome/browser/chrome_process_singleton.h"
303 #include "chrome/browser/process_singleton.h"
304 #endif  // BUILDFLAG(ENABLE_PROCESS_SINGLETON)
305
306 #if BUILDFLAG(ENABLE_BACKGROUND_MODE)
307 #include "chrome/browser/background/background_mode_manager.h"
308 #endif  // BUILDFLAG(ENABLE_BACKGROUND_MODE)
309
310 #if BUILDFLAG(ENABLE_EXTENSIONS)
311 #include "extensions/browser/extension_protocols.h"
312 #include "extensions/common/features/feature_provider.h"
313 #include "extensions/components/javascript_dialog_extensions_client/javascript_dialog_extension_client_impl.h"
314 #endif  // BUILDFLAG(ENABLE_EXTENSIONS)
315
316 #if BUILDFLAG(ENABLE_NACL)
317 #include "components/nacl/browser/nacl_process_host.h"
318 #endif  // BUILDFLAG(ENABLE_NACL)
319
320 #if BUILDFLAG(ENABLE_OFFLINE_PAGES)
321 #include "chrome/browser/offline_pages/offline_page_info_handler.h"
322 #endif
323
324 #if BUILDFLAG(ENABLE_PLUGINS)
325 #include "chrome/browser/plugins/plugin_prefs.h"
326 #endif
327
328 #if BUILDFLAG(ENABLE_PRINTING)
329 #include "chrome/common/printing/printing_init.h"
330 #endif
331
332 #if BUILDFLAG(ENABLE_PRINT_PREVIEW) && !defined(OFFICIAL_BUILD)
333 #include "printing/printed_document.h"
334 #endif
335
336 #if BUILDFLAG(ENABLE_RLZ)
337 #include "chrome/browser/rlz/chrome_rlz_tracker_delegate.h"
338 #include "components/rlz/rlz_tracker.h"  // nogncheck crbug.com/1125897
339 #endif  // BUILDFLAG(ENABLE_RLZ)
340
341 #if BUILDFLAG(IS_CHROMEOS_LACROS)
342 #include "ui/shell_dialogs/select_file_dialog_lacros.h"
343 #endif
344
345 #if defined(USE_AURA)
346 #include "ui/aura/env.h"
347 #endif
348
349 #if BUILDFLAG(IS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER)
350 #include "chrome/browser/spellchecker/spellcheck_factory.h"
351 #include "components/spellcheck/browser/pref_names.h"
352 #include "components/spellcheck/common/spellcheck_features.h"
353 #endif  // BUILDFLAG(IS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER)
354
355 namespace {
356
357 #if !BUILDFLAG(IS_ANDROID)
358 // Initialized in PreMainMessageLoopRun() and handed off to content:: in
359 // WillRunMainMessageLoop() (or in TakeRunLoopForTest() in tests)
360 std::unique_ptr<base::RunLoop>& GetMainRunLoopInstance() {
361   static base::NoDestructor<std::unique_ptr<base::RunLoop>>
362       main_run_loop_instance;
363   return *main_run_loop_instance;
364 }
365 #endif
366
367 // This function provides some ways to test crash and assertion handling
368 // behavior of the program.
369 void HandleTestParameters(const base::CommandLine& command_line) {
370   // This parameter causes a null pointer crash (crash reporter trigger).
371   if (command_line.HasSwitch(switches::kBrowserCrashTest)) {
372     base::ImmediateCrash();
373   }
374 }
375
376 // Initializes the initial profile, possibly doing some user prompting to pick
377 // a fallback profile. Returns either
378 // - kBrowserWindow mode with the newly created profile,
379 // - kProfilePicker mode indicating that the profile picker should be shown;
380 //   the profile is a guest profile in this case, or
381 // - kError mode with a nullptr profile if startup should not continue.
382 StartupProfileInfo CreateInitialProfile(
383     const base::FilePath& cur_dir,
384     const base::CommandLine& parsed_command_line) {
385   TRACE_EVENT0("startup", "ChromeBrowserMainParts::CreateProfile");
386   base::Time start = base::Time::Now();
387
388   bool last_used_profile_set = false;
389
390 // If the browser is launched due to activation on Windows native
391 // notification, the profile id encoded in the notification launch id should
392 // be chosen over all others.
393 #if BUILDFLAG(IS_WIN)
394   base::FilePath profile_basename =
395       NotificationLaunchId::GetNotificationLaunchProfileBaseName(
396           parsed_command_line);
397   if (!profile_basename.empty()) {
398     profiles::SetLastUsedProfile(profile_basename);
399     last_used_profile_set = true;
400   }
401 #endif  // BUILDFLAG(IS_WIN)
402
403   bool profile_dir_specified =
404       profiles::IsMultipleProfilesEnabled() &&
405       parsed_command_line.HasSwitch(switches::kProfileDirectory);
406   if (!last_used_profile_set && profile_dir_specified) {
407     profiles::SetLastUsedProfile(
408         parsed_command_line.GetSwitchValuePath(switches::kProfileDirectory));
409     last_used_profile_set = true;
410   }
411
412   if (last_used_profile_set &&
413       !parsed_command_line.HasSwitch(switches::kAppId)) {
414     // Clear kProfilesLastActive since the user only wants to launch a specific
415     // profile. Don't clear it if the user launched a web app, in order to not
416     // break any subsequent multi-profile session restore.
417     g_browser_process->local_state()->SetList(prefs::kProfilesLastActive,
418                                               base::Value::List());
419   }
420
421   StartupProfileInfo profile_info;
422 #if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_ANDROID)
423   profile_info = {ProfileManager::CreateInitialProfile(),
424                   StartupProfileMode::kBrowserWindow};
425
426   // TODO(port): fix this. See comments near the definition of |user_data_dir|.
427   // It is better to CHECK-fail here than it is to silently exit because of
428   // missing code in the above test.
429   CHECK(profile_info.profile) << "Cannot get default profile.";
430
431 #else
432 #if BUILDFLAG(IS_CHROMEOS_LACROS)
433   // Lacros has a special "primary" profile that is tied to the active ChromeOS
434   // user identity. Lacros might attempt to load this profile synchorously via
435   // `ProfileManager::GetPrimaryUserProfile()` or
436   // `ProfileManager::GetActiveUserProfile()`. In combination with asynchronous
437   // profile loading, this can lead to a crash (see https://crbug.com/1289527).
438   // Load the primary Lacros profile before any other profile to ensure that the
439   // primary profile is always loaded.
440   // TODO(https://crbug.com/1264436): remove this once Lacros no longer uses
441   // GetActiveUserProfile() and GetPrimaryUserProfile().
442   ProfileManager::GetPrimaryUserProfile();
443 #endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
444
445   profile_info = GetStartupProfile(cur_dir, parsed_command_line);
446
447   if (profile_info.mode == StartupProfileMode::kError &&
448       !last_used_profile_set) {
449     profile_info = GetFallbackStartupProfile();
450     base::UmaHistogramEnumeration(
451         "ProfilePicker.StartupMode.FallbackProfileUsed", profile_info.mode);
452   }
453
454   if (profile_info.mode == StartupProfileMode::kError) {
455     ProfileErrorType error_type =
456         profile_dir_specified ? ProfileErrorType::CREATE_FAILURE_SPECIFIED
457                               : ProfileErrorType::CREATE_FAILURE_ALL;
458
459     // TODO(lwchkg): What diagnostics do you want to include in the feedback
460     // report when an error occurs?
461     ShowProfileErrorDialog(error_type, IDS_COULDNT_STARTUP_PROFILE_ERROR,
462                            "Error creating initial profile.");
463     return profile_info;
464   }
465 #endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_ANDROID)
466
467   UMA_HISTOGRAM_LONG_TIMES(
468       "Startup.CreateFirstProfile", base::Time::Now() - start);
469   return profile_info;
470 }
471
472 #if BUILDFLAG(IS_MAC)
473 OSStatus KeychainCallback(SecKeychainEvent keychain_event,
474                           SecKeychainCallbackInfo* info, void* context) {
475   return noErr;
476 }
477 #endif  // BUILDFLAG(IS_MAC)
478
479 #if BUILDFLAG(ENABLE_PROCESS_SINGLETON)
480 void ProcessSingletonNotificationCallbackImpl(
481     const base::CommandLine& command_line,
482     const base::FilePath& current_directory) {
483   // Drop the request if the browser process is already shutting down.
484   if (!g_browser_process || g_browser_process->IsShuttingDown() ||
485       browser_shutdown::HasShutdownStarted()) {
486     return;
487   }
488
489 #if BUILDFLAG(IS_WIN)
490   // The uninstall command-line switch is handled by the origin process; see
491   // ChromeMainDelegate::PostEarlyInitialization(...). The other process won't
492   // be able to become the singleton process and will display a window asking
493   // the user to close running Chrome instances.
494   if (command_line.HasSwitch(switches::kUninstall)) {
495     return;
496   }
497 #endif
498
499   g_browser_process->platform_part()->OnBrowserLaunch();
500
501   StartupProfilePathInfo startup_profile_path_info =
502       GetStartupProfilePath(current_directory, command_line,
503                             /*ignore_profile_picker=*/false);
504   DCHECK_NE(startup_profile_path_info.reason, StartupProfileModeReason::kError);
505   base::UmaHistogramEnumeration(
506       "ProfilePicker.StartupMode.NotificationCallback",
507       StartupProfileModeFromReason(startup_profile_path_info.reason));
508   base::UmaHistogramEnumeration(
509       "ProfilePicker.StartupReason.NotificationCallback",
510       startup_profile_path_info.reason);
511
512   StartupBrowserCreator::ProcessCommandLineAlreadyRunning(
513       command_line, current_directory, startup_profile_path_info);
514
515   // Record now as the last successful chrome start.
516   if constexpr (kShouldRecordActiveUse) {
517     GoogleUpdateSettings::SetLastRunTime();
518   }
519 }
520 #endif  // BUILDFLAG(ENABLE_PROCESS_SINGLETON)
521
522 #if !BUILDFLAG(IS_ANDROID)
523 bool ShouldInstallSodaDuringPostProfileInit(
524     const base::CommandLine& command_line) {
525 #if BUILDFLAG(IS_CHROMEOS_ASH)
526   return base::FeatureList::IsEnabled(
527       ash::features::kOnDeviceSpeechRecognition);
528 #elif !BUILDFLAG(IS_CHROMEOS_LACROS) && BUILDFLAG(ENABLE_COMPONENT_UPDATER)
529   return !command_line.HasSwitch(switches::kDisableComponentUpdate);
530 #else
531   return false;
532 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
533 }
534 #endif  // !BUILDFLAG(IS_ANDROID)
535
536 void DisallowKeyedServiceFactoryRegistration() {
537   // From this point, do not allow KeyedServiceFactories to be registered, all
538   // factories should be registered in the main registration function
539   // `ChromeBrowserMainExtraPartsProfiles::EnsureBrowserContextKeyedServiceFactoriesBuilt()`.
540   BrowserContextDependencyManager::GetInstance()
541       ->DisallowKeyedServiceFactoryRegistration(
542           "ChromeBrowserMainExtraPartsProfiles::"
543           "EnsureBrowserContextKeyedServiceFactoriesBuilt()");
544 }
545
546 #if !BUILDFLAG(IS_ANDROID)
547 void StartWatchingForProcessShutdownHangs() {
548   // This HangWatcher scope is covering the shutdown phase up to the end of the
549   // process. Intentionally leak this instance so that it is not destroyed
550   // before process termination.
551   auto* watcher = new base::WatchHangsInScope(base::Seconds(30));
552   ANNOTATE_LEAKING_OBJECT_PTR(watcher);
553   std::ignore = watcher;
554 }
555 #endif  // !BUILDFLAG(IS_ANDROID)
556
557 }  // namespace
558
559 // ChromeBrowserMainParts::ProfileInitManager ----------------------------------
560
561 // Runs `CallPostProfileInit()` on all existing and future profiles, the
562 // initial profile is processed first. The initial profile is nullptr when the
563 // profile picker is shown.
564 class ChromeBrowserMainParts::ProfileInitManager
565     : public ProfileManagerObserver {
566  public:
567   ProfileInitManager(ChromeBrowserMainParts* browser_main,
568                      Profile* initial_profile);
569   ~ProfileInitManager() override;
570
571   ProfileInitManager(const ProfileInitManager&) = delete;
572   ProfileInitManager& operator=(const ProfileInitManager&) = delete;
573
574   // ProfileManagerObserver:
575   void OnProfileAdded(Profile* profile) override;
576   void OnProfileManagerDestroying() override;
577
578  private:
579   base::ScopedObservation<ProfileManager, ProfileManagerObserver>
580       profile_manager_observer_{this};
581   // Raw pointer. This is safe because `ChromeBrowserMainParts` owns `this`.
582   const raw_ptr<ChromeBrowserMainParts> browser_main_;
583 };
584
585 ChromeBrowserMainParts::ProfileInitManager::ProfileInitManager(
586     ChromeBrowserMainParts* browser_main,
587     Profile* initial_profile)
588     : browser_main_(browser_main) {
589   // `initial_profile` is null when the profile picker is shown.
590   if (initial_profile) {
591     browser_main_->CallPostProfileInit(initial_profile);
592   }
593
594   // Run `CallPostProfileInit()` on the other existing and future profiles.
595   ProfileManager* profile_manager = g_browser_process->profile_manager();
596   // Register the observer first, in case `OnProfileAdded()` causes a creation.
597   profile_manager_observer_.Observe(profile_manager);
598   for (auto* profile : profile_manager->GetLoadedProfiles()) {
599     DCHECK(profile);
600     if (profile == initial_profile) {
601       continue;
602     }
603     OnProfileAdded(profile);
604   }
605 }
606
607 ChromeBrowserMainParts::ProfileInitManager::~ProfileInitManager() = default;
608
609 void ChromeBrowserMainParts::ProfileInitManager::OnProfileAdded(
610     Profile* profile) {
611   if (profile->IsSystemProfile() || profile->IsGuestSession()) {
612     // Ignore the system profile that is used for displaying the profile picker,
613     // and the "parent" guest profile. `CallPostProfileInit()` should be called
614     // only for profiles that are used for browsing.
615     return;
616   }
617
618 #if BUILDFLAG(IS_CHROMEOS_ASH)
619   // Ignore ChromeOS helper profiles (sign-in, lockscreen, etc).
620   if (!ash::ProfileHelper::IsUserProfile(profile)) {
621     // Notify of new profile initialization only for regular profiles. The
622     // startup profile initialization is triggered by another code path.
623     return;
624   }
625 #endif
626
627   browser_main_->CallPostProfileInit(profile);
628 }
629
630 void ChromeBrowserMainParts::ProfileInitManager::OnProfileManagerDestroying() {
631   profile_manager_observer_.Reset();
632 }
633
634 // BrowserMainParts ------------------------------------------------------------
635
636 ChromeBrowserMainParts::ChromeBrowserMainParts(bool is_integration_test,
637                                                StartupData* startup_data)
638     : is_integration_test_(is_integration_test), startup_data_(startup_data) {
639   DCHECK(startup_data_);
640 #if BUILDFLAG(IS_CHROMEOS_ASH) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
641   if (is_integration_test_) {
642     extensions::ComponentLoader::DisableHelpAppForTesting();
643   }
644 #endif
645 }
646
647 ChromeBrowserMainParts::~ChromeBrowserMainParts() {
648   // Delete parts in the reverse of the order they were added.
649   while (!chrome_extra_parts_.empty())
650     chrome_extra_parts_.pop_back();
651 }
652
653 void ChromeBrowserMainParts::SetupMetrics() {
654   TRACE_EVENT0("startup", "ChromeBrowserMainParts::SetupMetrics");
655   CHECK(metrics::SubprocessMetricsProvider::CreateInstance());
656   metrics::MetricsService* metrics = browser_process_->metrics_service();
657   metrics->GetSyntheticTrialRegistry()->AddObserver(
658       variations::VariationsIdsProvider::GetInstance());
659   metrics->GetSyntheticTrialRegistry()->AddObserver(
660       variations::SyntheticTrialsActiveGroupIdProvider::GetInstance());
661   // Now that field trials have been created, initializes metrics recording.
662   metrics->InitializeMetricsRecordingState();
663
664   startup_data_->chrome_feature_list_creator()
665       ->browser_field_trials()
666       ->RegisterSyntheticTrials();
667 }
668
669 // static
670 void ChromeBrowserMainParts::StartMetricsRecording() {
671   TRACE_EVENT0("startup", "ChromeBrowserMainParts::StartMetricsRecording");
672
673   // Register a synthetic field trial for the sampling profiler configuration
674   // that was already chosen.
675   std::string trial_name, group_name;
676   if (ThreadProfilerConfiguration::Get()->GetSyntheticFieldTrial(&trial_name,
677                                                                  &group_name)) {
678     ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial(trial_name,
679                                                               group_name);
680   }
681
682 #if BUILDFLAG(IS_ANDROID)
683   // Android updates the metrics service dynamically depending on whether the
684   // application is in the foreground or not. Do not start here unless
685   // kUmaBackgroundSessions is enabled.
686   if (!base::FeatureList::IsEnabled(chrome::android::kUmaBackgroundSessions))
687     return;
688 #endif
689
690   g_browser_process->metrics_service()->CheckForClonedInstall();
691
692 #if BUILDFLAG(IS_WIN)
693   // The last live timestamp is used to assess whether a browser crash occurred
694   // due to a full system crash. Update the last live timestamp on a slow
695   // schedule to get the bast possible accuracy for the assessment.
696   g_browser_process->metrics_service()->StartUpdatingLastLiveTimestamp();
697 #endif
698
699   g_browser_process->GetMetricsServicesManager()->UpdateUploadPermissions(true);
700 }
701
702 void ChromeBrowserMainParts::RecordBrowserStartupTime() {
703   // Don't record any metrics if UI was displayed before this point e.g.
704   // warning dialogs or browser was started in background mode.
705   if (startup_metric_utils::GetBrowser().WasMainWindowStartupInterrupted()) {
706     return;
707   }
708
709   bool is_first_run = false;
710 #if !BUILDFLAG(IS_ANDROID)
711   // On Android, first run is handled in Java code, and the C++ side of Chrome
712   // doesn't know if this is the first run. This will cause some inaccuracy in
713   // the UMA statistics, but this should be minor (first runs are rare).
714   is_first_run = first_run::IsChromeFirstRun();
715 #endif  // BUILDFLAG(IS_ANDROID)
716
717   // Record collected startup metrics.
718   startup_metric_utils::GetBrowser().RecordBrowserMainMessageLoopStart(
719       base::TimeTicks::Now(), is_first_run);
720 }
721
722 // -----------------------------------------------------------------------------
723 // TODO(viettrungluu): move more/rest of BrowserMain() into BrowserMainParts.
724
725 #if BUILDFLAG(IS_WIN)
726 #define DLLEXPORT __declspec(dllexport)
727
728 // We use extern C for the prototype DLLEXPORT to avoid C++ name mangling.
729 extern "C" {
730 DLLEXPORT void __cdecl RelaunchChromeBrowserWithNewCommandLineIfNeeded();
731 }
732
733 DLLEXPORT void __cdecl RelaunchChromeBrowserWithNewCommandLineIfNeeded() {
734   // Need an instance of AtExitManager to handle singleton creations and
735   // deletions.  We need this new instance because, the old instance created
736   // in ChromeMain() got destructed when the function returned.
737   base::AtExitManager exit_manager;
738   upgrade_util::RelaunchChromeBrowserWithNewCommandLineIfNeeded();
739 }
740 #endif
741
742 // content::BrowserMainParts implementation ------------------------------------
743
744 int ChromeBrowserMainParts::PreEarlyInitialization() {
745   TRACE_EVENT0("startup", "ChromeBrowserMainParts::PreEarlyInitialization");
746   for (auto& chrome_extra_part : chrome_extra_parts_)
747     chrome_extra_part->PreEarlyInitialization();
748
749   // Create BrowserProcess in PreEarlyInitialization() so that we can load
750   // field trials (and all it depends upon).
751   browser_process_ = std::make_unique<BrowserProcessImpl>(startup_data_);
752
753   bool failed_to_load_resource_bundle = false;
754   const int load_local_state_result =
755       OnLocalStateLoaded(&failed_to_load_resource_bundle);
756
757   // Reuses the MetricsServicesManager and GetMetricsServicesManagerClient
758   // instances created in the FeatureListCreator so they won't be created
759   // again.
760   auto* chrome_feature_list_creator =
761       startup_data_->chrome_feature_list_creator();
762   browser_process_->SetMetricsServices(
763       chrome_feature_list_creator->TakeMetricsServicesManager(),
764       chrome_feature_list_creator->GetMetricsServicesManagerClient());
765
766   if (load_local_state_result == chrome::RESULT_CODE_MISSING_DATA &&
767       failed_to_load_resource_bundle) {
768     if (base::CommandLine::ForCurrentProcess()->HasSwitch(
769             switches::kNoErrorDialogs)) {
770       return chrome::RESULT_CODE_MISSING_DATA;
771     }
772     // Continue on and show error later (once UI has been initialized and main
773     // message loop is running).
774     return content::RESULT_CODE_NORMAL_EXIT;
775   }
776
777 #if BUILDFLAG(IS_WIN)
778   // If we are running stale binaries then relaunch and exit immediately.
779   if (upgrade_util::IsRunningOldChrome()) {
780     if (!upgrade_util::RelaunchChromeBrowser(
781             *base::CommandLine::ForCurrentProcess())) {
782       // The relaunch failed. Feel free to panic now.
783       NOTREACHED();
784     }
785
786     // Note, cannot return RESULT_CODE_NORMAL_EXIT here as this code needs to
787     // result in browser startup bailing.
788     return chrome::RESULT_CODE_NORMAL_EXIT_UPGRADE_RELAUNCHED;
789   }
790 #endif  // BUILDFLAG(IS_WIN)
791
792   return load_local_state_result;
793 }
794
795 void ChromeBrowserMainParts::PostEarlyInitialization() {
796   TRACE_EVENT0("startup", "ChromeBrowserMainParts::PostEarlyInitialization");
797   for (auto& chrome_extra_part : chrome_extra_parts_)
798     chrome_extra_part->PostEarlyInitialization();
799 }
800
801 void ChromeBrowserMainParts::ToolkitInitialized() {
802   TRACE_EVENT0("startup", "ChromeBrowserMainParts::ToolkitInitialized");
803
804   for (auto& chrome_extra_part : chrome_extra_parts_)
805     chrome_extra_part->ToolkitInitialized();
806
807   // Comes after the extra parts' calls since on GTK that builds the native
808   // theme that, in turn, adds the GTK core color mixer; core mixers should all
809   // be added before we add chrome mixers.
810   ui::ColorProviderManager::Get().AppendColorProviderInitializer(
811       base::BindRepeating(color::AddComponentsColorMixers));
812   ui::ColorProviderManager::Get().AppendColorProviderInitializer(
813       base::BindRepeating(AddChromeColorMixers));
814
815   InitializeActionIdStringMapping();
816 }
817
818 void ChromeBrowserMainParts::PreCreateMainMessageLoop() {
819   TRACE_EVENT0("startup", "ChromeBrowserMainParts::PreCreateMainMessageLoop");
820
821   for (auto& chrome_extra_part : chrome_extra_parts_)
822     chrome_extra_part->PreCreateMainMessageLoop();
823 }
824
825 void ChromeBrowserMainParts::PostCreateMainMessageLoop() {
826   TRACE_EVENT0("startup", "ChromeBrowserMainParts::PostCreateMainMessageLoop");
827
828 #if !BUILDFLAG(IS_ANDROID)
829   // Initialize the upgrade detector here after `ChromeBrowserMainPartsAsh`
830   // has had a chance to connect the DBus services.
831   UpgradeDetector::GetInstance()->Init();
832 #endif
833
834   ThreadProfiler::SetMainThreadTaskRunner(
835       base::SingleThreadTaskRunner::GetCurrentDefault());
836
837   // TODO(sebmarchand): Allow this to be created earlier if startup tracing is
838   // enabled.
839   trace_event_system_stats_monitor_ =
840       std::make_unique<tracing::TraceEventSystemStatsMonitor>();
841
842   // device_event_log must be initialized after the message loop. Calls to
843   // {DEVICE}_LOG prior to here will only be logged with VLOG. Some
844   // platforms (e.g. chromeos) may have already initialized this.
845   if (!device_event_log::IsInitialized())
846     device_event_log::Initialize(0 /* default max entries */);
847
848   for (auto& chrome_extra_part : chrome_extra_parts_)
849     chrome_extra_part->PostCreateMainMessageLoop();
850 }
851
852 int ChromeBrowserMainParts::PreCreateThreads() {
853   // IMPORTANT
854   // Calls in this function should not post tasks or create threads as
855   // components used to handle those tasks are not yet available. This work
856   // should be deferred to PreMainMessageLoopRunImpl.
857
858   TRACE_EVENT0("startup", "ChromeBrowserMainParts::PreCreateThreads");
859   result_code_ = PreCreateThreadsImpl();
860
861   if (result_code_ == content::RESULT_CODE_NORMAL_EXIT) {
862     // These members must be initialized before exiting this function normally.
863 #if !BUILDFLAG(IS_ANDROID)
864     DCHECK(browser_creator_.get());
865 #endif
866 #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
867     DCHECK(master_prefs_.get());
868 #endif
869
870     for (auto& chrome_extra_part : chrome_extra_parts_)
871       chrome_extra_part->PreCreateThreads();
872   }
873
874   // Create an instance of GpuModeManager to watch gpu mode pref change.
875   g_browser_process->gpu_mode_manager();
876
877   return result_code_;
878 }
879
880 int ChromeBrowserMainParts::OnLocalStateLoaded(
881     bool* failed_to_load_resource_bundle) {
882   *failed_to_load_resource_bundle = false;
883   if (!base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir_))
884     return chrome::RESULT_CODE_MISSING_DATA;
885
886   auto* platform_management_service =
887       policy::ManagementServiceFactory::GetForPlatform();
888   platform_management_service->UsePrefServiceAsCache(
889       browser_process_->local_state());
890   platform_management_service->RefreshCache(base::NullCallback());
891
892 #if BUILDFLAG(IS_WIN)
893   if (first_run::IsChromeFirstRun()) {
894     bool stats_default;
895     if (GoogleUpdateSettings::GetCollectStatsConsentDefault(&stats_default)) {
896       // |stats_default| == true means that the default state of consent for the
897       // product at the time of install was to report usage statistics, meaning
898       // "opt-out".
899       metrics::RecordMetricsReportingDefaultState(
900           browser_process_->local_state(),
901           stats_default ? metrics::EnableMetricsDefault::OPT_OUT
902                         : metrics::EnableMetricsDefault::OPT_IN);
903     }
904   }
905 #endif  // BUILDFLAG(IS_WIN)
906
907   std::string locale =
908       startup_data_->chrome_feature_list_creator()->actual_locale();
909   if (locale.empty()) {
910     *failed_to_load_resource_bundle = true;
911     return chrome::RESULT_CODE_MISSING_DATA;
912   }
913   browser_process_->SetApplicationLocale(locale);
914
915   const int apply_first_run_result = ApplyFirstRunPrefs();
916   if (apply_first_run_result != content::RESULT_CODE_NORMAL_EXIT)
917     return apply_first_run_result;
918
919   embedder_support::OriginTrialsSettingsStorage*
920       origin_trials_settings_storage =
921           browser_process_->GetOriginTrialsSettingsStorage();
922   embedder_support::SetupOriginTrialsCommandLineAndSettings(
923       browser_process_->local_state(), origin_trials_settings_storage);
924   blink::OriginTrialsSettingsProvider::Get()->SetSettings(
925       origin_trials_settings_storage->GetSettings());
926
927   metrics::EnableExpiryChecker(chrome_metrics::kExpiredHistogramsHashes);
928
929   return content::RESULT_CODE_NORMAL_EXIT;
930 }
931
932 int ChromeBrowserMainParts::ApplyFirstRunPrefs() {
933 // Android does first run in Java instead of native.
934 // Chrome OS has its own out-of-box-experience code.
935 #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
936   master_prefs_ = std::make_unique<first_run::MasterPrefs>();
937
938   std::unique_ptr<installer::InitialPreferences> installer_initial_prefs =
939       startup_data_->chrome_feature_list_creator()->TakeInitialPrefs();
940   if (!installer_initial_prefs)
941     return content::RESULT_CODE_NORMAL_EXIT;
942
943   // On first run, we need to process the predictor preferences before the
944   // browser's profile_manager object is created, but after ResourceBundle
945   // is initialized.
946   first_run::ProcessInitialPreferencesResult pip_result =
947       first_run::ProcessInitialPreferences(user_data_dir_,
948                                            std::move(installer_initial_prefs),
949                                            master_prefs_.get());
950   if (pip_result == first_run::EULA_EXIT_NOW)
951     return chrome::RESULT_CODE_EULA_REFUSED;
952
953   // TODO(macourteau): refactor preferences that are copied from
954   // master_preferences into local_state, as a "local_state" section in
955   // initial preferences. If possible, a generic solution would be preferred
956   // over a copy one-by-one of specific preferences. Also see related TODO
957   // in first_run.h.
958
959   PrefService* local_state = g_browser_process->local_state();
960   if (!master_prefs_->suppress_default_browser_prompt_for_version.empty()) {
961     local_state->SetString(
962         prefs::kBrowserSuppressDefaultBrowserPrompt,
963         master_prefs_->suppress_default_browser_prompt_for_version);
964   }
965 #if BUILDFLAG(IS_MAC)
966   if (!master_prefs_->confirm_to_quit) {
967     local_state->SetBoolean(prefs::kConfirmToQuitEnabled,
968                             master_prefs_->confirm_to_quit);
969   }
970 #endif  // BUILDFLAG(IS_MAC)
971 #endif  // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
972   return content::RESULT_CODE_NORMAL_EXIT;
973 }
974
975 int ChromeBrowserMainParts::PreCreateThreadsImpl() {
976   TRACE_EVENT0("startup", "ChromeBrowserMainParts::PreCreateThreadsImpl");
977
978   if (browser_process_->GetApplicationLocale().empty()) {
979     ShowMissingLocaleMessageBox();
980     return chrome::RESULT_CODE_MISSING_DATA;
981   }
982
983 #if !BUILDFLAG(IS_ANDROID)
984   chrome::MaybeShowInvalidUserDataDirWarningDialog();
985 #endif  // !BUILDFLAG(IS_ANDROID)
986
987   DCHECK(!user_data_dir_.empty());
988
989   // Force MediaCaptureDevicesDispatcher to be created on UI thread.
990   MediaCaptureDevicesDispatcher::GetInstance();
991
992   // Android's first run is done in Java instead of native.
993 #if !BUILDFLAG(IS_ANDROID)
994   // Cache first run state early.
995   first_run::IsChromeFirstRun();
996 #endif  // !BUILDFLAG(IS_ANDROID)
997
998   PrefService* local_state = browser_process_->local_state();
999
1000 #if BUILDFLAG(IS_CHROMEOS_ASH)
1001   ash::CrosSettings::Initialize(local_state);
1002   ash::StatsReportingController::Initialize(local_state);
1003   arc::StabilityMetricsManager::Initialize(local_state);
1004   ash::HWDataUsageController::Initialize(local_state);
1005 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
1006
1007   {
1008     TRACE_EVENT0(
1009         "startup",
1010         "ChromeBrowserMainParts::PreCreateThreadsImpl:InitBrowserProcessImpl");
1011     browser_process_->Init();
1012   }
1013
1014 #if !BUILDFLAG(IS_ANDROID)
1015   // These members must be initialized before returning from this function.
1016   // Android doesn't use StartupBrowserCreator.
1017   browser_creator_ = std::make_unique<StartupBrowserCreator>();
1018   // TODO(yfriedman): Refactor Android to re-use UMABrowsingActivityObserver
1019   chrome::UMABrowsingActivityObserver::Init();
1020 #endif  // !BUILDFLAG(IS_ANDROID)
1021
1022 #if BUILDFLAG(IS_WIN)
1023   // This is needed to enable ETW exporting. This is only relevant for the
1024   // browser process, as other processes enable it separately.
1025   base::trace_event::TraceEventETWExport::EnableETWExport();
1026 #endif  // BUILDFLAG(IS_WIN)
1027
1028   // Reset the command line in the crash report details, since we may have
1029   // just changed it to include experiments.
1030   crash_keys::SetCrashKeysFromCommandLine(
1031       *base::CommandLine::ForCurrentProcess());
1032
1033   browser_process_->browser_policy_connector()->OnResourceBundleCreated();
1034
1035 // Android does first run in Java instead of native.
1036 // Chrome OS has its own out-of-box-experience code.
1037 #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
1038   if (first_run::IsChromeFirstRun()) {
1039     if (!base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kApp) &&
1040         !base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kAppId)) {
1041       browser_creator_->AddFirstRunTabs(master_prefs_->new_tabs);
1042     }
1043
1044 #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
1045     // Create directory for user-level Native Messaging manifest files. This
1046     // makes it less likely that the directory will be created by third-party
1047     // software with incorrect owner or permission. See crbug.com/725513 .
1048     base::FilePath user_native_messaging_dir;
1049     CHECK(base::PathService::Get(chrome::DIR_USER_NATIVE_MESSAGING,
1050                                  &user_native_messaging_dir));
1051     if (!base::PathExists(user_native_messaging_dir))
1052       base::CreateDirectory(user_native_messaging_dir);
1053 #endif  // BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
1054   }
1055 #endif  // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
1056
1057 #if BUILDFLAG(IS_CHROMEOS)
1058   // Set the product channel for crash reports.
1059   if (!crash_reporter::IsCrashpadEnabled()) {
1060     breakpad::SetChannelCrashKey(
1061         chrome::GetChannelName(chrome::WithExtendedStable(true)));
1062   }
1063 #endif  // BUILDFLAG(IS_CHROMEOS)
1064
1065 #if BUILDFLAG(IS_MAC)
1066 #if defined(ARCH_CPU_X86_64)
1067   // The use of Rosetta to run the x64 version of Chromium on Arm is neither
1068   // tested nor maintained, and there are reports of it crashing in weird ways
1069   // (e.g. https://crbug.com/1305353). Warn the user if this is the case, as
1070   // it's almost certainly accidental on their part.
1071   if (base::mac::GetCPUType() == base::mac::CPUType::kTranslatedIntel) {
1072     LOG(ERROR) << "The use of Rosetta to run the x64 version of Chromium on "
1073                   "Arm is neither tested nor maintained, and unexpected "
1074                   "behavior will likely result. Please check that all tools "
1075                   "that spawn Chromium are Arm-native.";
1076     base::PlatformThread::Sleep(base::Seconds(3));
1077   }
1078 #endif  // defined(ARCH_CPU_X86_64)
1079
1080   // Get the Keychain API to register for distributed notifications on the main
1081   // thread, which has a proper CFRunloop, instead of later on the I/O thread,
1082   // which doesn't. This ensures those notifications will get delivered
1083   // properly. See issue 37766.
1084   // (Note that the callback mask here is empty. I don't want to register for
1085   // any callbacks, I just want to initialize the mechanism.)
1086
1087   // Much of the Keychain API was marked deprecated as of the macOS 13 SDK.
1088   // Removal of its use is tracked in https://crbug.com/1348251 but deprecation
1089   // warnings are disabled in the meanwhile.
1090 #pragma clang diagnostic push
1091 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1092   SecKeychainAddCallback(&KeychainCallback, 0, nullptr);
1093 #pragma clang diagnostic pop
1094
1095 #endif  // BUILDFLAG(IS_MAC)
1096
1097 // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
1098 // of lacros-chrome is complete.
1099 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || \
1100     BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_FUCHSIA)
1101   metrics::DesktopSessionDurationTracker::Initialize();
1102   ProfileActivityMetricsRecorder::Initialize();
1103   TouchModeStatsTracker::Initialize(
1104       metrics::DesktopSessionDurationTracker::Get(),
1105       ui::TouchUiController::Get());
1106 #endif
1107
1108   // Add Site Isolation switches as dictated by policy.
1109   auto* command_line = base::CommandLine::ForCurrentProcess();
1110   if (local_state->GetBoolean(prefs::kSitePerProcess) &&
1111       site_isolation::SiteIsolationPolicy::IsEnterprisePolicyApplicable() &&
1112       !command_line->HasSwitch(switches::kSitePerProcess)) {
1113     command_line->AppendSwitch(switches::kSitePerProcess);
1114   }
1115   // IsolateOrigins policy is taken care of through SiteIsolationPrefsObserver
1116   // (constructed and owned by BrowserProcessImpl).
1117
1118 #if BUILDFLAG(IS_ANDROID)
1119   // The admin should also be able to use these policies to force Site Isolation
1120   // off (on Android; using enterprise policies to disable Site Isolation is not
1121   // supported on other platforms).  Note that disabling either SitePerProcess
1122   // or IsolateOrigins via policy will disable both types of isolation.
1123   if ((local_state->IsManagedPreference(prefs::kSitePerProcess) &&
1124        !local_state->GetBoolean(prefs::kSitePerProcess)) ||
1125       (local_state->IsManagedPreference(prefs::kIsolateOrigins) &&
1126        local_state->GetString(prefs::kIsolateOrigins).empty())) {
1127     base::CommandLine::ForCurrentProcess()->AppendSwitch(
1128         switches::kDisableSiteIsolationForPolicy);
1129   }
1130 #endif
1131
1132   if (local_state->IsManagedPreference(
1133           prefs::kThrottleNonVisibleCrossOriginIframesAllowed) &&
1134       !local_state->GetBoolean(
1135           prefs::kThrottleNonVisibleCrossOriginIframesAllowed)) {
1136     base::CommandLine::ForCurrentProcess()->AppendSwitch(
1137         blink::switches::kDisableThrottleNonVisibleCrossOriginIframes);
1138   }
1139
1140   if (local_state->IsManagedPreference(
1141           prefs::kNewBaseUrlInheritanceBehaviorAllowed) &&
1142       !local_state->GetBoolean(prefs::kNewBaseUrlInheritanceBehaviorAllowed)) {
1143     base::CommandLine::ForCurrentProcess()->AppendSwitch(
1144         blink::switches::kDisableNewBaseUrlInheritanceBehavior);
1145   }
1146
1147   // ChromeOS needs ui::ResourceBundle::InitSharedInstance to be called before
1148   // this.
1149   browser_process_->PreCreateThreads();
1150
1151   // This must occur in PreCreateThreads() because it initializes global state
1152   // which is then read by all threads without synchronization. It must be after
1153   // browser_process_->PreCreateThreads() as that instantiates the IOThread
1154   // which is used in SetupMetrics().
1155   SetupMetrics();
1156
1157   return content::RESULT_CODE_NORMAL_EXIT;
1158 }
1159
1160 void ChromeBrowserMainParts::PostCreateThreads() {
1161   // This task should be posted after the IO thread starts, and prior to the
1162   // base version of the function being invoked. It is functionally okay to post
1163   // this task in method ChromeBrowserMainParts::BrowserThreadsStarted() which
1164   // we also need to add in this class, and call this method at the very top of
1165   // BrowserMainLoop::InitializeMainThread(). PostCreateThreads is preferred to
1166   // BrowserThreadsStarted as it matches the PreCreateThreads and CreateThreads
1167   // stages.
1168   content::GetIOThreadTaskRunner({})->PostTask(
1169       FROM_HERE, base::BindOnce(&ThreadProfiler::StartOnChildThread,
1170                                 metrics::CallStackProfileParams::Thread::kIo));
1171 // Sampling multiple threads might cause overhead on Android and we don't want
1172 // to enable it unless the data is needed.
1173 #if !BUILDFLAG(IS_ANDROID)
1174   // We pass in CreateCoreUnwindersFactory here since it lives in the chrome/
1175   // layer while TracingSamplerProfiler is outside of chrome/.
1176   content::GetIOThreadTaskRunner({})->PostTask(
1177       FROM_HERE,
1178       base::BindOnce(&tracing::TracingSamplerProfiler::
1179                          CreateOnChildThreadWithCustomUnwinders,
1180                      base::BindRepeating(&CreateCoreUnwindersFactory)));
1181 #endif
1182
1183 #if BUILDFLAG(ENABLE_PROCESS_SINGLETON)
1184   ChromeProcessSingleton::GetInstance()->StartWatching();
1185 #endif
1186
1187   tracing::MaybeSetupSystemTracingFromFieldTrial();
1188   tracing::SetupBackgroundTracingFromCommandLine();
1189
1190   for (auto& chrome_extra_part : chrome_extra_parts_)
1191     chrome_extra_part->PostCreateThreads();
1192 }
1193
1194 int ChromeBrowserMainParts::PreMainMessageLoopRun() {
1195   TRACE_EVENT0("startup", "ChromeBrowserMainParts::PreMainMessageLoopRun");
1196
1197   result_code_ = PreMainMessageLoopRunImpl();
1198
1199   for (auto& chrome_extra_part : chrome_extra_parts_)
1200     chrome_extra_part->PreMainMessageLoopRun();
1201
1202   return result_code_;
1203 }
1204
1205 // PreMainMessageLoopRun calls these extra stages in the following order:
1206 //  PreMainMessageLoopRunImpl()
1207 //   ... initial setup, including browser_process_ setup.
1208 //   PreProfileInit()
1209 //   ... additional setup, including CreateProfile()
1210 //   PostProfileInit()
1211 //   ... additional setup
1212 //   PreBrowserStart()
1213 //   ... browser_creator_->Start
1214 //   PostBrowserStart()
1215
1216 void ChromeBrowserMainParts::PreProfileInit() {
1217   TRACE_EVENT0("startup", "ChromeBrowserMainParts::PreProfileInit");
1218
1219   media::AudioManager::SetGlobalAppName(
1220       l10n_util::GetStringUTF8(IDS_SHORT_PRODUCT_NAME));
1221
1222   for (auto& chrome_extra_part : chrome_extra_parts_)
1223     chrome_extra_part->PreProfileInit();
1224
1225   DisallowKeyedServiceFactoryRegistration();
1226
1227 #if !BUILDFLAG(IS_ANDROID)
1228   // Ephemeral profiles may have been left behind if the browser crashed.
1229   g_browser_process->profile_manager()
1230       ->GetDeleteProfileHelper()
1231       .CleanUpEphemeralProfiles();
1232   // Files of deleted profiles can also be left behind after a crash.
1233   g_browser_process->profile_manager()
1234       ->GetDeleteProfileHelper()
1235       .CleanUpDeletedProfiles();
1236 #endif  // !BUILDFLAG(IS_ANDROID)
1237
1238 #if BUILDFLAG(ENABLE_EXTENSIONS)
1239   javascript_dialog_extensions_client::InstallClient();
1240 #endif  // BUILDFLAG(ENABLE_EXTENSIONS)
1241
1242 #if BUILDFLAG(IS_MAC)
1243   if (base::FeatureList::IsEnabled(features::kViewsJSAppModalDialog))
1244     InstallChromeJavaScriptAppModalDialogViewFactory();
1245   else
1246     InstallChromeJavaScriptAppModalDialogViewCocoaFactory();
1247 #else
1248   InstallChromeJavaScriptAppModalDialogViewFactory();
1249 #endif  // BUILDFLAG(IS_MAC)
1250
1251 #if BUILDFLAG(ENABLE_EXTENSIONS)
1252   SetChromeAppModalDialogManagerDelegate();
1253 #endif  // BUILDFLAG(ENABLE_EXTENSIONS)
1254
1255   media_router::ChromeMediaRouterFactory::DoPlatformInit();
1256 }
1257
1258 void ChromeBrowserMainParts::CallPostProfileInit(Profile* profile) {
1259   DCHECK(profile);
1260   bool is_initial_profile = !initialized_initial_profile_;
1261   initialized_initial_profile_ = true;
1262
1263   PostProfileInit(profile, is_initial_profile);
1264 }
1265
1266 void ChromeBrowserMainParts::PostProfileInit(Profile* profile,
1267                                              bool is_initial_profile) {
1268   if (is_initial_profile) {
1269     TRACE_EVENT0("startup", "ChromeBrowserMainParts::PostProfileInit");
1270   }
1271
1272   for (auto& chrome_extra_part : chrome_extra_parts_)
1273     chrome_extra_part->PostProfileInit(profile, is_initial_profile);
1274
1275 #if BUILDFLAG(IS_WIN)
1276   // Verify that the profile is not on a network share and if so prepare to show
1277   // notification to the user.
1278   if (NetworkProfileBubble::ShouldCheckNetworkProfile(profile)) {
1279     base::ThreadPool::PostTask(
1280         FROM_HERE, {base::MayBlock()},
1281         base::BindOnce(&NetworkProfileBubble::CheckNetworkProfile,
1282                        profile->GetPath()));
1283   }
1284
1285 #if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
1286   // Create the spellcheck service. This will asynchronously retrieve the
1287   // Windows platform spellcheck dictionary language tags used to populate the
1288   // context menu for editable content.
1289   if (spellcheck::UseBrowserSpellChecker() &&
1290       profile->GetPrefs()->GetBoolean(spellcheck::prefs::kSpellCheckEnable) &&
1291       !base::FeatureList::IsEnabled(
1292           spellcheck::kWinDelaySpellcheckServiceInit)) {
1293     SpellcheckServiceFactory::GetForContext(profile);
1294   }
1295 #endif  // BUILDFLAG(USE_BROWSER_SPELLCHECKER)
1296 #endif  // BUILDFLAG(IS_WIN)
1297
1298 #if !BUILDFLAG(IS_ANDROID)
1299   if (ShouldInstallSodaDuringPostProfileInit(
1300           *base::CommandLine::ForCurrentProcess())) {
1301     speech::SodaInstaller::GetInstance()->Init(profile->GetPrefs(),
1302                                                browser_process_->local_state());
1303   }
1304 #endif  // !BUILDFLAG(IS_ANDROID)
1305
1306 #if BUILDFLAG(ENABLE_RLZ) && !BUILDFLAG(IS_CHROMEOS_ASH)
1307   if (is_initial_profile) {
1308     // Init the RLZ library. This just binds the dll and schedules a task on the
1309     // file thread to be run sometime later. If this is the first run we record
1310     // the installation event.
1311     int ping_delay =
1312         profile->GetPrefs()->GetInteger(prefs::kRlzPingDelaySeconds);
1313     // Negative ping delay means to send ping immediately after a first search
1314     // is recorded.
1315     rlz::RLZTracker::SetRlzDelegate(
1316         std::make_unique<ChromeRLZTrackerDelegate>());
1317     rlz::RLZTracker::InitRlzDelayed(
1318         first_run::IsChromeFirstRun(), ping_delay < 0,
1319         base::Seconds(abs(ping_delay)),
1320         ChromeRLZTrackerDelegate::IsGoogleDefaultSearch(profile),
1321         ChromeRLZTrackerDelegate::IsGoogleHomepage(profile),
1322         ChromeRLZTrackerDelegate::IsGoogleInStartpages(profile));
1323   }
1324 #endif  // BUILDFLAG(ENABLE_RLZ) && !BUILDFLAG(IS_CHROMEOS_ASH)
1325
1326   language::LanguageUsageMetrics::RecordAcceptLanguages(
1327       profile->GetPrefs()->GetString(language::prefs::kAcceptLanguages));
1328   translate::TranslateMetricsLoggerImpl::LogApplicationStartMetrics(
1329       ChromeTranslateClient::CreateTranslatePrefs(profile->GetPrefs()));
1330 // On ChromeOS results in a crash. https://crbug.com/1151558
1331 #if !BUILDFLAG(IS_CHROMEOS_ASH)
1332   language::LanguageUsageMetrics::RecordPageLanguages(
1333       *UrlLanguageHistogramFactory::GetForBrowserContext(profile));
1334 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
1335
1336 #if (BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_TIZEN)) || BUILDFLAG(IS_WIN) || \
1337     BUILDFLAG(IS_MAC)  // FIXME : m120 bringup
1338   if (headless::IsHeadlessMode()) {
1339     headless::ReportHeadlessActionMetrics();
1340   }
1341 #endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
1342 }
1343
1344 void ChromeBrowserMainParts::PreBrowserStart() {
1345   TRACE_EVENT0("startup", "ChromeBrowserMainParts::PreBrowserStart");
1346   for (auto& chrome_extra_part : chrome_extra_parts_)
1347     chrome_extra_part->PreBrowserStart();
1348
1349 #if !BUILDFLAG(IS_ANDROID)
1350   // Start the tab manager here so that we give the most amount of time for the
1351   // other services to start up before we start adjusting the oom priority.
1352   g_browser_process->GetTabManager()->Start();
1353
1354   CheckPakFileIntegrity();
1355 #endif
1356
1357   // The RulesetService will make the filtering rules available to renderers
1358   // immediately after its construction, provided that the rules are already
1359   // available at no cost in an indexed format. This enables activating
1360   // subresource filtering, if needed, also for page loads on start-up.
1361   g_browser_process->subresource_filter_ruleset_service();
1362 }
1363
1364 void ChromeBrowserMainParts::PostBrowserStart() {
1365   TRACE_EVENT0("startup", "ChromeBrowserMainParts::PostBrowserStart");
1366   for (auto& chrome_extra_part : chrome_extra_parts_)
1367     chrome_extra_part->PostBrowserStart();
1368
1369 #if BUILDFLAG(ENABLE_PROCESS_SINGLETON)
1370   // Allow ProcessSingleton to process messages.
1371   // This is done here instead of just relying on the main message loop's start
1372   // to avoid rendezvous in RunLoops that may precede MainMessageLoopRun.
1373   ChromeProcessSingleton::GetInstance()->Unlock(base::BindRepeating(
1374       &ChromeBrowserMainParts::ProcessSingletonNotificationCallback));
1375 #endif  // BUILDFLAG(ENABLE_PROCESS_SINGLETON)
1376
1377   // Set up a task to delete old WebRTC log files for all profiles. Use a delay
1378   // to reduce the impact on startup time.
1379   content::GetUIThreadTaskRunner({})->PostDelayedTask(
1380       FROM_HERE,
1381       base::BindOnce(&WebRtcLogUtil::DeleteOldWebRtcLogFilesForAllProfiles),
1382       base::Minutes(1));
1383
1384 #if !BUILDFLAG(IS_ANDROID)
1385   if (base::FeatureList::IsEnabled(features::kWebUsb)) {
1386     web_usb_detector_ = std::make_unique<WebUsbDetector>();
1387     content::GetUIThreadTaskRunner({base::TaskPriority::BEST_EFFORT})
1388         ->PostTask(FROM_HERE,
1389                    base::BindOnce(&WebUsbDetector::Initialize,
1390                                   base::Unretained(web_usb_detector_.get())));
1391   }
1392 #endif
1393
1394   // At this point, StartupBrowserCreator::Start has run creating initial
1395   // browser windows and tabs, but no progress has been made in loading
1396   // content as the main message loop hasn't started processing tasks yet.
1397   // We setup to observe to the initial page load here to defer running
1398   // task posted via PostAfterStartupTask until its complete.
1399   AfterStartupTaskUtils::StartMonitoringStartup();
1400 }
1401
1402 int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() {
1403   TRACE_EVENT0("startup", "ChromeBrowserMainParts::PreMainMessageLoopRunImpl");
1404
1405   SCOPED_UMA_HISTOGRAM_LONG_TIMER("Startup.PreMainMessageLoopRunImplLongTime");
1406
1407 #if BUILDFLAG(IS_WIN)
1408   // Windows parental controls calls can be slow, so we do an early init here
1409   // that calculates this value off of the UI thread.
1410   InitializeWinParentalControls();
1411 #endif
1412
1413   // Now that the file thread has been started, start metrics.
1414   StartMetricsRecording();
1415
1416   // Do any initializating in the browser process that requires all threads
1417   // running.
1418   browser_process_->PreMainMessageLoopRun();
1419
1420 #if BUILDFLAG(IS_WIN)
1421   // If the command line specifies 'uninstall' then we need to work here
1422   // unless we detect another chrome browser running.
1423   if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kUninstall)) {
1424     return DoUninstallTasks(browser_util::IsBrowserAlreadyRunning());
1425   }
1426
1427   if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kHideIcons) ||
1428       base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kShowIcons)) {
1429     return ChromeBrowserMainPartsWin::HandleIconsCommands(
1430         *base::CommandLine::ForCurrentProcess());
1431   }
1432
1433   ui::SelectFileDialog::SetFactory(
1434       std::make_unique<ChromeSelectFileDialogFactory>());
1435 #elif BUILDFLAG(IS_CHROMEOS_LACROS)
1436   ui::SelectFileDialog::SetFactory(
1437       std::make_unique<ui::SelectFileDialogLacros::Factory>());
1438 #endif  // BUILDFLAG(IS_WIN)
1439
1440   // In headless mode provide alternate SelectFileDialog factory overriding
1441   // any platform specific SelectFileDialog implementation that may have been
1442   // set.
1443 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
1444   if (headless::IsHeadlessMode()) {
1445     headless::HeadlessSelectFileDialogFactory::SetUp();
1446   }
1447 #endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
1448
1449   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
1450           switches::kMakeDefaultBrowser)) {
1451     bool is_managed = g_browser_process->local_state()->IsManagedPreference(
1452         prefs::kDefaultBrowserSettingEnabled);
1453     if (is_managed && !g_browser_process->local_state()->GetBoolean(
1454         prefs::kDefaultBrowserSettingEnabled)) {
1455       return static_cast<int>(chrome::RESULT_CODE_ACTION_DISALLOWED_BY_POLICY);
1456     }
1457
1458     return shell_integration::SetAsDefaultBrowser()
1459                ? static_cast<int>(content::RESULT_CODE_NORMAL_EXIT)
1460                : static_cast<int>(chrome::RESULT_CODE_SHELL_INTEGRATION_FAILED);
1461   }
1462
1463 #if defined(USE_AURA)
1464   // Make sure aura::Env has been initialized.
1465   CHECK(aura::Env::GetInstance());
1466 #endif  // defined(USE_AURA)
1467
1468 #if BUILDFLAG(IS_WIN)
1469   // We must call DoUpgradeTasks now that we own the browser singleton to
1470   // finish upgrade tasks (swap) and relaunch if necessary.
1471   if (upgrade_util::DoUpgradeTasks(*base::CommandLine::ForCurrentProcess()))
1472     return chrome::RESULT_CODE_NORMAL_EXIT_UPGRADE_RELAUNCHED;
1473 #endif  // BUILDFLAG(IS_WIN)
1474
1475 #if !BUILDFLAG(IS_ANDROID) && BUILDFLAG(ENABLE_DOWNGRADE_PROCESSING)
1476   // Begin relaunch processing immediately if User Data migration is required
1477   // to handle a version downgrade.
1478   if (downgrade_manager_.PrepareUserDataDirectoryForCurrentVersion(
1479           user_data_dir_)) {
1480     return chrome::RESULT_CODE_DOWNGRADE_AND_RELAUNCH;
1481   }
1482   downgrade_manager_.UpdateLastVersion(user_data_dir_);
1483 #endif  // !BUILDFLAG(IS_ANDROID) && BUILDFLAG(ENABLE_DOWNGRADE_PROCESSING)
1484
1485 #if !BUILDFLAG(IS_CHROMEOS_ASH)
1486   // Initialize the chrome browser cloud management controller after
1487   // the browser process singleton is acquired to remove race conditions where
1488   // multiple browser processes start simultaneously.  The main
1489   // initialization of browser_policy_connector is performed inside
1490   // PreMainMessageLoopRun() so that policies can be applied as soon as
1491   // possible.
1492   //
1493   // Note that this protects against multiple browser process starts in
1494   // the same user data dir and not multiple starts across user data dirs.
1495   browser_process_->browser_policy_connector()->InitCloudManagementController(
1496       browser_process_->local_state(),
1497       browser_process_->system_network_context_manager()
1498           ->GetSharedURLLoaderFactory());
1499 #endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
1500
1501 #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
1502   // Wait for the chrome browser cloud management enrollment to finish.
1503   // If enrollment is not mandatory, this function returns immediately.
1504   // Abort the launch process if required enrollment fails.
1505   if (!browser_process_->browser_policy_connector()
1506            ->chrome_browser_cloud_management_controller()
1507            ->WaitUntilPolicyEnrollmentFinished()) {
1508     return chrome::RESULT_CODE_CLOUD_POLICY_ENROLLMENT_FAILED;
1509   }
1510 #endif  // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
1511
1512 #if BUILDFLAG(IS_WIN)
1513   // Check if there is any machine level Chrome installed on the current
1514   // machine. If yes and the current Chrome process is user level, we do not
1515   // allow the user level Chrome to run. So we notify the user and uninstall
1516   // user level Chrome.
1517   // Note this check needs to happen here (after the process singleton was
1518   // obtained but before potentially creating the first run sentinel).
1519   if (ChromeBrowserMainPartsWin::CheckMachineLevelInstall())
1520     return chrome::RESULT_CODE_MACHINE_LEVEL_INSTALL_EXISTS;
1521 #endif  // BUILDFLAG(IS_WIN)
1522
1523   // Desktop construction occurs here, (required before profile creation).
1524   PreProfileInit();
1525
1526 #if BUILDFLAG(ENABLE_NACL)
1527   // NaClBrowserDelegateImpl is accessed inside CreateInitialProfile().
1528   // So make sure to create it before that.
1529   nacl::NaClBrowser::SetDelegate(std::make_unique<NaClBrowserDelegateImpl>(
1530       browser_process_->profile_manager()));
1531 #endif  // BUILDFLAG(ENABLE_NACL)
1532
1533   // This step is costly and is already measured in Startup.CreateFirstProfile
1534   // and more directly Profile.CreateAndInitializeProfile.
1535   StartupProfileInfo profile_info = CreateInitialProfile(
1536       /*cur_dir=*/base::FilePath(), *base::CommandLine::ForCurrentProcess());
1537   base::UmaHistogramEnumeration(
1538       "ProfilePicker.StartupMode.CreateInitialProfile", profile_info.mode);
1539
1540   if (profile_info.mode == StartupProfileMode::kError)
1541     return content::RESULT_CODE_NORMAL_EXIT;
1542
1543 #if !BUILDFLAG(IS_ANDROID)
1544   // The first run sentinel must be created after the process singleton was
1545   // grabbed (where enabled) and no early return paths were otherwise hit above.
1546   first_run::CreateSentinelIfNeeded();
1547 #endif  // !BUILDFLAG(IS_ANDROID)
1548
1549 #if BUILDFLAG(ENABLE_BACKGROUND_MODE)
1550   // Autoload any profiles which are running background apps.
1551   // TODO(rlp): Do this on a separate thread. See http://crbug.com/99075.
1552   browser_process_->profile_manager()->AutoloadProfiles();
1553 #endif  // BUILDFLAG(ENABLE_BACKGROUND_MODE)
1554   // Post-profile init ---------------------------------------------------------
1555
1556   TranslateService::Initialize();
1557   if (base::FeatureList::IsEnabled(features::kGeoLanguage) ||
1558       language::GetOverrideLanguageModel() ==
1559           language::OverrideLanguageModel::GEO) {
1560     language::GeoLanguageProvider::GetInstance()->StartUp(
1561         browser_process_->local_state());
1562   }
1563
1564   // Needs to be done before PostProfileInit, since login manager on CrOS is
1565   // called inside PostProfileInit.
1566   content::WebUIControllerFactory::RegisterFactory(
1567       ChromeWebUIControllerFactory::GetInstance());
1568   RegisterChromeWebUIConfigs();
1569   RegisterChromeUntrustedWebUIConfigs();
1570
1571 #if BUILDFLAG(IS_ANDROID)
1572   page_info::SetPageInfoClient(new ChromePageInfoClient());
1573 #endif
1574
1575   // Needs to be done before PostProfileInit, to allow connecting DevTools
1576   // before WebUI for the CrOS login that can be called inside PostProfileInit
1577   g_browser_process->CreateDevToolsProtocolHandler();
1578   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
1579           ::switches::kAutoOpenDevToolsForTabs))
1580     g_browser_process->CreateDevToolsAutoOpener();
1581
1582   // Needs to be done before PostProfileInit, since the SODA Installer setup is
1583   // called inside PostProfileInit and depends on it.
1584 #if BUILDFLAG(ENABLE_COMPONENT_UPDATER)
1585   if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
1586           switches::kDisableComponentUpdate)) {
1587     component_updater::RegisterComponentsForUpdate();
1588   }
1589 #endif  // BUILDFLAG(ENABLE_COMPONENT_UPDATER)
1590
1591   // `profile` may be nullptr if the profile picker is shown.
1592   Profile* profile = profile_info.profile;
1593   // Call `PostProfileInit()`and set it up for profiles created later.
1594   profile_init_manager_ = std::make_unique<ProfileInitManager>(this, profile);
1595
1596 #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
1597   // Execute first run specific code after the PrefService has been initialized
1598   // and preferences have been registered since some of the import code depends
1599   // on preferences.
1600   if (first_run::IsChromeFirstRun()) {
1601     // `profile` may be nullptr even on first run, for example when the
1602     // "BrowserSignin" policy is set to "Force". If so, skip the auto import.
1603     if (profile) {
1604       first_run::AutoImport(profile, master_prefs_->import_bookmarks_path);
1605     }
1606
1607     // Note: This can pop-up the first run consent dialog on Linux & Mac.
1608     first_run::DoPostImportTasks(master_prefs_->make_chrome_default_for_user);
1609
1610     // The first run dialog is modal, and spins a RunLoop, which could receive
1611     // a SIGTERM, and call chrome::AttemptExit(). Exit cleanly in that case.
1612     if (browser_shutdown::IsTryingToQuit())
1613       return content::RESULT_CODE_NORMAL_EXIT;
1614   }
1615 #endif  // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
1616
1617 #if BUILDFLAG(IS_WIN)
1618   // Sets things up so that if we crash from this point on, a dialog will
1619   // popup asking the user to restart chrome. It is done this late to avoid
1620   // testing against a bunch of special cases that are taken care early on.
1621   ChromeBrowserMainPartsWin::PrepareRestartOnCrashEnviroment(
1622       *base::CommandLine::ForCurrentProcess());
1623
1624   // Registers Chrome with the Windows Restart Manager, which will restore the
1625   // Chrome session when the computer is restarted after a system update.
1626   // This could be run as late as WM_QUERYENDSESSION for system update reboots,
1627   // but should run on startup if extended to handle crashes/hangs/patches.
1628   // Also, better to run once here than once for each HWND's WM_QUERYENDSESSION.
1629   if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
1630           switches::kBrowserTest)) {
1631     ChromeBrowserMainPartsWin::RegisterApplicationRestart(
1632         *base::CommandLine::ForCurrentProcess());
1633   }
1634 #endif  // BUILDFLAG(IS_WIN)
1635
1636   // Configure modules that need access to resources.
1637   net::NetModule::SetResourceProvider(ChromeNetResourceProvider);
1638   media::SetLocalizedStringProvider(ChromeMediaLocalizedStringProvider);
1639
1640 #if !BUILDFLAG(IS_ANDROID)
1641   // In unittest mode, this will do nothing.  In normal mode, this will create
1642   // the global IntranetRedirectDetector instance, which will promptly go to
1643   // sleep for seven seconds (to avoid slowing startup), and wake up afterwards
1644   // to see if it should do anything else.
1645   //
1646   // A simpler way of doing all this would be to have some function which could
1647   // give the time elapsed since startup, and simply have this object check that
1648   // when asked to initialize itself, but this doesn't seem to exist.
1649   //
1650   // This can't be created in the BrowserProcessImpl constructor because it
1651   // needs to read prefs that get set after that runs.
1652   browser_process_->intranet_redirect_detector();
1653 #endif
1654
1655 #if BUILDFLAG(ENABLE_PRINT_PREVIEW) && !defined(OFFICIAL_BUILD)
1656   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
1657           switches::kDebugPrint)) {
1658     base::FilePath path =
1659         base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(
1660             switches::kDebugPrint);
1661     if (!path.empty())
1662       printing::PrintedDocument::SetDebugDumpPath(path);
1663   }
1664 #endif  // BUILDFLAG(ENABLE_PRINT_PREVIEW) && !defined(OFFICIAL_BUILD)
1665
1666 #if BUILDFLAG(ENABLE_PRINTING)
1667   printing::InitializeProcessForPrinting();
1668 #endif
1669
1670   HandleTestParameters(*base::CommandLine::ForCurrentProcess());
1671
1672   // This has to come before the first GetInstance() call. PreBrowserStart()
1673   // seems like a reasonable place to put this, except on Android,
1674   // OfflinePageInfoHandler::Register() below calls GetInstance().
1675   // TODO(thestig): See if the Android code below can be moved to later.
1676   sessions::ContentSerializedNavigationDriver::SetInstance(
1677       ChromeSerializedNavigationDriver::GetInstance());
1678
1679 #if BUILDFLAG(ENABLE_OFFLINE_PAGES)
1680   offline_pages::OfflinePageInfoHandler::Register();
1681 #endif
1682
1683 #if BUILDFLAG(ENABLE_NACL)
1684   nacl::NaClProcessHost::EarlyStartup();
1685 #endif  // BUILDFLAG(ENABLE_NACL)
1686
1687   PreBrowserStart();
1688
1689   variations::VariationsService* variations_service =
1690       browser_process_->variations_service();
1691   variations_service->PerformPreMainMessageLoopStartup();
1692
1693 #if BUILDFLAG(IS_ANDROID)
1694   // The profile picker is never shown on Android.
1695   DCHECK_EQ(profile_info.mode, StartupProfileMode::kBrowserWindow);
1696   DCHECK(profile);
1697   // Just initialize the policy prefs service here. Variations seed fetching
1698   // will be initialized when the app enters foreground mode.
1699   variations_service->set_policy_pref_service(profile->GetPrefs());
1700 #else
1701   // We are in regular browser boot sequence. Open initial tabs and enter the
1702   // main message loop.
1703   std::vector<Profile*> last_opened_profiles;
1704 #if !BUILDFLAG(IS_CHROMEOS_ASH)
1705   // On ChromeOS multiple profiles doesn't apply, and will break if we load
1706   // them this early as the cryptohome hasn't yet been mounted (which happens
1707   // only once we log in). And if we're launching a web app, we don't want to
1708   // restore the last opened profiles.
1709   if (!base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kAppId)) {
1710     last_opened_profiles =
1711         g_browser_process->profile_manager()->GetLastOpenedProfiles();
1712   }
1713 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
1714
1715   // This step is costly and is already measured in
1716   // Startup.StartupBrowserCreator_Start.
1717   if (browser_creator_->Start(*base::CommandLine::ForCurrentProcess(),
1718                               base::FilePath(), profile_info,
1719                               last_opened_profiles)) {
1720 // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
1721 // of lacros-chrome is complete.
1722 #if BUILDFLAG(IS_WIN) || (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS))
1723     // Initialize autoupdate timer. Timer callback costs basically nothing
1724     // when browser is not in persistent mode, so it's OK to let it ride on
1725     // the main thread. This needs to be done here because we don't want
1726     // to start the timer when Chrome is run inside a test harness.
1727     browser_process_->StartAutoupdateTimer();
1728 #endif  // BUILDFLAG(IS_WIN) || (BUILDFLAG(IS_LINUX) ||
1729         // BUILDFLAG(IS_CHROMEOS_LACROS))
1730
1731 // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
1732 // of lacros-chrome is complete.
1733 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
1734     // On Linux, the running exe will be updated if an upgrade becomes
1735     // available while the browser is running.  We need to save the last
1736     // modified time of the exe, so we can compare to determine if there is
1737     // an upgrade while the browser is kept alive by a persistent extension.
1738     upgrade_util::SaveLastModifiedTimeOfExe();
1739 #endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
1740
1741     // Record now as the last successful chrome start.
1742     if constexpr (kShouldRecordActiveUse) {
1743       GoogleUpdateSettings::SetLastRunTime();
1744     }
1745
1746     // Create the RunLoop for MainMessageLoopRun() to use and transfer
1747     // ownership of the browser's lifetime to the BrowserProcess.
1748     DCHECK(!GetMainRunLoopInstance());
1749     GetMainRunLoopInstance() = std::make_unique<base::RunLoop>();
1750     browser_process_->SetQuitClosure(
1751         GetMainRunLoopInstance()->QuitWhenIdleClosure());
1752   }
1753   browser_creator_.reset();
1754 #endif  // !BUILDFLAG(IS_ANDROID)
1755
1756   PostBrowserStart();
1757
1758 #if BUILDFLAG(ENABLE_DOWNGRADE_PROCESSING)
1759   // Clean up old user data directory, snapshots and disk cache directory.
1760   downgrade_manager_.DeleteMovedUserDataSoon(user_data_dir_);
1761 #endif
1762
1763   // This should be invoked as close as possible to the start of the browser's
1764   // main loop, but before the end of PreMainMessageLoopRun in order for
1765   // browser tests (which InterceptMainMessageLoopRun rather than
1766   // MainMessageLoopRun) to be able to see its side-effect.
1767   if (result_code_ <= 0)
1768     RecordBrowserStartupTime();
1769
1770   return result_code_;
1771 }
1772
1773 #if !BUILDFLAG(IS_ANDROID)
1774 bool ChromeBrowserMainParts::ShouldInterceptMainMessageLoopRun() {
1775   // Some early return paths in PreMainMessageLoopRunImpl intentionally prevent
1776   // the main run loop from being created. Use this as a signal to indicate that
1777   // the main message loop shouldn't be run.
1778   return !!GetMainRunLoopInstance();
1779 }
1780 #endif
1781
1782 void ChromeBrowserMainParts::WillRunMainMessageLoop(
1783     std::unique_ptr<base::RunLoop>& run_loop) {
1784 #if BUILDFLAG(IS_ANDROID)
1785   // Chrome on Android does not use default MessageLoop. It has its own
1786   // Android specific MessageLoop
1787   NOTREACHED();
1788 #else
1789   DCHECK(base::CurrentUIThread::IsSet());
1790
1791   run_loop = std::move(GetMainRunLoopInstance());
1792
1793   // Trace the entry and exit of this main message loop. We don't use the
1794   // TRACE_EVENT_BEGIN0 macro because the tracing infrastructure doesn't expect
1795   // a synchronous event around the main loop of a thread.
1796   TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(
1797       "toplevel", "ChromeBrowserMainParts::MainMessageLoopRun", this);
1798 #endif  // BUILDFLAG(IS_ANDROID)
1799 }
1800
1801 void ChromeBrowserMainParts::OnFirstIdle() {
1802   startup_metric_utils::GetBrowser().RecordBrowserMainLoopFirstIdle(
1803       base::TimeTicks::Now());
1804 #if BUILDFLAG(IS_ANDROID)
1805   sharing::ShareHistory::CreateForProfile(
1806       ProfileManager::GetPrimaryUserProfile());
1807 #endif
1808
1809 #if BUILDFLAG(IS_CHROMEOS)
1810   // If OneGroupPerRenderer feature is enabled, post a task to clean any left
1811   // over cgroups due to any unclean exits.
1812   if (base::FeatureList::IsEnabled(base::kOneGroupPerRenderer)) {
1813     base::ThreadPool::PostTask(
1814         FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
1815         base::BindOnce(&base::Process::CleanUpStaleProcessStates));
1816   }
1817 #endif  // BUILDFLAG(IS_CHROMEOS)
1818
1819   if (blink::IdentifiabilityStudySettings::Get()->IsActive()) {
1820     base::ThreadPool::PostTask(
1821         FROM_HERE,
1822         {base::TaskPriority::BEST_EFFORT,
1823          base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
1824         base::BindOnce(&ActivelySampleIdentifiableSurfaces));
1825   }
1826 }
1827
1828 void ChromeBrowserMainParts::PostMainMessageLoopRun() {
1829   TRACE_EVENT_NESTABLE_ASYNC_END0(
1830       "toplevel", "ChromeBrowserMainParts::MainMessageLoopRun", this);
1831   TRACE_EVENT0("startup", "ChromeBrowserMainParts::PostMainMessageLoopRun");
1832 #if BUILDFLAG(IS_ANDROID)
1833   // Chrome on Android does not use default MessageLoop. It has its own
1834   // Android specific MessageLoop
1835   NOTREACHED();
1836 #else
1837   // Shutdown the UpgradeDetector here before `ChromeBrowserMainPartsAsh`
1838   // disconnects DBus services in its PostDestroyThreads.
1839   UpgradeDetector::GetInstance()->Shutdown();
1840
1841   // Start watching hangs up to the end of the process.
1842   StartWatchingForProcessShutdownHangs();
1843
1844   // Two different types of hang detection cannot attempt to upload crashes at
1845   // the same time or they would interfere with each other. Do not start the
1846   // ShutdownWatcher if the HangWatcher is already collecting crash.
1847   // TODO(crbug.com/1327000): Migrate away from ShutdownWatcher and its old
1848   // timing.
1849   if (!base::HangWatcher::IsCrashReportingEnabled()) {
1850     // Start watching for jank during shutdown. It gets disarmed when
1851     // |shutdown_watcher_| object is destructed.
1852     constexpr base::TimeDelta kShutdownHangDelay{base::Seconds(300)};
1853     shutdown_watcher_ = std::make_unique<ShutdownWatcherHelper>();
1854     shutdown_watcher_->Arm(kShutdownHangDelay);
1855   }
1856
1857   web_usb_detector_.reset();
1858
1859   for (auto& chrome_extra_part : chrome_extra_parts_)
1860     chrome_extra_part->PostMainMessageLoopRun();
1861
1862   TranslateService::Shutdown();
1863
1864 #if BUILDFLAG(ENABLE_PROCESS_SINGLETON)
1865   ChromeProcessSingleton::GetInstance()->Cleanup();
1866 #endif  // BUILDFLAG(ENABLE_PROCESS_SINGLETON)
1867
1868   browser_process_->metrics_service()->Stop();
1869
1870   restart_last_session_ = browser_shutdown::ShutdownPreThreadsStop();
1871   browser_process_->StartTearDown();
1872 #endif  // BUILDFLAG(IS_ANDROID)
1873 }
1874
1875 void ChromeBrowserMainParts::PostDestroyThreads() {
1876 #if BUILDFLAG(IS_ANDROID)
1877   // On Android, there is no quit/exit. So the browser's main message loop will
1878   // not finish.
1879   NOTREACHED();
1880 #else
1881
1882   browser_shutdown::RestartMode restart_mode =
1883       browser_shutdown::RestartMode::kNoRestart;
1884
1885   if (restart_last_session_) {
1886     restart_mode = browser_shutdown::RestartMode::kRestartLastSession;
1887
1888 #if BUILDFLAG(ENABLE_BACKGROUND_MODE)
1889     if (BackgroundModeManager::should_restart_in_background())
1890       restart_mode = browser_shutdown::RestartMode::kRestartInBackground;
1891 #endif  // BUILDFLAG(ENABLE_BACKGROUND_MODE)
1892   }
1893
1894   browser_process_->PostDestroyThreads();
1895
1896   // We need to do this call as late as possible, but due to modularity, this
1897   // may be the last point in Chrome. This would be more effective if done at a
1898   // higher level on the stack, so that it is impossible for an early return to
1899   // bypass this code. Perhaps we need a *final* hook that is called on all
1900   // paths from content/browser/browser_main.
1901   //
1902   // Since we use |browser_process_|'s local state for this call, it must be
1903   // done before |browser_process_| is released.
1904   metrics::Shutdown(browser_process_->local_state());
1905
1906   profile_init_manager_.reset();
1907
1908 #if BUILDFLAG(IS_CHROMEOS_ASH)
1909   // These controllers make use of `browser_process_->local_state()`, so they
1910   // must be destroyed before `browser_process_`.
1911   // Shutting down in the reverse order of Initialize().
1912   ash::HWDataUsageController::Shutdown();
1913   arc::StabilityMetricsManager::Shutdown();
1914   ash::StatsReportingController::Shutdown();
1915   ash::CrosSettings::Shutdown();
1916 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
1917
1918 #if BUILDFLAG(ENABLE_DOWNGRADE_PROCESSING)
1919   if (result_code_ == chrome::RESULT_CODE_DOWNGRADE_AND_RELAUNCH) {
1920     // Process a pending User Data downgrade before restarting.
1921     downgrade_manager_.ProcessDowngrade(user_data_dir_);
1922
1923     // It's impossible for there to also be a user-driven relaunch since the
1924     // browser never fully starts in this case.
1925     DCHECK(!restart_last_session_);
1926     restart_mode = browser_shutdown::RestartMode::kRestartThisSession;
1927   }
1928 #endif  // BUILDFLAG(ENABLE_DOWNGRADE_PROCESSING)
1929
1930   // From this point, the BrowserProcess class is no longer alive.
1931   browser_process_.reset();
1932
1933   browser_shutdown::ShutdownPostThreadsStop(restart_mode);
1934
1935 #if !BUILDFLAG(IS_CHROMEOS_ASH)
1936   master_prefs_.reset();
1937 #endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
1938
1939   device_event_log::Shutdown();
1940 #endif  // BUILDFLAG(IS_ANDROID)
1941 }
1942
1943 // Public members:
1944
1945 void ChromeBrowserMainParts::AddParts(
1946     std::unique_ptr<ChromeBrowserMainExtraParts> parts) {
1947   chrome_extra_parts_.push_back(std::move(parts));
1948 }
1949
1950 #if !BUILDFLAG(IS_ANDROID)
1951 // static
1952 std::unique_ptr<base::RunLoop> ChromeBrowserMainParts::TakeRunLoopForTest() {
1953   DCHECK(GetMainRunLoopInstance());
1954   return std::move(GetMainRunLoopInstance());
1955 }
1956 #endif  // !BUILDFLAG(IS_ANDROID)
1957
1958 #if BUILDFLAG(ENABLE_PROCESS_SINGLETON)
1959 // static
1960 bool ChromeBrowserMainParts::ProcessSingletonNotificationCallback(
1961     const base::CommandLine& command_line,
1962     const base::FilePath& current_directory) {
1963   // Drop the request if the browser process is already shutting down.
1964   // Note that we're going to post an async task below. Even if the browser
1965   // process isn't shutting down right now, it could be by the time the task
1966   // starts running. So, an additional check needs to happen when it starts.
1967   // But regardless of any future check, there is no reason to post the task
1968   // now if we know we're already shutting down.
1969   if (!g_browser_process || g_browser_process->IsShuttingDown()) {
1970     return false;
1971   }
1972
1973   // Drop the request if headless mode is in effect or the request is from
1974   // a headless Chrome process.
1975 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
1976   if (headless::IsHeadlessMode() ||
1977       command_line.HasSwitch(switches::kHeadless)) {
1978     return false;
1979   }
1980 #endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
1981
1982   // In order to handle this request on Windows, there is platform specific
1983   // code in browser_finder.cc that requires making outbound COM calls to
1984   // cross-apartment shell objects (via IVirtualDesktopManager). That is not
1985   // allowed within a SendMessage handler, which this function is a part of.
1986   // So, we post a task to asynchronously finish the command line processing.
1987   return base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1988       FROM_HERE, base::BindOnce(&ProcessSingletonNotificationCallbackImpl,
1989                                 command_line, current_directory));
1990 }
1991 #endif  // BUILDFLAG(ENABLE_PROCESS_SINGLETON)