blob: e9a9e8f80662cf94b9da20270d1251f5005d6e91 [file] [log] [blame]
Jonathan Dixond3101b12012-04-12 20:51:51 +01001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.webkit;
18
Ignacio Solla451e3382014-11-10 10:35:54 +000019import android.annotation.SystemApi;
Mathew Inwood42afea22018-08-16 19:18:28 +010020import android.annotation.UnsupportedAppUsage;
Sudheer Shankadc589ac2016-11-10 15:30:17 -080021import android.app.ActivityManager;
Torne (Richard Coles)6c778ce2014-07-17 14:14:48 -070022import android.app.AppGlobals;
Jeff Sharkey85844912014-11-13 16:20:38 -080023import android.app.Application;
Torne (Richard Coles)6c778ce2014-07-17 14:14:48 -070024import android.content.Context;
Primiano Tucci1b7977b2014-07-25 19:19:32 +010025import android.content.pm.ApplicationInfo;
Torne (Richard Coles)0606cd52014-08-05 16:12:09 +010026import android.content.pm.PackageInfo;
Torne (Richard Coles)6c778ce2014-07-17 14:14:48 -070027import android.content.pm.PackageManager;
Gustav Senntoncd8f2732016-04-14 09:58:36 +010028import android.content.pm.Signature;
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +010029import android.os.RemoteException;
30import android.os.ServiceManager;
Torne (Richard Coles)38228822014-08-13 17:11:45 +010031import android.os.Trace;
Torne (Richard Coles)03ce9b32013-06-12 16:02:03 +010032import android.util.AndroidRuntimeException;
Gustav Senntoncd8f2732016-04-14 09:58:36 +010033import android.util.ArraySet;
Jonathan Dixond3101b12012-04-12 20:51:51 +010034import android.util.Log;
Jeff Sharkey85844912014-11-13 16:20:38 -080035
Torne (Richard Coles)12f64da2017-10-24 14:59:07 -040036import java.io.File;
Bo Liu48273852016-08-16 19:03:44 -070037import java.lang.reflect.Method;
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +010038
Jonathan Dixond3101b12012-04-12 20:51:51 +010039/**
40 * Top level factory, used creating all the main WebView implementation classes.
Jared Dukeb0e35842013-03-19 16:25:39 -070041 *
42 * @hide
Jonathan Dixond3101b12012-04-12 20:51:51 +010043 */
Ignacio Solla451e3382014-11-10 10:35:54 +000044@SystemApi
Jared Dukeb0e35842013-03-19 16:25:39 -070045public final class WebViewFactory {
Jonathan Dixona7eaa8e2013-07-25 19:52:47 -070046
Torne (Richard Coles)3b6ca992016-10-10 15:11:36 +010047 // visible for WebViewZygoteInit to look up the class by reflection and call preloadInZygote.
48 /** @hide */
Tao Bai755eded2017-01-09 18:35:44 -080049 private static final String CHROMIUM_WEBVIEW_FACTORY =
Shimi Zhang295c5a12017-12-14 19:03:30 -080050 "com.android.webview.chromium.WebViewChromiumFactoryProviderForP";
Jonathan Dixond3101b12012-04-12 20:51:51 +010051
Bo Liu48273852016-08-16 19:03:44 -070052 private static final String CHROMIUM_WEBVIEW_FACTORY_METHOD = "create";
53
Ben Murdoch5ced5022014-07-28 15:57:00 +010054 public static final String CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY =
55 "persist.sys.webview.vmsize";
Primiano Tucci1b7977b2014-07-25 19:19:32 +010056
Jonathan Dixond3101b12012-04-12 20:51:51 +010057 private static final String LOGTAG = "WebViewFactory";
58
59 private static final boolean DEBUG = false;
60
61 // Cache the factory both for efficiency, and ensure any one process gets all webviews from the
62 // same provider.
Mathew Inwood42afea22018-08-16 19:18:28 +010063 @UnsupportedAppUsage
Jonathan Dixond3101b12012-04-12 20:51:51 +010064 private static WebViewFactoryProvider sProviderInstance;
John Reck9f9d3452012-09-20 13:18:59 -070065 private static final Object sProviderLock = new Object();
Mathew Inwood42afea22018-08-16 19:18:28 +010066 @UnsupportedAppUsage
Torne (Richard Coles)84392d72014-08-14 16:43:18 +010067 private static PackageInfo sPackageInfo;
Torne (Richard Coles)ff937ac2017-10-02 17:09:32 -040068 private static Boolean sWebViewSupported;
Torne (Richard Coles)12f64da2017-10-24 14:59:07 -040069 private static boolean sWebViewDisabled;
70 private static String sDataDirectorySuffix; // stored here so it can be set without loading WV
Jonathan Dixond3101b12012-04-12 20:51:51 +010071
Gustav Sennton85edb6c2015-04-15 11:54:20 +010072 // Error codes for loadWebViewNativeLibraryFromPackage
73 public static final int LIBLOAD_SUCCESS = 0;
74 public static final int LIBLOAD_WRONG_PACKAGE_NAME = 1;
75 public static final int LIBLOAD_ADDRESS_SPACE_NOT_RESERVED = 2;
Gustav Sennton6258dcd2015-10-30 19:25:37 +000076
77 // error codes for waiting for WebView preparation
Gustav Sennton85edb6c2015-04-15 11:54:20 +010078 public static final int LIBLOAD_FAILED_WAITING_FOR_RELRO = 3;
79 public static final int LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES = 4;
80
81 // native relro loading error codes
82 public static final int LIBLOAD_FAILED_TO_OPEN_RELRO_FILE = 5;
83 public static final int LIBLOAD_FAILED_TO_LOAD_LIBRARY = 6;
84 public static final int LIBLOAD_FAILED_JNI_CALL = 7;
85
Gustav Sennton6258dcd2015-10-30 19:25:37 +000086 // more error codes for waiting for WebView preparation
Gustav Sennton26c82ff2016-03-11 13:06:40 +000087 public static final int LIBLOAD_FAILED_WAITING_FOR_WEBVIEW_REASON_UNKNOWN = 8;
Gustav Sennton6258dcd2015-10-30 19:25:37 +000088
Torne (Richard Coles)1a904122016-03-14 13:45:55 +000089 // error for namespace lookup
90 public static final int LIBLOAD_FAILED_TO_FIND_NAMESPACE = 10;
91
Gustav Senntonb715d402017-05-12 14:22:58 +010092
Gustav Sennton6258dcd2015-10-30 19:25:37 +000093 private static String getWebViewPreparationErrorReason(int error) {
94 switch (error) {
95 case LIBLOAD_FAILED_WAITING_FOR_RELRO:
96 return "Time out waiting for Relro files being created";
97 case LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES:
98 return "No WebView installed";
Gustav Sennton6258dcd2015-10-30 19:25:37 +000099 case LIBLOAD_FAILED_WAITING_FOR_WEBVIEW_REASON_UNKNOWN:
100 return "Crashed for unknown reason";
101 }
102 return "Unknown";
103 }
104
Gustav Senntoned98a1562017-06-06 14:25:49 +0100105 static class MissingWebViewPackageException extends Exception {
Gustav Senntona8366e72015-04-17 11:24:07 +0100106 public MissingWebViewPackageException(String message) { super(message); }
107 public MissingWebViewPackageException(Exception e) { super(e); }
108 }
109
Torne (Richard Coles)ff937ac2017-10-02 17:09:32 -0400110 private static boolean isWebViewSupported() {
111 // No lock; this is a benign race as Boolean's state is final and the PackageManager call
112 // will always return the same value.
113 if (sWebViewSupported == null) {
114 sWebViewSupported = AppGlobals.getInitialApplication().getPackageManager()
115 .hasSystemFeature(PackageManager.FEATURE_WEBVIEW);
116 }
117 return sWebViewSupported;
118 }
119
Gustav Sennton6ce92c92015-10-23 11:10:39 +0100120 /**
Gustav Sennton6ce92c92015-10-23 11:10:39 +0100121 * @hide
122 */
Torne (Richard Coles)12f64da2017-10-24 14:59:07 -0400123 static void disableWebView() {
124 synchronized (sProviderLock) {
125 if (sProviderInstance != null) {
126 throw new IllegalStateException(
127 "Can't disable WebView: WebView already initialized");
128 }
129 sWebViewDisabled = true;
130 }
131 }
132
133 /**
134 * @hide
135 */
136 static void setDataDirectorySuffix(String suffix) {
137 synchronized (sProviderLock) {
138 if (sProviderInstance != null) {
139 throw new IllegalStateException(
140 "Can't set data directory suffix: WebView already initialized");
141 }
142 if (suffix.indexOf(File.separatorChar) >= 0) {
143 throw new IllegalArgumentException("Suffix " + suffix
144 + " contains a path separator");
145 }
146 sDataDirectorySuffix = suffix;
147 }
148 }
149
150 /**
151 * @hide
152 */
153 static String getDataDirectorySuffix() {
154 synchronized (sProviderLock) {
155 return sDataDirectorySuffix;
156 }
157 }
158
159 /**
160 * @hide
161 */
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000162 public static String getWebViewLibrary(ApplicationInfo ai) {
Gustav Sennton2ed6fee2015-03-03 15:12:34 +0000163 if (ai.metaData != null)
164 return ai.metaData.getString("com.android.webview.WebViewLibrary");
165 return null;
Ben Murdochdc00a842014-07-17 14:55:00 +0100166 }
167
Torne (Richard Coles)84392d72014-08-14 16:43:18 +0100168 public static PackageInfo getLoadedPackageInfo() {
Gustav Senntonbf683e02016-09-15 14:42:50 +0100169 synchronized (sProviderLock) {
170 return sPackageInfo;
171 }
Torne (Richard Coles)84392d72014-08-14 16:43:18 +0100172 }
173
Gustav Sennton85edb6c2015-04-15 11:54:20 +0100174 /**
Tao Bai755eded2017-01-09 18:35:44 -0800175 * @hide
176 */
Gustav Sennton564c2fd2017-01-30 18:08:01 +0000177 public static Class<WebViewFactoryProvider> getWebViewProviderClass(ClassLoader clazzLoader)
178 throws ClassNotFoundException {
179 return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY,
180 true, clazzLoader);
Tao Bai755eded2017-01-09 18:35:44 -0800181 }
182
183 /**
Nate Fischer2be201e2017-10-26 10:43:00 -0700184 * Load the native library for the given package name if that package
Gustav Senntond97301822015-06-18 16:56:26 +0100185 * name is the same as the one providing the webview.
Gustav Sennton85edb6c2015-04-15 11:54:20 +0100186 */
Torne (Richard Coles)1a904122016-03-14 13:45:55 +0000187 public static int loadWebViewNativeLibraryFromPackage(String packageName,
188 ClassLoader clazzLoader) {
Torne (Richard Coles)ff937ac2017-10-02 17:09:32 -0400189 if (!isWebViewSupported()) {
190 return LIBLOAD_WRONG_PACKAGE_NAME;
191 }
192
Gustav Senntonb088cb32016-06-17 14:02:52 +0100193 WebViewProviderResponse response = null;
194 try {
195 response = getUpdateService().waitForAndGetProvider();
196 } catch (RemoteException e) {
197 Log.e(LOGTAG, "error waiting for relro creation", e);
198 return LIBLOAD_FAILED_WAITING_FOR_WEBVIEW_REASON_UNKNOWN;
Gustav Sennton6ce92c92015-10-23 11:10:39 +0100199 }
Gustav Senntonb088cb32016-06-17 14:02:52 +0100200
201
202 if (response.status != LIBLOAD_SUCCESS
203 && response.status != LIBLOAD_FAILED_WAITING_FOR_RELRO) {
204 return response.status;
205 }
206 if (!response.packageInfo.packageName.equals(packageName)) {
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000207 return LIBLOAD_WRONG_PACKAGE_NAME;
Gustav Senntonb088cb32016-06-17 14:02:52 +0100208 }
209
210 PackageManager packageManager = AppGlobals.getInitialApplication().getPackageManager();
Torne (Richard Coles)ec572f62018-02-21 15:55:24 -0500211 String libraryFileName;
Gustav Senntonb088cb32016-06-17 14:02:52 +0100212 try {
Torne (Richard Coles)ec572f62018-02-21 15:55:24 -0500213 PackageInfo packageInfo = packageManager.getPackageInfo(packageName,
Gustav Senntonb088cb32016-06-17 14:02:52 +0100214 PackageManager.GET_META_DATA | PackageManager.MATCH_DEBUG_TRIAGED_MISSING);
Torne (Richard Coles)ec572f62018-02-21 15:55:24 -0500215 libraryFileName = getWebViewLibrary(packageInfo.applicationInfo);
Gustav Senntonb088cb32016-06-17 14:02:52 +0100216 } catch (PackageManager.NameNotFoundException e) {
217 Log.e(LOGTAG, "Couldn't find package " + packageName);
218 return LIBLOAD_WRONG_PACKAGE_NAME;
219 }
Gustav Sennton6ce92c92015-10-23 11:10:39 +0100220
Torne (Richard Coles)ec572f62018-02-21 15:55:24 -0500221 int loadNativeRet = WebViewLibraryLoader.loadNativeLibrary(clazzLoader, libraryFileName);
222 // If we failed waiting for relro we want to return that fact even if we successfully
223 // load the relro file.
224 if (loadNativeRet == LIBLOAD_SUCCESS) return response.status;
225 return loadNativeRet;
Gustav Sennton85edb6c2015-04-15 11:54:20 +0100226 }
227
Mathew Inwood42afea22018-08-16 19:18:28 +0100228 @UnsupportedAppUsage
John Reck9f9d3452012-09-20 13:18:59 -0700229 static WebViewFactoryProvider getProvider() {
230 synchronized (sProviderLock) {
231 // For now the main purpose of this function (and the factory abstraction) is to keep
Torne (Richard Coles)d892afc2013-10-14 17:14:04 +0100232 // us honest and minimize usage of WebView internals when binding the proxy.
John Reck9f9d3452012-09-20 13:18:59 -0700233 if (sProviderInstance != null) return sProviderInstance;
Jonathan Dixond3101b12012-04-12 20:51:51 +0100234
Jeff Sharkey85844912014-11-13 16:20:38 -0800235 final int uid = android.os.Process.myUid();
Robert Sesek450b55b2017-03-16 18:17:11 -0400236 if (uid == android.os.Process.ROOT_UID || uid == android.os.Process.SYSTEM_UID
237 || uid == android.os.Process.PHONE_UID || uid == android.os.Process.NFC_UID
238 || uid == android.os.Process.BLUETOOTH_UID) {
Jeff Sharkey85844912014-11-13 16:20:38 -0800239 throw new UnsupportedOperationException(
240 "For security reasons, WebView is not allowed in privileged processes");
241 }
242
Torne (Richard Coles)ff937ac2017-10-02 17:09:32 -0400243 if (!isWebViewSupported()) {
244 // Device doesn't support WebView; don't try to load it, just throw.
245 throw new UnsupportedOperationException();
246 }
247
Torne (Richard Coles)12f64da2017-10-24 14:59:07 -0400248 if (sWebViewDisabled) {
249 throw new IllegalStateException(
250 "WebView.disableWebView() was called: WebView is disabled");
251 }
252
Torne (Richard Coles)38228822014-08-13 17:11:45 +0100253 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.getProvider()");
Torne (Richard Coles)03ce9b32013-06-12 16:02:03 +0100254 try {
Gustav Senntona8366e72015-04-17 11:24:07 +0100255 Class<WebViewFactoryProvider> providerClass = getProviderClass();
Bo Liu48273852016-08-16 19:03:44 -0700256 Method staticFactory = null;
257 try {
258 staticFactory = providerClass.getMethod(
259 CHROMIUM_WEBVIEW_FACTORY_METHOD, WebViewDelegate.class);
260 } catch (Exception e) {
261 if (DEBUG) {
262 Log.w(LOGTAG, "error instantiating provider with static factory method", e);
263 }
264 }
Torne (Richard Coles)38228822014-08-13 17:11:45 +0100265
Gustav Sennton564c2fd2017-01-30 18:08:01 +0000266 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactoryProvider invocation");
Torne (Richard Coles)38228822014-08-13 17:11:45 +0100267 try {
Gustav Sennton564c2fd2017-01-30 18:08:01 +0000268 sProviderInstance = (WebViewFactoryProvider)
269 staticFactory.invoke(null, new WebViewDelegate());
Torne (Richard Coles)38228822014-08-13 17:11:45 +0100270 if (DEBUG) Log.v(LOGTAG, "Loaded provider: " + sProviderInstance);
271 return sProviderInstance;
272 } catch (Exception e) {
273 Log.e(LOGTAG, "error instantiating provider", e);
274 throw new AndroidRuntimeException(e);
275 } finally {
276 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
Torne (Richard Coles)38228822014-08-13 17:11:45 +0100277 }
Torne (Richard Coles)03ce9b32013-06-12 16:02:03 +0100278 } finally {
Torne (Richard Coles)38228822014-08-13 17:11:45 +0100279 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
Torne (Richard Coles)03ce9b32013-06-12 16:02:03 +0100280 }
Jonathan Dixond3101b12012-04-12 20:51:51 +0100281 }
Jonathan Dixond3101b12012-04-12 20:51:51 +0100282 }
283
Gustav Senntoncd8f2732016-04-14 09:58:36 +0100284 /**
Nate Fischer0a6140d2017-09-05 12:37:49 -0700285 * Returns {@code true} if the signatures match, {@code false} otherwise
Gustav Senntoncd8f2732016-04-14 09:58:36 +0100286 */
287 private static boolean signaturesEquals(Signature[] s1, Signature[] s2) {
288 if (s1 == null) {
289 return s2 == null;
290 }
291 if (s2 == null) return false;
292
293 ArraySet<Signature> set1 = new ArraySet<>();
294 for(Signature signature : s1) {
295 set1.add(signature);
296 }
297 ArraySet<Signature> set2 = new ArraySet<>();
298 for(Signature signature : s2) {
299 set2.add(signature);
300 }
301 return set1.equals(set2);
302 }
303
304 // Throws MissingWebViewPackageException on failure
Gustav Senntonb715d402017-05-12 14:22:58 +0100305 private static void verifyPackageInfo(PackageInfo chosen, PackageInfo toUse)
306 throws MissingWebViewPackageException {
Gustav Senntoncd8f2732016-04-14 09:58:36 +0100307 if (!chosen.packageName.equals(toUse.packageName)) {
308 throw new MissingWebViewPackageException("Failed to verify WebView provider, "
309 + "packageName mismatch, expected: "
310 + chosen.packageName + " actual: " + toUse.packageName);
311 }
Dianne Hackborn3accca02013-09-20 09:32:11 -0700312 if (chosen.getLongVersionCode() > toUse.getLongVersionCode()) {
Gustav Senntoncd8f2732016-04-14 09:58:36 +0100313 throw new MissingWebViewPackageException("Failed to verify WebView provider, "
Dianne Hackborn3accca02013-09-20 09:32:11 -0700314 + "version code is lower than expected: " + chosen.getLongVersionCode()
315 + " actual: " + toUse.getLongVersionCode());
Gustav Senntoncd8f2732016-04-14 09:58:36 +0100316 }
317 if (getWebViewLibrary(toUse.applicationInfo) == null) {
318 throw new MissingWebViewPackageException("Tried to load an invalid WebView provider: "
319 + toUse.packageName);
320 }
321 if (!signaturesEquals(chosen.signatures, toUse.signatures)) {
322 throw new MissingWebViewPackageException("Failed to verify WebView provider, "
323 + "signature mismatch");
324 }
325 }
326
Torne (Richard Coles)04526702017-01-13 14:19:39 +0000327 /**
328 * If the ApplicationInfo provided is for a stub WebView, fix up the object to include the
329 * required values from the donor package. If the ApplicationInfo is for a full WebView,
330 * leave it alone. Throws MissingWebViewPackageException if the donor is missing.
331 */
Gustav Senntonb715d402017-05-12 14:22:58 +0100332 private static void fixupStubApplicationInfo(ApplicationInfo ai, PackageManager pm)
333 throws MissingWebViewPackageException {
Torne (Richard Coles)04526702017-01-13 14:19:39 +0000334 String donorPackageName = null;
335 if (ai.metaData != null) {
336 donorPackageName = ai.metaData.getString("com.android.webview.WebViewDonorPackage");
337 }
338 if (donorPackageName != null) {
339 PackageInfo donorPackage;
340 try {
341 donorPackage = pm.getPackageInfo(
342 donorPackageName,
343 PackageManager.GET_SHARED_LIBRARY_FILES
344 | PackageManager.MATCH_DEBUG_TRIAGED_MISSING
345 | PackageManager.MATCH_UNINSTALLED_PACKAGES
346 | PackageManager.MATCH_FACTORY_ONLY);
347 } catch (PackageManager.NameNotFoundException e) {
348 throw new MissingWebViewPackageException("Failed to find donor package: " +
349 donorPackageName);
350 }
351 ApplicationInfo donorInfo = donorPackage.applicationInfo;
352
353 // Replace the stub's code locations with the donor's.
354 ai.sourceDir = donorInfo.sourceDir;
355 ai.splitSourceDirs = donorInfo.splitSourceDirs;
356 ai.nativeLibraryDir = donorInfo.nativeLibraryDir;
357 ai.secondaryNativeLibraryDir = donorInfo.secondaryNativeLibraryDir;
358
359 // Copy the donor's primary and secondary ABIs, since the stub doesn't have native code
360 // and so they are unset.
361 ai.primaryCpuAbi = donorInfo.primaryCpuAbi;
362 ai.secondaryCpuAbi = donorInfo.secondaryCpuAbi;
363 }
364 }
365
Mathew Inwood42afea22018-08-16 19:18:28 +0100366 @UnsupportedAppUsage
Gustav Senntonb715d402017-05-12 14:22:58 +0100367 private static Context getWebViewContextAndSetProvider() throws MissingWebViewPackageException {
Gustav Senntoncd8f2732016-04-14 09:58:36 +0100368 Application initialApplication = AppGlobals.getInitialApplication();
369 try {
370 WebViewProviderResponse response = null;
371 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW,
372 "WebViewUpdateService.waitForAndGetProvider()");
373 try {
374 response = getUpdateService().waitForAndGetProvider();
375 } finally {
376 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
377 }
Gustav Senntonfd07efa2016-05-23 13:09:03 +0100378 if (response.status != LIBLOAD_SUCCESS
379 && response.status != LIBLOAD_FAILED_WAITING_FOR_RELRO) {
Gustav Senntoncd8f2732016-04-14 09:58:36 +0100380 throw new MissingWebViewPackageException("Failed to load WebView provider: "
381 + getWebViewPreparationErrorReason(response.status));
382 }
383 // Register to be killed before fetching package info - so that we will be
384 // killed if the package info goes out-of-date.
385 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "ActivityManager.addPackageDependency()");
386 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800387 ActivityManager.getService().addPackageDependency(
Gustav Senntoncd8f2732016-04-14 09:58:36 +0100388 response.packageInfo.packageName);
389 } finally {
390 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
391 }
392 // Fetch package info and verify it against the chosen package
393 PackageInfo newPackageInfo = null;
Torne (Richard Coles)04526702017-01-13 14:19:39 +0000394 PackageManager pm = initialApplication.getPackageManager();
Gustav Senntoncd8f2732016-04-14 09:58:36 +0100395 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "PackageManager.getPackageInfo()");
396 try {
Torne (Richard Coles)04526702017-01-13 14:19:39 +0000397 newPackageInfo = pm.getPackageInfo(
Gustav Senntoncd8f2732016-04-14 09:58:36 +0100398 response.packageInfo.packageName,
399 PackageManager.GET_SHARED_LIBRARY_FILES
400 | PackageManager.MATCH_DEBUG_TRIAGED_MISSING
401 // Make sure that we fetch the current provider even if its not
402 // installed for the current user
403 | PackageManager.MATCH_UNINSTALLED_PACKAGES
404 // Fetch signatures for verification
405 | PackageManager.GET_SIGNATURES
406 // Get meta-data for meta data flag verification
407 | PackageManager.GET_META_DATA);
408 } finally {
409 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
410 }
411
412 // Validate the newly fetched package info, throws MissingWebViewPackageException on
413 // failure
414 verifyPackageInfo(response.packageInfo, newPackageInfo);
415
Torne (Richard Coles)04526702017-01-13 14:19:39 +0000416 ApplicationInfo ai = newPackageInfo.applicationInfo;
417 fixupStubApplicationInfo(ai, pm);
418
Gustav Senntoncd8f2732016-04-14 09:58:36 +0100419 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW,
420 "initialApplication.createApplicationContext");
421 try {
422 // Construct an app context to load the Java code into the current app.
423 Context webViewContext = initialApplication.createApplicationContext(
Torne (Richard Coles)04526702017-01-13 14:19:39 +0000424 ai,
Gustav Senntoncd8f2732016-04-14 09:58:36 +0100425 Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
Gustav Senntonb088cb32016-06-17 14:02:52 +0100426 sPackageInfo = newPackageInfo;
Gustav Senntoncd8f2732016-04-14 09:58:36 +0100427 return webViewContext;
428 } finally {
429 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
430 }
431 } catch (RemoteException | PackageManager.NameNotFoundException e) {
432 throw new MissingWebViewPackageException("Failed to load WebView provider: " + e);
433 }
434 }
435
Mathew Inwood42afea22018-08-16 19:18:28 +0100436 @UnsupportedAppUsage
Gustav Senntona8366e72015-04-17 11:24:07 +0100437 private static Class<WebViewFactoryProvider> getProviderClass() {
Gustav Senntoncd8f2732016-04-14 09:58:36 +0100438 Context webViewContext = null;
439 Application initialApplication = AppGlobals.getInitialApplication();
440
Gustav Senntona8366e72015-04-17 11:24:07 +0100441 try {
Gustav Senntonfc424472016-01-06 17:11:09 +0000442 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW,
Gustav Senntoncd8f2732016-04-14 09:58:36 +0100443 "WebViewFactory.getWebViewContextAndSetProvider()");
Gustav Senntonfc424472016-01-06 17:11:09 +0000444 try {
Gustav Senntoncd8f2732016-04-14 09:58:36 +0100445 webViewContext = getWebViewContextAndSetProvider();
Gustav Senntonfc424472016-01-06 17:11:09 +0000446 } finally {
447 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000448 }
Gustav Senntona8366e72015-04-17 11:24:07 +0100449 Log.i(LOGTAG, "Loading " + sPackageInfo.packageName + " version " +
Dianne Hackborn3accca02013-09-20 09:32:11 -0700450 sPackageInfo.versionName + " (code " + sPackageInfo.getLongVersionCode() + ")");
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000451
Gustav Senntona8366e72015-04-17 11:24:07 +0100452 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.getChromiumProviderClass()");
453 try {
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000454 initialApplication.getAssets().addAssetPathAsSharedLibrary(
455 webViewContext.getApplicationInfo().sourceDir);
456 ClassLoader clazzLoader = webViewContext.getClassLoader();
Torne (Richard Coles)1a904122016-03-14 13:45:55 +0000457
458 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.loadNativeLibrary()");
Torne (Richard Coles)ec572f62018-02-21 15:55:24 -0500459 WebViewLibraryLoader.loadNativeLibrary(clazzLoader,
460 getWebViewLibrary(sPackageInfo.applicationInfo));
Torne (Richard Coles)1a904122016-03-14 13:45:55 +0000461 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
462
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000463 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "Class.forName()");
464 try {
Tao Bai755eded2017-01-09 18:35:44 -0800465 return getWebViewProviderClass(clazzLoader);
Gustav Sennton564c2fd2017-01-30 18:08:01 +0000466 } finally {
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000467 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
468 }
Gustav Senntona8366e72015-04-17 11:24:07 +0100469 } catch (ClassNotFoundException e) {
470 Log.e(LOGTAG, "error loading provider", e);
471 throw new AndroidRuntimeException(e);
472 } finally {
473 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
474 }
475 } catch (MissingWebViewPackageException e) {
Gustav Senntona8366e72015-04-17 11:24:07 +0100476 Log.e(LOGTAG, "Chromium WebView package does not exist", e);
477 throw new AndroidRuntimeException(e);
478 }
479 }
480
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +0100481 /**
482 * Perform any WebView loading preparations that must happen in the zygote.
483 * Currently, this means allocating address space to load the real JNI library later.
484 */
485 public static void prepareWebViewInZygote() {
486 try {
Gustav Senntoned98a1562017-06-06 14:25:49 +0100487 WebViewLibraryLoader.reserveAddressSpaceInZygote();
Primiano Tucci810c0522014-07-25 18:03:16 +0100488 } catch (Throwable t) {
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +0100489 // Log and discard errors at this stage as we must not crash the zygote.
Primiano Tucci810c0522014-07-25 18:03:16 +0100490 Log.e(LOGTAG, "error preparing native loader", t);
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +0100491 }
492 }
493
Gustav Sennton6258dcd2015-10-30 19:25:37 +0000494 /**
495 * @hide
496 */
497 public static int onWebViewProviderChanged(PackageInfo packageInfo) {
Gustav Sennton0e541ef2017-10-24 14:28:26 +0100498 int startedRelroProcesses = 0;
Torne (Richard Coles)4fd8aa52017-09-19 15:21:29 -0400499 ApplicationInfo originalAppInfo = new ApplicationInfo(packageInfo.applicationInfo);
Ben Murdoch5ced5022014-07-28 15:57:00 +0100500 try {
Torne (Richard Coles)04526702017-01-13 14:19:39 +0000501 fixupStubApplicationInfo(packageInfo.applicationInfo,
502 AppGlobals.getInitialApplication().getPackageManager());
503
Gustav Sennton0e541ef2017-10-24 14:28:26 +0100504 startedRelroProcesses = WebViewLibraryLoader.prepareNativeLibraries(packageInfo);
Torne (Richard Coles)27cb0d22014-08-08 18:24:12 +0100505 } catch (Throwable t) {
506 // Log and discard errors at this stage as we must not crash the system server.
507 Log.e(LOGTAG, "error preparing webview native library", t);
Ben Murdoch5ced5022014-07-28 15:57:00 +0100508 }
Robert Sesekded20982016-08-15 13:59:13 -0400509
Torne (Richard Coles)4fd8aa52017-09-19 15:21:29 -0400510 WebViewZygote.onWebViewProviderChanged(packageInfo, originalAppInfo);
Robert Sesekded20982016-08-15 13:59:13 -0400511
Gustav Sennton0e541ef2017-10-24 14:28:26 +0100512 return startedRelroProcesses;
Ben Murdoch5ced5022014-07-28 15:57:00 +0100513 }
514
Gustav Sennton1c177d82016-03-29 20:43:11 +0100515 private static String WEBVIEW_UPDATE_SERVICE_NAME = "webviewupdate";
516
517 /** @hide */
Mathew Inwood42afea22018-08-16 19:18:28 +0100518 @UnsupportedAppUsage
Gustav Sennton1c177d82016-03-29 20:43:11 +0100519 public static IWebViewUpdateService getUpdateService() {
Torne (Richard Coles)ff937ac2017-10-02 17:09:32 -0400520 if (isWebViewSupported()) {
Torne (Richard Coles)29675b22017-10-04 11:29:58 -0400521 return getUpdateServiceUnchecked();
Torne (Richard Coles)ff937ac2017-10-02 17:09:32 -0400522 } else {
523 return null;
524 }
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +0100525 }
Torne (Richard Coles)29675b22017-10-04 11:29:58 -0400526
527 /** @hide */
528 static IWebViewUpdateService getUpdateServiceUnchecked() {
529 return IWebViewUpdateService.Stub.asInterface(
530 ServiceManager.getService(WEBVIEW_UPDATE_SERVICE_NAME));
531 }
Jonathan Dixond3101b12012-04-12 20:51:51 +0100532}