Loading core/java/android/webkit/IWebViewUpdateService.aidl +5 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,11 @@ interface IWebViewUpdateService { */ WebViewProviderInfo[] getValidWebViewPackages(); /** * Fetch all packages that could potentially implement WebView. */ WebViewProviderInfo[] getAllWebViewPackages(); /** * Used by DevelopmentSetting to get the name of the WebView provider currently in use. */ Loading core/java/android/webkit/WebViewFactory.java +1 −90 Original line number Diff line number Diff line Loading @@ -128,98 +128,9 @@ public final class WebViewFactory { public MissingWebViewPackageException(Exception e) { super(e); } } private static String TAG_START = "webviewproviders"; private static String TAG_WEBVIEW_PROVIDER = "webviewprovider"; private static String TAG_PACKAGE_NAME = "packageName"; private static String TAG_DESCRIPTION = "description"; // Whether or not the provider must be explicitly chosen by the user to be used. private static String TAG_AVAILABILITY = "availableByDefault"; private static String TAG_SIGNATURE = "signature"; private static String TAG_FALLBACK = "isFallback"; /** * Reads all signatures at the current depth (within the current provider) from the XML parser. */ private static String[] readSignatures(XmlResourceParser parser) throws IOException, XmlPullParserException { List<String> signatures = new ArrayList<String>(); int outerDepth = parser.getDepth(); while(XmlUtils.nextElementWithin(parser, outerDepth)) { if (parser.getName().equals(TAG_SIGNATURE)) { // Parse the value within the signature tag String signature = parser.nextText(); signatures.add(signature); } else { Log.e(LOGTAG, "Found an element in a webview provider that is not a signature"); } } return signatures.toArray(new String[signatures.size()]); } /** * Returns all packages declared in the framework resources as potential WebView providers. * @hide * */ public static WebViewProviderInfo[] getWebViewPackages() { int numFallbackPackages = 0; XmlResourceParser parser = null; List<WebViewProviderInfo> webViewProviders = new ArrayList<WebViewProviderInfo>(); try { parser = AppGlobals.getInitialApplication().getResources().getXml( com.android.internal.R.xml.config_webview_packages); XmlUtils.beginDocument(parser, TAG_START); while(true) { XmlUtils.nextElement(parser); String element = parser.getName(); if (element == null) { break; } if (element.equals(TAG_WEBVIEW_PROVIDER)) { String packageName = parser.getAttributeValue(null, TAG_PACKAGE_NAME); if (packageName == null) { throw new MissingWebViewPackageException( "WebView provider in framework resources missing package name"); } String description = parser.getAttributeValue(null, TAG_DESCRIPTION); if (description == null) { throw new MissingWebViewPackageException( "WebView provider in framework resources missing description"); } boolean availableByDefault = "true".equals( 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()) { numFallbackPackages++; if (numFallbackPackages > 1) { throw new AndroidRuntimeException( "There can be at most one webview fallback package."); } } webViewProviders.add(currentProvider); } else { Log.e(LOGTAG, "Found an element that is not a webview provider"); } } } catch(XmlPullParserException e) { throw new MissingWebViewPackageException("Error when parsing WebView meta data " + e); } catch(IOException e) { throw new MissingWebViewPackageException("Error when parsing WebView meta data " + e); } finally { if (parser != null) parser.close(); } return webViewProviders.toArray(new WebViewProviderInfo[webViewProviders.size()]); } // TODO (gsennton) remove when committing webview xts test change public static String getWebViewPackageName() { WebViewProviderInfo[] providers = getWebViewPackages(); return providers[0].packageName; return null; } /** Loading core/java/android/webkit/WebViewProviderInfo.java +4 −0 Original line number Diff line number Diff line Loading @@ -150,6 +150,8 @@ public class WebViewProviderInfo implements Parcelable { private WebViewProviderInfo(Parcel in) { packageName = in.readString(); description = in.readString(); availableByDefault = (in.readInt() > 0); isFallback = (in.readInt() > 0); signatures = in.createStringArray(); packageInfo = null; } Loading @@ -163,6 +165,8 @@ public class WebViewProviderInfo implements Parcelable { public void writeToParcel(Parcel out, int flags) { out.writeString(packageName); out.writeString(description); out.writeInt(availableByDefault ? 1 : 0); out.writeInt(isFallback ? 1 : 0); out.writeStringArray(signatures); } Loading services/core/java/com/android/server/webkit/WebViewUpdateService.java +25 −37 Original line number Diff line number Diff line Loading @@ -35,14 +35,14 @@ import android.os.RemoteException; import android.os.ResultReceiver; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; import android.provider.Settings.Global; import android.provider.Settings; import android.util.AndroidRuntimeException; import android.util.Slog; import android.webkit.IWebViewUpdateService; import android.webkit.WebViewFactory; import android.webkit.WebViewProviderInfo; import android.webkit.WebViewProviderResponse; import android.webkit.WebViewFactory; import com.android.server.SystemService; Loading Loading @@ -76,9 +76,11 @@ public class WebViewUpdateService extends SystemService { private WebViewProviderInfo[] mCurrentValidWebViewPackages = null; private BroadcastReceiver mWebViewUpdatedReceiver; private WebViewUtilityInterface mWebViewUtility; public WebViewUpdateService(Context context) { super(context); mWebViewUtility = new WebViewUtilityImpl(); } @Override Loading Loading @@ -114,7 +116,7 @@ public class WebViewUpdateService extends SystemService { updateFallbackState(context, intent); for (WebViewProviderInfo provider : WebViewFactory.getWebViewPackages()) { for (WebViewProviderInfo provider : mWebViewUtility.getWebViewPackages()) { String webviewPackage = "package:" + provider.packageName; if (webviewPackage.equals(intent.getDataString())) { Loading Loading @@ -153,11 +155,7 @@ public class WebViewUpdateService extends SystemService { // package that was not the previous provider then we must kill // packages dependent on the old package ourselves. The framework // only kills dependents of packages that are being removed. try { ActivityManagerNative.getDefault().killPackageDependents( oldProviderName, UserHandle.USER_ALL); } catch (RemoteException e) { } mWebViewUtility.killPackageDependents(oldProviderName); } return; } Loading @@ -170,7 +168,7 @@ public class WebViewUpdateService extends SystemService { filter.addAction(Intent.ACTION_PACKAGE_CHANGED); filter.addDataScheme("package"); // Make sure we only receive intents for WebView packages from our config file. for (WebViewProviderInfo provider : WebViewFactory.getWebViewPackages()) { for (WebViewProviderInfo provider : mWebViewUtility.getWebViewPackages()) { filter.addDataSchemeSpecificPart(provider.packageName, PatternMatcher.PATTERN_LITERAL); } getContext().registerReceiver(mWebViewUpdatedReceiver, filter); Loading Loading @@ -210,7 +208,7 @@ public class WebViewUpdateService extends SystemService { void handleNewUser(int userId) { if (!isFallbackLogicEnabled()) return; WebViewProviderInfo[] webviewProviders = WebViewFactory.getWebViewPackages(); WebViewProviderInfo[] webviewProviders = mWebViewUtility.getWebViewPackages(); WebViewProviderInfo fallbackProvider = getFallbackProvider(webviewProviders); if (fallbackProvider == null) return; boolean existsValidNonFallbackProvider = Loading @@ -228,7 +226,7 @@ public class WebViewUpdateService extends SystemService { void updateFallbackState(final Context context, final Intent intent) { if (!isFallbackLogicEnabled()) return; WebViewProviderInfo[] webviewProviders = WebViewFactory.getWebViewPackages(); WebViewProviderInfo[] webviewProviders = mWebViewUtility.getWebViewPackages(); if (intent != null && (intent.getAction().equals(Intent.ACTION_PACKAGE_ADDED) || intent.getAction().equals(Intent.ACTION_PACKAGE_CHANGED))) { Loading Loading @@ -319,10 +317,10 @@ public class WebViewUpdateService extends SystemService { return false; } private static boolean isFallbackPackage(String packageName) { private boolean isFallbackPackage(String packageName) { if (packageName == null || !isFallbackLogicEnabled()) return false; WebViewProviderInfo[] webviewPackages = WebViewFactory.getWebViewPackages(); WebViewProviderInfo[] webviewPackages = mWebViewUtility.getWebViewPackages(); WebViewProviderInfo fallbackProvider = getFallbackProvider(webviewPackages); return (fallbackProvider != null && packageName.equals(fallbackProvider.packageName)); Loading Loading @@ -359,13 +357,13 @@ public class WebViewUpdateService extends SystemService { PackageInfo newPackage = null; synchronized(this) { oldPackage = mCurrentWebViewPackage; updateUserSetting(newProviderName); mWebViewUtility.updateUserSetting(getContext(), newProviderName); try { newPackage = findPreferredWebViewPackage(); if (oldPackage != null && newPackage.packageName.equals(oldPackage.packageName)) { // If we don't perform the user change, revert the settings change. updateUserSetting(newPackage.packageName); mWebViewUtility.updateUserSetting(getContext(), newPackage.packageName); return newPackage.packageName; } } catch (WebViewFactory.MissingWebViewPackageException e) { Loading @@ -378,12 +376,8 @@ public class WebViewUpdateService extends SystemService { onWebViewProviderChanged(newPackage); } // Kill apps using the old provider try { if (oldPackage != null) { ActivityManagerNative.getDefault().killPackageDependents( oldPackage.packageName, UserHandle.USER_ALL); } } catch (RemoteException e) { mWebViewUtility.killPackageDependents(oldPackage.packageName); } return newPackage.packageName; } Loading @@ -397,14 +391,14 @@ public class WebViewUpdateService extends SystemService { mAnyWebViewInstalled = true; if (mNumRelroCreationsStarted == mNumRelroCreationsFinished) { mCurrentWebViewPackage = newPackage; updateUserSetting(newPackage.packageName); mWebViewUtility.updateUserSetting(getContext(), newPackage.packageName); // The relro creations might 'finish' (not start at all) before // WebViewFactory.onWebViewProviderChanged which means we might not know the number // of started creations before they finish. mNumRelroCreationsStarted = NUMBER_OF_RELROS_UNKNOWN; mNumRelroCreationsFinished = 0; mNumRelroCreationsStarted = WebViewFactory.onWebViewProviderChanged(newPackage); mNumRelroCreationsStarted = mWebViewUtility.onWebViewProviderChanged(newPackage); // If the relro creations finish before we know the number of started creations we // will have to do any cleanup/notifying here. checkIfRelrosDoneLocked(); Loading @@ -421,7 +415,7 @@ public class WebViewUpdateService extends SystemService { * */ private void updateValidWebViewPackages() { List<WebViewProviderInfo> webViewProviders = new ArrayList<WebViewProviderInfo>(Arrays.asList(WebViewFactory.getWebViewPackages())); new ArrayList<WebViewProviderInfo>(Arrays.asList(mWebViewUtility.getWebViewPackages())); Iterator<WebViewProviderInfo> it = webViewProviders.iterator(); // remove non-valid packages while(it.hasNext()) { Loading @@ -435,17 +429,6 @@ public class WebViewUpdateService extends SystemService { } } private static String getUserChosenWebViewProvider() { return Settings.Global.getString(AppGlobals.getInitialApplication().getContentResolver(), Settings.Global.WEBVIEW_PROVIDER); } private void updateUserSetting(String newProviderName) { Settings.Global.putString(getContext().getContentResolver(), Settings.Global.WEBVIEW_PROVIDER, newProviderName == null ? "" : newProviderName); } /** * Returns either the package info of the WebView provider determined in the following way: * If the user has chosen a provider then use that if it is valid, Loading @@ -456,7 +439,7 @@ public class WebViewUpdateService extends SystemService { private PackageInfo findPreferredWebViewPackage() { WebViewProviderInfo[] providers = mCurrentValidWebViewPackages; String userChosenProvider = getUserChosenWebViewProvider(); String userChosenProvider = mWebViewUtility.getUserChosenWebViewProvider(getContext()); // If the user has chosen provider, use that for (WebViewProviderInfo provider : providers) { Loading Loading @@ -615,6 +598,11 @@ public class WebViewUpdateService extends SystemService { } } @Override // Binder call public WebViewProviderInfo[] getAllWebViewPackages() { return WebViewUpdateService.this.mWebViewUtility.getWebViewPackages(); } @Override // Binder call public String getCurrentWebViewPackageName() { synchronized(WebViewUpdateService.this) { Loading @@ -626,7 +614,7 @@ public class WebViewUpdateService extends SystemService { @Override // Binder call public boolean isFallbackPackage(String packageName) { return WebViewUpdateService.isFallbackPackage(packageName); return WebViewUpdateService.this.isFallbackPackage(packageName); } @Override // Binder call Loading services/core/java/com/android/server/webkit/WebViewUtilityImpl.java 0 → 100644 +161 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.webkit; import android.app.ActivityManagerNative; import android.app.AppGlobals; import android.content.Context; import android.content.pm.PackageInfo; import android.content.res.XmlResourceParser; import android.os.RemoteException; import android.os.UserHandle; import android.provider.Settings; import android.util.AndroidRuntimeException; import android.util.Log; import android.webkit.WebViewFactory; import android.webkit.WebViewFactory.MissingWebViewPackageException; import android.webkit.WebViewProviderInfo; import com.android.internal.util.XmlUtils; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.xmlpull.v1.XmlPullParserException; /** * Default implementation for the WebView preparation Utility interface. * @hide */ public class WebViewUtilityImpl implements WebViewUtilityInterface { private static final String TAG = WebViewUtilityImpl.class.getSimpleName(); private static final String TAG_START = "webviewproviders"; private static final String TAG_WEBVIEW_PROVIDER = "webviewprovider"; private static final String TAG_PACKAGE_NAME = "packageName"; private static final String TAG_DESCRIPTION = "description"; // Whether or not the provider must be explicitly chosen by the user to be used. private static final String TAG_AVAILABILITY = "availableByDefault"; private static final String TAG_SIGNATURE = "signature"; private static final String TAG_FALLBACK = "isFallback"; /** * Returns all packages declared in the framework resources as potential WebView providers. * @hide * */ @Override public WebViewProviderInfo[] getWebViewPackages() { int numFallbackPackages = 0; XmlResourceParser parser = null; List<WebViewProviderInfo> webViewProviders = new ArrayList<WebViewProviderInfo>(); try { parser = AppGlobals.getInitialApplication().getResources().getXml( com.android.internal.R.xml.config_webview_packages); XmlUtils.beginDocument(parser, TAG_START); while(true) { XmlUtils.nextElement(parser); String element = parser.getName(); if (element == null) { break; } if (element.equals(TAG_WEBVIEW_PROVIDER)) { String packageName = parser.getAttributeValue(null, TAG_PACKAGE_NAME); if (packageName == null) { throw new MissingWebViewPackageException( "WebView provider in framework resources missing package name"); } String description = parser.getAttributeValue(null, TAG_DESCRIPTION); if (description == null) { throw new MissingWebViewPackageException( "WebView provider in framework resources missing description"); } boolean availableByDefault = "true".equals( 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()) { numFallbackPackages++; if (numFallbackPackages > 1) { throw new AndroidRuntimeException( "There can be at most one webview fallback package."); } } webViewProviders.add(currentProvider); } else { Log.e(TAG, "Found an element that is not a webview provider"); } } } catch(XmlPullParserException e) { throw new MissingWebViewPackageException("Error when parsing WebView meta data " + e); } catch(IOException e) { throw new MissingWebViewPackageException("Error when parsing WebView meta data " + e); } finally { if (parser != null) parser.close(); } return webViewProviders.toArray(new WebViewProviderInfo[webViewProviders.size()]); } /** * Reads all signatures at the current depth (within the current provider) from the XML parser. */ private static String[] readSignatures(XmlResourceParser parser) throws IOException, XmlPullParserException { List<String> signatures = new ArrayList<String>(); int outerDepth = parser.getDepth(); while(XmlUtils.nextElementWithin(parser, outerDepth)) { if (parser.getName().equals(TAG_SIGNATURE)) { // Parse the value within the signature tag String signature = parser.nextText(); signatures.add(signature); } else { Log.e(TAG, "Found an element in a webview provider that is not a signature"); } } return signatures.toArray(new String[signatures.size()]); } @Override public int onWebViewProviderChanged(PackageInfo packageInfo) { return WebViewFactory.onWebViewProviderChanged(packageInfo); } @Override public String getUserChosenWebViewProvider(Context context) { return Settings.Global.getString(context.getContentResolver(), Settings.Global.WEBVIEW_PROVIDER); } @Override public void updateUserSetting(Context context, String newProviderName) { Settings.Global.putString(context.getContentResolver(), Settings.Global.WEBVIEW_PROVIDER, newProviderName == null ? "" : newProviderName); } @Override public void killPackageDependents(String packageName) { try { ActivityManagerNative.getDefault().killPackageDependents(packageName, UserHandle.USER_ALL); } catch (RemoteException e) { } } } Loading
core/java/android/webkit/IWebViewUpdateService.aidl +5 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,11 @@ interface IWebViewUpdateService { */ WebViewProviderInfo[] getValidWebViewPackages(); /** * Fetch all packages that could potentially implement WebView. */ WebViewProviderInfo[] getAllWebViewPackages(); /** * Used by DevelopmentSetting to get the name of the WebView provider currently in use. */ Loading
core/java/android/webkit/WebViewFactory.java +1 −90 Original line number Diff line number Diff line Loading @@ -128,98 +128,9 @@ public final class WebViewFactory { public MissingWebViewPackageException(Exception e) { super(e); } } private static String TAG_START = "webviewproviders"; private static String TAG_WEBVIEW_PROVIDER = "webviewprovider"; private static String TAG_PACKAGE_NAME = "packageName"; private static String TAG_DESCRIPTION = "description"; // Whether or not the provider must be explicitly chosen by the user to be used. private static String TAG_AVAILABILITY = "availableByDefault"; private static String TAG_SIGNATURE = "signature"; private static String TAG_FALLBACK = "isFallback"; /** * Reads all signatures at the current depth (within the current provider) from the XML parser. */ private static String[] readSignatures(XmlResourceParser parser) throws IOException, XmlPullParserException { List<String> signatures = new ArrayList<String>(); int outerDepth = parser.getDepth(); while(XmlUtils.nextElementWithin(parser, outerDepth)) { if (parser.getName().equals(TAG_SIGNATURE)) { // Parse the value within the signature tag String signature = parser.nextText(); signatures.add(signature); } else { Log.e(LOGTAG, "Found an element in a webview provider that is not a signature"); } } return signatures.toArray(new String[signatures.size()]); } /** * Returns all packages declared in the framework resources as potential WebView providers. * @hide * */ public static WebViewProviderInfo[] getWebViewPackages() { int numFallbackPackages = 0; XmlResourceParser parser = null; List<WebViewProviderInfo> webViewProviders = new ArrayList<WebViewProviderInfo>(); try { parser = AppGlobals.getInitialApplication().getResources().getXml( com.android.internal.R.xml.config_webview_packages); XmlUtils.beginDocument(parser, TAG_START); while(true) { XmlUtils.nextElement(parser); String element = parser.getName(); if (element == null) { break; } if (element.equals(TAG_WEBVIEW_PROVIDER)) { String packageName = parser.getAttributeValue(null, TAG_PACKAGE_NAME); if (packageName == null) { throw new MissingWebViewPackageException( "WebView provider in framework resources missing package name"); } String description = parser.getAttributeValue(null, TAG_DESCRIPTION); if (description == null) { throw new MissingWebViewPackageException( "WebView provider in framework resources missing description"); } boolean availableByDefault = "true".equals( 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()) { numFallbackPackages++; if (numFallbackPackages > 1) { throw new AndroidRuntimeException( "There can be at most one webview fallback package."); } } webViewProviders.add(currentProvider); } else { Log.e(LOGTAG, "Found an element that is not a webview provider"); } } } catch(XmlPullParserException e) { throw new MissingWebViewPackageException("Error when parsing WebView meta data " + e); } catch(IOException e) { throw new MissingWebViewPackageException("Error when parsing WebView meta data " + e); } finally { if (parser != null) parser.close(); } return webViewProviders.toArray(new WebViewProviderInfo[webViewProviders.size()]); } // TODO (gsennton) remove when committing webview xts test change public static String getWebViewPackageName() { WebViewProviderInfo[] providers = getWebViewPackages(); return providers[0].packageName; return null; } /** Loading
core/java/android/webkit/WebViewProviderInfo.java +4 −0 Original line number Diff line number Diff line Loading @@ -150,6 +150,8 @@ public class WebViewProviderInfo implements Parcelable { private WebViewProviderInfo(Parcel in) { packageName = in.readString(); description = in.readString(); availableByDefault = (in.readInt() > 0); isFallback = (in.readInt() > 0); signatures = in.createStringArray(); packageInfo = null; } Loading @@ -163,6 +165,8 @@ public class WebViewProviderInfo implements Parcelable { public void writeToParcel(Parcel out, int flags) { out.writeString(packageName); out.writeString(description); out.writeInt(availableByDefault ? 1 : 0); out.writeInt(isFallback ? 1 : 0); out.writeStringArray(signatures); } Loading
services/core/java/com/android/server/webkit/WebViewUpdateService.java +25 −37 Original line number Diff line number Diff line Loading @@ -35,14 +35,14 @@ import android.os.RemoteException; import android.os.ResultReceiver; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; import android.provider.Settings.Global; import android.provider.Settings; import android.util.AndroidRuntimeException; import android.util.Slog; import android.webkit.IWebViewUpdateService; import android.webkit.WebViewFactory; import android.webkit.WebViewProviderInfo; import android.webkit.WebViewProviderResponse; import android.webkit.WebViewFactory; import com.android.server.SystemService; Loading Loading @@ -76,9 +76,11 @@ public class WebViewUpdateService extends SystemService { private WebViewProviderInfo[] mCurrentValidWebViewPackages = null; private BroadcastReceiver mWebViewUpdatedReceiver; private WebViewUtilityInterface mWebViewUtility; public WebViewUpdateService(Context context) { super(context); mWebViewUtility = new WebViewUtilityImpl(); } @Override Loading Loading @@ -114,7 +116,7 @@ public class WebViewUpdateService extends SystemService { updateFallbackState(context, intent); for (WebViewProviderInfo provider : WebViewFactory.getWebViewPackages()) { for (WebViewProviderInfo provider : mWebViewUtility.getWebViewPackages()) { String webviewPackage = "package:" + provider.packageName; if (webviewPackage.equals(intent.getDataString())) { Loading Loading @@ -153,11 +155,7 @@ public class WebViewUpdateService extends SystemService { // package that was not the previous provider then we must kill // packages dependent on the old package ourselves. The framework // only kills dependents of packages that are being removed. try { ActivityManagerNative.getDefault().killPackageDependents( oldProviderName, UserHandle.USER_ALL); } catch (RemoteException e) { } mWebViewUtility.killPackageDependents(oldProviderName); } return; } Loading @@ -170,7 +168,7 @@ public class WebViewUpdateService extends SystemService { filter.addAction(Intent.ACTION_PACKAGE_CHANGED); filter.addDataScheme("package"); // Make sure we only receive intents for WebView packages from our config file. for (WebViewProviderInfo provider : WebViewFactory.getWebViewPackages()) { for (WebViewProviderInfo provider : mWebViewUtility.getWebViewPackages()) { filter.addDataSchemeSpecificPart(provider.packageName, PatternMatcher.PATTERN_LITERAL); } getContext().registerReceiver(mWebViewUpdatedReceiver, filter); Loading Loading @@ -210,7 +208,7 @@ public class WebViewUpdateService extends SystemService { void handleNewUser(int userId) { if (!isFallbackLogicEnabled()) return; WebViewProviderInfo[] webviewProviders = WebViewFactory.getWebViewPackages(); WebViewProviderInfo[] webviewProviders = mWebViewUtility.getWebViewPackages(); WebViewProviderInfo fallbackProvider = getFallbackProvider(webviewProviders); if (fallbackProvider == null) return; boolean existsValidNonFallbackProvider = Loading @@ -228,7 +226,7 @@ public class WebViewUpdateService extends SystemService { void updateFallbackState(final Context context, final Intent intent) { if (!isFallbackLogicEnabled()) return; WebViewProviderInfo[] webviewProviders = WebViewFactory.getWebViewPackages(); WebViewProviderInfo[] webviewProviders = mWebViewUtility.getWebViewPackages(); if (intent != null && (intent.getAction().equals(Intent.ACTION_PACKAGE_ADDED) || intent.getAction().equals(Intent.ACTION_PACKAGE_CHANGED))) { Loading Loading @@ -319,10 +317,10 @@ public class WebViewUpdateService extends SystemService { return false; } private static boolean isFallbackPackage(String packageName) { private boolean isFallbackPackage(String packageName) { if (packageName == null || !isFallbackLogicEnabled()) return false; WebViewProviderInfo[] webviewPackages = WebViewFactory.getWebViewPackages(); WebViewProviderInfo[] webviewPackages = mWebViewUtility.getWebViewPackages(); WebViewProviderInfo fallbackProvider = getFallbackProvider(webviewPackages); return (fallbackProvider != null && packageName.equals(fallbackProvider.packageName)); Loading Loading @@ -359,13 +357,13 @@ public class WebViewUpdateService extends SystemService { PackageInfo newPackage = null; synchronized(this) { oldPackage = mCurrentWebViewPackage; updateUserSetting(newProviderName); mWebViewUtility.updateUserSetting(getContext(), newProviderName); try { newPackage = findPreferredWebViewPackage(); if (oldPackage != null && newPackage.packageName.equals(oldPackage.packageName)) { // If we don't perform the user change, revert the settings change. updateUserSetting(newPackage.packageName); mWebViewUtility.updateUserSetting(getContext(), newPackage.packageName); return newPackage.packageName; } } catch (WebViewFactory.MissingWebViewPackageException e) { Loading @@ -378,12 +376,8 @@ public class WebViewUpdateService extends SystemService { onWebViewProviderChanged(newPackage); } // Kill apps using the old provider try { if (oldPackage != null) { ActivityManagerNative.getDefault().killPackageDependents( oldPackage.packageName, UserHandle.USER_ALL); } } catch (RemoteException e) { mWebViewUtility.killPackageDependents(oldPackage.packageName); } return newPackage.packageName; } Loading @@ -397,14 +391,14 @@ public class WebViewUpdateService extends SystemService { mAnyWebViewInstalled = true; if (mNumRelroCreationsStarted == mNumRelroCreationsFinished) { mCurrentWebViewPackage = newPackage; updateUserSetting(newPackage.packageName); mWebViewUtility.updateUserSetting(getContext(), newPackage.packageName); // The relro creations might 'finish' (not start at all) before // WebViewFactory.onWebViewProviderChanged which means we might not know the number // of started creations before they finish. mNumRelroCreationsStarted = NUMBER_OF_RELROS_UNKNOWN; mNumRelroCreationsFinished = 0; mNumRelroCreationsStarted = WebViewFactory.onWebViewProviderChanged(newPackage); mNumRelroCreationsStarted = mWebViewUtility.onWebViewProviderChanged(newPackage); // If the relro creations finish before we know the number of started creations we // will have to do any cleanup/notifying here. checkIfRelrosDoneLocked(); Loading @@ -421,7 +415,7 @@ public class WebViewUpdateService extends SystemService { * */ private void updateValidWebViewPackages() { List<WebViewProviderInfo> webViewProviders = new ArrayList<WebViewProviderInfo>(Arrays.asList(WebViewFactory.getWebViewPackages())); new ArrayList<WebViewProviderInfo>(Arrays.asList(mWebViewUtility.getWebViewPackages())); Iterator<WebViewProviderInfo> it = webViewProviders.iterator(); // remove non-valid packages while(it.hasNext()) { Loading @@ -435,17 +429,6 @@ public class WebViewUpdateService extends SystemService { } } private static String getUserChosenWebViewProvider() { return Settings.Global.getString(AppGlobals.getInitialApplication().getContentResolver(), Settings.Global.WEBVIEW_PROVIDER); } private void updateUserSetting(String newProviderName) { Settings.Global.putString(getContext().getContentResolver(), Settings.Global.WEBVIEW_PROVIDER, newProviderName == null ? "" : newProviderName); } /** * Returns either the package info of the WebView provider determined in the following way: * If the user has chosen a provider then use that if it is valid, Loading @@ -456,7 +439,7 @@ public class WebViewUpdateService extends SystemService { private PackageInfo findPreferredWebViewPackage() { WebViewProviderInfo[] providers = mCurrentValidWebViewPackages; String userChosenProvider = getUserChosenWebViewProvider(); String userChosenProvider = mWebViewUtility.getUserChosenWebViewProvider(getContext()); // If the user has chosen provider, use that for (WebViewProviderInfo provider : providers) { Loading Loading @@ -615,6 +598,11 @@ public class WebViewUpdateService extends SystemService { } } @Override // Binder call public WebViewProviderInfo[] getAllWebViewPackages() { return WebViewUpdateService.this.mWebViewUtility.getWebViewPackages(); } @Override // Binder call public String getCurrentWebViewPackageName() { synchronized(WebViewUpdateService.this) { Loading @@ -626,7 +614,7 @@ public class WebViewUpdateService extends SystemService { @Override // Binder call public boolean isFallbackPackage(String packageName) { return WebViewUpdateService.isFallbackPackage(packageName); return WebViewUpdateService.this.isFallbackPackage(packageName); } @Override // Binder call Loading
services/core/java/com/android/server/webkit/WebViewUtilityImpl.java 0 → 100644 +161 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.webkit; import android.app.ActivityManagerNative; import android.app.AppGlobals; import android.content.Context; import android.content.pm.PackageInfo; import android.content.res.XmlResourceParser; import android.os.RemoteException; import android.os.UserHandle; import android.provider.Settings; import android.util.AndroidRuntimeException; import android.util.Log; import android.webkit.WebViewFactory; import android.webkit.WebViewFactory.MissingWebViewPackageException; import android.webkit.WebViewProviderInfo; import com.android.internal.util.XmlUtils; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.xmlpull.v1.XmlPullParserException; /** * Default implementation for the WebView preparation Utility interface. * @hide */ public class WebViewUtilityImpl implements WebViewUtilityInterface { private static final String TAG = WebViewUtilityImpl.class.getSimpleName(); private static final String TAG_START = "webviewproviders"; private static final String TAG_WEBVIEW_PROVIDER = "webviewprovider"; private static final String TAG_PACKAGE_NAME = "packageName"; private static final String TAG_DESCRIPTION = "description"; // Whether or not the provider must be explicitly chosen by the user to be used. private static final String TAG_AVAILABILITY = "availableByDefault"; private static final String TAG_SIGNATURE = "signature"; private static final String TAG_FALLBACK = "isFallback"; /** * Returns all packages declared in the framework resources as potential WebView providers. * @hide * */ @Override public WebViewProviderInfo[] getWebViewPackages() { int numFallbackPackages = 0; XmlResourceParser parser = null; List<WebViewProviderInfo> webViewProviders = new ArrayList<WebViewProviderInfo>(); try { parser = AppGlobals.getInitialApplication().getResources().getXml( com.android.internal.R.xml.config_webview_packages); XmlUtils.beginDocument(parser, TAG_START); while(true) { XmlUtils.nextElement(parser); String element = parser.getName(); if (element == null) { break; } if (element.equals(TAG_WEBVIEW_PROVIDER)) { String packageName = parser.getAttributeValue(null, TAG_PACKAGE_NAME); if (packageName == null) { throw new MissingWebViewPackageException( "WebView provider in framework resources missing package name"); } String description = parser.getAttributeValue(null, TAG_DESCRIPTION); if (description == null) { throw new MissingWebViewPackageException( "WebView provider in framework resources missing description"); } boolean availableByDefault = "true".equals( 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()) { numFallbackPackages++; if (numFallbackPackages > 1) { throw new AndroidRuntimeException( "There can be at most one webview fallback package."); } } webViewProviders.add(currentProvider); } else { Log.e(TAG, "Found an element that is not a webview provider"); } } } catch(XmlPullParserException e) { throw new MissingWebViewPackageException("Error when parsing WebView meta data " + e); } catch(IOException e) { throw new MissingWebViewPackageException("Error when parsing WebView meta data " + e); } finally { if (parser != null) parser.close(); } return webViewProviders.toArray(new WebViewProviderInfo[webViewProviders.size()]); } /** * Reads all signatures at the current depth (within the current provider) from the XML parser. */ private static String[] readSignatures(XmlResourceParser parser) throws IOException, XmlPullParserException { List<String> signatures = new ArrayList<String>(); int outerDepth = parser.getDepth(); while(XmlUtils.nextElementWithin(parser, outerDepth)) { if (parser.getName().equals(TAG_SIGNATURE)) { // Parse the value within the signature tag String signature = parser.nextText(); signatures.add(signature); } else { Log.e(TAG, "Found an element in a webview provider that is not a signature"); } } return signatures.toArray(new String[signatures.size()]); } @Override public int onWebViewProviderChanged(PackageInfo packageInfo) { return WebViewFactory.onWebViewProviderChanged(packageInfo); } @Override public String getUserChosenWebViewProvider(Context context) { return Settings.Global.getString(context.getContentResolver(), Settings.Global.WEBVIEW_PROVIDER); } @Override public void updateUserSetting(Context context, String newProviderName) { Settings.Global.putString(context.getContentResolver(), Settings.Global.WEBVIEW_PROVIDER, newProviderName == null ? "" : newProviderName); } @Override public void killPackageDependents(String packageName) { try { ActivityManagerNative.getDefault().killPackageDependents(packageName, UserHandle.USER_ALL); } catch (RemoteException e) { } } }