Chromium Code Reviews| Index: content/browser/browser_main_loop.cc |
| diff --git a/content/browser/browser_main.cc b/content/browser/browser_main_loop.cc |
| similarity index 59% |
| copy from content/browser/browser_main.cc |
| copy to content/browser/browser_main_loop.cc |
| index c9432ae45d93514519ff8276c5ceaddd40b454b2..70ffb443b6e2e8b38cbff95d8c24257bbe6fc8b7 100644 |
| --- a/content/browser/browser_main.cc |
| +++ b/content/browser/browser_main_loop.cc |
| @@ -2,27 +2,22 @@ |
| // 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/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/result_codes.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_client.h" |
|
jam
2011/10/25 06:11:28
nit: by convention we don't include this when incl
stevenjb
2011/10/25 19:21:18
Done.
|
| #include "content/public/common/content_switches.h" |
| #include "crypto/nss_util.h" |
| -#include "net/base/network_change_notifier.h" |
| #include "net/base/ssl_config_service.h" |
| #include "net/socket/client_socket_factory.h" |
| #include "net/socket/tcp_client_socket.h" |
| @@ -33,10 +28,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 +40,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 +140,50 @@ static void SetUpGLibLogHandler() { |
| namespace content { |
| -BrowserMainParts::BrowserMainParts(const MainFunctionParams& parameters) |
| +class BrowserMainLoopImpl : public BrowserMainLoop { |
| + public: |
| + explicit BrowserMainLoopImpl(const MainFunctionParams& parameters); |
| + virtual ~BrowserMainLoopImpl(); |
| + |
| + void Init(); |
| + |
| + // BrowserMainLoop implementation |
| + virtual void EarlyInitialization() OVERRIDE; |
| + virtual void InitializeToolkit() OVERRIDE; |
| + virtual void MainMessageLoopStart() OVERRIDE; |
| + virtual void RunMainMessageLoopParts( |
| + bool* completed_main_message_loop) OVERRIDE; |
| + virtual void MainMessageLoopRun() OVERRIDE; |
| + |
| + virtual int GetResultCode() const OVERRIDE { return result_code_; } |
| + |
| + private: |
| + void InitializeMainThread(); |
| + |
| + // Members initialized on construction --------------------------------------- |
| + |
| + const MainFunctionParams& parameters_; |
| + const CommandLine& parsed_command_line_; |
| + int result_code_; |
| + |
| + // Vector of BrowserMainParts set by CreateBrowserMainParts ------------------ |
| + // The BrowserParts fucntions for each part are called in the order added. |
| + // They are released (destroyed) in the reverse order. |
| + std::vector<BrowserMainParts*> parts_; |
| + |
| + // Members initialized in |MainMessageLoopStart()| --------------------------- |
| + scoped_ptr<MessageLoop> main_message_loop_; |
| + scoped_ptr<base::SystemMonitor> system_monitor_; |
| + scoped_ptr<HighResolutionTimerManager> hi_res_timer_manager_; |
| + scoped_ptr<net::NetworkChangeNotifier> network_change_notifier_; |
| + scoped_ptr<BrowserThread> main_thread_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(BrowserMainLoopImpl); |
| +}; |
| + |
| +// BrowserMainLoopImpl construction / destructione ============================= |
| + |
| +BrowserMainLoopImpl::BrowserMainLoopImpl(const MainFunctionParams& parameters) |
| : parameters_(parameters), |
| parsed_command_line_(parameters.command_line_), |
| result_code_(content::RESULT_CODE_NORMAL_EXIT) { |
| @@ -176,14 +192,29 @@ BrowserMainParts::BrowserMainParts(const MainFunctionParams& parameters) |
| #endif |
| } |
| -BrowserMainParts::~BrowserMainParts() { |
| +BrowserMainLoopImpl::~BrowserMainLoopImpl() { |
| + // Destroy added parts in reverse order. |
| + for (size_t i = parts_.size()-1; i >= 0; --i) |
| + delete parts_[i]; |
| + parts_.clear(); |
| + |
| #if defined(OS_WIN) |
| OleUninitialize(); |
| #endif |
| } |
| -void BrowserMainParts::EarlyInitialization() { |
| - PreEarlyInitialization(); |
| +void BrowserMainLoopImpl::Init() { |
| + GetContentClient()->browser()->CreateBrowserMainParts( |
| + parameters_, parts_); |
| +} |
| + |
| +// BrowserMainLoopImpl stages ================================================== |
| + |
| +void BrowserMainLoopImpl::EarlyInitialization() { |
| + for (size_t i = 0; i < parts_.size(); ++i) |
| + parts_[i]->PreEarlyInitialization(); |
| + |
| + // Start watching for jank during shutdown. It gets disarmed when |
| #if defined(OS_WIN) |
| net::EnsureWinsockInit(); |
| @@ -192,49 +223,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_.size(); ++i) |
| + parts_[i]->PostEarlyInitialization(); |
| } |
| -void BrowserMainParts::MainMessageLoopStart() { |
| - PreMainMessageLoopStart(); |
| +void BrowserMainLoopImpl::MainMessageLoopStart() { |
| + for (size_t i = 0; i < parts_.size(); ++i) |
| + parts_[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 +284,47 @@ void BrowserMainParts::MainMessageLoopStart() { |
| network_change_notifier_.reset(net::NetworkChangeNotifier::Create()); |
| - PostMainMessageLoopStart(); |
| + for (size_t i = 0; i < parts_.size(); ++i) |
| + parts_[i]->PostMainMessageLoopStart(); |
| } |
| -static bool g_exited_main_message_loop = false; |
| - |
| -void BrowserMainParts::RunMainMessageLoopParts() { |
| - PreMainMessageLoopRun(); |
| +void BrowserMainLoopImpl::RunMainMessageLoopParts( |
| + bool* completed_main_message_loop) { |
| + for (size_t i = 0; i < parts_.size(); ++i) |
| + parts_[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 |
| + // BrowserMainLoopImpl::MainMessageLoopRun loop will be run. |
| + bool ran_main_loop = false; |
| + for (size_t i = 0; i < parts_.size(); ++i) { |
| + int result_code = result_code_; |
| + if (parts_[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_.size(); ++i) |
| + parts_[i]->PostMainMessageLoopRun(); |
| } |
| -void BrowserMainParts::InitializeMainThread() { |
| +void BrowserMainLoopImpl::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 +335,12 @@ void BrowserMainParts::InitializeMainThread() { |
| MessageLoop::current())); |
| } |
| -void BrowserMainParts::InitializeToolkit() { |
| +void BrowserMainLoopImpl::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 +357,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 +386,13 @@ void BrowserMainParts::InitializeToolkit() { |
| LOG_GETLASTERROR(FATAL); |
| #endif |
| - ToolkitInitialized(); |
| -} |
| - |
| -void BrowserMainParts::PreEarlyInitialization() { |
| -} |
| - |
| -void BrowserMainParts::PostEarlyInitialization() { |
| -} |
| - |
| -void BrowserMainParts::PreMainMessageLoopStart() { |
| + for (size_t i = 0; i < parts_.size(); ++i) |
| + parts_[i]->ToolkitInitialized(); |
| } |
| -void BrowserMainParts::PostMainMessageLoopStart() { |
| -} |
| - |
| -void BrowserMainParts::PreMainMessageLoopRun() { |
| -} |
| - |
| -void BrowserMainParts::MainMessageLoopRun() { |
| - if (parameters().ui_task) |
| - MessageLoopForUI::current()->PostTask(FROM_HERE, parameters().ui_task); |
| +void BrowserMainLoopImpl::MainMessageLoopRun() { |
| + if (parameters_.ui_task) |
| + MessageLoopForUI::current()->PostTask(FROM_HERE, parameters_.ui_task); |
| #if defined(OS_MACOSX) |
| MessageLoopForUI::current()->Run(); |
| @@ -359,83 +401,14 @@ void BrowserMainParts::MainMessageLoopRun() { |
| #endif |
| } |
| -void BrowserMainParts::PostMainMessageLoopRun() { |
| -} |
| - |
| -void BrowserMainParts::ToolkitInitialized() { |
| -} |
| +// BrowserMainLoop |
| -bool ExitedMainMessageLoop() { |
| - return g_exited_main_message_loop; |
| +// static |
| +BrowserMainLoop* BrowserMainLoop::CreateInstance( |
| + const MainFunctionParams& parameters) { |
| + BrowserMainLoopImpl* instance = new BrowserMainLoopImpl(parameters); |
| + instance->Init(); |
| + return instance; |
| } |
| } // 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(); |
| -} |