| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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/cocoa/keystone_glue.h" | 5 #import "chrome/browser/cocoa/keystone_glue.h" |
| 6 | 6 |
| 7 #include <sys/param.h> | 7 #include <sys/param.h> |
| 8 #include <sys/mount.h> | 8 #include <sys/mount.h> |
| 9 | 9 |
| 10 #include <vector> | 10 #include <vector> |
| (...skipping 14 matching lines...) Expand all Loading... |
| 25 typedef enum { | 25 typedef enum { |
| 26 kKSPathExistenceChecker, | 26 kKSPathExistenceChecker, |
| 27 } KSExistenceCheckerType; | 27 } KSExistenceCheckerType; |
| 28 | 28 |
| 29 typedef enum { | 29 typedef enum { |
| 30 kKSRegistrationUserTicket, | 30 kKSRegistrationUserTicket, |
| 31 kKSRegistrationSystemTicket, | 31 kKSRegistrationSystemTicket, |
| 32 kKSRegistrationDontKnowWhatKindOfTicket, | 32 kKSRegistrationDontKnowWhatKindOfTicket, |
| 33 } KSRegistrationTicketType; | 33 } KSRegistrationTicketType; |
| 34 | 34 |
| 35 NSString* KSRegistrationVersionKey = @"Version"; |
| 36 NSString* KSRegistrationExistenceCheckerTypeKey = @"ExistenceCheckerType"; |
| 37 NSString* KSRegistrationExistenceCheckerStringKey = @"ExistenceCheckerString"; |
| 38 NSString* KSRegistrationServerURLStringKey = @"URLString"; |
| 39 NSString* KSRegistrationPreserveTrustedTesterTokenKey = @"PreserveTTT"; |
| 40 NSString* KSRegistrationTagKey = @"Tag"; |
| 41 NSString* KSRegistrationTagPathKey = @"TagPath"; |
| 42 NSString* KSRegistrationTagKeyKey = @"TagKey"; |
| 43 |
| 35 NSString *KSRegistrationDidCompleteNotification = | 44 NSString *KSRegistrationDidCompleteNotification = |
| 36 @"KSRegistrationDidCompleteNotification"; | 45 @"KSRegistrationDidCompleteNotification"; |
| 37 NSString *KSRegistrationPromotionDidCompleteNotification = | 46 NSString *KSRegistrationPromotionDidCompleteNotification = |
| 38 @"KSRegistrationPromotionDidCompleteNotification"; | 47 @"KSRegistrationPromotionDidCompleteNotification"; |
| 39 | 48 |
| 40 NSString *KSRegistrationCheckForUpdateNotification = | 49 NSString *KSRegistrationCheckForUpdateNotification = |
| 41 @"KSRegistrationCheckForUpdateNotification"; | 50 @"KSRegistrationCheckForUpdateNotification"; |
| 42 NSString *KSRegistrationStatusKey = @"Status"; | 51 NSString *KSRegistrationStatusKey = @"Status"; |
| 43 NSString *KSRegistrationVersionKey = @"Version"; | |
| 44 NSString *KSRegistrationUpdateCheckErrorKey = @"Error"; | 52 NSString *KSRegistrationUpdateCheckErrorKey = @"Error"; |
| 45 | 53 |
| 46 NSString *KSRegistrationStartUpdateNotification = | 54 NSString *KSRegistrationStartUpdateNotification = |
| 47 @"KSRegistrationStartUpdateNotification"; | 55 @"KSRegistrationStartUpdateNotification"; |
| 48 NSString *KSUpdateCheckSuccessfulKey = @"CheckSuccessful"; | 56 NSString *KSUpdateCheckSuccessfulKey = @"CheckSuccessful"; |
| 49 NSString *KSUpdateCheckSuccessfullyInstalledKey = @"SuccessfullyInstalled"; | 57 NSString *KSUpdateCheckSuccessfullyInstalledKey = @"SuccessfullyInstalled"; |
| 50 | 58 |
| 51 NSString *KSRegistrationRemoveExistingTag = @""; | 59 NSString *KSRegistrationRemoveExistingTag = @""; |
| 52 #define KSRegistrationPreserveExistingTag nil | 60 #define KSRegistrationPreserveExistingTag nil |
| 53 | 61 |
| 54 } // namespace | 62 } // namespace |
| 55 | 63 |
| 56 @interface KSRegistration : NSObject | 64 @interface KSRegistration : NSObject |
| 57 | 65 |
| 58 + (id)registrationWithProductID:(NSString*)productID; | 66 + (id)registrationWithProductID:(NSString*)productID; |
| 59 | 67 |
| 60 - (BOOL)registerWithVersion:(NSString*)version | 68 - (BOOL)registerWithParameters:(NSDictionary*)args; |
| 61 existenceCheckerType:(KSExistenceCheckerType)xctype | |
| 62 existenceCheckerString:(NSString*)xc | |
| 63 serverURLString:(NSString*)serverURLString | |
| 64 preserveTTToken:(BOOL)preserveToken | |
| 65 tag:(NSString*)tag; | |
| 66 | 69 |
| 67 - (BOOL)promoteWithVersion:(NSString*)version | 70 - (BOOL)promoteWithParameters:(NSDictionary*)args |
| 68 existenceCheckerType:(KSExistenceCheckerType)xctype | 71 authorization:(AuthorizationRef)authorization; |
| 69 existenceCheckerString:(NSString*)xc | |
| 70 serverURLString:(NSString*)serverURLString | |
| 71 preserveTTToken:(BOOL)preserveToken | |
| 72 tag:(NSString*)tag | |
| 73 authorization:(AuthorizationRef)authorization; | |
| 74 | 72 |
| 75 - (void)setActive; | 73 - (void)setActive; |
| 76 - (void)checkForUpdate; | 74 - (void)checkForUpdate; |
| 77 - (void)startUpdate; | 75 - (void)startUpdate; |
| 78 - (KSRegistrationTicketType)ticketType; | 76 - (KSRegistrationTicketType)ticketType; |
| 79 | 77 |
| 80 @end // @interface KSRegistration | 78 @end // @interface KSRegistration |
| 81 | 79 |
| 82 @interface KeystoneGlue(Private) | 80 @interface KeystoneGlue(Private) |
| 83 | 81 |
| 82 // Returns the path to the application's Info.plist file. This returns the |
| 83 // outer application bundle's Info.plist, not the framework's Info.plist. |
| 84 - (NSString*)appInfoPlistPath; |
| 85 |
| 86 // Returns a dictionary containing parameters to be used for a KSRegistration |
| 87 // -registerWithParameters: or -promoteWithParameters:authorization: call. |
| 88 - (NSDictionary*)keystoneParameters; |
| 89 |
| 84 // Called when Keystone registration completes. | 90 // Called when Keystone registration completes. |
| 85 - (void)registrationComplete:(NSNotification*)notification; | 91 - (void)registrationComplete:(NSNotification*)notification; |
| 86 | 92 |
| 87 // Called periodically to announce activity by pinging the Keystone server. | 93 // Called periodically to announce activity by pinging the Keystone server. |
| 88 - (void)markActive:(NSTimer*)timer; | 94 - (void)markActive:(NSTimer*)timer; |
| 89 | 95 |
| 90 // Called when an update check or update installation is complete. Posts the | 96 // Called when an update check or update installation is complete. Posts the |
| 91 // kAutoupdateStatusNotification notification to the default notification | 97 // kAutoupdateStatusNotification notification to the default notification |
| 92 // center. | 98 // center. |
| 93 - (void)updateStatus:(AutoupdateStatus)status version:(NSString*)version; | 99 - (void)updateStatus:(AutoupdateStatus)status version:(NSString*)version; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 138 - (void)changePermissionsForPromotionWithTool:(NSString*)toolPath; | 144 - (void)changePermissionsForPromotionWithTool:(NSString*)toolPath; |
| 139 - (void)changePermissionsForPromotionComplete; | 145 - (void)changePermissionsForPromotionComplete; |
| 140 | 146 |
| 141 @end // @interface KeystoneGlue(Private) | 147 @end // @interface KeystoneGlue(Private) |
| 142 | 148 |
| 143 const NSString* const kAutoupdateStatusNotification = | 149 const NSString* const kAutoupdateStatusNotification = |
| 144 @"AutoupdateStatusNotification"; | 150 @"AutoupdateStatusNotification"; |
| 145 const NSString* const kAutoupdateStatusStatus = @"status"; | 151 const NSString* const kAutoupdateStatusStatus = @"status"; |
| 146 const NSString* const kAutoupdateStatusVersion = @"version"; | 152 const NSString* const kAutoupdateStatusVersion = @"version"; |
| 147 | 153 |
| 154 namespace { |
| 155 |
| 156 const NSString* const kChannelKey = @"KSChannelID"; |
| 157 |
| 158 } // namespace |
| 159 |
| 148 @implementation KeystoneGlue | 160 @implementation KeystoneGlue |
| 149 | 161 |
| 150 + (id)defaultKeystoneGlue { | 162 + (id)defaultKeystoneGlue { |
| 151 static bool sTriedCreatingDefaultKeystoneGlue = false; | 163 static bool sTriedCreatingDefaultKeystoneGlue = false; |
| 152 // TODO(jrg): use base::SingletonObjC<KeystoneGlue> | 164 // TODO(jrg): use base::SingletonObjC<KeystoneGlue> |
| 153 static KeystoneGlue* sDefaultKeystoneGlue = nil; // leaked | 165 static KeystoneGlue* sDefaultKeystoneGlue = nil; // leaked |
| 154 | 166 |
| 155 if (!sTriedCreatingDefaultKeystoneGlue) { | 167 if (!sTriedCreatingDefaultKeystoneGlue) { |
| 156 sTriedCreatingDefaultKeystoneGlue = true; | 168 sTriedCreatingDefaultKeystoneGlue = true; |
| 157 | 169 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 | 238 |
| 227 NSString* appPath = [appBundle bundlePath]; | 239 NSString* appPath = [appBundle bundlePath]; |
| 228 NSString* url = [infoDictionary objectForKey:@"KSUpdateURL"]; | 240 NSString* url = [infoDictionary objectForKey:@"KSUpdateURL"]; |
| 229 NSString* version = [infoDictionary objectForKey:@"KSVersion"]; | 241 NSString* version = [infoDictionary objectForKey:@"KSVersion"]; |
| 230 | 242 |
| 231 if (!productID || !appPath || !url || !version) { | 243 if (!productID || !appPath || !url || !version) { |
| 232 // If parameters required for Keystone are missing, don't use it. | 244 // If parameters required for Keystone are missing, don't use it. |
| 233 return; | 245 return; |
| 234 } | 246 } |
| 235 | 247 |
| 236 NSString* channel = [infoDictionary objectForKey:@"KSChannelID"]; | 248 NSString* channel = [infoDictionary objectForKey:kChannelKey]; |
| 237 // The stable channel has no tag. If updating to stable, remove the | 249 // The stable channel has no tag. If updating to stable, remove the |
| 238 // dev and beta tags since we've been "promoted". | 250 // dev and beta tags since we've been "promoted". |
| 239 if (channel == nil) | 251 if (channel == nil) |
| 240 channel = KSRegistrationRemoveExistingTag; | 252 channel = KSRegistrationRemoveExistingTag; |
| 241 | 253 |
| 242 productID_ = [productID retain]; | 254 productID_ = [productID retain]; |
| 243 appPath_ = [appPath retain]; | 255 appPath_ = [appPath retain]; |
| 244 url_ = [url retain]; | 256 url_ = [url retain]; |
| 245 version_ = [version retain]; | 257 version_ = [version retain]; |
| 246 channel_ = [channel retain]; | 258 channel_ = [channel retain]; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 261 // Harness the KSRegistration class. | 273 // Harness the KSRegistration class. |
| 262 Class ksrClass = [ksrBundle classNamed:@"KSRegistration"]; | 274 Class ksrClass = [ksrBundle classNamed:@"KSRegistration"]; |
| 263 KSRegistration* ksr = [ksrClass registrationWithProductID:productID_]; | 275 KSRegistration* ksr = [ksrClass registrationWithProductID:productID_]; |
| 264 if (!ksr) | 276 if (!ksr) |
| 265 return NO; | 277 return NO; |
| 266 | 278 |
| 267 registration_ = [ksr retain]; | 279 registration_ = [ksr retain]; |
| 268 return YES; | 280 return YES; |
| 269 } | 281 } |
| 270 | 282 |
| 283 - (NSString*)appInfoPlistPath { |
| 284 // NSBundle ought to have a way to access this path directly, but it |
| 285 // doesn't. |
| 286 return [[appPath_ stringByAppendingPathComponent:@"Contents"] |
| 287 stringByAppendingPathComponent:@"Info.plist"]; |
| 288 } |
| 289 |
| 290 - (NSDictionary*)keystoneParameters { |
| 291 NSNumber* xcType = [NSNumber numberWithInt:kKSPathExistenceChecker]; |
| 292 NSNumber* preserveTTToken = [NSNumber numberWithBool:YES]; |
| 293 NSString* tagPath = [self appInfoPlistPath]; |
| 294 |
| 295 return [NSDictionary dictionaryWithObjectsAndKeys: |
| 296 version_, KSRegistrationVersionKey, |
| 297 xcType, KSRegistrationExistenceCheckerTypeKey, |
| 298 appPath_, KSRegistrationExistenceCheckerStringKey, |
| 299 url_, KSRegistrationServerURLStringKey, |
| 300 preserveTTToken, KSRegistrationPreserveTrustedTesterTokenKey, |
| 301 channel_, KSRegistrationTagKey, |
| 302 tagPath, KSRegistrationTagPathKey, |
| 303 kChannelKey, KSRegistrationTagKeyKey, |
| 304 nil]; |
| 305 } |
| 306 |
| 271 - (void)registerWithKeystone { | 307 - (void)registerWithKeystone { |
| 272 [self updateStatus:kAutoupdateRegistering version:nil]; | 308 [self updateStatus:kAutoupdateRegistering version:nil]; |
| 273 | 309 |
| 274 if (![registration_ registerWithVersion:version_ | 310 NSDictionary* parameters = [self keystoneParameters]; |
| 275 existenceCheckerType:kKSPathExistenceChecker | 311 if (![registration_ registerWithParameters:parameters]) { |
| 276 existenceCheckerString:appPath_ | |
| 277 serverURLString:url_ | |
| 278 preserveTTToken:YES | |
| 279 tag:channel_]) { | |
| 280 [self updateStatus:kAutoupdateRegisterFailed version:nil]; | 312 [self updateStatus:kAutoupdateRegisterFailed version:nil]; |
| 281 return; | 313 return; |
| 282 } | 314 } |
| 283 | 315 |
| 284 // Upon completion, KSRegistrationDidCompleteNotification will be posted, | 316 // Upon completion, KSRegistrationDidCompleteNotification will be posted, |
| 285 // and -registrationComplete: will be called. | 317 // and -registrationComplete: will be called. |
| 286 | 318 |
| 287 // Mark an active RIGHT NOW; don't wait an hour for the first one. | 319 // Mark an active RIGHT NOW; don't wait an hour for the first one. |
| 288 [registration_ setActive]; | 320 [registration_ setActive]; |
| 289 | 321 |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 391 object:nil] autorelease]; | 423 object:nil] autorelease]; |
| 392 | 424 |
| 393 NSOperationQueue* operationQueue = [WorkerPoolObjC sharedOperationQueue]; | 425 NSOperationQueue* operationQueue = [WorkerPoolObjC sharedOperationQueue]; |
| 394 [operationQueue addOperation:operation]; | 426 [operationQueue addOperation:operation]; |
| 395 } | 427 } |
| 396 | 428 |
| 397 // Runs on a thread managed by NSOperationQueue. | 429 // Runs on a thread managed by NSOperationQueue. |
| 398 - (void)determineUpdateStatus { | 430 - (void)determineUpdateStatus { |
| 399 DCHECK(![NSThread isMainThread]); | 431 DCHECK(![NSThread isMainThread]); |
| 400 | 432 |
| 401 NSString* appInfoPlistPath = | 433 NSString* appInfoPlistPath = [self appInfoPlistPath]; |
| 402 [[appPath_ stringByAppendingPathComponent:@"Contents"] | |
| 403 stringByAppendingPathComponent:@"Info.plist"]; | |
| 404 NSDictionary* infoPlist = | 434 NSDictionary* infoPlist = |
| 405 [NSDictionary dictionaryWithContentsOfFile:appInfoPlistPath]; | 435 [NSDictionary dictionaryWithContentsOfFile:appInfoPlistPath]; |
| 406 NSString* version = [infoPlist objectForKey:@"CFBundleShortVersionString"]; | 436 NSString* version = [infoPlist objectForKey:@"CFBundleShortVersionString"]; |
| 407 | 437 |
| 408 [self performSelectorOnMainThread:@selector(determineUpdateStatusForVersion:) | 438 [self performSelectorOnMainThread:@selector(determineUpdateStatusForVersion:) |
| 409 withObject:version | 439 withObject:version |
| 410 waitUntilDone:NO]; | 440 waitUntilDone:NO]; |
| 411 } | 441 } |
| 412 | 442 |
| 413 // Runs on the main thread. | 443 // Runs on the main thread. |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 602 | 632 |
| 603 // TODO(mark): Remove when able! | 633 // TODO(mark): Remove when able! |
| 604 // | 634 // |
| 605 // keystone_promote_preflight is hopefully temporary. It's here to ensure | 635 // keystone_promote_preflight is hopefully temporary. It's here to ensure |
| 606 // that the Keystone system ticket store is in a usable state for all users | 636 // that the Keystone system ticket store is in a usable state for all users |
| 607 // on the system. Ideally, Keystone's installer or another part of Keystone | 637 // on the system. Ideally, Keystone's installer or another part of Keystone |
| 608 // would handle this. The underlying problem is http://b/2285921, and it | 638 // would handle this. The underlying problem is http://b/2285921, and it |
| 609 // causes http://b/2289908, which this workaround addresses. | 639 // causes http://b/2289908, which this workaround addresses. |
| 610 // | 640 // |
| 611 // This is run synchronously, which isn't optimal, but | 641 // This is run synchronously, which isn't optimal, but |
| 612 // -[KSRegistration promoteWithVersion:...] is currently synchronous too, | 642 // -[KSRegistration promoteWithParameters:authorization:] is currently |
| 613 // and this operation needs to happen before that one. | 643 // synchronous too, and this operation needs to happen before that one. |
| 614 // | 644 // |
| 615 // TODO(mark): Make asynchronous. That only makes sense if the promotion | 645 // TODO(mark): Make asynchronous. That only makes sense if the promotion |
| 616 // operation itself is asynchronous too. http://b/2290009. Hopefully, | 646 // operation itself is asynchronous too. http://b/2290009. Hopefully, |
| 617 // the Keystone promotion code will just be changed to do what preflight | 647 // the Keystone promotion code will just be changed to do what preflight |
| 618 // now does, and then the preflight script can be removed instead. | 648 // now does, and then the preflight script can be removed instead. |
| 619 NSString* preflightPath = | 649 NSString* preflightPath = |
| 620 [mac_util::MainAppBundle() pathForResource:@"keystone_promote_preflight" | 650 [mac_util::MainAppBundle() pathForResource:@"keystone_promote_preflight" |
| 621 ofType:@"sh"]; | 651 ofType:@"sh"]; |
| 622 const char* preflightPathC = [preflightPath fileSystemRepresentation]; | 652 const char* preflightPathC = [preflightPath fileSystemRepresentation]; |
| 623 const char* arguments[] = {NULL}; | 653 const char* arguments[] = {NULL}; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 640 [self updateStatus:kAutoupdatePromoteFailed version:nil]; | 670 [self updateStatus:kAutoupdatePromoteFailed version:nil]; |
| 641 return; | 671 return; |
| 642 } | 672 } |
| 643 | 673 |
| 644 // Hang on to the AuthorizationRef so that it can be used once promotion is | 674 // Hang on to the AuthorizationRef so that it can be used once promotion is |
| 645 // complete. Do this before asking Keystone to promote the ticket, because | 675 // complete. Do this before asking Keystone to promote the ticket, because |
| 646 // -promotionComplete: may be called from inside the Keystone promotion | 676 // -promotionComplete: may be called from inside the Keystone promotion |
| 647 // call. | 677 // call. |
| 648 authorization_.swap(authorization); | 678 authorization_.swap(authorization); |
| 649 | 679 |
| 650 if (![registration_ promoteWithVersion:version_ | 680 NSDictionary* parameters = [self keystoneParameters]; |
| 651 existenceCheckerType:kKSPathExistenceChecker | 681 if (![registration_ promoteWithParameters:parameters |
| 652 existenceCheckerString:appPath_ | 682 authorization:authorization_]) { |
| 653 serverURLString:url_ | |
| 654 preserveTTToken:YES | |
| 655 tag:channel_ | |
| 656 authorization:authorization_]) { | |
| 657 [self updateStatus:kAutoupdatePromoteFailed version:nil]; | 683 [self updateStatus:kAutoupdatePromoteFailed version:nil]; |
| 658 authorization_.reset(); | 684 authorization_.reset(); |
| 659 return; | 685 return; |
| 660 } | 686 } |
| 661 | 687 |
| 662 // Upon completion, KSRegistrationPromotionDidCompleteNotification will be | 688 // Upon completion, KSRegistrationPromotionDidCompleteNotification will be |
| 663 // posted, and -promotionComplete: will be called. | 689 // posted, and -promotionComplete: will be called. |
| 664 } | 690 } |
| 665 | 691 |
| 666 - (void)promotionComplete:(NSNotification*)notification { | 692 - (void)promotionComplete:(NSNotification*)notification { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 719 waitUntilDone:NO]; | 745 waitUntilDone:NO]; |
| 720 } | 746 } |
| 721 | 747 |
| 722 - (void)changePermissionsForPromotionComplete { | 748 - (void)changePermissionsForPromotionComplete { |
| 723 authorization_.reset(); | 749 authorization_.reset(); |
| 724 | 750 |
| 725 [self updateStatus:kAutoupdatePromoted version:nil]; | 751 [self updateStatus:kAutoupdatePromoted version:nil]; |
| 726 } | 752 } |
| 727 | 753 |
| 728 @end // @implementation KeystoneGlue | 754 @end // @implementation KeystoneGlue |
| OLD | NEW |