• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/bin/sh
2
3# Copyright (c) 2012 The Chromium Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7# This script signs the Chromoting binaries, builds the Chrome Remote Desktop
8# installer and then packages it into a .dmg.  It requires that Packages be
9# installed (for 'packagesbuild').
10# Packages: http://s.sudre.free.fr/Software/Packages/about.html
11#
12# usage: do_signing.sh output_dir input_dir [codesign_keychain codesign_id
13#            [productsign_id]]
14#
15# The final disk image (dmg) is placed in |output_dir|.
16
17set -e -u
18
19ME="$(basename "${0}")"
20readonly ME
21
22declare -a g_cleanup_dirs
23
24setup() {
25  local input_dir="${1}"
26
27  # The file that contains the properties for this signing build.
28  # The file should contain only key=value pairs, one per line.
29  PROPS_FILENAME="${input_dir}/do_signing.props"
30
31  # Individually load the properties for this build. Don't 'source' the file
32  # to guard against code accidentally being added to the props file.
33  HOST_UNINSTALLER_NAME=$(read_property "HOST_UNINSTALLER_NAME")
34  HOST_PKG=$(read_property "HOST_PKG")
35  DMG_VOLUME_NAME=$(read_property "DMG_VOLUME_NAME")
36  DMG_FILE_NAME=$(read_property "DMG_FILE_NAME")
37
38  # Binaries to sign.
39  ME2ME_HOST='PrivilegedHelperTools/org.chromium.chromoting.me2me_host.app'
40  UNINSTALLER="Applications/${HOST_UNINSTALLER_NAME}.app"
41  PREFPANE='PreferencePanes/org.chromium.chromoting.prefPane'
42
43  # The Chromoting Host installer is a meta-package that consists of 3
44  # components:
45  #  * Chromoting Host Service package
46  #  * Chromoting Host Uninstaller package
47  #  * Keystone package (GoogleSoftwareUpdate - for Official builds only)
48  PKGPROJ_HOST='ChromotingHost.pkgproj'
49  PKGPROJ_HOST_SERVICE='ChromotingHostService.pkgproj'
50  PKGPROJ_HOST_UNINSTALLER='ChromotingHostUninstaller.pkgproj'
51
52  # Final (user-visible) pkg name.
53  PKG_FINAL="${HOST_PKG}.pkg"
54
55  DMG_FILE_NAME="${DMG_FILE_NAME}.dmg"
56
57  # Temp directory for Packages output.
58  PKG_DIR=build
59  g_cleanup_dirs+=("${PKG_DIR}")
60
61  # Temp directories for building the dmg.
62  DMG_TEMP_DIR="$(mktemp -d -t "${ME}"-dmg)"
63  g_cleanup_dirs+=("${DMG_TEMP_DIR}")
64
65  DMG_EMPTY_DIR="$(mktemp -d -t "${ME}"-empty)"
66  g_cleanup_dirs+=("${DMG_EMPTY_DIR}")
67}
68
69err() {
70  echo "[$(date +'%Y-%m-%d %H:%M:%S%z')]: ${@}" >&2
71}
72
73err_exit() {
74  err "${@}"
75  exit 1
76}
77
78# shell_safe_path ensures that |path| is safe to pass to tools as a
79# command-line argument. If the first character in |path| is "-", "./" is
80# prepended to it. The possibly-modified |path| is output.
81shell_safe_path() {
82  local path="${1}"
83  if [[ "${path:0:1}" = "-" ]]; then
84    echo "./${path}"
85  else
86    echo "${path}"
87  fi
88}
89
90# Read a single property from the properties file.
91read_property() {
92  local property="${1}"
93  local filename="${PROPS_FILENAME}"
94  echo `grep "${property}" "${filename}" | tail -n 1 | cut -d "=" -f2-`
95}
96
97verify_clean_dir() {
98  local dir="${1}"
99  if [[ ! -d "${dir}" ]]; then
100    mkdir "${dir}"
101  fi
102
103  if [[ -e "${output_dir}/${DMG_FILE_NAME}" ]]; then
104    err "Output directory is dirty from previous build."
105    exit 1
106  fi
107}
108
109sign() {
110  local name="${1}"
111  local keychain="${2}"
112  local id="${3}"
113
114  if [[ ! -e "${name}" ]]; then
115    err_exit "Input file doesn't exist: ${name}"
116  fi
117
118  echo Signing "${name}"
119  codesign -vv -s "${id}" --keychain "${keychain}" "${name}"
120  codesign -v "${name}"
121}
122
123sign_binaries() {
124  local input_dir="${1}"
125  local keychain="${2}"
126  local id="${3}"
127
128  sign "${input_dir}/${ME2ME_HOST}" "${keychain}" "${id}"
129  sign "${input_dir}/${UNINSTALLER}" "${keychain}" "${id}"
130  sign "${input_dir}/${PREFPANE}" "${keychain}" "${id}"
131}
132
133sign_installer() {
134  local input_dir="${1}"
135  local keychain="${2}"
136  local id="${3}"
137
138  local package="${input_dir}/${PKG_DIR}/${PKG_FINAL}"
139  productsign --sign "${id}" --keychain "${keychain}" \
140      "${package}" "${package}.signed"
141  mv -f "${package}.signed" "${package}"
142}
143
144build_package() {
145  local pkg="${1}"
146  echo "Building .pkg from ${pkg}"
147  packagesbuild -v "${pkg}"
148}
149
150build_packages() {
151  local input_dir="${1}"
152  build_package "${input_dir}/${PKGPROJ_HOST_SERVICE}"
153  build_package "${input_dir}/${PKGPROJ_HOST_UNINSTALLER}"
154  build_package "${input_dir}/${PKGPROJ_HOST}"
155}
156
157build_dmg() {
158  local input_dir="${1}"
159  local output_dir="${2}"
160
161  # Create the .dmg.
162  echo "Building .dmg..."
163  "${input_dir}/pkg-dmg" \
164      --format UDBZ \
165      --tempdir "${DMG_TEMP_DIR}" \
166      --source "${DMG_EMPTY_DIR}" \
167      --target "${output_dir}/${DMG_FILE_NAME}" \
168      --volname "${DMG_VOLUME_NAME}" \
169      --copy "${input_dir}/${PKG_DIR}/${PKG_FINAL}" \
170      --copy "${input_dir}/Scripts/keystone_install.sh:/.keystone_install"
171
172  if [[ ! -f "${output_dir}/${DMG_FILE_NAME}" ]]; then
173    err_exit "Unable to create disk image: ${DMG_FILE_NAME}"
174  fi
175}
176
177cleanup() {
178  if [[ "${#g_cleanup_dirs[@]}" > 0 ]]; then
179    rm -rf "${g_cleanup_dirs[@]}"
180  fi
181}
182
183usage() {
184  echo "Usage: ${ME} output_dir input_dir [keychain codesign_id"\
185      "[productsign_id]]" >&2
186  echo "  Sign the binaries using the specified <codesign_id>, build" >&2
187  echo "  the installer and then sign the installer using the given" >&2
188  echo "  <productsign_id>." >&2
189  echo "  If the <keychain> and signing ids are not specified then the" >&2
190  echo "  installer is built without signing any binaries." >&2
191}
192
193main() {
194  local output_dir="$(shell_safe_path "${1}")"
195  local input_dir="$(shell_safe_path "${2}")"
196  local do_sign_binaries=0
197  local keychain=""
198  if [[ ${#} -ge 3 ]]; then
199    keychain="$(shell_safe_path "${3}")"
200    do_sign_binaries=1
201    echo "Signing binaries using ${keychain}"
202  else
203    echo "Not signing binaries (no keychain or identify specified)"
204  fi
205  local codesign_id=""
206  if [[ ${#} -ge 4 ]]; then
207    codesign_id="${4}"
208  fi
209  local productsign_id=""
210  if [[ ${#} -ge 5 ]]; then
211    productsign_id="${5}"
212  fi
213
214  if [[ "${do_sign_binaries}" == 1 && -z "${codesign_id}" ]]; then
215    err_exit "Can't sign binaries - please specify a codesign_id"
216  fi
217
218  setup "${input_dir}"
219  verify_clean_dir "${output_dir}"
220
221  if [[ "${do_sign_binaries}" == 1 ]]; then
222    sign_binaries "${input_dir}" "${keychain}" "${codesign_id}"
223  fi
224  build_packages "${input_dir}"
225  if [[ "${do_sign_binaries}" == 1 && -n "${productsign_id}" ]]; then
226    echo "Signing installer..."
227    sign_installer "${input_dir}" "${keychain}" "${productsign_id}"
228  fi
229  build_dmg "${input_dir}" "${output_dir}"
230
231  cleanup
232}
233
234if [[ ${#} < 2 ]]; then
235  usage
236  exit 1
237fi
238
239main "${@}"
240exit ${?}
241