Chromium Code Reviews| Index: chrome/browser/mac/keystone_glue.mm |
| diff --git a/chrome/browser/mac/keystone_glue.mm b/chrome/browser/mac/keystone_glue.mm |
| index c6333e7c65031739873ab630349ace1d5f8c0f3d..8e2780decc23ac8084b2d53ff25a94ba190dabf9 100644 |
| --- a/chrome/browser/mac/keystone_glue.mm |
| +++ b/chrome/browser/mac/keystone_glue.mm |
| @@ -59,6 +59,11 @@ NSString* SystemBrandFilePath() { |
| return [kBrandSystemFile stringByStandardizingPath]; |
| } |
| +// Non-localized error message to return when we can't initiate any actions |
|
Mark Mentovai
2016/03/23 15:52:03
Why is this not localized?
This should be localiz
Boris Vidolov
2016/03/23 17:17:24
If I follow the code correctly, this message shoul
Mark Mentovai
2016/03/23 17:22:06
Boris Vidolov wrote:
Boris Vidolov
2016/03/23 17:37:29
Agree.
Ryan Myers (chromium)
2016/03/23 22:29:38
OK, removing and going back to DCHECKs. (TBH, I'm
|
| +// because Keystone isn't present or won't initialize. |
| +NSString* kNoRegistrationErrorMessage = |
| + @"Cannot start automatic updates - KeystoneRegistration not available."; |
| + |
| // Adaptor for scheduling an Objective-C method call on a |WorkerPool| |
| // thread. |
| class PerformBridge : public base::RefCountedThreadSafe<PerformBridge> { |
| @@ -127,7 +132,9 @@ class PerformBridge : public base::RefCountedThreadSafe<PerformBridge> { |
| // Called when an update check or update installation is complete. Posts the |
| // kAutoupdateStatusNotification notification to the default notification |
| // center. |
| -- (void)updateStatus:(AutoupdateStatus)status version:(NSString*)version; |
| +- (void)updateStatus:(AutoupdateStatus)status |
| + version:(NSString*)version |
| + error:(NSString*)error; |
| // Returns the version of the currently-installed application on disk. |
| - (NSString*)currentlyInstalledVersion; |
| @@ -135,7 +142,7 @@ class PerformBridge : public base::RefCountedThreadSafe<PerformBridge> { |
| // These three methods are used to determine the version of the application |
| // currently installed on disk, compare that to the currently-running version, |
| // decide whether any updates have been installed, and call |
| -// -updateStatus:version:. |
| +// -updateStatus:version:error:. |
| // |
| // In order to check the version on disk, the installed application's |
| // Info.plist dictionary must be read; in order to see changes as updates are |
| @@ -153,8 +160,8 @@ class PerformBridge : public base::RefCountedThreadSafe<PerformBridge> { |
| // CFBundleShortVersionString key, and performs |
| // -determineUpdateStatusForVersion: on the main thread. |
| // -determineUpdateStatusForVersion: does the actual comparison of the version |
| -// on disk with the running version and calls -updateStatus:version: with the |
| -// results of its analysis. |
| +// on disk with the running version and calls -updateStatus:version:error: with |
| +// the results of its analysis. |
| - (void)determineUpdateStatusAsync; |
| - (void)determineUpdateStatus; |
| - (void)determineUpdateStatusForVersion:(NSString*)version; |
| @@ -208,6 +215,7 @@ class PerformBridge : public base::RefCountedThreadSafe<PerformBridge> { |
| NSString* const kAutoupdateStatusNotification = @"AutoupdateStatusNotification"; |
| NSString* const kAutoupdateStatusStatus = @"status"; |
| NSString* const kAutoupdateStatusVersion = @"version"; |
| +NSString* const kAutoupdateStatusErrorMessages = @"errormessages"; |
| namespace { |
| @@ -536,12 +544,21 @@ NSString* const kVersionKey = @"KSVersion"; |
| } |
| - (void)registerWithKeystone { |
| - [self updateStatus:kAutoupdateRegistering version:nil]; |
| + [self updateStatus:kAutoupdateRegistering version:nil error:nil]; |
| + |
| + if (!registration_) { |
|
Mark Mentovai
2016/03/23 15:52:04
This can happen before you enter the “registering”
Boris Vidolov
2016/03/23 17:17:24
I don't see how this could happen: see +[KeystoneG
Mark Mentovai
2016/03/23 17:22:06
Boris Vidolov wrote:
Boris Vidolov
2016/03/23 17:37:29
I am fine with DCHECK for "registration_". Then it
Ryan Myers (chromium)
2016/03/23 22:29:38
Done.
|
| + [self updateStatus:kAutoupdateRegisterFailed |
| + version:nil |
| + error:kNoRegistrationErrorMessage]; |
| + return; |
| + } |
| NSDictionary* parameters = [self keystoneParameters]; |
| BOOL result = [registration_ registerWithParameters:parameters]; |
| if (!result) { |
| - [self updateStatus:kAutoupdateRegisterFailed version:nil]; |
| + // TODO: If Keystone ever makes a variant of this API with a withError: |
| + // parameter, include the error message here in the call to updateStatus:. |
| + [self updateStatus:kAutoupdateRegisterFailed version:nil error:nil]; |
| return; |
| } |
| @@ -562,15 +579,22 @@ NSString* const kVersionKey = @"KSVersion"; |
| - (void)registrationComplete:(NSNotification*)notification { |
| NSDictionary* userInfo = [notification userInfo]; |
| + NSString* errorMessages = |
| + [userInfo objectForKey:ksr::KSRegistrationUpdateCheckRawErrorMessagesKey]; |
|
Mark Mentovai
2016/03/23 15:52:03
When you pull things out of a dictionary, use ObjC
Ryan Myers (chromium)
2016/03/23 22:29:38
Done, both here and elsewhere in the file (i.e. in
|
| + |
| if ([[userInfo objectForKey:ksr::KSRegistrationStatusKey] boolValue]) { |
| if ([self isSystemTicketDoomed]) { |
| - [self updateStatus:kAutoupdateNeedsPromotion version:nil]; |
| + [self updateStatus:kAutoupdateNeedsPromotion |
| + version:nil |
| + error:errorMessages]; |
| } else { |
| - [self updateStatus:kAutoupdateRegistered version:nil]; |
| + [self updateStatus:kAutoupdateRegistered version:nil error:errorMessages]; |
| } |
| } else { |
| // Dump registration_? |
| - [self updateStatus:kAutoupdateRegisterFailed version:nil]; |
| + [self updateStatus:kAutoupdateRegisterFailed |
| + version:nil |
| + error:errorMessages]; |
| } |
| } |
| @@ -583,14 +607,20 @@ NSString* const kVersionKey = @"KSVersion"; |
| } |
| - (void)checkForUpdate { |
| - DCHECK(![self asyncOperationPending]); |
| + if ([self asyncOperationPending]) { |
|
Mark Mentovai
2016/03/23 15:52:04
This can come after the registration_ check. Same
Ryan Myers (chromium)
2016/03/23 22:29:38
Done.
|
| + // Update check already in process; return without doing anything. |
| + VLOG(1) << "checkForUpdate ignored; async operation pending"; |
|
Mark Mentovai
2016/03/23 15:52:03
I wasn’t a fan of the three VLOGs that this file a
Ryan Myers (chromium)
2016/03/23 22:29:38
They're nice to have, but not necessary IMO. At b
|
| + return; |
| + } |
| if (!registration_) { |
| - [self updateStatus:kAutoupdateCheckFailed version:nil]; |
| + [self updateStatus:kAutoupdateCheckFailed |
| + version:nil |
| + error:kNoRegistrationErrorMessage]; |
| return; |
| } |
| - [self updateStatus:kAutoupdateChecking version:nil]; |
| + [self updateStatus:kAutoupdateChecking version:nil error:nil]; |
| // All checks from inside Chrome are considered user-initiated, because they |
| // only happen following a user action, such as visiting the about page. |
| @@ -604,15 +634,19 @@ NSString* const kVersionKey = @"KSVersion"; |
| - (void)checkForUpdateComplete:(NSNotification*)notification { |
| NSDictionary* userInfo = [notification userInfo]; |
| + NSString* errorMessages = |
| + [userInfo objectForKey:ksr::KSRegistrationUpdateCheckRawErrorMessagesKey]; |
| if ([[userInfo objectForKey:ksr::KSRegistrationUpdateCheckErrorKey] |
| boolValue]) { |
| - [self updateStatus:kAutoupdateCheckFailed version:nil]; |
| + [self updateStatus:kAutoupdateCheckFailed version:nil error:errorMessages]; |
| } else if ([[userInfo objectForKey:ksr::KSRegistrationStatusKey] boolValue]) { |
| // If an update is known to be available, go straight to |
| // -updateStatus:version:. It doesn't matter what's currently on disk. |
| NSString* version = [userInfo objectForKey:ksr::KSRegistrationVersionKey]; |
| - [self updateStatus:kAutoupdateAvailable version:version]; |
| + [self updateStatus:kAutoupdateAvailable |
| + version:version |
| + error:errorMessages]; |
| } else { |
| // If no updates are available, check what's on disk, because an update |
| // may have already been installed. This check happens on another thread, |
| @@ -622,14 +656,20 @@ NSString* const kVersionKey = @"KSVersion"; |
| } |
| - (void)installUpdate { |
| - DCHECK(![self asyncOperationPending]); |
| + if ([self asyncOperationPending]) { |
| + // Update check already in process; return without doing anything. |
| + VLOG(1) << "installUpdate ignored; async operation pending"; |
| + return; |
| + } |
| if (!registration_) { |
| - [self updateStatus:kAutoupdateInstallFailed version:nil]; |
| + [self updateStatus:kAutoupdateInstallFailed |
| + version:nil |
| + error:kNoRegistrationErrorMessage]; |
| return; |
| } |
| - [self updateStatus:kAutoupdateInstalling version:nil]; |
| + [self updateStatus:kAutoupdateInstalling version:nil error:nil]; |
| [registration_ startUpdate]; |
| @@ -639,6 +679,8 @@ NSString* const kVersionKey = @"KSVersion"; |
| - (void)installUpdateComplete:(NSNotification*)notification { |
| NSDictionary* userInfo = [notification userInfo]; |
| + NSString* errorMsgs = |
|
Mark Mentovai
2016/03/23 15:52:03
Don’t abbreviate. Elsewhere, this was named errorM
Ryan Myers (chromium)
2016/03/23 22:29:38
Done.
|
| + [userInfo objectForKey:ksr::KSRegistrationUpdateCheckRawErrorMessagesKey]; |
| // http://crbug.com/160308 and b/7517358: when using system Keystone and on |
| // a user ticket, KSUpdateCheckSuccessfulKey will be NO even when an update |
| @@ -646,7 +688,7 @@ NSString* const kVersionKey = @"KSVersion"; |
| // KSUpdateCheckSuccessfullyInstalledKey is checked. |
| if (![[userInfo objectForKey:ksr::KSUpdateCheckSuccessfullyInstalledKey] |
| intValue]) { |
| - [self updateStatus:kAutoupdateInstallFailed version:nil]; |
| + [self updateStatus:kAutoupdateInstallFailed version:nil error:errorMsgs]; |
| } else { |
| updateSuccessfullyInstalled_ = YES; |
| @@ -709,10 +751,12 @@ NSString* const kVersionKey = @"KSVersion"; |
| } |
| } |
| - [self updateStatus:status version:version]; |
| + [self updateStatus:status version:version error:nil]; |
| } |
| -- (void)updateStatus:(AutoupdateStatus)status version:(NSString*)version { |
| +- (void)updateStatus:(AutoupdateStatus)status |
| + version:(NSString*)version |
| + error:(NSString *)error { |
|
Mark Mentovai
2016/03/23 15:52:03
Chromium style is NSString*, no space in there. Co
Ryan Myers (chromium)
2016/03/23 22:29:38
Done.
|
| NSNumber* statusNumber = [NSNumber numberWithInt:status]; |
| NSMutableDictionary* dictionary = |
| [NSMutableDictionary dictionaryWithObject:statusNumber |
| @@ -720,6 +764,9 @@ NSString* const kVersionKey = @"KSVersion"; |
| if (version) { |
| [dictionary setObject:version forKey:kAutoupdateStatusVersion]; |
| } |
| + if (error) { |
| + [dictionary setObject:version forKey:kAutoupdateStatusErrorMessages]; |
| + } |
| NSNotification* notification = |
| [NSNotification notificationWithName:kAutoupdateStatusNotification |
| @@ -838,6 +885,7 @@ NSString* const kVersionKey = @"KSVersion"; |
| // not lock each other out, it may be possible to arrive here while an |
| // asynchronous operation is pending, or even after promotion has already |
| // occurred. Just quietly return without doing anything. |
| + VLOG(1) << "promoteTicket ignored; async operation pending"; |
| return; |
| } |
| @@ -862,6 +910,7 @@ NSString* const kVersionKey = @"KSVersion"; |
| if ([self asyncOperationPending]) { |
| // Starting a synchronous operation while an asynchronous one is pending |
| // could be trouble. |
| + VLOG(1) << "promoteTicketWithAuth ignored; async operation pending"; |
| return; |
| } |
| if (!synchronous && ![self wantsPromotion]) { |
| @@ -873,7 +922,7 @@ NSString* const kVersionKey = @"KSVersion"; |
| synchronousPromotion_ = synchronous; |
| - [self updateStatus:kAutoupdatePromoting version:nil]; |
| + [self updateStatus:kAutoupdatePromoting version:nil error:nil]; |
| // TODO(mark): Remove when able! |
| // |
| @@ -922,12 +971,24 @@ NSString* const kVersionKey = @"KSVersion"; |
| if (status != errAuthorizationSuccess) { |
| OSSTATUS_LOG(ERROR, status) |
| << "AuthorizationExecuteWithPrivileges preflight"; |
| - [self updateStatus:kAutoupdatePromoteFailed version:nil]; |
| + |
| + NSString *errorMessage = |
| + [NSString stringWithFormat:@"Pre-flight script failed to launch: %ld", |
|
Mark Mentovai
2016/03/23 15:52:03
This ought to be localized. Line 987 too.
Ryan Myers (chromium)
2016/03/23 22:29:38
Done.
|
| + (long)status]; |
| + [self updateStatus:kAutoupdatePromoteFailed |
| + version:nil |
| + error:errorMessage]; |
| return; |
| } |
| if (exit_status != 0) { |
| LOG(ERROR) << "keystone_promote_preflight status " << exit_status; |
| - [self updateStatus:kAutoupdatePromoteFailed version:nil]; |
| + |
| + NSString *errorMessage = |
| + [NSString stringWithFormat:@"Promotion pre-flight script failed: %d", |
| + exit_status]; |
| + [self updateStatus:kAutoupdatePromoteFailed |
| + version:nil |
| + error:errorMessage]; |
| return; |
| } |
| @@ -951,7 +1012,9 @@ NSString* const kVersionKey = @"KSVersion"; |
| if (![registration_ promoteWithParameters:parameters |
| authorization:authorization_]) { |
| - [self updateStatus:kAutoupdatePromoteFailed version:nil]; |
| + // TODO: If Keystone ever makes a variant of this API with a withError: |
| + // parameter, include the error message here in the call to updateStatus:. |
| + [self updateStatus:kAutoupdatePromoteFailed version:nil error:nil]; |
| authorization_.reset(); |
| return; |
| } |
| @@ -980,7 +1043,7 @@ NSString* const kVersionKey = @"KSVersion"; |
| } |
| } else { |
| authorization_.reset(); |
| - [self updateStatus:kAutoupdatePromoteFailed version:nil]; |
| + [self updateStatus:kAutoupdatePromoteFailed version:nil error:nil]; |
| } |
| if (synchronousPromotion_) { |
| @@ -1036,7 +1099,7 @@ NSString* const kVersionKey = @"KSVersion"; |
| - (void)changePermissionsForPromotionComplete { |
| authorization_.reset(); |
| - [self updateStatus:kAutoupdatePromoted version:nil]; |
| + [self updateStatus:kAutoupdatePromoted version:nil error:nil]; |
| } |
| - (void)setAppPath:(NSString*)appPath { |