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:
Honza Bambas 2013-09-20 11:11:25 +02:00
Родитель d1b254f231
Коммит 894ba59236
274 изменённых файлов: 9823 добавлений и 2927 удалений

Просмотреть файл

@ -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 }
};

16
netwerk/cache/nsApplicationCacheService.cpp поставляемый
Просмотреть файл

@ -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

2
netwerk/cache/nsCacheUtils.cpp поставляемый
Просмотреть файл

@ -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!");

62
netwerk/cache/nsDiskCacheDeviceSQL.cpp поставляемый
Просмотреть файл

@ -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);
}
}

4
netwerk/cache/nsDiskCacheDeviceSQL.h поставляемый
Просмотреть файл

@ -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

Разница между файлами не показана из-за своего большого размера Загрузить разницу

301
netwerk/cache2/CacheEntry.h Normal file
Просмотреть файл

@ -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

25
netwerk/cache2/CacheLog.h Normal file
Просмотреть файл

@ -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

51
netwerk/cache2/moz.build Normal file
Просмотреть файл

@ -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);
}
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше