summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/content/IntentFilter.java37
-rw-r--r--core/java/android/content/pm/IntentFilterVerificationInfo.java2
-rw-r--r--core/java/android/content/pm/PackageParser.java1
-rw-r--r--core/java/android/content/pm/ResolveInfo.java10
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java113
-rw-r--r--services/core/java/com/android/server/pm/Settings.java12
6 files changed, 142 insertions, 33 deletions
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index 590d791b8195..044e3e3c303f 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -517,6 +517,38 @@ public class IntentFilter implements Parcelable {
}
/**
+ * Return if this filter handle all HTTP or HTTPS data URI or not.
+ *
+ * @return True if the filter handle all HTTP or HTTPS data URI. False otherwise.
+ *
+ * This will check if if the Intent action is {@link android.content.Intent#ACTION_VIEW} and
+ * the Intent category is {@link android.content.Intent#CATEGORY_BROWSABLE} and the Intent
+ * data scheme is "http" or "https" and that there is no specific host defined.
+ *
+ * @hide
+ */
+ public final boolean handleAllWebDataURI() {
+ return hasWebDataURI() && (countDataAuthorities() == 0);
+ }
+
+ /**
+ * Return if this filter has any HTTP or HTTPS data URI or not.
+ *
+ * @return True if the filter has any HTTP or HTTPS data URI. False otherwise.
+ *
+ * This will check if if the Intent action is {@link android.content.Intent#ACTION_VIEW} and
+ * the Intent category is {@link android.content.Intent#CATEGORY_BROWSABLE} and the Intent
+ * data scheme is "http" or "https".
+ *
+ * @hide
+ */
+ public final boolean hasWebDataURI() {
+ return hasAction(Intent.ACTION_VIEW) &&
+ hasCategory(Intent.CATEGORY_BROWSABLE) &&
+ (hasDataScheme(SCHEME_HTTP) || hasDataScheme(SCHEME_HTTPS));
+ }
+
+ /**
* Return if this filter needs to be automatically verified again its data URIs or not.
*
* @return True if the filter needs to be automatically verified. False otherwise.
@@ -530,10 +562,7 @@ public class IntentFilter implements Parcelable {
* @hide
*/
public final boolean needsVerification() {
- return hasAction(Intent.ACTION_VIEW) &&
- hasCategory(Intent.CATEGORY_BROWSABLE) &&
- (hasDataScheme(SCHEME_HTTP) || hasDataScheme(SCHEME_HTTPS)) &&
- getAutoVerify();
+ return hasWebDataURI() && getAutoVerify();
}
/**
diff --git a/core/java/android/content/pm/IntentFilterVerificationInfo.java b/core/java/android/content/pm/IntentFilterVerificationInfo.java
index 28cbaa8852b7..e50b0ff17a0a 100644
--- a/core/java/android/content/pm/IntentFilterVerificationInfo.java
+++ b/core/java/android/content/pm/IntentFilterVerificationInfo.java
@@ -36,7 +36,7 @@ import java.util.ArrayList;
/**
* The {@link com.android.server.pm.PackageManagerService} maintains some
- * {@link IntentFilterVerificationInfo}s for each domain / package / class name per user.
+ * {@link IntentFilterVerificationInfo}s for each domain / package name.
*
* @hide
*/
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index bdbed7551cae..6b9d3f8a79d2 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -2794,6 +2794,7 @@ public class PackageParser {
if (!aii.hasAction(Intent.ACTION_VIEW)) continue;
if (aii.hasDataScheme(IntentFilter.SCHEME_HTTP) ||
aii.hasDataScheme(IntentFilter.SCHEME_HTTPS)) {
+ Slog.d(TAG, "hasDomainURLs:true for package:" + pkg.packageName);
return true;
}
}
diff --git a/core/java/android/content/pm/ResolveInfo.java b/core/java/android/content/pm/ResolveInfo.java
index 7b141f050e67..05f5e90e56d7 100644
--- a/core/java/android/content/pm/ResolveInfo.java
+++ b/core/java/android/content/pm/ResolveInfo.java
@@ -144,9 +144,9 @@ public class ResolveInfo implements Parcelable {
public boolean system;
/**
- * @hide Does the associated IntentFilter needs verification ?
+ * @hide Does the associated IntentFilter comes from a Browser ?
*/
- public boolean filterNeedsVerification;
+ public boolean handleAllWebDataURI;
private ComponentInfo getComponentInfo() {
if (activityInfo != null) return activityInfo;
@@ -288,7 +288,7 @@ public class ResolveInfo implements Parcelable {
resolvePackageName = orig.resolvePackageName;
system = orig.system;
targetUserId = orig.targetUserId;
- filterNeedsVerification = orig.filterNeedsVerification;
+ handleAllWebDataURI = orig.handleAllWebDataURI;
}
public String toString() {
@@ -350,7 +350,7 @@ public class ResolveInfo implements Parcelable {
dest.writeInt(targetUserId);
dest.writeInt(system ? 1 : 0);
dest.writeInt(noResourceId ? 1 : 0);
- dest.writeInt(filterNeedsVerification ? 1 : 0);
+ dest.writeInt(handleAllWebDataURI ? 1 : 0);
}
public static final Creator<ResolveInfo> CREATOR
@@ -396,7 +396,7 @@ public class ResolveInfo implements Parcelable {
targetUserId = source.readInt();
system = source.readInt() != 0;
noResourceId = source.readInt() != 0;
- filterNeedsVerification = source.readInt() != 0;
+ handleAllWebDataURI = source.readInt() != 0;
}
public static class DisplayNameComparator
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 80a4351d08dc..42b4aaf0d906 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -560,7 +560,6 @@ public class PackageManagerService extends IPackageManager.Stub {
mIntentFilterVerificationStates.get(verificationId);
String packageName = ivs.getPackageName();
- boolean modified = false;
ArrayList<PackageParser.ActivityIntentInfo> filters = ivs.getFilters();
final int filterCount = filters.size();
@@ -571,9 +570,8 @@ public class PackageManagerService extends IPackageManager.Stub {
}
ArrayList<String> domainsList = new ArrayList<>(domainsSet);
synchronized (mPackages) {
- modified = mSettings.createIntentFilterVerificationIfNeededLPw(
- packageName, domainsList);
- if (modified) {
+ if (mSettings.createIntentFilterVerificationIfNeededLPw(
+ packageName, domainsList) != null) {
scheduleWriteSettingsLocked();
}
}
@@ -698,8 +696,7 @@ public class PackageManagerService extends IPackageManager.Stub {
ivs = createDomainVerificationState(verifierId, userId, verificationId,
packageName);
}
- ArrayList<String> hosts = filter.getHostsList();
- if (!hasValidHosts(hosts)) {
+ if (!hasValidDomains(filter)) {
return false;
}
ivs.addFilter(filter);
@@ -719,17 +716,35 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
- private static boolean hasValidHosts(ArrayList<String> hosts) {
- if (hosts.size() == 0) {
- Slog.d(TAG, "IntentFilter does not contain any data hosts");
+ private static boolean hasValidDomains(ActivityIntentInfo filter) {
+ return hasValidDomains(filter, true);
+ }
+
+ private static boolean hasValidDomains(ActivityIntentInfo filter, boolean logging) {
+ boolean hasHTTPorHTTPS = filter.hasDataScheme(IntentFilter.SCHEME_HTTP) ||
+ filter.hasDataScheme(IntentFilter.SCHEME_HTTPS);
+ if (!hasHTTPorHTTPS) {
+ if (logging) {
+ Slog.d(TAG, "IntentFilter does not contain any HTTP or HTTPS data scheme");
+ }
return false;
}
+ ArrayList<String> hosts = filter.getHostsList();
+ if (hosts.size() == 0) {
+ if (logging) {
+ Slog.d(TAG, "IntentFilter does not contain any data hosts");
+ }
+ // We still return true as this is the case of any Browser
+ return true;
+ }
String hostEndBase = null;
for (String host : hosts) {
String[] hostParts = host.split("\\.");
// Should be at minimum a host like "example.com"
if (hostParts.length < 2) {
- Slog.d(TAG, "IntentFilter does not contain a valid data host name: " + host);
+ if (logging) {
+ Slog.d(TAG, "IntentFilter does not contain a valid data host name: " + host);
+ }
return false;
}
// Verify that we have the same ending domain
@@ -739,7 +754,9 @@ public class PackageManagerService extends IPackageManager.Stub {
hostEndBase = hostEnd;
}
if (!hostEnd.equalsIgnoreCase(hostEndBase)) {
- Slog.d(TAG, "IntentFilter does not contain the same data domains");
+ if (logging) {
+ Slog.d(TAG, "IntentFilter does not contain the same data domains");
+ }
return false;
}
}
@@ -2176,6 +2193,8 @@ public class PackageManagerService extends IPackageManager.Stub {
mIntentFilterVerifier = new IntentVerifierProxy(mContext,
mIntentFilterVerifierComponent);
+ primeDomainVerificationsLPw(false);
+
} // synchronized (mPackages)
} // synchronized (mInstallLock)
@@ -2272,6 +2291,50 @@ public class PackageManagerService extends IPackageManager.Stub {
return verifierComponentName;
}
+ private void primeDomainVerificationsLPw(boolean logging) {
+ Slog.d(TAG, "Start priming domain verification");
+ boolean updated = false;
+ ArrayList<String> allHosts = new ArrayList<>();
+ for (PackageParser.Package pkg : mPackages.values()) {
+ final String packageName = pkg.packageName;
+ if (!hasDomainURLs(pkg)) {
+ if (logging) {
+ Slog.d(TAG, "No priming domain verifications for " +
+ "package with no domain URLs: " + packageName);
+ }
+ continue;
+ }
+ for (PackageParser.Activity a : pkg.activities) {
+ for (ActivityIntentInfo filter : a.intents) {
+ if (hasValidDomains(filter, false)) {
+ allHosts.addAll(filter.getHostsList());
+ }
+ }
+ }
+ if (allHosts.size() > 0) {
+ allHosts.add("*");
+ }
+ IntentFilterVerificationInfo ivi =
+ mSettings.createIntentFilterVerificationIfNeededLPw(packageName, allHosts);
+ if (ivi != null) {
+ // We will always log this
+ Slog.d(TAG, "Priming domain verifications for package: " + packageName);
+ ivi.setStatus(INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS);
+ updated = true;
+ }
+ else {
+ if (logging) {
+ Slog.d(TAG, "No priming domain verifications for package: " + packageName);
+ }
+ }
+ allHosts.clear();
+ }
+ if (updated) {
+ scheduleWriteSettingsLocked();
+ }
+ Slog.d(TAG, "End priming domain verification");
+ }
+
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
@@ -3947,6 +4010,8 @@ public class PackageManagerService extends IPackageManager.Stub {
}
final int userId = UserHandle.getCallingUserId();
ArrayList<ResolveInfo> result = new ArrayList<ResolveInfo>();
+ ArrayList<ResolveInfo> neverList = new ArrayList<ResolveInfo>();
+ ArrayList<ResolveInfo> matchAllList = new ArrayList<ResolveInfo>();
synchronized (mPackages) {
final int count = candidates.size();
// First, try to use the domain prefered App
@@ -3959,13 +4024,28 @@ public class PackageManagerService extends IPackageManager.Stub {
int status = getDomainVerificationStatusLPr(ps, userId);
if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS) {
result.add(info);
+ } else if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER) {
+ neverList.add(info);
+ }
+ // Add to the special match all list (Browser use case)
+ if (info.handleAllWebDataURI) {
+ matchAllList.add(info);
}
}
}
- // There is not much we can do, add all candidates
+ // If there is nothing selected, add all candidates and remove the ones that the User
+ // has explicitely put into the INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER state and
+ // also remove any .
+ // If there is still none after this pass, add all Browser Apps and let the User decide
+ // with the Disambiguation dialog if there are several ones.
if (result.size() == 0) {
result.addAll(candidates);
}
+ result.removeAll(neverList);
+ result.removeAll(matchAllList);
+ if (result.size() == 0) {
+ result.addAll(matchAllList);
+ }
}
if (DEBUG_PREFERRED) {
Slog.v("TAG", "Filtered results with prefered activities. New candidates count: " +
@@ -7843,7 +7923,7 @@ public class PackageManagerService extends IPackageManager.Stub {
res.filter = info;
}
if (info != null) {
- res.filterNeedsVerification = info.needsVerification();
+ res.handleAllWebDataURI = info.handleAllWebDataURI();
}
res.priority = info.getPriority();
res.preferredOrder = activity.owner.mPreferredOrder;
@@ -11234,9 +11314,8 @@ public class PackageManagerService extends IPackageManager.Stub {
count++;
} else {
Slog.d(TAG, "No verification needed for IntentFilter:" + filter.toString());
- ArrayList<String> list = filter.getHostsList();
- if (hasValidHosts(list)) {
- allHosts.addAll(list);
+ if (hasValidDomains(filter)) {
+ allHosts.addAll(filter.getHostsList());
}
}
}
@@ -11251,7 +11330,7 @@ public class PackageManagerService extends IPackageManager.Stub {
Slog.d(TAG, "No need to start any IntentFilter verification!");
if (allHosts.size() > 0 && hasDomainURLs(pkg) &&
mSettings.createIntentFilterVerificationIfNeededLPw(
- packageName, allHosts)) {
+ packageName, allHosts) != null) {
scheduleWriteSettingsLocked();
}
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 2e2053d54ce8..bfcc3db66370 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -966,19 +966,19 @@ final class Settings {
}
/* package protected */
- boolean createIntentFilterVerificationIfNeededLPw(String packageName,
+ IntentFilterVerificationInfo createIntentFilterVerificationIfNeededLPw(String packageName,
ArrayList<String> domains) {
PackageSetting ps = mPackages.get(packageName);
if (ps == null) {
Slog.w(PackageManagerService.TAG, "No package known for name: " + packageName);
- return false;
+ return null;
}
- if (ps.getIntentFilterVerificationInfo() == null) {
- IntentFilterVerificationInfo ivi = new IntentFilterVerificationInfo(packageName, domains);
+ IntentFilterVerificationInfo ivi = ps.getIntentFilterVerificationInfo();
+ if (ivi == null) {
+ ivi = new IntentFilterVerificationInfo(packageName, domains);
ps.setIntentFilterVerificationInfo(ivi);
- return true;
}
- return false;
+ return ivi;
}
int getIntentFilterVerificationStatusLPr(String packageName, int userId) {