10529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#!/usr/bin/env python
20529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch# Copyright (c) 2014 The Chromium Authors. All rights reserved.
30529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch# Use of this source code is governed by a BSD-style license that can be
40529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch# found in the LICENSE file.
50529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
60529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch# Disable the lint error for too-long lines for the URL below.
70529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch# pylint: disable=C0301
80529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
90529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch"""Fix Chrome App manifest.json files for use with multi-platform zip files.
100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
110529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochSee info about multi-platform zip files here:
120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochhttps://developer.chrome.com/native-client/devguide/distributing#packaged-application
130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
140529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochThe manifest.json file needs to point to the correct platform-specific paths,
150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbut we build all toolchains and configurations in the same tree. As a result,
160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochwe can't have one manifest.json for all combinations.
170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
180529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochInstead, we update the top-level manifest.json file during the build:
190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  "platforms": [
210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    {
220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      "nacl_arch": "x86-64",
230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      "sub_package_path": "_platform_specific/x86-64/"
240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    },
250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    ...
260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
270529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochBecomes
280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  "platforms": [
300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    {
310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      "nacl_arch": "x86-64",
320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      "sub_package_path": "<toolchain>/<config>/_platform_specific/x86-64/"
330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    },
340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    ...
350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch"""
360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochimport collections
380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochimport json
390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochimport optparse
400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochimport os
410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochimport sys
420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochif sys.version_info < (2, 6, 0):
440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  sys.stderr.write("python 2.6 or later is required run this script\n")
450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  sys.exit(1)
460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochclass Error(Exception):
490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  """Local Error class for this file."""
500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  pass
510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochdef Trace(msg):
540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if Trace.verbose:
550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    sys.stderr.write(str(msg) + '\n')
560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
570529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTrace.verbose = False
580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochdef main(argv):
610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  parser = optparse.OptionParser(
620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      usage='Usage: %prog [options] manifest.json', description=__doc__)
630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  parser.add_option('-p', '--prefix',
640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                    help='Prefix to set for all sub_package_paths in the '
650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                    'manifest. If none is specified, the prefix will be '
660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                    'removed; i.e. the start of the path will be '
670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                    '"_platform_specific/..."')
680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  parser.add_option('-v', '--verbose',
690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                    help='Verbose output', action='store_true')
700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  options, args = parser.parse_args(argv)
720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if options.verbose:
730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    Trace.verbose = True
740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if not args:
760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    parser.error('Expected manifest file.')
770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  manifest = args[0]
790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  Trace('Reading %s' % manifest)
810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  with open(manifest) as f:
820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    # Keep the dictionary order. This is only supported on Python 2.7+
830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if sys.version_info >= (2, 7, 0):
840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      data = json.load(f, object_pairs_hook=collections.OrderedDict)
850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    else:
860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      data = json.load(f)
870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if 'platforms' not in data:
890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    raise Error('%s does not have "platforms" key.' % manifest)
900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  platforms = data['platforms']
920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if type(platforms) is not list:
930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    raise Error('Expected "platforms" key to be array.')
940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if options.prefix:
960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    prefix = options.prefix + '/'
970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  else:
980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    prefix = ''
990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  for platform in platforms:
1010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    nacl_arch = platform.get('nacl_arch')
1020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if 'sub_package_path' not in platform:
1040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      raise Error('Expected each platform to have "sub_package_path" key.')
1050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    sub_package_path = platform['sub_package_path']
1070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    index = sub_package_path.find('_platform_specific')
1080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if index == -1:
1090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      raise Error('Could not find "_platform_specific" in the '
1100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                  '"sub_package_path" key.')
1110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    new_path = prefix + sub_package_path[index:]
1130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    platform['sub_package_path'] = new_path
1140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    Trace('  %s: "%s" -> "%s"' % (nacl_arch, sub_package_path, new_path))
1160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  with open(manifest, 'w') as f:
1180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    json.dump(data, f, indent=2)
1190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return 0
1210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochif __name__ == '__main__':
1240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  try:
1250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    rtn = main(sys.argv[1:])
1260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  except Error, e:
1270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    sys.stderr.write('%s: %s\n' % (os.path.basename(__file__), e))
1280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    rtn = 1
1290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  except KeyboardInterrupt:
1300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    sys.stderr.write('%s: interrupted\n' % os.path.basename(__file__))
1310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    rtn = 1
1320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  sys.exit(rtn)
133