Bug 397417: monitor disk usage of offline apps in the UI. r=enndeakin (nsDOMStorage change), r/sr=mconnor, ui-r/blocking-firefox3=beltzner

This commit is contained in:
2008-02-26 13:13:17 -08:00
parent ae4ca936d5
commit c8c98c3c73
6 changed files with 196 additions and 10 deletions

View File

@@ -4999,12 +4999,18 @@ var OfflineApps = {
// OfflineApps Public Methods // OfflineApps Public Methods
init: function () init: function ()
{ {
// XXX: empty init left as a placeholder for patch in bug 397417 var obs = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
obs.addObserver(this, "dom-storage-warn-quota-exceeded", false);
obs.addObserver(this, "offline-cache-update-completed", false);
}, },
uninit: function () uninit: function ()
{ {
// XXX: empty uninit left as a placeholder for patch in bug 397417 var obs = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
obs.removeObserver(this, "dom-storage-warn-quota-exceeded");
obs.removeObserver(this, "offline-cache-update-completed");
}, },
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
@@ -5032,6 +5038,92 @@ var OfflineApps = {
} }
}, },
_getManifestURI: function(aWindow) {
var attr = aWindow.document.documentElement.getAttribute("manifest");
if (!attr) return null;
try {
var ios = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
var contentURI = ios.newURI(aWindow.location.href, null, null);
return ios.newURI(attr, aWindow.document.characterSet, contentURI);
} catch (e) {
return null;
}
},
// A cache update isn't tied to a specific window. Try to find
// the best browser in which to warn the user about space usage
_getBrowserForCacheUpdate: function(aCacheUpdate) {
// Prefer the current browser
var uri = this._getManifestURI(gBrowser.mCurrentBrowser.contentWindow);
if (uri && uri.equals(aCacheUpdate.manifestURI)) {
return gBrowser.mCurrentBrowser;
}
var browsers = getBrowser().browsers;
for (var i = 0; i < browsers.length; ++i) {
uri = this._getManifestURI(browsers[i].contentWindow);
if (uri && uri.equals(aCacheUpdate.manifestURI)) {
return browsers[i];
}
}
return null;
},
_warnUsage: function(aBrowser, aURI) {
if (!aBrowser)
return;
var notificationBox = gBrowser.getNotificationBox(aBrowser);
var notification = notificationBox.getNotificationWithValue("offline-app-usage");
if (!notification) {
var bundle_browser = document.getElementById("bundle_browser");
var buttons = [{
label: bundle_browser.getString("offlineApps.manageUsage"),
accessKey: bundle_browser.getString("offlineApps.manageUsageAccessKey"),
callback: OfflineApps.manage
}];
var warnQuota = gPrefService.getIntPref("offline-apps.quota.warn");
const priority = notificationBox.PRIORITY_WARNING_MEDIUM;
var message = bundle_browser.getFormattedString("offlineApps.usage",
[ aURI.host,
warnQuota / 1024 ]);
notificationBox.appendNotification(message, "offline-app-usage",
"chrome://browser/skin/Info.png",
priority, buttons);
}
// Now that we've warned once, prevent the warning from showing up
// again.
var pm = Cc["@mozilla.org/permissionmanager;1"].
getService(Ci.nsIPermissionManager);
pm.add(aURI, "offline-app",
Ci.nsIOfflineCacheUpdateService.ALLOW_NO_WARN);
},
_checkUsage: function(aURI) {
var pm = Cc["@mozilla.org/permissionmanager;1"].
getService(Ci.nsIPermissionManager);
// if the user has already allowed excessive usage, don't bother checking
if (pm.testExactPermission(aURI, "offline-app") !=
Ci.nsIOfflineCacheUpdateService.ALLOW_NO_WARN) {
var usage = getOfflineAppUsage(aURI.asciiHost);
var warnQuota = gPrefService.getIntPref("offline-apps.quota.warn");
if (usage >= warnQuota * 1024) {
return true;
}
}
return false;
},
offlineAppRequested: function(aContentWindow) { offlineAppRequested: function(aContentWindow) {
if (!gPrefService.getBoolPref("browser.offline-apps.notify")) { if (!gPrefService.getBoolPref("browser.offline-apps.notify")) {
return; return;
@@ -5106,6 +5198,10 @@ var OfflineApps = {
pm.add(currentURI, "offline-app", Ci.nsIPermissionManager.DENY_ACTION); pm.add(currentURI, "offline-app", Ci.nsIPermissionManager.DENY_ACTION);
}, },
manage: function() {
openAdvancedPreferences("networkTab");
},
_startFetching: function() { _startFetching: function() {
var manifest = content.document.documentElement.getAttribute("manifest"); var manifest = content.document.documentElement.getAttribute("manifest");
if (!manifest) if (!manifest)
@@ -5121,6 +5217,37 @@ var OfflineApps = {
var updateService = Cc["@mozilla.org/offlinecacheupdate-service;1"]. var updateService = Cc["@mozilla.org/offlinecacheupdate-service;1"].
getService(Ci.nsIOfflineCacheUpdateService); getService(Ci.nsIOfflineCacheUpdateService);
updateService.scheduleUpdate(manifestURI, contentURI); updateService.scheduleUpdate(manifestURI, contentURI);
},
/////////////////////////////////////////////////////////////////////////////
// nsIObserver
observe: function (aSubject, aTopic, aState)
{
if (aTopic == "dom-storage-warn-quota-exceeded") {
if (aSubject) {
var uri = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService).
newURI(aSubject.location.href, null, null);
if (OfflineApps._checkUsage(uri)) {
var browserWindow =
this._getBrowserWindowForContentWindow(aSubject);
var browser = this._getBrowserForContentWindow(browserWindow,
aSubject);
OfflineApps._warnUsage(browser, uri);
}
}
} else if (aTopic == "offline-cache-update-completed") {
var cacheUpdate = aSubject.QueryInterface(Ci.nsIOfflineCacheUpdate);
var uri = cacheUpdate.manifestURI;
if (OfflineApps._checkUsage(uri)) {
var browser = this._getBrowserForCacheUpdate(cacheUpdate);
if (browser) {
OfflineApps._warnUsage(browser, cacheUpdate.manifestURI);
}
}
}
} }
}; };

View File

@@ -384,10 +384,28 @@ function openPreferences(paneID)
var pane = win.document.getElementById(paneID); var pane = win.document.getElementById(paneID);
win.document.documentElement.showPane(pane); win.document.documentElement.showPane(pane);
} }
return win;
}
return openDialog("chrome://browser/content/preferences/preferences.xul",
"Preferences", features, paneID);
}
function openAdvancedPreferences(tabID)
{
var win = openPreferences("paneAdvanced");
if (win) {
var selectTab = function() {
var tabs = win.document.getElementById("advancedPrefs");
tabs.selectedTab = win.document.getElementById(tabID);
}
if (win.document.getElementById("advancedPrefs")) {
selectTab();
} else {
win.addEventListener("load", selectTab, false);
}
} }
else
openDialog("chrome://browser/content/preferences/preferences.xul",
"Preferences", features, paneID);
} }
/** /**
@@ -637,3 +655,21 @@ function isValidFeed(aData, aPrincipal, aIsFeed)
return aIsFeed; return aIsFeed;
} }
function getOfflineAppUsage(host)
{
var cacheService = Components.classes["@mozilla.org/network/cache-service;1"].
getService(Components.interfaces.nsICacheService);
var cacheSession = cacheService.createSession("HTTP-offline",
Components.interfaces.nsICache.STORE_OFFLINE,
true).
QueryInterface(Components.interfaces.nsIOfflineCacheSession);
var usage = cacheSession.getDomainUsage(host);
var storageManager = Components.classes["@mozilla.org/dom/storagemanager;1"].
getService(Components.interfaces.nsIDOMStorageManager);
usage += storageManager.getUsage(host);
return usage;
}

View File

@@ -37,6 +37,9 @@
# #
# ***** END LICENSE BLOCK ***** # ***** END LICENSE BLOCK *****
// Load DownloadUtils module for convertByteUnits
Cu.import("resource://gre/modules/DownloadUtils.jsm");
var gAdvancedPane = { var gAdvancedPane = {
_inited: false, _inited: false,
@@ -217,6 +220,8 @@ var gAdvancedPane = {
list.removeChild(list.firstChild); list.removeChild(list.firstChild);
} }
var bundle = document.getElementById("bundlePreferences");
var enumerator = pm.enumerator; var enumerator = pm.enumerator;
while (enumerator.hasMoreElements()) { while (enumerator.hasMoreElements()) {
var perm = enumerator.getNext().QueryInterface(Components.interfaces.nsIPermission); var perm = enumerator.getNext().QueryInterface(Components.interfaces.nsIPermission);
@@ -225,9 +230,13 @@ var gAdvancedPane = {
perm.capability != Components.interfaces.nsIPermissionManager.DENY_ACTION) { perm.capability != Components.interfaces.nsIPermissionManager.DENY_ACTION) {
var row = document.createElement("listitem"); var row = document.createElement("listitem");
row.id = ""; row.id = "";
row.className = "listitem"; row.className = "offlineapp";
row.setAttribute("label", perm.host); row.setAttribute("host", perm.host);
var converted = DownloadUtils.
convertByteUnits(getOfflineAppUsage(perm.host));
row.setAttribute("usage",
bundle.getFormattedString("offlineAppUsage",
converted));
list.appendChild(row); list.appendChild(row);
} }
} }
@@ -248,7 +257,7 @@ var gAdvancedPane = {
{ {
var list = document.getElementById("offlineAppsList"); var list = document.getElementById("offlineAppsList");
var item = list.selectedItem; var item = list.selectedItem;
var host = item.getAttribute("label"); var host = item.getAttribute("host");
var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"] var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService); .getService(Components.interfaces.nsIPromptService);

View File

@@ -51,3 +51,7 @@ richlistitem[selected="true"] {
display: -moz-box; display: -moz-box;
min-width: 16px; min-width: 16px;
} }
listitem.offlineapp {
-moz-binding: url("chrome://browser/content/preferences/handlers.xml#offlineapp");
}

View File

@@ -100,4 +100,14 @@
</binding> </binding>
<binding id="offlineapp"
extends="chrome://global/content/bindings/listbox.xml#listitem">
<content>
<children>
<xul:listcell xbl:inherits="label=host"/>
<xul:listcell xbl:inherits="label=usage"/>
</children>
</content>
</binding>
</bindings> </bindings>

View File

@@ -135,7 +135,7 @@ GetQuota(const nsAString &aDomain, PRInt32 *aQuota, PRInt32 *aWarnQuota)
perm != nsIPermissionManager::DENY_ACTION) { perm != nsIPermissionManager::DENY_ACTION) {
// This is an offline app, give more space by default. // This is an offline app, give more space by default.
*aQuota = ((PRInt32)nsContentUtils::GetIntPref(kOfflineAppQuota, *aQuota = ((PRInt32)nsContentUtils::GetIntPref(kOfflineAppQuota,
DEFAULT_OFFLINE_WARN_QUOTA * 1024)); DEFAULT_OFFLINE_APP_QUOTA) * 1024);
if (perm == nsIOfflineCacheUpdateService::ALLOW_NO_WARN) { if (perm == nsIOfflineCacheUpdateService::ALLOW_NO_WARN) {
*aWarnQuota = -1; *aWarnQuota = -1;