Commit 0d8cf3b7 authored by Mila Green's avatar Mila Green Committed by Commit Bot

Updater: Promote Candidate from admin task.

Bug: 1072061
Change-Id: I6b903e5e4c47ee1368faf57a2388b92b39c2a2fa
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2208605
Commit-Queue: Mila Green <milagreen@chromium.org>
Reviewed-by: default avatarRobert Sesek <rsesek@chromium.org>
Cr-Commit-Position: refs/heads/master@{#774649}
parent 4de7b77b
...@@ -141,7 +141,7 @@ using base::SysUTF8ToNSString; ...@@ -141,7 +141,7 @@ using base::SysUTF8ToNSString;
} }
- (void)haltForUpdateToVersion:(NSString* _Nonnull)version - (void)haltForUpdateToVersion:(NSString* _Nonnull)version
reply:(void (^_Nonnull)(bool shouldUpdate))reply { reply:(void (^_Nonnull)(BOOL shouldUpdate))reply {
auto errorHandler = ^(NSError* xpcError) { auto errorHandler = ^(NSError* xpcError) {
LOG(ERROR) << "XPC connection failed: " LOG(ERROR) << "XPC connection failed: "
<< base::SysNSStringToUTF8([xpcError description]); << base::SysNSStringToUTF8([xpcError description]);
......
...@@ -11,7 +11,9 @@ ...@@ -11,7 +11,9 @@
#include "base/command_line.h" #include "base/command_line.h"
#include "base/mac/scoped_block.h" #include "base/mac/scoped_block.h"
#include "base/mac/scoped_nsobject.h" #include "base/mac/scoped_nsobject.h"
#include "base/no_destructor.h"
#include "base/strings/sys_string_conversions.h" #include "base/strings/sys_string_conversions.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/sequenced_task_runner_handle.h" #include "base/threading/sequenced_task_runner_handle.h"
#include "base/version.h" #include "base/version.h"
#include "chrome/updater/mac/setup/setup.h" #include "chrome/updater/mac/setup/setup.h"
...@@ -21,53 +23,78 @@ ...@@ -21,53 +23,78 @@
#include "chrome/updater/update_service.h" #include "chrome/updater/update_service.h"
#include "chrome/updater/updater_version.h" #include "chrome/updater/updater_version.h"
const NSInteger kMaxRedialAttempts = 3;
const base::Version& GetSelfVersion() {
static base::NoDestructor<base::Version> self_version(
base::Version(UPDATER_VERSION_STRING));
return *self_version;
}
@interface CRUUpdateCheckXPCServiceImpl @interface CRUUpdateCheckXPCServiceImpl
: NSObject <CRUUpdateChecking, CRUAdministering> : NSObject <CRUUpdateChecking, CRUAdministering>
- (instancetype)init NS_UNAVAILABLE; - (instancetype)init NS_UNAVAILABLE;
// Designated initializers. // Designated initializers.
- (instancetype)initWithUpdateService:(updater::UpdateService*)service
callbackRunner:(scoped_refptr<base::SequencedTaskRunner>)
callbackRunner;
- (instancetype)initWithUpdateService:(updater::UpdateService*)service - (instancetype)initWithUpdateService:(updater::UpdateService*)service
callbackRunner:(scoped_refptr<base::SequencedTaskRunner>) callbackRunner:(scoped_refptr<base::SequencedTaskRunner>)
callbackRunner callbackRunner
updateCheckXPCConnection:(base::scoped_nsobject<NSXPCConnection>)
updateCheckXPCConnection
NS_DESIGNATED_INITIALIZER; NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithUpdateService:(updater::UpdateService*)service
updaterConnectionOptions:(NSXPCConnectionOptions)options
callbackRunner:(scoped_refptr<base::SequencedTaskRunner>)
callbackRunner;
@end @end
@implementation CRUUpdateCheckXPCServiceImpl { @implementation CRUUpdateCheckXPCServiceImpl {
updater::UpdateService* _service; updater::UpdateService* _service;
scoped_refptr<base::SequencedTaskRunner> _callbackRunner; scoped_refptr<base::SequencedTaskRunner> _callbackRunner;
NSXPCConnectionOptions _updateCheckXPCConnectionOptions;
base::scoped_nsobject<NSXPCConnection> _updateCheckXPCConnection; base::scoped_nsobject<NSXPCConnection> _updateCheckXPCConnection;
NSInteger _redialAttempts;
} }
- (instancetype)initWithUpdateService:(updater::UpdateService*)service - (instancetype)initWithUpdateService:(updater::UpdateService*)service
callbackRunner:(scoped_refptr<base::SequencedTaskRunner>) callbackRunner:(scoped_refptr<base::SequencedTaskRunner>)
callbackRunner { callbackRunner {
[self initWithUpdateService:service if (self = [super init]) {
callbackRunner:callbackRunner _service = service;
updateCheckXPCConnection:base::scoped_nsobject<NSXPCConnection>(nil)]; _callbackRunner = callbackRunner;
}
return self; return self;
} }
- (instancetype)initWithUpdateService:(updater::UpdateService*)service - (instancetype)initWithUpdateService:(updater::UpdateService*)service
updaterConnectionOptions:(NSXPCConnectionOptions)options
callbackRunner:(scoped_refptr<base::SequencedTaskRunner>) callbackRunner:(scoped_refptr<base::SequencedTaskRunner>)
callbackRunner callbackRunner {
updateCheckXPCConnection:(base::scoped_nsobject<NSXPCConnection>) [self initWithUpdateService:service callbackRunner:callbackRunner];
updateCheckXPCConnection { _updateCheckXPCConnectionOptions = options;
if (self = [super init]) { [self dialUpdateCheckXPCConnection];
_service = service;
_callbackRunner = callbackRunner;
_updateCheckXPCConnection = updateCheckXPCConnection;
}
return self; return self;
} }
- (void)dialUpdateCheckXPCConnection {
_updateCheckXPCConnection.reset([[NSXPCConnection alloc]
initWithMachServiceName:updater::GetGoogleUpdateServiceMachName().get()
options:_updateCheckXPCConnectionOptions]);
_updateCheckXPCConnection.get().remoteObjectInterface =
updater::GetXPCUpdateCheckingInterface();
_updateCheckXPCConnection.get().interruptionHandler = ^{
LOG(WARNING) << "CRUUpdateCheckingService: XPC connection interrupted.";
};
_updateCheckXPCConnection.get().invalidationHandler = ^{
LOG(WARNING) << "CRUUpdateCheckingService: XPC connection invalidated.";
};
[_updateCheckXPCConnection resume];
}
#pragma mark CRUUpdateChecking #pragma mark CRUUpdateChecking
- (void)checkForUpdatesWithUpdateState:(id<CRUUpdateStateObserving>)updateState - (void)checkForUpdatesWithUpdateState:(id<CRUUpdateStateObserving>)updateState
reply:(void (^_Nonnull)(int rc))reply { reply:(void (^_Nonnull)(int rc))reply {
...@@ -181,8 +208,7 @@ ...@@ -181,8 +208,7 @@
} }
- (BOOL)isUpdaterVersionLowerThanCandidateVersion:(NSString* _Nonnull)version { - (BOOL)isUpdaterVersionLowerThanCandidateVersion:(NSString* _Nonnull)version {
const base::Version selfVersion = const base::Version selfVersion = GetSelfVersion();
base::Version(base::SysNSStringToUTF8(@UPDATER_VERSION_STRING));
CHECK(selfVersion.IsValid()); CHECK(selfVersion.IsValid());
const base::Version candidateVersion = const base::Version candidateVersion =
base::Version(base::SysNSStringToUTF8(version)); base::Version(base::SysNSStringToUTF8(version));
...@@ -193,7 +219,7 @@ ...@@ -193,7 +219,7 @@
} }
- (void)haltForUpdateToVersion:(NSString* _Nonnull)candidateVersion - (void)haltForUpdateToVersion:(NSString* _Nonnull)candidateVersion
reply:(void (^_Nonnull)(bool shouldUpdate))reply { reply:(void (^_Nonnull)(BOOL shouldUpdate))reply {
if (reply) { if (reply) {
if ([self isUpdaterVersionLowerThanCandidateVersion:candidateVersion]) { if ([self isUpdaterVersionLowerThanCandidateVersion:candidateVersion]) {
// Halt the service for a long time, so that the update to the candidate // Halt the service for a long time, so that the update to the candidate
...@@ -208,56 +234,108 @@ ...@@ -208,56 +234,108 @@
} }
#pragma mark CRUAdministering #pragma mark CRUAdministering
- (void)promoteCandidate {
// TODO: crbug 1072061
// Actually do the self test. For now assume it passes.
BOOL selfTestPassed = YES;
if (!selfTestPassed) {
LOG(ERROR) << "Candidate versioned: '"
<< UPDATER_VERSION_STRING "' failed self test.";
return;
}
auto haltErrorHandler = ^(NSError* haltError) {
LOG(ERROR) << "XPC connection failed: "
<< base::SysNSStringToUTF8([haltError description]);
// Try to redial the connection
if (++_redialAttempts <= kMaxRedialAttempts) {
[self dialUpdateCheckXPCConnection];
[self promoteCandidate];
return;
} else {
LOG(ERROR) << "XPC connection redialed maximum number of times.";
}
};
auto haltReply = ^(BOOL halted) {
VLOG(0) << "Response from haltForUpdateToVersion:reply: = " << halted;
if (halted) {
updater::PromoteCandidate();
} else {
LOG(ERROR) << "The active service refused to halt for update to version: "
<< UPDATER_VERSION_STRING;
}
};
[[_updateCheckXPCConnection.get()
remoteObjectProxyWithErrorHandler:haltErrorHandler]
haltForUpdateToVersion:@UPDATER_VERSION_STRING
reply:haltReply];
}
- (void)performAdminTasks { - (void)performAdminTasks {
// Get the version of the active service. base::scoped_nsobject<NSError> versionError;
auto errorHandler = ^(NSError* xpcError) {
if (!_updateCheckXPCConnection) {
[self promoteCandidate];
return;
}
auto versionErrorHandler = ^(NSError* versionError) {
LOG(ERROR) << "XPC connection failed: " LOG(ERROR) << "XPC connection failed: "
<< base::SysNSStringToUTF8([xpcError description]); << base::SysNSStringToUTF8([versionError description]);
}; };
auto reply = ^(NSString* _Nullable activeServiceVersionString) { auto versionReply = ^(NSString* _Nullable activeServiceVersionString) {
if (activeServiceVersionString) { if (activeServiceVersionString) {
const base::Version activeServiceVersion = const base::Version activeServiceVersion =
base::Version(base::SysNSStringToUTF8(activeServiceVersionString)); base::Version(base::SysNSStringToUTF8(activeServiceVersionString));
CHECK(activeServiceVersion.IsValid()); const base::Version selfVersion = GetSelfVersion();
const base::Version selfVersion =
base::Version(base::SysNSStringToUTF8(@UPDATER_VERSION_STRING)); if (!selfVersion.IsValid()) {
CHECK(selfVersion.IsValid());
int versionComparisonResult = selfVersion.CompareTo(activeServiceVersion);
if (versionComparisonResult > 0) {
// If the versioned service is a higher version than the active service,
// activate the versioned service.
updater::PromoteCandidate();
} else if (versionComparisonResult < 0) {
// If the versioned service is a lower version than the active service,
// remove the versioned service.
updater::UninstallCandidate(); updater::UninstallCandidate();
} else if (!activeServiceVersion.IsValid()) {
[self promoteCandidate];
} else { } else {
// If the versioned service is the same version as the active service, int versionComparisonResult =
// check for updates. selfVersion.CompareTo(activeServiceVersion);
auto updateCheckErrorHandler = ^(NSError* xpcError) {
LOG(ERROR) << "XPC connection failed: " if (versionComparisonResult > 0) {
<< base::SysNSStringToUTF8([xpcError description]); // If the versioned service is a higher version than the active
}; // service, run a self test and activate the versioned service.
[self promoteCandidate];
auto updateCheckReply = ^(int error) { } else if (versionComparisonResult < 0) {
VLOG(0) << "UpdateAll complete: exit_code = " << error; // If the versioned service is a lower version than the active
}; // service, remove the versioned service.
updater::UninstallCandidate();
base::scoped_nsprotocol<id<CRUUpdateStateObserving>> stateObserver( } else {
[[CRUUpdateStateObserver alloc] // If the versioned service is the same version as the active
initWithRepeatingCallback: // service, check for updates.
base::BindRepeating( base::scoped_nsobject<NSError> updateCheckError;
[](updater::UpdateService::UpdateState) {})
callbackRunner:_callbackRunner]); base::scoped_nsprotocol<id<CRUUpdateStateObserving>> stateObserver(
[[CRUUpdateStateObserver alloc]
// TODO: crbug 1072061 initWithRepeatingCallback:
// Need to wait for the async reply? base::BindRepeating(
[[_updateCheckXPCConnection.get() [](updater::UpdateService::UpdateState) {})
remoteObjectProxyWithErrorHandler:updateCheckErrorHandler] callbackRunner:_callbackRunner]);
checkForUpdatesWithUpdateState:stateObserver.get()
reply:updateCheckReply]; auto updateCheckErrorHandler = ^(NSError* updateCheckError) {
LOG(ERROR) << "XPC connection failed: "
<< base::SysNSStringToUTF8(
[updateCheckError description]);
};
auto updateCheckReply = ^(int error) {
VLOG(0) << "UpdateAll complete: exit_code = " << error;
};
[[_updateCheckXPCConnection.get()
remoteObjectProxyWithErrorHandler:updateCheckErrorHandler]
checkForUpdatesWithUpdateState:stateObserver
reply:updateCheckReply];
}
} }
} else { } else {
// Active service version is nil. // Active service version is nil.
...@@ -265,16 +343,9 @@ ...@@ -265,16 +343,9 @@
} }
}; };
if (!_updateCheckXPCConnection) { [[_updateCheckXPCConnection.get()
// Activate the service. remoteObjectProxyWithErrorHandler:versionErrorHandler]
updater::PromoteCandidate(); getUpdaterVersionWithReply:versionReply];
} else {
// TODO: crbug 1072061
// Need to wait for the async reply?
[[_updateCheckXPCConnection.get()
remoteObjectProxyWithErrorHandler:errorHandler]
getUpdaterVersionWithReply:reply];
}
} }
@end @end
...@@ -330,36 +401,18 @@ ...@@ -330,36 +401,18 @@
// Check to see if the other side of the connection is "okay"; // Check to see if the other side of the connection is "okay";
// if not, invalidate newConnection and return NO. // if not, invalidate newConnection and return NO.
base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); base::CommandLine* cmdLine = base::CommandLine::ForCurrentProcess();
NSXPCConnectionOptions options = cmdline->HasSwitch(updater::kSystemSwitch) NSXPCConnectionOptions options = cmdLine->HasSwitch(updater::kSystemSwitch)
? NSXPCConnectionPrivileged ? NSXPCConnectionPrivileged
: 0; : 0;
base::scoped_nsobject<NSXPCConnection> updateCheckXPCConnection(
[[NSXPCConnection alloc]
initWithMachServiceName:updater::GetGoogleUpdateServiceMachName()
.get()
options:options]);
updateCheckXPCConnection.get().remoteObjectInterface =
updater::GetXPCUpdateCheckingInterface();
updateCheckXPCConnection.get().interruptionHandler = ^{
LOG(WARNING) << "CRUUpdateCheckingService: XPC connection interrupted.";
};
updateCheckXPCConnection.get().invalidationHandler = ^{
LOG(WARNING) << "CRUUpdateCheckingService: XPC connection invalidated.";
};
[updateCheckXPCConnection resume];
newConnection.exportedInterface = updater::GetXPCAdministeringInterface(); newConnection.exportedInterface = updater::GetXPCAdministeringInterface();
base::scoped_nsobject<CRUUpdateCheckXPCServiceImpl> object( base::scoped_nsobject<CRUUpdateCheckXPCServiceImpl> object(
[[CRUUpdateCheckXPCServiceImpl alloc] [[CRUUpdateCheckXPCServiceImpl alloc]
initWithUpdateService:_service.get() initWithUpdateService:_service.get()
callbackRunner:_callbackRunner.get() updaterConnectionOptions:options
updateCheckXPCConnection:updateCheckXPCConnection]); callbackRunner:_callbackRunner.get()]);
newConnection.exportedObject = object.get(); newConnection.exportedObject = object.get();
[newConnection resume]; [newConnection resume];
return YES; return YES;
......
...@@ -51,7 +51,7 @@ ...@@ -51,7 +51,7 @@
// Checks if |version| is newer. Returns the result in the reply block. // Checks if |version| is newer. Returns the result in the reply block.
- (void)haltForUpdateToVersion:(NSString* _Nonnull)version - (void)haltForUpdateToVersion:(NSString* _Nonnull)version
reply:(void (^_Nonnull)(bool shouldUpdate))reply; reply:(void (^_Nonnull)(BOOL shouldUpdate))reply;
@end @end
......
...@@ -127,7 +127,7 @@ NSString* GetMachServiceName() { ...@@ -127,7 +127,7 @@ NSString* GetMachServiceName() {
} }
- (void)haltForUpdateToVersion:(NSString* _Nonnull)version - (void)haltForUpdateToVersion:(NSString* _Nonnull)version
reply:(void (^_Nonnull)(bool shouldUpdate))reply { reply:(void (^_Nonnull)(BOOL shouldUpdate))reply {
auto errorHandler = ^(NSError* xpcError) { auto errorHandler = ^(NSError* xpcError) {
LOG(ERROR) << "XPC connection failed: " LOG(ERROR) << "XPC connection failed: "
<< base::SysNSStringToUTF8([xpcError description]); << base::SysNSStringToUTF8([xpcError description]);
......
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