1d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon/* 2d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon * Copyright (C) 2012 The Android Open Source Project 3d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon * 4d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon * Licensed under the Apache License, Version 2.0 (the "License"); 5d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon * you may not use this file except in compliance with the License. 6d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon * You may obtain a copy of the License at 7d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon * 8d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon * http://www.apache.org/licenses/LICENSE-2.0 9d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon * 10d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon * Unless required by applicable law or agreed to in writing, software 11d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon * distributed under the License is distributed on an "AS IS" BASIS, 12d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon * See the License for the specific language governing permissions and 14d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon * limitations under the License. 15d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon */ 16d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon 17d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixonpackage android.webkit; 18d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon 19451e338c51e8c45efc0d21536dfae6f78f6d5e06Ignacio Sollaimport android.annotation.SystemApi; 20810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucciimport android.app.ActivityManagerInternal; 216c778cebc73e7eb76510f6e2183d804b8c07082bTorne (Richard Coles)import android.app.AppGlobals; 2285844916b8a7cc7f6aabc6c37af7380a4c000bcbJeff Sharkeyimport android.app.Application; 236c778cebc73e7eb76510f6e2183d804b8c07082bTorne (Richard Coles)import android.content.Context; 241b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucciimport android.content.pm.ApplicationInfo; 250606cd572ad345fb2c40456509feac626c68dee3Torne (Richard Coles)import android.content.pm.PackageInfo; 266c778cebc73e7eb76510f6e2183d804b8c07082bTorne (Richard Coles)import android.content.pm.PackageManager; 2708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)import android.os.Build; 2808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)import android.os.Process; 2908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)import android.os.RemoteException; 3008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)import android.os.ServiceManager; 31e09e976dad1d974ca28381451b0bbbeafbb872d5Ben Murdochimport android.os.StrictMode; 325ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdochimport android.os.SystemProperties; 333822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles)import android.os.Trace; 341b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucciimport android.text.TextUtils; 3503ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles)import android.util.AndroidRuntimeException; 36d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixonimport android.util.Log; 3785844916b8a7cc7f6aabc6c37af7380a4c000bcbJeff Sharkey 38810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucciimport com.android.server.LocalServices; 3985844916b8a7cc7f6aabc6c37af7380a4c000bcbJeff Sharkey 4008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)import dalvik.system.VMRuntime; 4108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) 4208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)import java.io.File; 43b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwinimport java.io.IOException; 441b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucciimport java.util.Arrays; 45b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwinimport java.util.zip.ZipEntry; 46b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwinimport java.util.zip.ZipFile; 4708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) 48d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon/** 49d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon * Top level factory, used creating all the main WebView implementation classes. 50b0e35846b818bdf0db9cafe881a8a535116d596eJared Duke * 51b0e35846b818bdf0db9cafe881a8a535116d596eJared Duke * @hide 52d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon */ 53451e338c51e8c45efc0d21536dfae6f78f6d5e06Ignacio Solla@SystemApi 54b0e35846b818bdf0db9cafe881a8a535116d596eJared Dukepublic final class WebViewFactory { 55a7eaa8ee222611c28f050158db4b68c4d893a8a9Jonathan Dixon 56e09e976dad1d974ca28381451b0bbbeafbb872d5Ben Murdoch private static final String CHROMIUM_WEBVIEW_FACTORY = 57a9bbd9439c3043bd76a7474e6dca3c8131b1b258Torne (Richard Coles) "com.android.webview.chromium.WebViewChromiumFactoryProvider"; 58d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon 590e04bcfbdc1845c931b45b3498aef438b944e961Ben Murdoch private static final String NULL_WEBVIEW_FACTORY = 600e04bcfbdc1845c931b45b3498aef438b944e961Ben Murdoch "com.android.webview.nullwebview.NullWebViewFactoryProvider"; 610e04bcfbdc1845c931b45b3498aef438b944e961Ben Murdoch 6208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) private static final String CHROMIUM_WEBVIEW_NATIVE_RELRO_32 = 6308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) "/data/misc/shared_relro/libwebviewchromium32.relro"; 6408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) private static final String CHROMIUM_WEBVIEW_NATIVE_RELRO_64 = 6508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) "/data/misc/shared_relro/libwebviewchromium64.relro"; 6608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) 675ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch public static final String CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY = 685ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch "persist.sys.webview.vmsize"; 695ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch private static final long CHROMIUM_WEBVIEW_DEFAULT_VMSIZE_BYTES = 100 * 1024 * 1024; 701b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci 71d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon private static final String LOGTAG = "WebViewFactory"; 72d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon 73d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon private static final boolean DEBUG = false; 74d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon 75d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon // Cache the factory both for efficiency, and ensure any one process gets all webviews from the 76d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon // same provider. 77d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon private static WebViewFactoryProvider sProviderInstance; 789f9d34552f53c534141584a5ad4a8a49ad7939dcJohn Reck private static final Object sProviderLock = new Object(); 7908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) private static boolean sAddressSpaceReserved = false; 8084392d74fef177a87bc96a255761daf39569e726Torne (Richard Coles) private static PackageInfo sPackageInfo; 81d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon 8285edb6c6bff62e163e4490951ec49a958c63fad0Gustav Sennton // Error codes for loadWebViewNativeLibraryFromPackage 8385edb6c6bff62e163e4490951ec49a958c63fad0Gustav Sennton public static final int LIBLOAD_SUCCESS = 0; 8485edb6c6bff62e163e4490951ec49a958c63fad0Gustav Sennton public static final int LIBLOAD_WRONG_PACKAGE_NAME = 1; 8585edb6c6bff62e163e4490951ec49a958c63fad0Gustav Sennton public static final int LIBLOAD_ADDRESS_SPACE_NOT_RESERVED = 2; 8685edb6c6bff62e163e4490951ec49a958c63fad0Gustav Sennton public static final int LIBLOAD_FAILED_WAITING_FOR_RELRO = 3; 8785edb6c6bff62e163e4490951ec49a958c63fad0Gustav Sennton public static final int LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES = 4; 8885edb6c6bff62e163e4490951ec49a958c63fad0Gustav Sennton 8985edb6c6bff62e163e4490951ec49a958c63fad0Gustav Sennton // native relro loading error codes 9085edb6c6bff62e163e4490951ec49a958c63fad0Gustav Sennton public static final int LIBLOAD_FAILED_TO_OPEN_RELRO_FILE = 5; 9185edb6c6bff62e163e4490951ec49a958c63fad0Gustav Sennton public static final int LIBLOAD_FAILED_TO_LOAD_LIBRARY = 6; 9285edb6c6bff62e163e4490951ec49a958c63fad0Gustav Sennton public static final int LIBLOAD_FAILED_JNI_CALL = 7; 9385edb6c6bff62e163e4490951ec49a958c63fad0Gustav Sennton 94a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton private static class MissingWebViewPackageException extends AndroidRuntimeException { 95a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton public MissingWebViewPackageException(String message) { super(message); } 96a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton public MissingWebViewPackageException(Exception e) { super(e); } 97a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton } 98a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton 99dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdoch public static String getWebViewPackageName() { 100d9730182212b157083321ea4e2209182f1fbb72fGustav Sennton return AppGlobals.getInitialApplication().getString( 101d9730182212b157083321ea4e2209182f1fbb72fGustav Sennton com.android.internal.R.string.config_webViewPackageName); 1022ed6fee15c85ff991f64ecfa8c1c4738e0fdf9b6Gustav Sennton } 1032ed6fee15c85ff991f64ecfa8c1c4738e0fdf9b6Gustav Sennton 104d9730182212b157083321ea4e2209182f1fbb72fGustav Sennton private static PackageInfo fetchPackageInfo() { 1052ed6fee15c85ff991f64ecfa8c1c4738e0fdf9b6Gustav Sennton PackageManager pm = AppGlobals.getInitialApplication().getPackageManager(); 106d9730182212b157083321ea4e2209182f1fbb72fGustav Sennton try { 107d9730182212b157083321ea4e2209182f1fbb72fGustav Sennton return pm.getPackageInfo(getWebViewPackageName(), PackageManager.GET_META_DATA); 108d9730182212b157083321ea4e2209182f1fbb72fGustav Sennton } catch (PackageManager.NameNotFoundException e) { 109d9730182212b157083321ea4e2209182f1fbb72fGustav Sennton throw new MissingWebViewPackageException(e); 1102ed6fee15c85ff991f64ecfa8c1c4738e0fdf9b6Gustav Sennton } 1112ed6fee15c85ff991f64ecfa8c1c4738e0fdf9b6Gustav Sennton } 1122ed6fee15c85ff991f64ecfa8c1c4738e0fdf9b6Gustav Sennton 113a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton // throws MissingWebViewPackageException 1142ed6fee15c85ff991f64ecfa8c1c4738e0fdf9b6Gustav Sennton private static ApplicationInfo getWebViewApplicationInfo() { 115d9730182212b157083321ea4e2209182f1fbb72fGustav Sennton if (sPackageInfo == null) { 116d9730182212b157083321ea4e2209182f1fbb72fGustav Sennton return fetchPackageInfo().applicationInfo; 117d9730182212b157083321ea4e2209182f1fbb72fGustav Sennton } else { 1182ed6fee15c85ff991f64ecfa8c1c4738e0fdf9b6Gustav Sennton return sPackageInfo.applicationInfo; 119d9730182212b157083321ea4e2209182f1fbb72fGustav Sennton } 1202ed6fee15c85ff991f64ecfa8c1c4738e0fdf9b6Gustav Sennton } 1212ed6fee15c85ff991f64ecfa8c1c4738e0fdf9b6Gustav Sennton 1222ed6fee15c85ff991f64ecfa8c1c4738e0fdf9b6Gustav Sennton private static String getWebViewLibrary(ApplicationInfo ai) { 1232ed6fee15c85ff991f64ecfa8c1c4738e0fdf9b6Gustav Sennton if (ai.metaData != null) 1242ed6fee15c85ff991f64ecfa8c1c4738e0fdf9b6Gustav Sennton return ai.metaData.getString("com.android.webview.WebViewLibrary"); 1252ed6fee15c85ff991f64ecfa8c1c4738e0fdf9b6Gustav Sennton return null; 126dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdoch } 127dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdoch 12884392d74fef177a87bc96a255761daf39569e726Torne (Richard Coles) public static PackageInfo getLoadedPackageInfo() { 12984392d74fef177a87bc96a255761daf39569e726Torne (Richard Coles) return sPackageInfo; 13084392d74fef177a87bc96a255761daf39569e726Torne (Richard Coles) } 13184392d74fef177a87bc96a255761daf39569e726Torne (Richard Coles) 13285edb6c6bff62e163e4490951ec49a958c63fad0Gustav Sennton /** 13385edb6c6bff62e163e4490951ec49a958c63fad0Gustav Sennton * Load the native library for the given package name iff that package 134d9730182212b157083321ea4e2209182f1fbb72fGustav Sennton * name is the same as the one providing the webview. 13585edb6c6bff62e163e4490951ec49a958c63fad0Gustav Sennton */ 13685edb6c6bff62e163e4490951ec49a958c63fad0Gustav Sennton public static int loadWebViewNativeLibraryFromPackage(String packageName) { 137d9730182212b157083321ea4e2209182f1fbb72fGustav Sennton sPackageInfo = fetchPackageInfo(); 13885edb6c6bff62e163e4490951ec49a958c63fad0Gustav Sennton if (packageName != null && packageName.equals(sPackageInfo.packageName)) { 13985edb6c6bff62e163e4490951ec49a958c63fad0Gustav Sennton return loadNativeLibrary(); 14085edb6c6bff62e163e4490951ec49a958c63fad0Gustav Sennton } 14185edb6c6bff62e163e4490951ec49a958c63fad0Gustav Sennton return LIBLOAD_WRONG_PACKAGE_NAME; 14285edb6c6bff62e163e4490951ec49a958c63fad0Gustav Sennton } 14385edb6c6bff62e163e4490951ec49a958c63fad0Gustav Sennton 1449f9d34552f53c534141584a5ad4a8a49ad7939dcJohn Reck static WebViewFactoryProvider getProvider() { 1459f9d34552f53c534141584a5ad4a8a49ad7939dcJohn Reck synchronized (sProviderLock) { 1469f9d34552f53c534141584a5ad4a8a49ad7939dcJohn Reck // For now the main purpose of this function (and the factory abstraction) is to keep 147d892afc88d3c67a7fe1c9550bfa7a452051d031dTorne (Richard Coles) // us honest and minimize usage of WebView internals when binding the proxy. 1489f9d34552f53c534141584a5ad4a8a49ad7939dcJohn Reck if (sProviderInstance != null) return sProviderInstance; 149d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon 15085844916b8a7cc7f6aabc6c37af7380a4c000bcbJeff Sharkey final int uid = android.os.Process.myUid(); 15185844916b8a7cc7f6aabc6c37af7380a4c000bcbJeff Sharkey if (uid == android.os.Process.ROOT_UID || uid == android.os.Process.SYSTEM_UID) { 15285844916b8a7cc7f6aabc6c37af7380a4c000bcbJeff Sharkey throw new UnsupportedOperationException( 15385844916b8a7cc7f6aabc6c37af7380a4c000bcbJeff Sharkey "For security reasons, WebView is not allowed in privileged processes"); 15485844916b8a7cc7f6aabc6c37af7380a4c000bcbJeff Sharkey } 15585844916b8a7cc7f6aabc6c37af7380a4c000bcbJeff Sharkey 1563822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles) Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.getProvider()"); 15703ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles) try { 158a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton Class<WebViewFactoryProvider> providerClass = getProviderClass(); 1593822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles) 1603822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles) StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); 1613822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles) Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "providerClass.newInstance()"); 1623822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles) try { 1631ea39b350c2a1c2595ab3b7c4ba3ab8a3b029315Ignacio Solla sProviderInstance = providerClass.getConstructor(WebViewDelegate.class) 1641ea39b350c2a1c2595ab3b7c4ba3ab8a3b029315Ignacio Solla .newInstance(new WebViewDelegate()); 1653822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles) if (DEBUG) Log.v(LOGTAG, "Loaded provider: " + sProviderInstance); 1663822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles) return sProviderInstance; 1673822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles) } catch (Exception e) { 1683822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles) Log.e(LOGTAG, "error instantiating provider", e); 1693822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles) throw new AndroidRuntimeException(e); 1703822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles) } finally { 1713822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles) Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW); 1723822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles) StrictMode.setThreadPolicy(oldPolicy); 1733822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles) } 17403ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles) } finally { 1753822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles) Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW); 176e09e976dad1d974ca28381451b0bbbeafbb872d5Ben Murdoch } 177d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon } 178d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon } 179d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon 180a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton private static Class<WebViewFactoryProvider> getProviderClass() { 181a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton try { 182a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton // First fetch the package info so we can log the webview package version. 183d9730182212b157083321ea4e2209182f1fbb72fGustav Sennton sPackageInfo = fetchPackageInfo(); 184a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton Log.i(LOGTAG, "Loading " + sPackageInfo.packageName + " version " + 185a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton sPackageInfo.versionName + " (code " + sPackageInfo.versionCode + ")"); 186a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton 187a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.loadNativeLibrary()"); 188a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton loadNativeLibrary(); 189a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW); 190a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton 191a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.getChromiumProviderClass()"); 192a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton try { 193a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton return getChromiumProviderClass(); 194a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton } catch (ClassNotFoundException e) { 195a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton Log.e(LOGTAG, "error loading provider", e); 196a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton throw new AndroidRuntimeException(e); 197a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton } finally { 198a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW); 199a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton } 200a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton } catch (MissingWebViewPackageException e) { 201a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton // If the package doesn't exist, then try loading the null WebView instead. 202a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton // If that succeeds, then this is a device without WebView support; if it fails then 203a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton // swallow the failure, complain that the real WebView is missing and rethrow the 204a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton // original exception. 205a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton try { 206a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton return (Class<WebViewFactoryProvider>) Class.forName(NULL_WEBVIEW_FACTORY); 207a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton } catch (ClassNotFoundException e2) { 208a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton // Ignore. 209a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton } 210a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton Log.e(LOGTAG, "Chromium WebView package does not exist", e); 211a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton throw new AndroidRuntimeException(e); 212a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton } 213a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton } 214a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton 215a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton // throws MissingWebViewPackageException 216a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton private static Class<WebViewFactoryProvider> getChromiumProviderClass() 217a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton throws ClassNotFoundException { 21863d3d8a458cfc124ebd183994d3d152d3b06c1d8Marcin Kosiba Application initialApplication = AppGlobals.getInitialApplication(); 2190e04bcfbdc1845c931b45b3498aef438b944e961Ben Murdoch try { 2200606cd572ad345fb2c40456509feac626c68dee3Torne (Richard Coles) // Construct a package context to load the Java code into the current app. 2212ed6fee15c85ff991f64ecfa8c1c4738e0fdf9b6Gustav Sennton Context webViewContext = initialApplication.createPackageContext( 222d9730182212b157083321ea4e2209182f1fbb72fGustav Sennton sPackageInfo.packageName, 223d9730182212b157083321ea4e2209182f1fbb72fGustav Sennton Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY); 22463d3d8a458cfc124ebd183994d3d152d3b06c1d8Marcin Kosiba initialApplication.getAssets().addAssetPath( 22563d3d8a458cfc124ebd183994d3d152d3b06c1d8Marcin Kosiba webViewContext.getApplicationInfo().sourceDir); 2266c778cebc73e7eb76510f6e2183d804b8c07082bTorne (Richard Coles) ClassLoader clazzLoader = webViewContext.getClassLoader(); 2273822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles) Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "Class.forName()"); 2283822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles) try { 2293822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles) return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY, true, 2303822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles) clazzLoader); 2313822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles) } finally { 2323822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles) Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW); 2333822882b32d9b1b803aaff9b657a91d680f1d0f9Torne (Richard Coles) } 2346c778cebc73e7eb76510f6e2183d804b8c07082bTorne (Richard Coles) } catch (PackageManager.NameNotFoundException e) { 235a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton throw new MissingWebViewPackageException(e); 2360e04bcfbdc1845c931b45b3498aef438b944e961Ben Murdoch } 237d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon } 23808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) 23908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) /** 24008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) * Perform any WebView loading preparations that must happen in the zygote. 24108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) * Currently, this means allocating address space to load the real JNI library later. 24208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) */ 24308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) public static void prepareWebViewInZygote() { 24408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) try { 24508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) System.loadLibrary("webviewchromium_loader"); 2465ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch long addressSpaceToReserve = 2475ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch SystemProperties.getLong(CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY, 2485ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch CHROMIUM_WEBVIEW_DEFAULT_VMSIZE_BYTES); 2495ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch sAddressSpaceReserved = nativeReserveAddressSpace(addressSpaceToReserve); 2505ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch 25108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) if (sAddressSpaceReserved) { 2525ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch if (DEBUG) { 2535ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch Log.v(LOGTAG, "address space reserved: " + addressSpaceToReserve + " bytes"); 2545ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch } 25508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) } else { 2565ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch Log.e(LOGTAG, "reserving " + addressSpaceToReserve + 2575ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch " bytes of address space failed"); 25808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) } 259810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci } catch (Throwable t) { 26008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) // Log and discard errors at this stage as we must not crash the zygote. 261810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci Log.e(LOGTAG, "error preparing native loader", t); 26208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) } 26308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) } 26408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) 26508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) /** 26608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) * Perform any WebView loading preparations that must happen at boot from the system server, 2675ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch * after the package manager has started or after an update to the webview is installed. 26808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) * This must be called in the system server. 26908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) * Currently, this means spawning the child processes which will create the relro files. 27008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) */ 27108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) public static void prepareWebViewInSystemServer() { 2725ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch String[] nativePaths = null; 2735ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch try { 2745ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch nativePaths = getWebViewNativeLibraryPaths(); 27527cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles) } catch (Throwable t) { 27627cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles) // Log and discard errors at this stage as we must not crash the system server. 27727cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles) Log.e(LOGTAG, "error preparing webview native library", t); 2785ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch } 2795ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch prepareWebViewInSystemServer(nativePaths); 2805ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch } 2815ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch 2825ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch private static void prepareWebViewInSystemServer(String[] nativeLibraryPaths) { 28308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) if (DEBUG) Log.v(LOGTAG, "creating relro files"); 2845ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch 2855ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch // We must always trigger createRelRo regardless of the value of nativeLibraryPaths. Any 2865ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch // unexpected values will be handled there to ensure that we trigger notifying any process 2875ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch // waiting on relreo creation. 2885ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch if (Build.SUPPORTED_32_BIT_ABIS.length > 0) { 2895ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch if (DEBUG) Log.v(LOGTAG, "Create 32 bit relro"); 2905ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch createRelroFile(false /* is64Bit */, nativeLibraryPaths); 2915ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch } 2925ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch 2935ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch if (Build.SUPPORTED_64_BIT_ABIS.length > 0) { 2945ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch if (DEBUG) Log.v(LOGTAG, "Create 64 bit relro"); 2955ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch createRelroFile(true /* is64Bit */, nativeLibraryPaths); 2965ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch } 2975ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch } 2985ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch 2995ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch public static void onWebViewUpdateInstalled() { 3005ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch String[] nativeLibs = null; 3015ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch try { 3025ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch nativeLibs = WebViewFactory.getWebViewNativeLibraryPaths(); 30327cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles) if (nativeLibs != null) { 30427cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles) long newVmSize = 0L; 30527cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles) 30627cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles) for (String path : nativeLibs) { 307b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin if (path == null || TextUtils.isEmpty(path)) continue; 30827cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles) if (DEBUG) Log.d(LOGTAG, "Checking file size of " + path); 30927cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles) File f = new File(path); 31027cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles) if (f.exists()) { 311b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin newVmSize = Math.max(newVmSize, f.length()); 312b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin continue; 313b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin } 314519919b0d4b9ebeb685ce9f3632078545792e408Simon Baldwin if (path.contains("!/")) { 315519919b0d4b9ebeb685ce9f3632078545792e408Simon Baldwin String[] split = TextUtils.split(path, "!/"); 316b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin if (split.length == 2) { 317c52839277b8714d150a9fe276b6ba3fa8a0cbf38Torne (Richard Coles) try (ZipFile z = new ZipFile(split[0])) { 318b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin ZipEntry e = z.getEntry(split[1]); 319b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin if (e != null && e.getMethod() == ZipEntry.STORED) { 320b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin newVmSize = Math.max(newVmSize, e.getSize()); 321b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin continue; 322b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin } 323b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin } 324b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin catch (IOException e) { 325b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin Log.e(LOGTAG, "error reading APK file " + split[0] + ", ", e); 326b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin } 32727cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles) } 3285ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch } 329b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin Log.e(LOGTAG, "error sizing load for " + path); 3305ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch } 3315ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch 33227cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles) if (DEBUG) { 33327cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles) Log.v(LOGTAG, "Based on library size, need " + newVmSize + 33427cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles) " bytes of address space."); 33527cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles) } 33627cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles) // The required memory can be larger than the file on disk (due to .bss), and an 33727cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles) // upgraded version of the library will likely be larger, so always attempt to 33827cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles) // reserve twice as much as we think to allow for the library to grow during this 33927cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles) // boot cycle. 34027cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles) newVmSize = Math.max(2 * newVmSize, CHROMIUM_WEBVIEW_DEFAULT_VMSIZE_BYTES); 34127cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles) Log.d(LOGTAG, "Setting new address space to " + newVmSize); 34227cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles) SystemProperties.set(CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY, 34327cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles) Long.toString(newVmSize)); 3445ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch } 34527cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles) } catch (Throwable t) { 34627cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles) // Log and discard errors at this stage as we must not crash the system server. 34727cb0d22a839f9fc132ae6b4e7c059c75a1826e1Torne (Richard Coles) Log.e(LOGTAG, "error preparing webview native library", t); 34808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) } 3495ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch prepareWebViewInSystemServer(nativeLibs); 35008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) } 35108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) 352a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton // throws MissingWebViewPackageException 353b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin private static String getLoadFromApkPath(String apkPath, 354b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin String[] abiList, 355b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin String nativeLibFileName) { 356b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin // Search the APK for a native library conforming to a listed ABI. 357c52839277b8714d150a9fe276b6ba3fa8a0cbf38Torne (Richard Coles) try (ZipFile z = new ZipFile(apkPath)) { 358b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin for (String abi : abiList) { 359b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin final String entry = "lib/" + abi + "/" + nativeLibFileName; 360b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin ZipEntry e = z.getEntry(entry); 361b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin if (e != null && e.getMethod() == ZipEntry.STORED) { 362b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin // Return a path formatted for dlopen() load from APK. 363519919b0d4b9ebeb685ce9f3632078545792e408Simon Baldwin return apkPath + "!/" + entry; 364b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin } 365b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin } 366b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin } catch (IOException e) { 367b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin throw new MissingWebViewPackageException(e); 368b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin } 369b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin return ""; 370b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin } 371b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin 372b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin // throws MissingWebViewPackageException 373a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton private static String[] getWebViewNativeLibraryPaths() { 3742ed6fee15c85ff991f64ecfa8c1c4738e0fdf9b6Gustav Sennton ApplicationInfo ai = getWebViewApplicationInfo(); 3752ed6fee15c85ff991f64ecfa8c1c4738e0fdf9b6Gustav Sennton final String NATIVE_LIB_FILE_NAME = getWebViewLibrary(ai); 3761b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci 3771b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci String path32; 3781b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci String path64; 3791b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci boolean primaryArchIs64bit = VMRuntime.is64BitAbi(ai.primaryCpuAbi); 3801b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci if (!TextUtils.isEmpty(ai.secondaryCpuAbi)) { 3811b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci // Multi-arch case. 3821b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci if (primaryArchIs64bit) { 3831b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci // Primary arch: 64-bit, secondary: 32-bit. 3841b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci path64 = ai.nativeLibraryDir; 3851b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci path32 = ai.secondaryNativeLibraryDir; 3861b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci } else { 3871b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci // Primary arch: 32-bit, secondary: 64-bit. 3881b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci path64 = ai.secondaryNativeLibraryDir; 3891b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci path32 = ai.nativeLibraryDir; 3901b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci } 3911b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci } else if (primaryArchIs64bit) { 3921b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci // Single-arch 64-bit. 3931b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci path64 = ai.nativeLibraryDir; 3941b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci path32 = ""; 3951b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci } else { 3961b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci // Single-arch 32-bit. 3971b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci path32 = ai.nativeLibraryDir; 3981b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci path64 = ""; 3991b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci } 400b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin 401b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin // Form the full paths to the extracted native libraries. 402b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin // If libraries were not extracted, try load from APK paths instead. 403b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin if (!TextUtils.isEmpty(path32)) { 404b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin path32 += "/" + NATIVE_LIB_FILE_NAME; 405b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin File f = new File(path32); 406b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin if (!f.exists()) { 407b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin path32 = getLoadFromApkPath(ai.sourceDir, 408b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin Build.SUPPORTED_32_BIT_ABIS, 409b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin NATIVE_LIB_FILE_NAME); 410b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin } 411b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin } 412b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin if (!TextUtils.isEmpty(path64)) { 413b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin path64 += "/" + NATIVE_LIB_FILE_NAME; 414b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin File f = new File(path64); 415b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin if (!f.exists()) { 416b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin path64 = getLoadFromApkPath(ai.sourceDir, 417b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin Build.SUPPORTED_64_BIT_ABIS, 418b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin NATIVE_LIB_FILE_NAME); 419b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin } 420b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin } 421b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin 422b98082dcfb45a82d9b12dbf0d2f88acffe96a1c4Simon Baldwin if (DEBUG) Log.v(LOGTAG, "Native 32-bit lib: " + path32 + ", 64-bit lib: " + path64); 4231b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci return new String[] { path32, path64 }; 4241b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci } 4251b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci 4265ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch private static void createRelroFile(final boolean is64Bit, String[] nativeLibraryPaths) { 4271b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci final String abi = 4281b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci is64Bit ? Build.SUPPORTED_64_BIT_ABIS[0] : Build.SUPPORTED_32_BIT_ABIS[0]; 429810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci 430810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci // crashHandler is invoked by the ActivityManagerService when the isolated process crashes. 431810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci Runnable crashHandler = new Runnable() { 432810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci @Override 433810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci public void run() { 434810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci try { 4351b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci Log.e(LOGTAG, "relro file creator for " + abi + " crashed. Proceeding without"); 436810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci getUpdateService().notifyRelroCreationCompleted(is64Bit, false); 437810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci } catch (RemoteException e) { 438810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci Log.e(LOGTAG, "Cannot reach WebViewUpdateService. " + e.getMessage()); 439810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci } 440810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci } 441810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci }; 442810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci 44308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) try { 4445ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch if (nativeLibraryPaths == null 4455ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch || nativeLibraryPaths[0] == null || nativeLibraryPaths[1] == null) { 4465ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch throw new IllegalArgumentException( 4475ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch "Native library paths to the WebView RelRo process must not be null!"); 4485ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch } 449161536b5970ba5ab43233e7695ef69ba2bb804f4Primiano Tucci int pid = LocalServices.getService(ActivityManagerInternal.class).startIsolatedProcess( 4505ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch RelroFileCreator.class.getName(), nativeLibraryPaths, "WebViewLoader-" + abi, abi, 451810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci Process.SHARED_RELRO_UID, crashHandler); 452e76e81a227a29db5223d231ec88ecb02fa4d6835Primiano Tucci if (pid <= 0) throw new Exception("Failed to start the relro file creator process"); 453810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci } catch (Throwable t) { 45408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) // Log and discard errors as we must not crash the system server. 455810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci Log.e(LOGTAG, "error starting relro file creator for abi " + abi, t); 456810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci crashHandler.run(); 45708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) } 45808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) } 45908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) 46008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) private static class RelroFileCreator { 46108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) // Called in an unprivileged child process to create the relro file. 46208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) public static void main(String[] args) { 463161536b5970ba5ab43233e7695ef69ba2bb804f4Primiano Tucci boolean result = false; 464161536b5970ba5ab43233e7695ef69ba2bb804f4Primiano Tucci boolean is64Bit = VMRuntime.getRuntime().is64Bit(); 4651b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci try{ 4661b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci if (args.length != 2 || args[0] == null || args[1] == null) { 4671b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci Log.e(LOGTAG, "Invalid RelroFileCreator args: " + Arrays.toString(args)); 4681b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci return; 4691b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci } 4701b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci Log.v(LOGTAG, "RelroFileCreator (64bit = " + is64Bit + "), " + 4711b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci " 32-bit lib: " + args[0] + ", 64-bit lib: " + args[1]); 4721b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci if (!sAddressSpaceReserved) { 4731b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci Log.e(LOGTAG, "can't create relro file; address space not reserved"); 4741b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci return; 4751b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci } 476161536b5970ba5ab43233e7695ef69ba2bb804f4Primiano Tucci result = nativeCreateRelroFile(args[0] /* path32 */, 477161536b5970ba5ab43233e7695ef69ba2bb804f4Primiano Tucci args[1] /* path64 */, 478161536b5970ba5ab43233e7695ef69ba2bb804f4Primiano Tucci CHROMIUM_WEBVIEW_NATIVE_RELRO_32, 479161536b5970ba5ab43233e7695ef69ba2bb804f4Primiano Tucci CHROMIUM_WEBVIEW_NATIVE_RELRO_64); 480e76e81a227a29db5223d231ec88ecb02fa4d6835Primiano Tucci if (result && DEBUG) Log.v(LOGTAG, "created relro file"); 481161536b5970ba5ab43233e7695ef69ba2bb804f4Primiano Tucci } finally { 482161536b5970ba5ab43233e7695ef69ba2bb804f4Primiano Tucci // We must do our best to always notify the update service, even if something fails. 4831b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci try { 4841b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci getUpdateService().notifyRelroCreationCompleted(is64Bit, result); 4851b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci } catch (RemoteException e) { 4861b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci Log.e(LOGTAG, "error notifying update service", e); 4871b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci } 488161536b5970ba5ab43233e7695ef69ba2bb804f4Primiano Tucci 489161536b5970ba5ab43233e7695ef69ba2bb804f4Primiano Tucci if (!result) Log.e(LOGTAG, "failed to create relro file"); 490161536b5970ba5ab43233e7695ef69ba2bb804f4Primiano Tucci 4911b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci // Must explicitly exit or else this process will just sit around after we return. 4921b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci System.exit(0); 4931b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci } 49408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) } 49508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) } 49608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) 49785edb6c6bff62e163e4490951ec49a958c63fad0Gustav Sennton private static int loadNativeLibrary() { 49808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) if (!sAddressSpaceReserved) { 49908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) Log.e(LOGTAG, "can't load with relro file; address space not reserved"); 50085edb6c6bff62e163e4490951ec49a958c63fad0Gustav Sennton return LIBLOAD_ADDRESS_SPACE_NOT_RESERVED; 50108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) } 50208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) 50308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) try { 50408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) getUpdateService().waitForRelroCreationCompleted(VMRuntime.getRuntime().is64Bit()); 50508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) } catch (RemoteException e) { 50608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) Log.e(LOGTAG, "error waiting for relro creation, proceeding without", e); 50785edb6c6bff62e163e4490951ec49a958c63fad0Gustav Sennton return LIBLOAD_FAILED_WAITING_FOR_RELRO; 50808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) } 50908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) 5101b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci try { 5111b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci String[] args = getWebViewNativeLibraryPaths(); 51285edb6c6bff62e163e4490951ec49a958c63fad0Gustav Sennton int result = nativeLoadWithRelroFile(args[0] /* path32 */, 5131b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci args[1] /* path64 */, 5141b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci CHROMIUM_WEBVIEW_NATIVE_RELRO_32, 5151b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci CHROMIUM_WEBVIEW_NATIVE_RELRO_64); 51685edb6c6bff62e163e4490951ec49a958c63fad0Gustav Sennton if (result != LIBLOAD_SUCCESS) { 5171b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci Log.w(LOGTAG, "failed to load with relro file, proceeding without"); 5181b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci } else if (DEBUG) { 5191b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci Log.v(LOGTAG, "loaded with relro file"); 5201b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci } 52185edb6c6bff62e163e4490951ec49a958c63fad0Gustav Sennton return result; 522a8366e78b58aeb392a9dcc7301183e881d99c783Gustav Sennton } catch (MissingWebViewPackageException e) { 5231b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci Log.e(LOGTAG, "Failed to list WebView package libraries for loadNativeLibrary", e); 52485edb6c6bff62e163e4490951ec49a958c63fad0Gustav Sennton return LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES; 52508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) } 52608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) } 52708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) 52808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) private static IWebViewUpdateService getUpdateService() { 52908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) return IWebViewUpdateService.Stub.asInterface(ServiceManager.getService("webviewupdate")); 53008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) } 53108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) 5325ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch private static native boolean nativeReserveAddressSpace(long addressSpaceToReserve); 53308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) private static native boolean nativeCreateRelroFile(String lib32, String lib64, 53408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) String relro32, String relro64); 53585edb6c6bff62e163e4490951ec49a958c63fad0Gustav Sennton private static native int nativeLoadWithRelroFile(String lib32, String lib64, 53608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) String relro32, String relro64); 537d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon} 538