Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #import "chrome/browser/mac/keystone_glue.h" | 5 #import "chrome/browser/mac/keystone_glue.h" |
| 6 | 6 |
| 7 #include <sys/mount.h> | 7 #include <sys/mount.h> |
| 8 #include <sys/param.h> | 8 #include <sys/param.h> |
| 9 #include <sys/stat.h> | 9 #include <sys/stat.h> |
| 10 | 10 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 52 NSString* kBrandUserFile = @"~/Library/Google/" kBrandFileName; | 52 NSString* kBrandUserFile = @"~/Library/Google/" kBrandFileName; |
| 53 NSString* kBrandSystemFile = @"/Library/Google/" kBrandFileName; | 53 NSString* kBrandSystemFile = @"/Library/Google/" kBrandFileName; |
| 54 | 54 |
| 55 NSString* UserBrandFilePath() { | 55 NSString* UserBrandFilePath() { |
| 56 return [kBrandUserFile stringByStandardizingPath]; | 56 return [kBrandUserFile stringByStandardizingPath]; |
| 57 } | 57 } |
| 58 NSString* SystemBrandFilePath() { | 58 NSString* SystemBrandFilePath() { |
| 59 return [kBrandSystemFile stringByStandardizingPath]; | 59 return [kBrandSystemFile stringByStandardizingPath]; |
| 60 } | 60 } |
| 61 | 61 |
| 62 // 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
| |
| 63 // because Keystone isn't present or won't initialize. | |
| 64 NSString* kNoRegistrationErrorMessage = | |
| 65 @"Cannot start automatic updates - KeystoneRegistration not available."; | |
| 66 | |
| 62 // Adaptor for scheduling an Objective-C method call on a |WorkerPool| | 67 // Adaptor for scheduling an Objective-C method call on a |WorkerPool| |
| 63 // thread. | 68 // thread. |
| 64 class PerformBridge : public base::RefCountedThreadSafe<PerformBridge> { | 69 class PerformBridge : public base::RefCountedThreadSafe<PerformBridge> { |
| 65 public: | 70 public: |
| 66 | 71 |
| 67 // Call |sel| on |target| with |arg| in a WorkerPool thread. | 72 // Call |sel| on |target| with |arg| in a WorkerPool thread. |
| 68 // |target| and |arg| are retained, |arg| may be |nil|. | 73 // |target| and |arg| are retained, |arg| may be |nil|. |
| 69 static void PostPerform(id target, SEL sel, id arg) { | 74 static void PostPerform(id target, SEL sel, id arg) { |
| 70 DCHECK(target); | 75 DCHECK(target); |
| 71 DCHECK(sel); | 76 DCHECK(sel); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 120 | 125 |
| 121 // Set the registration active and pass profile count parameters. | 126 // Set the registration active and pass profile count parameters. |
| 122 - (void)setRegistrationActive; | 127 - (void)setRegistrationActive; |
| 123 | 128 |
| 124 // Called periodically to announce activity by pinging the Keystone server. | 129 // Called periodically to announce activity by pinging the Keystone server. |
| 125 - (void)markActive:(NSTimer*)timer; | 130 - (void)markActive:(NSTimer*)timer; |
| 126 | 131 |
| 127 // Called when an update check or update installation is complete. Posts the | 132 // Called when an update check or update installation is complete. Posts the |
| 128 // kAutoupdateStatusNotification notification to the default notification | 133 // kAutoupdateStatusNotification notification to the default notification |
| 129 // center. | 134 // center. |
| 130 - (void)updateStatus:(AutoupdateStatus)status version:(NSString*)version; | 135 - (void)updateStatus:(AutoupdateStatus)status |
| 136 version:(NSString*)version | |
| 137 error:(NSString*)error; | |
| 131 | 138 |
| 132 // Returns the version of the currently-installed application on disk. | 139 // Returns the version of the currently-installed application on disk. |
| 133 - (NSString*)currentlyInstalledVersion; | 140 - (NSString*)currentlyInstalledVersion; |
| 134 | 141 |
| 135 // These three methods are used to determine the version of the application | 142 // These three methods are used to determine the version of the application |
| 136 // currently installed on disk, compare that to the currently-running version, | 143 // currently installed on disk, compare that to the currently-running version, |
| 137 // decide whether any updates have been installed, and call | 144 // decide whether any updates have been installed, and call |
| 138 // -updateStatus:version:. | 145 // -updateStatus:version:error:. |
| 139 // | 146 // |
| 140 // In order to check the version on disk, the installed application's | 147 // In order to check the version on disk, the installed application's |
| 141 // Info.plist dictionary must be read; in order to see changes as updates are | 148 // Info.plist dictionary must be read; in order to see changes as updates are |
| 142 // applied, the dictionary must be read each time, bypassing any caches such | 149 // applied, the dictionary must be read each time, bypassing any caches such |
| 143 // as the one that NSBundle might be maintaining. Reading files can be a | 150 // as the one that NSBundle might be maintaining. Reading files can be a |
| 144 // blocking operation, and blocking operations are to be avoided on the main | 151 // blocking operation, and blocking operations are to be avoided on the main |
| 145 // thread. I'm not quite sure what jank means, but I bet that a blocked main | 152 // thread. I'm not quite sure what jank means, but I bet that a blocked main |
| 146 // thread would cause some of it. | 153 // thread would cause some of it. |
| 147 // | 154 // |
| 148 // -determineUpdateStatusAsync is called on the main thread to initiate the | 155 // -determineUpdateStatusAsync is called on the main thread to initiate the |
| 149 // operation. It performs initial set-up work that must be done on the main | 156 // operation. It performs initial set-up work that must be done on the main |
| 150 // thread and arranges for -determineUpdateStatus to be called on a work queue | 157 // thread and arranges for -determineUpdateStatus to be called on a work queue |
| 151 // thread managed by WorkerPool. | 158 // thread managed by WorkerPool. |
| 152 // -determineUpdateStatus then reads the Info.plist, gets the version from the | 159 // -determineUpdateStatus then reads the Info.plist, gets the version from the |
| 153 // CFBundleShortVersionString key, and performs | 160 // CFBundleShortVersionString key, and performs |
| 154 // -determineUpdateStatusForVersion: on the main thread. | 161 // -determineUpdateStatusForVersion: on the main thread. |
| 155 // -determineUpdateStatusForVersion: does the actual comparison of the version | 162 // -determineUpdateStatusForVersion: does the actual comparison of the version |
| 156 // on disk with the running version and calls -updateStatus:version: with the | 163 // on disk with the running version and calls -updateStatus:version:error: with |
| 157 // results of its analysis. | 164 // the results of its analysis. |
| 158 - (void)determineUpdateStatusAsync; | 165 - (void)determineUpdateStatusAsync; |
| 159 - (void)determineUpdateStatus; | 166 - (void)determineUpdateStatus; |
| 160 - (void)determineUpdateStatusForVersion:(NSString*)version; | 167 - (void)determineUpdateStatusForVersion:(NSString*)version; |
| 161 | 168 |
| 162 // Returns YES if registration_ is definitely on a user ticket. If definitely | 169 // Returns YES if registration_ is definitely on a user ticket. If definitely |
| 163 // on a system ticket, or uncertain of ticket type (due to an older version | 170 // on a system ticket, or uncertain of ticket type (due to an older version |
| 164 // of Keystone being used), returns NO. | 171 // of Keystone being used), returns NO. |
| 165 - (BOOL)isUserTicket; | 172 - (BOOL)isUserTicket; |
| 166 | 173 |
| 167 // Returns YES if Keystone is definitely installed at the system level, | 174 // Returns YES if Keystone is definitely installed at the system level, |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 201 // tag key. If a full installer (as opposed to a binary diff/delta patch) is | 208 // tag key. If a full installer (as opposed to a binary diff/delta patch) is |
| 202 // required, the tag suffix will contain the string "-full". If no special | 209 // required, the tag suffix will contain the string "-full". If no special |
| 203 // treatment is required, the tag suffix will be an empty string. | 210 // treatment is required, the tag suffix will be an empty string. |
| 204 - (NSString*)tagSuffix; | 211 - (NSString*)tagSuffix; |
| 205 | 212 |
| 206 @end // @interface KeystoneGlue (Private) | 213 @end // @interface KeystoneGlue (Private) |
| 207 | 214 |
| 208 NSString* const kAutoupdateStatusNotification = @"AutoupdateStatusNotification"; | 215 NSString* const kAutoupdateStatusNotification = @"AutoupdateStatusNotification"; |
| 209 NSString* const kAutoupdateStatusStatus = @"status"; | 216 NSString* const kAutoupdateStatusStatus = @"status"; |
| 210 NSString* const kAutoupdateStatusVersion = @"version"; | 217 NSString* const kAutoupdateStatusVersion = @"version"; |
| 218 NSString* const kAutoupdateStatusErrorMessages = @"errormessages"; | |
| 211 | 219 |
| 212 namespace { | 220 namespace { |
| 213 | 221 |
| 214 NSString* const kChannelKey = @"KSChannelID"; | 222 NSString* const kChannelKey = @"KSChannelID"; |
| 215 NSString* const kBrandKey = @"KSBrandID"; | 223 NSString* const kBrandKey = @"KSBrandID"; |
| 216 NSString* const kVersionKey = @"KSVersion"; | 224 NSString* const kVersionKey = @"KSVersion"; |
| 217 | 225 |
| 218 } // namespace | 226 } // namespace |
| 219 | 227 |
| 220 @implementation KeystoneGlue | 228 @implementation KeystoneGlue |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 529 NSArray* profileCountsInformation = | 537 NSArray* profileCountsInformation = |
| 530 [NSArray arrayWithObjects:numAccountsAttr, numSignedInAccountsAttr, nil]; | 538 [NSArray arrayWithObjects:numAccountsAttr, numSignedInAccountsAttr, nil]; |
| 531 | 539 |
| 532 if (![registration_ setActiveWithReportingAttributes:profileCountsInformation | 540 if (![registration_ setActiveWithReportingAttributes:profileCountsInformation |
| 533 error:&reportingError]) { | 541 error:&reportingError]) { |
| 534 VLOG(1) << [reportingError localizedDescription]; | 542 VLOG(1) << [reportingError localizedDescription]; |
| 535 } | 543 } |
| 536 } | 544 } |
| 537 | 545 |
| 538 - (void)registerWithKeystone { | 546 - (void)registerWithKeystone { |
| 539 [self updateStatus:kAutoupdateRegistering version:nil]; | 547 [self updateStatus:kAutoupdateRegistering version:nil error:nil]; |
| 548 | |
| 549 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.
| |
| 550 [self updateStatus:kAutoupdateRegisterFailed | |
| 551 version:nil | |
| 552 error:kNoRegistrationErrorMessage]; | |
| 553 return; | |
| 554 } | |
| 540 | 555 |
| 541 NSDictionary* parameters = [self keystoneParameters]; | 556 NSDictionary* parameters = [self keystoneParameters]; |
| 542 BOOL result = [registration_ registerWithParameters:parameters]; | 557 BOOL result = [registration_ registerWithParameters:parameters]; |
| 543 if (!result) { | 558 if (!result) { |
| 544 [self updateStatus:kAutoupdateRegisterFailed version:nil]; | 559 // TODO: If Keystone ever makes a variant of this API with a withError: |
| 560 // parameter, include the error message here in the call to updateStatus:. | |
| 561 [self updateStatus:kAutoupdateRegisterFailed version:nil error:nil]; | |
| 545 return; | 562 return; |
| 546 } | 563 } |
| 547 | 564 |
| 548 // Upon completion, ksr::KSRegistrationDidCompleteNotification will be | 565 // Upon completion, ksr::KSRegistrationDidCompleteNotification will be |
| 549 // posted, and -registrationComplete: will be called. | 566 // posted, and -registrationComplete: will be called. |
| 550 | 567 |
| 551 // Set up hourly activity pings. | 568 // Set up hourly activity pings. |
| 552 timer_ = [NSTimer scheduledTimerWithTimeInterval:60 * 60 // One hour | 569 timer_ = [NSTimer scheduledTimerWithTimeInterval:60 * 60 // One hour |
| 553 target:self | 570 target:self |
| 554 selector:@selector(markActive:) | 571 selector:@selector(markActive:) |
| 555 userInfo:nil | 572 userInfo:nil |
| 556 repeats:YES]; | 573 repeats:YES]; |
| 557 } | 574 } |
| 558 | 575 |
| 559 - (BOOL)isRegisteredAndActive { | 576 - (BOOL)isRegisteredAndActive { |
| 560 return registrationActive_; | 577 return registrationActive_; |
| 561 } | 578 } |
| 562 | 579 |
| 563 - (void)registrationComplete:(NSNotification*)notification { | 580 - (void)registrationComplete:(NSNotification*)notification { |
| 564 NSDictionary* userInfo = [notification userInfo]; | 581 NSDictionary* userInfo = [notification userInfo]; |
| 582 NSString* errorMessages = | |
| 583 [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
| |
| 584 | |
| 565 if ([[userInfo objectForKey:ksr::KSRegistrationStatusKey] boolValue]) { | 585 if ([[userInfo objectForKey:ksr::KSRegistrationStatusKey] boolValue]) { |
| 566 if ([self isSystemTicketDoomed]) { | 586 if ([self isSystemTicketDoomed]) { |
| 567 [self updateStatus:kAutoupdateNeedsPromotion version:nil]; | 587 [self updateStatus:kAutoupdateNeedsPromotion |
| 588 version:nil | |
| 589 error:errorMessages]; | |
| 568 } else { | 590 } else { |
| 569 [self updateStatus:kAutoupdateRegistered version:nil]; | 591 [self updateStatus:kAutoupdateRegistered version:nil error:errorMessages]; |
| 570 } | 592 } |
| 571 } else { | 593 } else { |
| 572 // Dump registration_? | 594 // Dump registration_? |
| 573 [self updateStatus:kAutoupdateRegisterFailed version:nil]; | 595 [self updateStatus:kAutoupdateRegisterFailed |
| 596 version:nil | |
| 597 error:errorMessages]; | |
| 574 } | 598 } |
| 575 } | 599 } |
| 576 | 600 |
| 577 - (void)stopTimer { | 601 - (void)stopTimer { |
| 578 [timer_ invalidate]; | 602 [timer_ invalidate]; |
| 579 } | 603 } |
| 580 | 604 |
| 581 - (void)markActive:(NSTimer*)timer { | 605 - (void)markActive:(NSTimer*)timer { |
| 582 [self setRegistrationActive]; | 606 [self setRegistrationActive]; |
| 583 } | 607 } |
| 584 | 608 |
| 585 - (void)checkForUpdate { | 609 - (void)checkForUpdate { |
| 586 DCHECK(![self asyncOperationPending]); | 610 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.
| |
| 587 | 611 // Update check already in process; return without doing anything. |
| 588 if (!registration_) { | 612 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
| |
| 589 [self updateStatus:kAutoupdateCheckFailed version:nil]; | |
| 590 return; | 613 return; |
| 591 } | 614 } |
| 592 | 615 |
| 593 [self updateStatus:kAutoupdateChecking version:nil]; | 616 if (!registration_) { |
| 617 [self updateStatus:kAutoupdateCheckFailed | |
| 618 version:nil | |
| 619 error:kNoRegistrationErrorMessage]; | |
| 620 return; | |
| 621 } | |
| 622 | |
| 623 [self updateStatus:kAutoupdateChecking version:nil error:nil]; | |
| 594 | 624 |
| 595 // All checks from inside Chrome are considered user-initiated, because they | 625 // All checks from inside Chrome are considered user-initiated, because they |
| 596 // only happen following a user action, such as visiting the about page. | 626 // only happen following a user action, such as visiting the about page. |
| 597 // Non-user-initiated checks are the periodic checks automatically made by | 627 // Non-user-initiated checks are the periodic checks automatically made by |
| 598 // Keystone, which don't come through this code path (or even this process). | 628 // Keystone, which don't come through this code path (or even this process). |
| 599 [registration_ checkForUpdateWasUserInitiated:YES]; | 629 [registration_ checkForUpdateWasUserInitiated:YES]; |
| 600 | 630 |
| 601 // Upon completion, ksr::KSRegistrationCheckForUpdateNotification will be | 631 // Upon completion, ksr::KSRegistrationCheckForUpdateNotification will be |
| 602 // posted, and -checkForUpdateComplete: will be called. | 632 // posted, and -checkForUpdateComplete: will be called. |
| 603 } | 633 } |
| 604 | 634 |
| 605 - (void)checkForUpdateComplete:(NSNotification*)notification { | 635 - (void)checkForUpdateComplete:(NSNotification*)notification { |
| 606 NSDictionary* userInfo = [notification userInfo]; | 636 NSDictionary* userInfo = [notification userInfo]; |
| 637 NSString* errorMessages = | |
| 638 [userInfo objectForKey:ksr::KSRegistrationUpdateCheckRawErrorMessagesKey]; | |
| 607 | 639 |
| 608 if ([[userInfo objectForKey:ksr::KSRegistrationUpdateCheckErrorKey] | 640 if ([[userInfo objectForKey:ksr::KSRegistrationUpdateCheckErrorKey] |
| 609 boolValue]) { | 641 boolValue]) { |
| 610 [self updateStatus:kAutoupdateCheckFailed version:nil]; | 642 [self updateStatus:kAutoupdateCheckFailed version:nil error:errorMessages]; |
| 611 } else if ([[userInfo objectForKey:ksr::KSRegistrationStatusKey] boolValue]) { | 643 } else if ([[userInfo objectForKey:ksr::KSRegistrationStatusKey] boolValue]) { |
| 612 // If an update is known to be available, go straight to | 644 // If an update is known to be available, go straight to |
| 613 // -updateStatus:version:. It doesn't matter what's currently on disk. | 645 // -updateStatus:version:. It doesn't matter what's currently on disk. |
| 614 NSString* version = [userInfo objectForKey:ksr::KSRegistrationVersionKey]; | 646 NSString* version = [userInfo objectForKey:ksr::KSRegistrationVersionKey]; |
| 615 [self updateStatus:kAutoupdateAvailable version:version]; | 647 [self updateStatus:kAutoupdateAvailable |
| 648 version:version | |
| 649 error:errorMessages]; | |
| 616 } else { | 650 } else { |
| 617 // If no updates are available, check what's on disk, because an update | 651 // If no updates are available, check what's on disk, because an update |
| 618 // may have already been installed. This check happens on another thread, | 652 // may have already been installed. This check happens on another thread, |
| 619 // and -updateStatus:version: will be called on the main thread when done. | 653 // and -updateStatus:version: will be called on the main thread when done. |
| 620 [self determineUpdateStatusAsync]; | 654 [self determineUpdateStatusAsync]; |
| 621 } | 655 } |
| 622 } | 656 } |
| 623 | 657 |
| 624 - (void)installUpdate { | 658 - (void)installUpdate { |
| 625 DCHECK(![self asyncOperationPending]); | 659 if ([self asyncOperationPending]) { |
| 626 | 660 // Update check already in process; return without doing anything. |
| 627 if (!registration_) { | 661 VLOG(1) << "installUpdate ignored; async operation pending"; |
| 628 [self updateStatus:kAutoupdateInstallFailed version:nil]; | |
| 629 return; | 662 return; |
| 630 } | 663 } |
| 631 | 664 |
| 632 [self updateStatus:kAutoupdateInstalling version:nil]; | 665 if (!registration_) { |
| 666 [self updateStatus:kAutoupdateInstallFailed | |
| 667 version:nil | |
| 668 error:kNoRegistrationErrorMessage]; | |
| 669 return; | |
| 670 } | |
| 671 | |
| 672 [self updateStatus:kAutoupdateInstalling version:nil error:nil]; | |
| 633 | 673 |
| 634 [registration_ startUpdate]; | 674 [registration_ startUpdate]; |
| 635 | 675 |
| 636 // Upon completion, ksr::KSRegistrationStartUpdateNotification will be | 676 // Upon completion, ksr::KSRegistrationStartUpdateNotification will be |
| 637 // posted, and -installUpdateComplete: will be called. | 677 // posted, and -installUpdateComplete: will be called. |
| 638 } | 678 } |
| 639 | 679 |
| 640 - (void)installUpdateComplete:(NSNotification*)notification { | 680 - (void)installUpdateComplete:(NSNotification*)notification { |
| 641 NSDictionary* userInfo = [notification userInfo]; | 681 NSDictionary* userInfo = [notification userInfo]; |
| 682 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.
| |
| 683 [userInfo objectForKey:ksr::KSRegistrationUpdateCheckRawErrorMessagesKey]; | |
| 642 | 684 |
| 643 // http://crbug.com/160308 and b/7517358: when using system Keystone and on | 685 // http://crbug.com/160308 and b/7517358: when using system Keystone and on |
| 644 // a user ticket, KSUpdateCheckSuccessfulKey will be NO even when an update | 686 // a user ticket, KSUpdateCheckSuccessfulKey will be NO even when an update |
| 645 // was installed correctly, so don't check it. It should be redudnant when | 687 // was installed correctly, so don't check it. It should be redudnant when |
| 646 // KSUpdateCheckSuccessfullyInstalledKey is checked. | 688 // KSUpdateCheckSuccessfullyInstalledKey is checked. |
| 647 if (![[userInfo objectForKey:ksr::KSUpdateCheckSuccessfullyInstalledKey] | 689 if (![[userInfo objectForKey:ksr::KSUpdateCheckSuccessfullyInstalledKey] |
| 648 intValue]) { | 690 intValue]) { |
| 649 [self updateStatus:kAutoupdateInstallFailed version:nil]; | 691 [self updateStatus:kAutoupdateInstallFailed version:nil error:errorMsgs]; |
| 650 } else { | 692 } else { |
| 651 updateSuccessfullyInstalled_ = YES; | 693 updateSuccessfullyInstalled_ = YES; |
| 652 | 694 |
| 653 // Nothing in the notification dictionary reports the version that was | 695 // Nothing in the notification dictionary reports the version that was |
| 654 // installed. Figure it out based on what's on disk. | 696 // installed. Figure it out based on what's on disk. |
| 655 [self determineUpdateStatusAsync]; | 697 [self determineUpdateStatusAsync]; |
| 656 } | 698 } |
| 657 } | 699 } |
| 658 | 700 |
| 659 - (NSString*)currentlyInstalledVersion { | 701 - (NSString*)currentlyInstalledVersion { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 702 status = kAutoupdateCurrent; | 744 status = kAutoupdateCurrent; |
| 703 } else { | 745 } else { |
| 704 // If the version on disk doesn't match what's currently running, an | 746 // If the version on disk doesn't match what's currently running, an |
| 705 // update must have been applied in the background, without this app's | 747 // update must have been applied in the background, without this app's |
| 706 // direct participation. Leave updateSuccessfullyInstalled_ alone | 748 // direct participation. Leave updateSuccessfullyInstalled_ alone |
| 707 // because there's no direct knowledge of what actually happened. | 749 // because there's no direct knowledge of what actually happened. |
| 708 status = kAutoupdateInstalled; | 750 status = kAutoupdateInstalled; |
| 709 } | 751 } |
| 710 } | 752 } |
| 711 | 753 |
| 712 [self updateStatus:status version:version]; | 754 [self updateStatus:status version:version error:nil]; |
| 713 } | 755 } |
| 714 | 756 |
| 715 - (void)updateStatus:(AutoupdateStatus)status version:(NSString*)version { | 757 - (void)updateStatus:(AutoupdateStatus)status |
| 758 version:(NSString*)version | |
| 759 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.
| |
| 716 NSNumber* statusNumber = [NSNumber numberWithInt:status]; | 760 NSNumber* statusNumber = [NSNumber numberWithInt:status]; |
| 717 NSMutableDictionary* dictionary = | 761 NSMutableDictionary* dictionary = |
| 718 [NSMutableDictionary dictionaryWithObject:statusNumber | 762 [NSMutableDictionary dictionaryWithObject:statusNumber |
| 719 forKey:kAutoupdateStatusStatus]; | 763 forKey:kAutoupdateStatusStatus]; |
| 720 if (version) { | 764 if (version) { |
| 721 [dictionary setObject:version forKey:kAutoupdateStatusVersion]; | 765 [dictionary setObject:version forKey:kAutoupdateStatusVersion]; |
| 722 } | 766 } |
| 767 if (error) { | |
| 768 [dictionary setObject:version forKey:kAutoupdateStatusErrorMessages]; | |
| 769 } | |
| 723 | 770 |
| 724 NSNotification* notification = | 771 NSNotification* notification = |
| 725 [NSNotification notificationWithName:kAutoupdateStatusNotification | 772 [NSNotification notificationWithName:kAutoupdateStatusNotification |
| 726 object:self | 773 object:self |
| 727 userInfo:dictionary]; | 774 userInfo:dictionary]; |
| 728 recentNotification_.reset([notification retain]); | 775 recentNotification_.reset([notification retain]); |
| 729 | 776 |
| 730 [[NSNotificationCenter defaultCenter] postNotification:notification]; | 777 [[NSNotificationCenter defaultCenter] postNotification:notification]; |
| 731 } | 778 } |
| 732 | 779 |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 831 | 878 |
| 832 return [appPath_ hasPrefix:@"/Applications/"]; | 879 return [appPath_ hasPrefix:@"/Applications/"]; |
| 833 } | 880 } |
| 834 | 881 |
| 835 - (void)promoteTicket { | 882 - (void)promoteTicket { |
| 836 if ([self asyncOperationPending] || ![self wantsPromotion]) { | 883 if ([self asyncOperationPending] || ![self wantsPromotion]) { |
| 837 // Because there are multiple ways of reaching promoteTicket that might | 884 // Because there are multiple ways of reaching promoteTicket that might |
| 838 // not lock each other out, it may be possible to arrive here while an | 885 // not lock each other out, it may be possible to arrive here while an |
| 839 // asynchronous operation is pending, or even after promotion has already | 886 // asynchronous operation is pending, or even after promotion has already |
| 840 // occurred. Just quietly return without doing anything. | 887 // occurred. Just quietly return without doing anything. |
| 888 VLOG(1) << "promoteTicket ignored; async operation pending"; | |
| 841 return; | 889 return; |
| 842 } | 890 } |
| 843 | 891 |
| 844 NSString* prompt = l10n_util::GetNSStringFWithFixup( | 892 NSString* prompt = l10n_util::GetNSStringFWithFixup( |
| 845 IDS_PROMOTE_AUTHENTICATION_PROMPT, | 893 IDS_PROMOTE_AUTHENTICATION_PROMPT, |
| 846 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); | 894 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); |
| 847 base::mac::ScopedAuthorizationRef authorization( | 895 base::mac::ScopedAuthorizationRef authorization( |
| 848 base::mac::AuthorizationCreateToRunAsRoot( | 896 base::mac::AuthorizationCreateToRunAsRoot( |
| 849 base::mac::NSToCFCast(prompt))); | 897 base::mac::NSToCFCast(prompt))); |
| 850 if (!authorization.get()) { | 898 if (!authorization.get()) { |
| 851 return; | 899 return; |
| 852 } | 900 } |
| 853 | 901 |
| 854 [self promoteTicketWithAuthorization:authorization.release() synchronous:NO]; | 902 [self promoteTicketWithAuthorization:authorization.release() synchronous:NO]; |
| 855 } | 903 } |
| 856 | 904 |
| 857 - (void)promoteTicketWithAuthorization:(AuthorizationRef)authorization_arg | 905 - (void)promoteTicketWithAuthorization:(AuthorizationRef)authorization_arg |
| 858 synchronous:(BOOL)synchronous { | 906 synchronous:(BOOL)synchronous { |
| 859 base::mac::ScopedAuthorizationRef authorization(authorization_arg); | 907 base::mac::ScopedAuthorizationRef authorization(authorization_arg); |
| 860 authorization_arg = NULL; | 908 authorization_arg = NULL; |
| 861 | 909 |
| 862 if ([self asyncOperationPending]) { | 910 if ([self asyncOperationPending]) { |
| 863 // Starting a synchronous operation while an asynchronous one is pending | 911 // Starting a synchronous operation while an asynchronous one is pending |
| 864 // could be trouble. | 912 // could be trouble. |
| 913 VLOG(1) << "promoteTicketWithAuth ignored; async operation pending"; | |
| 865 return; | 914 return; |
| 866 } | 915 } |
| 867 if (!synchronous && ![self wantsPromotion]) { | 916 if (!synchronous && ![self wantsPromotion]) { |
| 868 // If operating synchronously, the call came from the installer, which | 917 // If operating synchronously, the call came from the installer, which |
| 869 // means that a system ticket is required. Otherwise, only allow | 918 // means that a system ticket is required. Otherwise, only allow |
| 870 // promotion if it's wanted. | 919 // promotion if it's wanted. |
| 871 return; | 920 return; |
| 872 } | 921 } |
| 873 | 922 |
| 874 synchronousPromotion_ = synchronous; | 923 synchronousPromotion_ = synchronous; |
| 875 | 924 |
| 876 [self updateStatus:kAutoupdatePromoting version:nil]; | 925 [self updateStatus:kAutoupdatePromoting version:nil error:nil]; |
| 877 | 926 |
| 878 // TODO(mark): Remove when able! | 927 // TODO(mark): Remove when able! |
| 879 // | 928 // |
| 880 // keystone_promote_preflight will copy the current brand information out to | 929 // keystone_promote_preflight will copy the current brand information out to |
| 881 // the system level so all users can share the data as part of the ticket | 930 // the system level so all users can share the data as part of the ticket |
| 882 // promotion. | 931 // promotion. |
| 883 // | 932 // |
| 884 // It will also ensure that the Keystone system ticket store is in a usable | 933 // It will also ensure that the Keystone system ticket store is in a usable |
| 885 // state for all users on the system. Ideally, Keystone's installer or | 934 // state for all users on the system. Ideally, Keystone's installer or |
| 886 // another part of Keystone would handle this. The underlying problem is | 935 // another part of Keystone would handle this. The underlying problem is |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 915 OSStatus status = base::mac::ExecuteWithPrivilegesAndWait( | 964 OSStatus status = base::mac::ExecuteWithPrivilegesAndWait( |
| 916 authorization, | 965 authorization, |
| 917 preflightPathC, | 966 preflightPathC, |
| 918 kAuthorizationFlagDefaults, | 967 kAuthorizationFlagDefaults, |
| 919 arguments, | 968 arguments, |
| 920 NULL, // pipe | 969 NULL, // pipe |
| 921 &exit_status); | 970 &exit_status); |
| 922 if (status != errAuthorizationSuccess) { | 971 if (status != errAuthorizationSuccess) { |
| 923 OSSTATUS_LOG(ERROR, status) | 972 OSSTATUS_LOG(ERROR, status) |
| 924 << "AuthorizationExecuteWithPrivileges preflight"; | 973 << "AuthorizationExecuteWithPrivileges preflight"; |
| 925 [self updateStatus:kAutoupdatePromoteFailed version:nil]; | 974 |
| 975 NSString *errorMessage = | |
| 976 [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.
| |
| 977 (long)status]; | |
| 978 [self updateStatus:kAutoupdatePromoteFailed | |
| 979 version:nil | |
| 980 error:errorMessage]; | |
| 926 return; | 981 return; |
| 927 } | 982 } |
| 928 if (exit_status != 0) { | 983 if (exit_status != 0) { |
| 929 LOG(ERROR) << "keystone_promote_preflight status " << exit_status; | 984 LOG(ERROR) << "keystone_promote_preflight status " << exit_status; |
| 930 [self updateStatus:kAutoupdatePromoteFailed version:nil]; | 985 |
| 986 NSString *errorMessage = | |
| 987 [NSString stringWithFormat:@"Promotion pre-flight script failed: %d", | |
| 988 exit_status]; | |
| 989 [self updateStatus:kAutoupdatePromoteFailed | |
| 990 version:nil | |
| 991 error:errorMessage]; | |
| 931 return; | 992 return; |
| 932 } | 993 } |
| 933 | 994 |
| 934 // Hang on to the AuthorizationRef so that it can be used once promotion is | 995 // Hang on to the AuthorizationRef so that it can be used once promotion is |
| 935 // complete. Do this before asking Keystone to promote the ticket, because | 996 // complete. Do this before asking Keystone to promote the ticket, because |
| 936 // -promotionComplete: may be called from inside the Keystone promotion | 997 // -promotionComplete: may be called from inside the Keystone promotion |
| 937 // call. | 998 // call. |
| 938 authorization_.swap(authorization); | 999 authorization_.swap(authorization); |
| 939 | 1000 |
| 940 NSDictionary* parameters = [self keystoneParameters]; | 1001 NSDictionary* parameters = [self keystoneParameters]; |
| 941 | 1002 |
| 942 // If the brand file is user level, update parameters to point to the new | 1003 // If the brand file is user level, update parameters to point to the new |
| 943 // system level file during promotion. | 1004 // system level file during promotion. |
| 944 if (brandFileType_ == kBrandFileTypeUser) { | 1005 if (brandFileType_ == kBrandFileTypeUser) { |
| 945 NSMutableDictionary* temp_parameters = | 1006 NSMutableDictionary* temp_parameters = |
| 946 [[parameters mutableCopy] autorelease]; | 1007 [[parameters mutableCopy] autorelease]; |
| 947 [temp_parameters setObject:SystemBrandFilePath() | 1008 [temp_parameters setObject:SystemBrandFilePath() |
| 948 forKey:ksr::KSRegistrationBrandPathKey]; | 1009 forKey:ksr::KSRegistrationBrandPathKey]; |
| 949 parameters = temp_parameters; | 1010 parameters = temp_parameters; |
| 950 } | 1011 } |
| 951 | 1012 |
| 952 if (![registration_ promoteWithParameters:parameters | 1013 if (![registration_ promoteWithParameters:parameters |
| 953 authorization:authorization_]) { | 1014 authorization:authorization_]) { |
| 954 [self updateStatus:kAutoupdatePromoteFailed version:nil]; | 1015 // TODO: If Keystone ever makes a variant of this API with a withError: |
| 1016 // parameter, include the error message here in the call to updateStatus:. | |
| 1017 [self updateStatus:kAutoupdatePromoteFailed version:nil error:nil]; | |
| 955 authorization_.reset(); | 1018 authorization_.reset(); |
| 956 return; | 1019 return; |
| 957 } | 1020 } |
| 958 | 1021 |
| 959 // Upon completion, ksr::KSRegistrationPromotionDidCompleteNotification will | 1022 // Upon completion, ksr::KSRegistrationPromotionDidCompleteNotification will |
| 960 // be posted, and -promotionComplete: will be called. | 1023 // be posted, and -promotionComplete: will be called. |
| 961 | 1024 |
| 962 // If synchronous, see to it that this happens immediately. Give it a | 1025 // If synchronous, see to it that this happens immediately. Give it a |
| 963 // 10-second deadline. | 1026 // 10-second deadline. |
| 964 if (synchronous) { | 1027 if (synchronous) { |
| 965 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 10, false); | 1028 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 10, false); |
| 966 } | 1029 } |
| 967 } | 1030 } |
| 968 | 1031 |
| 969 - (void)promotionComplete:(NSNotification*)notification { | 1032 - (void)promotionComplete:(NSNotification*)notification { |
| 970 NSDictionary* userInfo = [notification userInfo]; | 1033 NSDictionary* userInfo = [notification userInfo]; |
| 971 if ([[userInfo objectForKey:ksr::KSRegistrationStatusKey] boolValue]) { | 1034 if ([[userInfo objectForKey:ksr::KSRegistrationStatusKey] boolValue]) { |
| 972 if (synchronousPromotion_) { | 1035 if (synchronousPromotion_) { |
| 973 // Short-circuit: if performing a synchronous promotion, the promotion | 1036 // Short-circuit: if performing a synchronous promotion, the promotion |
| 974 // came from the installer, which already set the permissions properly. | 1037 // came from the installer, which already set the permissions properly. |
| 975 // Rather than run a duplicate permission-changing operation, jump | 1038 // Rather than run a duplicate permission-changing operation, jump |
| 976 // straight to "done." | 1039 // straight to "done." |
| 977 [self changePermissionsForPromotionComplete]; | 1040 [self changePermissionsForPromotionComplete]; |
| 978 } else { | 1041 } else { |
| 979 [self changePermissionsForPromotionAsync]; | 1042 [self changePermissionsForPromotionAsync]; |
| 980 } | 1043 } |
| 981 } else { | 1044 } else { |
| 982 authorization_.reset(); | 1045 authorization_.reset(); |
| 983 [self updateStatus:kAutoupdatePromoteFailed version:nil]; | 1046 [self updateStatus:kAutoupdatePromoteFailed version:nil error:nil]; |
| 984 } | 1047 } |
| 985 | 1048 |
| 986 if (synchronousPromotion_) { | 1049 if (synchronousPromotion_) { |
| 987 // The run loop doesn't need to wait for this any longer. | 1050 // The run loop doesn't need to wait for this any longer. |
| 988 CFRunLoopRef runLoop = CFRunLoopGetCurrent(); | 1051 CFRunLoopRef runLoop = CFRunLoopGetCurrent(); |
| 989 CFRunLoopStop(runLoop); | 1052 CFRunLoopStop(runLoop); |
| 990 CFRunLoopWakeUp(runLoop); | 1053 CFRunLoopWakeUp(runLoop); |
| 991 } | 1054 } |
| 992 } | 1055 } |
| 993 | 1056 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1029 | 1092 |
| 1030 SEL selector = @selector(changePermissionsForPromotionComplete); | 1093 SEL selector = @selector(changePermissionsForPromotionComplete); |
| 1031 [self performSelectorOnMainThread:selector | 1094 [self performSelectorOnMainThread:selector |
| 1032 withObject:nil | 1095 withObject:nil |
| 1033 waitUntilDone:NO]; | 1096 waitUntilDone:NO]; |
| 1034 } | 1097 } |
| 1035 | 1098 |
| 1036 - (void)changePermissionsForPromotionComplete { | 1099 - (void)changePermissionsForPromotionComplete { |
| 1037 authorization_.reset(); | 1100 authorization_.reset(); |
| 1038 | 1101 |
| 1039 [self updateStatus:kAutoupdatePromoted version:nil]; | 1102 [self updateStatus:kAutoupdatePromoted version:nil error:nil]; |
| 1040 } | 1103 } |
| 1041 | 1104 |
| 1042 - (void)setAppPath:(NSString*)appPath { | 1105 - (void)setAppPath:(NSString*)appPath { |
| 1043 if (appPath != appPath_) { | 1106 if (appPath != appPath_) { |
| 1044 [appPath_ release]; | 1107 [appPath_ release]; |
| 1045 appPath_ = [appPath copy]; | 1108 appPath_ = [appPath copy]; |
| 1046 } | 1109 } |
| 1047 } | 1110 } |
| 1048 | 1111 |
| 1049 - (BOOL)wantsFullInstaller { | 1112 - (BOOL)wantsFullInstaller { |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1131 return [KeystoneGlue defaultKeystoneGlue] != nil; | 1194 return [KeystoneGlue defaultKeystoneGlue] != nil; |
| 1132 } | 1195 } |
| 1133 | 1196 |
| 1134 base::string16 CurrentlyInstalledVersion() { | 1197 base::string16 CurrentlyInstalledVersion() { |
| 1135 KeystoneGlue* keystoneGlue = [KeystoneGlue defaultKeystoneGlue]; | 1198 KeystoneGlue* keystoneGlue = [KeystoneGlue defaultKeystoneGlue]; |
| 1136 NSString* version = [keystoneGlue currentlyInstalledVersion]; | 1199 NSString* version = [keystoneGlue currentlyInstalledVersion]; |
| 1137 return base::SysNSStringToUTF16(version); | 1200 return base::SysNSStringToUTF16(version); |
| 1138 } | 1201 } |
| 1139 | 1202 |
| 1140 } // namespace keystone_glue | 1203 } // namespace keystone_glue |
| OLD | NEW |