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

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

Issue 8477004: Have content/ create and destroy its own threads. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Temporary - look at browser_list, browser_main_loop, content/p/b/browser_shutdown 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
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"
19 #include "content/public/browser/content_browser_client.h" 20 #include "content/public/browser/content_browser_client.h"
20 #include "content/public/common/content_switches.h" 21 #include "content/public/common/content_switches.h"
21 #include "content/public/common/main_function_params.h" 22 #include "content/public/common/main_function_params.h"
22 #include "content/public/common/result_codes.h" 23 #include "content/public/common/result_codes.h"
23 #include "crypto/nss_util.h" 24 #include "crypto/nss_util.h"
24 #include "net/base/network_change_notifier.h" 25 #include "net/base/network_change_notifier.h"
25 #include "net/base/ssl_config_service.h" 26 #include "net/base/ssl_config_service.h"
26 #include "net/socket/client_socket_factory.h" 27 #include "net/socket/client_socket_factory.h"
27 #include "net/socket/tcp_client_socket.h" 28 #include "net/socket/tcp_client_socket.h"
28 29
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
138 GLibLogHandler, 139 GLibLogHandler,
139 NULL); 140 NULL);
140 } 141 }
141 } 142 }
142 #endif 143 #endif
143 144
144 } // namespace 145 } // namespace
145 146
146 namespace content { 147 namespace content {
147 148
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 namespace browser_shutdown {
174
175 void ImmediateShutdownAndExitProcess() {
176 BrowserShutdownImpl::ImmediateShutdownAndExitProcess();
177 }
178
179 } // namespace browser_shutdown
148 180
149 // BrowserMainLoop construction / destructione ============================= 181 // BrowserMainLoop construction / destructione =============================
150 182
151 BrowserMainLoop::BrowserMainLoop(const content::MainFunctionParams& parameters) 183 BrowserMainLoop::BrowserMainLoop(const content::MainFunctionParams& parameters)
152 : parameters_(parameters), 184 : parameters_(parameters),
153 parsed_command_line_(parameters.command_line), 185 parsed_command_line_(parameters.command_line),
154 result_code_(content::RESULT_CODE_NORMAL_EXIT) { 186 result_code_(content::RESULT_CODE_NORMAL_EXIT) {
187 DCHECK(!current_browser_main_loop);
188 current_browser_main_loop = this;
155 #if defined(OS_WIN) 189 #if defined(OS_WIN)
156 OleInitialize(NULL); 190 OleInitialize(NULL);
157 #endif 191 #endif
158 } 192 }
159 193
160 BrowserMainLoop::~BrowserMainLoop() { 194 BrowserMainLoop::~BrowserMainLoop() {
195 DCHECK_EQ(this, current_browser_main_loop);
196 current_browser_main_loop = NULL;
161 #if defined(OS_WIN) 197 #if defined(OS_WIN)
162 OleUninitialize(); 198 OleUninitialize();
163 #endif 199 #endif
164 } 200 }
165 201
166 void BrowserMainLoop::Init() { 202 void BrowserMainLoop::Init() {
167 parts_.reset( 203 parts_.reset(
168 GetContentClient()->browser()->CreateBrowserMainParts(parameters_)); 204 GetContentClient()->browser()->CreateBrowserMainParts(parameters_));
169 } 205 }
170 206
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 293
258 if (parts_.get()) 294 if (parts_.get())
259 parts_->PostMainMessageLoopStart(); 295 parts_->PostMainMessageLoopStart();
260 } 296 }
261 297
262 void BrowserMainLoop::RunMainMessageLoopParts( 298 void BrowserMainLoop::RunMainMessageLoopParts(
263 bool* completed_main_message_loop) { 299 bool* completed_main_message_loop) {
264 if (parts_.get()) 300 if (parts_.get())
265 parts_->PreMainMessageLoopRun(); 301 parts_->PreMainMessageLoopRun();
266 302
303 base::Thread::Options io_message_loop_options;
304 io_message_loop_options.message_loop_type = MessageLoop::TYPE_IO;
305 base::Thread::Options ui_message_loop_options;
306 ui_message_loop_options.message_loop_type = MessageLoop::TYPE_UI;
307
308 db_thread_.reset(new BrowserProcessSubThread(BrowserThread::DB));
309 db_thread_->Start();
310
311 file_thread_.reset(new BrowserProcessSubThread(BrowserThread::FILE));
312 #if defined(OS_WIN)
313 // On Windows, the FILE thread needs to be have a UI message loop
314 // which pumps messages in such a way that Google Update can
315 // communicate back to us.
316 file_thread_->StartWithOptions(ui_message_loop_options);
317 #else
318 file_thread_->StartWithOptions(io_message_loop_options);
319 #endif
320
321 process_launcher_thread_.reset(
322 new BrowserProcessSubThread(BrowserThread::PROCESS_LAUNCHER));
323 process_launcher_thread_->Start();
324
325 cache_thread_.reset(new BrowserProcessSubThread(BrowserThread::CACHE));
326 cache_thread_->StartWithOptions(io_message_loop_options);
327 io_thread_.reset(new BrowserProcessSubThread(BrowserThread::IO));
328 io_thread_->StartWithOptions(io_message_loop_options);
329 #if defined(OS_CHROMEOS)
330 web_socket_proxy_thread_.reset(
331 new BrowserProcessSubThread(BrowserThread::WEB_SOCKET_PROXY));
332 web_socket_proxy_thread_->StartWithOptions(io_message_loop_options);
333 #endif
334
335 if (parts_.get())
336 parts_->PreMainMessageLoopRunThreadsCreated();
337
267 TRACE_EVENT_BEGIN_ETW("BrowserMain:MESSAGE_LOOP", 0, ""); 338 TRACE_EVENT_BEGIN_ETW("BrowserMain:MESSAGE_LOOP", 0, "");
268 // If the UI thread blocks, the whole UI is unresponsive. 339 // If the UI thread blocks, the whole UI is unresponsive.
269 // Do not allow disk IO from the UI thread. 340 // Do not allow disk IO from the UI thread.
270 base::ThreadRestrictions::SetIOAllowed(false); 341 base::ThreadRestrictions::SetIOAllowed(false);
271 342
272 bool ran_main_loop = false; 343 bool ran_main_loop = false;
273 if (parts_.get()) 344 if (parts_.get())
274 ran_main_loop = parts_->MainMessageLoopRun(&result_code_); 345 ran_main_loop = parts_->MainMessageLoopRun(&result_code_);
275 346
276 if (!ran_main_loop) 347 if (!ran_main_loop)
277 MainMessageLoopRun(); 348 MainMessageLoopRun();
278 349
279 TRACE_EVENT_END_ETW("BrowserMain:MESSAGE_LOOP", 0, ""); 350 TRACE_EVENT_END_ETW("BrowserMain:MESSAGE_LOOP", 0, "");
280 351
281 if (completed_main_message_loop) 352 if (completed_main_message_loop)
282 *completed_main_message_loop = true; 353 *completed_main_message_loop = true;
283 354
355 ShutdownThreadsAndCleanUp();
356 }
357
358 void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
359 // Teardown may start in PostMainMessageLoopRun, and during teardown we
360 // need to be able to perform IO.
361 base::ThreadRestrictions::SetIOAllowed(true);
362 BrowserThread::PostTask(
363 BrowserThread::IO,
364 FROM_HERE,
365 NewRunnableFunction(&base::ThreadRestrictions::SetIOAllowed, true));
366
284 if (parts_.get()) 367 if (parts_.get())
285 parts_->PostMainMessageLoopRun(); 368 parts_->PostMainMessageLoopRun();
369
370 // Must be size_t so we can subtract from it.
371 for (size_t thread_id = BrowserThread::ID_COUNT - 1;
372 thread_id >= BrowserThread::DB;
373 --thread_id) {
374 // Find the thread object we want to stop. Looping over all valid
375 // BrowserThread IDs and DCHECKing on a missing case in the switch
376 // statement helps avoid a mismatch between this code and the
377 // BrowserThread::ID enumeration.
378 //
379 // The destruction order is the reverse order of occurrence in the
380 // BrowserThread::ID list. The rationale for the order is as
381 // follows (need to be filled in a bit):
382 //
383 // - (Not sure why the WEB_SOCKET_PROXY thread is stopped first.)
384 //
385 // - The IO thread is the only user of the CACHE thread.
386 //
387 // - The PROCESS_LAUNCHER thread must be stopped after IO in case
388 // the IO thread posted a task to terminate a process on the
389 // process launcher thread.
390 //
391 // - (Not sure why FILE needs to stop before WEBKIT.)
392 //
393 // - The WEBKIT thread (which currently is the responsibility of
394 // the embedder to stop, by destroying ResourceDispatcherHost
395 // before the DB thread is stopped)
396 //
397 // - (Not sure why DB stops last.)
398 scoped_ptr<BrowserProcessSubThread>* thread_to_stop = NULL;
399 switch (thread_id) {
400 case BrowserThread::UI:
401 case BrowserThread::ID_COUNT:
402 NOTREACHED();
403 break;
404 case BrowserThread::DB:
405 thread_to_stop = &db_thread_;
406 break;
407 case BrowserThread::WEBKIT:
408 // For now, the WebKit thread in the browser is owned by
409 // ResourceDispatcherHost, not by the content framework. Until
410 // this is fixed, we don't stop the thread but still call
411 // Pre/PostStopThread for the ID.
412 break;
413 case BrowserThread::FILE:
414 thread_to_stop = &file_thread_;
415 break;
416 case BrowserThread::PROCESS_LAUNCHER:
417 thread_to_stop = &process_launcher_thread_;
418 break;
419 case BrowserThread::CACHE:
420 thread_to_stop = &cache_thread_;
421 break;
422 case BrowserThread::IO:
423 thread_to_stop = &io_thread_;
424 break;
425 #if defined(OS_CHROMEOS)
426 case BrowserThread::WEB_SOCKET_PROXY:
427 thread_to_stop = &web_socket_proxy_thread_;
428 break;
429 #endif
430 }
431
432 BrowserThread::ID id = static_cast<BrowserThread::ID>(thread_id);
433
434 if (parts_.get())
435 parts_->PreStopThread(id);
436 if (thread_to_stop)
437 thread_to_stop->reset();
438 if (parts_.get())
439 parts_->PostStopThread(id);
440 }
441
442 if (parts_.get())
443 parts_->FinalCleanup();
286 } 444 }
287 445
288 void BrowserMainLoop::InitializeMainThread() { 446 void BrowserMainLoop::InitializeMainThread() {
289 const char* kThreadName = "CrBrowserMain"; 447 const char* kThreadName = "CrBrowserMain";
290 base::PlatformThread::SetName(kThreadName); 448 base::PlatformThread::SetName(kThreadName);
291 main_message_loop_->set_thread_name(kThreadName); 449 main_message_loop_->set_thread_name(kThreadName);
292 450
293 // Register the main thread by instantiating it, but don't call any methods. 451 // Register the main thread by instantiating it, but don't call any methods.
294 main_thread_.reset(new BrowserThreadImpl(BrowserThread::UI, 452 main_thread_.reset(new BrowserThreadImpl(BrowserThread::UI,
295 MessageLoop::current())); 453 MessageLoop::current()));
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
340 MessageLoopForUI::current()->PostTask(FROM_HERE, parameters_.ui_task); 498 MessageLoopForUI::current()->PostTask(FROM_HERE, parameters_.ui_task);
341 499
342 #if defined(OS_MACOSX) 500 #if defined(OS_MACOSX)
343 MessageLoopForUI::current()->Run(); 501 MessageLoopForUI::current()->Run();
344 #else 502 #else
345 MessageLoopForUI::current()->RunWithDispatcher(NULL); 503 MessageLoopForUI::current()->RunWithDispatcher(NULL);
346 #endif 504 #endif
347 } 505 }
348 506
349 } // namespace content 507 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698