summaryrefslogtreecommitdiff
path: root/core/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/app/ActivityManagerNative.java21
-rw-r--r--core/java/android/app/IActivityManager.java2
-rw-r--r--core/java/android/provider/Settings.java7
-rw-r--r--core/java/android/webkit/IWebViewUpdateService.aidl26
-rw-r--r--core/java/android/webkit/WebViewFactory.java281
-rw-r--r--core/java/android/webkit/WebViewProviderInfo.aidl19
-rw-r--r--core/java/android/webkit/WebViewProviderInfo.java140
-rw-r--r--core/java/android/webkit/WebViewProviderResponse.aidl19
-rw-r--r--core/java/android/webkit/WebViewProviderResponse.java61
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;
+}