blob: 00d87bd8d9fee3ed29632306eed87f43abbca240 [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;
Jonathan Dixond3101b12012-04-12 20:51:51 +010022import android.util.Log;
23
Ben Murdoche09e9762012-07-19 14:48:13 +010024import dalvik.system.PathClassLoader;
25
Jonathan Dixond3101b12012-04-12 20:51:51 +010026/**
27 * Top level factory, used creating all the main WebView implementation classes.
Jared Dukeb0e35842013-03-19 16:25:39 -070028 *
29 * @hide
Jonathan Dixond3101b12012-04-12 20:51:51 +010030 */
Jared Dukeb0e35842013-03-19 16:25:39 -070031public final class WebViewFactory {
32 public static final String WEBVIEW_EXPERIMENTAL_PROPERTY = "persist.sys.webview.exp";
33 private static final String DEPRECATED_CHROMIUM_PROPERTY = "webview.use_chromium";
34
Jonathan Dixond3101b12012-04-12 20:51:51 +010035 // Default Provider factory class name.
Ben Murdoche09e9762012-07-19 14:48:13 +010036 // TODO: When the Chromium powered WebView is ready, it should be the default factory class.
37 private static final String DEFAULT_WEBVIEW_FACTORY = "android.webkit.WebViewClassic$Factory";
38 private static final String CHROMIUM_WEBVIEW_FACTORY =
Torne (Richard Coles)a9bbd942012-10-24 11:59:22 +010039 "com.android.webview.chromium.WebViewChromiumFactoryProvider";
Ben Murdoche09e9762012-07-19 14:48:13 +010040 private static final String CHROMIUM_WEBVIEW_JAR = "/system/framework/webviewchromium.jar";
Jonathan Dixond3101b12012-04-12 20:51:51 +010041
42 private static final String LOGTAG = "WebViewFactory";
43
44 private static final boolean DEBUG = false;
45
46 // Cache the factory both for efficiency, and ensure any one process gets all webviews from the
47 // same provider.
48 private static WebViewFactoryProvider sProviderInstance;
John Reck9f9d3452012-09-20 13:18:59 -070049 private static final Object sProviderLock = new Object();
Jonathan Dixond3101b12012-04-12 20:51:51 +010050
Jared Dukeb0e35842013-03-19 16:25:39 -070051 public static boolean isExperimentalWebViewAvailable() {
52 return Build.IS_DEBUGGABLE && (new java.io.File(CHROMIUM_WEBVIEW_JAR).exists());
53 }
54
John Reck9f9d3452012-09-20 13:18:59 -070055 static WebViewFactoryProvider getProvider() {
56 synchronized (sProviderLock) {
57 // For now the main purpose of this function (and the factory abstraction) is to keep
58 // us honest and minimize usage of WebViewClassic internals when binding the proxy.
59 if (sProviderInstance != null) return sProviderInstance;
Jonathan Dixond3101b12012-04-12 20:51:51 +010060
Jared Dukeb0e35842013-03-19 16:25:39 -070061 if (isExperimentalWebViewEnabled()) {
John Reck9f9d3452012-09-20 13:18:59 -070062 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
63 try {
64 sProviderInstance = loadChromiumProvider();
65 if (DEBUG) Log.v(LOGTAG, "Loaded Chromium provider: " + sProviderInstance);
66 } finally {
67 StrictMode.setThreadPolicy(oldPolicy);
68 }
Ben Murdoche09e9762012-07-19 14:48:13 +010069 }
Ben Murdoche09e9762012-07-19 14:48:13 +010070
Ben Murdoche09e9762012-07-19 14:48:13 +010071 if (sProviderInstance == null) {
John Reck9f9d3452012-09-20 13:18:59 -070072 if (DEBUG) Log.v(LOGTAG, "Falling back to default provider: "
73 + DEFAULT_WEBVIEW_FACTORY);
74 sProviderInstance = getFactoryByName(DEFAULT_WEBVIEW_FACTORY,
75 WebViewFactory.class.getClassLoader());
76 if (sProviderInstance == null) {
77 if (DEBUG) Log.v(LOGTAG, "Falling back to explicit linkage");
78 sProviderInstance = new WebViewClassic.Factory();
79 }
Ben Murdoche09e9762012-07-19 14:48:13 +010080 }
John Reck9f9d3452012-09-20 13:18:59 -070081 return sProviderInstance;
Jonathan Dixond3101b12012-04-12 20:51:51 +010082 }
Jonathan Dixond3101b12012-04-12 20:51:51 +010083 }
84
Jared Dukeb0e35842013-03-19 16:25:39 -070085 // For debug builds, we allow a system property to specify that we should use the
86 // experimtanl Chromium powered WebView. This enables us to switch between
87 // implementations at runtime. For user (release) builds, don't allow this.
88 private static boolean isExperimentalWebViewEnabled() {
89 if (!isExperimentalWebViewAvailable())
90 return false;
91 if (SystemProperties.getBoolean(DEPRECATED_CHROMIUM_PROPERTY, false)) {
92 Log.w(LOGTAG, String.format("The property %s has been deprecated. Please use %s.",
93 DEPRECATED_CHROMIUM_PROPERTY, WEBVIEW_EXPERIMENTAL_PROPERTY));
94 return true;
95 }
96 return SystemProperties.getBoolean(WEBVIEW_EXPERIMENTAL_PROPERTY, false);
97 }
98
Ben Murdoche09e9762012-07-19 14:48:13 +010099 // TODO: This allows us to have the legacy and Chromium WebView coexist for development
100 // and side-by-side testing. After transition, remove this when no longer required.
101 private static WebViewFactoryProvider loadChromiumProvider() {
102 ClassLoader clazzLoader = new PathClassLoader(CHROMIUM_WEBVIEW_JAR, null,
103 WebViewFactory.class.getClassLoader());
104 return getFactoryByName(CHROMIUM_WEBVIEW_FACTORY, clazzLoader);
105 }
106
107 private static WebViewFactoryProvider getFactoryByName(String providerName,
108 ClassLoader loader) {
Jonathan Dixond3101b12012-04-12 20:51:51 +0100109 try {
110 if (DEBUG) Log.v(LOGTAG, "attempt to load class " + providerName);
Ben Murdoche09e9762012-07-19 14:48:13 +0100111 Class<?> c = Class.forName(providerName, true, loader);
Jonathan Dixond3101b12012-04-12 20:51:51 +0100112 if (DEBUG) Log.v(LOGTAG, "instantiating factory");
113 return (WebViewFactoryProvider) c.newInstance();
114 } catch (ClassNotFoundException e) {
115 Log.e(LOGTAG, "error loading " + providerName, e);
116 } catch (IllegalAccessException e) {
117 Log.e(LOGTAG, "error loading " + providerName, e);
118 } catch (InstantiationException e) {
119 Log.e(LOGTAG, "error loading " + providerName, e);
120 }
121 return null;
122 }
123}