diff options
author | viettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-27 13:55:21 +0000 |
---|---|---|
committer | viettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-27 13:55:21 +0000 |
commit | 1fec6435d5d98e899515a394b087236b729235f2 (patch) | |
tree | 911897d941ec4fd15a094c02e83fe38747387146 /chrome/browser | |
parent | 05b0054aa9d9d48f5a7ded8d8488088e441c6fba (diff) | |
download | chromium_src-1fec6435d5d98e899515a394b087236b729235f2.zip chromium_src-1fec6435d5d98e899515a394b087236b729235f2.tar.gz chromium_src-1fec6435d5d98e899515a394b087236b729235f2.tar.bz2 |
BrowserMain() refactoring, part 2.
Add "MainMessageLoopStart()" and related platform methods to handle tasks
directly tied to the start of the main message loop.
BUG=none
TEST=everything still works
Review URL: http://codereview.chromium.org/2931007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@53783 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/browser_main.cc | 69 | ||||
-rw-r--r-- | chrome/browser/browser_main.h | 44 | ||||
-rw-r--r-- | chrome/browser/browser_main_gtk.cc | 3 | ||||
-rw-r--r-- | chrome/browser/browser_main_mac.mm | 116 | ||||
-rw-r--r-- | chrome/browser/browser_main_posix.cc | 123 | ||||
-rw-r--r-- | chrome/browser/browser_main_posix.h | 20 | ||||
-rw-r--r-- | chrome/browser/browser_main_win.cc | 10 |
7 files changed, 224 insertions, 161 deletions
diff --git a/chrome/browser/browser_main.cc b/chrome/browser/browser_main.cc index 746df9f..aaeeb08 100644 --- a/chrome/browser/browser_main.cc +++ b/chrome/browser/browser_main.cc @@ -158,7 +158,10 @@ BrowserMainParts::BrowserMainParts(const MainFunctionParams& parameters) parsed_command_line_(parameters.command_line_) { } -// BrowserMainParts: EarlyInitialization() and related ------------------------- +BrowserMainParts::~BrowserMainParts() { +} + +// BrowserMainParts: |EarlyInitialization()| and related ----------------------- void BrowserMainParts::EarlyInitialization() { PreEarlyInitialization(); @@ -317,6 +320,33 @@ void BrowserMainParts::InitializeSSL() { #endif } +// BrowserMainParts: |MainMessageLoopStart()| and related ---------------------- + +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 SystemMonitor); + hi_res_timer_manager_.reset(new HighResolutionTimerManager); + network_change_notifier_.reset(net::NetworkChangeNotifier::Create()); + + InitializeMainThread(); + + PostMainMessageLoopStart(); +} + +void BrowserMainParts::InitializeMainThread() { + const char* kThreadName = "CrBrowserMain"; + 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 ChromeThread(ChromeThread::UI, + MessageLoop::current())); +} + // ----------------------------------------------------------------------------- // TODO(viettrungluu): move more/rest of BrowserMain() into above structure @@ -680,39 +710,18 @@ int BrowserMain(const MainFunctionParams& parameters) { parts(BrowserMainParts::CreateBrowserMainParts(parameters)); parts->EarlyInitialization(); + parts->MainMessageLoopStart(); - // TODO(viettrungluu): put the remainder into BrowserMainParts - const CommandLine& parsed_command_line = parameters.command_line_; - base::ScopedNSAutoreleasePool* pool = parameters.autorelease_pool_; - - // WARNING: If we get a WM_ENDSESSION objects created on the stack here + // 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. // TODO(beng, brettw): someday, break this out into sub functions with well // defined roles (e.g. pre/post-profile startup, etc). - // Do platform-specific things (such as finishing initializing Cocoa) - // prior to instantiating the message loop. This could be turned into a - // broadcast notification. - WillInitializeMainMessageLoop(parameters); - - MessageLoop main_message_loop(MessageLoop::TYPE_UI); - - SystemMonitor system_monitor; - HighResolutionTimerManager hi_res_timer_manager; - scoped_ptr<net::NetworkChangeNotifier> network_change_notifier( - net::NetworkChangeNotifier::Create()); - - const char* kThreadName = "CrBrowserMain"; - PlatformThread::SetName(kThreadName); - main_message_loop.set_thread_name(kThreadName); - - // Register the main thread by instantiating it, but don't call any methods. - ChromeThread main_thread(ChromeThread::UI, MessageLoop::current()); - - // TODO(viettrungluu): temporary while I refactor BrowserMain() - parts->TemporaryPosix_1(); + // TODO(viettrungluu): put the remainder into BrowserMainParts + const CommandLine& parsed_command_line = parameters.command_line_; + base::ScopedNSAutoreleasePool* pool = parameters.autorelease_pool_; FilePath user_data_dir; #if defined(OS_WIN) @@ -776,9 +785,9 @@ int BrowserMain(const MainFunctionParams& parameters) { if (parameters.ui_task) { g_browser_process->SetApplicationLocale("en-US"); } else { - // Mac starts it earlier in WillInitializeMainMessageLoop (because - // it is needed when loading the MainMenu.nib and the language doesn't - // depend on anything since it comes from Cocoa. + // Mac starts it earlier in |PreMainMessageLoopStart()| (because it is + // needed when loading the MainMenu.nib and the language doesn't depend on + // anything since it comes from Cocoa. #if defined(OS_MACOSX) g_browser_process->SetApplicationLocale(l10n_util::GetLocaleOverride()); #else diff --git a/chrome/browser/browser_main.h b/chrome/browser/browser_main.h index 268c4b6..c7e8925 100644 --- a/chrome/browser/browser_main.h +++ b/chrome/browser/browser_main.h @@ -8,11 +8,20 @@ #include "base/basictypes.h" #include "base/field_trial.h" +#include "base/scoped_ptr.h" #include "base/tracked_objects.h" +class ChromeThread; class CommandLine; +class HighResolutionTimerManager; struct MainFunctionParams; +class MessageLoop; class MetricsService; +class SystemMonitor; + +namespace net { +class NetworkChangeNotifier; +} // BrowserMainParts: // This class contains different "stages" to be executed in |BrowserMain()|, @@ -34,6 +43,10 @@ class MetricsService; // - EarlyInitialization: things which should be done as soon as possible on // program start (such as setting up signal handlers) and things to be done // at some generic time before the start of the main message loop. +// - MainMessageLoopStart: things beginning with the start of the main message +// loop and ending with initialization of the main thread; platform-specific +// things which should be done immediately before the start of the main +// message loop should go in |PreMainMessageLoopStart()|. // - (more to come) class BrowserMainParts { public: @@ -42,14 +55,11 @@ class BrowserMainParts { static BrowserMainParts* CreateBrowserMainParts( const MainFunctionParams& parameters); + virtual ~BrowserMainParts(); + // Parts to be called by |BrowserMain()|. void EarlyInitialization(); - - // TODO(viettrungluu): This currently contains (POSIX) initialization done - // later than "EarlyInitialization()" but dependent on it. Once the - // refactoring includes that later stage, this should be put in some more - // generic platform-dependent method. - virtual void TemporaryPosix_1() {} + void MainMessageLoopStart(); protected: explicit BrowserMainParts(const MainFunctionParams& parameters); @@ -61,13 +71,18 @@ class BrowserMainParts { const CommandLine& parsed_command_line() const { return parsed_command_line_; } + MessageLoop& main_message_loop() const { + return *main_message_loop_; + } - private: // Methods to be overridden to provide platform-specific code; these // correspond to the "parts" above. virtual void PreEarlyInitialization() {} virtual void PostEarlyInitialization() {} + virtual void PreMainMessageLoopStart() {} + virtual void PostMainMessageLoopStart() {} + private: // Methods for |EarlyInitialization()| --------------------------------------- // A/B test for the maximum number of persistent connections per host. @@ -82,6 +97,10 @@ class BrowserMainParts { // Used to initialize NSPR where appropriate. void InitializeSSL(); + // Methods for |MainMessageLoopStart()| -------------------------------------- + + void InitializeMainThread(); + // Members initialized on construction --------------------------------------- const MainFunctionParams& parameters_; @@ -97,14 +116,17 @@ class BrowserMainParts { // Statistical testing infrastructure for the entire browser. FieldTrialList field_trial_; + // Members initialized in |MainMessageLoopStart()| --------------------------- + scoped_ptr<MessageLoop> main_message_loop_; + scoped_ptr<SystemMonitor> system_monitor_; + scoped_ptr<HighResolutionTimerManager> hi_res_timer_manager_; + scoped_ptr<net::NetworkChangeNotifier> network_change_notifier_; + scoped_ptr<ChromeThread> main_thread_; + DISALLOW_COPY_AND_ASSIGN(BrowserMainParts); }; -// Perform platform-specific work that needs to be done before the main -// message loop is created, initialized, and entered. -void WillInitializeMainMessageLoop(const MainFunctionParams& parameters); - // Perform platform-specific work that needs to be done after the main event // loop has ended. void DidEndMainMessageLoop(); diff --git a/chrome/browser/browser_main_gtk.cc b/chrome/browser/browser_main_gtk.cc index c64d573..520c652 100644 --- a/chrome/browser/browser_main_gtk.cc +++ b/chrome/browser/browser_main_gtk.cc @@ -14,9 +14,6 @@ #include "chrome/app/breakpad_linux.h" #endif -void WillInitializeMainMessageLoop(const MainFunctionParams& parameters) { -} - void DidEndMainMessageLoop() { } diff --git a/chrome/browser/browser_main_mac.mm b/chrome/browser/browser_main_mac.mm index 34cca50..0fd8fb9 100644 --- a/chrome/browser/browser_main_mac.mm +++ b/chrome/browser/browser_main_mac.mm @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/browser_main.h" +#include "chrome/browser/browser_main_posix.h" #import <Cocoa/Cocoa.h> @@ -26,54 +26,6 @@ #include "chrome/common/notification_service.h" #include "chrome/common/result_codes.h" -// Tell Cooca to finish its initalization, which we want to do manually -// instead of calling NSApplicationMain(). The primary reason is that NSAM() -// never returns, which would leave all the objects currently on the stack -// in scoped_ptrs hanging and never cleaned up. We then load the main nib -// directly. The main event loop is run from common code using the -// MessageLoop API, which works out ok for us because it's a wrapper around -// CFRunLoop. -void WillInitializeMainMessageLoop(const MainFunctionParams& parameters) { - // Initialize NSApplication using the custom subclass. - [BrowserCrApplication sharedApplication]; - - // If ui_task is not NULL, the app is actually a browser_test, so startup is - // handled outside of BrowserMain (which is what called this). - if (!parameters.ui_task) { - // The browser process only wants to support the language Cocoa will use, so - // force the app locale to be overriden with that value. - l10n_util::OverrideLocaleWithCocoaLocale(); - - // Before we load the nib, we need to start up the resource bundle so we - // have the strings avaiable for localization. - std::wstring pref_locale; - // TODO(markusheintz): Read preference pref::kApplicationLocale in order to - // enforce the application locale. - ResourceBundle::InitSharedInstance(pref_locale); - - FilePath resources_pack_path; - PathService::Get(chrome::FILE_RESOURCES_PACK, &resources_pack_path); - ResourceBundle::AddDataPackToSharedInstance(resources_pack_path); - } - - // Now load the nib (from the right bundle). - scoped_nsobject<NSNib> - nib([[NSNib alloc] initWithNibNamed:@"MainMenu" - bundle:mac_util::MainAppBundle()]); - [nib instantiateNibWithOwner:NSApp topLevelObjects:nil]; - // Make sure the app controller has been created. - DCHECK([NSApp delegate]); - - // This is a no-op if the KeystoneRegistration framework is not present. - // The framework is only distributed with branded Google Chrome builds. - [[KeystoneGlue defaultKeystoneGlue] registerWithKeystone]; - - // Prevent Cocoa from turning command-line arguments into - // |-application:openFiles:|, since we already handle them directly. - [[NSUserDefaults standardUserDefaults] - setObject:@"NO" forKey:@"NSTreatUnknownArgumentsAsOpen"]; -} - void DidEndMainMessageLoop() { AppController* appController = [NSApp delegate]; [appController didEndMainMessageLoop]; @@ -104,3 +56,69 @@ bool CheckMachineLevelInstall() { void PrepareRestartOnCrashEnviroment(const CommandLine& parsed_command_line) { } + +// BrowserMainPartsMac --------------------------------------------------------- + +class BrowserMainPartsMac : public BrowserMainPartsPosix { + public: + explicit BrowserMainPartsMac(const MainFunctionParams& parameters) + : BrowserMainPartsPosix(parameters) {} + + protected: + virtual void PreMainMessageLoopStart() { + BrowserMainPartsPosix::PreMainMessageLoopStart(); + + // Tell Cooca to finish its initalization, which we want to do manually + // instead of calling NSApplicationMain(). The primary reason is that NSAM() + // never returns, which would leave all the objects currently on the stack + // in scoped_ptrs hanging and never cleaned up. We then load the main nib + // directly. The main event loop is run from common code using the + // MessageLoop API, which works out ok for us because it's a wrapper around + // CFRunLoop. + + // Initialize NSApplication using the custom subclass. + [BrowserCrApplication sharedApplication]; + + // If ui_task is not NULL, the app is actually a browser_test, so startup is + // handled outside of BrowserMain (which is what called this). + if (!parameters().ui_task) { + // The browser process only wants to support the language Cocoa will use, + // so force the app locale to be overriden with that value. + l10n_util::OverrideLocaleWithCocoaLocale(); + + // Before we load the nib, we need to start up the resource bundle so we + // have the strings avaiable for localization. + std::wstring pref_locale; + // TODO(markusheintz): Read preference pref::kApplicationLocale in order + // to enforce the application locale. + ResourceBundle::InitSharedInstance(pref_locale); + + FilePath resources_pack_path; + PathService::Get(chrome::FILE_RESOURCES_PACK, &resources_pack_path); + ResourceBundle::AddDataPackToSharedInstance(resources_pack_path); + } + + // Now load the nib (from the right bundle). + scoped_nsobject<NSNib> + nib([[NSNib alloc] initWithNibNamed:@"MainMenu" + bundle:mac_util::MainAppBundle()]); + [nib instantiateNibWithOwner:NSApp topLevelObjects:nil]; + // Make sure the app controller has been created. + DCHECK([NSApp delegate]); + + // This is a no-op if the KeystoneRegistration framework is not present. + // The framework is only distributed with branded Google Chrome builds. + [[KeystoneGlue defaultKeystoneGlue] registerWithKeystone]; + + // Prevent Cocoa from turning command-line arguments into + // |-application:openFiles:|, since we already handle them directly. + [[NSUserDefaults standardUserDefaults] + setObject:@"NO" forKey:@"NSTreatUnknownArgumentsAsOpen"]; + } +}; + +// static +BrowserMainParts* BrowserMainParts::CreateBrowserMainParts( + const MainFunctionParams& parameters) { + return new BrowserMainPartsMac(parameters); +} diff --git a/chrome/browser/browser_main_posix.cc b/chrome/browser/browser_main_posix.cc index bae79f5..1f90bdc 100644 --- a/chrome/browser/browser_main_posix.cc +++ b/chrome/browser/browser_main_posix.cc @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "chrome/browser/browser_main_posix.h" + #include <errno.h> #include <signal.h> #include <sys/resource.h> @@ -11,7 +13,6 @@ #include "base/logging.h" #include "base/string_util.h" #include "chrome/browser/browser_list.h" -#include "chrome/browser/browser_main.h" #include "chrome/browser/chrome_thread.h" #include "chrome/common/chrome_switches.h" @@ -155,76 +156,72 @@ void SetFileDescriptorLimit(unsigned int max_descriptors) { // BrowserMainPartsPosix ------------------------------------------------------- -class BrowserMainPartsPosix : public BrowserMainParts { - public: - explicit BrowserMainPartsPosix(const MainFunctionParams& parameters) - : BrowserMainParts(parameters) {} +void BrowserMainPartsPosix::PreEarlyInitialization() { + // We need to accept SIGCHLD, even though our handler is a no-op because + // otherwise we cannot wait on children. (According to POSIX 2001.) + struct sigaction action; + memset(&action, 0, sizeof(action)); + action.sa_handler = SIGCHLDHandler; + CHECK(sigaction(SIGCHLD, &action, NULL) == 0); - virtual void TemporaryPosix_1() { - int pipefd[2]; - int ret = pipe(pipefd); - if (ret < 0) { - PLOG(DFATAL) << "Failed to create pipe"; - } else { - g_shutdown_pipe_read_fd = pipefd[0]; - g_shutdown_pipe_write_fd = pipefd[1]; - const size_t kShutdownDetectorThreadStackSize = 4096; - if (!PlatformThread::CreateNonJoinable( - kShutdownDetectorThreadStackSize, - new ShutdownDetector(g_shutdown_pipe_read_fd))) { - LOG(DFATAL) << "Failed to create shutdown detector task."; - } - } - } + // If adding to this list of signal handlers, note the new signal probably + // needs to be reset in child processes. See + // base/process_util_posix.cc:LaunchApp - private: - virtual void PreEarlyInitialization() { - // We need to accept SIGCHLD, even though our handler is a no-op because - // otherwise we cannot wait on children. (According to POSIX 2001.) - struct sigaction action; - memset(&action, 0, sizeof(action)); - action.sa_handler = SIGCHLDHandler; - CHECK(sigaction(SIGCHLD, &action, NULL) == 0); - - // If adding to this list of signal handlers, note the new signal probably - // needs to be reset in child processes. See - // base/process_util_posix.cc:LaunchApp - - // We need to handle SIGTERM, because that is how many POSIX-based distros - // ask processes to quit gracefully at shutdown time. - memset(&action, 0, sizeof(action)); - action.sa_handler = SIGTERMHandler; - CHECK(sigaction(SIGTERM, &action, NULL) == 0); - // Also handle SIGINT - when the user terminates the browser via Ctrl+C. If - // the browser process is being debugged, GDB will catch the SIGINT first. - action.sa_handler = SIGINTHandler; - CHECK(sigaction(SIGINT, &action, NULL) == 0); - // And SIGHUP, for when the terminal disappears. On shutdown, many Linux - // distros send SIGHUP, SIGTERM, and then SIGKILL. - action.sa_handler = SIGHUPHandler; - CHECK(sigaction(SIGHUP, &action, NULL) == 0); - - const std::string fd_limit_string = - parsed_command_line().GetSwitchValueASCII( - switches::kFileDescriptorLimit); - int fd_limit = 0; - if (!fd_limit_string.empty()) { - StringToInt(fd_limit_string, &fd_limit); - } + // We need to handle SIGTERM, because that is how many POSIX-based distros ask + // processes to quit gracefully at shutdown time. + memset(&action, 0, sizeof(action)); + action.sa_handler = SIGTERMHandler; + CHECK(sigaction(SIGTERM, &action, NULL) == 0); + // Also handle SIGINT - when the user terminates the browser via Ctrl+C. If + // the browser process is being debugged, GDB will catch the SIGINT first. + action.sa_handler = SIGINTHandler; + CHECK(sigaction(SIGINT, &action, NULL) == 0); + // And SIGHUP, for when the terminal disappears. On shutdown, many Linux + // distros send SIGHUP, SIGTERM, and then SIGKILL. + action.sa_handler = SIGHUPHandler; + CHECK(sigaction(SIGHUP, &action, NULL) == 0); + + const std::string fd_limit_string = + parsed_command_line().GetSwitchValueASCII( + switches::kFileDescriptorLimit); + int fd_limit = 0; + if (!fd_limit_string.empty()) { + StringToInt(fd_limit_string, &fd_limit); + } #if defined(OS_MACOSX) - // We use quite a few file descriptors for our IPC, and the default limit on - // the Mac is low (256), so bump it up if there is no explicit override. - if (fd_limit == 0) { - fd_limit = 1024; - } + // We use quite a few file descriptors for our IPC, and the default limit on + // the Mac is low (256), so bump it up if there is no explicit override. + if (fd_limit == 0) { + fd_limit = 1024; + } #endif // OS_MACOSX - if (fd_limit > 0) - SetFileDescriptorLimit(fd_limit); + if (fd_limit > 0) + SetFileDescriptorLimit(fd_limit); +} + +void BrowserMainPartsPosix::PostMainMessageLoopStart() { + int pipefd[2]; + int ret = pipe(pipefd); + if (ret < 0) { + PLOG(DFATAL) << "Failed to create pipe"; + } else { + g_shutdown_pipe_read_fd = pipefd[0]; + g_shutdown_pipe_write_fd = pipefd[1]; + const size_t kShutdownDetectorThreadStackSize = 4096; + if (!PlatformThread::CreateNonJoinable( + kShutdownDetectorThreadStackSize, + new ShutdownDetector(g_shutdown_pipe_read_fd))) { + LOG(DFATAL) << "Failed to create shutdown detector task."; + } } -}; +} +// Mac further subclasses BrowserMainPartsPosix +#if !defined(OS_MACOSX) // static BrowserMainParts* BrowserMainParts::CreateBrowserMainParts( const MainFunctionParams& parameters) { return new BrowserMainPartsPosix(parameters); } +#endif // !defined(OS_MACOSX) diff --git a/chrome/browser/browser_main_posix.h b/chrome/browser/browser_main_posix.h new file mode 100644 index 0000000..bd247e9 --- /dev/null +++ b/chrome/browser/browser_main_posix.h @@ -0,0 +1,20 @@ +// Copyright (c) 2010 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. + +#ifndef CHROME_BROWSER_BROWSER_MAIN_POSIX_H_ +#define CHROME_BROWSER_BROWSER_MAIN_POSIX_H_ + +#include "chrome/browser/browser_main.h" + +class BrowserMainPartsPosix : public BrowserMainParts { + public: + explicit BrowserMainPartsPosix(const MainFunctionParams& parameters) + : BrowserMainParts(parameters) {} + + protected: + virtual void PreEarlyInitialization(); + virtual void PostMainMessageLoopStart(); +}; + +#endif // CHROME_BROWSER_BROWSER_MAIN_POSIX_H_ diff --git a/chrome/browser/browser_main_win.cc b/chrome/browser/browser_main_win.cc index 588a76c..b76545a 100644 --- a/chrome/browser/browser_main_win.cc +++ b/chrome/browser/browser_main_win.cc @@ -33,10 +33,6 @@ #include "views/focus/accelerator_handler.h" #include "views/window/window.h" -void WillInitializeMainMessageLoop(const MainFunctionParams& parameters) { - OleInitialize(NULL); -} - void DidEndMainMessageLoop() { OleUninitialize(); } @@ -211,11 +207,15 @@ class BrowserMainPartsWin : public BrowserMainParts { explicit BrowserMainPartsWin(const MainFunctionParams& parameters) : BrowserMainParts(parameters) {} - private: + protected: virtual void PreEarlyInitialization() { // Initialize Winsock. net::EnsureWinsockInit(); } + + virtual void PreMainMessageLoopStart() { + OleInitialize(NULL); + } }; // static |