| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # | 2 # |
| 3 # Copyright 2015 The Chromium Authors. All rights reserved. | 3 # Copyright 2015 The Chromium Authors. All rights reserved. |
| 4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
| 6 """Creates an AndroidManifest.xml for an incremental APK. | 6 """Creates an AndroidManifest.xml for an incremental APK. |
| 7 | 7 |
| 8 Given the manifest file for the real APK, generates an AndroidManifest.xml with | 8 Given the manifest file for the real APK, generates an AndroidManifest.xml with |
| 9 the application class changed to IncrementalApplication. | 9 the application class changed to IncrementalApplication. |
| 10 """ | 10 """ |
| 11 | 11 |
| 12 import argparse | 12 import argparse |
| 13 import os | 13 import os |
| 14 import sys | 14 import sys |
| 15 from xml.etree import ElementTree | 15 from xml.etree import ElementTree |
| 16 | 16 |
| 17 sys.path.append(os.path.join(os.path.dirname(__file__), os.path.pardir, 'gyp')) | 17 sys.path.append(os.path.join(os.path.dirname(__file__), os.path.pardir, 'gyp')) |
| 18 from util import build_utils | 18 from util import build_utils |
| 19 | 19 |
| 20 _ANDROID_NAMESPACE = 'http://schemas.android.com/apk/res/android' | 20 _ANDROID_NAMESPACE = 'http://schemas.android.com/apk/res/android' |
| 21 ElementTree.register_namespace('android', _ANDROID_NAMESPACE) | 21 ElementTree.register_namespace('android', _ANDROID_NAMESPACE) |
| 22 | 22 |
| 23 _INCREMENTAL_APP_NAME = 'org.chromium.incrementalinstall.BootstrapApplication' | 23 _INCREMENTAL_APP_NAME = 'org.chromium.incrementalinstall.BootstrapApplication' |
| 24 _META_DATA_NAME = 'incremental-install-real-app' | 24 _META_DATA_APP_NAME = 'incremental-install-real-app' |
| 25 _META_DATA_INSTRUMENTATION_NAME = 'incremental-install-real-instrumentation' |
| 25 _DEFAULT_APPLICATION_CLASS = 'android.app.Application' | 26 _DEFAULT_APPLICATION_CLASS = 'android.app.Application' |
| 27 _DEFAULT_INSTRUMENTATION_CLASS = 'android.app.Instrumentation' |
| 26 | 28 |
| 27 | 29 |
| 28 def _AddNamespace(name): | 30 def _AddNamespace(name): |
| 29 """Adds the android namespace prefix to the given identifier.""" | 31 """Adds the android namespace prefix to the given identifier.""" |
| 30 return '{%s}%s' % (_ANDROID_NAMESPACE, name) | 32 return '{%s}%s' % (_ANDROID_NAMESPACE, name) |
| 31 | 33 |
| 32 def _ParseArgs(): | 34 def _ParseArgs(): |
| 33 parser = argparse.ArgumentParser() | 35 parser = argparse.ArgumentParser() |
| 34 build_utils.AddDepfileOption(parser) | 36 build_utils.AddDepfileOption(parser) |
| 35 parser.add_argument('--src-manifest', | 37 parser.add_argument('--src-manifest', |
| 36 help='The main manifest of the app', | 38 help='The main manifest of the app', |
| 37 required=True) | 39 required=True) |
| 38 parser.add_argument('--out-manifest', | 40 parser.add_argument('--out-manifest', |
| 39 help='The output manifest', | 41 help='The output manifest', |
| 40 required=True) | 42 required=True) |
| 41 parser.add_argument('--disable-isolated-processes', | 43 parser.add_argument('--disable-isolated-processes', |
| 42 help='Changes all android:isolatedProcess to false. ' | 44 help='Changes all android:isolatedProcess to false. ' |
| 43 'This is required on Android M+', | 45 'This is required on Android M+', |
| 44 action='store_true') | 46 action='store_true') |
| 45 return parser.parse_args() | 47 return parser.parse_args() |
| 46 | 48 |
| 47 | 49 |
| 50 def _CreateMetaData(parent, name, value): |
| 51 meta_data_node = ElementTree.SubElement(parent, 'meta-data') |
| 52 meta_data_node.set(_AddNamespace('name'), name) |
| 53 meta_data_node.set(_AddNamespace('value'), value) |
| 54 |
| 55 |
| 48 def _ProcessManifest(main_manifest, disable_isolated_processes): | 56 def _ProcessManifest(main_manifest, disable_isolated_processes): |
| 49 """Returns a transformed AndroidManifest.xml for use with _incremental apks. | 57 """Returns a transformed AndroidManifest.xml for use with _incremental apks. |
| 50 | 58 |
| 51 Args: | 59 Args: |
| 52 main_manifest: Manifest contents to transform. | 60 main_manifest: Manifest contents to transform. |
| 53 disable_isolated_processes: Whether to set all isolatedProcess attributes to | 61 disable_isolated_processes: Whether to set all isolatedProcess attributes to |
| 54 false | 62 false |
| 55 | 63 |
| 56 Returns: | 64 Returns: |
| 57 The transformed AndroidManifest.xml. | 65 The transformed AndroidManifest.xml. |
| 58 """ | 66 """ |
| 59 if disable_isolated_processes: | 67 if disable_isolated_processes: |
| 60 main_manifest = main_manifest.replace('isolatedProcess="true"', | 68 main_manifest = main_manifest.replace('isolatedProcess="true"', |
| 61 'isolatedProcess="false"') | 69 'isolatedProcess="false"') |
| 62 | 70 |
| 63 doc = ElementTree.fromstring(main_manifest) | 71 doc = ElementTree.fromstring(main_manifest) |
| 64 app_node = doc.find('application') | 72 app_node = doc.find('application') |
| 65 if app_node is None: | 73 if app_node is None: |
| 66 app_node = ElementTree.SubElement(doc, 'application') | 74 app_node = ElementTree.SubElement(doc, 'application') |
| 67 | 75 |
| 68 real_app_class = app_node.get(_AddNamespace('name'), | 76 real_app_class = app_node.get(_AddNamespace('name'), |
| 69 _DEFAULT_APPLICATION_CLASS) | 77 _DEFAULT_APPLICATION_CLASS) |
| 70 app_node.set(_AddNamespace('name'), _INCREMENTAL_APP_NAME) | 78 app_node.set(_AddNamespace('name'), _INCREMENTAL_APP_NAME) |
| 79 _CreateMetaData(app_node, _META_DATA_APP_NAME, real_app_class) |
| 71 | 80 |
| 72 meta_data_node = ElementTree.SubElement(app_node, 'meta-data') | 81 # Seems to be a bug in ElementTree, as doc.find() doesn't work here. |
| 73 meta_data_node.set(_AddNamespace('name'), _META_DATA_NAME) | 82 instrumentation_nodes = doc.findall('instrumentation') |
| 74 meta_data_node.set(_AddNamespace('value'), real_app_class) | 83 if instrumentation_nodes: |
| 84 instrumentation_node = instrumentation_nodes[0] |
| 85 real_instrumentation_class = instrumentation_node.get(_AddNamespace('name')) |
| 86 instrumentation_node.set(_AddNamespace('name'), |
| 87 _DEFAULT_INSTRUMENTATION_CLASS) |
| 88 _CreateMetaData(app_node, _META_DATA_INSTRUMENTATION_NAME, |
| 89 real_instrumentation_class) |
| 90 |
| 75 return ElementTree.tostring(doc, encoding='UTF-8') | 91 return ElementTree.tostring(doc, encoding='UTF-8') |
| 76 | 92 |
| 77 | 93 |
| 78 def main(): | 94 def main(): |
| 79 options = _ParseArgs() | 95 options = _ParseArgs() |
| 80 with open(options.src_manifest) as f: | 96 with open(options.src_manifest) as f: |
| 81 main_manifest_data = f.read() | 97 main_manifest_data = f.read() |
| 82 new_manifest_data = _ProcessManifest(main_manifest_data, | 98 new_manifest_data = _ProcessManifest(main_manifest_data, |
| 83 options.disable_isolated_processes) | 99 options.disable_isolated_processes) |
| 84 with open(options.out_manifest, 'w') as f: | 100 with open(options.out_manifest, 'w') as f: |
| 85 f.write(new_manifest_data) | 101 f.write(new_manifest_data) |
| 86 | 102 |
| 87 if options.depfile: | 103 if options.depfile: |
| 88 build_utils.WriteDepfile( | 104 build_utils.WriteDepfile( |
| 89 options.depfile, | 105 options.depfile, |
| 90 [options.src_manifest] + build_utils.GetPythonDependencies()) | 106 [options.src_manifest] + build_utils.GetPythonDependencies()) |
| 91 | 107 |
| 92 | 108 |
| 93 if __name__ == '__main__': | 109 if __name__ == '__main__': |
| 94 main() | 110 main() |
| OLD | NEW |