WebViewFactory.java revision e76e81a227a29db5223d231ec88ecb02fa4d6835
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 19810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucciimport android.app.ActivityManagerInternal; 2063d3d8a458cfc124ebd183994d3d152d3b06c1d8Marcin Kosibaimport android.app.Application; 216c778cebc73e7eb76510f6e2183d804b8c07082bTorne (Richard Coles)import android.app.AppGlobals; 226c778cebc73e7eb76510f6e2183d804b8c07082bTorne (Richard Coles)import android.content.Context; 231b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucciimport android.content.pm.ApplicationInfo; 246c778cebc73e7eb76510f6e2183d804b8c07082bTorne (Richard Coles)import android.content.pm.PackageManager; 2508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)import android.os.Build; 2608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)import android.os.Process; 2708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)import android.os.RemoteException; 2808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)import android.os.ServiceManager; 29e09e976dad1d974ca28381451b0bbbeafbb872d5Ben Murdochimport android.os.StrictMode; 305ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdochimport android.os.SystemProperties; 311b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucciimport android.text.TextUtils; 3203ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles)import android.util.AndroidRuntimeException; 33d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixonimport android.util.Log; 34810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucciimport com.android.server.LocalServices; 3508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)import dalvik.system.VMRuntime; 3608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) 3708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)import java.io.File; 381b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucciimport java.util.Arrays; 3908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) 4008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)import com.android.internal.os.Zygote; 41d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon 42d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon/** 43d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon * Top level factory, used creating all the main WebView implementation classes. 44b0e35846b818bdf0db9cafe881a8a535116d596eJared Duke * 45b0e35846b818bdf0db9cafe881a8a535116d596eJared Duke * @hide 46d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon */ 47b0e35846b818bdf0db9cafe881a8a535116d596eJared Dukepublic final class WebViewFactory { 48a7eaa8ee222611c28f050158db4b68c4d893a8a9Jonathan Dixon 49e09e976dad1d974ca28381451b0bbbeafbb872d5Ben Murdoch private static final String CHROMIUM_WEBVIEW_FACTORY = 50a9bbd9439c3043bd76a7474e6dca3c8131b1b258Torne (Richard Coles) "com.android.webview.chromium.WebViewChromiumFactoryProvider"; 51d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon 520e04bcfbdc1845c931b45b3498aef438b944e961Ben Murdoch private static final String NULL_WEBVIEW_FACTORY = 530e04bcfbdc1845c931b45b3498aef438b944e961Ben Murdoch "com.android.webview.nullwebview.NullWebViewFactoryProvider"; 540e04bcfbdc1845c931b45b3498aef438b944e961Ben Murdoch 5508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) private static final String CHROMIUM_WEBVIEW_NATIVE_RELRO_32 = 5608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) "/data/misc/shared_relro/libwebviewchromium32.relro"; 5708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) private static final String CHROMIUM_WEBVIEW_NATIVE_RELRO_64 = 5808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) "/data/misc/shared_relro/libwebviewchromium64.relro"; 5908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) 605ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch public static final String CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY = 615ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch "persist.sys.webview.vmsize"; 625ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch private static final long CHROMIUM_WEBVIEW_DEFAULT_VMSIZE_BYTES = 100 * 1024 * 1024; 631b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci 64d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon private static final String LOGTAG = "WebViewFactory"; 65d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon 66d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon private static final boolean DEBUG = false; 67d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon 68d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon // Cache the factory both for efficiency, and ensure any one process gets all webviews from the 69d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon // same provider. 70d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon private static WebViewFactoryProvider sProviderInstance; 719f9d34552f53c534141584a5ad4a8a49ad7939dcJohn Reck private static final Object sProviderLock = new Object(); 7208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) private static boolean sAddressSpaceReserved = false; 73d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon 74dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdoch public static String getWebViewPackageName() { 755651fc2feeed3af1bd0991e32788a8936d698811Torne (Richard Coles) return AppGlobals.getInitialApplication().getString( 765651fc2feeed3af1bd0991e32788a8936d698811Torne (Richard Coles) com.android.internal.R.string.config_webViewPackageName); 77dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdoch } 78dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdoch 799f9d34552f53c534141584a5ad4a8a49ad7939dcJohn Reck static WebViewFactoryProvider getProvider() { 809f9d34552f53c534141584a5ad4a8a49ad7939dcJohn Reck synchronized (sProviderLock) { 819f9d34552f53c534141584a5ad4a8a49ad7939dcJohn Reck // For now the main purpose of this function (and the factory abstraction) is to keep 82d892afc88d3c67a7fe1c9550bfa7a452051d031dTorne (Richard Coles) // us honest and minimize usage of WebView internals when binding the proxy. 839f9d34552f53c534141584a5ad4a8a49ad7939dcJohn Reck if (sProviderInstance != null) return sProviderInstance; 84d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon 8508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) loadNativeLibrary(); 8608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) 8703ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles) Class<WebViewFactoryProvider> providerClass; 8803ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles) try { 8903ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles) providerClass = getFactoryClass(); 9003ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles) } catch (ClassNotFoundException e) { 9103ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles) Log.e(LOGTAG, "error loading provider", e); 9203ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles) throw new AndroidRuntimeException(e); 93e09e976dad1d974ca28381451b0bbbeafbb872d5Ben Murdoch } 94e09e976dad1d974ca28381451b0bbbeafbb872d5Ben Murdoch 9503ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles) StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); 9603ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles) try { 9703ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles) sProviderInstance = providerClass.newInstance(); 9803ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles) if (DEBUG) Log.v(LOGTAG, "Loaded provider: " + sProviderInstance); 9903ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles) return sProviderInstance; 10003ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles) } catch (Exception e) { 10103ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles) Log.e(LOGTAG, "error instantiating provider", e); 10203ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles) throw new AndroidRuntimeException(e); 10303ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles) } finally { 10403ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles) StrictMode.setThreadPolicy(oldPolicy); 105e09e976dad1d974ca28381451b0bbbeafbb872d5Ben Murdoch } 106d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon } 107d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon } 108d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon 10903ce9b3e69f1eec85e7e7cbfd65bb9093e74cea8Torne (Richard Coles) private static Class<WebViewFactoryProvider> getFactoryClass() throws ClassNotFoundException { 11063d3d8a458cfc124ebd183994d3d152d3b06c1d8Marcin Kosiba Application initialApplication = AppGlobals.getInitialApplication(); 1110e04bcfbdc1845c931b45b3498aef438b944e961Ben Murdoch try { 11263d3d8a458cfc124ebd183994d3d152d3b06c1d8Marcin Kosiba Context webViewContext = initialApplication.createPackageContext( 1136c778cebc73e7eb76510f6e2183d804b8c07082bTorne (Richard Coles) getWebViewPackageName(), 1146c778cebc73e7eb76510f6e2183d804b8c07082bTorne (Richard Coles) Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY); 11563d3d8a458cfc124ebd183994d3d152d3b06c1d8Marcin Kosiba initialApplication.getAssets().addAssetPath( 11663d3d8a458cfc124ebd183994d3d152d3b06c1d8Marcin Kosiba webViewContext.getApplicationInfo().sourceDir); 1176c778cebc73e7eb76510f6e2183d804b8c07082bTorne (Richard Coles) ClassLoader clazzLoader = webViewContext.getClassLoader(); 1186c778cebc73e7eb76510f6e2183d804b8c07082bTorne (Richard Coles) return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY, true, 1196c778cebc73e7eb76510f6e2183d804b8c07082bTorne (Richard Coles) clazzLoader); 1206c778cebc73e7eb76510f6e2183d804b8c07082bTorne (Richard Coles) } catch (PackageManager.NameNotFoundException e) { 1216c778cebc73e7eb76510f6e2183d804b8c07082bTorne (Richard Coles) Log.e(LOGTAG, "Chromium WebView package does not exist"); 1220e04bcfbdc1845c931b45b3498aef438b944e961Ben Murdoch return (Class<WebViewFactoryProvider>) Class.forName(NULL_WEBVIEW_FACTORY); 1230e04bcfbdc1845c931b45b3498aef438b944e961Ben Murdoch } 124d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon } 12508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) 12608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) /** 12708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) * Perform any WebView loading preparations that must happen in the zygote. 12808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) * Currently, this means allocating address space to load the real JNI library later. 12908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) */ 13008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) public static void prepareWebViewInZygote() { 13108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) try { 13208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) System.loadLibrary("webviewchromium_loader"); 1335ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch long addressSpaceToReserve = 1345ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch SystemProperties.getLong(CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY, 1355ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch CHROMIUM_WEBVIEW_DEFAULT_VMSIZE_BYTES); 1365ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch sAddressSpaceReserved = nativeReserveAddressSpace(addressSpaceToReserve); 1375ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch 13808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) if (sAddressSpaceReserved) { 1395ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch if (DEBUG) { 1405ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch Log.v(LOGTAG, "address space reserved: " + addressSpaceToReserve + " bytes"); 1415ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch } 14208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) } else { 1435ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch Log.e(LOGTAG, "reserving " + addressSpaceToReserve + 1445ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch " bytes of address space failed"); 14508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) } 146810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci } catch (Throwable t) { 14708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) // Log and discard errors at this stage as we must not crash the zygote. 148810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci Log.e(LOGTAG, "error preparing native loader", t); 14908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) } 15008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) } 15108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) 15208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) /** 15308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) * Perform any WebView loading preparations that must happen at boot from the system server, 1545ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch * after the package manager has started or after an update to the webview is installed. 15508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) * This must be called in the system server. 15608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) * Currently, this means spawning the child processes which will create the relro files. 15708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) */ 15808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) public static void prepareWebViewInSystemServer() { 1595ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch String[] nativePaths = null; 1605ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch try { 1615ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch nativePaths = getWebViewNativeLibraryPaths(); 1625ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch } catch (PackageManager.NameNotFoundException e) { 1635ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch } 1645ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch prepareWebViewInSystemServer(nativePaths); 1655ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch } 1665ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch 1675ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch private static void prepareWebViewInSystemServer(String[] nativeLibraryPaths) { 16808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) if (DEBUG) Log.v(LOGTAG, "creating relro files"); 1695ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch 1705ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch // We must always trigger createRelRo regardless of the value of nativeLibraryPaths. Any 1715ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch // unexpected values will be handled there to ensure that we trigger notifying any process 1725ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch // waiting on relreo creation. 1735ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch if (Build.SUPPORTED_32_BIT_ABIS.length > 0) { 1745ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch if (DEBUG) Log.v(LOGTAG, "Create 32 bit relro"); 1755ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch createRelroFile(false /* is64Bit */, nativeLibraryPaths); 1765ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch } 1775ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch 1785ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch if (Build.SUPPORTED_64_BIT_ABIS.length > 0) { 1795ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch if (DEBUG) Log.v(LOGTAG, "Create 64 bit relro"); 1805ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch createRelroFile(true /* is64Bit */, nativeLibraryPaths); 1815ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch } 1825ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch } 1835ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch 1845ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch public static void onWebViewUpdateInstalled() { 1855ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch String[] nativeLibs = null; 1865ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch try { 1875ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch nativeLibs = WebViewFactory.getWebViewNativeLibraryPaths(); 1885ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch } catch (PackageManager.NameNotFoundException e) { 18908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) } 1905ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch 1915ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch if (nativeLibs != null) { 1925ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch long newVmSize = 0L; 1935ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch 1945ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch for (String path : nativeLibs) { 1955ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch if (DEBUG) Log.d(LOGTAG, "Checking file size of " + path); 1965ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch if (path == null) continue; 1975ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch File f = new File(path); 1985ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch if (f.exists()) { 1995ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch long length = f.length(); 2005ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch if (length > newVmSize) { 2015ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch newVmSize = length; 2025ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch } 2035ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch } 2045ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch } 2055ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch 2065ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch if (DEBUG) { 2075ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch Log.v(LOGTAG, "Based on library size, need " + newVmSize + 2085ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch " bytes of address space."); 2095ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch } 2105ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch // The required memory can be larger than the file on disk (due to .bss), and an 2115ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch // upgraded version of the library will likely be larger, so always attempt to reserve 2125ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch // twice as much as we think to allow for the library to grow during this boot cycle. 2135ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch newVmSize = Math.max(2 * newVmSize, CHROMIUM_WEBVIEW_DEFAULT_VMSIZE_BYTES); 2145ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch Log.d(LOGTAG, "Setting new address space to " + newVmSize); 2155ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch SystemProperties.set(CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY, 2165ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch Long.toString(newVmSize)); 21708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) } 2185ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch prepareWebViewInSystemServer(nativeLibs); 21908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) } 22008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) 2211b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci private static String[] getWebViewNativeLibraryPaths() 2221b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci throws PackageManager.NameNotFoundException { 2231b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci final String NATIVE_LIB_FILE_NAME = "libwebviewchromium.so"; 2241b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci 2251b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci PackageManager pm = AppGlobals.getInitialApplication().getPackageManager(); 2261b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci ApplicationInfo ai = pm.getApplicationInfo(getWebViewPackageName(), 0); 2271b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci 2281b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci String path32; 2291b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci String path64; 2301b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci boolean primaryArchIs64bit = VMRuntime.is64BitAbi(ai.primaryCpuAbi); 2311b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci if (!TextUtils.isEmpty(ai.secondaryCpuAbi)) { 2321b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci // Multi-arch case. 2331b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci if (primaryArchIs64bit) { 2341b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci // Primary arch: 64-bit, secondary: 32-bit. 2351b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci path64 = ai.nativeLibraryDir; 2361b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci path32 = ai.secondaryNativeLibraryDir; 2371b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci } else { 2381b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci // Primary arch: 32-bit, secondary: 64-bit. 2391b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci path64 = ai.secondaryNativeLibraryDir; 2401b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci path32 = ai.nativeLibraryDir; 2411b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci } 2421b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci } else if (primaryArchIs64bit) { 2431b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci // Single-arch 64-bit. 2441b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci path64 = ai.nativeLibraryDir; 2451b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci path32 = ""; 2461b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci } else { 2471b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci // Single-arch 32-bit. 2481b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci path32 = ai.nativeLibraryDir; 2491b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci path64 = ""; 2501b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci } 2511b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci if (!TextUtils.isEmpty(path32)) path32 += "/" + NATIVE_LIB_FILE_NAME; 2521b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci if (!TextUtils.isEmpty(path64)) path64 += "/" + NATIVE_LIB_FILE_NAME; 2531b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci return new String[] { path32, path64 }; 2541b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci } 2551b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci 2565ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch private static void createRelroFile(final boolean is64Bit, String[] nativeLibraryPaths) { 2571b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci final String abi = 2581b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci is64Bit ? Build.SUPPORTED_64_BIT_ABIS[0] : Build.SUPPORTED_32_BIT_ABIS[0]; 259810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci 260810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci // crashHandler is invoked by the ActivityManagerService when the isolated process crashes. 261810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci Runnable crashHandler = new Runnable() { 262810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci @Override 263810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci public void run() { 264810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci try { 2651b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci Log.e(LOGTAG, "relro file creator for " + abi + " crashed. Proceeding without"); 266810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci getUpdateService().notifyRelroCreationCompleted(is64Bit, false); 267810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci } catch (RemoteException e) { 268810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci Log.e(LOGTAG, "Cannot reach WebViewUpdateService. " + e.getMessage()); 269810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci } 270810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci } 271810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci }; 272810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci 27308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) try { 2745ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch if (nativeLibraryPaths == null 2755ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch || nativeLibraryPaths[0] == null || nativeLibraryPaths[1] == null) { 2765ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch throw new IllegalArgumentException( 2775ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch "Native library paths to the WebView RelRo process must not be null!"); 2785ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch } 279161536b5970ba5ab43233e7695ef69ba2bb804f4Primiano Tucci int pid = LocalServices.getService(ActivityManagerInternal.class).startIsolatedProcess( 2805ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch RelroFileCreator.class.getName(), nativeLibraryPaths, "WebViewLoader-" + abi, abi, 281810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci Process.SHARED_RELRO_UID, crashHandler); 282e76e81a227a29db5223d231ec88ecb02fa4d6835Primiano Tucci if (pid <= 0) throw new Exception("Failed to start the relro file creator process"); 283810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci } catch (Throwable t) { 28408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) // Log and discard errors as we must not crash the system server. 285810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci Log.e(LOGTAG, "error starting relro file creator for abi " + abi, t); 286810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci crashHandler.run(); 28708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) } 28808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) } 28908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) 29008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) private static class RelroFileCreator { 29108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) // Called in an unprivileged child process to create the relro file. 29208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) public static void main(String[] args) { 293161536b5970ba5ab43233e7695ef69ba2bb804f4Primiano Tucci boolean result = false; 294161536b5970ba5ab43233e7695ef69ba2bb804f4Primiano Tucci boolean is64Bit = VMRuntime.getRuntime().is64Bit(); 2951b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci try{ 2961b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci if (args.length != 2 || args[0] == null || args[1] == null) { 2971b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci Log.e(LOGTAG, "Invalid RelroFileCreator args: " + Arrays.toString(args)); 2981b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci return; 2991b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci } 3001b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci Log.v(LOGTAG, "RelroFileCreator (64bit = " + is64Bit + "), " + 3011b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci " 32-bit lib: " + args[0] + ", 64-bit lib: " + args[1]); 3021b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci if (!sAddressSpaceReserved) { 3031b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci Log.e(LOGTAG, "can't create relro file; address space not reserved"); 3041b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci return; 3051b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci } 306161536b5970ba5ab43233e7695ef69ba2bb804f4Primiano Tucci result = nativeCreateRelroFile(args[0] /* path32 */, 307161536b5970ba5ab43233e7695ef69ba2bb804f4Primiano Tucci args[1] /* path64 */, 308161536b5970ba5ab43233e7695ef69ba2bb804f4Primiano Tucci CHROMIUM_WEBVIEW_NATIVE_RELRO_32, 309161536b5970ba5ab43233e7695ef69ba2bb804f4Primiano Tucci CHROMIUM_WEBVIEW_NATIVE_RELRO_64); 310e76e81a227a29db5223d231ec88ecb02fa4d6835Primiano Tucci if (result && DEBUG) Log.v(LOGTAG, "created relro file"); 311161536b5970ba5ab43233e7695ef69ba2bb804f4Primiano Tucci } finally { 312161536b5970ba5ab43233e7695ef69ba2bb804f4Primiano Tucci // We must do our best to always notify the update service, even if something fails. 3131b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci try { 3141b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci getUpdateService().notifyRelroCreationCompleted(is64Bit, result); 3151b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci } catch (RemoteException e) { 3161b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci Log.e(LOGTAG, "error notifying update service", e); 3171b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci } 318161536b5970ba5ab43233e7695ef69ba2bb804f4Primiano Tucci 319161536b5970ba5ab43233e7695ef69ba2bb804f4Primiano Tucci if (!result) Log.e(LOGTAG, "failed to create relro file"); 320161536b5970ba5ab43233e7695ef69ba2bb804f4Primiano Tucci 3211b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci // Must explicitly exit or else this process will just sit around after we return. 3221b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci System.exit(0); 3231b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci } 32408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) } 32508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) } 32608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) 32708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) private static void loadNativeLibrary() { 32808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) if (!sAddressSpaceReserved) { 32908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) Log.e(LOGTAG, "can't load with relro file; address space not reserved"); 33008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) return; 33108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) } 33208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) 33308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) try { 33408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) getUpdateService().waitForRelroCreationCompleted(VMRuntime.getRuntime().is64Bit()); 33508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) } catch (RemoteException e) { 33608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) Log.e(LOGTAG, "error waiting for relro creation, proceeding without", e); 33708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) return; 33808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) } 33908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) 3401b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci try { 3411b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci String[] args = getWebViewNativeLibraryPaths(); 3421b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci boolean result = nativeLoadWithRelroFile(args[0] /* path32 */, 3431b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci args[1] /* path64 */, 3441b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci CHROMIUM_WEBVIEW_NATIVE_RELRO_32, 3451b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci CHROMIUM_WEBVIEW_NATIVE_RELRO_64); 3461b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci if (!result) { 3471b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci Log.w(LOGTAG, "failed to load with relro file, proceeding without"); 3481b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci } else if (DEBUG) { 3491b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci Log.v(LOGTAG, "loaded with relro file"); 3501b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci } 3511b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci } catch (PackageManager.NameNotFoundException e) { 3521b7977b608cd07366a1708aba36d48203f85bbbdPrimiano Tucci Log.e(LOGTAG, "Failed to list WebView package libraries for loadNativeLibrary", e); 35308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) } 35408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) } 35508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) 35608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) private static IWebViewUpdateService getUpdateService() { 35708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) return IWebViewUpdateService.Stub.asInterface(ServiceManager.getService("webviewupdate")); 35808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) } 35908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) 3605ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch private static native boolean nativeReserveAddressSpace(long addressSpaceToReserve); 36108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) private static native boolean nativeCreateRelroFile(String lib32, String lib64, 36208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) String relro32, String relro64); 36308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) private static native boolean nativeLoadWithRelroFile(String lib32, String lib64, 36408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) String relro32, String relro64); 365d3101b1d300f5942fdb7dfa323dc8830c4edc007Jonathan Dixon} 366