// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#import "chrome/browser/mac/keystone_glue.h"

#include <sys/mount.h>
#include <sys/param.h>
#include <sys/stat.h>

#include <vector>

#include "base/bind.h"
#include "base/file_version_info.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/mac/authorization_util.h"
#include "base/mac/bundle_locations.h"
#include "base/mac/foundation_util.h"
#include "base/mac/mac_logging.h"
#include "base/mac/scoped_nsautorelease_pool.h"
#include "base/memory/ref_counted.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/sys_string_conversions.h"
#include "base/task/post_task.h"
#include "base/version.h"
#include "build/build_config.h"
#import "chrome/browser/mac/keystone_registration.h"
#include "chrome/common/channel_info.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/grit/chromium_strings.h"
#include "chrome/grit/generated_resources.h"
#include "components/version_info/version_info.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/l10n/l10n_util_mac.h"

namespace {

namespace ksr = keystone_registration;

// Constants for the brand file (uses an external file so it can survive
// updates to Chrome.)

#if defined(GOOGLE_CHROME_BUILD)
#define kStableBrandFileName @"Google Chrome Brand.plist"
#define kCanaryBrandFileName @"Google Chrome Canary Brand.plist"
#elif defined(CHROMIUM_BUILD)
#define kStableBrandFileName @"Chromium Brand.plist"
#define kCanaryBrandFileName @"Chromium Canary Brand.plist"
#else
#error Unknown branding
#endif

// These directories are hardcoded in Keystone promotion preflight and the
// Keystone install script, so NSSearchPathForDirectoriesInDomains isn't used
// since the scripts couldn't use anything like that.
NSString* kStableBrandUserFile = @"~/Library/Google/" kStableBrandFileName;
NSString* kStableBrandSystemFile = @"/Library/Google/" kStableBrandFileName;
NSString* kCanaryBrandUserFile = @"~/Library/Google/" kCanaryBrandFileName;
NSString* kCanaryBrandSystemFile = @"/Library/Google/" kCanaryBrandFileName;

NSString* UserBrandFilePath(version_info::Channel channel) {
  NSString* file = (channel == version_info::Channel::CANARY)
                       ? kCanaryBrandUserFile
                       : kStableBrandUserFile;
  return [file stringByStandardizingPath];
}

NSString* SystemBrandFilePath(version_info::Channel channel) {
  NSString* file = (channel == version_info::Channel::CANARY)
                       ? kCanaryBrandSystemFile
                       : kStableBrandSystemFile;
  return [file stringByStandardizingPath];
}

// Adaptor for scheduling an Objective-C method call in TaskScheduler.
class PerformBridge : public base::RefCountedThreadSafe<PerformBridge> {
 public:

