mirror of
https://gitcode.com/github-mirrors/react-native-update-cli.git
synced 2025-09-17 18:06:10 +08:00
217 lines
6.7 KiB
JavaScript
217 lines
6.7 KiB
JavaScript
// From https://github.com/openstf/adbkit-apkreader
|
|
const BinaryXmlParser = require('./binary')
|
|
|
|
const INTENT_MAIN = 'android.intent.action.MAIN'
|
|
const CATEGORY_LAUNCHER = 'android.intent.category.LAUNCHER'
|
|
|
|
class ManifestParser {
|
|
constructor (buffer, options = {}) {
|
|
this.buffer = buffer
|
|
this.xmlParser = new BinaryXmlParser(this.buffer, options)
|
|
}
|
|
|
|
collapseAttributes (element) {
|
|
const collapsed = Object.create(null)
|
|
for (let attr of Array.from(element.attributes)) {
|
|
collapsed[attr.name] = attr.typedValue.value
|
|
}
|
|
return collapsed
|
|
}
|
|
|
|
parseIntents (element, target) {
|
|
target.intentFilters = []
|
|
target.metaData = []
|
|
|
|
return element.childNodes.forEach(element => {
|
|
switch (element.nodeName) {
|
|
case 'intent-filter': {
|
|
const intentFilter = this.collapseAttributes(element)
|
|
|
|
intentFilter.actions = []
|
|
intentFilter.categories = []
|
|
intentFilter.data = []
|
|
|
|
element.childNodes.forEach(element => {
|
|
switch (element.nodeName) {
|
|
case 'action':
|
|
intentFilter.actions.push(this.collapseAttributes(element))
|
|
break
|
|
case 'category':
|
|
intentFilter.categories.push(this.collapseAttributes(element))
|
|
break
|
|
case 'data':
|
|
intentFilter.data.push(this.collapseAttributes(element))
|
|
break
|
|
}
|
|
})
|
|
|
|
target.intentFilters.push(intentFilter)
|
|
break
|
|
}
|
|
case 'meta-data':
|
|
target.metaData.push(this.collapseAttributes(element))
|
|
break
|
|
}
|
|
})
|
|
}
|
|
|
|
parseApplication (element) {
|
|
const app = this.collapseAttributes(element)
|
|
|
|
app.activities = []
|
|
app.activityAliases = []
|
|
app.launcherActivities = []
|
|
app.services = []
|
|
app.receivers = []
|
|
app.providers = []
|
|
app.usesLibraries = []
|
|
app.metaData = []
|
|
|
|
element.childNodes.forEach(element => {
|
|
switch (element.nodeName) {
|
|
case 'activity': {
|
|
const activity = this.collapseAttributes(element)
|
|
this.parseIntents(element, activity)
|
|
app.activities.push(activity)
|
|
if (this.isLauncherActivity(activity)) {
|
|
app.launcherActivities.push(activity)
|
|
}
|
|
break
|
|
}
|
|
case 'activity-alias': {
|
|
const activityAlias = this.collapseAttributes(element)
|
|
this.parseIntents(element, activityAlias)
|
|
app.activityAliases.push(activityAlias)
|
|
if (this.isLauncherActivity(activityAlias)) {
|
|
app.launcherActivities.push(activityAlias)
|
|
}
|
|
break
|
|
}
|
|
case 'service': {
|
|
const service = this.collapseAttributes(element)
|
|
this.parseIntents(element, service)
|
|
app.services.push(service)
|
|
break
|
|
}
|
|
case 'receiver': {
|
|
const receiver = this.collapseAttributes(element)
|
|
this.parseIntents(element, receiver)
|
|
app.receivers.push(receiver)
|
|
break
|
|
}
|
|
case 'provider': {
|
|
const provider = this.collapseAttributes(element)
|
|
|
|
provider.grantUriPermissions = []
|
|
provider.metaData = []
|
|
provider.pathPermissions = []
|
|
|
|
element.childNodes.forEach(element => {
|
|
switch (element.nodeName) {
|
|
case 'grant-uri-permission':
|
|
provider.grantUriPermissions.push(this.collapseAttributes(element))
|
|
break
|
|
case 'meta-data':
|
|
provider.metaData.push(this.collapseAttributes(element))
|
|
break
|
|
case 'path-permission':
|
|
provider.pathPermissions.push(this.collapseAttributes(element))
|
|
break
|
|
}
|
|
})
|
|
|
|
app.providers.push(provider)
|
|
break
|
|
}
|
|
case 'uses-library':
|
|
app.usesLibraries.push(this.collapseAttributes(element))
|
|
break
|
|
case 'meta-data':
|
|
app.metaData.push(this.collapseAttributes(element))
|
|
break
|
|
}
|
|
})
|
|
|
|
return app
|
|
}
|
|
|
|
isLauncherActivity (activity) {
|
|
return activity.intentFilters.some(function (filter) {
|
|
const hasMain = filter.actions.some(action => action.name === INTENT_MAIN)
|
|
if (!hasMain) {
|
|
return false
|
|
}
|
|
return filter.categories.some(category => category.name === CATEGORY_LAUNCHER)
|
|
})
|
|
}
|
|
|
|
parse () {
|
|
const document = this.xmlParser.parse()
|
|
const manifest = this.collapseAttributes(document)
|
|
|
|
manifest.usesPermissions = []
|
|
manifest.usesPermissionsSDK23 = []
|
|
manifest.permissions = []
|
|
manifest.permissionTrees = []
|
|
manifest.permissionGroups = []
|
|
manifest.instrumentation = null
|
|
manifest.usesSdk = null
|
|
manifest.usesConfiguration = null
|
|
manifest.usesFeatures = []
|
|
manifest.supportsScreens = null
|
|
manifest.compatibleScreens = []
|
|
manifest.supportsGlTextures = []
|
|
manifest.application = Object.create(null)
|
|
|
|
document.childNodes.forEach(element => {
|
|
switch (element.nodeName) {
|
|
case 'uses-permission':
|
|
manifest.usesPermissions.push(this.collapseAttributes(element))
|
|
break
|
|
case 'uses-permission-sdk-23':
|
|
manifest.usesPermissionsSDK23.push(this.collapseAttributes(element))
|
|
break
|
|
case 'permission':
|
|
manifest.permissions.push(this.collapseAttributes(element))
|
|
break
|
|
case 'permission-tree':
|
|
manifest.permissionTrees.push(this.collapseAttributes(element))
|
|
break
|
|
case 'permission-group':
|
|
manifest.permissionGroups.push(this.collapseAttributes(element))
|
|
break
|
|
case 'instrumentation':
|
|
manifest.instrumentation = this.collapseAttributes(element)
|
|
break
|
|
case 'uses-sdk':
|
|
manifest.usesSdk = this.collapseAttributes(element)
|
|
break
|
|
case 'uses-configuration':
|
|
manifest.usesConfiguration = this.collapseAttributes(element)
|
|
break
|
|
case 'uses-feature':
|
|
manifest.usesFeatures.push(this.collapseAttributes(element))
|
|
break
|
|
case 'supports-screens':
|
|
manifest.supportsScreens = this.collapseAttributes(element)
|
|
break
|
|
case 'compatible-screens':
|
|
element.childNodes.forEach(screen => {
|
|
return manifest.compatibleScreens.push(this.collapseAttributes(screen))
|
|
})
|
|
break
|
|
case 'supports-gl-texture':
|
|
manifest.supportsGlTextures.push(this.collapseAttributes(element))
|
|
break
|
|
case 'application':
|
|
manifest.application = this.parseApplication(element)
|
|
break
|
|
}
|
|
})
|
|
|
|
return manifest
|
|
}
|
|
}
|
|
|
|
module.exports = ManifestParser
|