зеркало из https://github.com/mozilla/gecko-dev.git
Bug 913807 - HTTP cache v2: API+top service+integration+tests, off by default, r=michal+ehsan+mark.finkle+fabrice+mhammond+gavin
This commit is contained in:
Родитель
d1b254f231
Коммит
894ba59236
|
@ -25,6 +25,8 @@ pref("browser.cache.disk.smart_size.first_run", false);
|
|||
pref("browser.cache.memory.enable", true);
|
||||
pref("browser.cache.memory.capacity", 1024); // kilobytes
|
||||
|
||||
pref("browser.cache.memory_limit", 2048); // 2 MB
|
||||
|
||||
/* image cache prefs */
|
||||
pref("image.cache.size", 1048576); // bytes
|
||||
pref("image.high_quality_downscaling.enabled", false);
|
||||
|
|
|
@ -254,6 +254,7 @@
|
|||
@BINPATH@/components/mozfind.xpt
|
||||
@BINPATH@/components/necko_about.xpt
|
||||
@BINPATH@/components/necko_cache.xpt
|
||||
@BINPATH@/components/necko_cache2.xpt
|
||||
@BINPATH@/components/necko_cookie.xpt
|
||||
@BINPATH@/components/necko_dns.xpt
|
||||
@BINPATH@/components/necko_file.xpt
|
||||
|
|
|
@ -2,6 +2,10 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const Cu = Components.utils;
|
||||
Cu.import("resource://gre/modules/LoadContextInfo.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
//******** define a js object to implement nsITreeView
|
||||
function pageInfoTreeView(treeid, copycol)
|
||||
{
|
||||
|
@ -216,13 +220,15 @@ const ATOM_CONTRACTID = "@mozilla.org/atom-service;1";
|
|||
|
||||
// a number of services I'll need later
|
||||
// the cache services
|
||||
const nsICacheService = Components.interfaces.nsICacheService;
|
||||
const ACCESS_READ = Components.interfaces.nsICache.ACCESS_READ;
|
||||
const cacheService = Components.classes["@mozilla.org/network/cache-service;1"].getService(nsICacheService);
|
||||
var httpCacheSession = cacheService.createSession("HTTP", 0, true);
|
||||
httpCacheSession.doomEntriesIfExpired = false;
|
||||
var ftpCacheSession = cacheService.createSession("FTP", 0, true);
|
||||
ftpCacheSession.doomEntriesIfExpired = false;
|
||||
const nsICacheStorageService = Components.interfaces.nsICacheStorageService;
|
||||
const nsICacheStorage = Components.interfaces.nsICacheStorage;
|
||||
const cacheService = Components.classes["@mozilla.org/netwerk/cache-storage-service;1"].getService(nsICacheStorageService);
|
||||
|
||||
var loadContextInfo = LoadContextInfo.fromLoadContext(
|
||||
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIWebNavigation)
|
||||
.QueryInterface(Components.interfaces.nsILoadContext), false);
|
||||
var diskStorage = cacheService.diskCacheStorage(loadContextInfo, false);
|
||||
|
||||
const nsICookiePermission = Components.interfaces.nsICookiePermission;
|
||||
const nsIPermissionManager = Components.interfaces.nsIPermissionManager;
|
||||
|
@ -463,19 +469,16 @@ function toggleGroupbox(id)
|
|||
|
||||
function openCacheEntry(key, cb)
|
||||
{
|
||||
var tries = 0;
|
||||
var checkCacheListener = {
|
||||
onCacheEntryAvailable: function(entry, access, status) {
|
||||
if (entry || tries == 1) {
|
||||
cb(entry);
|
||||
}
|
||||
else {
|
||||
tries++;
|
||||
ftpCacheSession.asyncOpenCacheEntry(key, ACCESS_READ, this, true);
|
||||
}
|
||||
}
|
||||
onCacheEntryCheck: function(entry, appCache) {
|
||||
return nsICacheEntryOpenCallback.ENTRY_VALID;
|
||||
},
|
||||
onCacheEntryAvailable: function(entry, isNew, appCache, status) {
|
||||
cb(entry);
|
||||
},
|
||||
get mainThreadOnly() { return true; }
|
||||
};
|
||||
httpCacheSession.asyncOpenCacheEntry(key, ACCESS_READ, checkCacheListener, true);
|
||||
diskStorage.asyncOpenURI(Services.io.newURI(key, null, null), "", nsICacheStorage.OPEN_READONLY, checkCacheListener);
|
||||
}
|
||||
|
||||
function makeGeneralTab()
|
||||
|
|
|
@ -113,12 +113,12 @@ Sanitizer.prototype = {
|
|||
cache: {
|
||||
clear: function ()
|
||||
{
|
||||
var cacheService = Cc["@mozilla.org/network/cache-service;1"].
|
||||
getService(Ci.nsICacheService);
|
||||
var cache = Cc["@mozilla.org/netwerk/cache-storage-service;1"].
|
||||
getService(Ci.nsICacheStorageService);
|
||||
try {
|
||||
// Cache doesn't consult timespan, nor does it have the
|
||||
// facility for timespan-based eviction. Wipe it.
|
||||
cacheService.evictEntries(Ci.nsICache.STORE_ANYWHERE);
|
||||
cache.clear();
|
||||
} catch(er) {}
|
||||
|
||||
var imageCache = Cc["@mozilla.org/image/tools;1"].
|
||||
|
|
|
@ -59,7 +59,7 @@ function generatorTest() {
|
|||
});
|
||||
|
||||
// LOAD_FLAGS_BYPASS_CACHE isn't good enough. So clear the cache.
|
||||
Services.cache.evictEntries(Services.cache.STORE_ANYWHERE);
|
||||
Services.cache2.clear();
|
||||
|
||||
let [uri, title] = tests[0];
|
||||
content.location = uri;
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
let {LoadContextInfo} = Cu.import("resource://gre/modules/LoadContextInfo.jsm", null);
|
||||
|
||||
function test() {
|
||||
// initialization
|
||||
waitForExplicitFinish();
|
||||
|
@ -8,27 +11,33 @@ function test() {
|
|||
let testURI = "http://mochi.test:8888/browser/browser/base/content/test/general/bug792517.html";
|
||||
let fileName;
|
||||
let MockFilePicker = SpecialPowers.MockFilePicker;
|
||||
let cache = Cc["@mozilla.org/network/cache-service;1"]
|
||||
.getService(Ci.nsICacheService);
|
||||
let cache = Cc["@mozilla.org/netwerk/cache-storage-service;1"]
|
||||
.getService(Ci.nsICacheStorageService);
|
||||
|
||||
function checkDiskCacheFor(filename) {
|
||||
let visitor = {
|
||||
visitDevice: function(deviceID, deviceInfo) {
|
||||
if (deviceID == "disk")
|
||||
info(deviceID + " device contains " + deviceInfo.entryCount + " entries");
|
||||
return deviceID == "disk";
|
||||
function checkDiskCacheFor(filename, goon) {
|
||||
Visitor.prototype = {
|
||||
onCacheStorageInfo: function(num, consumption)
|
||||
{
|
||||
info("disk storage contains " + num + " entries");
|
||||
},
|
||||
|
||||
visitEntry: function(deviceID, entryInfo) {
|
||||
info(entryInfo.key);
|
||||
is(entryInfo.key.contains(filename), false, "web content present in disk cache");
|
||||
onCacheEntryInfo: function(entry)
|
||||
{
|
||||
info(entry.key);
|
||||
is(entry.key.contains(filename), false, "web content present in disk cache");
|
||||
},
|
||||
onCacheEntryVisitCompleted: function()
|
||||
{
|
||||
goon();
|
||||
}
|
||||
};
|
||||
cache.visitEntries(visitor);
|
||||
function Visitor() {}
|
||||
|
||||
var storage = cache.diskCacheStorage(LoadContextInfo.default, false);
|
||||
storage.asyncVisitStorage(new Visitor(), true /* Do walk entries */);
|
||||
}
|
||||
|
||||
function contextMenuOpened(aWindow, event) {
|
||||
cache.evictEntries(Ci.nsICache.STORE_ANYWHERE);
|
||||
cache.clear();
|
||||
|
||||
event.currentTarget.removeEventListener("popupshown", contextMenuOpened);
|
||||
|
||||
|
@ -65,8 +74,7 @@ function test() {
|
|||
|
||||
// Give the request a chance to finish and create a cache entry
|
||||
executeSoon(function() {
|
||||
checkDiskCacheFor(fileName);
|
||||
finish();
|
||||
checkDiskCacheFor(fileName, finish);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ function goOffline() {
|
|||
BrowserOffline.toggleOfflineStatus();
|
||||
Services.prefs.setIntPref('network.proxy.type', 0);
|
||||
// LOAD_FLAGS_BYPASS_CACHE isn't good enough. So clear the cache.
|
||||
Services.cache.evictEntries(Components.interfaces.nsICache.STORE_ANYWHERE);
|
||||
Services.cache2.clear();
|
||||
}
|
||||
|
||||
function goOnline(callback) {
|
||||
|
|
|
@ -9,6 +9,7 @@ const Cr = Components.results;
|
|||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/LoadContextInfo.jsm");
|
||||
|
||||
// Import common head.
|
||||
let (commonFile = do_get_file("../../../../../toolkit/components/places/tests/head_common.js", false)) {
|
||||
|
|
|
@ -134,13 +134,15 @@ function getDistinctNotifications() {
|
|||
}
|
||||
|
||||
function storeCache(aURL, aContent) {
|
||||
let cache = Cc["@mozilla.org/network/cache-service;1"].
|
||||
getService(Ci.nsICacheService);
|
||||
let session = cache.createSession("FTP", Ci.nsICache.STORE_ANYWHERE,
|
||||
Ci.nsICache.STREAM_BASED);
|
||||
let cache = Services.cache2;
|
||||
let storage = cache.diskCacheStorage(LoadContextInfo.default, false);
|
||||
|
||||
var storeCacheListener = {
|
||||
onCacheEntryAvailable: function (entry, access, status) {
|
||||
onCacheEntryCheck: function (entry, appcache) {
|
||||
return nsICacheEntryOpenCallback.ENTRY_VALID;
|
||||
},
|
||||
|
||||
onCacheEntryAvailable: function (entry, isnew, appcache, status) {
|
||||
do_check_eq(status, Cr.NS_OK);
|
||||
|
||||
entry.setMetaDataElement("servertype", "0");
|
||||
|
@ -158,26 +160,24 @@ function storeCache(aURL, aContent) {
|
|||
}
|
||||
};
|
||||
|
||||
session.asyncOpenCacheEntry(aURL,
|
||||
Ci.nsICache.ACCESS_READ_WRITE,
|
||||
storeCacheListener);
|
||||
storage.asyncOpenURI(Services.io.newURI(aURL, null, null), "",
|
||||
Ci.nsICacheStorage.OPEN_NORMALLY,
|
||||
storeCacheListener);
|
||||
}
|
||||
|
||||
|
||||
function checkCache(aURL) {
|
||||
let cache = Cc["@mozilla.org/network/cache-service;1"].
|
||||
getService(Ci.nsICacheService);
|
||||
let session = cache.createSession("FTP", Ci.nsICache.STORE_ANYWHERE,
|
||||
Ci.nsICache.STREAM_BASED);
|
||||
let cache = Services.cache2;
|
||||
let storage = cache.diskCacheStorage(LoadContextInfo.default, false);
|
||||
|
||||
var checkCacheListener = {
|
||||
onCacheEntryAvailable: function (entry, access, status) {
|
||||
onCacheEntryAvailable: function (entry, isnew, appcache, status) {
|
||||
do_check_eq(status, Cr.NS_ERROR_CACHE_KEY_NOT_FOUND);
|
||||
do_test_finished();
|
||||
}
|
||||
};
|
||||
|
||||
session.asyncOpenCacheEntry(aURL,
|
||||
Ci.nsICache.ACCESS_READ,
|
||||
checkCacheListener);
|
||||
storage.asyncOpenURI(Services.io.newURI(aURL, null, null), "",
|
||||
Ci.nsICacheStorage.OPEN_READONLY,
|
||||
checkCacheListener);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
Components.utils.import("resource://gre/modules/DownloadUtils.jsm");
|
||||
Components.utils.import("resource://gre/modules/ctypes.jsm");
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource://gre/modules/LoadContextInfo.jsm");
|
||||
|
||||
var gAdvancedPane = {
|
||||
_inited: false,
|
||||
|
@ -77,8 +78,8 @@ var gAdvancedPane = {
|
|||
this.initSubmitHealthReport();
|
||||
#endif
|
||||
|
||||
this.updateActualCacheSize("disk");
|
||||
this.updateActualCacheSize("offline");
|
||||
this.updateActualCacheSize();
|
||||
this.updateActualAppCacheSize();
|
||||
|
||||
// Notify observers that the UI is now ready
|
||||
Services.obs.notifyObservers(window, "advanced-pane-loaded", null);
|
||||
|
@ -296,22 +297,64 @@ var gAdvancedPane = {
|
|||
"", null);
|
||||
},
|
||||
|
||||
// Retrieves the amount of space currently used by disk or offline cache
|
||||
updateActualCacheSize: function (device)
|
||||
// Retrieves the amount of space currently used by disk cache
|
||||
updateActualCacheSize: function ()
|
||||
{
|
||||
var sum = 0;
|
||||
function updateUI(consumption) {
|
||||
var actualSizeLabel = document.getElementById("actualDiskCacheSize");
|
||||
var sizeStrings = DownloadUtils.convertByteUnits(consumption);
|
||||
var prefStrBundle = document.getElementById("bundlePreferences");
|
||||
var sizeStr = prefStrBundle.getFormattedString("actualDiskCacheSize", sizeStrings);
|
||||
actualSizeLabel.value = sizeStr;
|
||||
}
|
||||
|
||||
Visitor.prototype = {
|
||||
expected: 0,
|
||||
sum: 0,
|
||||
QueryInterface: function listener_qi(iid) {
|
||||
if (iid.equals(Ci.nsISupports) ||
|
||||
iid.equals(Ci.nsICacheStorageVisitor)) {
|
||||
return this;
|
||||
}
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
onCacheStorageInfo: function(num, consumption)
|
||||
{
|
||||
this.sum += consumption;
|
||||
if (!--this.expected)
|
||||
updateUI(this.sum);
|
||||
}
|
||||
};
|
||||
function Visitor(callbacksExpected) {
|
||||
this.expected = callbacksExpected;
|
||||
}
|
||||
|
||||
var cacheService =
|
||||
Components.classes["@mozilla.org/netwerk/cache-storage-service;1"]
|
||||
.getService(Components.interfaces.nsICacheStorageService);
|
||||
// non-anonymous
|
||||
var storage1 = cacheService.diskCacheStorage(LoadContextInfo.default, false);
|
||||
// anonymous
|
||||
var storage2 = cacheService.diskCacheStorage(LoadContextInfo.anonymous, false);
|
||||
|
||||
// expect 2 callbacks
|
||||
var visitor = new Visitor(2);
|
||||
storage1.asyncVisitStorage(visitor, false /* Do not walk entries */);
|
||||
storage2.asyncVisitStorage(visitor, false /* Do not walk entries */);
|
||||
},
|
||||
|
||||
// Retrieves the amount of space currently used by offline cache
|
||||
updateActualAppCacheSize: function ()
|
||||
{
|
||||
var visitor = {
|
||||
visitDevice: function (deviceID, deviceInfo)
|
||||
{
|
||||
if (deviceID == device) {
|
||||
var actualSizeLabel = document.getElementById(device == "disk" ?
|
||||
"actualDiskCacheSize" :
|
||||
"actualAppCacheSize");
|
||||
if (deviceID == "offline") {
|
||||
var actualSizeLabel = document.getElementById("actualAppCacheSize");
|
||||
var sizeStrings = DownloadUtils.convertByteUnits(deviceInfo.totalSize);
|
||||
var prefStrBundle = document.getElementById("bundlePreferences");
|
||||
var sizeStr = prefStrBundle.getFormattedString(device == "disk" ?
|
||||
"actualDiskCacheSize" :
|
||||
"actualAppCacheSize",
|
||||
sizeStrings);
|
||||
var sizeStr = prefStrBundle.getFormattedString("actualAppCacheSize", sizeStrings);
|
||||
actualSizeLabel.value = sizeStr;
|
||||
}
|
||||
// Do not enumerate entries
|
||||
|
@ -372,12 +415,12 @@ var gAdvancedPane = {
|
|||
*/
|
||||
clearCache: function ()
|
||||
{
|
||||
var cacheService = Components.classes["@mozilla.org/network/cache-service;1"]
|
||||
.getService(Components.interfaces.nsICacheService);
|
||||
var cache = Components.classes["@mozilla.org/netwerk/cache-storage-service;1"]
|
||||
.getService(Components.interfaces.nsICacheStorageService);
|
||||
try {
|
||||
cacheService.evictEntries(Components.interfaces.nsICache.STORE_ANYWHERE);
|
||||
cache.clear();
|
||||
} catch(ex) {}
|
||||
this.updateActualCacheSize("disk");
|
||||
this.updateActualCacheSize();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -388,7 +431,7 @@ var gAdvancedPane = {
|
|||
Components.utils.import("resource:///modules/offlineAppCache.jsm");
|
||||
OfflineAppCacheHelper.clear();
|
||||
|
||||
this.updateActualCacheSize("offline");
|
||||
this.updateActualAppCacheSize();
|
||||
this.updateOfflineApps();
|
||||
},
|
||||
|
||||
|
@ -533,7 +576,7 @@ var gAdvancedPane = {
|
|||
|
||||
list.removeChild(item);
|
||||
gAdvancedPane.offlineAppSelected();
|
||||
this.updateActualCacheSize("offline");
|
||||
this.updateActualAppCacheSize();
|
||||
},
|
||||
|
||||
// UPDATE TAB
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
// Load DownloadUtils module for convertByteUnits
|
||||
Components.utils.import("resource://gre/modules/DownloadUtils.jsm");
|
||||
Components.utils.import("resource://gre/modules/LoadContextInfo.jsm");
|
||||
|
||||
var gAdvancedPane = {
|
||||
_inited: false,
|
||||
|
@ -67,8 +68,8 @@ var gAdvancedPane = {
|
|||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
this.initSubmitHealthReport();
|
||||
#endif
|
||||
this.updateActualCacheSize("disk");
|
||||
this.updateActualCacheSize("offline");
|
||||
this.updateActualCacheSize();
|
||||
this.updateActualAppCacheSize();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -278,22 +279,67 @@ var gAdvancedPane = {
|
|||
null);
|
||||
},
|
||||
|
||||
// Retrieves the amount of space currently used by disk or offline cache
|
||||
updateActualCacheSize: function (device)
|
||||
// Retrieves the amount of space currently used by disk cache
|
||||
updateActualCacheSize: function ()
|
||||
{
|
||||
var sum = 0;
|
||||
function updateUI(consumption) {
|
||||
var actualSizeLabel = document.getElementById("actualDiskCacheSize");
|
||||
var sizeStrings = DownloadUtils.convertByteUnits(consumption);
|
||||
var prefStrBundle = document.getElementById("bundlePreferences");
|
||||
var sizeStr = prefStrBundle.getFormattedString("actualDiskCacheSize", sizeStrings);
|
||||
actualSizeLabel.value = sizeStr;
|
||||
}
|
||||
|
||||
Visitor.prototype = {
|
||||
expected: 0,
|
||||
sum: 0,
|
||||
QueryInterface: function listener_qi(iid) {
|
||||
if (iid.equals(Ci.nsISupports) ||
|
||||
iid.equals(Ci.nsICacheStorageVisitor)) {
|
||||
return this;
|
||||
}
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
onCacheStorageInfo: function(num, consumption)
|
||||
{
|
||||
this.sum += consumption;
|
||||
if (!--this.expected)
|
||||
updateUI(this.sum);
|
||||
},
|
||||
onCacheEntryInfo: function(entry)
|
||||
{
|
||||
}
|
||||
};
|
||||
function Visitor(callbacksExpected) {
|
||||
this.expected = callbacksExpected;
|
||||
}
|
||||
|
||||
var cacheService =
|
||||
Components.classes["@mozilla.org/netwerk/cache-storage-service;1"]
|
||||
.getService(Components.interfaces.nsICacheStorageService);
|
||||
// non-anonymous
|
||||
var storage1 = cacheService.diskCacheStorage(LoadContextInfo.default, false);
|
||||
// anonymous
|
||||
var storage2 = cacheService.diskCacheStorage(LoadContextInfo.anonymous, false);
|
||||
|
||||
// expect 2 callbacks
|
||||
var visitor = new Visitor(2);
|
||||
storage1.asyncVisitStorage(visitor, false /* Do not walk entries */);
|
||||
storage2.asyncVisitStorage(visitor, false /* Do not walk entries */);
|
||||
},
|
||||
|
||||
// Retrieves the amount of space currently used by offline cache
|
||||
updateActualAppCacheSize: function ()
|
||||
{
|
||||
var visitor = {
|
||||
visitDevice: function (deviceID, deviceInfo)
|
||||
{
|
||||
if (deviceID == device) {
|
||||
var actualSizeLabel = document.getElementById(device == "disk" ?
|
||||
"actualDiskCacheSize" :
|
||||
"actualAppCacheSize");
|
||||
if (deviceID == "offline") {
|
||||
var actualSizeLabel = document.getElementById("actualAppCacheSize");
|
||||
var sizeStrings = DownloadUtils.convertByteUnits(deviceInfo.totalSize);
|
||||
var prefStrBundle = document.getElementById("bundlePreferences");
|
||||
var sizeStr = prefStrBundle.getFormattedString(device == "disk" ?
|
||||
"actualDiskCacheSize" :
|
||||
"actualAppCacheSize",
|
||||
sizeStrings);
|
||||
var sizeStr = prefStrBundle.getFormattedString("actualAppCacheSize", sizeStrings);
|
||||
actualSizeLabel.value = sizeStr;
|
||||
}
|
||||
// Do not enumerate entries
|
||||
|
@ -359,7 +405,7 @@ var gAdvancedPane = {
|
|||
try {
|
||||
cacheService.evictEntries(Components.interfaces.nsICache.STORE_ANYWHERE);
|
||||
} catch(ex) {}
|
||||
this.updateActualCacheSize("disk");
|
||||
this.updateActualCacheSize();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -370,7 +416,7 @@ var gAdvancedPane = {
|
|||
Components.utils.import("resource:///modules/offlineAppCache.jsm");
|
||||
OfflineAppCacheHelper.clear();
|
||||
|
||||
this.updateActualCacheSize("offline");
|
||||
this.updateActualAppCacheSize();
|
||||
this.updateOfflineApps();
|
||||
},
|
||||
|
||||
|
@ -516,7 +562,7 @@ var gAdvancedPane = {
|
|||
|
||||
list.removeChild(item);
|
||||
gAdvancedPane.offlineAppSelected();
|
||||
this.updateActualCacheSize("offline");
|
||||
this.updateActualAppCacheSize();
|
||||
},
|
||||
|
||||
// UPDATE TAB
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
// This test covers MozTrap test 6047
|
||||
// bug 880621
|
||||
|
||||
let {LoadContextInfo} = Cu.import("resource://gre/modules/LoadContextInfo.jsm", null);
|
||||
|
||||
let tmp = {};
|
||||
|
||||
Cc["@mozilla.org/moz/jssubscript-loader;1"]
|
||||
|
@ -20,10 +22,11 @@ function test() {
|
|||
|
||||
sanitizeCache();
|
||||
|
||||
let nrEntriesR1 = get_device_entry_count("disk");
|
||||
is (nrEntriesR1, 0, "Disk cache reports 0KB and has no entries");
|
||||
let nrEntriesR1 = getStorageEntryCount("regular", function(nrEntriesR1) {
|
||||
is(nrEntriesR1, 0, "Disk cache reports 0KB and has no entries");
|
||||
|
||||
get_cache_for_private_window();
|
||||
get_cache_for_private_window();
|
||||
});
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
|
@ -61,29 +64,42 @@ function sanitizeCache() {
|
|||
}
|
||||
|
||||
function get_cache_service() {
|
||||
return Components.classes["@mozilla.org/network/cache-service;1"]
|
||||
.getService(Components.interfaces.nsICacheService);
|
||||
return Components.classes["@mozilla.org/netwerk/cache-storage-service;1"]
|
||||
.getService(Components.interfaces.nsICacheStorageService);
|
||||
}
|
||||
|
||||
function get_device_entry_count(device) {
|
||||
function getStorageEntryCount(device, goon) {
|
||||
var cs = get_cache_service();
|
||||
var entry_count = -1;
|
||||
|
||||
var storage;
|
||||
switch (device) {
|
||||
case "private":
|
||||
storage = cs.diskCacheStorage(LoadContextInfo.private, false);
|
||||
break;
|
||||
case "regular":
|
||||
storage = cs.diskCacheStorage(LoadContextInfo.default, false);
|
||||
break;
|
||||
default:
|
||||
throw "Unknown device " + device + " at getStorageEntryCount";
|
||||
}
|
||||
|
||||
var visitor = {
|
||||
visitDevice: function (deviceID, deviceInfo) {
|
||||
if (device == deviceID) {
|
||||
entry_count = deviceInfo.entryCount;
|
||||
}
|
||||
return false;
|
||||
entryCount: 0,
|
||||
onCacheStorageInfo: function (aEntryCount, aConsumption) {
|
||||
},
|
||||
visitEntry: function (deviceID, entryInfo) {
|
||||
do_throw("nsICacheVisitor.visitEntry should not be called " +
|
||||
"when checking the availability of devices");
|
||||
onCacheEntryInfo: function(entry)
|
||||
{
|
||||
info(device + ":" + entry.key + "\n");
|
||||
if (entry.key.match(/^http:\/\/example.org\//))
|
||||
++this.entryCount;
|
||||
},
|
||||
onCacheEntryVisitCompleted: function()
|
||||
{
|
||||
goon(this.entryCount);
|
||||
}
|
||||
};
|
||||
|
||||
cs.visitEntries(visitor);
|
||||
return entry_count;
|
||||
storage.asyncVisitStorage(visitor, true);
|
||||
}
|
||||
|
||||
function get_cache_for_private_window () {
|
||||
|
@ -104,16 +120,18 @@ function get_cache_for_private_window () {
|
|||
|
||||
executeSoon(function() {
|
||||
|
||||
let nrEntriesP = get_device_entry_count("memory");
|
||||
is (nrEntriesP, 1, "Memory cache reports some entries from example.org domain");
|
||||
getStorageEntryCount("private", function(nrEntriesP) {
|
||||
ok(nrEntriesP >= 1, "Memory cache reports some entries from example.org domain");
|
||||
|
||||
let nrEntriesR2 = get_device_entry_count("disk");
|
||||
is (nrEntriesR2, 0, "Disk cache reports 0KB and has no entries");
|
||||
getStorageEntryCount("regular", function(nrEntriesR2) {
|
||||
is(nrEntriesR2, 0, "Disk cache reports 0KB and has no entries");
|
||||
|
||||
cleanup();
|
||||
cleanup();
|
||||
|
||||
win.close();
|
||||
finish();
|
||||
win.close();
|
||||
finish();
|
||||
});
|
||||
});
|
||||
});
|
||||
}, true);
|
||||
});
|
||||
|
|
|
@ -13,16 +13,16 @@ function test() {
|
|||
let testURI = 'http://' + TEST_HOST + '/browser/browser/devtools/styleeditor/test/test_private.html';
|
||||
|
||||
function checkCache() {
|
||||
checkDiskCacheFor(TEST_HOST);
|
||||
|
||||
gUI = null;
|
||||
finish();
|
||||
checkDiskCacheFor(TEST_HOST, function() {
|
||||
gUI = null;
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
||||
function doTest(aWindow) {
|
||||
aWindow.gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
|
||||
aWindow.gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
|
||||
cache.evictEntries(Ci.nsICache.STORE_ANYWHERE);
|
||||
cache.clear();
|
||||
openStyleEditorInWindow(aWindow, function(panel) {
|
||||
gUI = panel.UI;
|
||||
gUI.on("editor-added", onEditorAdded);
|
||||
|
|
|
@ -9,12 +9,14 @@ const TEST_HOST = 'mochi.test:8888';
|
|||
let tempScope = {};
|
||||
Cu.import("resource://gre/modules/devtools/Loader.jsm", tempScope);
|
||||
let TargetFactory = tempScope.devtools.TargetFactory;
|
||||
Components.utils.import("resource://gre/modules/devtools/Console.jsm", tempScope);
|
||||
Cu.import("resource://gre/modules/LoadContextInfo.jsm", tempScope);
|
||||
let LoadContextInfo = tempScope.LoadContextInfo;
|
||||
Cu.import("resource://gre/modules/devtools/Console.jsm", tempScope);
|
||||
let console = tempScope.console;
|
||||
|
||||
let gPanelWindow;
|
||||
let cache = Cc["@mozilla.org/network/cache-service;1"]
|
||||
.getService(Ci.nsICacheService);
|
||||
let cache = Cc["@mozilla.org/netwerk/cache-storage-service;1"]
|
||||
.getService(Ci.nsICacheStorageService);
|
||||
|
||||
|
||||
// Import the GCLI test helper
|
||||
|
@ -84,25 +86,30 @@ function addTabAndLaunchStyleEditorChromeWhenLoaded(aCallback, aSheet, aLine, aC
|
|||
}
|
||||
*/
|
||||
|
||||
function checkDiskCacheFor(host)
|
||||
function checkDiskCacheFor(host, done)
|
||||
{
|
||||
let foundPrivateData = false;
|
||||
|
||||
let visitor = {
|
||||
visitDevice: function(deviceID, deviceInfo) {
|
||||
if (deviceID == "disk")
|
||||
info("disk device contains " + deviceInfo.entryCount + " entries");
|
||||
return deviceID == "disk";
|
||||
Visitor.prototype = {
|
||||
onCacheStorageInfo: function(num, consumption)
|
||||
{
|
||||
info("disk storage contains " + num + " entries");
|
||||
},
|
||||
|
||||
visitEntry: function(deviceID, entryInfo) {
|
||||
info(entryInfo.key);
|
||||
foundPrivateData |= entryInfo.key.contains(host);
|
||||
onCacheEntryInfo: function(entry)
|
||||
{
|
||||
info(entry.key);
|
||||
foundPrivateData |= entry.key.contains(host);
|
||||
},
|
||||
onCacheEntryVisitCompleted: function()
|
||||
{
|
||||
is(foundPrivateData, false, "web content present in disk cache");
|
||||
done();
|
||||
}
|
||||
};
|
||||
cache.visitEntries(visitor);
|
||||
is(foundPrivateData, false, "private data present in disk cache");
|
||||
function Visitor() {}
|
||||
|
||||
var storage = cache.diskCacheStorage(LoadContextInfo.default, false);
|
||||
storage.asyncVisitStorage(new Visitor(), true /* Do walk entries */);
|
||||
}
|
||||
|
||||
registerCleanupFunction(cleanup);
|
||||
|
|
|
@ -263,6 +263,7 @@
|
|||
@BINPATH@/components/mozfind.xpt
|
||||
@BINPATH@/components/necko_about.xpt
|
||||
@BINPATH@/components/necko_cache.xpt
|
||||
@BINPATH@/components/necko_cache2.xpt
|
||||
@BINPATH@/components/necko_cookie.xpt
|
||||
@BINPATH@/components/necko_dns.xpt
|
||||
@BINPATH@/components/necko_file.xpt
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "LoadContextInfo",
|
||||
"resource://gre/modules/LoadContextInfo.jsm");
|
||||
function Sanitizer() {}
|
||||
|
||||
Sanitizer.prototype = {
|
||||
|
@ -85,9 +87,9 @@ Sanitizer.prototype = {
|
|||
cache: {
|
||||
clear: function ()
|
||||
{
|
||||
var cacheService = Cc["@mozilla.org/network/cache-service;1"].getService(Ci.nsICacheService);
|
||||
var cache = Cc["@mozilla.org/netwerk/cache-storage-service;1"].getService(Ci.nsICacheStorageService);
|
||||
try {
|
||||
cacheService.evictEntries(Ci.nsICache.STORE_ANYWHERE);
|
||||
cache.clear();
|
||||
} catch(er) {}
|
||||
|
||||
let imageCache = Cc["@mozilla.org/image/cache;1"].getService(Ci.imgICache);
|
||||
|
@ -143,9 +145,10 @@ Sanitizer.prototype = {
|
|||
offlineApps: {
|
||||
clear: function ()
|
||||
{
|
||||
var cacheService = Cc["@mozilla.org/network/cache-service;1"].getService(Ci.nsICacheService);
|
||||
var cacheService = Cc["@mozilla.org/netwerk/cache-storage-service;1"].getService(Ci.nsICacheStorageService);
|
||||
var appCacheStorage = cacheService.appCacheStorage(LoadContextInfo.default, null);
|
||||
try {
|
||||
cacheService.evictEntries(Ci.nsICache.STORE_OFFLINE);
|
||||
appCacheStorage.asyncEvictStorage(null);
|
||||
} catch(er) {}
|
||||
},
|
||||
|
||||
|
|
|
@ -4,15 +4,17 @@
|
|||
|
||||
this.EXPORTED_SYMBOLS = ["OfflineAppCacheHelper"];
|
||||
|
||||
Components.utils.import('resource://gre/modules/LoadContextInfo.jsm');
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
this.OfflineAppCacheHelper = {
|
||||
clear: function() {
|
||||
var cacheService = Cc["@mozilla.org/network/cache-service;1"].
|
||||
getService(Ci.nsICacheService);
|
||||
var cacheService = Cc["@mozilla.org/netwerk/cache-storage-service;1"].getService(Ci.nsICacheStorageService);
|
||||
var appCacheStorage = cacheService.appCacheStorage(LoadContextInfo.default, null);
|
||||
try {
|
||||
cacheService.evictEntries(Ci.nsICache.STORE_OFFLINE);
|
||||
appCacheStorage.asyncEvictStorage(null);
|
||||
} catch(er) {}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -11,9 +11,9 @@
|
|||
var url = "bug482935.sjs";
|
||||
|
||||
function clearCache() {
|
||||
SpecialPowers.Cc["@mozilla.org/network/cache-service;1"].
|
||||
getService(SpecialPowers.Ci.nsICacheService).
|
||||
evictEntries(SpecialPowers.Ci.nsICache.STORE_ANYWHERE);
|
||||
SpecialPowers.Cc["@mozilla.org/netwerk/cache-storage-service;1"].
|
||||
getService(SpecialPowers.Ci.nsICacheStorageService).
|
||||
clear();
|
||||
}
|
||||
|
||||
// Tests that the response is cached if the request is cancelled
|
||||
|
|
|
@ -803,9 +803,16 @@ nsDOMOfflineResourceList::CacheKeys()
|
|||
nsCOMPtr<nsIWebNavigation> webNav = do_GetInterface(window);
|
||||
nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(webNav);
|
||||
|
||||
uint32_t appId = 0;
|
||||
bool inBrowser = false;
|
||||
if (loadContext) {
|
||||
loadContext->GetAppId(&appId);
|
||||
loadContext->GetIsInBrowserElement(&inBrowser);
|
||||
}
|
||||
|
||||
nsAutoCString groupID;
|
||||
mApplicationCacheService->BuildGroupID(
|
||||
mManifestURI, loadContext, groupID);
|
||||
mApplicationCacheService->BuildGroupIDForApp(
|
||||
mManifestURI, appId, inBrowser, groupID);
|
||||
|
||||
nsCOMPtr<nsIApplicationCache> appCache;
|
||||
mApplicationCacheService->GetActiveCache(groupID,
|
||||
|
|
|
@ -14,7 +14,7 @@ function manifestUpdated()
|
|||
.getService(SpecialPowers.Ci.nsIApplicationCacheService);
|
||||
|
||||
var foreign2cache = appCacheService.chooseApplicationCache(
|
||||
"http://mochi.test:8888/tests/dom/tests/mochitest/ajax/offline/foreign2.html", OfflineTest.loadContext());
|
||||
"http://mochi.test:8888/tests/dom/tests/mochitest/ajax/offline/foreign2.html", OfflineTest.loadContextInfo());
|
||||
|
||||
window.opener.OfflineTest.ok(foreign2cache, "Foreign 2 cache present, chosen for foreign2.html");
|
||||
window.opener.OfflineTest.is(foreign2cache.manifestURI.asciiSpec, "http://mochi.test:8888/tests/dom/tests/mochitest/ajax/offline/foreign2.cacheManifest")
|
||||
|
@ -41,7 +41,7 @@ function onLoaded()
|
|||
window.opener.OfflineTest.ok(!foreign2cache, "Foreign 2 cache not present");
|
||||
|
||||
foreign1cache = appCacheService.chooseApplicationCache(
|
||||
"http://mochi.test:8888/tests/dom/tests/mochitest/ajax/offline/foreign2.html", window.opener.OfflineTest.loadContext());
|
||||
"http://mochi.test:8888/tests/dom/tests/mochitest/ajax/offline/foreign2.html", window.opener.OfflineTest.loadContextInfo());
|
||||
window.opener.OfflineTest.ok(!foreign1cache, "foreign2.html not chosen from foreign1 cache");
|
||||
|
||||
try
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
// Utility functions for offline tests.
|
||||
var Cc = SpecialPowers.Cc;
|
||||
var Ci = SpecialPowers.Ci;
|
||||
var Cu = SpecialPowers.Cu;
|
||||
var LoadContextInfo = Cu.import("resource://gre/modules/LoadContextInfo.jsm", {}).LoadContextInfo;
|
||||
|
||||
const kNetBase = 2152398848; // 0x804B0000
|
||||
var NS_ERROR_CACHE_KEY_NOT_FOUND = kNetBase + 61;
|
||||
|
@ -335,13 +337,18 @@ loadContext: function()
|
|||
.getInterface(SpecialPowers.Ci.nsILoadContext);
|
||||
},
|
||||
|
||||
loadContextInfo: function()
|
||||
{
|
||||
return LoadContextInfo.fromLoadContext(this.loadContext(), false);
|
||||
},
|
||||
|
||||
getActiveCache: function(overload)
|
||||
{
|
||||
// Note that this is the current active cache in the cache stack, not the
|
||||
// one associated with this window.
|
||||
var serv = Cc["@mozilla.org/network/application-cache-service;1"]
|
||||
.getService(Ci.nsIApplicationCacheService);
|
||||
var groupID = serv.buildGroupID(this.manifestURL(overload), this.loadContext());
|
||||
var groupID = serv.buildGroupID(this.manifestURL(overload), this.loadContextInfo());
|
||||
return serv.getActiveCache(groupID);
|
||||
},
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ function manifestUpdated()
|
|||
.getService(SpecialPowers.Ci.nsIApplicationCacheService);
|
||||
|
||||
foreign1cache = appCacheService.chooseApplicationCache(
|
||||
"http://mochi.test:8888/tests/dom/tests/mochitest/ajax/offline/foreign2.html", OfflineTest.loadContext());
|
||||
"http://mochi.test:8888/tests/dom/tests/mochitest/ajax/offline/foreign2.html", OfflineTest.loadContextInfo());
|
||||
|
||||
OfflineTest.ok(foreign1cache, "foreign2.html chosen from foreign1 cache");
|
||||
OfflineTest.is(foreign1cache.manifestURI.asciiSpec, "http://mochi.test:8888/tests/dom/tests/mochitest/ajax/offline/foreign1.cacheManifest")
|
||||
|
|
|
@ -23,6 +23,13 @@ var gGotImplicitVersion = 0;
|
|||
var gGotDynamicVersion = 0;
|
||||
var gGotOnError = false;
|
||||
|
||||
function createURI(urispec)
|
||||
{
|
||||
var ioServ = Components.classes["@mozilla.org/network/io-service;1"]
|
||||
.getService(Components.interfaces.nsIIOService);
|
||||
return ioServ.newURI(urispec, null, null);
|
||||
}
|
||||
|
||||
// test
|
||||
|
||||
function manifestUpdated()
|
||||
|
@ -112,12 +119,12 @@ function goOffline()
|
|||
};
|
||||
|
||||
// Delete HTTP cache to ensure we are going from offline cache
|
||||
var sessionServ = Cc["@mozilla.org/network/cache-service;1"]
|
||||
.getService(Ci.nsICacheService);
|
||||
cacheSession = sessionServ.createSession("HTTP", Ci.nsICache.STORE_ANYWHERE, Ci.nsICache.STREAM_BASED);
|
||||
cacheSession.doomEntry("http://mochi.test:8888/tests/dom/tests/mochitest/ajax/offline/notonwhitelist.html", null);
|
||||
cacheSession.doomEntry("http://mochi.test:8888/tests/dom/tests/mochitest/ajax/offline/updatingIframe.sjs", null);
|
||||
cacheSession.doomEntry("http://mochi.test:8888/tests/dom/tests/mochitest/ajax/offline/updatingImplicit.html", listener);
|
||||
var cache = Cc["@mozilla.org/network/cache-storage-service;1"]
|
||||
.getService(Ci.nsICacheStorageService);
|
||||
var storage = cache.diskCacheStorage(LoadContextInfo.default, false);
|
||||
storage.asyncDoomURI(createURI("http://mochi.test:8888/tests/dom/tests/mochitest/ajax/offline/notonwhitelist.html"), "", null);
|
||||
storage.asyncDoomURI(createURI("http://mochi.test:8888/tests/dom/tests/mochitest/ajax/offline/updatingIframe.sjs"), "", null);
|
||||
storage.asyncDoomURI(createURI("http://mochi.test:8888/tests/dom/tests/mochitest/ajax/offline/updatingImplicit.html"), "", listener);
|
||||
}
|
||||
|
||||
function goOfflineContinue()
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
|
||||
#include "nsICacheVisitor.h"
|
||||
#include "nsICacheEntry.h"
|
||||
|
||||
#include "plstr.h" // PL_strcasestr(...)
|
||||
#include "nsNetUtil.h"
|
||||
|
@ -339,7 +339,7 @@ void imgRequest::SetCacheValidation(imgCacheEntry* aCacheEntry, nsIRequest* aReq
|
|||
nsCOMPtr<nsISupports> cacheToken;
|
||||
cacheChannel->GetCacheToken(getter_AddRefs(cacheToken));
|
||||
if (cacheToken) {
|
||||
nsCOMPtr<nsICacheEntryInfo> entryDesc(do_QueryInterface(cacheToken));
|
||||
nsCOMPtr<nsICacheEntry> entryDesc(do_QueryInterface(cacheToken));
|
||||
if (entryDesc) {
|
||||
uint32_t expiration;
|
||||
/* get the expiration time from the caching channel's token */
|
||||
|
|
|
@ -98,8 +98,9 @@ function run_loadImage_tests() {
|
|||
}
|
||||
|
||||
Services.obs.addObserver(observer, "cacheservice:empty-cache", false);
|
||||
let cs = Cc["@mozilla.org/network/cache-service;1"].getService(Ci.nsICacheService);
|
||||
cs.evictEntries(Ci.nsICache.STORE_ANYWHERE);
|
||||
let cs = Cc["@mozilla.org/netwerk/cache-storage-service;1"]
|
||||
.getService(Ci.nsICacheStorageService);
|
||||
cs.clear();
|
||||
}
|
||||
|
||||
function cleanup()
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
#include "nsMathMLOperators.h"
|
||||
#include "Navigator.h"
|
||||
#include "DOMStorageObserver.h"
|
||||
#include "CacheObserver.h"
|
||||
#include "DisplayItemClip.h"
|
||||
|
||||
#include "AudioChannelService.h"
|
||||
|
@ -123,6 +124,7 @@ using namespace mozilla::system;
|
|||
extern void NS_ShutdownEventTargetChainRecycler();
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::net;
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::dom::ipc;
|
||||
using namespace mozilla::dom::time;
|
||||
|
@ -278,6 +280,8 @@ nsLayoutStatics::Initialize()
|
|||
|
||||
HTMLVideoElement::Init();
|
||||
|
||||
CacheObserver::Init();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -399,4 +403,6 @@ nsLayoutStatics::Shutdown()
|
|||
DisplayItemClip::Shutdown();
|
||||
|
||||
nsDocument::XPCOMShutdown();
|
||||
|
||||
CacheObserver::Shutdown();
|
||||
}
|
||||
|
|
|
@ -64,6 +64,8 @@ pref("browser.cache.memory.enable", true);
|
|||
#endif
|
||||
pref("browser.cache.memory.capacity", 1024); // kilobytes
|
||||
|
||||
pref("browser.cache.memory_limit", 5120); // 5 MB
|
||||
|
||||
/* image cache prefs */
|
||||
pref("image.cache.size", 1048576); // bytes
|
||||
pref("image.high_quality_downscaling.enabled", false);
|
||||
|
|
|
@ -203,6 +203,7 @@
|
|||
@BINPATH@/components/mozfind.xpt
|
||||
@BINPATH@/components/necko_about.xpt
|
||||
@BINPATH@/components/necko_cache.xpt
|
||||
@BINPATH@/components/necko_cache2.xpt
|
||||
@BINPATH@/components/necko_cookie.xpt
|
||||
@BINPATH@/components/necko_dns.xpt
|
||||
@BINPATH@/components/necko_file.xpt
|
||||
|
|
|
@ -68,9 +68,9 @@ Sanitizer.prototype = {
|
|||
cache: {
|
||||
clear: function ()
|
||||
{
|
||||
var cacheService = Cc["@mozilla.org/network/cache-service;1"].getService(Ci.nsICacheService);
|
||||
var cache = Cc["@mozilla.org/netwerk/cache-storage-service;1"].getService(Ci.nsICacheStorageService);
|
||||
try {
|
||||
cacheService.evictEntries(Ci.nsICache.STORE_ANYWHERE);
|
||||
cache.clear();
|
||||
} catch(er) {}
|
||||
|
||||
let imageCache = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
|
||||
|
@ -126,9 +126,10 @@ Sanitizer.prototype = {
|
|||
offlineApps: {
|
||||
clear: function ()
|
||||
{
|
||||
var cacheService = Cc["@mozilla.org/network/cache-service;1"].getService(Ci.nsICacheService);
|
||||
var cacheService = Cc["@mozilla.org/netwerk/cache-storage-service;1"].getService(Ci.nsICacheStorageService);
|
||||
var appCacheStorage = cacheService.appCacheStorage(LoadContextInfo.default, null);
|
||||
try {
|
||||
cacheService.evictEntries(Ci.nsICache.STORE_OFFLINE);
|
||||
appCacheStorage.asyncEvictStorage(null);
|
||||
} catch(er) {}
|
||||
},
|
||||
|
||||
|
|
|
@ -38,6 +38,13 @@ pref("general.warnOnAboutConfig", true);
|
|||
// maximum number of dated backups to keep at any time
|
||||
pref("browser.bookmarks.max_backups", 5);
|
||||
|
||||
// Preference for switching the cache backend, can be changed freely at runtime
|
||||
// 0 - use the old (Darin's) cache [DEFAULT]
|
||||
// 1 - use the new cache back-end (cache v2)
|
||||
// 2 - do a random choise for A/B testing (browser chooses old or new back-end at startup
|
||||
// and keeps it per session)
|
||||
pref("browser.cache.use_new_backend", 0);
|
||||
|
||||
pref("browser.cache.disk.enable", true);
|
||||
// Is this the first-time smartsizing has been introduced?
|
||||
pref("browser.cache.disk.smart_size.first_run", true);
|
||||
|
@ -60,6 +67,9 @@ pref("browser.cache.disk_cache_ssl", true);
|
|||
// 0 = once-per-session, 1 = each-time, 2 = never, 3 = when-appropriate/automatically
|
||||
pref("browser.cache.check_doc_frequency", 3);
|
||||
|
||||
// Limit for how much memory the cache can consume, for any data, in Kb
|
||||
pref("browser.cache.memory_limit", 51200); // 50 MB
|
||||
|
||||
pref("browser.cache.offline.enable", true);
|
||||
// enable offline apps by default, disable prompt
|
||||
pref("offline-apps.allow_by_default", true);
|
||||
|
@ -4123,7 +4133,7 @@ pref("layers.offmainthreadcomposition.enabled", true);
|
|||
pref("layers.use-deprecated-textures", false);
|
||||
#else
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
pref("layers.use-deprecated-textures", false);
|
||||
pref("layers.use-deprecated-textures", true);
|
||||
#else
|
||||
pref("layers.offmainthreadcomposition.enabled", false);
|
||||
pref("layers.use-deprecated-textures", true);
|
||||
|
|
|
@ -46,6 +46,7 @@ XPIDL_SOURCES += [
|
|||
'nsIIncrementalDownload.idl',
|
||||
'nsIInputStreamChannel.idl',
|
||||
'nsIInputStreamPump.idl',
|
||||
'nsILoadContextInfo.idl',
|
||||
'nsILoadGroup.idl',
|
||||
'nsILoadGroupChild.idl',
|
||||
'nsIMIMEInputStream.idl',
|
||||
|
|
|
@ -9,13 +9,13 @@
|
|||
interface nsIApplicationCache;
|
||||
interface nsIFile;
|
||||
interface nsIURI;
|
||||
interface nsILoadContext;
|
||||
interface nsILoadContextInfo;
|
||||
|
||||
/**
|
||||
* The application cache service manages the set of application cache
|
||||
* groups.
|
||||
*/
|
||||
[scriptable, uuid(9b5b2cde-d5dd-48d3-87f8-8e8b776952a8)]
|
||||
[scriptable, uuid(03b41c3d-0816-4134-8b2e-4f5afbdb1f06)]
|
||||
interface nsIApplicationCacheService : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -23,7 +23,7 @@ interface nsIApplicationCacheService : nsISupports
|
|||
* URL and the given load context.
|
||||
*/
|
||||
ACString buildGroupID(in nsIURI aManifestURL,
|
||||
in nsILoadContext aLoadContext);
|
||||
in nsILoadContextInfo aLoadContextInfo);
|
||||
|
||||
/**
|
||||
* Same as buildGroupID method, just doesn't require load context.
|
||||
|
@ -87,7 +87,7 @@ interface nsIApplicationCacheService : nsISupports
|
|||
* Try to find the best application cache to serve a resource.
|
||||
*/
|
||||
nsIApplicationCache chooseApplicationCache(in ACString key,
|
||||
[optional] in nsILoadContext loadContext);
|
||||
[optional] in nsILoadContextInfo aLoadContextInfo);
|
||||
|
||||
/**
|
||||
* Flags the key as being opportunistically cached.
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
/**
|
||||
* Helper interface to carry informatin about the load context
|
||||
* encapsulating an AppID, IsInBrowser and IsPrivite properties.
|
||||
* It shall be used where nsILoadContext cannot be used or is not
|
||||
* available.
|
||||
*/
|
||||
[scriptable, uuid(1ea9cbdb-9df4-46a0-8c45-f4091aad9459)]
|
||||
interface nsILoadContextInfo : nsISupports
|
||||
{
|
||||
/**
|
||||
* Whether the context is in a Private Browsing mode
|
||||
*/
|
||||
readonly attribute boolean isPrivate;
|
||||
|
||||
/**
|
||||
* Whether the context belongs under an App
|
||||
*/
|
||||
const unsigned long NO_APP_ID = 0;
|
||||
const unsigned long UNKNOWN_APP_ID = 4294967295; // UINT32_MAX
|
||||
readonly attribute uint32_t appId;
|
||||
|
||||
/**
|
||||
* Whether the context is in a browser tag
|
||||
*/
|
||||
readonly attribute boolean isInBrowserElement;
|
||||
|
||||
/**
|
||||
* Whether the load is initiated as anonymous
|
||||
*/
|
||||
readonly attribute boolean isAnonymous;
|
||||
|
||||
%{C++
|
||||
/**
|
||||
* De-XPCOMed getters
|
||||
*/
|
||||
bool IsPrivate()
|
||||
{
|
||||
bool pb;
|
||||
GetIsPrivate(&pb);
|
||||
return pb;
|
||||
}
|
||||
|
||||
uint32_t AppId()
|
||||
{
|
||||
uint32_t appId;
|
||||
GetAppId(&appId);
|
||||
return appId;
|
||||
}
|
||||
|
||||
bool IsInBrowserElement()
|
||||
{
|
||||
bool ib;
|
||||
GetIsInBrowserElement(&ib);
|
||||
return ib;
|
||||
}
|
||||
|
||||
bool IsAnonymous()
|
||||
{
|
||||
bool anon;
|
||||
GetIsAnonymous(&anon);
|
||||
return anon;
|
||||
}
|
||||
%}
|
||||
};
|
|
@ -0,0 +1,115 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "LoadContextInfo.h"
|
||||
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsILoadContext.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
NS_IMPL_ISUPPORTS1(LoadContextInfo, nsILoadContextInfo)
|
||||
|
||||
LoadContextInfo::LoadContextInfo(bool aIsPrivate, uint32_t aAppId, bool aIsInBrowser, bool aIsAnonymous)
|
||||
: mAppId(aAppId)
|
||||
, mIsPrivate(aIsPrivate)
|
||||
, mIsInBrowser(aIsInBrowser)
|
||||
, mIsAnonymous(aIsAnonymous)
|
||||
{
|
||||
}
|
||||
|
||||
LoadContextInfo::~LoadContextInfo()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP LoadContextInfo::GetIsPrivate(bool *aIsPrivate)
|
||||
{
|
||||
*aIsPrivate = mIsPrivate;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP LoadContextInfo::GetAppId(uint32_t *aAppId)
|
||||
{
|
||||
*aAppId = mAppId;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP LoadContextInfo::GetIsInBrowserElement(bool *aIsInBrowser)
|
||||
{
|
||||
*aIsInBrowser = mIsInBrowser;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP LoadContextInfo::GetIsAnonymous(bool *aIsAnonymous)
|
||||
{
|
||||
*aIsAnonymous = mIsAnonymous;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
LoadContextInfo *
|
||||
GetLoadContextInfo(nsIChannel * aChannel)
|
||||
{
|
||||
bool pb = NS_UsePrivateBrowsing(aChannel);
|
||||
uint32_t appId;
|
||||
bool ib;
|
||||
if (!NS_GetAppInfo(aChannel, &appId, &ib)) {
|
||||
appId = nsILoadContextInfo::NO_APP_ID;
|
||||
ib = false;
|
||||
}
|
||||
|
||||
bool anon = false;
|
||||
nsLoadFlags loadFlags;
|
||||
nsresult rv = aChannel->GetLoadFlags(&loadFlags);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
anon = !!(loadFlags & nsIChannel::LOAD_ANONYMOUS);
|
||||
|
||||
return new LoadContextInfo(pb, appId, ib, anon);
|
||||
}
|
||||
|
||||
LoadContextInfo *
|
||||
GetLoadContextInfo(nsILoadContext * aLoadContext, bool aIsAnonymous)
|
||||
{
|
||||
if (!aLoadContext)
|
||||
return new LoadContextInfo(false, nsILoadContextInfo::NO_APP_ID, false, aIsAnonymous); // nullptr?
|
||||
|
||||
bool pb = aLoadContext->UsePrivateBrowsing();
|
||||
|
||||
bool ib;
|
||||
nsresult rv = aLoadContext->GetIsInBrowserElement(&ib);
|
||||
if (NS_FAILED(rv))
|
||||
ib = false; // todo NS_WARNING...
|
||||
|
||||
uint32_t appId;
|
||||
rv = aLoadContext->GetAppId(&appId);
|
||||
if (NS_FAILED(rv))
|
||||
appId = nsILoadContextInfo::NO_APP_ID;
|
||||
|
||||
return new LoadContextInfo(pb, appId, ib, aIsAnonymous);
|
||||
}
|
||||
|
||||
LoadContextInfo *
|
||||
GetLoadContextInfo(nsILoadContextInfo* aInfo)
|
||||
{
|
||||
return new LoadContextInfo(aInfo->IsPrivate(),
|
||||
aInfo->AppId(),
|
||||
aInfo->IsInBrowserElement(),
|
||||
aInfo->IsAnonymous());
|
||||
}
|
||||
|
||||
LoadContextInfo *
|
||||
GetLoadContextInfo(bool const aIsPrivate,
|
||||
uint32_t const aAppId,
|
||||
bool const aIsInBrowserElement,
|
||||
bool const aIsAnonymous)
|
||||
{
|
||||
return new LoadContextInfo(aIsPrivate,
|
||||
aAppId,
|
||||
aIsInBrowserElement,
|
||||
aIsAnonymous);
|
||||
}
|
||||
|
||||
} // net
|
||||
} // mozilla
|
|
@ -0,0 +1,53 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsLoadContextInfo_h__
|
||||
#define nsLoadContextInfo_h__
|
||||
|
||||
#include "nsILoadContextInfo.h"
|
||||
|
||||
class nsIChannel;
|
||||
class nsILoadContext;
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class LoadContextInfo : public nsILoadContextInfo
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSILOADCONTEXTINFO
|
||||
|
||||
LoadContextInfo(bool aIsPrivate, uint32_t aAppId, bool aIsInBrowser, bool aIsAnonymous);
|
||||
|
||||
private:
|
||||
virtual ~LoadContextInfo();
|
||||
|
||||
protected:
|
||||
uint32_t mAppId;
|
||||
bool mIsPrivate : 1;
|
||||
bool mIsInBrowser : 1;
|
||||
bool mIsAnonymous : 1;
|
||||
};
|
||||
|
||||
LoadContextInfo *
|
||||
GetLoadContextInfo(nsIChannel * aChannel);
|
||||
|
||||
LoadContextInfo *
|
||||
GetLoadContextInfo(nsILoadContext * aLoadContext,
|
||||
bool aAnonymous);
|
||||
|
||||
LoadContextInfo *
|
||||
GetLoadContextInfo(nsILoadContextInfo* aInfo);
|
||||
|
||||
LoadContextInfo *
|
||||
GetLoadContextInfo(bool const aIsPrivate = false,
|
||||
uint32_t const aAppId = nsILoadContextInfo::NO_APP_ID,
|
||||
bool const aIsInBrowserElement = false,
|
||||
bool const aIsAnonymous = false);
|
||||
|
||||
} // net
|
||||
} // mozilla
|
||||
|
||||
#endif
|
|
@ -23,6 +23,7 @@ CPP_SOURCES += [
|
|||
'BackgroundFileSaver.cpp',
|
||||
'Dashboard.cpp',
|
||||
'EventTokenBucket.cpp',
|
||||
'LoadContextInfo.cpp',
|
||||
'NetworkActivityMonitor.cpp',
|
||||
'ProxyAutoConfig.cpp',
|
||||
'RedirectChannelRegistrar.cpp',
|
||||
|
|
|
@ -12,6 +12,7 @@ SHARED_LIBRARY_LIBS = \
|
|||
../streamconv/converters/$(LIB_PREFIX)nkcnvts_s.$(LIB_SUFFIX) \
|
||||
../mime/$(LIB_PREFIX)nkmime_s.$(LIB_SUFFIX) \
|
||||
../cache/$(LIB_PREFIX)nkcache_s.$(LIB_SUFFIX) \
|
||||
../cache2/$(LIB_PREFIX)nkcache2_s.$(LIB_SUFFIX) \
|
||||
../protocol/about/$(LIB_PREFIX)nkabout_s.$(LIB_SUFFIX) \
|
||||
$(foreach d,$(filter-out about,$(NECKO_PROTOCOLS)), \
|
||||
../protocol/$(d)/$(LIB_PREFIX)nk$(d)_s.$(LIB_SUFFIX)) \
|
||||
|
|
|
@ -123,6 +123,10 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsSerializationHelper)
|
|||
typedef mozilla::net::RedirectChannelRegistrar RedirectChannelRegistrar;
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(RedirectChannelRegistrar)
|
||||
|
||||
#include "CacheStorageService.h"
|
||||
typedef mozilla::net::CacheStorageService CacheStorageService;
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(CacheStorageService)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern nsresult
|
||||
|
@ -807,6 +811,7 @@ NS_DEFINE_NAMED_CID(NS_NETWORK_LINK_SERVICE_CID);
|
|||
#endif
|
||||
NS_DEFINE_NAMED_CID(NS_SERIALIZATION_HELPER_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_REDIRECTCHANNELREGISTRAR_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_CACHE_STORAGE_SERVICE_CID);
|
||||
|
||||
static const mozilla::Module::CIDEntry kNeckoCIDs[] = {
|
||||
{ &kNS_IOSERVICE_CID, false, nullptr, nsIOServiceConstructor },
|
||||
|
@ -946,6 +951,7 @@ static const mozilla::Module::CIDEntry kNeckoCIDs[] = {
|
|||
#endif
|
||||
{ &kNS_SERIALIZATION_HELPER_CID, false, nullptr, nsSerializationHelperConstructor },
|
||||
{ &kNS_REDIRECTCHANNELREGISTRAR_CID, false, nullptr, RedirectChannelRegistrarConstructor },
|
||||
{ &kNS_CACHE_STORAGE_SERVICE_CID, false, nullptr, CacheStorageServiceConstructor },
|
||||
{ nullptr }
|
||||
};
|
||||
|
||||
|
@ -1088,6 +1094,7 @@ static const mozilla::Module::ContractIDEntry kNeckoContracts[] = {
|
|||
#endif
|
||||
{ NS_SERIALIZATION_HELPER_CONTRACTID, &kNS_SERIALIZATION_HELPER_CID },
|
||||
{ NS_REDIRECTCHANNELREGISTRAR_CONTRACTID, &kNS_REDIRECTCHANNELREGISTRAR_CID },
|
||||
{ NS_CACHE_STORAGE_SERVICE_CONTRACTID, &kNS_CACHE_STORAGE_SERVICE_CID },
|
||||
{ nullptr }
|
||||
};
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "nsCRT.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsILoadContextInfo.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
|
@ -28,7 +29,7 @@ nsApplicationCacheService::nsApplicationCacheService()
|
|||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationCacheService::BuildGroupID(nsIURI *aManifestURL,
|
||||
nsILoadContext *aLoadContext,
|
||||
nsILoadContextInfo *aLoadContextInfo,
|
||||
nsACString &_result)
|
||||
{
|
||||
nsresult rv;
|
||||
|
@ -36,12 +37,9 @@ nsApplicationCacheService::BuildGroupID(nsIURI *aManifestURL,
|
|||
uint32_t appId = NECKO_NO_APP_ID;
|
||||
bool isInBrowserElement = false;
|
||||
|
||||
if (aLoadContext) {
|
||||
rv = aLoadContext->GetAppId(&appId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aLoadContext->GetIsInBrowserElement(&isInBrowserElement);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (aLoadContextInfo) {
|
||||
appId = aLoadContextInfo->AppId();
|
||||
isInBrowserElement = aLoadContextInfo->IsInBrowserElement();
|
||||
}
|
||||
|
||||
rv = nsOfflineCacheDevice::BuildApplicationCacheGroupID(
|
||||
|
@ -134,7 +132,7 @@ nsApplicationCacheService::DeactivateGroup(const nsACString &group)
|
|||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationCacheService::ChooseApplicationCache(const nsACString &key,
|
||||
nsILoadContext *aLoadContext,
|
||||
nsILoadContextInfo *aLoadContextInfo,
|
||||
nsIApplicationCache **out)
|
||||
{
|
||||
if (!mCacheService)
|
||||
|
@ -144,7 +142,7 @@ nsApplicationCacheService::ChooseApplicationCache(const nsACString &key,
|
|||
nsresult rv = mCacheService->GetOfflineDevice(getter_AddRefs(device));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return device->ChooseApplicationCache(key, aLoadContext, out);
|
||||
return device->ChooseApplicationCache(key, aLoadContextInfo, out);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -63,7 +63,7 @@ nsShutdownThread::BlockingShutdown(nsIThread *aThread)
|
|||
|
||||
{
|
||||
MutexAutoLock lock(st->mLock);
|
||||
rv = aThread->Dispatch(st, NS_DISPATCH_NORMAL);
|
||||
rv = workerThread->Dispatch(st, NS_DISPATCH_NORMAL);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING(
|
||||
"Dispatching event in nsShutdownThread::BlockingShutdown failed!");
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "nsArrayUtils.h"
|
||||
#include "nsIArray.h"
|
||||
#include "nsIVariant.h"
|
||||
#include "nsILoadContextInfo.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsISerializable.h"
|
||||
#include "nsSerializationHelper.h"
|
||||
|
@ -2423,31 +2424,33 @@ nsOfflineCacheDevice::DiscardByAppId(int32_t appID, bool browserEntriesOnly)
|
|||
rv = AppendJARIdentifier(jaridsuffix, appID, browserEntriesOnly);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
AutoResetStatement statement(mStatement_EnumerateApps);
|
||||
rv = statement->BindUTF8StringByIndex(0, jaridsuffix);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool hasRows;
|
||||
rv = statement->ExecuteStep(&hasRows);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
while (hasRows) {
|
||||
nsAutoCString group;
|
||||
rv = statement->GetUTF8String(0, group);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCString clientID;
|
||||
rv = statement->GetUTF8String(1, clientID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIRunnable> ev =
|
||||
new nsOfflineCacheDiscardCache(this, group, clientID);
|
||||
|
||||
rv = nsCacheService::DispatchToCacheIOThread(ev);
|
||||
{
|
||||
AutoResetStatement statement(mStatement_EnumerateApps);
|
||||
rv = statement->BindUTF8StringByIndex(0, jaridsuffix);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool hasRows;
|
||||
rv = statement->ExecuteStep(&hasRows);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
while (hasRows) {
|
||||
nsAutoCString group;
|
||||
rv = statement->GetUTF8String(0, group);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCString clientID;
|
||||
rv = statement->GetUTF8String(1, clientID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIRunnable> ev =
|
||||
new nsOfflineCacheDiscardCache(this, group, clientID);
|
||||
|
||||
rv = nsCacheService::DispatchToCacheIOThread(ev);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = statement->ExecuteStep(&hasRows);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
if (!browserEntriesOnly) {
|
||||
|
@ -2462,7 +2465,7 @@ nsOfflineCacheDevice::DiscardByAppId(int32_t appID, bool browserEntriesOnly)
|
|||
bool
|
||||
nsOfflineCacheDevice::CanUseCache(nsIURI *keyURI,
|
||||
const nsACString &clientID,
|
||||
nsILoadContext *loadContext)
|
||||
nsILoadContextInfo *loadContextInfo)
|
||||
{
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
|
@ -2493,12 +2496,9 @@ nsOfflineCacheDevice::CanUseCache(nsIURI *keyURI,
|
|||
uint32_t appId = NECKO_NO_APP_ID;
|
||||
bool isInBrowserElement = false;
|
||||
|
||||
if (loadContext) {
|
||||
rv = loadContext->GetAppId(&appId);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
rv = loadContext->GetIsInBrowserElement(&isInBrowserElement);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
if (loadContextInfo) {
|
||||
appId = loadContextInfo->AppId();
|
||||
isInBrowserElement = loadContextInfo->IsInBrowserElement();
|
||||
}
|
||||
|
||||
// Check the groupID we found is equal to groupID based
|
||||
|
@ -2518,7 +2518,7 @@ nsOfflineCacheDevice::CanUseCache(nsIURI *keyURI,
|
|||
|
||||
nsresult
|
||||
nsOfflineCacheDevice::ChooseApplicationCache(const nsACString &key,
|
||||
nsILoadContext *loadContext,
|
||||
nsILoadContextInfo *loadContextInfo,
|
||||
nsIApplicationCache **out)
|
||||
{
|
||||
*out = nullptr;
|
||||
|
@ -2546,7 +2546,7 @@ nsOfflineCacheDevice::ChooseApplicationCache(const nsACString &key,
|
|||
rv = statement->GetUTF8String(0, clientID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (CanUseCache(keyURI, clientID, loadContext)) {
|
||||
if (CanUseCache(keyURI, clientID, loadContextInfo)) {
|
||||
return GetApplicationCache(clientID, out);
|
||||
}
|
||||
}
|
||||
|
@ -2578,7 +2578,7 @@ nsOfflineCacheDevice::ChooseApplicationCache(const nsACString &key,
|
|||
rv = nsstatement->GetUTF8String(0, clientID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (CanUseCache(keyURI, clientID, loadContext)) {
|
||||
if (CanUseCache(keyURI, clientID, loadContextInfo)) {
|
||||
return GetApplicationCache(clientID, out);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -157,7 +157,7 @@ public:
|
|||
nsresult DeactivateGroup(const nsACString &group);
|
||||
|
||||
nsresult ChooseApplicationCache(const nsACString &key,
|
||||
nsILoadContext *loadContext,
|
||||
nsILoadContextInfo *loadContext,
|
||||
nsIApplicationCache **out);
|
||||
|
||||
nsresult CacheOpportunistically(nsIApplicationCache* cache,
|
||||
|
@ -208,7 +208,7 @@ private:
|
|||
nsresult EnableEvictionObserver();
|
||||
nsresult DisableEvictionObserver();
|
||||
|
||||
bool CanUseCache(nsIURI *keyURI, const nsACString &clientID, nsILoadContext *loadContext);
|
||||
bool CanUseCache(nsIURI *keyURI, const nsACString &clientID, nsILoadContextInfo *loadContext);
|
||||
|
||||
nsresult MarkEntry(const nsCString &clientID,
|
||||
const nsACString &key,
|
||||
|
|
|
@ -0,0 +1,156 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "AppCacheStorage.h"
|
||||
#include "CacheStorageService.h"
|
||||
#include "CacheLog.h"
|
||||
|
||||
#include "OldWrappers.h"
|
||||
|
||||
#include "nsICacheEntryDoomCallback.h"
|
||||
|
||||
#include "nsICacheService.h"
|
||||
#include "nsIApplicationCache.h"
|
||||
#include "nsIApplicationCacheService.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(AppCacheStorage, CacheStorage)
|
||||
|
||||
AppCacheStorage::AppCacheStorage(nsILoadContextInfo* aInfo,
|
||||
nsIApplicationCache* aAppCache)
|
||||
: CacheStorage(aInfo, true /* disk */, false /* lookup app cache */)
|
||||
, mAppCache(aAppCache)
|
||||
{
|
||||
MOZ_COUNT_CTOR(AppCacheStorage);
|
||||
}
|
||||
|
||||
AppCacheStorage::~AppCacheStorage()
|
||||
{
|
||||
ProxyReleaseMainThread(mAppCache);
|
||||
MOZ_COUNT_DTOR(AppCacheStorage);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP AppCacheStorage::AsyncOpenURI(nsIURI *aURI,
|
||||
const nsACString & aIdExtension,
|
||||
uint32_t aFlags,
|
||||
nsICacheEntryOpenCallback *aCallback)
|
||||
{
|
||||
if (!CacheStorageService::Self())
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
NS_ENSURE_ARG(aURI);
|
||||
NS_ENSURE_ARG(aCallback);
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIApplicationCache> appCache = mAppCache;
|
||||
|
||||
if (!appCache) {
|
||||
rv = ChooseApplicationCache(aURI, getter_AddRefs(appCache));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
if (!appCache) {
|
||||
LOG(("AppCacheStorage::AsyncOpenURI entry not found in any appcache, giving up"));
|
||||
aCallback->OnCacheEntryAvailable(nullptr, false, nullptr, NS_ERROR_CACHE_KEY_NOT_FOUND);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> noRefURI;
|
||||
rv = aURI->CloneIgnoringRef(getter_AddRefs(noRefURI));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoCString cacheKey;
|
||||
rv = noRefURI->GetAsciiSpec(cacheKey);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsRefPtr<_OldCacheLoad> appCacheLoad =
|
||||
new _OldCacheLoad(cacheKey, aCallback, appCache,
|
||||
LoadInfo(), WriteToDisk(), aFlags);
|
||||
rv = appCacheLoad->Start();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP AppCacheStorage::AsyncDoomURI(nsIURI *aURI, const nsACString & aIdExtension,
|
||||
nsICacheEntryDoomCallback* aCallback)
|
||||
{
|
||||
if (!CacheStorageService::Self())
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
if (!mAppCache) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
// TODO - remove entry from app cache
|
||||
// I think no one is using this...
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP AppCacheStorage::AsyncEvictStorage(nsICacheEntryDoomCallback* aCallback)
|
||||
{
|
||||
if (!CacheStorageService::Self())
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIApplicationCacheService> appCacheService =
|
||||
do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!mAppCache) {
|
||||
if (LoadInfo()->AppId() == nsILoadContextInfo::NO_APP_ID &&
|
||||
!LoadInfo()->IsInBrowserElement()) {
|
||||
|
||||
// Clear everything.
|
||||
nsCOMPtr<nsICacheService> serv =
|
||||
do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = serv->EvictEntries(nsICache::STORE_OFFLINE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
else {
|
||||
// Clear app or inbrowser staff.
|
||||
rv = appCacheService->DiscardByAppId(LoadInfo()->AppId(),
|
||||
LoadInfo()->IsInBrowserElement());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Discard the group
|
||||
nsAutoCString groupID;
|
||||
rv = mAppCache->GetGroupID(groupID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = appCacheService->DeactivateGroup(groupID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
if (aCallback)
|
||||
aCallback->OnCacheEntryDoomed(NS_OK);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP AppCacheStorage::AsyncVisitStorage(nsICacheStorageVisitor* aVisitor,
|
||||
bool aVisitEntries)
|
||||
{
|
||||
if (!CacheStorageService::Self())
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
LOG(("AppCacheStorage::AsyncVisitStorage [this=%p, cb=%p]", this, aVisitor));
|
||||
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
} // net
|
||||
} // mozilla
|
|
@ -0,0 +1,37 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef AppCacheStorage__h__
|
||||
#define AppCacheStorage__h__
|
||||
|
||||
#include "CacheStorage.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsILoadContextInfo.h"
|
||||
#include "nsIApplicationCache.h"
|
||||
|
||||
class nsIApplicationCache;
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class AppCacheStorage : public CacheStorage
|
||||
{
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSICACHESTORAGE
|
||||
|
||||
public:
|
||||
AppCacheStorage(nsILoadContextInfo* aInfo,
|
||||
nsIApplicationCache* aAppCache);
|
||||
|
||||
private:
|
||||
virtual ~AppCacheStorage();
|
||||
|
||||
nsCOMPtr<nsIApplicationCache> mAppCache;
|
||||
};
|
||||
|
||||
} // net
|
||||
} // mozilla
|
||||
|
||||
#endif
|
|
@ -0,0 +1,186 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "CacheEntriesEnumerator.h"
|
||||
|
||||
#include "CacheFileIOManager.h"
|
||||
#include "CacheFile.h"
|
||||
|
||||
#include "nsIDirectoryEnumerator.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsIThread.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
CacheEntriesEnumerator::CacheEntriesEnumerator(nsIFile* aEntriesDirectory)
|
||||
: mEntriesDirectory(aEntriesDirectory)
|
||||
{
|
||||
MOZ_COUNT_CTOR(CacheEntriesEnumerator);
|
||||
}
|
||||
|
||||
CacheEntriesEnumerator::~CacheEntriesEnumerator()
|
||||
{
|
||||
MOZ_COUNT_DTOR(CacheEntriesEnumerator);
|
||||
|
||||
if (mEnumerator) {
|
||||
mEnumerator->Close();
|
||||
ProxyReleaseMainThread(mEnumerator);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult CacheEntriesEnumerator::Init()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> e;
|
||||
rv = mEntriesDirectory->GetDirectoryEntries(getter_AddRefs(e));
|
||||
|
||||
if (NS_ERROR_FILE_NOT_FOUND == rv || NS_ERROR_FILE_TARGET_DOES_NOT_EXIST == rv) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mEnumerator = do_QueryInterface(e, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool CacheEntriesEnumerator::HasMore()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (!mThreadCheck)
|
||||
mThreadCheck = NS_GetCurrentThread();
|
||||
else
|
||||
MOZ_ASSERT(mThreadCheck == NS_GetCurrentThread());
|
||||
#endif
|
||||
|
||||
if (!mEnumerator) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mCurrentFile)
|
||||
return true;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
rv = mEnumerator->GetNextFile(getter_AddRefs(mCurrentFile));
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
mEnumerator->Close();
|
||||
mEnumerator = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
return !!mCurrentFile;
|
||||
}
|
||||
|
||||
namespace { // anon
|
||||
|
||||
class FileConsumer : public CacheFileListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
nsresult Init(nsCSubstring const & aKey,
|
||||
CacheEntriesEnumeratorCallback* aCallback);
|
||||
|
||||
virtual ~FileConsumer() {}
|
||||
|
||||
private:
|
||||
NS_IMETHOD OnFileReady(nsresult aResult, bool aIsNew);
|
||||
NS_IMETHOD OnFileDoomed(nsresult aResult) { return NS_OK; }
|
||||
|
||||
nsRefPtr<CacheFile> mFile;
|
||||
nsRefPtr<CacheEntriesEnumeratorCallback> mCallback;
|
||||
};
|
||||
|
||||
nsresult FileConsumer::Init(const nsCSubstring &aKey,
|
||||
CacheEntriesEnumeratorCallback *aCallback)
|
||||
{
|
||||
mCallback = aCallback;
|
||||
|
||||
mFile = new CacheFile();
|
||||
nsresult rv = mFile->Init(aKey, false, false, false, true, this);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP FileConsumer::OnFileReady(nsresult aResult, bool aIsNew)
|
||||
{
|
||||
//MOZ_ASSERT(!aIsNew);
|
||||
|
||||
if (NS_FAILED(aResult)) {
|
||||
mCallback->OnFile(nullptr);
|
||||
}
|
||||
else {
|
||||
mCallback->OnFile(mFile);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(FileConsumer, CacheFileListener);
|
||||
|
||||
} // anon
|
||||
|
||||
nsresult CacheEntriesEnumerator::GetNextCacheFile(CacheEntriesEnumeratorCallback* aCallback)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
MOZ_ASSERT(mThreadCheck == NS_GetCurrentThread());
|
||||
#endif
|
||||
|
||||
nsresult rv;
|
||||
|
||||
NS_ENSURE_TRUE(mCurrentFile, NS_ERROR_UNEXPECTED);
|
||||
|
||||
nsAutoCString key;
|
||||
rv = mCurrentFile->GetNativeLeafName(key);
|
||||
|
||||
mCurrentFile = nullptr;
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsRefPtr<FileConsumer> consumer = new FileConsumer();
|
||||
rv = consumer->Init(key, aCallback);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult CacheEntriesEnumerator::GetNextFile(nsIFile** aFile)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
MOZ_ASSERT(mThreadCheck == NS_GetCurrentThread());
|
||||
#endif
|
||||
|
||||
NS_ENSURE_TRUE(mCurrentFile, NS_ERROR_UNEXPECTED);
|
||||
|
||||
mCurrentFile.forget(aFile);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult CacheEntriesEnumerator::GetCacheFileFromFile(nsIFile* aFile,
|
||||
CacheEntriesEnumeratorCallback* aCallback)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsAutoCString key;
|
||||
rv = aFile->GetNativeLeafName(key);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsRefPtr<FileConsumer> consumer = new FileConsumer();
|
||||
rv = consumer->Init(key, aCallback);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // net
|
||||
} // mozilla
|
|
@ -0,0 +1,55 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef CacheEntriesEnumerator__h__
|
||||
#define CacheEntriesEnumerator__h__
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
class nsIFile;
|
||||
class nsIDirectoryEnumerator;
|
||||
class nsIThread;
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class CacheFileIOManager;
|
||||
class CacheFileListener;
|
||||
class CacheFile;
|
||||
|
||||
class CacheEntriesEnumeratorCallback : public nsISupports
|
||||
{
|
||||
public:
|
||||
virtual void OnFile(CacheFile* aFile) = 0;
|
||||
};
|
||||
|
||||
class CacheEntriesEnumerator
|
||||
{
|
||||
public:
|
||||
~CacheEntriesEnumerator();
|
||||
|
||||
bool HasMore();
|
||||
nsresult GetNextCacheFile(CacheEntriesEnumeratorCallback* aCallback);
|
||||
nsresult GetNextFile(nsIFile** aFile);
|
||||
nsresult GetCacheFileFromFile(nsIFile* aFile, CacheEntriesEnumeratorCallback* aCallback);
|
||||
|
||||
protected:
|
||||
friend class CacheFileIOManager;
|
||||
CacheEntriesEnumerator(nsIFile* aEntriesDirectory);
|
||||
nsresult Init();
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIDirectoryEnumerator> mEnumerator;
|
||||
nsCOMPtr<nsIFile> mEntriesDirectory;
|
||||
nsCOMPtr<nsIFile> mCurrentFile;
|
||||
|
||||
#ifdef DEBUG
|
||||
nsCOMPtr<nsIThread> mThreadCheck;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // net
|
||||
} // mozilla
|
||||
|
||||
#endif
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,301 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef CacheEntry__h__
|
||||
#define CacheEntry__h__
|
||||
|
||||
#include "nsICacheEntry.h"
|
||||
#include "CacheFile.h"
|
||||
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsICacheEntryOpenCallback.h"
|
||||
#include "nsICacheEntryDoomCallback.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsString.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
|
||||
static inline uint32_t
|
||||
PRTimeToSeconds(PRTime t_usec)
|
||||
{
|
||||
PRTime usec_per_sec = PR_USEC_PER_SEC;
|
||||
return uint32_t(t_usec /= usec_per_sec);
|
||||
}
|
||||
|
||||
#define NowInSeconds() PRTimeToSeconds(PR_Now())
|
||||
|
||||
class nsIStorageStream;
|
||||
class nsIOutputStream;
|
||||
class nsIURI;
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class CacheStorageService;
|
||||
class CacheStorage;
|
||||
|
||||
namespace {
|
||||
class FrecencyComparator;
|
||||
class ExpirationComparator;
|
||||
class EvictionRunnable;
|
||||
class WalkRunnable;
|
||||
}
|
||||
|
||||
class CacheEntry : public nsICacheEntry
|
||||
, public nsIRunnable
|
||||
, public CacheFileListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSICACHEENTRY
|
||||
NS_DECL_NSIRUNNABLE
|
||||
|
||||
CacheEntry(const nsACString& aStorageID, nsIURI* aURI, const nsACString& aEnhanceID,
|
||||
bool aUseDisk);
|
||||
|
||||
void AsyncOpen(nsICacheEntryOpenCallback* aCallback, uint32_t aFlags);
|
||||
|
||||
public:
|
||||
uint32_t GetMetadataMemoryConsumption();
|
||||
nsCString const &GetStorageID() const { return mStorageID; }
|
||||
nsCString const &GetEnhanceID() const { return mEnhanceID; }
|
||||
nsIURI* GetURI() const { return mURI; }
|
||||
bool UsingDisk() const;
|
||||
bool SetUsingDisk(bool aUsingDisk);
|
||||
|
||||
// Methods for entry management (eviction from memory),
|
||||
// called only on the management thread.
|
||||
|
||||
// TODO make these inline
|
||||
double GetFrecency() const;
|
||||
uint32_t GetExpirationTime() const;
|
||||
|
||||
bool IsRegistered() const;
|
||||
bool CanRegister() const;
|
||||
void SetRegistered(bool aRegistered);
|
||||
|
||||
enum EPurge {
|
||||
PURGE_DATA_ONLY_DISK_BACKED,
|
||||
PURGE_WHOLE_ONLY_DISK_BACKED,
|
||||
PURGE_WHOLE,
|
||||
};
|
||||
|
||||
bool Purge(uint32_t aWhat);
|
||||
void PurgeAndDoom();
|
||||
void DoomAlreadyRemoved();
|
||||
|
||||
nsresult HashingKeyWithStorage(nsACString &aResult);
|
||||
nsresult HashingKey(nsACString &aResult);
|
||||
|
||||
static nsresult HashingKey(nsCSubstring const& aStorageID,
|
||||
nsCSubstring const& aEnhanceID,
|
||||
nsIURI* aURI,
|
||||
nsACString &aResult);
|
||||
|
||||
// Accessed only on the service management thread
|
||||
double mFrecency;
|
||||
uint32_t mSortingExpirationTime;
|
||||
|
||||
private:
|
||||
virtual ~CacheEntry();
|
||||
|
||||
// CacheFileListener
|
||||
NS_IMETHOD OnFileReady(nsresult aResult, bool aIsNew);
|
||||
NS_IMETHOD OnFileDoomed(nsresult aResult);
|
||||
|
||||
// Keep the service alive during life-time of an entry
|
||||
nsRefPtr<CacheStorageService> mService;
|
||||
|
||||
// We must monitor when a cache entry whose consumer is responsible
|
||||
// for writing it the first time gets released. We must then invoke
|
||||
// waiting callbacks to not break the chain.
|
||||
class Handle : public nsICacheEntry
|
||||
{
|
||||
public:
|
||||
Handle(CacheEntry* aEntry);
|
||||
virtual ~Handle();
|
||||
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_FORWARD_NSICACHEENTRY(mEntry->)
|
||||
private:
|
||||
nsRefPtr<CacheEntry> mEntry;
|
||||
};
|
||||
|
||||
// Since OnCacheEntryAvailable must be invoked on the main thread
|
||||
// we need a runnable for it...
|
||||
class AvailableCallbackRunnable : public nsRunnable
|
||||
{
|
||||
public:
|
||||
AvailableCallbackRunnable(CacheEntry* aEntry,
|
||||
nsICacheEntryOpenCallback* aCallback,
|
||||
bool aReadOnly,
|
||||
bool aNotWanted)
|
||||
: mEntry(aEntry), mCallback(aCallback)
|
||||
, mReadOnly(aReadOnly), mNotWanted(aNotWanted) {}
|
||||
|
||||
private:
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
mEntry->InvokeAvailableCallback(mCallback, mReadOnly, mNotWanted);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<CacheEntry> mEntry;
|
||||
nsCOMPtr<nsICacheEntryOpenCallback> mCallback;
|
||||
bool mReadOnly : 1;
|
||||
bool mNotWanted : 1;
|
||||
};
|
||||
|
||||
// Since OnCacheEntryDoomed must be invoked on the main thread
|
||||
// we need a runnable for it...
|
||||
class DoomCallbackRunnable : public nsRunnable
|
||||
{
|
||||
public:
|
||||
DoomCallbackRunnable(CacheEntry* aEntry, nsresult aRv)
|
||||
: mEntry(aEntry), mRv(aRv) {}
|
||||
|
||||
private:
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
nsCOMPtr<nsICacheEntryDoomCallback> callback;
|
||||
{
|
||||
mozilla::MutexAutoLock lock(mEntry->mLock);
|
||||
mEntry->mDoomCallback.swap(callback);
|
||||
}
|
||||
|
||||
if (callback)
|
||||
callback->OnCacheEntryDoomed(mRv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<CacheEntry> mEntry;
|
||||
nsresult mRv;
|
||||
};
|
||||
|
||||
// Loads from disk asynchronously
|
||||
bool Load(bool aTruncate, bool aPriority);
|
||||
void OnLoaded();
|
||||
|
||||
void RememberCallback(nsICacheEntryOpenCallback* aCallback, bool aReadOnly);
|
||||
bool PendingCallbacks();
|
||||
void InvokeCallbacks();
|
||||
bool InvokeCallback(nsICacheEntryOpenCallback* aCallback, bool aReadOnly);
|
||||
void InvokeAvailableCallback(nsICacheEntryOpenCallback* aCallback, bool aReadOnly, bool aNotWanted);
|
||||
void InvokeCallbacksMainThread();
|
||||
|
||||
nsresult OpenOutputStreamInternal(int64_t offset, nsIOutputStream * *_retval);
|
||||
|
||||
// When this entry is new and recreated w/o a callback, we need to wrap it
|
||||
// with a handle to detect writing consumer is gone.
|
||||
Handle* NewWriteHandle();
|
||||
void OnWriterClosed(Handle const* aHandle);
|
||||
|
||||
// Schedules a background operation on the management thread.
|
||||
// When executed on the management thread directly, the operation(s)
|
||||
// is (are) executed immediately.
|
||||
void BackgroundOp(uint32_t aOperation, bool aForceAsync = false);
|
||||
|
||||
already_AddRefed<CacheEntry> ReopenTruncated(nsICacheEntryOpenCallback* aCallback);
|
||||
void TransferCallbacks(CacheEntry const& aFromEntry);
|
||||
|
||||
mozilla::Mutex mLock;
|
||||
|
||||
nsCOMArray<nsICacheEntryOpenCallback> mCallbacks, mReadOnlyCallbacks;
|
||||
nsCOMPtr<nsICacheEntryDoomCallback> mDoomCallback;
|
||||
|
||||
nsRefPtr<CacheFile> mFile;
|
||||
nsresult mFileStatus;
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
nsCString mEnhanceID;
|
||||
nsCString mStorageID;
|
||||
|
||||
// Whether it's allowed to persist the data to disk
|
||||
// Synchronized by the service management lock.
|
||||
// Hence, leave it as a standalone boolean.
|
||||
bool mUseDisk;
|
||||
|
||||
// Set when entry is doomed with AsyncDoom() or DoomAlreadyRemoved().
|
||||
// Left as a standalone flag to not bother with locking (there is no need).
|
||||
bool mIsDoomed;
|
||||
|
||||
// Following flags are all synchronized with the cache entry lock.
|
||||
|
||||
// Whether security info has already been looked up in metadata.
|
||||
bool mSecurityInfoLoaded : 1;
|
||||
// Prevents any callback invocation
|
||||
bool mPreventCallbacks : 1;
|
||||
// Accessed only on the management thread.
|
||||
// Whether this entry is registered in the storage service helper arrays
|
||||
bool mIsRegistered : 1;
|
||||
// After deregistration entry is no allowed to register again
|
||||
bool mIsRegistrationAllowed : 1;
|
||||
// Way around when having a callback that cannot be invoked on non-main thread
|
||||
bool mHasMainThreadOnlyCallback : 1;
|
||||
// true: after load and an existing file, or after output stream has been opened.
|
||||
// note - when opening an input stream, and this flag is false, output stream
|
||||
// is open along ; this makes input streams on new entries behave correctly
|
||||
// when EOF is reached (WOULD_BLOCK is returned).
|
||||
// false: after load and a new file, or dropped to back to false when a writer
|
||||
// fails to open an output stream.
|
||||
bool mHasData : 1;
|
||||
|
||||
#ifdef MOZ_LOGGING
|
||||
static char const * StateString(uint32_t aState);
|
||||
#endif
|
||||
|
||||
enum EState { // transiting to:
|
||||
NOTLOADED = 0, // -> LOADING | EMPTY
|
||||
LOADING = 1, // -> EMPTY | READY
|
||||
EMPTY = 2, // -> WRITING
|
||||
WRITING = 3, // -> EMPTY | READY
|
||||
READY = 4, // -> REVALIDATING
|
||||
REVALIDATING = 5 // -> READY
|
||||
};
|
||||
|
||||
// State of this entry.
|
||||
EState mState;
|
||||
|
||||
// If a new (empty) entry is requested to open an input stream before
|
||||
// output stream has been opened, we must open output stream internally
|
||||
// on CacheFile and hold until writer releases the entry or opens the output
|
||||
// stream for read (then we trade him mOutputStream).
|
||||
nsCOMPtr<nsIOutputStream> mOutputStream;
|
||||
|
||||
// Weak reference to the current writter. There can be more then one
|
||||
// writer at a time and OnWriterClosed() must be processed only for the
|
||||
// current one.
|
||||
Handle* mWriter;
|
||||
|
||||
// Background thread scheduled operation. Set (under the lock) one
|
||||
// of this flags to tell the background thread what to do.
|
||||
class Ops {
|
||||
public:
|
||||
static uint32_t const REGISTER = 1 << 0;
|
||||
static uint32_t const FRECENCYUPDATE = 1 << 1;
|
||||
static uint32_t const DOOM = 1 << 2;
|
||||
static uint32_t const CALLBACKS = 1 << 3;
|
||||
|
||||
Ops() : mFlags(0) { }
|
||||
uint32_t Grab() { uint32_t flags = mFlags; mFlags = 0; return flags; }
|
||||
bool Set(uint32_t aFlags) { if (mFlags & aFlags) return false; mFlags |= aFlags; return true; }
|
||||
private:
|
||||
uint32_t mFlags;
|
||||
} mBackgroundOperations;
|
||||
|
||||
nsCOMPtr<nsISupports> mSecurityInfo;
|
||||
|
||||
int64_t mPredictedDataSize;
|
||||
uint32_t mDataSize; // ???
|
||||
};
|
||||
|
||||
} // net
|
||||
} // mozilla
|
||||
|
||||
#endif
|
|
@ -0,0 +1,250 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "CacheIOThread.h"
|
||||
#include "CacheFileIOManager.h"
|
||||
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "mozilla/VisualEventTracer.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
NS_IMPL_ISUPPORTS1(CacheIOThread, nsIThreadObserver)
|
||||
|
||||
CacheIOThread::CacheIOThread()
|
||||
: mMonitor("CacheIOThread")
|
||||
, mThread(nullptr)
|
||||
, mLowestLevelWaiting(LAST_LEVEL)
|
||||
, mHasXPCOMEvents(false)
|
||||
, mShutdown(false)
|
||||
{
|
||||
}
|
||||
|
||||
CacheIOThread::~CacheIOThread()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
for (uint32_t level = 0; level < LAST_LEVEL; ++level) {
|
||||
MOZ_ASSERT(!mEventQueue[level].Length());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
nsresult CacheIOThread::Init()
|
||||
{
|
||||
mThread = PR_CreateThread(PR_USER_THREAD, ThreadFunc, this,
|
||||
PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
|
||||
PR_JOINABLE_THREAD, 128 * 1024);
|
||||
if (!mThread)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult CacheIOThread::Dispatch(nsIRunnable* aRunnable, uint32_t aLevel)
|
||||
{
|
||||
NS_ENSURE_ARG(aLevel < LAST_LEVEL);
|
||||
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
|
||||
if (mShutdown && (PR_GetCurrentThread() != mThread))
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
mEventQueue[aLevel].AppendElement(aRunnable);
|
||||
if (mLowestLevelWaiting > aLevel)
|
||||
mLowestLevelWaiting = aLevel;
|
||||
|
||||
mMonitor.NotifyAll();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool CacheIOThread::IsCurrentThread()
|
||||
{
|
||||
return mThread == PR_GetCurrentThread();
|
||||
}
|
||||
|
||||
nsresult CacheIOThread::Shutdown()
|
||||
{
|
||||
{
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
mShutdown = true;
|
||||
mMonitor.NotifyAll();
|
||||
}
|
||||
|
||||
PR_JoinThread(mThread);
|
||||
mThread = nullptr;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIEventTarget> CacheIOThread::Target()
|
||||
{
|
||||
nsCOMPtr<nsIEventTarget> target;
|
||||
|
||||
if (mThread)
|
||||
{
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
if (!mXPCOMThread)
|
||||
lock.Wait();
|
||||
|
||||
target = mXPCOMThread;
|
||||
}
|
||||
|
||||
return target.forget();
|
||||
}
|
||||
|
||||
// static
|
||||
void CacheIOThread::ThreadFunc(void* aClosure)
|
||||
{
|
||||
PR_SetCurrentThreadName("Cache2 I/O");
|
||||
CacheIOThread* thread = static_cast<CacheIOThread*>(aClosure);
|
||||
thread->ThreadFunc();
|
||||
}
|
||||
|
||||
void CacheIOThread::ThreadFunc()
|
||||
{
|
||||
nsCOMPtr<nsIThreadInternal> threadInternal;
|
||||
|
||||
{
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
|
||||
// This creates nsThread for this PRThread
|
||||
mXPCOMThread = NS_GetCurrentThread();
|
||||
|
||||
threadInternal = do_QueryInterface(mXPCOMThread);
|
||||
if (threadInternal)
|
||||
threadInternal->SetObserver(this);
|
||||
|
||||
lock.NotifyAll();
|
||||
|
||||
static PRIntervalTime const waitTime = PR_MillisecondsToInterval(5000);
|
||||
|
||||
do {
|
||||
loopStart:
|
||||
// Reset the lowest level now, so that we can detect a new event on
|
||||
// a lower level (i.e. higher priority) has been scheduled while
|
||||
// executing any previously scheduled event.
|
||||
mLowestLevelWaiting = LAST_LEVEL;
|
||||
|
||||
// Process xpcom events first
|
||||
while (mHasXPCOMEvents) {
|
||||
eventtracer::AutoEventTracer tracer(this, eventtracer::eExec, eventtracer::eDone,
|
||||
"net::cache::io::level(xpcom)");
|
||||
|
||||
mHasXPCOMEvents = false;
|
||||
MonitorAutoUnlock unlock(mMonitor);
|
||||
|
||||
bool processedEvent;
|
||||
nsresult rv;
|
||||
do {
|
||||
rv = mXPCOMThread->ProcessNextEvent(false, &processedEvent);
|
||||
} while (NS_SUCCEEDED(rv) && processedEvent);
|
||||
}
|
||||
|
||||
uint32_t level;
|
||||
for (level = 0; level < LAST_LEVEL; ++level) {
|
||||
if (!mEventQueue[level].Length()) {
|
||||
// no events on this level, go to the next level
|
||||
continue;
|
||||
}
|
||||
|
||||
LoopOneLevel(level);
|
||||
|
||||
// Go to the first (lowest) level again
|
||||
goto loopStart;
|
||||
}
|
||||
|
||||
if (EventsPending())
|
||||
continue;
|
||||
|
||||
lock.Wait(waitTime);
|
||||
|
||||
if (EventsPending())
|
||||
continue;
|
||||
|
||||
} while (!mShutdown);
|
||||
|
||||
MOZ_ASSERT(!EventsPending());
|
||||
} // lock
|
||||
|
||||
if (threadInternal)
|
||||
threadInternal->SetObserver(nullptr);
|
||||
}
|
||||
|
||||
static const char* const sLevelTraceName[] = {
|
||||
"net::cache::io::level(0)",
|
||||
"net::cache::io::level(1)",
|
||||
"net::cache::io::level(2)",
|
||||
"net::cache::io::level(3)",
|
||||
"net::cache::io::level(4)",
|
||||
"net::cache::io::level(5)",
|
||||
"net::cache::io::level(6)",
|
||||
"net::cache::io::level(7)",
|
||||
"net::cache::io::level(8)",
|
||||
"net::cache::io::level(9)",
|
||||
"net::cache::io::level(10)",
|
||||
"net::cache::io::level(11)",
|
||||
"net::cache::io::level(12)"
|
||||
};
|
||||
|
||||
void CacheIOThread::LoopOneLevel(uint32_t aLevel)
|
||||
{
|
||||
eventtracer::AutoEventTracer tracer(this, eventtracer::eExec, eventtracer::eDone,
|
||||
sLevelTraceName[aLevel]);
|
||||
|
||||
nsTArray<nsRefPtr<nsIRunnable> > events;
|
||||
events.SwapElements(mEventQueue[aLevel]);
|
||||
uint32_t length = events.Length();
|
||||
|
||||
bool returnEvents = false;
|
||||
uint32_t index;
|
||||
{
|
||||
MonitorAutoUnlock unlock(mMonitor);
|
||||
|
||||
for (index = 0; index < length; ++index) {
|
||||
if (EventsPending(aLevel)) {
|
||||
// Somebody scheduled a new event on a lower level, break and harry
|
||||
// to execute it! Don't forget to return what we haven't exec.
|
||||
returnEvents = true;
|
||||
break;
|
||||
}
|
||||
|
||||
events[index]->Run();
|
||||
events[index] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (returnEvents)
|
||||
mEventQueue[aLevel].InsertElementsAt(0, events.Elements() + index, length - index);
|
||||
}
|
||||
|
||||
bool CacheIOThread::EventsPending(uint32_t aLastLevel)
|
||||
{
|
||||
return mLowestLevelWaiting < aLastLevel || mHasXPCOMEvents;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP CacheIOThread::OnDispatchedEvent(nsIThreadInternal *thread)
|
||||
{
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
mHasXPCOMEvents = true;
|
||||
lock.Notify();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP CacheIOThread::OnProcessNextEvent(nsIThreadInternal *thread, bool mayWait, uint32_t recursionDepth)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP CacheIOThread::AfterProcessNextEvent(nsIThreadInternal *thread, uint32_t recursionDepth)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // net
|
||||
} // mozilla
|
|
@ -0,0 +1,69 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef CacheIOThread__h__
|
||||
#define CacheIOThread__h__
|
||||
|
||||
#include "nsIThreadInternal.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "prthread.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "mozilla/Monitor.h"
|
||||
|
||||
class nsIRunnable;
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class CacheIOThread : public nsIThreadObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSITHREADOBSERVER
|
||||
|
||||
CacheIOThread();
|
||||
virtual ~CacheIOThread();
|
||||
|
||||
enum ELevel {
|
||||
IMMEDIATE,
|
||||
DOOM_PRIORITY,
|
||||
OPEN_PRIORITY,
|
||||
READ_PRIORITY,
|
||||
DOOM,
|
||||
OPEN,
|
||||
READ,
|
||||
OPEN_TRUNCATE,
|
||||
WRITE,
|
||||
CLOSE,
|
||||
EVICT,
|
||||
LAST_LEVEL
|
||||
};
|
||||
|
||||
nsresult Init();
|
||||
nsresult Dispatch(nsIRunnable* aRunnable, uint32_t aLevel);
|
||||
bool IsCurrentThread();
|
||||
nsresult Shutdown();
|
||||
already_AddRefed<nsIEventTarget> Target();
|
||||
|
||||
private:
|
||||
static void ThreadFunc(void* aClosure);
|
||||
void ThreadFunc();
|
||||
void LoopOneLevel(uint32_t aLevel);
|
||||
bool EventsPending(uint32_t aLastLevel = LAST_LEVEL);
|
||||
|
||||
mozilla::Monitor mMonitor;
|
||||
PRThread* mThread;
|
||||
nsCOMPtr<nsIThread> mXPCOMThread;
|
||||
uint32_t mLowestLevelWaiting;
|
||||
nsTArray<nsRefPtr<nsIRunnable> > mEventQueue[LAST_LEVEL];
|
||||
|
||||
bool mHasXPCOMEvents;
|
||||
bool mShutdown;
|
||||
};
|
||||
|
||||
} // net
|
||||
} // mozilla
|
||||
|
||||
#endif
|
|
@ -0,0 +1,30 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "CacheLog.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
#if defined(PR_LOGGING)
|
||||
// Log module for cache2 (2013) cache implementation logging...
|
||||
//
|
||||
// To enable logging (see prlog.h for full details):
|
||||
//
|
||||
// set NSPR_LOG_MODULES=cache2:5
|
||||
// set NSPR_LOG_FILE=nspr.log
|
||||
//
|
||||
// this enables PR_LOG_DEBUG level information and places all output in
|
||||
// the file nspr.log
|
||||
PRLogModuleInfo* GetCache2Log()
|
||||
{
|
||||
static PRLogModuleInfo *sLog;
|
||||
if (!sLog)
|
||||
sLog = PR_NewLogModule("cache2");
|
||||
return sLog;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // net
|
||||
} // mozilla
|
|
@ -0,0 +1,25 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef CacheLog__h__
|
||||
#define CacheLog__h__
|
||||
|
||||
#define FORCE_PR_LOG
|
||||
|
||||
#include "prlog.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
#if defined(PR_LOGGING)
|
||||
extern PRLogModuleInfo* GetCache2Log();
|
||||
#define LOG(x) PR_LOG(GetCache2Log(), PR_LOG_DEBUG, x)
|
||||
#else
|
||||
#define LOG(x)
|
||||
#endif /* PR_LOGGING */
|
||||
|
||||
} // net
|
||||
} // mozilla
|
||||
|
||||
#endif
|
|
@ -0,0 +1,148 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "CacheObserver.h"
|
||||
|
||||
#include "CacheStorageService.h"
|
||||
#include "CacheFileIOManager.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
CacheObserver* CacheObserver::sSelf = nullptr;
|
||||
|
||||
static uint32_t const kDefaultMemoryLimit = 50 * 1024; // 50 MB
|
||||
uint32_t CacheObserver::sMemoryLimit = kDefaultMemoryLimit;
|
||||
|
||||
static uint32_t const kDefaultUseNewCache = 0; // Don't use the new cache by default
|
||||
uint32_t CacheObserver::sUseNewCache = kDefaultUseNewCache;
|
||||
|
||||
NS_IMPL_ISUPPORTS2(CacheObserver,
|
||||
nsIObserver,
|
||||
nsISupportsWeakReference)
|
||||
|
||||
nsresult
|
||||
CacheObserver::Init()
|
||||
{
|
||||
if (sSelf) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (!obs) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
sSelf = new CacheObserver();
|
||||
NS_ADDREF(sSelf);
|
||||
|
||||
obs->AddObserver(sSelf, "prefservice:after-app-defaults", true);
|
||||
obs->AddObserver(sSelf, "profile-do-change", true);
|
||||
obs->AddObserver(sSelf, "profile-before-change", true);
|
||||
obs->AddObserver(sSelf, "xpcom-shutdown", true);
|
||||
obs->AddObserver(sSelf, "last-pb-context-exited", true);
|
||||
obs->AddObserver(sSelf, "memory-pressure", true);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
CacheObserver::Shutdown()
|
||||
{
|
||||
if (!sSelf) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
NS_RELEASE(sSelf);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
CacheObserver::AttachToPreferences()
|
||||
{
|
||||
mozilla::Preferences::AddUintVarCache(
|
||||
&sMemoryLimit, "browser.cache.memory_limit", kDefaultMemoryLimit);
|
||||
mozilla::Preferences::AddUintVarCache(
|
||||
&sUseNewCache, "browser.cache.use_new_backend", kDefaultUseNewCache);
|
||||
}
|
||||
|
||||
// static
|
||||
bool const CacheObserver::UseNewCache()
|
||||
{
|
||||
switch (sUseNewCache) {
|
||||
case 0: // use the old cache backend
|
||||
return false;
|
||||
|
||||
case 1: // use the new cache backend
|
||||
return true;
|
||||
|
||||
case 2: // use A/B testing
|
||||
{
|
||||
static bool const sABTest = rand() & 1;
|
||||
return sABTest;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CacheObserver::Observe(nsISupports* aSubject,
|
||||
const char* aTopic,
|
||||
const PRUnichar* aData)
|
||||
{
|
||||
if (!strcmp(aTopic, "prefservice:after-app-defaults")) {
|
||||
CacheFileIOManager::Init();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!strcmp(aTopic, "profile-do-change")) {
|
||||
CacheFileIOManager::Init();
|
||||
CacheFileIOManager::OnProfile();
|
||||
AttachToPreferences();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!strcmp(aTopic, "profile-before-change")) {
|
||||
nsRefPtr<CacheStorageService> service = CacheStorageService::Self();
|
||||
if (service)
|
||||
service->Shutdown();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!strcmp(aTopic, "xpcom-shutdown")) {
|
||||
nsRefPtr<CacheStorageService> service = CacheStorageService::Self();
|
||||
if (service)
|
||||
service->Shutdown();
|
||||
|
||||
CacheFileIOManager::Shutdown();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!strcmp(aTopic, "last-pb-context-exited")) {
|
||||
nsRefPtr<CacheStorageService> service = CacheStorageService::Self();
|
||||
if (service)
|
||||
service->DropPrivateBrowsingEntries();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!strcmp(aTopic, "memory-pressure")) {
|
||||
nsRefPtr<CacheStorageService> service = CacheStorageService::Self();
|
||||
if (service)
|
||||
service->PurgeFromMemory(nsICacheStorageService::PURGE_EVERYTHING);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // net
|
||||
} // mozilla
|
|
@ -0,0 +1,44 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef CacheObserver__h__
|
||||
#define CacheObserver__h__
|
||||
|
||||
#include "nsIObserver.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class CacheObserver : public nsIObserver
|
||||
, public nsSupportsWeakReference
|
||||
{
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
virtual ~CacheObserver() {}
|
||||
|
||||
static nsresult Init();
|
||||
static nsresult Shutdown();
|
||||
static CacheObserver* Self() { return sSelf; }
|
||||
|
||||
// Access to preferences
|
||||
static uint32_t const MemoryLimit() // <0.5MB,1024MB>, result in bytes.
|
||||
{ return std::max(512U, std::min(1048576U, sMemoryLimit)) << 10; }
|
||||
static bool const UseNewCache();
|
||||
|
||||
private:
|
||||
static CacheObserver* sSelf;
|
||||
|
||||
void AttachToPreferences();
|
||||
|
||||
static uint32_t sMemoryLimit;
|
||||
static uint32_t sUseNewCache;
|
||||
};
|
||||
|
||||
} // net
|
||||
} // mozilla
|
||||
|
||||
#endif
|
|
@ -0,0 +1,155 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "CacheStorage.h"
|
||||
#include "CacheStorageService.h"
|
||||
#include "CacheEntry.h"
|
||||
#include "CacheLog.h"
|
||||
|
||||
#include "OldWrappers.h"
|
||||
|
||||
#include "nsICacheEntryDoomCallback.h"
|
||||
|
||||
#include "nsIApplicationCache.h"
|
||||
#include "nsIApplicationCacheService.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
NS_IMPL_ISUPPORTS1(CacheStorage, nsICacheStorage)
|
||||
|
||||
CacheStorage::CacheStorage(nsILoadContextInfo* aInfo,
|
||||
bool aAllowDisk,
|
||||
bool aLookupAppCache)
|
||||
: mLoadContextInfo(GetLoadContextInfo(aInfo))
|
||||
, mWriteToDisk(aAllowDisk)
|
||||
, mLookupAppCache(aLookupAppCache)
|
||||
{
|
||||
}
|
||||
|
||||
CacheStorage::~CacheStorage()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP CacheStorage::AsyncOpenURI(nsIURI *aURI,
|
||||
const nsACString & aIdExtension,
|
||||
uint32_t aFlags,
|
||||
nsICacheEntryOpenCallback *aCallback)
|
||||
{
|
||||
if (!CacheStorageService::Self())
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
NS_ENSURE_ARG(aURI);
|
||||
NS_ENSURE_ARG(aCallback);
|
||||
|
||||
nsresult rv;
|
||||
|
||||
bool truncate = aFlags & nsICacheStorage::OPEN_TRUNCATE;
|
||||
|
||||
nsCOMPtr<nsIURI> noRefURI;
|
||||
rv = aURI->CloneIgnoringRef(getter_AddRefs(noRefURI));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIApplicationCache> appCache;
|
||||
if (LookupAppCache()) {
|
||||
MOZ_ASSERT(!truncate);
|
||||
|
||||
rv = ChooseApplicationCache(noRefURI, getter_AddRefs(appCache));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
if (appCache) {
|
||||
nsAutoCString cacheKey;
|
||||
rv = noRefURI->GetAsciiSpec(cacheKey);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsRefPtr<_OldCacheLoad> appCacheLoad =
|
||||
new _OldCacheLoad(cacheKey, aCallback, appCache,
|
||||
LoadInfo(), WriteToDisk(), aFlags);
|
||||
rv = appCacheLoad->Start();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
LOG(("CacheStorage::AsyncOpenURI loading from appcache"));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<CacheEntry> entry;
|
||||
rv = CacheStorageService::Self()->AddStorageEntry(
|
||||
this, noRefURI, aIdExtension,
|
||||
true, // create always
|
||||
truncate, // replace any existing one?
|
||||
getter_AddRefs(entry));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// May invoke the callback synchronously
|
||||
entry->AsyncOpen(aCallback, aFlags);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP CacheStorage::AsyncDoomURI(nsIURI *aURI, const nsACString & aIdExtension,
|
||||
nsICacheEntryDoomCallback* aCallback)
|
||||
{
|
||||
if (!CacheStorageService::Self())
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsresult rv = CacheStorageService::Self()->DoomStorageEntry(
|
||||
this, aURI, aIdExtension, aCallback);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP CacheStorage::AsyncEvictStorage(nsICacheEntryDoomCallback* aCallback)
|
||||
{
|
||||
if (!CacheStorageService::Self())
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsresult rv = CacheStorageService::Self()->DoomStorageEntries(
|
||||
this, aCallback);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP CacheStorage::AsyncVisitStorage(nsICacheStorageVisitor* aVisitor,
|
||||
bool aVisitEntries)
|
||||
{
|
||||
LOG(("CacheStorage::AsyncVisitStorage [this=%p, cb=%p, disk=%d]", this, aVisitor, (bool)mWriteToDisk));
|
||||
if (!CacheStorageService::Self())
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsresult rv = CacheStorageService::Self()->WalkStorageEntries(
|
||||
this, aVisitEntries, aVisitor);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Internal
|
||||
|
||||
nsresult CacheStorage::ChooseApplicationCache(nsIURI* aURI,
|
||||
nsIApplicationCache** aCache)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIApplicationCacheService> appCacheService =
|
||||
do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoCString cacheKey;
|
||||
rv = aURI->GetAsciiSpec(cacheKey);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = appCacheService->ChooseApplicationCache(cacheKey, LoadInfo(), aCache);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // net
|
||||
} // mozilla
|
|
@ -0,0 +1,59 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef CacheStorage__h__
|
||||
#define CacheStorage__h__
|
||||
|
||||
#include "nsICacheStorage.h"
|
||||
#include "CacheEntry.h"
|
||||
#include "LoadContextInfo.h"
|
||||
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsILoadContextInfo.h"
|
||||
#include "nsIApplicationCache.h"
|
||||
#include "nsICacheEntryDoomCallback.h"
|
||||
|
||||
class nsIURI;
|
||||
class nsIApplicationCache;
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
// This dance is needed to make CacheEntryTable declarable-only in headers
|
||||
// w/o exporting CacheEntry.h file to make nsNetModule.cpp compilable.
|
||||
typedef nsRefPtrHashtable<nsCStringHashKey, CacheEntry> TCacheEntryTable;
|
||||
class CacheEntryTable : public TCacheEntryTable { };
|
||||
|
||||
class CacheStorage : public nsICacheStorage
|
||||
{
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSICACHESTORAGE
|
||||
|
||||
public:
|
||||
CacheStorage(nsILoadContextInfo* aInfo,
|
||||
bool aAllowDisk,
|
||||
bool aLookupAppCache);
|
||||
|
||||
protected:
|
||||
virtual ~CacheStorage();
|
||||
|
||||
nsresult ChooseApplicationCache(nsIURI* aURI, nsIApplicationCache** aCache);
|
||||
|
||||
nsRefPtr<LoadContextInfo> mLoadContextInfo;
|
||||
bool mWriteToDisk : 1;
|
||||
bool mLookupAppCache : 1;
|
||||
|
||||
public:
|
||||
nsIApplicationCache* AppCache() const { return nullptr; }
|
||||
nsILoadContextInfo* LoadInfo() const { return mLoadContextInfo; }
|
||||
bool WriteToDisk() const { return mWriteToDisk && !mLoadContextInfo->IsPrivate(); }
|
||||
bool LookupAppCache() const { return mLookupAppCache; }
|
||||
};
|
||||
|
||||
} // net
|
||||
} // mozilla
|
||||
|
||||
#endif
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,222 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef CacheStorageService__h__
|
||||
#define CacheStorageService__h__
|
||||
|
||||
#include "nsICacheStorageService.h"
|
||||
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsString.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsProxyRelease.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
class nsIURI;
|
||||
class nsICacheEntryOpenCallback;
|
||||
class nsICacheEntryDoomCallback;
|
||||
class nsICacheStorageVisitor;
|
||||
class nsIRunnable;
|
||||
class nsIThread;
|
||||
class nsIEventTarget;
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class CacheStorageService;
|
||||
class CacheStorage;
|
||||
class CacheEntry;
|
||||
class CacheEntryTable;
|
||||
|
||||
class CacheMemoryConsumer
|
||||
{
|
||||
private:
|
||||
friend class CacheStorageService;
|
||||
uint32_t mReportedMemoryConsumption;
|
||||
protected:
|
||||
CacheMemoryConsumer();
|
||||
void DoMemoryReport(uint32_t aCurrentSize);
|
||||
};
|
||||
|
||||
class CacheStorageService : public nsICacheStorageService
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSICACHESTORAGESERVICE
|
||||
|
||||
CacheStorageService();
|
||||
|
||||
void Shutdown();
|
||||
void DropPrivateBrowsingEntries();
|
||||
|
||||
static CacheStorageService* Self() { return sSelf; }
|
||||
nsresult Dispatch(nsIRunnable* aEvent);
|
||||
static bool IsOnManagementThread() { return sSelf && NS_GetCurrentThread() == sSelf->mThread; }
|
||||
static bool IsRunning() { return sSelf && !sSelf->mShutdown; }
|
||||
nsIEventTarget* Thread() const { return mThread; }
|
||||
mozilla::Mutex& Lock() { return mLock; }
|
||||
|
||||
private:
|
||||
virtual ~CacheStorageService();
|
||||
void ShutdownBackground();
|
||||
|
||||
private:
|
||||
// The following methods may only be called on the management
|
||||
// thread.
|
||||
friend class CacheEntry;
|
||||
|
||||
/**
|
||||
* Registers the entry in management ordered arrays, a mechanism
|
||||
* helping with weighted purge of entries.
|
||||
* Management arrays keep hard reference to the entry. Entry is
|
||||
* responsible to remove it self or the service is responsible to
|
||||
* remove the entry when it's no longer needed.
|
||||
*/
|
||||
void RegisterEntry(CacheEntry* aEntry);
|
||||
|
||||
/**
|
||||
* Deregisters the entry from management arrays. References are
|
||||
* then released.
|
||||
*/
|
||||
void UnregisterEntry(CacheEntry* aEntry);
|
||||
|
||||
/**
|
||||
* Removes the entry from the related entry hash table, if still present.
|
||||
*/
|
||||
void RemoveEntry(CacheEntry* aEntry);
|
||||
|
||||
/**
|
||||
* Tells the storage service whether this entry is only to be stored in
|
||||
* memory.
|
||||
*/
|
||||
void RecordMemoryOnlyEntry(CacheEntry* aEntry,
|
||||
bool aOnlyInMemory,
|
||||
bool aOverwrite);
|
||||
|
||||
private:
|
||||
// Following methods are thread safe to call.
|
||||
friend class CacheStorage;
|
||||
|
||||
/**
|
||||
* Get, or create when not existing and demanded, an entry for the storage
|
||||
* and uri+id extension.
|
||||
*/
|
||||
nsresult AddStorageEntry(CacheStorage const* aStorage,
|
||||
nsIURI* aURI,
|
||||
const nsACString & aIdExtension,
|
||||
bool aCreateIfNotExist,
|
||||
bool aReplace,
|
||||
CacheEntry** aResult);
|
||||
|
||||
/**
|
||||
* Removes the entry from the related entry hash table, if still present
|
||||
* and returns it.
|
||||
*/
|
||||
nsresult DoomStorageEntry(CacheStorage const* aStorage,
|
||||
nsIURI* aURI,
|
||||
const nsACString & aIdExtension,
|
||||
nsICacheEntryDoomCallback* aCallback);
|
||||
|
||||
/**
|
||||
* Removes and returns entry table for the storage.
|
||||
*/
|
||||
nsresult DoomStorageEntries(CacheStorage const* aStorage,
|
||||
nsICacheEntryDoomCallback* aCallback);
|
||||
|
||||
/**
|
||||
* Walk all entiries beloging to the storage.
|
||||
*/
|
||||
nsresult WalkStorageEntries(CacheStorage const* aStorage,
|
||||
bool aVisitEntries,
|
||||
nsICacheStorageVisitor* aVisitor);
|
||||
|
||||
private:
|
||||
friend class CacheMemoryConsumer;
|
||||
|
||||
/**
|
||||
* When memory consumption of this entry radically changes, this method
|
||||
* is called to reflect the size of allocated memory. This call may purge
|
||||
* unspecified number of entries from memory (but not from disk).
|
||||
*/
|
||||
void OnMemoryConsumptionChange(CacheMemoryConsumer* aConsumer,
|
||||
uint32_t aCurrentMemoryConsumption);
|
||||
void PurgeOverMemoryLimit();
|
||||
|
||||
private:
|
||||
class PurgeFromMemoryRunnable : public nsRunnable
|
||||
{
|
||||
public:
|
||||
PurgeFromMemoryRunnable(CacheStorageService* aService, uint32_t aWhat)
|
||||
: mService(aService), mWhat(aWhat) { }
|
||||
|
||||
private:
|
||||
virtual ~PurgeFromMemoryRunnable() { }
|
||||
|
||||
NS_IMETHOD Run() {
|
||||
mService->PurgeAll(mWhat);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<CacheStorageService> mService;
|
||||
uint32_t mWhat;
|
||||
};
|
||||
|
||||
/**
|
||||
* Purges entries from memory based on the frecency ordered array.
|
||||
*/
|
||||
void PurgeByFrecency(bool &aFrecencyNeedsSort, uint32_t aWhat);
|
||||
void PurgeExpired();
|
||||
void PurgeAll(uint32_t aWhat);
|
||||
|
||||
nsresult DoomStorageEntries(nsCSubstring const& aContextKey,
|
||||
bool aDiskStorage,
|
||||
nsICacheEntryDoomCallback* aCallback);
|
||||
nsresult AddStorageEntry(nsCSubstring const& aContextKey,
|
||||
nsIURI* aURI,
|
||||
const nsACString & aIdExtension,
|
||||
bool aWriteToDisk,
|
||||
bool aCreateIfNotExist,
|
||||
bool aReplace,
|
||||
CacheEntry** aResult);
|
||||
|
||||
static CacheStorageService* sSelf;
|
||||
|
||||
mozilla::Mutex mLock;
|
||||
|
||||
bool mShutdown;
|
||||
|
||||
// The service thread
|
||||
nsCOMPtr<nsIThread> mThread;
|
||||
|
||||
// Accessible only on the service thread
|
||||
nsTArray<nsRefPtr<CacheEntry> > mFrecencyArray;
|
||||
nsTArray<nsRefPtr<CacheEntry> > mExpirationArray;
|
||||
mozilla::Atomic<uint32_t> mMemorySize;
|
||||
bool mPurging;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
void ProxyReleaseMainThread(nsCOMPtr<T> &object)
|
||||
{
|
||||
T* release;
|
||||
object.forget(&release);
|
||||
|
||||
nsCOMPtr<nsIThread> mainThread;
|
||||
NS_GetMainThread(getter_AddRefs(mainThread));
|
||||
NS_ProxyRelease(mainThread, release);
|
||||
}
|
||||
|
||||
} // net
|
||||
} // mozilla
|
||||
|
||||
#define NS_CACHE_STORAGE_SERVICE_CID \
|
||||
{ 0xea70b098, 0x5014, 0x4e21, \
|
||||
{ 0xae, 0xe1, 0x75, 0xe6, 0xb2, 0xc4, 0xb8, 0xe0 } } \
|
||||
|
||||
#define NS_CACHE_STORAGE_SERVICE_CONTRACTID \
|
||||
"@mozilla.org/netwerk/cache-storage-service;1"
|
||||
|
||||
#endif
|
|
@ -0,0 +1,17 @@
|
|||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DEPTH = @DEPTH@
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
LOCAL_INCLUDES = \
|
||||
-I$(srcdir)/../base/src \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
|
@ -0,0 +1,866 @@
|
|||
// Stuff to link the old imp to the new api - will go away!
|
||||
|
||||
#include "OldWrappers.h"
|
||||
#include "CacheStorage.h"
|
||||
#include "CacheStorageService.h"
|
||||
#include "CacheLog.h"
|
||||
#include "LoadContextInfo.h"
|
||||
|
||||
#include "nsIURI.h"
|
||||
#include "nsICacheService.h"
|
||||
#include "nsICacheSession.h"
|
||||
#include "nsIApplicationCache.h"
|
||||
#include "nsIApplicationCacheService.h"
|
||||
#include "nsIStreamTransportService.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsICacheEntryDoomCallback.h"
|
||||
#include "nsICacheListener.h"
|
||||
#include "nsICacheStorageVisitor.h"
|
||||
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsProxyRelease.h"
|
||||
|
||||
static NS_DEFINE_CID(kStreamTransportServiceCID,
|
||||
NS_STREAMTRANSPORTSERVICE_CID);
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
namespace { // anon
|
||||
|
||||
// Fires the doom callback back on the main thread
|
||||
// after the cache I/O thread is looped.
|
||||
|
||||
class DoomCallbackSynchronizer : public nsRunnable
|
||||
{
|
||||
public:
|
||||
DoomCallbackSynchronizer(nsICacheEntryDoomCallback* cb) : mCB(cb)
|
||||
{
|
||||
MOZ_COUNT_CTOR(DoomCallbackSynchronizer);
|
||||
}
|
||||
nsresult Dispatch();
|
||||
|
||||
private:
|
||||
virtual ~DoomCallbackSynchronizer()
|
||||
{
|
||||
MOZ_COUNT_DTOR(DoomCallbackSynchronizer);
|
||||
}
|
||||
|
||||
NS_DECL_NSIRUNNABLE
|
||||
nsCOMPtr<nsICacheEntryDoomCallback> mCB;
|
||||
};
|
||||
|
||||
nsresult DoomCallbackSynchronizer::Dispatch()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsICacheService> serv =
|
||||
do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIEventTarget> eventTarget;
|
||||
rv = serv->GetCacheIOTarget(getter_AddRefs(eventTarget));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = eventTarget->Dispatch(this, NS_DISPATCH_NORMAL);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DoomCallbackSynchronizer::Run()
|
||||
{
|
||||
if (!NS_IsMainThread()) {
|
||||
NS_DispatchToMainThread(this);
|
||||
}
|
||||
else {
|
||||
if (mCB)
|
||||
mCB->OnCacheEntryDoomed(NS_OK);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Receives doom callback from the old API and forwards to the new API
|
||||
|
||||
class DoomCallbackWrapper : public nsICacheListener
|
||||
{
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSICACHELISTENER
|
||||
|
||||
DoomCallbackWrapper(nsICacheEntryDoomCallback* cb) : mCB(cb)
|
||||
{
|
||||
MOZ_COUNT_CTOR(DoomCallbackWrapper);
|
||||
}
|
||||
|
||||
private:
|
||||
virtual ~DoomCallbackWrapper()
|
||||
{
|
||||
MOZ_COUNT_DTOR(DoomCallbackWrapper);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsICacheEntryDoomCallback> mCB;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1(DoomCallbackWrapper, nsICacheListener);
|
||||
|
||||
NS_IMETHODIMP DoomCallbackWrapper::OnCacheEntryAvailable(nsICacheEntryDescriptor *descriptor,
|
||||
nsCacheAccessMode accessGranted,
|
||||
nsresult status)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DoomCallbackWrapper::OnCacheEntryDoomed(nsresult status)
|
||||
{
|
||||
if (!mCB)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
mCB->OnCacheEntryDoomed(status);
|
||||
mCB = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Receives visit callbacks from the old API and forwards it to the new API
|
||||
|
||||
class VisitCallbackWrapper : public nsICacheVisitor
|
||||
{
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSICACHEVISITOR
|
||||
|
||||
VisitCallbackWrapper(char* const deviceID,
|
||||
nsICacheStorageVisitor* cb,
|
||||
bool visitEntries)
|
||||
: mCB(cb)
|
||||
, mVisitEntries(visitEntries)
|
||||
, mDeviceID(deviceID)
|
||||
{
|
||||
MOZ_COUNT_CTOR(VisitCallbackWrapper);
|
||||
}
|
||||
|
||||
private:
|
||||
virtual ~VisitCallbackWrapper();
|
||||
nsCOMPtr<nsICacheStorageVisitor> mCB;
|
||||
bool mVisitEntries;
|
||||
char* const mDeviceID;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1(VisitCallbackWrapper, nsICacheVisitor)
|
||||
|
||||
VisitCallbackWrapper::~VisitCallbackWrapper()
|
||||
{
|
||||
if (mVisitEntries)
|
||||
mCB->OnCacheEntryVisitCompleted();
|
||||
|
||||
MOZ_COUNT_DTOR(VisitCallbackWrapper);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP VisitCallbackWrapper::VisitDevice(const char * deviceID,
|
||||
nsICacheDeviceInfo *deviceInfo,
|
||||
bool *_retval)
|
||||
{
|
||||
if (!mCB)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*_retval = false;
|
||||
if (strcmp(deviceID, mDeviceID)) {
|
||||
// Not the device we want to visit
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
|
||||
uint32_t entryCount;
|
||||
rv = deviceInfo->GetEntryCount(&entryCount);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
uint32_t totalSize;
|
||||
rv = deviceInfo->GetTotalSize(&totalSize);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mCB->OnCacheStorageInfo(entryCount, totalSize);
|
||||
*_retval = mVisitEntries;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP VisitCallbackWrapper::VisitEntry(const char * deviceID,
|
||||
nsICacheEntryInfo *entryInfo,
|
||||
bool *_retval)
|
||||
{
|
||||
MOZ_ASSERT(!strcmp(deviceID, mDeviceID));
|
||||
|
||||
nsRefPtr<_OldCacheEntryWrapper> wrapper = new _OldCacheEntryWrapper(entryInfo);
|
||||
nsresult rv = mCB->OnCacheEntryInfo(wrapper);
|
||||
*_retval = NS_SUCCEEDED(rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // anon
|
||||
|
||||
|
||||
// _OldCacheEntryWrapper
|
||||
|
||||
_OldCacheEntryWrapper::_OldCacheEntryWrapper(nsICacheEntryDescriptor* desc)
|
||||
: mOldDesc(desc), mOldInfo(desc)
|
||||
{
|
||||
MOZ_COUNT_CTOR(_OldCacheEntryWrapper);
|
||||
LOG(("Creating _OldCacheEntryWrapper %p for descriptor %p", this, desc));
|
||||
}
|
||||
|
||||
_OldCacheEntryWrapper::_OldCacheEntryWrapper(nsICacheEntryInfo* info)
|
||||
: mOldInfo(info)
|
||||
{
|
||||
MOZ_COUNT_CTOR(_OldCacheEntryWrapper);
|
||||
LOG(("Creating _OldCacheEntryWrapper %p for info %p", this, info));
|
||||
}
|
||||
|
||||
_OldCacheEntryWrapper::~_OldCacheEntryWrapper()
|
||||
{
|
||||
MOZ_COUNT_DTOR(_OldCacheEntryWrapper);
|
||||
LOG(("Destroying _OldCacheEntryWrapper %p for descriptor %p", this, mOldInfo.get()));
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(_OldCacheEntryWrapper, nsICacheEntry)
|
||||
|
||||
NS_IMETHODIMP _OldCacheEntryWrapper::AsyncDoom(nsICacheEntryDoomCallback* listener)
|
||||
{
|
||||
nsRefPtr<DoomCallbackWrapper> cb = listener
|
||||
? new DoomCallbackWrapper(listener)
|
||||
: nullptr;
|
||||
return AsyncDoom(cb);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP _OldCacheEntryWrapper::GetDataSize(int64_t *aSize)
|
||||
{
|
||||
uint32_t size;
|
||||
nsresult rv = GetDataSize(&size);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
*aSize = size;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP _OldCacheEntryWrapper::GetPersistToDisk(bool *aPersistToDisk)
|
||||
{
|
||||
if (!mOldDesc) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsCacheStoragePolicy policy;
|
||||
rv = mOldDesc->GetStoragePolicy(&policy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*aPersistToDisk = policy != nsICache::STORE_IN_MEMORY;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP _OldCacheEntryWrapper::SetPersistToDisk(bool aPersistToDisk)
|
||||
{
|
||||
if (!mOldDesc) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsCacheStoragePolicy policy;
|
||||
rv = mOldDesc->GetStoragePolicy(&policy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (policy == nsICache::STORE_OFFLINE) {
|
||||
return aPersistToDisk
|
||||
? NS_OK
|
||||
: NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
policy = aPersistToDisk
|
||||
? nsICache::STORE_ON_DISK
|
||||
: nsICache::STORE_IN_MEMORY;
|
||||
rv = mOldDesc->SetStoragePolicy(policy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP _OldCacheEntryWrapper::Recreate(nsICacheEntry** aResult)
|
||||
{
|
||||
NS_ENSURE_TRUE(mOldDesc, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
nsCacheAccessMode mode;
|
||||
nsresult rv = mOldDesc->GetAccessGranted(&mode);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!(mode & nsICache::ACCESS_WRITE))
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
LOG(("_OldCacheEntryWrapper::Recreate [this=%p]", this));
|
||||
|
||||
nsCOMPtr<nsICacheEntry> self(this);
|
||||
self.forget(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP _OldCacheEntryWrapper::OpenInputStream(int64_t offset,
|
||||
nsIInputStream * *_retval)
|
||||
{
|
||||
if (offset > PR_UINT32_MAX)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
return OpenInputStream(uint32_t(offset), _retval);
|
||||
}
|
||||
NS_IMETHODIMP _OldCacheEntryWrapper::OpenOutputStream(int64_t offset,
|
||||
nsIOutputStream * *_retval)
|
||||
{
|
||||
if (offset > PR_UINT32_MAX)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
return OpenOutputStream(uint32_t(offset), _retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP _OldCacheEntryWrapper::MaybeMarkValid()
|
||||
{
|
||||
LOG(("_OldCacheEntryWrapper::MaybeMarkValid [this=%p]", this));
|
||||
|
||||
NS_ENSURE_TRUE(mOldDesc, NS_ERROR_NULL_POINTER);
|
||||
|
||||
nsCacheAccessMode mode;
|
||||
nsresult rv = mOldDesc->GetAccessGranted(&mode);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (mode & nsICache::ACCESS_WRITE) {
|
||||
LOG(("Marking cache entry valid [entry=%p, descr=%p]", this, mOldDesc));
|
||||
return mOldDesc->MarkValid();
|
||||
}
|
||||
|
||||
LOG(("Not marking read-only cache entry valid [entry=%p, descr=%p]", this, mOldDesc));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP _OldCacheEntryWrapper::HasWriteAccess(bool aWriteAllowed_unused, bool *aWriteAccess)
|
||||
{
|
||||
NS_ENSURE_TRUE(mOldDesc, NS_ERROR_NULL_POINTER);
|
||||
NS_ENSURE_ARG(aWriteAccess);
|
||||
|
||||
nsCacheAccessMode mode;
|
||||
nsresult rv = mOldDesc->GetAccessGranted(&mode);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*aWriteAccess = !!(mode & nsICache::ACCESS_WRITE);
|
||||
|
||||
LOG(("_OldCacheEntryWrapper::HasWriteAccess [this=%p, write-access=%d]", this, *aWriteAccess));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
namespace { // anon
|
||||
|
||||
void
|
||||
GetCacheSessionNameForStoragePolicy(
|
||||
nsCacheStoragePolicy storagePolicy,
|
||||
bool isPrivate,
|
||||
uint32_t appId,
|
||||
bool inBrowser,
|
||||
nsACString& sessionName)
|
||||
{
|
||||
MOZ_ASSERT(!isPrivate || storagePolicy == nsICache::STORE_IN_MEMORY);
|
||||
|
||||
switch (storagePolicy) {
|
||||
case nsICache::STORE_IN_MEMORY:
|
||||
sessionName.AssignASCII(isPrivate ? "HTTP-memory-only-PB" : "HTTP-memory-only");
|
||||
break;
|
||||
case nsICache::STORE_OFFLINE:
|
||||
sessionName.AssignLiteral("HTTP-offline");
|
||||
break;
|
||||
default:
|
||||
sessionName.AssignLiteral("HTTP");
|
||||
break;
|
||||
}
|
||||
if (appId != nsILoadContextInfo::NO_APP_ID || inBrowser) {
|
||||
sessionName.Append('~');
|
||||
sessionName.AppendInt(appId);
|
||||
sessionName.Append('~');
|
||||
sessionName.AppendInt(inBrowser);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
GetCacheSession(bool aWriteToDisk,
|
||||
nsILoadContextInfo* aLoadInfo,
|
||||
nsIApplicationCache* aAppCache,
|
||||
nsICacheSession** _result)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCacheStoragePolicy storagePolicy;
|
||||
if (aAppCache)
|
||||
storagePolicy = nsICache::STORE_OFFLINE;
|
||||
else if (!aWriteToDisk || aLoadInfo->IsPrivate())
|
||||
storagePolicy = nsICache::STORE_IN_MEMORY;
|
||||
else
|
||||
storagePolicy = nsICache::STORE_ANYWHERE;
|
||||
|
||||
nsAutoCString clientId;
|
||||
if (aAppCache) {
|
||||
aAppCache->GetClientID(clientId);
|
||||
}
|
||||
else {
|
||||
GetCacheSessionNameForStoragePolicy(
|
||||
storagePolicy,
|
||||
aLoadInfo->IsPrivate(),
|
||||
aLoadInfo->AppId(),
|
||||
aLoadInfo->IsInBrowserElement(),
|
||||
clientId);
|
||||
}
|
||||
|
||||
LOG((" GetCacheSession for client=%s, policy=%d", clientId.get(), storagePolicy));
|
||||
|
||||
nsCOMPtr<nsICacheService> serv =
|
||||
do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsICacheSession> session;
|
||||
rv = serv->CreateSession(clientId.get(),
|
||||
storagePolicy,
|
||||
nsICache::STREAM_BASED,
|
||||
getter_AddRefs(session));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = session->SetIsPrivate(aLoadInfo->IsPrivate());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = session->SetDoomEntriesIfExpired(false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (aAppCache) {
|
||||
nsCOMPtr<nsIFile> profileDirectory;
|
||||
aAppCache->GetProfileDirectory(getter_AddRefs(profileDirectory));
|
||||
if (profileDirectory)
|
||||
rv = session->SetProfileDirectory(profileDirectory);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
session.forget(_result);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // anon
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED1(_OldCacheLoad, nsRunnable, nsICacheListener)
|
||||
|
||||
_OldCacheLoad::_OldCacheLoad(nsCSubstring const& aCacheKey,
|
||||
nsICacheEntryOpenCallback* aCallback,
|
||||
nsIApplicationCache* aAppCache,
|
||||
nsILoadContextInfo* aLoadInfo,
|
||||
bool aWriteToDisk,
|
||||
uint32_t aFlags)
|
||||
: mCacheKey(aCacheKey)
|
||||
, mCallback(aCallback)
|
||||
, mLoadInfo(GetLoadContextInfo(aLoadInfo))
|
||||
, mFlags(aFlags)
|
||||
, mWriteToDisk(aWriteToDisk)
|
||||
, mMainThreadOnly(true)
|
||||
, mNew(true)
|
||||
, mStatus(NS_ERROR_UNEXPECTED)
|
||||
, mRunCount(0)
|
||||
, mAppCache(aAppCache)
|
||||
{
|
||||
MOZ_COUNT_CTOR(_OldCacheLoad);
|
||||
}
|
||||
|
||||
_OldCacheLoad::~_OldCacheLoad()
|
||||
{
|
||||
ProxyReleaseMainThread(mAppCache);
|
||||
MOZ_COUNT_DTOR(_OldCacheLoad);
|
||||
}
|
||||
|
||||
nsresult _OldCacheLoad::Start()
|
||||
{
|
||||
LOG(("_OldCacheLoad::Start [this=%p, key=%s]", this, mCacheKey.get()));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
bool mainThreadOnly;
|
||||
if (mCallback && (
|
||||
NS_SUCCEEDED(mCallback->GetMainThreadOnly(&mainThreadOnly)) &&
|
||||
!mainThreadOnly)) {
|
||||
mMainThreadOnly = false;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// XXX: Start the cache service; otherwise DispatchToCacheIOThread will
|
||||
// fail.
|
||||
nsCOMPtr<nsICacheService> service =
|
||||
do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
|
||||
|
||||
// Ensure the stream transport service gets initialized on the main thread
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsIStreamTransportService> sts =
|
||||
do_GetService(kStreamTransportServiceCID, &rv);
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = service->GetCacheIOTarget(getter_AddRefs(mCacheThread));
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = mCacheThread->Dispatch(this, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
_OldCacheLoad::Run()
|
||||
{
|
||||
LOG(("_OldCacheLoad::Run [this=%p, key=%s, cb=%p]", this, mCacheKey.get(), mCallback.get()));
|
||||
|
||||
nsresult rv;
|
||||
|
||||
if (!NS_IsMainThread()) {
|
||||
nsCOMPtr<nsICacheSession> session;
|
||||
rv = GetCacheSession(mWriteToDisk, mLoadInfo, mAppCache, getter_AddRefs(session));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// AsyncOpenCacheEntry isn't really async when its called on the
|
||||
// cache service thread.
|
||||
|
||||
nsCacheAccessMode cacheAccess;
|
||||
if (mFlags & nsICacheStorage::OPEN_TRUNCATE)
|
||||
cacheAccess = nsICache::ACCESS_WRITE;
|
||||
else if ((mFlags & nsICacheStorage::OPEN_READONLY) || mAppCache)
|
||||
cacheAccess = nsICache::ACCESS_READ;
|
||||
else
|
||||
cacheAccess = nsICache::ACCESS_READ_WRITE;
|
||||
|
||||
LOG((" session->AsyncOpenCacheEntry with access=%d", cacheAccess));
|
||||
|
||||
bool bypassBusy = mFlags & nsICacheStorage::OPEN_BYPASS_IF_BUSY;
|
||||
rv = session->AsyncOpenCacheEntry(mCacheKey, cacheAccess, this, bypassBusy);
|
||||
|
||||
if (NS_SUCCEEDED(rv))
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Opening failed, propagate the error to the consumer
|
||||
LOG((" Opening cache entry failed with rv=0x%08x", rv));
|
||||
mStatus = rv;
|
||||
mNew = false;
|
||||
NS_DispatchToMainThread(this);
|
||||
} else {
|
||||
if (!mCallback) {
|
||||
LOG((" duplicate call, bypassed"));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mMainThreadOnly)
|
||||
Check();
|
||||
|
||||
// break cycles
|
||||
nsCOMPtr<nsICacheEntryOpenCallback> cb = mCallback.forget();
|
||||
mCacheThread = nullptr;
|
||||
nsCOMPtr<nsICacheEntry> entry = mCacheEntry.forget();
|
||||
|
||||
rv = cb->OnCacheEntryAvailable(entry, mNew, mAppCache, mStatus);
|
||||
|
||||
if (NS_FAILED(rv) && entry) {
|
||||
LOG((" cb->OnCacheEntryAvailable failed with rv=0x%08x", rv));
|
||||
if (mNew)
|
||||
entry->AsyncDoom(nullptr);
|
||||
else
|
||||
entry->Close();
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
_OldCacheLoad::OnCacheEntryAvailable(nsICacheEntryDescriptor *entry,
|
||||
nsCacheAccessMode access,
|
||||
nsresult status)
|
||||
{
|
||||
LOG(("_OldCacheLoad::OnCacheEntryAvailable [this=%p, ent=%p, cb=%p, appcache=%p, access=%x]",
|
||||
this, entry, mCallback.get(), mAppCache.get(), access));
|
||||
|
||||
// XXX Bug 759805: Sometimes we will call this method directly from
|
||||
// HttpCacheQuery::Run when AsyncOpenCacheEntry fails, but
|
||||
// AsyncOpenCacheEntry will also call this method. As a workaround, we just
|
||||
// ensure we only execute this code once.
|
||||
NS_ENSURE_TRUE(mRunCount == 0, NS_ERROR_UNEXPECTED);
|
||||
++mRunCount;
|
||||
|
||||
mCacheEntry = entry ? new _OldCacheEntryWrapper(entry) : nullptr;
|
||||
mStatus = status;
|
||||
mNew = access == nsICache::ACCESS_WRITE;
|
||||
|
||||
if (!mMainThreadOnly)
|
||||
Check();
|
||||
|
||||
return NS_DispatchToMainThread(this);
|
||||
}
|
||||
|
||||
void
|
||||
_OldCacheLoad::Check()
|
||||
{
|
||||
if (!mCacheEntry)
|
||||
return;
|
||||
|
||||
if (mNew)
|
||||
return;
|
||||
|
||||
uint32_t result;
|
||||
nsresult rv = mCallback->OnCacheEntryCheck(mCacheEntry, mAppCache, &result);
|
||||
LOG((" OnCacheEntryCheck result ent=%p, cb=%p, appcache=%p, rv=0x%08x, result=%d",
|
||||
mCacheEntry.get(), mCallback.get(), mAppCache.get(), rv, result));
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("cache check failed");
|
||||
}
|
||||
|
||||
if (result == nsICacheEntryOpenCallback::ENTRY_NOT_WANTED) {
|
||||
mCacheEntry->Close();
|
||||
mCacheEntry = nullptr;
|
||||
mStatus = NS_ERROR_CACHE_KEY_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
_OldCacheLoad::OnCacheEntryDoomed(nsresult)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
// nsICacheStorage old cache wrapper
|
||||
|
||||
NS_IMPL_ISUPPORTS1(_OldStorage, nsICacheStorage)
|
||||
|
||||
_OldStorage::_OldStorage(nsILoadContextInfo* aInfo,
|
||||
bool aAllowDisk,
|
||||
bool aLookupAppCache,
|
||||
bool aOfflineStorage,
|
||||
nsIApplicationCache* aAppCache)
|
||||
: mLoadInfo(GetLoadContextInfo(aInfo))
|
||||
, mAppCache(aAppCache)
|
||||
, mWriteToDisk(aAllowDisk)
|
||||
, mLookupAppCache(aLookupAppCache)
|
||||
, mOfflineStorage(aOfflineStorage)
|
||||
{
|
||||
MOZ_COUNT_CTOR(_OldStorage);
|
||||
}
|
||||
|
||||
_OldStorage::~_OldStorage()
|
||||
{
|
||||
MOZ_COUNT_DTOR(_OldStorage);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP _OldStorage::AsyncOpenURI(nsIURI *aURI,
|
||||
const nsACString & aIdExtension,
|
||||
uint32_t aFlags,
|
||||
nsICacheEntryOpenCallback *aCallback)
|
||||
{
|
||||
NS_ENSURE_ARG(aURI);
|
||||
NS_ENSURE_ARG(aCallback);
|
||||
|
||||
#ifdef MOZ_LOGGING
|
||||
nsAutoCString uriSpec;
|
||||
aURI->GetAsciiSpec(uriSpec);
|
||||
LOG(("_OldStorage::AsyncOpenURI [this=%p, uri=%s, ide=%s, flags=%x]",
|
||||
this, uriSpec.get(), aIdExtension.BeginReading(), aFlags));
|
||||
#endif
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsAutoCString cacheKey;
|
||||
rv = AssembleCacheKey(aURI, aIdExtension, cacheKey);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!mAppCache && (mLookupAppCache || mOfflineStorage)) {
|
||||
rv = ChooseApplicationCache(cacheKey, getter_AddRefs(mAppCache));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
nsRefPtr<_OldCacheLoad> cacheLoad =
|
||||
new _OldCacheLoad(cacheKey, aCallback, mAppCache,
|
||||
mLoadInfo, mWriteToDisk, aFlags);
|
||||
|
||||
rv = cacheLoad->Start();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP _OldStorage::AsyncDoomURI(nsIURI *aURI, const nsACString & aIdExtension,
|
||||
nsICacheEntryDoomCallback* aCallback)
|
||||
{
|
||||
LOG(("_OldStorage::AsyncDoomURI"));
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsAutoCString cacheKey;
|
||||
rv = AssembleCacheKey(aURI, aIdExtension, cacheKey);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsICacheSession> session;
|
||||
rv = GetCacheSession(mWriteToDisk, mLoadInfo, mAppCache, getter_AddRefs(session));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsRefPtr<DoomCallbackWrapper> cb = aCallback
|
||||
? new DoomCallbackWrapper(aCallback)
|
||||
: nullptr;
|
||||
rv = session->DoomEntry(cacheKey, cb);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP _OldStorage::AsyncEvictStorage(nsICacheEntryDoomCallback* aCallback)
|
||||
{
|
||||
LOG(("_OldStorage::AsyncEvictStorage"));
|
||||
|
||||
nsresult rv;
|
||||
|
||||
if (!mAppCache && mOfflineStorage) {
|
||||
// Special casing for pure offline storage
|
||||
if (mLoadInfo->AppId() == nsILoadContextInfo::NO_APP_ID &&
|
||||
!mLoadInfo->IsInBrowserElement()) {
|
||||
|
||||
// Clear everything.
|
||||
nsCOMPtr<nsICacheService> serv =
|
||||
do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = serv->EvictEntries(nsICache::STORE_OFFLINE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
else {
|
||||
// Clear app or inbrowser staff.
|
||||
nsCOMPtr<nsIApplicationCacheService> appCacheService =
|
||||
do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = appCacheService->DiscardByAppId(mLoadInfo->AppId(),
|
||||
mLoadInfo->IsInBrowserElement());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
else {
|
||||
nsCOMPtr<nsICacheSession> session;
|
||||
rv = GetCacheSession(mWriteToDisk, mLoadInfo, mAppCache, getter_AddRefs(session));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = session->EvictEntries();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
if (aCallback) {
|
||||
nsRefPtr<DoomCallbackSynchronizer> sync =
|
||||
new DoomCallbackSynchronizer(aCallback);
|
||||
rv = sync->Dispatch();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP _OldStorage::AsyncVisitStorage(nsICacheStorageVisitor* aVisitor,
|
||||
bool aVisitEntries)
|
||||
{
|
||||
LOG(("_OldStorage::AsyncVisitStorage"));
|
||||
|
||||
NS_ENSURE_ARG(aVisitor);
|
||||
|
||||
if (mLoadInfo->IsAnonymous()) {
|
||||
// There is no concept of 'anonymous' storage in the old cache
|
||||
// since anon cache entries are stored in 'non-anon' storage
|
||||
// with a special prefix.
|
||||
// Just fake we have 0 items with 0 consumption. This at least
|
||||
// prevents displaying double size in the advanced section of
|
||||
// the Options dialog.
|
||||
aVisitor->OnCacheStorageInfo(0, 0);
|
||||
if (aVisitEntries)
|
||||
aVisitor->OnCacheEntryVisitCompleted();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsICacheService> serv =
|
||||
do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
char* deviceID;
|
||||
if (mAppCache || mOfflineStorage) {
|
||||
deviceID = const_cast<char*>("offline");
|
||||
} else if (!mWriteToDisk || mLoadInfo->IsPrivate()) {
|
||||
deviceID = const_cast<char*>("memory");
|
||||
} else {
|
||||
deviceID = const_cast<char*>("disk");
|
||||
}
|
||||
|
||||
nsRefPtr<VisitCallbackWrapper> cb = new VisitCallbackWrapper(
|
||||
deviceID, aVisitor, aVisitEntries);
|
||||
rv = serv->VisitEntries(cb);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Internal
|
||||
|
||||
nsresult _OldStorage::AssembleCacheKey(nsIURI *aURI,
|
||||
nsACString const & aIdExtension,
|
||||
nsACString & aCacheKey)
|
||||
{
|
||||
// Copied from nsHttpChannel::AssembleCacheKey
|
||||
|
||||
aCacheKey.Truncate();
|
||||
|
||||
if (mLoadInfo->IsAnonymous()) {
|
||||
aCacheKey.AssignLiteral("anon&");
|
||||
}
|
||||
|
||||
if (!aIdExtension.IsEmpty()) {
|
||||
aCacheKey.AppendPrintf("id=%s&", aIdExtension.BeginReading());
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIURI> noRefURI;
|
||||
rv = aURI->CloneIgnoringRef(getter_AddRefs(noRefURI));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoCString uriSpec;
|
||||
rv = noRefURI->GetAsciiSpec(uriSpec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!aCacheKey.IsEmpty()) {
|
||||
aCacheKey.AppendLiteral("uri=");
|
||||
}
|
||||
aCacheKey.Append(uriSpec);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult _OldStorage::ChooseApplicationCache(nsCSubstring const &cacheKey,
|
||||
nsIApplicationCache** aCache)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIApplicationCacheService> appCacheService =
|
||||
do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = appCacheService->ChooseApplicationCache(cacheKey, mLoadInfo, aCache);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // net
|
||||
} // mozilla
|
|
@ -0,0 +1,120 @@
|
|||
// Stuff to link the old imp to the new api - will go away!
|
||||
|
||||
#ifndef OLDWRAPPERS__H__
|
||||
#define OLDWRAPPERS__H__
|
||||
|
||||
#include "nsICacheEntry.h"
|
||||
#include "nsICacheListener.h"
|
||||
#include "nsICacheStorage.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsICacheEntryOpenCallback.h"
|
||||
#include "nsICacheEntryDescriptor.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
class nsIURI;
|
||||
class nsICacheEntryOpenCallback;
|
||||
class nsIApplicationCache;
|
||||
class nsILoadContextInfo;
|
||||
|
||||
namespace mozilla { namespace net {
|
||||
|
||||
class CacheStorage;
|
||||
|
||||
class _OldCacheEntryWrapper : public nsICacheEntry
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_FORWARD_SAFE_NSICACHEENTRYDESCRIPTOR(mOldDesc)
|
||||
NS_FORWARD_NSICACHEENTRYINFO(mOldInfo->)
|
||||
|
||||
NS_IMETHOD AsyncDoom(nsICacheEntryDoomCallback* listener);
|
||||
NS_IMETHOD GetPersistToDisk(bool *aPersistToDisk);
|
||||
NS_IMETHOD SetPersistToDisk(bool aPersistToDisk);
|
||||
NS_IMETHOD SetValid() { return NS_OK; }
|
||||
NS_IMETHOD MetaDataReady() { return NS_OK; }
|
||||
NS_IMETHOD Recreate(nsICacheEntry**);
|
||||
NS_IMETHOD GetDataSize(int64_t *size);
|
||||
NS_IMETHOD OpenInputStream(int64_t offset, nsIInputStream * *_retval);
|
||||
NS_IMETHOD OpenOutputStream(int64_t offset, nsIOutputStream * *_retval);
|
||||
NS_IMETHOD MaybeMarkValid();
|
||||
NS_IMETHOD HasWriteAccess(bool aWriteOnly, bool *aWriteAccess);
|
||||
|
||||
_OldCacheEntryWrapper(nsICacheEntryDescriptor* desc);
|
||||
_OldCacheEntryWrapper(nsICacheEntryInfo* info);
|
||||
|
||||
virtual ~_OldCacheEntryWrapper();
|
||||
|
||||
private:
|
||||
_OldCacheEntryWrapper() MOZ_DELETE;
|
||||
nsICacheEntryDescriptor* mOldDesc; // ref holded in mOldInfo
|
||||
nsCOMPtr<nsICacheEntryInfo> mOldInfo;
|
||||
};
|
||||
|
||||
|
||||
class _OldCacheLoad : public nsRunnable
|
||||
, public nsICacheListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIRUNNABLE
|
||||
NS_DECL_NSICACHELISTENER
|
||||
|
||||
_OldCacheLoad(nsCSubstring const& aCacheKey,
|
||||
nsICacheEntryOpenCallback* aCallback,
|
||||
nsIApplicationCache* aAppCache,
|
||||
nsILoadContextInfo* aLoadInfo,
|
||||
bool aWriteToDisk,
|
||||
uint32_t aFlags);
|
||||
virtual ~_OldCacheLoad();
|
||||
|
||||
nsresult Start();
|
||||
|
||||
private:
|
||||
void Check();
|
||||
|
||||
nsCOMPtr<nsIEventTarget> mCacheThread;
|
||||
|
||||
nsCString mCacheKey;
|
||||
nsCOMPtr<nsICacheEntryOpenCallback> mCallback;
|
||||
nsCOMPtr<nsILoadContextInfo> mLoadInfo;
|
||||
uint32_t mFlags;
|
||||
|
||||
bool const mWriteToDisk : 1;
|
||||
bool mMainThreadOnly : 1;
|
||||
bool mNew : 1;
|
||||
|
||||
nsCOMPtr<nsICacheEntry> mCacheEntry;
|
||||
nsresult mStatus;
|
||||
uint32_t mRunCount;
|
||||
nsCOMPtr<nsIApplicationCache> mAppCache;
|
||||
};
|
||||
|
||||
|
||||
class _OldStorage : public nsICacheStorage
|
||||
{
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSICACHESTORAGE
|
||||
|
||||
public:
|
||||
_OldStorage(nsILoadContextInfo* aInfo,
|
||||
bool aAllowDisk,
|
||||
bool aLookupAppCache,
|
||||
bool aOfflineStorage,
|
||||
nsIApplicationCache* aAppCache);
|
||||
|
||||
private:
|
||||
virtual ~_OldStorage();
|
||||
nsresult AssembleCacheKey(nsIURI *aURI, nsACString const & aIdExtension, nsACString & _result);
|
||||
nsresult ChooseApplicationCache(nsCSubstring const &cacheKey, nsIApplicationCache** aCache);
|
||||
|
||||
nsCOMPtr<nsILoadContextInfo> mLoadInfo;
|
||||
nsCOMPtr<nsIApplicationCache> mAppCache;
|
||||
bool const mWriteToDisk : 1;
|
||||
bool const mLookupAppCache : 1;
|
||||
bool const mOfflineStorage : 1;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,51 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsICacheEntry.idl',
|
||||
'nsICacheEntryDoomCallback.idl',
|
||||
'nsICacheEntryOpenCallback.idl',
|
||||
'nsICacheStorage.idl',
|
||||
'nsICacheStorageService.idl',
|
||||
'nsICacheStorageVisitor.idl',
|
||||
]
|
||||
|
||||
XPIDL_MODULE = 'necko_cache2'
|
||||
|
||||
MODULE = 'nkcache2'
|
||||
|
||||
EXPORTS += [
|
||||
'CacheObserver.h',
|
||||
'CacheStorageService.h',
|
||||
]
|
||||
|
||||
CPP_SOURCES += [
|
||||
'AppCacheStorage.cpp',
|
||||
'CacheEntriesEnumerator.cpp',
|
||||
'CacheEntry.cpp',
|
||||
'CacheFile.cpp',
|
||||
'CacheFileChunk.cpp',
|
||||
'CacheFileMetadata.cpp',
|
||||
'CacheFileInputStream.cpp',
|
||||
'CacheFileIOManager.cpp',
|
||||
'CacheFileOutputStream.cpp',
|
||||
'CacheHashUtils.cpp',
|
||||
'CacheIOThread.cpp',
|
||||
'CacheLog.cpp',
|
||||
'CacheObserver.cpp',
|
||||
'CacheStorage.cpp',
|
||||
'CacheStorageService.cpp',
|
||||
'OldWrappers.cpp',
|
||||
]
|
||||
|
||||
LIBRARY_NAME = 'nkcache2_s'
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
||||
LIBXUL_LIBRARY = True
|
||||
|
||||
MSVC_ENABLE_PGO = True
|
||||
|
|
@ -0,0 +1,203 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIInputStream;
|
||||
interface nsIOutputStream;
|
||||
interface nsICacheEntryDoomCallback;
|
||||
|
||||
// ************************ REMOVE **********************
|
||||
typedef long nsCacheAccessMode;
|
||||
typedef long nsCacheStoragePolicy;
|
||||
|
||||
interface nsICacheListener;
|
||||
interface nsIFile;
|
||||
interface nsICacheMetaDataVisitor;
|
||||
|
||||
[scriptable, uuid(1785f6f1-18b3-4cb4-ae99-6c5545c1de19)]
|
||||
interface nsICacheEntry : nsISupports
|
||||
{
|
||||
/**
|
||||
* Get the key identifying the cache entry.
|
||||
*/
|
||||
readonly attribute ACString key;
|
||||
|
||||
/**
|
||||
* Whether the data can be persist to disk.
|
||||
* NOTE: This attribute must be set BEFORE opening the output stream.
|
||||
* Switching this flag does not immediately affect creation of the disk
|
||||
* file from memory-only data or eviction of the disk file and loading it
|
||||
* to memory-only.
|
||||
*/
|
||||
attribute boolean persistToDisk;
|
||||
|
||||
/**
|
||||
* Get the number of times the cache entry has been opened.
|
||||
*/
|
||||
readonly attribute long fetchCount;
|
||||
|
||||
/**
|
||||
* Get the last time the cache entry was opened (in seconds since the Epoch).
|
||||
*/
|
||||
readonly attribute uint32_t lastFetched;
|
||||
|
||||
/**
|
||||
* Get the last time the cache entry was modified (in seconds since the Epoch).
|
||||
*/
|
||||
readonly attribute uint32_t lastModified;
|
||||
|
||||
/**
|
||||
* Get the expiration time of the cache entry (in seconds since the Epoch).
|
||||
*/
|
||||
readonly attribute uint32_t expirationTime;
|
||||
|
||||
/**
|
||||
* Set the time at which the cache entry should be considered invalid (in
|
||||
* seconds since the Epoch).
|
||||
*/
|
||||
void setExpirationTime(in uint32_t expirationTime);
|
||||
|
||||
/**
|
||||
* Open blocking input stream to cache data. Use the stream transport
|
||||
* service to asynchronously read this stream on a background thread.
|
||||
* The returned stream MAY implement nsISeekableStream.
|
||||
*
|
||||
* @param offset
|
||||
* read starting from this offset into the cached data. an offset
|
||||
* beyond the end of the stream has undefined consequences.
|
||||
*
|
||||
* @return blocking, unbuffered input stream.
|
||||
*/
|
||||
nsIInputStream openInputStream(in long long offset);
|
||||
|
||||
/**
|
||||
* Open non-blocking output stream to cache data. The returned stream
|
||||
* MAY implement nsISeekableStream.
|
||||
*
|
||||
* If opening an output stream to existing cached data, the data will be
|
||||
* truncated to the specified offset.
|
||||
*
|
||||
* @param offset
|
||||
* write starting from this offset into the cached data. an offset
|
||||
* beyond the end of the stream has undefined consequences.
|
||||
*
|
||||
* @return blocking, unbuffered output stream.
|
||||
*/
|
||||
nsIOutputStream openOutputStream(in long long offset);
|
||||
|
||||
/**
|
||||
* Stores the Content-Length specified in the HTTP header for this
|
||||
* entry. Checked before we write to the cache entry, to prevent ever
|
||||
* taking up space in the cache for an entry that we know up front
|
||||
* is going to have to be evicted anyway. See bug 588507.
|
||||
*/
|
||||
attribute int64_t predictedDataSize;
|
||||
|
||||
/**
|
||||
* Get/set security info on the cache entry for this descriptor.
|
||||
*/
|
||||
attribute nsISupports securityInfo;
|
||||
|
||||
/**
|
||||
* Get the size of the cache entry data, as stored. This may differ
|
||||
* from the entry's dataSize, if the entry is compressed.
|
||||
*/
|
||||
readonly attribute unsigned long storageDataSize;
|
||||
|
||||
/**
|
||||
* Asynchronously doom an entry. Listener will be notified about the status
|
||||
* of the operation. Null may be passed if caller doesn't care about the
|
||||
* result.
|
||||
*/
|
||||
void asyncDoom(in nsICacheEntryDoomCallback listener);
|
||||
|
||||
/**
|
||||
* Methods for accessing meta data. Meta data is a table of key/value
|
||||
* string pairs. The strings do not have to conform to any particular
|
||||
* charset, but they must be null terminated.
|
||||
*/
|
||||
string getMetaDataElement(in string key);
|
||||
void setMetaDataElement(in string key, in string value);
|
||||
|
||||
/**
|
||||
* Claims that all metadata on this entry are up-to-date and this entry
|
||||
* now can be delivered to other waiting consumers.
|
||||
*
|
||||
* We need such method since metadata must be delivered synchronously.
|
||||
*/
|
||||
void metaDataReady();
|
||||
|
||||
/**
|
||||
* Called by consumer upon 304/206 response from the server. This marks
|
||||
* the entry content as positively revalidated.
|
||||
* Consumer uses this method after the consumer has returned ENTRY_NEEDS_REVALIDATION
|
||||
* result from onCacheEntryCheck and after successfull revalidation with the server.
|
||||
*/
|
||||
void setValid();
|
||||
|
||||
/**
|
||||
* Doom this entry and open a new, empty, entry for write. Consumer has
|
||||
* to exchange this entry for the newly created.
|
||||
* Used on 200 responses to conditional requests.
|
||||
*
|
||||
* @returns
|
||||
* - an entry that can be used to write to
|
||||
* @throws
|
||||
* - NS_ERROR_NOT_AVAILABLE when the entry cannot be from some reason
|
||||
* recreated for write
|
||||
*/
|
||||
nsICacheEntry recreate();
|
||||
|
||||
/**
|
||||
* Returns the length of data this entry holds.
|
||||
* @throws
|
||||
* NS_ERROR_IN_PROGRESS when the write is still in progress.
|
||||
*/
|
||||
readonly attribute long long dataSize;
|
||||
|
||||
/**
|
||||
* FOR BACKWARD COMPATIBILITY ONLY
|
||||
* When the old cache backend is eventually removed, this method
|
||||
* can be removed too.
|
||||
*
|
||||
* In the new backend: this method is no-op
|
||||
* In the old backend: this method delegates to nsICacheEntryDescriptor.close()
|
||||
*/
|
||||
void close();
|
||||
|
||||
/**
|
||||
* FOR BACKWARD COMPATIBILITY ONLY
|
||||
* Marks the entry as valid so that others can use it and get only readonly
|
||||
* access when the entry is held by the 1st writer.
|
||||
*/
|
||||
void markValid();
|
||||
|
||||
/****************************************************************************
|
||||
* The following methods might be added to some nsICacheEntryInternal
|
||||
* interface since we want to remove them as soon as the old cache backend is
|
||||
* completely removed.
|
||||
*/
|
||||
|
||||
/**
|
||||
* FOR BACKWARD COMPATIBILITY ONLY
|
||||
* Marks the entry as valid when write access is acquired.
|
||||
*/
|
||||
void maybeMarkValid();
|
||||
|
||||
/**
|
||||
* FOR BACKWARD COMPATIBILITY ONLY / KINDA HACK
|
||||
* @param aWriteAllowed
|
||||
* consumer indicates whether write to the entry is allowed for it
|
||||
* depends on implementation how the flag is handled
|
||||
* @returns
|
||||
* true when write access is acquired for this entry
|
||||
* false otherwise
|
||||
*/
|
||||
boolean hasWriteAccess(in boolean aWriteAllowed);
|
||||
|
||||
// *************** GET RID OF THESE ??? ***************
|
||||
void setDataSize(in unsigned long size);
|
||||
attribute nsCacheStoragePolicy storagePolicy;
|
||||
};
|
|
@ -0,0 +1,15 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, uuid(2f8896be-232f-4140-afb3-1faffb56f3c6)]
|
||||
interface nsICacheEntryDoomCallback : nsISupports
|
||||
{
|
||||
/**
|
||||
* Callback invoked after an entry or entries has/have been
|
||||
* doomed from the cache.
|
||||
*/
|
||||
void onCacheEntryDoomed(in nsresult aResult);
|
||||
};
|
|
@ -0,0 +1,83 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsICacheEntry;
|
||||
interface nsIApplicationCache;
|
||||
|
||||
[scriptable, uuid(cdd8b9be-71f0-4b0a-a7f4-626fbb3d2e9b)]
|
||||
interface nsICacheEntryOpenCallback : nsISupports
|
||||
{
|
||||
/**
|
||||
* State of the entry determined by onCacheEntryCheck.
|
||||
*
|
||||
* ENTRY_WANTED - the consumer is interested in the entry, we will pass it.
|
||||
* ENTRY_NEEDS_REVALIDATION - entry needs to be revalidated first with origin server,
|
||||
* this means the loading channel will decide whether to use the entry content
|
||||
* as is after it gets a positive response from the server about validity of the
|
||||
* content ; when a new content needs to be loaded from the server, the loading
|
||||
* channel opens a new entry with OPEN_TRUNCATE flag which dooms the one
|
||||
* this check has been made for.
|
||||
* ENTRY_NOT_WANTED - the consumer is not interested in the entry, we will not pass it.
|
||||
*/
|
||||
const unsigned long ENTRY_WANTED = 0;
|
||||
const unsigned long ENTRY_NEEDS_REVALIDATION = 1;
|
||||
const unsigned long ENTRY_NOT_WANTED = 2;
|
||||
|
||||
/**
|
||||
* Callback to perform any validity checks before the entry should be used.
|
||||
* Called before onCacheEntryAvailable callback.
|
||||
*
|
||||
* @param aEntry
|
||||
* An entry to examine. Consumer has a chance to decide whether the
|
||||
* entry is valid or not.
|
||||
* @param aApplicationCache
|
||||
* Optional, application cache the entry has been found in, if any.
|
||||
* @return
|
||||
* State of the entry, see the constants just above.
|
||||
*
|
||||
* NOTE: This callback is invoked on the cache background thread.
|
||||
*/
|
||||
unsigned long onCacheEntryCheck(in nsICacheEntry aEntry,
|
||||
in nsIApplicationCache aApplicationCache);
|
||||
|
||||
/**
|
||||
* Callback implemented by consumers of nsICacheStorage fetching
|
||||
* result of the cache async open request.
|
||||
*
|
||||
* @param aEntry
|
||||
* The entry bound to the originally requested URI. May be null when
|
||||
* loading from a particular application cache and the URI has not
|
||||
* been found in that application cache.
|
||||
* @param aNew
|
||||
* Whether no data so far has been stored for this entry, i.e. reading
|
||||
* it will just fail. When aNew is true, a server request should be
|
||||
* made and data stored to this new entry.
|
||||
* @param aApplicationCache
|
||||
* When an entry had been found in an application cache, this is the
|
||||
* given application cache. It should be associated with the loading
|
||||
* channel.
|
||||
* @param aResult
|
||||
* Result of request. This may be a failure only when one of these
|
||||
* issues occur:
|
||||
* - the cache storage service could not be started due to some unexpected
|
||||
* faulure
|
||||
* - there is not enough disk space to create new entries
|
||||
* - cache entry was not found in a given application cache
|
||||
*
|
||||
* NOTE: In the current implementation this callback is invoked on the main thread
|
||||
* however, we would like to call this on a different thread in the future.
|
||||
*/
|
||||
void onCacheEntryAvailable(in nsICacheEntry aEntry,
|
||||
in boolean aNew,
|
||||
in nsIApplicationCache aApplicationCache,
|
||||
in nsresult aResult);
|
||||
|
||||
/**
|
||||
* Whether this callback can be invoked on any thread, or just on the main thread
|
||||
* when the consumer is e.g. a JS.
|
||||
*/
|
||||
readonly attribute boolean mainThreadOnly;
|
||||
};
|
|
@ -0,0 +1,92 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIURI;
|
||||
interface nsICacheEntryOpenCallback;
|
||||
interface nsICacheEntryDoomCallback;
|
||||
interface nsICacheStorageVisitor;
|
||||
|
||||
/**
|
||||
* Representation of a cache storage. There can be just-in-mem,
|
||||
* in-mem+on-disk, in-mem+on-disk+app-cache or just a specific
|
||||
* app-cache storage.
|
||||
*/
|
||||
[scriptable, uuid(d983ba0c-433f-4017-abc1-93af737c82e4)]
|
||||
interface nsICacheStorage : nsISupports
|
||||
{
|
||||
/**
|
||||
* Placeholder for specifying "no special flags" during open.
|
||||
*/
|
||||
const uint32_t OPEN_NORMALLY = 0;
|
||||
|
||||
/**
|
||||
* Rewrite any existing data when opening a URL.
|
||||
*/
|
||||
const uint32_t OPEN_TRUNCATE = 1 << 0;
|
||||
|
||||
/**
|
||||
* Only open an existing entry. Don't create a new one.
|
||||
*/
|
||||
const uint32_t OPEN_READONLY = 1 << 1;
|
||||
|
||||
/**
|
||||
* Use for first-paint blocking loads.
|
||||
*/
|
||||
const uint32_t OPEN_PRIORITY = 1 << 2;
|
||||
|
||||
/**
|
||||
* BACKWARD COMPATIBILITY ONLY
|
||||
*
|
||||
* Reflects LOAD_BYPASS_LOCAL_CACHE_IF_BUSY. Only used for the old
|
||||
* backend compatibility. Doesn't have any mening in the new
|
||||
* implementation.
|
||||
*/
|
||||
const uint32_t OPEN_BYPASS_IF_BUSY = 1 << 31;
|
||||
|
||||
/**
|
||||
* Asynchronously opens a cache entry for the specified URI.
|
||||
* Result is fetched asynchronously via the callback.
|
||||
*
|
||||
* @param aURI
|
||||
* The URI to search in cache or to open for writting.
|
||||
* @param aIdExtension
|
||||
* Any string that will extend (distinguish) the entry. Two entries
|
||||
* with the same aURI but different aIdExtension will be comletely
|
||||
* different entries. If you don't know what aIdExtension should be
|
||||
* leave it empty.
|
||||
* @param aFlags
|
||||
* OPEN_NORMALLY - open cache entry normally for read and write
|
||||
* OPEN_TRUNCATE - delete any existing entry before opening it
|
||||
* OPEN_READONLY - don't create an entry if there is none
|
||||
* OPEN_PRIORITY - give this request a priority over others
|
||||
* OPEN_BYPASS_IF_BUSY - backward compatibility only, LOAD_BYPASS_LOCAL_CACHE_IF_BUSY
|
||||
* @param aCallback
|
||||
* The consumer that receives the result.
|
||||
* IMPORTANT: The callback may be called sooner the method returns.
|
||||
*/
|
||||
void asyncOpenURI(in nsIURI aURI, in ACString aIdExtension,
|
||||
in uint32_t aFlags,
|
||||
in nsICacheEntryOpenCallback aCallback);
|
||||
|
||||
/**
|
||||
* Asynchronously removes an entry belonging to the URI from the cache.
|
||||
*/
|
||||
void asyncDoomURI(in nsIURI aURI, in ACString aIdExtension,
|
||||
in nsICacheEntryDoomCallback aCallback);
|
||||
|
||||
/**
|
||||
* Asynchronously removes all cached entries under this storage.
|
||||
* NOTE: Disk storage also evicts memory storage.
|
||||
*/
|
||||
void asyncEvictStorage(in nsICacheEntryDoomCallback aCallback);
|
||||
|
||||
/**
|
||||
* Visits the storage and its entries.
|
||||
* NOTE: Disk storage also visits memory storage.
|
||||
*/
|
||||
void asyncVisitStorage(in nsICacheStorageVisitor aVisitor,
|
||||
in boolean aVisitEntries);
|
||||
};
|
|
@ -0,0 +1,82 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsICacheStorage;
|
||||
interface nsILoadContextInfo;
|
||||
interface nsIApplicationCache;
|
||||
interface nsIEventTarget;
|
||||
|
||||
/**
|
||||
* Provides access to particual cache storages of the network URI cache.
|
||||
*/
|
||||
[scriptable, uuid(d669bf30-b6d9-48e1-a8fb-33cd18b0d752)]
|
||||
interface nsICacheStorageService : nsISupports
|
||||
{
|
||||
/**
|
||||
* Get storage where entries will only remain in memory, never written
|
||||
* to the disk.
|
||||
*
|
||||
* @param aLoadContextInfo
|
||||
* Information about the loading context, this focuses the storage JAR and
|
||||
* respects separate storage for private browsing.
|
||||
*/
|
||||
nsICacheStorage memoryCacheStorage(in nsILoadContextInfo aLoadContextInfo);
|
||||
|
||||
/**
|
||||
* Get storage where entries will be written to disk when not forbidden by
|
||||
* response headers.
|
||||
*
|
||||
* @param aLookupAppCache
|
||||
* When set true (for top level document loading channels) app cache will
|
||||
* be first to check on to find entries in.
|
||||
*/
|
||||
nsICacheStorage diskCacheStorage(in nsILoadContextInfo aLoadContextInfo,
|
||||
in bool aLookupAppCache);
|
||||
|
||||
/**
|
||||
* Get storage for a specified application cache obtained using some different
|
||||
* mechanism.
|
||||
*
|
||||
* @param aLoadContextInfo
|
||||
* Mandatory reference to a load context information.
|
||||
* @param aApplicationCache
|
||||
* Optional reference to an existing appcache. When left null, this will
|
||||
* work with offline cache as a whole.
|
||||
*/
|
||||
nsICacheStorage appCacheStorage(in nsILoadContextInfo aLoadContextInfo,
|
||||
in nsIApplicationCache aApplicationCache);
|
||||
|
||||
/**
|
||||
* Evict the whole cache.
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* Purge only data of disk backed entries. Metadata are left for
|
||||
* performance purposes.
|
||||
*/
|
||||
const uint32_t PURGE_DISK_DATA_ONLY = 1;
|
||||
/**
|
||||
* Purge whole disk backed entries from memory. Disk files will
|
||||
* be left unattended.
|
||||
*/
|
||||
const uint32_t PURGE_DISK_ALL = 2;
|
||||
/**
|
||||
* Purge all entries we keep in memory, including memory-storage
|
||||
* entries. This may be dangerous to use.
|
||||
*/
|
||||
const uint32_t PURGE_EVERYTHING = 3;
|
||||
/**
|
||||
* Purges data we keep warmed in memory. Use for tests and for
|
||||
* saving memory.
|
||||
*/
|
||||
void purgeFromMemory(in uint32_t aWhat);
|
||||
|
||||
/**
|
||||
* I/O thread target to use for any operations on disk
|
||||
*/
|
||||
readonly attribute nsIEventTarget ioTarget;
|
||||
};
|
|
@ -0,0 +1,23 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsICacheEntry;
|
||||
|
||||
[scriptable, uuid(692dda47-3b21-4d0d-853a-f4d27cc324d0)]
|
||||
interface nsICacheStorageVisitor : nsISupports
|
||||
{
|
||||
/**
|
||||
*/
|
||||
void onCacheStorageInfo(in uint32_t aEntryCount, in uint64_t aConsumption);
|
||||
|
||||
/**
|
||||
*/
|
||||
void onCacheEntryInfo(in nsICacheEntry aEntry);
|
||||
|
||||
/**
|
||||
*/
|
||||
void onCacheEntryVisitCompleted();
|
||||
};
|
|
@ -12,6 +12,7 @@ PARALLEL_DIRS += [
|
|||
'mime',
|
||||
'streamconv',
|
||||
'cache',
|
||||
'cache2',
|
||||
'protocol',
|
||||
'system',
|
||||
'ipc',
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#include "nsNetUtil.h"
|
||||
#include "nsISupportsPriority.h"
|
||||
#include "nsIAuthPromptProvider.h"
|
||||
#include "nsICacheEntryDescriptor.h"
|
||||
#include "nsSerializationHelper.h"
|
||||
#include "nsISerializable.h"
|
||||
#include "nsIAssociatedContentSecurity.h"
|
||||
|
@ -336,8 +335,8 @@ HttpChannelParent::RecvCancel(const nsresult& status)
|
|||
bool
|
||||
HttpChannelParent::RecvSetCacheTokenCachedCharset(const nsCString& charset)
|
||||
{
|
||||
if (mCacheDescriptor)
|
||||
mCacheDescriptor->SetMetaDataElement("charset", charset.get());
|
||||
if (mCacheEntry)
|
||||
mCacheEntry->SetMetaDataElement("charset", charset.get());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -407,7 +406,7 @@ HttpChannelParent::RecvDocumentChannelCleanup()
|
|||
{
|
||||
// From now on only using mAssociatedContentSecurity. Free everything else.
|
||||
mChannel = 0; // Reclaim some memory sooner.
|
||||
mCacheDescriptor = 0; // Else we'll block other channels reading same URI
|
||||
mCacheEntry = 0; // Else we'll block other channels reading same URI
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -464,7 +463,10 @@ HttpChannelParent::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
|
|||
|
||||
// Keep the cache entry for future use in RecvSetCacheTokenCachedCharset().
|
||||
// It could be already released by nsHttpChannel at that time.
|
||||
chan->GetCacheToken(getter_AddRefs(mCacheDescriptor));
|
||||
nsCOMPtr<nsISupports> cacheEntry;
|
||||
chan->GetCacheToken(getter_AddRefs(cacheEntry));
|
||||
mCacheEntry = do_QueryInterface(cacheEntry);
|
||||
|
||||
|
||||
nsCString secInfoSerialization;
|
||||
nsCOMPtr<nsISupports> secInfoSupp;
|
||||
|
@ -482,7 +484,7 @@ HttpChannelParent::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
|
|||
!!responseHead,
|
||||
requestHead->Headers(),
|
||||
isFromCache,
|
||||
mCacheDescriptor ? true : false,
|
||||
mCacheEntry ? true : false,
|
||||
expirationTime, cachedCharset, secInfoSerialization,
|
||||
httpChan->GetSelfAddr(), httpChan->GetPeerAddr()))
|
||||
{
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#include "nsIProgressEventSink.h"
|
||||
#include "nsHttpChannel.h"
|
||||
|
||||
class nsICacheEntryDescriptor;
|
||||
class nsICacheEntry;
|
||||
class nsIAssociatedContentSecurity;
|
||||
class nsHttpHandler;
|
||||
|
||||
|
@ -99,7 +99,7 @@ protected:
|
|||
|
||||
private:
|
||||
nsCOMPtr<nsIChannel> mChannel;
|
||||
nsCOMPtr<nsICacheEntryDescriptor> mCacheDescriptor;
|
||||
nsCOMPtr<nsICacheEntry> mCacheEntry;
|
||||
nsCOMPtr<nsIAssociatedContentSecurity> mAssociatedContentSecurity;
|
||||
bool mIPCClosed; // PHttpChannel actor has been Closed()
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include "nsNetUtil.h"
|
||||
#include "nsISupportsPriority.h"
|
||||
#include "nsIAuthPromptProvider.h"
|
||||
#include "nsICacheEntryDescriptor.h"
|
||||
#include "nsSerializationHelper.h"
|
||||
#include "nsISerializable.h"
|
||||
#include "nsIAssociatedContentSecurity.h"
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -15,8 +15,8 @@
|
|||
|
||||
#include "nsIHttpEventSink.h"
|
||||
#include "nsICachingChannel.h"
|
||||
#include "nsICacheEntryDescriptor.h"
|
||||
#include "nsICacheListener.h"
|
||||
#include "nsICacheEntry.h"
|
||||
#include "nsICacheEntryOpenCallback.h"
|
||||
#include "nsIApplicationCacheChannel.h"
|
||||
#include "nsIPrompt.h"
|
||||
#include "nsIResumableChannel.h"
|
||||
|
@ -39,8 +39,6 @@ class nsIPrincipal;
|
|||
|
||||
namespace mozilla { namespace net {
|
||||
|
||||
class HttpCacheQuery;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsHttpChannel
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -49,7 +47,7 @@ class nsHttpChannel : public HttpBaseChannel
|
|||
, public HttpAsyncAborter<nsHttpChannel>
|
||||
, public nsIStreamListener
|
||||
, public nsICachingChannel
|
||||
, public nsICacheListener
|
||||
, public nsICacheEntryOpenCallback
|
||||
, public nsITransportEventSink
|
||||
, public nsIProtocolProxyCallback
|
||||
, public nsIHttpAuthenticableChannel
|
||||
|
@ -66,7 +64,7 @@ public:
|
|||
NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
|
||||
NS_DECL_NSICACHEINFOCHANNEL
|
||||
NS_DECL_NSICACHINGCHANNEL
|
||||
NS_DECL_NSICACHELISTENER
|
||||
NS_DECL_NSICACHEENTRYOPENCALLBACK
|
||||
NS_DECL_NSITRANSPORTEVENTSINK
|
||||
NS_DECL_NSIPROTOCOLPROXYCALLBACK
|
||||
NS_DECL_NSIPROXIEDCHANNEL
|
||||
|
@ -143,12 +141,12 @@ public: /* internal necko use only */
|
|||
// is gone. Needed for e10s (see HttpChannelParent::RecvDocumentChannelCleanup)
|
||||
class OfflineCacheEntryAsForeignMarker {
|
||||
nsCOMPtr<nsIApplicationCache> mApplicationCache;
|
||||
nsCString mCacheKey;
|
||||
nsCOMPtr<nsIURI> mCacheURI;
|
||||
public:
|
||||
OfflineCacheEntryAsForeignMarker(nsIApplicationCache* appCache,
|
||||
const nsCSubstring& key)
|
||||
nsIURI* aURI)
|
||||
: mApplicationCache(appCache)
|
||||
, mCacheKey(key)
|
||||
, mCacheURI(aURI)
|
||||
{}
|
||||
|
||||
nsresult MarkAsForeign();
|
||||
|
@ -156,6 +154,37 @@ public: /* internal necko use only */
|
|||
|
||||
OfflineCacheEntryAsForeignMarker* GetOfflineCacheEntryAsForeignMarker();
|
||||
|
||||
// Helper to keep cache callbacks wait flags consistent
|
||||
class AutoCacheWaitFlags
|
||||
{
|
||||
public:
|
||||
AutoCacheWaitFlags(nsHttpChannel* channel)
|
||||
: mChannel(channel)
|
||||
, mKeep(0)
|
||||
{
|
||||
// Flags must be set before entering any AsyncOpenCacheEntry call.
|
||||
mChannel->mCacheEntriesToWaitFor =
|
||||
nsHttpChannel::WAIT_FOR_CACHE_ENTRY |
|
||||
nsHttpChannel::WAIT_FOR_OFFLINE_CACHE_ENTRY;
|
||||
}
|
||||
|
||||
void Keep(uint32_t flags)
|
||||
{
|
||||
// Called after successful call to appropriate AsyncOpenCacheEntry call.
|
||||
mKeep |= flags;
|
||||
}
|
||||
|
||||
~AutoCacheWaitFlags()
|
||||
{
|
||||
// Keep only flags those are left to be wait for.
|
||||
mChannel->mCacheEntriesToWaitFor &= mKeep;
|
||||
}
|
||||
|
||||
private:
|
||||
nsHttpChannel* mChannel;
|
||||
uint32_t mKeep : 2;
|
||||
};
|
||||
|
||||
private:
|
||||
typedef nsresult (nsHttpChannel::*nsContinueRedirectionFunc)(nsresult result);
|
||||
|
||||
|
@ -207,24 +236,24 @@ private:
|
|||
|
||||
// cache specific methods
|
||||
nsresult OpenCacheEntry(bool usingSSL);
|
||||
nsresult OnOfflineCacheEntryAvailable(nsICacheEntryDescriptor *aEntry,
|
||||
nsCacheAccessMode aAccess,
|
||||
nsresult OnOfflineCacheEntryAvailable(nsICacheEntry *aEntry,
|
||||
bool aNew,
|
||||
nsIApplicationCache* aAppCache,
|
||||
nsresult aResult);
|
||||
nsresult OpenNormalCacheEntry(bool usingSSL);
|
||||
nsresult OnNormalCacheEntryAvailable(nsICacheEntryDescriptor *aEntry,
|
||||
nsCacheAccessMode aAccess,
|
||||
nsresult OnNormalCacheEntryAvailable(nsICacheEntry *aEntry,
|
||||
bool aNew,
|
||||
nsresult aResult);
|
||||
nsresult OpenOfflineCacheEntryForWriting();
|
||||
nsresult OnOfflineCacheEntryForWritingAvailable(
|
||||
nsICacheEntryDescriptor *aEntry,
|
||||
nsCacheAccessMode aAccess,
|
||||
nsresult aResult);
|
||||
nsresult OnCacheEntryAvailableInternal(nsICacheEntryDescriptor *entry,
|
||||
nsCacheAccessMode access,
|
||||
nsresult status);
|
||||
nsresult OnOfflineCacheEntryForWritingAvailable(nsICacheEntry *aEntry,
|
||||
nsIApplicationCache* aAppCache,
|
||||
nsresult aResult);
|
||||
nsresult OnCacheEntryAvailableInternal(nsICacheEntry *entry,
|
||||
bool aNew,
|
||||
nsIApplicationCache* aAppCache,
|
||||
nsresult status);
|
||||
nsresult GenerateCacheKey(uint32_t postID, nsACString &key);
|
||||
nsresult UpdateExpirationTime();
|
||||
nsresult CheckCache();
|
||||
nsresult CheckPartial(nsICacheEntry* aEntry, int64_t *aSize, int64_t *aContentLength);
|
||||
bool ShouldUpdateOfflineCacheEntry();
|
||||
nsresult ReadFromCache(bool alreadyMarkedValid);
|
||||
void CloseCacheEntry(bool doomOnFailure);
|
||||
|
@ -232,14 +261,12 @@ private:
|
|||
nsresult InitCacheEntry();
|
||||
void UpdateInhibitPersistentCachingFlag();
|
||||
nsresult InitOfflineCacheEntry();
|
||||
nsresult AddCacheEntryHeaders(nsICacheEntryDescriptor *entry);
|
||||
nsresult StoreAuthorizationMetaData(nsICacheEntryDescriptor *entry);
|
||||
nsresult AddCacheEntryHeaders(nsICacheEntry *entry);
|
||||
nsresult StoreAuthorizationMetaData(nsICacheEntry *entry);
|
||||
nsresult FinalizeCacheEntry();
|
||||
nsresult InstallCacheListener(uint32_t offset = 0);
|
||||
nsresult InstallOfflineCacheListener();
|
||||
nsresult InstallCacheListener(int64_t offset = 0);
|
||||
nsresult InstallOfflineCacheListener(int64_t offset = 0);
|
||||
void MaybeInvalidateCacheEntryForSubsequentGet();
|
||||
nsCacheStoragePolicy DetermineStoragePolicy();
|
||||
nsresult DetermineCacheAccess(nsCacheAccessMode *_retval);
|
||||
void AsyncOnExamineCachedResponse();
|
||||
|
||||
// Handle the bogus Content-Encoding Apache sometimes sends
|
||||
|
@ -267,7 +294,7 @@ private:
|
|||
void InvalidateCacheEntryForLocation(const char *location);
|
||||
void AssembleCacheKey(const char *spec, uint32_t postID, nsACString &key);
|
||||
nsresult CreateNewURI(const char *loc, nsIURI **newURI);
|
||||
void DoInvalidateCacheEntry(const nsCString &key);
|
||||
void DoInvalidateCacheEntry(nsIURI* aURI);
|
||||
|
||||
// Ref RFC2616 13.10: "invalidation... MUST only be performed if
|
||||
// the host part is the same as in the Request-URI"
|
||||
|
@ -289,8 +316,12 @@ private:
|
|||
// and ensure the transaction is updated to use it.
|
||||
void UpdateAggregateCallbacks();
|
||||
|
||||
// Disk cache is skipped for some requests when it is behaving slowly
|
||||
bool ShouldSkipCache();
|
||||
static bool HasQueryString(nsHttpAtom method, nsIURI * uri);
|
||||
bool ResponseWouldVary(nsICacheEntry* entry) const;
|
||||
bool MustValidateBasedOnQueryUrl() const;
|
||||
nsresult MaybeSetupByteRangeRequest(int64_t partialLen, int64_t contentLength);
|
||||
nsresult SetupByteRangeRequest(int64_t partialLen);
|
||||
nsresult OpenCacheInputStream(nsICacheEntry* cacheEntry, bool startBuffering);
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsISupports> mSecurityInfo;
|
||||
|
@ -302,24 +333,17 @@ private:
|
|||
uint64_t mLogicalOffset;
|
||||
|
||||
// cache specific data
|
||||
nsRefPtr<HttpCacheQuery> mCacheQuery;
|
||||
nsCOMPtr<nsICacheEntryDescriptor> mCacheEntry;
|
||||
nsCOMPtr<nsICacheEntry> mCacheEntry;
|
||||
// We must close mCacheInputStream explicitly to avoid leaks.
|
||||
AutoClose<nsIInputStream> mCacheInputStream;
|
||||
nsRefPtr<nsInputStreamPump> mCachePump;
|
||||
nsAutoPtr<nsHttpResponseHead> mCachedResponseHead;
|
||||
nsCOMPtr<nsISupports> mCachedSecurityInfo;
|
||||
nsCacheAccessMode mCacheAccess;
|
||||
mozilla::Telemetry::ID mCacheEntryDeviceTelemetryID;
|
||||
uint32_t mPostID;
|
||||
uint32_t mRequestTime;
|
||||
|
||||
typedef nsresult (nsHttpChannel:: *nsOnCacheEntryAvailableCallback)(
|
||||
nsICacheEntryDescriptor *, nsCacheAccessMode, nsresult);
|
||||
nsOnCacheEntryAvailableCallback mOnCacheEntryAvailableCallback;
|
||||
|
||||
nsCOMPtr<nsICacheEntryDescriptor> mOfflineCacheEntry;
|
||||
nsCacheAccessMode mOfflineCacheAccess;
|
||||
nsCOMPtr<nsICacheEntry> mOfflineCacheEntry;
|
||||
uint32_t mOfflineCacheLastModifiedTime;
|
||||
nsCOMPtr<nsIApplicationCache> mApplicationCacheForWrite;
|
||||
|
||||
|
@ -333,12 +357,14 @@ private:
|
|||
|
||||
friend class AutoRedirectVetoNotifier;
|
||||
friend class HttpAsyncAborter<nsHttpChannel>;
|
||||
friend class HttpCacheQuery;
|
||||
|
||||
nsCOMPtr<nsIURI> mRedirectURI;
|
||||
nsCOMPtr<nsIChannel> mRedirectChannel;
|
||||
uint32_t mRedirectType;
|
||||
|
||||
static const uint32_t WAIT_FOR_CACHE_ENTRY = 1;
|
||||
static const uint32_t WAIT_FOR_OFFLINE_CACHE_ENTRY = 2;
|
||||
|
||||
// state flags
|
||||
uint32_t mCachedContentIsValid : 1;
|
||||
uint32_t mCachedContentIsPartial : 1;
|
||||
|
@ -359,6 +385,18 @@ private:
|
|||
// True if mRequestTime has been set. In such a case it is safe to update
|
||||
// the cache entry's expiration time. Otherwise, it is not(see bug 567360).
|
||||
uint32_t mRequestTimeInitialized : 1;
|
||||
uint32_t mCacheEntryIsReadOnly : 1;
|
||||
uint32_t mCacheEntryIsWriteOnly : 1;
|
||||
// see WAIT_FOR_* constants above
|
||||
uint32_t mCacheEntriesToWaitFor : 2;
|
||||
uint32_t mHasQueryString : 1;
|
||||
// whether cache entry data write was in progress during cache entry check
|
||||
// when true, after we finish read from cache we must check all data
|
||||
// had been loaded from cache. If not, then an error has to be propagated
|
||||
// to the consumer.
|
||||
uint32_t mConcurentCacheAccess : 1;
|
||||
// whether the request is setup be byte-range
|
||||
uint32_t mIsPartialRequest : 1;
|
||||
|
||||
nsTArray<nsContinueRedirectionFunc> mRedirectFuncStack;
|
||||
|
||||
|
|
|
@ -23,10 +23,11 @@
|
|||
#include "nsIHttpChannel.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsIStandardURL.h"
|
||||
#include "nsICacheService.h"
|
||||
#include "LoadContextInfo.h"
|
||||
#include "nsICacheStorageService.h"
|
||||
#include "nsICacheStorage.h"
|
||||
#include "nsICategoryManager.h"
|
||||
#include "nsCategoryManagerUtils.h"
|
||||
#include "nsICacheService.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsIPrefBranch.h"
|
||||
#include "nsIPrefLocalizedString.h"
|
||||
|
@ -1715,29 +1716,84 @@ nsHttpHandler::GetCacheSessionNameForStoragePolicy(
|
|||
// nsHttpHandler::nsIObserver
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static void
|
||||
EvictCacheSession(nsCacheStoragePolicy aPolicy,
|
||||
bool aPrivateBrowsing,
|
||||
uint32_t aAppId,
|
||||
bool aInBrowser)
|
||||
namespace { // anon
|
||||
|
||||
class CacheStorageEvictHelper
|
||||
{
|
||||
nsAutoCString clientId;
|
||||
nsHttpHandler::GetCacheSessionNameForStoragePolicy(aPolicy,
|
||||
aPrivateBrowsing,
|
||||
aAppId, aInBrowser,
|
||||
clientId);
|
||||
nsCOMPtr<nsICacheService> serv =
|
||||
do_GetService(NS_CACHESERVICE_CONTRACTID);
|
||||
nsCOMPtr<nsICacheSession> session;
|
||||
nsresult rv = serv->CreateSession(clientId.get(),
|
||||
nsICache::STORE_ANYWHERE,
|
||||
nsICache::STREAM_BASED,
|
||||
getter_AddRefs(session));
|
||||
if (NS_SUCCEEDED(rv) && session) {
|
||||
session->EvictEntries();
|
||||
}
|
||||
public:
|
||||
CacheStorageEvictHelper(uint32_t appId, bool browserOnly)
|
||||
: mAppId(appId), mBrowserOnly(browserOnly) { }
|
||||
|
||||
nsresult Run();
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsICacheStorageService> mCacheStorageService;
|
||||
uint32_t mAppId;
|
||||
bool mBrowserOnly;
|
||||
|
||||
nsresult ClearStorage(bool const aPrivate,
|
||||
bool const aInBrowser,
|
||||
bool const aAnonymous);
|
||||
};
|
||||
|
||||
nsresult
|
||||
CacheStorageEvictHelper::Run()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
mCacheStorageService = do_GetService(
|
||||
"@mozilla.org/netwerk/cache-storage-service;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Clear all [private X anonymous] combinations
|
||||
rv = ClearStorage(false, mBrowserOnly, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = ClearStorage(false, mBrowserOnly, true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = ClearStorage(true, mBrowserOnly, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = ClearStorage(true, mBrowserOnly, true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
CacheStorageEvictHelper::ClearStorage(bool const aPrivate,
|
||||
bool const aInBrowser,
|
||||
bool const aAnonymous)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsRefPtr<LoadContextInfo> info = GetLoadContextInfo(
|
||||
aPrivate, mAppId, aInBrowser, aAnonymous);
|
||||
|
||||
nsCOMPtr<nsICacheStorage> storage;
|
||||
|
||||
// Clear disk storage
|
||||
rv = mCacheStorageService->DiskCacheStorage(info, false,
|
||||
getter_AddRefs(storage));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = storage->AsyncEvictStorage(nullptr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Clear memory storage
|
||||
rv = mCacheStorageService->MemoryCacheStorage(info,
|
||||
getter_AddRefs(storage));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = storage->AsyncEvictStorage(nullptr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!aInBrowser) {
|
||||
rv = ClearStorage(aPrivate, true, aAnonymous);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // anon
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHttpHandler::Observe(nsISupports *subject,
|
||||
const char *topic,
|
||||
|
@ -1807,27 +1863,9 @@ nsHttpHandler::Observe(nsISupports *subject,
|
|||
|
||||
MOZ_ASSERT(appId != NECKO_UNKNOWN_APP_ID);
|
||||
|
||||
// Now we ensure that all unique session name combinations are cleared.
|
||||
struct {
|
||||
nsCacheStoragePolicy policy;
|
||||
bool privateBrowsing;
|
||||
} policies[] = { {nsICache::STORE_OFFLINE, false},
|
||||
{nsICache::STORE_IN_MEMORY, false},
|
||||
{nsICache::STORE_IN_MEMORY, true},
|
||||
{nsICache::STORE_ON_DISK, false} };
|
||||
|
||||
for (uint32_t i = 0; i < NS_ARRAY_LENGTH(policies); i++) {
|
||||
EvictCacheSession(policies[i].policy,
|
||||
policies[i].privateBrowsing,
|
||||
appId, browserOnly);
|
||||
|
||||
if (!browserOnly) {
|
||||
EvictCacheSession(policies[i].policy,
|
||||
policies[i].privateBrowsing,
|
||||
appId, true);
|
||||
}
|
||||
}
|
||||
|
||||
CacheStorageEvictHelper helper(appId, browserOnly);
|
||||
rv = helper.Run();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -1,44 +1,97 @@
|
|||
Components.utils.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
Components.utils.import('resource://gre/modules/LoadContextInfo.jsm');
|
||||
|
||||
var _CSvc;
|
||||
function get_cache_service() {
|
||||
if (_CSvc)
|
||||
return _CSvc;
|
||||
|
||||
return _CSvc = Components.classes["@mozilla.org/network/cache-service;1"]
|
||||
.getService(Components.interfaces.nsICacheService);
|
||||
return _CSvc = Components.classes["@mozilla.org/netwerk/cache-storage-service;1"]
|
||||
.getService(Components.interfaces.nsICacheStorageService);
|
||||
}
|
||||
|
||||
function evict_cache_entries(where)
|
||||
{
|
||||
if (where == null)
|
||||
where = Components.interfaces.nsICache.STORE_ANYWHERE;
|
||||
var clearDisk = (!where || where == "disk" || where == "all");
|
||||
var clearMem = (!where || where == "memory" || where == "all");
|
||||
var clearAppCache = (where == "appcache");
|
||||
|
||||
get_cache_service().evictEntries(where);
|
||||
var svc = get_cache_service();
|
||||
var storage;
|
||||
|
||||
if (clearMem) {
|
||||
storage = svc.memoryCacheStorage(LoadContextInfo.default);
|
||||
storage.asyncEvictStorage(null);
|
||||
}
|
||||
|
||||
if (clearDisk) {
|
||||
storage = svc.diskCacheStorage(LoadContextInfo.default, false);
|
||||
storage.asyncEvictStorage(null);
|
||||
}
|
||||
|
||||
if (clearAppCache) {
|
||||
storage = svc.appCacheStorage(LoadContextInfo.default, null);
|
||||
storage.asyncEvictStorage(null);
|
||||
}
|
||||
}
|
||||
|
||||
function asyncOpenCacheEntry(key, sessionName, storagePolicy, access, callback)
|
||||
function createURI(urispec)
|
||||
{
|
||||
var ioServ = Components.classes["@mozilla.org/network/io-service;1"]
|
||||
.getService(Components.interfaces.nsIIOService);
|
||||
return ioServ.newURI(urispec, null, null);
|
||||
}
|
||||
|
||||
function getCacheStorage(where, lci, appcache)
|
||||
{
|
||||
if (!lci) lci = LoadContextInfo.default;
|
||||
var svc = get_cache_service();
|
||||
switch (where) {
|
||||
case "disk": return svc.diskCacheStorage(lci, false);
|
||||
case "memory": return svc.memoryCacheStorage(lci);
|
||||
case "appcache": return svc.appCacheStorage(lci, appcache);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function asyncOpenCacheEntry(key, where, flags, lci, callback, appcache)
|
||||
{
|
||||
key = createURI(key);
|
||||
|
||||
function CacheListener() { }
|
||||
CacheListener.prototype = {
|
||||
_appCache: appcache,
|
||||
|
||||
QueryInterface: function (iid) {
|
||||
if (iid.equals(Components.interfaces.nsICacheListener) ||
|
||||
if (iid.equals(Components.interfaces.nsICacheEntryOpenCallback) ||
|
||||
iid.equals(Components.interfaces.nsISupports))
|
||||
return this;
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
|
||||
onCacheEntryAvailable: function (entry, access, status) {
|
||||
callback(status, entry);
|
||||
onCacheEntryCheck: function(entry, appCache) {
|
||||
if (typeof callback === "object")
|
||||
return callback.onCacheEntryCheck(entry, appCache);
|
||||
return Ci.nsICacheEntryOpenCallback.ENTRY_WANTED;
|
||||
},
|
||||
|
||||
onCacheEntryAvailable: function (entry, isnew, appCache, status) {
|
||||
if (typeof callback === "object") {
|
||||
// Root us at the callback
|
||||
callback.__cache_listener_root = this;
|
||||
callback.onCacheEntryAvailable(entry, isnew, appCache, status);
|
||||
}
|
||||
else
|
||||
callback(status, entry, appCache);
|
||||
},
|
||||
|
||||
get mainThreadOnly() {
|
||||
return true;
|
||||
},
|
||||
|
||||
run: function () {
|
||||
var cache = get_cache_service();
|
||||
var session = cache.createSession(
|
||||
sessionName,
|
||||
storagePolicy,
|
||||
Components.interfaces.nsICache.STREAM_BASED);
|
||||
session.asyncOpenCacheEntry(key, access, this);
|
||||
var storage = getCacheStorage(where, lci, this._appCache);
|
||||
storage.asyncOpenURI(key, "", flags, this);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -47,68 +100,51 @@ function asyncOpenCacheEntry(key, sessionName, storagePolicy, access, callback)
|
|||
|
||||
function syncWithCacheIOThread(callback)
|
||||
{
|
||||
asyncOpenCacheEntry(
|
||||
"nonexistententry",
|
||||
"HTTP",
|
||||
Components.interfaces.nsICache.STORE_ANYWHERE,
|
||||
Components.interfaces.nsICache.ACCESS_READ,
|
||||
function(status, entry) {
|
||||
do_check_eq(status, Components.results.NS_ERROR_CACHE_KEY_NOT_FOUND);
|
||||
callback();
|
||||
});
|
||||
if (!newCacheBackEndUsed()) {
|
||||
asyncOpenCacheEntry(
|
||||
"http://nonexistententry/", "disk", Ci.nsICacheStorage.OPEN_READONLY, null,
|
||||
function(status, entry) {
|
||||
do_check_eq(status, Components.results.NS_ERROR_CACHE_KEY_NOT_FOUND);
|
||||
callback();
|
||||
});
|
||||
}
|
||||
else {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
function get_device_entry_count(device) {
|
||||
var cs = get_cache_service();
|
||||
var entry_count = -1;
|
||||
function get_device_entry_count(where, lci, continuation) {
|
||||
var storage = getCacheStorage(where, lci);
|
||||
if (!storage) {
|
||||
continuation(-1, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
var visitor = {
|
||||
visitDevice: function (deviceID, deviceInfo) {
|
||||
if (device == deviceID)
|
||||
entry_count = deviceInfo.entryCount;
|
||||
return false;
|
||||
onCacheStorageInfo: function (entryCount, consumption) {
|
||||
do_execute_soon(function() {
|
||||
continuation(entryCount, consumption);
|
||||
});
|
||||
},
|
||||
visitEntry: function (deviceID, entryInfo) {
|
||||
do_throw("nsICacheVisitor.visitEntry should not be called " +
|
||||
"when checking the availability of devices");
|
||||
}
|
||||
};
|
||||
|
||||
// get the device entry count
|
||||
cs.visitEntries(visitor);
|
||||
|
||||
return entry_count;
|
||||
storage.asyncVisitStorage(visitor, false);
|
||||
}
|
||||
|
||||
function asyncCheckCacheEntryPresence(key, sessionName, storagePolicy, shouldExist, doomOnExpire, continuation)
|
||||
function asyncCheckCacheEntryPresence(key, where, shouldExist, continuation, appCache)
|
||||
{
|
||||
var listener =
|
||||
{
|
||||
QueryInterface : function(iid)
|
||||
{
|
||||
if (iid.equals(Components.interfaces.nsICacheListener))
|
||||
return this;
|
||||
throw Components.results.NS_NOINTERFACE;
|
||||
},
|
||||
onCacheEntryAvailable : function(descriptor, accessGranted, status)
|
||||
{
|
||||
asyncOpenCacheEntry(key, where, Ci.nsICacheStorage.OPEN_READONLY, null,
|
||||
function(status, entry) {
|
||||
if (shouldExist) {
|
||||
dump("TEST-INFO | checking cache key " + key + " exists @ " + sessionName);
|
||||
dump("TEST-INFO | checking cache key " + key + " exists @ " + where);
|
||||
do_check_eq(status, Cr.NS_OK);
|
||||
do_check_true(!!descriptor);
|
||||
do_check_true(!!entry);
|
||||
} else {
|
||||
dump("TEST-INFO | checking cache key " + key + " doesn't exist @ " + sessionName);
|
||||
dump("TEST-INFO | checking cache key " + key + " doesn't exist @ " + where);
|
||||
do_check_eq(status, Cr.NS_ERROR_CACHE_KEY_NOT_FOUND);
|
||||
do_check_null(descriptor);
|
||||
do_check_null(entry);
|
||||
}
|
||||
continuation();
|
||||
}
|
||||
};
|
||||
|
||||
var service = Cc["@mozilla.org/network/cache-service;1"].getService(Ci.nsICacheService);
|
||||
var session = service.createSession(sessionName,
|
||||
storagePolicy,
|
||||
true);
|
||||
session.doomEntriesIfExpired = doomOnExpire;
|
||||
session.asyncOpenCacheEntry(key, Ci.nsICache.ACCESS_READ, listener);
|
||||
}, appCache);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,372 @@
|
|||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
|
||||
function newCacheBackEndUsed()
|
||||
{
|
||||
var cache1srv = Components.classes["@mozilla.org/network/cache-service;1"]
|
||||
.getService(Components.interfaces.nsICacheService);
|
||||
var cache2srv = Components.classes["@mozilla.org/netwerk/cache-storage-service;1"]
|
||||
.getService(Components.interfaces.nsICacheStorageService);
|
||||
|
||||
return cache1srv.cacheIOTarget != cache2srv.ioTarget;
|
||||
}
|
||||
|
||||
var callbacks = new Array();
|
||||
|
||||
// Expect an existing entry
|
||||
const NORMAL = 0;
|
||||
// Expect a new entry
|
||||
const NEW = 1 << 0;
|
||||
// Return early from onCacheEntryCheck and set the callback to state it expects onCacheEntryCheck to happen
|
||||
const NOTVALID = 1 << 1;
|
||||
// Throw from onCacheEntryAvailable
|
||||
const THROWAVAIL = 1 << 2;
|
||||
// Open entry for reading-only
|
||||
const READONLY = 1 << 3;
|
||||
// Expect the entry to not be found
|
||||
const NOTFOUND = 1 << 4;
|
||||
// Return ENTRY_NEEDS_REVALIDATION from onCacheEntryCheck
|
||||
const REVAL = 1 << 5;
|
||||
// Return ENTRY_PARTIAL from onCacheEntryCheck, in combo with NEW or RECREATE bypasses check for emptiness of the entry
|
||||
const PARTIAL = 1 << 6
|
||||
// Expect the entry is doomed, i.e. the output stream should not be possible to open
|
||||
const DOOMED = 1 << 7;
|
||||
// Don't trigger the go-on callback until the entry is written
|
||||
const WAITFORWRITE = 1 << 8;
|
||||
// Don't write data (i.e. don't open output stream)
|
||||
const METAONLY = 1 << 9;
|
||||
// Do recreation of an existing cache entry
|
||||
const RECREATE = 1 << 10;
|
||||
// Do not give me the entry
|
||||
const NOTWANTED = 1 << 11;
|
||||
|
||||
var log_c2 = true;
|
||||
function LOG_C2(o, m)
|
||||
{
|
||||
if (!log_c2) return;
|
||||
if (!m)
|
||||
dump("TEST-INFO | CACHE2: " + o + "\n");
|
||||
else
|
||||
dump("TEST-INFO | CACHE2: callback #" + o.order + "(" + (o.workingData || "---") + ") " + m + "\n");
|
||||
}
|
||||
|
||||
function pumpReadStream(inputStream, goon)
|
||||
{
|
||||
if (inputStream.isNonBlocking()) {
|
||||
// non-blocking stream, must read via pump
|
||||
var pump = Cc["@mozilla.org/network/input-stream-pump;1"]
|
||||
.createInstance(Ci.nsIInputStreamPump);
|
||||
pump.init(inputStream, -1, -1, 0, 0, true);
|
||||
var data = "";
|
||||
pump.asyncRead({
|
||||
onStartRequest: function (aRequest, aContext) { },
|
||||
onDataAvailable: function (aRequest, aContext, aInputStream, aOffset, aCount)
|
||||
{
|
||||
var wrapper = Cc["@mozilla.org/scriptableinputstream;1"].
|
||||
createInstance(Ci.nsIScriptableInputStream);
|
||||
wrapper.init(aInputStream);
|
||||
var str = wrapper.read(wrapper.available());
|
||||
LOG_C2("reading data '" + str.substring(0,5) + "'");
|
||||
data += str;
|
||||
},
|
||||
onStopRequest: function (aRequest, aContext, aStatusCode)
|
||||
{
|
||||
LOG_C2("done reading data: " + aStatusCode);
|
||||
do_check_eq(aStatusCode, Cr.NS_OK);
|
||||
goon(data);
|
||||
},
|
||||
}, null);
|
||||
}
|
||||
else {
|
||||
// blocking stream
|
||||
var data = read_stream(inputStream, inputStream.available());
|
||||
goon(data);
|
||||
}
|
||||
}
|
||||
|
||||
OpenCallback.prototype =
|
||||
{
|
||||
QueryInterface: function listener_qi(iid) {
|
||||
if (iid.equals(Ci.nsISupports) ||
|
||||
iid.equals(Ci.nsICacheEntryOpenCallback)) {
|
||||
return this;
|
||||
}
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
onCacheEntryCheck: function(entry, appCache)
|
||||
{
|
||||
LOG_C2(this, "onCacheEntryCheck");
|
||||
do_check_true(!this.onCheckPassed);
|
||||
this.onCheckPassed = true;
|
||||
|
||||
if (this.behavior & NOTVALID) {
|
||||
LOG_C2(this, "onCacheEntryCheck DONE, return ENTRY_WANTED");
|
||||
return Ci.nsICacheEntryOpenCallback.ENTRY_WANTED;
|
||||
}
|
||||
|
||||
if (this.behavior & NOTWANTED) {
|
||||
LOG_C2(this, "onCacheEntryCheck DONE, return ENTRY_NOT_WANTED");
|
||||
return Ci.nsICacheEntryOpenCallback.ENTRY_NOT_WANTED;
|
||||
}
|
||||
|
||||
do_check_eq(entry.getMetaDataElement("meto"), this.workingMetadata);
|
||||
|
||||
// check for sane flag combination
|
||||
do_check_neq(this.behavior & (REVAL|PARTIAL), REVAL|PARTIAL);
|
||||
|
||||
if (this.behavior & (REVAL|PARTIAL)) {
|
||||
LOG_C2(this, "onCacheEntryCheck DONE, return REVAL");
|
||||
return Ci.nsICacheEntryOpenCallback.ENTRY_NEEDS_REVALIDATION;
|
||||
}
|
||||
|
||||
LOG_C2(this, "onCacheEntryCheck DONE, return ENTRY_WANTED");
|
||||
return Ci.nsICacheEntryOpenCallback.ENTRY_WANTED;
|
||||
},
|
||||
onCacheEntryAvailable: function(entry, isnew, appCache, status)
|
||||
{
|
||||
LOG_C2(this, "onCacheEntryAvailable, " + this.behavior);
|
||||
do_check_true(!this.onAvailPassed);
|
||||
this.onAvailPassed = true;
|
||||
|
||||
do_check_eq(isnew, !!(this.behavior & NEW));
|
||||
|
||||
if (this.behavior & (NOTFOUND|NOTWANTED)) {
|
||||
do_check_eq(status, Cr.NS_ERROR_CACHE_KEY_NOT_FOUND);
|
||||
do_check_false(!!entry);
|
||||
if (this.behavior & THROWAVAIL)
|
||||
this.throwAndNotify(entry);
|
||||
this.goon(entry);
|
||||
}
|
||||
else if (this.behavior & (NEW|RECREATE)) {
|
||||
do_check_true(!!entry);
|
||||
|
||||
if (this.behavior & RECREATE) {
|
||||
entry = entry.recreate();
|
||||
do_check_true(!!entry);
|
||||
}
|
||||
|
||||
if (this.behavior & THROWAVAIL)
|
||||
this.throwAndNotify(entry);
|
||||
|
||||
if (!(this.behavior & WAITFORWRITE))
|
||||
this.goon(entry);
|
||||
|
||||
if (!(this.behavior & PARTIAL)) {
|
||||
try {
|
||||
entry.getMetaDataElement("meto");
|
||||
do_check_true(false);
|
||||
}
|
||||
catch (ex) {}
|
||||
}
|
||||
|
||||
var self = this;
|
||||
do_execute_soon(function() { // emulate network latency
|
||||
entry.setMetaDataElement("meto", self.workingMetadata);
|
||||
entry.metaDataReady();
|
||||
if (self.behavior & METAONLY) {
|
||||
// Since forcing GC/CC doesn't trigger OnWriterClosed, we have to set the entry valid manually :(
|
||||
entry.setValid();
|
||||
entry.close();
|
||||
return;
|
||||
}
|
||||
do_execute_soon(function() { // emulate more network latency
|
||||
if (self.behavior & DOOMED) {
|
||||
try {
|
||||
var os = entry.openOutputStream(0);
|
||||
do_check_true(false);
|
||||
} catch (ex) {
|
||||
do_check_true(true);
|
||||
}
|
||||
if (self.behavior & WAITFORWRITE)
|
||||
self.goon(entry);
|
||||
return;
|
||||
}
|
||||
|
||||
var offset = (self.behavior & PARTIAL)
|
||||
? entry.dataSize
|
||||
: 0;
|
||||
LOG_C2(self, "openOutputStream @ " + offset);
|
||||
var os = entry.openOutputStream(offset);
|
||||
LOG_C2(self, "writing data");
|
||||
var wrt = os.write(self.workingData, self.workingData.length);
|
||||
do_check_eq(wrt, self.workingData.length);
|
||||
os.close();
|
||||
if (self.behavior & WAITFORWRITE)
|
||||
self.goon(entry);
|
||||
|
||||
entry.close();
|
||||
})
|
||||
})
|
||||
}
|
||||
else { // NORMAL
|
||||
do_check_true(!!entry);
|
||||
do_check_eq(entry.getMetaDataElement("meto"), this.workingMetadata);
|
||||
if (this.behavior & THROWAVAIL)
|
||||
this.throwAndNotify(entry);
|
||||
|
||||
var wrapper = Cc["@mozilla.org/scriptableinputstream;1"].
|
||||
createInstance(Ci.nsIScriptableInputStream);
|
||||
var self = this;
|
||||
pumpReadStream(entry.openInputStream(0), function(data) {
|
||||
do_check_eq(data, self.workingData);
|
||||
self.onDataCheckPassed = true;
|
||||
LOG_C2(self, "entry read done");
|
||||
self.goon(entry);
|
||||
entry.close();
|
||||
});
|
||||
}
|
||||
},
|
||||
get mainThreadOnly() {
|
||||
return true;
|
||||
},
|
||||
selfCheck: function()
|
||||
{
|
||||
LOG_C2(this, "selfCheck");
|
||||
|
||||
do_check_true(this.onCheckPassed);
|
||||
do_check_true(this.onAvailPassed);
|
||||
do_check_true(this.onDataCheckPassed);
|
||||
},
|
||||
throwAndNotify: function(entry)
|
||||
{
|
||||
LOG_C2(this, "Throwing");
|
||||
var self = this;
|
||||
do_execute_soon(function() {
|
||||
LOG_C2(self, "Notifying");
|
||||
self.goon(entry);
|
||||
});
|
||||
throw Cr.NS_ERROR_FAILURE;
|
||||
}
|
||||
};
|
||||
|
||||
function OpenCallback(behavior, workingMetadata, workingData, goon)
|
||||
{
|
||||
this.behavior = behavior;
|
||||
this.workingMetadata = workingMetadata;
|
||||
this.workingData = workingData;
|
||||
this.goon = goon;
|
||||
this.onCheckPassed = (!!(behavior & (NEW|RECREATE)) || !workingMetadata) && !(behavior & NOTVALID);
|
||||
this.onAvailPassed = false;
|
||||
this.onDataCheckPassed = !!(behavior & (NEW|RECREATE|NOTWANTED)) || !workingMetadata;
|
||||
callbacks.push(this);
|
||||
this.order = callbacks.length;
|
||||
}
|
||||
|
||||
VisitCallback.prototype =
|
||||
{
|
||||
QueryInterface: function listener_qi(iid) {
|
||||
if (iid.equals(Ci.nsISupports) ||
|
||||
iid.equals(Ci.nsICacheStorageVisitor)) {
|
||||
return this;
|
||||
}
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
onCacheStorageInfo: function(num, consumption)
|
||||
{
|
||||
LOG_C2(this, "onCacheStorageInfo: num=" + num + ", size=" + consumption);
|
||||
do_check_eq(this.num, num);
|
||||
if (newCacheBackEndUsed()) {
|
||||
// Consumption is as expected only in the new backend
|
||||
do_check_eq(this.consumption, consumption);
|
||||
}
|
||||
if (!this.entries)
|
||||
this.notify();
|
||||
},
|
||||
onCacheEntryInfo: function(entry)
|
||||
{
|
||||
var key = entry.key;
|
||||
LOG_C2(this, "onCacheEntryInfo: key=" + key);
|
||||
|
||||
do_check_true(!!this.entries);
|
||||
|
||||
var index = this.entries.indexOf(key);
|
||||
do_check_true(index > -1);
|
||||
|
||||
this.entries.splice(index, 1);
|
||||
},
|
||||
onCacheEntryVisitCompleted: function()
|
||||
{
|
||||
LOG_C2(this, "onCacheEntryVisitCompleted");
|
||||
if (this.entries)
|
||||
do_check_eq(this.entries.length, 0);
|
||||
this.notify();
|
||||
},
|
||||
notify: function()
|
||||
{
|
||||
do_check_true(!!this.goon);
|
||||
var goon = this.goon;
|
||||
this.goon = null;
|
||||
do_execute_soon(goon);
|
||||
},
|
||||
selfCheck: function()
|
||||
{
|
||||
do_check_true(!this.entries || !this.entries.length);
|
||||
}
|
||||
};
|
||||
|
||||
function VisitCallback(num, consumption, entries, goon)
|
||||
{
|
||||
this.num = num;
|
||||
this.consumption = consumption;
|
||||
this.entries = entries;
|
||||
this.goon = goon;
|
||||
callbacks.push(this);
|
||||
this.order = callbacks.length;
|
||||
}
|
||||
|
||||
EvictionCallback.prototype =
|
||||
{
|
||||
QueryInterface: function listener_qi(iid) {
|
||||
if (iid.equals(Ci.nsISupports) ||
|
||||
iid.equals(Ci.nsICacheEntryDoomCallback)) {
|
||||
return this;
|
||||
}
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
onCacheEntryDoomed: function(result)
|
||||
{
|
||||
do_check_eq(this.expectedSuccess, result == Cr.NS_OK);
|
||||
this.goon();
|
||||
},
|
||||
selfCheck: function() {}
|
||||
}
|
||||
|
||||
function EvictionCallback(success, goon)
|
||||
{
|
||||
this.expectedSuccess = success;
|
||||
this.goon = goon;
|
||||
callbacks.push(this);
|
||||
this.order = callbacks.length;
|
||||
}
|
||||
|
||||
MultipleCallbacks.prototype =
|
||||
{
|
||||
fired: function()
|
||||
{
|
||||
if (--this.pending == 0)
|
||||
{
|
||||
var self = this;
|
||||
if (this.delayed)
|
||||
do_execute_soon(function() { self.goon(); });
|
||||
else
|
||||
this.goon();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function MultipleCallbacks(number, goon, delayed)
|
||||
{
|
||||
this.pending = number;
|
||||
this.goon = goon;
|
||||
this.delayed = delayed;
|
||||
}
|
||||
|
||||
function finish_cache2_test()
|
||||
{
|
||||
callbacks.forEach(function(callback, index) {
|
||||
callback.selfCheck();
|
||||
});
|
||||
do_test_finished();
|
||||
}
|
|
@ -1,8 +1,6 @@
|
|||
const CC = Components.Constructor;
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cr = Components.results;
|
||||
const Cu = Components.utils;
|
||||
const CC = Components.Constructor;
|
||||
|
||||
const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
|
||||
"nsIBinaryInputStream",
|
||||
|
|
|
@ -1,11 +1,6 @@
|
|||
"use strict";
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=761228
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
|
||||
Cu.import("resource://testing-common/httpd.js");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "URL", function() {
|
||||
|
@ -36,9 +31,9 @@ function make_channel(url) {
|
|||
}
|
||||
|
||||
function clearCache() {
|
||||
var service = Components.classes["@mozilla.org/network/cache-service;1"]
|
||||
.getService(Ci.nsICacheService);
|
||||
service.evictEntries(Ci.nsICache.STORE_ANYWHERE);
|
||||
var service = Components.classes["@mozilla.org/netwerk/cache-storage-service;1"]
|
||||
.getService(Ci.nsICacheStorageService);
|
||||
service.clear();
|
||||
}
|
||||
|
||||
function alwaysReturn304Handler(metadata, response) {
|
||||
|
@ -80,8 +75,7 @@ add_test(function test_unexpected_304() {
|
|||
// the cache.
|
||||
add_test(function test_304_stored_in_cache() {
|
||||
asyncOpenCacheEntry(
|
||||
baseURI + existingCached304, "HTTP",
|
||||
Ci.nsICache.STORE_ANYWHERE, Ci.nsICache.ACCESS_READ_WRITE,
|
||||
baseURI + existingCached304, "disk", Ci.nsICacheStorage.OPEN_NORMALLY, null,
|
||||
function (entryStatus, cacheEntry) {
|
||||
cacheEntry.setMetaDataElement("request-method", "GET");
|
||||
cacheEntry.setMetaDataElement("response-head",
|
||||
|
|
|
@ -1,8 +1,3 @@
|
|||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
|
||||
Cu.import("resource://testing-common/httpd.js");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "URL", function() {
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
*
|
||||
* See also https://bugzilla.mozilla.org/show_bug.cgi?id=609667
|
||||
*/
|
||||
const Cr = Components.results;
|
||||
|
||||
var BS = '\\';
|
||||
var DQUOTE = '"';
|
||||
|
|
|
@ -8,11 +8,6 @@
|
|||
* This file tests the methods on NetUtil.jsm.
|
||||
*/
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
|
||||
Cu.import("resource://testing-common/httpd.js");
|
||||
|
||||
Components.utils.import("resource://gre/modules/NetUtil.jsm");
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
Components.utils.import("resource://gre/modules/NetUtil.jsm");
|
||||
const Ci = Components.interfaces;
|
||||
const Cr = Components.results;
|
||||
|
||||
var gIoService = Components.classes["@mozilla.org/network/io-service;1"]
|
||||
.getService(Components.interfaces.nsIIOService);
|
||||
|
|
|
@ -4,11 +4,6 @@
|
|||
// etc--see HttpBaseChannel::IsSafeMethod). Since no prompting is possible
|
||||
// in xpcshell, we get an error for prompts, and the request fails.
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
|
||||
Cu.import("resource://testing-common/httpd.js");
|
||||
|
||||
var sSame;
|
||||
|
|
|
@ -3,9 +3,6 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
let gDashboard = Cc['@mozilla.org/network/dashboard;1']
|
||||
.getService(Ci.nsIDashboard);
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// socket should elicit NS_ERROR_SOCKET_ADDRESS_IN_USE on non-Windows
|
||||
// machines.
|
||||
|
||||
const { classes: Cc, interfaces: Ci, results: Cr, Constructor: CC } = Components;
|
||||
const CC = Components.Constructor;
|
||||
|
||||
const ServerSocket = CC("@mozilla.org/network/server-socket;1",
|
||||
"nsIServerSocket",
|
||||
|
|
|
@ -1,8 +1,3 @@
|
|||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
|
||||
Cu.import("resource://testing-common/httpd.js");
|
||||
|
||||
var httpserver = new HttpServer();
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
|
|
|
@ -10,11 +10,6 @@
|
|||
* <copied from="test_authentication.js"/>
|
||||
*/
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
|
||||
Cu.import("resource://testing-common/httpd.js");
|
||||
|
||||
const FLAG_RETURN_FALSE = 1 << 0;
|
||||
|
|
|
@ -1,11 +1,6 @@
|
|||
// This file tests authentication prompt callbacks
|
||||
// TODO NIT use do_check_eq(expected, actual) consistently, not sometimes eq(actual, expected)
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
|
||||
Cu.import("resource://testing-common/httpd.js");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "URL", function() {
|
||||
|
|
|
@ -7,11 +7,6 @@
|
|||
* This file tests components that implement nsIBackgroundFileSaver.
|
||||
*/
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Globals
|
||||
|
||||
|
|
|
@ -4,11 +4,6 @@
|
|||
// specified in RFC 2616 section 14.9.3 by letting max-age
|
||||
// take precedence
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
|
||||
Cu.import("resource://testing-common/httpd.js");
|
||||
const BUGID = "203271";
|
||||
|
||||
|
|
|
@ -2,56 +2,17 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cr = Components.results;
|
||||
|
||||
// names for cache devices
|
||||
const kDiskDevice = "disk";
|
||||
const kMemoryDevice = "memory";
|
||||
const kOfflineDevice = "offline";
|
||||
const kPrivate = "private";
|
||||
const kOfflineDevice = "appcache";
|
||||
|
||||
const kCacheA = "cache-A";
|
||||
const kCacheA2 = "cache-A2";
|
||||
const kCacheB = "cache-B";
|
||||
const kCacheC = "cache-C";
|
||||
const kCacheA = "http://cache/A";
|
||||
const kCacheA2 = "http://cache/A2";
|
||||
const kCacheB = "http://cache/B";
|
||||
const kCacheC = "http://cache/C";
|
||||
const kTestContent = "test content";
|
||||
|
||||
// the name for our cache session
|
||||
const kPrivateBrowsing = "PrivateBrowsing";
|
||||
|
||||
function check_devices_available(devices) {
|
||||
var cs = get_cache_service();
|
||||
var found_devices = [];
|
||||
|
||||
var visitor = {
|
||||
visitDevice: function (deviceID, deviceInfo) {
|
||||
found_devices.push(deviceID);
|
||||
return false;
|
||||
},
|
||||
visitEntry: function (deviceID, entryInfo) {
|
||||
do_throw("nsICacheVisitor.visitEntry should not be called " +
|
||||
"when checking the availability of devices");
|
||||
}
|
||||
};
|
||||
|
||||
// get the list of active devices
|
||||
cs.visitEntries(visitor);
|
||||
|
||||
// see if any of the required devices was missing
|
||||
if (devices.sort().toString() != found_devices.sort().toString()) {
|
||||
do_throw("Expected to find these devices: \"" + devices.sort().toString() +
|
||||
"\", but found these instead: \"" + found_devices.sort().toString() + "\"");
|
||||
}
|
||||
|
||||
// see if any extra devices have been found
|
||||
if (found_devices.length > devices.length) {
|
||||
do_throw("Expected to find these devices: [" + devices.join(", ") +
|
||||
"], but instead got: [" + found_devices.join(", ") + "]");
|
||||
}
|
||||
}
|
||||
|
||||
function make_input_stream_scriptable(input) {
|
||||
var wrapper = Cc["@mozilla.org/scriptableinputstream;1"].
|
||||
createInstance(Ci.nsIScriptableInputStream);
|
||||
|
@ -62,27 +23,15 @@ function make_input_stream_scriptable(input) {
|
|||
const entries = [
|
||||
// key content device should exist after leaving PB
|
||||
[kCacheA, kTestContent, kMemoryDevice, true],
|
||||
[kCacheA2, kTestContent, kPrivate, false],
|
||||
[kCacheA2, kTestContent, kDiskDevice, false],
|
||||
[kCacheB, kTestContent, kDiskDevice, true],
|
||||
[kCacheC, kTestContent, kOfflineDevice, true]
|
||||
]
|
||||
|
||||
function get_storage_policy(device)
|
||||
{
|
||||
switch (device) {
|
||||
case kDiskDevice:
|
||||
return Ci.nsICache.STORE_ON_DISK;
|
||||
case kOfflineDevice:
|
||||
return Ci.nsICache.STORE_OFFLINE;
|
||||
case kMemoryDevice:
|
||||
case kPrivate:
|
||||
return Ci.nsICache.STORE_IN_MEMORY;
|
||||
}
|
||||
do_throw("unknown device");
|
||||
}
|
||||
|
||||
var store_idx;
|
||||
var store_cb = null;
|
||||
var appCache = null;
|
||||
|
||||
function store_entries(cb)
|
||||
{
|
||||
if (cb) {
|
||||
|
@ -95,35 +44,28 @@ function store_entries(cb)
|
|||
return;
|
||||
}
|
||||
|
||||
var cache = get_cache_service();
|
||||
var session = cache.createSession(kPrivateBrowsing,
|
||||
get_storage_policy(entries[store_idx][2]),
|
||||
Ci.nsICache.STREAM_BASED);
|
||||
if (entries[store_idx][2] == kPrivate) {
|
||||
session.isPrivate = true;
|
||||
}
|
||||
|
||||
session.asyncOpenCacheEntry(entries[store_idx][0],
|
||||
Ci.nsICache.ACCESS_WRITE,
|
||||
store_data);
|
||||
asyncOpenCacheEntry(entries[store_idx][0],
|
||||
entries[store_idx][2],
|
||||
Ci.nsICacheStorage.OPEN_TRUNCATE,
|
||||
LoadContextInfo.custom(!entries[store_idx][3]),
|
||||
store_data,
|
||||
appCache);
|
||||
}
|
||||
|
||||
var store_data = {
|
||||
onCacheEntryAvailable: function oCEA(entry, access, status) {
|
||||
do_check_eq(status, Cr.NS_OK);
|
||||
var os = entry.openOutputStream(0);
|
||||
var store_data = function(status, entry) {
|
||||
do_check_eq(status, Cr.NS_OK);
|
||||
var os = entry.openOutputStream(0);
|
||||
|
||||
var written = os.write(entries[store_idx][1], entries[store_idx][1].length);
|
||||
if (written != entries[store_idx][1].length) {
|
||||
do_throw("os.write has not written all data!\n" +
|
||||
" Expected: " + entries[store_idx][1].length + "\n" +
|
||||
" Actual: " + written + "\n");
|
||||
}
|
||||
os.close();
|
||||
entry.close();
|
||||
store_idx++;
|
||||
do_execute_soon(store_entries);
|
||||
var written = os.write(entries[store_idx][1], entries[store_idx][1].length);
|
||||
if (written != entries[store_idx][1].length) {
|
||||
do_throw("os.write has not written all data!\n" +
|
||||
" Expected: " + entries[store_idx][1].length + "\n" +
|
||||
" Actual: " + written + "\n");
|
||||
}
|
||||
os.close();
|
||||
entry.close();
|
||||
store_idx++;
|
||||
do_execute_soon(store_entries);
|
||||
};
|
||||
|
||||
var check_idx;
|
||||
|
@ -142,41 +84,42 @@ function check_entries(cb, pbExited)
|
|||
return;
|
||||
}
|
||||
|
||||
var cache = get_cache_service();
|
||||
var session = cache.createSession(kPrivateBrowsing,
|
||||
get_storage_policy(entries[check_idx][2]),
|
||||
Ci.nsICache.STREAM_BASED);
|
||||
if (entries[check_idx][2] == kPrivate) {
|
||||
session.isPrivate = true;
|
||||
}
|
||||
|
||||
session.asyncOpenCacheEntry(entries[check_idx][0],
|
||||
Ci.nsICache.ACCESS_READ,
|
||||
check_data);
|
||||
asyncOpenCacheEntry(entries[check_idx][0],
|
||||
entries[check_idx][2],
|
||||
Ci.nsICacheStorage.OPEN_READONLY,
|
||||
LoadContextInfo.custom(!entries[check_idx][3]),
|
||||
check_data,
|
||||
appCache);
|
||||
}
|
||||
|
||||
var check_data = {
|
||||
onCacheEntryAvailable: function oCEA(entry, access, status) {
|
||||
if (!check_pb_exited || entries[check_idx][3]) {
|
||||
do_check_eq(status, Cr.NS_OK);
|
||||
var is = make_input_stream_scriptable(entry.openInputStream(0));
|
||||
var read = is.read(is.available());
|
||||
is.close();
|
||||
entry.close();
|
||||
do_check_eq(read, entries[check_idx][1]);
|
||||
} else {
|
||||
do_check_eq(status, Cr.NS_ERROR_CACHE_KEY_NOT_FOUND);
|
||||
}
|
||||
|
||||
var check_data = function (status, entry) {
|
||||
var cont = function() {
|
||||
check_idx++;
|
||||
do_execute_soon(check_entries);
|
||||
}
|
||||
|
||||
if (!check_pb_exited || entries[check_idx][3]) {
|
||||
do_check_eq(status, Cr.NS_OK);
|
||||
var is = entry.openInputStream(0);
|
||||
pumpReadStream(is, function(read) {
|
||||
entry.close();
|
||||
do_check_eq(read, entries[check_idx][1]);
|
||||
cont();
|
||||
});
|
||||
} else {
|
||||
do_check_eq(status, Cr.NS_ERROR_CACHE_KEY_NOT_FOUND);
|
||||
cont();
|
||||
}
|
||||
};
|
||||
|
||||
function run_test() {
|
||||
// Simulate a profile dir for xpcshell
|
||||
do_get_profile();
|
||||
|
||||
appCache = Cc["@mozilla.org/network/application-cache-service;1"].
|
||||
getService(Ci.nsIApplicationCacheService).
|
||||
getApplicationCache("fake-client-id|fake-group-id");
|
||||
|
||||
// Start off with an empty cache
|
||||
evict_cache_entries();
|
||||
|
||||
|
@ -187,9 +130,6 @@ function run_test() {
|
|||
}
|
||||
|
||||
function run_test2() {
|
||||
// Make sure all three cache devices are available initially
|
||||
check_devices_available([kMemoryDevice, kDiskDevice, kOfflineDevice]);
|
||||
|
||||
// Check if cache-A, cache-A2, cache-B and cache-C are available
|
||||
check_entries(run_test3, false);
|
||||
}
|
||||
|
@ -200,12 +140,10 @@ function run_test3() {
|
|||
getService(Ci.nsIObserverService);
|
||||
obsvc.notifyObservers(null, "last-pb-context-exited", null);
|
||||
|
||||
// Make sure all three cache devices are still available
|
||||
check_devices_available([kMemoryDevice, kDiskDevice, kOfflineDevice]);
|
||||
|
||||
// Make sure the memory device is not empty
|
||||
do_check_eq(get_device_entry_count(kMemoryDevice), 1);
|
||||
|
||||
// Check if cache-A is gone, and cache-B and cache-C are still available
|
||||
check_entries(do_test_finished, true);
|
||||
get_device_entry_count(kMemoryDevice, null, function(count) {
|
||||
do_check_eq(count, 1);
|
||||
// Check if cache-A is gone, and cache-B and cache-C are still available
|
||||
check_entries(do_test_finished, true);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -2,10 +2,6 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const Cu = Components.utils;
|
||||
const Ci = Components.interfaces;
|
||||
const Cc = Components.classes;
|
||||
|
||||
Cu.import("resource://testing-common/httpd.js");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
|
|
|
@ -1,7 +1,3 @@
|
|||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cr = Components.results;
|
||||
|
||||
function run_test() {
|
||||
var ios = Cc["@mozilla.org/network/io-service;1"].
|
||||
getService(Ci.nsIIOService);
|
||||
|
|
|
@ -1,8 +1,3 @@
|
|||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
|
||||
Cu.import("resource://testing-common/httpd.js");
|
||||
|
||||
var server;
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
const url = "http://foo.com/folder/file?/.";
|
||||
|
||||
function run_test() {
|
||||
|
|
|
@ -1,8 +1,3 @@
|
|||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
|
||||
Cu.import("resource://testing-common/httpd.js");
|
||||
|
||||
var server;
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
/* verify that certain invalid URIs are not parsed by the resource
|
||||
protocol handler */
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cr = Components.results;
|
||||
|
||||
const specs = [
|
||||
"resource:////",
|
||||
"resource:///http://www.mozilla.org/",
|
||||
|
|
|
@ -90,9 +90,7 @@ function next_test() {
|
|||
do_test_finished();
|
||||
else {
|
||||
asyncOpenCacheEntry(URL,
|
||||
"FTP",
|
||||
Components.interfaces.nsICache.STORE_ANYWHERE,
|
||||
Components.interfaces.nsICache.ACCESS_READ_WRITE,
|
||||
"disk", Ci.nsICacheStorage.OPEN_NORMALLY, null,
|
||||
storeData);
|
||||
}
|
||||
}
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче