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 "base/bind.h" 8 #include "base/command_line.h" 9 #include "base/debug/trace_event.h" 10 #include "base/file_util.h" 11 #include "base/logging.h" 12 #include "base/message_loop/message_loop.h" 13 #include "base/metrics/field_trial.h" 14 #include "base/metrics/histogram.h" 15 #include "base/path_service.h" 16 #include "base/pending_task.h" 17 #include "base/power_monitor/power_monitor.h" 18 #include "base/power_monitor/power_monitor_device_source.h" 19 #include "base/process/process_metrics.h" 20 #include "base/run_loop.h" 21 #include "base/strings/string_number_conversions.h" 22 #include "base/system_monitor/system_monitor.h" 23 #include "base/thread_task_runner_handle.h" 24 #include "base/threading/thread_restrictions.h" 25 #include "base/timer/hi_res_timer_manager.h" 26 #include "content/browser/battery_status/battery_status_service.h" 27 #include "content/browser/browser_thread_impl.h" 28 #include "content/browser/device_sensors/device_inertial_sensor_service.h" 29 #include "content/browser/download/save_file_manager.h" 30 #include "content/browser/gamepad/gamepad_service.h" 31 #include "content/browser/gpu/browser_gpu_channel_host_factory.h" 32 #include "content/browser/gpu/compositor_util.h" 33 #include "content/browser/gpu/gpu_data_manager_impl.h" 34 #include "content/browser/gpu/gpu_process_host.h" 35 #include "content/browser/gpu/gpu_process_host_ui_shim.h" 36 #include "content/browser/histogram_synchronizer.h" 37 #include "content/browser/loader/resource_dispatcher_host_impl.h" 38 #include "content/browser/media/capture/audio_mirroring_manager.h" 39 #include "content/browser/media/media_internals.h" 40 #include "content/browser/net/browser_online_state_observer.h" 41 #include "content/browser/plugin_service_impl.h" 42 #include "content/browser/renderer_host/media/media_stream_manager.h" 43 #include "content/browser/speech/speech_recognition_manager_impl.h" 44 #include "content/browser/startup_task_runner.h" 45 #include "content/browser/time_zone_monitor.h" 46 #include "content/browser/webui/content_web_ui_controller_factory.h" 47 #include "content/browser/webui/url_data_manager.h" 48 #include "content/public/browser/browser_main_parts.h" 49 #include "content/public/browser/browser_shutdown.h" 50 #include "content/public/browser/content_browser_client.h" 51 #include "content/public/browser/render_process_host.h" 52 #include "content/public/browser/tracing_controller.h" 53 #include "content/public/common/content_switches.h" 54 #include "content/public/common/main_function_params.h" 55 #include "content/public/common/result_codes.h" 56 #include "crypto/nss_util.h" 57 #include "media/audio/audio_manager.h" 58 #include "media/base/media.h" 59 #include "media/base/user_input_monitor.h" 60 #include "media/midi/midi_manager.h" 61 #include "net/base/network_change_notifier.h" 62 #include "net/socket/client_socket_factory.h" 63 #include "net/ssl/ssl_config_service.h" 64 #include "ui/base/clipboard/clipboard.h" 65 66 #if defined(USE_AURA) || (defined(OS_MACOSX) && !defined(OS_IOS)) 67 #include "content/browser/compositor/image_transport_factory.h" 68 #endif 69 70 #if defined(USE_AURA) 71 #include "content/public/browser/context_factory.h" 72 #include "ui/aura/env.h" 73 #endif 74 75 #if !defined(OS_IOS) 76 #include "content/browser/renderer_host/render_process_host_impl.h" 77 #endif 78 79 #if defined(OS_ANDROID) 80 #include "base/android/jni_android.h" 81 #include "content/browser/android/browser_startup_controller.h" 82 #include "content/browser/android/surface_texture_peer_browser_impl.h" 83 #include "content/browser/android/tracing_controller_android.h" 84 #include "ui/gl/gl_surface.h" 85 #endif 86 87 #if defined(OS_MACOSX) && !defined(OS_IOS) 88 #include "content/browser/bootstrap_sandbox_mac.h" 89 #include "content/browser/theme_helper_mac.h" 90 #endif 91 92 #if defined(OS_WIN) 93 #include <windows.h> 94 #include <commctrl.h> 95 #include <shellapi.h> 96 97 #include "content/browser/system_message_window_win.h" 98 #include "content/common/sandbox_win.h" 99 #include "net/base/winsock_init.h" 100 #include "ui/base/l10n/l10n_util_win.h" 101 #endif 102 103 #if defined(USE_GLIB) 104 #include <glib-object.h> 105 #endif 106 107 #if defined(OS_LINUX) && defined(USE_UDEV) 108 #include "content/browser/device_monitor_udev.h" 109 #elif defined(OS_MACOSX) && !defined(OS_IOS) 110 #include "content/browser/device_monitor_mac.h" 111 #endif 112 113 #if defined(OS_POSIX) && !defined(OS_MACOSX) 114 #include "content/browser/renderer_host/render_sandbox_host_linux.h" 115 #include "content/browser/zygote_host/zygote_host_impl_linux.h" 116 #include "sandbox/linux/suid/client/setuid_sandbox_client.h" 117 #endif 118 119 #if defined(TCMALLOC_TRACE_MEMORY_SUPPORTED) 120 #include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h" 121 #endif 122 123 #if defined(USE_X11) 124 #include "ui/gfx/x/x11_connection.h" 125 #include "ui/gfx/x/x11_types.h" 126 #endif 127 128 // One of the linux specific headers defines this as a macro. 129 #ifdef DestroyAll 130 #undef DestroyAll 131 #endif 132 133 namespace content { 134 namespace { 135 136 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) 137 void SetupSandbox(const CommandLine& parsed_command_line) { 138 TRACE_EVENT0("startup", "SetupSandbox"); 139 base::FilePath sandbox_binary; 140 141 scoped_ptr<sandbox::SetuidSandboxClient> setuid_sandbox_client( 142 sandbox::SetuidSandboxClient::Create()); 143 144 const bool want_setuid_sandbox = 145 !parsed_command_line.HasSwitch(switches::kNoSandbox) && 146 !parsed_command_line.HasSwitch(switches::kDisableSetuidSandbox) && 147 !setuid_sandbox_client->IsDisabledViaEnvironment(); 148 149 static const char no_suid_error[] = 150 "Running without the SUID sandbox! See " 151 "https://code.google.com/p/chromium/wiki/LinuxSUIDSandboxDevelopment " 152 "for more information on developing with the sandbox on."; 153 if (want_setuid_sandbox) { 154 sandbox_binary = setuid_sandbox_client->GetSandboxBinaryPath(); 155 if (sandbox_binary.empty()) { 156 // This needs to be fatal. Talk to security (at) chromium.org if you feel 157 // otherwise. 158 LOG(FATAL) << no_suid_error; 159 } 160 } else { 161 LOG(ERROR) << no_suid_error; 162 } 163 164 // Tickle the sandbox host and zygote host so they fork now. 165 RenderSandboxHostLinux::GetInstance()->Init(); 166 ZygoteHostImpl::GetInstance()->Init(sandbox_binary.value()); 167 } 168 #endif 169 170 #if defined(USE_GLIB) 171 static void GLibLogHandler(const gchar* log_domain, 172 GLogLevelFlags log_level, 173 const gchar* message, 174 gpointer userdata) { 175 if (!log_domain) 176 log_domain = "<unknown>"; 177 if (!message) 178 message = "<no message>"; 179 180 if (strstr(message, "Unable to retrieve the file info for")) { 181 LOG(ERROR) << "GTK File code error: " << message; 182 } else if (strstr(message, "Could not find the icon") && 183 strstr(log_domain, "Gtk")) { 184 LOG(ERROR) << "GTK icon error: " << message; 185 } else if (strstr(message, "Theme file for default has no") || 186 strstr(message, "Theme directory") || 187 strstr(message, "theme pixmap") || 188 strstr(message, "locate theme engine")) { 189 LOG(ERROR) << "GTK theme error: " << message; 190 } else if (strstr(message, "Unable to create Ubuntu Menu Proxy") && 191 strstr(log_domain, "<unknown>")) { 192 LOG(ERROR) << "GTK menu proxy create failed"; 193 } else if (strstr(message, "Out of memory") && 194 strstr(log_domain, "<unknown>")) { 195 LOG(ERROR) << "DBus call timeout or out of memory: " 196 << "http://crosbug.com/15496"; 197 } else if (strstr(message, "Could not connect: Connection refused") && 198 strstr(log_domain, "<unknown>")) { 199 LOG(ERROR) << "DConf settings backend could not connect to session bus: " 200 << "http://crbug.com/179797"; 201 } else if (strstr(message, "Attempting to store changes into") || 202 strstr(message, "Attempting to set the permissions of")) { 203 LOG(ERROR) << message << " (http://bugs.chromium.org/161366)"; 204 } else if (strstr(message, "drawable is not a native X11 window")) { 205 LOG(ERROR) << message << " (http://bugs.chromium.org/329991)"; 206 } else { 207 LOG(DFATAL) << log_domain << ": " << message; 208 } 209 } 210 211 static void SetUpGLibLogHandler() { 212 // Register GLib-handled assertions to go through our logging system. 213 const char* kLogDomains[] = { NULL, "Gtk", "Gdk", "GLib", "GLib-GObject" }; 214 for (size_t i = 0; i < arraysize(kLogDomains); i++) { 215 g_log_set_handler(kLogDomains[i], 216 static_cast<GLogLevelFlags>(G_LOG_FLAG_RECURSION | 217 G_LOG_FLAG_FATAL | 218 G_LOG_LEVEL_ERROR | 219 G_LOG_LEVEL_CRITICAL | 220 G_LOG_LEVEL_WARNING), 221 GLibLogHandler, 222 NULL); 223 } 224 } 225 #endif 226 227 void OnStoppedStartupTracing(const base::FilePath& trace_file) { 228 VLOG(0) << "Completed startup tracing to " << trace_file.value(); 229 } 230 231 #if defined(USE_AURA) 232 bool ShouldInitializeBrowserGpuChannelAndTransportSurface() { 233 return true; 234 } 235 #elif defined(OS_MACOSX) && !defined(OS_IOS) 236 bool ShouldInitializeBrowserGpuChannelAndTransportSurface() { 237 return IsDelegatedRendererEnabled(); 238 } 239 #endif 240 241 } // namespace 242 243 // The currently-running BrowserMainLoop. There can be one or zero. 244 BrowserMainLoop* g_current_browser_main_loop = NULL; 245 246 // This is just to be able to keep ShutdownThreadsAndCleanUp out of 247 // the public interface of BrowserMainLoop. 248 class BrowserShutdownImpl { 249 public: 250 static void ImmediateShutdownAndExitProcess() { 251 DCHECK(g_current_browser_main_loop); 252 g_current_browser_main_loop->ShutdownThreadsAndCleanUp(); 253 254 #if defined(OS_WIN) 255 // At this point the message loop is still running yet we've shut everything 256 // down. If any messages are processed we'll likely crash. Exit now. 257 ExitProcess(RESULT_CODE_NORMAL_EXIT); 258 #elif defined(OS_POSIX) && !defined(OS_MACOSX) 259 _exit(RESULT_CODE_NORMAL_EXIT); 260 #else 261 NOTIMPLEMENTED(); 262 #endif 263 } 264 }; 265 266 void ImmediateShutdownAndExitProcess() { 267 BrowserShutdownImpl::ImmediateShutdownAndExitProcess(); 268 } 269 270 // For measuring memory usage after each task. Behind a command line flag. 271 class BrowserMainLoop::MemoryObserver : public base::MessageLoop::TaskObserver { 272 public: 273 MemoryObserver() {} 274 virtual ~MemoryObserver() {} 275 276 virtual void WillProcessTask(const base::PendingTask& pending_task) OVERRIDE { 277 } 278 279 virtual void DidProcessTask(const base::PendingTask& pending_task) OVERRIDE { 280 #if !defined(OS_IOS) // No ProcessMetrics on IOS. 281 scoped_ptr<base::ProcessMetrics> process_metrics( 282 base::ProcessMetrics::CreateProcessMetrics( 283 #if defined(OS_MACOSX) 284 base::GetCurrentProcessHandle(), NULL)); 285 #else 286 base::GetCurrentProcessHandle())); 287 #endif 288 size_t private_bytes; 289 process_metrics->GetMemoryBytes(&private_bytes, NULL); 290 HISTOGRAM_MEMORY_KB("Memory.BrowserUsed", private_bytes >> 10); 291 #endif 292 } 293 private: 294 DISALLOW_COPY_AND_ASSIGN(MemoryObserver); 295 }; 296 297 298 // BrowserMainLoop construction / destruction ============================= 299 300 BrowserMainLoop* BrowserMainLoop::GetInstance() { 301 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 302 return g_current_browser_main_loop; 303 } 304 305 BrowserMainLoop::BrowserMainLoop(const MainFunctionParams& parameters) 306 : parameters_(parameters), 307 parsed_command_line_(parameters.command_line), 308 result_code_(RESULT_CODE_NORMAL_EXIT), 309 created_threads_(false), 310 // ContentMainRunner should have enabled tracing of the browser process 311 // when kTraceStartup is in the command line. 312 is_tracing_startup_( 313 parameters.command_line.HasSwitch(switches::kTraceStartup)) { 314 DCHECK(!g_current_browser_main_loop); 315 g_current_browser_main_loop = this; 316 } 317 318 BrowserMainLoop::~BrowserMainLoop() { 319 DCHECK_EQ(this, g_current_browser_main_loop); 320 #if !defined(OS_IOS) 321 ui::Clipboard::DestroyClipboardForCurrentThread(); 322 #endif // !defined(OS_IOS) 323 g_current_browser_main_loop = NULL; 324 } 325 326 void BrowserMainLoop::Init() { 327 TRACE_EVENT0("startup", "BrowserMainLoop::Init"); 328 parts_.reset( 329 GetContentClient()->browser()->CreateBrowserMainParts(parameters_)); 330 } 331 332 // BrowserMainLoop stages ================================================== 333 334 void BrowserMainLoop::EarlyInitialization() { 335 TRACE_EVENT0("startup", "BrowserMainLoop::EarlyInitialization"); 336 337 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) 338 // No thread should be created before this call, as SetupSandbox() 339 // will end-up using fork(). 340 SetupSandbox(parsed_command_line_); 341 #endif 342 343 #if defined(USE_X11) 344 if (parsed_command_line_.HasSwitch(switches::kSingleProcess) || 345 parsed_command_line_.HasSwitch(switches::kInProcessGPU)) { 346 if (!gfx::InitializeThreadedX11()) { 347 LOG(ERROR) << "Failed to put Xlib into threaded mode."; 348 } 349 } 350 #endif 351 352 // GLib's spawning of new processes is buggy, so it's important that at this 353 // point GLib does not need to start DBUS. Chrome should always start with 354 // DBUS_SESSION_BUS_ADDRESS properly set. See crbug.com/309093. 355 #if defined(USE_GLIB) 356 // g_type_init will be deprecated in 2.36. 2.35 is the development 357 // version for 2.36, hence do not call g_type_init starting 2.35. 358 // http://developer.gnome.org/gobject/unstable/gobject-Type-Information.html#g-type-init 359 #if !GLIB_CHECK_VERSION(2, 35, 0) 360 // GLib type system initialization. Needed at least for gconf, 361 // used in net/proxy/proxy_config_service_linux.cc. Most likely 362 // this is superfluous as gtk_init() ought to do this. It's 363 // definitely harmless, so retained as a reminder of this 364 // requirement for gconf. 365 g_type_init(); 366 #endif 367 368 SetUpGLibLogHandler(); 369 #endif 370 371 if (parts_) 372 parts_->PreEarlyInitialization(); 373 374 #if defined(OS_MACOSX) 375 // We use quite a few file descriptors for our IPC, and the default limit on 376 // the Mac is low (256), so bump it up. 377 base::SetFdLimit(1024); 378 #endif 379 380 #if defined(OS_WIN) 381 net::EnsureWinsockInit(); 382 #endif 383 384 #if !defined(USE_OPENSSL) 385 // We want to be sure to init NSPR on the main thread. 386 crypto::EnsureNSPRInit(); 387 #endif // !defined(USE_OPENSSL) 388 389 #if !defined(OS_IOS) 390 if (parsed_command_line_.HasSwitch(switches::kRendererProcessLimit)) { 391 std::string limit_string = parsed_command_line_.GetSwitchValueASCII( 392 switches::kRendererProcessLimit); 393 size_t process_limit; 394 if (base::StringToSizeT(limit_string, &process_limit)) { 395 RenderProcessHost::SetMaxRendererProcessCount(process_limit); 396 } 397 } 398 #endif // !defined(OS_IOS) 399 400 if (parts_) 401 parts_->PostEarlyInitialization(); 402 } 403 404 void BrowserMainLoop::MainMessageLoopStart() { 405 TRACE_EVENT0("startup", "BrowserMainLoop::MainMessageLoopStart"); 406 if (parts_) { 407 TRACE_EVENT0("startup", 408 "BrowserMainLoop::MainMessageLoopStart:PreMainMessageLoopStart"); 409 parts_->PreMainMessageLoopStart(); 410 } 411 412 #if defined(OS_WIN) 413 // If we're running tests (ui_task is non-null), then the ResourceBundle 414 // has already been initialized. 415 if (!parameters_.ui_task) { 416 // Override the configured locale with the user's preferred UI language. 417 l10n_util::OverrideLocaleWithUILanguageList(); 418 } 419 #endif 420 421 // Create a MessageLoop if one does not already exist for the current thread. 422 if (!base::MessageLoop::current()) 423 main_message_loop_.reset(new base::MessageLoopForUI); 424 425 InitializeMainThread(); 426 427 { 428 TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:SystemMonitor"); 429 system_monitor_.reset(new base::SystemMonitor); 430 } 431 { 432 TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:PowerMonitor"); 433 scoped_ptr<base::PowerMonitorSource> power_monitor_source( 434 new base::PowerMonitorDeviceSource()); 435 power_monitor_.reset(new base::PowerMonitor(power_monitor_source.Pass())); 436 } 437 { 438 TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:HighResTimerManager"); 439 hi_res_timer_manager_.reset(new base::HighResolutionTimerManager); 440 } 441 { 442 TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:NetworkChangeNotifier"); 443 network_change_notifier_.reset(net::NetworkChangeNotifier::Create()); 444 } 445 446 #if !defined(OS_IOS) 447 { 448 TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:MediaFeatures"); 449 media::InitializeCPUSpecificMediaFeatures(); 450 } 451 { 452 TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:AudioMan"); 453 audio_manager_.reset(media::AudioManager::Create( 454 MediaInternals::GetInstance())); 455 } 456 { 457 TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:MidiManager"); 458 midi_manager_.reset(media::MidiManager::Create()); 459 } 460 { 461 TRACE_EVENT0("startup", 462 "BrowserMainLoop::Subsystem:ContentWebUIController"); 463 WebUIControllerFactory::RegisterFactory( 464 ContentWebUIControllerFactory::GetInstance()); 465 } 466 467 { 468 TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:AudioMirroringManager"); 469 audio_mirroring_manager_.reset(new AudioMirroringManager()); 470 } 471 { 472 TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:OnlineStateObserver"); 473 online_state_observer_.reset(new BrowserOnlineStateObserver); 474 } 475 476 { 477 system_stats_monitor_.reset(new base::debug::TraceEventSystemStatsMonitor( 478 base::ThreadTaskRunnerHandle::Get())); 479 } 480 #endif // !defined(OS_IOS) 481 482 #if defined(OS_WIN) 483 system_message_window_.reset(new SystemMessageWindowWin); 484 #endif 485 486 if (parts_) 487 parts_->PostMainMessageLoopStart(); 488 489 #if !defined(OS_IOS) 490 // Start tracing to a file if needed. Only do this after starting the main 491 // message loop to avoid calling MessagePumpForUI::ScheduleWork() before 492 // MessagePumpForUI::Start() as it will crash the browser. 493 if (is_tracing_startup_) { 494 TRACE_EVENT0("startup", "BrowserMainLoop::InitStartupTracing"); 495 InitStartupTracing(parsed_command_line_); 496 } 497 #endif // !defined(OS_IOS) 498 499 #if defined(OS_ANDROID) 500 { 501 TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:SurfaceTexturePeer"); 502 SurfaceTexturePeer::InitInstance(new SurfaceTexturePeerBrowserImpl()); 503 } 504 #endif 505 506 if (parsed_command_line_.HasSwitch(switches::kMemoryMetrics)) { 507 TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:MemoryObserver"); 508 memory_observer_.reset(new MemoryObserver()); 509 base::MessageLoop::current()->AddTaskObserver(memory_observer_.get()); 510 } 511 512 #if defined(TCMALLOC_TRACE_MEMORY_SUPPORTED) 513 trace_memory_controller_.reset(new base::debug::TraceMemoryController( 514 base::MessageLoop::current()->message_loop_proxy(), 515 ::HeapProfilerWithPseudoStackStart, 516 ::HeapProfilerStop, 517 ::GetHeapProfile)); 518 #endif 519 } 520 521 int BrowserMainLoop::PreCreateThreads() { 522 if (parts_) { 523 TRACE_EVENT0("startup", 524 "BrowserMainLoop::CreateThreads:PreCreateThreads"); 525 result_code_ = parts_->PreCreateThreads(); 526 } 527 528 #if defined(ENABLE_PLUGINS) 529 // Prior to any processing happening on the io thread, we create the 530 // plugin service as it is predominantly used from the io thread, 531 // but must be created on the main thread. The service ctor is 532 // inexpensive and does not invoke the io_thread() accessor. 533 { 534 TRACE_EVENT0("startup", "BrowserMainLoop::CreateThreads:PluginService"); 535 PluginService::GetInstance()->Init(); 536 } 537 #endif 538 539 #if !defined(OS_IOS) && (!defined(GOOGLE_CHROME_BUILD) || defined(OS_ANDROID)) 540 // Single-process is an unsupported and not fully tested mode, so 541 // don't enable it for official Chrome builds (except on Android). 542 if (parsed_command_line_.HasSwitch(switches::kSingleProcess)) 543 RenderProcessHost::SetRunRendererInProcess(true); 544 #endif 545 return result_code_; 546 } 547 548 void BrowserMainLoop::CreateStartupTasks() { 549 TRACE_EVENT0("startup", "BrowserMainLoop::CreateStartupTasks"); 550 551 // First time through, we really want to create all the tasks 552 if (!startup_task_runner_.get()) { 553 #if defined(OS_ANDROID) 554 startup_task_runner_ = make_scoped_ptr(new StartupTaskRunner( 555 base::Bind(&BrowserStartupComplete), 556 base::MessageLoop::current()->message_loop_proxy())); 557 #else 558 startup_task_runner_ = make_scoped_ptr(new StartupTaskRunner( 559 base::Callback<void(int)>(), 560 base::MessageLoop::current()->message_loop_proxy())); 561 #endif 562 StartupTask pre_create_threads = 563 base::Bind(&BrowserMainLoop::PreCreateThreads, base::Unretained(this)); 564 startup_task_runner_->AddTask(pre_create_threads); 565 566 StartupTask create_threads = 567 base::Bind(&BrowserMainLoop::CreateThreads, base::Unretained(this)); 568 startup_task_runner_->AddTask(create_threads); 569 570 StartupTask browser_thread_started = base::Bind( 571 &BrowserMainLoop::BrowserThreadsStarted, base::Unretained(this)); 572 startup_task_runner_->AddTask(browser_thread_started); 573 574 StartupTask pre_main_message_loop_run = base::Bind( 575 &BrowserMainLoop::PreMainMessageLoopRun, base::Unretained(this)); 576 startup_task_runner_->AddTask(pre_main_message_loop_run); 577 578 #if defined(OS_ANDROID) 579 if (BrowserMayStartAsynchronously()) { 580 startup_task_runner_->StartRunningTasksAsync(); 581 } 582 #endif 583 } 584 #if defined(OS_ANDROID) 585 if (!BrowserMayStartAsynchronously()) { 586 // A second request for asynchronous startup can be ignored, so 587 // StartupRunningTasksAsync is only called first time through. If, however, 588 // this is a request for synchronous startup then it must override any 589 // previous call for async startup, so we call RunAllTasksNow() 590 // unconditionally. 591 startup_task_runner_->RunAllTasksNow(); 592 } 593 #else 594 startup_task_runner_->RunAllTasksNow(); 595 #endif 596 } 597 598 int BrowserMainLoop::CreateThreads() { 599 TRACE_EVENT0("startup", "BrowserMainLoop::CreateThreads"); 600 601 base::Thread::Options default_options; 602 base::Thread::Options io_message_loop_options; 603 io_message_loop_options.message_loop_type = base::MessageLoop::TYPE_IO; 604 base::Thread::Options ui_message_loop_options; 605 ui_message_loop_options.message_loop_type = base::MessageLoop::TYPE_UI; 606 607 // Start threads in the order they occur in the BrowserThread::ID 608 // enumeration, except for BrowserThread::UI which is the main 609 // thread. 610 // 611 // Must be size_t so we can increment it. 612 for (size_t thread_id = BrowserThread::UI + 1; 613 thread_id < BrowserThread::ID_COUNT; 614 ++thread_id) { 615 scoped_ptr<BrowserProcessSubThread>* thread_to_start = NULL; 616 base::Thread::Options* options = &default_options; 617 618 switch (thread_id) { 619 case BrowserThread::DB: 620 TRACE_EVENT_BEGIN1("startup", 621 "BrowserMainLoop::CreateThreads:start", 622 "Thread", "BrowserThread::DB"); 623 thread_to_start = &db_thread_; 624 break; 625 case BrowserThread::FILE_USER_BLOCKING: 626 TRACE_EVENT_BEGIN1("startup", 627 "BrowserMainLoop::CreateThreads:start", 628 "Thread", "BrowserThread::FILE_USER_BLOCKING"); 629 thread_to_start = &file_user_blocking_thread_; 630 break; 631 case BrowserThread::FILE: 632 TRACE_EVENT_BEGIN1("startup", 633 "BrowserMainLoop::CreateThreads:start", 634 "Thread", "BrowserThread::FILE"); 635 thread_to_start = &file_thread_; 636 #if defined(OS_WIN) 637 // On Windows, the FILE thread needs to be have a UI message loop 638 // which pumps messages in such a way that Google Update can 639 // communicate back to us. 640 options = &ui_message_loop_options; 641 #else 642 options = &io_message_loop_options; 643 #endif 644 break; 645 case BrowserThread::PROCESS_LAUNCHER: 646 TRACE_EVENT_BEGIN1("startup", 647 "BrowserMainLoop::CreateThreads:start", 648 "Thread", "BrowserThread::PROCESS_LAUNCHER"); 649 thread_to_start = &process_launcher_thread_; 650 break; 651 case BrowserThread::CACHE: 652 TRACE_EVENT_BEGIN1("startup", 653 "BrowserMainLoop::CreateThreads:start", 654 "Thread", "BrowserThread::CACHE"); 655 thread_to_start = &cache_thread_; 656 options = &io_message_loop_options; 657 break; 658 case BrowserThread::IO: 659 TRACE_EVENT_BEGIN1("startup", 660 "BrowserMainLoop::CreateThreads:start", 661 "Thread", "BrowserThread::IO"); 662 thread_to_start = &io_thread_; 663 options = &io_message_loop_options; 664 break; 665 case BrowserThread::UI: 666 case BrowserThread::ID_COUNT: 667 default: 668 NOTREACHED(); 669 break; 670 } 671 672 BrowserThread::ID id = static_cast<BrowserThread::ID>(thread_id); 673 674 if (thread_to_start) { 675 (*thread_to_start).reset(new BrowserProcessSubThread(id)); 676 (*thread_to_start)->StartWithOptions(*options); 677 } else { 678 NOTREACHED(); 679 } 680 681 TRACE_EVENT_END0("startup", "BrowserMainLoop::CreateThreads:start"); 682 } 683 created_threads_ = true; 684 return result_code_; 685 } 686 687 int BrowserMainLoop::PreMainMessageLoopRun() { 688 if (parts_) { 689 TRACE_EVENT0("startup", 690 "BrowserMainLoop::CreateThreads:PreMainMessageLoopRun"); 691 parts_->PreMainMessageLoopRun(); 692 } 693 694 // If the UI thread blocks, the whole UI is unresponsive. 695 // Do not allow disk IO from the UI thread. 696 base::ThreadRestrictions::SetIOAllowed(false); 697 base::ThreadRestrictions::DisallowWaiting(); 698 return result_code_; 699 } 700 701 void BrowserMainLoop::RunMainMessageLoopParts() { 702 TRACE_EVENT_BEGIN_ETW("BrowserMain:MESSAGE_LOOP", 0, ""); 703 704 bool ran_main_loop = false; 705 if (parts_) 706 ran_main_loop = parts_->MainMessageLoopRun(&result_code_); 707 708 if (!ran_main_loop) 709 MainMessageLoopRun(); 710 711 TRACE_EVENT_END_ETW("BrowserMain:MESSAGE_LOOP", 0, ""); 712 } 713 714 void BrowserMainLoop::ShutdownThreadsAndCleanUp() { 715 if (!created_threads_) { 716 // Called early, nothing to do 717 return; 718 } 719 TRACE_EVENT0("shutdown", "BrowserMainLoop::ShutdownThreadsAndCleanUp"); 720 721 // Teardown may start in PostMainMessageLoopRun, and during teardown we 722 // need to be able to perform IO. 723 base::ThreadRestrictions::SetIOAllowed(true); 724 BrowserThread::PostTask( 725 BrowserThread::IO, FROM_HERE, 726 base::Bind(base::IgnoreResult(&base::ThreadRestrictions::SetIOAllowed), 727 true)); 728 729 #if !defined(OS_IOS) 730 if (RenderProcessHost::run_renderer_in_process()) 731 RenderProcessHostImpl::ShutDownInProcessRenderer(); 732 #endif 733 734 if (parts_) { 735 TRACE_EVENT0("shutdown", 736 "BrowserMainLoop::Subsystem:PostMainMessageLoopRun"); 737 parts_->PostMainMessageLoopRun(); 738 } 739 740 trace_memory_controller_.reset(); 741 system_stats_monitor_.reset(); 742 743 #if !defined(OS_IOS) 744 // Destroying the GpuProcessHostUIShims on the UI thread posts a task to 745 // delete related objects on the GPU thread. This must be done before 746 // stopping the GPU thread. The GPU thread will close IPC channels to renderer 747 // processes so this has to happen before stopping the IO thread. 748 { 749 TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:GPUProcessHostShim"); 750 GpuProcessHostUIShim::DestroyAll(); 751 } 752 // Cancel pending requests and prevent new requests. 753 if (resource_dispatcher_host_) { 754 TRACE_EVENT0("shutdown", 755 "BrowserMainLoop::Subsystem:ResourceDispatcherHost"); 756 resource_dispatcher_host_.get()->Shutdown(); 757 } 758 759 #if defined(USE_AURA) || defined(OS_MACOSX) 760 if (ShouldInitializeBrowserGpuChannelAndTransportSurface()) { 761 TRACE_EVENT0("shutdown", 762 "BrowserMainLoop::Subsystem:ImageTransportFactory"); 763 ImageTransportFactory::Terminate(); 764 } 765 #endif 766 767 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) 768 ZygoteHostImpl::GetInstance()->TearDownAfterLastChild(); 769 #endif // defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) 770 771 // The device monitors are using |system_monitor_| as dependency, so delete 772 // them before |system_monitor_| goes away. 773 // On Mac and windows, the monitor needs to be destroyed on the same thread 774 // as they were created. On Linux, the monitor will be deleted when IO thread 775 // goes away. 776 #if defined(OS_WIN) 777 system_message_window_.reset(); 778 #elif defined(OS_MACOSX) 779 device_monitor_mac_.reset(); 780 #endif 781 #endif // !defined(OS_IOS) 782 783 // Must be size_t so we can subtract from it. 784 for (size_t thread_id = BrowserThread::ID_COUNT - 1; 785 thread_id >= (BrowserThread::UI + 1); 786 --thread_id) { 787 // Find the thread object we want to stop. Looping over all valid 788 // BrowserThread IDs and DCHECKing on a missing case in the switch 789 // statement helps avoid a mismatch between this code and the 790 // BrowserThread::ID enumeration. 791 // 792 // The destruction order is the reverse order of occurrence in the 793 // BrowserThread::ID list. The rationale for the order is as 794 // follows (need to be filled in a bit): 795 // 796 // 797 // - The IO thread is the only user of the CACHE thread. 798 // 799 // - The PROCESS_LAUNCHER thread must be stopped after IO in case 800 // the IO thread posted a task to terminate a process on the 801 // process launcher thread. 802 // 803 // - (Not sure why DB stops last.) 804 switch (thread_id) { 805 case BrowserThread::DB: { 806 TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:DBThread"); 807 db_thread_.reset(); 808 } 809 break; 810 case BrowserThread::FILE_USER_BLOCKING: { 811 TRACE_EVENT0("shutdown", 812 "BrowserMainLoop::Subsystem:FileUserBlockingThread"); 813 file_user_blocking_thread_.reset(); 814 } 815 break; 816 case BrowserThread::FILE: { 817 TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:FileThread"); 818 #if !defined(OS_IOS) 819 // Clean up state that lives on or uses the file_thread_ before 820 // it goes away. 821 if (resource_dispatcher_host_) 822 resource_dispatcher_host_.get()->save_file_manager()->Shutdown(); 823 #endif // !defined(OS_IOS) 824 file_thread_.reset(); 825 } 826 break; 827 case BrowserThread::PROCESS_LAUNCHER: { 828 TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:LauncherThread"); 829 process_launcher_thread_.reset(); 830 } 831 break; 832 case BrowserThread::CACHE: { 833 TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:CacheThread"); 834 cache_thread_.reset(); 835 } 836 break; 837 case BrowserThread::IO: { 838 TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:IOThread"); 839 io_thread_.reset(); 840 } 841 break; 842 case BrowserThread::UI: 843 case BrowserThread::ID_COUNT: 844 default: 845 NOTREACHED(); 846 break; 847 } 848 } 849 850 #if !defined(OS_IOS) 851 { 852 TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:IndexedDBThread"); 853 indexed_db_thread_.reset(); 854 } 855 #endif 856 857 // Close the blocking I/O pool after the other threads. Other threads such 858 // as the I/O thread may need to schedule work like closing files or flushing 859 // data during shutdown, so the blocking pool needs to be available. There 860 // may also be slow operations pending that will blcok shutdown, so closing 861 // it here (which will block until required operations are complete) gives 862 // more head start for those operations to finish. 863 { 864 TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:ThreadPool"); 865 BrowserThreadImpl::ShutdownThreadPool(); 866 } 867 868 #if !defined(OS_IOS) 869 // Must happen after the IO thread is shutdown since this may be accessed from 870 // it. 871 { 872 TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:GPUChannelFactory"); 873 if (BrowserGpuChannelHostFactory::instance()) 874 BrowserGpuChannelHostFactory::Terminate(); 875 } 876 877 // Must happen after the I/O thread is shutdown since this class lives on the 878 // I/O thread and isn't threadsafe. 879 { 880 TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:GamepadService"); 881 GamepadService::GetInstance()->Terminate(); 882 } 883 { 884 TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:SensorService"); 885 DeviceInertialSensorService::GetInstance()->Shutdown(); 886 } 887 { 888 TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:BatteryStatusService"); 889 BatteryStatusService::GetInstance()->Shutdown(); 890 } 891 { 892 TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:DeleteDataSources"); 893 URLDataManager::DeleteDataSources(); 894 } 895 #endif // !defined(OS_IOS) 896 897 if (parts_) { 898 TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:PostDestroyThreads"); 899 parts_->PostDestroyThreads(); 900 } 901 } 902 903 void BrowserMainLoop::InitializeMainThread() { 904 TRACE_EVENT0("startup", "BrowserMainLoop::InitializeMainThread"); 905 const char* kThreadName = "CrBrowserMain"; 906 base::PlatformThread::SetName(kThreadName); 907 if (main_message_loop_) 908 main_message_loop_->set_thread_name(kThreadName); 909 910 // Register the main thread by instantiating it, but don't call any methods. 911 main_thread_.reset( 912 new BrowserThreadImpl(BrowserThread::UI, base::MessageLoop::current())); 913 } 914 915 int BrowserMainLoop::BrowserThreadsStarted() { 916 TRACE_EVENT0("startup", "BrowserMainLoop::BrowserThreadsStarted"); 917 918 #if !defined(OS_IOS) 919 indexed_db_thread_.reset(new base::Thread("IndexedDB")); 920 indexed_db_thread_->Start(); 921 #endif 922 923 #if defined(OS_ANDROID) 924 // Up the priority of anything that touches with display tasks 925 // (this thread is UI thread, and io_thread_ is for IPCs). 926 io_thread_->SetPriority(base::kThreadPriority_Display); 927 base::PlatformThread::SetThreadPriority( 928 base::PlatformThread::CurrentHandle(), 929 base::kThreadPriority_Display); 930 #endif 931 932 #if !defined(OS_IOS) 933 HistogramSynchronizer::GetInstance(); 934 935 bool initialize_gpu_data_manager = true; 936 #if defined(OS_ANDROID) 937 // On Android, GLSurface::InitializeOneOff() must be called before initalizing 938 // the GpuDataManagerImpl as it uses the GL bindings. crbug.com/326295 939 if (!gfx::GLSurface::InitializeOneOff()) { 940 LOG(ERROR) << "GLSurface::InitializeOneOff failed"; 941 initialize_gpu_data_manager = false; 942 } 943 #endif 944 945 // Initialize the GpuDataManager before we set up the MessageLoops because 946 // otherwise we'll trigger the assertion about doing IO on the UI thread. 947 if (initialize_gpu_data_manager) 948 GpuDataManagerImpl::GetInstance()->Initialize(); 949 950 bool always_uses_gpu = true; 951 bool established_gpu_channel = false; 952 #if defined(USE_AURA) || defined(OS_MACOSX) 953 if (ShouldInitializeBrowserGpuChannelAndTransportSurface()) { 954 established_gpu_channel = true; 955 if (!GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor()) { 956 established_gpu_channel = always_uses_gpu = false; 957 } 958 BrowserGpuChannelHostFactory::Initialize(established_gpu_channel); 959 ImageTransportFactory::Initialize(); 960 #if defined(USE_AURA) 961 if (aura::Env::GetInstance()) { 962 aura::Env::GetInstance()->set_context_factory( 963 content::GetContextFactory()); 964 } 965 #endif 966 } 967 #elif defined(OS_ANDROID) 968 established_gpu_channel = true; 969 BrowserGpuChannelHostFactory::Initialize(established_gpu_channel); 970 #endif 971 972 #if defined(OS_LINUX) && defined(USE_UDEV) 973 device_monitor_linux_.reset(new DeviceMonitorLinux()); 974 #elif defined(OS_MACOSX) 975 device_monitor_mac_.reset(new DeviceMonitorMac()); 976 #endif 977 978 // RDH needs the IO thread to be created 979 { 980 TRACE_EVENT0("startup", 981 "BrowserMainLoop::BrowserThreadsStarted:InitResourceDispatcherHost"); 982 resource_dispatcher_host_.reset(new ResourceDispatcherHostImpl()); 983 } 984 985 // MediaStreamManager needs the IO thread to be created. 986 { 987 TRACE_EVENT0("startup", 988 "BrowserMainLoop::BrowserThreadsStarted:InitMediaStreamManager"); 989 media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get())); 990 } 991 992 { 993 TRACE_EVENT0("startup", 994 "BrowserMainLoop::BrowserThreadsStarted:InitSpeechRecognition"); 995 speech_recognition_manager_.reset(new SpeechRecognitionManagerImpl( 996 audio_manager_.get(), media_stream_manager_.get())); 997 } 998 999 { 1000 TRACE_EVENT0( 1001 "startup", 1002 "BrowserMainLoop::BrowserThreadsStarted::InitUserInputMonitor"); 1003 user_input_monitor_ = media::UserInputMonitor::Create( 1004 io_thread_->message_loop_proxy(), main_thread_->message_loop_proxy()); 1005 } 1006 1007 { 1008 TRACE_EVENT0("startup", 1009 "BrowserMainLoop::BrowserThreadsStarted::TimeZoneMonitor"); 1010 time_zone_monitor_ = TimeZoneMonitor::Create(); 1011 } 1012 1013 // Alert the clipboard class to which threads are allowed to access the 1014 // clipboard: 1015 std::vector<base::PlatformThreadId> allowed_clipboard_threads; 1016 // The current thread is the UI thread. 1017 allowed_clipboard_threads.push_back(base::PlatformThread::CurrentId()); 1018 #if defined(OS_WIN) 1019 // On Windows, clipboards are also used on the File or IO threads. 1020 allowed_clipboard_threads.push_back(file_thread_->thread_id()); 1021 allowed_clipboard_threads.push_back(io_thread_->thread_id()); 1022 #endif 1023 ui::Clipboard::SetAllowedThreads(allowed_clipboard_threads); 1024 1025 // When running the GPU thread in-process, avoid optimistically starting it 1026 // since creating the GPU thread races against creation of the one-and-only 1027 // ChildProcess instance which is created by the renderer thread. 1028 if (GpuDataManagerImpl::GetInstance()->GpuAccessAllowed(NULL) && 1029 !established_gpu_channel && 1030 always_uses_gpu && 1031 !parsed_command_line_.HasSwitch(switches::kSingleProcess) && 1032 !parsed_command_line_.HasSwitch(switches::kInProcessGPU)) { 1033 TRACE_EVENT_INSTANT0("gpu", "Post task to launch GPU process", 1034 TRACE_EVENT_SCOPE_THREAD); 1035 BrowserThread::PostTask( 1036 BrowserThread::IO, FROM_HERE, base::Bind( 1037 base::IgnoreResult(&GpuProcessHost::Get), 1038 GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, 1039 CAUSE_FOR_GPU_LAUNCH_BROWSER_STARTUP)); 1040 } 1041 1042 #if defined(OS_MACOSX) 1043 ThemeHelperMac::GetInstance(); 1044 if (ShouldEnableBootstrapSandbox()) { 1045 TRACE_EVENT0("startup", 1046 "BrowserMainLoop::BrowserThreadsStarted:BootstrapSandbox"); 1047 CHECK(GetBootstrapSandbox()); 1048 } 1049 #endif // defined(OS_MACOSX) 1050 1051 #endif // !defined(OS_IOS) 1052 1053 return result_code_; 1054 } 1055 1056 bool BrowserMainLoop::InitializeToolkit() { 1057 TRACE_EVENT0("startup", "BrowserMainLoop::InitializeToolkit"); 1058 // TODO(evan): this function is rather subtle, due to the variety 1059 // of intersecting ifdefs we have. To keep it easy to follow, there 1060 // are no #else branches on any #ifs. 1061 // TODO(stevenjb): Move platform specific code into platform specific Parts 1062 // (Need to add InitializeToolkit stage to BrowserParts). 1063 // See also GTK setup in EarlyInitialization, above, and associated comments. 1064 1065 #if defined(OS_WIN) 1066 // Init common control sex. 1067 INITCOMMONCONTROLSEX config; 1068 config.dwSize = sizeof(config); 1069 config.dwICC = ICC_WIN95_CLASSES; 1070 if (!InitCommonControlsEx(&config)) 1071 PLOG(FATAL); 1072 #endif 1073 1074 #if defined(USE_AURA) 1075 1076 #if defined(USE_X11) 1077 if (!gfx::GetXDisplay()) 1078 return false; 1079 #endif 1080 1081 // Env creates the compositor. Aura widgets need the compositor to be created 1082 // before they can be initialized by the browser. 1083 aura::Env::CreateInstance(true); 1084 #endif // defined(USE_AURA) 1085 1086 if (parts_) 1087 parts_->ToolkitInitialized(); 1088 1089 return true; 1090 } 1091 1092 void BrowserMainLoop::MainMessageLoopRun() { 1093 #if defined(OS_ANDROID) 1094 // Android's main message loop is the Java message loop. 1095 NOTREACHED(); 1096 #else 1097 DCHECK(base::MessageLoopForUI::IsCurrent()); 1098 if (parameters_.ui_task) 1099 base::MessageLoopForUI::current()->PostTask(FROM_HERE, 1100 *parameters_.ui_task); 1101 1102 base::RunLoop run_loop; 1103 run_loop.Run(); 1104 #endif 1105 } 1106 1107 void BrowserMainLoop::InitStartupTracing(const CommandLine& command_line) { 1108 DCHECK(is_tracing_startup_); 1109 1110 base::FilePath trace_file = command_line.GetSwitchValuePath( 1111 switches::kTraceStartupFile); 1112 // trace_file = "none" means that startup events will show up for the next 1113 // begin/end tracing (via about:tracing or AutomationProxy::BeginTracing/ 1114 // EndTracing, for example). 1115 if (trace_file == base::FilePath().AppendASCII("none")) 1116 return; 1117 1118 if (trace_file.empty()) { 1119 #if defined(OS_ANDROID) 1120 TracingControllerAndroid::GenerateTracingFilePath(&trace_file); 1121 #else 1122 // Default to saving the startup trace into the current dir. 1123 trace_file = base::FilePath().AppendASCII("chrometrace.log"); 1124 #endif 1125 } 1126 1127 std::string delay_str = command_line.GetSwitchValueASCII( 1128 switches::kTraceStartupDuration); 1129 int delay_secs = 5; 1130 if (!delay_str.empty() && !base::StringToInt(delay_str, &delay_secs)) { 1131 DLOG(WARNING) << "Could not parse --" << switches::kTraceStartupDuration 1132 << "=" << delay_str << " defaulting to 5 (secs)"; 1133 delay_secs = 5; 1134 } 1135 1136 BrowserThread::PostDelayedTask( 1137 BrowserThread::UI, FROM_HERE, 1138 base::Bind(&BrowserMainLoop::EndStartupTracing, 1139 base::Unretained(this), trace_file), 1140 base::TimeDelta::FromSeconds(delay_secs)); 1141 } 1142 1143 void BrowserMainLoop::EndStartupTracing(const base::FilePath& trace_file) { 1144 is_tracing_startup_ = false; 1145 TracingController::GetInstance()->DisableRecording( 1146 trace_file, base::Bind(&OnStoppedStartupTracing)); 1147 } 1148 1149 } // namespace content 1150