tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

merge_manifest.py (6040B)


      1 #!/usr/bin/env python3
      2 
      3 # Copyright 2017 The Chromium Authors
      4 # Use of this source code is governed by a BSD-style license that can be
      5 # found in the LICENSE file.
      6 
      7 """Merges dependency Android manifests into a root manifest."""
      8 
      9 import argparse
     10 import collections
     11 import contextlib
     12 import os
     13 import sys
     14 import tempfile
     15 import xml.etree.ElementTree as ElementTree
     16 
     17 from util import build_utils
     18 from util import manifest_utils
     19 import action_helpers  # build_utils adds //build to sys.path.
     20 
     21 _MANIFEST_MERGER_MAIN_CLASS = 'com.android.manifmerger.Merger'
     22 
     23 
     24 @contextlib.contextmanager
     25 def _ProcessMainManifest(manifest_path, min_sdk_version, target_sdk_version,
     26                         max_sdk_version, manifest_package):
     27  """Patches the main Android manifest"""
     28  doc, manifest, _ = manifest_utils.ParseManifest(manifest_path)
     29  manifest_utils.SetUsesSdk(manifest, target_sdk_version, min_sdk_version,
     30                            max_sdk_version)
     31  assert manifest_utils.GetPackage(manifest) or manifest_package, \
     32            'Must set manifest package in GN or in AndroidManifest.xml'
     33  if manifest_package:
     34    manifest.set('package', manifest_package)
     35  tmp_prefix = manifest_path.replace(os.path.sep, '-')
     36  with tempfile.NamedTemporaryFile(prefix=tmp_prefix) as patched_manifest:
     37    manifest_utils.SaveManifest(doc, patched_manifest.name)
     38    yield patched_manifest.name, manifest_utils.GetPackage(manifest)
     39 
     40 
     41 @contextlib.contextmanager
     42 def _ProcessOtherManifest(manifest_path, min_sdk_version, target_sdk_version,
     43                          seen_package_names):
     44  """Patches non-main AndroidManifest.xml if necessary."""
     45  # 1. Ensure targetSdkVersion is set to the expected value to avoid
     46  #    spurious permissions being added (b/222331337).
     47  # 2. Ensure all manifests have a unique package name so that the merger
     48  #    does not fail when this happens.
     49  doc, manifest, _ = manifest_utils.ParseManifest(manifest_path)
     50 
     51  changed_api = manifest_utils.SetTargetApiIfUnset(manifest, target_sdk_version)
     52 
     53  package_name = manifest_utils.GetPackage(manifest)
     54  # Ignore minSdkVersion from androidx.pdf library. The client code will ensure
     55  # not to call into the library API on older Android versions.
     56  if package_name.startswith('androidx.pdf'):
     57    manifest_utils.OverrideMinSdkVersionIfPresent(manifest, min_sdk_version)
     58    changed_api = True
     59  package_count = seen_package_names[package_name]
     60  seen_package_names[package_name] += 1
     61  if package_count > 0:
     62    manifest.set('package', f'{package_name}_{package_count}')
     63 
     64  if package_count > 0 or changed_api:
     65    tmp_prefix = manifest_path.replace(os.path.sep, '-')
     66    with tempfile.NamedTemporaryFile(prefix=tmp_prefix) as patched_manifest:
     67      manifest_utils.SaveManifest(doc, patched_manifest.name)
     68      yield patched_manifest.name
     69  else:
     70    yield manifest_path
     71 
     72 
     73 def main(argv):
     74  argv = build_utils.ExpandFileArgs(argv)
     75  parser = argparse.ArgumentParser(description=__doc__)
     76  action_helpers.add_depfile_arg(parser)
     77  parser.add_argument('--manifest-merger-jar',
     78                      help='Path to SDK\'s manifest merger jar.',
     79                      required=True)
     80  parser.add_argument('--root-manifest',
     81                      help='Root manifest which to merge into',
     82                      required=True)
     83  parser.add_argument('--output', help='Output manifest path', required=True)
     84  parser.add_argument('--extras',
     85                      help='GN list of additional manifest to merge')
     86  parser.add_argument(
     87      '--min-sdk-version',
     88      required=True,
     89      help='android:minSdkVersion for merging.')
     90  parser.add_argument(
     91      '--target-sdk-version',
     92      required=True,
     93      help='android:targetSdkVersion for merging.')
     94  parser.add_argument(
     95      '--max-sdk-version', help='android:maxSdkVersion for merging.')
     96  parser.add_argument(
     97      '--manifest-package',
     98      help='Package name of the merged AndroidManifest.xml.')
     99  parser.add_argument('--warnings-as-errors',
    100                      action='store_true',
    101                      help='Treat all warnings as errors.')
    102  args = parser.parse_args(argv)
    103 
    104  with action_helpers.atomic_output(args.output) as output:
    105    cmd = build_utils.JavaCmd() + [
    106        '-cp',
    107        args.manifest_merger_jar,
    108        _MANIFEST_MERGER_MAIN_CLASS,
    109        '--out',
    110        output.name,
    111        '--property',
    112        'MIN_SDK_VERSION=' + args.min_sdk_version,
    113        '--property',
    114        'TARGET_SDK_VERSION=' + args.target_sdk_version,
    115    ]
    116 
    117    if args.max_sdk_version:
    118      cmd += [
    119          '--property',
    120          'MAX_SDK_VERSION=' + args.max_sdk_version,
    121      ]
    122 
    123    extras = action_helpers.parse_gn_list(args.extras)
    124 
    125    with contextlib.ExitStack() as stack:
    126      root_manifest, package = stack.enter_context(
    127          _ProcessMainManifest(args.root_manifest, args.min_sdk_version,
    128                               args.target_sdk_version, args.max_sdk_version,
    129                               args.manifest_package))
    130      if extras:
    131        seen_package_names = collections.Counter()
    132        extras_processed = [
    133            stack.enter_context(
    134                _ProcessOtherManifest(e, args.min_sdk_version,
    135                                      args.target_sdk_version,
    136                                      seen_package_names)) for e in extras
    137        ]
    138        cmd += ['--libs', ':'.join(extras_processed)]
    139      cmd += [
    140          '--main',
    141          root_manifest,
    142          '--property',
    143          'PACKAGE=' + package,
    144          '--remove-tools-declarations',
    145      ]
    146      build_utils.CheckOutput(
    147          cmd,
    148          # https://issuetracker.google.com/issues/63514300:
    149          # The merger doesn't set a nonzero exit code for failures.
    150          fail_func=lambda returncode, stderr: returncode != 0 or build_utils.
    151          IsTimeStale(output.name, [root_manifest] + extras),
    152          fail_on_output=args.warnings_as_errors)
    153 
    154  if args.depfile:
    155    action_helpers.write_depfile(args.depfile, args.output, inputs=extras)
    156 
    157 
    158 if __name__ == '__main__':
    159  main(sys.argv[1:])