Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(339)

Side by Side Diff: content/browser/browser_main.cc

Issue 8302016: Make GTK and Aura parts orthogonal to OS parts (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/browser_main.h" 5 #include "content/browser/browser_main.h"
6 6
7 #include "base/allocator/allocator_shim.h" 7 #include "base/allocator/allocator_shim.h"
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/debug/trace_event.h" 9 #include "base/debug/trace_event.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 GLibLogHandler, 160 GLibLogHandler,
161 NULL); 161 NULL);
162 } 162 }
163 } 163 }
164 #endif 164 #endif
165 165
166 } // namespace 166 } // namespace
167 167
168 namespace content { 168 namespace content {
169 169
170 BrowserMainParts::BrowserMainParts(const MainFunctionParams& parameters) 170 // 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.
171
172 // 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.
173 // Each stage is represented by a single BrowserMainLoop method
174 // (e.g., "EarlyInitialization()"), which does the following:
175 // - calls a method (e.g., "PreEarlyInitialization()") for each member of
176 // |parts_|. Parts will imlement platform or tookit specific code for that
177 // stage.
178 // - calls various methods for things common to all platforms (for that stage).
179 // - calls a method (e.g., "PostEarlyInitialization()") for platform-specific
180 // code to be called after the common code.
181 //
182 // Stages:
183 // - EarlyInitialization: things which should be done as soon as possible on
184 // program start (such as setting up signal handlers) and things to be done
185 // at some generic time before the start of the main message loop.
186 // - MainMessageLoopStart: things beginning with the start of the main message
187 // loop and ending with initialization of the main thread; platform-specific
188 // things which should be done immediately before the start of the main
189 // message loop should go in |PreMainMessageLoopStart()|.
190 // - RunMainMessageLoopParts: things to be done before and after invoking the
191 // main message loop run method (e.g. MessageLoopForUI::current()->Run()).
192 //
193 // How to add stuff (to existing parts):
194 // - Figure out when your new code should be executed. What must happen
195 // before/after your code is executed? Are there performance reasons for
196 // running your code at a particular time? Document these things!
197 // - Split out any platform-specific bits. Please avoid #ifdefs it at all
198 // possible. You have two choices for platform-specific code: (1) Execute it
199 // from one of the platform-specific |Pre/Post...()| methods; do this if the
200 // code is unique to a platform type. Or (2) execute it from one of the
201 // "parts" (e.g., |EarlyInitialization()|) and provide platform-specific
202 // implementations of your code (in a virtual method); do this if you need to
203 // provide different implementations across most/all platforms.
204 // - Unless your new code is just one or two lines, put it into a separate
205 // method with a well-defined purpose. (Likewise, if you're adding to an
206 // existing chunk which makes it longer than one or two lines, please move
207 // the code out into a separate method.)
208
209 class BrowserMainLoop {
210 public:
211 explicit BrowserMainLoop(const MainFunctionParams& parameters);
212 virtual ~BrowserMainLoop();
213 void Init();
214
215 // Parts to be called by |BrowserMain()|.
216 void EarlyInitialization();
217 void InitializeToolkit();
218 void MainMessageLoopStart();
219 void RunMainMessageLoopParts();
220 void MainMessageLoopRun();
221
222 int result_code() const { return result_code_; }
223
224 protected:
225 // Run main message loop. Invokes MessageLoopForUI::current()->Run unless
226 // overridden.
227
228 // Accessors for data members (below) ----------------------------------------
229 const MainFunctionParams& parameters() const {
230 return parameters_;
231 }
232 const CommandLine& parsed_command_line() const {
233 return parsed_command_line_;
234 }
235 MessageLoop& main_message_loop() const {
236 return *main_message_loop_;
237 }
238
239 private:
240 void InitializeMainThread();
241
242 // Members initialized on construction ---------------------------------------
243
244 const MainFunctionParams& parameters_;
245 const CommandLine& parsed_command_line_;
246 int result_code_;
247
248 // Vector of BrowserMainParts set by CreateBrowserMainParts ------------------
249 // The BrowserParts fucntions for each part are called in the order added.
250 // They are released (destroyed) in the reverse order.
251 typedef ContentBrowserClient::BrowserMainPartsList PartsList;
252 PartsList parts_;
253
254 // Members initialized in |MainMessageLoopStart()| ---------------------------
255 scoped_ptr<MessageLoop> main_message_loop_;
256 scoped_ptr<base::SystemMonitor> system_monitor_;
257 scoped_ptr<HighResolutionTimerManager> hi_res_timer_manager_;
258 scoped_ptr<net::NetworkChangeNotifier> network_change_notifier_;
259 scoped_ptr<BrowserThread> main_thread_;
260
261 DISALLOW_COPY_AND_ASSIGN(BrowserMainLoop);
262 };
263
264 // BrowserMainLoop construction / destruction ==================================
265
266 BrowserMainLoop::BrowserMainLoop(const MainFunctionParams& parameters)
171 : parameters_(parameters), 267 : parameters_(parameters),
172 parsed_command_line_(parameters.command_line_), 268 parsed_command_line_(parameters.command_line_),
173 result_code_(content::RESULT_CODE_NORMAL_EXIT) { 269 result_code_(content::RESULT_CODE_NORMAL_EXIT) {
174 #if defined(OS_WIN) 270 #if defined(OS_WIN)
175 OleInitialize(NULL); 271 OleInitialize(NULL);
176 #endif 272 #endif
177 } 273 }
178 274
179 BrowserMainParts::~BrowserMainParts() { 275 BrowserMainLoop::~BrowserMainLoop() {
276 // Destroy added parts in reverse order.
277 for (PartsList::reverse_iterator riter = parts_.rbegin();
278 riter != parts_.rend(); ++riter) {
279 delete *riter;
280 }
281 parts_.clear();
282
180 #if defined(OS_WIN) 283 #if defined(OS_WIN)
181 OleUninitialize(); 284 OleUninitialize();
182 #endif 285 #endif
183 } 286 }
184 287
185 void BrowserMainParts::EarlyInitialization() { 288 void BrowserMainLoop::Init() {
186 PreEarlyInitialization(); 289 content::GetContentClient()->browser()->CreateBrowserMainParts(
290 parameters_, parts_);
291 }
292
293 // BrowserMainLoop stages =====================================================
294
295 void BrowserMainLoop::EarlyInitialization() {
296 for (PartsList::iterator iter = parts_.begin();
297 iter != parts_.end(); ++iter) {
298 (*iter)->PreEarlyInitialization();
299 }
300
301 // Start watching for jank during shutdown. It gets disarmed when
187 302
188 #if defined(OS_WIN) 303 #if defined(OS_WIN)
189 net::EnsureWinsockInit(); 304 net::EnsureWinsockInit();
190 #endif 305 #endif
191 306
192 // Use NSS for SSL by default. 307 // Use NSS for SSL by default.
193 // The default client socket factory uses NSS for SSL by default on 308 // The default client socket factory uses NSS for SSL by default on
194 // Windows and Mac. 309 // Windows and Mac.
310 bool init_nspr = false;
195 #if defined(OS_WIN) || defined(OS_MACOSX) 311 #if defined(OS_WIN) || defined(OS_MACOSX)
196 if (parsed_command_line().HasSwitch(switches::kUseSystemSSL)) { 312 if (parsed_command_line().HasSwitch(switches::kUseSystemSSL)) {
197 net::ClientSocketFactory::UseSystemSSL(); 313 net::ClientSocketFactory::UseSystemSSL();
198 } else { 314 } else {
315 init_nspr = true;
316 }
199 #elif defined(USE_NSS) 317 #elif defined(USE_NSS)
200 if (true) { 318 init_nspr = true;
201 #else
202 if (false) {
203 #endif 319 #endif
320 if (init_nspr) {
204 // We want to be sure to init NSPR on the main thread. 321 // We want to be sure to init NSPR on the main thread.
205 crypto::EnsureNSPRInit(); 322 crypto::EnsureNSPRInit();
206 } 323 }
207 324
208 #if defined(OS_POSIX) && !defined(OS_MACOSX) 325 #if defined(OS_POSIX) && !defined(OS_MACOSX)
209 SetupSandbox(parsed_command_line()); 326 SetupSandbox(parsed_command_line());
210 #endif 327 #endif
211 328
212 if (parsed_command_line().HasSwitch(switches::kDisableSSLFalseStart)) 329 if (parsed_command_line().HasSwitch(switches::kDisableSSLFalseStart))
213 net::SSLConfigService::DisableFalseStart(); 330 net::SSLConfigService::DisableFalseStart();
214 if (parsed_command_line().HasSwitch(switches::kEnableSSLCachedInfo)) 331 if (parsed_command_line().HasSwitch(switches::kEnableSSLCachedInfo))
215 net::SSLConfigService::EnableCachedInfo(); 332 net::SSLConfigService::EnableCachedInfo();
216 if (parsed_command_line().HasSwitch(switches::kEnableOriginBoundCerts)) 333 if (parsed_command_line().HasSwitch(switches::kEnableOriginBoundCerts))
217 net::SSLConfigService::EnableOriginBoundCerts(); 334 net::SSLConfigService::EnableOriginBoundCerts();
218 if (parsed_command_line().HasSwitch( 335 if (parsed_command_line().HasSwitch(
219 switches::kEnableDNSCertProvenanceChecking)) { 336 switches::kEnableDNSCertProvenanceChecking)) {
220 net::SSLConfigService::EnableDNSCertProvenanceChecking(); 337 net::SSLConfigService::EnableDNSCertProvenanceChecking();
221 } 338 }
222 339
223 // TODO(abarth): Should this move to InitializeNetworkOptions? This doesn't 340 // TODO(abarth): Should this move to InitializeNetworkOptions? This doesn't
224 // seem dependent on SSL initialization(). 341 // seem dependent on SSL initialization().
225 if (parsed_command_line().HasSwitch(switches::kEnableTcpFastOpen)) 342 if (parsed_command_line().HasSwitch(switches::kEnableTcpFastOpen))
226 net::set_tcp_fastopen_enabled(true); 343 net::set_tcp_fastopen_enabled(true);
227 344
228 PostEarlyInitialization(); 345 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
346 iter != parts_.end(); ++iter) {
347 (*iter)->PostEarlyInitialization();
348 }
229 } 349 }
230 350
231 void BrowserMainParts::MainMessageLoopStart() { 351 void BrowserMainLoop::MainMessageLoopStart() {
232 PreMainMessageLoopStart(); 352 for (PartsList::iterator iter = parts_.begin();
353 iter != parts_.end(); ++iter) {
354 (*iter)->PreMainMessageLoopStart();
355 }
233 356
234 #if defined(OS_WIN) 357 #if defined(OS_WIN)
235 // If we're running tests (ui_task is non-null), then the ResourceBundle 358 // If we're running tests (ui_task is non-null), then the ResourceBundle
236 // has already been initialized. 359 // has already been initialized.
237 if (!parameters().ui_task) { 360 if (!parameters().ui_task) {
238 // Override the configured locale with the user's preferred UI language. 361 // Override the configured locale with the user's preferred UI language.
239 l10n_util::OverrideLocaleWithUILanguageList(); 362 l10n_util::OverrideLocaleWithUILanguageList();
240 } 363 }
241 #endif 364 #endif
242 365
243 main_message_loop_.reset(new MessageLoop(MessageLoop::TYPE_UI)); 366 main_message_loop_.reset(new MessageLoop(MessageLoop::TYPE_UI));
244 367
245 InitializeMainThread(); 368 InitializeMainThread();
246 369
247 system_monitor_.reset(new base::SystemMonitor); 370 system_monitor_.reset(new base::SystemMonitor);
248 hi_res_timer_manager_.reset(new HighResolutionTimerManager); 371 hi_res_timer_manager_.reset(new HighResolutionTimerManager);
249 372
250 network_change_notifier_.reset(net::NetworkChangeNotifier::Create()); 373 network_change_notifier_.reset(net::NetworkChangeNotifier::Create());
251 374
252 PostMainMessageLoopStart(); 375 for (PartsList::iterator iter = parts_.begin();
376 iter != parts_.end(); ++iter) {
377 (*iter)->PostMainMessageLoopStart();
378 }
253 } 379 }
254 380
255 static bool g_exited_main_message_loop = false; 381 static bool g_exited_main_message_loop = false;
256 382
257 void BrowserMainParts::RunMainMessageLoopParts() { 383 void BrowserMainLoop::RunMainMessageLoopParts() {
258 PreMainMessageLoopRun(); 384 for (PartsList::iterator iter = parts_.begin();
385 iter != parts_.end(); ++iter) {
386 int result = (*iter)->PreMainMessageLoopRun();
387 if (result != content::RESULT_CODE_NORMAL_EXIT)
388 result_code_ = result;
389 }
259 390
260 TRACE_EVENT_BEGIN_ETW("BrowserMain:MESSAGE_LOOP", 0, ""); 391 TRACE_EVENT_BEGIN_ETW("BrowserMain:MESSAGE_LOOP", 0, "");
261 // If the UI thread blocks, the whole UI is unresponsive. 392 // If the UI thread blocks, the whole UI is unresponsive.
262 // Do not allow disk IO from the UI thread. 393 // Do not allow disk IO from the UI thread.
263 base::ThreadRestrictions::SetIOAllowed(false); 394 base::ThreadRestrictions::SetIOAllowed(false);
264 MainMessageLoopRun(); 395
396 // Iterate through each of the parts. If any of them ran the main
397 // message loop then they should return |true|. Otherwise
398 // BrowserMainLoop::MainMessageLoopRun loop will be run.
399 bool ran_main_loop = false;
400 for (PartsList::iterator iter = parts_.begin();
401 iter != parts_.end(); ++iter) {
402 if ((*iter)->MainMessageLoopRun())
403 ran_main_loop = true;
404 }
405 if (!ran_main_loop)
406 MainMessageLoopRun();
407
265 TRACE_EVENT_END_ETW("BrowserMain:MESSAGE_LOOP", 0, ""); 408 TRACE_EVENT_END_ETW("BrowserMain:MESSAGE_LOOP", 0, "");
266 409
267 g_exited_main_message_loop = true; 410 g_exited_main_message_loop = true;
268 411
269 PostMainMessageLoopRun(); 412 for (PartsList::iterator iter = parts_.begin();
413 iter != parts_.end(); ++iter) {
414 (*iter)->PostMainMessageLoopRun();
415 }
270 } 416 }
271 417
272 void BrowserMainParts::InitializeMainThread() { 418 void BrowserMainLoop::InitializeMainThread() {
273 const char* kThreadName = "CrBrowserMain"; 419 const char* kThreadName = "CrBrowserMain";
274 base::PlatformThread::SetName(kThreadName); 420 base::PlatformThread::SetName(kThreadName);
275 main_message_loop().set_thread_name(kThreadName); 421 main_message_loop().set_thread_name(kThreadName);
276 422
277 #if defined(TRACK_ALL_TASK_OBJECTS) 423 #if defined(TRACK_ALL_TASK_OBJECTS)
278 tracked_objects::ThreadData::InitializeThreadContext(kThreadName); 424 tracked_objects::ThreadData::InitializeThreadContext(kThreadName);
279 #endif // TRACK_ALL_TASK_OBJECTS 425 #endif // TRACK_ALL_TASK_OBJECTS
280 426
281 // Register the main thread by instantiating it, but don't call any methods. 427 // Register the main thread by instantiating it, but don't call any methods.
282 main_thread_.reset(new BrowserThread(BrowserThread::UI, 428 main_thread_.reset(new BrowserThread(BrowserThread::UI,
283 MessageLoop::current())); 429 MessageLoop::current()));
284 } 430 }
285 431
286 void BrowserMainParts::InitializeToolkit() { 432 void BrowserMainLoop::InitializeToolkit() {
287 // TODO(evan): this function is rather subtle, due to the variety 433 // TODO(evan): this function is rather subtle, due to the variety
288 // of intersecting ifdefs we have. To keep it easy to follow, there 434 // of intersecting ifdefs we have. To keep it easy to follow, there
289 // are no #else branches on any #ifs. 435 // are no #else branches on any #ifs.
290 436 // TODO(stevenjb): Move platform specific code into platform specific Parts
437 // (Need to add InitializeToolkit stage to BrowserParts).
291 #if defined(OS_LINUX) 438 #if defined(OS_LINUX)
292 // We want to call g_thread_init(), but in some codepaths (tests) it 439 // We want to call g_thread_init(), but in some codepaths (tests) it
293 // is possible it has already been called. In older versions of 440 // is possible it has already been called. In older versions of
294 // GTK, it is an error to call g_thread_init twice; unfortunately, 441 // GTK, it is an error to call g_thread_init twice; unfortunately,
295 // the API to tell whether it has been called already was also only 442 // the API to tell whether it has been called already was also only
296 // added in a newer version of GTK! Thankfully, this non-intuitive 443 // added in a newer version of GTK! Thankfully, this non-intuitive
297 // check is actually equivalent and sufficient to work around the 444 // check is actually equivalent and sufficient to work around the
298 // error. 445 // error.
299 if (!g_thread_supported()) 446 if (!g_thread_supported())
300 g_thread_init(NULL); 447 g_thread_init(NULL);
(...skipping 22 matching lines...) Expand all
323 470
324 #if defined(OS_WIN) 471 #if defined(OS_WIN)
325 // Init common control sex. 472 // Init common control sex.
326 INITCOMMONCONTROLSEX config; 473 INITCOMMONCONTROLSEX config;
327 config.dwSize = sizeof(config); 474 config.dwSize = sizeof(config);
328 config.dwICC = ICC_WIN95_CLASSES; 475 config.dwICC = ICC_WIN95_CLASSES;
329 if (!InitCommonControlsEx(&config)) 476 if (!InitCommonControlsEx(&config))
330 LOG_GETLASTERROR(FATAL); 477 LOG_GETLASTERROR(FATAL);
331 #endif 478 #endif
332 479
333 ToolkitInitialized(); 480 for (PartsList::iterator iter = parts_.begin();
481 iter != parts_.end(); ++iter) {
482 (*iter)->ToolkitInitialized();
483 }
334 } 484 }
335 485
336 void BrowserMainParts::PreEarlyInitialization() { 486 void BrowserMainLoop::MainMessageLoopRun() {
337 }
338
339 void BrowserMainParts::PostEarlyInitialization() {
340 }
341
342 void BrowserMainParts::PreMainMessageLoopStart() {
343 }
344
345 void BrowserMainParts::PostMainMessageLoopStart() {
346 }
347
348 void BrowserMainParts::PreMainMessageLoopRun() {
349 }
350
351 void BrowserMainParts::MainMessageLoopRun() {
352 if (parameters().ui_task) 487 if (parameters().ui_task)
353 MessageLoopForUI::current()->PostTask(FROM_HERE, parameters().ui_task); 488 MessageLoopForUI::current()->PostTask(FROM_HERE, parameters().ui_task);
354 489
355 #if defined(OS_MACOSX) 490 #if defined(OS_MACOSX)
356 MessageLoopForUI::current()->Run(); 491 MessageLoopForUI::current()->Run();
357 #else 492 #else
358 MessageLoopForUI::current()->Run(NULL); 493 MessageLoopForUI::current()->Run(NULL);
359 #endif 494 #endif
360 } 495 }
361 496
362 void BrowserMainParts::PostMainMessageLoopRun() {
363 }
364
365 void BrowserMainParts::ToolkitInitialized() {
366 }
367
368 bool ExitedMainMessageLoop() { 497 bool ExitedMainMessageLoop() {
369 return g_exited_main_message_loop; 498 return g_exited_main_message_loop;
370 } 499 }
371 500
372 } // namespace content 501 } // namespace content
373 502
374 // Main routine for running as the Browser process. 503 // Main routine for running as the Browser process.
375 int BrowserMain(const MainFunctionParams& parameters) { 504 int BrowserMain(const MainFunctionParams& parameters) {
376 TRACE_EVENT_BEGIN_ETW("BrowserMain", 0, ""); 505 TRACE_EVENT_BEGIN_ETW("BrowserMain", 0, "");
377 506
378 NotificationServiceImpl main_notification_service; 507 NotificationServiceImpl main_notification_service;
379 508
380 scoped_ptr<content::BrowserMainParts> parts( 509 scoped_ptr<content::BrowserMainLoop> main_loop(
381 content::GetContentClient()->browser()->CreateBrowserMainParts( 510 new content::BrowserMainLoop(parameters));
382 parameters));
383 if (!parts.get())
384 parts.reset(new content::BrowserMainParts(parameters));
385 511
386 parts->EarlyInitialization(); 512 main_loop->Init();
513
514 main_loop->EarlyInitialization();
387 515
388 // Must happen before we try to use a message loop or display any UI. 516 // Must happen before we try to use a message loop or display any UI.
389 parts->InitializeToolkit(); 517 main_loop->InitializeToolkit();
390 518
391 parts->MainMessageLoopStart(); 519 main_loop->MainMessageLoopStart();
392 520
393 // WARNING: If we get a WM_ENDSESSION, objects created on the stack here 521 // WARNING: If we get a WM_ENDSESSION, objects created on the stack here
394 // are NOT deleted. If you need something to run during WM_ENDSESSION add it 522 // are NOT deleted. If you need something to run during WM_ENDSESSION add it
395 // to browser_shutdown::Shutdown or BrowserProcess::EndSession. 523 // to browser_shutdown::Shutdown or BrowserProcess::EndSession.
396 524
397 // !!!!!!!!!! READ ME !!!!!!!!!! 525 // !!!!!!!!!! READ ME !!!!!!!!!!
398 // I (viettrungluu) am in the process of refactoring |BrowserMain()|. If you 526 // I (viettrungluu) am in the process of refactoring |BrowserMain()|. If you
399 // need to add something above this comment, read the documentation in 527 // need to add something above this comment, read the documentation in
400 // browser_main.h. If you need to add something below, please do the 528 // browser_main.h. If you need to add something below, please do the
401 // following: 529 // following:
(...skipping 25 matching lines...) Expand all
427 // initialize the sandbox broker, which requires the process to swap its 555 // initialize the sandbox broker, which requires the process to swap its
428 // window station. During this time all the UI will be broken. This has to 556 // window station. During this time all the UI will be broken. This has to
429 // run before threads and windows are created. 557 // run before threads and windows are created.
430 InitializeBrokerServices(parameters, parameters.command_line_); 558 InitializeBrokerServices(parameters, parameters.command_line_);
431 559
432 base::win::ScopedCOMInitializer com_initializer; 560 base::win::ScopedCOMInitializer com_initializer;
433 #endif // OS_WIN 561 #endif // OS_WIN
434 562
435 base::StatisticsRecorder statistics; 563 base::StatisticsRecorder statistics;
436 564
437 parts->RunMainMessageLoopParts(); 565 main_loop->RunMainMessageLoopParts();
438 566
439 TRACE_EVENT_END_ETW("BrowserMain", 0, 0); 567 TRACE_EVENT_END_ETW("BrowserMain", 0, 0);
440 return parts->result_code(); 568
569 return main_loop->result_code();
441 } 570 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698