content-buffer: Make URL loading more robust to errors from invalid URLs
[conkeror.git] / modules / load-spec.js
blob70621c7f58343bae5961247075d16a3c5d1d65ff
1 /**
2  * (C) Copyright 2007-2008 Jeremy Maitin-Shepard
3  *
4  * Use, modification, and distribution are subject to the terms specified in the
5  * COPYING file.
6 **/
8 /**
9  * A load_spec has the following properties:
10  *
11  * Name:        Required?   Type:           Description:
12  * -----        ---------   -----           ------------
13  * uri          required    string          Specifies the URI of the target.
14  *
15  * document     optional    nsIDOMDocument  Specifies a document corresponding to the target.
16  *                                          Can also provide a default value for the mime_type property,
17  *                                          the title property, and the source_frame property.
18  *
19  * flags        optional    number          Specifies flags to pass to nsIWebNavigation.loadURI
20  *
21  * cache_key    optional    nsISHEntry      Specifies a key for accessing the target from the cache.
22  *
23  * referrer     optional    nsIURI          Specifies the referrer URI to use to access the target.
24  *
25  * post_data    optional    nsIInputStream  Specifies POST data to use to access the target.
26  *                                          The request headers should be included in this stream.
27  *
28  * request_mime_type
29  *              optional    string          Specifies the MIME type for the request post data.
30  *
31  * raw_post_data
32  *              optional    nsIInputStream  Specifies the POST data to use to access the target.
33  *                                          The request_mime_type property must also be set.
34  *                                          This provides a value for post_data.
35  *
36  * mime_type    optional    string          Specifies the MIME type of the target.
37  *
38  * title        optional    string          Specifies a title/description text associated with the target.
39  *
40  * source_frame optional    nsIDOMWindow    Specifies the frame from which the link to the target was "obtained".
41  *                                          Can provide a default value for referrer if document is not specified.
42  *
43  * filename     optional    string          Specifies a default filename to use to save the target.
44  *
45  * filename_extension
46  *              optional    string          Specifies a default filename extension to use to save the target.
47  *
48  * suggest_filename_from_uri
49  *              optional    boolean         Specifies whether to attempt to generate a filename from the URI.
50  *                                          Defaults to true.
51  */
53 require("webjump.js");
55 function load_spec(x) { x.__proto__ = load_spec.prototype; return x; }
57 function is_load_spec(x) {
58     return (typeof(x) == "string") || (x instanceof load_spec);
61 function load_spec_document(x) {
62     return x.document;
65 function load_spec_title(x) {
66     if (x.title)
67         return x.title;
68     if (x.document)
69         return x.document.title;
70     return null;
73 function load_spec_mime_type(x) {
74     if (typeof(x) == "object") {
75         if (x.mime_type)
76             return x.mime_type;
77         if (x.document)
78             return x.document.contentType || "application/octet-stream";
79     }
80     return mime_type_from_uri(load_spec_uri(x));
83 function load_spec_filename(x) {
84     return x.filename;
87 function load_spec_filename_extension(x) {
88     return x.filename_extension;
91 function get_web_navigation_for_frame(frame) {
92     var ifr = frame.QueryInterface(Ci.nsIInterfaceRequestor);
93     return ifr.getInterface(Ci.nsIWebNavigation);
96 function get_SHEntry_for_document(doc)
98     try
99     {
100         var frame = doc.defaultView;
101         var webNav = get_web_navigation_for_frame(frame);
102         var pageLoader = webNav.QueryInterface(Ci.nsIWebPageDescriptor);
103         var desc = pageLoader.currentDescriptor.QueryInterface(Ci.nsISHEntry);
104         return desc;
105     } catch (e) { return null; }
108 function load_spec_set_properties_from_sh_entry(x) {
109     var sh_entry = get_SHEntry_for_document(x.document);
110     if (sh_entry != null) {
111         x.cache_key = sh_entry;
112         x.referrer = sh_entry.referrerURI;
113         x.post_data = sh_entry.postData;
114     }
117 function load_spec_referrer(x) {
118     if (x.referrer)
119         return x.referrer;
120     if (x.document) {
121         load_spec_set_properties_from_sh_entry(x);
122         return x.referrer;
123     }
124     if (x.source_frame) {
125         x.referrer = x.source_frame.document.documentURIObject;
126         return x.referrer;
127     }
128     return null;
131 function load_spec_post_data(x) {
132     if (x.post_data)
133         return x.post_data;
134     if (x.raw_post_data) {
135         let y = x.raw_post_data;
136         if (typeof(y) == "string")
137             y = string_input_stream(y);
138         x.post_data = mime_input_stream(y, [["Content-Type", x.request_mime_type]]);
139         return x.post_data;
140     }
141     if (x.document) {
142         load_spec_set_properties_from_sh_entry(x);
143         return x.post_data;
144     }
145     return null;
148 function load_spec_raw_post_data(x) {
149     return x.raw_post_data;
152 function load_spec_request_mime_type(x) {
153     return x.request_mime_type;
156 function load_spec_cache_key(x) {
157     if (x.cache_key)
158         return x.cache_key;
159     if (x.document) {
160         load_spec_set_properties_from_sh_entry(x);
161         return x.cache_key;
162     }
163     return null;
166 function load_spec_source_frame(x) {
167     if (x.source_frame)
168         return x.source_frame;
169     if (x.document)
170         return x.document.defaultView;
171     return null;
174 function load_spec_uri_string(x) {
175     if (typeof(x) == "string")
176         x = get_url_or_webjump(x);
177     if (typeof(x) == "string")
178        return x;
179     if (x.uri)
180         return x.uri;
181     if (x.document && x.document.defaultView)
182         return x.document.defaultView.location.href;
183     if (x.document)
184         return x.document.documentURI;
185     return null;
188 function load_spec_uri(x) {
189     if (x.document && x.document.defaultView)
190         return make_uri(x.document.defaultView.location.href);
191     if (x.document)
192         return x.document.documentURIObject;
193     return make_uri(load_spec_uri_string(x));
196 function load_spec_flags(x) {
197     return x.load_spec_flags;
200 function load_spec_mime_info(x) {
201     var type = load_spec_mime_type(x);
202     return mime_info_from_mime_type(type);
205 function load_spec_default_shell_command(x) {
206     var mime_type = load_spec_mime_type(x);
207     return get_mime_type_external_handler(mime_type);
210 /* Target can be either a content_buffer or an nsIWebNavigation */
211 function apply_load_spec(target, spec) {
212     var uri = load_spec_uri_string(spec);
213     var flags = load_spec_flags(spec);
214     var referrer = load_spec_referrer(spec);
215     var post_data = load_spec_post_data(spec);
217     if (flags == null)
218         flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
220     try {
221         make_uri(uri); // Check that the URI is valid
222     } catch (e) {
223         throw interactive_error("Invalid URL: " + uri);
224     }
226     if (target instanceof content_buffer) {
227         try {
228             target.web_navigation.loadURI(uri, flags, referrer, post_data, null /* headers */);
229             target._display_URI = uri;
230             buffer_description_change_hook.run(target);
231         } catch (e) {
232             /* Ignore error for now */
233         }
234     } else
235         target.loadURI(uri, flags, referrer, post_data, null /* headers */);