Bug 1144689 - Allow setting manually a fetch time and modified time for cache entries. r=fabrice

This commit is contained in:
Antonio M. Amaya 2015-04-06 06:14:00 +02:00
parent 25df92a2d7
commit ffd9c6817a

View File

@ -46,32 +46,43 @@ function enableOfflineCacheForApp(aPrincipal) {
}
function storeCache(applicationCache, url, file, itemType) {
function storeCache(applicationCache, url, file, itemType, metadata) {
let storage =
Services.cache2.appCacheStorage(LoadContextInfo.default, applicationCache);
let uri = Services.io.newURI(url, null, null);
let nowGMT = new Date().toGMTString();
metadata = metadata || {};
metadata.lastFetched = metadata.lastFetched || nowGMT;
metadata.lastModified = metadata.lastModified || nowGMT;
storage.asyncOpenURI(uri, "", nsICacheStorage.OPEN_TRUNCATE, {
onCacheEntryAvailable:
function (cacheEntry, isNew, appCache, result) {
cacheEntry.setMetaDataElement('request-method', 'GET');
cacheEntry.setMetaDataElement('response-head', 'HTTP/1.1 200 OK\r\n');
cacheEntry.setMetaDataElement("request-method", "GET");
cacheEntry.setMetaDataElement("response-head",
"HTTP/1.1 200 OK\r\n" +
"Date: " + metadata.lastFetched + "\r\n" +
"Last-Modified: " + metadata.lastModified + "\r\n" +
"Cache-Control: no-cache\r\n");
let outputStream = cacheEntry.openOutputStream(0);
// Input-Output stream machinery in order to push nsIFile content into cache
let inputStream = Cc['@mozilla.org/network/file-input-stream;1']
// Input-Output stream machinery in order to push nsIFile content into
// cache
let inputStream = Cc["@mozilla.org/network/file-input-stream;1"]
.createInstance(Ci.nsIFileInputStream);
inputStream.init(file, 1, -1, null);
let bufferedOutputStream = Cc['@mozilla.org/network/buffered-output-stream;1']
.createInstance(Ci.nsIBufferedOutputStream);
let bufferedOutputStream =
Cc["@mozilla.org/network/buffered-output-stream;1"]
.createInstance(Ci.nsIBufferedOutputStream);
bufferedOutputStream.init(outputStream, 1024);
bufferedOutputStream.writeFrom(inputStream, inputStream.available());
bufferedOutputStream.flush();
bufferedOutputStream.close();
inputStream.close();
cacheEntry.setExpirationTime(0);
cacheEntry.markValid();
debug (file.path + ' -> ' + url + ' (' + itemType + ')');
debug (file.path + " -> " + url + " (" + itemType + ")");
applicationCache.markEntry(url, itemType);
cacheEntry.close();
}
@ -206,8 +217,12 @@ function installCache(app) {
return;
}
let cacheDir = makeFile(app.cachePath)
let cacheDir = makeFile(app.cachePath);
cacheDir.append(app.appId);
let resourcesMetadata = cacheDir.clone();
resourcesMetadata.append('resources_metadata.json');
cacheDir.append('cache');
if (!cacheDir.exists())
return;
@ -218,55 +233,72 @@ function installCache(app) {
return;
let principal = Services.scriptSecurityManager.getAppCodebasePrincipal(
app.origin, app.localId, false);
app.origin, app.localId, false);
enableOfflineCacheForApp(principal);
// If the build has been correctly configured, this should not happen!
// If we install the cache anyway, it won't be updateable. If we don't install
// it, the application won't be useable offline.
let metadataLoaded;
if (!resourcesMetadata.exists()) {
// Not debug, since this is something that should be logged always!
dump("OfflineCacheInstaller: App " + app.appId + " does have an app cache" +
" but does not have a resources_metadata.json file!");
metadataLoaded = Promise.resolve({});
} else {
metadataLoaded = new Promise(
(resolve, reject) =>
readFile(resourcesMetadata, principal, content => resolve(JSON.parse(content))));
}
// Get the url for the manifest.
let appcacheURL = app.appcache_path;
metadataLoaded.then(function(metadata) {
enableOfflineCacheForApp(principal);
// The group ID contains application id and 'f' for not being hosted in
// a browser element, but a mozbrowser iframe.
// See netwerk/cache/nsDiskCacheDeviceSQL.cpp: AppendJARIdentifier
let groupID = appcacheURL + '#' + app.localId+ '+f';
let applicationCache = applicationCacheService.createApplicationCache(groupID);
applicationCache.activate();
// Get the url for the manifest.
let appcacheURL = app.appcache_path;
readFile(cacheManifest, principal, function readAppCache(content) {
let entries = parseAppCache(app, cacheManifest.path, content);
// The group ID contains application id and 'f' for not being hosted in
// a browser element, but a mozbrowser iframe.
// See netwerk/cache/nsDiskCacheDeviceSQL.cpp: AppendJARIdentifier
let groupID = appcacheURL + '#' + app.localId+ '+f';
let applicationCache = applicationCacheService.createApplicationCache(groupID);
applicationCache.activate();
entries.urls.forEach(function processCachedFile(url) {
// Get this nsIFile from cache folder for this URL
// We have absolute urls, so remove the origin part to locate the
// files.
let path = url.replace(app.origin.spec, '');
let file = cacheDir.clone();
let paths = path.split('/');
paths.forEach(file.append);
readFile(cacheManifest, principal, function readAppCache(content) {
let entries = parseAppCache(app, cacheManifest.path, content);
if (!file.exists()) {
let msg = 'File ' + file.path + ' exists in the manifest but does ' +
'not points to a real file.';
throw new Error(msg);
}
entries.urls.forEach(function processCachedFile(url) {
// Get this nsIFile from cache folder for this URL
// We have absolute urls, so remove the origin part to locate the
// files.
let path = url.replace(app.origin.spec, '');
let file = cacheDir.clone();
let paths = path.split('/');
paths.forEach(file.append);
let itemType = nsIApplicationCache.ITEM_EXPLICIT;
if (entries.fallbacks.indexOf(url) > -1) {
debug('add fallback: ' + url + '\n');
itemType |= nsIApplicationCache.ITEM_FALLBACK;
}
storeCache(applicationCache, url, file, itemType);
if (!file.exists()) {
let msg = 'File ' + file.path + ' exists in the manifest but does ' +
'not points to a real file.';
throw new Error(msg);
}
let itemType = nsIApplicationCache.ITEM_EXPLICIT;
if (entries.fallbacks.indexOf(url) > -1) {
debug('add fallback: ' + url + '\n');
itemType |= nsIApplicationCache.ITEM_FALLBACK;
}
storeCache(applicationCache, url, file, itemType, metadata[path]);
});
let array = new MutableArray();
entries.namespaces.forEach(function processNamespace([type, spec, data]) {
debug('add namespace: ' + type + ' - ' + spec + ' - ' + data + '\n');
array.appendElement(new Namespace(type, spec, data), false);
});
applicationCache.addNamespaces(array);
storeCache(applicationCache, appcacheURL, cacheManifest,
nsIApplicationCache.ITEM_MANIFEST);
});
let array = new MutableArray();
entries.namespaces.forEach(function processNamespace([type, spec, data]) {
debug('add namespace: ' + type + ' - ' + spec + ' - ' + data + '\n');
array.appendElement(new Namespace(type, spec, data), false);
});
applicationCache.addNamespaces(array);
storeCache(applicationCache, appcacheURL, cacheManifest,
nsIApplicationCache.ITEM_MANIFEST);
});
}