diff options
Diffstat (limited to 'application/basilisk/components/preferences/SiteDataManager.jsm')
-rw-r--r-- | application/basilisk/components/preferences/SiteDataManager.jsm | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/application/basilisk/components/preferences/SiteDataManager.jsm b/application/basilisk/components/preferences/SiteDataManager.jsm new file mode 100644 index 0000000000..a86aafef01 --- /dev/null +++ b/application/basilisk/components/preferences/SiteDataManager.jsm @@ -0,0 +1,205 @@ +"use strict"; + +const { classes: Cc, interfaces: Ci, utils: Cu } = Components; + +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); + +XPCOMUtils.defineLazyModuleGetter(this, "OfflineAppCacheHelper", + "resource:///modules/offlineAppCache.jsm"); + +this.EXPORTED_SYMBOLS = [ + "SiteDataManager" +]; + +this.SiteDataManager = { + + _qms: Services.qms, + + _diskCache: Services.cache2.diskCacheStorage(Services.loadContextInfo.default, false), + + _appCache: Cc["@mozilla.org/network/application-cache-service;1"].getService(Ci.nsIApplicationCacheService), + + // A Map of sites using the persistent-storage API (have requested persistent-storage permission) + // Key is site's origin. + // Value is one object holding: + // - perm: persistent-storage permision; instance of nsIPermission + // - status: the permission granted/rejected status + // - quotaUsage: the usage of indexedDB and localStorage. + // - appCacheList: an array of app cache; instances of nsIApplicationCache + // - diskCacheList: an array. Each element is object holding metadata of http cache: + // - dataSize: that http cache size + // - idEnhance: the id extension of that http cache + _sites: new Map(), + + _updateQuotaPromise: null, + + _updateDiskCachePromise: null, + + _quotaUsageRequests: null, + + updateSites() { + // Clear old data and requests first + this._sites.clear(); + this._cancelQuotaUpdate(); + + // Collect sites granted/rejected with the persistent-storage permission + let perm = null; + let status = null; + let e = Services.perms.enumerator; + while (e.hasMoreElements()) { + perm = e.getNext(); + status = Services.perms.testExactPermissionFromPrincipal(perm.principal, "persistent-storage"); + if (status === Ci.nsIPermissionManager.ALLOW_ACTION || + status === Ci.nsIPermissionManager.DENY_ACTION) { + this._sites.set(perm.principal.origin, { + perm, + status, + quotaUsage: 0, + appCacheList: [], + diskCacheList: [] + }); + } + } + + this._updateQuota(); + this._updateAppCache(); + this._updateDiskCache(); + + Promise.all([this._updateQuotaPromise, this._updateDiskCachePromise]) + .then(() => { + Services.obs.notifyObservers(null, "sitedatamanager:sites-updated", null); + }); + }, + + _updateQuota() { + this._quotaUsageRequests = []; + let promises = []; + for (let site of this._sites.values()) { + promises.push(new Promise(resolve => { + let callback = { + onUsageResult(request) { + site.quotaUsage = request.usage; + resolve(); + } + }; + // XXX: The work of integrating localStorage into Quota Manager is in progress. + // After the bug 742822 and 1286798 landed, localStorage usage will be included. + // So currently only get indexedDB usage. + this._quotaUsageRequests.push( + this._qms.getUsageForPrincipal(site.perm.principal, callback)); + })); + } + this._updateQuotaPromise = Promise.all(promises); + }, + + _cancelQuotaUpdate() { + if (this._quotaUsageRequests) { + for (let request of this._quotaUsageRequests) { + request.cancel(); + } + this._quotaUsageRequests = null; + } + }, + + _updateAppCache() { + let groups = this._appCache.getGroups(); + for (let site of this._sites.values()) { + for (let group of groups) { + let uri = Services.io.newURI(group); + if (site.perm.matchesURI(uri, true)) { + let cache = this._appCache.getActiveCache(group); + site.appCacheList.push(cache); + } + } + } + }, + + _updateDiskCache() { + this._updateDiskCachePromise = new Promise(resolve => { + if (this._sites.size) { + let sites = this._sites; + let visitor = { + onCacheEntryInfo(uri, idEnhance, dataSize) { + for (let site of sites.values()) { + if (site.perm.matchesURI(uri, true)) { + site.diskCacheList.push({ + dataSize, + idEnhance + }); + break; + } + } + }, + onCacheEntryVisitCompleted() { + resolve(); + } + }; + this._diskCache.asyncVisitStorage(visitor, true); + } else { + resolve(); + } + }); + }, + + getTotalUsage() { + return Promise.all([this._updateQuotaPromise, this._updateDiskCachePromise]) + .then(() => { + let usage = 0; + for (let site of this._sites.values()) { + let cache = null; + for (cache of site.appCacheList) { + usage += cache.usage; + } + for (cache of site.diskCacheList) { + usage += cache.dataSize; + } + usage += site.quotaUsage; + } + return usage; + }); + }, + + _removePermission(site) { + Services.perms.removePermission(site.perm); + }, + + _removeQuotaUsage(site) { + this._qms.clearStoragesForPrincipal(site.perm.principal, null, true); + }, + + removeAll() { + for (let site of this._sites.values()) { + this._removePermission(site); + this._removeQuotaUsage(site); + } + Services.cache2.clear(); + Services.cookies.removeAll(); + OfflineAppCacheHelper.clear(); + this.updateSites(); + }, + + getSites() { + return Promise.all([this._updateQuotaPromise, this._updateDiskCachePromise]) + .then(() => { + let list = []; + for (let [origin, site] of this._sites) { + let cache = null; + let usage = site.quotaUsage; + for (cache of site.appCacheList) { + usage += cache.usage; + } + for (cache of site.diskCacheList) { + usage += cache.dataSize; + } + list.push({ + usage, + status: site.status, + uri: NetUtil.newURI(origin) + }); + } + return list; + }); + } +}; |