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.AndroidRuntimeException;
23import android.util.Log;
24
25/**
26 * Top level factory, used creating all the main WebView implementation classes.
27 *
28 * @hide
29 */
30public final class WebViewFactory {
31
32    private static final String CHROMIUM_WEBVIEW_FACTORY =
33            "com.android.webview.chromium.WebViewChromiumFactoryProvider";
34
35    private static final String LOGTAG = "WebViewFactory";
36
37    private static final boolean DEBUG = false;
38
39    private static class Preloader {
40        static WebViewFactoryProvider sPreloadedProvider;
41        static {
42            try {
43                sPreloadedProvider = getFactoryClass().newInstance();
44            } catch (Exception e) {
45                Log.w(LOGTAG, "error preloading provider", e);
46            }
47        }
48    }
49
50    // Cache the factory both for efficiency, and ensure any one process gets all webviews from the
51    // same provider.
52    private static WebViewFactoryProvider sProviderInstance;
53    private static final Object sProviderLock = new Object();
54
55    public static boolean isExperimentalWebViewAvailable() {
56        // TODO: Remove callers of this method then remove it.
57        return false;  // Hide the toggle in Developer Settings.
58    }
59
60    /** @hide */
61    public static void setUseExperimentalWebView(boolean enable) {
62        // TODO: Remove callers of this method then remove it.
63    }
64
65    /** @hide */
66    public static boolean useExperimentalWebView() {
67        // TODO: Remove callers of this method then remove it.
68        return true;
69    }
70
71    /** @hide */
72    public static boolean isUseExperimentalWebViewSet() {
73        // TODO: Remove callers of this method then remove it.
74        return false;  // User has not modifed Developer Settings
75    }
76
77    static WebViewFactoryProvider getProvider() {
78        synchronized (sProviderLock) {
79            // For now the main purpose of this function (and the factory abstraction) is to keep
80            // us honest and minimize usage of WebView internals when binding the proxy.
81            if (sProviderInstance != null) return sProviderInstance;
82
83            Class<WebViewFactoryProvider> providerClass;
84            try {
85                providerClass = getFactoryClass();
86            } catch (ClassNotFoundException e) {
87                Log.e(LOGTAG, "error loading provider", e);
88                throw new AndroidRuntimeException(e);
89            }
90
91            // This implicitly loads Preloader even if it wasn't preloaded at boot.
92            if (Preloader.sPreloadedProvider != null &&
93                Preloader.sPreloadedProvider.getClass() == providerClass) {
94                sProviderInstance = Preloader.sPreloadedProvider;
95                if (DEBUG) Log.v(LOGTAG, "Using preloaded provider: " + sProviderInstance);
96                return sProviderInstance;
97            }
98
99            // The preloaded provider isn't the one we wanted; construct our own.
100            StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
101            try {
102                sProviderInstance = providerClass.newInstance();
103                if (DEBUG) Log.v(LOGTAG, "Loaded provider: " + sProviderInstance);
104                return sProviderInstance;
105            } catch (Exception e) {
106                Log.e(LOGTAG, "error instantiating provider", e);
107                throw new AndroidRuntimeException(e);
108            } finally {
109                StrictMode.setThreadPolicy(oldPolicy);
110            }
111        }
112    }
113
114    private static Class<WebViewFactoryProvider> getFactoryClass() throws ClassNotFoundException {
115        return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY);
116    }
117}
118