tor-browser

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

generate_android_manifest.py (4563B)


      1 #!/usr/bin/env python3
      2 #
      3 # Copyright 2015 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 """Creates an AndroidManifest.xml for an incremental APK.
      7 
      8 Given the manifest file for the real APK, generates an AndroidManifest.xml with
      9 the application class changed to IncrementalApplication.
     10 """
     11 
     12 import argparse
     13 import os
     14 import sys
     15 from xml.etree import ElementTree
     16 
     17 sys.path.append(os.path.join(os.path.dirname(__file__), os.path.pardir, 'gyp'))
     18 from util import build_utils
     19 from util import manifest_utils
     20 import action_helpers  # build_utils adds //build to sys.path.
     21 
     22 _DEFAULT_APPLICATION_CLASS = 'android.app.Application'
     23 _INCREMENTAL_APP_NAME = 'org.chromium.incrementalinstall.BootstrapApplication'
     24 _INCREMENTAL_APP_COMPONENT_FACTORY = (
     25    'org.chromium.incrementalinstall.BootstrapAppComponentFactory')
     26 _META_DATA_APP_NAME = 'incremental-install-application'
     27 _META_DATA_APP_COMPONENT_FACTORY = 'incremental-install-app-component-factory'
     28 _META_DATA_INSTRUMENTATION_NAMES = [
     29    'incremental-install-instrumentation-0',
     30    'incremental-install-instrumentation-1',
     31 ]
     32 _INCREMENTAL_INSTRUMENTATION_CLASSES = [
     33    'android.app.Instrumentation',
     34    'org.chromium.incrementalinstall.SecondInstrumentation',
     35 ]
     36 
     37 
     38 def _AddNamespace(name):
     39  """Adds the android namespace prefix to the given identifier."""
     40  return '{%s}%s' % (manifest_utils.ANDROID_NAMESPACE, name)
     41 
     42 
     43 def _ParseArgs(args):
     44  parser = argparse.ArgumentParser()
     45  parser.add_argument('--src-manifest',
     46                      required=True,
     47                      help='The main manifest of the app.')
     48  parser.add_argument('--dst-manifest',
     49                      required=True,
     50                      help='The output modified manifest.')
     51  parser.add_argument('--disable-isolated-processes',
     52                      help='Changes all android:isolatedProcess to false. '
     53                           'This is required on Android M+',
     54                      action='store_true')
     55 
     56  ret = parser.parse_args(build_utils.ExpandFileArgs(args))
     57  return ret
     58 
     59 
     60 def _CreateMetaData(parent, name, value):
     61  meta_data_node = ElementTree.SubElement(parent, 'meta-data')
     62  meta_data_node.set(_AddNamespace('name'), name)
     63  meta_data_node.set(_AddNamespace('value'), value)
     64 
     65 
     66 def _ProcessManifest(path, disable_isolated_processes):
     67  doc, _, app_node = manifest_utils.ParseManifest(path)
     68 
     69  # Pylint for some reason things app_node is an int.
     70  # pylint: disable=no-member
     71  real_app_class = app_node.get(_AddNamespace('name'),
     72                                _DEFAULT_APPLICATION_CLASS)
     73  app_node.set(_AddNamespace('name'), _INCREMENTAL_APP_NAME)
     74  # pylint: enable=no-member
     75  _CreateMetaData(app_node, _META_DATA_APP_NAME, real_app_class)
     76 
     77  real_acf = app_node.get(_AddNamespace('appComponentFactory'))
     78  if real_acf:
     79    app_node.set(_AddNamespace('appComponentFactory'),
     80                 _INCREMENTAL_APP_COMPONENT_FACTORY)
     81    _CreateMetaData(app_node, _META_DATA_APP_COMPONENT_FACTORY, real_acf)
     82 
     83  # Seems to be a bug in ElementTree, as doc.find() doesn't work here.
     84  instrumentation_nodes = doc.findall('instrumentation')
     85  assert len(instrumentation_nodes) <= 2, (
     86      'Need to update incremental install to support >2 <instrumentation> tags')
     87  for i, instrumentation_node in enumerate(instrumentation_nodes):
     88    real_instrumentation_class = instrumentation_node.get(_AddNamespace('name'))
     89    instrumentation_node.set(_AddNamespace('name'),
     90                             _INCREMENTAL_INSTRUMENTATION_CLASSES[i])
     91    _CreateMetaData(app_node, _META_DATA_INSTRUMENTATION_NAMES[i],
     92                    real_instrumentation_class)
     93 
     94  ret = ElementTree.tostring(doc.getroot(), encoding='UTF-8')
     95  # Disable check for page-aligned native libraries.
     96  ret = ret.replace(b'extractNativeLibs="false"', b'extractNativeLibs="true"')
     97  if disable_isolated_processes:
     98    ret = ret.replace(b'isolatedProcess="true"', b'isolatedProcess="false"')
     99    # externalService only matters for isolatedProcess="true". See:
    100    # https://developer.android.com/reference/android/R.attr#externalService
    101    ret = ret.replace(b'externalService="true"', b'externalService="false"')
    102  return ret
    103 
    104 
    105 def main(raw_args):
    106  options = _ParseArgs(raw_args)
    107 
    108  new_manifest_data = _ProcessManifest(options.src_manifest,
    109                                       options.disable_isolated_processes)
    110  with action_helpers.atomic_output(options.dst_manifest) as out_manifest:
    111    out_manifest.write(new_manifest_data)
    112 
    113 
    114 if __name__ == '__main__':
    115  main(sys.argv[1:])