From 59e2ad93bf37c7ded44c033d38fe7c972e2f4118 Mon Sep 17 00:00:00 2001 From: Andrei Popescu Date: Tue, 28 Jul 2009 13:38:06 +0100 Subject: [PATCH] Wire in the AppCache out-of-space callback --- api/current.xml | 4 ++ core/java/android/webkit/CallbackProxy.java | 57 +++++++++++++++++-- core/java/android/webkit/WebChromeClient.java | 19 ++++++- core/java/android/webkit/WebStorage.java | 21 +++++-- core/java/android/webkit/WebViewCore.java | 44 +++++++++++--- .../dumprendertree/TestShellActivity.java | 2 +- 6 files changed, 129 insertions(+), 18 deletions(-) diff --git a/api/current.xml b/api/current.xml index 4dabd6f55db85..3c79b907cb875 100644 --- a/api/current.xml +++ b/api/current.xml @@ -163330,6 +163330,8 @@ + + @@ -164990,6 +164992,8 @@ + + diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java index 3b67fb6fc0ade..a6d03470fbad4 100644 --- a/core/java/android/webkit/CallbackProxy.java +++ b/core/java/android/webkit/CallbackProxy.java @@ -99,8 +99,9 @@ class CallbackProxy extends Handler { private static final int RECEIVED_CERTIFICATE = 124; private static final int SWITCH_OUT_HISTORY = 125; private static final int EXCEEDED_DATABASE_QUOTA = 126; - private static final int JS_TIMEOUT = 127; - private static final int ADD_MESSAGE_TO_CONSOLE = 128; + private static final int REACHED_APPCACHE_MAXSIZE = 127; + private static final int JS_TIMEOUT = 128; + private static final int ADD_MESSAGE_TO_CONSOLE = 129; // Message triggered by the client to resume execution private static final int NOTIFY = 200; @@ -410,11 +411,30 @@ class CallbackProxy extends Handler { String url = (String) map.get("url"); long currentQuota = ((Long) map.get("currentQuota")).longValue(); + long totalUsedQuota = + ((Long) map.get("totalUsedQuota")).longValue(); WebStorage.QuotaUpdater quotaUpdater = (WebStorage.QuotaUpdater) map.get("quotaUpdater"); mWebChromeClient.onExceededDatabaseQuota(url, - databaseIdentifier, currentQuota, quotaUpdater); + databaseIdentifier, currentQuota, totalUsedQuota, + quotaUpdater); + } + break; + + case REACHED_APPCACHE_MAXSIZE: + if (mWebChromeClient != null) { + HashMap map = + (HashMap) msg.obj; + long spaceNeeded = + ((Long) map.get("spaceNeeded")).longValue(); + long totalUsedQuota = + ((Long) map.get("totalUsedQuota")).longValue(); + WebStorage.QuotaUpdater quotaUpdater = + (WebStorage.QuotaUpdater) map.get("quotaUpdater"); + + mWebChromeClient.onReachedMaxAppCacheSize(spaceNeeded, + totalUsedQuota, quotaUpdater); } break; @@ -1120,13 +1140,14 @@ class CallbackProxy extends Handler { * @param databaseIdentifier The identifier of the database that the * transaction that caused the overflow was running on. * @param currentQuota The current quota the origin is allowed. + * @param totalUsedQuota is the sum of all origins' quota. * @param quotaUpdater An instance of a class encapsulating a callback * to WebViewCore to run when the decision to allow or deny more * quota has been made. */ public void onExceededDatabaseQuota( String url, String databaseIdentifier, long currentQuota, - WebStorage.QuotaUpdater quotaUpdater) { + long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater) { if (mWebChromeClient == null) { quotaUpdater.updateQuota(currentQuota); return; @@ -1137,11 +1158,39 @@ class CallbackProxy extends Handler { map.put("databaseIdentifier", databaseIdentifier); map.put("url", url); map.put("currentQuota", currentQuota); + map.put("totalUsedQuota", totalUsedQuota); map.put("quotaUpdater", quotaUpdater); exceededQuota.obj = map; sendMessage(exceededQuota); } + /** + * Called by WebViewCore to inform the Java side that the appcache has + * exceeded its max size. + * @param spaceNeeded is the amount of disk space that would be needed + * in order for the last appcache operation to succeed. + * @param totalUsedQuota is the sum of all origins' quota. + * @param quotaUpdater An instance of a class encapsulating a callback + * to WebViewCore to run when the decision to allow or deny a bigger + * app cache size has been made. + * @hide pending API council approval. + */ + public void onReachedMaxAppCacheSize(long spaceNeeded, + long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater) { + if (mWebChromeClient == null) { + quotaUpdater.updateQuota(0); + return; + } + + Message msg = obtainMessage(REACHED_APPCACHE_MAXSIZE); + HashMap map = new HashMap(); + map.put("spaceNeeded", spaceNeeded); + map.put("totalUsedQuota", totalUsedQuota); + map.put("quotaUpdater", quotaUpdater); + msg.obj = map; + sendMessage(msg); + } + /** * Called by WebViewCore when we have a message to be added to the JavaScript * error console. Sends a message to the Java side with the details. diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java index dd43b8b9f06c9..fa78777cd9a3a 100644 --- a/core/java/android/webkit/WebChromeClient.java +++ b/core/java/android/webkit/WebChromeClient.java @@ -198,17 +198,34 @@ public class WebChromeClient { * @param databaseIdentifier The identifier of the database that caused the * quota overflow. * @param currentQuota The current quota for the origin. + * @param totalUsedQuota is the sum of all origins' quota. * @param quotaUpdater A callback to inform the WebCore thread that a new * quota is available. This callback must always be executed at some * point to ensure that the sleeping WebCore thread is woken up. */ public void onExceededDatabaseQuota(String url, String databaseIdentifier, - long currentQuota, WebStorage.QuotaUpdater quotaUpdater) { + long currentQuota, long totalUsedQuota, + WebStorage.QuotaUpdater quotaUpdater) { // This default implementation passes the current quota back to WebCore. // WebCore will interpret this that new quota was declined. quotaUpdater.updateQuota(currentQuota); } + /** + * Tell the client that the Application Cache has exceeded its max size. + * @param spaceNeeded is the amount of disk space that would be needed + * in order for the last appcache operation to succeed. + * @param totalUsedQuota is the sum of all origins' quota. + * @param quotaUpdater A callback to inform the WebCore thread that a new + * app cache size is available. This callback must always be executed at + * some point to ensure that the sleeping WebCore thread is woken up. + * @hide pending API council approval. + */ + public void onReachedMaxAppCacheSize(long spaceNeeded, long totalUsedQuota, + WebStorage.QuotaUpdater quotaUpdater) { + quotaUpdater.updateQuota(0); + } + /** * Tell the client that a JavaScript execution timeout has occured. And the * client may decide whether or not to interrupt the execution. If the diff --git a/core/java/android/webkit/WebStorage.java b/core/java/android/webkit/WebStorage.java index 1a60dbaec6697..c3b359eb64e2f 100644 --- a/core/java/android/webkit/WebStorage.java +++ b/core/java/android/webkit/WebStorage.java @@ -55,7 +55,8 @@ public final class WebStorage { // that we protect via a lock and update in syncValues(). // This is needed to transfer this data across threads. private static Lock mLock = new ReentrantLock(); - private static Condition mCacheUpdated = mLock.newCondition(); + private static Condition mUpdateCondition = mLock.newCondition(); + private static boolean mUpdateAvailable; // Message ids static final int UPDATE = 0; @@ -133,8 +134,11 @@ public final class WebStorage { Set ret = null; mLock.lock(); try { + mUpdateAvailable = false; update(); - mCacheUpdated.await(); + while (!mUpdateAvailable) { + mUpdateCondition.await(); + } ret = mOrigins; } catch (InterruptedException e) { Log.e(TAG, "Exception while waiting on the updated origins", e); @@ -155,8 +159,11 @@ public final class WebStorage { } mLock.lock(); try { + mUpdateAvailable = false; update(); - mCacheUpdated.await(); + while (!mUpdateAvailable) { + mUpdateCondition.await(); + } Long usage = mUsages.get(origin); if (usage != null) { ret = usage.longValue(); @@ -180,8 +187,11 @@ public final class WebStorage { } mLock.lock(); try { + mUpdateAvailable = false; update(); - mCacheUpdated.await(); + while (!mUpdateAvailable) { + mUpdateCondition.await(); + } Long quota = mQuotas.get(origin); if (quota != null) { ret = quota.longValue(); @@ -286,7 +296,8 @@ public final class WebStorage { mQuotas.put(origin, new Long(nativeGetQuotaForOrigin(origin))); mUsages.put(origin, new Long(nativeGetUsageForOrigin(origin))); } - mCacheUpdated.signal(); + mUpdateAvailable = true; + mUpdateCondition.signal(); mLock.unlock(); } diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java index 36c5f0c87c31e..85867b485d8d3 100644 --- a/core/java/android/webkit/WebViewCore.java +++ b/core/java/android/webkit/WebViewCore.java @@ -36,6 +36,7 @@ import android.view.SurfaceHolder; import android.view.SurfaceView; import java.util.ArrayList; +import java.util.Set; import junit.framework.Assert; @@ -247,7 +248,7 @@ final class WebViewCore { } /** - * Notify the user that the origin has exceeded it's database quota. + * Notify the browser that the origin has exceeded it's database quota. * @param url The URL that caused the overflow. * @param databaseIdentifier The identifier of the database. * @param currentQuota The current quota for the origin. @@ -260,13 +261,27 @@ final class WebViewCore { // awaken the sleeping webcore thread when a decision from the // client to allow or deny quota is available. mCallbackProxy.onExceededDatabaseQuota(url, databaseIdentifier, - currentQuota, new WebStorage.QuotaUpdater() { + currentQuota, getUsedQuota(), new WebStorage.QuotaUpdater() { public void updateQuota(long quota) { - nativeSetDatabaseQuota(quota); + nativeSetNewStorageLimit(quota); } }); } + /** + * Notify the browser that the appcache has exceeded its max size. + * @param spaceNeeded is the amount of disk space that would be needed + * in order for the last appcache operation to succeed. + */ + protected void reachedMaxAppCacheSize(long spaceNeeded) { + mCallbackProxy.onReachedMaxAppCacheSize(spaceNeeded, getUsedQuota(), + new WebStorage.QuotaUpdater() { + public void updateQuota(long quota) { + nativeSetNewStorageLimit(quota); + } + }); + } + /** * Invoke a javascript confirm dialog. * @param message The message displayed in the dialog. @@ -440,11 +455,11 @@ final class WebViewCore { /* * Inform webcore that the user has decided whether to allow or deny new - * quota for the current origin and that the main thread should wake up - * now. - * @param quota The new quota. + * quota for the current origin or more space for the app cache, and that + * the main thread should wake up now. + * @param limit Is the new quota for an origin or new app cache max size. */ - private native void nativeSetDatabaseQuota(long quota); + private native void nativeSetNewStorageLimit(long limit); private native void nativeUpdatePluginState(int framePtr, int nodePtr, int state); @@ -1395,6 +1410,21 @@ final class WebViewCore { } } + // Utility method for exceededDatabaseQuota and reachedMaxAppCacheSize + // callbacks. Computes the sum of database quota for all origins. + private long getUsedQuota() { + WebStorage webStorage = WebStorage.getInstance(); + Set origins = webStorage.getOrigins(); + if (origins == null) { + return 0; + } + long usedQuota = 0; + for (String origin : origins) { + usedQuota += webStorage.getQuotaForOrigin(origin); + } + return usedQuota; + } + // Used to avoid posting more than one draw message. private boolean mDrawIsScheduled; diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java index 4483a8efb261f..30e1d99bdac26 100644 --- a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java @@ -538,7 +538,7 @@ public class TestShellActivity extends Activity implements LayoutTestController @Override public void onExceededDatabaseQuota(String url_str, - String databaseIdentifier, long currentQuota, + String databaseIdentifier, long currentQuota, long totalUsedQuota, WebStorage.QuotaUpdater callback) { if (mDumpDatabaseCallbacks) { if (mDatabaseCallbackStrings == null) {