blob: 67ef5bddf3e4f281df96cdd269b23208ed220567 [file] [log] [blame]
[email protected]38d0b2d42012-01-18 03:37:341// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]b48c9182011-10-26 18:03:302// 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
[email protected]820de972012-01-03 18:23:047#include "base/bind.h"
[email protected]b48c9182011-10-26 18:03:308#include "base/command_line.h"
9#include "base/debug/trace_event.h"
[email protected]b3aabd342012-06-04 19:33:5610#include "base/hi_res_timer_manager.h"
[email protected]b48c9182011-10-26 18:03:3011#include "base/logging.h"
12#include "base/message_loop.h"
13#include "base/metrics/field_trial.h"
14#include "base/metrics/histogram.h"
[email protected]1d88aea92013-02-03 08:16:2415#include "base/pending_task.h"
[email protected]6c5905b72013-04-03 19:06:5116#include "base/power_monitor/power_monitor.h"
17#include "base/system_monitor/system_monitor.h"
[email protected]8e937c1e2012-06-28 22:57:3018#include "base/run_loop.h"
[email protected]a6381cb52012-02-13 22:39:3419#include "base/string_number_conversions.h"
[email protected]b48c9182011-10-26 18:03:3020#include "base/threading/thread_restrictions.h"
[email protected]c38831a12011-10-28 12:44:4921#include "content/browser/browser_thread_impl.h"
[email protected]99907362012-01-11 05:41:4022#include "content/browser/download/save_file_manager.h"
[email protected]ac671e782012-06-05 18:48:2023#include "content/browser/gamepad/gamepad_service.h"
[email protected]5b040e592012-02-10 02:56:1024#include "content/browser/gpu/browser_gpu_channel_host_factory.h"
[email protected]7e343152012-09-20 21:49:5325#include "content/browser/gpu/gpu_data_manager_impl.h"
[email protected]99af54b2012-03-03 01:06:5026#include "content/browser/gpu/gpu_process_host.h"
[email protected]64d69de42012-02-06 00:19:5427#include "content/browser/gpu/gpu_process_host_ui_shim.h"
[email protected]c6ff6a32012-07-17 19:01:0128#include "content/browser/histogram_synchronizer.h"
[email protected]c2b77b2392011-12-02 13:00:1629#include "content/browser/in_process_webkit/webkit_thread.h"
[email protected]678c0362012-12-05 08:02:4430#include "content/browser/loader/resource_dispatcher_host_impl.h"
[email protected]bff327f2012-03-11 22:17:1931#include "content/browser/net/browser_online_state_observer.h"
[email protected]99907362012-01-11 05:41:4032#include "content/browser/plugin_service_impl.h"
[email protected]f8d17372013-01-11 09:31:4733#include "content/browser/renderer_host/media/audio_mirroring_manager.h"
[email protected]5a3097162012-07-06 12:03:0534#include "content/browser/renderer_host/media/media_stream_manager.h"
[email protected]28df14d2012-05-16 14:51:2235#include "content/browser/speech/speech_recognition_manager_impl.h"
[email protected]3a85b1f2013-02-01 04:47:4036#include "content/browser/tracing/trace_controller_impl.h"
[email protected]64ccac32013-01-29 21:40:0437#include "content/browser/webui/content_web_ui_controller_factory.h"
[email protected]33c1c26a2013-01-24 21:56:2638#include "content/browser/webui/url_data_manager.h"
[email protected]b48c9182011-10-26 18:03:3039#include "content/public/browser/browser_main_parts.h"
[email protected]2e5b60a22011-11-28 15:56:4140#include "content/public/browser/browser_shutdown.h"
[email protected]3220d1b2012-12-08 04:13:3541#include "content/public/browser/compositor_util.h"
[email protected]b48c9182011-10-26 18:03:3042#include "content/public/browser/content_browser_client.h"
[email protected]a6381cb52012-02-13 22:39:3443#include "content/public/browser/render_process_host.h"
[email protected]b48c9182011-10-26 18:03:3044#include "content/public/common/content_switches.h"
[email protected]4573fbd2011-10-31 20:25:1845#include "content/public/common/main_function_params.h"
[email protected]b48c9182011-10-26 18:03:3046#include "content/public/common/result_codes.h"
47#include "crypto/nss_util.h"
[email protected]52e456b92012-02-23 17:13:1848#include "media/audio/audio_manager.h"
[email protected]8e15369c2013-05-10 00:30:1549#include "media/base/media.h"
[email protected]b48c9182011-10-26 18:03:3050#include "net/base/network_change_notifier.h"
[email protected]b48c9182011-10-26 18:03:3051#include "net/socket/client_socket_factory.h"
[email protected]536fd0b2013-03-14 17:41:5752#include "net/ssl/ssl_config_service.h"
[email protected]2dd33552012-09-11 16:39:5553#include "ui/base/clipboard/clipboard.h"
[email protected]b48c9182011-10-26 18:03:3054
[email protected]894e8fc2012-02-24 13:29:5055#if defined(USE_AURA)
56#include "content/browser/renderer_host/image_transport_factory.h"
57#endif
58
[email protected]40bdb122012-11-10 03:02:3859#if defined(OS_ANDROID)
60#include "base/android/jni_android.h"
61#include "content/browser/android/surface_texture_peer_browser_impl.h"
62#include "content/browser/device_orientation/data_fetcher_impl_android.h"
[email protected]e9875de72013-01-24 01:55:0663// TODO(epenner): Move thread priorities to base. (crbug.com/170549)
64#include <sys/resource.h>
[email protected]40bdb122012-11-10 03:02:3865#endif
66
[email protected]b48c9182011-10-26 18:03:3067#if defined(OS_WIN)
68#include <windows.h>
69#include <commctrl.h>
[email protected]b48c9182011-10-26 18:03:3070#include <shellapi.h>
71
[email protected]cd1cd4c02011-11-15 01:59:4972#include "content/browser/system_message_window_win.h"
[email protected]34f48682013-03-20 00:30:1873#include "content/common/sandbox_win.h"
[email protected]b48c9182011-10-26 18:03:3074#include "net/base/winsock_init.h"
[email protected]536fd0b2013-03-14 17:41:5775#include "ui/base/l10n/l10n_util_win.h"
[email protected]b48c9182011-10-26 18:03:3076#endif
77
[email protected]e60c0232011-11-11 19:56:3578#if defined(OS_LINUX) || defined(OS_OPENBSD)
[email protected]b48c9182011-10-26 18:03:3079#include <glib-object.h>
80#endif
81
[email protected]97646c92012-07-31 20:30:0882#if defined(OS_LINUX)
83#include "content/browser/device_monitor_linux.h"
[email protected]a34087bd2012-10-11 17:05:3084#elif defined(OS_MACOSX) && !defined(OS_IOS)
[email protected]14625442012-08-15 12:51:4285#include "content/browser/device_monitor_mac.h"
[email protected]97646c92012-07-31 20:30:0886#endif
87
[email protected]a13283cc2012-04-05 00:21:2288#if defined(TOOLKIT_GTK)
[email protected]b48c9182011-10-26 18:03:3089#include "ui/gfx/gtk_util.h"
90#endif
91
92#if defined(OS_POSIX) && !defined(OS_MACOSX)
93#include <sys/stat.h>
[email protected]094797b72012-09-15 10:51:0594
95#include "base/process_util.h"
[email protected]b48c9182011-10-26 18:03:3096#include "content/browser/renderer_host/render_sandbox_host_linux.h"
[email protected]13d6b3c2012-07-24 01:31:3197#include "content/browser/zygote_host/zygote_host_impl_linux.h"
[email protected]b48c9182011-10-26 18:03:3098#endif
99
[email protected]462d4a32012-01-19 00:11:04100#if defined(USE_X11)
101#include <X11/Xlib.h>
102#endif
103
[email protected]64d69de42012-02-06 00:19:54104// One of the linux specific headers defines this as a macro.
105#ifdef DestroyAll
106#undef DestroyAll
107#endif
108
[email protected]130757672012-10-24 00:26:19109namespace content {
[email protected]b48c9182011-10-26 18:03:30110namespace {
111
[email protected]a08029b42012-04-25 03:18:46112#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
[email protected]b48c9182011-10-26 18:03:30113void SetupSandbox(const CommandLine& parsed_command_line) {
114 // TODO(evanm): move this into SandboxWrapper; I'm just trying to move this
115 // code en masse out of chrome_main for now.
116 const char* sandbox_binary = NULL;
117 struct stat st;
118
119 // In Chromium branded builds, developers can set an environment variable to
120 // use the development sandbox. See
121 // http://code.google.com/p/chromium/wiki/LinuxSUIDSandboxDevelopment
[email protected]094797b72012-09-15 10:51:05122 if (stat(base::kProcSelfExe, &st) == 0 && st.st_uid == getuid())
[email protected]b48c9182011-10-26 18:03:30123 sandbox_binary = getenv("CHROME_DEVEL_SANDBOX");
124
125#if defined(LINUX_SANDBOX_PATH)
126 if (!sandbox_binary)
127 sandbox_binary = LINUX_SANDBOX_PATH;
128#endif
129
130 std::string sandbox_cmd;
131 if (sandbox_binary && !parsed_command_line.HasSwitch(switches::kNoSandbox))
132 sandbox_cmd = sandbox_binary;
133
134 // Tickle the sandbox host and zygote host so they fork now.
[email protected]c2c68b1f2012-02-25 00:29:15135 RenderSandboxHostLinux::GetInstance()->Init(sandbox_cmd);
136 ZygoteHostImpl::GetInstance()->Init(sandbox_cmd);
[email protected]b48c9182011-10-26 18:03:30137}
138#endif
139
[email protected]e60c0232011-11-11 19:56:35140#if defined(OS_LINUX) || defined(OS_OPENBSD)
[email protected]b48c9182011-10-26 18:03:30141static void GLibLogHandler(const gchar* log_domain,
142 GLogLevelFlags log_level,
143 const gchar* message,
144 gpointer userdata) {
145 if (!log_domain)
146 log_domain = "<unknown>";
147 if (!message)
148 message = "<no message>";
149
150 if (strstr(message, "Loading IM context type") ||
151 strstr(message, "wrong ELF class: ELFCLASS64")) {
152 // http://crbug.com/9643
153 // Until we have a real 64-bit build or all of these 32-bit package issues
154 // are sorted out, don't fatal on ELF 32/64-bit mismatch warnings and don't
155 // spam the user with more than one of them.
156 static bool alerted = false;
157 if (!alerted) {
158 LOG(ERROR) << "Bug 9643: " << log_domain << ": " << message;
159 alerted = true;
160 }
[email protected]8a1ea192011-11-29 22:40:50161 } else if (strstr(message, "Unable to retrieve the file info for")) {
162 LOG(ERROR) << "GTK File code error: " << message;
[email protected]b48c9182011-10-26 18:03:30163 } else if (strstr(message, "Theme file for default has no") ||
164 strstr(message, "Theme directory") ||
[email protected]2bdaecf2011-12-15 02:44:55165 strstr(message, "theme pixmap") ||
166 strstr(message, "locate theme engine")) {
[email protected]b48c9182011-10-26 18:03:30167 LOG(ERROR) << "GTK theme error: " << message;
[email protected]45d8f472012-09-20 19:29:20168 } else if (strstr(message, "Unable to create Ubuntu Menu Proxy") &&
169 strstr(log_domain, "<unknown>")) {
170 LOG(ERROR) << "GTK menu proxy create failed";
[email protected]b48c9182011-10-26 18:03:30171 } else if (strstr(message, "gtk_drag_dest_leave: assertion")) {
172 LOG(ERROR) << "Drag destination deleted: http://crbug.com/18557";
173 } else if (strstr(message, "Out of memory") &&
174 strstr(log_domain, "<unknown>")) {
175 LOG(ERROR) << "DBus call timeout or out of memory: "
176 << "http://crosbug.com/15496";
[email protected]0ed43012013-03-05 04:02:29177 } else if (strstr(message, "Could not connect: Connection refused") &&
178 strstr(log_domain, "<unknown>")) {
179 LOG(ERROR) << "DConf settings backend could not connect to session bus: "
180 << "http://crbug.com/179797";
[email protected]b48c9182011-10-26 18:03:30181 } else if (strstr(message, "XDG_RUNTIME_DIR variable not set")) {
182 LOG(ERROR) << message << " (http://bugs.chromium.org/97293)";
[email protected]238d5c32012-11-20 02:27:40183 } else if (strstr(message, "Attempting to store changes into") ||
184 strstr(message, "Attempting to set the permissions of")) {
185 LOG(ERROR) << message << " (http://bugs.chromium.org/161366)";
[email protected]b48c9182011-10-26 18:03:30186 } else {
187 LOG(DFATAL) << log_domain << ": " << message;
188 }
189}
190
191static void SetUpGLibLogHandler() {
192 // Register GLib-handled assertions to go through our logging system.
193 const char* kLogDomains[] = { NULL, "Gtk", "Gdk", "GLib", "GLib-GObject" };
194 for (size_t i = 0; i < arraysize(kLogDomains); i++) {
195 g_log_set_handler(kLogDomains[i],
196 static_cast<GLogLevelFlags>(G_LOG_FLAG_RECURSION |
197 G_LOG_FLAG_FATAL |
198 G_LOG_LEVEL_ERROR |
199 G_LOG_LEVEL_CRITICAL |
200 G_LOG_LEVEL_WARNING),
201 GLibLogHandler,
202 NULL);
203 }
204}
205#endif
206
207} // namespace
208
[email protected]2e5b60a22011-11-28 15:56:41209// The currently-running BrowserMainLoop. There can be one or zero.
[email protected]52e456b92012-02-23 17:13:18210BrowserMainLoop* g_current_browser_main_loop = NULL;
[email protected]2e5b60a22011-11-28 15:56:41211
212// This is just to be able to keep ShutdownThreadsAndCleanUp out of
213// the public interface of BrowserMainLoop.
214class BrowserShutdownImpl {
215 public:
216 static void ImmediateShutdownAndExitProcess() {
[email protected]52e456b92012-02-23 17:13:18217 DCHECK(g_current_browser_main_loop);
218 g_current_browser_main_loop->ShutdownThreadsAndCleanUp();
[email protected]2e5b60a22011-11-28 15:56:41219
220#if defined(OS_WIN)
221 // At this point the message loop is still running yet we've shut everything
222 // down. If any messages are processed we'll likely crash. Exit now.
[email protected]130757672012-10-24 00:26:19223 ExitProcess(RESULT_CODE_NORMAL_EXIT);
[email protected]2e5b60a22011-11-28 15:56:41224#elif defined(OS_POSIX) && !defined(OS_MACOSX)
[email protected]130757672012-10-24 00:26:19225 _exit(RESULT_CODE_NORMAL_EXIT);
[email protected]2e5b60a22011-11-28 15:56:41226#else
227 NOTIMPLEMENTED();
228#endif
229 }
230};
231
232void ImmediateShutdownAndExitProcess() {
233 BrowserShutdownImpl::ImmediateShutdownAndExitProcess();
234}
[email protected]b48c9182011-10-26 18:03:30235
[email protected]ee57f332013-01-31 18:13:54236// For measuring memory usage after each task. Behind a command line flag.
[email protected]dd32b1272013-05-04 14:17:11237class BrowserMainLoop::MemoryObserver : public base::MessageLoop::TaskObserver {
[email protected]ee57f332013-01-31 18:13:54238 public:
239 MemoryObserver() {}
240 virtual ~MemoryObserver() {}
241
[email protected]1d88aea92013-02-03 08:16:24242 virtual void WillProcessTask(const base::PendingTask& pending_task) OVERRIDE {
243 }
[email protected]ee57f332013-01-31 18:13:54244
[email protected]1d88aea92013-02-03 08:16:24245 virtual void DidProcessTask(const base::PendingTask& pending_task) OVERRIDE {
[email protected]66ad3072013-02-25 08:53:34246#if !defined(OS_IOS) // No ProcessMetrics on IOS.
247 scoped_ptr<base::ProcessMetrics> process_metrics(
248 base::ProcessMetrics::CreateProcessMetrics(
249#if defined(OS_MACOSX)
250 base::GetCurrentProcessHandle(), NULL));
251#else
252 base::GetCurrentProcessHandle()));
253#endif
254 size_t private_bytes;
255 process_metrics->GetMemoryBytes(&private_bytes, NULL);
256 HISTOGRAM_MEMORY_KB("Memory.BrowserUsed", private_bytes >> 10);
[email protected]ee57f332013-01-31 18:13:54257#endif
258 }
259 private:
260 DISALLOW_COPY_AND_ASSIGN(MemoryObserver);
261};
262
263
[email protected]52e456b92012-02-23 17:13:18264// static
[email protected]67dfea902012-04-03 01:49:09265media::AudioManager* BrowserMainLoop::GetAudioManager() {
[email protected]52e456b92012-02-23 17:13:18266 return g_current_browser_main_loop->audio_manager_.get();
267}
268
[email protected]5a3097162012-07-06 12:03:05269// static
[email protected]f8d17372013-01-11 09:31:47270AudioMirroringManager* BrowserMainLoop::GetAudioMirroringManager() {
271 return g_current_browser_main_loop->audio_mirroring_manager_.get();
272}
273
274// static
[email protected]1d232b92012-10-29 17:39:07275MediaStreamManager* BrowserMainLoop::GetMediaStreamManager() {
[email protected]5a3097162012-07-06 12:03:05276 return g_current_browser_main_loop->media_stream_manager_.get();
277}
[email protected]e974ad292012-03-07 07:34:51278// BrowserMainLoop construction / destruction =============================
[email protected]b48c9182011-10-26 18:03:30279
[email protected]130757672012-10-24 00:26:19280BrowserMainLoop::BrowserMainLoop(const MainFunctionParams& parameters)
[email protected]b48c9182011-10-26 18:03:30281 : parameters_(parameters),
[email protected]badf5cf2011-10-29 03:44:44282 parsed_command_line_(parameters.command_line),
[email protected]130757672012-10-24 00:26:19283 result_code_(RESULT_CODE_NORMAL_EXIT) {
[email protected]52e456b92012-02-23 17:13:18284 DCHECK(!g_current_browser_main_loop);
285 g_current_browser_main_loop = this;
[email protected]b48c9182011-10-26 18:03:30286}
287
288BrowserMainLoop::~BrowserMainLoop() {
[email protected]52e456b92012-02-23 17:13:18289 DCHECK_EQ(this, g_current_browser_main_loop);
[email protected]a34087bd2012-10-11 17:05:30290#if !defined(OS_IOS)
[email protected]2dd33552012-09-11 16:39:55291 ui::Clipboard::DestroyClipboardForCurrentThread();
[email protected]a34087bd2012-10-11 17:05:30292#endif // !defined(OS_IOS)
[email protected]52e456b92012-02-23 17:13:18293 g_current_browser_main_loop = NULL;
[email protected]b48c9182011-10-26 18:03:30294}
295
296void BrowserMainLoop::Init() {
[email protected]aa328c72013-05-03 10:55:43297 TRACE_EVENT0("startup", "BrowserMainLoop::Init")
[email protected]50462bf02011-11-21 19:13:31298 parts_.reset(
299 GetContentClient()->browser()->CreateBrowserMainParts(parameters_));
[email protected]b48c9182011-10-26 18:03:30300}
301
302// BrowserMainLoop stages ==================================================
303
304void BrowserMainLoop::EarlyInitialization() {
[email protected]aa328c72013-05-03 10:55:43305 TRACE_EVENT0("startup", "BrowserMainLoop::EarlyInitialization")
[email protected]462d4a32012-01-19 00:11:04306#if defined(USE_X11)
307 if (parsed_command_line_.HasSwitch(switches::kSingleProcess) ||
308 parsed_command_line_.HasSwitch(switches::kInProcessGPU)) {
309 if (!XInitThreads()) {
310 LOG(ERROR) << "Failed to put Xlib into threaded mode.";
311 }
312 }
313#endif
314
[email protected]59383c782013-04-17 16:43:27315 if (parts_)
[email protected]50462bf02011-11-21 19:13:31316 parts_->PreEarlyInitialization();
[email protected]b48c9182011-10-26 18:03:30317
[email protected]b48c9182011-10-26 18:03:30318#if defined(OS_WIN)
319 net::EnsureWinsockInit();
320#endif
321
[email protected]1648b292011-11-03 23:57:39322#if !defined(USE_OPENSSL)
[email protected]8cbcabf2013-01-16 03:08:54323 // We want to be sure to init NSPR on the main thread.
324 crypto::EnsureNSPRInit();
[email protected]1648b292011-11-03 23:57:39325#endif // !defined(USE_OPENSSL)
[email protected]b48c9182011-10-26 18:03:30326
[email protected]a08029b42012-04-25 03:18:46327#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
[email protected]b48c9182011-10-26 18:03:30328 SetupSandbox(parsed_command_line_);
329#endif
330
[email protected]b48c9182011-10-26 18:03:30331 if (parsed_command_line_.HasSwitch(switches::kEnableSSLCachedInfo))
332 net::SSLConfigService::EnableCachedInfo();
[email protected]b48c9182011-10-26 18:03:30333
[email protected]759a86a2012-09-10 14:42:54334#if !defined(OS_IOS)
[email protected]a6381cb52012-02-13 22:39:34335 if (parsed_command_line_.HasSwitch(switches::kRendererProcessLimit)) {
336 std::string limit_string = parsed_command_line_.GetSwitchValueASCII(
337 switches::kRendererProcessLimit);
338 size_t process_limit;
339 if (base::StringToSizeT(limit_string, &process_limit)) {
[email protected]130757672012-10-24 00:26:19340 RenderProcessHost::SetMaxRendererProcessCount(process_limit);
[email protected]a6381cb52012-02-13 22:39:34341 }
342 }
[email protected]759a86a2012-09-10 14:42:54343#endif // !defined(OS_IOS)
[email protected]a6381cb52012-02-13 22:39:34344
[email protected]59383c782013-04-17 16:43:27345 if (parts_)
[email protected]50462bf02011-11-21 19:13:31346 parts_->PostEarlyInitialization();
[email protected]b48c9182011-10-26 18:03:30347}
348
349void BrowserMainLoop::MainMessageLoopStart() {
[email protected]aa328c72013-05-03 10:55:43350 TRACE_EVENT0("startup", "BrowserMainLoop::MainMessageLoopStart")
351 if (parts_) {
352 TRACE_EVENT0("startup",
353 "BrowserMainLoop::MainMessageLoopStart:PreMainMessageLoopStart");
[email protected]50462bf02011-11-21 19:13:31354 parts_->PreMainMessageLoopStart();
[email protected]aa328c72013-05-03 10:55:43355 }
[email protected]b48c9182011-10-26 18:03:30356
357#if defined(OS_WIN)
358 // If we're running tests (ui_task is non-null), then the ResourceBundle
359 // has already been initialized.
[email protected]716476c2011-12-29 00:07:03360 if (!parameters_.ui_task) {
[email protected]b48c9182011-10-26 18:03:30361 // Override the configured locale with the user's preferred UI language.
362 l10n_util::OverrideLocaleWithUILanguageList();
363 }
364#endif
365
[email protected]de88c5e2012-04-10 23:35:23366 // Create a MessageLoop if one does not already exist for the current thread.
[email protected]dd32b1272013-05-04 14:17:11367 if (!base::MessageLoop::current())
368 main_message_loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_UI));
[email protected]b48c9182011-10-26 18:03:30369
370 InitializeMainThread();
371
[email protected]759a86a2012-09-10 14:42:54372 system_monitor_.reset(new base::SystemMonitor);
[email protected]6c5905b72013-04-03 19:06:51373 power_monitor_.reset(new base::PowerMonitor);
[email protected]759a86a2012-09-10 14:42:54374 hi_res_timer_manager_.reset(new HighResolutionTimerManager);
375 network_change_notifier_.reset(net::NetworkChangeNotifier::Create());
[email protected]8e15369c2013-05-10 00:30:15376
377 media::InitializeCPUSpecificMediaFeatures();
[email protected]759a86a2012-09-10 14:42:54378 audio_manager_.reset(media::AudioManager::Create());
379
380#if !defined(OS_IOS)
[email protected]64ccac32013-01-29 21:40:04381 WebUIControllerFactory::RegisterFactory(
382 ContentWebUIControllerFactory::GetInstance());
383
384 audio_mirroring_manager_.reset(new AudioMirroringManager());
385
[email protected]50f38422011-11-09 19:21:33386 // Start tracing to a file if needed.
[email protected]900e9122012-03-13 15:43:08387 if (base::debug::TraceLog::GetInstance()->IsEnabled()) {
388 TraceControllerImpl::GetInstance()->InitStartupTracing(
389 parsed_command_line_);
390 }
[email protected]50f38422011-11-09 19:21:33391
[email protected]bff327f2012-03-11 22:17:19392 online_state_observer_.reset(new BrowserOnlineStateObserver);
[email protected]ebd71962012-12-20 02:56:55393#endif // !defined(OS_IOS)
[email protected]b48c9182011-10-26 18:03:30394
[email protected]ebd71962012-12-20 02:56:55395#if defined(ENABLE_PLUGINS)
[email protected]99907362012-01-11 05:41:40396 // Prior to any processing happening on the io thread, we create the
397 // plugin service as it is predominantly used from the io thread,
398 // but must be created on the main thread. The service ctor is
399 // inexpensive and does not invoke the io_thread() accessor.
400 PluginService::GetInstance()->Init();
[email protected]ebd71962012-12-20 02:56:55401#endif
[email protected]759a86a2012-09-10 14:42:54402
403#if defined(OS_WIN)
404 system_message_window_.reset(new SystemMessageWindowWin);
405#endif
[email protected]99907362012-01-11 05:41:40406
[email protected]59383c782013-04-17 16:43:27407 if (parts_)
[email protected]50462bf02011-11-21 19:13:31408 parts_->PostMainMessageLoopStart();
[email protected]40bdb122012-11-10 03:02:38409
410#if defined(OS_ANDROID)
[email protected]1d018072013-03-06 04:23:28411 SurfaceTexturePeer::InitInstance(new SurfaceTexturePeerBrowserImpl());
[email protected]40bdb122012-11-10 03:02:38412 DataFetcherImplAndroid::Init(base::android::AttachCurrentThread());
413#endif
[email protected]ee57f332013-01-31 18:13:54414
415 if (parsed_command_line_.HasSwitch(switches::kMemoryMetrics)) {
416 memory_observer_.reset(new MemoryObserver());
[email protected]dd32b1272013-05-04 14:17:11417 base::MessageLoop::current()->AddTaskObserver(memory_observer_.get());
[email protected]ee57f332013-01-31 18:13:54418 }
[email protected]b48c9182011-10-26 18:03:30419}
420
[email protected]f573ed6b2012-02-10 15:58:52421void BrowserMainLoop::CreateThreads() {
[email protected]aa328c72013-05-03 10:55:43422 TRACE_EVENT0("startup", "BrowserMainLoop::CreateThreads")
423
424 if (parts_) {
425 TRACE_EVENT0("startup",
426 "BrowserMainLoop::MainMessageLoopStart:PreCreateThreads");
[email protected]69479b922012-02-02 09:56:20427 result_code_ = parts_->PreCreateThreads();
[email protected]aa328c72013-05-03 10:55:43428 }
[email protected]69479b922012-02-02 09:56:20429
[email protected]dfd53652012-10-25 00:20:02430#if !defined(OS_IOS) && (!defined(GOOGLE_CHROME_BUILD) || defined(OS_ANDROID))
431 // Single-process is an unsupported and not fully tested mode, so
432 // don't enable it for official Chrome builds (except on Android).
433 if (parsed_command_line_.HasSwitch(switches::kSingleProcess))
434 RenderProcessHost::SetRunRendererInProcess(true);
435#endif
436
[email protected]69479b922012-02-02 09:56:20437 if (result_code_ > 0)
438 return;
[email protected]2e5b60a22011-11-28 15:56:41439
440 base::Thread::Options default_options;
441 base::Thread::Options io_message_loop_options;
[email protected]dd32b1272013-05-04 14:17:11442 io_message_loop_options.message_loop_type = base::MessageLoop::TYPE_IO;
[email protected]2e5b60a22011-11-28 15:56:41443 base::Thread::Options ui_message_loop_options;
[email protected]dd32b1272013-05-04 14:17:11444 ui_message_loop_options.message_loop_type = base::MessageLoop::TYPE_UI;
[email protected]2e5b60a22011-11-28 15:56:41445
446 // Start threads in the order they occur in the BrowserThread::ID
447 // enumeration, except for BrowserThread::UI which is the main
448 // thread.
449 //
450 // Must be size_t so we can increment it.
451 for (size_t thread_id = BrowserThread::UI + 1;
452 thread_id < BrowserThread::ID_COUNT;
453 ++thread_id) {
454 scoped_ptr<BrowserProcessSubThread>* thread_to_start = NULL;
455 base::Thread::Options* options = &default_options;
456
457 switch (thread_id) {
458 case BrowserThread::DB:
[email protected]aa328c72013-05-03 10:55:43459 TRACE_EVENT_BEGIN1("startup",
460 "BrowserMainLoop::CreateThreads:start",
461 "Thread", "BrowserThread::DB");
[email protected]2e5b60a22011-11-28 15:56:41462 thread_to_start = &db_thread_;
463 break;
[email protected]e1dd5622011-12-20 12:28:58464 case BrowserThread::WEBKIT_DEPRECATED:
[email protected]c2b77b2392011-12-02 13:00:16465 // Special case as WebKitThread is a separate
466 // type. |thread_to_start| is not used in this case.
[email protected]aa328c72013-05-03 10:55:43467 TRACE_EVENT_BEGIN1("startup",
468 "BrowserMainLoop::CreateThreads:start",
469 "Thread", "BrowserThread::WEBKIT_DEPRECATED");
[email protected]2e5b60a22011-11-28 15:56:41470 break;
[email protected]31dbf9d2011-12-07 01:25:30471 case BrowserThread::FILE_USER_BLOCKING:
[email protected]aa328c72013-05-03 10:55:43472 TRACE_EVENT_BEGIN1("startup",
473 "BrowserMainLoop::CreateThreads:start",
474 "Thread", "BrowserThread::FILE_USER_BLOCKING");
[email protected]31dbf9d2011-12-07 01:25:30475 thread_to_start = &file_user_blocking_thread_;
476 break;
[email protected]2e5b60a22011-11-28 15:56:41477 case BrowserThread::FILE:
[email protected]aa328c72013-05-03 10:55:43478 TRACE_EVENT_BEGIN1("startup",
479 "BrowserMainLoop::CreateThreads:start",
480 "Thread", "BrowserThread::FILE");
[email protected]2e5b60a22011-11-28 15:56:41481 thread_to_start = &file_thread_;
482#if defined(OS_WIN)
483 // On Windows, the FILE thread needs to be have a UI message loop
484 // which pumps messages in such a way that Google Update can
485 // communicate back to us.
486 options = &ui_message_loop_options;
487#else
488 options = &io_message_loop_options;
489#endif
490 break;
491 case BrowserThread::PROCESS_LAUNCHER:
[email protected]aa328c72013-05-03 10:55:43492 TRACE_EVENT_BEGIN1("startup",
493 "BrowserMainLoop::CreateThreads:start",
494 "Thread", "BrowserThread::PROCESS_LAUNCHER");
[email protected]2e5b60a22011-11-28 15:56:41495 thread_to_start = &process_launcher_thread_;
496 break;
497 case BrowserThread::CACHE:
[email protected]aa328c72013-05-03 10:55:43498 TRACE_EVENT_BEGIN1("startup",
499 "BrowserMainLoop::CreateThreads:start",
500 "Thread", "BrowserThread::CACHE");
[email protected]2e5b60a22011-11-28 15:56:41501 thread_to_start = &cache_thread_;
502 options = &io_message_loop_options;
503 break;
504 case BrowserThread::IO:
[email protected]aa328c72013-05-03 10:55:43505 TRACE_EVENT_BEGIN1("startup",
506 "BrowserMainLoop::CreateThreads:start",
507 "Thread", "BrowserThread::IO");
[email protected]2e5b60a22011-11-28 15:56:41508 thread_to_start = &io_thread_;
509 options = &io_message_loop_options;
510 break;
[email protected]2e5b60a22011-11-28 15:56:41511 case BrowserThread::UI:
512 case BrowserThread::ID_COUNT:
513 default:
514 NOTREACHED();
515 break;
516 }
517
518 BrowserThread::ID id = static_cast<BrowserThread::ID>(thread_id);
519
[email protected]e1dd5622011-12-20 12:28:58520 if (thread_id == BrowserThread::WEBKIT_DEPRECATED) {
[email protected]759a86a2012-09-10 14:42:54521#if !defined(OS_IOS)
[email protected]c2b77b2392011-12-02 13:00:16522 webkit_thread_.reset(new WebKitThread);
523 webkit_thread_->Initialize();
[email protected]759a86a2012-09-10 14:42:54524#endif
[email protected]c2b77b2392011-12-02 13:00:16525 } else if (thread_to_start) {
[email protected]2e5b60a22011-11-28 15:56:41526 (*thread_to_start).reset(new BrowserProcessSubThread(id));
527 (*thread_to_start)->StartWithOptions(*options);
[email protected]c2b77b2392011-12-02 13:00:16528 } else {
529 NOTREACHED();
[email protected]2e5b60a22011-11-28 15:56:41530 }
[email protected]aa328c72013-05-03 10:55:43531
532 TRACE_EVENT_END0("startup", "BrowserMainLoop::CreateThreads:start");
533
[email protected]2e5b60a22011-11-28 15:56:41534 }
535
[email protected]99907362012-01-11 05:41:40536 BrowserThreadsStarted();
537
[email protected]aa328c72013-05-03 10:55:43538 if (parts_) {
539 TRACE_EVENT0("startup",
540 "BrowserMainLoop::CreateThreads:PreMainMessageLoopRun");
[email protected]50462bf02011-11-21 19:13:31541 parts_->PreMainMessageLoopRun();
[email protected]aa328c72013-05-03 10:55:43542 }
[email protected]b48c9182011-10-26 18:03:30543
[email protected]b48c9182011-10-26 18:03:30544 // If the UI thread blocks, the whole UI is unresponsive.
545 // Do not allow disk IO from the UI thread.
546 base::ThreadRestrictions::SetIOAllowed(false);
[email protected]3a7b66d2012-04-26 16:34:16547 base::ThreadRestrictions::DisallowWaiting();
[email protected]f573ed6b2012-02-10 15:58:52548}
549
550void BrowserMainLoop::RunMainMessageLoopParts() {
551 TRACE_EVENT_BEGIN_ETW("BrowserMain:MESSAGE_LOOP", 0, "");
[email protected]b48c9182011-10-26 18:03:30552
[email protected]b48c9182011-10-26 18:03:30553 bool ran_main_loop = false;
[email protected]59383c782013-04-17 16:43:27554 if (parts_)
[email protected]50462bf02011-11-21 19:13:31555 ran_main_loop = parts_->MainMessageLoopRun(&result_code_);
556
[email protected]b48c9182011-10-26 18:03:30557 if (!ran_main_loop)
558 MainMessageLoopRun();
559
560 TRACE_EVENT_END_ETW("BrowserMain:MESSAGE_LOOP", 0, "");
[email protected]2e5b60a22011-11-28 15:56:41561}
562
563void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
564 // Teardown may start in PostMainMessageLoopRun, and during teardown we
565 // need to be able to perform IO.
566 base::ThreadRestrictions::SetIOAllowed(true);
567 BrowserThread::PostTask(
[email protected]8f5a7e492012-01-01 02:14:47568 BrowserThread::IO, FROM_HERE,
[email protected]71cb8aa2011-12-29 19:14:00569 base::Bind(base::IgnoreResult(&base::ThreadRestrictions::SetIOAllowed),
570 true));
[email protected]2e5b60a22011-11-28 15:56:41571
[email protected]59383c782013-04-17 16:43:27572 if (parts_)
[email protected]50462bf02011-11-21 19:13:31573 parts_->PostMainMessageLoopRun();
[email protected]2e5b60a22011-11-28 15:56:41574
[email protected]759a86a2012-09-10 14:42:54575#if !defined(OS_IOS)
[email protected]64d69de42012-02-06 00:19:54576 // Destroying the GpuProcessHostUIShims on the UI thread posts a task to
577 // delete related objects on the GPU thread. This must be done before
578 // stopping the GPU thread. The GPU thread will close IPC channels to renderer
579 // processes so this has to happen before stopping the IO thread.
580 GpuProcessHostUIShim::DestroyAll();
581
[email protected]99907362012-01-11 05:41:40582 // Cancel pending requests and prevent new requests.
[email protected]59383c782013-04-17 16:43:27583 if (resource_dispatcher_host_)
[email protected]99907362012-01-11 05:41:40584 resource_dispatcher_host_.get()->Shutdown();
585
[email protected]894e8fc2012-02-24 13:29:50586#if defined(USE_AURA)
587 ImageTransportFactory::Terminate();
588#endif
[email protected]5b040e592012-02-10 02:56:10589
[email protected]14625442012-08-15 12:51:42590 // The device monitors are using |system_monitor_| as dependency, so delete
591 // them before |system_monitor_| goes away.
592 // On Mac and windows, the monitor needs to be destroyed on the same thread
593 // as they were created. On Linux, the monitor will be deleted when IO thread
594 // goes away.
595#if defined(OS_WIN)
596 system_message_window_.reset();
597#elif defined(OS_MACOSX)
598 device_monitor_mac_.reset();
599#endif
[email protected]759a86a2012-09-10 14:42:54600#endif // !defined(OS_IOS)
[email protected]14625442012-08-15 12:51:42601
[email protected]2e5b60a22011-11-28 15:56:41602 // Must be size_t so we can subtract from it.
603 for (size_t thread_id = BrowserThread::ID_COUNT - 1;
604 thread_id >= (BrowserThread::UI + 1);
605 --thread_id) {
606 // Find the thread object we want to stop. Looping over all valid
607 // BrowserThread IDs and DCHECKing on a missing case in the switch
608 // statement helps avoid a mismatch between this code and the
609 // BrowserThread::ID enumeration.
610 //
611 // The destruction order is the reverse order of occurrence in the
612 // BrowserThread::ID list. The rationale for the order is as
613 // follows (need to be filled in a bit):
614 //
[email protected]2e5b60a22011-11-28 15:56:41615 //
616 // - The IO thread is the only user of the CACHE thread.
617 //
618 // - The PROCESS_LAUNCHER thread must be stopped after IO in case
619 // the IO thread posted a task to terminate a process on the
620 // process launcher thread.
621 //
622 // - (Not sure why FILE needs to stop before WEBKIT.)
623 //
624 // - The WEBKIT thread (which currently is the responsibility of
625 // the embedder to stop, by destroying ResourceDispatcherHost
626 // before the DB thread is stopped)
627 //
628 // - (Not sure why DB stops last.)
629 scoped_ptr<BrowserProcessSubThread>* thread_to_stop = NULL;
630 switch (thread_id) {
631 case BrowserThread::DB:
632 thread_to_stop = &db_thread_;
633 break;
[email protected]e1dd5622011-12-20 12:28:58634 case BrowserThread::WEBKIT_DEPRECATED:
[email protected]c2b77b2392011-12-02 13:00:16635 // Special case as WebKitThread is a separate
636 // type. |thread_to_stop| is not used in this case.
[email protected]99907362012-01-11 05:41:40637
638 // Need to destroy ResourceDispatcherHost before PluginService
639 // and since it caches a pointer to it.
640 resource_dispatcher_host_.reset();
[email protected]2e5b60a22011-11-28 15:56:41641 break;
[email protected]31dbf9d2011-12-07 01:25:30642 case BrowserThread::FILE_USER_BLOCKING:
643 thread_to_stop = &file_user_blocking_thread_;
644 break;
[email protected]2e5b60a22011-11-28 15:56:41645 case BrowserThread::FILE:
646 thread_to_stop = &file_thread_;
[email protected]99907362012-01-11 05:41:40647
[email protected]759a86a2012-09-10 14:42:54648#if !defined(OS_IOS)
[email protected]99907362012-01-11 05:41:40649 // Clean up state that lives on or uses the file_thread_ before
650 // it goes away.
[email protected]59383c782013-04-17 16:43:27651 if (resource_dispatcher_host_)
[email protected]99907362012-01-11 05:41:40652 resource_dispatcher_host_.get()->save_file_manager()->Shutdown();
[email protected]759a86a2012-09-10 14:42:54653#endif // !defined(OS_IOS)
[email protected]2e5b60a22011-11-28 15:56:41654 break;
655 case BrowserThread::PROCESS_LAUNCHER:
656 thread_to_stop = &process_launcher_thread_;
657 break;
658 case BrowserThread::CACHE:
659 thread_to_stop = &cache_thread_;
660 break;
661 case BrowserThread::IO:
662 thread_to_stop = &io_thread_;
663 break;
[email protected]2e5b60a22011-11-28 15:56:41664 case BrowserThread::UI:
665 case BrowserThread::ID_COUNT:
666 default:
667 NOTREACHED();
668 break;
669 }
670
671 BrowserThread::ID id = static_cast<BrowserThread::ID>(thread_id);
672
[email protected]e1dd5622011-12-20 12:28:58673 if (id == BrowserThread::WEBKIT_DEPRECATED) {
[email protected]759a86a2012-09-10 14:42:54674#if !defined(OS_IOS)
[email protected]c2b77b2392011-12-02 13:00:16675 webkit_thread_.reset();
[email protected]759a86a2012-09-10 14:42:54676#endif
[email protected]c2b77b2392011-12-02 13:00:16677 } else if (thread_to_stop) {
[email protected]2e5b60a22011-11-28 15:56:41678 thread_to_stop->reset();
[email protected]c2b77b2392011-12-02 13:00:16679 } else {
680 NOTREACHED();
681 }
[email protected]2e5b60a22011-11-28 15:56:41682 }
683
[email protected]3189013e2012-01-19 04:11:57684 // Close the blocking I/O pool after the other threads. Other threads such
685 // as the I/O thread may need to schedule work like closing files or flushing
686 // data during shutdown, so the blocking pool needs to be available. There
687 // may also be slow operations pending that will blcok shutdown, so closing
688 // it here (which will block until required operations are complete) gives
689 // more head start for those operations to finish.
690 BrowserThreadImpl::ShutdownThreadPool();
691
[email protected]a34087bd2012-10-11 17:05:30692#if !defined(OS_IOS)
[email protected]33fee2e52013-01-12 17:16:24693 // Must happen after the IO thread is shutdown since this may be accessed from
694 // it.
695 BrowserGpuChannelHostFactory::Terminate();
696
[email protected]00c0d042012-09-10 07:06:39697 // Must happen after the I/O thread is shutdown since this class lives on the
698 // I/O thread and isn't threadsafe.
699 GamepadService::GetInstance()->Terminate();
[email protected]33c1c26a2013-01-24 21:56:26700
[email protected]5bf1646f52013-01-28 03:57:02701 URLDataManager::DeleteDataSources();
[email protected]a34087bd2012-10-11 17:05:30702#endif // !defined(OS_IOS)
[email protected]00c0d042012-09-10 07:06:39703
[email protected]59383c782013-04-17 16:43:27704 if (parts_)
[email protected]2e5b60a22011-11-28 15:56:41705 parts_->PostDestroyThreads();
[email protected]b48c9182011-10-26 18:03:30706}
707
708void BrowserMainLoop::InitializeMainThread() {
709 const char* kThreadName = "CrBrowserMain";
710 base::PlatformThread::SetName(kThreadName);
[email protected]59383c782013-04-17 16:43:27711 if (main_message_loop_)
[email protected]de88c5e2012-04-10 23:35:23712 main_message_loop_->set_thread_name(kThreadName);
[email protected]b48c9182011-10-26 18:03:30713
714 // Register the main thread by instantiating it, but don't call any methods.
[email protected]dd32b1272013-05-04 14:17:11715 main_thread_.reset(
716 new BrowserThreadImpl(BrowserThread::UI, base::MessageLoop::current()));
[email protected]b48c9182011-10-26 18:03:30717}
718
[email protected]e9875de72013-01-24 01:55:06719#if defined(OS_ANDROID)
720// TODO(epenner): Move thread priorities to base. (crbug.com/170549)
721namespace {
722void SetHighThreadPriority() {
723 int nice_value = -6; // High priority.
724 setpriority(PRIO_PROCESS, base::PlatformThread::CurrentId(), nice_value);
725}
726}
727#endif
728
[email protected]99907362012-01-11 05:41:40729void BrowserMainLoop::BrowserThreadsStarted() {
[email protected]aa328c72013-05-03 10:55:43730 TRACE_EVENT0("startup", "BrowserMainLoop::BrowserThreadsStarted")
[email protected]e9875de72013-01-24 01:55:06731#if defined(OS_ANDROID)
732// TODO(epenner): Move thread priorities to base. (crbug.com/170549)
733 BrowserThread::PostTask(BrowserThread::UI,
734 FROM_HERE,
735 base::Bind(&SetHighThreadPriority));
736 BrowserThread::PostTask(BrowserThread::IO,
737 FROM_HERE,
738 base::Bind(&SetHighThreadPriority));
739#endif
740
[email protected]759a86a2012-09-10 14:42:54741#if !defined(OS_IOS)
[email protected]c6ff6a32012-07-17 19:01:01742 HistogramSynchronizer::GetInstance();
743
[email protected]130757672012-10-24 00:26:19744 BrowserGpuChannelHostFactory::Initialize();
[email protected]c6ff6a32012-07-17 19:01:01745#if defined(USE_AURA)
746 ImageTransportFactory::Initialize();
747#endif
748
[email protected]97646c92012-07-31 20:30:08749#if defined(OS_LINUX)
750 device_monitor_linux_.reset(new DeviceMonitorLinux());
[email protected]14625442012-08-15 12:51:42751#elif defined(OS_MACOSX)
752 device_monitor_mac_.reset(new DeviceMonitorMac());
[email protected]97646c92012-07-31 20:30:08753#endif
754
[email protected]aa328c72013-05-03 10:55:43755 // RDH needs the IO thread to be created
756 {
757 TRACE_EVENT0("startup",
758 "BrowserMainLoop::BrowserThreadsStarted:InitResourceDispatcherHost");
759 resource_dispatcher_host_.reset(new ResourceDispatcherHostImpl());
760 }
[email protected]b14b873b2012-05-03 03:56:09761
[email protected]89c6eaf2012-11-26 18:52:27762 // MediaStreamManager needs the IO thread to be created.
[email protected]aa328c72013-05-03 10:55:43763 {
764 TRACE_EVENT0("startup",
765 "BrowserMainLoop::BrowserThreadsStarted:InitMediaStreamManager");
766 media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get()));
767 }
[email protected]89c6eaf2012-11-26 18:52:27768
[email protected]7e343152012-09-20 21:49:53769 // Initialize the GpuDataManager before we set up the MessageLoops because
[email protected]b14b873b2012-05-03 03:56:09770 // otherwise we'll trigger the assertion about doing IO on the UI thread.
[email protected]7e343152012-09-20 21:49:53771 GpuDataManagerImpl::GetInstance()->Initialize();
[email protected]759a86a2012-09-10 14:42:54772#endif // !OS_IOS
773
774#if defined(ENABLE_INPUT_SPEECH)
[email protected]aa328c72013-05-03 10:55:43775 {
776 TRACE_EVENT0("startup",
777 "BrowserMainLoop::BrowserThreadsStarted:InitSpeechRecognition");
778 speech_recognition_manager_.reset(new SpeechRecognitionManagerImpl());
779 }
[email protected]759a86a2012-09-10 14:42:54780#endif
[email protected]2dd33552012-09-11 16:39:55781
[email protected]a34087bd2012-10-11 17:05:30782#if !defined(OS_IOS)
[email protected]2dd33552012-09-11 16:39:55783 // Alert the clipboard class to which threads are allowed to access the
784 // clipboard:
785 std::vector<base::PlatformThreadId> allowed_clipboard_threads;
786 // The current thread is the UI thread.
787 allowed_clipboard_threads.push_back(base::PlatformThread::CurrentId());
788#if defined(OS_WIN)
789 // On Windows, clipboards are also used on the File or IO threads.
790 allowed_clipboard_threads.push_back(file_thread_->thread_id());
791 allowed_clipboard_threads.push_back(io_thread_->thread_id());
792#endif
793 ui::Clipboard::SetAllowedThreads(allowed_clipboard_threads);
[email protected]3220d1b2012-12-08 04:13:35794
795 // When running the GPU thread in-process, avoid optimistically starting it
796 // since creating the GPU thread races against creation of the one-and-only
797 // ChildProcess instance which is created by the renderer thread.
[email protected]a0401382013-05-07 00:12:55798 if (GpuDataManagerImpl::GetInstance()->GpuAccessAllowed(NULL) &&
[email protected]dcc72db2013-01-02 00:44:18799 IsForceCompositingModeEnabled() &&
[email protected]3220d1b2012-12-08 04:13:35800 !parsed_command_line_.HasSwitch(switches::kDisableGpuProcessPrelaunch) &&
801 !parsed_command_line_.HasSwitch(switches::kSingleProcess) &&
802 !parsed_command_line_.HasSwitch(switches::kInProcessGPU)) {
[email protected]c76faea2013-03-26 07:42:42803 TRACE_EVENT_INSTANT0("gpu", "Post task to launch GPU process",
804 TRACE_EVENT_SCOPE_THREAD);
[email protected]3220d1b2012-12-08 04:13:35805 BrowserThread::PostTask(
806 BrowserThread::IO, FROM_HERE, base::Bind(
807 base::IgnoreResult(&GpuProcessHost::Get),
808 GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
809 CAUSE_FOR_GPU_LAUNCH_BROWSER_STARTUP));
810 }
[email protected]a34087bd2012-10-11 17:05:30811#endif // !defined(OS_IOS)
[email protected]99907362012-01-11 05:41:40812}
813
[email protected]b48c9182011-10-26 18:03:30814void BrowserMainLoop::InitializeToolkit() {
[email protected]aa328c72013-05-03 10:55:43815 TRACE_EVENT0("startup", "BrowserMainLoop::InitializeToolkit")
[email protected]b48c9182011-10-26 18:03:30816 // TODO(evan): this function is rather subtle, due to the variety
817 // of intersecting ifdefs we have. To keep it easy to follow, there
818 // are no #else branches on any #ifs.
819 // TODO(stevenjb): Move platform specific code into platform specific Parts
820 // (Need to add InitializeToolkit stage to BrowserParts).
[email protected]e60c0232011-11-11 19:56:35821#if defined(OS_LINUX) || defined(OS_OPENBSD)
[email protected]048277282013-01-24 04:39:33822 // g_type_init will be deprecated in 2.36. 2.35 is the development
823 // version for 2.36, hence do not call g_type_init starting 2.35.
824 // http://developer.gnome.org/gobject/unstable/gobject-Type-Information.html#g-type-init
825#if !GLIB_CHECK_VERSION(2, 35, 0)
[email protected]b48c9182011-10-26 18:03:30826 // Glib type system initialization. Needed at least for gconf,
827 // used in net/proxy/proxy_config_service_linux.cc. Most likely
828 // this is superfluous as gtk_init() ought to do this. It's
829 // definitely harmless, so retained as a reminder of this
830 // requirement for gconf.
831 g_type_init();
[email protected]048277282013-01-24 04:39:33832#endif
[email protected]b48c9182011-10-26 18:03:30833
[email protected]b48c9182011-10-26 18:03:30834#if !defined(USE_AURA)
[email protected]38d0b2d42012-01-18 03:37:34835 gfx::GtkInitFromCommandLine(parsed_command_line_);
[email protected]b48c9182011-10-26 18:03:30836#endif
837
838 SetUpGLibLogHandler();
839#endif
840
841#if defined(TOOLKIT_GTK)
842 // It is important for this to happen before the first run dialog, as it
843 // styles the dialog as well.
844 gfx::InitRCStyles();
845#endif
846
847#if defined(OS_WIN)
848 // Init common control sex.
849 INITCOMMONCONTROLSEX config;
850 config.dwSize = sizeof(config);
851 config.dwICC = ICC_WIN95_CLASSES;
852 if (!InitCommonControlsEx(&config))
853 LOG_GETLASTERROR(FATAL);
854#endif
855
[email protected]59383c782013-04-17 16:43:27856 if (parts_)
[email protected]50462bf02011-11-21 19:13:31857 parts_->ToolkitInitialized();
[email protected]b48c9182011-10-26 18:03:30858}
859
860void BrowserMainLoop::MainMessageLoopRun() {
[email protected]8e937c1e2012-06-28 22:57:30861#if defined(OS_ANDROID)
[email protected]a08029b42012-04-25 03:18:46862 // Android's main message loop is the Java message loop.
863 NOTREACHED();
[email protected]b48c9182011-10-26 18:03:30864#else
[email protected]dd32b1272013-05-04 14:17:11865 DCHECK_EQ(base::MessageLoop::TYPE_UI, base::MessageLoop::current()->type());
[email protected]8e937c1e2012-06-28 22:57:30866 if (parameters_.ui_task)
[email protected]dd32b1272013-05-04 14:17:11867 base::MessageLoopForUI::current()->PostTask(FROM_HERE,
868 *parameters_.ui_task);
[email protected]8e937c1e2012-06-28 22:57:30869
870 base::RunLoop run_loop;
871 run_loop.Run();
[email protected]b48c9182011-10-26 18:03:30872#endif
873}
874
875} // namespace content