kludge issue 513
[conkeror.git] / modules / load-spec.js
bloba07894e51204aadba66a85699b57a737a2f36d46
1 /**
2 * (C) Copyright 2007-2008 Jeremy Maitin-Shepard
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:
11 * Name: Required? Type: Description:
12 * ----- --------- ----- ------------
13 * uri required string Specifies the URI of the target.
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.
19 * element optional nsIDOMNode The DOM node of a load_spec created by load_spec_from_element.
21 * flags optional number Specifies flags to pass to nsIWebNavigation.loadURI
23 * cache_key optional nsISHEntry Specifies a key for accessing the target from the cache.
25 * referrer optional nsIURI Specifies the referrer URI to use to access the target.
27 * post_data optional nsIInputStream Specifies POST data to use to access the target.
28 * The request headers should be included in this stream.
30 * request_mime_type
31 * optional string Specifies the MIME type for the request post data.
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.
38 * mime_type optional string Specifies the MIME type of the target.
40 * title optional string Specifies a title/description text associated with the target.
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.
45 * filename optional string Specifies a default filename to use to save the target.
47 * filename_extension
48 * optional string Specifies a default filename extension to use to save the target.
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;
62 var spec = {
63 uri: uri,
64 element: elem,
65 title: title
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"))
89 url = elem.href;
90 title = elem.title || elem.textContent;
92 else if (elem instanceof Ci.nsIDOMHTMLImageElement) {
93 url = elem.src;
94 title = elem.title || elem.alt;
96 else if (elem.hasAttribute("id") ||
97 (elem instanceof Ci.nsIDOMHTMLAnchorElement &&
98 elem.hasAttribute("name"))) {
99 return page_fragment_load_spec(elem);
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;
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;
119 node = node.parentNode;
121 if (url)
122 url = makeURLAbsolute(node.baseURI, url);
123 title = node.title || node.textContent;
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;
133 spec.element = elem;
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))
147 spec = load_spec_from_element(x);
148 } else if (typeof(x) == "object") {
149 spec = x;
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;
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;
239 if (x.source_frame) {
240 x.referrer = x.source_frame.document.documentURIObject;
241 return x.referrer;
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;
256 if (x.document) {
257 load_spec_set_properties_from_sh_entry(x);
258 return x.post_data;
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;
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) {}
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 */
362 } else {
363 try {
364 target.loadURI(uri, flags, referrer, post_data, null /* headers */);
365 } catch (e) {
366 /* Ignore error for now */
371 provide("load-spec");