diff options
-rw-r--r-- | api/system-current.txt | 1 | ||||
-rw-r--r-- | core/java/android/webkit/WebViewFactory.java | 3 | ||||
-rw-r--r-- | core/java/android/webkit/WebViewLibraryLoader.java | 218 | ||||
-rw-r--r-- | core/tests/webkit/Android.mk | 45 | ||||
-rw-r--r-- | core/tests/webkit/AndroidManifest.xml | 30 | ||||
-rw-r--r-- | core/tests/webkit/AndroidTest.xml | 30 | ||||
-rw-r--r-- | core/tests/webkit/OWNERS | 3 | ||||
-rw-r--r-- | core/tests/webkit/apk_with_native_libs/Android.mk | 71 | ||||
-rw-r--r-- | core/tests/webkit/apk_with_native_libs/inapk/AndroidManifest.xml | 29 | ||||
-rw-r--r-- | core/tests/webkit/apk_with_native_libs/jni/Android.mk | 32 | ||||
-rw-r--r-- | core/tests/webkit/apk_with_native_libs/jni/WebViewTestJniOnLoad.cpp | 21 | ||||
-rw-r--r-- | core/tests/webkit/apk_with_native_libs/ondisk/AndroidManifest.xml | 28 | ||||
-rw-r--r-- | core/tests/webkit/apk_with_native_libs/src/com/google/android/xts/webview_list/WebViewLoadingTestClass.java | 24 | ||||
-rw-r--r-- | core/tests/webkit/unit_tests_src/com/android/webkit/WebViewLibraryLoaderTest.java | 329 | ||||
-rw-r--r-- | native/webview/loader/loader.cpp | 20 |
15 files changed, 58 insertions, 826 deletions
diff --git a/api/system-current.txt b/api/system-current.txt index 6a00815e78a8..161d5cf71146 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -6708,7 +6708,6 @@ package android.webkit { method public static android.content.pm.PackageInfo getLoadedPackageInfo(); method public static int loadWebViewNativeLibraryFromPackage(java.lang.String, java.lang.ClassLoader); method public static void prepareWebViewInZygote(); - field public static final java.lang.String CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY = "persist.sys.webview.vmsize"; field public static final int LIBLOAD_ADDRESS_SPACE_NOT_RESERVED = 2; // 0x2 field public static final int LIBLOAD_FAILED_JNI_CALL = 7; // 0x7 field public static final int LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES = 4; // 0x4 diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java index e0ccda98bf1d..cc0cf0293648 100644 --- a/core/java/android/webkit/WebViewFactory.java +++ b/core/java/android/webkit/WebViewFactory.java @@ -50,9 +50,6 @@ public final class WebViewFactory { private static final String CHROMIUM_WEBVIEW_FACTORY_METHOD = "create"; - public static final String CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY = - "persist.sys.webview.vmsize"; - private static final String LOGTAG = "WebViewFactory"; private static final boolean DEBUG = false; diff --git a/core/java/android/webkit/WebViewLibraryLoader.java b/core/java/android/webkit/WebViewLibraryLoader.java index cabba06bdff5..5a6aebaaad51 100644 --- a/core/java/android/webkit/WebViewLibraryLoader.java +++ b/core/java/android/webkit/WebViewLibraryLoader.java @@ -17,15 +17,14 @@ package android.webkit; import android.annotation.NonNull; -import android.annotation.Nullable; import android.app.ActivityManagerInternal; -import android.content.pm.ApplicationInfo; +import android.app.ActivityThread; +import android.app.LoadedApk; +import android.content.Context; import android.content.pm.PackageInfo; import android.os.Build; import android.os.Process; import android.os.RemoteException; -import android.os.SystemProperties; -import android.text.TextUtils; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; @@ -33,11 +32,7 @@ import com.android.server.LocalServices; import dalvik.system.VMRuntime; -import java.io.File; -import java.io.IOException; import java.util.Arrays; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; /** * @hide @@ -50,7 +45,6 @@ public class WebViewLibraryLoader { "/data/misc/shared_relro/libwebviewchromium32.relro"; private static final String CHROMIUM_WEBVIEW_NATIVE_RELRO_64 = "/data/misc/shared_relro/libwebviewchromium64.relro"; - private static final long CHROMIUM_WEBVIEW_DEFAULT_VMSIZE_BYTES = 100 * 1024 * 1024; private static final boolean DEBUG = false; @@ -69,18 +63,26 @@ public class WebViewLibraryLoader { boolean result = false; boolean is64Bit = VMRuntime.getRuntime().is64Bit(); try { - if (args.length != 1 || args[0] == null) { + if (args.length != 2 || args[0] == null || args[1] == null) { Log.e(LOGTAG, "Invalid RelroFileCreator args: " + Arrays.toString(args)); return; } - Log.v(LOGTAG, "RelroFileCreator (64bit = " + is64Bit + "), lib: " + args[0]); + String packageName = args[0]; + String libraryFileName = args[1]; + Log.v(LOGTAG, "RelroFileCreator (64bit = " + is64Bit + "), package: " + + packageName + " library: " + libraryFileName); if (!sAddressSpaceReserved) { Log.e(LOGTAG, "can't create relro file; address space not reserved"); return; } - result = nativeCreateRelroFile(args[0] /* path */, + LoadedApk apk = ActivityThread.currentActivityThread().getPackageInfo( + packageName, + null, + Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY); + result = nativeCreateRelroFile(libraryFileName, is64Bit ? CHROMIUM_WEBVIEW_NATIVE_RELRO_64 : - CHROMIUM_WEBVIEW_NATIVE_RELRO_32); + CHROMIUM_WEBVIEW_NATIVE_RELRO_32, + apk.getClassLoader()); if (result && DEBUG) Log.v(LOGTAG, "created relro file"); } finally { // We must do our best to always notify the update service, even if something fails. @@ -101,7 +103,8 @@ public class WebViewLibraryLoader { /** * Create a single relro file by invoking an isolated process that to do the actual work. */ - static void createRelroFile(final boolean is64Bit, @NonNull WebViewNativeLibrary nativeLib) { + static void createRelroFile(final boolean is64Bit, @NonNull String packageName, + @NonNull String libraryFileName) { final String abi = is64Bit ? Build.SUPPORTED_64_BIT_ABIS[0] : Build.SUPPORTED_32_BIT_ABIS[0]; @@ -119,13 +122,10 @@ public class WebViewLibraryLoader { }; try { - if (nativeLib == null || nativeLib.path == null) { - throw new IllegalArgumentException( - "Native library paths to the WebView RelRo process must not be null!"); - } boolean success = LocalServices.getService(ActivityManagerInternal.class) .startIsolatedProcess( - RelroFileCreator.class.getName(), new String[] { nativeLib.path }, + RelroFileCreator.class.getName(), + new String[] { packageName, libraryFileName }, "WebViewLoader-" + abi, abi, Process.SHARED_RELRO_UID, crashHandler); if (!success) throw new Exception("Failed to start the relro file creator process"); } catch (Throwable t) { @@ -140,83 +140,50 @@ public class WebViewLibraryLoader { * be called whenever we change WebView provider. * @return the number of relro processes started. */ - static int prepareNativeLibraries(PackageInfo webviewPackageInfo) - throws WebViewFactory.MissingWebViewPackageException { - WebViewNativeLibrary nativeLib32bit = - getWebViewNativeLibrary(webviewPackageInfo, false /* is64bit */); - WebViewNativeLibrary nativeLib64bit = - getWebViewNativeLibrary(webviewPackageInfo, true /* is64bit */); - updateWebViewZygoteVmSize(nativeLib32bit, nativeLib64bit); - - return createRelros(nativeLib32bit, nativeLib64bit); + static int prepareNativeLibraries(@NonNull PackageInfo webViewPackageInfo) { + // TODO(torne): new way of calculating VM size + // updateWebViewZygoteVmSize(nativeLib32bit, nativeLib64bit); + String libraryFileName = WebViewFactory.getWebViewLibrary( + webViewPackageInfo.applicationInfo); + if (libraryFileName == null) { + // Can't do anything with no filename, don't spawn any processes. + return 0; + } + return createRelros(webViewPackageInfo.packageName, libraryFileName); } /** * @return the number of relro processes started. */ - private static int createRelros(@Nullable WebViewNativeLibrary nativeLib32bit, - @Nullable WebViewNativeLibrary nativeLib64bit) { + private static int createRelros(@NonNull String packageName, @NonNull String libraryFileName) { if (DEBUG) Log.v(LOGTAG, "creating relro files"); int numRelros = 0; if (Build.SUPPORTED_32_BIT_ABIS.length > 0) { - if (nativeLib32bit == null) { - Log.e(LOGTAG, "No 32-bit WebView library path, skipping relro creation."); - } else { - if (DEBUG) Log.v(LOGTAG, "Create 32 bit relro"); - createRelroFile(false /* is64Bit */, nativeLib32bit); - numRelros++; - } + if (DEBUG) Log.v(LOGTAG, "Create 32 bit relro"); + createRelroFile(false /* is64Bit */, packageName, libraryFileName); + numRelros++; } if (Build.SUPPORTED_64_BIT_ABIS.length > 0) { - if (nativeLib64bit == null) { - Log.e(LOGTAG, "No 64-bit WebView library path, skipping relro creation."); - } else { - if (DEBUG) Log.v(LOGTAG, "Create 64 bit relro"); - createRelroFile(true /* is64Bit */, nativeLib64bit); - numRelros++; - } + if (DEBUG) Log.v(LOGTAG, "Create 64 bit relro"); + createRelroFile(true /* is64Bit */, packageName, libraryFileName); + numRelros++; } return numRelros; } /** - * - * @return the native WebView libraries in the new WebView APK. - */ - private static void updateWebViewZygoteVmSize( - @Nullable WebViewNativeLibrary nativeLib32bit, - @Nullable WebViewNativeLibrary nativeLib64bit) - throws WebViewFactory.MissingWebViewPackageException { - // Find the native libraries of the new WebView package, to change the size of the - // memory region in the Zygote reserved for the library. - long newVmSize = 0L; - - if (nativeLib32bit != null) newVmSize = Math.max(newVmSize, nativeLib32bit.size); - if (nativeLib64bit != null) newVmSize = Math.max(newVmSize, nativeLib64bit.size); - - if (DEBUG) { - Log.v(LOGTAG, "Based on library size, need " + newVmSize - + " bytes of address space."); - } - // The required memory can be larger than the file on disk (due to .bss), and an - // upgraded version of the library will likely be larger, so always attempt to - // reserve twice as much as we think to allow for the library to grow during this - // boot cycle. - newVmSize = Math.max(2 * newVmSize, CHROMIUM_WEBVIEW_DEFAULT_VMSIZE_BYTES); - Log.d(LOGTAG, "Setting new address space to " + newVmSize); - setWebViewZygoteVmSize(newVmSize); - } - - /** * Reserve space for the native library to be loaded into. */ static void reserveAddressSpaceInZygote() { System.loadLibrary("webviewchromium_loader"); - long addressSpaceToReserve = - SystemProperties.getLong(WebViewFactory.CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY, - CHROMIUM_WEBVIEW_DEFAULT_VMSIZE_BYTES); + boolean is64Bit = VMRuntime.getRuntime().is64Bit(); + // On 64-bit address space is really cheap and we can reserve 1GB which is plenty. + // On 32-bit it's fairly scarce and we should keep it to a realistic number that + // permits some future growth but doesn't hog space: we use 100MB which is more than 2x + // the current requirement. + long addressSpaceToReserve = is64Bit ? 1 * 1024 * 1024 * 1024 : 100 * 1024 * 1024; sAddressSpaceReserved = nativeReserveAddressSpace(addressSpaceToReserve); if (sAddressSpaceReserved) { @@ -253,106 +220,7 @@ public class WebViewLibraryLoader { return result; } - /** - * Fetch WebView's native library paths from {@param packageInfo}. - * @hide - */ - @Nullable - @VisibleForTesting - public static WebViewNativeLibrary getWebViewNativeLibrary(PackageInfo packageInfo, - boolean is64bit) throws WebViewFactory.MissingWebViewPackageException { - ApplicationInfo ai = packageInfo.applicationInfo; - final String nativeLibFileName = WebViewFactory.getWebViewLibrary(ai); - - String dir = getWebViewNativeLibraryDirectory(ai, is64bit /* 64bit */); - - WebViewNativeLibrary lib = findNativeLibrary(ai, nativeLibFileName, - is64bit ? Build.SUPPORTED_64_BIT_ABIS : Build.SUPPORTED_32_BIT_ABIS, dir); - - if (DEBUG) { - Log.v(LOGTAG, String.format("Native %d-bit lib: %s", is64bit ? 64 : 32, lib.path)); - } - return lib; - } - - /** - * @return the directory of the native WebView library with bitness {@param is64bit}. - * @hide - */ - @VisibleForTesting - public static String getWebViewNativeLibraryDirectory(ApplicationInfo ai, boolean is64bit) { - // Primary arch has the same bitness as the library we are looking for. - if (is64bit == VMRuntime.is64BitAbi(ai.primaryCpuAbi)) return ai.nativeLibraryDir; - - // Secondary arch has the same bitness as the library we are looking for. - if (!TextUtils.isEmpty(ai.secondaryCpuAbi)) { - return ai.secondaryNativeLibraryDir; - } - - return ""; - } - - /** - * @return an object describing a native WebView library given the directory path of that - * library, or null if the library couldn't be found. - */ - @Nullable - private static WebViewNativeLibrary findNativeLibrary(ApplicationInfo ai, - String nativeLibFileName, String[] abiList, String libDirectory) - throws WebViewFactory.MissingWebViewPackageException { - if (TextUtils.isEmpty(libDirectory)) return null; - String libPath = libDirectory + "/" + nativeLibFileName; - File f = new File(libPath); - if (f.exists()) { - return new WebViewNativeLibrary(libPath, f.length()); - } else { - return getLoadFromApkPath(ai.sourceDir, abiList, nativeLibFileName); - } - } - - /** - * @hide - */ - @VisibleForTesting - public static class WebViewNativeLibrary { - public final String path; - public final long size; - - WebViewNativeLibrary(String path, long size) { - this.path = path; - this.size = size; - } - } - - private static WebViewNativeLibrary getLoadFromApkPath(String apkPath, - String[] abiList, - String nativeLibFileName) - throws WebViewFactory.MissingWebViewPackageException { - // Search the APK for a native library conforming to a listed ABI. - try (ZipFile z = new ZipFile(apkPath)) { - for (String abi : abiList) { - final String entry = "lib/" + abi + "/" + nativeLibFileName; - ZipEntry e = z.getEntry(entry); - if (e != null && e.getMethod() == ZipEntry.STORED) { - // Return a path formatted for dlopen() load from APK. - return new WebViewNativeLibrary(apkPath + "!/" + entry, e.getSize()); - } - } - } catch (IOException e) { - throw new WebViewFactory.MissingWebViewPackageException(e); - } - return null; - } - - /** - * Sets the size of the memory area in which to store the relro section. - */ - private static void setWebViewZygoteVmSize(long vmSize) { - SystemProperties.set(WebViewFactory.CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY, - Long.toString(vmSize)); - } - static native boolean nativeReserveAddressSpace(long addressSpaceToReserve); - static native boolean nativeCreateRelroFile(String lib, String relro); + static native boolean nativeCreateRelroFile(String lib, String relro, ClassLoader clazzLoader); static native int nativeLoadWithRelroFile(String lib, String relro, ClassLoader clazzLoader); } diff --git a/core/tests/webkit/Android.mk b/core/tests/webkit/Android.mk deleted file mode 100644 index 45f6957c10e7..000000000000 --- a/core/tests/webkit/Android.mk +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright (C) 2017 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. - -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -# We only want this apk build for tests. -LOCAL_MODULE_TAGS := tests - -LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS) - - -# Include all test java files. -LOCAL_SRC_FILES := \ - $(call all-java-files-under, unit_tests_src) - -LOCAL_JAVA_LIBRARIES := android.test.runner - -LOCAL_STATIC_JAVA_LIBRARIES := \ - android-support-test - -LOCAL_PACKAGE_NAME := WebViewLoadingTests -LOCAL_PRIVATE_PLATFORM_APIS := true -LOCAL_CERTIFICATE := platform - -LOCAL_COMPATIBILITY_SUITE := device-tests - -LOCAL_REQUIRED_MODULES := \ - WebViewLoadingOnDiskTestApk \ - WebViewLoadingFromApkTestApk - -include $(BUILD_PACKAGE) - -include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/core/tests/webkit/AndroidManifest.xml b/core/tests/webkit/AndroidManifest.xml deleted file mode 100644 index 42accdf66891..000000000000 --- a/core/tests/webkit/AndroidManifest.xml +++ /dev/null @@ -1,30 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2017 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. ---> - -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.webkit.tests" - android:sharedUserId="android.uid.system"> - - <application> - <uses-library android:name="android.test.runner" /> - </application> - - <instrumentation - android:name="android.support.test.runner.AndroidJUnitRunner" - android:targetPackage="com.android.webkit.tests" - android:label="Frameworks WebView Loader Tests" /> - -</manifest> diff --git a/core/tests/webkit/AndroidTest.xml b/core/tests/webkit/AndroidTest.xml deleted file mode 100644 index 4c50b7df3368..000000000000 --- a/core/tests/webkit/AndroidTest.xml +++ /dev/null @@ -1,30 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2017 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. ---> -<configuration description="Runs Frameworks WebView Loading Tests."> - <option name="test-suite-tag" value="apct" /> - <option name="test-suite-tag" value="apct-instrumentation" /> - <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> - <option name="test-file-name" value="WebViewLoadingTests.apk" /> - <option name="test-file-name" value="WebViewLoadingOnDiskTestApk.apk" /> - <option name="test-file-name" value="WebViewLoadingFromApkTestApk.apk" /> - <option name="cleanup-apks" value="true" /> - <option name="alt-dir" value="out" /> - </target_preparer> - - <test class="com.android.tradefed.testtype.AndroidJUnitTest" > - <option name="package" value="com.android.webkit.tests" /> - </test> -</configuration> diff --git a/core/tests/webkit/OWNERS b/core/tests/webkit/OWNERS deleted file mode 100644 index 00e540a46ab2..000000000000 --- a/core/tests/webkit/OWNERS +++ /dev/null @@ -1,3 +0,0 @@ -changwan@google.com -tobiasjs@google.com -torne@google.com diff --git a/core/tests/webkit/apk_with_native_libs/Android.mk b/core/tests/webkit/apk_with_native_libs/Android.mk deleted file mode 100644 index e18a7e0df175..000000000000 --- a/core/tests/webkit/apk_with_native_libs/Android.mk +++ /dev/null @@ -1,71 +0,0 @@ -# Copyright (C) 2017 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. - -LOCAL_PATH := $(call my-dir) -MY_PATH := $(LOCAL_PATH) - -# Set shared variables -MY_MODULE_TAGS := optional -MY_JNI_SHARED_LIBRARIES := libwebviewtest_jni -MY_MODULE_PATH := $(TARGET_OUT_DATA_APPS) -MY_SRC_FILES := $(call all-java-files-under, src) -MY_CFLAGS := -Wall -Werror -MY_SDK_VERSION := system_current -MY_PROGUARD_ENABLED := disabled -MY_MULTILIB := both - -# Recurse down the file tree. -include $(call all-subdir-makefiles) - - - -# Builds an apk containing native libraries that will be unzipped on the device. -include $(CLEAR_VARS) - -LOCAL_PATH := $(MY_PATH) -LOCAL_PACKAGE_NAME := WebViewLoadingOnDiskTestApk -LOCAL_MANIFEST_FILE := ondisk/AndroidManifest.xml - -LOCAL_MODULE_TAGS := $(MY_MODULE_TAGS) -LOCAL_JNI_SHARED_LIBRARIES := $(MY_JNI_SHARED_LIBRARIES) -LOCAL_MODULE_PATH := $(MY_MODULE_PATH) -LOCAL_SRC_FILES := $(MY_SRC_FILES) -LOCAL_CFLAGS := $(MY_CFLAGS) -LOCAL_SDK_VERSION := $(MY_SDK_VERSION) -LOCAL_PROGUARD_ENABLED := $(MY_PROGUARD_ENABLED) -LOCAL_MULTILIB := $(MY_MULTILIB) -LOCAL_COMPATIBILITY_SUITE := device-tests - -include $(BUILD_PACKAGE) - - -# Builds an apk containing uncompressed native libraries that have to be -# accessed through the APK itself on the device. -include $(CLEAR_VARS) - -LOCAL_PATH := $(MY_PATH) -LOCAL_PACKAGE_NAME := WebViewLoadingFromApkTestApk -LOCAL_MANIFEST_FILE := inapk/AndroidManifest.xml - -LOCAL_MODULE_TAGS := $(MY_MODULE_TAGS) -LOCAL_JNI_SHARED_LIBRARIES := $(MY_JNI_SHARED_LIBRARIES) -LOCAL_MODULE_PATH := $(MY_MODULE_PATH) -LOCAL_SRC_FILES := $(MY_SRC_FILES) -LOCAL_CFLAGS := $(MY_CFLAGS) -LOCAL_SDK_VERSION := $(MY_SDK_VERSION) -LOCAL_PROGUARD_ENABLED := $(MY_PROGUARD_ENABLED) -LOCAL_MULTILIB := $(MY_MULTILIB) -LOCAL_COMPATIBILITY_SUITE := device-tests - -include $(BUILD_PACKAGE) diff --git a/core/tests/webkit/apk_with_native_libs/inapk/AndroidManifest.xml b/core/tests/webkit/apk_with_native_libs/inapk/AndroidManifest.xml deleted file mode 100644 index 868b2388d135..000000000000 --- a/core/tests/webkit/apk_with_native_libs/inapk/AndroidManifest.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - * Copyright (C) 2017 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. - --> - -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.webviewloading_test_from_apk" - android:versionCode="1" - android:versionName="0.0.0.1"> - - <application android:label="WebView Loading Test APK" - android:multiArch="true" - android:extractNativeLibs="false"> - <meta-data android:name="com.android.webview.WebViewLibrary" - android:value="libwebviewtest_jni.so" /> - </application> -</manifest> diff --git a/core/tests/webkit/apk_with_native_libs/jni/Android.mk b/core/tests/webkit/apk_with_native_libs/jni/Android.mk deleted file mode 100644 index fd5b5eb50c5f..000000000000 --- a/core/tests/webkit/apk_with_native_libs/jni/Android.mk +++ /dev/null @@ -1,32 +0,0 @@ -# -# Copyright (C) 2017 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. -# - -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_MODULE := libwebviewtest_jni - -LOCAL_MODULE_TAGS := optional - -LOCAL_SRC_FILES := WebViewTestJniOnLoad.cpp - -LOCAL_C_INCLUDES := $(JNI_H_INCLUDE) - -LOCAL_SDK_VERSION := current - -LOCAL_MULTILIB := both - -include $(BUILD_SHARED_LIBRARY) diff --git a/core/tests/webkit/apk_with_native_libs/jni/WebViewTestJniOnLoad.cpp b/core/tests/webkit/apk_with_native_libs/jni/WebViewTestJniOnLoad.cpp deleted file mode 100644 index 0ced4ee12ac5..000000000000 --- a/core/tests/webkit/apk_with_native_libs/jni/WebViewTestJniOnLoad.cpp +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2017 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. - */ - -#include <jni.h> - -jint JNI_OnLoad(JavaVM * /*vm*/, void * /*reserved*/) { - return JNI_VERSION_1_4; -} diff --git a/core/tests/webkit/apk_with_native_libs/ondisk/AndroidManifest.xml b/core/tests/webkit/apk_with_native_libs/ondisk/AndroidManifest.xml deleted file mode 100644 index ffffeb8e1630..000000000000 --- a/core/tests/webkit/apk_with_native_libs/ondisk/AndroidManifest.xml +++ /dev/null @@ -1,28 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - * Copyright (C) 2017 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. - --> - -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.webviewloading_test_on_disk" - android:versionCode="1" - android:versionName="0.0.0.1"> - - <application android:label="WebView Loading Test APK" - android:multiArch="true"> - <meta-data android:name="com.android.webview.WebViewLibrary" - android:value="libwebviewtest_jni.so" /> - </application> -</manifest> diff --git a/core/tests/webkit/apk_with_native_libs/src/com/google/android/xts/webview_list/WebViewLoadingTestClass.java b/core/tests/webkit/apk_with_native_libs/src/com/google/android/xts/webview_list/WebViewLoadingTestClass.java deleted file mode 100644 index 0efa4b4ac694..000000000000 --- a/core/tests/webkit/apk_with_native_libs/src/com/google/android/xts/webview_list/WebViewLoadingTestClass.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2017 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.webview.chromium; - -/** - * An empty class for testing purposes. - */ -public class WebViewLoadingTestClass { -} diff --git a/core/tests/webkit/unit_tests_src/com/android/webkit/WebViewLibraryLoaderTest.java b/core/tests/webkit/unit_tests_src/com/android/webkit/WebViewLibraryLoaderTest.java deleted file mode 100644 index e2f2d37a4d68..000000000000 --- a/core/tests/webkit/unit_tests_src/com/android/webkit/WebViewLibraryLoaderTest.java +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Copyright (C) 2017 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 static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.os.Build; -import android.os.Bundle; -import android.util.Log; - -import android.support.test.filters.MediumTest; -import android.support.test.filters.SmallTest; -import android.support.test.runner.AndroidJUnit4; -import android.support.test.InstrumentationRegistry; - -import java.io.File; -import java.io.IOException; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -/** - * Unit tests for {@link WebViewLibraryLoader}. - * Use the following command to run these tests: - * make WebViewLoadingTests \ - * && adb install -r -d \ - * ${ANDROID_PRODUCT_OUT}/data/app/WebViewLoadingTests/WebViewLoadingTests.apk \ - * && adb shell am instrument -e class 'android.webkit.WebViewLibraryLoaderTest' -w \ - * 'com.android.webkit.tests/android.support.test.runner.AndroidJUnitRunner' - */ -@RunWith(AndroidJUnit4.class) -public final class WebViewLibraryLoaderTest { - private static final String WEBVIEW_LIBS_ON_DISK_TEST_APK = - "com.android.webviewloading_test_on_disk"; - private static final String WEBVIEW_LIBS_IN_APK_TEST_APK = - "com.android.webviewloading_test_from_apk"; - private static final String WEBVIEW_LOADING_TEST_NATIVE_LIB = "libwebviewtest_jni.so"; - - private PackageInfo webviewOnDiskPackageInfo; - private PackageInfo webviewFromApkPackageInfo; - - @Before public void setUp() throws PackageManager.NameNotFoundException { - PackageManager pm = InstrumentationRegistry.getContext().getPackageManager(); - webviewOnDiskPackageInfo = - pm.getPackageInfo(WEBVIEW_LIBS_ON_DISK_TEST_APK, PackageManager.GET_META_DATA); - webviewFromApkPackageInfo = - pm.getPackageInfo(WEBVIEW_LIBS_IN_APK_TEST_APK, PackageManager.GET_META_DATA); - } - - private static boolean is64BitDevice() { - return Build.SUPPORTED_64_BIT_ABIS.length > 0; - } - - // We test the getWebViewNativeLibraryDirectory method here because it handled several different - // cases/combinations and it seems unnecessary to create one test-apk for each such combination - // and arch. - - /** - * Ensure we fetch the correct native library directories in the multi-arch case where - * the primary ABI is 64-bit. - */ - @SmallTest - @Test public void testGetWebViewLibDirMultiArchPrimary64bit() { - final String nativeLib = "nativeLib"; - final String secondaryNativeLib = "secondaryNativeLib"; - PackageInfo packageInfo = new PackageInfo(); - ApplicationInfo ai = new ApplicationInfoBuilder(). - // See VMRuntime.ABI_TO_INSTRUCTION_SET_MAP - setPrimaryCpuAbi("arm64-v8a"). - setNativeLibraryDir(nativeLib). - setSecondaryCpuAbi("armeabi"). - setSecondaryNativeLibraryDir(secondaryNativeLib). - create(); - packageInfo.applicationInfo = ai; - String actual32Lib = - WebViewLibraryLoader.getWebViewNativeLibraryDirectory(ai, false /* is64bit */); - String actual64Lib = - WebViewLibraryLoader.getWebViewNativeLibraryDirectory(ai, true /* is64bit */); - assertEquals(nativeLib, actual64Lib); - assertEquals(secondaryNativeLib, actual32Lib); - } - - /** - * Ensure we fetch the correct native library directory in the 64-bit single-arch case. - */ - @SmallTest - @Test public void testGetWebViewLibDirSingleArch64bit() { - final String nativeLib = "nativeLib"; - PackageInfo packageInfo = new PackageInfo(); - ApplicationInfo ai = new ApplicationInfoBuilder(). - // See VMRuntime.ABI_TO_INSTRUCTION_SET_MAP - setPrimaryCpuAbi("arm64-v8a"). - setNativeLibraryDir(nativeLib). - create(); - packageInfo.applicationInfo = ai; - String actual64Lib = - WebViewLibraryLoader.getWebViewNativeLibraryDirectory(ai, true /* is64bit */); - assertEquals(nativeLib, actual64Lib); - } - - /** - * Ensure we fetch the correct native library directory in the 32-bit single-arch case. - */ - @SmallTest - @Test public void testGetWebViewLibDirSingleArch32bit() { - final String nativeLib = "nativeLib"; - PackageInfo packageInfo = new PackageInfo(); - ApplicationInfo ai = new ApplicationInfoBuilder(). - // See VMRuntime.ABI_TO_INSTRUCTION_SET_MAP - setPrimaryCpuAbi("armeabi-v7a"). - setNativeLibraryDir(nativeLib). - create(); - packageInfo.applicationInfo = ai; - String actual32Lib = - WebViewLibraryLoader.getWebViewNativeLibraryDirectory(ai, false /* is64bit */); - assertEquals(nativeLib, actual32Lib); - } - - /** - * Ensure we fetch the correct 32-bit library path from an APK with 32-bit and 64-bit - * libraries unzipped onto disk. - */ - @MediumTest - @Test public void testGetWebViewLibraryPathOnDisk32Bit() - throws WebViewFactory.MissingWebViewPackageException { - WebViewLibraryLoader.WebViewNativeLibrary actualNativeLib = - WebViewLibraryLoader.getWebViewNativeLibrary( - webviewOnDiskPackageInfo, false /* is64bit */); - String expectedLibaryDirectory = is64BitDevice() ? - webviewOnDiskPackageInfo.applicationInfo.secondaryNativeLibraryDir : - webviewOnDiskPackageInfo.applicationInfo.nativeLibraryDir; - String lib32Path = expectedLibaryDirectory + "/" + WEBVIEW_LOADING_TEST_NATIVE_LIB; - assertEquals("Fetched incorrect 32-bit path from WebView library.", - lib32Path, actualNativeLib.path); - } - - /** - * Ensure we fetch the correct 64-bit library path from an APK with 32-bit and 64-bit - * libraries unzipped onto disk. - */ - @MediumTest - @Test public void testGetWebViewLibraryPathOnDisk64Bit() - throws WebViewFactory.MissingWebViewPackageException { - // A 32-bit device will not unpack 64-bit libraries. - if (!is64BitDevice()) return; - - WebViewLibraryLoader.WebViewNativeLibrary actualNativeLib = - WebViewLibraryLoader.getWebViewNativeLibrary( - webviewOnDiskPackageInfo, true /* is64bit */); - String lib64Path = webviewOnDiskPackageInfo.applicationInfo.nativeLibraryDir - + "/" + WEBVIEW_LOADING_TEST_NATIVE_LIB; - assertEquals("Fetched incorrect 64-bit path from WebView library.", - lib64Path, actualNativeLib.path); - } - - /** - * Check the size of the 32-bit library fetched from an APK with both 32-bit and 64-bit - * libraries unzipped onto disk. - */ - @MediumTest - @Test public void testGetWebView32BitLibrarySizeOnDiskIsNonZero() - throws WebViewFactory.MissingWebViewPackageException { - WebViewLibraryLoader.WebViewNativeLibrary actual32BitNativeLib = - WebViewLibraryLoader.getWebViewNativeLibrary( - webviewOnDiskPackageInfo, false /* is64bit */); - assertTrue(actual32BitNativeLib.size > 0); - } - - /** - * Check the size of the 64-bit library fetched from an APK with both 32-bit and 64-bit - * libraries unzipped onto disk. - */ - @MediumTest - @Test public void testGetWebView64BitLibrarySizeOnDiskIsNonZero() - throws WebViewFactory.MissingWebViewPackageException { - // A 32-bit device will not unpack 64-bit libraries. - if (!is64BitDevice()) return; - WebViewLibraryLoader.WebViewNativeLibrary actual64BitNativeLib = - WebViewLibraryLoader.getWebViewNativeLibrary( - webviewOnDiskPackageInfo, true /* is64bit */); - assertTrue(actual64BitNativeLib.size > 0); - } - - /** - * Ensure we fetch the correct 32-bit library path from an APK with both 32-bit and 64-bit - * libraries stored uncompressed in the APK. - */ - @MediumTest - @Test public void testGetWebView32BitLibraryPathFromApk() - throws WebViewFactory.MissingWebViewPackageException, IOException { - WebViewLibraryLoader.WebViewNativeLibrary actualNativeLib = - WebViewLibraryLoader.getWebViewNativeLibrary( - webviewFromApkPackageInfo, false /* is64bit */); - // The device might have ignored the app's request to not extract native libs, so first - // check whether the library paths match those of extracted libraries. - String expectedLibaryDirectory = is64BitDevice() ? - webviewFromApkPackageInfo.applicationInfo.secondaryNativeLibraryDir : - webviewFromApkPackageInfo.applicationInfo.nativeLibraryDir; - String lib32Path = expectedLibaryDirectory + "/" + WEBVIEW_LOADING_TEST_NATIVE_LIB; - if (lib32Path.equals(actualNativeLib.path)) { - // If the libraries were extracted to disk, ensure that they're actually there. - assertTrue("The given WebView library doesn't exist.", - new File(actualNativeLib.path).exists()); - } else { // The libraries were not extracted to disk. - assertIsValidZipEntryPath(actualNativeLib.path, - webviewFromApkPackageInfo.applicationInfo.sourceDir); - } - } - - /** - * Ensure we fetch the correct 32-bit library path from an APK with both 32-bit and 64-bit - * libraries stored uncompressed in the APK. - */ - @MediumTest - @Test public void testGetWebView64BitLibraryPathFromApk() - throws WebViewFactory.MissingWebViewPackageException, IOException { - // A 32-bit device will not unpack 64-bit libraries. - if (!is64BitDevice()) return; - - WebViewLibraryLoader.WebViewNativeLibrary actualNativeLib = - WebViewLibraryLoader.getWebViewNativeLibrary( - webviewFromApkPackageInfo, true /* is64bit */); - assertIsValidZipEntryPath(actualNativeLib.path, - webviewFromApkPackageInfo.applicationInfo.sourceDir); - } - - private static void assertIsValidZipEntryPath(String path, String zipFilePath) - throws IOException { - assertTrue("The path to a zip entry must start with the path to the zip file itself." - + "Expected zip path: " + zipFilePath + ", actual zip entry: " + path, - path.startsWith(zipFilePath + "!/")); - String[] pathSplit = path.split("!/"); - assertEquals("A zip file path should have two parts, the zip path, and the zip entry path.", - 2, pathSplit.length); - ZipFile zipFile = new ZipFile(pathSplit[0]); - assertNotNull("Path doesn't point to a valid zip entry: " + path, - zipFile.getEntry(pathSplit[1])); - } - - - /** - * Check the size of the 32-bit library fetched from an APK with both 32-bit and 64-bit - * libraries stored uncompressed in the APK. - */ - @MediumTest - @Test public void testGetWebView32BitLibrarySizeFromApkIsNonZero() - throws WebViewFactory.MissingWebViewPackageException { - WebViewLibraryLoader.WebViewNativeLibrary actual32BitNativeLib = - WebViewLibraryLoader.getWebViewNativeLibrary( - webviewFromApkPackageInfo, false /* is64bit */); - assertTrue(actual32BitNativeLib.size > 0); - } - - /** - * Check the size of the 64-bit library fetched from an APK with both 32-bit and 64-bit - * libraries stored uncompressed in the APK. - */ - @MediumTest - @Test public void testGetWebView64BitLibrarySizeFromApkIsNonZero() - throws WebViewFactory.MissingWebViewPackageException { - // A 32-bit device will not unpack 64-bit libraries. - if (!is64BitDevice()) return; - - WebViewLibraryLoader.WebViewNativeLibrary actual64BitNativeLib = - WebViewLibraryLoader.getWebViewNativeLibrary( - webviewFromApkPackageInfo, true /* is64bit */); - assertTrue(actual64BitNativeLib.size > 0); - } - - private static class ApplicationInfoBuilder { - ApplicationInfo ai; - - public ApplicationInfoBuilder setPrimaryCpuAbi(String primaryCpuAbi) { - ai.primaryCpuAbi = primaryCpuAbi; - return this; - } - - public ApplicationInfoBuilder setSecondaryCpuAbi(String secondaryCpuAbi) { - ai.secondaryCpuAbi = secondaryCpuAbi; - return this; - } - - public ApplicationInfoBuilder setNativeLibraryDir(String nativeLibraryDir) { - ai.nativeLibraryDir = nativeLibraryDir; - return this; - } - - public ApplicationInfoBuilder setSecondaryNativeLibraryDir( - String secondaryNativeLibraryDir) { - ai.secondaryNativeLibraryDir = secondaryNativeLibraryDir; - return this; - } - - public ApplicationInfoBuilder setMetaData(Bundle metaData) { - ai.metaData = metaData; - return this; - } - - public ApplicationInfoBuilder() { - ai = new android.content.pm.ApplicationInfo(); - } - - public ApplicationInfo create() { - return ai; - } - } -} diff --git a/native/webview/loader/loader.cpp b/native/webview/loader/loader.cpp index adb371dde0fc..fee2a259cb54 100644 --- a/native/webview/loader/loader.cpp +++ b/native/webview/loader/loader.cpp @@ -64,7 +64,8 @@ jboolean DoReserveAddressSpace(jlong size) { return JNI_TRUE; } -jboolean DoCreateRelroFile(const char* lib, const char* relro) { +jboolean DoCreateRelroFile(JNIEnv* env, const char* lib, const char* relro, + jobject clazzLoader) { // Try to unlink the old file, since if this is being called, the old one is // obsolete. if (unlink(relro) != 0 && errno != ENOENT) { @@ -82,11 +83,19 @@ jboolean DoCreateRelroFile(const char* lib, const char* relro) { ALOGE("Failed to create temporary file %s: %s", relro_tmp, strerror(errno)); return JNI_FALSE; } + android_namespace_t* ns = + android::FindNamespaceByClassLoader(env, clazzLoader); + if (ns == NULL) { + ALOGE("Failed to find classloader namespace"); + return JNI_FALSE; + } android_dlextinfo extinfo; - extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_WRITE_RELRO; + extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_WRITE_RELRO | + ANDROID_DLEXT_USE_NAMESPACE; extinfo.reserved_addr = gReservedAddress; extinfo.reserved_size = gReservedSize; extinfo.relro_fd = tmp_fd; + extinfo.library_namespace = ns; void* handle = android_dlopen_ext(lib, RTLD_NOW, &extinfo); int close_result = close(tmp_fd); if (handle == NULL) { @@ -143,13 +152,14 @@ jboolean ReserveAddressSpace(JNIEnv*, jclass, jlong size) { return DoReserveAddressSpace(size); } -jboolean CreateRelroFile(JNIEnv* env, jclass, jstring lib, jstring relro) { +jboolean CreateRelroFile(JNIEnv* env, jclass, jstring lib, jstring relro, + jobject clazzLoader) { jboolean ret = JNI_FALSE; const char* lib_utf8 = env->GetStringUTFChars(lib, NULL); if (lib_utf8 != NULL) { const char* relro_utf8 = env->GetStringUTFChars(relro, NULL); if (relro_utf8 != NULL) { - ret = DoCreateRelroFile(lib_utf8, relro_utf8); + ret = DoCreateRelroFile(env, lib_utf8, relro_utf8, clazzLoader); env->ReleaseStringUTFChars(relro, relro_utf8); } env->ReleaseStringUTFChars(lib, lib_utf8); @@ -179,7 +189,7 @@ const JNINativeMethod kJniMethods[] = { { "nativeReserveAddressSpace", "(J)Z", reinterpret_cast<void*>(ReserveAddressSpace) }, { "nativeCreateRelroFile", - "(Ljava/lang/String;Ljava/lang/String;)Z", + "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;)Z", reinterpret_cast<void*>(CreateRelroFile) }, { "nativeLoadWithRelroFile", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;)I", |