diff options
-rw-r--r-- | core/java/android/webkit/WebSettings.java | 22 | ||||
-rw-r--r-- | core/java/android/webkit/WebStorage.java | 248 | ||||
-rw-r--r-- | core/java/android/webkit/WebViewCore.java | 4 |
3 files changed, 274 insertions, 0 deletions
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java index 5a2cd26..883aa28 100644 --- a/core/java/android/webkit/WebSettings.java +++ b/core/java/android/webkit/WebSettings.java @@ -141,6 +141,7 @@ public class WebSettings { private boolean mBlockNetworkLoads; private boolean mJavaScriptEnabled = false; private boolean mPluginsEnabled = false; + private long mWebStorageDefaultQuota = 0; private boolean mJavaScriptCanOpenWindowsAutomatically = false; private boolean mUseDoubleTree = false; private boolean mUseWideViewport = false; @@ -903,6 +904,18 @@ public class WebSettings { } /** + * @hide + * Set the default quota for WebStorage DBs + * @param quota the default quota in bytes + */ + public synchronized void setWebStorageDefaultQuota(long quota) { + if (mWebStorageDefaultQuota != quota) { + mWebStorageDefaultQuota = quota; + postSync(); + } + } + + /** * Set the path to where database storage API databases should be saved. * This will update WebCore when the Sync runs in the C++ side. * @param databasePath String path to the directory where databases should @@ -996,6 +1009,15 @@ public class WebSettings { } /** + * @hide + * Return the default quota for WebStorage DBs + * @return the default quota in bytes + */ + public synchronized long getWebStorageDefaultQuota() { + return mWebStorageDefaultQuota; + } + + /** * Tell javascript to open windows automatically. This applies to the * javascript function window.open(). * @param flag True if javascript can open windows automatically. diff --git a/core/java/android/webkit/WebStorage.java b/core/java/android/webkit/WebStorage.java index a0faf76..f27360d 100644 --- a/core/java/android/webkit/WebStorage.java +++ b/core/java/android/webkit/WebStorage.java @@ -16,6 +16,16 @@ 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. */ @@ -32,4 +42,242 @@ public final class WebStorage { 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(); } diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java index b364952..be405dd 100644 --- a/core/java/android/webkit/WebViewCore.java +++ b/core/java/android/webkit/WebViewCore.java @@ -143,6 +143,8 @@ final class WebViewCore { // The WebIconDatabase needs to be initialized within the UI thread so // just request the instance here. WebIconDatabase.getInstance(); + // Create the WebStorage singleton + WebStorage.getInstance(); // Send a message to initialize the WebViewCore. Message init = sWebCoreHandler.obtainMessage( WebCoreThread.INITIALIZE, this); @@ -162,6 +164,8 @@ final class WebViewCore { mSettings.syncSettingsAndCreateHandler(mBrowserFrame); // Create the handler and transfer messages for the IconDatabase WebIconDatabase.getInstance().createHandler(); + // Create the handler for WebStorage + WebStorage.getInstance().createHandler(); // The transferMessages call will transfer all pending messages to the // WebCore thread handler. mEventHub.transferMessages(); |