
@QA: This CL is a no-op. The meaning of this phase has diverged and become increasingly confusing over the years. This is not the timing at which the main message loop starts but rather this is where it is created. The previous term is easily confused with things like VariationsService::PerformPreMainMessageLoopStartup startup_metric_utils::RecordBrowserMainMessageLoopStart that actually represent when the message loop starts. This confusion has led to new calls being associated with the wrong phase, e.g. https://chromium-review.googlesource.com/c/chromium/src/+/2685139/6#message-d1f863178a7982698d1ff5a032b79e33e9e1d5ce Bug: 1175074 Change-Id: I0535042abe69431501c9b3da3cfb2eae445fde0a Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2892278 Commit-Queue: Gabriel Charette <gab@chromium.org> Reviewed-by: John Abd-El-Malek <jam@chromium.org> Owners-Override: John Abd-El-Malek <jam@chromium.org> Cr-Commit-Position: refs/heads/master@{#883468}
212 lines
6.8 KiB
C++
212 lines
6.8 KiB
C++
// Copyright (c) 2012 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.
|
|
|
|
#include "content/browser/browser_main_runner_impl.h"
|
|
|
|
#include <memory>
|
|
|
|
#include "base/base_switches.h"
|
|
#include "base/check.h"
|
|
#include "base/command_line.h"
|
|
#include "base/debug/debugger.h"
|
|
#include "base/debug/leak_annotations.h"
|
|
#include "base/lazy_instance.h"
|
|
#include "base/metrics/histogram_macros.h"
|
|
#include "base/run_loop.h"
|
|
#include "base/synchronization/atomic_flag.h"
|
|
#include "base/time/time.h"
|
|
#include "base/trace_event/heap_profiler_allocation_context_tracker.h"
|
|
#include "base/trace_event/trace_event.h"
|
|
#include "build/build_config.h"
|
|
#include "components/tracing/common/trace_startup_config.h"
|
|
#include "components/tracing/common/tracing_switches.h"
|
|
#include "content/browser/browser_main_loop.h"
|
|
#include "content/browser/notification_service_impl.h"
|
|
#include "content/browser/tracing/startup_tracing_controller.h"
|
|
#include "content/common/content_switches_internal.h"
|
|
#include "content/public/common/content_switches.h"
|
|
#include "content/public/common/main_function_params.h"
|
|
#include "third_party/skia/include/core/SkGraphics.h"
|
|
#include "ui/base/ime/init/input_method_initializer.h"
|
|
#include "ui/gfx/font_util.h"
|
|
|
|
#if defined(OS_ANDROID)
|
|
#include "content/browser/android/tracing_controller_android.h"
|
|
#endif
|
|
|
|
#if defined(OS_WIN)
|
|
#include "base/win/windows_version.h"
|
|
#include "ui/base/win/scoped_ole_initializer.h"
|
|
#endif
|
|
|
|
namespace content {
|
|
namespace {
|
|
|
|
base::LazyInstance<base::AtomicFlag>::Leaky g_exited_main_message_loop;
|
|
|
|
} // namespace
|
|
|
|
// static
|
|
std::unique_ptr<BrowserMainRunnerImpl> BrowserMainRunnerImpl::Create() {
|
|
return std::make_unique<BrowserMainRunnerImpl>();
|
|
}
|
|
|
|
BrowserMainRunnerImpl::BrowserMainRunnerImpl()
|
|
: initialization_started_(false),
|
|
is_shutdown_(false),
|
|
scoped_execution_fence_(
|
|
std::make_unique<base::ThreadPoolInstance::ScopedExecutionFence>()) {}
|
|
|
|
BrowserMainRunnerImpl::~BrowserMainRunnerImpl() {
|
|
if (initialization_started_ && !is_shutdown_)
|
|
Shutdown();
|
|
}
|
|
|
|
int BrowserMainRunnerImpl::Initialize(const MainFunctionParams& parameters) {
|
|
SCOPED_UMA_HISTOGRAM_LONG_TIMER(
|
|
"Startup.BrowserMainRunnerImplInitializeLongTime");
|
|
TRACE_EVENT0("startup", "BrowserMainRunnerImpl::Initialize");
|
|
|
|
// On Android we normally initialize the browser in a series of UI thread
|
|
// tasks. While this is happening a second request can come from the OS or
|
|
// another application to start the browser. If this happens then we must
|
|
// not run these parts of initialization twice.
|
|
if (!initialization_started_) {
|
|
initialization_started_ = true;
|
|
|
|
const base::TimeTicks start_time_step1 = base::TimeTicks::Now();
|
|
|
|
SkGraphics::Init();
|
|
|
|
if (parameters.command_line.HasSwitch(switches::kWaitForDebugger))
|
|
base::debug::WaitForDebugger(60, true);
|
|
|
|
if (parameters.command_line.HasSwitch(switches::kBrowserStartupDialog))
|
|
WaitForDebugger("Browser");
|
|
|
|
notification_service_ = std::make_unique<NotificationServiceImpl>();
|
|
|
|
#if defined(OS_WIN)
|
|
// Ole must be initialized before starting message pump, so that TSF
|
|
// (Text Services Framework) module can interact with the message pump
|
|
// on Windows 8 Metro mode.
|
|
ole_initializer_ = std::make_unique<ui::ScopedOleInitializer>();
|
|
#endif // OS_WIN
|
|
|
|
gfx::InitializeFonts();
|
|
|
|
main_loop_ = std::make_unique<BrowserMainLoop>(
|
|
parameters, std::move(scoped_execution_fence_));
|
|
|
|
main_loop_->Init();
|
|
|
|
if (parameters.created_main_parts_closure) {
|
|
std::move(*parameters.created_main_parts_closure)
|
|
.Run(main_loop_->parts());
|
|
delete parameters.created_main_parts_closure;
|
|
}
|
|
|
|
const int early_init_error_code = main_loop_->EarlyInitialization();
|
|
if (early_init_error_code > 0)
|
|
return early_init_error_code;
|
|
|
|
// Must happen before we try to use a message loop or display any UI.
|
|
if (!main_loop_->InitializeToolkit())
|
|
return 1;
|
|
|
|
main_loop_->PreCreateMainMessageLoop();
|
|
main_loop_->CreateMainMessageLoop();
|
|
main_loop_->PostCreateMainMessageLoop();
|
|
|
|
// 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.
|
|
|
|
ui::InitializeInputMethod();
|
|
UMA_HISTOGRAM_TIMES("Startup.BrowserMainRunnerImplInitializeStep1Time",
|
|
base::TimeTicks::Now() - start_time_step1);
|
|
}
|
|
const base::TimeTicks start_time_step2 = base::TimeTicks::Now();
|
|
main_loop_->CreateStartupTasks();
|
|
int result_code = main_loop_->GetResultCode();
|
|
if (result_code > 0)
|
|
return result_code;
|
|
|
|
UMA_HISTOGRAM_TIMES("Startup.BrowserMainRunnerImplInitializeStep2Time",
|
|
base::TimeTicks::Now() - start_time_step2);
|
|
|
|
// Return -1 to indicate no early termination.
|
|
return -1;
|
|
}
|
|
|
|
#if defined(OS_ANDROID)
|
|
void BrowserMainRunnerImpl::SynchronouslyFlushStartupTasks() {
|
|
main_loop_->SynchronouslyFlushStartupTasks();
|
|
}
|
|
#endif
|
|
|
|
int BrowserMainRunnerImpl::Run() {
|
|
DCHECK(initialization_started_);
|
|
DCHECK(!is_shutdown_);
|
|
main_loop_->RunMainMessageLoop();
|
|
return main_loop_->GetResultCode();
|
|
}
|
|
|
|
void BrowserMainRunnerImpl::Shutdown() {
|
|
DCHECK(initialization_started_);
|
|
DCHECK(!is_shutdown_);
|
|
|
|
#ifdef LEAK_SANITIZER
|
|
// Invoke leak detection now, to avoid dealing with shutdown-only leaks.
|
|
// Normally this will have already happened in
|
|
// BroserProcessImpl::ReleaseModule(), so this call has no effect. This is
|
|
// only for processes which do not instantiate a BrowserProcess.
|
|
// If leaks are found, the process will exit here.
|
|
__lsan_do_leak_check();
|
|
#endif
|
|
|
|
main_loop_->PreShutdown();
|
|
|
|
// Finalize the startup tracing session if it is still active.
|
|
StartupTracingController::GetInstance().WaitUntilStopped();
|
|
|
|
{
|
|
// The trace event has to stay between profiler creation and destruction.
|
|
TRACE_EVENT0("shutdown", "BrowserMainRunner");
|
|
g_exited_main_message_loop.Get().Set();
|
|
|
|
main_loop_->ShutdownThreadsAndCleanUp();
|
|
|
|
ui::ShutdownInputMethod();
|
|
#if defined(OS_WIN)
|
|
ole_initializer_.reset(NULL);
|
|
#endif
|
|
#if defined(OS_ANDROID)
|
|
// Forcefully terminates the RunLoop inside MessagePumpForUI, ensuring
|
|
// proper shutdown for content_browsertests. Shutdown() is not used by
|
|
// the actual browser.
|
|
if (base::RunLoop::IsRunningOnCurrentThread())
|
|
base::RunLoop::QuitCurrentDeprecated();
|
|
#endif
|
|
main_loop_.reset(nullptr);
|
|
|
|
notification_service_.reset(nullptr);
|
|
|
|
is_shutdown_ = true;
|
|
}
|
|
}
|
|
|
|
// static
|
|
std::unique_ptr<BrowserMainRunner> BrowserMainRunner::Create() {
|
|
return BrowserMainRunnerImpl::Create();
|
|
}
|
|
|
|
// static
|
|
bool BrowserMainRunner::ExitedMainMessageLoop() {
|
|
return g_exited_main_message_loop.IsCreated() &&
|
|
g_exited_main_message_loop.Get().IsSet();
|
|
}
|
|
|
|
} // namespace content
|