WebStorage.java revision af9c77edbddfcf87a4dc17b95db84bf741674a9a
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
2311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roardimport java.util.concurrent.locks.Condition;
2411e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roardimport java.util.concurrent.locks.Lock;
2511e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roardimport java.util.concurrent.locks.ReentrantLock;
2611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roardimport java.util.HashMap;
27af9c77edbddfcf87a4dc17b95db84bf741674a9aAndrei Popescuimport java.util.HashSet;
28af9c77edbddfcf87a4dc17b95db84bf741674a9aAndrei Popescuimport java.util.Iterator;
29af9c77edbddfcf87a4dc17b95db84bf741674a9aAndrei Popescuimport java.util.Set;
3011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
317df1985e86635af006be3dfa65987d60e290b5deBen Murdoch/**
327df1985e86635af006be3dfa65987d60e290b5deBen Murdoch * Functionality for manipulating the webstorage databases.
337df1985e86635af006be3dfa65987d60e290b5deBen Murdoch */
347df1985e86635af006be3dfa65987d60e290b5deBen Murdochpublic final class WebStorage {
357df1985e86635af006be3dfa65987d60e290b5deBen Murdoch
367df1985e86635af006be3dfa65987d60e290b5deBen Murdoch    /**
377df1985e86635af006be3dfa65987d60e290b5deBen Murdoch     * Encapsulates a callback function to be executed when a new quota is made
387df1985e86635af006be3dfa65987d60e290b5deBen Murdoch     * available. We primarily want this to allow us to call back the sleeping
397df1985e86635af006be3dfa65987d60e290b5deBen Murdoch     * WebCore thread from outside the WebViewCore class (as the native call
407df1985e86635af006be3dfa65987d60e290b5deBen Murdoch     * is private). It is imperative that this the setDatabaseQuota method is
417df1985e86635af006be3dfa65987d60e290b5deBen Murdoch     * executed once a decision to either allow or deny new quota is made,
427df1985e86635af006be3dfa65987d60e290b5deBen Murdoch     * otherwise the WebCore thread will remain asleep.
437df1985e86635af006be3dfa65987d60e290b5deBen Murdoch     */
447df1985e86635af006be3dfa65987d60e290b5deBen Murdoch    public interface QuotaUpdater {
457df1985e86635af006be3dfa65987d60e290b5deBen Murdoch        public void updateQuota(long newQuota);
467df1985e86635af006be3dfa65987d60e290b5deBen Murdoch    };
4711e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
4811e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    // Log tag
4911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    private static final String TAG = "webstorage";
5011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
5111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    // Global instance of a WebStorage
5211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    private static WebStorage sWebStorage;
5311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
5411e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    // We keep a copy of the origins, quotas and usages
5511e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    // that we protect via a lock and update in syncValues()
5611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    private static Lock mLock = new ReentrantLock();
5711e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    private static Condition mCacheUpdated = mLock.newCondition();
5811e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
5911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    // Message ids
6011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    static final int UPDATE = 0;
6111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    static final int SET_QUOTA_ORIGIN = 1;
6211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    static final int DELETE_ORIGIN = 2;
6311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    static final int DELETE_ALL = 3;
6411e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
65af9c77edbddfcf87a4dc17b95db84bf741674a9aAndrei Popescu    private Set <String> mOrigins;
6611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    private HashMap <String, Long> mQuotas = new HashMap<String, Long>();
6711e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    private HashMap <String, Long> mUsages = new HashMap<String, Long>();
6811e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
6911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    private Handler mHandler = null;
7011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
7111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    private class Origin {
7211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        String mOrigin = null;
7311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        long mQuota = 0;
7411e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
7511e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        public Origin(String origin, long quota) {
7611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            mOrigin = origin;
7711e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            mQuota = quota;
7811e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        }
7911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
8011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        public Origin(String origin) {
8111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            mOrigin = origin;
8211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        }
8311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
8411e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        public String getOrigin() {
8511e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            return mOrigin;
8611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        }
8711e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
8811e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        public long getQuota() {
8911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            return mQuota;
9011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        }
9111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    }
9211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
9311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    /**
9411e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     * @hide
9511e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     * Message handler
9611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     */
9711e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    public void createHandler() {
9811e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        if (mHandler == null) {
9911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            mHandler = new Handler() {
10011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                @Override
10111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                public void handleMessage(Message msg) {
10211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                    switch (msg.what) {
10311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                        case SET_QUOTA_ORIGIN: {
10411e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                            Origin website = (Origin) msg.obj;
10511e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                            nativeSetQuotaForOrigin(website.getOrigin(),
10611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                                                    website.getQuota());
10711e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                            syncValues();
10811e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                            } break;
10911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
11011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                        case DELETE_ORIGIN: {
11111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                            Origin website = (Origin) msg.obj;
11211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                            nativeDeleteOrigin(website.getOrigin());
11311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                            syncValues();
11411e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                            } break;
11511e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
11611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                        case DELETE_ALL:
117af9c77edbddfcf87a4dc17b95db84bf741674a9aAndrei Popescu                            nativeDeleteAllData();
11811e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                            syncValues();
11911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                            break;
12011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
12111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                        case UPDATE:
12211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                            syncValues();
12311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                            break;
12411e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                    }
12511e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                }
12611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            };
12711e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        }
12811e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    }
12911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
13011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    /**
13111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     * @hide
13211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     * Returns a list of origins having a database
13311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     */
134af9c77edbddfcf87a4dc17b95db84bf741674a9aAndrei Popescu    public Set getOrigins() {
135af9c77edbddfcf87a4dc17b95db84bf741674a9aAndrei Popescu        Set ret = null;
13611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        mLock.lock();
13711e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        try {
13811e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            update();
13911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            mCacheUpdated.await();
14011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            ret = mOrigins;
14111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        } catch (InterruptedException e) {
14211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            Log.e(TAG, "Exception while waiting on the updated origins", e);
14311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        } finally {
14411e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            mLock.unlock();
14511e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        }
14611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        return ret;
14711e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    }
14811e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
14911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    /**
15011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     * @hide
15111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     * Returns the use for a given origin
15211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     */
15311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    public long getUsageForOrigin(String origin) {
15411e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        long ret = 0;
15511e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        if (origin == null) {
15611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard          return ret;
15711e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        }
15811e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        mLock.lock();
15911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        try {
16011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            update();
16111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            mCacheUpdated.await();
16211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            Long usage = mUsages.get(origin);
16311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            if (usage != null) {
16411e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                ret = usage.longValue();
16511e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            }
16611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        } catch (InterruptedException e) {
16711e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            Log.e(TAG, "Exception while waiting on the updated origins", e);
16811e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        } finally {
16911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            mLock.unlock();
17011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        }
17111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        return ret;
17211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    }
17311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
17411e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    /**
17511e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     * @hide
17611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     * Returns the quota for a given origin
17711e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     */
17811e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    public long getQuotaForOrigin(String origin) {
17911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        long ret = 0;
18011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        if (origin == null) {
18111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard          return ret;
18211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        }
18311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        mLock.lock();
18411e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        try {
18511e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            update();
18611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            mCacheUpdated.await();
18711e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            Long quota = mQuotas.get(origin);
18811e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            if (quota != null) {
18911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard                ret = quota.longValue();
19011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            }
19111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        } catch (InterruptedException e) {
19211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            Log.e(TAG, "Exception while waiting on the updated origins", e);
19311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        } finally {
19411e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            mLock.unlock();
19511e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        }
19611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        return ret;
19711e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    }
19811e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
19911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    /**
20011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     * @hide
20111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     * Set the quota for a given origin
20211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     */
20311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    public void setQuotaForOrigin(String origin, long quota) {
20411e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        if (origin != null) {
2055647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch            if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
2065647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch                nativeSetQuotaForOrigin(origin, quota);
2075647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch                syncValues();
2085647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch            } else {
2095647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch                postMessage(Message.obtain(null, SET_QUOTA_ORIGIN,
2105647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch                    new Origin(origin, quota)));
2115647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch            }
21211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        }
21311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    }
21411e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
21511e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    /**
21611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     * @hide
21711e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     * Delete a given origin
21811e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     */
21911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    public void deleteOrigin(String origin) {
22011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        if (origin != null) {
2215647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch            if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
2225647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch                nativeDeleteOrigin(origin);
2235647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch                syncValues();
2245647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch            } else {
2255647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch                postMessage(Message.obtain(null, DELETE_ORIGIN,
2265647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch                    new Origin(origin)));
2275647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch            }
22811e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        }
22911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    }
23011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
23111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    /**
23211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     * @hide
23311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     * Delete all databases
23411e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     */
235af9c77edbddfcf87a4dc17b95db84bf741674a9aAndrei Popescu    public void deleteAllData() {
2365647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch        if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
237af9c77edbddfcf87a4dc17b95db84bf741674a9aAndrei Popescu            nativeDeleteAllData();
2385647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch            syncValues();
2395647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch        } else {
2405647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch            postMessage(Message.obtain(null, DELETE_ALL));
2415647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch        }
24211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    }
24311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
24411e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    /**
24511e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     * Utility function to send a message to our handler
24611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     */
24711e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    private void postMessage(Message msg) {
24811e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        if (mHandler != null) {
24911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            mHandler.sendMessage(msg);
25011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        }
25111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    }
25211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
25311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    /**
25411e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     * @hide
25511e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     * Get the global instance of WebStorage.
25611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     * @return A single instance of WebStorage.
25711e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     */
25811e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    public static WebStorage getInstance() {
25911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard      if (sWebStorage == null) {
26011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard          sWebStorage = new WebStorage();
26111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard      }
26211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard      return sWebStorage;
26311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    }
26411e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
26511e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    /**
26611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     * @hide
26711e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     * Post a Sync request
26811e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     */
26911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    public void update() {
2705647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch        if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
2715647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch            syncValues();
2725647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch        } else {
2735647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch            postMessage(Message.obtain(null, UPDATE));
2745647bb3cc21428dd5242255323dff13c71a3343dBen Murdoch        }
27511e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    }
27611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
27711e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    /**
27811e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     * Run on the webcore thread
27911e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     * sync the local cached values with the real ones
28011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard     */
28111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    private void syncValues() {
28211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        mLock.lock();
283af9c77edbddfcf87a4dc17b95db84bf741674a9aAndrei Popescu        Set tmp = nativeGetOrigins();
284af9c77edbddfcf87a4dc17b95db84bf741674a9aAndrei Popescu        mOrigins = new HashSet<String>();
28511e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        mQuotas.clear();
28611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        mUsages.clear();
287af9c77edbddfcf87a4dc17b95db84bf741674a9aAndrei Popescu        Iterator<String> iter = tmp.iterator();
288af9c77edbddfcf87a4dc17b95db84bf741674a9aAndrei Popescu        while (iter.hasNext()) {
289af9c77edbddfcf87a4dc17b95db84bf741674a9aAndrei Popescu            String origin = iter.next();
29011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            mOrigins.add(origin);
29111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            mQuotas.put(origin, new Long(nativeGetQuotaForOrigin(origin)));
29211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard            mUsages.put(origin, new Long(nativeGetUsageForOrigin(origin)));
29311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        }
29411e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        mCacheUpdated.signal();
29511e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard        mLock.unlock();
29611e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    }
29711e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard
29811e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    // Native functions
299af9c77edbddfcf87a4dc17b95db84bf741674a9aAndrei Popescu    private static native Set nativeGetOrigins();
30011e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    private static native long nativeGetUsageForOrigin(String origin);
30111e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    private static native long nativeGetQuotaForOrigin(String origin);
30211e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    private static native void nativeSetQuotaForOrigin(String origin, long quota);
30311e8fe5a7208c9cd6afc2a0373761ae506d7707fNicolas Roard    private static native void nativeDeleteOrigin(String origin);
304af9c77edbddfcf87a4dc17b95db84bf741674a9aAndrei Popescu    private static native void nativeDeleteAllData();
3057df1985e86635af006be3dfa65987d60e290b5deBen Murdoch}
306