Skip to content

Commit 78aaf45

Browse files
feat: Add a possibility to grant/revoke all application permissions (#768)
1 parent 157dbe2 commit 78aaf45

File tree

1 file changed

+34
-15
lines changed

1 file changed

+34
-15
lines changed

lib/commands/general.js

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ import { util } from 'appium/support';
44
import moment from 'moment';
55
import { longSleep } from 'asyncbox';
66
import { errors } from 'appium/driver';
7+
import B from 'bluebird';
78

89
const MOMENT_FORMAT_ISO8601 = 'YYYY-MM-DDTHH:mm:ssZ';
10+
const ALL_PERMISSIONS_MAGIC = 'all';
911

1012
let commands = {}, helpers = {}, extensions = {};
1113

@@ -309,7 +311,10 @@ const PERMISSION_ACTION = {
309311
/**
310312
* @typedef {Object} ChangePermissionsOptions
311313
* @property {!string|Array<string>} permissions - The full name of the permission to be changed
312-
* or a list of permissions. Mandatory argument.
314+
* or a list of permissions. Check https://developer.android.com/reference/android/Manifest.permission
315+
* to get the full list of standard Android permssion names. Mandatory argument.
316+
* If 'all' magic string is passed then the chosen action is going to be applied to all
317+
* permisisons requested/granted by 'appPackage'.
313318
* @property {string} appPackage [this.opts.appPackage] - The application package to set change
314319
* permissions on. Defaults to the package name under test.
315320
* @property {string} action [grant] - One of `PERMISSION_ACTION` values
@@ -327,24 +332,38 @@ commands.mobileChangePermissions = async function mobileChangePermissions (opts
327332
appPackage = this.opts.appPackage,
328333
action = PERMISSION_ACTION.GRANT,
329334
} = opts;
330-
if (!util.hasValue(permissions)) {
335+
if (_.isNil(permissions)) {
331336
throw new errors.InvalidArgumentError(`'permissions' argument is required`);
332337
}
338+
if (_.isEmpty(permissions)) {
339+
throw new errors.InvalidArgumentError(`'permissions' argument must not be empty`);
340+
}
341+
const lowerAction = _.toLower(action);
342+
if (![PERMISSION_ACTION.GRANT, PERMISSION_ACTION.REVOKE].includes(lowerAction)) {
343+
throw new errors.InvalidArgumentError(`Unknown action '${action}'. ` +
344+
`Only ${JSON.stringify(_.values(PERMISSION_ACTION))} actions are supported`);
345+
}
333346

334-
let actionFunc;
335-
switch (_.toLower(action)) {
336-
case PERMISSION_ACTION.GRANT:
337-
actionFunc = (appPackage, permission) => this.adb.grantPermission(appPackage, permission);
338-
break;
339-
case PERMISSION_ACTION.REVOKE:
340-
actionFunc = (appPackage, permission) => this.adb.revokePermission(appPackage, permission);
341-
break;
342-
default:
343-
throw new errors.InvalidArgumentError(`Unknown action '${action}'. ` +
344-
`Only ${JSON.stringify(_.values(PERMISSION_ACTION))} actions are supported`);
347+
let affectedPermissions = _.isArray(permissions) ? permissions : [permissions];
348+
if (_.toLower(permissions) === ALL_PERMISSIONS_MAGIC) {
349+
const dumpsys = await this.adb.shell(['dumpsys', 'package', appPackage]);
350+
const grantedPermissions = await this.adb.getGrantedPermissions(appPackage, dumpsys);
351+
if (lowerAction === PERMISSION_ACTION.GRANT) {
352+
const reqPermissons = await this.adb.getReqPermissions(appPackage, dumpsys);
353+
affectedPermissions = _.difference(reqPermissons, grantedPermissions);
354+
} else {
355+
affectedPermissions = grantedPermissions;
356+
}
357+
if (_.isEmpty(affectedPermissions)) {
358+
this.log.info(`'${appPackage}' contains no permissions to ${lowerAction}`);
359+
return;
360+
}
345361
}
346-
for (const permission of (_.isArray(permissions) ? permissions : [permissions])) {
347-
await actionFunc(appPackage, permission);
362+
363+
if (lowerAction === PERMISSION_ACTION.GRANT) {
364+
await this.adb.grantPermissions(appPackage, affectedPermissions);
365+
} else {
366+
await B.all(affectedPermissions.map((name) => this.adb.revokePermission(appPackage, name)));
348367
}
349368
};
350369

0 commit comments

Comments
 (0)