def HandlePermissions(permissions, xmldoc): """ Implement the mapping of permission list to the AndroidManifest.xml file. Args: permissions: the permissions defined in Crosswalk and Android Manifest specification. xmldoc: the parsed xmldoc of the AndroidManifest.xml file, used for reading and writing. """ if permissions: existing_permission_list = [] used_permissions = xmldoc.getElementsByTagName("uses-permission") for item in used_permissions: existing_permission_list.append(item.getAttribute("android:name")) for permission in permissions.split(':'): if permission.lower() not in list(permission_mapping_table.keys()): print( 'Error: permission \'%s\' related API is not supported.' % permission) sys.exit(1) permission_item = permission_mapping_table.get(permission.lower()) if permission_item: for android_permission in permission_item: if android_permission not in existing_permission_list: existing_permission_list.append(android_permission) AddElementAttribute(xmldoc, 'uses-permission', 'android:name', android_permission)
def CustomizeExtensions(app_info, extensions): """Copy the files from external extensions and merge them into APK. The directory of one external extension should be like: myextension/ myextension.jar myextension.js myextension.json That means the name of the internal files should be the same as the directory name. For .jar files, they'll be copied to xwalk-extensions/ and then built into classes.dex in make_apk.py. For .js files, they'll be copied into assets/xwalk-extensions/. For .json files, the'll be merged into one file called extensions-config.json and copied into assets/. """ if not extensions: return name = app_info.android_name app_dir = GetBuildDir(name) apk_assets_path = os.path.join(app_dir, 'assets') extensions_string = 'xwalk-extensions' # Set up the target directories and files. dest_jar_path = os.path.join(app_dir, extensions_string) os.mkdir(dest_jar_path) dest_js_path = os.path.join(apk_assets_path, extensions_string) os.mkdir(dest_js_path) apk_extensions_json_path = os.path.join(apk_assets_path, 'extensions-config.json') # Split the paths into a list. extension_paths = extensions.split(os.pathsep) extension_json_list = [] for source_path in extension_paths: if not os.path.exists(source_path): print('Error: can not find the extension directory \'%s\'.' % source_path) sys.exit(9) # Remove redundant separators to avoid empty basename. source_path = os.path.normpath(source_path) extension_name = os.path.basename(source_path) # Copy .jar file into xwalk-extensions. CopyExtensionFile(extension_name, '.jar', source_path, dest_jar_path) # Copy .js file into assets/xwalk-extensions. CopyExtensionFile(extension_name, '.js', source_path, dest_js_path) # Merge .json file into assets/xwalk-extensions. file_name = extension_name + '.json' src_file = os.path.join(source_path, file_name) if not os.path.isfile(src_file): print('Error: %s was not found in %s.' % (file_name, source_path)) sys.exit(9) else: src_file_handle = open(src_file) src_file_content = src_file_handle.read() json_output = json.JSONDecoder().decode(src_file_content) # Below 3 properties are used by runtime. See extension manager. # And 'permissions' will be merged. if not ('name' in json_output and 'class' in json_output and 'jsapi' in json_output): print( 'Error: properties \'name\', \'class\' and \'jsapi\' in a json ' 'file are mandatory.') sys.exit(9) # Reset the path for JavaScript. js_path_prefix = extensions_string + '/' + extension_name + '/' json_output['jsapi'] = js_path_prefix + json_output['jsapi'] extension_json_list.append(json_output) # Merge the permissions of extensions into AndroidManifest.xml. manifest_path = os.path.join(app_dir, 'AndroidManifest.xml') xmldoc = minidom.parse(manifest_path) if ('permissions' in json_output): # Get used permission list to avoid repetition as "--permissions" # option can also be used to declare used permissions. existingList = [] usedPermissions = xmldoc.getElementsByTagName( "uses-permission") for used in usedPermissions: existingList.append(used.getAttribute("android:name")) # Add the permissions to manifest file if not used yet. for p in json_output['permissions']: if p in existingList: continue AddElementAttribute(xmldoc, 'uses-permission', 'android:name', p) existingList.append(p) # Write to the manifest file to save the update. file_handle = open(manifest_path, 'w') xmldoc.writexml(file_handle, encoding='utf-8') file_handle.close() if 'manifest' in json_output: manifest_merge_path = os.path.join(source_path, json_output['manifest']) if not os.path.isfile(manifest_merge_path): print('Error: %s specified in the extension\'s JSON ' 'could not be found.' % manifest_merge_path) sys.exit(9) xmldoc_merge = minidom.parse(manifest_merge_path) manifest_nodes = xmldoc.getElementsByTagName('manifest') manifest_nodes_merge = xmldoc_merge.getElementsByTagName( 'manifest') if not manifest_nodes: print('Error: %s does not have a <manifest> node.' % manifest_path) sys.exit(9) if not manifest_nodes_merge: print('Error: %s does not have a <manifest> node.' % manifest_merge_path) sys.exit(9) MergeNodes(manifest_nodes[0], manifest_nodes_merge[0]) with open(manifest_path, 'w') as file_handle: xmldoc.writexml(file_handle, encoding='utf-8') # Write configuration of extensions into the target extensions-config.json. if extension_json_list: extensions_string = json.JSONEncoder().encode(extension_json_list) extension_json_file = open(apk_extensions_json_path, 'w') extension_json_file.write(extensions_string) extension_json_file.close()
def CustomizeXML(app_info, description, icon_dict, manifest, permissions): app_version = app_info.app_version app_versionCode = app_info.app_versionCode name = app_info.android_name orientation = app_info.orientation package = app_info.package app_name = app_info.app_name app_dir = GetBuildDir(name) # Chinese character with unicode get from 'manifest.json' will cause # 'UnicodeEncodeError' when finally wrote to 'AndroidManifest.xml'. app_name = EncodingUnicodeValue(app_name) # If string start with '@' or '?', it will be treated as Android resource, # which will cause 'No resource found' error, # append a space before '@' or '?' to fix that. if app_name.startswith('@') or app_name.startswith('?'): app_name = ' ' + app_name manifest_path = os.path.join(app_dir, 'AndroidManifest.xml') if not os.path.isfile(manifest_path): print('Please make sure AndroidManifest.xml' ' exists under template folder.') sys.exit(6) CustomizeStringXML(name, description) CustomizeThemeXML(name, app_info.fullscreen_flag, manifest) xmldoc = minidom.parse(manifest_path) EditElementAttribute(xmldoc, 'manifest', 'package', package) if app_versionCode: EditElementAttribute(xmldoc, 'manifest', 'android:versionCode', str(app_versionCode)) if app_version: EditElementAttribute(xmldoc, 'manifest', 'android:versionName', app_version) if description: EditElementAttribute(xmldoc, 'manifest', 'android:description', "@string/description") HandlePermissions(permissions, xmldoc) if app_info.mode == 'download': AddElementAttribute( xmldoc, 'uses-permission', 'android:name', 'android.permission.DOWNLOAD_WITHOUT_NOTIFICATION') EditElementAttribute(xmldoc, 'application', 'android:label', app_name) activity_name = package + '.' + name + 'Activity' EditElementAttribute(xmldoc, 'activity', 'android:name', activity_name) EditElementAttribute(xmldoc, 'activity', 'android:label', app_name) if orientation: EditElementAttribute(xmldoc, 'activity', 'android:screenOrientation', orientation) icon_name = CustomizeIcon(name, app_info.app_root, app_info.icon, icon_dict) if icon_name: EditElementAttribute(xmldoc, 'application', 'android:icon', '@drawable/%s' % icon_name) if app_info.xwalk_apk_url: meta_data = xmldoc.createElement('meta-data') meta_data.setAttribute('android:name', 'xwalk_apk_url') meta_data.setAttribute('android:value', app_info.xwalk_apk_url) app_node = xmldoc.getElementsByTagName('application')[0] comment = 'The download URL of Crosswalk runtime library APK. \n\ Default updater use the Android download manager to fetch the url' app_node.appendChild(xmldoc.createComment(comment)) app_node.appendChild(meta_data) if app_info.mode == 'download': meta_data = xmldoc.createElement('meta-data') meta_data.setAttribute('android:name', 'xwalk_enable_download_mode') meta_data.setAttribute('android:value', 'enable') comment = 'Make application run in silent download mode.' app_node.appendChild(xmldoc.createComment(comment)) app_node.appendChild(meta_data) file_handle = open(os.path.join(app_dir, 'AndroidManifest.xml'), 'w') xmldoc.writexml(file_handle, encoding='utf-8') file_handle.close()