Recently we landed the new HTTP cache for Firefox ("cache2") on mozilla-central. It has been in nightly builds for a while now and seems very likely to stick on the tree and ship in Firefox 32.
Given the positive data we have so far, we're taking another step today to making the new cache official: we have disabled the old APIs for accessing the HTTP cache, so addons will now need to use the cache2 APIs. One important benefit of this is that the cache2 APIs are more efficient and never block on the main thread. The other benefit is that the old cache APIs were no longer pointing at actual data any more (it's in cache2) :)
This means that the following interfaces are now no longer supported:
- nsICache
- nsICacheService
- nsICacheSession
- nsICacheEntryDescriptor
- nsICacheListener
- nsICacheVisitor
(Note: for now nsICacheService can still be obtained: however, calling any of its methods will throw NS_ERROR_NOT_IMPLEMENTED.)
Access to previously stored cache sessions is no longer possible, and the update also causes a one-time deletion of old cache data from users' disks.
Going forward addons must instead use the cache2 equivalents:
- nsICacheStorageService
- nsICacheStorage
- nsICacheEntry
- nsICacheStorageVisitor
- nsICacheEntryDoomCallback
- nsICacheEntryOpenCallback
Below are some examples of how to migrate code from the old to the new cache API. See the new HTTP cache v2 documentation for more details.
The new cache2 implementation gets rid of some of terrible features of the old cache (frequent total data loss, main thread jank during I/O), and significantly improves page load performance. We apologize for the developer inconvenience of needing to upgrade to a new API, but we hope the performance benefits outweight it in the long run.
Example of the cache v1 code (now obsolete) for opening a cache entry:
var cacheService = Components.classes["@mozilla.org/network/cache-service;1"]
.getService(Components.interfaces.nsICacheService);
var session = cacheService.createSession(
"HTTP",
Components.interfaces.nsICache.STORE_ANYWHERE,
Components.interfaces.nsICache.STREAM_BASED
);
session.asyncOpenCacheEntry(
"http://foo.com/bar.html",
Components.interfaces.nsICache.ACCESS_READ_WRITE,
{
onCacheEntryAvailable: function (entry, access, status) {
// And here is the cache v1 entry
}
}
);
Example of the cache v2 code doing the same thing:
let {LoadContextInfo} = Components.utils.import(
"resource://gre/modules/LoadContextInfo.jsm", {}
);
let {PrivateBrowsingUtils} = Components.utils.import(
"resource://gre/modules/PrivateBrowsingUtils.jsm", {}
);
var cacheService = Components.classes["@mozilla.org/netwerk/cache-storage-service;1"]
.getService(Components.interfaces.nsICacheStorageService);
var storage = cacheService.diskCacheStorage(
// Note: make sure |window| is the window you want
LoadContextInfo.fromLoadContext(
PrivateBrowsingUtils.privacyContextFromWindow(window, false)),
false
);
storage.asyncOpenURI(
makeURI("http://foo.com/bar.html"),
"",
Components.interfaces.nsICacheStorage.OPEN_NORMALLY,
{
onCacheEntryCheck: function (entry, appcache) {
return Ci.nsICacheEntryOpenCallback.ENTRY_WANTED;
},
onCacheEntryAvailable: function (entry, isnew, appcache, status) {
// And here is the cache v2 entry
}
}
);
There is a lot of similarities, instead of a cache session we now have a cache storage having a similar meaning - to represent a distinctive space in the whole cache storage - it's just less generic as it was before so that it cannot be misused now. There is now a mandatory argument when getting a storage - nsILoadContextInfo object that distinguishes whether the cache entry belongs to a Private Browsing context, to an Anonymous load or has an App ID.
(Credits to Jason Duell for help with this blog post)