Chromium Code Reviews| Index: chrome/installer/mac/keystone_install.sh |
| diff --git a/chrome/installer/mac/keystone_install.sh b/chrome/installer/mac/keystone_install.sh |
| index 1dbb6ed5945834bed577829fdb2455b7f4640cf5..d1dd31a9f3182cd93bfec7c0c96ec6186e449796 100755 |
| --- a/chrome/installer/mac/keystone_install.sh |
| +++ b/chrome/installer/mac/keystone_install.sh |
| @@ -29,13 +29,11 @@ |
| # 9 Could not get the version, update URL, or channel after update |
| # 10 Updated application does not have the version number from the update |
| # 11 ksadmin failure |
| -# 12 dirpatcher failed for versioned directory |
| -# 13 dirpatcher failed for outer .app bundle |
| # |
| # The following exit codes are not used by this script, but can be used to |
|
Nico
2014/01/02 23:56:28
or are they?
|
| # convey special meaning to Keystone: |
| # 66 (unused) success, request reboot |
| -# 77 (unused) try installation again later |
| +# 77 try installation again later |
| set -eu |
| @@ -61,6 +59,8 @@ shopt -s nullglob |
| ME="$(basename "${0}")" |
| readonly ME |
| +readonly KS_CHANNEL_KEY="KSChannelID" |
| + |
| # Workaround for http://code.google.com/p/chromium/issues/detail?id=83180#c3 |
| # In bash 4.0, "declare VAR" no longer initializes VAR if not already set. |
| : ${GOOGLE_CHROME_UPDATER_DEBUG:=} |
| @@ -451,6 +451,14 @@ ksadmin_supports_versionpath_versionkey() { |
| # return value. |
| } |
| +has_32_bit_only_cpu() { |
| + local cpu_64_bit_capable="$(sysctl -n hw.cpu64bit_capable 2>/dev/null)" |
| + [[ -z "${cpu_64_bit_capable}" || "${cpu_64_bit_capable}" -eq 0 ]] |
| + |
| + # The return value of the comparison is used as this function's return |
| + # value. |
| +} |
| + |
| # Runs "defaults read" to obtain the value of a key in a property list. As |
| # with "defaults read", an absolute path to a plist is supplied, without the |
| # ".plist" extension. |
| @@ -484,6 +492,75 @@ infoplist_read() { |
| __CFPREFERENCES_AVOID_DAEMON=1 defaults read "${@}" |
| } |
| +mark_failed_patch_update() { |
| + local product_id="${1}" |
| + local want_full_installer_path="${2}" |
| + local old_ks_plist="${3}" |
| + local old_version_app="${4}" |
| + |
| + set +e |
| + |
| + note "marking failed patch update" |
| + |
| + # Chrome can't easily read its Keystone ticket prior to registration, and |
| + # when Chrome registers with Keystone, it obliterates old tag values in its |
| + # ticket. Therefore, an alternative mechanism is provided to signal to |
| + # Chrome that a full installer is desired. If the .want_full_installer file |
| + # is present and it contains Chrome's current version number, Chrome will |
| + # include "-full" in its tag when it registers with Keystone. This allows |
| + # "-full" to persist in the tag even after Chrome is relaunched, which on a |
| + # user ticket, triggers a re-registration. |
| + echo "${old_version_app}" > "${want_full_installer_path}" |
| + chmod 644 "${want_full_installer_path}" |
| + |
| + local old_ks_plist_path="${old_ks_plist}.plist" |
| + |
| + local channel |
| + channel="$(infoplist_read "${old_ks_plist}" "${KS_CHANNEL_KEY}" 2> /dev/null)" |
| + |
| + local tag="${channel}" |
| + local tag_key="${KS_CHANNEL_KEY}" |
| + if has_32_bit_only_cpu; then |
| + tag="${tag}-32bit" |
| + tag_key="${tag_key}-32bit" |
| + fi |
| + |
| + tag="${tag}-full" |
| + tag_key="${tag_key}-full" |
| + |
| + note "tag = ${tag}" |
| + note "tag_key = ${tag_key}" |
| + |
| + # Using ksadmin without --register only updates specified values in the |
| + # ticket, without changing existing values. |
|
Nico
2014/01/02 23:56:28
…without changing other existing…
|
| + local ksadmin_args=( |
| + --productid "${product_id}" |
| + ) |
| + |
| + if ksadmin_supports_tag; then |
| + ksadmin_args+=( |
| + --tag "${tag}" |
| + ) |
| + fi |
| + |
| + if ksadmin_supports_tagpath_tagkey; then |
| + ksadmin_args+=( |
| + --tag-path "${old_ks_plist_path}" |
| + --tag-key "${tag_key}" |
| + ) |
| + fi |
| + |
| + note "ksadmin_args = ${ksadmin_args[*]}" |
| + |
| + if ! ksadmin "${ksadmin_args[@]}"; then |
| + err "ksadmin failed" |
| + fi |
| + |
| + note "marked failed patch update" |
| + |
| + set -e |
| +} |
| + |
| usage() { |
| echo "usage: ${ME} update_dmg_mount_point" >& 2 |
| } |
| @@ -513,7 +590,6 @@ main() { |
| readonly KS_VERSION_KEY="KSVersion" |
| readonly KS_PRODUCT_KEY="KSProductID" |
| readonly KS_URL_KEY="KSUpdateURL" |
| - readonly KS_CHANNEL_KEY="KSChannelID" |
| readonly KS_BRAND_KEY="KSBrandID" |
| readonly QUARANTINE_ATTR="com.apple.quarantine" |
| @@ -740,6 +816,9 @@ main() { |
| fi |
| note "installed_app = ${installed_app}" |
| + local want_full_installer_path="${installed_app}/.want_full_installer" |
| + note "want_full_installer_path = ${want_full_installer_path}" |
| + |
| if [[ "${installed_app:0:1}" != "/" ]] || |
| ! [[ -d "${installed_app}" ]]; then |
| err "installed_app must be an absolute path to a directory" |
| @@ -902,7 +981,11 @@ main() { |
| "${patch_versioned_dir}" \ |
| "${versioned_dir_target}"; then |
| err "dirpatcher of versioned directory failed, status ${PIPESTATUS[0]}" |
| - exit 12 |
| + mark_failed_patch_update "${product_id}" \ |
| + "${want_full_installer_path}" \ |
| + "${old_ks_plist}" \ |
| + "${old_version_app}" |
| + exit 77 |
| fi |
| fi |
| @@ -956,7 +1039,11 @@ main() { |
| "${patch_app_dir}" \ |
| "${update_app}"; then |
| err "dirpatcher of app directory failed, status ${PIPESTATUS[0]}" |
| - exit 13 |
| + mark_failed_patch_update "${product_id}" \ |
| + "${want_full_installer_path}" \ |
| + "${old_ks_plist}" \ |
| + "${old_version_app}" |
| + exit 77 |
| fi |
| fi |
| @@ -1004,6 +1091,11 @@ main() { |
| note "g_temp_dir = ${g_temp_dir}" |
| fi |
| + # Clean up any old .want_full_installer files from previous dirpatcher |
| + # failures. This is not considered a critical step, because this file |
| + # normally does not exist at all. |
| + rm -f "${want_full_installer_path}" || true |
| + |
| # If necessary, touch the outermost .app so that it appears to the outside |
| # world that something was done to the bundle. This will cause |
| # LaunchServices to invalidate the information it has cached about the |
| @@ -1057,6 +1149,15 @@ main() { |
| "${KS_CHANNEL_KEY}" 2> /dev/null || true)" |
| note "channel = ${channel}" |
| + local tag="${channel}" |
| + local tag_key="${KS_CHANNEL_KEY}" |
| + if has_32_bit_only_cpu; then |
| + tag="${tag}-32bit" |
| + tag_key="${tag_key}-32bit" |
| + fi |
| + note "tag = ${tag}" |
| + note "tag_key = ${tag_key}" |
| + |
| # Make sure that the update was successful by comparing the version found in |
| # the update with the version now on disk. |
| if [[ "${new_version_ks}" != "${update_version_ks}" ]]; then |
| @@ -1165,14 +1266,14 @@ main() { |
| if ksadmin_supports_tag; then |
| ksadmin_args+=( |
| - --tag "${channel}" |
| + --tag "${tag}" |
| ) |
| fi |
| if ksadmin_supports_tagpath_tagkey; then |
| ksadmin_args+=( |
| --tag-path "${installed_app_plist_path}" |
| - --tag-key "${KS_CHANNEL_KEY}" |
| + --tag-key "${tag_key}" |
| ) |
| fi |