#!/usr/bin/env python

# 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.

#
# Xcode supports build variable substitutions and CPP; sadly, that doesn't work
# because:
#
# 1. Xcode wants to do the Info.plist work before it runs any build phases,
#    this means if we were to generate a .h file for INFOPLIST_PREFIX_HEADER
#    we'd have to put it in another target so it runs in time.
# 2. Xcode also doesn't check to see if the header being used as a prefix for
#    the Info.plist has changed.  So even if we updated it, it's only looking
#    at the modtime of the info.plist to see if that's changed.
#
# So, we work around all of this by making a script build phase that will run
# during the app build, and simply update the info.plist in place.  This way
# by the time the app target is done, the info.plist is correct.
#

import optparse
import os
from os import environ as env
import plistlib
import re
import subprocess
import sys
import tempfile

TOP = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))


def _GetOutput(args):
    """Runs a subprocess and waits for termination. Returns (stdout, returncode)
  of the process. stderr is attached to the parent."""
    proc = subprocess.Popen(args, stdout=subprocess.PIPE)
    (stdout, stderr) = proc.communicate()
    return (stdout, proc.returncode)


def _GetOutputNoError(args):
    """Similar to _GetOutput() but ignores stderr. If there's an error launching
  the child (like file not found), the exception will be caught and (None, 1)
  will be returned to mimic quiet failure."""
    try:
        proc = subprocess.Popen(
            args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    except OSError:
        return (None, 1)
    (stdout, stderr) = proc.communicate()
    return (stdout, proc.returncode)


def _RemoveKeys(plist, *keys):
    """Removes a varargs of keys from the plist."""
    for key in keys:
        try:
            del plist[key]
        except KeyError:
            pass


def _AddVersionKeys(plist, version=None):
    """Adds the product version number into the plist. Returns True on success and
  False on error. The error will be printed to stderr."""
    if version:
        match = re.match('\d+\.\d+\.(\d+\.\d+)$', version)
        if not match:
            print >> sys.stderr, 'Invalid version string specified: "%s"' % version
            return False

        full_version = match.group(0)
        bundle_version = match.group(1)

    else:
        # Pull in the Chrome version number.
        VERSION_TOOL = os.path.join(TOP, 'build/util/version.py')
        VERSION_FILE = os.path.join(TOP, 'chrome/VERSION')

        (stdout, retval1) = _GetOutput([
            VERSION_TOOL, '-f', VERSION_FILE, '-t',
            '@MAJOR@.@MINOR@.@BUILD@.@PATCH@'
        ])
        full_version = stdout.rstrip()

        (stdout, retval2) = _GetOutput(
            [VERSION_TOOL, '-f', VERSION_FILE, '-t', '@BUILD@.@PATCH@'])
        bundle_version = stdout.rstrip()

        # If either of the two version commands finished with non-zero returncode,
        # report the error up.
        if retval1 or retval2:
            return False

    # Add public version info so "Get Info" works.
    plist['CFBundleShortVersionString'] = full_version

    # Honor the 429496.72.95 limit.  The maximum comes from splitting 2^32 - 1
    # into  6, 2, 2 digits.  The limitation was present in Tiger, but it could
    # have been fixed in later OS release, but hasn't been tested (it's easy
    # enough to find out with "lsregister -dump).
    # http://lists.apple.com/archives/carbon-dev/2006/Jun/msg00139.html
    # BUILD will always be an increasing value, so BUILD_PATH gives us something
    # unique that meetings what LS wants.
    plist['CFBundleVersion'] = bundle_version

    # Return with no error.
    return True


def _DoSCMKeys(plist, add_keys):
    """Adds the SCM information, visible in about:version, to property list. If
  |add_keys| is True, it will insert the keys, otherwise it will remove them."""
    scm_revision = None
    if add_keys:
        # Pull in the Chrome revision number.
        VERSION_TOOL = os.path.join(TOP, 'build/util/version.py')
        LASTCHANGE_FILE = os.path.join(TOP, 'build/util/LASTCHANGE')
        (stdout, retval) = _GetOutput(
            [VERSION_TOOL, '-f', LASTCHANGE_FILE, '-t', '@LASTCHANGE@'])
        if retval:
            return False
        scm_revision = stdout.rstrip()

    # See if the operation failed.
    _RemoveKeys(plist, 'SCMRevision')
    if scm_revision != None:
        plist['SCMRevision'] = scm_revision
    elif add_keys:
        print >> sys.stderr, 'Could not determine SCM revision.  This may be OK.'

    return True


def _AddBreakpadKeys(plist, branding):
    """Adds the Breakpad keys. This must be called AFTER _AddVersionKeys() and
  also requires the |branding| argument."""
    plist['BreakpadReportInterval'] = '3600'  # Deliberately a string.
    plist['BreakpadProduct'] = '%s_Mac' % branding
    plist['BreakpadProductDisplay'] = branding
    plist['BreakpadVersion'] = plist['CFBundleShortVersionString']
    # These are both deliberately strings and not boolean.
    plist['BreakpadSendAndExit'] = 'YES'
    plist['BreakpadSkipConfirm'] = 'YES'


def _RemoveBreakpadKeys(plist):
    """Removes any set Breakpad keys."""
    _RemoveKeys(plist, 'BreakpadURL', 'BreakpadReportInterval',
                'BreakpadProduct', 'BreakpadProductDisplay', 'BreakpadVersion',
                'BreakpadSendAndExit', 'BreakpadSkipConfirm')


def _TagSuffixes():
    # Keep this list sorted in the order that tag suffix components are to
    # appear in a tag value. That is to say, it should be sorted per ASCII.
    components = ('32bit', 'full')
    assert tuple(sorted(components)) == components

    components_len = len(components)
    combinations = 1 << components_len
    tag_suffixes = []
    for combination in xrange(0, combinations):
        tag_suffix = ''
        for component_index in xrange(0, components_len):
            if combination & (1 << component_index):
                tag_suffix += '-' + components[component_index]
        tag_suffixes.append(tag_suffix)
    return tag_suffixes


def _AddKeystoneKeys(plist, bundle_identifier):
    """Adds the Keystone keys. This must be called AFTER _AddVersionKeys() and
  also requires the |bundle_identifier| argument (com.example.product)."""
    plist['KSVersion'] = plist['CFBundleShortVersionString']
    plist['KSProductID'] = bundle_identifier
    plist['KSUpdateURL'] = 'https://tools.google.com/service/update2'

    _RemoveKeys(plist, 'KSChannelID')
    for tag_suffix in _TagSuffixes():
        if tag_suffix:
            plist['KSChannelID' + tag_suffix] = tag_suffix


def _RemoveKeystoneKeys(plist):
    """Removes any set Keystone keys."""
    _RemoveKeys(plist, 'KSVersion', 'KSProductID', 'KSUpdateURL')

    tag_keys = []
    for tag_suffix in _TagSuffixes():
        tag_keys.append('KSChannelID' + tag_suffix)
    _RemoveKeys(plist, *tag_keys)


def Main(argv):
    parser = optparse.OptionParser('%prog [options]')
    parser.add_option(
        '--breakpad',
        dest='use_breakpad',
        action='store',
        type='int',
        default=False,
        help='Enable Breakpad [1 or 0]')
    parser.add_option(
        '--breakpad_uploads',
        dest='breakpad_uploads',
        action='store',
        type='int',
        default=False,
        help='Enable Breakpad\'s uploading of crash dumps [1 or 0]')
    parser.add_option(
        '--keystone',
        dest='use_keystone',
        action='store',
        type='int',
        default=False,
        help='Enable Keystone [1 or 0]')
    parser.add_option(
        '--scm',
        dest='add_scm_info',
        action='store',
        type='int',
        default=True,
        help='Add SCM metadata [1 or 0]')
    parser.add_option(
        '--branding',
        dest='branding',
        action='store',
        type='string',
        default=None,
        help='The branding of the binary')
    parser.add_option(
        '--bundle_id',
        dest='bundle_identifier',
        action='store',
        type='string',
        default=None,
        help='The bundle id of the binary')
    parser.add_option(
        '--version',
        dest='version',
        action='store',
        type='string',
        default=None,
        help='The version string [major.minor.build.patch]')
    (options, args) = parser.parse_args(argv)

    if len(args) > 0:
        print >> sys.stderr, parser.get_usage()
        return 1

    # Read the plist into its parsed format.
    DEST_INFO_PLIST = os.path.join(env['TARGET_BUILD_DIR'],
                                   env['INFOPLIST_PATH'])
    plist = plistlib.readPlist(DEST_INFO_PLIST)

    # Insert the product version.
    if not _AddVersionKeys(plist, version=options.version):
        return 2

    # Add Breakpad if configured to do so.
    if options.use_breakpad:
        if options.branding is None:
            print >> sys.stderr, 'Use of Breakpad requires branding.'
            return 1
        _AddBreakpadKeys(plist, options.branding)
        if options.breakpad_uploads:
            plist['BreakpadURL'] = 'https://clients2.google.com/cr/report'
        else:
            # This allows crash dumping to a file without uploading the
            # dump, for testing purposes.  Breakpad does not recognise
            # "none" as a special value, but this does stop crash dump
            # uploading from happening.  We need to specify something
            # because if "BreakpadURL" is not present, Breakpad will not
            # register its crash handler and no crash dumping will occur.
            plist['BreakpadURL'] = 'none'
    else:
        _RemoveBreakpadKeys(plist)

    # Only add Keystone in Release builds.
    if options.use_keystone and env['CONFIGURATION'] == 'Release':
        if options.bundle_identifier is None:
            print >> sys.stderr, 'Use of Keystone requires the bundle id.'
            return 1
        _AddKeystoneKeys(plist, options.bundle_identifier)
    else:
        _RemoveKeystoneKeys(plist)

    # Adds or removes any SCM keys.
    if not _DoSCMKeys(plist, options.add_scm_info):
        return 3

    # Now that all keys have been mutated, rewrite the file.
    temp_info_plist = tempfile.NamedTemporaryFile()
    plistlib.writePlist(plist, temp_info_plist.name)

    # Info.plist will work perfectly well in any plist format, but traditionally
    # applications use xml1 for this, so convert it to ensure that it's valid.
    proc = subprocess.Popen([
        'plutil', '-convert', 'xml1', '-o', DEST_INFO_PLIST,
        temp_info_plist.name
    ])
    proc.wait()
    return proc.returncode


if __name__ == '__main__':
    sys.exit(Main(sys.argv[1:]))
