Index: content/browser/browser_main_loop.cc |
diff --git a/content/browser/browser_main.cc b/content/browser/browser_main_loop.cc |
similarity index 60% |
copy from content/browser/browser_main.cc |
copy to content/browser/browser_main_loop.cc |
index c0ef41ef31fe63f1c4e0bdaf71513f2b50626d9a..944d40c7e34f010b711dc38cc96fe6abcb2b953d 100644 |
--- a/content/browser/browser_main.cc |
+++ b/content/browser/browser_main_loop.cc |
@@ -2,22 +2,21 @@ |
// 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 "content/browser/browser_main_loop.h" |
-#include "base/allocator/allocator_shim.h" |
#include "base/command_line.h" |
#include "base/debug/trace_event.h" |
#include "base/logging.h" |
+#include "base/message_loop.h" |
#include "base/metrics/field_trial.h" |
#include "base/metrics/histogram.h" |
-#include "base/system_monitor/system_monitor.h" |
#include "base/threading/thread_restrictions.h" |
#include "base/tracked_objects.h" |
#include "content/browser/browser_thread.h" |
-#include "content/browser/notification_service_impl.h" |
#include "content/common/hi_res_timer_manager.h" |
#include "content/common/main_function_params.h" |
#include "content/common/sandbox_policy.h" |
+#include "content/public/browser/browser_main_parts.h" |
#include "content/public/browser/content_browser_client.h" |
#include "content/public/common/content_switches.h" |
#include "content/public/common/result_codes.h" |
@@ -33,10 +32,8 @@ |
#include <ole2.h> |
#include <shellapi.h> |
-#include "base/win/scoped_com_initializer.h" |
-#include "net/base/winsock_init.h" |
-#include "sandbox/src/sandbox.h" |
#include "ui/base/l10n/l10n_util_win.h" |
+#include "net/base/winsock_init.h" |
#endif |
#if defined(OS_LINUX) |
@@ -47,39 +44,19 @@ |
#include <dbus/dbus-glib.h> |
#endif |
+#if defined(TOOLKIT_USES_GTK) |
+#include "ui/gfx/gtk_util.h" |
+#endif |
+ |
#if defined(OS_POSIX) && !defined(OS_MACOSX) |
#include <sys/stat.h> |
- |
#include "content/browser/renderer_host/render_sandbox_host_linux.h" |
#include "content/browser/zygote_host_linux.h" |
#endif |
-#if defined(TOOLKIT_USES_GTK) |
-#include "ui/gfx/gtk_util.h" |
-#endif |
- |
namespace { |
-#if defined(OS_WIN) |
-// Windows-specific initialization code for the sandbox broker services. |
-void InitializeBrokerServices(const MainFunctionParams& parameters, |
- const CommandLine& parsed_command_line) { |
- 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(); |
- } |
- } |
-} |
-#elif defined(OS_POSIX) && !defined(OS_MACOSX) |
+#if defined(OS_POSIX) && !defined(OS_MACOSX) |
void SetupSandbox(const CommandLine& parsed_command_line) { |
// TODO(evanm): move this into SandboxWrapper; I'm just trying to move this |
// code en masse out of chrome_main for now. |
@@ -167,7 +144,10 @@ static void SetUpGLibLogHandler() { |
namespace content { |
-BrowserMainParts::BrowserMainParts(const MainFunctionParams& parameters) |
+ |
+// BrowserMainLoop construction / destructione ============================= |
+ |
+BrowserMainLoop::BrowserMainLoop(const MainFunctionParams& parameters) |
: parameters_(parameters), |
parsed_command_line_(parameters.command_line_), |
result_code_(content::RESULT_CODE_NORMAL_EXIT) { |
@@ -176,14 +156,29 @@ BrowserMainParts::BrowserMainParts(const MainFunctionParams& parameters) |
#endif |
} |
-BrowserMainParts::~BrowserMainParts() { |
+BrowserMainLoop::~BrowserMainLoop() { |
+ // Destroy added parts in reverse order. |
+ for (int i = static_cast<int>(parts_list_.size())-1; i >= 0; --i) |
+ delete parts_list_[i]; |
+ parts_list_.clear(); |
+ |
#if defined(OS_WIN) |
OleUninitialize(); |
#endif |
} |
-void BrowserMainParts::EarlyInitialization() { |
- PreEarlyInitialization(); |
+void BrowserMainLoop::Init() { |
+ GetContentClient()->browser()->CreateBrowserMainParts( |
+ parameters_, &parts_list_); |
+} |
+ |
+// BrowserMainLoop stages ================================================== |
+ |
+void BrowserMainLoop::EarlyInitialization() { |
+ for (size_t i = 0; i < parts_list_.size(); ++i) |
+ parts_list_[i]->PreEarlyInitialization(); |
+ |
+ // Start watching for jank during shutdown. It gets disarmed when |
#if defined(OS_WIN) |
net::EnsureWinsockInit(); |
@@ -192,49 +187,53 @@ void BrowserMainParts::EarlyInitialization() { |
// Use NSS for SSL by default. |
// The default client socket factory uses NSS for SSL by default on |
// Windows and Mac. |
+ bool init_nspr = false; |
#if defined(OS_WIN) || defined(OS_MACOSX) |
- if (parsed_command_line().HasSwitch(switches::kUseSystemSSL)) { |
+ if (parsed_command_line_.HasSwitch(switches::kUseSystemSSL)) { |
net::ClientSocketFactory::UseSystemSSL(); |
} else { |
+ init_nspr = true; |
+ } |
#elif defined(USE_NSS) |
- if (true) { |
-#else |
- if (false) { |
+ init_nspr = true; |
#endif |
+ if (init_nspr) { |
// We want to be sure to init NSPR on the main thread. |
crypto::EnsureNSPRInit(); |
} |
#if defined(OS_POSIX) && !defined(OS_MACOSX) |
- SetupSandbox(parsed_command_line()); |
+ SetupSandbox(parsed_command_line_); |
#endif |
- if (parsed_command_line().HasSwitch(switches::kDisableSSLFalseStart)) |
+ if (parsed_command_line_.HasSwitch(switches::kDisableSSLFalseStart)) |
net::SSLConfigService::DisableFalseStart(); |
- if (parsed_command_line().HasSwitch(switches::kEnableSSLCachedInfo)) |
+ if (parsed_command_line_.HasSwitch(switches::kEnableSSLCachedInfo)) |
net::SSLConfigService::EnableCachedInfo(); |
- if (parsed_command_line().HasSwitch(switches::kEnableOriginBoundCerts)) |
+ if (parsed_command_line_.HasSwitch(switches::kEnableOriginBoundCerts)) |
net::SSLConfigService::EnableOriginBoundCerts(); |
- if (parsed_command_line().HasSwitch( |
+ if (parsed_command_line_.HasSwitch( |
switches::kEnableDNSCertProvenanceChecking)) { |
net::SSLConfigService::EnableDNSCertProvenanceChecking(); |
} |
// TODO(abarth): Should this move to InitializeNetworkOptions? This doesn't |
// seem dependent on SSL initialization(). |
- if (parsed_command_line().HasSwitch(switches::kEnableTcpFastOpen)) |
+ if (parsed_command_line_.HasSwitch(switches::kEnableTcpFastOpen)) |
net::set_tcp_fastopen_enabled(true); |
- PostEarlyInitialization(); |
+ for (size_t i = 0; i < parts_list_.size(); ++i) |
+ parts_list_[i]->PostEarlyInitialization(); |
} |
-void BrowserMainParts::MainMessageLoopStart() { |
- PreMainMessageLoopStart(); |
+void BrowserMainLoop::MainMessageLoopStart() { |
+ for (size_t i = 0; i < parts_list_.size(); ++i) |
+ parts_list_[i]->PreMainMessageLoopStart(); |
#if defined(OS_WIN) |
// If we're running tests (ui_task is non-null), then the ResourceBundle |
// has already been initialized. |
- if (!parameters().ui_task) { |
+ if (!parameters_.ui_task) { |
// Override the configured locale with the user's preferred UI language. |
l10n_util::OverrideLocaleWithUILanguageList(); |
} |
@@ -249,30 +248,47 @@ void BrowserMainParts::MainMessageLoopStart() { |
network_change_notifier_.reset(net::NetworkChangeNotifier::Create()); |
- PostMainMessageLoopStart(); |
+ for (size_t i = 0; i < parts_list_.size(); ++i) |
+ parts_list_[i]->PostMainMessageLoopStart(); |
} |
-static bool g_exited_main_message_loop = false; |
- |
-void BrowserMainParts::RunMainMessageLoopParts() { |
- PreMainMessageLoopRun(); |
+void BrowserMainLoop::RunMainMessageLoopParts( |
+ bool* completed_main_message_loop) { |
+ for (size_t i = 0; i < parts_list_.size(); ++i) |
+ parts_list_[i]->PreMainMessageLoopRun(); |
TRACE_EVENT_BEGIN_ETW("BrowserMain:MESSAGE_LOOP", 0, ""); |
// If the UI thread blocks, the whole UI is unresponsive. |
// Do not allow disk IO from the UI thread. |
base::ThreadRestrictions::SetIOAllowed(false); |
- MainMessageLoopRun(); |
+ |
+ // Iterate through each of the parts. If any of them ran the main |
+ // message loop then they should return |true|. Otherwise |
+ // BrowserMainLoop::MainMessageLoopRun loop will be run. |
+ bool ran_main_loop = false; |
+ for (size_t i = 0; i < parts_list_.size(); ++i) { |
+ int result_code = result_code_; |
+ if (parts_list_[i]->MainMessageLoopRun(&result_code)) { |
+ ran_main_loop = true; |
+ result_code_ = result_code; |
+ } |
+ } |
+ if (!ran_main_loop) |
+ MainMessageLoopRun(); |
+ |
TRACE_EVENT_END_ETW("BrowserMain:MESSAGE_LOOP", 0, ""); |
- g_exited_main_message_loop = true; |
+ if (completed_main_message_loop) |
+ *completed_main_message_loop = true; |
- PostMainMessageLoopRun(); |
+ for (size_t i = 0; i < parts_list_.size(); ++i) |
+ parts_list_[i]->PostMainMessageLoopRun(); |
} |
-void BrowserMainParts::InitializeMainThread() { |
+void BrowserMainLoop::InitializeMainThread() { |
const char* kThreadName = "CrBrowserMain"; |
base::PlatformThread::SetName(kThreadName); |
- main_message_loop().set_thread_name(kThreadName); |
+ main_message_loop_->set_thread_name(kThreadName); |
#if defined(TRACK_ALL_TASK_OBJECTS) |
tracked_objects::ThreadData::InitializeThreadContext(kThreadName); |
@@ -283,11 +299,12 @@ void BrowserMainParts::InitializeMainThread() { |
MessageLoop::current())); |
} |
-void BrowserMainParts::InitializeToolkit() { |
+void BrowserMainLoop::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. |
- |
+ // TODO(stevenjb): Move platform specific code into platform specific Parts |
+ // (Need to add InitializeToolkit stage to BrowserParts). |
#if defined(OS_LINUX) |
// We want to call g_thread_init(), but in some codepaths (tests) it |
// is possible it has already been called. In older versions of |
@@ -304,14 +321,17 @@ void BrowserMainParts::InitializeToolkit() { |
// definitely harmless, so retained as a reminder of this |
// requirement for gconf. |
g_type_init(); |
+ |
#if defined(OS_CHROMEOS) |
// ChromeOS still uses dbus-glib, so initialize its threading here. |
// TODO(satorux, stevenjb): remove this once it is no longer needed. |
dbus_g_thread_init(); |
#endif |
+ |
#if !defined(USE_AURA) |
- gfx::GtkInitFromCommandLine(parameters().command_line_); |
+ gfx::GtkInitFromCommandLine(parameters_.command_line_); |
#endif |
+ |
SetUpGLibLogHandler(); |
#endif |
@@ -330,27 +350,13 @@ void BrowserMainParts::InitializeToolkit() { |
LOG_GETLASTERROR(FATAL); |
#endif |
- ToolkitInitialized(); |
+ for (size_t i = 0; i < parts_list_.size(); ++i) |
+ parts_list_[i]->ToolkitInitialized(); |
} |
-void BrowserMainParts::PreEarlyInitialization() { |
-} |
- |
-void BrowserMainParts::PostEarlyInitialization() { |
-} |
- |
-void BrowserMainParts::PreMainMessageLoopStart() { |
-} |
- |
-void BrowserMainParts::PostMainMessageLoopStart() { |
-} |
- |
-void BrowserMainParts::PreMainMessageLoopRun() { |
-} |
- |
-void BrowserMainParts::MainMessageLoopRun() { |
- if (parameters().ui_task) |
- MessageLoopForUI::current()->PostTask(FROM_HERE, parameters().ui_task); |
+void BrowserMainLoop::MainMessageLoopRun() { |
+ if (parameters_.ui_task) |
+ MessageLoopForUI::current()->PostTask(FROM_HERE, parameters_.ui_task); |
#if defined(OS_MACOSX) |
MessageLoopForUI::current()->Run(); |
@@ -359,83 +365,4 @@ void BrowserMainParts::MainMessageLoopRun() { |
#endif |
} |
-void BrowserMainParts::PostMainMessageLoopRun() { |
-} |
- |
-void BrowserMainParts::ToolkitInitialized() { |
-} |
- |
-bool ExitedMainMessageLoop() { |
- return g_exited_main_message_loop; |
-} |
- |
} // namespace content |
- |
-// Main routine for running as the Browser process. |
-int BrowserMain(const MainFunctionParams& parameters) { |
- TRACE_EVENT_BEGIN_ETW("BrowserMain", 0, ""); |
- |
- NotificationServiceImpl main_notification_service; |
- |
- scoped_ptr<content::BrowserMainParts> parts( |
- content::GetContentClient()->browser()->CreateBrowserMainParts( |
- parameters)); |
- if (!parts.get()) |
- parts.reset(new content::BrowserMainParts(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 |
- |
-#if defined(OS_WIN) |
-#if !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 |
- // 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, parameters.command_line_); |
- |
- base::win::ScopedCOMInitializer com_initializer; |
-#endif // OS_WIN |
- |
- base::StatisticsRecorder statistics; |
- |
- parts->RunMainMessageLoopParts(); |
- |
- TRACE_EVENT_END_ETW("BrowserMain", 0, 0); |
- return parts->result_code(); |
-} |