Merge change 8984

* changes:
  Fix issue 2019031: Volume changes have no effect.
diff --git a/api/current.xml b/api/current.xml
index 4dabd6f..3c79b90 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -163330,6 +163330,8 @@
 </parameter>
 <parameter name="currentQuota" type="long">
 </parameter>
+<parameter name="totalUsedQuota" type="long">
+</parameter>
 <parameter name="quotaUpdater" type="android.webkit.WebStorage.QuotaUpdater">
 </parameter>
 </method>
@@ -164990,6 +164992,8 @@
 </parameter>
 <parameter name="currentQuota" type="long">
 </parameter>
+<parameter name="totalUsedQuota" type="long">
+</parameter>
 <parameter name="quotaUpdater" type="android.webkit.WebStorage.QuotaUpdater">
 </parameter>
 </method>
diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java
index 3b67fb6..ed77ce8 100644
--- a/core/java/android/webkit/CallbackProxy.java
+++ b/core/java/android/webkit/CallbackProxy.java
@@ -72,38 +72,41 @@
     private final Context mContext;
 
     // Message Ids
-    private static final int PAGE_STARTED              = 100;
-    private static final int RECEIVED_ICON             = 101;
-    private static final int RECEIVED_TITLE            = 102;
-    private static final int OVERRIDE_URL              = 103;
-    private static final int AUTH_REQUEST              = 104;
-    private static final int SSL_ERROR                 = 105;
-    private static final int PROGRESS                  = 106;
-    private static final int UPDATE_VISITED            = 107;
-    private static final int LOAD_RESOURCE             = 108;
-    private static final int CREATE_WINDOW             = 109;
-    private static final int CLOSE_WINDOW              = 110;
-    private static final int SAVE_PASSWORD             = 111;
-    private static final int JS_ALERT                  = 112;
-    private static final int JS_CONFIRM                = 113;
-    private static final int JS_PROMPT                 = 114;
-    private static final int JS_UNLOAD                 = 115;
-    private static final int ASYNC_KEYEVENTS           = 116;
-    private static final int TOO_MANY_REDIRECTS        = 117;
-    private static final int DOWNLOAD_FILE             = 118;
-    private static final int REPORT_ERROR              = 119;
-    private static final int RESEND_POST_DATA          = 120;
-    private static final int PAGE_FINISHED             = 121;
-    private static final int REQUEST_FOCUS             = 122;
-    private static final int SCALE_CHANGED             = 123;
-    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 PAGE_STARTED                        = 100;
+    private static final int RECEIVED_ICON                       = 101;
+    private static final int RECEIVED_TITLE                      = 102;
+    private static final int OVERRIDE_URL                        = 103;
+    private static final int AUTH_REQUEST                        = 104;
+    private static final int SSL_ERROR                           = 105;
+    private static final int PROGRESS                            = 106;
+    private static final int UPDATE_VISITED                      = 107;
+    private static final int LOAD_RESOURCE                       = 108;
+    private static final int CREATE_WINDOW                       = 109;
+    private static final int CLOSE_WINDOW                        = 110;
+    private static final int SAVE_PASSWORD                       = 111;
+    private static final int JS_ALERT                            = 112;
+    private static final int JS_CONFIRM                          = 113;
+    private static final int JS_PROMPT                           = 114;
+    private static final int JS_UNLOAD                           = 115;
+    private static final int ASYNC_KEYEVENTS                     = 116;
+    private static final int TOO_MANY_REDIRECTS                  = 117;
+    private static final int DOWNLOAD_FILE                       = 118;
+    private static final int REPORT_ERROR                        = 119;
+    private static final int RESEND_POST_DATA                    = 120;
+    private static final int PAGE_FINISHED                       = 121;
+    private static final int REQUEST_FOCUS                       = 122;
+    private static final int SCALE_CHANGED                       = 123;
+    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 REACHED_APPCACHE_MAXSIZE            = 127;
+    private static final int JS_TIMEOUT                          = 128;
+    private static final int ADD_MESSAGE_TO_CONSOLE              = 129;
+    private static final int GEOLOCATION_PERMISSIONS_SHOW_PROMPT = 130;
+    private static final int GEOLOCATION_PERMISSIONS_HIDE_PROMPT = 131;
 
     // Message triggered by the client to resume execution
-    private static final int NOTIFY                    = 200;
+    private static final int NOTIFY                              = 200;
 
     // Result transportation object for returning results across thread
     // boundaries.
@@ -410,11 +413,49 @@
                     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<String, Object> map =
+                            (HashMap<String, Object>) 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;
+
+            case GEOLOCATION_PERMISSIONS_SHOW_PROMPT:
+                if (mWebChromeClient != null) {
+                    HashMap<String, Object> map =
+                            (HashMap<String, Object>) msg.obj;
+                    String origin = (String) map.get("origin");
+                    GeolocationPermissions.Callback callback =
+                            (GeolocationPermissions.Callback)
+                            map.get("callback");
+                    mWebChromeClient.onGeolocationPermissionsShowPrompt(origin,
+                            callback);
+                }
+                break;
+
+            case GEOLOCATION_PERMISSIONS_HIDE_PROMPT:
+                if (mWebChromeClient != null) {
+                    mWebChromeClient.onGeolocationPermissionsHidePrompt();
                 }
                 break;
 
@@ -1120,13 +1161,14 @@
      * @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,12 +1179,78 @@
         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<String, Object> map = new HashMap();
+        map.put("spaceNeeded", spaceNeeded);
+        map.put("totalUsedQuota", totalUsedQuota);
+        map.put("quotaUpdater", quotaUpdater);
+        msg.obj = map;
+        sendMessage(msg);
+    }
+
+    /**
+     * Called by WebViewCore to instruct the browser to display a prompt to ask
+     * the user to set the Geolocation permission state for the given origin.
+     * @param origin The origin requesting Geolocation permsissions.
+     * @param callback The callback to call once a permission state has been
+     *     obtained.
+     * @hide pending API council review.
+     */
+    public void onGeolocationPermissionsShowPrompt(String origin,
+            GeolocationPermissions.Callback callback) {
+        if (mWebChromeClient == null) {
+            return;
+        }
+
+        Message showMessage =
+                obtainMessage(GEOLOCATION_PERMISSIONS_SHOW_PROMPT);
+        HashMap<String, Object> map = new HashMap();
+        map.put("origin", origin);
+        map.put("callback", callback);
+        showMessage.obj = map;
+        sendMessage(showMessage);
+    }
+
+    /**
+     * Called by WebViewCore to instruct the browser to hide the Geolocation
+     * permissions prompt.
+     * origin.
+     * @hide pending API council review.
+     */
+    public void onGeolocationPermissionsHidePrompt() {
+        if (mWebChromeClient == null) {
+            return;
+        }
+
+        Message hideMessage = obtainMessage(GEOLOCATION_PERMISSIONS_HIDE_PROMPT);
+        sendMessage(hideMessage);
+    }
+
+    /**
      * 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.
      * @param message The message to add to the console.
diff --git a/core/java/android/webkit/GeolocationPermissions.java b/core/java/android/webkit/GeolocationPermissions.java
new file mode 100755
index 0000000..d06d7e2
--- /dev/null
+++ b/core/java/android/webkit/GeolocationPermissions.java
@@ -0,0 +1,202 @@
+/*
+ * 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.Set;
+
+
+/**
+ * Implements the Java side of GeolocationPermissions. Simply marshalls calls
+ * from the UI thread to the WebKit thread.
+ * @hide
+ */
+public final class GeolocationPermissions {
+    /**
+     * Callback interface used by the browser to report a Geolocation permission
+     * state set by the user in response to a permissions prompt.
+     */
+    public interface Callback {
+        public void invoke(String origin, boolean allow, boolean remember);
+    };
+
+    // Log tag
+    private static final String TAG = "geolocationPermissions";
+
+    // Global instance
+    private static GeolocationPermissions sInstance;
+
+    private Handler mHandler;
+
+    // Members used to transfer the origins and permissions between threads.
+    private Set<String> mOrigins;
+    private boolean mAllowed;
+    private static Lock mLock = new ReentrantLock();
+    private static boolean mUpdated;
+    private static Condition mUpdatedCondition = mLock.newCondition();
+
+    // Message ids
+    static final int GET_ORIGINS = 0;
+    static final int GET_ALLOWED = 1;
+    static final int CLEAR = 2;
+    static final int CLEAR_ALL = 3;
+
+    /**
+     * Gets the singleton instance of the class.
+     */
+    public static GeolocationPermissions getInstance() {
+      if (sInstance == null) {
+          sInstance = new GeolocationPermissions();
+      }
+      return sInstance;
+    }
+
+    /**
+     * Creates the message handler. Must be called on the WebKit thread.
+     */
+    public void createHandler() {
+        if (mHandler == null) {
+            mHandler = new Handler() {
+                @Override
+                public void handleMessage(Message msg) {
+                    // Runs on the WebKit thread.
+                    switch (msg.what) {
+                        case GET_ORIGINS:
+                            getOriginsImpl();
+                            break;
+                        case GET_ALLOWED:
+                            getAllowedImpl((String) msg.obj);
+                            break;
+                        case CLEAR:
+                            nativeClear((String) msg.obj);
+                            break;
+                        case CLEAR_ALL:
+                            nativeClearAll();
+                            break;
+                    }
+                }
+            };
+        }
+    }
+
+    /**
+     * Utility function to send a message to our handler.
+     */
+    private void postMessage(Message msg) {
+        assert(mHandler != null);
+        mHandler.sendMessage(msg);
+    }
+
+    /**
+     * Gets the set of origins for which Geolocation permissions are stored.
+     * Note that we represent the origins as strings. These are created using
+     * WebCore::SecurityOrigin::toString(). As long as all 'HTML 5 modules'
+     * (Database, Geolocation etc) do so, it's safe to match up origins for the
+     * purposes of displaying UI.
+     */
+    public Set getOrigins() {
+        // Called on the UI thread.
+        Set origins = null;
+        mLock.lock();
+        try {
+            mUpdated = false;
+            postMessage(Message.obtain(null, GET_ORIGINS));
+            while (!mUpdated) {
+                mUpdatedCondition.await();
+            }
+            origins = mOrigins;
+        } catch (InterruptedException e) {
+            Log.e(TAG, "Exception while waiting for update", e);
+        } finally {
+            mLock.unlock();
+        }
+        return origins;
+    }
+
+    /**
+     * Helper method to get the set of origins.
+     */
+    private void getOriginsImpl() {
+        // Called on the WebKit thread.
+        mLock.lock();
+        mOrigins = nativeGetOrigins();
+        mUpdated = true;
+        mUpdatedCondition.signal();
+        mLock.unlock();
+    }
+
+    /**
+     * Gets the permission state for the specified origin.
+     */
+    public boolean getAllowed(String origin) {
+        // Called on the UI thread.
+        boolean allowed = false;
+        mLock.lock();
+        try {
+            mUpdated = false;
+            postMessage(Message.obtain(null, GET_ALLOWED, origin));
+            while (!mUpdated) {
+                mUpdatedCondition.await();
+            }
+            allowed = mAllowed;
+        } catch (InterruptedException e) {
+            Log.e(TAG, "Exception while waiting for update", e);
+        } finally {
+            mLock.unlock();
+        }
+        return allowed;
+    }
+
+    /**
+     * Helper method to get the permission state.
+     */
+    private void getAllowedImpl(String origin) {
+        // Called on the WebKit thread.
+        mLock.lock();
+        mAllowed = nativeGetAllowed(origin);
+        mUpdated = true;
+        mUpdatedCondition.signal();
+        mLock.unlock();
+    }
+
+    /**
+     * Clears the permission state for the specified origin.
+     */
+    public void clear(String origin) {
+        // Called on the UI thread.
+        postMessage(Message.obtain(null, CLEAR, origin));
+    }
+
+    /**
+     * Clears the permission state for all origins.
+     */
+    public void clearAll() {
+        // Called on the UI thread.
+        postMessage(Message.obtain(null, CLEAR_ALL));
+    }
+
+    // Native functions, run on the WebKit thread.
+    private static native Set nativeGetOrigins();
+    private static native boolean nativeGetAllowed(String origin);
+    private static native void nativeClear(String origin);
+    private static native void nativeClearAll();
+}
diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java
index dd43b8b..d52406d 100644
--- a/core/java/android/webkit/WebChromeClient.java
+++ b/core/java/android/webkit/WebChromeClient.java
@@ -198,17 +198,48 @@
     * @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);
+    }
+
+    /**
+     * Instructs the client to show a prompt to ask the user to set the
+     * Geolocation permission state for the specified origin.
+     * @hide pending API council approval.
+     */
+    public void onGeolocationPermissionsShowPrompt(String origin,
+            GeolocationPermissions.Callback callback) {}
+
+    /**
+     * Instructs the client to hide the Geolocation permissions prompt.
+     * @hide pending API council approval.
+     */
+    public void onGeolocationPermissionsHidePrompt() {}
+
     /**
      * Tell the client that a JavaScript execution timeout has occured. And the
      * client may decide whether or not to interrupt the execution. If the
@@ -232,6 +263,5 @@
      * @param sourceID The name of the source file that caused the error.
      * @hide pending API council.
      */
-    public void addMessageToConsole(String message, int lineNumber, String sourceID) {
-    }
+    public void addMessageToConsole(String message, int lineNumber, String sourceID) {}
 }
diff --git a/core/java/android/webkit/WebStorage.java b/core/java/android/webkit/WebStorage.java
index 1a60dba..c3b359e 100644
--- a/core/java/android/webkit/WebStorage.java
+++ b/core/java/android/webkit/WebStorage.java
@@ -55,7 +55,8 @@
     // 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 @@
         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 @@
         }
         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 @@
         }
         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 @@
             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 36c5f0c8..4afc4cd 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -36,6 +36,7 @@
 import android.view.SurfaceView;
 
 import java.util.ArrayList;
+import java.util.Set;
 
 import junit.framework.Assert;
 
@@ -166,6 +167,8 @@
         WebIconDatabase.getInstance().createHandler();
         // Create the handler for WebStorage
         WebStorage.getInstance().createHandler();
+        // Create the handler for GeolocationPermissions.
+        GeolocationPermissions.getInstance().createHandler();
         // The transferMessages call will transfer all pending messages to the
         // WebCore thread handler.
         mEventHub.transferMessages();
@@ -247,7 +250,7 @@
     }
 
     /**
-     * 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,14 +263,55 @@
         // 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);
+                    }
+                });
+    }
+
+    /**
+     * Shows a prompt to ask the user to set the Geolocation permission state
+     * for the given origin.
+     * @param origin The origin for which Geolocation permissions are
+     *     requested.
+     */
+    protected void geolocationPermissionsShowPrompt(String origin) {
+        mCallbackProxy.onGeolocationPermissionsShowPrompt(origin,
+                new GeolocationPermissions.Callback() {
+          public void invoke(String origin, boolean allow, boolean remember) {
+            GeolocationPermissionsData data = new GeolocationPermissionsData();
+            data.mOrigin = origin;
+            data.mAllow = allow;
+            data.mRemember = remember;
+            // Marshall to WebCore thread.
+            sendMessage(EventHub.GEOLOCATION_PERMISSIONS_PROVIDE, data);
+          }
+        });
+    }
+
+    /**
+     * Hides the Geolocation permissions prompt.
+     */
+    protected void geolocationPermissionsHidePrompt() {
+        mCallbackProxy.onGeolocationPermissionsHidePrompt();
+    }
+
+    /**
      * Invoke a javascript confirm dialog.
      * @param message The message displayed in the dialog.
      * @return True if the user confirmed or false if the user cancelled.
@@ -440,14 +484,24 @@
 
     /*
      * 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);
 
+    /**
+     * Provide WebCore with a Geolocation permission state for the specified
+     * origin.
+     * @param origin The origin for which Geolocation permissions are provided.
+     * @param allow Whether Geolocation permissions are allowed.
+     * @param remember Whether this decision should be remembered beyond the
+     *     life of the current page.
+     */
+    private native void nativeGeolocationPermissionsProvide(String origin, boolean allow, boolean remember);
+
     // EventHub for processing messages
     private final EventHub mEventHub;
     // WebCore thread handler
@@ -591,6 +645,12 @@
         int mState;
     }
 
+    static class GeolocationPermissionsData {
+        String mOrigin;
+        boolean mAllow;
+        boolean mRemember;
+    }
+
         static final String[] HandlerDebugString = {
             "SCROLL_TEXT_INPUT", // = 99
             "LOAD_URL", // = 100;
@@ -716,6 +776,8 @@
         static final int DUMP_NAVTREE = 172;
 
         static final int SET_JS_FLAGS = 173;
+        // Geolocation
+        static final int GEOLOCATION_PERMISSIONS_PROVIDE = 180;
 
         // private message ids
         private static final int DESTROY =     200;
@@ -1102,6 +1164,12 @@
 
                         case SET_JS_FLAGS:
                             nativeSetJsFlags((String)msg.obj);
+
+                        case GEOLOCATION_PERMISSIONS_PROVIDE:
+                            GeolocationPermissionsData data =
+                                    (GeolocationPermissionsData) msg.obj;
+                            nativeGeolocationPermissionsProvide(data.mOrigin,
+                                    data.mAllow, data.mRemember);
                             break;
 
                         case SYNC_SCROLL:
@@ -1395,6 +1463,21 @@
         }
     }
 
+    // Utility method for exceededDatabaseQuota and reachedMaxAppCacheSize
+    // callbacks. Computes the sum of database quota for all origins.
+    private long getUsedQuota() {
+        WebStorage webStorage = WebStorage.getInstance();
+        Set<String> 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 4483a8e..30e1d99 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
@@ -538,7 +538,7 @@
 
         @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) {