WebViewChromiumFactoryProvider.java revision 991b0c63bb8c0b0d8577a255b026117e9f37cece
146f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)/*
246f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles) * Copyright (C) 2012 The Android Open Source Project
346f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles) *
446f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles) * Licensed under the Apache License, Version 2.0 (the "License");
546f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles) * you may not use this file except in compliance with the License.
646f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles) * You may obtain a copy of the License at
746f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles) *
846f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles) *      http://www.apache.org/licenses/LICENSE-2.0
946f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles) *
1046f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles) * Unless required by applicable law or agreed to in writing, software
1146f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles) * distributed under the License is distributed on an "AS IS" BASIS,
1246f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles) * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1346f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles) * See the License for the specific language governing permissions and
1446f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles) * limitations under the License.
1546f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles) */
1646f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)
1746f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)package com.android.webview.chromium;
1846f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)
1946f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)import android.app.ActivityThread;
2046f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)import android.content.Context;
21009ed27511c4606dcd16b352489b2d3f70b4b513Kristian Monsenimport android.content.SharedPreferences;
2246f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)import android.os.Looper;
2346f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)import android.webkit.CookieManager;
2446f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)import android.webkit.GeolocationPermissions;
2546f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)import android.webkit.WebIconDatabase;
2646f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)import android.webkit.WebStorage;
2746f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)import android.webkit.WebView;
2846f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)import android.webkit.WebViewDatabase;
2946f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)import android.webkit.WebViewFactoryProvider;
3046f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)import android.webkit.WebViewProvider;
3146f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)
32a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixonimport org.chromium.android_webview.AwContents;
33d5f17bbd8703a56ac084a64b1ce2f673f67bd72dKristian Monsenimport org.chromium.android_webview.AwCookieManager;
34009ed27511c4606dcd16b352489b2d3f70b4b513Kristian Monsenimport org.chromium.android_webview.AwGeolocationPermissions;
3546f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)import org.chromium.base.PathService;
36e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liuimport org.chromium.base.PathUtils;
37e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liuimport org.chromium.base.ThreadUtils;
38e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liuimport org.chromium.content.app.LibraryLoader;
39e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liuimport org.chromium.content.browser.AndroidBrowserProcess;
4046f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)import org.chromium.content.browser.ContentSettings;
4146f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)import org.chromium.content.browser.ContentViewStatics;
4246f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)import org.chromium.content.browser.ResourceExtractor;
4346f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)
4446f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)public class WebViewChromiumFactoryProvider implements WebViewFactoryProvider {
4546f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)
4646f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)    private final Object mLock = new Object();
4746f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)
48009ed27511c4606dcd16b352489b2d3f70b4b513Kristian Monsen    private static final String CHROMIUM_PREFS_NAME = "WebViewChromiumPrefs";
49009ed27511c4606dcd16b352489b2d3f70b4b513Kristian Monsen
5046f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)    // Initialization guarded by mLock.
51009ed27511c4606dcd16b352489b2d3f70b4b513Kristian Monsen    private SharedPreferences mWebViewChromiumSharedPreferences;
52aadb04e4198e1f0dce390e9434cb189603b8e713Jonathan Dixon    private Statics mStaticMethods;
53aadb04e4198e1f0dce390e9434cb189603b8e713Jonathan Dixon    private GeolocationPermissionsAdapter mGeolocationPermissions;
54aadb04e4198e1f0dce390e9434cb189603b8e713Jonathan Dixon    private CookieManagerAdapter mCookieManager;
55aadb04e4198e1f0dce390e9434cb189603b8e713Jonathan Dixon    private WebIconDatabaseAdapter mWebIconDatabase;
56aadb04e4198e1f0dce390e9434cb189603b8e713Jonathan Dixon    private WebStorageAdapter mWebStorage;
57aadb04e4198e1f0dce390e9434cb189603b8e713Jonathan Dixon    private WebViewDatabaseAdapter mWebViewDatabase;
5846f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)
59e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu    // Initialization guarded by mLock.
60e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu    private GeolocationPermissionsAdapter mGeolocationPermissionsAdapter;
6146f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)
62e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu    // Read/write protected by mLock.
63e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu    private boolean mInitialized;
643053d8bc3be48b0cbc6f33e1975c03a10ac303a5Jonathan Dixon
65e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu    private void loadPlatSupportLibrary() {
66a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon        // Load glue-layer support library.
67a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon        System.loadLibrary("webviewchromium_plat_support");
68a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon        DrawGLFunctor.setChromiumAwDrawGLFunction(AwContents.getAwDrawGLFunction());
69991b0c63bb8c0b0d8577a255b026117e9f37ceceJonathan Dixon        AwContents.setAwDrawSWFunctionTable(GraphicsUtils.getDrawSWFunctionTable());
70a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon    }
71a2b0d0b4d6d1ff22fbb1329e358e1cc0a112aab3Jonathan Dixon
72e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu    // TODO(joth): Much of this initialization logic could be moved into the chromium tree.
73e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu    private void ensureChromiumNativeInitializedLocked() {
7446f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)        assert Thread.holdsLock(mLock);
7546f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)
76e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu        if (mInitialized) {
77e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu            return;
78e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu        }
793053d8bc3be48b0cbc6f33e1975c03a10ac303a5Jonathan Dixon
80e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu        // We must post to the UI thread to cover the case that the user
81e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu        // has invoked Chromium startup by using the (thread-safe)
82e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu        // CookieManager rather than creating a WebView.
83e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
84e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu            @Override
85e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu            public void run() {
86e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu                PathUtils.setPrivateDataDirectorySuffix("webview");
87e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu                // We don't need to extract any paks because for WebView, they are
88e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu                // in the system image.
89e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu                ResourceExtractor.setMandatoryPaksToExtract("");
90e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu
91e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu                LibraryLoader.setLibraryToLoad("webviewchromium");
92e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu
93e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu                // TODO: Ultimately we want to do this step in the zygote
94e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu                // process, so we should split this init step into two parts -
95e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu                // one generic bit that loads the library and another that performs
96e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu                // the app specific parts.
97e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu                LibraryLoader.loadAndInitSync();
98e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu
99e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu                PathService.override(PathService.DIR_MODULE, "/system/lib/");
100e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu                // TODO: DIR_RESOURCE_PAKS_ANDROID needs to live somewhere sensible,
101e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu                // inlined here for simplicity setting up the HTMLViewer demo. Unfortunately
102e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu                // it can't go into base.PathService, as the native constant it refers to
103e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu                // lives in the ui/ layer. See ui/base/ui_base_paths.h
104e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu                final int DIR_RESOURCE_PAKS_ANDROID = 3003;
105e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu                PathService.override(DIR_RESOURCE_PAKS_ANDROID,
106e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu                        "/system/framework/webview/paks");
107e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu
108e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu                // Caching for later use, possibly from other threads
109e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu                mWebViewChromiumSharedPreferences = ActivityThread.currentApplication().
110e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu                        getSharedPreferences(CHROMIUM_PREFS_NAME, Context.MODE_PRIVATE);
111e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu
112e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu                AndroidBrowserProcess.initContentViewProcess(ActivityThread.currentApplication(),
113e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu                        AndroidBrowserProcess.MAX_RENDERERS_SINGLE_PROCESS);
114e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu
115e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu                loadPlatSupportLibrary();
116e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu            }
117e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu        });
118e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu        mInitialized = true;
11946f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)    }
12046f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)
12146f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)    @Override
12246f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)    public Statics getStatics() {
12346f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)        synchronized (mLock) {
12446f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)            if (mStaticMethods == null) {
125e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu                // TODO: Optimization potential: most these methods only need the native library
126e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu                // loaded, not the entire browser process initialized. See also http://b/7009882
127e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu                ensureChromiumNativeInitializedLocked();
12846f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)                mStaticMethods = new WebViewFactoryProvider.Statics() {
12946f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)                    @Override
13046f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)                    public String findAddress(String addr) {
13146f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)                        return ContentViewStatics.findAddress(addr);
13246f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)                    }
13346f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)
13446f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)                    @Override
13546f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)                    public void setPlatformNotificationsEnabled(boolean enable) {
13646f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)                        // noop
13746f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)                    }
13846f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)
139e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu                    // TODO: There's no @Override to keep the build green for folks building
140e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu                    // against jb-dev or an out of date master. At some point, add @Override.
14146f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)                    public String getDefaultUserAgent(Context context) {
14246f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)                        return ContentSettings.getDefaultUserAgent();
14346f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)                    }
14446f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)                };
14546f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)            }
14646f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)        }
14746f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)        return mStaticMethods;
14846f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)    }
14946f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)
15046f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)    @Override
15146f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)    public WebViewProvider createWebView(WebView webView, WebView.PrivateAccess privateAccess) {
15246f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)        assert Looper.myLooper() == Looper.getMainLooper();
15346f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)        synchronized (mLock) {
154e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu            ensureChromiumNativeInitializedLocked();
15546f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)            ResourceProvider.registerResources(webView.getContext());
15646f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)        }
15746f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)        return new WebViewChromium(webView, privateAccess);
15846f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)    }
15946f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)
16046f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)    @Override
16146f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)    public GeolocationPermissions getGeolocationPermissions() {
162009ed27511c4606dcd16b352489b2d3f70b4b513Kristian Monsen        synchronized (mLock) {
163aadb04e4198e1f0dce390e9434cb189603b8e713Jonathan Dixon            if (mGeolocationPermissions == null) {
164e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu                ensureChromiumNativeInitializedLocked();
165e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu                mGeolocationPermissionsAdapter = new GeolocationPermissionsAdapter(
166009ed27511c4606dcd16b352489b2d3f70b4b513Kristian Monsen                        new AwGeolocationPermissions(mWebViewChromiumSharedPreferences));
167009ed27511c4606dcd16b352489b2d3f70b4b513Kristian Monsen            }
168009ed27511c4606dcd16b352489b2d3f70b4b513Kristian Monsen        }
169aadb04e4198e1f0dce390e9434cb189603b8e713Jonathan Dixon        return mGeolocationPermissions;
17046f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)    }
17146f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)
17246f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)    @Override
17346f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)    public CookieManager getCookieManager() {
17446f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)        synchronized (mLock) {
175aadb04e4198e1f0dce390e9434cb189603b8e713Jonathan Dixon            if (mCookieManager == null) {
176e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu                ensureChromiumNativeInitializedLocked();
177d5f17bbd8703a56ac084a64b1ce2f673f67bd72dKristian Monsen                mCookieManager = new CookieManagerAdapter(new AwCookieManager());
17846f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)            }
17946f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)        }
180aadb04e4198e1f0dce390e9434cb189603b8e713Jonathan Dixon        return mCookieManager;
18146f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)    }
18246f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)
18346f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)    @Override
18446f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)    public WebIconDatabase getWebIconDatabase() {
185aadb04e4198e1f0dce390e9434cb189603b8e713Jonathan Dixon        synchronized (mLock) {
186aadb04e4198e1f0dce390e9434cb189603b8e713Jonathan Dixon            if (mWebIconDatabase == null) {
187e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu                ensureChromiumNativeInitializedLocked();
188aadb04e4198e1f0dce390e9434cb189603b8e713Jonathan Dixon                mWebIconDatabase = new WebIconDatabaseAdapter();
189aadb04e4198e1f0dce390e9434cb189603b8e713Jonathan Dixon            }
190aadb04e4198e1f0dce390e9434cb189603b8e713Jonathan Dixon        }
191aadb04e4198e1f0dce390e9434cb189603b8e713Jonathan Dixon        return mWebIconDatabase;
19246f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)    }
19346f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)
19446f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)    @Override
19546f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)    public WebStorage getWebStorage() {
196aadb04e4198e1f0dce390e9434cb189603b8e713Jonathan Dixon        synchronized (mLock) {
197aadb04e4198e1f0dce390e9434cb189603b8e713Jonathan Dixon            if (mWebStorage == null) {
198e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu                ensureChromiumNativeInitializedLocked();
199aadb04e4198e1f0dce390e9434cb189603b8e713Jonathan Dixon                mWebStorage = new WebStorageAdapter();
200aadb04e4198e1f0dce390e9434cb189603b8e713Jonathan Dixon            }
201aadb04e4198e1f0dce390e9434cb189603b8e713Jonathan Dixon        }
202aadb04e4198e1f0dce390e9434cb189603b8e713Jonathan Dixon        return mWebStorage;
20346f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)    }
20446f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)
20546f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)    @Override
20646f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)    public WebViewDatabase getWebViewDatabase(Context context) {
20746f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)        synchronized (mLock) {
208aadb04e4198e1f0dce390e9434cb189603b8e713Jonathan Dixon            if (mWebViewDatabase == null) {
209e49b38ed53e1b3be1530e4eb1b49ce6ba6f62db1Bo Liu                ensureChromiumNativeInitializedLocked();
210aadb04e4198e1f0dce390e9434cb189603b8e713Jonathan Dixon                mWebViewDatabase = new WebViewDatabaseAdapter();
211aadb04e4198e1f0dce390e9434cb189603b8e713Jonathan Dixon            }
21246f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)        }
213aadb04e4198e1f0dce390e9434cb189603b8e713Jonathan Dixon        return mWebViewDatabase;
21446f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)    }
21546f104289826e85ba76a1a2139d7ecc7daca07b1Torne (Richard Coles)}
216