mime-type-override.js: override how an HTTP request is handled
[conkeror.git] / modules / mime-type-override.js
blob49e4b8f0dfb29d9be0e6704cc8d1fc78fc63e3e7
1 /**
2  * (C) Copyright 2008 Jeremy Maitin-Shepard
3  *
4  * Portions of this file are derived from the "Open in Browser" extension,
5  * (C) Copyright 2006 Sylvain Pasche.
6  *
7  * Use, modification, and distribution are subject to the terms specified in the
8  * COPYING file.
9  **/
11 /**
12  * This module was inspired by the "Open in Browser" extension by Sylvain
13  * Pasche, available at http://www.spasche.net/mozilla/.
14  *
15  * This module implements (in a somewhat hacky way) overriding of the
16  * server-specified mime type for specified URLs. It works by registering an
17  * observer for the "http-on-examine-response" and
18  * "http-on-examine-merged-response" topics and changes the response MIME type
19  * of the nsIHTTPChannel object passed as the subject, as well as clearing any
20  * "Content-disposition" header.
21  *
22  * Unfortunately, due to the design, this hack does not work for FTP.
23  *
24  **/
26 let EXAMINE_TOPIC = "http-on-examine-response";
27 let EXAMINE_MERGED_TOPIC = "http-on-examine-merged-response";
29 let table = new string_hashmap();
31 let timeout = 10000; // 10000 milliseconds = 10 seconds
33 let table_size = 0;
35 // uri must be an instance of nsIURI
36 function can_override_mime_type_for_uri(uri) {
37     return uri.schemeIs("http") || uri.schemeIs("https");
40 const cache_service = Cc["@mozilla.org/network/cache-service;1"].getService(Ci.nsICacheService);
42 function clear_http_cache_entry(uri_string) {
43     var http_cache_session = cache_service.createSession("HTTP", 0, true);
44     http_cache_session.doomEntriesIfExpired = false;
45     try {
46         // Remove the ref component of the URL
47         var cache_key = uri_string.replace(/#.*$/, "");
48         var entry = http_cache_session.openCacheEntry(cacheKey, Ci.nsICache.ACCESS_READ, false);
49         entry.doom();
50         entry.close();
51     } catch (e) { }
54 let clear_override = function(uri_string) {
55     table.remove(uri_string);
56     table_size--;
58     if (table_size == 0) {
59         observer_service.removeObserver(observer, EXAMINE_TOPIC);
60         observer_service.removeObserver(observer, EXAMINE_MERGED_TOPIC);
61     }
64 let observer = {
65     observe: function (subject, topic, data) {
66         if (topic != EXAMINE_TOPIC && topic != EXAMINE_MERGED_TOPIC)
67             return;
69         subject.QueryInterface(Ci.nsIHttpChannel);
71         var uri_string = subject.originalURI.spec;
72         var obj = table.get(uri_string);
73         if (!obj)
74             return;
76         obj.timer.cancel();
78         subject.contentType = obj.mime_type;
80         // drop content-disposition header
81         subject.setResponseHeader("Content-Disposition", "", false);
83         clear_override(uri_string);
84     }
89 // uri must be an instance of nsIURI and can_override_mime_type_for_uri must
90 // return true for the passed uri.
92 // mime_type must be a string
93 function override_mime_type_for_next_load(uri, mime_type) {
95     clear_http_cache_entry(uri.spec);
97     var obj = table.get(uri.spec);
98     if (obj)
99         obj.timer.cancel();
100     else
101         table_size++;
103     obj = { mime_type: mime_type };
105     obj.timer = call_after_timeout(function () {
106                                        clear_override(uri.spec);
107                                    }, timeout);
109     if (table_size == 1) {
110         observer_service.addObserver(observer, EXAMINE_TOPIC, false);
111         observer_service.addObserver(observer, EXAMINE_MERGED_TOPIC, false);
112     }
113     table.put(uri.spec, obj);