WebViewFactory.java revision eb665d66bac9aa3d7bf1834cfda6c886f721b157
1/* 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 19import android.os.Build; 20import android.os.StrictMode; 21import android.os.SystemProperties; 22import android.util.Log; 23 24import dalvik.system.PathClassLoader; 25 26/** 27 * Top level factory, used creating all the main WebView implementation classes. 28 * 29 * @hide 30 */ 31public final class WebViewFactory { 32 public static final boolean DEFAULT_TO_EXPERIMENTAL_WEBVIEW = false; 33 public static final String WEBVIEW_EXPERIMENTAL_PROPERTY = "persist.sys.webview.exp"; 34 private static final String FORCE_PROVIDER_PROPERTY = "webview.force_provider"; 35 private static final String FORCE_PROVIDER_PROPERTY_VALUE_CHROMIUM = "chromium"; 36 private static final String FORCE_PROVIDER_PROPERTY_VALUE_CLASSIC = "classic"; 37 38 // Default Provider factory class name. 39 // TODO: When the Chromium powered WebView is ready, it should be the default factory class. 40 private static final String DEFAULT_WEBVIEW_FACTORY = "android.webkit.WebViewClassic$Factory"; 41 private static final String CHROMIUM_WEBVIEW_FACTORY = 42 "com.android.webview.chromium.WebViewChromiumFactoryProvider"; 43 44 private static final String LOGTAG = "WebViewFactory"; 45 46 private static final boolean DEBUG = false; 47 48 // Cache the factory both for efficiency, and ensure any one process gets all webviews from the 49 // same provider. 50 private static WebViewFactoryProvider sProviderInstance; 51 private static final Object sProviderLock = new Object(); 52 53 public static boolean isExperimentalWebViewAvailable() { 54 try { 55 // Pass false so we don't initialize the class at this point, as this will be wasted if 56 // it's not enabled. 57 Class.forName(CHROMIUM_WEBVIEW_FACTORY, false, WebViewFactory.class.getClassLoader()); 58 return true; 59 } catch (ClassNotFoundException e) { 60 return false; 61 } 62 } 63 64 static WebViewFactoryProvider getProvider() { 65 synchronized (sProviderLock) { 66 // For now the main purpose of this function (and the factory abstraction) is to keep 67 // us honest and minimize usage of WebViewClassic internals when binding the proxy. 68 if (sProviderInstance != null) return sProviderInstance; 69 70 if (isExperimentalWebViewEnabled()) { 71 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); 72 try { 73 sProviderInstance = getFactoryByName(CHROMIUM_WEBVIEW_FACTORY); 74 if (DEBUG) Log.v(LOGTAG, "Loaded Chromium provider: " + sProviderInstance); 75 } finally { 76 StrictMode.setThreadPolicy(oldPolicy); 77 } 78 } 79 80 if (sProviderInstance == null) { 81 if (DEBUG) Log.v(LOGTAG, "Falling back to default provider: " 82 + DEFAULT_WEBVIEW_FACTORY); 83 sProviderInstance = getFactoryByName(DEFAULT_WEBVIEW_FACTORY); 84 if (sProviderInstance == null) { 85 if (DEBUG) Log.v(LOGTAG, "Falling back to explicit linkage"); 86 sProviderInstance = new WebViewClassic.Factory(); 87 } 88 } 89 return sProviderInstance; 90 } 91 } 92 93 // For debug builds, we allow a system property to specify that we should use the 94 // experimtanl Chromium powered WebView. This enables us to switch between 95 // implementations at runtime. For user (release) builds, don't allow this. 96 private static boolean isExperimentalWebViewEnabled() { 97 if (!isExperimentalWebViewAvailable()) return false; 98 boolean use_experimental_webview = SystemProperties.getBoolean( 99 WEBVIEW_EXPERIMENTAL_PROPERTY, DEFAULT_TO_EXPERIMENTAL_WEBVIEW); 100 String forceProviderName = SystemProperties.get(FORCE_PROVIDER_PROPERTY); 101 if (forceProviderName.isEmpty()) return use_experimental_webview; 102 103 Log.i(LOGTAG, String.format("Provider overridden by property: %s=%s", 104 FORCE_PROVIDER_PROPERTY, forceProviderName)); 105 if (forceProviderName.equals(FORCE_PROVIDER_PROPERTY_VALUE_CHROMIUM)) return true; 106 if (forceProviderName.equals(FORCE_PROVIDER_PROPERTY_VALUE_CLASSIC)) return false; 107 Log.e(LOGTAG, String.format("Unrecognized provider: %s", forceProviderName)); 108 return use_experimental_webview; 109 } 110 111 private static WebViewFactoryProvider getFactoryByName(String providerName) { 112 try { 113 if (DEBUG) Log.v(LOGTAG, "attempt to load class " + providerName); 114 Class<?> c = Class.forName(providerName); 115 if (DEBUG) Log.v(LOGTAG, "instantiating factory"); 116 return (WebViewFactoryProvider) c.newInstance(); 117 } catch (ClassNotFoundException e) { 118 Log.e(LOGTAG, "error loading " + providerName, e); 119 } catch (IllegalAccessException e) { 120 Log.e(LOGTAG, "error loading " + providerName, e); 121 } catch (InstantiationException e) { 122 Log.e(LOGTAG, "error loading " + providerName, e); 123 } 124 return null; 125 } 126} 127