OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2011 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.h" |
| 6 |
| 7 #include "base/allocator/allocator_shim.h" |
| 8 #include "base/command_line.h" |
| 9 #include "base/debug/trace_event.h" |
| 10 #include "base/logging.h" |
| 11 #include "base/metrics/field_trial.h" |
| 12 #include "base/metrics/histogram.h" |
| 13 #include "base/system_monitor/system_monitor.h" |
| 14 #include "content/browser/browser_thread.h" |
| 15 #include "content/browser/content_browser_client.h" |
| 16 #include "content/common/content_switches.h" |
| 17 #include "content/common/hi_res_timer_manager.h" |
| 18 #include "content/common/main_function_params.h" |
| 19 #include "content/common/sandbox_policy.h" |
| 20 #include "net/base/network_change_notifier.h" |
| 21 #include "net/base/ssl_config_service.h" |
| 22 #include "net/socket/tcp_client_socket.h" |
| 23 |
| 24 #if defined(OS_WIN) |
| 25 #include <windows.h> |
| 26 #include <commctrl.h> |
| 27 #include <shellapi.h> |
| 28 |
| 29 #include "sandbox/src/sandbox.h" |
| 30 #endif |
| 31 |
| 32 #if defined(OS_POSIX) && !defined(OS_MACOSX) |
| 33 #include <dbus/dbus-glib.h> |
| 34 #endif |
| 35 |
| 36 #if defined(TOOLKIT_USES_GTK) |
| 37 #include "ui/gfx/gtk_util.h" |
| 38 #endif |
| 39 |
| 40 namespace { |
| 41 |
| 42 // Windows-specific initialization code for the sandbox broker services. This |
| 43 // is just a NOP on non-Windows platforms to reduce ifdefs later on. |
| 44 void InitializeBrokerServices(const MainFunctionParams& parameters, |
| 45 const CommandLine& parsed_command_line) { |
| 46 #if defined(OS_WIN) |
| 47 sandbox::BrokerServices* broker_services = |
| 48 parameters.sandbox_info_.BrokerServices(); |
| 49 if (broker_services) { |
| 50 sandbox::InitBrokerServices(broker_services); |
| 51 if (!parsed_command_line.HasSwitch(switches::kNoSandbox)) { |
| 52 bool use_winsta = !parsed_command_line.HasSwitch( |
| 53 switches::kDisableAltWinstation); |
| 54 // Precreate the desktop and window station used by the renderers. |
| 55 sandbox::TargetPolicy* policy = broker_services->CreatePolicy(); |
| 56 sandbox::ResultCode result = policy->CreateAlternateDesktop(use_winsta); |
| 57 CHECK(sandbox::SBOX_ERROR_FAILED_TO_SWITCH_BACK_WINSTATION != result); |
| 58 policy->Release(); |
| 59 } |
| 60 } |
| 61 #endif |
| 62 } |
| 63 |
| 64 #if defined(TOOLKIT_USES_GTK) |
| 65 static void GLibLogHandler(const gchar* log_domain, |
| 66 GLogLevelFlags log_level, |
| 67 const gchar* message, |
| 68 gpointer userdata) { |
| 69 if (!log_domain) |
| 70 log_domain = "<unknown>"; |
| 71 if (!message) |
| 72 message = "<no message>"; |
| 73 |
| 74 if (strstr(message, "Loading IM context type") || |
| 75 strstr(message, "wrong ELF class: ELFCLASS64")) { |
| 76 // http://crbug.com/9643 |
| 77 // Until we have a real 64-bit build or all of these 32-bit package issues |
| 78 // are sorted out, don't fatal on ELF 32/64-bit mismatch warnings and don't |
| 79 // spam the user with more than one of them. |
| 80 static bool alerted = false; |
| 81 if (!alerted) { |
| 82 LOG(ERROR) << "Bug 9643: " << log_domain << ": " << message; |
| 83 alerted = true; |
| 84 } |
| 85 } else if (strstr(message, "Theme file for default has no") || |
| 86 strstr(message, "Theme directory") || |
| 87 strstr(message, "theme pixmap")) { |
| 88 LOG(ERROR) << "GTK theme error: " << message; |
| 89 } else if (strstr(message, "gtk_drag_dest_leave: assertion")) { |
| 90 LOG(ERROR) << "Drag destination deleted: http://crbug.com/18557"; |
| 91 } else if (strstr(message, "Out of memory") && |
| 92 strstr(log_domain, "<unknown>")) { |
| 93 LOG(ERROR) << "DBus call timeout or out of memory: " |
| 94 << "http://crosbug.com/15496"; |
| 95 } else { |
| 96 LOG(DFATAL) << log_domain << ": " << message; |
| 97 } |
| 98 } |
| 99 |
| 100 static void SetUpGLibLogHandler() { |
| 101 // Register GLib-handled assertions to go through our logging system. |
| 102 const char* kLogDomains[] = { NULL, "Gtk", "Gdk", "GLib", "GLib-GObject" }; |
| 103 for (size_t i = 0; i < arraysize(kLogDomains); i++) { |
| 104 g_log_set_handler(kLogDomains[i], |
| 105 static_cast<GLogLevelFlags>(G_LOG_FLAG_RECURSION | |
| 106 G_LOG_FLAG_FATAL | |
| 107 G_LOG_LEVEL_ERROR | |
| 108 G_LOG_LEVEL_CRITICAL | |
| 109 G_LOG_LEVEL_WARNING), |
| 110 GLibLogHandler, |
| 111 NULL); |
| 112 } |
| 113 } |
| 114 #endif |
| 115 |
| 116 } // namespace |
| 117 |
| 118 namespace content { |
| 119 |
| 120 BrowserMainParts::BrowserMainParts(const MainFunctionParams& parameters) |
| 121 : parameters_(parameters), |
| 122 parsed_command_line_(parameters.command_line_) { |
| 123 } |
| 124 |
| 125 BrowserMainParts::~BrowserMainParts() { |
| 126 } |
| 127 |
| 128 void BrowserMainParts::EarlyInitialization() { |
| 129 PreEarlyInitialization(); |
| 130 |
| 131 if (parsed_command_line().HasSwitch(switches::kEnableBenchmarking)) |
| 132 base::FieldTrial::EnableBenchmarking(); |
| 133 |
| 134 InitializeSSL(); |
| 135 |
| 136 if (parsed_command_line().HasSwitch(switches::kDisableSSLFalseStart)) |
| 137 net::SSLConfigService::DisableFalseStart(); |
| 138 if (parsed_command_line().HasSwitch(switches::kEnableSSLCachedInfo)) |
| 139 net::SSLConfigService::EnableCachedInfo(); |
| 140 if (parsed_command_line().HasSwitch(switches::kEnableOriginBoundCerts)) |
| 141 net::SSLConfigService::EnableOriginBoundCerts(); |
| 142 if (parsed_command_line().HasSwitch( |
| 143 switches::kEnableDNSCertProvenanceChecking)) { |
| 144 net::SSLConfigService::EnableDNSCertProvenanceChecking(); |
| 145 } |
| 146 |
| 147 // TODO(abarth): Should this move to InitializeNetworkOptions? This doesn't |
| 148 // seem dependent on InitializeSSL(). |
| 149 if (parsed_command_line().HasSwitch(switches::kEnableTcpFastOpen)) |
| 150 net::set_tcp_fastopen_enabled(true); |
| 151 |
| 152 PostEarlyInitialization(); |
| 153 } |
| 154 |
| 155 void BrowserMainParts::MainMessageLoopStart() { |
| 156 PreMainMessageLoopStart(); |
| 157 |
| 158 main_message_loop_.reset(new MessageLoop(MessageLoop::TYPE_UI)); |
| 159 |
| 160 // TODO(viettrungluu): should these really go before setting the thread name? |
| 161 system_monitor_.reset(new base::SystemMonitor); |
| 162 hi_res_timer_manager_.reset(new HighResolutionTimerManager); |
| 163 |
| 164 InitializeMainThread(); |
| 165 |
| 166 network_change_notifier_.reset(net::NetworkChangeNotifier::Create()); |
| 167 |
| 168 PostMainMessageLoopStart(); |
| 169 } |
| 170 |
| 171 void BrowserMainParts::InitializeMainThread() { |
| 172 const char* kThreadName = "CrBrowserMain"; |
| 173 base::PlatformThread::SetName(kThreadName); |
| 174 main_message_loop().set_thread_name(kThreadName); |
| 175 |
| 176 // Register the main thread by instantiating it, but don't call any methods. |
| 177 main_thread_.reset(new BrowserThread(BrowserThread::UI, |
| 178 MessageLoop::current())); |
| 179 } |
| 180 |
| 181 void BrowserMainParts::InitializeToolkit() { |
| 182 // TODO(evan): this function is rather subtle, due to the variety |
| 183 // of intersecting ifdefs we have. To keep it easy to follow, there |
| 184 // are no #else branches on any #ifs. |
| 185 |
| 186 #if defined(TOOLKIT_USES_GTK) |
| 187 // We want to call g_thread_init(), but in some codepaths (tests) it |
| 188 // is possible it has already been called. In older versions of |
| 189 // GTK, it is an error to call g_thread_init twice; unfortunately, |
| 190 // the API to tell whether it has been called already was also only |
| 191 // added in a newer version of GTK! Thankfully, this non-intuitive |
| 192 // check is actually equivalent and sufficient to work around the |
| 193 // error. |
| 194 if (!g_thread_supported()) |
| 195 g_thread_init(NULL); |
| 196 // Glib type system initialization. Needed at least for gconf, |
| 197 // used in net/proxy/proxy_config_service_linux.cc. Most likely |
| 198 // this is superfluous as gtk_init() ought to do this. It's |
| 199 // definitely harmless, so retained as a reminder of this |
| 200 // requirement for gconf. |
| 201 g_type_init(); |
| 202 // We use glib-dbus for geolocation and it's possible other libraries |
| 203 // (e.g. gnome-keyring) will use it, so initialize its threading here |
| 204 // as well. |
| 205 dbus_g_thread_init(); |
| 206 gfx::GtkInitFromCommandLine(parameters().command_line_); |
| 207 SetUpGLibLogHandler(); |
| 208 #endif |
| 209 |
| 210 #if defined(TOOLKIT_GTK) |
| 211 // It is important for this to happen before the first run dialog, as it |
| 212 // styles the dialog as well. |
| 213 gfx::InitRCStyles(); |
| 214 #endif |
| 215 |
| 216 #if defined(OS_WIN) |
| 217 // Init common control sex. |
| 218 INITCOMMONCONTROLSEX config; |
| 219 config.dwSize = sizeof(config); |
| 220 config.dwICC = ICC_WIN95_CLASSES; |
| 221 if (!InitCommonControlsEx(&config)) |
| 222 LOG_GETLASTERROR(FATAL); |
| 223 #endif |
| 224 |
| 225 ToolkitInitialized(); |
| 226 } |
| 227 |
| 228 void BrowserMainParts::PreEarlyInitialization() { |
| 229 } |
| 230 |
| 231 void BrowserMainParts::PostEarlyInitialization() { |
| 232 } |
| 233 |
| 234 void BrowserMainParts::PreMainMessageLoopStart() { |
| 235 } |
| 236 |
| 237 void BrowserMainParts::PostMainMessageLoopStart() { |
| 238 } |
| 239 |
| 240 void BrowserMainParts::InitializeSSL() { |
| 241 } |
| 242 |
| 243 void BrowserMainParts::ToolkitInitialized() { |
| 244 } |
| 245 |
| 246 int BrowserMainParts::TemporaryContinue() { |
| 247 return 0; |
| 248 } |
| 249 |
| 250 } // namespace content |
| 251 |
| 252 // Main routine for running as the Browser process. |
| 253 int BrowserMain(const MainFunctionParams& parameters) { |
| 254 TRACE_EVENT_BEGIN_ETW("BrowserMain", 0, ""); |
| 255 |
| 256 scoped_ptr<content::BrowserMainParts> parts( |
| 257 content::GetContentClient()->browser()->CreateBrowserMainParts( |
| 258 parameters)); |
| 259 |
| 260 parts->EarlyInitialization(); |
| 261 |
| 262 // Must happen before we try to use a message loop or display any UI. |
| 263 parts->InitializeToolkit(); |
| 264 |
| 265 parts->MainMessageLoopStart(); |
| 266 |
| 267 // WARNING: If we get a WM_ENDSESSION, objects created on the stack here |
| 268 // are NOT deleted. If you need something to run during WM_ENDSESSION add it |
| 269 // to browser_shutdown::Shutdown or BrowserProcess::EndSession. |
| 270 |
| 271 // !!!!!!!!!! READ ME !!!!!!!!!! |
| 272 // I (viettrungluu) am in the process of refactoring |BrowserMain()|. If you |
| 273 // need to add something above this comment, read the documentation in |
| 274 // browser_main.h. If you need to add something below, please do the |
| 275 // following: |
| 276 // - Figure out where you should add your code. Do NOT just pick a random |
| 277 // location "which works". |
| 278 // - Document the dependencies apart from compile-time-checkable ones. What |
| 279 // must happen before your new code is executed? Does your new code need to |
| 280 // run before something else? Are there performance reasons for executing |
| 281 // your code at that point? |
| 282 // - If you need to create a (persistent) object, heap allocate it and keep a |
| 283 // |scoped_ptr| to it rather than allocating it on the stack. Otherwise |
| 284 // I'll have to convert your code when I refactor. |
| 285 // - Unless your new code is just a couple of lines, factor it out into a |
| 286 // function with a well-defined purpose. Do NOT just add it inline in |
| 287 // |BrowserMain()|. |
| 288 // Thanks! |
| 289 |
| 290 // TODO(viettrungluu): put the remainder into BrowserMainParts |
| 291 const CommandLine& parsed_command_line = parameters.command_line_; |
| 292 |
| 293 #if defined(OS_WIN) && !defined(NO_TCMALLOC) |
| 294 // When linking shared libraries, NO_TCMALLOC is defined, and dynamic |
| 295 // allocator selection is not supported. |
| 296 |
| 297 // Make this call before going multithreaded, or spawning any subprocesses. |
| 298 base::allocator::SetupSubprocessAllocator(); |
| 299 #endif // OS_WIN |
| 300 |
| 301 // The broker service initialization needs to run early because it will |
| 302 // initialize the sandbox broker, which requires the process to swap its |
| 303 // window station. During this time all the UI will be broken. This has to |
| 304 // run before threads and windows are created. |
| 305 InitializeBrokerServices(parameters, parsed_command_line); |
| 306 |
| 307 // Initialize histogram statistics gathering system. |
| 308 base::StatisticsRecorder statistics; |
| 309 |
| 310 // TODO(jam): bring the content parts from this chrome function here. |
| 311 int result_code = parts->TemporaryContinue(); |
| 312 |
| 313 // Release BrowserMainParts here, before shutting down CrosLibrary, since |
| 314 // some of the classes initialized there have CrosLibrary dependencies. |
| 315 parts.reset(NULL); |
| 316 |
| 317 TRACE_EVENT_END_ETW("BrowserMain", 0, 0); |
| 318 return result_code; |
| 319 } |
OLD | NEW |