blob: 2ee0961a658298eca76e79210a713bb936b9b2c9 [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
Ben Murdoche09e9762012-07-19 14:48:13 +010019import android.os.Build;
20import android.os.StrictMode;
21import android.os.SystemProperties;
Torne (Richard Coles)03ce9b32013-06-12 16:02:03 +010022import android.util.AndroidRuntimeException;
Jonathan Dixond3101b12012-04-12 20:51:51 +010023import android.util.Log;
24
25/**
26 * Top level factory, used creating all the main WebView implementation classes.
Jared Dukeb0e35842013-03-19 16:25:39 -070027 *
28 * @hide
Jonathan Dixond3101b12012-04-12 20:51:51 +010029 */
Jared Dukeb0e35842013-03-19 16:25:39 -070030public final class WebViewFactory {
Primiano Tuccieb665d62013-05-17 11:50:19 +010031 public static final boolean DEFAULT_TO_EXPERIMENTAL_WEBVIEW = false;
Jared Dukeb0e35842013-03-19 16:25:39 -070032 public static final String WEBVIEW_EXPERIMENTAL_PROPERTY = "persist.sys.webview.exp";
Primiano Tuccieb665d62013-05-17 11:50:19 +010033 private static final String FORCE_PROVIDER_PROPERTY = "webview.force_provider";
34 private static final String FORCE_PROVIDER_PROPERTY_VALUE_CHROMIUM = "chromium";
35 private static final String FORCE_PROVIDER_PROPERTY_VALUE_CLASSIC = "classic";
Jared Dukeb0e35842013-03-19 16:25:39 -070036
Jonathan Dixond3101b12012-04-12 20:51:51 +010037 // Default Provider factory class name.
Ben Murdoche09e9762012-07-19 14:48:13 +010038 // TODO: When the Chromium powered WebView is ready, it should be the default factory class.
39 private static final String DEFAULT_WEBVIEW_FACTORY = "android.webkit.WebViewClassic$Factory";
40 private static final String CHROMIUM_WEBVIEW_FACTORY =
Torne (Richard Coles)a9bbd942012-10-24 11:59:22 +010041 "com.android.webview.chromium.WebViewChromiumFactoryProvider";
Jonathan Dixond3101b12012-04-12 20:51:51 +010042
43 private static final String LOGTAG = "WebViewFactory";
44
45 private static final boolean DEBUG = false;
46
Torne (Richard Coles)03ce9b32013-06-12 16:02:03 +010047 private static class Preloader {
48 static WebViewFactoryProvider sPreloadedProvider;
49 static {
50 try {
51 sPreloadedProvider = getFactoryClass().newInstance();
52 } catch (Exception e) {
53 Log.w(LOGTAG, "error preloading provider", e);
54 }
55 }
56 }
57
Jonathan Dixond3101b12012-04-12 20:51:51 +010058 // Cache the factory both for efficiency, and ensure any one process gets all webviews from the
59 // same provider.
60 private static WebViewFactoryProvider sProviderInstance;
John Reck9f9d3452012-09-20 13:18:59 -070061 private static final Object sProviderLock = new Object();
Jonathan Dixond3101b12012-04-12 20:51:51 +010062
Jared Dukeb0e35842013-03-19 16:25:39 -070063 public static boolean isExperimentalWebViewAvailable() {
Torne (Richard Coles)eb07f3c2013-06-04 15:50:13 +010064 try {
65 // Pass false so we don't initialize the class at this point, as this will be wasted if
66 // it's not enabled.
67 Class.forName(CHROMIUM_WEBVIEW_FACTORY, false, WebViewFactory.class.getClassLoader());
68 return true;
69 } catch (ClassNotFoundException e) {
70 return false;
71 }
Jared Dukeb0e35842013-03-19 16:25:39 -070072 }
73
John Reck9f9d3452012-09-20 13:18:59 -070074 static WebViewFactoryProvider getProvider() {
75 synchronized (sProviderLock) {
76 // For now the main purpose of this function (and the factory abstraction) is to keep
77 // us honest and minimize usage of WebViewClassic internals when binding the proxy.
78 if (sProviderInstance != null) return sProviderInstance;
Jonathan Dixond3101b12012-04-12 20:51:51 +010079
Torne (Richard Coles)03ce9b32013-06-12 16:02:03 +010080 Class<WebViewFactoryProvider> providerClass;
81 try {
82 providerClass = getFactoryClass();
83 } catch (ClassNotFoundException e) {
84 Log.e(LOGTAG, "error loading provider", e);
85 throw new AndroidRuntimeException(e);
Ben Murdoche09e9762012-07-19 14:48:13 +010086 }
Ben Murdoche09e9762012-07-19 14:48:13 +010087
Torne (Richard Coles)03ce9b32013-06-12 16:02:03 +010088 // This implicitly loads Preloader even if it wasn't preloaded at boot.
89 if (Preloader.sPreloadedProvider != null &&
90 Preloader.sPreloadedProvider.getClass() == providerClass) {
91 sProviderInstance = Preloader.sPreloadedProvider;
92 if (DEBUG) Log.v(LOGTAG, "Using preloaded provider: " + sProviderInstance);
93 return sProviderInstance;
Ben Murdoche09e9762012-07-19 14:48:13 +010094 }
Torne (Richard Coles)03ce9b32013-06-12 16:02:03 +010095
96 // The preloaded provider isn't the one we wanted; construct our own.
97 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
98 try {
99 sProviderInstance = providerClass.newInstance();
100 if (DEBUG) Log.v(LOGTAG, "Loaded provider: " + sProviderInstance);
101 return sProviderInstance;
102 } catch (Exception e) {
103 Log.e(LOGTAG, "error instantiating provider", e);
104 throw new AndroidRuntimeException(e);
105 } finally {
106 StrictMode.setThreadPolicy(oldPolicy);
107 }
Jonathan Dixond3101b12012-04-12 20:51:51 +0100108 }
Jonathan Dixond3101b12012-04-12 20:51:51 +0100109 }
110
Torne (Richard Coles)03ce9b32013-06-12 16:02:03 +0100111 // We allow a system property to specify that we should use the experimental Chromium powered
112 // WebView. This enables us to switch between implementations at runtime.
Jared Dukeb0e35842013-03-19 16:25:39 -0700113 private static boolean isExperimentalWebViewEnabled() {
Primiano Tuccieb665d62013-05-17 11:50:19 +0100114 if (!isExperimentalWebViewAvailable()) return false;
115 boolean use_experimental_webview = SystemProperties.getBoolean(
116 WEBVIEW_EXPERIMENTAL_PROPERTY, DEFAULT_TO_EXPERIMENTAL_WEBVIEW);
117 String forceProviderName = SystemProperties.get(FORCE_PROVIDER_PROPERTY);
118 if (forceProviderName.isEmpty()) return use_experimental_webview;
119
120 Log.i(LOGTAG, String.format("Provider overridden by property: %s=%s",
121 FORCE_PROVIDER_PROPERTY, forceProviderName));
122 if (forceProviderName.equals(FORCE_PROVIDER_PROPERTY_VALUE_CHROMIUM)) return true;
123 if (forceProviderName.equals(FORCE_PROVIDER_PROPERTY_VALUE_CLASSIC)) return false;
124 Log.e(LOGTAG, String.format("Unrecognized provider: %s", forceProviderName));
125 return use_experimental_webview;
Jared Dukeb0e35842013-03-19 16:25:39 -0700126 }
127
Torne (Richard Coles)03ce9b32013-06-12 16:02:03 +0100128 private static Class<WebViewFactoryProvider> getFactoryClass() throws ClassNotFoundException {
129 if (isExperimentalWebViewEnabled()) {
130 return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY);
131 } else {
132 return (Class<WebViewFactoryProvider>) Class.forName(DEFAULT_WEBVIEW_FACTORY);
Jonathan Dixond3101b12012-04-12 20:51:51 +0100133 }
Jonathan Dixond3101b12012-04-12 20:51:51 +0100134 }
135}