Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(141)

Side by Side Diff: chrome/browser/mac/keystone_glue.mm

Issue 1769703002: Add viewing of error messages from Keystone upon self-update failure. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Code review feedback pt2 Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698