Loading core/java/android/content/IntentFilter.java +33 −4 Original line number Diff line number Diff line Loading @@ -516,6 +516,38 @@ public class IntentFilter implements Parcelable { return ((mVerifyState & STATE_VERIFY_AUTO) == 1); } /** * 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. * Loading @@ -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(); } /** Loading core/java/android/content/pm/IntentFilterVerificationInfo.java +1 −1 Original line number Diff line number Diff line Loading @@ -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 */ Loading core/java/android/content/pm/PackageParser.java +1 −0 Original line number Diff line number Diff line Loading @@ -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; } } Loading core/java/android/content/pm/ResolveInfo.java +5 −5 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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() { Loading Loading @@ -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 Loading Loading @@ -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 Loading services/core/java/com/android/server/pm/PackageManagerService.java +96 −17 Original line number Diff line number Diff line Loading @@ -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(); Loading @@ -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(); } } Loading Loading @@ -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); Loading @@ -719,17 +716,35 @@ public class PackageManagerService extends IPackageManager.Stub { } } private static boolean hasValidHosts(ArrayList<String> 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"); return false; } // 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) { 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 Loading @@ -739,7 +754,9 @@ public class PackageManagerService extends IPackageManager.Stub { hostEndBase = hostEnd; } if (!hostEnd.equalsIgnoreCase(hostEndBase)) { if (logging) { Slog.d(TAG, "IntentFilter does not contain the same data domains"); } return false; } } Loading Loading @@ -2164,6 +2181,8 @@ public class PackageManagerService extends IPackageManager.Stub { mIntentFilterVerifier = new IntentVerifierProxy(mContext, mIntentFilterVerifierComponent); primeDomainVerificationsLPw(false); } // synchronized (mPackages) } // synchronized (mInstallLock) Loading Loading @@ -2260,6 +2279,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 { Loading Loading @@ -3935,6 +3998,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 Loading @@ -3947,13 +4012,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: " + Loading Loading @@ -7831,7 +7911,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; Loading Loading @@ -11222,9 +11302,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()); } } } Loading @@ -11239,7 +11318,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(); } } Loading Loading
core/java/android/content/IntentFilter.java +33 −4 Original line number Diff line number Diff line Loading @@ -516,6 +516,38 @@ public class IntentFilter implements Parcelable { return ((mVerifyState & STATE_VERIFY_AUTO) == 1); } /** * 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. * Loading @@ -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(); } /** Loading
core/java/android/content/pm/IntentFilterVerificationInfo.java +1 −1 Original line number Diff line number Diff line Loading @@ -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 */ Loading
core/java/android/content/pm/PackageParser.java +1 −0 Original line number Diff line number Diff line Loading @@ -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; } } Loading
core/java/android/content/pm/ResolveInfo.java +5 −5 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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() { Loading Loading @@ -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 Loading Loading @@ -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 Loading
services/core/java/com/android/server/pm/PackageManagerService.java +96 −17 Original line number Diff line number Diff line Loading @@ -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(); Loading @@ -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(); } } Loading Loading @@ -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); Loading @@ -719,17 +716,35 @@ public class PackageManagerService extends IPackageManager.Stub { } } private static boolean hasValidHosts(ArrayList<String> 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"); return false; } // 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) { 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 Loading @@ -739,7 +754,9 @@ public class PackageManagerService extends IPackageManager.Stub { hostEndBase = hostEnd; } if (!hostEnd.equalsIgnoreCase(hostEndBase)) { if (logging) { Slog.d(TAG, "IntentFilter does not contain the same data domains"); } return false; } } Loading Loading @@ -2164,6 +2181,8 @@ public class PackageManagerService extends IPackageManager.Stub { mIntentFilterVerifier = new IntentVerifierProxy(mContext, mIntentFilterVerifierComponent); primeDomainVerificationsLPw(false); } // synchronized (mPackages) } // synchronized (mInstallLock) Loading Loading @@ -2260,6 +2279,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 { Loading Loading @@ -3935,6 +3998,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 Loading @@ -3947,13 +4012,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: " + Loading Loading @@ -7831,7 +7911,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; Loading Loading @@ -11222,9 +11302,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()); } } } Loading @@ -11239,7 +11318,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(); } } Loading