Use the estimated size of new databases as the default quota if we have enough space to satisfy it.

Change-Id:I23daac8fbf27f50f304ee53060353423deaed50a
diff --git a/src/com/android/browser/BrowserActivity.java b/src/com/android/browser/BrowserActivity.java
index 818056c..c766c74 100644
--- a/src/com/android/browser/BrowserActivity.java
+++ b/src/com/android/browser/BrowserActivity.java
@@ -3088,17 +3088,18 @@
          * @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 the database.
          * @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!
          */
         @Override
         public void onExceededDatabaseQuota(String url,
-            String databaseIdentifier, long currentQuota, long totalUsedQuota,
-            WebStorage.QuotaUpdater quotaUpdater) {
+            String databaseIdentifier, long currentQuota, long estimatedSize,
+            long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater) {
             mSettings.getWebStorageSizeManager().onExceededDatabaseQuota(
-                    url, databaseIdentifier, currentQuota, totalUsedQuota,
-                    quotaUpdater);
+                    url, databaseIdentifier, currentQuota, estimatedSize,
+                    totalUsedQuota, quotaUpdater);
         }
 
         /**
diff --git a/src/com/android/browser/WebStorageSizeManager.java b/src/com/android/browser/WebStorageSizeManager.java
index 40d30a2..d5347cb 100644
--- a/src/com/android/browser/WebStorageSizeManager.java
+++ b/src/com/android/browser/WebStorageSizeManager.java
@@ -72,18 +72,11 @@
  * sum of all other origins' quota) and deciding if a quota increase for the
  * out-of-space origin is allowed or not.
  *
- * The default quota for an origin is min(ORIGIN_DEFAULT_QUOTA, unused_quota).
+ * The default quota for an origin is its estimated size. If we cannot satisfy
+ * the estimated size, then WebCore will not create the database.
  * Quota increases are done in steps, where the increase step is
  * min(QUOTA_INCREASE_STEP, unused_quota).
  *
- * This approach has the drawback that space may remain unused if there
- * are many websites that store a lot less content than ORIGIN_DEFAULT_QUOTA.
- * We deal with this by picking a value for ORIGIN_DEFAULT_QUOTA that is smaller
- * than what the HTML 5 spec recommends. At the same time, picking a very small
- * value for ORIGIN_DEFAULT_QUOTA may create performance problems since it's
- * more likely for origins to have to rollback and restart transactions as a
- * result of reaching the quota more often.
- *
  * When all the Web storage space is used, the WebStorageSizeManager creates
  * a system notification that will guide the user to the WebSettings UI. There,
  * the user can free some of the Web storage space by deleting all the data used
@@ -215,8 +208,8 @@
      *     deny quota has been made. Don't forget to call this!
      */
     public void onExceededDatabaseQuota(String url,
-        String databaseIdentifier, long currentQuota, long totalUsedQuota,
-        WebStorage.QuotaUpdater quotaUpdater) {
+        String databaseIdentifier, long currentQuota, long estimatedSize,
+        long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater) {
         if(LOGV_ENABLED) {
             Log.v(LOGTAG,
                   "Received onExceededDatabaseQuota for "
@@ -252,9 +245,22 @@
         // We have enough space inside mGlobalLimit.
         long newOriginQuota = currentQuota;
         if (newOriginQuota == 0) {
-            // This is a new origin. It wants an initial quota.
-            newOriginQuota =
-                Math.min(ORIGIN_DEFAULT_QUOTA, totalUnusedQuota);
+            // This is a new origin, give it the size it asked for if possible.
+            // If we cannot satisfy the estimatedSize, we should return 0 as
+            // returning a value less that what the site requested will lead
+            // to webcore not creating the database.
+            if (totalUnusedQuota >= estimatedSize) {
+                newOriginQuota = estimatedSize;
+            } else {
+                if (LOGV_ENABLED) {
+                    Log.v(LOGTAG,
+                          "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.
@@ -379,4 +385,5 @@
             mgr.notify(OUT_OF_SPACE_ID, notification);
         }
     }
-}
\ No newline at end of file
+}
+
diff --git a/tests/src/com/android/browser/WebStorageSizeManagerUnitTests.java b/tests/src/com/android/browser/WebStorageSizeManagerUnitTests.java
index a2604e0..b7956d7 100644
--- a/tests/src/com/android/browser/WebStorageSizeManagerUnitTests.java
+++ b/tests/src/com/android/browser/WebStorageSizeManagerUnitTests.java
@@ -82,8 +82,8 @@
      */
     public void testCallbacks() {
         long totalUsedQuota = 0;
-        final long defaultQuota = WebStorageSizeManager.ORIGIN_DEFAULT_QUOTA;  // 3MB
         final long quotaIncrease = WebStorageSizeManager.QUOTA_INCREASE_STEP;  // 1MB
+
         // We have 75 MB total, 24MB free so the global limit will be 12 MB.
         mDiskInfo.setTotalSizeBytes(bytes(75));
         mDiskInfo.setFreeSpaceSizeBytes(bytes(24));
@@ -93,46 +93,56 @@
         WebStorageSizeManager manager = new WebStorageSizeManager(null, mDiskInfo, mAppCacheInfo);
         // We add origin 1.
         long origin1Quota = 0;
-        manager.onExceededDatabaseQuota("1", "1", origin1Quota, totalUsedQuota, mQuotaUpdater);
-        assertEquals(defaultQuota, mNewQuota);
+        long origin1EstimatedSize = bytes(3.5);
+        manager.onExceededDatabaseQuota("1", "1", origin1Quota, origin1EstimatedSize, totalUsedQuota, mQuotaUpdater);
+        assertEquals(origin1EstimatedSize, mNewQuota);
         origin1Quota = mNewQuota;
         totalUsedQuota += origin1Quota;
 
         // We add origin 2.
         long origin2Quota = 0;
-        manager.onExceededDatabaseQuota("2", "2", origin2Quota, totalUsedQuota, mQuotaUpdater);
-        assertEquals(defaultQuota, mNewQuota);
+        long origin2EstimatedSize = bytes(2.5);
+        manager.onExceededDatabaseQuota("2", "2", origin2Quota, origin2EstimatedSize, totalUsedQuota, mQuotaUpdater);
+        assertEquals(origin2EstimatedSize, mNewQuota);
         origin2Quota = mNewQuota;
         totalUsedQuota += origin2Quota;
 
         // Origin 1 runs out of space.
-        manager.onExceededDatabaseQuota("1", "1", origin1Quota, totalUsedQuota, mQuotaUpdater);
-        assertEquals(defaultQuota + quotaIncrease, mNewQuota);
+        manager.onExceededDatabaseQuota("1", "1", origin1Quota, origin1EstimatedSize, totalUsedQuota, mQuotaUpdater);
+        assertEquals(origin1EstimatedSize + quotaIncrease, mNewQuota);
         totalUsedQuota -= origin1Quota;
         origin1Quota = mNewQuota;
         totalUsedQuota += origin1Quota;
 
         // Origin 2 runs out of space.
-        manager.onExceededDatabaseQuota("2", "2", origin2Quota, totalUsedQuota, mQuotaUpdater);
-        assertEquals(defaultQuota + quotaIncrease, mNewQuota);
+        manager.onExceededDatabaseQuota("2", "2", origin2Quota, origin2EstimatedSize, totalUsedQuota, mQuotaUpdater);
+        assertEquals(origin2EstimatedSize + quotaIncrease, mNewQuota);
         totalUsedQuota -= origin2Quota;
         origin2Quota = mNewQuota;
         totalUsedQuota += origin2Quota;
 
-        // We add origin 3. TotalUsedQuota is 8 (3 + 3 + 1 + 1). AppCacheMaxSize is 3 (12 / 4).
+        // We add origin 3. TotalUsedQuota is 8 (3.5 + 2.5 + 1 + 1). AppCacheMaxSize is 3 (12 / 4).
         // So we have 1 MB free.
         long origin3Quota = 0;
-        manager.onExceededDatabaseQuota("3", "3", origin3Quota, totalUsedQuota, mQuotaUpdater);
-        assertEquals(bytes(1), mNewQuota);  // 1MB
+        long origin3EstimatedSize = bytes(5);
+        manager.onExceededDatabaseQuota("3", "3", origin3Quota, origin3EstimatedSize, totalUsedQuota, mQuotaUpdater);
+        assertEquals(0, mNewQuota);  // We cannot satisfy the estimatedSize
         origin3Quota = mNewQuota;
         totalUsedQuota += origin3Quota;
 
-        // Origin 1 runs out of space again. We're also out of space so we can't give it more.
-        manager.onExceededDatabaseQuota("1", "1", origin1Quota, totalUsedQuota, mQuotaUpdater);
+        // 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);
+        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);
         assertEquals(origin1Quota, mNewQuota);
 
         // We try adding a new origin. Which will fail.
-        manager.onExceededDatabaseQuota("4", "4", 0, totalUsedQuota, mQuotaUpdater);
+        manager.onExceededDatabaseQuota("4", "4", 0, bytes(1), totalUsedQuota, mQuotaUpdater);
         assertEquals(0, mNewQuota);
 
         // AppCache size increases to 2MB...
@@ -144,17 +154,18 @@
         // The user nukes origin 2
         totalUsedQuota -= origin2Quota;
         origin2Quota = 0;
-        // TotalUsedQuota is 5 (9 - 4). AppCacheMaxSize is 3. AppCacheSize is 2.
+        // TotalUsedQuota is 5.5 (9 - 3.5). AppCacheMaxSize is 3. AppCacheSize is 2.
         // AppCache wants 1.5MB more
         manager.onReachedMaxAppCacheSize(bytes(1.5), totalUsedQuota, mQuotaUpdater);
         mAppCacheInfo.setAppCacheSizeBytes(mAppCacheInfo.getAppCacheSizeBytes() + bytes(2.5));
-        assertEquals(mAppCacheInfo.getAppCacheSizeBytes(), mNewQuota);
+        assertEquals(mAppCacheInfo.getAppCacheSizeBytes(), mNewQuota - WebStorageSizeManager.APPCACHE_MAXSIZE_PADDING);
 
         // We try adding a new origin. This time we succeed.
-        // TotalUsedQuota is 5. AppCacheMaxSize is 4.5. So we have 12 - 9.5 = 2.5 available.
+        // TotalUsedQuota is 5.5. AppCacheMaxSize is 5.0. So we have 12 - 10.5 = 1.5 available.
         long origin4Quota = 0;
-        manager.onExceededDatabaseQuota("4", "4", origin4Quota, totalUsedQuota, mQuotaUpdater);
-        assertEquals(bytes(2.5), mNewQuota);
+        long origin4EstimatedSize = bytes(1.5);
+        manager.onExceededDatabaseQuota("4", "4", origin4Quota, origin4EstimatedSize, totalUsedQuota, mQuotaUpdater);
+        assertEquals(bytes(1.5), mNewQuota);
         origin4Quota = mNewQuota;
         totalUsedQuota += origin4Quota;
     }