| 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 |
| 11 #include <vector> | 11 #include <vector> |
| 12 | 12 |
| 13 #include "base/bind.h" | 13 #include "base/bind.h" |
| 14 #include "base/location.h" | 14 #include "base/location.h" |
| 15 #include "base/logging.h" | 15 #include "base/logging.h" |
| 16 #include "base/mac/authorization_util.h" | 16 #include "base/mac/authorization_util.h" |
| 17 #include "base/mac/bundle_locations.h" | 17 #include "base/mac/bundle_locations.h" |
| 18 #include "base/mac/foundation_util.h" | 18 #include "base/mac/foundation_util.h" |
| 19 #include "base/mac/mac_logging.h" | 19 #include "base/mac/mac_logging.h" |
| 20 #include "base/mac/scoped_nsautorelease_pool.h" | 20 #include "base/mac/scoped_nsautorelease_pool.h" |
| 21 #include "base/memory/ref_counted.h" | 21 #include "base/memory/ref_counted.h" |
| 22 #include "base/strings/string_number_conversions.h" |
| 22 #include "base/strings/sys_string_conversions.h" | 23 #include "base/strings/sys_string_conversions.h" |
| 23 #include "base/threading/worker_pool.h" | 24 #include "base/threading/worker_pool.h" |
| 24 #include "build/build_config.h" | 25 #include "build/build_config.h" |
| 25 #import "chrome/browser/mac/keystone_registration.h" | 26 #import "chrome/browser/mac/keystone_registration.h" |
| 26 #include "chrome/common/channel_info.h" | 27 #include "chrome/common/channel_info.h" |
| 27 #include "chrome/common/chrome_constants.h" | 28 #include "chrome/common/chrome_constants.h" |
| 28 #include "chrome/grit/chromium_strings.h" | 29 #include "chrome/grit/chromium_strings.h" |
| 29 #include "chrome/grit/generated_resources.h" | 30 #include "chrome/grit/generated_resources.h" |
| 30 #include "components/version_info/version_info.h" | 31 #include "components/version_info/version_info.h" |
| 31 #include "ui/base/l10n/l10n_util.h" | 32 #include "ui/base/l10n/l10n_util.h" |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 120 | 121 |
| 121 // Set the registration active and pass profile count parameters. | 122 // Set the registration active and pass profile count parameters. |
| 122 - (void)setRegistrationActive; | 123 - (void)setRegistrationActive; |
| 123 | 124 |
| 124 // Called periodically to announce activity by pinging the Keystone server. | 125 // Called periodically to announce activity by pinging the Keystone server. |
| 125 - (void)markActive:(NSTimer*)timer; | 126 - (void)markActive:(NSTimer*)timer; |
| 126 | 127 |
| 127 // Called when an update check or update installation is complete. Posts the | 128 // Called when an update check or update installation is complete. Posts the |
| 128 // kAutoupdateStatusNotification notification to the default notification | 129 // kAutoupdateStatusNotification notification to the default notification |
| 129 // center. | 130 // center. |
| 130 - (void)updateStatus:(AutoupdateStatus)status version:(NSString*)version; | 131 - (void)updateStatus:(AutoupdateStatus)status |
| 132 version:(NSString*)version |
| 133 error:(NSString*)error; |
| 131 | 134 |
| 132 // Returns the version of the currently-installed application on disk. | 135 // Returns the version of the currently-installed application on disk. |
| 133 - (NSString*)currentlyInstalledVersion; | 136 - (NSString*)currentlyInstalledVersion; |
| 134 | 137 |
| 135 // These three methods are used to determine the version of the application | 138 // These three methods are used to determine the version of the application |
| 136 // currently installed on disk, compare that to the currently-running version, | 139 // currently installed on disk, compare that to the currently-running version, |
| 137 // decide whether any updates have been installed, and call | 140 // decide whether any updates have been installed, and call |
| 138 // -updateStatus:version:. | 141 // -updateStatus:version:error:. |
| 139 // | 142 // |
| 140 // In order to check the version on disk, the installed application's | 143 // 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 | 144 // 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 | 145 // 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 | 146 // 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 | 147 // 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 | 148 // thread. I'm not quite sure what jank means, but I bet that a blocked main |
| 146 // thread would cause some of it. | 149 // thread would cause some of it. |
| 147 // | 150 // |
| 148 // -determineUpdateStatusAsync is called on the main thread to initiate the | 151 // -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 | 152 // 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 | 153 // thread and arranges for -determineUpdateStatus to be called on a work queue |
| 151 // thread managed by WorkerPool. | 154 // thread managed by WorkerPool. |
| 152 // -determineUpdateStatus then reads the Info.plist, gets the version from the | 155 // -determineUpdateStatus then reads the Info.plist, gets the version from the |
| 153 // CFBundleShortVersionString key, and performs | 156 // CFBundleShortVersionString key, and performs |
| 154 // -determineUpdateStatusForVersion: on the main thread. | 157 // -determineUpdateStatusForVersion: on the main thread. |
| 155 // -determineUpdateStatusForVersion: does the actual comparison of the version | 158 // -determineUpdateStatusForVersion: does the actual comparison of the version |
| 156 // on disk with the running version and calls -updateStatus:version: with the | 159 // on disk with the running version and calls -updateStatus:version:error: with |
| 157 // results of its analysis. | 160 // the results of its analysis. |
| 158 - (void)determineUpdateStatusAsync; | 161 - (void)determineUpdateStatusAsync; |
| 159 - (void)determineUpdateStatus; | 162 - (void)determineUpdateStatus; |
| 160 - (void)determineUpdateStatusForVersion:(NSString*)version; | 163 - (void)determineUpdateStatusForVersion:(NSString*)version; |
| 161 | 164 |
| 162 // Returns YES if registration_ is definitely on a user ticket. If definitely | 165 // 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 | 166 // on a system ticket, or uncertain of ticket type (due to an older version |
| 164 // of Keystone being used), returns NO. | 167 // of Keystone being used), returns NO. |
| 165 - (BOOL)isUserTicket; | 168 - (BOOL)isUserTicket; |
| 166 | 169 |
| 167 // Returns YES if Keystone is definitely installed at the system level, | 170 // 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 | 204 // 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 | 205 // required, the tag suffix will contain the string "-full". If no special |
| 203 // treatment is required, the tag suffix will be an empty string. | 206 // treatment is required, the tag suffix will be an empty string. |
| 204 - (NSString*)tagSuffix; | 207 - (NSString*)tagSuffix; |
| 205 | 208 |
| 206 @end // @interface KeystoneGlue (Private) | 209 @end // @interface KeystoneGlue (Private) |
| 207 | 210 |
| 208 NSString* const kAutoupdateStatusNotification = @"AutoupdateStatusNotification"; | 211 NSString* const kAutoupdateStatusNotification = @"AutoupdateStatusNotification"; |
| 209 NSString* const kAutoupdateStatusStatus = @"status"; | 212 NSString* const kAutoupdateStatusStatus = @"status"; |
| 210 NSString* const kAutoupdateStatusVersion = @"version"; | 213 NSString* const kAutoupdateStatusVersion = @"version"; |
| 214 NSString* const kAutoupdateStatusErrorMessages = @"errormessages"; |
| 211 | 215 |
| 212 namespace { | 216 namespace { |
| 213 | 217 |
| 214 NSString* const kChannelKey = @"KSChannelID"; | 218 NSString* const kChannelKey = @"KSChannelID"; |
| 215 NSString* const kBrandKey = @"KSBrandID"; | 219 NSString* const kBrandKey = @"KSBrandID"; |
| 216 NSString* const kVersionKey = @"KSVersion"; | 220 NSString* const kVersionKey = @"KSVersion"; |
| 217 | 221 |
| 218 } // namespace | 222 } // namespace |
| 219 | 223 |
| 220 @implementation KeystoneGlue | 224 @implementation KeystoneGlue |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 282 // what's significant here: it's used to locate the outermost part of the | 286 // what's significant here: it's used to locate the outermost part of the |
| 283 // application for the existence checker and other operations that need to | 287 // application for the existence checker and other operations that need to |
| 284 // see the entire application bundle. | 288 // see the entire application bundle. |
| 285 return [base::mac::OuterBundle() infoDictionary]; | 289 return [base::mac::OuterBundle() infoDictionary]; |
| 286 } | 290 } |
| 287 | 291 |
| 288 - (void)loadParameters { | 292 - (void)loadParameters { |
| 289 NSBundle* appBundle = base::mac::OuterBundle(); | 293 NSBundle* appBundle = base::mac::OuterBundle(); |
| 290 NSDictionary* infoDictionary = [self infoDictionary]; | 294 NSDictionary* infoDictionary = [self infoDictionary]; |
| 291 | 295 |
| 292 NSString* productID = [infoDictionary objectForKey:@"KSProductID"]; | 296 NSString* productID = base::mac::ObjCCast<NSString>( |
| 297 [infoDictionary objectForKey:@"KSProductID"]); |
| 293 if (productID == nil) { | 298 if (productID == nil) { |
| 294 productID = [appBundle bundleIdentifier]; | 299 productID = [appBundle bundleIdentifier]; |
| 295 } | 300 } |
| 296 | 301 |
| 297 NSString* appPath = [appBundle bundlePath]; | 302 NSString* appPath = [appBundle bundlePath]; |
| 298 NSString* url = [infoDictionary objectForKey:@"KSUpdateURL"]; | 303 NSString* url = base::mac::ObjCCast<NSString>( |
| 299 NSString* version = [infoDictionary objectForKey:kVersionKey]; | 304 [infoDictionary objectForKey:@"KSUpdateURL"]); |
| 305 NSString* version = base::mac::ObjCCast<NSString>( |
| 306 [infoDictionary objectForKey:kVersionKey]); |
| 300 | 307 |
| 301 if (!productID || !appPath || !url || !version) { | 308 if (!productID || !appPath || !url || !version) { |
| 302 // If parameters required for Keystone are missing, don't use it. | 309 // If parameters required for Keystone are missing, don't use it. |
| 303 return; | 310 return; |
| 304 } | 311 } |
| 305 | 312 |
| 306 NSString* channel = [infoDictionary objectForKey:kChannelKey]; | 313 NSString* channel = base::mac::ObjCCast<NSString>( |
| 314 [infoDictionary objectForKey:kChannelKey]); |
| 307 // The stable channel has no tag. If updating to stable, remove the | 315 // The stable channel has no tag. If updating to stable, remove the |
| 308 // dev and beta tags since we've been "promoted". | 316 // dev and beta tags since we've been "promoted". |
| 309 if (channel == nil) | 317 if (channel == nil) |
| 310 channel = ksr::KSRegistrationRemoveExistingTag; | 318 channel = ksr::KSRegistrationRemoveExistingTag; |
| 311 | 319 |
| 312 productID_ = [productID retain]; | 320 productID_ = [productID retain]; |
| 313 appPath_ = [appPath retain]; | 321 appPath_ = [appPath retain]; |
| 314 url_ = [url retain]; | 322 url_ = [url retain]; |
| 315 version_ = [version retain]; | 323 version_ = [version retain]; |
| 316 channel_ = [channel retain]; | 324 channel_ = [channel retain]; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 358 | 366 |
| 359 // Clean up any old user level file. | 367 // Clean up any old user level file. |
| 360 if ([fm fileExistsAtPath:userBrandFile]) { | 368 if ([fm fileExistsAtPath:userBrandFile]) { |
| 361 [fm removeItemAtPath:userBrandFile error:NULL]; | 369 [fm removeItemAtPath:userBrandFile error:NULL]; |
| 362 } | 370 } |
| 363 | 371 |
| 364 } else { | 372 } else { |
| 365 // User | 373 // User |
| 366 | 374 |
| 367 NSDictionary* infoDictionary = [self infoDictionary]; | 375 NSDictionary* infoDictionary = [self infoDictionary]; |
| 368 NSString* appBundleBrandID = [infoDictionary objectForKey:kBrandKey]; | 376 NSString* appBundleBrandID = base::mac::ObjCCast<NSString>( |
| 377 [infoDictionary objectForKey:kBrandKey]); |
| 369 | 378 |
| 370 NSString* storedBrandID = nil; | 379 NSString* storedBrandID = nil; |
| 371 if ([fm fileExistsAtPath:userBrandFile]) { | 380 if ([fm fileExistsAtPath:userBrandFile]) { |
| 372 NSDictionary* storedBrandDict = | 381 NSDictionary* storedBrandDict = |
| 373 [NSDictionary dictionaryWithContentsOfFile:userBrandFile]; | 382 [NSDictionary dictionaryWithContentsOfFile:userBrandFile]; |
| 374 storedBrandID = [storedBrandDict objectForKey:kBrandKey]; | 383 storedBrandID = base::mac::ObjCCast<NSString>( |
| 384 [storedBrandDict objectForKey:kBrandKey]); |
| 375 } | 385 } |
| 376 | 386 |
| 377 if ((appBundleBrandID != nil) && | 387 if ((appBundleBrandID != nil) && |
| 378 (![storedBrandID isEqualTo:appBundleBrandID])) { | 388 (![storedBrandID isEqualTo:appBundleBrandID])) { |
| 379 // App and store don't match, update store and use it. | 389 // App and store don't match, update store and use it. |
| 380 NSDictionary* storedBrandDict = | 390 NSDictionary* storedBrandDict = |
| 381 [NSDictionary dictionaryWithObject:appBundleBrandID | 391 [NSDictionary dictionaryWithObject:appBundleBrandID |
| 382 forKey:kBrandKey]; | 392 forKey:kBrandKey]; |
| 383 // If Keystone hasn't been installed yet, the location the brand file | 393 // If Keystone hasn't been installed yet, the location the brand file |
| 384 // is written to won't exist, so manually create the directory. | 394 // is written to won't exist, so manually create the directory. |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 487 preserveTTToken, ksr::KSRegistrationPreserveTrustedTesterTokenKey, | 497 preserveTTToken, ksr::KSRegistrationPreserveTrustedTesterTokenKey, |
| 488 tagValue, ksr::KSRegistrationTagKey, | 498 tagValue, ksr::KSRegistrationTagKey, |
| 489 appInfoPlistPath, ksr::KSRegistrationTagPathKey, | 499 appInfoPlistPath, ksr::KSRegistrationTagPathKey, |
| 490 tagKey, ksr::KSRegistrationTagKeyKey, | 500 tagKey, ksr::KSRegistrationTagKeyKey, |
| 491 brandPath, ksr::KSRegistrationBrandPathKey, | 501 brandPath, ksr::KSRegistrationBrandPathKey, |
| 492 brandKey, ksr::KSRegistrationBrandKeyKey, | 502 brandKey, ksr::KSRegistrationBrandKeyKey, |
| 493 nil]; | 503 nil]; |
| 494 } | 504 } |
| 495 | 505 |
| 496 - (void)setRegistrationActive { | 506 - (void)setRegistrationActive { |
| 497 if (!registration_) | 507 DCHECK(registration_); |
| 498 return; | 508 |
| 499 registrationActive_ = YES; | 509 registrationActive_ = YES; |
| 500 | 510 |
| 501 // Should never have zero profiles. Do not report this value. | 511 // Should never have zero profiles. Do not report this value. |
| 502 if (!numProfiles_) { | 512 if (!numProfiles_) { |
| 503 [registration_ setActive]; | 513 [registration_ setActive]; |
| 504 return; | 514 return; |
| 505 } | 515 } |
| 506 | 516 |
| 507 NSError* reportingError = nil; | 517 NSError* reportingError = nil; |
| 508 | 518 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 529 NSArray* profileCountsInformation = | 539 NSArray* profileCountsInformation = |
| 530 [NSArray arrayWithObjects:numAccountsAttr, numSignedInAccountsAttr, nil]; | 540 [NSArray arrayWithObjects:numAccountsAttr, numSignedInAccountsAttr, nil]; |
| 531 | 541 |
| 532 if (![registration_ setActiveWithReportingAttributes:profileCountsInformation | 542 if (![registration_ setActiveWithReportingAttributes:profileCountsInformation |
| 533 error:&reportingError]) { | 543 error:&reportingError]) { |
| 534 VLOG(1) << [reportingError localizedDescription]; | 544 VLOG(1) << [reportingError localizedDescription]; |
| 535 } | 545 } |
| 536 } | 546 } |
| 537 | 547 |
| 538 - (void)registerWithKeystone { | 548 - (void)registerWithKeystone { |
| 539 [self updateStatus:kAutoupdateRegistering version:nil]; | 549 DCHECK(registration_); |
| 550 |
| 551 [self updateStatus:kAutoupdateRegistering version:nil error:nil]; |
| 540 | 552 |
| 541 NSDictionary* parameters = [self keystoneParameters]; | 553 NSDictionary* parameters = [self keystoneParameters]; |
| 542 BOOL result = [registration_ registerWithParameters:parameters]; | 554 BOOL result = [registration_ registerWithParameters:parameters]; |
| 543 if (!result) { | 555 if (!result) { |
| 544 [self updateStatus:kAutoupdateRegisterFailed version:nil]; | 556 // TODO: If Keystone ever makes a variant of this API with a withError: |
| 557 // parameter, include the error message here in the call to updateStatus:. |
| 558 [self updateStatus:kAutoupdateRegisterFailed version:nil error:nil]; |
| 545 return; | 559 return; |
| 546 } | 560 } |
| 547 | 561 |
| 548 // Upon completion, ksr::KSRegistrationDidCompleteNotification will be | 562 // Upon completion, ksr::KSRegistrationDidCompleteNotification will be |
| 549 // posted, and -registrationComplete: will be called. | 563 // posted, and -registrationComplete: will be called. |
| 550 | 564 |
| 551 // Set up hourly activity pings. | 565 // Set up hourly activity pings. |
| 552 timer_ = [NSTimer scheduledTimerWithTimeInterval:60 * 60 // One hour | 566 timer_ = [NSTimer scheduledTimerWithTimeInterval:60 * 60 // One hour |
| 553 target:self | 567 target:self |
| 554 selector:@selector(markActive:) | 568 selector:@selector(markActive:) |
| 555 userInfo:nil | 569 userInfo:nil |
| 556 repeats:YES]; | 570 repeats:YES]; |
| 557 } | 571 } |
| 558 | 572 |
| 559 - (BOOL)isRegisteredAndActive { | 573 - (BOOL)isRegisteredAndActive { |
| 560 return registrationActive_; | 574 return registrationActive_; |
| 561 } | 575 } |
| 562 | 576 |
| 563 - (void)registrationComplete:(NSNotification*)notification { | 577 - (void)registrationComplete:(NSNotification*)notification { |
| 564 NSDictionary* userInfo = [notification userInfo]; | 578 NSDictionary* userInfo = [notification userInfo]; |
| 565 if ([[userInfo objectForKey:ksr::KSRegistrationStatusKey] boolValue]) { | 579 NSNumber* status = base::mac::ObjCCast<NSNumber>( |
| 580 [userInfo objectForKey:ksr::KSRegistrationStatusKey]); |
| 581 NSString* errorMessages = base::mac::ObjCCast<NSString>( |
| 582 [userInfo objectForKey:ksr::KSRegistrationUpdateCheckRawErrorMessagesKey]); |
| 583 |
| 584 if ([status boolValue]) { |
| 566 if ([self isSystemTicketDoomed]) { | 585 if ([self isSystemTicketDoomed]) { |
| 567 [self updateStatus:kAutoupdateNeedsPromotion version:nil]; | 586 [self updateStatus:kAutoupdateNeedsPromotion |
| 587 version:nil |
| 588 error:errorMessages]; |
| 568 } else { | 589 } else { |
| 569 [self updateStatus:kAutoupdateRegistered version:nil]; | 590 [self updateStatus:kAutoupdateRegistered |
| 591 version:nil |
| 592 error:errorMessages]; |
| 570 } | 593 } |
| 571 } else { | 594 } else { |
| 572 // Dump registration_? | 595 // Dump registration_? |
| 573 [self updateStatus:kAutoupdateRegisterFailed version:nil]; | 596 [self updateStatus:kAutoupdateRegisterFailed |
| 597 version:nil |
| 598 error:errorMessages]; |
| 574 } | 599 } |
| 575 } | 600 } |
| 576 | 601 |
| 577 - (void)stopTimer { | 602 - (void)stopTimer { |
| 578 [timer_ invalidate]; | 603 [timer_ invalidate]; |
| 579 } | 604 } |
| 580 | 605 |
| 581 - (void)markActive:(NSTimer*)timer { | 606 - (void)markActive:(NSTimer*)timer { |
| 582 [self setRegistrationActive]; | 607 [self setRegistrationActive]; |
| 583 } | 608 } |
| 584 | 609 |
| 585 - (void)checkForUpdate { | 610 - (void)checkForUpdate { |
| 586 DCHECK(![self asyncOperationPending]); | 611 DCHECK(registration_); |
| 587 | 612 |
| 588 if (!registration_) { | 613 if ([self asyncOperationPending]) { |
| 589 [self updateStatus:kAutoupdateCheckFailed version:nil]; | 614 // Update check already in process; return without doing anything. |
| 590 return; | 615 return; |
| 591 } | 616 } |
| 592 | 617 |
| 593 [self updateStatus:kAutoupdateChecking version:nil]; | 618 [self updateStatus:kAutoupdateChecking version:nil error:nil]; |
| 594 | 619 |
| 595 // All checks from inside Chrome are considered user-initiated, because they | 620 // All checks from inside Chrome are considered user-initiated, because they |
| 596 // only happen following a user action, such as visiting the about page. | 621 // only happen following a user action, such as visiting the about page. |
| 597 // Non-user-initiated checks are the periodic checks automatically made by | 622 // 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). | 623 // Keystone, which don't come through this code path (or even this process). |
| 599 [registration_ checkForUpdateWasUserInitiated:YES]; | 624 [registration_ checkForUpdateWasUserInitiated:YES]; |
| 600 | 625 |
| 601 // Upon completion, ksr::KSRegistrationCheckForUpdateNotification will be | 626 // Upon completion, ksr::KSRegistrationCheckForUpdateNotification will be |
| 602 // posted, and -checkForUpdateComplete: will be called. | 627 // posted, and -checkForUpdateComplete: will be called. |
| 603 } | 628 } |
| 604 | 629 |
| 605 - (void)checkForUpdateComplete:(NSNotification*)notification { | 630 - (void)checkForUpdateComplete:(NSNotification*)notification { |
| 606 NSDictionary* userInfo = [notification userInfo]; | 631 NSDictionary* userInfo = [notification userInfo]; |
| 632 NSNumber* error = base::mac::ObjCCast<NSNumber>( |
| 633 [userInfo objectForKey:ksr::KSRegistrationUpdateCheckErrorKey]); |
| 634 NSNumber* status = base::mac::ObjCCast<NSNumber>( |
| 635 [userInfo objectForKey:ksr::KSRegistrationStatusKey]); |
| 636 NSString* errorMessages = base::mac::ObjCCast<NSString>( |
| 637 [userInfo objectForKey:ksr::KSRegistrationUpdateCheckRawErrorMessagesKey]); |
| 607 | 638 |
| 608 if ([[userInfo objectForKey:ksr::KSRegistrationUpdateCheckErrorKey] | 639 if ([error boolValue]) { |
| 609 boolValue]) { | 640 [self updateStatus:kAutoupdateCheckFailed |
| 610 [self updateStatus:kAutoupdateCheckFailed version:nil]; | 641 version:nil |
| 611 } else if ([[userInfo objectForKey:ksr::KSRegistrationStatusKey] boolValue]) { | 642 error:errorMessages]; |
| 643 } else if ([status 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 = base::mac::ObjCCast<NSString>( |
| 615 [self updateStatus:kAutoupdateAvailable version:version]; | 647 [userInfo objectForKey:ksr::KSRegistrationVersionKey]); |
| 648 [self updateStatus:kAutoupdateAvailable |
| 649 version:version |
| 650 error:errorMessages]; |
| 616 } else { | 651 } else { |
| 617 // If no updates are available, check what's on disk, because an update | 652 // 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, | 653 // may have already been installed. This check happens on another thread, |
| 619 // and -updateStatus:version: will be called on the main thread when done. | 654 // and -updateStatus:version: will be called on the main thread when done. |
| 620 [self determineUpdateStatusAsync]; | 655 [self determineUpdateStatusAsync]; |
| 621 } | 656 } |
| 622 } | 657 } |
| 623 | 658 |
| 624 - (void)installUpdate { | 659 - (void)installUpdate { |
| 625 DCHECK(![self asyncOperationPending]); | 660 DCHECK(registration_); |
| 626 | 661 |
| 627 if (!registration_) { | 662 if ([self asyncOperationPending]) { |
| 628 [self updateStatus:kAutoupdateInstallFailed version:nil]; | 663 // Update check already in process; return without doing anything. |
| 629 return; | 664 return; |
| 630 } | 665 } |
| 631 | 666 |
| 632 [self updateStatus:kAutoupdateInstalling version:nil]; | 667 [self updateStatus:kAutoupdateInstalling version:nil error:nil]; |
| 633 | 668 |
| 634 [registration_ startUpdate]; | 669 [registration_ startUpdate]; |
| 635 | 670 |
| 636 // Upon completion, ksr::KSRegistrationStartUpdateNotification will be | 671 // Upon completion, ksr::KSRegistrationStartUpdateNotification will be |
| 637 // posted, and -installUpdateComplete: will be called. | 672 // posted, and -installUpdateComplete: will be called. |
| 638 } | 673 } |
| 639 | 674 |
| 640 - (void)installUpdateComplete:(NSNotification*)notification { | 675 - (void)installUpdateComplete:(NSNotification*)notification { |
| 641 NSDictionary* userInfo = [notification userInfo]; | 676 NSDictionary* userInfo = [notification userInfo]; |
| 677 NSNumber* successfulInstall = base::mac::ObjCCast<NSNumber>( |
| 678 [userInfo objectForKey:ksr::KSUpdateCheckSuccessfullyInstalledKey]); |
| 679 NSString* errorMessages = base::mac::ObjCCast<NSString>( |
| 680 [userInfo objectForKey:ksr::KSRegistrationUpdateCheckRawErrorMessagesKey]); |
| 642 | 681 |
| 643 // http://crbug.com/160308 and b/7517358: when using system Keystone and on | 682 // 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 | 683 // 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 | 684 // was installed correctly, so don't check it. It should be redudnant when |
| 646 // KSUpdateCheckSuccessfullyInstalledKey is checked. | 685 // KSUpdateCheckSuccessfullyInstalledKey is checked. |
| 647 if (![[userInfo objectForKey:ksr::KSUpdateCheckSuccessfullyInstalledKey] | 686 if (![successfulInstall intValue]) { |
| 648 intValue]) { | 687 [self updateStatus:kAutoupdateInstallFailed |
| 649 [self updateStatus:kAutoupdateInstallFailed version:nil]; | 688 version:nil |
| 689 error:errorMessages]; |
| 650 } else { | 690 } else { |
| 651 updateSuccessfullyInstalled_ = YES; | 691 updateSuccessfullyInstalled_ = YES; |
| 652 | 692 |
| 653 // Nothing in the notification dictionary reports the version that was | 693 // Nothing in the notification dictionary reports the version that was |
| 654 // installed. Figure it out based on what's on disk. | 694 // installed. Figure it out based on what's on disk. |
| 655 [self determineUpdateStatusAsync]; | 695 [self determineUpdateStatusAsync]; |
| 656 } | 696 } |
| 657 } | 697 } |
| 658 | 698 |
| 659 - (NSString*)currentlyInstalledVersion { | 699 - (NSString*)currentlyInstalledVersion { |
| 660 NSString* appInfoPlistPath = [self appInfoPlistPath]; | 700 NSString* appInfoPlistPath = [self appInfoPlistPath]; |
| 661 NSDictionary* infoPlist = | 701 NSDictionary* infoPlist = |
| 662 [NSDictionary dictionaryWithContentsOfFile:appInfoPlistPath]; | 702 [NSDictionary dictionaryWithContentsOfFile:appInfoPlistPath]; |
| 663 return [infoPlist objectForKey:@"CFBundleShortVersionString"]; | 703 return base::mac::ObjCCast<NSString>( |
| 704 [infoPlist objectForKey:@"CFBundleShortVersionString"]); |
| 664 } | 705 } |
| 665 | 706 |
| 666 // Runs on the main thread. | 707 // Runs on the main thread. |
| 667 - (void)determineUpdateStatusAsync { | 708 - (void)determineUpdateStatusAsync { |
| 668 DCHECK([NSThread isMainThread]); | 709 DCHECK([NSThread isMainThread]); |
| 669 | 710 |
| 670 PerformBridge::PostPerform(self, @selector(determineUpdateStatus)); | 711 PerformBridge::PostPerform(self, @selector(determineUpdateStatus)); |
| 671 } | 712 } |
| 672 | 713 |
| 673 // Runs on a thread managed by WorkerPool. | 714 // Runs on a thread managed by WorkerPool. |
| (...skipping 28 matching lines...) Expand all Loading... |
| 702 status = kAutoupdateCurrent; | 743 status = kAutoupdateCurrent; |
| 703 } else { | 744 } else { |
| 704 // If the version on disk doesn't match what's currently running, an | 745 // 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 | 746 // update must have been applied in the background, without this app's |
| 706 // direct participation. Leave updateSuccessfullyInstalled_ alone | 747 // direct participation. Leave updateSuccessfullyInstalled_ alone |
| 707 // because there's no direct knowledge of what actually happened. | 748 // because there's no direct knowledge of what actually happened. |
| 708 status = kAutoupdateInstalled; | 749 status = kAutoupdateInstalled; |
| 709 } | 750 } |
| 710 } | 751 } |
| 711 | 752 |
| 712 [self updateStatus:status version:version]; | 753 [self updateStatus:status version:version error:nil]; |
| 713 } | 754 } |
| 714 | 755 |
| 715 - (void)updateStatus:(AutoupdateStatus)status version:(NSString*)version { | 756 - (void)updateStatus:(AutoupdateStatus)status |
| 757 version:(NSString*)version |
| 758 error:(NSString*)error { |
| 716 NSNumber* statusNumber = [NSNumber numberWithInt:status]; | 759 NSNumber* statusNumber = [NSNumber numberWithInt:status]; |
| 717 NSMutableDictionary* dictionary = | 760 NSMutableDictionary* dictionary = |
| 718 [NSMutableDictionary dictionaryWithObject:statusNumber | 761 [NSMutableDictionary dictionaryWithObject:statusNumber |
| 719 forKey:kAutoupdateStatusStatus]; | 762 forKey:kAutoupdateStatusStatus]; |
| 720 if (version) { | 763 if (version) { |
| 721 [dictionary setObject:version forKey:kAutoupdateStatusVersion]; | 764 [dictionary setObject:version forKey:kAutoupdateStatusVersion]; |
| 722 } | 765 } |
| 766 if (error) { |
| 767 [dictionary setObject:version forKey:kAutoupdateStatusErrorMessages]; |
| 768 } |
| 723 | 769 |
| 724 NSNotification* notification = | 770 NSNotification* notification = |
| 725 [NSNotification notificationWithName:kAutoupdateStatusNotification | 771 [NSNotification notificationWithName:kAutoupdateStatusNotification |
| 726 object:self | 772 object:self |
| 727 userInfo:dictionary]; | 773 userInfo:dictionary]; |
| 728 recentNotification_.reset([notification retain]); | 774 recentNotification_.reset([notification retain]); |
| 729 | 775 |
| 730 [[NSNotificationCenter defaultCenter] postNotification:notification]; | 776 [[NSNotificationCenter defaultCenter] postNotification:notification]; |
| 731 } | 777 } |
| 732 | 778 |
| 733 - (NSNotification*)recentNotification { | 779 - (NSNotification*)recentNotification { |
| 734 return [[recentNotification_ retain] autorelease]; | 780 return [[recentNotification_ retain] autorelease]; |
| 735 } | 781 } |
| 736 | 782 |
| 737 - (AutoupdateStatus)recentStatus { | 783 - (AutoupdateStatus)recentStatus { |
| 738 NSDictionary* dictionary = [recentNotification_ userInfo]; | 784 NSDictionary* dictionary = [recentNotification_ userInfo]; |
| 739 return static_cast<AutoupdateStatus>( | 785 NSNumber* status = base::mac::ObjCCastStrict<NSNumber>( |
| 740 [[dictionary objectForKey:kAutoupdateStatusStatus] intValue]); | 786 [dictionary objectForKey:kAutoupdateStatusStatus]); |
| 787 return static_cast<AutoupdateStatus>([status intValue]); |
| 741 } | 788 } |
| 742 | 789 |
| 743 - (BOOL)asyncOperationPending { | 790 - (BOOL)asyncOperationPending { |
| 744 AutoupdateStatus status = [self recentStatus]; | 791 AutoupdateStatus status = [self recentStatus]; |
| 745 return status == kAutoupdateRegistering || | 792 return status == kAutoupdateRegistering || |
| 746 status == kAutoupdateChecking || | 793 status == kAutoupdateChecking || |
| 747 status == kAutoupdateInstalling || | 794 status == kAutoupdateInstalling || |
| 748 status == kAutoupdatePromoting; | 795 status == kAutoupdatePromoting; |
| 749 } | 796 } |
| 750 | 797 |
| 751 - (BOOL)isUserTicket { | 798 - (BOOL)isUserTicket { |
| 799 DCHECK(registration_); |
| 752 return [registration_ ticketType] == ksr::kKSRegistrationUserTicket; | 800 return [registration_ ticketType] == ksr::kKSRegistrationUserTicket; |
| 753 } | 801 } |
| 754 | 802 |
| 755 - (BOOL)isSystemKeystone { | 803 - (BOOL)isSystemKeystone { |
| 756 struct stat statbuf; | 804 struct stat statbuf; |
| 757 if (stat("/Library/Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle/" | 805 if (stat("/Library/Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle/" |
| 758 "Contents/MacOS/ksadmin", | 806 "Contents/MacOS/ksadmin", |
| 759 &statbuf) != 0) { | 807 &statbuf) != 0) { |
| 760 return NO; | 808 return NO; |
| 761 } | 809 } |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 { |
| 907 DCHECK(registration_); |
| 908 |
| 859 base::mac::ScopedAuthorizationRef authorization(authorization_arg); | 909 base::mac::ScopedAuthorizationRef authorization(authorization_arg); |
| 860 authorization_arg = NULL; | 910 authorization_arg = NULL; |
| 861 | 911 |
| 862 if ([self asyncOperationPending]) { | 912 if ([self asyncOperationPending]) { |
| 863 // Starting a synchronous operation while an asynchronous one is pending | 913 // Starting a synchronous operation while an asynchronous one is pending |
| 864 // could be trouble. | 914 // could be trouble. |
| 865 return; | 915 return; |
| 866 } | 916 } |
| 867 if (!synchronous && ![self wantsPromotion]) { | 917 if (!synchronous && ![self wantsPromotion]) { |
| 868 // If operating synchronously, the call came from the installer, which | 918 // If operating synchronously, the call came from the installer, which |
| 869 // means that a system ticket is required. Otherwise, only allow | 919 // means that a system ticket is required. Otherwise, only allow |
| 870 // promotion if it's wanted. | 920 // promotion if it's wanted. |
| 871 return; | 921 return; |
| 872 } | 922 } |
| 873 | 923 |
| 874 synchronousPromotion_ = synchronous; | 924 synchronousPromotion_ = synchronous; |
| 875 | 925 |
| 876 [self updateStatus:kAutoupdatePromoting version:nil]; | 926 [self updateStatus:kAutoupdatePromoting version:nil error:nil]; |
| 877 | 927 |
| 878 // TODO(mark): Remove when able! | 928 // TODO(mark): Remove when able! |
| 879 // | 929 // |
| 880 // keystone_promote_preflight will copy the current brand information out to | 930 // 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 | 931 // the system level so all users can share the data as part of the ticket |
| 882 // promotion. | 932 // promotion. |
| 883 // | 933 // |
| 884 // It will also ensure that the Keystone system ticket store is in a usable | 934 // 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 | 935 // state for all users on the system. Ideally, Keystone's installer or |
| 886 // another part of Keystone would handle this. The underlying problem is | 936 // another part of Keystone would handle this. The underlying problem is |
| (...skipping 26 matching lines...) Expand all Loading... |
| 913 | 963 |
| 914 int exit_status; | 964 int exit_status; |
| 915 OSStatus status = base::mac::ExecuteWithPrivilegesAndWait( | 965 OSStatus status = base::mac::ExecuteWithPrivilegesAndWait( |
| 916 authorization, | 966 authorization, |
| 917 preflightPathC, | 967 preflightPathC, |
| 918 kAuthorizationFlagDefaults, | 968 kAuthorizationFlagDefaults, |
| 919 arguments, | 969 arguments, |
| 920 NULL, // pipe | 970 NULL, // pipe |
| 921 &exit_status); | 971 &exit_status); |
| 922 if (status != errAuthorizationSuccess) { | 972 if (status != errAuthorizationSuccess) { |
| 923 OSSTATUS_LOG(ERROR, status) | 973 // It's possible to get an OS-provided error string for this return code |
| 924 << "AuthorizationExecuteWithPrivileges preflight"; | 974 // using base::mac::DescriptionFromOSStatus, but most of those strings are |
| 925 [self updateStatus:kAutoupdatePromoteFailed version:nil]; | 975 // not useful/actionable for users, so we stick with the error code instead. |
| 976 NSString* errorMessage = |
| 977 l10n_util::GetNSStringFWithFixup(IDS_PROMOTE_PREFLIGHT_LAUNCH_ERROR, |
| 978 base::IntToString16(status)); |
| 979 [self updateStatus:kAutoupdatePromoteFailed |
| 980 version:nil |
| 981 error:errorMessage]; |
| 926 return; | 982 return; |
| 927 } | 983 } |
| 928 if (exit_status != 0) { | 984 if (exit_status != 0) { |
| 929 LOG(ERROR) << "keystone_promote_preflight status " << exit_status; | 985 NSString* errorMessage = |
| 930 [self updateStatus:kAutoupdatePromoteFailed version:nil]; | 986 l10n_util::GetNSStringFWithFixup(IDS_PROMOTE_PREFLIGHT_SCRIPT_ERROR, |
| 987 base::IntToString16(status)); |
| 988 [self updateStatus:kAutoupdatePromoteFailed |
| 989 version:nil |
| 990 error:errorMessage]; |
| 931 return; | 991 return; |
| 932 } | 992 } |
| 933 | 993 |
| 934 // Hang on to the AuthorizationRef so that it can be used once promotion is | 994 // 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 | 995 // complete. Do this before asking Keystone to promote the ticket, because |
| 936 // -promotionComplete: may be called from inside the Keystone promotion | 996 // -promotionComplete: may be called from inside the Keystone promotion |
| 937 // call. | 997 // call. |
| 938 authorization_.swap(authorization); | 998 authorization_.swap(authorization); |
| 939 | 999 |
| 940 NSDictionary* parameters = [self keystoneParameters]; | 1000 NSDictionary* parameters = [self keystoneParameters]; |
| 941 | 1001 |
| 942 // If the brand file is user level, update parameters to point to the new | 1002 // If the brand file is user level, update parameters to point to the new |
| 943 // system level file during promotion. | 1003 // system level file during promotion. |
| 944 if (brandFileType_ == kBrandFileTypeUser) { | 1004 if (brandFileType_ == kBrandFileTypeUser) { |
| 945 NSMutableDictionary* temp_parameters = | 1005 NSMutableDictionary* temp_parameters = |
| 946 [[parameters mutableCopy] autorelease]; | 1006 [[parameters mutableCopy] autorelease]; |
| 947 [temp_parameters setObject:SystemBrandFilePath() | 1007 [temp_parameters setObject:SystemBrandFilePath() |
| 948 forKey:ksr::KSRegistrationBrandPathKey]; | 1008 forKey:ksr::KSRegistrationBrandPathKey]; |
| 949 parameters = temp_parameters; | 1009 parameters = temp_parameters; |
| 950 } | 1010 } |
| 951 | 1011 |
| 952 if (![registration_ promoteWithParameters:parameters | 1012 if (![registration_ promoteWithParameters:parameters |
| 953 authorization:authorization_]) { | 1013 authorization:authorization_]) { |
| 954 [self updateStatus:kAutoupdatePromoteFailed version:nil]; | 1014 // TODO: If Keystone ever makes a variant of this API with a withError: |
| 1015 // parameter, include the error message here in the call to updateStatus:. |
| 1016 [self updateStatus:kAutoupdatePromoteFailed version:nil error:nil]; |
| 955 authorization_.reset(); | 1017 authorization_.reset(); |
| 956 return; | 1018 return; |
| 957 } | 1019 } |
| 958 | 1020 |
| 959 // Upon completion, ksr::KSRegistrationPromotionDidCompleteNotification will | 1021 // Upon completion, ksr::KSRegistrationPromotionDidCompleteNotification will |
| 960 // be posted, and -promotionComplete: will be called. | 1022 // be posted, and -promotionComplete: will be called. |
| 961 | 1023 |
| 962 // If synchronous, see to it that this happens immediately. Give it a | 1024 // If synchronous, see to it that this happens immediately. Give it a |
| 963 // 10-second deadline. | 1025 // 10-second deadline. |
| 964 if (synchronous) { | 1026 if (synchronous) { |
| 965 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 10, false); | 1027 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 10, false); |
| 966 } | 1028 } |
| 967 } | 1029 } |
| 968 | 1030 |
| 969 - (void)promotionComplete:(NSNotification*)notification { | 1031 - (void)promotionComplete:(NSNotification*)notification { |
| 970 NSDictionary* userInfo = [notification userInfo]; | 1032 NSDictionary* userInfo = [notification userInfo]; |
| 971 if ([[userInfo objectForKey:ksr::KSRegistrationStatusKey] boolValue]) { | 1033 NSNumber* status = base::mac::ObjCCast<NSNumber>( |
| 1034 [userInfo objectForKey:ksr::KSRegistrationStatusKey]); |
| 1035 |
| 1036 if ([status boolValue]) { |
| 972 if (synchronousPromotion_) { | 1037 if (synchronousPromotion_) { |
| 973 // Short-circuit: if performing a synchronous promotion, the promotion | 1038 // Short-circuit: if performing a synchronous promotion, the promotion |
| 974 // came from the installer, which already set the permissions properly. | 1039 // came from the installer, which already set the permissions properly. |
| 975 // Rather than run a duplicate permission-changing operation, jump | 1040 // Rather than run a duplicate permission-changing operation, jump |
| 976 // straight to "done." | 1041 // straight to "done." |
| 977 [self changePermissionsForPromotionComplete]; | 1042 [self changePermissionsForPromotionComplete]; |
| 978 } else { | 1043 } else { |
| 979 [self changePermissionsForPromotionAsync]; | 1044 [self changePermissionsForPromotionAsync]; |
| 980 } | 1045 } |
| 981 } else { | 1046 } else { |
| 982 authorization_.reset(); | 1047 authorization_.reset(); |
| 983 [self updateStatus:kAutoupdatePromoteFailed version:nil]; | 1048 [self updateStatus:kAutoupdatePromoteFailed version:nil error:nil]; |
| 984 } | 1049 } |
| 985 | 1050 |
| 986 if (synchronousPromotion_) { | 1051 if (synchronousPromotion_) { |
| 987 // The run loop doesn't need to wait for this any longer. | 1052 // The run loop doesn't need to wait for this any longer. |
| 988 CFRunLoopRef runLoop = CFRunLoopGetCurrent(); | 1053 CFRunLoopRef runLoop = CFRunLoopGetCurrent(); |
| 989 CFRunLoopStop(runLoop); | 1054 CFRunLoopStop(runLoop); |
| 990 CFRunLoopWakeUp(runLoop); | 1055 CFRunLoopWakeUp(runLoop); |
| 991 } | 1056 } |
| 992 } | 1057 } |
| 993 | 1058 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1029 | 1094 |
| 1030 SEL selector = @selector(changePermissionsForPromotionComplete); | 1095 SEL selector = @selector(changePermissionsForPromotionComplete); |
| 1031 [self performSelectorOnMainThread:selector | 1096 [self performSelectorOnMainThread:selector |
| 1032 withObject:nil | 1097 withObject:nil |
| 1033 waitUntilDone:NO]; | 1098 waitUntilDone:NO]; |
| 1034 } | 1099 } |
| 1035 | 1100 |
| 1036 - (void)changePermissionsForPromotionComplete { | 1101 - (void)changePermissionsForPromotionComplete { |
| 1037 authorization_.reset(); | 1102 authorization_.reset(); |
| 1038 | 1103 |
| 1039 [self updateStatus:kAutoupdatePromoted version:nil]; | 1104 [self updateStatus:kAutoupdatePromoted version:nil error:nil]; |
| 1040 } | 1105 } |
| 1041 | 1106 |
| 1042 - (void)setAppPath:(NSString*)appPath { | 1107 - (void)setAppPath:(NSString*)appPath { |
| 1043 if (appPath != appPath_) { | 1108 if (appPath != appPath_) { |
| 1044 [appPath_ release]; | 1109 [appPath_ release]; |
| 1045 appPath_ = [appPath copy]; | 1110 appPath_ = [appPath copy]; |
| 1046 } | 1111 } |
| 1047 } | 1112 } |
| 1048 | 1113 |
| 1049 - (BOOL)wantsFullInstaller { | 1114 - (BOOL)wantsFullInstaller { |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1131 return [KeystoneGlue defaultKeystoneGlue] != nil; | 1196 return [KeystoneGlue defaultKeystoneGlue] != nil; |
| 1132 } | 1197 } |
| 1133 | 1198 |
| 1134 base::string16 CurrentlyInstalledVersion() { | 1199 base::string16 CurrentlyInstalledVersion() { |
| 1135 KeystoneGlue* keystoneGlue = [KeystoneGlue defaultKeystoneGlue]; | 1200 KeystoneGlue* keystoneGlue = [KeystoneGlue defaultKeystoneGlue]; |
| 1136 NSString* version = [keystoneGlue currentlyInstalledVersion]; | 1201 NSString* version = [keystoneGlue currentlyInstalledVersion]; |
| 1137 return base::SysNSStringToUTF16(version); | 1202 return base::SysNSStringToUTF16(version); |
| 1138 } | 1203 } |
| 1139 | 1204 |
| 1140 } // namespace keystone_glue | 1205 } // namespace keystone_glue |
| OLD | NEW |