new module to enable editing and deleting of bookmarks
[conkeror/arlinius.git] / modules / load-spec.js
bloba07894e51204aadba66a85699b57a737a2f36d46
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  * element      optional    nsIDOMNode      The DOM node of a load_spec created by load_spec_from_element.
20  *
21  * flags        optional    number          Specifies flags to pass to nsIWebNavigation.loadURI
22  *
23  * cache_key    optional    nsISHEntry      Specifies a key for accessing the target from the cache.
24  *
25  * referrer     optional    nsIURI          Specifies the referrer URI to use to access the target.
26  *
27  * post_data    optional    nsIInputStream  Specifies POST data to use to access the target.
28  *                                          The request headers should be included in this stream.
29  *
30  * request_mime_type
31  *              optional    string          Specifies the MIME type for the request post data.
32  *
33  * raw_post_data
34  *              optional    nsIInputStream  Specifies the POST data to use to access the target.
35  *                                          The request_mime_type property must also be set.
36  *                                          This provides a value for post_data.
37  *
38  * mime_type    optional    string          Specifies the MIME type of the target.
39  *
40  * title        optional    string          Specifies a title/description text associated with the target.
41  *
42  * source_frame optional    nsIDOMWindow    Specifies the frame from which the link to the target was "obtained".
43  *                                          Can provide a default value for referrer if document is not specified.
44  *
45  * filename     optional    string          Specifies a default filename to use to save the target.
46  *
47  * filename_extension
48  *              optional    string          Specifies a default filename extension to use to save the target.
49  *
50  */
52 require("webjump.js");
54 function page_fragment_load_spec (elem) {
55     var uri = makeURLAbsolute(elem.ownerDocument.documentURI,
56                               "#" + (elem.id || elem.name));
57     var title = elem.ownerDocument.title;
58     if (elem.textContent) {
59         if (title) title += ' - ';
60         title += elem.textContent;
61     }
62     var spec = {
63         uri: uri,
64         element: elem,
65         title: title
66     };
67     spec.__proto__ = load_spec.prototype;
68     return spec;
71 function load_spec_from_element (elem) {
72     var spec = {};
73     if (elem instanceof Ci.nsIDOMWindow)
74         spec.document = elem.document;
76     else if (elem instanceof Ci.nsIDOMHTMLFrameElement ||
77              elem instanceof Ci.nsIDOMHTMLIFrameElement)
78         spec.document = elem.contentDocument;
80     else {
81         var url = null;
82         var title = null;
84         if ((elem instanceof Ci.nsIDOMHTMLAnchorElement ||
85              elem instanceof Ci.nsIDOMHTMLAreaElement ||
86              elem instanceof Ci.nsIDOMHTMLLinkElement) &&
87             elem.hasAttribute("href"))
88         {
89             url = elem.href;
90             title = elem.title || elem.textContent;
91         }
92         else if (elem instanceof Ci.nsIDOMHTMLImageElement) {
93             url = elem.src;
94             title = elem.title || elem.alt;
95         }
96         else if (elem.hasAttribute("id") ||
97                  (elem instanceof Ci.nsIDOMHTMLAnchorElement &&
98                   elem.hasAttribute("name"))) {
99             return page_fragment_load_spec(elem);
100         }
101         else {
102             var node = elem;
103             while (node && !(node instanceof Ci.nsIDOMHTMLAnchorElement))
104                 node = node.parentNode;
105             if (node) {
106                 if (node.hasAttribute("href"))
107                     url = node.href;
108                 else
109                     node = null;
110             }
111             if (!node) {
112                 // Try simple XLink
113                 node = elem;
114                 while (node) {
115                     if (node.nodeType == Ci.nsIDOMNode.ELEMENT_NODE) {
116                         url = node.getAttributeNS(XLINK_NS, "href");
117                         break;
118                     }
119                     node = node.parentNode;
120                 }
121                 if (url)
122                     url = makeURLAbsolute(node.baseURI, url);
123                 title = node.title || node.textContent;
124             }
125         }
126         if (url && url.length > 0) {
127             if (title && title.length == 0)
128                 title = null;
129             spec.uri = url;
130             spec.source_frame = elem.ownerDocument.defaultView;
131             spec.title = title;
132         }
133         spec.element = elem;
134     }
135     return spec;
138 function load_spec (x) {
139     var spec;
140     if (typeof(x) == "string")
141         x = get_url_or_webjump(x);
142     if (typeof(x) == "string")
143         spec = { uri: x };
144     else if ((x instanceof Ci.nsIDOMNode) ||
145              (x instanceof Ci.nsIDOMWindow))
146     {
147         spec = load_spec_from_element(x);
148     } else if (typeof(x) == "object") {
149         spec = x;
150     }
151     if (! load_spec_uri_string(spec))
152         throw new Error("Invalid load-spec");
153     spec.__proto__ = load_spec.prototype;
154     return spec;
156 load_spec.prototype = {
157     constructor: load_spec,
158     toString: function () "#<load_spec>",
159     cache_key: null,
160     document: null,
161     element: null,
162     filename: null,
163     filename_extension: null,
164     forced_charset: null,
165     load_spec_flags: null,
166     mime_type: null,
167     post_data: null,
168     raw_post_data: null,
169     referrer: null,
170     request_mime_type: null,
171     source_frame: null,
172     title: null,
173     uri: null
176 function load_spec_document (x) {
177     return x.document;
180 function load_spec_element (x) {
181     return x.element;
184 function load_spec_title (x) {
185     if (x.title)
186         return x.title;
187     if (x.document)
188         return x.document.title;
189     return null;
192 function load_spec_mime_type (x) {
193     if (x.mime_type)
194         return x.mime_type;
195     if (x.document)
196         return x.document.contentType || "application/octet-stream";
197     return mime_type_from_uri(load_spec_uri(x));
200 function load_spec_filename (x) {
201     return x.filename;
204 function load_spec_filename_extension (x) {
205     return x.filename_extension;
208 function get_web_navigation_for_frame (frame) {
209     var ifr = frame.QueryInterface(Ci.nsIInterfaceRequestor);
210     return ifr.getInterface(Ci.nsIWebNavigation);
213 function get_SHEntry_for_document (doc) {
214     try {
215         var frame = doc.defaultView;
216         var webNav = get_web_navigation_for_frame(frame);
217         var pageLoader = webNav.QueryInterface(Ci.nsIWebPageDescriptor);
218         var desc = pageLoader.currentDescriptor.QueryInterface(Ci.nsISHEntry);
219         return desc;
220     } catch (e) { return null; }
223 function load_spec_set_properties_from_sh_entry (x) {
224     var sh_entry = get_SHEntry_for_document(x.document);
225     if (sh_entry != null) {
226         x.cache_key = sh_entry;
227         x.referrer = sh_entry.referrerURI;
228         x.post_data = sh_entry.postData;
229     }
232 function load_spec_referrer (x) {
233     if (x.referrer)
234         return x.referrer;
235     if (x.document) {
236         load_spec_set_properties_from_sh_entry(x);
237         return x.referrer;
238     }
239     if (x.source_frame) {
240         x.referrer = x.source_frame.document.documentURIObject;
241         return x.referrer;
242     }
243     return null;
246 function load_spec_post_data (x) {
247     if (x.post_data)
248         return x.post_data;
249     if (x.raw_post_data) {
250         let y = x.raw_post_data;
251         if (typeof y == "string")
252             y = string_input_stream(y);
253         x.post_data = mime_input_stream(y, [["Content-Type", x.request_mime_type]]);
254         return x.post_data;
255     }
256     if (x.document) {
257         load_spec_set_properties_from_sh_entry(x);
258         return x.post_data;
259     }
260     return null;
263 function load_spec_raw_post_data (x) {
264     return x.raw_post_data;
267 function load_spec_request_mime_type (x) {
268     return x.request_mime_type;
271 function load_spec_cache_key (x) {
272     if (x.cache_key)
273         return x.cache_key;
274     if (x.document) {
275         load_spec_set_properties_from_sh_entry(x);
276         return x.cache_key;
277     }
278     return null;
281 function load_spec_source_frame (x) {
282     if (x.source_frame)
283         return x.source_frame;
284     if (x.document)
285         return x.document.defaultView;
286     return null;
289 function load_spec_uri_string (x) {
290     if (x.uri)
291         return x.uri;
292     if (x.document && x.document.defaultView)
293         return x.document.defaultView.location.href;
294     if (x.document)
295         return x.document.documentURI;
296     return null;
299 function load_spec_uri (x) {
300     if (x.document && x.document.defaultView)
301         return make_uri(x.document.defaultView.location.href);
302     if (x.document)
303         return x.document.documentURIObject;
304     return make_uri(load_spec_uri_string(x));
307 function load_spec_flags (x) {
308     return x.load_spec_flags;
311 function load_spec_mime_info (x) {
312     var type = load_spec_mime_type(x);
313     return mime_info_from_mime_type(type);
316 function load_spec_default_shell_command (x) {
317     var mime_type = load_spec_mime_type(x);
318     return external_content_handlers.get(mime_type);
321 function load_spec_forced_charset (x) {
322     return x.forced_charset;
325 define_variable('forced_charset_list', null,
326     "Alist mapping url-regexps to forced charsets.  The first match "+
327     "will be used.");
329 /* Target can be either a content_buffer or an nsIWebNavigation */
330 function apply_load_spec (target, spec) {
331     if (! (spec instanceof load_spec))
332         spec = load_spec(spec);
333     var uri = load_spec_uri_string(spec);
334     var flags = load_spec_flags(spec);
335     var referrer = load_spec_referrer(spec);
336     var post_data = load_spec_post_data(spec);
337     var forced_charset = load_spec_forced_charset(spec);
339     if (! forced_charset && forced_charset_list)
340         forced_charset = predicate_alist_match(forced_charset_list, uri);
342     if (forced_charset) {
343         try {
344             var atomservice = Cc['@mozilla.org/atom-service;1']
345                 .getService(Ci.nsIAtomService);
346             target.web_navigation.documentCharsetInfo.forcedCharset =
347                 atomservice.getAtom(forced_charset);
348         } catch (e) {}
349     }
351     if (flags == null)
352         flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
354     if (target instanceof content_buffer) {
355         try {
356             target.web_navigation.loadURI(uri, flags, referrer, post_data, null /* headers */);
357             target._display_uri = uri;
358             buffer_description_change_hook.run(target);
359         } catch (e) {
360             /* Ignore error for now */
361         }
362     } else {
363         try {
364             target.loadURI(uri, flags, referrer, post_data, null /* headers */);
365         } catch (e) {
366             /* Ignore error for now */
367         }
368     }
371 provide("load-spec");