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)
Exemplo n.º 2
0
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()
Exemplo n.º 3
0
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()