blob: e500006fe3d9fd84933ff9484c09a9840be82e40 [file] [log] [blame]
// Copyright 2020 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 <utility>
#include "base/bind.h"
#include "base/callback.h"
#include "base/check.h"
#include "base/command_line.h"
#include "base/i18n/icu_util.h"
#include "base/logging.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_task_runner_handle.h"
#include "base/version.h"
#include "build/build_config.h"
#include "chrome/updater/constants.h"
#include "chrome/updater/control_service.h"
#include "chrome/updater/persisted_data.h"
#include "chrome/updater/prefs.h"
#include "chrome/updater/registration_data.h"
#include "chrome/updater/setup.h"
#include "chrome/updater/update_service.h"
#include "chrome/updater/updater_version.h"
#include "components/prefs/pref_service.h"
namespace updater {
#if !defined(OS_WIN)
namespace {
class SplashScreenImpl : public SplashScreen {
public:
// Overrides for SplashScreen.
void Show() override {}
void Dismiss(base::OnceClosure callback) override {
base::SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE,
std::move(callback));
}
};
class AppInstallControllerImpl : public AppInstallController {
public:
// Override for AppInstallController.
void InstallApp(const std::string& app_id,
base::OnceCallback<void(int)> callback) override {
base::SequencedTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), 0));
}
protected:
~AppInstallControllerImpl() override = default;
};
} // namespace
scoped_refptr<App> MakeAppInstall() {
return base::MakeRefCounted<AppInstall>(
base::BindRepeating([]() -> std::unique_ptr<SplashScreen> {
return std::make_unique<SplashScreenImpl>();
}),
base::BindRepeating([]() -> scoped_refptr<AppInstallController> {
return base::MakeRefCounted<AppInstallControllerImpl>();
}));
}
#endif // !defined(OS_WIN)
AppInstall::AppInstall(SplashScreen::Maker splash_screen_maker,
AppInstallController::Maker app_install_controller_maker)
: splash_screen_maker_(std::move(splash_screen_maker)),
app_install_controller_maker_(app_install_controller_maker) {
DCHECK(splash_screen_maker_);
DCHECK(app_install_controller_maker_);
}
AppInstall::~AppInstall() = default;
void AppInstall::Initialize() {
base::i18n::InitializeICU();
}
void AppInstall::FirstTaskRun() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(base::ThreadTaskRunnerHandle::IsSet());
splash_screen_ = splash_screen_maker_.Run();
splash_screen_->Show();
base::ThreadPool::PostTask(
FROM_HERE,
{base::MayBlock(), base::TaskPriority::USER_BLOCKING,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
base::BindOnce(
&InstallCandidate, false, base::SequencedTaskRunnerHandle::Get(),
base::BindOnce(
[](SplashScreen* splash_screen,
base::OnceCallback<void(int)> done, int result) {
splash_screen->Dismiss(base::BindOnce(std::move(done), result));
},
splash_screen_.get(),
base::BindOnce(&AppInstall::InstallCandidateDone, this))));
}
void AppInstall::InstallCandidateDone(int result) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (result != 0) {
Shutdown(result);
return;
}
// Invoke ControlService::Run to wake this version of the updater, do an
// update check, and possibly promote this version as a result.
// The instance of |CreateControlService| has sequence affinity. Bind it
// in the closure to ensure it is released in this sequence.
scoped_refptr<ControlService> control_service = CreateControlService();
control_service->Run(base::BindOnce(
[](scoped_refptr<ControlService> /*control_service*/,
scoped_refptr<AppInstall> app_install) {
app_install->RegisterUpdater();
},
control_service, base::WrapRefCounted(this)));
}
void AppInstall::RegisterUpdater() {
// TODO(crbug.com/1128060): We should update the updater's registration with
// the new version, brand code, etc. For now, fake it.
RegistrationResponse result;
result.status_code = 0;
RegisterUpdaterDone(result);
}
void AppInstall::RegisterUpdaterDone(const RegistrationResponse& response) {
VLOG(1) << "Updater registration complete, code = " << response.status_code;
HandleAppId();
}
void AppInstall::HandleAppId() {
const std::string app_id =
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(kAppIdSwitch);
if (app_id.empty()) {
Shutdown(0);
return;
}
app_install_controller_ = app_install_controller_maker_.Run();
app_install_controller_->InstallApp(
app_id, base::BindOnce(&AppInstall::Shutdown, this));
}
} // namespace updater