Firefox HTTP cache v1 API disabled

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)

6 thoughts on “Firefox HTTP cache v1 API disabled

  1. Are we working with AMO to notify cache1 consumers?

    General announcements are nice, but hearing, “Hey Frank, we found evidence that you’re using this…” is probably more effective.

    1. Yes, the cache v1 API disable bug has been marked as ‘addon-compat’ and appropriate people are taking care. According directly targeting add-on authors, we have tools for checking the add-on sources. There are few extension using the old APIs, I will do my best to let the authors be contacted.

      Edit: we have examined the sources and there seems to be no currently maintained extension that would only be using the old cache APIs with a need to migrate. There is not “Frank” to tell to.

  2. Congratulations! The new cache is enabled in the current release, and I must say it makes the browser a joy to use on most devices. It was definitely worth the wait. My thanks go to you and Mr. Novotný, and everyone else at Mozilla for NOT giving up on this.

  3. I am trying to make old code to work with Firefox 32. I am not sure how should force expire cache using cache2 APIs?

    Here is the cache V1 code I am trying to convert.

    var cacheService = Cc[“@mozilla.org/network/cache-service;1”].getService(Ci.nsICacheService);

    // force expire the invoices cache
    var getInvoiceSession = cacheService.createSession(“HTTP”, 0, false);
    getInvoiceSession.asyncOpenCacheEntry(main_url +”api/v1/invoices/?paid=false&format=json”, 2, cacheListener);

    1. Just to make your inquiry clear, the ‘2’ at asyncOpenCacheEntry means access only for writing – nsICache.ACCESS_WRITE. Please next time use a flag defined in an interface.

      The new cache equivalent is following:

      var storage = cacheService.diskCacheStorage(…);
      storage.asyncOpenURI(makeURI(main_url +”api/v1/invoices/?paid=false&format=json”), “”, Components.interfaces.nsICacheStorage.OPEN_TRUNCATE, cacheListener);

      For other flags, please see nsICacheStorage interface or the documentation at https://developer.mozilla.org/en-US/docs/HTTP_Cache

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.