Index: content/browser/browser_main.cc |
=================================================================== |
--- content/browser/browser_main.cc (revision 0) |
+++ content/browser/browser_main.cc (revision 0) |
@@ -0,0 +1,319 @@ |
+// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "content/browser/browser_main.h" |
+ |
+#include "base/allocator/allocator_shim.h" |
+#include "base/command_line.h" |
+#include "base/debug/trace_event.h" |
+#include "base/logging.h" |
+#include "base/metrics/field_trial.h" |
+#include "base/metrics/histogram.h" |
+#include "base/system_monitor/system_monitor.h" |
+#include "content/browser/browser_thread.h" |
+#include "content/browser/content_browser_client.h" |
+#include "content/common/content_switches.h" |
+#include "content/common/hi_res_timer_manager.h" |
+#include "content/common/main_function_params.h" |
+#include "content/common/sandbox_policy.h" |
+#include "net/base/network_change_notifier.h" |
+#include "net/base/ssl_config_service.h" |
+#include "net/socket/tcp_client_socket.h" |
+ |
+#if defined(OS_WIN) |
+#include <windows.h> |
+#include <commctrl.h> |
+#include <shellapi.h> |
+ |
+#include "sandbox/src/sandbox.h" |
+#endif |
+ |
+#if defined(OS_POSIX) && !defined(OS_MACOSX) |
+#include <dbus/dbus-glib.h> |
+#endif |
+ |
+#if defined(TOOLKIT_USES_GTK) |
+#include "ui/gfx/gtk_util.h" |
+#endif |
+ |
+namespace { |
+ |
+// Windows-specific initialization code for the sandbox broker services. This |
+// is just a NOP on non-Windows platforms to reduce ifdefs later on. |
+void InitializeBrokerServices(const MainFunctionParams& parameters, |
+ const CommandLine& parsed_command_line) { |
+#if defined(OS_WIN) |
+ sandbox::BrokerServices* broker_services = |
+ parameters.sandbox_info_.BrokerServices(); |
+ if (broker_services) { |
+ sandbox::InitBrokerServices(broker_services); |
+ if (!parsed_command_line.HasSwitch(switches::kNoSandbox)) { |
+ bool use_winsta = !parsed_command_line.HasSwitch( |
+ switches::kDisableAltWinstation); |
+ // Precreate the desktop and window station used by the renderers. |
+ sandbox::TargetPolicy* policy = broker_services->CreatePolicy(); |
+ sandbox::ResultCode result = policy->CreateAlternateDesktop(use_winsta); |
+ CHECK(sandbox::SBOX_ERROR_FAILED_TO_SWITCH_BACK_WINSTATION != result); |
+ policy->Release(); |
+ } |
+ } |
+#endif |
+} |
+ |
+#if defined(TOOLKIT_USES_GTK) |
+static void GLibLogHandler(const gchar* log_domain, |
+ GLogLevelFlags log_level, |
+ const gchar* message, |
+ gpointer userdata) { |
+ if (!log_domain) |
+ log_domain = "<unknown>"; |
+ if (!message) |
+ message = "<no message>"; |
+ |
+ if (strstr(message, "Loading IM context type") || |
+ strstr(message, "wrong ELF class: ELFCLASS64")) { |
+ // http://crbug.com/9643 |
+ // Until we have a real 64-bit build or all of these 32-bit package issues |
+ // are sorted out, don't fatal on ELF 32/64-bit mismatch warnings and don't |
+ // spam the user with more than one of them. |
+ static bool alerted = false; |
+ if (!alerted) { |
+ LOG(ERROR) << "Bug 9643: " << log_domain << ": " << message; |
+ alerted = true; |
+ } |
+ } else if (strstr(message, "Theme file for default has no") || |
+ strstr(message, "Theme directory") || |
+ strstr(message, "theme pixmap")) { |
+ LOG(ERROR) << "GTK theme error: " << message; |
+ } else if (strstr(message, "gtk_drag_dest_leave: assertion")) { |
+ LOG(ERROR) << "Drag destination deleted: http://crbug.com/18557"; |
+ } else if (strstr(message, "Out of memory") && |
+ strstr(log_domain, "<unknown>")) { |
+ LOG(ERROR) << "DBus call timeout or out of memory: " |
+ << "http://crosbug.com/15496"; |
+ } else { |
+ LOG(DFATAL) << log_domain << ": " << message; |
+ } |
+} |
+ |
+static void SetUpGLibLogHandler() { |
+ // Register GLib-handled assertions to go through our logging system. |
+ const char* kLogDomains[] = { NULL, "Gtk", "Gdk", "GLib", "GLib-GObject" }; |
+ for (size_t i = 0; i < arraysize(kLogDomains); i++) { |
+ g_log_set_handler(kLogDomains[i], |
+ static_cast<GLogLevelFlags>(G_LOG_FLAG_RECURSION | |
+ G_LOG_FLAG_FATAL | |
+ G_LOG_LEVEL_ERROR | |
+ G_LOG_LEVEL_CRITICAL | |
+ G_LOG_LEVEL_WARNING), |
+ GLibLogHandler, |
+ NULL); |
+ } |
+} |
+#endif |
+ |
+} // namespace |
+ |
+namespace content { |
+ |
+BrowserMainParts::BrowserMainParts(const MainFunctionParams& parameters) |
+ : parameters_(parameters), |
+ parsed_command_line_(parameters.command_line_) { |
+} |
+ |
+BrowserMainParts::~BrowserMainParts() { |
+} |
+ |
+void BrowserMainParts::EarlyInitialization() { |
+ PreEarlyInitialization(); |
+ |
+ if (parsed_command_line().HasSwitch(switches::kEnableBenchmarking)) |
+ base::FieldTrial::EnableBenchmarking(); |
+ |
+ InitializeSSL(); |
+ |
+ if (parsed_command_line().HasSwitch(switches::kDisableSSLFalseStart)) |
+ net::SSLConfigService::DisableFalseStart(); |
+ if (parsed_command_line().HasSwitch(switches::kEnableSSLCachedInfo)) |
+ net::SSLConfigService::EnableCachedInfo(); |
+ if (parsed_command_line().HasSwitch(switches::kEnableOriginBoundCerts)) |
+ net::SSLConfigService::EnableOriginBoundCerts(); |
+ if (parsed_command_line().HasSwitch( |
+ switches::kEnableDNSCertProvenanceChecking)) { |
+ net::SSLConfigService::EnableDNSCertProvenanceChecking(); |
+ } |
+ |
+ // TODO(abarth): Should this move to InitializeNetworkOptions? This doesn't |
+ // seem dependent on InitializeSSL(). |
+ if (parsed_command_line().HasSwitch(switches::kEnableTcpFastOpen)) |
+ net::set_tcp_fastopen_enabled(true); |
+ |
+ PostEarlyInitialization(); |
+} |
+ |
+void BrowserMainParts::MainMessageLoopStart() { |
+ PreMainMessageLoopStart(); |
+ |
+ main_message_loop_.reset(new MessageLoop(MessageLoop::TYPE_UI)); |
+ |
+ // TODO(viettrungluu): should these really go before setting the thread name? |
+ system_monitor_.reset(new base::SystemMonitor); |
+ hi_res_timer_manager_.reset(new HighResolutionTimerManager); |
+ |
+ InitializeMainThread(); |
+ |
+ network_change_notifier_.reset(net::NetworkChangeNotifier::Create()); |
+ |
+ PostMainMessageLoopStart(); |
+} |
+ |
+void BrowserMainParts::InitializeMainThread() { |
+ const char* kThreadName = "CrBrowserMain"; |
+ base::PlatformThread::SetName(kThreadName); |
+ main_message_loop().set_thread_name(kThreadName); |
+ |
+ // Register the main thread by instantiating it, but don't call any methods. |
+ main_thread_.reset(new BrowserThread(BrowserThread::UI, |
+ MessageLoop::current())); |
+} |
+ |
+void BrowserMainParts::InitializeToolkit() { |
+ // TODO(evan): this function is rather subtle, due to the variety |
+ // of intersecting ifdefs we have. To keep it easy to follow, there |
+ // are no #else branches on any #ifs. |
+ |
+#if defined(TOOLKIT_USES_GTK) |
+ // We want to call g_thread_init(), but in some codepaths (tests) it |
+ // is possible it has already been called. In older versions of |
+ // GTK, it is an error to call g_thread_init twice; unfortunately, |
+ // the API to tell whether it has been called already was also only |
+ // added in a newer version of GTK! Thankfully, this non-intuitive |
+ // check is actually equivalent and sufficient to work around the |
+ // error. |
+ if (!g_thread_supported()) |
+ g_thread_init(NULL); |
+ // Glib type system initialization. Needed at least for gconf, |
+ // used in net/proxy/proxy_config_service_linux.cc. Most likely |
+ // this is superfluous as gtk_init() ought to do this. It's |
+ // definitely harmless, so retained as a reminder of this |
+ // requirement for gconf. |
+ g_type_init(); |
+ // We use glib-dbus for geolocation and it's possible other libraries |
+ // (e.g. gnome-keyring) will use it, so initialize its threading here |
+ // as well. |
+ dbus_g_thread_init(); |
+ gfx::GtkInitFromCommandLine(parameters().command_line_); |
+ SetUpGLibLogHandler(); |
+#endif |
+ |
+#if defined(TOOLKIT_GTK) |
+ // It is important for this to happen before the first run dialog, as it |
+ // styles the dialog as well. |
+ gfx::InitRCStyles(); |
+#endif |
+ |
+#if defined(OS_WIN) |
+ // Init common control sex. |
+ INITCOMMONCONTROLSEX config; |
+ config.dwSize = sizeof(config); |
+ config.dwICC = ICC_WIN95_CLASSES; |
+ if (!InitCommonControlsEx(&config)) |
+ LOG_GETLASTERROR(FATAL); |
+#endif |
+ |
+ ToolkitInitialized(); |
+} |
+ |
+void BrowserMainParts::PreEarlyInitialization() { |
+} |
+ |
+void BrowserMainParts::PostEarlyInitialization() { |
+} |
+ |
+void BrowserMainParts::PreMainMessageLoopStart() { |
+} |
+ |
+void BrowserMainParts::PostMainMessageLoopStart() { |
+} |
+ |
+void BrowserMainParts::InitializeSSL() { |
+} |
+ |
+void BrowserMainParts::ToolkitInitialized() { |
+} |
+ |
+int BrowserMainParts::TemporaryContinue() { |
+ return 0; |
+} |
+ |
+} // namespace content |
+ |
+// Main routine for running as the Browser process. |
+int BrowserMain(const MainFunctionParams& parameters) { |
+ TRACE_EVENT_BEGIN_ETW("BrowserMain", 0, ""); |
+ |
+ scoped_ptr<content::BrowserMainParts> parts( |
+ content::GetContentClient()->browser()->CreateBrowserMainParts( |
+ parameters)); |
+ |
+ parts->EarlyInitialization(); |
+ |
+ // Must happen before we try to use a message loop or display any UI. |
+ parts->InitializeToolkit(); |
+ |
+ parts->MainMessageLoopStart(); |
+ |
+ // WARNING: If we get a WM_ENDSESSION, objects created on the stack here |
+ // are NOT deleted. If you need something to run during WM_ENDSESSION add it |
+ // to browser_shutdown::Shutdown or BrowserProcess::EndSession. |
+ |
+ // !!!!!!!!!! READ ME !!!!!!!!!! |
+ // I (viettrungluu) am in the process of refactoring |BrowserMain()|. If you |
+ // need to add something above this comment, read the documentation in |
+ // browser_main.h. If you need to add something below, please do the |
+ // following: |
+ // - Figure out where you should add your code. Do NOT just pick a random |
+ // location "which works". |
+ // - Document the dependencies apart from compile-time-checkable ones. What |
+ // must happen before your new code is executed? Does your new code need to |
+ // run before something else? Are there performance reasons for executing |
+ // your code at that point? |
+ // - If you need to create a (persistent) object, heap allocate it and keep a |
+ // |scoped_ptr| to it rather than allocating it on the stack. Otherwise |
+ // I'll have to convert your code when I refactor. |
+ // - Unless your new code is just a couple of lines, factor it out into a |
+ // function with a well-defined purpose. Do NOT just add it inline in |
+ // |BrowserMain()|. |
+ // Thanks! |
+ |
+ // TODO(viettrungluu): put the remainder into BrowserMainParts |
+ const CommandLine& parsed_command_line = parameters.command_line_; |
+ |
+#if defined(OS_WIN) && !defined(NO_TCMALLOC) |
+ // When linking shared libraries, NO_TCMALLOC is defined, and dynamic |
+ // allocator selection is not supported. |
+ |
+ // Make this call before going multithreaded, or spawning any subprocesses. |
+ base::allocator::SetupSubprocessAllocator(); |
+#endif // OS_WIN |
+ |
+ // The broker service initialization needs to run early because it will |
+ // initialize the sandbox broker, which requires the process to swap its |
+ // window station. During this time all the UI will be broken. This has to |
+ // run before threads and windows are created. |
+ InitializeBrokerServices(parameters, parsed_command_line); |
+ |
+ // Initialize histogram statistics gathering system. |
+ base::StatisticsRecorder statistics; |
+ |
+ // TODO(jam): bring the content parts from this chrome function here. |
+ int result_code = parts->TemporaryContinue(); |
+ |
+ // Release BrowserMainParts here, before shutting down CrosLibrary, since |
+ // some of the classes initialized there have CrosLibrary dependencies. |
+ parts.reset(NULL); |
+ |
+ TRACE_EVENT_END_ETW("BrowserMain", 0, 0); |
+ return result_code; |
+} |
Property changes on: content\browser\browser_main.cc |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |