From 2200f581c7e64e5d1fb6067b0a0a0996c4fa8ea7 Mon Sep 17 00:00:00 2001 From: "dcamp%mozilla.com" Date: Wed, 23 Jan 2008 02:54:06 +0000 Subject: [PATCH] Bug 397416: Raise globalStorage quota for domains with the offline-app permission. r=enndeakin, sr=dveditz, blocking1.9=sicking --- dom/src/storage/Makefile.in | 1 + dom/src/storage/nsDOMStorage.cpp | 74 ++++++++++++++++++-- dom/src/storage/nsDOMStorageDB.cpp | 5 +- dom/src/storage/nsDOMStorageDB.h | 3 +- modules/libpref/src/init/all.js | 8 +++ uriloader/prefetch/nsIOfflineCacheUpdate.idl | 13 ++++ 6 files changed, 98 insertions(+), 6 deletions(-) diff --git a/dom/src/storage/Makefile.in b/dom/src/storage/Makefile.in index 5f35765eaa1..afe1e59b66f 100644 --- a/dom/src/storage/Makefile.in +++ b/dom/src/storage/Makefile.in @@ -60,6 +60,7 @@ REQUIRES = xpcom \ unicharutil \ widget \ xpconnect \ + prefetch \ $(NULL) ifdef MOZ_STORAGE diff --git a/dom/src/storage/nsDOMStorage.cpp b/dom/src/storage/nsDOMStorage.cpp index da01a99872e..f5ea300892e 100644 --- a/dom/src/storage/nsDOMStorage.cpp +++ b/dom/src/storage/nsDOMStorage.cpp @@ -54,18 +54,26 @@ #include "nsICookiePermission.h" #include "nsIPermissionManager.h" #include "nsCycleCollectionParticipant.h" +#include "nsIOfflineCacheUpdate.h" +#include "nsIJSContextStack.h" static const PRUint32 ASK_BEFORE_ACCEPT = 1; static const PRUint32 ACCEPT_SESSION = 2; static const PRUint32 BEHAVIOR_REJECT = 2; static const PRUint32 DEFAULT_QUOTA = 5 * 1024; +// Be generous with offline apps by default... +static const PRUint32 DEFAULT_OFFLINE_APP_QUOTA = 200 * 1024; +// ... but warn if it goes over this amount +static const PRUint32 DEFAULT_OFFLINE_WARN_QUOTA = 50 * 1024; static const char kPermissionType[] = "cookie"; static const char kStorageEnabled[] = "dom.storage.enabled"; static const char kDefaultQuota[] = "dom.storage.default_quota"; static const char kCookiesBehavior[] = "network.cookie.cookieBehavior"; static const char kCookiesLifetimePolicy[] = "network.cookie.lifetimePolicy"; +static const char kOfflineAppWarnQuota[] = "offline-apps.quota.warn"; +static const char kOfflineAppQuota[] = "offline-apps.quota.max"; // // Helper that tells us whether the caller is secure or not. @@ -104,11 +112,44 @@ IsCallerSecure() return NS_SUCCEEDED(rv) && isHttps; } -static PRInt32 -GetQuota(const nsAString &domain) + +// Returns two quotas - A hard limit for which adding data will be an error, +// and a limit after which a warning event will be sent to the observer +// service. The warn limit may be -1, in which case there will be no warning. +static void +GetQuota(const nsAString &aDomain, PRInt32 *aQuota, PRInt32 *aWarnQuota) { + // Fake a URI for the permission manager + nsCOMPtr uri; + NS_NewURI(getter_AddRefs(uri), NS_LITERAL_STRING("http://") + aDomain); + + if (uri) { + nsCOMPtr permissionManager = + do_GetService(NS_PERMISSIONMANAGER_CONTRACTID); + + PRUint32 perm; + if (permissionManager && + NS_SUCCEEDED(permissionManager->TestExactPermission(uri, "offline-app", &perm)) && + perm != nsIPermissionManager::UNKNOWN_ACTION && + perm != nsIPermissionManager::DENY_ACTION) { + // This is an offline app, give more space by default. + *aQuota = ((PRInt32)nsContentUtils::GetIntPref(kOfflineAppQuota, + DEFAULT_OFFLINE_WARN_QUOTA * 1024)); + + if (perm == nsIOfflineCacheUpdateService::ALLOW_NO_WARN) { + *aWarnQuota = -1; + } else { + *aWarnQuota = ((PRInt32)nsContentUtils::GetIntPref(kOfflineAppWarnQuota, + DEFAULT_OFFLINE_WARN_QUOTA) * 1024); + } + return; + } + } + // FIXME: per-domain quotas? - return ((PRInt32)nsContentUtils::GetIntPref(kDefaultQuota, DEFAULT_QUOTA) * 1024); + *aQuota = ((PRInt32)nsContentUtils::GetIntPref(kDefaultQuota, + DEFAULT_QUOTA) * 1024); + *aWarnQuota = -1; } nsSessionStorageEntry::nsSessionStorageEntry(KeyTypePointer aStr) @@ -771,12 +812,37 @@ nsDOMStorage::SetDBValue(const nsAString& aKey, currentDomain = mDomain; } + PRInt32 quota; + PRInt32 warnQuota; + GetQuota(currentDomain, "a, &warnQuota); + + PRInt32 usage; rv = gStorageDB->SetKey(mDomain, aKey, aValue, aSecure, - currentDomain, GetQuota(currentDomain)); + currentDomain, quota, &usage); NS_ENSURE_SUCCESS(rv, rv); mItemsCached = PR_FALSE; + if (warnQuota >= 0 && usage > warnQuota) { + // try to include the window that exceeded the warn quota + nsCOMPtr window; + JSContext *cx; + nsCOMPtr stack = + do_GetService("@mozilla.org/js/xpc/ContextStack;1"); + if (stack && NS_SUCCEEDED(stack->Peek(&cx)) && cx) { + nsCOMPtr scriptContext; + scriptContext = GetScriptContextFromJSContext(cx); + if (scriptContext) { + window = do_QueryInterface(scriptContext->GetGlobalObject()); + } + } + + nsCOMPtr os = + do_GetService("@mozilla.org/observer-service;1"); + os->NotifyObservers(window, "dom-storage-warn-quota-exceeded", + currentDomain.get()); + } + BroadcastChangeNotification(); #endif diff --git a/dom/src/storage/nsDOMStorageDB.cpp b/dom/src/storage/nsDOMStorageDB.cpp index c979f7b7a3b..6127375ffeb 100644 --- a/dom/src/storage/nsDOMStorageDB.cpp +++ b/dom/src/storage/nsDOMStorageDB.cpp @@ -271,7 +271,8 @@ nsDOMStorageDB::SetKey(const nsAString& aDomain, const nsAString& aValue, PRBool aSecure, const nsAString& aOwner, - PRInt32 aQuota) + PRInt32 aQuota, + PRInt32 *aNewUsage) { mozStorageStatementScoper scope(mGetKeyValueStatement); @@ -362,6 +363,8 @@ nsDOMStorageDB::SetKey(const nsAString& aDomain, mCachedUsage = usage; } + *aNewUsage = usage; + return NS_OK; } diff --git a/dom/src/storage/nsDOMStorageDB.h b/dom/src/storage/nsDOMStorageDB.h index 3e522d83063..3594f142e42 100644 --- a/dom/src/storage/nsDOMStorageDB.h +++ b/dom/src/storage/nsDOMStorageDB.h @@ -85,7 +85,8 @@ public: const nsAString& aValue, PRBool aSecure, const nsAString& aOwner, - PRInt32 aQuota); + PRInt32 aQuota, + PRInt32* aNewUsage); /** * Set the secure flag for a key in storage. Does nothing if the key was diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index f18f934c10e..23d8755c5af 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -71,6 +71,14 @@ pref("browser.cache.offline.enable", true); // offline cache capacity in kilobytes pref("browser.cache.offline.capacity", 10240); +// offline apps should be limited to this much data in global storage +// (in kilobytes) +pref("offline-apps.quota.max", 204800); + +// the user should be warned if offline app disk usage exceeds this amount +// (in kilobytes) +pref("offline-apps.quota.warn", 51200); + // Fastback caching - if this pref is negative, then we calculate the number // of content viewers to cache based on the amount of available memory. pref("browser.sessionhistory.max_total_viewers", -1); diff --git a/uriloader/prefetch/nsIOfflineCacheUpdate.idl b/uriloader/prefetch/nsIOfflineCacheUpdate.idl index 75a1e985bc4..a64fb53a484 100644 --- a/uriloader/prefetch/nsIOfflineCacheUpdate.idl +++ b/uriloader/prefetch/nsIOfflineCacheUpdate.idl @@ -204,6 +204,19 @@ interface nsIOfflineCacheUpdate : nsISupports { [scriptable, uuid(3abee04b-5bbb-4405-b659-35f780e38da0)] interface nsIOfflineCacheUpdateService : nsISupports { + /** + * Constants for the offline-app permission. + * + * XXX: This isn't a great place for this, but it's really the only + * private offline-app-related interface + */ + + /** + * Allow the domain to use offline APIs, and don't warn about excessive + * usage. + */ + const unsigned long ALLOW_NO_WARN = 3; + /** * Access to the list of cache updates that have been scheduled. */