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

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

Issue 8718012: Revert 111695 - Have content/ create and destroy its own threads. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 9 years 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
« no previous file with comments | « content/browser/browser_main_loop.h ('k') | content/browser/browser_process_sub_thread.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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_loop.h" 5 #include "content/browser/browser_main_loop.h"
6 6
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "base/debug/trace_event.h" 8 #include "base/debug/trace_event.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/message_loop.h" 10 #include "base/message_loop.h"
11 #include "base/metrics/field_trial.h" 11 #include "base/metrics/field_trial.h"
12 #include "base/metrics/histogram.h" 12 #include "base/metrics/histogram.h"
13 #include "base/threading/thread_restrictions.h" 13 #include "base/threading/thread_restrictions.h"
14 #include "content/browser/browser_thread_impl.h" 14 #include "content/browser/browser_thread_impl.h"
15 #include "content/browser/trace_controller.h" 15 #include "content/browser/trace_controller.h"
16 #include "content/common/hi_res_timer_manager.h" 16 #include "content/common/hi_res_timer_manager.h"
17 #include "content/common/sandbox_policy.h" 17 #include "content/common/sandbox_policy.h"
18 #include "content/public/browser/browser_main_parts.h" 18 #include "content/public/browser/browser_main_parts.h"
19 #include "content/public/browser/browser_shutdown.h"
20 #include "content/public/browser/content_browser_client.h" 19 #include "content/public/browser/content_browser_client.h"
21 #include "content/public/common/content_switches.h" 20 #include "content/public/common/content_switches.h"
22 #include "content/public/common/main_function_params.h" 21 #include "content/public/common/main_function_params.h"
23 #include "content/public/common/result_codes.h" 22 #include "content/public/common/result_codes.h"
24 #include "crypto/nss_util.h" 23 #include "crypto/nss_util.h"
25 #include "net/base/network_change_notifier.h" 24 #include "net/base/network_change_notifier.h"
26 #include "net/base/ssl_config_service.h" 25 #include "net/base/ssl_config_service.h"
27 #include "net/socket/client_socket_factory.h" 26 #include "net/socket/client_socket_factory.h"
28 #include "net/socket/tcp_client_socket.h" 27 #include "net/socket/tcp_client_socket.h"
29 28
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 GLibLogHandler, 138 GLibLogHandler,
140 NULL); 139 NULL);
141 } 140 }
142 } 141 }
143 #endif 142 #endif
144 143
145 } // namespace 144 } // namespace
146 145
147 namespace content { 146 namespace content {
148 147
149 // The currently-running BrowserMainLoop. There can be one or zero.
150 // This is stored to enable immediate shutdown when needed.
151 BrowserMainLoop* current_browser_main_loop = NULL;
152
153 // This is just to be able to keep ShutdownThreadsAndCleanUp out of
154 // the public interface of BrowserMainLoop.
155 class BrowserShutdownImpl {
156 public:
157 static void ImmediateShutdownAndExitProcess() {
158 DCHECK(current_browser_main_loop);
159 current_browser_main_loop->ShutdownThreadsAndCleanUp();
160
161 #if defined(OS_WIN)
162 // At this point the message loop is still running yet we've shut everything
163 // down. If any messages are processed we'll likely crash. Exit now.
164 ExitProcess(content::RESULT_CODE_NORMAL_EXIT);
165 #elif defined(OS_POSIX) && !defined(OS_MACOSX)
166 _exit(content::RESULT_CODE_NORMAL_EXIT);
167 #else
168 NOTIMPLEMENTED();
169 #endif
170 }
171 };
172
173 void ImmediateShutdownAndExitProcess() {
174 BrowserShutdownImpl::ImmediateShutdownAndExitProcess();
175 }
176 148
177 // BrowserMainLoop construction / destructione ============================= 149 // BrowserMainLoop construction / destructione =============================
178 150
179 BrowserMainLoop::BrowserMainLoop(const content::MainFunctionParams& parameters) 151 BrowserMainLoop::BrowserMainLoop(const content::MainFunctionParams& parameters)
180 : parameters_(parameters), 152 : parameters_(parameters),
181 parsed_command_line_(parameters.command_line), 153 parsed_command_line_(parameters.command_line),
182 result_code_(content::RESULT_CODE_NORMAL_EXIT) { 154 result_code_(content::RESULT_CODE_NORMAL_EXIT) {
183 DCHECK(!current_browser_main_loop);
184 current_browser_main_loop = this;
185 #if defined(OS_WIN) 155 #if defined(OS_WIN)
186 OleInitialize(NULL); 156 OleInitialize(NULL);
187 #endif 157 #endif
188 } 158 }
189 159
190 BrowserMainLoop::~BrowserMainLoop() { 160 BrowserMainLoop::~BrowserMainLoop() {
191 DCHECK_EQ(this, current_browser_main_loop);
192 current_browser_main_loop = NULL;
193 #if defined(OS_WIN) 161 #if defined(OS_WIN)
194 OleUninitialize(); 162 OleUninitialize();
195 #endif 163 #endif
196 } 164 }
197 165
198 void BrowserMainLoop::Init() { 166 void BrowserMainLoop::Init() {
199 parts_.reset( 167 parts_.reset(
200 GetContentClient()->browser()->CreateBrowserMainParts(parameters_)); 168 GetContentClient()->browser()->CreateBrowserMainParts(parameters_));
201 } 169 }
202 170
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 system_message_window_.reset(new SystemMessageWindowWin); 255 system_message_window_.reset(new SystemMessageWindowWin);
288 #endif 256 #endif
289 257
290 if (parts_.get()) 258 if (parts_.get())
291 parts_->PostMainMessageLoopStart(); 259 parts_->PostMainMessageLoopStart();
292 } 260 }
293 261
294 void BrowserMainLoop::RunMainMessageLoopParts( 262 void BrowserMainLoop::RunMainMessageLoopParts(
295 bool* completed_main_message_loop) { 263 bool* completed_main_message_loop) {
296 if (parts_.get()) 264 if (parts_.get())
297 parts_->PreCreateThreads();
298
299 base::Thread::Options default_options;
300 base::Thread::Options io_message_loop_options;
301 io_message_loop_options.message_loop_type = MessageLoop::TYPE_IO;
302 base::Thread::Options ui_message_loop_options;
303 ui_message_loop_options.message_loop_type = MessageLoop::TYPE_UI;
304
305 // Start threads in the order they occur in the BrowserThread::ID
306 // enumeration, except for BrowserThread::UI which is the main
307 // thread.
308 //
309 // Must be size_t so we can increment it.
310 for (size_t thread_id = BrowserThread::UI + 1;
311 thread_id < BrowserThread::ID_COUNT;
312 ++thread_id) {
313 scoped_ptr<BrowserProcessSubThread>* thread_to_start = NULL;
314 base::Thread::Options* options = &default_options;
315
316 switch (thread_id) {
317 case BrowserThread::DB:
318 thread_to_start = &db_thread_;
319 break;
320 case BrowserThread::WEBKIT:
321 // For now, the WebKit thread in the browser is owned by
322 // ResourceDispatcherHost, not by the content framework. Until
323 // this is fixed, we don't start the thread but still call
324 // Pre/PostStartThread for the ID.
325 break;
326 case BrowserThread::FILE:
327 thread_to_start = &file_thread_;
328 #if defined(OS_WIN)
329 // On Windows, the FILE thread needs to be have a UI message loop
330 // which pumps messages in such a way that Google Update can
331 // communicate back to us.
332 options = &ui_message_loop_options;
333 #else
334 options = &io_message_loop_options;
335 #endif
336 break;
337 case BrowserThread::PROCESS_LAUNCHER:
338 thread_to_start = &process_launcher_thread_;
339 break;
340 case BrowserThread::CACHE:
341 thread_to_start = &cache_thread_;
342 options = &io_message_loop_options;
343 break;
344 case BrowserThread::IO:
345 thread_to_start = &io_thread_;
346 options = &io_message_loop_options;
347 break;
348 #if defined(OS_CHROMEOS)
349 case BrowserThread::WEB_SOCKET_PROXY:
350 thread_to_start = &web_socket_proxy_thread_;
351 options = &io_message_loop_options;
352 break;
353 #endif
354 case BrowserThread::UI:
355 case BrowserThread::ID_COUNT:
356 default:
357 NOTREACHED();
358 break;
359 }
360
361 BrowserThread::ID id = static_cast<BrowserThread::ID>(thread_id);
362
363 if (parts_.get())
364 parts_->PreStartThread(id);
365
366 if (thread_to_start) {
367 (*thread_to_start).reset(new BrowserProcessSubThread(id));
368 (*thread_to_start)->StartWithOptions(*options);
369 }
370
371 if (parts_.get())
372 parts_->PostStartThread(id);
373 }
374
375 if (parts_.get())
376 parts_->PreMainMessageLoopRun(); 265 parts_->PreMainMessageLoopRun();
377 266
378 TRACE_EVENT_BEGIN_ETW("BrowserMain:MESSAGE_LOOP", 0, ""); 267 TRACE_EVENT_BEGIN_ETW("BrowserMain:MESSAGE_LOOP", 0, "");
379 // If the UI thread blocks, the whole UI is unresponsive. 268 // If the UI thread blocks, the whole UI is unresponsive.
380 // Do not allow disk IO from the UI thread. 269 // Do not allow disk IO from the UI thread.
381 base::ThreadRestrictions::SetIOAllowed(false); 270 base::ThreadRestrictions::SetIOAllowed(false);
382 271
383 bool ran_main_loop = false; 272 bool ran_main_loop = false;
384 if (parts_.get()) 273 if (parts_.get())
385 ran_main_loop = parts_->MainMessageLoopRun(&result_code_); 274 ran_main_loop = parts_->MainMessageLoopRun(&result_code_);
386 275
387 if (!ran_main_loop) 276 if (!ran_main_loop)
388 MainMessageLoopRun(); 277 MainMessageLoopRun();
389 278
390 TRACE_EVENT_END_ETW("BrowserMain:MESSAGE_LOOP", 0, ""); 279 TRACE_EVENT_END_ETW("BrowserMain:MESSAGE_LOOP", 0, "");
391 280
392 if (completed_main_message_loop) 281 if (completed_main_message_loop)
393 *completed_main_message_loop = true; 282 *completed_main_message_loop = true;
394 283
395 ShutdownThreadsAndCleanUp();
396 }
397
398 void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
399 // Teardown may start in PostMainMessageLoopRun, and during teardown we
400 // need to be able to perform IO.
401 base::ThreadRestrictions::SetIOAllowed(true);
402 BrowserThread::PostTask(
403 BrowserThread::IO,
404 FROM_HERE,
405 NewRunnableFunction(&base::ThreadRestrictions::SetIOAllowed, true));
406
407 if (parts_.get()) 284 if (parts_.get())
408 parts_->PostMainMessageLoopRun(); 285 parts_->PostMainMessageLoopRun();
409
410 // Must be size_t so we can subtract from it.
411 for (size_t thread_id = BrowserThread::ID_COUNT - 1;
412 thread_id >= (BrowserThread::UI + 1);
413 --thread_id) {
414 // Find the thread object we want to stop. Looping over all valid
415 // BrowserThread IDs and DCHECKing on a missing case in the switch
416 // statement helps avoid a mismatch between this code and the
417 // BrowserThread::ID enumeration.
418 //
419 // The destruction order is the reverse order of occurrence in the
420 // BrowserThread::ID list. The rationale for the order is as
421 // follows (need to be filled in a bit):
422 //
423 // - (Not sure why the WEB_SOCKET_PROXY thread is stopped first.)
424 //
425 // - The IO thread is the only user of the CACHE thread.
426 //
427 // - The PROCESS_LAUNCHER thread must be stopped after IO in case
428 // the IO thread posted a task to terminate a process on the
429 // process launcher thread.
430 //
431 // - (Not sure why FILE needs to stop before WEBKIT.)
432 //
433 // - The WEBKIT thread (which currently is the responsibility of
434 // the embedder to stop, by destroying ResourceDispatcherHost
435 // before the DB thread is stopped)
436 //
437 // - (Not sure why DB stops last.)
438 scoped_ptr<BrowserProcessSubThread>* thread_to_stop = NULL;
439 switch (thread_id) {
440 case BrowserThread::DB:
441 thread_to_stop = &db_thread_;
442 break;
443 case BrowserThread::WEBKIT:
444 // For now, the WebKit thread in the browser is owned by
445 // ResourceDispatcherHost, not by the content framework. Until
446 // this is fixed, we don't stop the thread but still call
447 // Pre/PostStopThread for the ID.
448 break;
449 case BrowserThread::FILE:
450 thread_to_stop = &file_thread_;
451 break;
452 case BrowserThread::PROCESS_LAUNCHER:
453 thread_to_stop = &process_launcher_thread_;
454 break;
455 case BrowserThread::CACHE:
456 thread_to_stop = &cache_thread_;
457 break;
458 case BrowserThread::IO:
459 thread_to_stop = &io_thread_;
460 break;
461 #if defined(OS_CHROMEOS)
462 case BrowserThread::WEB_SOCKET_PROXY:
463 thread_to_stop = &web_socket_proxy_thread_;
464 break;
465 #endif
466 case BrowserThread::UI:
467 case BrowserThread::ID_COUNT:
468 default:
469 NOTREACHED();
470 break;
471 }
472
473 BrowserThread::ID id = static_cast<BrowserThread::ID>(thread_id);
474
475 if (parts_.get())
476 parts_->PreStopThread(id);
477 if (thread_to_stop)
478 thread_to_stop->reset();
479 if (parts_.get())
480 parts_->PostStopThread(id);
481 }
482
483 if (parts_.get())
484 parts_->PostDestroyThreads();
485 } 286 }
486 287
487 void BrowserMainLoop::InitializeMainThread() { 288 void BrowserMainLoop::InitializeMainThread() {
488 const char* kThreadName = "CrBrowserMain"; 289 const char* kThreadName = "CrBrowserMain";
489 base::PlatformThread::SetName(kThreadName); 290 base::PlatformThread::SetName(kThreadName);
490 main_message_loop_->set_thread_name(kThreadName); 291 main_message_loop_->set_thread_name(kThreadName);
491 292
492 // Register the main thread by instantiating it, but don't call any methods. 293 // Register the main thread by instantiating it, but don't call any methods.
493 main_thread_.reset(new BrowserThreadImpl(BrowserThread::UI, 294 main_thread_.reset(new BrowserThreadImpl(BrowserThread::UI,
494 MessageLoop::current())); 295 MessageLoop::current()));
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
539 MessageLoopForUI::current()->PostTask(FROM_HERE, parameters_.ui_task); 340 MessageLoopForUI::current()->PostTask(FROM_HERE, parameters_.ui_task);
540 341
541 #if defined(OS_MACOSX) 342 #if defined(OS_MACOSX)
542 MessageLoopForUI::current()->Run(); 343 MessageLoopForUI::current()->Run();
543 #else 344 #else
544 MessageLoopForUI::current()->RunWithDispatcher(NULL); 345 MessageLoopForUI::current()->RunWithDispatcher(NULL);
545 #endif 346 #endif
546 } 347 }
547 348
548 } // namespace content 349 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/browser_main_loop.h ('k') | content/browser/browser_process_sub_thread.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698