Loading core/java/android/webkit/WebViewProviderInfo.java +8 −118 Original line number Diff line number Diff line Loading @@ -16,32 +16,16 @@ package android.webkit; import android.app.AppGlobals; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.Signature; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; import android.util.AndroidRuntimeException; import android.util.Base64; import java.util.Arrays; /** @hide */ public class WebViewProviderInfo implements Parcelable { public final class WebViewProviderInfo implements Parcelable { /** * @hide */ public static class WebViewPackageNotFoundException extends AndroidRuntimeException { public WebViewPackageNotFoundException(String message) { super(message); } public WebViewPackageNotFoundException(Exception e) { super(e); } } public WebViewProviderInfo(String packageName, String description, boolean availableByDefault, boolean isFallback, String[] signatures) { public WebViewProviderInfo(String packageName, String description, boolean availableByDefault, boolean isFallback, String[] signatures) { this.packageName = packageName; this.description = description; this.availableByDefault = availableByDefault; Loading @@ -49,92 +33,6 @@ public class WebViewProviderInfo implements Parcelable { this.signatures = signatures; } private boolean hasValidSignature() { if (Build.IS_DEBUGGABLE) return true; Signature[] packageSignatures; try { // If no signature is declared, instead check whether the package is included in the // system. if (signatures == null || signatures.length == 0) return getPackageInfo().applicationInfo.isSystemApp(); packageSignatures = getPackageInfo().signatures; } catch (WebViewPackageNotFoundException e) { return false; } if (packageSignatures.length != 1) return false; final byte[] packageSignature = packageSignatures[0].toByteArray(); // Return whether the package signature matches any of the valid signatures for (String signature : signatures) { final byte[] validSignature = Base64.decode(signature, Base64.DEFAULT); if (Arrays.equals(packageSignature, validSignature)) return true; } return false; } /** * Returns whether this provider is valid for use as a WebView provider. */ public boolean isValidProvider() { ApplicationInfo applicationInfo; try { applicationInfo = getPackageInfo().applicationInfo; } catch (WebViewPackageNotFoundException e) { return false; } if (hasValidSignature() && WebViewFactory.getWebViewLibrary(applicationInfo) != null) { return true; } return false; } /** * Returns whether this package is enabled. * This state can be changed by the user from Settings->Apps */ public boolean isEnabled() { try { // Explicitly fetch up-to-date package info here since the enabled-state of the package // might have changed since we last fetched its package info. updatePackageInfo(); return getPackageInfo().applicationInfo.enabled; } catch (WebViewPackageNotFoundException e) { return false; } } /** * Returns whether the provider is always available as long as it is valid. * If this returns false, the provider will only be used if the user chose this provider. */ public boolean isAvailableByDefault() { return availableByDefault; } public boolean isFallbackPackage() { return isFallback; } private void updatePackageInfo() { try { PackageManager pm = AppGlobals.getInitialApplication().getPackageManager(); packageInfo = pm.getPackageInfo(packageName, PACKAGE_FLAGS); } catch (PackageManager.NameNotFoundException e) { throw new WebViewPackageNotFoundException(e); } } public PackageInfo getPackageInfo() { if (packageInfo == null) { updatePackageInfo(); } return packageInfo; } // aidl stuff public static final Parcelable.Creator<WebViewProviderInfo> CREATOR = new Parcelable.Creator<WebViewProviderInfo>() { Loading @@ -153,7 +51,6 @@ public class WebViewProviderInfo implements Parcelable { availableByDefault = (in.readInt() > 0); isFallback = (in.readInt() > 0); signatures = in.createStringArray(); packageInfo = null; } @Override Loading @@ -171,16 +68,9 @@ public class WebViewProviderInfo implements Parcelable { } // fields read from framework resource public String packageName; public String description; private boolean availableByDefault; private boolean isFallback; private String[] signatures; private PackageInfo packageInfo; // flags declaring we want extra info from the package manager private final static int PACKAGE_FLAGS = PackageManager.GET_META_DATA | PackageManager.GET_SIGNATURES | PackageManager.MATCH_DEBUG_TRIAGED_MISSING; public final String packageName; public final String description; public final boolean availableByDefault; public final boolean isFallback; public final String[] signatures; } services/core/java/com/android/server/webkit/WebViewUpdateService.java +124 −55 Original line number Diff line number Diff line Loading @@ -26,9 +26,11 @@ import android.content.pm.ApplicationInfo; import android.content.pm.IPackageDeleteObserver; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.Signature; import android.content.pm.UserInfo; import android.os.Binder; import android.os.Build; import android.os.PatternMatcher; import android.os.Process; import android.os.RemoteException; Loading @@ -38,6 +40,7 @@ import android.os.UserManager; import android.provider.Settings.Global; import android.provider.Settings; import android.util.AndroidRuntimeException; import android.util.Base64; import android.util.Slog; import android.webkit.IWebViewUpdateService; import android.webkit.WebViewFactory; Loading Loading @@ -72,8 +75,6 @@ public class WebViewUpdateService extends SystemService { // The WebView package currently in use (or the one we are preparing). private PackageInfo mCurrentWebViewPackage = null; // The WebView providers that are currently available. private WebViewProviderInfo[] mCurrentValidWebViewPackages = null; private BroadcastReceiver mWebViewUpdatedReceiver; private WebViewUtilityInterface mWebViewUtility; Loading Loading @@ -126,7 +127,6 @@ public class WebViewUpdateService extends SystemService { PackageInfo newPackage = null; synchronized(WebViewUpdateService.this) { try { updateValidWebViewPackages(); newPackage = findPreferredWebViewPackage(); if (mCurrentWebViewPackage != null) oldProviderName = mCurrentWebViewPackage.packageName; Loading Loading @@ -180,12 +180,18 @@ public class WebViewUpdateService extends SystemService { publishBinderService("webviewupdate", new BinderService(), true /*allowIsolated*/); } private static boolean existsValidNonFallbackProvider(WebViewProviderInfo[] providers) { private boolean existsValidNonFallbackProvider(WebViewProviderInfo[] providers) { for (WebViewProviderInfo provider : providers) { if (provider.isAvailableByDefault() && provider.isEnabled() && provider.isValidProvider() && !provider.isFallbackPackage()) { if (provider.availableByDefault && !provider.isFallback) { try { PackageInfo packageInfo = getPackageInfoForProvider(provider); if (isEnabledPackage(packageInfo) && isValidProvider(provider, packageInfo)) { return true; } } catch (NameNotFoundException e) { // A non-existent provider is neither valid nor enabled } } } return false; } Loading @@ -211,11 +217,9 @@ public class WebViewUpdateService extends SystemService { WebViewProviderInfo[] webviewProviders = mWebViewUtility.getWebViewPackages(); WebViewProviderInfo fallbackProvider = getFallbackProvider(webviewProviders); if (fallbackProvider == null) return; boolean existsValidNonFallbackProvider = existsValidNonFallbackProvider(webviewProviders); enablePackageForUser(fallbackProvider.packageName, !existsValidNonFallbackProvider, userId); enablePackageForUser(fallbackProvider.packageName, !existsValidNonFallbackProvider(webviewProviders), userId); } /** Loading @@ -236,7 +240,7 @@ public class WebViewUpdateService extends SystemService { for (WebViewProviderInfo provider : webviewProviders) { String webviewPackage = "package:" + provider.packageName; if (webviewPackage.equals(intent.getDataString())) { if (provider.isAvailableByDefault()) { if (provider.availableByDefault) { changedPackage = provider.packageName; } break; Loading @@ -251,10 +255,16 @@ public class WebViewUpdateService extends SystemService { if (fallbackProvider == null) return; boolean existsValidNonFallbackProvider = existsValidNonFallbackProvider(webviewProviders); boolean isFallbackEnabled = false; try { isFallbackEnabled = isEnabledPackage(getPackageInfoForProvider(fallbackProvider)); } catch (NameNotFoundException e) { } if (existsValidNonFallbackProvider // During an OTA the primary user's WebView state might differ from other users', so // ignore the state of that user during boot. && (fallbackProvider.isEnabled() || intent == null)) { && (isFallbackEnabled || intent == null)) { // Uninstall and disable fallback package for all users. context.getPackageManager().deletePackage(fallbackProvider.packageName, new IPackageDeleteObserver.Stub() { Loading @@ -273,7 +283,7 @@ public class WebViewUpdateService extends SystemService { } else if (!existsValidNonFallbackProvider // During an OTA the primary user's WebView state might differ from other users', so // ignore the state of that user during boot. && (!fallbackProvider.isEnabled() || intent==null)) { && (!isFallbackEnabled || intent==null)) { // Enable the fallback package for all users. UserManager userManager = (UserManager)context.getSystemService(Context.USER_SERVICE); Loading @@ -299,24 +309,13 @@ public class WebViewUpdateService extends SystemService { */ private static WebViewProviderInfo getFallbackProvider(WebViewProviderInfo[] webviewPackages) { for (WebViewProviderInfo provider : webviewPackages) { if (provider.isFallbackPackage()) { if (provider.isFallback) { return provider; } } return null; } private static boolean containsAvailableNonFallbackProvider( WebViewProviderInfo[] webviewPackages) { for (WebViewProviderInfo provider : webviewPackages) { if (provider.isAvailableByDefault() && provider.isEnabled() && provider.isValidProvider() && !provider.isFallbackPackage()) { return true; } } return false; } private boolean isFallbackPackage(String packageName) { if (packageName == null || !isFallbackLogicEnabled()) return false; Loading @@ -336,7 +335,6 @@ public class WebViewUpdateService extends SystemService { updateFallbackState(getContext(), null); try { synchronized(this) { updateValidWebViewPackages(); mCurrentWebViewPackage = findPreferredWebViewPackage(); onWebViewProviderChanged(mCurrentWebViewPackage); } Loading Loading @@ -408,24 +406,41 @@ public class WebViewUpdateService extends SystemService { } } private ProviderAndPackageInfo[] getValidWebViewPackagesAndInfos() { WebViewProviderInfo[] allProviders = mWebViewUtility.getWebViewPackages(); List<ProviderAndPackageInfo> providers = new ArrayList<>(); for(int n = 0; n < allProviders.length; n++) { try { PackageInfo packageInfo = getPackageInfoForProvider(allProviders[n]); if (isValidProvider(allProviders[n], packageInfo)) { providers.add(new ProviderAndPackageInfo(allProviders[n], packageInfo)); } } catch (NameNotFoundException e) { // Don't add non-existent packages } } return providers.toArray(new ProviderAndPackageInfo[providers.size()]); } /** * Updates the currently valid WebView provider packages. * Should be used when a provider has been installed or removed. * @hide * Fetch only the currently valid WebView packages. **/ private void updateValidWebViewPackages() { List<WebViewProviderInfo> webViewProviders = new ArrayList<WebViewProviderInfo>(Arrays.asList(mWebViewUtility.getWebViewPackages())); Iterator<WebViewProviderInfo> it = webViewProviders.iterator(); // remove non-valid packages while(it.hasNext()) { WebViewProviderInfo current = it.next(); if (!current.isValidProvider()) it.remove(); private WebViewProviderInfo[] getValidWebViewPackages() { ProviderAndPackageInfo[] providersAndPackageInfos = getValidWebViewPackagesAndInfos(); WebViewProviderInfo[] providers = new WebViewProviderInfo[providersAndPackageInfos.length]; for(int n = 0; n < providersAndPackageInfos.length; n++) { providers[n] = providersAndPackageInfos[n].provider; } synchronized(this) { mCurrentValidWebViewPackages = webViewProviders.toArray(new WebViewProviderInfo[webViewProviders.size()]); return providers; } private class ProviderAndPackageInfo { public final WebViewProviderInfo provider; public final PackageInfo packageInfo; public ProviderAndPackageInfo(WebViewProviderInfo provider, PackageInfo packageInfo) { this.provider = provider; this.packageInfo = packageInfo; } } Loading @@ -437,28 +452,30 @@ public class WebViewUpdateService extends SystemService { * @hide */ private PackageInfo findPreferredWebViewPackage() { WebViewProviderInfo[] providers = mCurrentValidWebViewPackages; ProviderAndPackageInfo[] providers = getValidWebViewPackagesAndInfos(); String userChosenProvider = mWebViewUtility.getUserChosenWebViewProvider(getContext()); // If the user has chosen provider, use that for (WebViewProviderInfo provider : providers) { if (provider.packageName.equals(userChosenProvider) && provider.isEnabled()) { return provider.getPackageInfo(); for (ProviderAndPackageInfo providerAndPackage : providers) { if (providerAndPackage.provider.packageName.equals(userChosenProvider) && isEnabledPackage(providerAndPackage.packageInfo)) { return providerAndPackage.packageInfo; } } // User did not choose, or the choice failed; use the most stable provider that is // enabled and available by default (not through user choice). for (WebViewProviderInfo provider : providers) { if (provider.isAvailableByDefault() && provider.isEnabled()) { return provider.getPackageInfo(); for (ProviderAndPackageInfo providerAndPackage : providers) { if (providerAndPackage.provider.availableByDefault && isEnabledPackage(providerAndPackage.packageInfo)) { return providerAndPackage.packageInfo; } } // Could not find any enabled package either, use the most stable provider. for (WebViewProviderInfo provider : providers) { return provider.getPackageInfo(); for (ProviderAndPackageInfo providerAndPackage : providers) { return providerAndPackage.packageInfo; } mAnyWebViewInstalled = false; Loading @@ -466,6 +483,60 @@ public class WebViewUpdateService extends SystemService { "Could not find a loadable WebView package"); } /** * Returns whether this provider is valid for use as a WebView provider. */ private static boolean isValidProvider(WebViewProviderInfo configInfo, PackageInfo packageInfo) { if (providerHasValidSignature(configInfo, packageInfo) && WebViewFactory.getWebViewLibrary(packageInfo.applicationInfo) != null) { return true; } return false; } private static boolean providerHasValidSignature(WebViewProviderInfo provider, PackageInfo packageInfo) { if (Build.IS_DEBUGGABLE) return true; Signature[] packageSignatures; // If no signature is declared, instead check whether the package is included in the // system. if (provider.signatures == null || provider.signatures.length == 0) { return packageInfo.applicationInfo.isSystemApp(); } packageSignatures = packageInfo.signatures; if (packageSignatures.length != 1) return false; final byte[] packageSignature = packageSignatures[0].toByteArray(); // Return whether the package signature matches any of the valid signatures for (String signature : provider.signatures) { final byte[] validSignature = Base64.decode(signature, Base64.DEFAULT); if (Arrays.equals(packageSignature, validSignature)) return true; } return false; } /** * Returns whether the given package is enabled. * This state can be changed by the user from Settings->Apps */ private static boolean isEnabledPackage(PackageInfo packageInfo) { return packageInfo.applicationInfo.enabled; } private static PackageInfo getPackageInfoForProvider(WebViewProviderInfo configInfo) throws NameNotFoundException { PackageManager pm = AppGlobals.getInitialApplication().getPackageManager(); return pm.getPackageInfo(configInfo.packageName, PACKAGE_FLAGS); } // flags declaring we want extra info from the package manager for webview providers private final static int PACKAGE_FLAGS = PackageManager.GET_META_DATA | PackageManager.GET_SIGNATURES | PackageManager.MATCH_DEBUG_TRIAGED_MISSING; /** * Returns whether WebView is ready and is not going to go through its preparation phase again * directly. Loading Loading @@ -593,9 +664,7 @@ public class WebViewUpdateService extends SystemService { @Override // Binder call public WebViewProviderInfo[] getValidWebViewPackages() { synchronized(WebViewUpdateService.this) { return mCurrentValidWebViewPackages; } return WebViewUpdateService.this.getValidWebViewPackages(); } @Override // Binder call Loading services/core/java/com/android/server/webkit/WebViewUtilityImpl.java +4 −4 Original line number Diff line number Diff line Loading @@ -87,10 +87,10 @@ public class WebViewUtilityImpl implements WebViewUtilityInterface { parser.getAttributeValue(null, TAG_AVAILABILITY)); boolean isFallback = "true".equals( parser.getAttributeValue(null, TAG_FALLBACK)); WebViewProviderInfo currentProvider = new WebViewProviderInfo(packageName, description, availableByDefault, isFallback, readSignatures(parser)); if (currentProvider.isFallbackPackage()) { WebViewProviderInfo currentProvider = new WebViewProviderInfo( packageName, description, availableByDefault, isFallback, readSignatures(parser)); if (currentProvider.isFallback) { numFallbackPackages++; if (numFallbackPackages > 1) { throw new AndroidRuntimeException( Loading Loading
core/java/android/webkit/WebViewProviderInfo.java +8 −118 Original line number Diff line number Diff line Loading @@ -16,32 +16,16 @@ package android.webkit; import android.app.AppGlobals; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.Signature; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; import android.util.AndroidRuntimeException; import android.util.Base64; import java.util.Arrays; /** @hide */ public class WebViewProviderInfo implements Parcelable { public final class WebViewProviderInfo implements Parcelable { /** * @hide */ public static class WebViewPackageNotFoundException extends AndroidRuntimeException { public WebViewPackageNotFoundException(String message) { super(message); } public WebViewPackageNotFoundException(Exception e) { super(e); } } public WebViewProviderInfo(String packageName, String description, boolean availableByDefault, boolean isFallback, String[] signatures) { public WebViewProviderInfo(String packageName, String description, boolean availableByDefault, boolean isFallback, String[] signatures) { this.packageName = packageName; this.description = description; this.availableByDefault = availableByDefault; Loading @@ -49,92 +33,6 @@ public class WebViewProviderInfo implements Parcelable { this.signatures = signatures; } private boolean hasValidSignature() { if (Build.IS_DEBUGGABLE) return true; Signature[] packageSignatures; try { // If no signature is declared, instead check whether the package is included in the // system. if (signatures == null || signatures.length == 0) return getPackageInfo().applicationInfo.isSystemApp(); packageSignatures = getPackageInfo().signatures; } catch (WebViewPackageNotFoundException e) { return false; } if (packageSignatures.length != 1) return false; final byte[] packageSignature = packageSignatures[0].toByteArray(); // Return whether the package signature matches any of the valid signatures for (String signature : signatures) { final byte[] validSignature = Base64.decode(signature, Base64.DEFAULT); if (Arrays.equals(packageSignature, validSignature)) return true; } return false; } /** * Returns whether this provider is valid for use as a WebView provider. */ public boolean isValidProvider() { ApplicationInfo applicationInfo; try { applicationInfo = getPackageInfo().applicationInfo; } catch (WebViewPackageNotFoundException e) { return false; } if (hasValidSignature() && WebViewFactory.getWebViewLibrary(applicationInfo) != null) { return true; } return false; } /** * Returns whether this package is enabled. * This state can be changed by the user from Settings->Apps */ public boolean isEnabled() { try { // Explicitly fetch up-to-date package info here since the enabled-state of the package // might have changed since we last fetched its package info. updatePackageInfo(); return getPackageInfo().applicationInfo.enabled; } catch (WebViewPackageNotFoundException e) { return false; } } /** * Returns whether the provider is always available as long as it is valid. * If this returns false, the provider will only be used if the user chose this provider. */ public boolean isAvailableByDefault() { return availableByDefault; } public boolean isFallbackPackage() { return isFallback; } private void updatePackageInfo() { try { PackageManager pm = AppGlobals.getInitialApplication().getPackageManager(); packageInfo = pm.getPackageInfo(packageName, PACKAGE_FLAGS); } catch (PackageManager.NameNotFoundException e) { throw new WebViewPackageNotFoundException(e); } } public PackageInfo getPackageInfo() { if (packageInfo == null) { updatePackageInfo(); } return packageInfo; } // aidl stuff public static final Parcelable.Creator<WebViewProviderInfo> CREATOR = new Parcelable.Creator<WebViewProviderInfo>() { Loading @@ -153,7 +51,6 @@ public class WebViewProviderInfo implements Parcelable { availableByDefault = (in.readInt() > 0); isFallback = (in.readInt() > 0); signatures = in.createStringArray(); packageInfo = null; } @Override Loading @@ -171,16 +68,9 @@ public class WebViewProviderInfo implements Parcelable { } // fields read from framework resource public String packageName; public String description; private boolean availableByDefault; private boolean isFallback; private String[] signatures; private PackageInfo packageInfo; // flags declaring we want extra info from the package manager private final static int PACKAGE_FLAGS = PackageManager.GET_META_DATA | PackageManager.GET_SIGNATURES | PackageManager.MATCH_DEBUG_TRIAGED_MISSING; public final String packageName; public final String description; public final boolean availableByDefault; public final boolean isFallback; public final String[] signatures; }
services/core/java/com/android/server/webkit/WebViewUpdateService.java +124 −55 Original line number Diff line number Diff line Loading @@ -26,9 +26,11 @@ import android.content.pm.ApplicationInfo; import android.content.pm.IPackageDeleteObserver; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.Signature; import android.content.pm.UserInfo; import android.os.Binder; import android.os.Build; import android.os.PatternMatcher; import android.os.Process; import android.os.RemoteException; Loading @@ -38,6 +40,7 @@ import android.os.UserManager; import android.provider.Settings.Global; import android.provider.Settings; import android.util.AndroidRuntimeException; import android.util.Base64; import android.util.Slog; import android.webkit.IWebViewUpdateService; import android.webkit.WebViewFactory; Loading Loading @@ -72,8 +75,6 @@ public class WebViewUpdateService extends SystemService { // The WebView package currently in use (or the one we are preparing). private PackageInfo mCurrentWebViewPackage = null; // The WebView providers that are currently available. private WebViewProviderInfo[] mCurrentValidWebViewPackages = null; private BroadcastReceiver mWebViewUpdatedReceiver; private WebViewUtilityInterface mWebViewUtility; Loading Loading @@ -126,7 +127,6 @@ public class WebViewUpdateService extends SystemService { PackageInfo newPackage = null; synchronized(WebViewUpdateService.this) { try { updateValidWebViewPackages(); newPackage = findPreferredWebViewPackage(); if (mCurrentWebViewPackage != null) oldProviderName = mCurrentWebViewPackage.packageName; Loading Loading @@ -180,12 +180,18 @@ public class WebViewUpdateService extends SystemService { publishBinderService("webviewupdate", new BinderService(), true /*allowIsolated*/); } private static boolean existsValidNonFallbackProvider(WebViewProviderInfo[] providers) { private boolean existsValidNonFallbackProvider(WebViewProviderInfo[] providers) { for (WebViewProviderInfo provider : providers) { if (provider.isAvailableByDefault() && provider.isEnabled() && provider.isValidProvider() && !provider.isFallbackPackage()) { if (provider.availableByDefault && !provider.isFallback) { try { PackageInfo packageInfo = getPackageInfoForProvider(provider); if (isEnabledPackage(packageInfo) && isValidProvider(provider, packageInfo)) { return true; } } catch (NameNotFoundException e) { // A non-existent provider is neither valid nor enabled } } } return false; } Loading @@ -211,11 +217,9 @@ public class WebViewUpdateService extends SystemService { WebViewProviderInfo[] webviewProviders = mWebViewUtility.getWebViewPackages(); WebViewProviderInfo fallbackProvider = getFallbackProvider(webviewProviders); if (fallbackProvider == null) return; boolean existsValidNonFallbackProvider = existsValidNonFallbackProvider(webviewProviders); enablePackageForUser(fallbackProvider.packageName, !existsValidNonFallbackProvider, userId); enablePackageForUser(fallbackProvider.packageName, !existsValidNonFallbackProvider(webviewProviders), userId); } /** Loading @@ -236,7 +240,7 @@ public class WebViewUpdateService extends SystemService { for (WebViewProviderInfo provider : webviewProviders) { String webviewPackage = "package:" + provider.packageName; if (webviewPackage.equals(intent.getDataString())) { if (provider.isAvailableByDefault()) { if (provider.availableByDefault) { changedPackage = provider.packageName; } break; Loading @@ -251,10 +255,16 @@ public class WebViewUpdateService extends SystemService { if (fallbackProvider == null) return; boolean existsValidNonFallbackProvider = existsValidNonFallbackProvider(webviewProviders); boolean isFallbackEnabled = false; try { isFallbackEnabled = isEnabledPackage(getPackageInfoForProvider(fallbackProvider)); } catch (NameNotFoundException e) { } if (existsValidNonFallbackProvider // During an OTA the primary user's WebView state might differ from other users', so // ignore the state of that user during boot. && (fallbackProvider.isEnabled() || intent == null)) { && (isFallbackEnabled || intent == null)) { // Uninstall and disable fallback package for all users. context.getPackageManager().deletePackage(fallbackProvider.packageName, new IPackageDeleteObserver.Stub() { Loading @@ -273,7 +283,7 @@ public class WebViewUpdateService extends SystemService { } else if (!existsValidNonFallbackProvider // During an OTA the primary user's WebView state might differ from other users', so // ignore the state of that user during boot. && (!fallbackProvider.isEnabled() || intent==null)) { && (!isFallbackEnabled || intent==null)) { // Enable the fallback package for all users. UserManager userManager = (UserManager)context.getSystemService(Context.USER_SERVICE); Loading @@ -299,24 +309,13 @@ public class WebViewUpdateService extends SystemService { */ private static WebViewProviderInfo getFallbackProvider(WebViewProviderInfo[] webviewPackages) { for (WebViewProviderInfo provider : webviewPackages) { if (provider.isFallbackPackage()) { if (provider.isFallback) { return provider; } } return null; } private static boolean containsAvailableNonFallbackProvider( WebViewProviderInfo[] webviewPackages) { for (WebViewProviderInfo provider : webviewPackages) { if (provider.isAvailableByDefault() && provider.isEnabled() && provider.isValidProvider() && !provider.isFallbackPackage()) { return true; } } return false; } private boolean isFallbackPackage(String packageName) { if (packageName == null || !isFallbackLogicEnabled()) return false; Loading @@ -336,7 +335,6 @@ public class WebViewUpdateService extends SystemService { updateFallbackState(getContext(), null); try { synchronized(this) { updateValidWebViewPackages(); mCurrentWebViewPackage = findPreferredWebViewPackage(); onWebViewProviderChanged(mCurrentWebViewPackage); } Loading Loading @@ -408,24 +406,41 @@ public class WebViewUpdateService extends SystemService { } } private ProviderAndPackageInfo[] getValidWebViewPackagesAndInfos() { WebViewProviderInfo[] allProviders = mWebViewUtility.getWebViewPackages(); List<ProviderAndPackageInfo> providers = new ArrayList<>(); for(int n = 0; n < allProviders.length; n++) { try { PackageInfo packageInfo = getPackageInfoForProvider(allProviders[n]); if (isValidProvider(allProviders[n], packageInfo)) { providers.add(new ProviderAndPackageInfo(allProviders[n], packageInfo)); } } catch (NameNotFoundException e) { // Don't add non-existent packages } } return providers.toArray(new ProviderAndPackageInfo[providers.size()]); } /** * Updates the currently valid WebView provider packages. * Should be used when a provider has been installed or removed. * @hide * Fetch only the currently valid WebView packages. **/ private void updateValidWebViewPackages() { List<WebViewProviderInfo> webViewProviders = new ArrayList<WebViewProviderInfo>(Arrays.asList(mWebViewUtility.getWebViewPackages())); Iterator<WebViewProviderInfo> it = webViewProviders.iterator(); // remove non-valid packages while(it.hasNext()) { WebViewProviderInfo current = it.next(); if (!current.isValidProvider()) it.remove(); private WebViewProviderInfo[] getValidWebViewPackages() { ProviderAndPackageInfo[] providersAndPackageInfos = getValidWebViewPackagesAndInfos(); WebViewProviderInfo[] providers = new WebViewProviderInfo[providersAndPackageInfos.length]; for(int n = 0; n < providersAndPackageInfos.length; n++) { providers[n] = providersAndPackageInfos[n].provider; } synchronized(this) { mCurrentValidWebViewPackages = webViewProviders.toArray(new WebViewProviderInfo[webViewProviders.size()]); return providers; } private class ProviderAndPackageInfo { public final WebViewProviderInfo provider; public final PackageInfo packageInfo; public ProviderAndPackageInfo(WebViewProviderInfo provider, PackageInfo packageInfo) { this.provider = provider; this.packageInfo = packageInfo; } } Loading @@ -437,28 +452,30 @@ public class WebViewUpdateService extends SystemService { * @hide */ private PackageInfo findPreferredWebViewPackage() { WebViewProviderInfo[] providers = mCurrentValidWebViewPackages; ProviderAndPackageInfo[] providers = getValidWebViewPackagesAndInfos(); String userChosenProvider = mWebViewUtility.getUserChosenWebViewProvider(getContext()); // If the user has chosen provider, use that for (WebViewProviderInfo provider : providers) { if (provider.packageName.equals(userChosenProvider) && provider.isEnabled()) { return provider.getPackageInfo(); for (ProviderAndPackageInfo providerAndPackage : providers) { if (providerAndPackage.provider.packageName.equals(userChosenProvider) && isEnabledPackage(providerAndPackage.packageInfo)) { return providerAndPackage.packageInfo; } } // User did not choose, or the choice failed; use the most stable provider that is // enabled and available by default (not through user choice). for (WebViewProviderInfo provider : providers) { if (provider.isAvailableByDefault() && provider.isEnabled()) { return provider.getPackageInfo(); for (ProviderAndPackageInfo providerAndPackage : providers) { if (providerAndPackage.provider.availableByDefault && isEnabledPackage(providerAndPackage.packageInfo)) { return providerAndPackage.packageInfo; } } // Could not find any enabled package either, use the most stable provider. for (WebViewProviderInfo provider : providers) { return provider.getPackageInfo(); for (ProviderAndPackageInfo providerAndPackage : providers) { return providerAndPackage.packageInfo; } mAnyWebViewInstalled = false; Loading @@ -466,6 +483,60 @@ public class WebViewUpdateService extends SystemService { "Could not find a loadable WebView package"); } /** * Returns whether this provider is valid for use as a WebView provider. */ private static boolean isValidProvider(WebViewProviderInfo configInfo, PackageInfo packageInfo) { if (providerHasValidSignature(configInfo, packageInfo) && WebViewFactory.getWebViewLibrary(packageInfo.applicationInfo) != null) { return true; } return false; } private static boolean providerHasValidSignature(WebViewProviderInfo provider, PackageInfo packageInfo) { if (Build.IS_DEBUGGABLE) return true; Signature[] packageSignatures; // If no signature is declared, instead check whether the package is included in the // system. if (provider.signatures == null || provider.signatures.length == 0) { return packageInfo.applicationInfo.isSystemApp(); } packageSignatures = packageInfo.signatures; if (packageSignatures.length != 1) return false; final byte[] packageSignature = packageSignatures[0].toByteArray(); // Return whether the package signature matches any of the valid signatures for (String signature : provider.signatures) { final byte[] validSignature = Base64.decode(signature, Base64.DEFAULT); if (Arrays.equals(packageSignature, validSignature)) return true; } return false; } /** * Returns whether the given package is enabled. * This state can be changed by the user from Settings->Apps */ private static boolean isEnabledPackage(PackageInfo packageInfo) { return packageInfo.applicationInfo.enabled; } private static PackageInfo getPackageInfoForProvider(WebViewProviderInfo configInfo) throws NameNotFoundException { PackageManager pm = AppGlobals.getInitialApplication().getPackageManager(); return pm.getPackageInfo(configInfo.packageName, PACKAGE_FLAGS); } // flags declaring we want extra info from the package manager for webview providers private final static int PACKAGE_FLAGS = PackageManager.GET_META_DATA | PackageManager.GET_SIGNATURES | PackageManager.MATCH_DEBUG_TRIAGED_MISSING; /** * Returns whether WebView is ready and is not going to go through its preparation phase again * directly. Loading Loading @@ -593,9 +664,7 @@ public class WebViewUpdateService extends SystemService { @Override // Binder call public WebViewProviderInfo[] getValidWebViewPackages() { synchronized(WebViewUpdateService.this) { return mCurrentValidWebViewPackages; } return WebViewUpdateService.this.getValidWebViewPackages(); } @Override // Binder call Loading
services/core/java/com/android/server/webkit/WebViewUtilityImpl.java +4 −4 Original line number Diff line number Diff line Loading @@ -87,10 +87,10 @@ public class WebViewUtilityImpl implements WebViewUtilityInterface { parser.getAttributeValue(null, TAG_AVAILABILITY)); boolean isFallback = "true".equals( parser.getAttributeValue(null, TAG_FALLBACK)); WebViewProviderInfo currentProvider = new WebViewProviderInfo(packageName, description, availableByDefault, isFallback, readSignatures(parser)); if (currentProvider.isFallbackPackage()) { WebViewProviderInfo currentProvider = new WebViewProviderInfo( packageName, description, availableByDefault, isFallback, readSignatures(parser)); if (currentProvider.isFallback) { numFallbackPackages++; if (numFallbackPackages > 1) { throw new AndroidRuntimeException( Loading