cache: switch to an asynchronous interface for opening and clearing cache entries...
authorJeremy Maitin-Shepard <jeremy@jeremyms.com>
Tue, 5 Feb 2013 05:40:43 +0000 (4 21:40 -0800)
committerJeremy Maitin-Shepard <jeremy@jeremyms.com>
Tue, 5 Feb 2013 05:40:43 +0000 (4 21:40 -0800)
This fixes mime-type-override.

modules/cache.js
modules/commands.js
modules/content-handler.js
modules/mime-type-override.js

index 816760c..c1ae926 100644 (file)
@@ -17,35 +17,65 @@ const CACHE_SESSION_HTTP         = "HTTP";
 const CACHE_SESSION_HTTP_OFFLINE = "HTTP-offline";
 const CACHE_SESSION_FTP          = "FTP";
 
-// Returns null if uri is not cached.
-function cache_entry_open (cache_type, cache_session, uri) {
+function cache_error (code) {
+    let xpcom_exc = Components.Exception("", code);
+    let e = new Error("cache error: " + xpcom_exc.name);
+    e.result = code;
+    e.__proto__ = cache_error.prototype;
+    return e;
+}
+cache_error.prototype.__proto__ = Error.prototype;
+
+function cache_entry_open(cache_session, uri) {
     if (uri instanceof Ci.nsIURI)
         uri = uri.spec;
+
     let session = cache_service.createSession(cache_session, 0, true);
     session.doomEntriesIfExpired = false;
-    // Remove the ref component of the URL
+
+    let cc = yield CONTINUATION;
+
+    cache_listener = {
+        onCacheEntryAvailable: function onCacheEntryAvailable(descriptor, accessGranted, status) {
+            if (status != Cr.NS_OK)
+                cc.throw(cache_error(status));
+            else
+                cc(descriptor);
+        }
+    };
+
     let cache_key = uri.replace(/#.*$/, "");
-    try {
-        return session.openCacheEntry(cache_key,
-                                      Ci.nsICache.ACCESS_READ,
-                                      false);
-    }
-    catch (ex) {
-        if (ex.name == "NS_ERROR_CACHE_KEY_NOT_FOUND" ||
-            ex.name == "NS_ERROR_CACHE_WAIT_FOR_VALIDATION")
-            return null;
-        throw ex;
-    }
+    session.asyncOpenCacheEntry(cache_key, Ci.nsICache.ACCESS_READ, cache_listener);
+    yield co_return(yield SUSPEND);
 }
 
-// Returns false if uri is not cached, else true.
-function cache_entry_clear (cache_type, cache_session, uri) {
-    let entry = cache_entry_open(cache_type, cache_session, uri);
-    if (entry == null)
-        return false;
-    entry.doom();
-    entry.close();
-    return true;
+function cache_entry_clear(cache_session, uri) {
+    if (uri instanceof Ci.nsIURI)
+        uri = uri.spec;
+
+    let session = cache_service.createSession(cache_session, 0, true);
+    session.doomEntriesIfExpired = false;
+
+    let cc = yield CONTINUATION;
+
+    cache_listener = {
+        onCacheEntryDoomed: function onCacheEntryDoomed(status) {
+            switch (status) {
+            case Cr.NS_OK:
+                cc(true);
+                break;
+            case Cr.NS_ERROR_NOT_AVAILABLE:
+                cc(false);
+                break;
+            default:
+                cc.throw(cache_error(status));
+            }
+        }
+    };
+
+    let cache_key = uri.replace(/#.*$/, "");
+    session.doomEntry(cache_key, cache_listener);
+    yield co_return(yield SUSPEND);
 }
 
 function cache_clear (cache_type) {
index dd42214..c2abc32 100644 (file)
@@ -715,7 +715,7 @@ function view_as_mime_type (I, target) {
             $prompt = "View internally as",
             $initial_value = suggested_type,
             $select);
-        override_mime_type_for_next_load(load_spec_uri(spec), mime_type);
+        yield override_mime_type_for_next_load(load_spec_uri(spec), mime_type);
         browser_object_follow(I.buffer, target, spec);
     } finally {
         panel.destroy();
index e59b55d..af4bb5d 100644 (file)
@@ -147,7 +147,7 @@ function content_handler_view_internally (ctx) {
         $initial_value = suggested_type,
         $select);
     ctx.abort(); // abort before reloading
-    override_mime_type_for_next_load(ctx.launcher.source, mime_type);
+    yield override_mime_type_for_next_load(ctx.launcher.source, mime_type);
     ctx.frame.location = ctx.launcher.source.spec; // reload
 }
 
dissimilarity index 66%
index e131fc7..4bd9a30 100644 (file)
-/**
- * (C) Copyright 2008 Jeremy Maitin-Shepard
- *
- * Portions of this file are derived from the "Open in Browser" extension,
- * (C) Copyright 2006 Sylvain Pasche.
- *
- * Use, modification, and distribution are subject to the terms specified in the
- * COPYING file.
- **/
-
-/**
- * This module was inspired by the "Open in Browser" extension by Sylvain
- * Pasche, available at <http://www.spasche.net/openinbrowser/>.
- *
- * This module implements (in a somewhat hacky way) overriding of the
- * server-specified mime type for specified URLs. It works by registering an
- * observer for the "http-on-examine-response" and
- * "http-on-examine-merged-response" topics and changes the response MIME type
- * of the nsIHTTPChannel object passed as the subject, as well as clearing any
- * "Content-disposition" header.
- *
- * Unfortunately, due to the design, this hack does not work for FTP.
- *
- **/
-
-let EXAMINE_TOPIC = "http-on-examine-response";
-let EXAMINE_MERGED_TOPIC = "http-on-examine-merged-response";
-
-let table = {};
-
-let timeout = 10000; // 10000 milliseconds = 10 seconds
-
-let table_size = 0;
-
-// uri must be an instance of nsIURI
-function can_override_mime_type_for_uri(uri) {
-    return uri.schemeIs("http") || uri.schemeIs("https");
-}
-
-let clear_override = function(uri_string) {
-    delete table[uri_string];
-    table_size--;
-
-    if (table_size == 0) {
-        observer_service.removeObserver(observer, EXAMINE_TOPIC);
-        observer_service.removeObserver(observer, EXAMINE_MERGED_TOPIC);
-    }
-}
-
-let observer = {
-    observe: function (subject, topic, data) {
-        if (topic != EXAMINE_TOPIC && topic != EXAMINE_MERGED_TOPIC)
-            return;
-
-        subject.QueryInterface(Ci.nsIHttpChannel);
-
-        var uri_string = subject.originalURI.spec;
-        var obj = table[uri_string];
-        if (!obj)
-            return;
-
-        obj.timer.cancel();
-
-        subject.contentType = obj.mime_type;
-
-        // drop content-disposition header
-        subject.setResponseHeader("Content-Disposition", "", false);
-
-        clear_override(uri_string);
-    }
-};
-
-
-
-// uri must be an instance of nsIURI and can_override_mime_type_for_uri must
-// return true for the passed uri.
-
-// mime_type must be a string
-function override_mime_type_for_next_load(uri, mime_type) {
-    cache_entry_clear(CACHE_ALL, CACHE_SESSION_HTTP, uri);
-
-    var obj = table[uri.spec];
-    if (obj)
-        obj.timer.cancel();
-    else
-        table_size++;
-
-    obj = { mime_type: mime_type };
-
-    obj.timer = call_after_timeout(function () {
-                                       clear_override(uri.spec);
-                                   }, timeout);
-
-    if (table_size == 1) {
-        observer_service.addObserver(observer, EXAMINE_TOPIC, false);
-        observer_service.addObserver(observer, EXAMINE_MERGED_TOPIC, false);
-    }
-    table[uri.spec] = obj;
-}
-
-provide("mime-type-override");
+/**
+ * (C) Copyright 2008 Jeremy Maitin-Shepard
+ *
+ * Portions of this file are derived from the "Open in Browser" extension,
+ * (C) Copyright 2006 Sylvain Pasche.
+ *
+ * Use, modification, and distribution are subject to the terms specified in the
+ * COPYING file.
+ **/
+
+/**
+ * This module was inspired by the "Open in Browser" extension by Sylvain
+ * Pasche, available at <http://www.spasche.net/openinbrowser/>.
+ *
+ * This module implements (in a somewhat hacky way) overriding of the
+ * server-specified mime type for specified URLs. It works by registering an
+ * observer for the "http-on-examine-response" and
+ * "http-on-examine-merged-response" topics and changes the response MIME type
+ * of the nsIHTTPChannel object passed as the subject, as well as clearing any
+ * "Content-disposition" header.
+ *
+ * Unfortunately, due to the design, this hack does not work for FTP.
+ *
+ **/
+{ // new scope
+
+    let EXAMINE_TOPIC = "http-on-examine-response";
+    let EXAMINE_MERGED_TOPIC = "http-on-examine-merged-response";
+
+    let table = {};
+
+    let timeout = 10000; // 10000 milliseconds = 10 seconds
+
+    let table_size = 0;
+
+    // uri must be an instance of nsIURI
+    function can_override_mime_type_for_uri(uri) {
+        return uri.schemeIs("http") || uri.schemeIs("https");
+    }
+
+    let clear_override = function(uri_string) {
+        delete table[uri_string];
+        table_size--;
+
+        if (table_size == 0) {
+            observer_service.removeObserver(observer, EXAMINE_TOPIC);
+            observer_service.removeObserver(observer, EXAMINE_MERGED_TOPIC);
+        }
+    }
+
+    let observer = {
+        observe: function (subject, topic, data) {
+            if (topic != EXAMINE_TOPIC && topic != EXAMINE_MERGED_TOPIC)
+                return;
+
+            subject.QueryInterface(Ci.nsIHttpChannel);
+
+            var uri_string = subject.originalURI.spec;
+            var obj = table[uri_string];
+            if (!obj)
+                return;
+
+            obj.timer.cancel();
+
+            subject.contentType = obj.mime_type;
+
+            // drop content-disposition header
+            subject.setResponseHeader("Content-Disposition", "", false);
+
+            clear_override(uri_string);
+        }
+    };
+
+
+
+    // uri must be an instance of nsIURI and can_override_mime_type_for_uri must
+    // return true for the passed uri.
+
+    // mime_type must be a string
+    function override_mime_type_for_next_load(uri, mime_type) {
+        yield cache_entry_clear(CACHE_SESSION_HTTP, uri);
+
+        var obj = table[uri.spec];
+        if (obj)
+            obj.timer.cancel();
+        else
+            table_size++;
+
+        obj = { mime_type: mime_type };
+
+        obj.timer = call_after_timeout(function () {
+            clear_override(uri.spec);
+        }, timeout);
+
+        if (table_size == 1) {
+            observer_service.addObserver(observer, EXAMINE_TOPIC, false);
+            observer_service.addObserver(observer, EXAMINE_MERGED_TOPIC, false);
+        }
+        table[uri.spec] = obj;
+    }
+}
+provide("mime-type-override");