blob: 481ea542cbc5bef82cde00fa6bad08a7d382bf4c [file] [log] [blame]
// Copyright 2019 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 "chrome/updater/app/app_install.h"
#include <memory>
#include <string>
#include <vector>
#include "base/callback.h"
#include "base/check.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/sequence_checker.h"
#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/threading/thread_checker.h"
#include "base/threading/thread_restrictions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "base/win/atl.h"
#include "chrome/updater/update_service.h"
#include "chrome/updater/update_service_internal.h"
#include "chrome/updater/win/install_progress_observer.h"
#include "chrome/updater/win/ui/progress_wnd.h"
#include "chrome/updater/win/ui/resources/resources.grh"
#include "chrome/updater/win/ui/splash_screen.h"
#include "chrome/updater/win/ui/util.h"
#include "chrome/updater/win/win_util.h"
namespace updater {
namespace {
// TODO(sorin): remove the hardcoding of the application name.
// https://crbug.com/1065588
constexpr char16_t kAppNameChrome[] = u"Google Chrome";
// Implements a simple inter-thread communication protocol based on Windows
// messages exchanged between the application installer and its UI.
//
// Since the installer code and the UI code execute on different threads, the
// installer can't invoke directly functions exposed by the UI.
// This class translates a function call made by the installer to any of the
// overriden virtual functions into posting a window message with specific
// arguments to the progress window implemented by the UI. Handling such
// message consists of unpacking the arguments of the message, and invoking
// the UI code in the correct thread, which is the thread that owns the window.
class InstallProgressObserverIPC : public InstallProgressObserver {
public:
// Used as an inter-thread communication mechanism between the installer and
// UI threads.
static constexpr unsigned int WM_PROGRESS_WINDOW_IPC = WM_APP + 1;
explicit InstallProgressObserverIPC(ui::ProgressWnd* progress_wnd);
InstallProgressObserverIPC(const InstallProgressObserverIPC&) = delete;
InstallProgressObserverIPC& operator=(const InstallProgressObserverIPC&) =
delete;
~InstallProgressObserverIPC() override = default;
// Called by the window proc when a specific application message is processed
// by the progress window. This call always occurs in the context of the
// thread which owns the window.
void Invoke(WPARAM wparam, LPARAM lparam);
// Overrides for InstallProgressObserver.
// Called by the application installer code on the main udpater thread.
void OnCheckingForUpdate() override;
void OnUpdateAvailable(const std::u16string& app_id,
const std::u16string& app_name,
const std::u16string& version_string) override;
void OnWaitingToDownload(const std::u16string& app_id,
const std::u16string& app_name) override;
void OnDownloading(const std::u16string& app_id,
const std::u16string& app_name,
int time_remaining_ms,
int pos) override;
void OnWaitingRetryDownload(const std::u16string& app_id,
const std::u16string& app_name,
const base::Time& next_retry_time) override;
void OnWaitingToInstall(const std::u16string& app_id,
const std::u16string& app_name,
bool* can_start_install) override;
void OnInstalling(const std::u16string& app_id,
const std::u16string& app_name,
int time_remaining_ms,
int pos) override;
void OnPause() override;
void OnComplete(const ObserverCompletionInfo& observer_info) override;
private:
enum class IPCAppMessages {
kOnCheckingForUpdate = 0,
kOnUpdateAvailable,
kOnWaitingToDownload,
kOnDownloading,
kOnWaitingRetryDownload,
kOnWaitingToInstall,
kOnInstalling,
kOnPause,
kOnComplete,
};
struct ParamOnUpdateAvailable {
ParamOnUpdateAvailable() = default;
ParamOnUpdateAvailable(const ParamOnUpdateAvailable&) = delete;
ParamOnUpdateAvailable& operator=(const ParamOnUpdateAvailable&) = delete;
std::u16string app_id;
std::u16string app_name;
std::u16string version_string;
};
struct ParamOnDownloading {
ParamOnDownloading() = default;
ParamOnDownloading(const ParamOnDownloading&) = delete;
ParamOnDownloading& operator=(const ParamOnDownloading&) = delete;
std::u16string app_id;
std::u16string app_name;
int time_remaining_ms = 0;
int pos = 0;
};
struct ParamOnWaitingToInstall {
ParamOnWaitingToInstall() = default;
ParamOnWaitingToInstall(const ParamOnWaitingToInstall&) = delete;
ParamOnWaitingToInstall& operator=(const ParamOnWaitingToInstall&) = delete;
std::u16string app_id;
std::u16string app_name;
};
struct ParamOnInstalling {
ParamOnInstalling() = default;
ParamOnInstalling(const ParamOnInstalling&) = delete;
ParamOnInstalling& operator=(const ParamOnInstalling&) = delete;
std::u16string app_id;
std::u16string app_name;
int time_remaining_ms = 0;
int pos = 0;
};
struct ParamOnComplete {
ParamOnComplete() = default;
ParamOnComplete(const ParamOnComplete&) = delete;
ParamOnComplete& operator=(const ParamOnComplete&) = delete;
ObserverCompletionInfo observer_info;
};
THREAD_CHECKER(thread_checker_);
// This member is not owned by this class.
ui::ProgressWnd* progress_wnd_ = nullptr;
// The thread id of the thread which owns the |ProgressWnd|.
int window_thread_id_ = 0;
};
InstallProgressObserverIPC::InstallProgressObserverIPC(
ui::ProgressWnd* progress_wnd)
: progress_wnd_(progress_wnd),
window_thread_id_(
::GetWindowThreadProcessId(progress_wnd_->m_hWnd, nullptr)) {
DCHECK(progress_wnd);
DCHECK(progress_wnd->m_hWnd);
DCHECK(IsWindow(progress_wnd->m_hWnd));
}
void InstallProgressObserverIPC::OnCheckingForUpdate() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(progress_wnd_);
::PostThreadMessage(window_thread_id_, WM_PROGRESS_WINDOW_IPC,
static_cast<WPARAM>(IPCAppMessages::kOnCheckingForUpdate),
0);
}
void InstallProgressObserverIPC::OnUpdateAvailable(
const std::u16string& app_id,
const std::u16string& app_name,
const std::u16string& version_string) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(progress_wnd_);
std::unique_ptr<ParamOnUpdateAvailable> param_on_update_available =
std::make_unique<ParamOnUpdateAvailable>();
param_on_update_available->app_id = app_id;
param_on_update_available->app_name = app_name;
param_on_update_available->version_string = version_string;
::PostThreadMessage(
window_thread_id_, WM_PROGRESS_WINDOW_IPC,
static_cast<WPARAM>(IPCAppMessages::kOnUpdateAvailable),
reinterpret_cast<LPARAM>(param_on_update_available.release()));
}
void InstallProgressObserverIPC::OnWaitingToDownload(
const std::u16string& app_id,
const std::u16string& app_name) {
NOTREACHED();
}
void InstallProgressObserverIPC::OnDownloading(const std::u16string& app_id,
const std::u16string& app_name,
int time_remaining_ms,
int pos) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(progress_wnd_);
std::unique_ptr<ParamOnDownloading> param_on_downloading =
std::make_unique<ParamOnDownloading>();
param_on_downloading->app_id = app_id;
param_on_downloading->app_name = app_name;
param_on_downloading->time_remaining_ms = time_remaining_ms;
param_on_downloading->pos = pos;
::PostThreadMessage(window_thread_id_, WM_PROGRESS_WINDOW_IPC,
static_cast<WPARAM>(IPCAppMessages::kOnDownloading),
reinterpret_cast<LPARAM>(param_on_downloading.release()));
}
void InstallProgressObserverIPC::OnWaitingRetryDownload(
const std::u16string& app_id,
const std::u16string& app_name,
const base::Time& next_retry_time) {
NOTREACHED();
}
void InstallProgressObserverIPC::OnWaitingToInstall(
const std::u16string& app_id,
const std::u16string& app_name,
bool* can_start_install) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(progress_wnd_);
std::unique_ptr<ParamOnWaitingToInstall> param_on_waiting_to_install =
std::make_unique<ParamOnWaitingToInstall>();
param_on_waiting_to_install->app_id = app_id;
param_on_waiting_to_install->app_name = app_name;
::PostThreadMessage(
window_thread_id_, WM_PROGRESS_WINDOW_IPC,
static_cast<WPARAM>(IPCAppMessages::kOnWaitingToInstall),
reinterpret_cast<LPARAM>(param_on_waiting_to_install.release()));
}
void InstallProgressObserverIPC::OnInstalling(const std::u16string& app_id,
const std::u16string& app_name,
int time_remaining_ms,
int pos) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
// TODO(sorin): implement progress, https://crbug.com/1014594.
DCHECK(progress_wnd_);
std::unique_ptr<ParamOnInstalling> param_on_installing =
std::make_unique<ParamOnInstalling>();
param_on_installing->app_id = app_id;
param_on_installing->app_name = app_name;
param_on_installing->time_remaining_ms = time_remaining_ms;
param_on_installing->pos = pos;
::PostThreadMessage(window_thread_id_, WM_PROGRESS_WINDOW_IPC,
static_cast<WPARAM>(IPCAppMessages::kOnInstalling),
reinterpret_cast<LPARAM>(param_on_installing.release()));
}
void InstallProgressObserverIPC::OnPause() {
NOTREACHED();
}
void InstallProgressObserverIPC::OnComplete(
const ObserverCompletionInfo& observer_info) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(progress_wnd_);
std::unique_ptr<ParamOnComplete> param_on_complete =
std::make_unique<ParamOnComplete>();
param_on_complete->observer_info = observer_info;
::PostThreadMessage(window_thread_id_, WM_PROGRESS_WINDOW_IPC,
static_cast<WPARAM>(IPCAppMessages::kOnComplete),
reinterpret_cast<LPARAM>(param_on_complete.release()));
}
void InstallProgressObserverIPC::Invoke(WPARAM wparam, LPARAM lparam) {
DCHECK_EQ(::GetWindowThreadProcessId(progress_wnd_->m_hWnd, nullptr),
::GetCurrentThreadId());
auto* observer = static_cast<InstallProgressObserver*>(progress_wnd_);
switch (static_cast<IPCAppMessages>(wparam)) {
case IPCAppMessages::kOnCheckingForUpdate:
observer->OnCheckingForUpdate();
break;
case IPCAppMessages::kOnUpdateAvailable: {
std::unique_ptr<ParamOnUpdateAvailable> param_on_update_available(
reinterpret_cast<ParamOnUpdateAvailable*>(lparam));
observer->OnUpdateAvailable(param_on_update_available->app_id,
param_on_update_available->app_name,
param_on_update_available->version_string);
break;
}
case IPCAppMessages::kOnDownloading: {
std::unique_ptr<ParamOnDownloading> param_on_downloading(
reinterpret_cast<ParamOnDownloading*>(lparam));
observer->OnDownloading(
param_on_downloading->app_id, param_on_downloading->app_name,
param_on_downloading->time_remaining_ms, param_on_downloading->pos);
break;
}
case IPCAppMessages::kOnWaitingToInstall: {
std::unique_ptr<ParamOnWaitingToInstall> param_on_waiting_to_install(
reinterpret_cast<ParamOnWaitingToInstall*>(lparam));
// TODO(sorin): implement cancelling of an install. crbug.com/1014591
bool can_install = false;
observer->OnWaitingToInstall(param_on_waiting_to_install->app_id,
param_on_waiting_to_install->app_name,
&can_install);
break;
}
case IPCAppMessages::kOnInstalling: {
std::unique_ptr<ParamOnInstalling> param_on_installing(
reinterpret_cast<ParamOnInstalling*>(lparam));
observer->OnInstalling(
param_on_installing->app_id, param_on_installing->app_name,
param_on_installing->time_remaining_ms, param_on_installing->pos);
break;
}
case IPCAppMessages::kOnComplete: {
std::unique_ptr<ParamOnComplete> param_on_complete(
reinterpret_cast<ParamOnComplete*>(lparam));
observer->OnComplete(param_on_complete->observer_info);
break;
}
default:
NOTREACHED();
break;
}
}
// Implements installing a single application by invoking the code in
// |UpdateService|, listening to |UpdateService| and UI events, and
// driving the UI code by calling the functions exposed by
// |InstallProgressObserver|. This class receives state changes for an install
// and it notifies the UI, which is an observer of this class.
//
// The UI code can't run in a thread where the message loop is an instance of
// |base::MessageLoop|. |base::MessageLoop| does not handle all the messages
// needed by the UI, since the UI is written in terms of WTL, and it requires
// a |WTL::MessageLoop| to work, for example, accelerators, dialog messages,
// TAB key, etc are all handled by WTL. Therefore, the UI code runs on its own
// thread. This thread owns all the UI objects, which must be created and
// destroyed on this thread. The rest of the code in this class runs on
// the updater main thread.
//
// This class controls the lifetime of the UI thread. Once the UI thread is
// created, it is going to run a message loop until the main thread initiates
// its teardown by posting a WM_QUIT message to it. This makes the UI message
// loop exit, and after that, the execution flow returns to the scheduler task,
// which has been running the UI message loop. Upon its completion, the task
// posts a reply to the main thread, which makes the main thread exit its run
// loop, and then the main thread returns to the destructor of this class,
// and destructs its class members.
class AppInstallControllerImpl : public AppInstallController,
public ui::ProgressWndEvents,
public WTL::CMessageFilter {
public:
AppInstallControllerImpl();
AppInstallControllerImpl(const AppInstallControllerImpl&) = delete;
AppInstallControllerImpl& operator=(const AppInstallControllerImpl&) = delete;
// Override for AppInstallController.
void InstallApp(const std::string& app_id,
base::OnceCallback<void(int)> callback) override;
private:
friend class base::RefCountedThreadSafe<AppInstallControllerImpl>;
~AppInstallControllerImpl() override;
// Overrides for OmahaWndEvents. These functions are called on the UI thread.
void DoClose() override {}
void DoExit() override;
// Overrides for CompleteWndEvents. This function is called on the UI thread.
bool DoLaunchBrowser(const std::u16string& url) override;
// Overrides for ProgressWndEvents. These functions are called on the UI
// thread.
bool DoRestartBrowser(bool restart_all_browsers,
const std::vector<std::u16string>& urls) override;
bool DoReboot() override;
void DoCancel() override {}
// Overrides for WTL::CMessageFilter.
BOOL PreTranslateMessage(MSG* msg) override;
// These functions are called on the UI thread.
void InitializeUI();
void RunUI();
// These functions are called on the main updater thread.
void DoInstallApp();
void InstallComplete(UpdateService::Result result);
void HandleInstallResult(const UpdateService::UpdateState& update_state);
// Returns the thread id of the thread which owns the progress window.
DWORD GetUIThreadID() const;
// Receives the state changes during handling of the Install function call.
void StateChange(UpdateService::UpdateState update_state);
SEQUENCE_CHECKER(sequence_checker_);
// Provides an execution environment for the updater main thread.
scoped_refptr<base::SequencedTaskRunner> main_task_runner_;
// Provides an execution environment for the UI code. Typically, it runs
// a single task which is the UI run loop.
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
// The application ID and the associated application name. The application
// name is displayed by the UI and it must be i18n.
std::string app_id_;
const std::u16string app_name_;
// The out-of-process service used for making RPC calls to install the app.
scoped_refptr<UpdateService> update_service_;
// The message loop associated with the UI.
std::unique_ptr<WTL::CMessageLoop> ui_message_loop_;
// The progress window.
std::unique_ptr<ui::ProgressWnd> progress_wnd_;
// The adapter for the inter-thread calls between the updater main thread
// and the UI thread.
std::unique_ptr<InstallProgressObserverIPC> install_progress_observer_ipc_;
// Called when InstallApp is done.
base::OnceCallback<void(int)> callback_;
};
// TODO(sorin): fix the hardcoding of the application name.
// https:crbug.com/1014298
AppInstallControllerImpl::AppInstallControllerImpl()
: main_task_runner_(base::SequencedTaskRunnerHandle::Get()),
ui_task_runner_(base::ThreadPool::CreateSingleThreadTaskRunner(
{base::TaskPriority::USER_BLOCKING,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
base::SingleThreadTaskRunnerThreadMode::DEDICATED)),
app_name_(kAppNameChrome) {}
AppInstallControllerImpl::~AppInstallControllerImpl() = default;
void AppInstallControllerImpl::InstallApp(
const std::string& app_id,
base::OnceCallback<void(int)> callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(base::ThreadTaskRunnerHandle::IsSet());
app_id_ = app_id;
callback_ = std::move(callback);
ui_task_runner_->PostTaskAndReply(
FROM_HERE, base::BindOnce(&AppInstallControllerImpl::InitializeUI, this),
base::BindOnce(&AppInstallControllerImpl::DoInstallApp, this));
}
void AppInstallControllerImpl::DoInstallApp() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// At this point, the UI has been initialized, which means the UI can be
// used from now on as an observer of the application install. The task
// below runs the UI message loop for the UI until it exits, because
// a WM_QUIT message has been posted to it.
ui_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&AppInstallControllerImpl::RunUI, this));
update_service_ = CreateUpdateService();
install_progress_observer_ipc_ =
std::make_unique<InstallProgressObserverIPC>(progress_wnd_.get());
update_service_->Update(
app_id_, UpdateService::Priority::kForeground,
base::BindRepeating(&AppInstallControllerImpl::StateChange, this),
base::BindOnce(&AppInstallControllerImpl::InstallComplete, this));
}
// TODO(crbug.com/1218219) - propagate error code in case of errors.
void AppInstallControllerImpl::InstallComplete(UpdateService::Result result) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (result == UpdateService::Result::kServiceFailed) {
UpdateService::UpdateState update_state;
update_state.app_id = app_id_;
update_state.state = UpdateService::UpdateState::State::kUpdateError;
update_state.error_category = UpdateService::ErrorCategory::kService;
update_state.error_code = -1;
HandleInstallResult(update_state);
}
update_service_ = nullptr;
}
void AppInstallControllerImpl::StateChange(
UpdateService::UpdateState update_state) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(install_progress_observer_ipc_);
CHECK_EQ(app_id_, update_state.app_id);
const auto app_id = base::ASCIIToUTF16(app_id_);
switch (update_state.state) {
case UpdateService::UpdateState::State::kCheckingForUpdates:
install_progress_observer_ipc_->OnCheckingForUpdate();
break;
case UpdateService::UpdateState::State::kUpdateAvailable:
install_progress_observer_ipc_->OnUpdateAvailable(
app_id, app_name_,
base::ASCIIToUTF16(update_state.next_version.GetString()));
break;
case UpdateService::UpdateState::State::kDownloading: {
// TODO(sorin): handle time remaining https://crbug.com/1014590.
const auto pos = GetDownloadProgress(update_state.downloaded_bytes,
update_state.total_bytes);
install_progress_observer_ipc_->OnDownloading(app_id, app_name_, -1,
pos != -1 ? pos : 0);
} break;
case UpdateService::UpdateState::State::kInstalling: {
// TODO(sorin): handle the install cancellation.
// https://crbug.com/1014591
bool can_start_install = false;
install_progress_observer_ipc_->OnWaitingToInstall(app_id, app_name_,
&can_start_install);
const int pos = update_state.install_progress;
install_progress_observer_ipc_->OnInstalling(app_id, app_name_, 0,
pos != -1 ? pos : 0);
break;
}
case UpdateService::UpdateState::State::kUpdated:
case UpdateService::UpdateState::State::kNoUpdate:
case UpdateService::UpdateState::State::kUpdateError:
HandleInstallResult(update_state);
break;
case UpdateService::UpdateState::State::kUnknown:
case UpdateService::UpdateState::State::kNotStarted:
break;
}
}
void AppInstallControllerImpl::HandleInstallResult(
const UpdateService::UpdateState& update_state) {
CompletionCodes completion_code = CompletionCodes::COMPLETION_CODE_ERROR;
std::wstring completion_text;
switch (update_state.state) {
case UpdateService::UpdateState::State::kUpdated:
VLOG(1) << "Update success.";
completion_code = CompletionCodes::COMPLETION_CODE_SUCCESS;
ui::LoadString(IDS_BUNDLE_INSTALLED_SUCCESSFULLY, &completion_text);
break;
case UpdateService::UpdateState::State::kNoUpdate:
VLOG(1) << "No updates.";
completion_code = CompletionCodes::COMPLETION_CODE_ERROR;
ui::LoadString(IDS_NO_UPDATE_RESPONSE, &completion_text);
break;
case UpdateService::UpdateState::State::kUpdateError:
VLOG(1) << "Updater error: " << update_state.error_code << ".";
completion_code = CompletionCodes::COMPLETION_CODE_ERROR;
ui::LoadString(IDS_INSTALL_FAILED, &completion_text);
break;
default:
NOTREACHED();
break;
}
ObserverCompletionInfo observer_info;
observer_info.completion_code = completion_code;
observer_info.completion_text = completion_text;
// TODO(sorin): implement handling the help URL. https://crbug.com/1014622
observer_info.help_url = u"http://www.google.com";
// TODO(sorin): implement the installer API and provide the
// application info in the observer info. https://crbug.com/1014630
observer_info.apps_info.push_back({});
install_progress_observer_ipc_->OnComplete(observer_info);
}
// Creates and shows the progress window. The window has thread affinity. It
// must be created, process its messages, and be destroyed on the same thread.
void AppInstallControllerImpl::InitializeUI() {
DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
base::ScopedDisallowBlocking no_blocking_allowed_on_ui_thread;
ui_message_loop_ = std::make_unique<WTL::CMessageLoop>();
ui_message_loop_->AddMessageFilter(this);
progress_wnd_ =
std::make_unique<ui::ProgressWnd>(ui_message_loop_.get(), nullptr);
progress_wnd_->SetEventSink(this);
progress_wnd_->Initialize();
progress_wnd_->Show();
}
void AppInstallControllerImpl::RunUI() {
DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
DCHECK_EQ(GetUIThreadID(), GetCurrentThreadId());
ui_message_loop_->Run();
ui_message_loop_->RemoveMessageFilter(this);
// This object is owned by the UI thread must be destroyed on this thread.
progress_wnd_ = nullptr;
main_task_runner_->PostTask(FROM_HERE,
base::BindOnce(std::move(callback_), 0));
}
void AppInstallControllerImpl::DoExit() {
DCHECK_EQ(GetUIThreadID(), GetCurrentThreadId());
PostThreadMessage(GetCurrentThreadId(), WM_QUIT, 0, 0);
}
BOOL AppInstallControllerImpl::PreTranslateMessage(MSG* msg) {
DCHECK_EQ(GetUIThreadID(), GetCurrentThreadId());
if (msg->message == InstallProgressObserverIPC::WM_PROGRESS_WINDOW_IPC) {
install_progress_observer_ipc_->Invoke(msg->wParam, msg->lParam);
return true;
}
return false;
}
DWORD AppInstallControllerImpl::GetUIThreadID() const {
DCHECK(progress_wnd_);
return ::GetWindowThreadProcessId(progress_wnd_->m_hWnd, nullptr);
}
bool AppInstallControllerImpl::DoLaunchBrowser(const std::u16string& url) {
DCHECK_EQ(GetUIThreadID(), GetCurrentThreadId());
return false;
}
bool AppInstallControllerImpl::DoRestartBrowser(
bool restart_all_browsers,
const std::vector<std::u16string>& urls) {
DCHECK_EQ(GetUIThreadID(), GetCurrentThreadId());
return false;
}
bool AppInstallControllerImpl::DoReboot() {
DCHECK_EQ(GetUIThreadID(), GetCurrentThreadId());
return false;
}
} // namespace
scoped_refptr<App> MakeAppInstall() {
return base::MakeRefCounted<AppInstall>(
base::BindRepeating([]() -> std::unique_ptr<SplashScreen> {
return std::make_unique<ui::SplashScreen>(kAppNameChrome);
}),
base::BindRepeating([]() -> scoped_refptr<AppInstallController> {
return base::MakeRefCounted<AppInstallControllerImpl>();
}));
}
} // namespace updater