Implement out of space notification
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 6876409..0056555 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -767,10 +767,9 @@
     <string name="default_button">OK</string>
 
     <!-- HTML5 dialogs -->
-
-    <!-- Database -->
-    <!-- Used as a toast notification after the user close the html5 webstorage permission dialog -->
-    <string name="webstorage_notification">The quota for this site can be changed in the Local Storage section of the Browser settings</string>
+    <!-- Used as a status bar notification when the browser is running out of space trying to allocate or increase the database quota for an HTML5 databae or application cache. -->
+    <string name="webstorage_outofspace_notification_title">Browser storage full</string>
+    <string name="webstorage_outofspace_notification_text">Click to free up space.</string>
     <!-- Used in the Browser Settings -->
     <string name="webstorage_clear_data_title">Clear stored data</string>
     <string name="webstorage_clear_data_summary">Remove all databases associated with this website</string>
diff --git a/src/com/android/browser/WebStorageSizeManager.java b/src/com/android/browser/WebStorageSizeManager.java
index ff21ea9..40d30a2 100644
--- a/src/com/android/browser/WebStorageSizeManager.java
+++ b/src/com/android/browser/WebStorageSizeManager.java
@@ -16,7 +16,11 @@
 
 package com.android.browser;
 
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
 import android.content.Context;
+import android.content.Intent;
 import android.os.StatFs;
 import android.util.Log;
 import android.webkit.WebStorage;
@@ -84,7 +88,6 @@
  * 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
  * by an origin.
- * TODO(andreip): implement the notification.
  */
 class WebStorageSizeManager {
     // Logging flags.
@@ -95,6 +98,14 @@
     public final static long ORIGIN_DEFAULT_QUOTA = 3 * 1024 * 1024;  // 3MB
     // The default value for quota increases.
     public final static long QUOTA_INCREASE_STEP = 1 * 1024 * 1024;  // 1MB
+    // Extra padding space for appcache maximum size increases. This is needed
+    // because WebKit sends us an estimate of the amount of space needed
+    // but this estimate may, currently, be slightly less than what is actually
+    // needed. We therefore add some 'padding'.
+    // TODO(andreip): fix this in WebKit.
+    public final static long APPCACHE_MAXSIZE_PADDING = 512 * 1024; // 512KB
+    // The system status bar notification id.
+    private final static int OUT_OF_SPACE_ID = 1;
     // The application context.
     private final Context mContext;
     // The global Web storage limit.
@@ -222,8 +233,16 @@
 
         if (totalUnusedQuota <= 0) {
             // There definitely isn't any more space. Fire notifications
-            // and exit.
-            scheduleOutOfSpaceNotification();
+            // if needed and exit.
+            if (totalUsedQuota > 0) {
+                // We only fire the notification if there are some other websites
+                // using some of the quota. This avoids the degenerate case where
+                // the first ever website to use Web storage tries to use more
+                // data than it is actually available. In such a case, showing
+                // the notification would not help at all since there is nothing
+                // the user can do.
+                scheduleOutOfSpaceNotification();
+            }
             quotaUpdater.updateQuota(currentQuota);
             if(LOGV_ENABLED) {
                 Log.v(LOGTAG, "onExceededDatabaseQuota: out of space.");
@@ -268,10 +287,18 @@
 
         long totalUnusedQuota = mGlobalLimit - totalUsedQuota - mAppCacheMaxSize;
 
-        if (totalUnusedQuota < spaceNeeded) {
+        if (totalUnusedQuota < spaceNeeded + APPCACHE_MAXSIZE_PADDING) {
             // There definitely isn't any more space. Fire notifications
-            // and exit.
-            scheduleOutOfSpaceNotification();
+            // if needed and exit.
+            if (totalUsedQuota > 0) {
+                // We only fire the notification if there are some other websites
+                // using some of the quota. This avoids the degenerate case where
+                // the first ever website to use Web storage tries to use more
+                // data than it is actually available. In such a case, showing
+                // the notification would not help at all since there is nothing
+                // the user can do.
+                scheduleOutOfSpaceNotification();
+            }
             quotaUpdater.updateQuota(0);
             if(LOGV_ENABLED) {
                 Log.v(LOGTAG, "onReachedMaxAppCacheSize: out of space.");
@@ -279,7 +306,7 @@
             return;
         }
         // There is enough space to accommodate spaceNeeded bytes.
-        mAppCacheMaxSize += spaceNeeded;
+        mAppCacheMaxSize += spaceNeeded + APPCACHE_MAXSIZE_PADDING;
         quotaUpdater.updateQuota(mAppCacheMaxSize);
 
         if(LOGV_ENABLED) {
@@ -324,6 +351,32 @@
     // Schedules a system notification that takes the user to the WebSettings
     // activity when clicked.
     private void scheduleOutOfSpaceNotification() {
-        // TODO(andreip): implement.
+        if(LOGV_ENABLED) {
+            Log.v(LOGTAG, "scheduleOutOfSpaceNotification called.");
+        }
+        if (mContext == null) {
+            // mContext can be null if we're running unit tests.
+            return;
+        }
+        // setup the notification boilerplate.
+        int icon = R.drawable.ic_launcher_browser;
+        CharSequence title = mContext.getString(
+                R.string.webstorage_outofspace_notification_title);
+        CharSequence text = mContext.getString(
+                R.string.webstorage_outofspace_notification_text);
+        long when = System.currentTimeMillis();
+        Intent intent = new Intent(mContext, WebsiteSettingsActivity.class);
+        PendingIntent contentIntent =
+            PendingIntent.getActivity(mContext, 0, intent, 0);
+        Notification notification = new Notification(icon, title, when);
+        notification.setLatestEventInfo(mContext, title, text, contentIntent);
+        notification.flags |= Notification.FLAG_AUTO_CANCEL;
+        // Fire away.
+        String ns = Context.NOTIFICATION_SERVICE;
+        NotificationManager mgr =
+            (NotificationManager) mContext.getSystemService(ns);
+        if (mgr != null) {
+            mgr.notify(OUT_OF_SPACE_ID, notification);
+        }
     }
 }
\ No newline at end of file