  // Call |sel| on |target| with |arg| in a WorkerPool thread.
  // |target| and |arg| are retained, |arg| may be |nil|.
  static void PostPerform(id target, SEL sel, id arg) {
    DCHECK(target);
    DCHECK(sel);

    scoped_refptr<PerformBridge> op = new PerformBridge(target, sel, arg);
    base::PostTaskWithTraits(FROM_HERE,
                             {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
                              base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
                             base::Bind(&PerformBridge::Run, op.get()));
  }

  // Convenience for the no-argument case.
  static void PostPerform(id target, SEL sel) {
    PostPerform(target, sel, nil);
  }

 private:
  // Allow RefCountedThreadSafe<> to delete.
  friend class base::RefCountedThreadSafe<PerformBridge>;

  PerformBridge(id target, SEL sel, id arg)
      : target_([target retain]),
        sel_(sel),
        arg_([arg retain]) {
  }

  ~PerformBridge() {}

  // Happens on a WorkerPool thread.
  void Run() {
    base::mac::ScopedNSAutoreleasePool pool;
    [target_ performSelector:sel_ withObject:arg_];
  }

  base::scoped_nsobject<id> target_;
  SEL sel_;
  base::scoped_nsobject<id> arg_;
};

}  // namespace

@interface KeystoneGlue (Private)

// Returns the path to the application's Info.plist file.  This returns the
// outer application bundle's Info.plist, not the framework's Info.plist.
- (NSString*)appInfoPlistPath;

// Returns a dictionary containing parameters to be used for a KSRegistration
// -registerWithParameters: or -promoteWithParameters:authorization: call.
- (NSDictionary*)keystoneParameters;

// Called when Keystone registration completes.
- (void)registrationComplete:(NSNotification*)notification;

// Set the registration active and pass profile count parameters.
- (void)setRegistrationActive;

// Called periodically to announce activity by pinging the Keystone server.
- (void)markActive:(NSTimer*)timer;

// Called when an update check or update installation is complete.  Posts the
// kAutoupdateStatusNotification notification to the default notification
// center.
- (void)updateStatus:(AutoupdateStatus)status
             version:(NSString*)version
               error:(NSString*)error;

// Returns the version of the currently-installed application on disk.
- (NSString*)currentlyInstalledVersion;

// These three methods are used to determine the version of the application
// currently installed on disk, compare that to the currently-running version,
// decide whether any updates have been installed, and call
// -updateStatus:version:error:.
//
// In order to check the version on disk, the installed application's
// Info.plist dictionary must be read; in order to see changes as updates are
// applied, the dictionary must be read each time, bypassing any caches such
// as the one that NSBundle might be maintaining.  Reading files can be a
// blocking operation, and blocking operations are to be avoided on the main
// thread.  I'm not quite sure what jank means, but I bet that a blocked main
// thread would cause some of it.
//
// -determineUpdateStatusAsync is called on the main thread to initiate the
// operation.  It performs initial set-up work that must be done on the main
// thread and arranges for -determineUpdateStatus to be called on a work queue
// thread managed by WorkerPool.
// -determineUpdateStatus then reads the Info.plist, gets the version from the
// CFBundleShortVersionString key, and performs
// -determineUpdateStatusForVersion: on the main thread.
// -determineUpdateStatusForVersion: does the actual comparison of the version
// on disk with the running version and calls -updateStatus:version:error: with
// the results of its analysis.
- (void)determineUpdateStatusAsync;
- (void)determineUpdateStatus;
- (void)determineUpdateStatusForVersion:(NSString*)version;

// Returns YES if registration_ is definitely on a system ticket.
- (BOOL)isSystemTicket;

// Returns YES if Keystone is definitely installed at the system level,
// determined by the presence of an executable ksadmin program at the expected
// system location.
- (BOOL)isSystemKeystone;

// Called when ticket promotion completes.
- (void)promotionComplete:(NSNotification*)notification;

// Changes the application's ownership and permissions so that all files are
// owned by root:wheel and all files and directories are writable only by
// root, but readable and executable as needed by everyone.
// -changePermissionsForPromotionAsync is called on the main thread by
// -promotionComplete.  That routine calls
// -changePermissionsForPromotionWithTool: on a work queue thread.  When done,
// -changePermissionsForPromotionComplete is called on the main thread.
- (void)changePermissionsForPromotionAsync;
- (void)changePermissionsForPromotionWithTool:(NSString*)toolPath;
- (void)changePermissionsForPromotionComplete;

// Returns the brand file path to use for Keystone.
- (NSString*)brandFilePath;

// YES if no update installation has succeeded since a binary diff patch
// installation failed. This signals the need to attempt a full installer
// which does not depend on applying a patch to existing files.
- (BOOL)wantsFullInstaller;

// Returns an NSString* suitable for appending to a Chrome Keystone tag value or
// tag key.  If a full installer (as opposed to a binary diff/delta patch) is
// required, the tag suffix will contain the string "-full". If no special
// treatment is required, the tag suffix will be an empty string.
- (NSString*)tagSuffix;

@end  // @interface KeystoneGlue (Private)

NSString* const kAutoupdateStatusNotification = @"AutoupdateStatusNotification";
NSString* const kAutoupdateStatusStatus = @"status";
NSString* const kAutoupdateStatusVersion = @"version";
NSString* const kAutoupdateStatusErrorMessages = @"errormessages";

namespace {

NSString* const kChannelKey = @"KSChannelID";
NSString* const kBrandKey = @"KSBrandID";
NSString* const kVersionKey = @"KSVersion";

}  // namespace

@implementation KeystoneGlue

+ (id)defaultKeystoneGlue {
  static bool sTriedCreatingDefaultKeystoneGlue = false;
  static KeystoneGlue* sDefaultKeystoneGlue = nil;  // leaked

  if (!sTriedCreatingDefaultKeystoneGlue) {
    sTriedCreatingDefaultKeystoneGlue = true;

    sDefaultKeystoneGlue = [[KeystoneGlue alloc] init];
    [sDefaultKeystoneGlue loadParameters];
    if (![sDefaultKeystoneGlue loadKeystoneRegistration]) {
      [sDefaultKeystoneGlue release];
      sDefaultKeystoneGlue = nil;
    }
  }
  return sDefaultKeystoneGlue;
}

- (id)init {
  if ((self = [super init])) {
    NSNotificationCenter* center = [NSNotificationCenter defaultCenter];

    [center addObserver:self
               selector:@selector(registrationComplete:)
                   name:ksr::KSRegistrationDidCompleteNotification
                 object:nil];

    [center addObserver:self
               selector:@selector(promotionComplete:)
                   name:ksr::KSRegistrationPromotionDidCompleteNotification
                 object:nil];

    [center addObserver:self
               selector:@selector(checkForUpdateComplete:)
                   name:ksr::KSRegistrationCheckForUpdateNotification
                 object:nil];

    [center addObserver:self
               selector:@selector(installUpdateComplete:)
                   name:ksr::KSRegistrationStartUpdateNotification
                 object:nil];
  }

  return self;
}

- (void)dealloc {
  [[NSNotificationCenter defaultCenter] removeObserver:self];
  [super dealloc];
}

- (NSDictionary*)infoDictionary {
  // Use base::mac::OuterBundle() to get the Chrome app's own bundle identifier
  // and path, not the framework's.  For auto-update, the application is
  // what's significant here: it's used to locate the outermost part of the
  // application for the existence checker and other operations that need to
  // see the entire application bundle.
  return [base::mac::OuterBundle() infoDictionary];
}

- (void)loadParameters {
  NSBundle* appBundle = base::mac::OuterBundle();
  NSDictionary* infoDictionary = [self infoDictionary];

  NSString* productID = base::mac::ObjCCast<NSString>(
      [infoDictionary objectForKey:@"KSProductID"]);
  if (productID == nil) {
    productID = [appBundle bundleIdentifier];
  }

  NSString* appPath = [appBundle bundlePath];
  NSString* url = base::mac::ObjCCast<NSString>(
      [infoDictionary objectForKey:@"KSUpdateURL"]);
  NSString* version = base::mac::ObjCCast<NSString>(
      [infoDictionary objectForKey:kVersionKey]);

  if (!productID || !appPath || !url || !version) {
    // If parameters required for Keystone are missing, don't use it.
    return;
  }

  std::string channel = chrome::GetChannelName();
  // The stable channel has no tag.  If updating to stable, remove the
  // dev and beta tags since we've been "promoted".
  version_info::Channel channelType = chrome::GetChannelByName(channel);
  if (channelType == version_info::Channel::STABLE) {
    channel = base::SysNSStringToUTF8(ksr::KSRegistrationRemoveExistingTag);
#if defined(GOOGLE_CHROME_BUILD)
    DCHECK(chrome::GetChannelByName(channel) == version_info::Channel::STABLE)
        << "-channel name modification has side effect";
#endif
  }

  productID_.reset([productID copy]);
  appPath_.reset([appPath copy]);
  url_.reset([url copy]);
  version_.reset([version copy]);
  channel_ = channel;
}

- (NSString*)brandFilePath {
  DCHECK(version_ != nil) << "-loadParameters must be called first";

  if (brandFile_)
    return brandFile_;

  NSFileManager* fm = [NSFileManager defaultManager];
  version_info::Channel channel = chrome::GetChannelByName(channel_);
  NSString* userBrandFile = UserBrandFilePath(channel);
  NSString* systemBrandFile = SystemBrandFilePath(channel);

  // Default to none.
  brandFile_.reset(@"", base::scoped_policy::RETAIN);

  // Only the stable and canary channel can have independent brand codes.

  if (channel == version_info::Channel::DEV ||
      channel == version_info::Channel::BETA) {
    // If on the dev or beta channel, this installation may have replaced
    // an older system-level installation. Check for a user brand file and
    // nuke it if present. Don't try to remove the system brand file, there
    // wouldn't be any permission to do so.
    //
    // Don't do this on the canary channel. The canary can run side-by-side
    // with another Google Chrome installation whose brand code, if any,
    // should remain intact.

    if ([fm fileExistsAtPath:userBrandFile]) {
      [fm removeItemAtPath:userBrandFile error:NULL];
    }

  } else if (channel == version_info::Channel::STABLE ||
             channel == version_info::Channel::CANARY) {
    // Stable and Canary use different app ids, so they can both have brand
    // codes. Even if Canary does not actively use brand codes, we want to
    // exercise the same logic, so that we can detect perf regressions early.

    // If there is a system brand file, use it.
    if ([fm fileExistsAtPath:systemBrandFile]) {
      // System

      // Use the system file that is there.
      brandFile_.reset(systemBrandFile, base::scoped_policy::RETAIN);

      // Clean up any old user level file.
      if ([fm fileExistsAtPath:userBrandFile]) {
        [fm removeItemAtPath:userBrandFile error:NULL];
      }

    } else {
      // User

      NSDictionary* infoDictionary = [self infoDictionary];
      NSString* appBundleBrandID = base::mac::ObjCCast<NSString>(
          [infoDictionary objectForKey:kBrandKey]);

      NSString* storedBrandID = nil;
      if ([fm fileExistsAtPath:userBrandFile]) {
        NSDictionary* storedBrandDict =
            [NSDictionary dictionaryWithContentsOfFile:userBrandFile];
        storedBrandID = base::mac::ObjCCast<NSString>(
            [storedBrandDict objectForKey:kBrandKey]);
      }

      if ((appBundleBrandID != nil) &&
          (![storedBrandID isEqualTo:appBundleBrandID])) {
        // App and store don't match, update store and use it.
        NSDictionary* storedBrandDict =
            [NSDictionary dictionaryWithObject:appBundleBrandID
                                        forKey:kBrandKey];
        // If Keystone hasn't been installed yet, the location the brand file
        // is written to won't exist, so manually create the directory.
        NSString* userBrandFileDirectory =
            [userBrandFile stringByDeletingLastPathComponent];
        if (![fm fileExistsAtPath:userBrandFileDirectory]) {
          if (![fm createDirectoryAtPath:userBrandFileDirectory
                  withIntermediateDirectories:YES
                                   attributes:nil
                                        error:NULL]) {
            LOG(ERROR) << "Failed to create the directory for the brand file";
          }
        }
        if ([storedBrandDict writeToFile:userBrandFile atomically:YES]) {
          brandFile_.reset(userBrandFile, base::scoped_policy::RETAIN);
        }
      } else if (storedBrandID) {
        // Had stored brand, use it.
        brandFile_.reset(userBrandFile, base::scoped_policy::RETAIN);
      }
    }
  }

  return brandFile_;
}

- (BOOL)loadKeystoneRegistration {
  if (!productID_ || !appPath_ || !url_ || !version_)
    return NO;

  // Load the KeystoneRegistration framework bundle if present.  It lives
  // inside the framework, so use base::mac::FrameworkBundle();
  NSString* ksrPath =
      [[base::mac::FrameworkBundle() privateFrameworksPath]
          stringByAppendingPathComponent:@"KeystoneRegistration.framework"];
  NSBundle* ksrBundle = [NSBundle bundleWithPath:ksrPath];
  [ksrBundle load];

  // Harness the KSRegistration class.
  Class ksrClass = [ksrBundle classNamed:@"KSRegistration"];
  KSRegistration* ksr = [ksrClass registrationWithProductID:productID_];
  if (!ksr)
    return NO;

  registration_.reset([ksr retain]);
  ksUnsignedReportingAttributeClass_ =
      [ksrBundle classNamed:@"KSUnsignedReportingAttribute"];
  return YES;
}

- (NSString*)appInfoPlistPath {
  // NSBundle ought to have a way to access this path directly, but it
  // doesn't.
  return [[appPath_ stringByAppendingPathComponent:@"Contents"]
             stringByAppendingPathComponent:@"Info.plist"];
}

- (NSDictionary*)keystoneParameters {
  NSNumber* xcType = [NSNumber numberWithInt:ksr::kKSPathExistenceChecker];
  NSNumber* preserveTTToken = [NSNumber numberWithBool:YES];
  NSString* appInfoPlistPath = [self appInfoPlistPath];
  NSString* brandKey = kBrandKey;
  NSString* brandPath = [self brandFilePath];

  if ([brandPath length] == 0) {
    // Brand path and brand key must be cleared together or ksadmin seems
    // to throw an error.
    brandKey = @"";
  }

  // Note that channel_ is permitted to be an empty string, but it must not be
  // nil.
  NSString* tagSuffix = [self tagSuffix];
  NSString* tagValue =
      [NSString stringWithFormat:@"%s%@", channel_.c_str(), tagSuffix];
  NSString* tagKey = [kChannelKey stringByAppendingString:tagSuffix];

  return @{
    ksr::KSRegistrationVersionKey : version_,
    ksr::KSRegistrationVersionPathKey : appInfoPlistPath,
    ksr::KSRegistrationVersionKeyKey : kVersionKey,
    ksr::KSRegistrationExistenceCheckerTypeKey : xcType,
    ksr::KSRegistrationExistenceCheckerStringKey : appPath_.get(),
    ksr::KSRegistrationServerURLStringKey : url_.get(),
    ksr::KSRegistrationPreserveTrustedTesterTokenKey : preserveTTToken,
    ksr::KSRegistrationTagKey : tagValue,
    ksr::KSRegistrationTagPathKey : appInfoPlistPath,
    ksr::KSRegistrationTagKeyKey : tagKey,
    ksr::KSRegistrationBrandPathKey : brandPath,
    ksr::KSRegistrationBrandKeyKey : brandKey
  };
}

- (void)setRegistrationActive {
  DCHECK(registration_);

  registrationActive_ = YES;

  // During startup, numProfiles_ defaults to 0.
  if (!numProfiles_) {
    [registration_ setActive];
    return;
  }

  NSError* reportingError = nil;

  KSReportingAttribute* numAccountsAttr =
      [ksUnsignedReportingAttributeClass_
          reportingAttributeWithValue:numProfiles_
                                 name:@"_NumAccounts"
                      aggregationType:kKSReportingAggregationSum
                                error:&reportingError];
  if (reportingError != nil)
    VLOG(1) << [reportingError localizedDescription];
  reportingError = nil;

  KSReportingAttribute* numSignedInAccountsAttr =
      [ksUnsignedReportingAttributeClass_
          reportingAttributeWithValue:numSignedInProfiles_
                                 name:@"_NumSignedIn"
                      aggregationType:kKSReportingAggregationSum
                                error:&reportingError];
  if (reportingError != nil)
    VLOG(1) << [reportingError localizedDescription];
  reportingError = nil;

  NSArray* profileCountsInformation =
      [NSArray arrayWithObjects:numAccountsAttr, numSignedInAccountsAttr, nil];

  if (![registration_ setActiveWithReportingAttributes:profileCountsInformation
                                                 error:&reportingError]) {
    VLOG(1) << [reportingError localizedDescription];
  }
}

- (void)registerWithKeystone {
  DCHECK(registration_);

  [self updateStatus:kAutoupdateRegistering version:nil error:nil];

  NSDictionary* parameters = [self keystoneParameters];
  BOOL result = [registration_ registerWithParameters:parameters];
  if (!result) {
    // TODO: If Keystone ever makes a variant of this API with a withError:
    // parameter, include the error message here in the call to updateStatus:.
    [self updateStatus:kAutoupdateRegisterFailed version:nil error:nil];
    return;
  }

  // Upon completion, ksr::KSRegistrationDidCompleteNotification will be
  // posted, and -registrationComplete: will be called.

  // Set up hourly activity pings.
  timer_ = [NSTimer scheduledTimerWithTimeInterval:60 * 60  // One hour
                                            target:self
                                          selector:@selector(markActive:)
                                          userInfo:nil
                                           repeats:YES];
}

- (BOOL)isRegisteredAndActive {
  return registrationActive_;
}

- (void)registrationComplete:(NSNotification*)notification {
  NSDictionary* userInfo = [notification userInfo];
  NSNumber* status = base::mac::ObjCCast<NSNumber>(
     [userInfo objectForKey:ksr::KSRegistrationStatusKey]);
  NSString* errorMessages = base::mac::ObjCCast<NSString>(
     [userInfo objectForKey:ksr::KSRegistrationUpdateCheckRawErrorMessagesKey]);

  if ([status boolValue]) {
    if ([self needsPromotion]) {
      [self updateStatus:kAutoupdateNeedsPromotion
                 version:nil
                   error:errorMessages];
    } else {
      [self updateStatus:kAutoupdateRegistered
                 version:nil
                   error:errorMessages];
    }
  } else {
    // Dump registration_?
    [self updateStatus:kAutoupdateRegisterFailed
               version:nil
                 error:errorMessages];
  }
}

- (void)stopTimer {
  [timer_ invalidate];
}

- (void)markActive:(NSTimer*)timer {
  [self setRegistrationActive];
}

- (void)checkForUpdate {
  DCHECK(registration_);

  if ([self asyncOperationPending]) {
    // Update check already in process; return without doing anything.
    return;
  }

  [self updateStatus:kAutoupdateChecking version:nil error:nil];

  // All checks from inside Chrome are considered user-initiated, because they
  // only happen following a user action, such as visiting the about page.
  // Non-user-initiated checks are the periodic checks automatically made by
  // Keystone, which don't come through this code path (or even this process).
  [registration_ checkForUpdateWasUserInitiated:YES];

  // Upon completion, ksr::KSRegistrationCheckForUpdateNotification will be
  // posted, and -checkForUpdateComplete: will be called.
}

- (void)checkForUpdateComplete:(NSNotification*)notification {
  NSDictionary* userInfo = [notification userInfo];
  NSNumber* error = base::mac::ObjCCast<NSNumber>(
      [userInfo objectForKey:ksr::KSRegistrationUpdateCheckErrorKey]);
  NSNumber* status = base::mac::ObjCCast<NSNumber>(
      [userInfo objectForKey:ksr::KSRegistrationStatusKey]);
  NSString* errorMessages = base::mac::ObjCCast<NSString>(
     [userInfo objectForKey:ksr::KSRegistrationUpdateCheckRawErrorMessagesKey]);

  if ([error boolValue]) {
    [self updateStatus:kAutoupdateCheckFailed
               version:nil
                 error:errorMessages];
  } else if ([status boolValue]) {
    // If an update is known to be available, go straight to
    // -updateStatus:version:.  It doesn't matter what's currently on disk.
    NSString* version = base::mac::ObjCCast<NSString>(
        [userInfo objectForKey:ksr::KSRegistrationVersionKey]);
    [self updateStatus:kAutoupdateAvailable
               version:version
                 error:errorMessages];
  } else {
    // If no updates are available, check what's on disk, because an update
    // may have already been installed.  This check happens on another thread,
    // and -updateStatus:version: will be called on the main thread when done.
    [self determineUpdateStatusAsync];
  }
}

- (void)installUpdate {
  DCHECK(registration_);

  if ([self asyncOperationPending]) {
    // Update check already in process; return without doing anything.
    return;
  }

  [self updateStatus:kAutoupdateInstalling version:nil error:nil];

  [registration_ startUpdate];

  // Upon completion, ksr::KSRegistrationStartUpdateNotification will be
  // posted, and -installUpdateComplete: will be called.
}

- (void)installUpdateComplete:(NSNotification*)notification {
  NSDictionary* userInfo = [notification userInfo];
  NSNumber* successfulInstall = base::mac::ObjCCast<NSNumber>(
      [userInfo objectForKey:ksr::KSUpdateCheckSuccessfullyInstalledKey]);
  NSString* errorMessages = base::mac::ObjCCast<NSString>(
     [userInfo objectForKey:ksr::KSRegistrationUpdateCheckRawErrorMessagesKey]);

  // http://crbug.com/160308 and b/7517358: when using system Keystone and on
  // a user ticket, KSUpdateCheckSuccessfulKey will be NO even when an update
  // was installed correctly, so don't check it. It should be redudnant when
  // KSUpdateCheckSuccessfullyInstalledKey is checked.
  if (![successfulInstall intValue]) {
    [self updateStatus:kAutoupdateInstallFailed
               version:nil
                 error:errorMessages];
  } else {
    updateSuccessfullyInstalled_ = YES;

    // Nothing in the notification dictionary reports the version that was
    // installed.  Figure it out based on what's on disk.
    [self determineUpdateStatusAsync];
  }
}

- (NSString*)currentlyInstalledVersion {
  NSString* appInfoPlistPath = [self appInfoPlistPath];
  NSDictionary* infoPlist =
      [NSDictionary dictionaryWithContentsOfFile:appInfoPlistPath];
  return base::mac::ObjCCast<NSString>(
      [infoPlist objectForKey:@"CFBundleShortVersionString"]);
}

// Runs on the main thread.
- (void)determineUpdateStatusAsync {
  DCHECK([NSThread isMainThread]);

  PerformBridge::PostPerform(self, @selector(determineUpdateStatus));
}

// Runs on a thread managed by WorkerPool.
- (void)determineUpdateStatus {
  DCHECK(![NSThread isMainThread]);

  NSString* version = [self currentlyInstalledVersion];

  [self performSelectorOnMainThread:@selector(determineUpdateStatusForVersion:)
                         withObject:version
                      waitUntilDone:NO];
}

// Runs on the main thread.
- (void)determineUpdateStatusForVersion:(NSString*)version {
  DCHECK([NSThread isMainThread]);

  AutoupdateStatus status;
  if (updateSuccessfullyInstalled_) {
    // If an update was successfully installed and this object saw it happen,
    // then don't even bother comparing versions.
    status = kAutoupdateInstalled;
  } else {
    NSString* currentVersion = base::SysUTF8ToNSString(chrome::kChromeVersion);
    if (!version) {
      // If the version on disk could not be determined, assume that
      // whatever's running is current.
      version = currentVersion;
      status = kAutoupdateCurrent;
    } else if ([version isEqualToString:currentVersion]) {
      status = kAutoupdateCurrent;
    } else {
      // If the version on disk doesn't match what's currently running, an
      // update must have been applied in the background, without this app's
      // direct participation.  Leave updateSuccessfullyInstalled_ alone
      // because there's no direct knowledge of what actually happened.
      status = kAutoupdateInstalled;
    }
  }

  [self updateStatus:status version:version error:nil];
}

- (void)updateStatus:(AutoupdateStatus)status
             version:(NSString*)version
               error:(NSString*)error {
  NSNumber* statusNumber = [NSNumber numberWithInt:status];
  NSMutableDictionary* dictionary =
      [NSMutableDictionary dictionaryWithObject:statusNumber
                                         forKey:kAutoupdateStatusStatus];
  if ([version length]) {
    [dictionary setObject:version forKey:kAutoupdateStatusVersion];
  }
  if ([error length]) {
    [dictionary setObject:error forKey:kAutoupdateStatusErrorMessages];
  }

  NSNotification* notification =
      [NSNotification notificationWithName:kAutoupdateStatusNotification
                                    object:self
                                  userInfo:dictionary];
  recentNotification_.reset([notification retain]);

  [[NSNotificationCenter defaultCenter] postNotification:notification];
}

- (NSNotification*)recentNotification {
  return [[recentNotification_ retain] autorelease];
}

- (AutoupdateStatus)recentStatus {
  NSDictionary* dictionary = [recentNotification_ userInfo];
  NSNumber* status = base::mac::ObjCCastStrict<NSNumber>(
      [dictionary objectForKey:kAutoupdateStatusStatus]);
  return static_cast<AutoupdateStatus>([status intValue]);
}

- (BOOL)asyncOperationPending {
  AutoupdateStatus status = [self recentStatus];
  return status == kAutoupdateRegistering ||
         status == kAutoupdateChecking ||
         status == kAutoupdateInstalling ||
         status == kAutoupdatePromoting;
}

- (BOOL)isSystemTicket {
  DCHECK(registration_);
  return [registration_ ticketType] == ksr::kKSRegistrationSystemTicket;
}

- (BOOL)isSystemKeystone {
  struct stat statbuf;
  if (stat("/Library/Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle/"
           "Contents/MacOS/ksadmin",
           &statbuf) != 0) {
    return NO;
  }

  if (!(statbuf.st_mode & S_IXUSR)) {
    return NO;
  }

  return YES;
}

- (BOOL)isOnReadOnlyFilesystem {
  const char* appPathC = [appPath_ fileSystemRepresentation];
  struct statfs statfsBuf;

  if (statfs(appPathC, &statfsBuf) != 0) {
    PLOG(ERROR) << "statfs";
    // Be optimistic about the filesystem's writability.
    return NO;
  }

  return (statfsBuf.f_flags & MNT_RDONLY) != 0;
}

- (BOOL)isAutoupdateEnabledForAllUsers {
  return [self isSystemKeystone] && [self isSystemTicket];
}

// Compares the version of the installed system Keystone to the version of
// KeystoneRegistration.framework. The method is a class method, so that
// tests can pick it up.
+ (BOOL)isValidSystemKeystone:(NSDictionary*)systemKeystonePlistContents
            comparedToBundled:(NSDictionary*)bundledKeystonePlistContents {
  NSString* versionKey = base::mac::CFToNSCast(kCFBundleVersionKey);

  // If the bundled version is missing or broken, this question is irrelevant.
  NSString* bundledKeystoneVersionString =
      base::mac::ObjCCast<NSString>(bundledKeystonePlistContents[versionKey]);
  if (!bundledKeystoneVersionString.length)
    return YES;
  base::Version bundled_version(
      base::SysNSStringToUTF8(bundledKeystoneVersionString));
  if (!bundled_version.IsValid())
    return YES;

  NSString* systemKeystoneVersionString =
      base::mac::ObjCCast<NSString>(systemKeystonePlistContents[versionKey]);
  if (!systemKeystoneVersionString.length)
    return NO;

  // Installed Keystone's version should always be >= than the bundled one.
  base::Version system_version(
      base::SysNSStringToUTF8(systemKeystoneVersionString));
  if (!system_version.IsValid() || system_version < bundled_version)
    return NO;

  return YES;
}

- (BOOL)isSystemKeystoneBroken {
  DCHECK([self isSystemKeystone])
      << "Call this method only for system Keystone.";

  NSDictionary* systemKeystonePlist =
      [NSDictionary dictionaryWithContentsOfFile:
                        @"/Library/Google/GoogleSoftwareUpdate/"
                        @"GoogleSoftwareUpdate.bundle/Contents/Info.plist"];
  NSBundle* keystoneFramework = [NSBundle bundleForClass:[registration_ class]];
  return ![[self class] isValidSystemKeystone:systemKeystonePlist
                            comparedToBundled:keystoneFramework.infoDictionary];
}

- (BOOL)needsPromotion {
  // Don't promote when on a read-only filesystem.
  if ([self isOnReadOnlyFilesystem]) {
    return NO;
  }

  BOOL isSystemKeystone = [self isSystemKeystone];
  if (isSystemKeystone) {
    // We can recover broken user keystone, but not broken system one.
    if ([self isSystemKeystoneBroken])
      return YES;
  }

  // System ticket requires system Keystone for the updates to work.
  if ([self isSystemTicket])
    return !isSystemKeystone;

  // Check the outermost bundle directory, the main executable path, and the
  // framework directory.  It may be enough to just look at the outermost
  // bundle directory, but checking an interior file and directory can be
  // helpful in case permissions are set differently only on the outermost
  // directory.  An interior file and directory are both checked because some
  // file operations, such as Snow Leopard's Finder's copy operation when
  // authenticating, may actually result in different ownership being applied
  // to files and directories.
  NSFileManager* fileManager = [NSFileManager defaultManager];
  NSString* executablePath = [base::mac::OuterBundle() executablePath];
  NSString* frameworkPath = [base::mac::FrameworkBundle() bundlePath];
  return ![fileManager isWritableFileAtPath:appPath_] ||
         ![fileManager isWritableFileAtPath:executablePath] ||
         ![fileManager isWritableFileAtPath:frameworkPath];
}

- (BOOL)wantsPromotion {
  if ([self needsPromotion]) {
    return YES;
  }

  // These are the same unpromotable cases as in -needsPromotion.
  if ([self isOnReadOnlyFilesystem] || [self isSystemTicket]) {
    return NO;
  }

  return [appPath_ hasPrefix:@"/Applications/"];
}

- (void)promoteTicket {
  if ([self asyncOperationPending] || ![self wantsPromotion]) {
    // Because there are multiple ways of reaching promoteTicket that might
    // not lock each other out, it may be possible to arrive here while an
    // asynchronous operation is pending, or even after promotion has already
    // occurred.  Just quietly return without doing anything.
    return;
  }

  NSString* prompt = l10n_util::GetNSStringFWithFixup(
      IDS_PROMOTE_AUTHENTICATION_PROMPT,
      l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
  base::mac::ScopedAuthorizationRef authorization(
      base::mac::AuthorizationCreateToRunAsRoot(
          base::mac::NSToCFCast(prompt)));
  if (!authorization.get()) {
    return;
  }

  [self promoteTicketWithAuthorization:authorization.release() synchronous:NO];
}

- (void)promoteTicketWithAuthorization:(AuthorizationRef)anAuthorization
                           synchronous:(BOOL)synchronous {
  DCHECK(registration_);

  base::mac::ScopedAuthorizationRef authorization(anAuthorization);
  anAuthorization = nullptr;

  if ([self asyncOperationPending]) {
    // Starting a synchronous operation while an asynchronous one is pending
    // could be trouble.
    return;
  }
  if (!synchronous && ![self wantsPromotion]) {
    // If operating synchronously, the call came from the installer, which
    // means that a system ticket is required.  Otherwise, only allow
    // promotion if it's wanted.
    return;
  }

  synchronousPromotion_ = synchronous;

  [self updateStatus:kAutoupdatePromoting version:nil error:nil];

  // TODO(mark): Remove when able!
  //
  // keystone_promote_preflight will copy the current brand information out to
  // the system level so all users can share the data as part of the ticket
  // promotion.
  //
  // It will also ensure that the Keystone system ticket store is in a usable
  // state for all users on the system.  Ideally, Keystone's installer or
  // another part of Keystone would handle this.  The underlying problem is
  // http://b/2285921, and it causes http://b/2289908, which this workaround
  // addresses.
  //
  // This is run synchronously, which isn't optimal, but
  // -[KSRegistration promoteWithParameters:authorization:] is currently
  // synchronous too, and this operation needs to happen before that one.
  //
  // TODO(mark): Make asynchronous.  That only makes sense if the promotion
  // operation itself is asynchronous too.  http://b/2290009.  Hopefully,
  // the Keystone promotion code will just be changed to do what preflight
  // now does, and then the preflight script can be removed instead.
  // However, preflight operation (and promotion) should only be asynchronous
  // if the synchronous parameter is NO.
  NSString* preflightPath =
      [base::mac::FrameworkBundle()
          pathForResource:@"keystone_promote_preflight"
                   ofType:@"sh"];
  const char* preflightPathC = [preflightPath fileSystemRepresentation];

  // This is typically a once per machine operation, so it is not worth caching
  // the type of brand file (user vs system). Figure it out here:
  version_info::Channel channel = chrome::GetChannelByName(channel_);
  NSString* userBrandFile = UserBrandFilePath(channel);
  NSString* systemBrandFile = SystemBrandFilePath(channel);
  const char* arguments[] = {NULL, NULL, NULL};
  BOOL userBrand = NO;
  if ([brandFile_ isEqualToString:userBrandFile]) {
    // Running with user level brand file, promote to the system level.
    userBrand = YES;
    arguments[0] = userBrandFile.UTF8String;
    arguments[1] = systemBrandFile.UTF8String;
  }

  int exit_status;
  OSStatus status = base::mac::ExecuteWithPrivilegesAndWait(
      authorization,
      preflightPathC,
      kAuthorizationFlagDefaults,
      arguments,
      NULL,  // pipe
      &exit_status);
  if (status != errAuthorizationSuccess) {
    // It's possible to get an OS-provided error string for this return code
    // using base::mac::DescriptionFromOSStatus, but most of those strings are
    // not useful/actionable for users, so we stick with the error code instead.
    NSString* errorMessage =
        l10n_util::GetNSStringFWithFixup(IDS_PROMOTE_PREFLIGHT_LAUNCH_ERROR,
                                         base::IntToString16(status));
    [self updateStatus:kAutoupdatePromoteFailed
               version:nil
                 error:errorMessage];
    return;
  }
  if (exit_status != 0) {
    NSString* errorMessage =
        l10n_util::GetNSStringFWithFixup(IDS_PROMOTE_PREFLIGHT_SCRIPT_ERROR,
                                         base::IntToString16(status));
    [self updateStatus:kAutoupdatePromoteFailed
               version:nil
                 error:errorMessage];
    return;
  }

  // Hang on to the AuthorizationRef so that it can be used once promotion is
  // complete.  Do this before asking Keystone to promote the ticket, because
  // -promotionComplete: may be called from inside the Keystone promotion
  // call.
  authorization_.swap(authorization);

  NSDictionary* parameters = [self keystoneParameters];

  // If the brand file is user level, update parameters to point to the new
  // system level file during promotion.
  if (userBrand) {
    NSMutableDictionary* tempParameters =
        [[parameters mutableCopy] autorelease];
    tempParameters[ksr::KSRegistrationBrandPathKey] = systemBrandFile;
    brandFile_.reset(systemBrandFile, base::scoped_policy::RETAIN);
    parameters = tempParameters;
  }

  if (![registration_ promoteWithParameters:parameters
                              authorization:authorization_]) {
    // TODO: If Keystone ever makes a variant of this API with a withError:
    // parameter, include the error message here in the call to updateStatus:.
    [self updateStatus:kAutoupdatePromoteFailed version:nil error:nil];
    authorization_.reset();
    return;
  }

  // Upon completion, ksr::KSRegistrationPromotionDidCompleteNotification will
  // be posted, and -promotionComplete: will be called.

  // If synchronous, see to it that this happens immediately. Give it a
  // 10-second deadline.
  if (synchronous) {
    CFRunLoopRunInMode(kCFRunLoopDefaultMode, 10, false);
  }
}

- (void)promotionComplete:(NSNotification*)notification {
  NSDictionary* userInfo = [notification userInfo];
  NSNumber* status = base::mac::ObjCCast<NSNumber>(
      [userInfo objectForKey:ksr::KSRegistrationStatusKey]);

  if ([status boolValue]) {
    if (synchronousPromotion_) {
      // Short-circuit: if performing a synchronous promotion, the promotion
      // came from the installer, which already set the permissions properly.
      // Rather than run a duplicate permission-changing operation, jump
      // straight to "done."
      [self changePermissionsForPromotionComplete];
    } else {
      [self changePermissionsForPromotionAsync];
    }
  } else {
    authorization_.reset();
    [self updateStatus:kAutoupdatePromoteFailed version:nil error:nil];
  }

  if (synchronousPromotion_) {
    // The run loop doesn't need to wait for this any longer.
    CFRunLoopRef runLoop = CFRunLoopGetCurrent();
    CFRunLoopStop(runLoop);
    CFRunLoopWakeUp(runLoop);
  }
}

- (void)changePermissionsForPromotionAsync {
  // NSBundle is not documented as being thread-safe.  Do NSBundle operations
  // on the main thread before jumping over to a WorkerPool-managed
  // thread to run the tool.
  DCHECK([NSThread isMainThread]);

  SEL selector = @selector(changePermissionsForPromotionWithTool:);
  NSString* toolPath =
      [base::mac::FrameworkBundle()
          pathForResource:@"keystone_promote_postflight"
                   ofType:@"sh"];

  PerformBridge::PostPerform(self, selector, toolPath);
}

- (void)changePermissionsForPromotionWithTool:(NSString*)toolPath {
  const char* toolPathC = [toolPath fileSystemRepresentation];

  const char* appPathC = [appPath_ fileSystemRepresentation];
  const char* arguments[] = {appPathC, NULL};

  int exit_status;
  OSStatus status = base::mac::ExecuteWithPrivilegesAndWait(
      authorization_,
      toolPathC,
      kAuthorizationFlagDefaults,
      arguments,
      NULL,  // pipe
      &exit_status);
  if (status != errAuthorizationSuccess) {
    OSSTATUS_LOG(ERROR, status)
        << "AuthorizationExecuteWithPrivileges postflight";
  } else if (exit_status != 0) {
    LOG(ERROR) << "keystone_promote_postflight status " << exit_status;
  }

  SEL selector = @selector(changePermissionsForPromotionComplete);
  [self performSelectorOnMainThread:selector
                         withObject:nil
                      waitUntilDone:NO];
}

- (void)changePermissionsForPromotionComplete {
  authorization_.reset();

  [self updateStatus:kAutoupdatePromoted version:nil error:nil];
}

- (void)setAppPath:(NSString*)appPath {
  if (appPath != appPath_) {
    appPath_.reset([appPath copy]);
  }
}

- (BOOL)wantsFullInstaller {
  // It's difficult to check the tag prior to Keystone registration, and
  // performing registration replaces the tag. keystone_install.sh
  // communicates a need for a full installer with Chrome in this file,
  // .want_full_installer.
  NSString* wantFullInstallerPath =
      [appPath_ stringByAppendingPathComponent:@".want_full_installer"];
  NSString* wantFullInstallerContents =
      [NSString stringWithContentsOfFile:wantFullInstallerPath
                                encoding:NSUTF8StringEncoding
                                   error:NULL];
  if (!wantFullInstallerContents) {
    return NO;
  }

  NSString* wantFullInstallerVersion =
      [wantFullInstallerContents stringByTrimmingCharactersInSet:
          [NSCharacterSet newlineCharacterSet]];
  return [wantFullInstallerVersion isEqualToString:version_];
}

- (NSString*)tagSuffix {
  // Tag suffix components are not entirely arbitrary: all possible tag keys
  // must be present in the application's Info.plist, there must be
  // server-side agreement on the processing and meaning of tag suffix
  // components, and other code that manipulates tag values (such as the
  // Keystone update installation script) must be tag suffix-aware. To reduce
  // the number of tag suffix combinations that need to be listed in
  // Info.plist, tag suffix components should only be appended to the tag
  // suffix in ASCII sort order.
  NSString* tagSuffix = @"";
  if ([self wantsFullInstaller]) {
    tagSuffix = [tagSuffix stringByAppendingString:@"-full"];
  }
  return tagSuffix;
}


- (void)updateProfileCountsWithNumProfiles:(uint32_t)profiles
                       numSignedInProfiles:(uint32_t)signedInProfiles {
  numProfiles_ = profiles;
  numSignedInProfiles_ = signedInProfiles;
  [self setRegistrationActive];
}

@end  // @implementation KeystoneGlue

namespace {

std::string BrandCodeInternal() {
  KeystoneGlue* keystone_glue = [KeystoneGlue defaultKeystoneGlue];
  NSString* brand_path = [keystone_glue brandFilePath];

  if (![brand_path length])
    return std::string();

  NSDictionary* dict =
      [NSDictionary dictionaryWithContentsOfFile:brand_path];
  NSString* brand_code =
      base::mac::ObjCCast<NSString>([dict objectForKey:kBrandKey]);
  if (brand_code)
    return base::SysNSStringToUTF8(brand_code);

  return std::string();
}

}  // namespace

namespace keystone_glue {

std::string BrandCode() {
  // |s_brand_code| is leaked.
  static std::string* s_brand_code = new std::string(BrandCodeInternal());
  return *s_brand_code;
}

bool KeystoneEnabled() {
  return [KeystoneGlue defaultKeystoneGlue] != nil;
}

base::string16 CurrentlyInstalledVersion() {
  KeystoneGlue* keystoneGlue = [KeystoneGlue defaultKeystoneGlue];
  NSString* version = [keystoneGlue currentlyInstalledVersion];
  return base::SysNSStringToUTF16(version);
}

}  // namespace keystone_glue
