Chromium Code Reviews| Index: content/browser/browser_main.cc |
| diff --git a/content/browser/browser_main.cc b/content/browser/browser_main.cc |
| index 5bccf00027bca08ea502993b69ec06709f2e11e8..46d47ece6835a7014a85aeef6dcf920fcc29db51 100644 |
| --- a/content/browser/browser_main.cc |
| +++ b/content/browser/browser_main.cc |
| @@ -167,7 +167,103 @@ static void SetUpGLibLogHandler() { |
| namespace content { |
| -BrowserMainParts::BrowserMainParts(const MainFunctionParams& parameters) |
| +// BrowserMainLoop |
|
jam
2011/10/24 19:36:00
nit: this should go into its own file, and also ha
stevenjb
2011/10/25 02:51:04
Done.
|
| + |
| +// This class contains different "stages" to be executed in |BrowserMain()|, |
|
jam
2011/10/24 19:36:00
nit: these comments are really meant for embedders
stevenjb
2011/10/25 02:51:04
Done.
|
| +// Each stage is represented by a single BrowserMainLoop method |
| +// (e.g., "EarlyInitialization()"), which does the following: |
| +// - calls a method (e.g., "PreEarlyInitialization()") for each member of |
| +// |parts_|. Parts will imlement platform or tookit specific code for that |
| +// stage. |
| +// - calls various methods for things common to all platforms (for that stage). |
| +// - calls a method (e.g., "PostEarlyInitialization()") for platform-specific |
| +// code to be called after the common code. |
| +// |
| +// Stages: |
| +// - 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()|. |
| +// - RunMainMessageLoopParts: things to be done before and after invoking the |
| +// main message loop run method (e.g. MessageLoopForUI::current()->Run()). |
| +// |
| +// How to add stuff (to existing parts): |
| +// - Figure out when your new code should be executed. What must happen |
| +// before/after your code is executed? Are there performance reasons for |
| +// running your code at a particular time? Document these things! |
| +// - Split out any platform-specific bits. Please avoid #ifdefs it at all |
| +// possible. You have two choices for platform-specific code: (1) Execute it |
| +// from one of the platform-specific |Pre/Post...()| methods; do this if the |
| +// code is unique to a platform type. Or (2) execute it from one of the |
| +// "parts" (e.g., |EarlyInitialization()|) and provide platform-specific |
| +// implementations of your code (in a virtual method); do this if you need to |
| +// provide different implementations across most/all platforms. |
| +// - Unless your new code is just one or two lines, put it into a separate |
| +// method with a well-defined purpose. (Likewise, if you're adding to an |
| +// existing chunk which makes it longer than one or two lines, please move |
| +// the code out into a separate method.) |
| + |
| +class BrowserMainLoop { |
| + public: |
| + explicit BrowserMainLoop(const MainFunctionParams& parameters); |
| + virtual ~BrowserMainLoop(); |
| + void Init(); |
| + |
| + // Parts to be called by |BrowserMain()|. |
| + void EarlyInitialization(); |
| + void InitializeToolkit(); |
| + void MainMessageLoopStart(); |
| + void RunMainMessageLoopParts(); |
| + void MainMessageLoopRun(); |
| + |
| + int result_code() const { return result_code_; } |
| + |
| + protected: |
| + // Run main message loop. Invokes MessageLoopForUI::current()->Run unless |
| + // overridden. |
| + |
| + // Accessors for data members (below) ---------------------------------------- |
| + const MainFunctionParams& parameters() const { |
| + return parameters_; |
| + } |
| + const CommandLine& parsed_command_line() const { |
| + return parsed_command_line_; |
| + } |
| + MessageLoop& main_message_loop() const { |
| + return *main_message_loop_; |
| + } |
| + |
| + 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. |
| + typedef ContentBrowserClient::BrowserMainPartsList PartsList; |
| + PartsList 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(BrowserMainLoop); |
| +}; |
| + |
| +// BrowserMainLoop construction / destruction ================================== |
| + |
| +BrowserMainLoop::BrowserMainLoop(const MainFunctionParams& parameters) |
| : parameters_(parameters), |
| parsed_command_line_(parameters.command_line_), |
| result_code_(content::RESULT_CODE_NORMAL_EXIT) { |
| @@ -176,14 +272,33 @@ BrowserMainParts::BrowserMainParts(const MainFunctionParams& parameters) |
| #endif |
| } |
| -BrowserMainParts::~BrowserMainParts() { |
| +BrowserMainLoop::~BrowserMainLoop() { |
| + // Destroy added parts in reverse order. |
| + for (PartsList::reverse_iterator riter = parts_.rbegin(); |
| + riter != parts_.rend(); ++riter) { |
| + delete *riter; |
| + } |
| + parts_.clear(); |
| + |
| #if defined(OS_WIN) |
| OleUninitialize(); |
| #endif |
| } |
| -void BrowserMainParts::EarlyInitialization() { |
| - PreEarlyInitialization(); |
| +void BrowserMainLoop::Init() { |
| + content::GetContentClient()->browser()->CreateBrowserMainParts( |
| + parameters_, parts_); |
| +} |
| + |
| +// BrowserMainLoop stages ===================================================== |
| + |
| +void BrowserMainLoop::EarlyInitialization() { |
| + for (PartsList::iterator iter = parts_.begin(); |
| + iter != parts_.end(); ++iter) { |
| + (*iter)->PreEarlyInitialization(); |
| + } |
| + |
| + // Start watching for jank during shutdown. It gets disarmed when |
| #if defined(OS_WIN) |
| net::EnsureWinsockInit(); |
| @@ -192,15 +307,17 @@ 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)) { |
| 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(); |
| } |
| @@ -225,11 +342,17 @@ void BrowserMainParts::EarlyInitialization() { |
| if (parsed_command_line().HasSwitch(switches::kEnableTcpFastOpen)) |
| net::set_tcp_fastopen_enabled(true); |
| - PostEarlyInitialization(); |
| + for (PartsList::iterator iter = parts_.begin(); |
|
jam
2011/10/24 19:36:00
convention is usually to not use an iterator for a
stevenjb
2011/10/25 02:51:04
Interesting, I did not know that. That reduces fle
|
| + iter != parts_.end(); ++iter) { |
| + (*iter)->PostEarlyInitialization(); |
| + } |
| } |
| -void BrowserMainParts::MainMessageLoopStart() { |
| - PreMainMessageLoopStart(); |
| +void BrowserMainLoop::MainMessageLoopStart() { |
| + for (PartsList::iterator iter = parts_.begin(); |
| + iter != parts_.end(); ++iter) { |
| + (*iter)->PreMainMessageLoopStart(); |
| + } |
| #if defined(OS_WIN) |
| // If we're running tests (ui_task is non-null), then the ResourceBundle |
| @@ -249,27 +372,50 @@ void BrowserMainParts::MainMessageLoopStart() { |
| network_change_notifier_.reset(net::NetworkChangeNotifier::Create()); |
| - PostMainMessageLoopStart(); |
| + for (PartsList::iterator iter = parts_.begin(); |
| + iter != parts_.end(); ++iter) { |
| + (*iter)->PostMainMessageLoopStart(); |
| + } |
| } |
| static bool g_exited_main_message_loop = false; |
| -void BrowserMainParts::RunMainMessageLoopParts() { |
| - PreMainMessageLoopRun(); |
| +void BrowserMainLoop::RunMainMessageLoopParts() { |
| + for (PartsList::iterator iter = parts_.begin(); |
| + iter != parts_.end(); ++iter) { |
| + int result = (*iter)->PreMainMessageLoopRun(); |
| + if (result != content::RESULT_CODE_NORMAL_EXIT) |
| + result_code_ = result; |
| + } |
| 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 (PartsList::iterator iter = parts_.begin(); |
| + iter != parts_.end(); ++iter) { |
| + if ((*iter)->MainMessageLoopRun()) |
| + ran_main_loop = true; |
| + } |
| + if (!ran_main_loop) |
| + MainMessageLoopRun(); |
| + |
| TRACE_EVENT_END_ETW("BrowserMain:MESSAGE_LOOP", 0, ""); |
| g_exited_main_message_loop = true; |
| - PostMainMessageLoopRun(); |
| + for (PartsList::iterator iter = parts_.begin(); |
| + iter != parts_.end(); ++iter) { |
| + (*iter)->PostMainMessageLoopRun(); |
| + } |
| } |
| -void BrowserMainParts::InitializeMainThread() { |
| +void BrowserMainLoop::InitializeMainThread() { |
| const char* kThreadName = "CrBrowserMain"; |
| base::PlatformThread::SetName(kThreadName); |
| main_message_loop().set_thread_name(kThreadName); |
| @@ -283,11 +429,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 |
| @@ -330,25 +477,13 @@ void BrowserMainParts::InitializeToolkit() { |
| LOG_GETLASTERROR(FATAL); |
| #endif |
| - ToolkitInitialized(); |
| -} |
| - |
| -void BrowserMainParts::PreEarlyInitialization() { |
| -} |
| - |
| -void BrowserMainParts::PostEarlyInitialization() { |
| -} |
| - |
| -void BrowserMainParts::PreMainMessageLoopStart() { |
| -} |
| - |
| -void BrowserMainParts::PostMainMessageLoopStart() { |
| -} |
| - |
| -void BrowserMainParts::PreMainMessageLoopRun() { |
| + for (PartsList::iterator iter = parts_.begin(); |
| + iter != parts_.end(); ++iter) { |
| + (*iter)->ToolkitInitialized(); |
| + } |
| } |
| -void BrowserMainParts::MainMessageLoopRun() { |
| +void BrowserMainLoop::MainMessageLoopRun() { |
| if (parameters().ui_task) |
| MessageLoopForUI::current()->PostTask(FROM_HERE, parameters().ui_task); |
| @@ -359,12 +494,6 @@ void BrowserMainParts::MainMessageLoopRun() { |
| #endif |
| } |
| -void BrowserMainParts::PostMainMessageLoopRun() { |
| -} |
| - |
| -void BrowserMainParts::ToolkitInitialized() { |
| -} |
| - |
| bool ExitedMainMessageLoop() { |
| return g_exited_main_message_loop; |
| } |
| @@ -377,18 +506,17 @@ int BrowserMain(const MainFunctionParams& parameters) { |
| NotificationServiceImpl main_notification_service; |
| - scoped_ptr<content::BrowserMainParts> parts( |
| - content::GetContentClient()->browser()->CreateBrowserMainParts( |
| - parameters)); |
| - if (!parts.get()) |
| - parts.reset(new content::BrowserMainParts(parameters)); |
| + scoped_ptr<content::BrowserMainLoop> main_loop( |
| + new content::BrowserMainLoop(parameters)); |
| - parts->EarlyInitialization(); |
| + main_loop->Init(); |
| + |
| + main_loop->EarlyInitialization(); |
| // Must happen before we try to use a message loop or display any UI. |
| - parts->InitializeToolkit(); |
| + main_loop->InitializeToolkit(); |
| - parts->MainMessageLoopStart(); |
| + main_loop->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 |
| @@ -434,8 +562,9 @@ int BrowserMain(const MainFunctionParams& parameters) { |
| base::StatisticsRecorder statistics; |
| - parts->RunMainMessageLoopParts(); |
| + main_loop->RunMainMessageLoopParts(); |
| TRACE_EVENT_END_ETW("BrowserMain", 0, 0); |
| - return parts->result_code(); |
| + |
| + return main_loop->result_code(); |
| } |