Commit 91ce318b authored by Joshua Pawlicki's avatar Joshua Pawlicki Committed by Commit Bot

updater: Promote to active using RPC in the --install case.

Also fixes a missing init in Mac server and a threading assert in Mac
DMG installation.

Also simplifies some integration testing.

Bug: 1122739, 1063435
Change-Id: I73b30e36aa5d18cbd4618717a8b617538843f08b
Fixed: 1122739
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2410818
Commit-Queue: Joshua Pawlicki <waffles@chromium.org>
Reviewed-by: default avatarSorin Jianu <sorin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#807022}
parent 4b1a557d
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "base/check.h" #include "base/check.h"
#include "base/command_line.h" #include "base/command_line.h"
#include "base/i18n/icu_util.h" #include "base/i18n/icu_util.h"
#include "base/logging.h"
#include "base/task/task_traits.h" #include "base/task/task_traits.h"
#include "base/task/thread_pool.h" #include "base/task/thread_pool.h"
#include "base/threading/sequenced_task_runner_handle.h" #include "base/threading/sequenced_task_runner_handle.h"
...@@ -21,7 +22,9 @@ ...@@ -21,7 +22,9 @@
#include "chrome/updater/control_service.h" #include "chrome/updater/control_service.h"
#include "chrome/updater/persisted_data.h" #include "chrome/updater/persisted_data.h"
#include "chrome/updater/prefs.h" #include "chrome/updater/prefs.h"
#include "chrome/updater/registration_data.h"
#include "chrome/updater/setup.h" #include "chrome/updater/setup.h"
#include "chrome/updater/update_service.h"
#include "chrome/updater/updater_version.h" #include "chrome/updater/updater_version.h"
#include "components/prefs/pref_service.h" #include "components/prefs/pref_service.h"
...@@ -78,13 +81,6 @@ AppInstall::~AppInstall() = default; ...@@ -78,13 +81,6 @@ AppInstall::~AppInstall() = default;
void AppInstall::Initialize() { void AppInstall::Initialize() {
base::i18n::InitializeICU(); base::i18n::InitializeICU();
// Creating |global_prefs_| requires acquiring a global lock, and this lock is
// typically owned by the RPC server. That means that if the server is
// running, the following code will block, and the install will not proceed
// until the server releases the lock.
global_prefs_ = CreateGlobalPrefs();
local_prefs_ = CreateLocalPrefs();
} }
void AppInstall::FirstTaskRun() { void AppInstall::FirstTaskRun() {
...@@ -94,22 +90,21 @@ void AppInstall::FirstTaskRun() { ...@@ -94,22 +90,21 @@ void AppInstall::FirstTaskRun() {
splash_screen_ = splash_screen_maker_.Run(); splash_screen_ = splash_screen_maker_.Run();
splash_screen_->Show(); splash_screen_->Show();
base::ThreadPool::PostTaskAndReplyWithResult( base::ThreadPool::PostTask(
FROM_HERE, FROM_HERE,
{base::MayBlock(), base::TaskPriority::USER_BLOCKING, {base::MayBlock(), base::TaskPriority::USER_BLOCKING,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
base::BindOnce([]() { return InstallCandidate(false); }),
base::BindOnce( base::BindOnce(
[](SplashScreen* splash_screen, base::OnceCallback<void(int)> done, &InstallCandidate, false, base::SequencedTaskRunnerHandle::Get(),
int result) { base::BindOnce(
splash_screen->Dismiss(base::BindOnce(std::move(done), result)); [](SplashScreen* splash_screen,
}, base::OnceCallback<void(int)> done, int result) {
splash_screen_.get(), splash_screen->Dismiss(base::BindOnce(std::move(done), result));
base::BindOnce(&AppInstall::InstallCandidateDone, this))); },
splash_screen_.get(),
base::BindOnce(&AppInstall::InstallCandidateDone, this))));
} }
// Updates the prefs if installing the updater is successful, then continue
// installing the application if --app-id is specified on the command line.
void AppInstall::InstallCandidateDone(int result) { void AppInstall::InstallCandidateDone(int result) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
...@@ -118,50 +113,42 @@ void AppInstall::InstallCandidateDone(int result) { ...@@ -118,50 +113,42 @@ void AppInstall::InstallCandidateDone(int result) {
return; return;
} }
// Invoke |HandleAppId| to continue the execution flow. // Invoke ControlService::Run to wake this version of the updater, do an
MakeActive(base::BindOnce(&AppInstall::HandleAppId, this)); // 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::HandleAppId() { void AppInstall::RegisterUpdater() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // 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);
}
// This releases the prefs lock, and the RPC server can be started. void AppInstall::RegisterUpdaterDone(const RegistrationResponse& response) {
global_prefs_ = nullptr; VLOG(1) << "Updater registration complete, code = " << response.status_code;
local_prefs_ = nullptr; HandleAppId();
}
// If no app id is provided, then invoke ControlService::Run to wake void AppInstall::HandleAppId() {
// this version of the updater, do an update check, and possibly promote
// this version as a result.
const std::string app_id = const std::string app_id =
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(kAppIdSwitch); base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(kAppIdSwitch);
if (app_id.empty()) { if (app_id.empty()) {
// The instance of |CreateControlService| has sequence affinity. Bind it Shutdown(0);
// 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->Shutdown(0); },
control_service, base::WrapRefCounted(this)));
return; return;
} }
app_install_controller_ = app_install_controller_maker_.Run(); app_install_controller_ = app_install_controller_maker_.Run();
app_install_controller_->InstallApp( app_install_controller_->InstallApp(
app_id, base::BindOnce(&AppInstall::Shutdown, this)); app_id, base::BindOnce(&AppInstall::Shutdown, this));
} }
// TODO(crbug.com/1109231) - this is a temporary workaround.
void AppInstall::MakeActive(base::OnceClosure done) {
local_prefs_->SetQualified(true);
local_prefs_->GetPrefService()->CommitPendingWrite(base::BindOnce(
[](base::OnceClosure done, PrefService* pref_service) {
DCHECK(pref_service);
auto persisted_data = base::MakeRefCounted<PersistedData>(pref_service);
persisted_data->SetProductVersion(
kUpdaterAppId, base::Version(UPDATER_VERSION_STRING));
pref_service->CommitPendingWrite(std::move(done));
},
std::move(done), global_prefs_->GetPrefService()));
}
} // namespace updater } // namespace updater
...@@ -20,13 +20,12 @@ class TaskRunner; ...@@ -20,13 +20,12 @@ class TaskRunner;
namespace updater { namespace updater {
class LocalPrefs; struct RegistrationResponse;
class GlobalPrefs;
// This class defines an interface for installing an application. The interface // This class defines an interface for installing an application. The interface
// is intended to be implemented for scenerios where UI and RPC calls to // is intended to be implemented for scenerios where UI and RPC calls to
// |UpdateService| are involved, hence the word `controller` in the name of // |UpdateService| are involved, hence the word `controller` in the name of
// the ]interface. // the interface.
class AppInstallController class AppInstallController
: public base::RefCountedThreadSafe<AppInstallController> { : public base::RefCountedThreadSafe<AppInstallController> {
public: public:
...@@ -57,14 +56,14 @@ class AppInstall : public App { ...@@ -57,14 +56,14 @@ class AppInstall : public App {
void InstallCandidateDone(int result); void InstallCandidateDone(int result);
void RegisterUpdater();
void RegisterUpdaterDone(const RegistrationResponse& response);
// Handles the --app-id command line argument, and triggers installing of the // Handles the --app-id command line argument, and triggers installing of the
// corresponding app-id if the argument is present. // corresponding app-id if the argument is present.
void HandleAppId(); void HandleAppId();
// Makes this version of the updater active, self-registers for updates, then
// runs the |done| closure.
void MakeActive(base::OnceClosure done);
// Bound to the main sequence. // Bound to the main sequence.
SEQUENCE_CHECKER(sequence_checker_); SEQUENCE_CHECKER(sequence_checker_);
...@@ -80,14 +79,6 @@ class AppInstall : public App { ...@@ -80,14 +79,6 @@ class AppInstall : public App {
scoped_refptr<AppInstallController> app_install_controller_; scoped_refptr<AppInstallController> app_install_controller_;
// These prefs objects are used to make the updater active and register this
// version of the updater for self-updates.
//
// TODO(crbug.com/1109231) - this is a temporary workaround until a better
// fix is found.
std::unique_ptr<LocalPrefs> local_prefs_;
std::unique_ptr<GlobalPrefs> global_prefs_;
scoped_refptr<base::TaskRunner> make_active_task_runner_; scoped_refptr<base::TaskRunner> make_active_task_runner_;
}; };
......
...@@ -134,9 +134,11 @@ void AppRegister::RegisterAppDone(const RegistrationResponse& response) { ...@@ -134,9 +134,11 @@ void AppRegister::RegisterAppDone(const RegistrationResponse& response) {
return; return;
} }
base::ThreadPool::PostTaskAndReplyWithResult( base::ThreadPool::PostTask(
FROM_HERE, {base::MayBlock()}, base::BindOnce(&InstallCandidate, false), FROM_HERE, {base::MayBlock()},
base::BindOnce(&AppRegister::InstallCandidateDone, this)); base::BindOnce(&InstallCandidate, false,
base::SequencedTaskRunnerHandle::Get(),
base::BindOnce(&AppRegister::InstallCandidateDone, this)));
} }
void AppRegister::InstallCandidateDone(int result) { void AppRegister::InstallCandidateDone(int result) {
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "base/version.h" #include "base/version.h"
#include "chrome/updater/configurator.h" #include "chrome/updater/configurator.h"
#include "chrome/updater/constants.h" #include "chrome/updater/constants.h"
#include "chrome/updater/persisted_data.h"
#include "chrome/updater/prefs.h" #include "chrome/updater/prefs.h"
#include "chrome/updater/updater_version.h" #include "chrome/updater/updater_version.h"
#include "components/prefs/pref_service.h" #include "components/prefs/pref_service.h"
...@@ -78,6 +79,12 @@ bool AppServer::SwapVersions(GlobalPrefs* global_prefs) { ...@@ -78,6 +79,12 @@ bool AppServer::SwapVersions(GlobalPrefs* global_prefs) {
if (!result) if (!result)
return false; return false;
global_prefs->SetActiveVersion(UPDATER_VERSION_STRING); global_prefs->SetActiveVersion(UPDATER_VERSION_STRING);
scoped_refptr<PersistedData> persisted_data =
base::MakeRefCounted<PersistedData>(global_prefs->GetPrefService());
if (!persisted_data->GetProductVersion(kUpdaterAppId).IsValid()) {
persisted_data->SetProductVersion(kUpdaterAppId,
base::Version(UPDATER_VERSION_STRING));
}
global_prefs->SetSwapping(false); global_prefs->SetSwapping(false);
PrefsCommitPendingWrites(global_prefs->GetPrefService()); PrefsCommitPendingWrites(global_prefs->GetPrefService());
return true; return true;
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/task/task_traits.h" #include "base/task/task_traits.h"
#include "base/task/thread_pool.h" #include "base/task/thread_pool.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/version.h" #include "base/version.h"
#include "chrome/updater/app/app.h" #include "chrome/updater/app/app.h"
#include "chrome/updater/configurator.h" #include "chrome/updater/configurator.h"
...@@ -41,9 +42,11 @@ void AppUpdate::Uninitialize() { ...@@ -41,9 +42,11 @@ void AppUpdate::Uninitialize() {
} }
void AppUpdate::FirstTaskRun() { void AppUpdate::FirstTaskRun() {
base::ThreadPool::PostTaskAndReplyWithResult( base::ThreadPool::PostTask(
FROM_HERE, {base::MayBlock()}, base::BindOnce(&InstallCandidate, false), FROM_HERE, {base::MayBlock()},
base::BindOnce(&AppUpdate::SetupDone, this)); base::BindOnce(&InstallCandidate, false,
base::SequencedTaskRunnerHandle::Get(),
base::BindOnce(&AppUpdate::SetupDone, this)));
} }
void AppUpdate::SetupDone(int result) { void AppUpdate::SetupDone(int result) {
......
...@@ -285,6 +285,7 @@ ...@@ -285,6 +285,7 @@
appServer:(scoped_refptr<updater::AppServerMac>)appServer { appServer:(scoped_refptr<updater::AppServerMac>)appServer {
if (self = [super init]) { if (self = [super init]) {
_service = service; _service = service;
_appServer = appServer;
_callbackRunner = base::SequencedTaskRunnerHandle::Get(); _callbackRunner = base::SequencedTaskRunnerHandle::Get();
} }
return self; return self;
......
...@@ -64,6 +64,7 @@ update_client::CrxComponent Installer::MakeCrxComponent() { ...@@ -64,6 +64,7 @@ update_client::CrxComponent Installer::MakeCrxComponent() {
const auto pv = persisted_data_->GetProductVersion(app_id_); const auto pv = persisted_data_->GetProductVersion(app_id_);
if (pv.IsValid()) { if (pv.IsValid()) {
pv_ = pv; pv_ = pv;
checker_path_ = persisted_data_->GetExistenceCheckerPath(app_id_);
fingerprint_ = persisted_data_->GetFingerprint(app_id_); fingerprint_ = persisted_data_->GetFingerprint(app_id_);
} else { } else {
pv_ = base::Version(kNullVersion); pv_ = base::Version(kNullVersion);
......
...@@ -102,6 +102,7 @@ class Installer final : public update_client::CrxInstaller { ...@@ -102,6 +102,7 @@ class Installer final : public update_client::CrxInstaller {
// These members are not updated when the installer succeeds. // These members are not updated when the installer succeeds.
base::Version pv_; base::Version pv_;
base::FilePath checker_path_;
std::string fingerprint_; std::string fingerprint_;
}; };
......
...@@ -17,10 +17,8 @@ int Installer::RunApplicationInstaller(const base::FilePath& app_installer, ...@@ -17,10 +17,8 @@ int Installer::RunApplicationInstaller(const base::FilePath& app_installer,
DVLOG(1) << "Running application install from DMG"; DVLOG(1) << "Running application install from DMG";
// InstallFromDMG() returns the exit code of the script. 0 is success and // InstallFromDMG() returns the exit code of the script. 0 is success and
// anything else should be an error. // anything else should be an error.
return InstallFromDMG( return InstallFromDMG(app_installer, checker_path_,
app_installer, persisted_data_->GetExistenceCheckerPath(app_id_), base::StrCat({pv_.GetString(), " ", arguments}));
base::StrCat({persisted_data_->GetProductVersion(app_id_).GetString(),
" ", arguments}));
} }
} // namespace updater } // namespace updater
...@@ -5,9 +5,19 @@ ...@@ -5,9 +5,19 @@
#ifndef CHROME_UPDATER_SETUP_H_ #ifndef CHROME_UPDATER_SETUP_H_
#define CHROME_UPDATER_SETUP_H_ #define CHROME_UPDATER_SETUP_H_
#include "base/callback_forward.h"
#include "base/memory/ref_counted.h"
namespace base {
class TaskRunner;
} // namespace base
namespace updater { namespace updater {
int InstallCandidate(bool is_machine); // Installs the candidate, then posts |callback| to |runner|.
void InstallCandidate(bool is_machine,
scoped_refptr<base::TaskRunner> runner,
base::OnceCallback<void(int)> callback);
} // namespace updater } // namespace updater
......
...@@ -5,10 +5,18 @@ ...@@ -5,10 +5,18 @@
#include "chrome/updater/mac/setup/setup.h" #include "chrome/updater/mac/setup/setup.h"
#include "chrome/updater/setup.h" #include "chrome/updater/setup.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/task_runner.h"
namespace updater { namespace updater {
int InstallCandidate(bool is_machine) { void InstallCandidate(bool is_machine,
return InstallCandidate(); scoped_refptr<base::TaskRunner> runner,
base::OnceCallback<void(int)> callback) {
runner->PostDelayedTask(
FROM_HERE, base::BindOnce(std::move(callback), InstallCandidate()),
base::TimeDelta::FromSeconds(3));
} }
} // namespace updater } // namespace updater
...@@ -5,10 +5,17 @@ ...@@ -5,10 +5,17 @@
#include "chrome/updater/setup.h" #include "chrome/updater/setup.h"
#include "chrome/updater/win/setup/setup.h" #include "chrome/updater/win/setup/setup.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/task_runner.h"
namespace updater { namespace updater {
int InstallCandidate(bool is_machine) { void InstallCandidate(bool is_machine,
return Setup(is_machine); scoped_refptr<base::TaskRunner> runner,
base::OnceCallback<void(int)> callback) {
runner->PostTask(FROM_HERE,
base::BindOnce(std::move(callback), Setup(is_machine)));
} }
} // namespace updater } // namespace updater
...@@ -55,22 +55,6 @@ class IntegrationTest : public ::testing::Test { ...@@ -55,22 +55,6 @@ class IntegrationTest : public ::testing::Test {
TEST_F(IntegrationTest, InstallUninstall) { TEST_F(IntegrationTest, InstallUninstall) {
Install(); Install();
ExpectInstalled(); ExpectInstalled();
Uninstall();
}
TEST_F(IntegrationTest, InstallAndPromote) {
Install();
ExpectInstalled();
// TODO(crbug.com/1109231): resolve implementation inconsistencies for
// different platforms. In this case, Windows promotes during Install, and
// as a post-condition, the version of the updater is active before --wake
// runs.
#if defined(OS_WIN)
ExpectActiveVersion(UPDATER_VERSION_STRING);
#else
ExpectActiveVersion("0");
#endif
RunWake(0); // Candidate qualifies and promotes to active.
ExpectActiveVersion(UPDATER_VERSION_STRING); ExpectActiveVersion(UPDATER_VERSION_STRING);
ExpectActive(); ExpectActive();
Uninstall(); Uninstall();
......
...@@ -128,7 +128,7 @@ void Install() { ...@@ -128,7 +128,7 @@ void Install() {
const base::FilePath path = GetExecutablePath(); const base::FilePath path = GetExecutablePath();
ASSERT_FALSE(path.empty()); ASSERT_FALSE(path.empty());
base::CommandLine command_line(path); base::CommandLine command_line(path);
command_line.AppendSwitch(kUpdateSwitch); command_line.AppendSwitch(kInstallSwitch);
int exit_code = -1; int exit_code = -1;
ASSERT_TRUE(Run(command_line, &exit_code)); ASSERT_TRUE(Run(command_line, &exit_code));
EXPECT_EQ(0, exit_code); EXPECT_EQ(0, exit_code);
......
...@@ -111,10 +111,10 @@ int HandleUpdaterCommands(const base::CommandLine* command_line) { ...@@ -111,10 +111,10 @@ int HandleUpdaterCommands(const base::CommandLine* command_line) {
#if defined(OS_WIN) #if defined(OS_WIN)
if (command_line->HasSwitch(kComServiceSwitch)) if (command_line->HasSwitch(kComServiceSwitch))
return ServiceMain::RunComService(command_line); return ServiceMain::RunComService(command_line);
#endif // OS_WIN
if (command_line->HasSwitch(kInstallSwitch)) if (command_line->HasSwitch(kInstallSwitch))
return MakeAppInstall()->Run(); return MakeAppInstall()->Run();
#endif // OS_WIN
if (command_line->HasSwitch(kUninstallSwitch)) if (command_line->HasSwitch(kUninstallSwitch))
return MakeAppUninstall()->Run(); return MakeAppUninstall()->Run();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment