Merge "Remove tabs."
diff --git a/src/com/android/browser/BrowserProvider.java b/src/com/android/browser/BrowserProvider.java
index cc96b9c..dda5765 100644
--- a/src/com/android/browser/BrowserProvider.java
+++ b/src/com/android/browser/BrowserProvider.java
@@ -405,16 +405,9 @@
         if (Settings.System.getInt(context.getContentResolver(),
                 Settings.System.SHOW_WEB_SUGGESTIONS,
                 1 /* default on */) == 1) {
-            Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
-            intent.addCategory(Intent.CATEGORY_DEFAULT);
-            ResolveInfo info = context.getPackageManager().resolveActivity(
-                    intent, PackageManager.MATCH_DEFAULT_ONLY);
-            if (info != null) {
-                ComponentName googleSearchComponent =
-                        new ComponentName(info.activityInfo.packageName,
-                                info.activityInfo.name);
-                mSearchableInfo = mSearchManager.getSearchableInfo(
-                        googleSearchComponent, false);
+            ComponentName webSearchComponent = mSearchManager.getWebSearchActivity();
+            if (webSearchComponent != null) {
+                mSearchableInfo = mSearchManager.getSearchableInfo(webSearchComponent);
             }
         }
     }
diff --git a/src/com/android/browser/WebStorageSizeManager.java b/src/com/android/browser/WebStorageSizeManager.java
index 3afcadc..dcf2f8b 100644
--- a/src/com/android/browser/WebStorageSizeManager.java
+++ b/src/com/android/browser/WebStorageSizeManager.java
@@ -209,6 +209,9 @@
      * @param databaseIdentifier the identifier of the database on
      *     which the transaction that caused the quota overflow was run
      * @param currentQuota the current quota for the origin.
+     * @param estimatedSize the estimated size of a new database, or 0 if
+     *     this has been invoked in response to an existing database
+     *     overflowing its quota.
      * @param totalUsedQuota is the sum of all origins' quota.
      * @param quotaUpdater The callback to run when a decision to allow or
      *     deny quota has been made. Don't forget to call this!
@@ -248,7 +251,8 @@
             }
             return;
         }
-        // We have enough space inside mGlobalLimit.
+
+        // We have some space inside mGlobalLimit.
         long newOriginQuota = currentQuota;
         if (newOriginQuota == 0) {
             // This is a new origin, give it the size it asked for if possible.
@@ -260,19 +264,31 @@
             } else {
                 if (LOGV_ENABLED) {
                     Log.v(LOGTAG,
-                          "onExceededDatabaseQuota: Unable to satisfy" +
-                          " estimatedSize for the new database " +
-                          " (estimatedSize: " + estimatedSize +
-                          ", unused quota: " + totalUnusedQuota);
+                            "onExceededDatabaseQuota: Unable to satisfy" +
+                            " estimatedSize for the new database " +
+                            " (estimatedSize: " + estimatedSize +
+                            ", unused quota: " + totalUnusedQuota);
                 }
                 newOriginQuota = 0;
             }
         } else {
             // This is an origin we have seen before. It wants a quota
-            // increase.
-            newOriginQuota +=
-                Math.min(QUOTA_INCREASE_STEP, totalUnusedQuota);
+            // increase. There are two circumstances: either the origin
+            // is creating a new database or it has overflowed an existing database.
+
+            // Increase the quota. If estimatedSize == 0, then this is a quota overflow
+            // rather than the creation of a new database.
+            long quotaIncrease = estimatedSize == 0 ?
+                    Math.min(QUOTA_INCREASE_STEP, totalUnusedQuota) :
+                    estimatedSize;
+            newOriginQuota += quotaIncrease;
+
+            if (quotaIncrease > totalUnusedQuota) {
+                // We can't fit, so deny quota.
+                newOriginQuota = currentQuota;
+            }
         }
+
         quotaUpdater.updateQuota(newOriginQuota);
 
         if(LOGV_ENABLED) {
diff --git a/tests/src/com/android/browser/WebStorageSizeManagerUnitTests.java b/tests/src/com/android/browser/WebStorageSizeManagerUnitTests.java
index b7956d7..354c4da 100644
--- a/tests/src/com/android/browser/WebStorageSizeManagerUnitTests.java
+++ b/tests/src/com/android/browser/WebStorageSizeManagerUnitTests.java
@@ -108,14 +108,14 @@
         totalUsedQuota += origin2Quota;
 
         // Origin 1 runs out of space.
-        manager.onExceededDatabaseQuota("1", "1", origin1Quota, origin1EstimatedSize, totalUsedQuota, mQuotaUpdater);
+        manager.onExceededDatabaseQuota("1", "1", origin1Quota, 0, totalUsedQuota, mQuotaUpdater);
         assertEquals(origin1EstimatedSize + quotaIncrease, mNewQuota);
         totalUsedQuota -= origin1Quota;
         origin1Quota = mNewQuota;
         totalUsedQuota += origin1Quota;
 
         // Origin 2 runs out of space.
-        manager.onExceededDatabaseQuota("2", "2", origin2Quota, origin2EstimatedSize, totalUsedQuota, mQuotaUpdater);
+        manager.onExceededDatabaseQuota("2", "2", origin2Quota, 0, totalUsedQuota, mQuotaUpdater);
         assertEquals(origin2EstimatedSize + quotaIncrease, mNewQuota);
         totalUsedQuota -= origin2Quota;
         origin2Quota = mNewQuota;
@@ -131,14 +131,14 @@
         totalUsedQuota += origin3Quota;
 
         // Origin 1 runs out of space again. It should increase it's quota to take the last 1MB.
-        manager.onExceededDatabaseQuota("1", "1", origin1Quota, origin1EstimatedSize, totalUsedQuota, mQuotaUpdater);
+        manager.onExceededDatabaseQuota("1", "1", origin1Quota, 0, totalUsedQuota, mQuotaUpdater);
         assertEquals(origin1Quota + quotaIncrease, mNewQuota);
         totalUsedQuota -= origin1Quota;
         origin1Quota = mNewQuota;
         totalUsedQuota += origin1Quota;
 
         // Origin 1 runs out of space again. It should inow fail to increase in size.
-        manager.onExceededDatabaseQuota("1", "1", origin1Quota, origin1EstimatedSize, totalUsedQuota, mQuotaUpdater);
+        manager.onExceededDatabaseQuota("1", "1", origin1Quota, 0, totalUsedQuota, mQuotaUpdater);
         assertEquals(origin1Quota, mNewQuota);
 
         // We try adding a new origin. Which will fail.
@@ -228,4 +228,73 @@
         maxSize = WebStorageSizeManager.calculateGlobalLimit(fileSystemSize, freeSpaceSize);
         assertEquals(0, maxSize);
     }
+
+    public void testManyDatabasesOnOneOrigin() {
+        // This test ensures that if an origin creates more than one database, the quota that is
+        // assigned to the origin after the second creation is enough to satisfy all databases
+        // under that origin.
+        // See b/2417477.
+
+        long totalUsedQuota = 0;
+        mDiskInfo.setTotalSizeBytes(bytes(100));
+        mDiskInfo.setFreeSpaceSizeBytes(bytes(100));
+        // This should give us a storage area of 13MB, with 3.25MB for appcache and 9.75MB for
+        // databases.
+        assertEquals(bytes(13), WebStorageSizeManager.calculateGlobalLimit(
+                mDiskInfo.getTotalSizeBytes(), mDiskInfo.getFreeSpaceSizeBytes()));
+
+        // We have an appcache file size of 0 MB.
+        mAppCacheInfo.setAppCacheSizeBytes(0);
+
+        // Create the manager.
+        WebStorageSizeManager manager = new WebStorageSizeManager(null, mDiskInfo, mAppCacheInfo);
+
+        // We add an origin.
+        long originQuota = 0;
+        long database1EstimatedSize = bytes(2);
+        manager.onExceededDatabaseQuota("1", "1", originQuota, database1EstimatedSize,
+                totalUsedQuota, mQuotaUpdater);
+        assertEquals(database1EstimatedSize, mNewQuota);
+        originQuota = mNewQuota;
+        totalUsedQuota = originQuota;
+
+        // Now try to create a new database under the origin, by invoking onExceededDatabaseQuota
+        // again. This time, request more space than the old quota + the quota increase step.
+        long database2EstimatedSize = bytes(3.5);
+        manager.onExceededDatabaseQuota("1", "2", originQuota, database2EstimatedSize,
+                totalUsedQuota, mQuotaUpdater);
+        assertEquals(database1EstimatedSize + database2EstimatedSize, mNewQuota);
+        originQuota = mNewQuota;
+        totalUsedQuota = originQuota;
+
+        // Create another database, but this time use a size that will overflow the space on the
+        // device. It should be denied.
+        long database3EstimatedSize = bytes(50);
+        manager.onExceededDatabaseQuota("1", "3", originQuota, database3EstimatedSize,
+                totalUsedQuota, mQuotaUpdater);
+        assertEquals(originQuota, mNewQuota);
+
+        // Create another database. This time, request less than the old quota.
+        long database4EstimatedSize = bytes(2);
+        manager.onExceededDatabaseQuota("1", "4", originQuota, database4EstimatedSize,
+                totalUsedQuota, mQuotaUpdater);
+        assertEquals(database1EstimatedSize + database2EstimatedSize + database4EstimatedSize,
+                mNewQuota);
+        originQuota = mNewQuota;
+        totalUsedQuota = originQuota;
+
+        // Now have the first database overflow it's quota. We should get 1 more MB.
+        manager.onExceededDatabaseQuota("1", "1", originQuota, 0, totalUsedQuota, mQuotaUpdater);
+        assertEquals(database1EstimatedSize + database2EstimatedSize + database4EstimatedSize +
+                bytes(1), mNewQuota);
+        originQuota = mNewQuota;
+        totalUsedQuota = originQuota;
+
+        // Create a db under the origin that uses a quota less than the usual quota increase step.
+        long database5EstimatedSize = bytes(0.5);
+        manager.onExceededDatabaseQuota("1", "5", originQuota, database5EstimatedSize,
+                totalUsedQuota, mQuotaUpdater);
+        assertEquals(database1EstimatedSize + database2EstimatedSize + database4EstimatedSize +
+                bytes(1) + database5EstimatedSize, mNewQuota);
+    }
 }