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

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: 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 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
120 120
121 // Set the registration active and pass profile count parameters. 121 // Set the registration active and pass profile count parameters.
122 - (void)setRegistrationActive; 122 - (void)setRegistrationActive;
123 123
124 // Called periodically to announce activity by pinging the Keystone server. 124 // Called periodically to announce activity by pinging the Keystone server.
125 - (void)markActive:(NSTimer*)timer; 125 - (void)markActive:(NSTimer*)timer;
126 126
127 // Called when an update check or update installation is complete. Posts the 127 // Called when an update check or update installation is complete. Posts the
128 // kAutoupdateStatusNotification notification to the default notification 128 // kAutoupdateStatusNotification notification to the default notification
129 // center. 129 // center.
130 - (void)updateStatus:(AutoupdateStatus)status version:(NSString*)version; 130 - (void)updateStatus:(AutoupdateStatus)status
131 version:(NSString*)version
132 error:(NSString *)error;
Boris Vidolov 2016/03/08 22:32:51 Fix the spaces around NSString pointer type. I bel
Ryan Myers (chromium) 2016/03/22 22:39:22 Done.
131 133
132 // Returns the version of the currently-installed application on disk. 134 // Returns the version of the currently-installed application on disk.
133 - (NSString*)currentlyInstalledVersion; 135 - (NSString*)currentlyInstalledVersion;
134 136
135 // These three methods are used to determine the version of the application 137 // These three methods are used to determine the version of the application
136 // currently installed on disk, compare that to the currently-running version, 138 // currently installed on disk, compare that to the currently-running version,
137 // decide whether any updates have been installed, and call 139 // decide whether any updates have been installed, and call
138 // -updateStatus:version:. 140 // -updateStatus:version:error:.
139 // 141 //
140 // In order to check the version on disk, the installed application's 142 // 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 143 // 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 144 // 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 145 // 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 146 // 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 147 // thread. I'm not quite sure what jank means, but I bet that a blocked main
146 // thread would cause some of it. 148 // thread would cause some of it.
147 // 149 //
148 // -determineUpdateStatusAsync is called on the main thread to initiate the 150 // -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 151 // 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 152 // thread and arranges for -determineUpdateStatus to be called on a work queue
151 // thread managed by WorkerPool. 153 // thread managed by WorkerPool.
152 // -determineUpdateStatus then reads the Info.plist, gets the version from the 154 // -determineUpdateStatus then reads the Info.plist, gets the version from the
153 // CFBundleShortVersionString key, and performs 155 // CFBundleShortVersionString key, and performs
154 // -determineUpdateStatusForVersion: on the main thread. 156 // -determineUpdateStatusForVersion: on the main thread.
155 // -determineUpdateStatusForVersion: does the actual comparison of the version 157 // -determineUpdateStatusForVersion: does the actual comparison of the version
156 // on disk with the running version and calls -updateStatus:version: with the 158 // on disk with the running version and calls -updateStatus:version:error: with
157 // results of its analysis. 159 // the results of its analysis.
158 - (void)determineUpdateStatusAsync; 160 - (void)determineUpdateStatusAsync;
159 - (void)determineUpdateStatus; 161 - (void)determineUpdateStatus;
160 - (void)determineUpdateStatusForVersion:(NSString*)version; 162 - (void)determineUpdateStatusForVersion:(NSString*)version;
161 163
162 // Returns YES if registration_ is definitely on a user ticket. If definitely 164 // 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 165 // on a system ticket, or uncertain of ticket type (due to an older version
164 // of Keystone being used), returns NO. 166 // of Keystone being used), returns NO.
165 - (BOOL)isUserTicket; 167 - (BOOL)isUserTicket;
166 168
167 // Returns YES if Keystone is definitely installed at the system level, 169 // 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 203 // 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 204 // required, the tag suffix will contain the string "-full". If no special
203 // treatment is required, the tag suffix will be an empty string. 205 // treatment is required, the tag suffix will be an empty string.
204 - (NSString*)tagSuffix; 206 - (NSString*)tagSuffix;
205 207
206 @end // @interface KeystoneGlue (Private) 208 @end // @interface KeystoneGlue (Private)
207 209
208 NSString* const kAutoupdateStatusNotification = @"AutoupdateStatusNotification"; 210 NSString* const kAutoupdateStatusNotification = @"AutoupdateStatusNotification";
209 NSString* const kAutoupdateStatusStatus = @"status"; 211 NSString* const kAutoupdateStatusStatus = @"status";
210 NSString* const kAutoupdateStatusVersion = @"version"; 212 NSString* const kAutoupdateStatusVersion = @"version";
213 NSString* const kAutoupdateStatusErrorMessages = @"errormessages";
211 214
212 namespace { 215 namespace {
213 216
214 NSString* const kChannelKey = @"KSChannelID"; 217 NSString* const kChannelKey = @"KSChannelID";
215 NSString* const kBrandKey = @"KSBrandID"; 218 NSString* const kBrandKey = @"KSBrandID";
216 NSString* const kVersionKey = @"KSVersion"; 219 NSString* const kVersionKey = @"KSVersion";
217 220
218 } // namespace 221 } // namespace
219 222
220 @implementation KeystoneGlue 223 @implementation KeystoneGlue
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after
529 NSArray* profileCountsInformation = 532 NSArray* profileCountsInformation =
530 [NSArray arrayWithObjects:numAccountsAttr, numSignedInAccountsAttr, nil]; 533 [NSArray arrayWithObjects:numAccountsAttr, numSignedInAccountsAttr, nil];
531 534
532 if (![registration_ setActiveWithReportingAttributes:profileCountsInformation 535 if (![registration_ setActiveWithReportingAttributes:profileCountsInformation
533 error:&reportingError]) { 536 error:&reportingError]) {
534 VLOG(1) << [reportingError localizedDescription]; 537 VLOG(1) << [reportingError localizedDescription];
535 } 538 }
536 } 539 }
537 540
538 - (void)registerWithKeystone { 541 - (void)registerWithKeystone {
539 [self updateStatus:kAutoupdateRegistering version:nil]; 542 [self updateStatus:kAutoupdateRegistering version:nil error:nil];
540 543
541 NSDictionary* parameters = [self keystoneParameters]; 544 NSDictionary* parameters = [self keystoneParameters];
542 BOOL result = [registration_ registerWithParameters:parameters]; 545 BOOL result = [registration_ registerWithParameters:parameters];
543 if (!result) { 546 if (!result) {
544 [self updateStatus:kAutoupdateRegisterFailed version:nil]; 547 // TODO: If Keystone ever makes a variant of this API with a withError:
548 // parameter, include the error message here in the call to updateStatus:.
549 [self updateStatus:kAutoupdateRegisterFailed version:nil error:nil];
545 return; 550 return;
546 } 551 }
547 552
548 // Upon completion, ksr::KSRegistrationDidCompleteNotification will be 553 // Upon completion, ksr::KSRegistrationDidCompleteNotification will be
549 // posted, and -registrationComplete: will be called. 554 // posted, and -registrationComplete: will be called.
550 555
551 // Set up hourly activity pings. 556 // Set up hourly activity pings.
552 timer_ = [NSTimer scheduledTimerWithTimeInterval:60 * 60 // One hour 557 timer_ = [NSTimer scheduledTimerWithTimeInterval:60 * 60 // One hour
553 target:self 558 target:self
554 selector:@selector(markActive:) 559 selector:@selector(markActive:)
555 userInfo:nil 560 userInfo:nil
556 repeats:YES]; 561 repeats:YES];
557 } 562 }
558 563
559 - (BOOL)isRegisteredAndActive { 564 - (BOOL)isRegisteredAndActive {
560 return registrationActive_; 565 return registrationActive_;
561 } 566 }
562 567
563 - (void)registrationComplete:(NSNotification*)notification { 568 - (void)registrationComplete:(NSNotification*)notification {
564 NSDictionary* userInfo = [notification userInfo]; 569 NSDictionary* userInfo = [notification userInfo];
570
571 // Error messages may be included, depending on the version of Keystone.
Boris Vidolov 2016/03/08 22:32:51 I don't believe that this is correct. It depends o
Ryan Myers (chromium) 2016/03/22 22:39:22 Done.
572 NSString *errorMessages =
Boris Vidolov 2016/03/08 22:32:51 Fix the position of the '*': should be "NSString*
Ryan Myers (chromium) 2016/03/22 22:39:22 Done.
573 [userInfo objectForKey:ksr::KSRegistrationUpdateCheckRawErrorMessagesKey];
574
565 if ([[userInfo objectForKey:ksr::KSRegistrationStatusKey] boolValue]) { 575 if ([[userInfo objectForKey:ksr::KSRegistrationStatusKey] boolValue]) {
566 if ([self isSystemTicketDoomed]) { 576 if ([self isSystemTicketDoomed]) {
Boris Vidolov 2016/03/08 22:32:51 Even in the happy case there could be warnings, re
Ryan Myers (chromium) 2016/03/22 22:39:22 Done. (Passed them on to updateStatus; version_upd
567 [self updateStatus:kAutoupdateNeedsPromotion version:nil]; 577 [self updateStatus:kAutoupdateNeedsPromotion version:nil error:nil];
568 } else { 578 } else {
569 [self updateStatus:kAutoupdateRegistered version:nil]; 579 [self updateStatus:kAutoupdateRegistered version:nil error:nil];
570 } 580 }
571 } else { 581 } else {
572 // Dump registration_? 582 // Dump registration_?
573 [self updateStatus:kAutoupdateRegisterFailed version:nil]; 583 [self updateStatus:kAutoupdateRegisterFailed
584 version:nil
585 error:errorMessages];
574 } 586 }
575 } 587 }
576 588
577 - (void)stopTimer { 589 - (void)stopTimer {
578 [timer_ invalidate]; 590 [timer_ invalidate];
579 } 591 }
580 592
581 - (void)markActive:(NSTimer*)timer { 593 - (void)markActive:(NSTimer*)timer {
582 [self setRegistrationActive]; 594 [self setRegistrationActive];
583 } 595 }
584 596
585 - (void)checkForUpdate { 597 - (void)checkForUpdate {
586 DCHECK(![self asyncOperationPending]); 598 DCHECK(![self asyncOperationPending]);
Boris Vidolov 2016/03/08 22:32:51 I believe that this should not be a debug check, b
Ryan Myers (chromium) 2016/03/22 22:39:22 Done.
587 599
588 if (!registration_) { 600 if (!registration_) {
589 [self updateStatus:kAutoupdateCheckFailed version:nil]; 601 [self updateStatus:kAutoupdateCheckFailed
602 version:nil
603 error:@"keystone_glue: Keystone not available."];
Boris Vidolov 2016/03/08 22:32:52 This should happen only on debug builds and Chrome
Ryan Myers (chromium) 2016/03/22 22:39:22 Done.
590 return; 604 return;
591 } 605 }
592 606
593 [self updateStatus:kAutoupdateChecking version:nil]; 607 [self updateStatus:kAutoupdateChecking version:nil error:nil];
594 608
595 // All checks from inside Chrome are considered user-initiated, because they 609 // All checks from inside Chrome are considered user-initiated, because they
596 // only happen following a user action, such as visiting the about page. 610 // only happen following a user action, such as visiting the about page.
597 // Non-user-initiated checks are the periodic checks automatically made by 611 // 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). 612 // Keystone, which don't come through this code path (or even this process).
599 [registration_ checkForUpdateWasUserInitiated:YES]; 613 [registration_ checkForUpdateWasUserInitiated:YES];
600 614
601 // Upon completion, ksr::KSRegistrationCheckForUpdateNotification will be 615 // Upon completion, ksr::KSRegistrationCheckForUpdateNotification will be
602 // posted, and -checkForUpdateComplete: will be called. 616 // posted, and -checkForUpdateComplete: will be called.
603 } 617 }
604 618
605 - (void)checkForUpdateComplete:(NSNotification*)notification { 619 - (void)checkForUpdateComplete:(NSNotification*)notification {
606 NSDictionary* userInfo = [notification userInfo]; 620 NSDictionary* userInfo = [notification userInfo];
607 621
622 // Error messages may be included, depending on the version of Keystone.
Boris Vidolov 2016/03/08 22:32:51 Ditto for the version of Keystone in the comment
Ryan Myers (chromium) 2016/03/22 22:39:22 Done.
623 NSString *errorMessages =
624 [userInfo objectForKey:ksr::KSRegistrationUpdateCheckRawErrorMessagesKey];
625
608 if ([[userInfo objectForKey:ksr::KSRegistrationUpdateCheckErrorKey] 626 if ([[userInfo objectForKey:ksr::KSRegistrationUpdateCheckErrorKey]
609 boolValue]) { 627 boolValue]) {
610 [self updateStatus:kAutoupdateCheckFailed version:nil]; 628 [self updateStatus:kAutoupdateCheckFailed version:nil error:errorMessages];
611 } else if ([[userInfo objectForKey:ksr::KSRegistrationStatusKey] boolValue]) { 629 } else if ([[userInfo objectForKey:ksr::KSRegistrationStatusKey] boolValue]) {
612 // If an update is known to be available, go straight to 630 // If an update is known to be available, go straight to
613 // -updateStatus:version:. It doesn't matter what's currently on disk. 631 // -updateStatus:version:. It doesn't matter what's currently on disk.
614 NSString* version = [userInfo objectForKey:ksr::KSRegistrationVersionKey]; 632 NSString* version = [userInfo objectForKey:ksr::KSRegistrationVersionKey];
615 [self updateStatus:kAutoupdateAvailable version:version]; 633 [self updateStatus:kAutoupdateAvailable version:version error:nil];
Boris Vidolov 2016/03/08 22:32:52 Again, maybe we should log the reported errors? It
Ryan Myers (chromium) 2016/03/22 22:39:22 Done.
616 } else { 634 } else {
617 // If no updates are available, check what's on disk, because an update 635 // 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, 636 // may have already been installed. This check happens on another thread,
619 // and -updateStatus:version: will be called on the main thread when done. 637 // and -updateStatus:version: will be called on the main thread when done.
620 [self determineUpdateStatusAsync]; 638 [self determineUpdateStatusAsync];
621 } 639 }
622 } 640 }
623 641
624 - (void)installUpdate { 642 - (void)installUpdate {
625 DCHECK(![self asyncOperationPending]); 643 DCHECK(![self asyncOperationPending]);
626 644
627 if (!registration_) { 645 if (!registration_) {
628 [self updateStatus:kAutoupdateInstallFailed version:nil]; 646 [self updateStatus:kAutoupdateInstallFailed
647 version:nil
648 error:@"keystone_glue: Keystone not available."];
Boris Vidolov 2016/03/08 22:32:52 Ditto
Ryan Myers (chromium) 2016/03/22 22:39:22 Done.
629 return; 649 return;
630 } 650 }
631 651
632 [self updateStatus:kAutoupdateInstalling version:nil]; 652 [self updateStatus:kAutoupdateInstalling version:nil error:nil];
633 653
634 [registration_ startUpdate]; 654 [registration_ startUpdate];
635 655
636 // Upon completion, ksr::KSRegistrationStartUpdateNotification will be 656 // Upon completion, ksr::KSRegistrationStartUpdateNotification will be
637 // posted, and -installUpdateComplete: will be called. 657 // posted, and -installUpdateComplete: will be called.
638 } 658 }
639 659
640 - (void)installUpdateComplete:(NSNotification*)notification { 660 - (void)installUpdateComplete:(NSNotification*)notification {
641 NSDictionary* userInfo = [notification userInfo]; 661 NSDictionary* userInfo = [notification userInfo];
642 662
663 // Error messages may be included, depending on the version of Keystone.
Boris Vidolov 2016/03/08 22:32:51 Ditto
Ryan Myers (chromium) 2016/03/22 22:39:22 Done.
Boris Vidolov 2016/03/23 00:24:13 Still here...
Ryan Myers (chromium) 2016/03/23 00:48:23 Done.
664 NSString *errorMsgs =
665 [userInfo objectForKey:ksr::KSRegistrationUpdateCheckRawErrorMessagesKey];
666
643 // http://crbug.com/160308 and b/7517358: when using system Keystone and on 667 // 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 668 // 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 669 // was installed correctly, so don't check it. It should be redudnant when
646 // KSUpdateCheckSuccessfullyInstalledKey is checked. 670 // KSUpdateCheckSuccessfullyInstalledKey is checked.
647 if (![[userInfo objectForKey:ksr::KSUpdateCheckSuccessfullyInstalledKey] 671 if (![[userInfo objectForKey:ksr::KSUpdateCheckSuccessfullyInstalledKey]
648 intValue]) { 672 intValue]) {
649 [self updateStatus:kAutoupdateInstallFailed version:nil]; 673 [self updateStatus:kAutoupdateInstallFailed version:nil error:errorMsgs];
650 } else { 674 } else {
651 updateSuccessfullyInstalled_ = YES; 675 updateSuccessfullyInstalled_ = YES;
Boris Vidolov 2016/03/08 22:32:52 Ditto for logging
Ryan Myers (chromium) 2016/03/22 22:39:22 Done.
652 676
653 // Nothing in the notification dictionary reports the version that was 677 // Nothing in the notification dictionary reports the version that was
654 // installed. Figure it out based on what's on disk. 678 // installed. Figure it out based on what's on disk.
655 [self determineUpdateStatusAsync]; 679 [self determineUpdateStatusAsync];
656 } 680 }
657 } 681 }
658 682
659 - (NSString*)currentlyInstalledVersion { 683 - (NSString*)currentlyInstalledVersion {
660 NSString* appInfoPlistPath = [self appInfoPlistPath]; 684 NSString* appInfoPlistPath = [self appInfoPlistPath];
661 NSDictionary* infoPlist = 685 NSDictionary* infoPlist =
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
702 status = kAutoupdateCurrent; 726 status = kAutoupdateCurrent;
703 } else { 727 } else {
704 // If the version on disk doesn't match what's currently running, an 728 // 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 729 // update must have been applied in the background, without this app's
706 // direct participation. Leave updateSuccessfullyInstalled_ alone 730 // direct participation. Leave updateSuccessfullyInstalled_ alone
707 // because there's no direct knowledge of what actually happened. 731 // because there's no direct knowledge of what actually happened.
708 status = kAutoupdateInstalled; 732 status = kAutoupdateInstalled;
709 } 733 }
710 } 734 }
711 735
712 [self updateStatus:status version:version]; 736 [self updateStatus:status version:version error:nil];
713 } 737 }
714 738
715 - (void)updateStatus:(AutoupdateStatus)status version:(NSString*)version { 739 - (void)updateStatus:(AutoupdateStatus)status
740 version:(NSString*)version
741 error:(NSString *)error {
716 NSNumber* statusNumber = [NSNumber numberWithInt:status]; 742 NSNumber* statusNumber = [NSNumber numberWithInt:status];
717 NSMutableDictionary* dictionary = 743 NSMutableDictionary* dictionary =
718 [NSMutableDictionary dictionaryWithObject:statusNumber 744 [NSMutableDictionary dictionaryWithObject:statusNumber
719 forKey:kAutoupdateStatusStatus]; 745 forKey:kAutoupdateStatusStatus];
720 if (version) { 746 if (version) {
721 [dictionary setObject:version forKey:kAutoupdateStatusVersion]; 747 [dictionary setObject:version forKey:kAutoupdateStatusVersion];
722 } 748 }
749 if (error) {
750 [dictionary setObject:version forKey:kAutoupdateStatusErrorMessages];
751 }
723 752
724 NSNotification* notification = 753 NSNotification* notification =
725 [NSNotification notificationWithName:kAutoupdateStatusNotification 754 [NSNotification notificationWithName:kAutoupdateStatusNotification
726 object:self 755 object:self
727 userInfo:dictionary]; 756 userInfo:dictionary];
728 recentNotification_.reset([notification retain]); 757 recentNotification_.reset([notification retain]);
729 758
730 [[NSNotificationCenter defaultCenter] postNotification:notification]; 759 [[NSNotificationCenter defaultCenter] postNotification:notification];
731 } 760 }
732 761
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
866 } 895 }
867 if (!synchronous && ![self wantsPromotion]) { 896 if (!synchronous && ![self wantsPromotion]) {
868 // If operating synchronously, the call came from the installer, which 897 // If operating synchronously, the call came from the installer, which
869 // means that a system ticket is required. Otherwise, only allow 898 // means that a system ticket is required. Otherwise, only allow
870 // promotion if it's wanted. 899 // promotion if it's wanted.
871 return; 900 return;
872 } 901 }
873 902
874 synchronousPromotion_ = synchronous; 903 synchronousPromotion_ = synchronous;
875 904
876 [self updateStatus:kAutoupdatePromoting version:nil]; 905 [self updateStatus:kAutoupdatePromoting version:nil error:nil];
877 906
878 // TODO(mark): Remove when able! 907 // TODO(mark): Remove when able!
879 // 908 //
880 // keystone_promote_preflight will copy the current brand information out to 909 // 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 910 // the system level so all users can share the data as part of the ticket
882 // promotion. 911 // promotion.
883 // 912 //
884 // It will also ensure that the Keystone system ticket store is in a usable 913 // 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 914 // state for all users on the system. Ideally, Keystone's installer or
886 // another part of Keystone would handle this. The underlying problem is 915 // another part of Keystone would handle this. The underlying problem is
(...skipping 28 matching lines...) Expand all
915 OSStatus status = base::mac::ExecuteWithPrivilegesAndWait( 944 OSStatus status = base::mac::ExecuteWithPrivilegesAndWait(
916 authorization, 945 authorization,
917 preflightPathC, 946 preflightPathC,
918 kAuthorizationFlagDefaults, 947 kAuthorizationFlagDefaults,
919 arguments, 948 arguments,
920 NULL, // pipe 949 NULL, // pipe
921 &exit_status); 950 &exit_status);
922 if (status != errAuthorizationSuccess) { 951 if (status != errAuthorizationSuccess) {
923 OSSTATUS_LOG(ERROR, status) 952 OSSTATUS_LOG(ERROR, status)
924 << "AuthorizationExecuteWithPrivileges preflight"; 953 << "AuthorizationExecuteWithPrivileges preflight";
925 [self updateStatus:kAutoupdatePromoteFailed version:nil]; 954
955 NSString *errorMessage =
956 [NSString stringWithFormat:@"Pre-flight script failed to launch: %ld",
957 (long)status];
958 [self updateStatus:kAutoupdatePromoteFailed
959 version:nil
960 error:errorMessage];
926 return; 961 return;
927 } 962 }
928 if (exit_status != 0) { 963 if (exit_status != 0) {
929 LOG(ERROR) << "keystone_promote_preflight status " << exit_status; 964 LOG(ERROR) << "keystone_promote_preflight status " << exit_status;
930 [self updateStatus:kAutoupdatePromoteFailed version:nil]; 965
966 NSString *errorMessage =
967 [NSString stringWithFormat:@"Promotion pre-flight script failed: %d",
968 exit_status];
969 [self updateStatus:kAutoupdatePromoteFailed
970 version:nil
971 error:errorMessage];
931 return; 972 return;
932 } 973 }
933 974
934 // Hang on to the AuthorizationRef so that it can be used once promotion is 975 // 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 976 // complete. Do this before asking Keystone to promote the ticket, because
936 // -promotionComplete: may be called from inside the Keystone promotion 977 // -promotionComplete: may be called from inside the Keystone promotion
937 // call. 978 // call.
938 authorization_.swap(authorization); 979 authorization_.swap(authorization);
939 980
940 NSDictionary* parameters = [self keystoneParameters]; 981 NSDictionary* parameters = [self keystoneParameters];
941 982
942 // If the brand file is user level, update parameters to point to the new 983 // If the brand file is user level, update parameters to point to the new
943 // system level file during promotion. 984 // system level file during promotion.
944 if (brandFileType_ == kBrandFileTypeUser) { 985 if (brandFileType_ == kBrandFileTypeUser) {
945 NSMutableDictionary* temp_parameters = 986 NSMutableDictionary* temp_parameters =
946 [[parameters mutableCopy] autorelease]; 987 [[parameters mutableCopy] autorelease];
947 [temp_parameters setObject:SystemBrandFilePath() 988 [temp_parameters setObject:SystemBrandFilePath()
948 forKey:ksr::KSRegistrationBrandPathKey]; 989 forKey:ksr::KSRegistrationBrandPathKey];
949 parameters = temp_parameters; 990 parameters = temp_parameters;
950 } 991 }
951 992
952 if (![registration_ promoteWithParameters:parameters 993 if (![registration_ promoteWithParameters:parameters
953 authorization:authorization_]) { 994 authorization:authorization_]) {
954 [self updateStatus:kAutoupdatePromoteFailed version:nil]; 995 // TODO: If Keystone ever makes a variant of this API with a withError:
996 // parameter, include the error message here in the call to updateStatus:.
997 [self updateStatus:kAutoupdatePromoteFailed version:nil error:nil];
955 authorization_.reset(); 998 authorization_.reset();
956 return; 999 return;
957 } 1000 }
958 1001
959 // Upon completion, ksr::KSRegistrationPromotionDidCompleteNotification will 1002 // Upon completion, ksr::KSRegistrationPromotionDidCompleteNotification will
960 // be posted, and -promotionComplete: will be called. 1003 // be posted, and -promotionComplete: will be called.
961 1004
962 // If synchronous, see to it that this happens immediately. Give it a 1005 // If synchronous, see to it that this happens immediately. Give it a
963 // 10-second deadline. 1006 // 10-second deadline.
964 if (synchronous) { 1007 if (synchronous) {
965 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 10, false); 1008 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 10, false);
966 } 1009 }
967 } 1010 }
968 1011
969 - (void)promotionComplete:(NSNotification*)notification { 1012 - (void)promotionComplete:(NSNotification*)notification {
970 NSDictionary* userInfo = [notification userInfo]; 1013 NSDictionary* userInfo = [notification userInfo];
971 if ([[userInfo objectForKey:ksr::KSRegistrationStatusKey] boolValue]) { 1014 if ([[userInfo objectForKey:ksr::KSRegistrationStatusKey] boolValue]) {
972 if (synchronousPromotion_) { 1015 if (synchronousPromotion_) {
973 // Short-circuit: if performing a synchronous promotion, the promotion 1016 // Short-circuit: if performing a synchronous promotion, the promotion
974 // came from the installer, which already set the permissions properly. 1017 // came from the installer, which already set the permissions properly.
975 // Rather than run a duplicate permission-changing operation, jump 1018 // Rather than run a duplicate permission-changing operation, jump
976 // straight to "done." 1019 // straight to "done."
977 [self changePermissionsForPromotionComplete]; 1020 [self changePermissionsForPromotionComplete];
978 } else { 1021 } else {
979 [self changePermissionsForPromotionAsync]; 1022 [self changePermissionsForPromotionAsync];
980 } 1023 }
981 } else { 1024 } else {
982 authorization_.reset(); 1025 authorization_.reset();
983 [self updateStatus:kAutoupdatePromoteFailed version:nil]; 1026 [self updateStatus:kAutoupdatePromoteFailed version:nil error:nil];
984 } 1027 }
985 1028
986 if (synchronousPromotion_) { 1029 if (synchronousPromotion_) {
987 // The run loop doesn't need to wait for this any longer. 1030 // The run loop doesn't need to wait for this any longer.
988 CFRunLoopRef runLoop = CFRunLoopGetCurrent(); 1031 CFRunLoopRef runLoop = CFRunLoopGetCurrent();
989 CFRunLoopStop(runLoop); 1032 CFRunLoopStop(runLoop);
990 CFRunLoopWakeUp(runLoop); 1033 CFRunLoopWakeUp(runLoop);
991 } 1034 }
992 } 1035 }
993 1036
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1029 1072
1030 SEL selector = @selector(changePermissionsForPromotionComplete); 1073 SEL selector = @selector(changePermissionsForPromotionComplete);
1031 [self performSelectorOnMainThread:selector 1074 [self performSelectorOnMainThread:selector
1032 withObject:nil 1075 withObject:nil
1033 waitUntilDone:NO]; 1076 waitUntilDone:NO];
1034 } 1077 }
1035 1078
1036 - (void)changePermissionsForPromotionComplete { 1079 - (void)changePermissionsForPromotionComplete {
1037 authorization_.reset(); 1080 authorization_.reset();
1038 1081
1039 [self updateStatus:kAutoupdatePromoted version:nil]; 1082 [self updateStatus:kAutoupdatePromoted version:nil error:nil];
1040 } 1083 }
1041 1084
1042 - (void)setAppPath:(NSString*)appPath { 1085 - (void)setAppPath:(NSString*)appPath {
1043 if (appPath != appPath_) { 1086 if (appPath != appPath_) {
1044 [appPath_ release]; 1087 [appPath_ release];
1045 appPath_ = [appPath copy]; 1088 appPath_ = [appPath copy];
1046 } 1089 }
1047 } 1090 }
1048 1091
1049 - (BOOL)wantsFullInstaller { 1092 - (BOOL)wantsFullInstaller {
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
1131 return [KeystoneGlue defaultKeystoneGlue] != nil; 1174 return [KeystoneGlue defaultKeystoneGlue] != nil;
1132 } 1175 }
1133 1176
1134 base::string16 CurrentlyInstalledVersion() { 1177 base::string16 CurrentlyInstalledVersion() {
1135 KeystoneGlue* keystoneGlue = [KeystoneGlue defaultKeystoneGlue]; 1178 KeystoneGlue* keystoneGlue = [KeystoneGlue defaultKeystoneGlue];
1136 NSString* version = [keystoneGlue currentlyInstalledVersion]; 1179 NSString* version = [keystoneGlue currentlyInstalledVersion];
1137 return base::SysNSStringToUTF16(version); 1180 return base::SysNSStringToUTF16(version);
1138 } 1181 }
1139 1182
1140 } // namespace keystone_glue 1183 } // namespace keystone_glue
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698