summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormark@chromium.org <mark@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-13 20:14:52 +0000
committermark@chromium.org <mark@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-13 20:14:52 +0000
commit4eeb018cc6f4b3a1d6715facaa3a3c54a22b4951 (patch)
tree6d37b0fdf811639f8657d74280609bf85d75ac10
parentf5c172084ebace23f2c639a4d08cb13a98a0d336 (diff)
downloadchromium_src-4eeb018cc6f4b3a1d6715facaa3a3c54a22b4951.zip
chromium_src-4eeb018cc6f4b3a1d6715facaa3a3c54a22b4951.tar.gz
chromium_src-4eeb018cc6f4b3a1d6715facaa3a3c54a22b4951.tar.bz2
Put the Keystone installation script and codesign driver script next to the
.app bundle, and make them available to the packaging system. This ensures that the packager uses the correct logic to sign a bundle, and places the correct Keystone auto-update script into the package. Because things may move around in the bundle and the proper codesign invocation may change between versions, it is correct to store the codesign logic with the package being signed. Similarly, because the correct way to perform an client-side auto-update may change between versions, it is correct to store the auto-update script with the code. BUG=14610 (in support of unbreaking auto-update) TEST=none Review URL: http://codereview.chromium.org/261048 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@28871 0039d316-1c4b-4281-b951-d872f2087c98
-rwxr-xr-xchrome/chrome.gyp43
-rw-r--r--chrome/tools/build/mac/FILES-official1
-rwxr-xr-xchrome/tools/build/mac/keystone_install.sh97
-rwxr-xr-xchrome/tools/build/mac/keystone_install_test.sh100
-rwxr-xr-xchrome/tools/build/mac/make_sign_sh28
-rw-r--r--chrome/tools/build/mac/sign.sh.in45
6 files changed, 314 insertions, 0 deletions
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 0aad98c..9afbdcf 100755
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -3393,6 +3393,15 @@
],
}],
['OS=="mac"', {
+ 'variables': {
+ 'mac_packaging_dir':
+ '<(PRODUCT_DIR)/<(mac_product_name) Packaging',
+ # <(PRODUCT_DIR) expands to $(BUILT_PRODUCTS_DIR), which doesn't
+ # work properly in a shell script, where ${BUILT_PRODUCTS_DIR} is
+ # needed.
+ 'mac_packaging_sh_dir':
+ '${BUILT_PRODUCTS_DIR}/<(mac_product_name) Packaging',
+ },
# 'branding' is a variable defined in common.gypi
# (e.g. "Chromium", "Chrome")
'conditions': [
@@ -3430,8 +3439,42 @@
'destination': '<(PRODUCT_DIR)/<(mac_product_name).app/Contents/Frameworks/',
'files': ['../third_party/googlemac/Releases/Keystone/KeystoneRegistration.framework'],
},
+ {
+ # Put keystone_install.sh where the packaging system will
+ # find it. The packager will copy this script to the
+ # correct location on the disk image.
+ 'destination': '<(mac_packaging_dir)',
+ 'files': [
+ 'tools/build/mac/keystone_install.sh',
+ ],
+ },
],
}], # mac_keystone
+ ['buildtype=="Official"', {
+ 'actions': [
+ {
+ # Create sign.sh, the script that the packaging system will
+ # use to sign the .app bundle.
+ 'action_name': 'Make sign.sh',
+ 'variables': {
+ 'make_sign_sh_path': 'tools/build/mac/make_sign_sh',
+ 'sign_sh_in_path': 'tools/build/mac/make_sign_sh',
+ },
+ 'inputs': [
+ '<(make_sign_sh_path)',
+ '<(sign_sh_in_path)',
+ ],
+ 'outputs': [
+ '<(mac_packaging_dir)/sign.sh',
+ ],
+ 'action': [
+ '<(make_sign_sh_path)',
+ '<(mac_packaging_sh_dir)',
+ '<(mac_product_name)',
+ ],
+ },
+ ],
+ }], # buildtype=="Official"
],
'product_name': '<(mac_product_name)',
'xcode_settings': {
diff --git a/chrome/tools/build/mac/FILES-official b/chrome/tools/build/mac/FILES-official
index fd80032..2d3802c6 100644
--- a/chrome/tools/build/mac/FILES-official
+++ b/chrome/tools/build/mac/FILES-official
@@ -1 +1,2 @@
Google Chrome.app
+Google Chrome Packaging
diff --git a/chrome/tools/build/mac/keystone_install.sh b/chrome/tools/build/mac/keystone_install.sh
new file mode 100755
index 0000000..173875a
--- /dev/null
+++ b/chrome/tools/build/mac/keystone_install.sh
@@ -0,0 +1,97 @@
+#!/bin/bash
+
+# Copyright (c) 2009 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.
+
+# Called by the Keystone system to update the installed application with a new
+# version from a disk image.
+
+# Return values:
+# 0 Happiness
+# 1 Unknown failure
+# 2 Basic sanity check destination failure (e.g. ticket points to nothing)
+# 3 Cannot get version of currently installed Chrome
+# 4 No permission to write in destination directory
+# 5 rsync failed
+# 6 Cannot get version or update URL of newly installed Chrome
+# 7 Post-install Chrome has same version as pre-install Chrome
+# 8 ksadmin failure
+# 10 Basic sanity check source failure (e.g. no app on disk image)
+
+set -e
+
+# The argument should be the disk image path. Make sure it exists.
+if [ $# -lt 1 ] || [ ! -d "${1}" ]; then
+ exit 10
+fi
+
+# Who we are.
+APP_NAME="Google Chrome.app"
+SRC="${1}/${APP_NAME}"
+
+# Sanity, make sure that there's something to copy from.
+if [ ! -d "${SRC}" ]; then
+ exit 10
+fi
+
+# Figure out where we're going.
+PRODUCT_ID=$(defaults read "${SRC}/Contents/Info" KSProductID || exit 3)
+DEST=$(ksadmin -pP "${PRODUCT_ID}" | grep xc= | sed -E 's/.+path=(.+)>$/\1/g')
+
+# More sanity checking.
+if [ -z "${SRC}" ] || [ -z "${DEST}" ] || [ ! -d $(dirname "${DEST}") ]; then
+ exit 2
+fi
+
+# Read old version to help confirm install happiness
+OLD_VERSION=$(defaults read "${DEST}/Contents/Info" KSVersion || exit 3)
+
+# Make sure we have permission to write the destination
+DEST_DIRECTORY=$(dirname "${DEST}")
+if [ ! -w "${DEST_DIRECTORY}" ]; then
+ exit 4
+fi
+
+# This usage will preserve any changes the user made to the application name.
+# TODO(jrg): this may choke a running Chrome.app; be smarter.
+# Note: If the rsync fails we do not update the ticket version.
+rsync -a --delete "${SRC}/" "${DEST}/" || exit 5
+
+# Read the new values (e.g. version)
+VERSION=$(defaults read "${DEST}/Contents/Info" KSVersion || exit 6)
+URL=$(defaults read "${DEST}/Contents/Info" KSUpdateURL || exit 6)
+# The channel ID is optional. Suppress stderr to prevent Keystone from seeing
+# possible error output.
+CHANNEL_ID=$(defaults read "${DEST}/Contents/Info" KSChannelID 2>/dev/null || \
+ true)
+
+# Compare old and new versions. If they are equal we failed somewhere.
+if [ "${OLD_VERSION}" = "${VERSION}" ]; then
+ exit 7
+fi
+
+# Notify LaunchServices.
+/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister "${DEST}"
+
+# Notify Keystone. Older versions of Keystone don't recognize --tag. If the
+# command with --tag fails, retry without it. In that case, Chrome will set
+# the tag when it runs.
+# TODO: The version of Keystone picking up --tag will also include support for
+# --ksdamin-version. At that point, we can check to see if ksadmin honors the
+# version check; if not, no --tag, if yes, do a case...esac on the version
+# patterns for any support checks we need.
+ksadmin --register \
+ -P "${PRODUCT_ID}" \
+ --version "${VERSION}" \
+ --xcpath "${DEST}" \
+ --url "${URL}" \
+ --tag "${CHANNEL_ID}" || \
+ ksadmin --register \
+ -P "${PRODUCT_ID}" \
+ --version "${VERSION}" \
+ --xcpath "${DEST}" \
+ --url "${URL}" || exit 8
+
+# Great success!
+exit 0
diff --git a/chrome/tools/build/mac/keystone_install_test.sh b/chrome/tools/build/mac/keystone_install_test.sh
new file mode 100755
index 0000000..b72a9d4
--- /dev/null
+++ b/chrome/tools/build/mac/keystone_install_test.sh
@@ -0,0 +1,100 @@
+#!/bin/bash
+
+# Copyright (c) 2009 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.
+
+# Test of the Mac Chrome installer.
+
+
+# Where I am
+DIR=$(dirname "${0}")
+
+# My installer to test
+INSTALLER="${DIR}"/keystone_install.sh
+if [ ! -f "${INSTALLER}" ]; then
+ echo "Can't find scripts." >& 2
+ exit 1
+fi
+
+# What I test
+APPNAME="Google Chrome.app"
+
+# Temp directory to be used as the disk image (source)
+TEMPDIR=$(mktemp -d ${TMPDIR}/$(basename ${0}).XXXXXX)
+PATH=$PATH:"${TEMPDIR}"
+
+# Clean up the temp directory
+function cleanup_tempdir() {
+ chmod u+w "${TEMPDIR}"
+ rm -rf "${TEMPDIR}"
+}
+
+# Run the installer and make sure it fails.
+# If it succeeds, we fail.
+# Arg0: string to print
+function fail_installer() {
+ echo $1
+ "${INSTALLER}" "${TEMPDIR}" >/dev/null 2>&1
+ RETURN=$?
+ if [ $RETURN -eq 0 ]; then
+ echo "Did not fail (which is a failure)" >& 2
+ cleanup_tempdir
+ exit 1
+ else
+ echo "Returns $RETURN"
+ fi
+}
+
+# Make sure installer works!
+# Arg0: string to print
+function pass_installer() {
+ echo $1
+ "${INSTALLER}" "${TEMPDIR}" >/dev/null 2>&1
+ RETURN=$?
+ if [ $RETURN -ne 0 ]; then
+ echo "FAILED; returned $RETURN but should have worked" >& 2
+ cleanup_tempdir
+ exit 1
+ else
+ echo "worked"
+ fi
+}
+
+# Most of the setup for an install source and dest
+function make_basic_src_and_dest() {
+ chmod ugo+w "${TEMPDIR}"
+ rm -rf "${TEMPDIR}"
+ mkdir -p "${TEMPDIR}/${APPNAME}/Contents"
+ defaults write "${TEMPDIR}/${APPNAME}/Contents/Info" \
+ KSProductID "com.google.Chrome"
+ defaults write "${TEMPDIR}/${APPNAME}/Contents/Info" KSVersion 1
+ DEST="${TEMPDIR}"/Dest.app
+ mkdir -p "${DEST}"/Contents
+ defaults write "${DEST}/Contents/Info" KSVersion 0
+ cat >"${TEMPDIR}"/ksadmin <<EOF
+#!/bin/sh
+echo "echo xc=<blah path=$DEST>"
+exit 0
+EOF
+ chmod u+x "${TEMPDIR}"/ksadmin
+}
+
+fail_installer "No source anything"
+
+mkdir "${TEMPDIR}"/"${APPNAME}"
+fail_installer "No source bundle"
+
+make_basic_src_and_dest
+chmod ugo-w "${TEMPDIR}"
+fail_installer "Writable dest directory"
+
+make_basic_src_and_dest
+fail_installer "Was no KSUpdateURL in dest after copy"
+
+make_basic_src_and_dest
+defaults write "${TEMPDIR}/${APPNAME}/Contents/Info" \
+ KSUpdateURL "http://foo.bar"
+pass_installer "ALL"
+
+cleanup_tempdir
diff --git a/chrome/tools/build/mac/make_sign_sh b/chrome/tools/build/mac/make_sign_sh
new file mode 100755
index 0000000..115882c
--- /dev/null
+++ b/chrome/tools/build/mac/make_sign_sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+# Copyright (c) 2009 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.
+
+# This script creates sign.sh, the script that will be used to sign the
+# application bundle and inner bundles. sign.sh is placed in the Packaging
+# directory next to the .app bundle. The packaging system is expected to run
+# sign.sh to sign everything.
+
+set -e
+
+if [ $# -ne 2 ] ; then
+ echo "usage: ${0} PACKAGING_DIR MAC_PRODUCT_NAME" >& 2
+ exit 1
+fi
+
+PACKAGING_DIR="${1}"
+MAC_PRODUCT_NAME="${2}"
+SIGN_SH_IN_FILE="$(dirname "${0}")/sign.sh.in"
+SIGN_SH_FILE="${PACKAGING_DIR}/sign.sh"
+
+mkdir -p "${PACKAGING_DIR}"
+sed -e "s/@MAC_PRODUCT_NAME@/${MAC_PRODUCT_NAME}/g" \
+ < "${SIGN_SH_IN_FILE}" \
+ > "${SIGN_SH_FILE}"
+chmod a+rx "${SIGN_SH_FILE}"
diff --git a/chrome/tools/build/mac/sign.sh.in b/chrome/tools/build/mac/sign.sh.in
new file mode 100644
index 0000000..41c8b58
--- /dev/null
+++ b/chrome/tools/build/mac/sign.sh.in
@@ -0,0 +1,45 @@
+#!/bin/sh
+
+# Copyright (c) 2009 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.
+
+# Using codesign, sign the application. Inner components are signed as needed,
+# then the outermost bundle is signed, and everything is verified.
+
+set -e
+
+if [ $# -ne 3 ] ; then
+ echo "usage: ${0} APP_PATH CODESIGN_KEYCHAIN CODESIGN_ID" >& 2
+ exit 1
+fi
+
+APP_PATH="${1}"
+CODESIGN_KEYCHAIN="${2}"
+CODESIGN_ID="${3}"
+
+# An .app bundle to be signed can be signed directly. Signging a framework
+# bundle requires that each version within be signed individually.
+# http://developer.apple.com/mac/library/technotes/tn2007/tn2206.html#TNTAG13
+
+BROWSER_APP="${APP_PATH}"
+FRAMEWORK="${BROWSER_APP}/Contents/Frameworks/@MAC_PRODUCT_NAME@ Framework.framework/Versions/A"
+HELPER_APP="${BROWSER_APP}/Contents/Resources/@MAC_PRODUCT_NAME@ Helper.app"
+
+echo "${0}: signing..."
+
+# Sign the outer .app last so that its seal includes the signed inner
+# components.
+
+codesign -s "${CODESIGN_ID}" --keychain "${CODESIGN_KEYCHAIN}" "${FRAMEWORK}"
+codesign -s "${CODESIGN_ID}" --keychain "${CODESIGN_KEYCHAIN}" "${HELPER_APP}"
+codesign -s "${CODESIGN_ID}" --keychain "${CODESIGN_KEYCHAIN}" "${BROWSER_APP}"
+
+# Verify everything to ensure that signing the outer bundle didn't break an
+# inner bundle.
+
+echo "${0}: verifying..."
+
+codesign -v "${FRAMEWORK}"
+codesign -v "${HELPER_APP}"
+codesign -v "${BROWSER_APP}"