Revoke domain user selection when approved through shell
This branch existed for the API, but not for the internal method used for shell. Bug: 183226822 Test: manual, debug while writing CTS Change-Id: If19bf9395f445249c3ca3b93b7f6d1a1bad3c5d8
This commit is contained in:
@@ -357,6 +357,8 @@ public class DomainVerificationService extends SystemService
|
||||
"State must be one of NO_RESPONSE, SUCCESS, APPROVED, or DENIED");
|
||||
}
|
||||
|
||||
ArraySet<String> verifiedDomains = new ArraySet<>();
|
||||
|
||||
if (packageName == null) {
|
||||
synchronized (mLock) {
|
||||
ArraySet<String> validDomains = new ArraySet<>();
|
||||
@@ -383,6 +385,10 @@ public class DomainVerificationService extends SystemService
|
||||
validDomains.retainAll(autoVerifyDomains);
|
||||
}
|
||||
|
||||
if (DomainVerificationState.isVerified(state)) {
|
||||
verifiedDomains.addAll(validDomains);
|
||||
}
|
||||
|
||||
setDomainVerificationStatusInternal(pkgState, state, validDomains);
|
||||
}
|
||||
}
|
||||
@@ -405,10 +411,22 @@ public class DomainVerificationService extends SystemService
|
||||
domains.retainAll(mCollector.collectValidAutoVerifyDomains(pkg));
|
||||
}
|
||||
|
||||
if (DomainVerificationState.isVerified(state)) {
|
||||
verifiedDomains.addAll(domains);
|
||||
}
|
||||
|
||||
setDomainVerificationStatusInternal(pkgState, state, domains);
|
||||
}
|
||||
}
|
||||
|
||||
// Mirror SystemApi behavior of revoking user selection for approved domains.
|
||||
if (DomainVerificationState.isVerified(state)) {
|
||||
final int size = verifiedDomains.size();
|
||||
for (int index = 0; index < size; index++) {
|
||||
removeUserStatesForDomain(verifiedDomains.valueAt(index));
|
||||
}
|
||||
}
|
||||
|
||||
mConnection.scheduleWriteSettings();
|
||||
}
|
||||
|
||||
@@ -522,47 +540,9 @@ public class DomainVerificationService extends SystemService
|
||||
// enabling. This allows an escape hatch in case multiple packages somehow get selected.
|
||||
// They can be disabled without blocking in a circular dependency.
|
||||
if (enabled) {
|
||||
// Cache the approved packages from the 1st pass because the search is expensive
|
||||
ArrayMap<String, List<String>> domainToApprovedPackages = new ArrayMap<>();
|
||||
|
||||
for (String domain : domains) {
|
||||
if (userState.getEnabledHosts().contains(domain)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Pair<List<String>, Integer> packagesToLevel = getApprovedPackages(domain,
|
||||
userId, APPROVAL_LEVEL_NONE + 1, mConnection::getPackageSettingLocked);
|
||||
int highestApproval = packagesToLevel.second;
|
||||
if (highestApproval > APPROVAL_LEVEL_SELECTION) {
|
||||
return DomainVerificationManager.ERROR_UNABLE_TO_APPROVE;
|
||||
}
|
||||
|
||||
domainToApprovedPackages.put(domain, packagesToLevel.first);
|
||||
}
|
||||
|
||||
// The removal for other packages must be done in a 2nd pass after it's determined
|
||||
// that no higher priority owners exist for all of the domains in the set.
|
||||
int mapSize = domainToApprovedPackages.size();
|
||||
for (int mapIndex = 0; mapIndex < mapSize; mapIndex++) {
|
||||
String domain = domainToApprovedPackages.keyAt(mapIndex);
|
||||
List<String> approvedPackages = domainToApprovedPackages.valueAt(mapIndex);
|
||||
int approvedSize = approvedPackages.size();
|
||||
for (int approvedIndex = 0; approvedIndex < approvedSize; approvedIndex++) {
|
||||
String approvedPackage = approvedPackages.get(approvedIndex);
|
||||
DomainVerificationPkgState approvedPkgState =
|
||||
mAttachedPkgStates.get(approvedPackage);
|
||||
if (approvedPkgState == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DomainVerificationInternalUserState approvedUserState =
|
||||
approvedPkgState.getUserState(userId);
|
||||
if (approvedUserState == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
approvedUserState.removeHost(domain);
|
||||
}
|
||||
int statusCode = revokeOtherUserSelections(userState, userId, domains);
|
||||
if (statusCode != DomainVerificationManager.STATUS_OK) {
|
||||
return statusCode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -579,83 +559,99 @@ public class DomainVerificationService extends SystemService
|
||||
|
||||
@Override
|
||||
public void setDomainVerificationUserSelectionInternal(@UserIdInt int userId,
|
||||
@Nullable String packageName, boolean enabled, @Nullable ArraySet<String> domains)
|
||||
@NonNull String packageName, boolean enabled, @Nullable ArraySet<String> domains)
|
||||
throws NameNotFoundException {
|
||||
mEnforcer.assertInternal(mConnection.getCallingUid());
|
||||
|
||||
|
||||
if (packageName == null) {
|
||||
synchronized (mLock) {
|
||||
Set<String> validDomains = new ArraySet<>();
|
||||
int size = mAttachedPkgStates.size();
|
||||
for (int index = 0; index < size; index++) {
|
||||
DomainVerificationPkgState pkgState = mAttachedPkgStates.valueAt(index);
|
||||
String pkgName = pkgState.getPackageName();
|
||||
PackageSetting pkgSetting = mConnection.getPackageSettingLocked(pkgName);
|
||||
AndroidPackage pkg = pkgSetting == null ? null : pkgSetting.getPkg();
|
||||
if (pkg == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (domains == null) {
|
||||
validDomains = mCollector.collectAllWebDomains(pkg);
|
||||
} else {
|
||||
validDomains.clear();
|
||||
validDomains.addAll(domains);
|
||||
}
|
||||
|
||||
setDomainVerificationUserSelectionInternal(userId, pkgState,
|
||||
pkg, enabled, validDomains);
|
||||
}
|
||||
synchronized (mLock) {
|
||||
DomainVerificationPkgState pkgState = mAttachedPkgStates.get(packageName);
|
||||
if (pkgState == null) {
|
||||
throw DomainVerificationUtils.throwPackageUnavailable(packageName);
|
||||
}
|
||||
} else {
|
||||
synchronized (mLock) {
|
||||
DomainVerificationPkgState pkgState = mAttachedPkgStates.get(packageName);
|
||||
if (pkgState == null) {
|
||||
throw DomainVerificationUtils.throwPackageUnavailable(packageName);
|
||||
|
||||
PackageSetting pkgSetting = mConnection.getPackageSettingLocked(packageName);
|
||||
AndroidPackage pkg = pkgSetting == null ? null : pkgSetting.getPkg();
|
||||
if (pkg == null) {
|
||||
throw DomainVerificationUtils.throwPackageUnavailable(packageName);
|
||||
}
|
||||
|
||||
Set<String> validDomains =
|
||||
domains == null ? mCollector.collectAllWebDomains(pkg) : domains;
|
||||
|
||||
validDomains.retainAll(mCollector.collectAllWebDomains(pkg));
|
||||
|
||||
if (userId == UserHandle.USER_ALL) {
|
||||
for (int aUserId : mConnection.getAllUserIds()) {
|
||||
DomainVerificationInternalUserState userState =
|
||||
pkgState.getOrCreateUserState(aUserId);
|
||||
revokeOtherUserSelections(userState, aUserId, validDomains);
|
||||
if (enabled) {
|
||||
userState.addHosts(validDomains);
|
||||
} else {
|
||||
userState.removeHosts(validDomains);
|
||||
}
|
||||
}
|
||||
|
||||
PackageSetting pkgSetting = mConnection.getPackageSettingLocked(packageName);
|
||||
AndroidPackage pkg = pkgSetting == null ? null : pkgSetting.getPkg();
|
||||
if (pkg == null) {
|
||||
throw DomainVerificationUtils.throwPackageUnavailable(packageName);
|
||||
} else {
|
||||
DomainVerificationInternalUserState userState =
|
||||
pkgState.getOrCreateUserState(userId);
|
||||
revokeOtherUserSelections(userState, userId, validDomains);
|
||||
if (enabled) {
|
||||
userState.addHosts(validDomains);
|
||||
} else {
|
||||
userState.removeHosts(validDomains);
|
||||
}
|
||||
|
||||
Set<String> validDomains =
|
||||
domains == null ? mCollector.collectAllWebDomains(pkg) : domains;
|
||||
|
||||
setDomainVerificationUserSelectionInternal(userId, pkgState, pkgSetting.getPkg(),
|
||||
enabled, validDomains);
|
||||
}
|
||||
}
|
||||
|
||||
mConnection.scheduleWriteSettings();
|
||||
}
|
||||
|
||||
private void setDomainVerificationUserSelectionInternal(int userId,
|
||||
@NonNull DomainVerificationPkgState pkgState, @NonNull AndroidPackage pkg,
|
||||
boolean enabled, Set<String> domains) {
|
||||
domains.retainAll(mCollector.collectAllWebDomains(pkg));
|
||||
private int revokeOtherUserSelections(@NonNull DomainVerificationInternalUserState userState,
|
||||
@UserIdInt int userId, @NonNull Set<String> domains) {
|
||||
// Cache the approved packages from the 1st pass because the search is expensive
|
||||
ArrayMap<String, List<String>> domainToApprovedPackages = new ArrayMap<>();
|
||||
|
||||
if (userId == UserHandle.USER_ALL) {
|
||||
for (int aUserId : mConnection.getAllUserIds()) {
|
||||
DomainVerificationInternalUserState userState =
|
||||
pkgState.getOrCreateUserState(aUserId);
|
||||
if (enabled) {
|
||||
userState.addHosts(domains);
|
||||
} else {
|
||||
userState.removeHosts(domains);
|
||||
}
|
||||
for (String domain : domains) {
|
||||
if (userState.getEnabledHosts().contains(domain)) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
DomainVerificationInternalUserState userState =
|
||||
pkgState.getOrCreateUserState(userId);
|
||||
if (enabled) {
|
||||
userState.addHosts(domains);
|
||||
} else {
|
||||
userState.removeHosts(domains);
|
||||
|
||||
Pair<List<String>, Integer> packagesToLevel = getApprovedPackages(domain,
|
||||
userId, APPROVAL_LEVEL_NONE + 1, mConnection::getPackageSettingLocked);
|
||||
int highestApproval = packagesToLevel.second;
|
||||
if (highestApproval > APPROVAL_LEVEL_SELECTION) {
|
||||
return DomainVerificationManager.ERROR_UNABLE_TO_APPROVE;
|
||||
}
|
||||
|
||||
domainToApprovedPackages.put(domain, packagesToLevel.first);
|
||||
}
|
||||
|
||||
// The removal for other packages must be done in a 2nd pass after it's determined
|
||||
// that no higher priority owners exist for all of the domains in the set.
|
||||
int mapSize = domainToApprovedPackages.size();
|
||||
for (int mapIndex = 0; mapIndex < mapSize; mapIndex++) {
|
||||
String domain = domainToApprovedPackages.keyAt(mapIndex);
|
||||
List<String> approvedPackages = domainToApprovedPackages.valueAt(mapIndex);
|
||||
int approvedSize = approvedPackages.size();
|
||||
for (int approvedIndex = 0; approvedIndex < approvedSize; approvedIndex++) {
|
||||
String approvedPackage = approvedPackages.get(approvedIndex);
|
||||
DomainVerificationPkgState approvedPkgState =
|
||||
mAttachedPkgStates.get(approvedPackage);
|
||||
if (approvedPkgState == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DomainVerificationInternalUserState approvedUserState =
|
||||
approvedPkgState.getUserState(userId);
|
||||
if (approvedUserState == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
approvedUserState.removeHost(domain);
|
||||
}
|
||||
}
|
||||
|
||||
return DomainVerificationManager.STATUS_OK;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -89,7 +89,7 @@ public class DomainVerificationShell {
|
||||
pw.println(" must be declared by the package for this to work. This command will not");
|
||||
pw.println(" report a failure for domains that could not be applied.");
|
||||
pw.println(" --user <USER_ID>: the user to change selections for");
|
||||
pw.println(" --package <PACKAGE>: the package to set, or \"all\" to set all packages");
|
||||
pw.println(" --package <PACKAGE>: the package to set");
|
||||
pw.println(" <ENABLED>: whether or not to approve the domain");
|
||||
pw.println(" <DOMAINS>: space separated list of domains to change, or \"all\" to");
|
||||
pw.println(" change every domain.");
|
||||
@@ -217,8 +217,6 @@ public class DomainVerificationShell {
|
||||
if (TextUtils.isEmpty(packageName)) {
|
||||
commandHandler.getErrPrintWriter().println("Error: no package specified");
|
||||
return false;
|
||||
} else if (packageName.equalsIgnoreCase("all")) {
|
||||
packageName = null;
|
||||
}
|
||||
|
||||
if (userId == null) {
|
||||
@@ -469,13 +467,15 @@ public class DomainVerificationShell {
|
||||
* Variant for use by PackageManagerShellCommand to allow the system/developer to override
|
||||
* the state for a domain.
|
||||
*
|
||||
* @param packageName the package whose state to change, or all packages if non is
|
||||
* specified
|
||||
* If an approval fails because of a higher level owner, this method will silently skip the
|
||||
* domain.
|
||||
*
|
||||
* @param packageName the package whose state to change
|
||||
* @param enabled whether the domain is now approved by the user
|
||||
* @param domains the set of domains to change, or null to affect all domains
|
||||
*/
|
||||
void setDomainVerificationUserSelectionInternal(@UserIdInt int userId,
|
||||
@Nullable String packageName, boolean enabled, @Nullable ArraySet<String> domains)
|
||||
@NonNull String packageName, boolean enabled, @Nullable ArraySet<String> domains)
|
||||
throws PackageManager.NameNotFoundException;
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user