cef/libcef/browser/ui_thread.cc

127 lines
3.6 KiB
C++

// Copyright 2020 The Chromium Embedded Framework Authors.
// Portions copyright 2014 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 "cef/libcef/browser/ui_thread.h"
#include "base/at_exit.h"
#include "base/logging.h"
#include "cef/libcef/browser/main_runner.h"
#include "cef/libcef/browser/thread_util.h"
#include "content/browser/scheduler/browser_task_executor.h"
#if BUILDFLAG(IS_LINUX)
#include "ui/base/ozone_buildflags.h"
#if BUILDFLAG(IS_OZONE_X11)
#include "ui/ozone/platform/x11/ozone_platform_x11.h"
#endif
#endif
#if BUILDFLAG(IS_WIN)
#include <Objbase.h>
#endif
CefUIThread::CefUIThread(CefMainRunner* runner,
base::OnceClosure setup_callback)
: runner_(runner), setup_callback_(std::move(setup_callback)) {}
CefUIThread::~CefUIThread() {
Stop();
}
void CefUIThread::Start() {
base::AutoLock lock(thread_lock_);
bool success = base::PlatformThread::CreateWithType(
0, this, &thread_, base::ThreadType::kDefault);
if (!success) {
LOG(FATAL) << "failed to UI create thread";
}
}
void CefUIThread::Stop() {
base::AutoLock lock(thread_lock_);
if (!stopping_) {
stopping_ = true;
CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefMainRunner::QuitMessageLoop,
base::Unretained(runner_)));
}
// Can't join if the |thread_| is either already gone or is non-joinable.
if (thread_.is_null()) {
return;
}
base::PlatformThread::Join(thread_);
thread_ = base::PlatformThreadHandle();
stopping_ = false;
}
bool CefUIThread::WaitUntilThreadStarted() const {
DCHECK(owning_sequence_checker_.CalledOnValidSequence());
start_event_.Wait();
return true;
}
void CefUIThread::InitializeBrowserRunner(
content::MainFunctionParams main_function_params) {
#if BUILDFLAG(IS_LINUX)
#if BUILDFLAG(IS_OZONE_X11)
// Disable creation of GtkUi (interface to GTK desktop features) and cause
// ui::GetDefaultLinuxUi() (and related functions) to return nullptr. We
// can't use GtkUi in combination with multi-threaded-message-loop because
// Chromium's GTK implementation doesn't use GDK threads. Light/dark theme
// changes will still be detected via DarkModeManagerLinux.
ui::SetMultiThreadedMessageLoopX11();
#endif
#endif
// Use our own browser process runner.
browser_runner_ = content::BrowserMainRunner::Create();
// Initialize browser process state. Uses the current thread's message loop.
int exit_code = browser_runner_->Initialize(std::move(main_function_params));
CHECK_EQ(exit_code, -1);
}
void CefUIThread::ThreadMain() {
base::PlatformThread::SetName("CefUIThread");
#if BUILDFLAG(IS_WIN)
// Initializes the COM library on the current thread.
CoInitialize(nullptr);
#endif
start_event_.Signal();
std::move(setup_callback_).Run();
runner_->RunMessageLoop();
// Stop may be called before InitializeBrowserRunner if
// content::ContentMainRun was not successful (for example, due to process
// singleton relaunch).
if (browser_runner_) {
browser_runner_->Shutdown();
browser_runner_.reset();
}
// This will be a no-op if there is no BrowserTaskExecutor.
content::BrowserTaskExecutor::Shutdown();
if (!shutdown_callback_.is_null()) {
std::move(shutdown_callback_).Run();
}
// Run exit callbacks on the UI thread to avoid sequence check failures.
base::AtExitManager::ProcessCallbacksNow();
#if BUILDFLAG(IS_WIN)
// Closes the COM library on the current thread. CoInitialize must
// be balanced by a corresponding call to CoUninitialize.
CoUninitialize();
#endif
}