17df1985e86635af006be3dfa65987d60e290b5deBen Murdoch/*
27df1985e86635af006be3dfa65987d60e290b5deBen Murdoch * Copyright (C) 2009 The Android Open Source Project
37df1985e86635af006be3dfa65987d60e290b5deBen Murdoch *
47df1985e86635af006be3dfa65987d60e290b5deBen Murdoch * Licensed under the Apache License, Version 2.0 (the "License");
57df1985e86635af006be3dfa65987d60e290b5deBen Murdoch * you may not use this file except in compliance with the License.
67df1985e86635af006be3dfa65987d60e290b5deBen Murdoch * You may obtain a copy of the License at
77df1985e86635af006be3dfa65987d60e290b5deBen Murdoch *
87df1985e86635af006be3dfa65987d60e290b5deBen Murdoch *      http://www.apache.org/licenses/LICENSE-2.0
97df1985e86635af006be3dfa65987d60e290b5deBen Murdoch *
107df1985e86635af006be3dfa65987d60e290b5deBen Murdoch * Unless required by applicable law or agreed to in writing, software
117df1985e86635af006be3dfa65987d60e290b5deBen Murdoch * distributed under the License is distributed on an "AS IS" BASIS,
127df1985e86635af006be3dfa65987d60e290b5deBen Murdoch * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137df1985e86635af006be3dfa65987d60e290b5deBen Murdoch * See the License for the specific language governing permissions and
147df1985e86635af006be3dfa65987d60e290b5deBen Murdoch * limitations under the License.
157df1985e86635af006be3dfa65987d60e290b5deBen Murdoch */
167df1985e86635af006be3dfa65987d60e290b5deBen Murdoch
177df1985e86635af006be3dfa65987d60e290b5deBen Murdochpackage android.webkit;
187df1985e86635af006be3dfa65987d60e290b5deBen Murdoch
1911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roardimport android.os.Handler;
2011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roardimport android.os.Message;
2111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roardimport android.util.Log;
2211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
236c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roardimport java.util.Collection;
246c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roardimport java.util.Map;
2511e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roardimport java.util.HashMap;
26af9c77edbddfcf87a4dc17b95db84bf741674a9aAndrei Popescuimport java.util.HashSet;
27af9c77edbddfcf87a4dc17b95db84bf741674a9aAndrei Popescuimport java.util.Iterator;
28af9c77edbddfcf87a4dc17b95db84bf741674a9aAndrei Popescuimport java.util.Set;
2911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
307df1985e86635af006be3dfa65987d60e290b5deBen Murdoch/**
317df1985e86635af006be3dfa65987d60e290b5deBen Murdoch * Functionality for manipulating the webstorage databases.
327df1985e86635af006be3dfa65987d60e290b5deBen Murdoch */
337df1985e86635af006be3dfa65987d60e290b5deBen Murdochpublic final class WebStorage {
347df1985e86635af006be3dfa65987d60e290b5deBen Murdoch
357df1985e86635af006be3dfa65987d60e290b5deBen Murdoch    /**
367df1985e86635af006be3dfa65987d60e290b5deBen Murdoch     * Encapsulates a callback function to be executed when a new quota is made
377df1985e86635af006be3dfa65987d60e290b5deBen Murdoch     * available. We primarily want this to allow us to call back the sleeping
387df1985e86635af006be3dfa65987d60e290b5deBen Murdoch     * WebCore thread from outside the WebViewCore class (as the native call
397df1985e86635af006be3dfa65987d60e290b5deBen Murdoch     * is private). It is imperative that this the setDatabaseQuota method is
407df1985e86635af006be3dfa65987d60e290b5deBen Murdoch     * executed once a decision to either allow or deny new quota is made,
417df1985e86635af006be3dfa65987d60e290b5deBen Murdoch     * otherwise the WebCore thread will remain asleep.
427df1985e86635af006be3dfa65987d60e290b5deBen Murdoch     */
437df1985e86635af006be3dfa65987d60e290b5deBen Murdoch    public interface QuotaUpdater {
447df1985e86635af006be3dfa65987d60e290b5deBen Murdoch        public void updateQuota(long newQuota);
457df1985e86635af006be3dfa65987d60e290b5deBen Murdoch    };
4611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
4711e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    // Log tag
4811e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    private static final String TAG = "webstorage";
4911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
5011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    // Global instance of a WebStorage
5111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    private static WebStorage sWebStorage;
5211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
5311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    // Message ids
5411e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    static final int UPDATE = 0;
5511e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    static final int SET_QUOTA_ORIGIN = 1;
5611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    static final int DELETE_ORIGIN = 2;
5711e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    static final int DELETE_ALL = 3;
586c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard    static final int GET_ORIGINS = 4;
596c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard    static final int GET_USAGE_ORIGIN = 5;
606c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard    static final int GET_QUOTA_ORIGIN = 6;
616c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard
626c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard    // Message ids on the UI thread
636c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard    static final int RETURN_ORIGINS = 0;
646c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard    static final int RETURN_USAGE_ORIGIN = 1;
656c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard    static final int RETURN_QUOTA_ORIGIN = 2;
666c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard
676c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard    private static final String ORIGINS = "origins";
686c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard    private static final String ORIGIN = "origin";
696c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard    private static final String CALLBACK = "callback";
706c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard    private static final String USAGE = "usage";
716c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard    private static final String QUOTA = "quota";
7211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
736c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard    private Map <String, Origin> mOrigins;
7411e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
7511e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    private Handler mHandler = null;
766c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard    private Handler mUIHandler = null;
7711e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
786c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard    static class Origin {
7911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        String mOrigin = null;
8011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        long mQuota = 0;
816c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard        long mUsage = 0;
826c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard
836c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard        public Origin(String origin, long quota, long usage) {
846c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard            mOrigin = origin;
856c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard            mQuota = quota;
866c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard            mUsage = usage;
876c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard        }
8811e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
8911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        public Origin(String origin, long quota) {
9011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            mOrigin = origin;
9111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            mQuota = quota;
9211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        }
9311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
9411e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        public Origin(String origin) {
9511e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            mOrigin = origin;
9611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        }
9711e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
9811e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        public String getOrigin() {
9911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            return mOrigin;
10011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        }
10111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
10211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        public long getQuota() {
10311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            return mQuota;
10411e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        }
1056c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard
1066c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard        public long getUsage() {
1076c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard            return mUsage;
1086c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard        }
1096c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard    }
1106c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard
1116c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard    /**
1126c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard     * @hide
1136c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard     * Message handler, UI side
1146c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard     */
1156c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard    public void createUIHandler() {
1166c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard        if (mUIHandler == null) {
1176c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard            mUIHandler = new Handler() {
1186c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                @Override
1196c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                public void handleMessage(Message msg) {
1206c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                    switch (msg.what) {
1216c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                        case RETURN_ORIGINS: {
1226c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            Map values = (Map) msg.obj;
1236c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            Map origins = (Map) values.get(ORIGINS);
1246c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            ValueCallback<Map> callback = (ValueCallback<Map>) values.get(CALLBACK);
1256c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            callback.onReceiveValue(origins);
1266c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            } break;
1276c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard
1286c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                        case RETURN_USAGE_ORIGIN: {
1296c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            Map values = (Map) msg.obj;
1306c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            ValueCallback<Long> callback = (ValueCallback<Long>) values.get(CALLBACK);
1316c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            callback.onReceiveValue((Long)values.get(USAGE));
1326c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            } break;
1336c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard
1346c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                        case RETURN_QUOTA_ORIGIN: {
1356c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            Map values = (Map) msg.obj;
1366c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            ValueCallback<Long> callback = (ValueCallback<Long>) values.get(CALLBACK);
1376c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            callback.onReceiveValue((Long)values.get(QUOTA));
1386c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            } break;
1396c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                    }
1406c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                }
1416c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard            };
1426c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard        }
14311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    }
14411e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
14511e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    /**
14611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     * @hide
1476c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard     * Message handler, webcore side
14811e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     */
149e4b2d4dc7db426052d1dfebc40f6b64a001b6d73Steve Block    public synchronized void createHandler() {
15011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        if (mHandler == null) {
15111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            mHandler = new Handler() {
15211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                @Override
15311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                public void handleMessage(Message msg) {
15411e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                    switch (msg.what) {
15511e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                        case SET_QUOTA_ORIGIN: {
15611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                            Origin website = (Origin) msg.obj;
15711e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                            nativeSetQuotaForOrigin(website.getOrigin(),
15811e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                                                    website.getQuota());
15911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                            } break;
16011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
16111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                        case DELETE_ORIGIN: {
16211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                            Origin website = (Origin) msg.obj;
16311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                            nativeDeleteOrigin(website.getOrigin());
16411e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                            } break;
16511e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
16611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                        case DELETE_ALL:
167af9c77edbddfcf87a4dc17b95db84bf741674a9aAndrei Popescu                            nativeDeleteAllData();
16811e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                            break;
16911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
1706c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                        case GET_ORIGINS: {
1716c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            syncValues();
1726c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            ValueCallback callback = (ValueCallback) msg.obj;
1736c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            Map origins = new HashMap(mOrigins);
1746c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            Map values = new HashMap<String, Object>();
1756c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            values.put(CALLBACK, callback);
1766c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            values.put(ORIGINS, origins);
1776c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            postUIMessage(Message.obtain(null, RETURN_ORIGINS, values));
1786c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            } break;
1796c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard
1806c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                        case GET_USAGE_ORIGIN: {
1816c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            syncValues();
1826c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            Map values = (Map) msg.obj;
1836c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            String origin = (String) values.get(ORIGIN);
1846c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            ValueCallback callback = (ValueCallback) values.get(CALLBACK);
1856c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            Origin website = mOrigins.get(origin);
1866c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            Map retValues = new HashMap<String, Object>();
1876c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            retValues.put(CALLBACK, callback);
1886c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            if (website != null) {
1896c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                                long usage = website.getUsage();
1906c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                                retValues.put(USAGE, new Long(usage));
1916c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            }
1926c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            postUIMessage(Message.obtain(null, RETURN_USAGE_ORIGIN, retValues));
1936c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            } break;
1946c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard
1956c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                        case GET_QUOTA_ORIGIN: {
1966c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            syncValues();
1976c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            Map values = (Map) msg.obj;
1986c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            String origin = (String) values.get(ORIGIN);
1996c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            ValueCallback callback = (ValueCallback) values.get(CALLBACK);
2006c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            Origin website = mOrigins.get(origin);
2016c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            Map retValues = new HashMap<String, Object>();
2026c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            retValues.put(CALLBACK, callback);
2036c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            if (website != null) {
2046c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                                long quota = website.getQuota();
2056c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                                retValues.put(QUOTA, new Long(quota));
2066c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            }
2076c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            postUIMessage(Message.obtain(null, RETURN_QUOTA_ORIGIN, retValues));
2086c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                            } break;
2096c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard
21011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                        case UPDATE:
21111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                            syncValues();
21211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                            break;
21311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                    }
21411e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                }
21511e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            };
21611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        }
21711e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    }
21811e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
2196c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard    /*
2206c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard     * When calling getOrigins(), getUsageForOrigin() and getQuotaForOrigin(),
2216c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard     * we need to get the values from webcore, but we cannot block while doing so
2226c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard     * as we used to do, as this could result in a full deadlock (other webcore
2236c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard     * messages received while we are still blocked here, see http://b/2127737).
2246c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard     *
2256c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard     * We have to do everything asynchronously, by providing a callback function.
2266c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard     * We post a message on the webcore thread (mHandler) that will get the result
2276c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard     * from webcore, and we post it back on the UI thread (using mUIHandler).
2286c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard     * We can then use the callback function to return the value.
2296c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard     */
2306c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard
23111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    /**
23211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     * Returns a list of origins having a database
23311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     */
2346c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard    public void getOrigins(ValueCallback<Map> callback) {
2356c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard        if (callback != null) {
2366c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard            if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
2376c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                syncValues();
2386c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                callback.onReceiveValue(mOrigins);
2396c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard            } else {
2406c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard                postMessage(Message.obtain(null, GET_ORIGINS, callback));
24159e2ad93bf37c7ded44c033d38fe7c972e2f4118Andrei Popescu            }
24211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        }
2436c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard    }
2446c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard
2456c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard    /**
2466c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard     * Returns a list of origins having a database
2476c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard     * should only be called from WebViewCore.
2486c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard     */
2496c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard    Collection<Origin> getOriginsSync() {
2506c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard        if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
2516c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard            update();
2526c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard            return mOrigins.values();
2536c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard        }
2546c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard        return null;
25511e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    }
25611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
25711e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    /**
25811e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     * Returns the use for a given origin
25911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     */
2606c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard    public void getUsageForOrigin(String origin, ValueCallback<Long> callback) {
2616c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard        if (callback == null) {
2626c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard            return;
2636c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard        }
26411e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        if (origin == null) {
2656c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard            callback.onReceiveValue(null);
2666c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard            return;
26711e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        }
2686c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard        if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
2696c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard            syncValues();
2706c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard            Origin website = mOrigins.get(origin);
2716c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard            callback.onReceiveValue(new Long(website.getUsage()));
2726c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard        } else {
2736c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard            HashMap values = new HashMap<String, Object>();
2746c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard            values.put(ORIGIN, origin);
2756c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard            values.put(CALLBACK, callback);
2766c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard            postMessage(Message.obtain(null, GET_USAGE_ORIGIN, values));
27711e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        }
27811e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    }
27911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
28011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    /**
28111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     * Returns the quota for a given origin
28211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     */
2836c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard    public void getQuotaForOrigin(String origin, ValueCallback<Long> callback) {
2846c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard        if (callback == null) {
2856c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard            return;
2866c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard        }
28711e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        if (origin == null) {
2886c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard            callback.onReceiveValue(null);
2896c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard            return;
29011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        }
2916c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard        if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
2926c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard            syncValues();
2936c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard            Origin website = mOrigins.get(origin);
2946c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard            callback.onReceiveValue(new Long(website.getUsage()));
2956c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard        } else {
2966c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard            HashMap values = new HashMap<String, Object>();
2976c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard            values.put(ORIGIN, origin);
2986c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard            values.put(CALLBACK, callback);
2996c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard            postMessage(Message.obtain(null, GET_QUOTA_ORIGIN, values));
30011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        }
30111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    }
30211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
30311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    /**
30411e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     * Set the quota for a given origin
30511e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     */
30611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    public void setQuotaForOrigin(String origin, long quota) {
30711e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        if (origin != null) {
3085647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch            if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
3095647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch                nativeSetQuotaForOrigin(origin, quota);
3105647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch            } else {
3115647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch                postMessage(Message.obtain(null, SET_QUOTA_ORIGIN,
3125647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch                    new Origin(origin, quota)));
3135647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch            }
31411e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        }
31511e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    }
31611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
31711e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    /**
31811e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     * Delete a given origin
31911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     */
32011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    public void deleteOrigin(String origin) {
32111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        if (origin != null) {
3225647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch            if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
3235647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch                nativeDeleteOrigin(origin);
3245647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch            } else {
3255647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch                postMessage(Message.obtain(null, DELETE_ORIGIN,
3265647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch                    new Origin(origin)));
3275647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch            }
32811e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        }
32911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    }
33011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
33111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    /**
33211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     * Delete all databases
33311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     */
334af9c77edbddfcf87a4dc17b95db84bf741674a9aAndrei Popescu    public void deleteAllData() {
3355647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch        if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
336af9c77edbddfcf87a4dc17b95db84bf741674a9aAndrei Popescu            nativeDeleteAllData();
3375647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch        } else {
3385647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch            postMessage(Message.obtain(null, DELETE_ALL));
3395647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch        }
34011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    }
34111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
34211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    /**
343427efcca1988e3f424e363808e8fd0978f4e78d1Steve Block     * Sets the maximum size of the ApplicationCache.
344427efcca1988e3f424e363808e8fd0978f4e78d1Steve Block     * This should only ever be called on the WebKit thread.
345427efcca1988e3f424e363808e8fd0978f4e78d1Steve Block     * @hide Pending API council approval
346427efcca1988e3f424e363808e8fd0978f4e78d1Steve Block     */
347427efcca1988e3f424e363808e8fd0978f4e78d1Steve Block    public void setAppCacheMaximumSize(long size) {
348427efcca1988e3f424e363808e8fd0978f4e78d1Steve Block        nativeSetAppCacheMaximumSize(size);
349427efcca1988e3f424e363808e8fd0978f4e78d1Steve Block    }
350427efcca1988e3f424e363808e8fd0978f4e78d1Steve Block
351427efcca1988e3f424e363808e8fd0978f4e78d1Steve Block    /**
35211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     * Utility function to send a message to our handler
35311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     */
354e4b2d4dc7db426052d1dfebc40f6b64a001b6d73Steve Block    private synchronized void postMessage(Message msg) {
35511e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        if (mHandler != null) {
35611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            mHandler.sendMessage(msg);
35711e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        }
35811e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    }
35911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
36011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    /**
3616c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard     * Utility function to send a message to the handler on the UI thread
3626c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard     */
3636c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard    private void postUIMessage(Message msg) {
3646c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard        if (mUIHandler != null) {
3656c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard            mUIHandler.sendMessage(msg);
3666c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard        }
3676c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard    }
3686c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard
3696c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard    /**
37011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     * Get the global instance of WebStorage.
37111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     * @return A single instance of WebStorage.
37211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     */
37311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    public static WebStorage getInstance() {
37411e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard      if (sWebStorage == null) {
37511e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard          sWebStorage = new WebStorage();
37611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard      }
37711e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard      return sWebStorage;
37811e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    }
37911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
38011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    /**
38111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     * @hide
38211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     * Post a Sync request
38311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     */
38411e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    public void update() {
3855647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch        if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
3865647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch            syncValues();
3875647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch        } else {
3885647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch            postMessage(Message.obtain(null, UPDATE));
3895647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch        }
39011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    }
39111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
39211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    /**
39311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     * Run on the webcore thread
3949a56bb838c099a318d4f961f290d324ed5f1949dAndrei Popescu     * set the local values with the current ones
39511e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     */
39611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    private void syncValues() {
3976c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard        Set<String> tmp = nativeGetOrigins();
3986c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard        mOrigins = new HashMap<String, Origin>();
3996c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard        for (String origin : tmp) {
4006c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard            Origin website = new Origin(origin,
40198409704134c262fdaab47055f60b7e01a4bc0b2Andrei Popescu                                 nativeGetQuotaForOrigin(origin),
40298409704134c262fdaab47055f60b7e01a4bc0b2Andrei Popescu                                 nativeGetUsageForOrigin(origin));
4036c24b4d10223cb522e6bdbf0e334f61e672f4366Nicolas Roard            mOrigins.put(origin, website);
40411e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        }
40511e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    }
40611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
40711e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    // Native functions
408af9c77edbddfcf87a4dc17b95db84bf741674a9aAndrei Popescu    private static native Set nativeGetOrigins();
40911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    private static native long nativeGetUsageForOrigin(String origin);
41011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    private static native long nativeGetQuotaForOrigin(String origin);
41111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    private static native void nativeSetQuotaForOrigin(String origin, long quota);
41211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    private static native void nativeDeleteOrigin(String origin);
413af9c77edbddfcf87a4dc17b95db84bf741674a9aAndrei Popescu    private static native void nativeDeleteAllData();
414427efcca1988e3f424e363808e8fd0978f4e78d1Steve Block    private static native void nativeSetAppCacheMaximumSize(long size);
4157df1985e86635af006be3dfa65987d60e290b5deBen Murdoch}
416