diff options
Diffstat (limited to 'core/java/android/webkit/WebStorage.java')
-rw-r--r-- | core/java/android/webkit/WebStorage.java | 283 |
1 files changed, 283 insertions, 0 deletions
diff --git a/core/java/android/webkit/WebStorage.java b/core/java/android/webkit/WebStorage.java new file mode 100644 index 0000000..f27360d --- /dev/null +++ b/core/java/android/webkit/WebStorage.java @@ -0,0 +1,283 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.webkit; + +import android.os.Handler; +import android.os.Message; +import android.util.Log; + +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; +import java.util.HashMap; +import java.util.Vector; + +/** + * Functionality for manipulating the webstorage databases. + */ +public final class WebStorage { + + /** + * Encapsulates a callback function to be executed when a new quota is made + * available. We primarily want this to allow us to call back the sleeping + * WebCore thread from outside the WebViewCore class (as the native call + * is private). It is imperative that this the setDatabaseQuota method is + * executed once a decision to either allow or deny new quota is made, + * otherwise the WebCore thread will remain asleep. + */ + public interface QuotaUpdater { + public void updateQuota(long newQuota); + }; + + // Log tag + private static final String TAG = "webstorage"; + + // Global instance of a WebStorage + private static WebStorage sWebStorage; + + // We keep a copy of the origins, quotas and usages + // that we protect via a lock and update in syncValues() + private static Lock mLock = new ReentrantLock(); + private static Condition mCacheUpdated = mLock.newCondition(); + + // Message ids + static final int UPDATE = 0; + static final int SET_QUOTA_ORIGIN = 1; + static final int DELETE_ORIGIN = 2; + static final int DELETE_ALL = 3; + + private Vector <String> mOrigins; + private HashMap <String, Long> mQuotas = new HashMap<String, Long>(); + private HashMap <String, Long> mUsages = new HashMap<String, Long>(); + + private Handler mHandler = null; + + private class Origin { + String mOrigin = null; + long mQuota = 0; + + public Origin(String origin, long quota) { + mOrigin = origin; + mQuota = quota; + } + + public Origin(String origin) { + mOrigin = origin; + } + + public String getOrigin() { + return mOrigin; + } + + public long getQuota() { + return mQuota; + } + } + + /** + * @hide + * Message handler + */ + public void createHandler() { + if (mHandler == null) { + mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case SET_QUOTA_ORIGIN: { + Origin website = (Origin) msg.obj; + nativeSetQuotaForOrigin(website.getOrigin(), + website.getQuota()); + syncValues(); + } break; + + case DELETE_ORIGIN: { + Origin website = (Origin) msg.obj; + nativeDeleteOrigin(website.getOrigin()); + syncValues(); + } break; + + case DELETE_ALL: + nativeDeleteAllDatabases(); + syncValues(); + break; + + case UPDATE: + syncValues(); + break; + } + } + }; + } + } + + /** + * @hide + * Returns a list of origins having a database + */ + public Vector getOrigins() { + Vector ret = null; + mLock.lock(); + try { + update(); + mCacheUpdated.await(); + ret = mOrigins; + } catch (InterruptedException e) { + Log.e(TAG, "Exception while waiting on the updated origins", e); + } finally { + mLock.unlock(); + } + return ret; + } + + /** + * @hide + * Returns the use for a given origin + */ + public long getUsageForOrigin(String origin) { + long ret = 0; + if (origin == null) { + return ret; + } + mLock.lock(); + try { + update(); + mCacheUpdated.await(); + Long usage = mUsages.get(origin); + if (usage != null) { + ret = usage.longValue(); + } + } catch (InterruptedException e) { + Log.e(TAG, "Exception while waiting on the updated origins", e); + } finally { + mLock.unlock(); + } + return ret; + } + + /** + * @hide + * Returns the quota for a given origin + */ + public long getQuotaForOrigin(String origin) { + long ret = 0; + if (origin == null) { + return ret; + } + mLock.lock(); + try { + update(); + mCacheUpdated.await(); + Long quota = mQuotas.get(origin); + if (quota != null) { + ret = quota.longValue(); + } + } catch (InterruptedException e) { + Log.e(TAG, "Exception while waiting on the updated origins", e); + } finally { + mLock.unlock(); + } + return ret; + } + + /** + * @hide + * Set the quota for a given origin + */ + public void setQuotaForOrigin(String origin, long quota) { + if (origin != null) { + postMessage(Message.obtain(null, SET_QUOTA_ORIGIN, + new Origin(origin, quota))); + } + } + + /** + * @hide + * Delete a given origin + */ + public void deleteOrigin(String origin) { + if (origin != null) { + postMessage(Message.obtain(null, DELETE_ORIGIN, + new Origin(origin))); + } + } + + /** + * @hide + * Delete all databases + */ + public void deleteAllDatabases() { + postMessage(Message.obtain(null, DELETE_ALL)); + } + + /** + * Utility function to send a message to our handler + */ + private void postMessage(Message msg) { + if (mHandler != null) { + mHandler.sendMessage(msg); + } + } + + /** + * @hide + * Get the global instance of WebStorage. + * @return A single instance of WebStorage. + */ + public static WebStorage getInstance() { + if (sWebStorage == null) { + sWebStorage = new WebStorage(); + } + return sWebStorage; + } + + /** + * @hide + * Post a Sync request + */ + public void update() { + postMessage(Message.obtain(null, UPDATE)); + } + + /** + * Run on the webcore thread + * sync the local cached values with the real ones + */ + private void syncValues() { + mLock.lock(); + Vector tmp = nativeGetOrigins(); + mOrigins = new Vector<String>(); + mQuotas.clear(); + mUsages.clear(); + for (int i = 0; i < tmp.size(); i++) { + String origin = (String) tmp.get(i); + mOrigins.add(origin); + mQuotas.put(origin, new Long(nativeGetQuotaForOrigin(origin))); + mUsages.put(origin, new Long(nativeGetUsageForOrigin(origin))); + } + mCacheUpdated.signal(); + mLock.unlock(); + } + + // Native functions + private static native Vector nativeGetOrigins(); + private static native long nativeGetUsageForOrigin(String origin); + private static native long nativeGetQuotaForOrigin(String origin); + private static native void nativeSetQuotaForOrigin(String origin, long quota); + private static native void nativeDeleteOrigin(String origin); + private static native void nativeDeleteAllDatabases(); +} |