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