1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
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 "content/browser/browser_main_loop.h"
6
7 #include <stddef.h>
8
9 #include <algorithm>
10 #include <memory>
11 #include <string>
12 #include <utility>
13 #include <vector>
14
15 #include "base/base_switches.h"
16 #include "base/bind.h"
17 #include "base/command_line.h"
18 #include "base/debug/alias.h"
19 #include "base/deferred_sequenced_task_runner.h"
20 #include "base/feature_list.h"
21 #include "base/location.h"
22 #include "base/logging.h"
23 #include "base/memory/memory_pressure_monitor.h"
24 #include "base/memory/ptr_util.h"
25 #include "base/message_loop/message_loop_current.h"
26 #include "base/metrics/field_trial.h"
27 #include "base/metrics/histogram_macros.h"
28 #include "base/metrics/user_metrics.h"
29 #include "base/no_destructor.h"
30 #include "base/path_service.h"
31 #include "base/pending_task.h"
32 #include "base/power_monitor/power_monitor.h"
33 #include "base/power_monitor/power_monitor_device_source.h"
34 #include "base/process/process_metrics.h"
35 #include "base/run_loop.h"
36 #include "base/scoped_observer.h"
37 #include "base/single_thread_task_runner.h"
38 #include "base/stl_util.h"
39 #include "base/strings/string_number_conversions.h"
40 #include "base/strings/string_split.h"
41 #include "base/synchronization/waitable_event.h"
42 #include "base/system/system_monitor.h"
43 #include "base/task/post_task.h"
44 #include "base/task/thread_pool/initialization_util.h"
45 #include "base/threading/thread.h"
46 #include "base/threading/thread_restrictions.h"
47 #include "base/threading/thread_task_runner_handle.h"
48 #include "base/time/time.h"
49 #include "base/timer/hi_res_timer_manager.h"
50 #include "base/trace_event/memory_dump_manager.h"
51 #include "base/trace_event/trace_event.h"
52 #include "base/util/memory_pressure/multi_source_memory_pressure_monitor.h"
53 #include "build/branding_buildflags.h"
54 #include "build/build_config.h"
55 #include "cc/base/histograms.h"
56 #include "components/discardable_memory/service/discardable_shared_memory_manager.h"
57 #include "components/services/storage/dom_storage/storage_area_impl.h"
58 #include "components/tracing/common/trace_startup_config.h"
59 #include "components/tracing/common/trace_to_console.h"
60 #include "components/tracing/common/tracing_switches.h"
61 #include "components/viz/host/compositing_mode_reporter_impl.h"
62 #include "components/viz/host/gpu_host_impl.h"
63 #include "components/viz/host/host_frame_sink_manager.h"
64 #include "content/browser/browser_thread_impl.h"
65 #include "content/browser/child_process_security_policy_impl.h"
66 #include "content/browser/compositor/viz_process_transport_factory.h"
67 #include "content/browser/download/save_file_manager.h"
68 #include "content/browser/field_trial_synchronizer.h"
69 #include "content/browser/gpu/browser_gpu_channel_host_factory.h"
70 #include "content/browser/gpu/browser_gpu_client_delegate.h"
71 #include "content/browser/gpu/compositor_util.h"
72 #include "content/browser/gpu/gpu_data_manager_impl.h"
73 #include "content/browser/gpu/gpu_process_host.h"
74 #include "content/browser/gpu/shader_cache_factory.h"
75 #include "content/browser/histogram_synchronizer.h"
76 #include "content/browser/media/capture/audio_mirroring_manager.h"
77 #include "content/browser/media/media_internals.h"
78 #include "content/browser/media/media_keys_listener_manager_impl.h"
79 #include "content/browser/net/browser_online_state_observer.h"
80 #include "content/browser/network_service_instance_impl.h"
81 #include "content/browser/renderer_host/media/media_stream_manager.h"
82 #include "content/browser/renderer_host/render_process_host_impl.h"
83 #include "content/browser/scheduler/browser_task_executor.h"
84 #include "content/browser/scheduler/responsiveness/watcher.h"
85 #include "content/browser/screenlock_monitor/screenlock_monitor.h"
86 #include "content/browser/screenlock_monitor/screenlock_monitor_device_source.h"
87 #if BUILDFLAG(ENABLE_WEB_SPEECH)
88 #include "content/browser/speech/speech_recognition_manager_impl.h"
89 #endif
90 #include "content/browser/startup_data_impl.h"
91 #include "content/browser/startup_task_runner.h"
92 #include "content/browser/tracing/background_tracing_manager_impl.h"
93 #include "content/browser/tracing/tracing_controller_impl.h"
94 #include "content/browser/utility_process_host.h"
95 #include "content/browser/webui/content_web_ui_controller_factory.h"
96 #include "content/browser/webui/url_data_manager.h"
97 #include "content/common/content_switches_internal.h"
98 #include "content/common/thread_pool_util.h"
99 #include "content/public/browser/audio_service.h"
100 #include "content/public/browser/browser_main_parts.h"
101 #include "content/public/browser/browser_task_traits.h"
102 #include "content/public/browser/browser_thread.h"
103 #include "content/public/browser/content_browser_client.h"
104 #include "content/public/browser/device_service.h"
105 #include "content/public/browser/gpu_data_manager_observer.h"
106 #include "content/public/browser/network_service_instance.h"
107 #include "content/public/browser/render_process_host.h"
108 #include "content/public/browser/service_process_host.h"
109 #include "content/public/browser/site_isolation_policy.h"
110 #include "content/public/common/content_client.h"
111 #include "content/public/common/content_features.h"
112 #include "content/public/common/content_switches.h"
113 #include "content/public/common/main_function_params.h"
114 #include "content/public/common/result_codes.h"
115 #include "content/public/common/service_names.mojom.h"
116 #include "device/fido/hid/fido_hid_discovery.h"
117 #include "device/gamepad/gamepad_service.h"
118 #include "media/audio/audio_manager.h"
119 #include "media/audio/audio_system.h"
120 #include "media/audio/audio_thread_impl.h"
121 #include "media/base/media.h"
122 #include "media/base/user_input_monitor.h"
123 #include "media/media_buildflags.h"
124 #include "media/midi/midi_service.h"
125 #include "media/mojo/buildflags.h"
126 #include "mojo/core/embedder/embedder.h"
127 #include "mojo/core/embedder/scoped_ipc_support.h"
128 #include "mojo/public/cpp/bindings/mojo_buildflags.h"
129 #include "mojo/public/cpp/bindings/sync_call_restrictions.h"
130 #include "net/base/network_change_notifier.h"
131 #include "net/socket/client_socket_factory.h"
132 #include "net/ssl/ssl_config_service.h"
133 #include "ppapi/buildflags/buildflags.h"
134 #include "services/audio/service.h"
135 #include "services/content/public/cpp/navigable_contents_view.h"
136 #include "services/data_decoder/public/cpp/service_provider.h"
137 #include "services/network/transitional_url_loader_factory_owner.h"
138 #include "services/service_manager/zygote/common/zygote_buildflags.h"
139 #include "skia/ext/event_tracer_impl.h"
140 #include "skia/ext/skia_memory_dump_provider.h"
141 #include "sql/sql_memory_dump_provider.h"
142 #include "ui/base/clipboard/clipboard.h"
143 #include "ui/display/display_features.h"
144 #include "ui/gfx/font_render_params.h"
145 #include "ui/gfx/switches.h"
146
147 #if defined(USE_AURA) || defined(OS_MACOSX)
148 #include "content/browser/compositor/image_transport_factory.h"
149 #endif
150
151 #if defined(USE_AURA)
152 #include "content/public/browser/context_factory.h"
153 #include "ui/aura/env.h"
154 #endif
155
156 #if defined(OS_ANDROID)
157 #include "base/android/jni_android.h"
158 #include "base/trace_event/cpufreq_monitor_android.h"
159 #include "components/tracing/common/graphics_memory_dump_provider_android.h"
160 #include "content/browser/android/browser_startup_controller.h"
161 #include "content/browser/android/launcher_thread.h"
162 #include "content/browser/android/scoped_surface_request_manager.h"
163 #include "content/browser/android/tracing_controller_android.h"
164 #include "content/browser/font_unique_name_lookup/font_unique_name_lookup.h"
165 #include "content/browser/screen_orientation/screen_orientation_delegate_android.h"
166 #include "media/base/android/media_drm_bridge_client.h"
167 #include "ui/android/screen_android.h"
168 #include "ui/display/screen.h"
169 #include "ui/gl/gl_surface.h"
170 #endif
171
172 #if defined(OS_MACOSX)
173 #include "content/browser/renderer_host/browser_compositor_view_mac.h"
174 #include "content/browser/theme_helper_mac.h"
175 #include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
176 #endif
177
178 #if defined(OS_WIN)
179 #include <commctrl.h>
180 #include <shellapi.h>
181 #include <windows.h>
182
183 #include "content/browser/renderer_host/dwrite_font_lookup_table_builder_win.h"
184 #include "net/base/winsock_init.h"
185 #include "services/service_manager/sandbox/win/sandbox_win.h"
186 #include "ui/display/win/screen_win.h"
187 #endif
188
189 #if defined(OS_CHROMEOS)
190 #include "chromeos/constants/chromeos_switches.h"
191 #include "device/bluetooth/bluetooth_adapter_factory.h"
192 #include "services/data_decoder/public/cpp/data_decoder.h"
193 #endif
194
195 #if defined(USE_GLIB)
196 #include <glib-object.h>
197 #endif
198
199 #if defined(OS_WIN)
200 #include "media/device_monitors/system_message_window_win.h"
201 #include "sandbox/win/src/process_mitigations.h"
202 #elif defined(OS_LINUX) && defined(USE_UDEV)
203 #include "media/device_monitors/device_monitor_udev.h"
204 #elif defined(OS_MACOSX)
205 #include "media/device_monitors/device_monitor_mac.h"
206 #endif
207
208 #if defined(OS_FUCHSIA)
209 #include <lib/zx/job.h>
210
211 #include "base/fuchsia/default_job.h"
212 #include "base/fuchsia/fuchsia_logging.h"
213 #endif // defined(OS_FUCHSIA)
214
215 #if defined(OS_POSIX) && !defined(OS_MACOSX)
216 #include "content/browser/sandbox_host_linux.h"
217 #endif
218
219 #if BUILDFLAG(ENABLE_PLUGINS)
220 #include "content/browser/plugin_service_impl.h"
221 #endif
222
223 #if BUILDFLAG(ENABLE_LIBRARY_CDMS)
224 #include "content/browser/media/cdm_registry_impl.h"
225 #endif
226
227 #if BUILDFLAG(ENABLE_WEBRTC)
228 #include "content/browser/webrtc/webrtc_internals.h"
229 #endif
230
231 #if defined(USE_X11)
232 #include "gpu/config/gpu_driver_bug_workaround_type.h"
233 #include "ui/base/x/x11_util_internal.h" // nogncheck
234 #include "ui/gfx/x/x11_connection.h" // nogncheck
235 #include "ui/gfx/x/x11_types.h" // nogncheck
236 #endif
237
238 #if defined(USE_NSS_CERTS)
239 #include "crypto/nss_util.h"
240 #endif
241
242 #if defined(ENABLE_IPC_FUZZER) && defined(OS_MACOSX)
243 #include "base/mac/foundation_util.h"
244 #endif
245
246 #if BUILDFLAG(MOJO_RANDOM_DELAYS_ENABLED)
247 #include "mojo/public/cpp/bindings/lib/test_random_mojo_delays.h"
248 #endif
249
250 #if defined(OS_BSD)
251 #include "content/browser/sandbox_host_linux.h"
252 #include "services/service_manager/zygote/common/common_sandbox_support_linux.h"
253 #include "content/public/common/common_sandbox_support_linux.h"
254 #include "services/service_manager/sandbox/sandbox.h"
255 #endif
256
257 // One of the linux specific headers defines this as a macro.
258 #ifdef DestroyAll
259 #undef DestroyAll
260 #endif
261
262 namespace content {
263 namespace {
264
265 #if defined(USE_GLIB)
GLibLogHandler(const gchar * log_domain,GLogLevelFlags log_level,const gchar * message,gpointer userdata)266 static void GLibLogHandler(const gchar* log_domain,
267 GLogLevelFlags log_level,
268 const gchar* message,
269 gpointer userdata) {
270 if (!log_domain)
271 log_domain = "<unknown>";
272 if (!message)
273 message = "<no message>";
274
275 GLogLevelFlags always_fatal_flags = g_log_set_always_fatal(G_LOG_LEVEL_MASK);
276 g_log_set_always_fatal(always_fatal_flags);
277 GLogLevelFlags fatal_flags =
278 g_log_set_fatal_mask(log_domain, G_LOG_LEVEL_MASK);
279 g_log_set_fatal_mask(log_domain, fatal_flags);
280 if ((always_fatal_flags | fatal_flags) & log_level) {
281 LOG(DFATAL) << log_domain << ": " << message;
282 } else if (log_level & (G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL)) {
283 LOG(ERROR) << log_domain << ": " << message;
284 } else if (log_level & (G_LOG_LEVEL_WARNING)) {
285 LOG(WARNING) << log_domain << ": " << message;
286 } else if (log_level &
287 (G_LOG_LEVEL_MESSAGE | G_LOG_LEVEL_INFO | G_LOG_LEVEL_DEBUG)) {
288 LOG(INFO) << log_domain << ": " << message;
289 } else {
290 NOTREACHED();
291 LOG(DFATAL) << log_domain << ": " << message;
292 }
293 }
294
SetUpGLibLogHandler()295 static void SetUpGLibLogHandler() {
296 // Register GLib-handled assertions to go through our logging system.
297 const char* const kLogDomains[] = {nullptr, "Gtk", "Gdk", "GLib",
298 "GLib-GObject"};
299 for (size_t i = 0; i < base::size(kLogDomains); i++) {
300 g_log_set_handler(
301 kLogDomains[i],
302 static_cast<GLogLevelFlags>(G_LOG_FLAG_RECURSION | G_LOG_FLAG_FATAL |
303 G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL |
304 G_LOG_LEVEL_WARNING),
305 GLibLogHandler, nullptr);
306 }
307 }
308 #endif // defined(USE_GLIB)
309
310 // Tell compiler not to inline this function so it's possible to tell what
311 // thread was unresponsive by inspecting the callstack.
ResetThread_IO(std::unique_ptr<BrowserProcessSubThread> io_thread)312 NOINLINE void ResetThread_IO(
313 std::unique_ptr<BrowserProcessSubThread> io_thread) {
314 const int line_number = __LINE__;
315 io_thread.reset();
316 base::debug::Alias(&line_number);
317 }
318
319 enum WorkerPoolType : size_t {
320 BACKGROUND = 0,
321 BACKGROUND_BLOCKING,
322 FOREGROUND,
323 FOREGROUND_BLOCKING,
324 WORKER_POOL_COUNT // Always last.
325 };
326
327 #if defined(OS_FUCHSIA)
328 // Create and register the job which will contain all child processes
329 // of the browser process as well as their descendents.
InitDefaultJob()330 void InitDefaultJob() {
331 zx::job job;
332 zx_status_t result = zx::job::create(*zx::job::default_job(), 0, &job);
333 ZX_CHECK(ZX_OK == result, result) << "zx_job_create";
334 base::SetDefaultJob(std::move(job));
335 }
336 #endif // defined(OS_FUCHSIA)
337
338 #if defined(ENABLE_IPC_FUZZER)
GetBuildDirectory(base::FilePath * result)339 bool GetBuildDirectory(base::FilePath* result) {
340 if (!base::PathService::Get(base::DIR_EXE, result))
341 return false;
342
343 #if defined(OS_MACOSX)
344 if (base::mac::AmIBundled()) {
345 // The bundled app executables (Chromium, TestShell, etc) live three
346 // levels down from the build directory, eg:
347 // Chromium.app/Contents/MacOS/Chromium
348 *result = result->DirName().DirName().DirName();
349 }
350 #endif
351 return true;
352 }
353
SetFileUrlPathAliasForIpcFuzzer()354 void SetFileUrlPathAliasForIpcFuzzer() {
355 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
356 switches::kFileUrlPathAlias))
357 return;
358
359 base::FilePath build_directory;
360 if (!GetBuildDirectory(&build_directory)) {
361 LOG(ERROR) << "Failed to get build directory for /gen path alias.";
362 return;
363 }
364
365 const base::CommandLine::StringType alias_switch =
366 FILE_PATH_LITERAL("/gen=") + build_directory.AppendASCII("gen").value();
367 base::CommandLine::ForCurrentProcess()->AppendSwitchNative(
368 switches::kFileUrlPathAlias, alias_switch);
369 }
370 #endif
371
CreateMemoryPressureMonitor(const base::CommandLine & command_line)372 std::unique_ptr<base::MemoryPressureMonitor> CreateMemoryPressureMonitor(
373 const base::CommandLine& command_line) {
374 // Behavior of browser tests should not depend on things outside of their
375 // control (like the amount of memory on the system running the tests).
376 if (command_line.HasSwitch(switches::kBrowserTest))
377 return nullptr;
378
379 std::unique_ptr<util::MultiSourceMemoryPressureMonitor> monitor;
380
381 #if defined(OS_CHROMEOS)
382 if (chromeos::switches::MemoryPressureHandlingEnabled())
383 monitor = std::make_unique<util::MultiSourceMemoryPressureMonitor>();
384 #elif defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_FUCHSIA)
385 monitor = std::make_unique<util::MultiSourceMemoryPressureMonitor>();
386 #endif
387 // No memory monitor on other platforms...
388
389 if (monitor)
390 monitor->Start();
391
392 return monitor;
393 }
394
395 #if defined(OS_CHROMEOS)
GetBleScanParser()396 mojo::PendingRemote<data_decoder::mojom::BleScanParser> GetBleScanParser() {
397 static base::NoDestructor<data_decoder::DataDecoder> decoder;
398 mojo::PendingRemote<data_decoder::mojom::BleScanParser> ble_scan_parser;
399 decoder->GetService()->BindBleScanParser(
400 ble_scan_parser.InitWithNewPipeAndPassReceiver());
401 return ble_scan_parser;
402 }
403 #endif // defined(OS_CHROMEOS)
404
405 #if defined(OS_WIN)
406 // Disable dynamic code using ACG. Prevents the browser process from generating
407 // dynamic code or modifying executable code. See comments in
408 // sandbox/win/src/security_level.h. Only available on Windows 10 RS1 (1607,
409 // Build 14393) onwards.
410 const base::Feature kBrowserDynamicCodeDisabled{
411 "BrowserDynamicCodeDisabled", base::FEATURE_DISABLED_BY_DEFAULT};
412 #endif // defined(OS_WIN)
413
414 class OopDataDecoder : public data_decoder::ServiceProvider {
415 public:
OopDataDecoder()416 OopDataDecoder() { data_decoder::ServiceProvider::Set(this); }
~OopDataDecoder()417 ~OopDataDecoder() override { data_decoder::ServiceProvider::Set(nullptr); }
418
419 // data_decoder::ServiceProvider implementation:
BindDataDecoderService(mojo::PendingReceiver<data_decoder::mojom::DataDecoderService> receiver)420 void BindDataDecoderService(
421 mojo::PendingReceiver<data_decoder::mojom::DataDecoderService> receiver)
422 override {
423 ServiceProcessHost::Launch(
424 std::move(receiver),
425 ServiceProcessHost::Options()
426 .WithSandboxType(service_manager::SandboxType::kUtility)
427 .WithDisplayName("Data Decoder Service")
428 .Pass());
429 }
430
431 private:
432 DISALLOW_COPY_AND_ASSIGN(OopDataDecoder);
433 };
434
BindHidManager(mojo::PendingReceiver<device::mojom::HidManager> receiver)435 void BindHidManager(mojo::PendingReceiver<device::mojom::HidManager> receiver) {
436 #if !defined(OS_ANDROID)
437 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
438 base::PostTask(FROM_HERE, {BrowserThread::UI},
439 base::BindOnce(&BindHidManager, std::move(receiver)));
440 return;
441 }
442
443 GetDeviceService().BindHidManager(std::move(receiver));
444 #endif
445 }
446
447 } // namespace
448
449 #if defined(USE_X11)
450 namespace internal {
451
452 // Forwards GPUInfo updates to ui::XVisualManager
453 class GpuDataManagerVisualProxy : public GpuDataManagerObserver {
454 public:
GpuDataManagerVisualProxy(GpuDataManagerImpl * gpu_data_manager)455 explicit GpuDataManagerVisualProxy(GpuDataManagerImpl* gpu_data_manager)
456 : gpu_data_manager_(gpu_data_manager) {
457 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kHeadless))
458 scoped_observer_.Add(gpu_data_manager_);
459 }
460
461 ~GpuDataManagerVisualProxy() override = default;
462
OnGpuInfoUpdate()463 void OnGpuInfoUpdate() override { OnUpdate(); }
OnGpuExtraInfoUpdate()464 void OnGpuExtraInfoUpdate() override { OnUpdate(); }
465
466 private:
OnUpdate()467 void OnUpdate() {
468 if (!gfx::GetXDisplay())
469 return;
470 gpu::GPUInfo gpu_info = gpu_data_manager_->GetGPUInfo();
471 gpu::GpuExtraInfo gpu_extra_info = gpu_data_manager_->GetGpuExtraInfo();
472 if (!ui::XVisualManager::GetInstance()->OnGPUInfoChanged(
473 gpu_info.software_rendering ||
474 !gpu_data_manager_->GpuAccessAllowed(nullptr),
475 gpu_extra_info.system_visual, gpu_extra_info.rgba_visual)) {
476 // The GPU process sent back bad visuals, which should never happen.
477 auto* gpu_process_host =
478 GpuProcessHost::Get(GPU_PROCESS_KIND_SANDBOXED, false);
479 if (gpu_process_host)
480 gpu_process_host->ForceShutdown();
481 }
482 }
483
484 GpuDataManagerImpl* gpu_data_manager_;
485
486 ScopedObserver<GpuDataManagerImpl, GpuDataManagerObserver> scoped_observer_{
487 this};
488
489 DISALLOW_COPY_AND_ASSIGN(GpuDataManagerVisualProxy);
490 };
491
492 } // namespace internal
493 #endif
494
495 #if defined(OS_WIN)
496 namespace {
497
498 // Provides a bridge whereby display::win::ScreenWin can ask the GPU process
499 // about the HDR status of the system.
500 class HDRProxy {
501 public:
Initialize()502 static void Initialize() {
503 display::win::ScreenWin::SetRequestHDRStatusCallback(
504 base::BindRepeating(&HDRProxy::RequestHDRStatus));
505 }
506
RequestHDRStatus()507 static void RequestHDRStatus() {
508 // The request must be sent to the GPU process from the IO thread.
509 base::PostTask(FROM_HERE, {BrowserThread::IO},
510 base::BindOnce(&HDRProxy::RequestOnIOThread));
511 }
512
513 private:
RequestOnIOThread()514 static void RequestOnIOThread() {
515 auto* gpu_process_host =
516 GpuProcessHost::Get(GPU_PROCESS_KIND_SANDBOXED, false);
517 if (gpu_process_host) {
518 auto* gpu_service = gpu_process_host->gpu_host()->gpu_service();
519 gpu_service->RequestHDRStatus(
520 base::BindOnce(&HDRProxy::GotResultOnIOThread));
521 } else {
522 bool hdr_enabled = false;
523 GotResultOnIOThread(hdr_enabled);
524 }
525 }
GotResultOnIOThread(bool hdr_enabled)526 static void GotResultOnIOThread(bool hdr_enabled) {
527 base::PostTask(FROM_HERE, {BrowserThread::UI},
528 base::BindOnce(&HDRProxy::GotResult, hdr_enabled));
529 }
GotResult(bool hdr_enabled)530 static void GotResult(bool hdr_enabled) {
531 display::win::ScreenWin::SetHDREnabled(hdr_enabled);
532 }
533 };
534
535 } // namespace
536 #endif
537
538 // The currently-running BrowserMainLoop. There can be one or zero.
539 BrowserMainLoop* g_current_browser_main_loop = nullptr;
540
541 #if defined(OS_ANDROID)
542
543 namespace {
544 // Whether or not BrowserMainLoop::CreateStartupTasks() posts any tasks.
545 bool g_post_startup_tasks = true;
546 } // namespace
547
548 // static
EnableStartupTasks(bool enabled)549 void BrowserMainLoop::EnableStartupTasks(bool enabled) {
550 g_post_startup_tasks = enabled;
551 }
552
553 #endif
554
555 // BrowserMainLoop construction / destruction =============================
556
GetInstance()557 BrowserMainLoop* BrowserMainLoop::GetInstance() {
558 DCHECK_CURRENTLY_ON(BrowserThread::UI);
559 return g_current_browser_main_loop;
560 }
561
562 // static
GetAudioManager()563 media::AudioManager* BrowserMainLoop::GetAudioManager() {
564 return g_current_browser_main_loop->audio_manager();
565 }
566
BrowserMainLoop(const MainFunctionParams & parameters,std::unique_ptr<base::ThreadPoolInstance::ScopedExecutionFence> scoped_execution_fence)567 BrowserMainLoop::BrowserMainLoop(
568 const MainFunctionParams& parameters,
569 std::unique_ptr<base::ThreadPoolInstance::ScopedExecutionFence>
570 scoped_execution_fence)
571 : parameters_(parameters),
572 parsed_command_line_(parameters.command_line),
573 result_code_(service_manager::RESULT_CODE_NORMAL_EXIT),
574 created_threads_(false),
575 scoped_execution_fence_(std::move(scoped_execution_fence))
576 #if !defined(OS_ANDROID)
577 ,
578 // TODO(fdoray): Create the fence on Android too. Not enabled yet because
579 // tests timeout. https://crbug.com/887407
580 scoped_best_effort_execution_fence_(base::in_place_t())
581 #endif
582 {
583 DCHECK(!g_current_browser_main_loop);
584 DCHECK(scoped_execution_fence_)
585 << "ThreadPool must be halted before kicking off content.";
586 g_current_browser_main_loop = this;
587
588 if (GetContentClient()->browser()->ShouldCreateThreadPool()) {
589 DCHECK(base::ThreadPoolInstance::Get());
590 }
591 }
592
~BrowserMainLoop()593 BrowserMainLoop::~BrowserMainLoop() {
594 DCHECK_EQ(this, g_current_browser_main_loop);
595 ui::Clipboard::DestroyClipboardForCurrentThread();
596 g_current_browser_main_loop = nullptr;
597 }
598
Init()599 void BrowserMainLoop::Init() {
600 TRACE_EVENT0("startup", "BrowserMainLoop::Init");
601
602 // |startup_data| is optional. If set, the thread owned by the data
603 // will be registered as BrowserThread::IO in CreateThreads() instead of
604 // creating a brand new thread.
605 if (parameters_.startup_data) {
606 StartupDataImpl* startup_data =
607 static_cast<StartupDataImpl*>(parameters_.startup_data);
608 // This is always invoked before |io_thread_| is initialized (i.e. never
609 // resets it).
610 io_thread_ = std::move(startup_data->ipc_thread);
611 mojo_ipc_support_ = std::move(startup_data->mojo_ipc_support);
612 service_manager_shutdown_closure_ =
613 std::move(startup_data->service_manager_shutdown_closure);
614 }
615
616 parts_ = GetContentClient()->browser()->CreateBrowserMainParts(parameters_);
617 }
618
619 // BrowserMainLoop stages ==================================================
620
EarlyInitialization()621 int BrowserMainLoop::EarlyInitialization() {
622 TRACE_EVENT0("startup", "BrowserMainLoop::EarlyInitialization");
623
624 #if BUILDFLAG(USE_ZYGOTE_HANDLE)
625 // The initialization of the sandbox host ends up with forking the Zygote
626 // process and requires no thread been forked. The initialization has happened
627 // by now since a thread to start the ServiceManager has been created
628 // before the browser main loop starts.
629 DCHECK(SandboxHostLinux::GetInstance()->IsInitialized());
630 #endif
631
632 #if defined(USE_X11) && !defined(TOOLKIT_QT)
633 if (UsingInProcessGpu()) {
634 if (!gfx::InitializeThreadedX11()) {
635 LOG(ERROR) << "Failed to put Xlib into threaded mode.";
636 }
637 }
638 #endif
639
640 // GLib's spawning of new processes is buggy, so it's important that at this
641 // point GLib does not need to start DBUS. Chrome should always start with
642 // DBUS_SESSION_BUS_ADDRESS properly set. See crbug.com/309093.
643 #if defined(USE_GLIB)
644 // g_type_init will be deprecated in 2.36. 2.35 is the development
645 // version for 2.36, hence do not call g_type_init starting 2.35.
646 // http://developer.gnome.org/gobject/unstable/gobject-Type-Information.html#g-type-init
647 #if !GLIB_CHECK_VERSION(2, 35, 0)
648 // GLib type system initialization. It's unclear if it's still required for
649 // any remaining code. Most likely this is superfluous as gtk_init() ought
650 // to do this. It's definitely harmless, so it's retained here.
651 g_type_init();
652 #endif // !GLIB_CHECK_VERSION(2, 35, 0)
653
654 SetUpGLibLogHandler();
655 #endif // defined(USE_GLIB)
656
657 if (parts_) {
658 const int pre_early_init_error_code = parts_->PreEarlyInitialization();
659 if (pre_early_init_error_code != service_manager::RESULT_CODE_NORMAL_EXIT)
660 return pre_early_init_error_code;
661 }
662
663 // Up the priority of the UI thread unless it was already high (since Mac
664 // and recent versions of Android (O+) do this automatically).
665 #if !defined(OS_MACOSX)
666 if (base::FeatureList::IsEnabled(
667 features::kBrowserUseDisplayThreadPriority) &&
668 base::PlatformThread::GetCurrentThreadPriority() <
669 base::ThreadPriority::DISPLAY) {
670 base::PlatformThread::SetCurrentThreadPriority(
671 base::ThreadPriority::DISPLAY);
672 }
673 #endif // !defined(OS_MACOSX)
674
675 #if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_BSD) || \
676 defined(OS_ANDROID)
677 // We use quite a few file descriptors for our IPC as well as disk the disk
678 // cache,and the default limit on the Mac is low (256), so bump it up.
679
680 // Same for Linux. The default various per distro, but it is 1024 on Fedora.
681 // Low soft limits combined with liberal use of file descriptors means power
682 // users can easily hit this limit with many open tabs. Bump up the limit to
683 // an arbitrarily high number. See https://crbug.com/539567
684 base::IncreaseFdLimitTo(8192);
685 #endif // defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_BSD) ||
686 // defined(OS_ANDROID)
687
688 #if defined(OS_WIN)
689 net::EnsureWinsockInit();
690 #endif
691
692 #if defined(USE_NSS_CERTS)
693 // We want to be sure to init NSPR on the main thread.
694 crypto::EnsureNSPRInit();
695 #endif
696
697 #if defined(OS_FUCHSIA)
698 InitDefaultJob();
699 #endif
700
701 #if defined(OS_WIN)
702 if (!parsed_command_line_.HasSwitch(switches::kSingleProcess)) {
703 if (base::FeatureList::IsEnabled(kBrowserDynamicCodeDisabled)) {
704 sandbox::ApplyProcessMitigationsToCurrentProcess(
705 sandbox::MITIGATION_DYNAMIC_CODE_DISABLE_WITH_OPT_OUT);
706 }
707 }
708 #endif
709
710 if (parsed_command_line_.HasSwitch(switches::kRendererProcessLimit)) {
711 std::string limit_string = parsed_command_line_.GetSwitchValueASCII(
712 switches::kRendererProcessLimit);
713 size_t process_limit;
714 if (base::StringToSizeT(limit_string, &process_limit)) {
715 RenderProcessHost::SetMaxRendererProcessCount(process_limit);
716 }
717 }
718
719 if (parts_)
720 parts_->PostEarlyInitialization();
721
722 return service_manager::RESULT_CODE_NORMAL_EXIT;
723 }
724
PreMainMessageLoopStart()725 void BrowserMainLoop::PreMainMessageLoopStart() {
726 TRACE_EVENT0("startup",
727 "BrowserMainLoop::MainMessageLoopStart:PreMainMessageLoopStart");
728 if (parts_) {
729 parts_->PreMainMessageLoopStart();
730 }
731 }
732
MainMessageLoopStart()733 void BrowserMainLoop::MainMessageLoopStart() {
734 // DO NOT add more code here. Use PreMainMessageLoopStart() above or
735 // PostMainMessageLoopStart() below.
736
737 TRACE_EVENT0("startup", "BrowserMainLoop::MainMessageLoopStart");
738 DCHECK(base::MessageLoopCurrentForUI::IsSet());
739 InitializeMainThread();
740 }
741
PostMainMessageLoopStart()742 void BrowserMainLoop::PostMainMessageLoopStart() {
743 {
744 TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:SystemMonitor");
745 system_monitor_.reset(new base::SystemMonitor);
746 }
747 {
748 TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:PowerMonitor");
749 if (!base::PowerMonitor::IsInitialized()) {
750 base::PowerMonitor::Initialize(
751 std::make_unique<base::PowerMonitorDeviceSource>());
752 }
753 }
754 {
755 TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:HighResTimerManager");
756 hi_res_timer_manager_.reset(new base::HighResolutionTimerManager);
757 }
758 {
759 TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:NetworkChangeNotifier");
760 // On Android if reduced mode started network service this would already be
761 // created.
762 network_change_notifier_ = net::NetworkChangeNotifier::CreateIfNeeded();
763 }
764 {
765 TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:ScreenlockMonitor");
766 std::unique_ptr<ScreenlockMonitorSource> screenlock_monitor_source =
767 std::make_unique<ScreenlockMonitorDeviceSource>();
768 screenlock_monitor_ = std::make_unique<ScreenlockMonitor>(
769 std::move(screenlock_monitor_source));
770 }
771 {
772 TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:MediaFeatures");
773 media::InitializeMediaLibrary();
774 }
775 {
776 TRACE_EVENT0("startup",
777 "BrowserMainLoop::Subsystem:ContentWebUIController");
778 WebUIControllerFactory::RegisterFactory(
779 ContentWebUIControllerFactory::GetInstance());
780 }
781
782 {
783 TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:OnlineStateObserver");
784 online_state_observer_.reset(new BrowserOnlineStateObserver);
785 }
786
787 {
788 base::SetRecordActionTaskRunner(
789 base::CreateSingleThreadTaskRunner({BrowserThread::UI}));
790 }
791
792 // TODO(boliu): kSingleProcess check is a temporary workaround for
793 // in-process Android WebView. crbug.com/503724 tracks proper fix.
794 if (!parsed_command_line_.HasSwitch(switches::kSingleProcess)) {
795 base::DiscardableMemoryAllocator::SetInstance(
796 discardable_memory::DiscardableSharedMemoryManager::Get());
797 }
798
799 if (parts_)
800 parts_->PostMainMessageLoopStart();
801
802 #if defined(OS_ANDROID)
803 {
804 TRACE_EVENT0("startup",
805 "BrowserMainLoop::Subsystem:ScopedSurfaceRequestManager");
806 if (UsingInProcessGpu()) {
807 gpu::ScopedSurfaceRequestConduit::SetInstance(
808 ScopedSurfaceRequestManager::GetInstance());
809 }
810 }
811
812 if (!parsed_command_line_.HasSwitch(
813 switches::kDisableScreenOrientationLock)) {
814 TRACE_EVENT0("startup",
815 "BrowserMainLoop::Subsystem:ScreenOrientationProvider");
816 screen_orientation_delegate_.reset(new ScreenOrientationDelegateAndroid());
817 }
818
819 base::trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(
820 base::trace_event::CPUFreqMonitor::GetInstance());
821 #endif
822
823 // Enable memory-infra dump providers.
824 InitSkiaEventTracer();
825 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
826 skia::SkiaMemoryDumpProvider::GetInstance(), "Skia", nullptr);
827 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
828 sql::SqlMemoryDumpProvider::GetInstance(), "Sql", nullptr);
829 #if defined(OS_CHROMEOS)
830 device::BluetoothAdapterFactory::SetBleScanParserCallback(
831 base::BindRepeating(&GetBleScanParser));
832 #else
833 // Chrome Remote Desktop needs TransitionalURLLoaderFactoryOwner on ChromeOS.
834 network::TransitionalURLLoaderFactoryOwner::DisallowUsageInProcess();
835 #endif
836 }
837
PreCreateThreads()838 int BrowserMainLoop::PreCreateThreads() {
839 // Make sure no accidental call to initialize GpuDataManager earlier.
840 DCHECK(!GpuDataManagerImpl::Initialized());
841 if (parts_) {
842 TRACE_EVENT0("startup", "BrowserMainLoop::CreateThreads:PreCreateThreads");
843
844 result_code_ = parts_->PreCreateThreads();
845 }
846
847 InitializeMemoryManagementComponent();
848
849 #if BUILDFLAG(ENABLE_PLUGINS)
850 // Prior to any processing happening on the IO thread, we create the
851 // plugin service as it is predominantly used from the IO thread,
852 // but must be created on the main thread. The service ctor is
853 // inexpensive and does not invoke the io_thread() accessor.
854 {
855 TRACE_EVENT0("startup", "BrowserMainLoop::CreateThreads:PluginService");
856 PluginService::GetInstance()->Init();
857 }
858 #endif
859
860 #if BUILDFLAG(ENABLE_LIBRARY_CDMS)
861 // Prior to any processing happening on the IO thread, we create the
862 // CDM service as it is predominantly used from the IO thread. This must
863 // be called on the main thread since it involves file path checks.
864 CdmRegistry::GetInstance()->Init();
865 #endif
866
867 #if defined(OS_MACOSX)
868 // The WindowResizeHelper allows the UI thread to wait on specific renderer
869 // and GPU messages from the IO thread. Initializing it before the IO thread
870 // starts ensures the affected IO thread messages always have somewhere to go.
871 ui::WindowResizeHelperMac::Get()->Init(base::ThreadTaskRunnerHandle::Get());
872 #endif
873
874 // GpuDataManager should be initialized in parts_->PreCreateThreads through
875 // ChromeBrowserMainExtraPartsGpu. However, if |parts_| is not set,
876 // initialize it here.
877 // Need to initialize in-process GpuDataManager before creating threads.
878 // It's unsafe to append the gpu command line switches to the global
879 // CommandLine::ForCurrentProcess object after threads are created.
880 GpuDataManagerImpl::GetInstance();
881 DCHECK(GpuDataManagerImpl::Initialized());
882
883 #if defined(USE_X11)
884 gpu_data_manager_visual_proxy_.reset(new internal::GpuDataManagerVisualProxy(
885 GpuDataManagerImpl::GetInstance()));
886 #endif
887
888 #if !BUILDFLAG(GOOGLE_CHROME_BRANDING) || defined(OS_ANDROID)
889 // Single-process is an unsupported and not fully tested mode, so
890 // don't enable it for official Chrome builds (except on Android).
891 if (parsed_command_line_.HasSwitch(switches::kSingleProcess))
892 RenderProcessHost::SetRunRendererInProcess(true);
893 #endif
894
895 // Initialize origins that require process isolation. Must be done
896 // after base::FeatureList is initialized, but before any navigations can
897 // happen.
898 SiteIsolationPolicy::ApplyGlobalIsolatedOrigins();
899
900 return result_code_;
901 }
902
PreShutdown()903 void BrowserMainLoop::PreShutdown() {
904 ui::Clipboard::OnPreShutdownForCurrentThread();
905 }
906
CreateStartupTasks()907 void BrowserMainLoop::CreateStartupTasks() {
908 TRACE_EVENT0("startup", "BrowserMainLoop::CreateStartupTasks");
909
910 DCHECK(!startup_task_runner_);
911 #if defined(OS_ANDROID)
912 // Some java scheduler tests need to test migration to C++, but the browser
913 // environment isn't set up fully and if these tasks run they may crash.
914 if (!g_post_startup_tasks)
915 return;
916
917 startup_task_runner_ = std::make_unique<StartupTaskRunner>(
918 base::BindOnce(&BrowserStartupComplete),
919 base::CreateSingleThreadTaskRunner(
920 {BrowserThread::UI, BrowserTaskType::kBootstrap}));
921 #else
922 startup_task_runner_ = std::make_unique<StartupTaskRunner>(
923 base::OnceCallback<void(int)>(), base::ThreadTaskRunnerHandle::Get());
924 #endif
925 StartupTask pre_create_threads = base::BindOnce(
926 &BrowserMainLoop::PreCreateThreads, base::Unretained(this));
927 startup_task_runner_->AddTask(std::move(pre_create_threads));
928
929 StartupTask create_threads =
930 base::BindOnce(&BrowserMainLoop::CreateThreads, base::Unretained(this));
931 startup_task_runner_->AddTask(std::move(create_threads));
932
933 StartupTask post_create_threads = base::BindOnce(
934 &BrowserMainLoop::PostCreateThreads, base::Unretained(this));
935 startup_task_runner_->AddTask(std::move(post_create_threads));
936
937 StartupTask browser_thread_started = base::BindOnce(
938 &BrowserMainLoop::BrowserThreadsStarted, base::Unretained(this));
939 startup_task_runner_->AddTask(std::move(browser_thread_started));
940
941 StartupTask pre_main_message_loop_run = base::BindOnce(
942 &BrowserMainLoop::PreMainMessageLoopRun, base::Unretained(this));
943 startup_task_runner_->AddTask(std::move(pre_main_message_loop_run));
944
945 #if defined(OS_ANDROID)
946 startup_task_runner_->StartRunningTasksAsync();
947 #else
948 startup_task_runner_->RunAllTasksNow();
949 #endif
950 }
951
952 scoped_refptr<base::SingleThreadTaskRunner>
GetResizeTaskRunner()953 BrowserMainLoop::GetResizeTaskRunner() {
954 #if defined(OS_MACOSX)
955 scoped_refptr<base::SingleThreadTaskRunner> task_runner =
956 ui::WindowResizeHelperMac::Get()->task_runner();
957 // In tests, WindowResizeHelperMac task runner might not be initialized.
958 return task_runner ? task_runner : base::ThreadTaskRunnerHandle::Get();
959 #else
960 return base::ThreadTaskRunnerHandle::Get();
961 #endif
962 }
963
964 gpu::GpuChannelEstablishFactory*
gpu_channel_establish_factory() const965 BrowserMainLoop::gpu_channel_establish_factory() const {
966 return BrowserGpuChannelHostFactory::instance();
967 }
968
969 #if defined(OS_ANDROID)
SynchronouslyFlushStartupTasks()970 void BrowserMainLoop::SynchronouslyFlushStartupTasks() {
971 startup_task_runner_->RunAllTasksNow();
972 }
973 #endif // OS_ANDROID
974
CreateThreads()975 int BrowserMainLoop::CreateThreads() {
976 TRACE_EVENT0("startup,rail", "BrowserMainLoop::CreateThreads");
977
978 // Release the ThreadPool's threads.
979 scoped_execution_fence_.reset();
980
981 // The |io_thread| can have optionally been injected into Init(), but if not,
982 // create it here. Thre thread is only tagged as BrowserThread::IO here in
983 // order to prevent any code from statically posting to it before
984 // CreateThreads() (as such maintaining the invariant that PreCreateThreads()
985 // et al. "happen-before" BrowserThread::IO is "brought up").
986 if (!io_thread_) {
987 io_thread_ = BrowserTaskExecutor::CreateIOThread();
988 }
989 io_thread_->RegisterAsBrowserThread();
990 BrowserTaskExecutor::InitializeIOThread();
991
992 // TODO(https://crbug.com/863341): Replace with a better API
993 GetContentClient()->browser()->PostAfterStartupTask(
994 FROM_HERE, base::SequencedTaskRunnerHandle::Get(),
995 base::BindOnce(
996 [](BrowserMainLoop* browser_main_loop) {
997 // Enable main thread and thread pool best effort queues. Non-best
998 // effort queues will already have been enabled. This will enable
999 // all queues on all browser threads, so we need to do this after
1000 // the threads have been created, i.e. here.
1001 content::BrowserTaskExecutor::EnableAllQueues();
1002 browser_main_loop->scoped_best_effort_execution_fence_.reset();
1003 },
1004 // Main thread tasks can't run after BrowserMainLoop destruction.
1005 // Accessing an Unretained pointer to BrowserMainLoop from a main
1006 // thread task is therefore safe.
1007 base::Unretained(this)));
1008
1009 created_threads_ = true;
1010 return result_code_;
1011 }
1012
PostCreateThreads()1013 int BrowserMainLoop::PostCreateThreads() {
1014 tracing_controller_ = std::make_unique<content::TracingControllerImpl>();
1015 content::BackgroundTracingManagerImpl::GetInstance()
1016 ->AddMetadataGeneratorFunction();
1017
1018 if (parts_) {
1019 TRACE_EVENT0("startup", "BrowserMainLoop::PostCreateThreads");
1020 parts_->PostCreateThreads();
1021 }
1022
1023 return result_code_;
1024 }
1025
PreMainMessageLoopRun()1026 int BrowserMainLoop::PreMainMessageLoopRun() {
1027 #if defined(OS_ANDROID)
1028 bool use_display_wide_color_gamut =
1029 GetContentClient()->browser()->GetWideColorGamutHeuristic() ==
1030 ContentBrowserClient::WideColorGamutHeuristic::kUseDisplay;
1031 // Let screen instance be overridable by parts.
1032 ui::SetScreenAndroid(use_display_wide_color_gamut);
1033 #endif
1034
1035 if (parts_) {
1036 TRACE_EVENT0("startup",
1037 "BrowserMainLoop::CreateThreads:PreMainMessageLoopRun");
1038
1039 parts_->PreMainMessageLoopRun();
1040 }
1041
1042 #if defined(OS_WIN)
1043 // ShellBrowserMainParts initializes a ShellBrowserContext with a profile
1044 // directory only in PreMainMessageLoopRun(). DWriteFontLookupTableBuilder
1045 // needs to access this directory, hence triggering after this stage has run.
1046 if (base::FeatureList::IsEnabled(features::kFontSrcLocalMatching)) {
1047 content::DWriteFontLookupTableBuilder::GetInstance()
1048 ->SchedulePrepareFontUniqueNameTableIfNeeded();
1049 }
1050 #endif
1051
1052 // If the UI thread blocks, the whole UI is unresponsive. Do not allow
1053 // unresponsive tasks from the UI thread and instantiate a
1054 // responsiveness::Watcher to catch jank induced by any blocking tasks not
1055 // instrumented with ScopedBlockingCall's assert.
1056 base::DisallowUnresponsiveTasks();
1057 #if !defined(TOOLKIT_QT)
1058 responsiveness_watcher_ = new responsiveness::Watcher;
1059 responsiveness_watcher_->SetUp();
1060 #endif
1061 return result_code_;
1062 }
1063
RunMainMessageLoopParts()1064 void BrowserMainLoop::RunMainMessageLoopParts() {
1065 // Don't use the TRACE_EVENT0 macro because the tracing infrastructure doesn't
1066 // expect synchronous events around the main loop of a thread.
1067 TRACE_EVENT_ASYNC_BEGIN0("toplevel", "BrowserMain:MESSAGE_LOOP", this);
1068
1069 bool ran_main_loop = false;
1070 if (parts_)
1071 ran_main_loop = parts_->MainMessageLoopRun(&result_code_);
1072
1073 if (!ran_main_loop)
1074 MainMessageLoopRun();
1075
1076 TRACE_EVENT_ASYNC_END0("toplevel", "BrowserMain:MESSAGE_LOOP", this);
1077 }
1078
ShutdownThreadsAndCleanUp()1079 void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
1080 if (!created_threads_) {
1081 // Called early, nothing to do
1082 return;
1083 }
1084 TRACE_EVENT0("shutdown", "BrowserMainLoop::ShutdownThreadsAndCleanUp");
1085
1086 // Teardown may start in PostMainMessageLoopRun, and during teardown we
1087 // need to be able to perform IO.
1088 base::ThreadRestrictions::SetIOAllowed(true);
1089 base::PostTask(
1090 FROM_HERE, {BrowserThread::IO},
1091 base::BindOnce(
1092 base::IgnoreResult(&base::ThreadRestrictions::SetIOAllowed), true));
1093
1094 // Also allow waiting to join threads.
1095 // TODO(https://crbug.com/800808): Ideally this (and the above SetIOAllowed()
1096 // would be scoped allowances). That would be one of the first step to ensure
1097 // no persistent work is being done after ThreadPoolInstance::Shutdown() in
1098 // order to move towards atomic shutdown.
1099 base::ThreadRestrictions::SetWaitAllowed(true);
1100 base::PostTask(
1101 FROM_HERE, {BrowserThread::IO},
1102 base::BindOnce(
1103 base::IgnoreResult(&base::ThreadRestrictions::SetWaitAllowed), true));
1104
1105 if (RenderProcessHost::run_renderer_in_process())
1106 RenderProcessHostImpl::ShutDownInProcessRenderer();
1107
1108 if (parts_) {
1109 TRACE_EVENT0("shutdown",
1110 "BrowserMainLoop::Subsystem:PostMainMessageLoopRun");
1111 parts_->PostMainMessageLoopRun();
1112 }
1113
1114 // Request shutdown to clean up allocated resources on the IO thread.
1115 if (midi_service_) {
1116 TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:MidiService");
1117 midi_service_->Shutdown();
1118 }
1119
1120 #if BUILDFLAG(ENABLE_WEB_SPEECH)
1121 TRACE_EVENT0("shutdown",
1122 "BrowserMainLoop::Subsystem:SpeechRecognitionManager");
1123 io_thread_->task_runner()->DeleteSoon(FROM_HERE,
1124 speech_recognition_manager_.release());
1125 #endif
1126
1127 memory_pressure_monitor_.reset();
1128
1129 ShutDownNetworkService();
1130
1131 #if defined(OS_MACOSX)
1132 BrowserCompositorMac::DisableRecyclingForShutdown();
1133 #endif
1134
1135 #if defined(USE_AURA) || defined(OS_MACOSX)
1136 {
1137 TRACE_EVENT0("shutdown",
1138 "BrowserMainLoop::Subsystem:ImageTransportFactory");
1139 ImageTransportFactory::Terminate();
1140 }
1141 #endif
1142
1143 #if !defined(OS_ANDROID)
1144 host_frame_sink_manager_.reset();
1145 compositing_mode_reporter_impl_.reset();
1146 #endif
1147
1148 // The device monitors are using |system_monitor_| as dependency, so delete
1149 // them before |system_monitor_| goes away.
1150 // On Mac and windows, the monitor needs to be destroyed on the same thread
1151 // as they were created. On Linux, the monitor will be deleted when IO thread
1152 // goes away.
1153 #if defined(OS_WIN)
1154 system_message_window_.reset();
1155 #elif defined(OS_MACOSX)
1156 device_monitor_mac_.reset();
1157 #endif
1158
1159 if (BrowserGpuChannelHostFactory::instance())
1160 BrowserGpuChannelHostFactory::instance()->CloseChannel();
1161
1162 // Shutdown the Service Manager and IPC.
1163 if (service_manager_shutdown_closure_)
1164 std::move(service_manager_shutdown_closure_).Run();
1165 mojo_ipc_support_.reset();
1166
1167 if (save_file_manager_)
1168 save_file_manager_->Shutdown();
1169
1170 {
1171 TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:IOThread");
1172 ResetThread_IO(std::move(io_thread_));
1173 }
1174
1175 {
1176 TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:ThreadPool");
1177 base::ThreadPoolInstance::Get()->Shutdown();
1178 }
1179
1180 // Must happen after the IO thread is shutdown since this may be accessed from
1181 // it.
1182 {
1183 TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:GPUChannelFactory");
1184 if (BrowserGpuChannelHostFactory::instance()) {
1185 BrowserGpuChannelHostFactory::Terminate();
1186 }
1187 }
1188
1189 // Must happen after the I/O thread is shutdown since this class lives on the
1190 // I/O thread and isn't threadsafe.
1191 {
1192 TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:GamepadService");
1193 device::GamepadService::GetInstance()->Terminate();
1194 }
1195 {
1196 TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:DeleteDataSources");
1197 URLDataManager::DeleteDataSources();
1198 }
1199 {
1200 TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:AudioMan");
1201 if (audio_manager_ && !audio_manager_->Shutdown()) {
1202 // Intentionally leak AudioManager if shutdown failed.
1203 // We might run into various CHECK(s) in AudioManager destructor.
1204 ignore_result(audio_manager_.release());
1205 // |user_input_monitor_| may be in use by stray streams in case
1206 // AudioManager shutdown failed.
1207 ignore_result(user_input_monitor_.release());
1208 }
1209
1210 // Leaking AudioSystem: we cannot correctly destroy it since Audio service
1211 // connection in there is bound to IO thread.
1212 ignore_result(audio_system_.release());
1213 }
1214
1215 if (parts_) {
1216 TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:PostDestroyThreads");
1217 parts_->PostDestroyThreads();
1218 }
1219 }
1220
audio_manager() const1221 media::AudioManager* BrowserMainLoop::audio_manager() const {
1222 DCHECK(audio_manager_) << "AudioManager is not instantiated - running the "
1223 "audio service out of process?";
1224 return audio_manager_.get();
1225 }
1226
GetCompositingModeReporter(mojo::PendingReceiver<viz::mojom::CompositingModeReporter> receiver)1227 void BrowserMainLoop::GetCompositingModeReporter(
1228 mojo::PendingReceiver<viz::mojom::CompositingModeReporter> receiver) {
1229 #if defined(OS_ANDROID)
1230 // Android doesn't support non-gpu compositing modes, and doesn't make a
1231 // CompositingModeReporter.
1232 return;
1233 #else
1234 compositing_mode_reporter_impl_->BindReceiver(std::move(receiver));
1235 #endif
1236 }
1237
InitializeMainThread()1238 void BrowserMainLoop::InitializeMainThread() {
1239 TRACE_EVENT0("startup", "BrowserMainLoop::InitializeMainThread");
1240 base::PlatformThread::SetName("CrBrowserMain");
1241
1242 // Register the main thread. The main thread's task runner should already have
1243 // been initialized in MainMessageLoopStart() (or before if
1244 // MessageLoopCurrent::Get() was externally provided).
1245 DCHECK(base::ThreadTaskRunnerHandle::IsSet());
1246 main_thread_.reset(new BrowserThreadImpl(
1247 BrowserThread::UI, base::ThreadTaskRunnerHandle::Get()));
1248 }
1249
BrowserThreadsStarted()1250 int BrowserMainLoop::BrowserThreadsStarted() {
1251 TRACE_EVENT0("startup", "BrowserMainLoop::BrowserThreadsStarted");
1252
1253 // Bring up Mojo IPC and the embedded Service Manager as early as possible.
1254 // Initializaing mojo requires the IO thread to have been initialized first,
1255 // so this cannot happen any earlier than now.
1256 InitializeMojo();
1257
1258 data_decoder_service_provider_ = std::make_unique<OopDataDecoder>();
1259
1260 HistogramSynchronizer::GetInstance();
1261
1262 #ifndef TOOLKIT_QT
1263 field_trial_synchronizer_ = base::MakeRefCounted<FieldTrialSynchronizer>();
1264 #endif
1265
1266 // cc assumes a single client name for metrics in a process, which is
1267 // is inconsistent with single process mode where both the renderer and
1268 // browser compositor run in the same process. In this case, avoid
1269 // initializing with a browser metric name to ensure we record metrics for the
1270 // renderer compositor.
1271 // Note that since single process mode is only used by webview in practice,
1272 // which doesn't have a browser compositor, this is not required anyway.
1273 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
1274 switches::kSingleProcess)) {
1275 cc::SetClientNameForMetrics("Browser");
1276 }
1277
1278 // Initialize the GPU shader cache. This needs to be initialized before
1279 // BrowserGpuChannelHostFactory below, since that depends on an initialized
1280 // ShaderCacheFactory.
1281 InitShaderCacheFactorySingleton(
1282 base::CreateSingleThreadTaskRunner({BrowserThread::IO}));
1283
1284 // Initialize the FontRenderParams on IO thread. This needs to be initialized
1285 // before gpu process initialization below.
1286 base::PostTask(FROM_HERE, {BrowserThread::IO},
1287 base::BindOnce(&viz::GpuHostImpl::InitFontRenderParams,
1288 gfx::GetFontRenderParams(
1289 gfx::FontRenderParamsQuery(), nullptr)));
1290
1291 bool always_uses_gpu = true;
1292 bool established_gpu_channel = false;
1293 #if defined(OS_ANDROID)
1294 // TODO(crbug.com/439322): This should be set to |true|.
1295 established_gpu_channel = false;
1296 always_uses_gpu = ShouldStartGpuProcessOnBrowserStartup();
1297 BrowserGpuChannelHostFactory::Initialize(established_gpu_channel);
1298 #else
1299 established_gpu_channel = true;
1300 if (parsed_command_line_.HasSwitch(switches::kDisableGpu) ||
1301 parsed_command_line_.HasSwitch(switches::kDisableGpuCompositing) ||
1302 parsed_command_line_.HasSwitch(switches::kDisableGpuEarlyInit)) {
1303 established_gpu_channel = always_uses_gpu = false;
1304 }
1305
1306 host_frame_sink_manager_ = std::make_unique<viz::HostFrameSinkManager>();
1307 BrowserGpuChannelHostFactory::Initialize(established_gpu_channel);
1308 compositing_mode_reporter_impl_ =
1309 std::make_unique<viz::CompositingModeReporterImpl>();
1310
1311 auto transport_factory = std::make_unique<VizProcessTransportFactory>(
1312 BrowserGpuChannelHostFactory::instance(), GetResizeTaskRunner(),
1313 compositing_mode_reporter_impl_.get());
1314 transport_factory->ConnectHostFrameSinkManager();
1315 ImageTransportFactory::SetFactory(std::move(transport_factory));
1316
1317 #if defined(USE_AURA)
1318 env_->set_context_factory(GetContextFactory());
1319 #endif // defined(USE_AURA)
1320 #endif // !defined(OS_ANDROID)
1321
1322 #if defined(OS_ANDROID)
1323 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
1324 tracing::GraphicsMemoryDumpProvider::GetInstance(), "AndroidGraphics",
1325 nullptr);
1326 #endif
1327
1328 {
1329 TRACE_EVENT0("startup", "BrowserThreadsStarted::Subsystem:AudioMan");
1330 InitializeAudio();
1331 }
1332
1333 {
1334 TRACE_EVENT0("startup", "BrowserThreadsStarted::Subsystem:MidiService");
1335 midi_service_.reset(new midi::MidiService);
1336 }
1337
1338 {
1339 TRACE_EVENT0("startup", "BrowserThreadsStarted::Subsystem:Devices");
1340 device::GamepadService::GetInstance()->StartUp(
1341 base::BindRepeating(&BindHidManager));
1342 #if BUILDFLAG(ENABLE_WEB_AUTH)
1343 device::FidoHidDiscovery::SetHidManagerBinder(
1344 base::BindRepeating(&BindHidManager));
1345 #endif
1346 }
1347
1348 #if defined(OS_WIN)
1349 HDRProxy::Initialize();
1350 system_message_window_.reset(new media::SystemMessageWindowWin);
1351 #elif defined(OS_LINUX) && defined(USE_UDEV)
1352 device_monitor_linux_ = std::make_unique<media::DeviceMonitorLinux>();
1353 #elif defined(OS_MACOSX)
1354 // On Mac, the audio task runner must belong to the main thread.
1355 // See audio_thread_impl.cc and https://crbug.com/158170.
1356 DCHECK(!audio_manager_ ||
1357 audio_manager_->GetTaskRunner()->BelongsToCurrentThread());
1358 device_monitor_mac_.reset(
1359 new media::DeviceMonitorMac(base::ThreadTaskRunnerHandle::Get()));
1360 #endif
1361
1362 #if BUILDFLAG(ENABLE_WEBRTC)
1363 // Instantiated once using CreateSingletonInstance(), and accessed only using
1364 // GetInstance(), which is not allowed to create the object. This allows us
1365 // to ensure that it cannot be used before objects it relies on have been
1366 // created; namely, WebRtcEventLogManager.
1367 // Allowed to leak when the browser exits.
1368 WebRTCInternals::CreateSingletonInstance();
1369 #endif
1370
1371 // MediaStreamManager needs the IO thread to be created.
1372 {
1373 TRACE_EVENT0(
1374 "startup",
1375 "BrowserMainLoop::BrowserThreadsStarted:InitMediaStreamManager");
1376
1377 scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner =
1378 audio_manager_ ? audio_manager_->GetTaskRunner() : nullptr;
1379
1380 #if defined(OS_MACOSX)
1381 // On Mac, the audio task runner must belong to the main thread.
1382 // See audio_thread_impl.cc and https://crbug.com/158170.
1383 if (audio_task_runner) {
1384 DCHECK(audio_task_runner->BelongsToCurrentThread());
1385 } else {
1386 audio_task_runner = base::ThreadTaskRunnerHandle::Get();
1387 }
1388 #endif
1389
1390 media_stream_manager_ = std::make_unique<MediaStreamManager>(
1391 audio_system_.get(), std::move(audio_task_runner));
1392 }
1393 #if BUILDFLAG(ENABLE_WEB_SPEECH)
1394 {
1395 TRACE_EVENT0(
1396 "startup",
1397 "BrowserMainLoop::BrowserThreadsStarted:InitSpeechRecognition");
1398 speech_recognition_manager_.reset(new SpeechRecognitionManagerImpl(
1399 audio_system_.get(), media_stream_manager_.get()));
1400 }
1401 #endif
1402
1403 {
1404 TRACE_EVENT0(
1405 "startup",
1406 "BrowserMainLoop::BrowserThreadsStarted::InitUserInputMonitor");
1407 user_input_monitor_ = media::UserInputMonitor::Create(
1408 io_thread_->task_runner(), base::ThreadTaskRunnerHandle::Get());
1409 }
1410
1411 {
1412 TRACE_EVENT0("startup",
1413 "BrowserMainLoop::BrowserThreadsStarted::SaveFileManager");
1414 save_file_manager_ = new SaveFileManager();
1415 }
1416
1417 // Alert the clipboard class to which threads are allowed to access the
1418 // clipboard:
1419 std::vector<base::PlatformThreadId> allowed_clipboard_threads;
1420 // The current thread is the UI thread.
1421 allowed_clipboard_threads.push_back(base::PlatformThread::CurrentId());
1422 #if defined(OS_WIN)
1423 // On Windows, clipboard is also used on the IO thread.
1424 allowed_clipboard_threads.push_back(io_thread_->GetThreadId());
1425 #endif
1426 ui::Clipboard::SetAllowedThreads(allowed_clipboard_threads);
1427
1428 if (GpuDataManagerImpl::GetInstance()->GpuProcessStartAllowed() &&
1429 !established_gpu_channel && always_uses_gpu) {
1430 TRACE_EVENT_INSTANT0("gpu", "Post task to launch GPU process",
1431 TRACE_EVENT_SCOPE_THREAD);
1432 base::PostTask(
1433 FROM_HERE, {BrowserThread::IO},
1434 base::BindOnce(base::IgnoreResult(&GpuProcessHost::Get),
1435 GPU_PROCESS_KIND_SANDBOXED, true /* force_create */));
1436 }
1437
1438 #if defined(OS_WIN)
1439 GpuDataManagerImpl::GetInstance()->OnBrowserThreadsStarted();
1440 #endif
1441
1442 if (MediaKeysListenerManager::IsMediaKeysListenerManagerEnabled()) {
1443 media_keys_listener_manager_ =
1444 std::make_unique<MediaKeysListenerManagerImpl>();
1445 }
1446
1447 #if defined(OS_MACOSX)
1448 ThemeHelperMac::GetInstance();
1449 #endif // defined(OS_MACOSX)
1450
1451 #if defined(OS_ANDROID)
1452 media::SetMediaDrmBridgeClient(GetContentClient()->GetMediaDrmBridgeClient());
1453 if (base::FeatureList::IsEnabled(features::kFontSrcLocalMatching)) {
1454 FontUniqueNameLookup::GetInstance();
1455 }
1456 #endif
1457
1458 #if defined(ENABLE_IPC_FUZZER)
1459 SetFileUrlPathAliasForIpcFuzzer();
1460 #endif
1461 return result_code_;
1462 }
1463
UsingInProcessGpu() const1464 bool BrowserMainLoop::UsingInProcessGpu() const {
1465 return parsed_command_line_.HasSwitch(switches::kSingleProcess) ||
1466 parsed_command_line_.HasSwitch(switches::kInProcessGPU);
1467 }
1468
InitializeMemoryManagementComponent()1469 void BrowserMainLoop::InitializeMemoryManagementComponent() {
1470 memory_pressure_monitor_ = CreateMemoryPressureMonitor(parsed_command_line_);
1471 }
1472
InitializeToolkit()1473 bool BrowserMainLoop::InitializeToolkit() {
1474 TRACE_EVENT0("startup", "BrowserMainLoop::InitializeToolkit");
1475
1476 // TODO(evan): this function is rather subtle, due to the variety
1477 // of intersecting ifdefs we have. To keep it easy to follow, there
1478 // are no #else branches on any #ifs.
1479 // TODO(stevenjb): Move platform specific code into platform specific Parts
1480 // (Need to add InitializeToolkit stage to BrowserParts).
1481 // See also GTK setup in EarlyInitialization, above, and associated comments.
1482
1483 #if defined(OS_WIN)
1484 INITCOMMONCONTROLSEX config;
1485 config.dwSize = sizeof(config);
1486 config.dwICC = ICC_WIN95_CLASSES;
1487 if (!InitCommonControlsEx(&config))
1488 PLOG(FATAL);
1489 #endif
1490
1491 #if defined(USE_AURA)
1492
1493 #if defined(USE_X11) && !defined(TOOLKIT_QT)
1494 if (!parsed_command_line_.HasSwitch(switches::kHeadless) &&
1495 !gfx::GetXDisplay()) {
1496 LOG(ERROR) << "Unable to open X display.";
1497 return false;
1498 }
1499 #endif
1500
1501 // Env creates the compositor. Aura widgets need the compositor to be created
1502 // before they can be initialized by the browser.
1503 env_ = aura::Env::CreateInstance();
1504 #endif // defined(USE_AURA)
1505
1506 if (parts_)
1507 parts_->ToolkitInitialized();
1508
1509 return true;
1510 }
1511
MainMessageLoopRun()1512 void BrowserMainLoop::MainMessageLoopRun() {
1513 #if defined(OS_ANDROID)
1514 // Android's main message loop is the Java message loop.
1515 NOTREACHED();
1516 #else
1517 base::RunLoop run_loop;
1518 parts_->PreDefaultMainMessageLoopRun(run_loop.QuitClosure());
1519 run_loop.Run();
1520 #endif
1521 }
1522
InitializeMojo()1523 void BrowserMainLoop::InitializeMojo() {
1524 if (!parsed_command_line_.HasSwitch(switches::kSingleProcess)) {
1525 // Disallow mojo sync calls in the browser process. Note that we allow sync
1526 // calls in single-process mode since renderer IPCs are made from a browser
1527 // thread.
1528 mojo::SyncCallRestrictions::DisallowSyncCall();
1529 }
1530
1531 // Ensure that any NavigableContentsViews constructed in the browser process
1532 // know they're running in the same process as the service.
1533 content::NavigableContentsView::SetClientRunningInServiceProcess();
1534
1535 // Start startup tracing through TracingController's interface. TraceLog has
1536 // been enabled in content_main_runner where threads are not available. Now We
1537 // need to start tracing for all other tracing agents, which require threads.
1538 // We can only do this after starting the main message loop to avoid calling
1539 // MessagePumpForUI::ScheduleWork() before MessagePumpForUI::Start().
1540 TracingControllerImpl::GetInstance()->StartStartupTracingIfNeeded();
1541
1542 #if BUILDFLAG(MOJO_RANDOM_DELAYS_ENABLED)
1543 mojo::BeginRandomMojoDelays();
1544 #endif
1545 }
1546
InitializeAudio()1547 void BrowserMainLoop::InitializeAudio() {
1548 DCHECK(!audio_manager_);
1549
1550 audio_manager_ = GetContentClient()->browser()->CreateAudioManager(
1551 MediaInternals::GetInstance());
1552 DCHECK_EQ(!!audio_manager_,
1553 GetContentClient()->browser()->OverridesAudioManager());
1554
1555 // Do not initialize |audio_manager_| if running out of process.
1556 if (!audio_manager_ &&
1557 (base::CommandLine::ForCurrentProcess()->HasSwitch(
1558 switches::kSingleProcess) ||
1559 !base::FeatureList::IsEnabled(features::kAudioServiceOutOfProcess))) {
1560 audio_manager_ =
1561 media::AudioManager::Create(std::make_unique<media::AudioThreadImpl>(),
1562 MediaInternals::GetInstance());
1563 CHECK(audio_manager_);
1564 }
1565
1566 // Iff |audio_manager_| is instantiated, the audio service will run
1567 // in-process. Complete the setup for that:
1568 if (audio_manager_) {
1569 AudioMirroringManager* const mirroring_manager =
1570 AudioMirroringManager::GetInstance();
1571 audio_manager_->SetDiverterCallbacks(
1572 mirroring_manager->GetAddDiverterCallback(),
1573 mirroring_manager->GetRemoveDiverterCallback());
1574
1575 TRACE_EVENT_INSTANT0("startup", "Starting Audio service task runner",
1576 TRACE_EVENT_SCOPE_THREAD);
1577 audio::Service::GetInProcessTaskRunner()->StartWithTaskRunner(
1578 audio_manager_->GetTaskRunner());
1579 }
1580
1581 if (base::FeatureList::IsEnabled(features::kAudioServiceLaunchOnStartup)) {
1582 // Schedule the audio service startup on the main thread.
1583 base::PostTask(
1584 FROM_HERE,
1585 {content::BrowserThread::UI, base::TaskPriority::BEST_EFFORT},
1586 base::BindOnce([]() {
1587 TRACE_EVENT0("audio", "Starting audio service");
1588 GetAudioService();
1589 }));
1590 }
1591
1592 audio_system_ = CreateAudioSystemForAudioService();
1593 CHECK(audio_system_);
1594 }
1595
AudioServiceOutOfProcess() const1596 bool BrowserMainLoop::AudioServiceOutOfProcess() const {
1597 // Returns true iff kAudioServiceOutOfProcess feature is enabled and if the
1598 // embedder does not provide its own in-process AudioManager.
1599 return base::FeatureList::IsEnabled(features::kAudioServiceOutOfProcess) &&
1600 !GetContentClient()->browser()->OverridesAudioManager();
1601 }
1602
1603 } // namespace content
1604