summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authorthomasvl@chromium.org <thomasvl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-27 12:53:12 +0000
committerthomasvl@chromium.org <thomasvl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-27 12:53:12 +0000
commitfc854db57337e41cd7b18cf5965b5a9b111d4416 (patch)
treef3ef2121ee34e7b4a423359ef26aaa3e6032d412 /chrome/browser
parent27d81c2f3f2aeec7f418fdd4341f4f9bd82292e8 (diff)
downloadchromium_src-fc854db57337e41cd7b18cf5965b5a9b111d4416.zip
chromium_src-fc854db57337e41cd7b18cf5965b5a9b111d4416.tar.gz
chromium_src-fc854db57337e41cd7b18cf5965b5a9b111d4416.tar.bz2
[Mac] Brand code support on the Mac:
- During keystone registration pull in the brand file at user to system level. - Clean up old user level brand files after moving to a system ticket. - During keystone ticket promotion, use the pref flight script to copy the brand information out to the system level. - When updating check to see if the user had manually updated the app and gotten a new brand code, if so, migrate that code into the right location. BUG=39131 TEST=email from tvl to QA with details. Review URL: http://codereview.chromium.org/1687012 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@45687 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/cocoa/keystone_glue.h11
-rw-r--r--chrome/browser/cocoa/keystone_glue.mm157
-rwxr-xr-xchrome/browser/cocoa/keystone_promote_preflight.sh42
3 files changed, 202 insertions, 8 deletions
diff --git a/chrome/browser/cocoa/keystone_glue.h b/chrome/browser/cocoa/keystone_glue.h
index 81d74a3..6ae4c1f 100644
--- a/chrome/browser/cocoa/keystone_glue.h
+++ b/chrome/browser/cocoa/keystone_glue.h
@@ -43,6 +43,16 @@ extern const NSString* const kAutoupdateStatusNotification;
extern const NSString* const kAutoupdateStatusStatus;
extern const NSString* const kAutoupdateStatusVersion;
+namespace {
+ enum BrandFileType {
+ kBrandFileTypeNotDetermined = 0,
+ kBrandFileTypeNone,
+ kBrandFileTypeUser,
+ kBrandFileTypeSystem,
+ };
+
+} // namespace
+
// KeystoneGlue is an adapter around the KSRegistration class, allowing it to
// be used without linking directly against its containing KeystoneRegistration
// framework. This is used in an environment where most builds (such as
@@ -66,6 +76,7 @@ extern const NSString* const kAutoupdateStatusVersion;
NSString* url_;
NSString* version_;
NSString* channel_; // Logically: Dev, Beta, or Stable.
+ BrandFileType brandFileType_;
// And the Keystone registration itself, with the active timer
KSRegistration* registration_; // strong
diff --git a/chrome/browser/cocoa/keystone_glue.mm b/chrome/browser/cocoa/keystone_glue.mm
index 468eca90..5cb125a 100644
--- a/chrome/browser/cocoa/keystone_glue.mm
+++ b/chrome/browser/cocoa/keystone_glue.mm
@@ -40,6 +40,8 @@ NSString* KSRegistrationPreserveTrustedTesterTokenKey = @"PreserveTTT";
NSString* KSRegistrationTagKey = @"Tag";
NSString* KSRegistrationTagPathKey = @"TagPath";
NSString* KSRegistrationTagKeyKey = @"TagKey";
+NSString* KSRegistrationBrandPathKey = @"BrandPath";
+NSString* KSRegistrationBrandKeyKey = @"BrandKey";
NSString *KSRegistrationDidCompleteNotification =
@"KSRegistrationDidCompleteNotification";
@@ -59,6 +61,30 @@ NSString *KSUpdateCheckSuccessfullyInstalledKey = @"SuccessfullyInstalled";
NSString *KSRegistrationRemoveExistingTag = @"";
#define KSRegistrationPreserveExistingTag nil
+// Constants for the brand file (uses an external file so it can survive updates
+// to Chrome.
+
+#if defined(GOOGLE_CHROME_BUILD)
+#define kBrandFileName @"Google Chrome Brand.plist";
+#elif defined(CHROMIUM_BUILD)
+#define kBrandFileName @"Chromium 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* kBrandUserFile = @"~/Library/Google/" kBrandFileName;
+NSString* kBrandSystemFile = @"/Library/Google/" kBrandFileName;
+
+NSString* UserBrandFilePath() {
+ return [kBrandUserFile stringByStandardizingPath];
+}
+NSString* SystemBrandFilePath() {
+ return [kBrandSystemFile stringByStandardizingPath];
+}
+
} // namespace
@interface KSRegistration : NSObject
@@ -144,6 +170,9 @@ NSString *KSRegistrationRemoveExistingTag = @"";
- (void)changePermissionsForPromotionWithTool:(NSString*)toolPath;
- (void)changePermissionsForPromotionComplete;
+// Returns the brand file path to use for Keystone.
+- (NSString*)brandFilePath;
+
@end // @interface KeystoneGlue(Private)
const NSString* const kAutoupdateStatusNotification =
@@ -154,6 +183,7 @@ const NSString* const kAutoupdateStatusVersion = @"version";
namespace {
const NSString* const kChannelKey = @"KSChannelID";
+const NSString* const kBrandKey = @"KSBrandID";
} // namespace
@@ -258,6 +288,88 @@ const NSString* const kChannelKey = @"KSChannelID";
channel_ = [channel retain];
}
+- (NSString*)brandFilePath {
+ DCHECK(version_ != nil) << "-loadParameters must be called first";
+
+ if (brandFileType_ == kBrandFileTypeNotDetermined) {
+
+ // Default to none.
+ brandFileType_ = kBrandFileTypeNone;
+
+ // Having a channel means Dev/Beta, so there is no brand code to go with
+ // those.
+ if ([channel_ length] == 0) {
+
+ NSString* userBrandFile = UserBrandFilePath();
+ NSString* systemBrandFile = SystemBrandFilePath();
+
+ NSFileManager* fm = [NSFileManager defaultManager];
+
+ // If there is a system brand file, use it.
+ if ([fm fileExistsAtPath:systemBrandFile]) {
+ // System
+
+ // Use the system file that is there.
+ brandFileType_ = kBrandFileTypeSystem;
+
+ // Clean up any old user level file.
+ if ([fm fileExistsAtPath:userBrandFile]) {
+ [fm removeItemAtPath:userBrandFile error:NULL];
+ }
+
+ } else {
+ // User
+
+ NSDictionary* infoDictionary = [self infoDictionary];
+ NSString* appBundleBrandID = [infoDictionary objectForKey:kBrandKey];
+
+ NSString* storedBrandID = nil;
+ if ([fm fileExistsAtPath:userBrandFile]) {
+ NSDictionary* storedBrandDict =
+ [NSDictionary dictionaryWithContentsOfFile:userBrandFile];
+ storedBrandID = [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 ([storedBrandDict writeToFile:userBrandFile atomically:YES]) {
+ brandFileType_ = kBrandFileTypeUser;
+ }
+ } else if (storedBrandID) {
+ // Had stored brand, use it.
+ brandFileType_ = kBrandFileTypeUser;
+ }
+ }
+ }
+
+ }
+
+ NSString* result = nil;
+ switch (brandFileType_) {
+ case kBrandFileTypeUser:
+ result = UserBrandFilePath();
+ break;
+
+ case kBrandFileTypeSystem:
+ result = SystemBrandFilePath();
+ break;
+
+ case kBrandFileTypeNotDetermined:
+ NOTIMPLEMENTED();
+ // Fall through
+ case kBrandFileTypeNone:
+ // Clear the value.
+ result = @"";
+ break;
+
+ }
+ return result;
+}
+
- (BOOL)loadKeystoneRegistration {
if (!productID_ || !appPath_ || !url_ || !version_)
return NO;
@@ -292,6 +404,15 @@ const NSString* const kChannelKey = @"KSChannelID";
NSNumber* preserveTTToken = [NSNumber numberWithBool:YES];
NSString* tagPath = [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 = @"";
+ }
+
return [NSDictionary dictionaryWithObjectsAndKeys:
version_, KSRegistrationVersionKey,
xcType, KSRegistrationExistenceCheckerTypeKey,
@@ -301,6 +422,8 @@ const NSString* const kChannelKey = @"KSChannelID";
channel_, KSRegistrationTagKey,
tagPath, KSRegistrationTagPathKey,
kChannelKey, KSRegistrationTagKeyKey,
+ brandPath, KSRegistrationBrandPathKey,
+ brandKey, KSRegistrationBrandKeyKey,
nil];
}
@@ -632,11 +755,15 @@ const NSString* const kChannelKey = @"KSChannelID";
// TODO(mark): Remove when able!
//
- // keystone_promote_preflight is hopefully temporary. It's here to 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.
+ // 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
@@ -650,7 +777,14 @@ const NSString* const kChannelKey = @"KSChannelID";
[mac_util::MainAppBundle() pathForResource:@"keystone_promote_preflight"
ofType:@"sh"];
const char* preflightPathC = [preflightPath fileSystemRepresentation];
- const char* arguments[] = {NULL};
+ const char* userBrandFile = NULL;
+ const char* systemBrandFile = NULL;
+ if (brandFileType_ == kBrandFileTypeUser) {
+ // Running with user level brand file, promote to the system level.
+ userBrandFile = [UserBrandFilePath() fileSystemRepresentation];
+ systemBrandFile = [SystemBrandFilePath() fileSystemRepresentation];
+ }
+ const char* arguments[] = {userBrandFile, systemBrandFile, NULL};
int exit_status;
status = authorization_util::ExecuteWithPrivilegesAndWait(
@@ -678,6 +812,17 @@ const NSString* const kChannelKey = @"KSChannelID";
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 (brandFileType_ == kBrandFileTypeUser) {
+ NSMutableDictionary* temp_parameters =
+ [[parameters mutableCopy] autorelease];
+ [temp_parameters setObject:SystemBrandFilePath()
+ forKey:KSRegistrationBrandPathKey];
+ parameters = temp_parameters;
+ }
+
if (![registration_ promoteWithParameters:parameters
authorization:authorization_]) {
[self updateStatus:kAutoupdatePromoteFailed version:nil];
diff --git a/chrome/browser/cocoa/keystone_promote_preflight.sh b/chrome/browser/cocoa/keystone_promote_preflight.sh
index d1c4c59..4bf31e8 100755
--- a/chrome/browser/cocoa/keystone_promote_preflight.sh
+++ b/chrome/browser/cocoa/keystone_promote_preflight.sh
@@ -8,6 +8,10 @@
# environment for Keystone installation. Ultimately, these features should be
# integrated directly into the Keystone installation.
#
+# If the two branding paths are given, then the branding information is also
+# copied and the permissions on the system branding file are set to be owned by
+# root, but readable by anyone.
+#
# Note that this script will be invoked with the real user ID set to the
# user's ID, but the effective user ID set to 0 (root). bash -p is used on
# the first line to prevent bash from setting the effective user ID to the
@@ -25,11 +29,45 @@ export PATH="/usr/bin:/usr/sbin:/bin:/sbin"
# chrome/browser/cocoa/authorization_util.h.
echo "${$}"
-if [ ${#} -ne 0 ] ; then
- echo "usage: ${0}" >& 2
+if [ ${#} -ne 0 ] && [ ${#} -ne 2 ] ; then
+ echo "usage: ${0} [USER_BRAND SYSTEM_BRAND]" >& 2
exit 2
fi
+if [ ${#} -eq 2 ] ; then
+ USER_BRAND="${1}"
+ SYSTEM_BRAND="${2}"
+
+ # Make sure that USER_BRAND is an absolute path and that it exists.
+ if [ -z "${USER_BRAND}" ] || \
+ [ "${USER_BRAND:0:1}" != "/" ] || \
+ [ ! -f "${USER_BRAND}" ] ; then
+ echo "${0}: must provide an absolute path naming an existing user file" >& 2
+ exit 3
+ fi
+
+ # Make sure that SYSTEM_BRAND is an absolute path.
+ if [ -z "${SYSTEM_BRAND}" ] || [ "${SYSTEM_BRAND:0:1}" != "/" ] ; then
+ echo "${0}: must provide an absolute path naming a system file" >& 2
+ exit 4
+ fi
+
+ # Make sure the directory for the system brand file exists.
+ SYSTEM_BRAND_DIR=$(dirname "${SYSTEM_BRAND}")
+ if [ ! -e "${SYSTEM_BRAND_DIR}" ] ; then
+ mkdir -p "${SYSTEM_BRAND_DIR}"
+ # Permissions on this directory will be fixed up at the end of this script.
+ fi
+
+ # Copy the brand file
+ cp "${USER_BRAND}" "${SYSTEM_BRAND}" >& /dev/null
+
+ # Ensure the right ownership and permissions
+ chown "root:wheel" "${SYSTEM_BRAND}" >& /dev/null
+ chmod "a+r,u+w,go-w" "${SYSTEM_BRAND}" >& /dev/null
+
+fi
+
OWNER_GROUP="root:admin"
CHMOD_MODE="a+rX,u+w,go-w"