diff options
Diffstat (limited to 'core/java')
| -rw-r--r-- | core/java/android/app/ActivityManagerNative.java | 21 | ||||
| -rw-r--r-- | core/java/android/app/IActivityManager.java | 2 | ||||
| -rw-r--r-- | core/java/android/provider/Settings.java | 7 | ||||
| -rw-r--r-- | core/java/android/webkit/IWebViewUpdateService.aidl | 26 | ||||
| -rw-r--r-- | core/java/android/webkit/WebViewFactory.java | 281 | ||||
| -rw-r--r-- | core/java/android/webkit/WebViewProviderInfo.aidl | 19 | ||||
| -rw-r--r-- | core/java/android/webkit/WebViewProviderInfo.java | 140 | ||||
| -rw-r--r-- | core/java/android/webkit/WebViewProviderResponse.aidl | 19 | ||||
| -rw-r--r-- | core/java/android/webkit/WebViewProviderResponse.java | 61 |
9 files changed, 454 insertions, 122 deletions
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index f3242a78f202..744c528c8602 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -1558,6 +1558,15 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM return true; } + case KILL_PACKAGE_DEPENDENTS_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + String packageName = data.readString(); + int userId = data.readInt(); + killPackageDependents(packageName, userId); + reply.writeNoException(); + return true; + } + case FORCE_STOP_PACKAGE_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); String packageName = data.readString(); @@ -4736,6 +4745,18 @@ class ActivityManagerProxy implements IActivityManager reply.recycle(); } + public void killPackageDependents(String packageName, int userId) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeString(packageName); + data.writeInt(userId); + mRemote.transact(KILL_PACKAGE_DEPENDENTS_TRANSACTION, data, reply, 0); + reply.readException(); + data.recycle(); + reply.recycle(); + } + public void forceStopPackage(String packageName, int userId) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 22a2d649739d..c3db8097b291 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -259,6 +259,7 @@ public interface IActivityManager extends IInterface { public void killBackgroundProcesses(final String packageName, int userId) throws RemoteException; public void killAllBackgroundProcesses() throws RemoteException; + public void killPackageDependents(final String packageName, int userId) throws RemoteException; public void forceStopPackage(final String packageName, int userId) throws RemoteException; // Note: probably don't want to allow applications access to these. @@ -912,4 +913,5 @@ public interface IActivityManager extends IInterface { int UNLOCK_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 351; int IN_MULTI_WINDOW_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 352; int IN_PICTURE_IN_PICTURE_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 353; + int KILL_PACKAGE_DEPENDENTS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 354; } diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 74fd8cd10de3..a1e551082799 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -5749,6 +5749,13 @@ public final class Settings { "camera_double_tap_power_gesture_disabled"; /** + * Name of the package used as WebView provider (if unset the provider is instead determined + * by the system). + * @hide + */ + public static final String WEBVIEW_PROVIDER = "webview_provider"; + + /** * This are the settings to be backed up. * * NOTE: Settings are backed up and restored in the order they appear diff --git a/core/java/android/webkit/IWebViewUpdateService.aidl b/core/java/android/webkit/IWebViewUpdateService.aidl index a77459b09251..89d5d69de392 100644 --- a/core/java/android/webkit/IWebViewUpdateService.aidl +++ b/core/java/android/webkit/IWebViewUpdateService.aidl @@ -16,6 +16,10 @@ package android.webkit; +import android.content.pm.PackageInfo; +import android.webkit.WebViewProviderInfo; +import android.webkit.WebViewProviderResponse; + /** * Private service to wait for the updatable WebView to be ready for use. * @hide @@ -25,12 +29,28 @@ interface IWebViewUpdateService { /** * Used by the relro file creator to notify the service that it's done. */ - void notifyRelroCreationCompleted(boolean is64Bit, boolean success); + void notifyRelroCreationCompleted(); /** * Used by WebViewFactory to block loading of WebView code until - * preparations are complete. + * preparations are complete. Returns the package used as WebView provider. */ - void waitForRelroCreationCompleted(boolean is64Bit); + WebViewProviderResponse waitForAndGetProvider(); + /** + * DevelopmentSettings uses this to notify WebViewUpdateService that a + * new provider has been selected by the user. + */ + void changeProviderAndSetting(String newProvider); + + /** + * DevelopmentSettings uses this to get the current available WebView + * providers (to display as choices to the user). + */ + WebViewProviderInfo[] getValidWebViewPackages(); + + /** + * Used by DevelopmentSetting to get the name of the WebView provider currently in use. + */ + String getCurrentWebViewPackageName(); } diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java index 229011db049c..01d15664f24a 100644 --- a/core/java/android/webkit/WebViewFactory.java +++ b/core/java/android/webkit/WebViewFactory.java @@ -24,6 +24,7 @@ import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; +import android.content.res.XmlResourceParser; import android.os.Build; import android.os.Process; import android.os.RemoteException; @@ -31,20 +32,27 @@ import android.os.ServiceManager; import android.os.StrictMode; import android.os.SystemProperties; import android.os.Trace; +import android.provider.Settings; +import android.provider.Settings.Secure; import android.text.TextUtils; import android.util.AndroidRuntimeException; import android.util.Log; +import com.android.internal.util.XmlUtils; import com.android.server.LocalServices; import dalvik.system.VMRuntime; import java.io.File; import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; +import org.xmlpull.v1.XmlPullParserException; + /** * Top level factory, used creating all the main WebView implementation classes. * @@ -83,6 +91,8 @@ public final class WebViewFactory { public static final int LIBLOAD_SUCCESS = 0; public static final int LIBLOAD_WRONG_PACKAGE_NAME = 1; public static final int LIBLOAD_ADDRESS_SPACE_NOT_RESERVED = 2; + + // error codes for waiting for WebView preparation public static final int LIBLOAD_FAILED_WAITING_FOR_RELRO = 3; public static final int LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES = 4; @@ -91,57 +101,95 @@ public final class WebViewFactory { public static final int LIBLOAD_FAILED_TO_LOAD_LIBRARY = 6; public static final int LIBLOAD_FAILED_JNI_CALL = 7; - private static class MissingWebViewPackageException extends AndroidRuntimeException { - public MissingWebViewPackageException(String message) { super(message); } - public MissingWebViewPackageException(Exception e) { super(e); } - } - - /** @hide */ - public static String[] getWebViewPackageNames() { - return AppGlobals.getInitialApplication().getResources().getStringArray( - com.android.internal.R.array.config_webViewPackageNames); - } - - // TODO (gsennton) remove when committing webview xts test change - public static String getWebViewPackageName() { - String[] webViewPackageNames = getWebViewPackageNames(); - return webViewPackageNames[webViewPackageNames.length-1]; + // more error codes for waiting for WebView preparation + public static final int LIBLOAD_WEBVIEW_BEING_REPLACED = 8; + public static final int LIBLOAD_FAILED_WAITING_FOR_WEBVIEW_REASON_UNKNOWN = 9; + + private static String getWebViewPreparationErrorReason(int error) { + switch (error) { + case LIBLOAD_FAILED_WAITING_FOR_RELRO: + return "Time out waiting for Relro files being created"; + case LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES: + return "No WebView installed"; + case LIBLOAD_WEBVIEW_BEING_REPLACED: + return "Time out waiting for WebView to be replaced"; + case LIBLOAD_FAILED_WAITING_FOR_WEBVIEW_REASON_UNKNOWN: + return "Crashed for unknown reason"; + } + return "Unknown"; } /** - * Return the package info of the first package in the webview priority list that contains - * webview. - * * @hide */ - public static PackageInfo findPreferredWebViewPackage() { - PackageManager pm = AppGlobals.getInitialApplication().getPackageManager(); + public static class MissingWebViewPackageException extends AndroidRuntimeException { + public MissingWebViewPackageException(String message) { super(message); } + public MissingWebViewPackageException(Exception e) { super(e); } + } - for (String packageName : getWebViewPackageNames()) { - try { - PackageInfo packageInfo = pm.getPackageInfo(packageName, - PackageManager.GET_META_DATA); - ApplicationInfo applicationInfo = packageInfo.applicationInfo; + 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"; + private static String TAG_SIGNATURE = "signature"; - // If the correct flag is set the package contains webview. - if (getWebViewLibrary(applicationInfo) != null) { - return packageInfo; + /** + * Returns all packages declared in the framework resources as potential WebView providers. + * @hide + * */ + public static WebViewProviderInfo[] getWebViewPackages() { + 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"); + } + String signature = parser.getAttributeValue(null, TAG_SIGNATURE); + webViewProviders.add( + new WebViewProviderInfo(packageName, description, signature)); + } + else { + Log.e(LOGTAG, "Found an element that is not a webview provider"); } - } catch (PackageManager.NameNotFoundException e) { } + } 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(); } - throw new MissingWebViewPackageException("Could not find a loadable WebView package"); + return webViewProviders.toArray(new WebViewProviderInfo[webViewProviders.size()]); } - // throws MissingWebViewPackageException - private static ApplicationInfo getWebViewApplicationInfo() { - if (sPackageInfo == null) - return findPreferredWebViewPackage().applicationInfo; - else - return sPackageInfo.applicationInfo; + + // TODO (gsennton) remove when committing webview xts test change + public static String getWebViewPackageName() { + WebViewProviderInfo[] providers = getWebViewPackages(); + return providers[0].packageName; } - private static String getWebViewLibrary(ApplicationInfo ai) { + /** + * @hide + */ + public static String getWebViewLibrary(ApplicationInfo ai) { if (ai.metaData != null) return ai.metaData.getString("com.android.webview.WebViewLibrary"); return null; @@ -156,16 +204,14 @@ public final class WebViewFactory { * name is the same as the one providing the webview. */ public static int loadWebViewNativeLibraryFromPackage(String packageName) { - try { - sPackageInfo = findPreferredWebViewPackage(); - } catch (MissingWebViewPackageException e) { - return LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES; + int ret = waitForProviderAndSetPackageInfo(); + if (ret != LIBLOAD_SUCCESS) { + return ret; } + if (!sPackageInfo.packageName.equals(packageName)) + return LIBLOAD_WRONG_PACKAGE_NAME; - if (packageName != null && packageName.equals(sPackageInfo.packageName)) { - return loadNativeLibrary(); - } - return LIBLOAD_WRONG_PACKAGE_NAME; + return loadNativeLibrary(); } static WebViewFactoryProvider getProvider() { @@ -207,17 +253,45 @@ public final class WebViewFactory { private static Class<WebViewFactoryProvider> getProviderClass() { try { // First fetch the package info so we can log the webview package version. - sPackageInfo = findPreferredWebViewPackage(); + int res = waitForProviderAndSetPackageInfo(); + if (res != LIBLOAD_SUCCESS) { + throw new MissingWebViewPackageException( + "Failed to load WebView provider, error: " + + getWebViewPreparationErrorReason(res)); + } Log.i(LOGTAG, "Loading " + sPackageInfo.packageName + " version " + sPackageInfo.versionName + " (code " + sPackageInfo.versionCode + ")"); + Application initialApplication = AppGlobals.getInitialApplication(); + Context webViewContext = null; + try { + // Construct a package context to load the Java code into the current app. + // This is done as early as possible since by constructing a package context we + // register the WebView package as a dependency for the current application so that + // when the WebView package is updated this application will be killed. + webViewContext = initialApplication.createPackageContext( + sPackageInfo.packageName, + Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY); + } catch (PackageManager.NameNotFoundException e) { + throw new MissingWebViewPackageException(e); + } + Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.loadNativeLibrary()"); loadNativeLibrary(); Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW); Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.getChromiumProviderClass()"); try { - return getChromiumProviderClass(); + initialApplication.getAssets().addAssetPathAsSharedLibrary( + webViewContext.getApplicationInfo().sourceDir); + ClassLoader clazzLoader = webViewContext.getClassLoader(); + Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "Class.forName()"); + try { + return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY, + true, clazzLoader); + } finally { + Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW); + } } catch (ClassNotFoundException e) { Log.e(LOGTAG, "error loading provider", e); throw new AndroidRuntimeException(e); @@ -239,30 +313,6 @@ public final class WebViewFactory { } } - // throws MissingWebViewPackageException - private static Class<WebViewFactoryProvider> getChromiumProviderClass() - throws ClassNotFoundException { - Application initialApplication = AppGlobals.getInitialApplication(); - try { - // Construct a package context to load the Java code into the current app. - Context webViewContext = initialApplication.createPackageContext( - sPackageInfo.packageName, - Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY); - initialApplication.getAssets().addAssetPathAsSharedLibrary( - webViewContext.getApplicationInfo().sourceDir); - ClassLoader clazzLoader = webViewContext.getClassLoader(); - Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "Class.forName()"); - try { - return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY, true, - clazzLoader); - } finally { - Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW); - } - } catch (PackageManager.NameNotFoundException e) { - throw new MissingWebViewPackageException(e); - } - } - /** * Perform any WebView loading preparations that must happen in the zygote. * Currently, this means allocating address space to load the real JNI library later. @@ -289,44 +339,34 @@ public final class WebViewFactory { } } - /** - * Perform any WebView loading preparations that must happen at boot from the system server, - * after the package manager has started or after an update to the webview is installed. - * This must be called in the system server. - * Currently, this means spawning the child processes which will create the relro files. - */ - public static void prepareWebViewInSystemServer() { - String[] nativePaths = null; - try { - nativePaths = getWebViewNativeLibraryPaths(); - } catch (Throwable t) { - // Log and discard errors at this stage as we must not crash the system server. - Log.e(LOGTAG, "error preparing webview native library", t); - } - prepareWebViewInSystemServer(nativePaths); - } - - private static void prepareWebViewInSystemServer(String[] nativeLibraryPaths) { + private static int prepareWebViewInSystemServer(String[] nativeLibraryPaths) { if (DEBUG) Log.v(LOGTAG, "creating relro files"); + int numRelros = 0; // We must always trigger createRelRo regardless of the value of nativeLibraryPaths. Any // unexpected values will be handled there to ensure that we trigger notifying any process - // waiting on relreo creation. + // waiting on relro creation. if (Build.SUPPORTED_32_BIT_ABIS.length > 0) { if (DEBUG) Log.v(LOGTAG, "Create 32 bit relro"); createRelroFile(false /* is64Bit */, nativeLibraryPaths); + numRelros++; } if (Build.SUPPORTED_64_BIT_ABIS.length > 0) { if (DEBUG) Log.v(LOGTAG, "Create 64 bit relro"); createRelroFile(true /* is64Bit */, nativeLibraryPaths); + numRelros++; } + return numRelros; } - public static void onWebViewUpdateInstalled() { + /** + * @hide + */ + public static int onWebViewProviderChanged(PackageInfo packageInfo) { String[] nativeLibs = null; try { - nativeLibs = WebViewFactory.getWebViewNativeLibraryPaths(); + nativeLibs = WebViewFactory.getWebViewNativeLibraryPaths(packageInfo); if (nativeLibs != null) { long newVmSize = 0L; @@ -373,7 +413,7 @@ public final class WebViewFactory { // Log and discard errors at this stage as we must not crash the system server. Log.e(LOGTAG, "error preparing webview native library", t); } - prepareWebViewInSystemServer(nativeLibs); + return prepareWebViewInSystemServer(nativeLibs); } // throws MissingWebViewPackageException @@ -397,8 +437,8 @@ public final class WebViewFactory { } // throws MissingWebViewPackageException - private static String[] getWebViewNativeLibraryPaths() { - ApplicationInfo ai = getWebViewApplicationInfo(); + private static String[] getWebViewNativeLibraryPaths(PackageInfo packageInfo) { + ApplicationInfo ai = packageInfo.applicationInfo; final String NATIVE_LIB_FILE_NAME = getWebViewLibrary(ai); String path32; @@ -460,7 +500,7 @@ public final class WebViewFactory { public void run() { try { Log.e(LOGTAG, "relro file creator for " + abi + " crashed. Proceeding without"); - getUpdateService().notifyRelroCreationCompleted(is64Bit, false); + getUpdateService().notifyRelroCreationCompleted(); } catch (RemoteException e) { Log.e(LOGTAG, "Cannot reach WebViewUpdateService. " + e.getMessage()); } @@ -508,7 +548,7 @@ public final class WebViewFactory { } finally { // We must do our best to always notify the update service, even if something fails. try { - getUpdateService().notifyRelroCreationCompleted(is64Bit, result); + getUpdateService().notifyRelroCreationCompleted(); } catch (RemoteException e) { Log.e(LOGTAG, "error notifying update service", e); } @@ -521,35 +561,38 @@ public final class WebViewFactory { } } + private static int waitForProviderAndSetPackageInfo() { + WebViewProviderResponse response = null; + try { + response = + getUpdateService().waitForAndGetProvider(); + if (response.status == WebViewFactory.LIBLOAD_SUCCESS) + sPackageInfo = response.packageInfo; + } catch (RemoteException e) { + Log.e(LOGTAG, "error waiting for relro creation", e); + return LIBLOAD_FAILED_WAITING_FOR_WEBVIEW_REASON_UNKNOWN; + } + return response.status; + } + + // Assumes that we have waited for relro creation and set sPackageInfo private static int loadNativeLibrary() { if (!sAddressSpaceReserved) { Log.e(LOGTAG, "can't load with relro file; address space not reserved"); return LIBLOAD_ADDRESS_SPACE_NOT_RESERVED; } - try { - getUpdateService().waitForRelroCreationCompleted(VMRuntime.getRuntime().is64Bit()); - } catch (RemoteException e) { - Log.e(LOGTAG, "error waiting for relro creation, proceeding without", e); - return LIBLOAD_FAILED_WAITING_FOR_RELRO; - } - - try { - String[] args = getWebViewNativeLibraryPaths(); - int result = nativeLoadWithRelroFile(args[0] /* path32 */, - args[1] /* path64 */, - CHROMIUM_WEBVIEW_NATIVE_RELRO_32, - CHROMIUM_WEBVIEW_NATIVE_RELRO_64); - if (result != LIBLOAD_SUCCESS) { - Log.w(LOGTAG, "failed to load with relro file, proceeding without"); - } else if (DEBUG) { - Log.v(LOGTAG, "loaded with relro file"); - } - return result; - } catch (MissingWebViewPackageException e) { - Log.e(LOGTAG, "Failed to list WebView package libraries for loadNativeLibrary", e); - return LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES; + String[] args = getWebViewNativeLibraryPaths(sPackageInfo); + int result = nativeLoadWithRelroFile(args[0] /* path32 */, + args[1] /* path64 */, + CHROMIUM_WEBVIEW_NATIVE_RELRO_32, + CHROMIUM_WEBVIEW_NATIVE_RELRO_64); + if (result != LIBLOAD_SUCCESS) { + Log.w(LOGTAG, "failed to load with relro file, proceeding without"); + } else if (DEBUG) { + Log.v(LOGTAG, "loaded with relro file"); } + return result; } private static IWebViewUpdateService getUpdateService() { diff --git a/core/java/android/webkit/WebViewProviderInfo.aidl b/core/java/android/webkit/WebViewProviderInfo.aidl new file mode 100644 index 000000000000..82e5a7936de8 --- /dev/null +++ b/core/java/android/webkit/WebViewProviderInfo.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2015 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 android.webkit; + +parcelable WebViewProviderInfo; diff --git a/core/java/android/webkit/WebViewProviderInfo.java b/core/java/android/webkit/WebViewProviderInfo.java new file mode 100644 index 000000000000..d5e3a230919b --- /dev/null +++ b/core/java/android/webkit/WebViewProviderInfo.java @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2015 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 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 { + + /** + * @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, String signature) { + this.packageName = packageName; + this.description = description; + this.signature = signature; + } + + 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 (signature == null) + return getPackageInfo().applicationInfo.isSystemApp(); + + packageSignatures = getPackageInfo().signatures; + } catch (WebViewPackageNotFoundException e) { + return false; + } + if (packageSignatures.length != 1) + return false; + final byte[] releaseSignature = Base64.decode(signature, Base64.DEFAULT); + return Arrays.equals(releaseSignature, packageSignatures[0].toByteArray()); + } + + /** + * 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; + } + + public PackageInfo getPackageInfo() { + if (packageInfo == null) { + try { + PackageManager pm = AppGlobals.getInitialApplication().getPackageManager(); + packageInfo = pm.getPackageInfo(packageName, PACKAGE_FLAGS); + } catch (PackageManager.NameNotFoundException e) { + throw new WebViewPackageNotFoundException(e); + } + } + return packageInfo; + } + + // aidl stuff + public static final Parcelable.Creator<WebViewProviderInfo> CREATOR = + new Parcelable.Creator<WebViewProviderInfo>() { + public WebViewProviderInfo createFromParcel(Parcel in) { + return new WebViewProviderInfo(in); + } + + public WebViewProviderInfo[] newArray(int size) { + return new WebViewProviderInfo[size]; + } + }; + + private WebViewProviderInfo(Parcel in) { + packageName = in.readString(); + description = in.readString(); + signature = in.readString(); + packageInfo = null; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeString(packageName); + out.writeString(description); + out.writeString(signature); + } + + // fields read from framework resource + public String packageName; + public String description; + + private String signature; + + 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; +} + diff --git a/core/java/android/webkit/WebViewProviderResponse.aidl b/core/java/android/webkit/WebViewProviderResponse.aidl new file mode 100644 index 000000000000..9c884cc7ad33 --- /dev/null +++ b/core/java/android/webkit/WebViewProviderResponse.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2015 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 android.webkit; + +parcelable WebViewProviderResponse; diff --git a/core/java/android/webkit/WebViewProviderResponse.java b/core/java/android/webkit/WebViewProviderResponse.java new file mode 100644 index 000000000000..f5e09e2be71e --- /dev/null +++ b/core/java/android/webkit/WebViewProviderResponse.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2015 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 android.webkit; + +import android.content.pm.PackageInfo; +import android.os.Parcel; +import android.os.Parcelable; + +/** @hide */ +public class WebViewProviderResponse implements Parcelable { + + public WebViewProviderResponse(PackageInfo packageInfo, int status) { + this.packageInfo = packageInfo; + this.status = status; + } + + // aidl stuff + public static final Parcelable.Creator<WebViewProviderResponse> CREATOR = + new Parcelable.Creator<WebViewProviderResponse>() { + public WebViewProviderResponse createFromParcel(Parcel in) { + return new WebViewProviderResponse(in); + } + + public WebViewProviderResponse[] newArray(int size) { + return new WebViewProviderResponse[size]; + } + }; + + private WebViewProviderResponse(Parcel in) { + packageInfo = in.readTypedObject(PackageInfo.CREATOR); + status = in.readInt(); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeTypedObject(packageInfo, flags); + out.writeInt(status); + } + + PackageInfo packageInfo; + int status; +} |
