utils.js: remove not-working clear_default_pref
[conkeror.git] / modules / utils.js
blob580fe1a60099360d8a075d068a6868412f852823
1 /***** BEGIN LICENSE BLOCK *****
2 Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 The contents of this file are subject to the Mozilla Public License Version
5 1.1 (the "License"); you may not use this file except in compliance with
6 the License. You may obtain a copy of the License at
7 http://www.mozilla.org/MPL/
9 Software distributed under the License is distributed on an "AS IS" basis,
10 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 for the specific language governing rights and limitations under the
12 License.
14 The Initial Developer of the Original Code is Shawn Betts.
15 Portions created by the Initial Developer are Copyright (C) 2004,2005
16 by the Initial Developer. All Rights Reserved.
18 Alternatively, the contents of this file may be used under the terms of
19 either the GNU General Public License Version 2 or later (the "GPL"), or
20 the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
21 in which case the provisions of the GPL or the LGPL are applicable instead
22 of those above. If you wish to allow use of your version of this file only
23 under the terms of either the GPL or the LGPL, and not to allow others to
24 use your version of this file under the terms of the MPL, indicate your
25 decision by deleting the provisions above and replace them with the notice
26 and other provisions required by the GPL or the LGPL. If you do not delete
27 the provisions above, a recipient may use your version of this file under
28 the terms of any one of the MPL, the GPL or the LGPL.
29 ***** END LICENSE BLOCK *****/
32  * Utility functions for application scope.
33  *
34  */
37 function string_hashset() {
40 string_hashset.prototype = {
41     constructor : string_hashset,
43     add : function(s) {
44         this["-" + s] = true;
45     },
46     
47     contains : function(s) {
48         return (("-" + s) in this);
49     },
51     remove : function (s) {
52         delete this["-" + s];
53     },
55     for_each : function (f) {
56         for (var i in this) {
57             if (i[0] == "-")
58                 f(i.slice(1));
59         }
60     }
63 function string_hashmap() {
66 string_hashmap.prototype = {
67     constructor : string_hashmap,
69     put : function(s,value) {
70         this["-" + s] = value;
71     },
72     
73     contains : function(s) {
74         return (("-" + s) in this);
75     },
77     get : function(s, default_value) {
78         if (this.contains(s))
79             return this["-" + s];
80         return default_value;
81     },
83     get_put_default : function(s, default_value) {
84         if (this.contains(s))
85             return this["-" + s];
86         return (this["-" + s] = default_value);
87     },
89     remove : function (s) {
90         delete this["-" + s];
91     },
93     for_each : function (f) {
94         for (var i in this) {
95             if (i[0] == "-")
96                 f(i.slice(1), this[i]);
97         }
98     },
100     for_each_value : function (f) {
101         for (var i in this) {
102             if (i[0] == "-")
103                 f(this[i]);
104         }
105     }
108 /// Window title formatting
111  * Default tile formatter.  The page url is ignored.  If there is a
112  * page_title, returns: "Page title - Conkeror".  Otherwise, it
113  * returns just: "Conkeror".
114  */
115 function default_title_formatter (window)
117     var page_title = window.buffers.current.title;
119     if (page_title && page_title.length > 0)
120         return page_title + " - Conkeror";
121     else
122         return "Conkeror";
125 var title_format_fn = null;
127 function set_window_title (window)
129     window.document.title = title_format_fn(window);
132 function init_window_title ()
134     title_format_fn = default_title_formatter;
136     add_hook("window_initialize_late_hook", set_window_title);
137     add_hook("current_content_buffer_location_change_hook",
138              function (buffer) {
139                  set_window_title(buffer.window);
140              });
141     add_hook("select_buffer_hook", function (buffer) { set_window_title(buffer.window); }, true);
142     add_hook("current_buffer_title_change_hook",
143              function (buffer) {
144                  set_window_title(buffer.window);
145              });
148 init_window_title ();
153 // Put the string on the clipboard
154 function writeToClipboard(str)
156     const gClipboardHelper = Components.classes["@mozilla.org/widget/clipboardhelper;1"]
157         .getService(Components.interfaces.nsIClipboardHelper);
158     gClipboardHelper.copyString(str);
162 function makeURLAbsolute (base, url)
164     // Construct nsIURL.
165     var ioService = Components.classes["@mozilla.org/network/io-service;1"]
166         .getService(Components.interfaces.nsIIOService);
167     var baseURI  = ioService.newURI(base, null, null);
169     return ioService.newURI (baseURI.resolve (url), null, null).spec;
173 function get_link_location (element)
175     if (element && element.getAttribute("href")) {
176         var loc = element.getAttribute("href");
177         return makeURLAbsolute(element.baseURI, loc);
178     }
179     return null;
183 function makeURL(aURL)
185     var ioService = Cc["@mozilla.org/network/io-service;1"]
186         .getService(Ci.nsIIOService);
187     return ioService.newURI(aURL, null, null);
190 function make_uri(uri) {
191     if (uri instanceof Ci.nsIURI)
192         return uri;
193     var io_service = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
194     return io_service.newURI(uri, null, null);
197 function makeFileURL(aFile)
199     var ioService = Cc["@mozilla.org/network/io-service;1"]
200         .getService(Ci.nsIIOService);
201     return ioService.newFileURI(aFile).QueryInterface(Ci.nsIURL);
205 function get_document_content_disposition (document_o)
207     var content_disposition = null;
208     try {
209         content_disposition =
210             document_o.defaultView
211             .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
212             .getInterface(Components.interfaces.nsIDOMWindowUtils)
213             .getDocumentMetadata("content-disposition");
214     } catch (e) { }
215     return content_disposition;
219 function set_focus_no_scroll(window, element)
221     window.document.commandDispatcher.suppressFocusScroll = true;
222     element.focus();
223     window.document.commandDispatcher.suppressFocusScroll = false;
226 function do_repeatedly_positive(func, n) {
227     var args = Array.prototype.slice.call(arguments, 2);
228     while (n-- > 0)
229         func.apply(null, args);
232 function do_repeatedly(func, n, positive_args, negative_args) {
233     if (n < 0)
234         do func.apply(null, negative_args); while (++n < 0);
235     else
236         while (n-- > 0) func.apply(null, positive_args);
239 // remove whitespace from the beginning and end
240 function trim_whitespace (str)
242     var tmp = new String (str);
243     return tmp.replace (/^\s+/, "").replace (/\s+$/, "");
246 function abs_point (node)
248     var orig = node;
249     var pt = {};
250     try {
251         pt.x = node.offsetLeft;
252         pt.y = node.offsetTop;
253         // find imagemap's coordinates
254         if (node.tagName == "AREA") {
255             var coords = node.getAttribute("coords").split(",");
256             pt.x += Number(coords[0]);
257             pt.y += Number(coords[1]);
258         }
260         node = node.offsetParent;
261         // Sometimes this fails, so just return what we got.
263         while (node.tagName != "BODY") {
264             pt.x += node.offsetLeft;
265             pt.y += node.offsetTop;
266             node = node.offsetParent;
267         }
268     } catch(e) {
269 //      node = orig;
270 //      while (node.tagName != "BODY") {
271 //          alert("okay: " + node + " " + node.tagName + " " + pt.x + " " + pt.y);
272 //          node = node.offsetParent;
273 //      }
274     }
275     return pt;
278 var xul_app_info = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo);
279 var xul_runtime = Cc['@mozilla.org/xre/app-info;1'].getService(Ci.nsIXULRuntime);
282 function get_os ()
284     // possible return values: 'Darwin', 'Linux', 'WINNT', ...
285     return xul_runtime.OS;
288 var default_directory = null;
290 var env = Cc['@mozilla.org/process/environment;1'].getService(Ci.nsIEnvironment);
291 function getenv (variable) {
292     if (env.exists (variable))
293         return env.get(variable);
294     return null;
297 function set_default_directory(directory_s) {
298     if (! directory_s)
299     {
300         if ( get_os() == "WINNT")
301         {
302             directory_s = getenv ('USERPROFILE') ||
303                 getenv ('HOMEDRIVE') + getenv ('HOMEPATH');
304         }
305         else {
306             directory_s = getenv ('HOME');
307         }
308     }
310     default_directory = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
311     default_directory.initWithPath (directory_s);
314 set_default_directory();
316 const XHTML_NS = "http://www.w3.org/1999/xhtml";
317 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
318 const MATHML_NS = "http://www.w3.org/1998/Math/MathML";
319 const XLINK_NS = "http://www.w3.org/1999/xlink";
321 function create_XUL(window, tag_name)
323     return window.document.createElementNS(XUL_NS, tag_name);
327 /* Used in calls to XPath evaluate */
328 function xpath_lookup_namespace(prefix) {
329     if (prefix == "xhtml")
330         return XHTML_NS;
331     if (prefix == "m")
332         return MATHML_NS;
333     if (prefix == "xul")
334         return XUL_NS;
335     return null;
338 function method_caller(obj, func) {
339     return function () {
340         func.apply(obj, arguments);
341     }
344 function shell_quote(str) {
345     var s = str.replace("\"", "\\\"", "g");
346     s = s.replace("$", "\$", "g");
347     return s;
350 function get_window_from_frame(frame) {
351     try {
352         var window = frame.QueryInterface(Ci.nsIInterfaceRequestor)
353             .getInterface(Ci.nsIWebNavigation)
354             .QueryInterface(Ci.nsIDocShellTreeItem)
355             .rootTreeItem
356             .QueryInterface(Ci.nsIInterfaceRequestor)
357             .getInterface(Ci.nsIDOMWindow).wrappedJSObject;
358         /* window is now an XPCSafeJSObjectWrapper */
359         window.escape_wrapper(function (w) { window = w; });
360         /* window is now completely unwrapped */
361         return window;
362     } catch (e) {
363         return null;
364     }
367 function get_buffer_from_frame(window, frame) {
368     var count = window.buffers.count;
369     for (var i = 0; i < count; ++i) {
370         var b = window.buffers.get_buffer(i);
371         if (b.top_frame == frame)
372             return b;
373     }
374     return null;
377 var file_locator = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
379 function get_shortdoc_string(doc) {
380     var shortdoc = null;
381     if (doc != null) {
382         var idx = doc.indexOf("\n");
383         if (idx >= 0)
384             shortdoc = doc.substring(0,idx);
385         else
386             shortdoc = doc;
387     }
388     return shortdoc;
391 var conkeror_source_code_path = null;
393 function source_code_reference(uri, line_number) {
394     this.uri = uri;
395     this.line_number = line_number;
397 source_code_reference.prototype = {
398     get module_name () {
399         if (this.uri.indexOf(module_uri_prefix) == 0)
400             return this.uri.substring(module_uri_prefix.length);
401         return null;
402     },
404     get file_name () {
405         var file_uri_prefix = "file://";
406         if (this.uri.indexOf(file_uri_prefix) == 0)
407             return this.uri.substring(file_uri_prefix.length);
408         return null;
409     },
411     get best_uri () {
412         if (conkeror_source_code_path != null) {
413             var module_name = this.module_name;
414             if (module_name != null)
415                 return "file://" + conkeror_source_code_path + "/modules/" + module_name;
416         }
417         return this.uri;
418     },
420     open_in_editor : function() {
421         yield open_with_external_editor(this.best_uri, $line = this.line_number);
422     }
425 var get_caller_source_code_reference_ignored_functions = {};
427 function get_caller_source_code_reference(extra_frames_back) {
428     /* Skip at least this function itself and whoever called it (and
429      * more if the caller wants to be skipped). */
430     var frames_to_skip = 2;
431     if (extra_frames_back != null)
432         frames_to_skip += extra_frames_back;
434     for (let f = Components.stack; f != null; f = f.caller) {
435         if (frames_to_skip > 0) {
436             --frames_to_skip;
437             continue;
438         }
439         if (get_caller_source_code_reference_ignored_functions[f.name])
440             continue;
441         return new source_code_reference(f.filename, f.lineNumber);
442     }
444     return null;
447 function ignore_function_for_get_caller_source_code_reference(func_name) {
448     get_caller_source_code_reference_ignored_functions[func_name] = 1;
451 require_later("external-editor.js");
453 function dom_generator(document, ns) {
454     this.document = document;
455     this.ns = ns;
457 dom_generator.prototype = {
458     element : function(tag, parent) {
459         var node = this.document.createElementNS(this.ns, tag);
460         var i = 1;
461         if (parent != null && (parent instanceof Ci.nsIDOMNode)) {
462             parent.appendChild(node);
463             i = 2;
464         }
465         for (; i < arguments.length; i += 2)
466             node.setAttribute(arguments[i], arguments[i+1]);
467         return node;
468     },
470     text : function(str, parent) {
471         var node = this.document.createTextNode(str);
472         if (parent)
473             parent.appendChild(node);
474         return node;
475     },
478     stylesheet_link : function(href, parent) {
479         var node = this.element("link");
480         node.setAttribute("rel", "stylesheet");
481         node.setAttribute("type", "text/css");
482         node.setAttribute("href", href);
483         if (parent)
484             parent.appendChild(node);
485         return node;
486     },
489     add_stylesheet : function (url) {
490         var head = this.document.documentElement.firstChild;
491         this.stylesheet_link(url, head);
492     }
496  * Generates a QueryInterface function suitable for an implemenation
497  * of an XPCOM interface.  Unlike XPCOMUtils, this uses the Function
498  * constructor to generate a slightly more efficient version.  The
499  * arguments can be either Strings or elements of
500  * Components.interfaces.
501  */
502 function generate_QI() {
503     var args = Array.prototype.slice.call(arguments).map(String).concat(["nsISupports"]);
504     var fstr = "if(" +
505         Array.prototype.map.call(args,
506                                  function (x)
507                                      "iid.equals(Components.interfaces." + x + ")")
508         .join("||") +
509         ") return this; throw Components.results.NS_ERROR_NO_INTERFACE;";
510     return new Function("iid", fstr);
513 function set_branch_pref(branch, name, value) {
514     if (typeof(value) == "string") {
515         branch.setCharPref(name, value);
516     } else if (typeof(value) == "number") {
517         branch.setIntPref(name, value);
518     } else if (typeof(value) == "boolean") {
519         branch.setBoolPref(name, value);
520     }
523 function default_pref(name, value) {
524     var branch = preferences.getDefaultBranch(null);
525     set_branch_pref(branch, name, value);
528 function user_pref(name, value) {
529     var branch = preferences.getBranch(null);
530     set_branch_pref(branch, name, value);
533 function get_branch_pref(branch, name) {
534     switch (branch.getPrefType(name)) {
535     case branch.PREF_STRING:
536         return branch.getCharPref(name);
537     case branch.PREF_INT:
538         return branch.getIntPref(name);
539     case branch.PREF_BOOL:
540         return branch.getBoolPref(name);
541     default:
542         return null;
543     }
546 function get_localized_pref(name) {
547     try {
548         return preferences.getBranch(null).getComplexValue(name, Ci.nsIPrefLocalizedString).data;
549     } catch (e) {
550         return null;
551     }
554 function get_pref(name) {
555     var branch = preferences.getBranch(null);
556     return get_branch_pref(branch, name);
559 function get_default_pref(name) {
560     var branch = preferences.getDefaultBranch(null);
561     return get_branch_pref(branch, name);
564 function clear_pref(name) {
565     var branch = preferences.getBranch(null);
566     return branch.clearUserPref(name);
569 function pref_has_user_value(name) {
570     var branch = preferences.getBranch(null);
571     return branch.prefHasUserValue(name);
574 function pref_has_default_value(name) {
575     var branch = preferences.getDefaultBranch(null);
576     return branch.prefHasUserValue(name);
579 function session_pref (name, value) {
580     try { clear_pref (name); }
581     catch (e) {}
582     return default_pref (name, value);
585 const USER_AGENT_OVERRIDE_PREF = "general.useragent.override";
587 function set_user_agent(str) {
588     session_pref(USER_AGENT_OVERRIDE_PREF, str);
591 function define_builtin_commands(prefix, do_command_function, toggle_mark, mark_active_predicate) {
593     // Specify a docstring
594     function D(cmd, docstring) {
595         var o = new String(cmd);
596         o.doc = docstring;
597         return o;
598     }
600     // Specify a forward/reverse pair
601     function R(a, b) {
602         var o = [a,b];
603         o.is_reverse_pair = true;
604         return o;
605     }
607     // Specify a movement/select command pair.
608     function S(command, movement, select) {
609         var o = [movement, select];
610         o.command = command;
611         o.is_move_select_pair = true;
612         return o;
613     }
615     var builtin_commands = [
616         S(D("beginning-of-line", "Move or extend the selection to the beginning of the current line."),
617           D("cmd_beginLine", "Move point to the beginning of the current line."),
618           D("cmd_selectBeginLine", "Extend selection to the beginning of the current line.")),
619         S(D("end-of-line", "Move or extend the selection to the end of the current line."),
620           D("cmd_endLine", "Move point to the end of the current line."),
621           D("cmd_selectEndLine", "Extend selection to the end of the current line.")),
622         D("cmd_copy", "Copy the selection into the clipboard."),
623         "cmd_copyOrDelete",
624         D("cmd_cut", "Cut the selection into the clipboard."),
625         "cmd_cutOrDelete",
626         D("cmd_deleteToBeginningOfLine", "Delete to the beginning of the current line."),
627         D("cmd_deleteToEndOfLine", "Delete to the end of the current line."),
628         S(D("beginning-of-first-line", "Move or extend the selection to the beginning of the first line."),
629           D("cmd_moveTop", "Move point to the beginning of the first line."),
630           D("cmd_selectTop", "Extend selection to the beginning of the first line.")),
631         S(D("end-of-last-line", "Move or extend the selection to the end of the last line."),
632           D("cmd_moveBottom", "Move point to the end of the last line."),
633           D("cmd_selectBottom", "Extend selection to the end of the last line.")),
634         D("cmd_selectAll", "Select all."),
635         "cmd_scrollBeginLine",
636         "cmd_scrollEndLine",
637         D("cmd_scrollTop", "Scroll to the top of the buffer."),
638         D("cmd_scrollBottom", "Scroll to the bottom of the buffer.")];
640     var builtin_commands_with_count = [
641         R(S(D("forward-char", "Move or extend the selection forward one character."),
642             D("cmd_charNext", "Move point forward one character."),
643             D("cmd_selectCharNext", "Extend selection forward one character.")),
644           S(D("backward-char", "Move or extend the selection backward one character."),
645             D("cmd_charPrevious", "Move point backward one character."),
646             D("cmd_selectCharPrevious", "Extend selection backward one character."))),
647         R(D("cmd_deleteCharForward", "Delete the following character."),
648           D("cmd_deleteCharBackward", "Delete the previous character.")),
649         R(D("cmd_deleteWordForward", "Delete the following word."),
650           D("cmd_deleteWordBackward", "Delete the previous word.")),
651         R(S(D("forward-line", "Move or extend the selection forward one line."),
652             D("cmd_lineNext", "Move point forward one line."),
653             "cmd_selectLineNext", "Extend selection forward one line."),
654           S(D("backward-line", "Move or extend the selection backward one line."),
655             D("cmd_linePrevious", "Move point backward one line."),
656             D("cmd_selectLinePrevious", "Extend selection backward one line."))),
657         R(S(D("forward-page", "Move or extend the selection forward one page."),
658             D("cmd_movePageDown", "Move point forward one page."),
659             D("cmd_selectPageDown", "Extend selection forward one page.")),
660           S(D("backward-page", "Move or extend the selection backward one page."),
661             D("cmd_movePageUp", "Move point backward one page."),
662             D("cmd_selectPageUp", "Extend selection backward one page."))),
663         R(D("cmd_undo", "Undo last editing action."),
664           D("cmd_redo", "Redo last editing action.")),
665         R(S(D("forward-word", "Move or extend the selection forward one word."),
666             D("cmd_wordNext", "Move point forward one word."),
667             D("cmd_selectWordNext", "Extend selection forward one word.")),
668           S(D("backward-word", "Move or extend the selection backward one word."),
669             D("cmd_wordPrevious", "Move point backward one word."),
670             D("cmd_selectWordPrevious", "Extend selection backward one word."))),
671         R(D("cmd_scrollPageUp", "Scroll up one page."),
672           D("cmd_scrollPageDown", "Scroll down one page.")),
673         R(D("cmd_scrollLineUp", "Scroll up one line."),
674           D("cmd_scrollLineDown", "Scroll down one line.")),
675         R(D("cmd_scrollLeft", "Scroll left."),
676           D("cmd_scrollRight", "Scroll right.")),
677         D("cmd_paste", "Insert the contents of the clipboard.")];
679     interactive(prefix + "set-mark",
680                 "Toggle whether the mark is active.\n" +
681                 "When the mark is active, movement commands affect the selection.",
682                 toggle_mark);
684     function doc_for_builtin(c) {
685         var s = "";
686         if (c.doc != null)
687             s += c.doc + "\n";
688         return s + "Run the built-in command " + c + ".";
689     }
691     function define_simple_command(c) {
692         interactive(prefix + c, doc_for_builtin(c), function (I) { do_command_function(I, c); });
693     }
695     function get_move_select_doc_string(c) {
696         return c.command.doc +
697             "\nSpecifically, if the mark is inactive, runs `" + prefix + c[0] + "'.  " +
698             "Otherwise, runs `" + prefix + c[1] + "'.\n" +
699             "To toggle whether the mark is active, use `" + prefix + "set-mark'.";
700     }
702     for each (let c_temp in builtin_commands)  {
703         let c = c_temp;
704         if (c.is_move_select_pair) {
705             interactive(prefix + c.command, get_move_select_doc_string(c), function (I) {
706                 do_command_function(I, mark_active_predicate(I) ? c[1] : c[0]);
707             });
708             define_simple_command(c[0]);
709             define_simple_command(c[1]);
710         }
711         else
712             define_simple_command(c);
713     }
715     function get_reverse_pair_doc_string(main_doc, alt_command) {
716         return main_doc + "\n" +
717             "The prefix argument specifies a repeat count for this command.  " +
718             "If the count is negative, `" + prefix + alt_command + "' is performed instead with " +
719             "a corresponding positive repeat count.";
720     }
722     function define_simple_reverse_pair(a, b) {
723         interactive(prefix + a, get_reverse_pair_doc_string(doc_for_builtin(a), b),
724                     function (I) {
725                         do_repeatedly(do_command_function, I.p, [I, a], [I, b]);
726                     });
727         interactive(prefix + b, get_reverse_pair_doc_string(doc_for_builtin(b), a),
728                     function (I) {
729                         do_repeatedly(do_command_function, I.p, [I, b], [I, a]);
730                     });
731     }
733     for each (let c_temp in builtin_commands_with_count)
734     {
735         let c = c_temp;
736         if (c.is_reverse_pair) {
737             if (c[0].is_move_select_pair) {
738                 interactive(prefix + c[0].command, get_reverse_pair_doc_string(get_move_select_doc_string(c[0]),
739                                                                                c[1].command),
740                             function (I) {
741                                 var idx = mark_active_predicate(I) ? 1 : 0;
742                                 do_repeatedly(do_command_function, I.p, [I, c[0][idx]], [I, c[1][idx]]);
743                             });
744                 interactive(prefix + c[1].command, get_reverse_pair_doc_string(get_move_select_doc_string(c[1]),
745                                                                                c[0].command),
746                             function (I) {
747                                 var idx = mark_active_predicate(I) ? 1 : 0;
748                                 do_repeatedly(do_command_function, I.p, [I, c[1][idx]], [I, c[0][idx]]);
749                             });
750                 define_simple_reverse_pair(c[0][0], c[1][0]);
751                 define_simple_reverse_pair(c[0][1], c[1][1]);
752             } else
753                 define_simple_reverse_pair(c[0], c[1]);
754         } else {
755             let doc = doc_for_builtin(c) +
756                 "\nThe prefix argument specifies a positive repeat count for this command.";
757             interactive(prefix + c, doc, function (I) {
758                 do_repeatedly_positive(do_command_function, I.p, I, c);
759             });
760         }
761     }
764 var observer_service = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
766 function abort(str) {
767     var e = new Error(str);
768     e.__proto__ = abort.prototype;
769     return e;
771 abort.prototype.__proto__ = Error.prototype;
774 function get_temporary_file(name) {
775     if (name == null)
776         name = "temp.txt";
777     var file = file_locator.get("TmpD", Ci.nsIFile);
778     file.append(name);
779     // Create the file now to ensure that no exploits are possible
780     file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0600);
781     return file;
785 /* FIXME: This should be moved somewhere else, perhaps. */
786 function create_info_panel(window, panel_class, row_arr) {
787     /* Show information panel above minibuffer */
789     var g = new dom_generator(window.document, XUL_NS);
791     var p = g.element("vbox", "class", "panel " + panel_class, "flex", "0");
792     var grid = g.element("grid", p);
793     var cols = g.element("columns", grid);
794     g.element("column", cols, "flex", "0");
795     g.element("column", cols, "flex", "1");
797     var rows = g.element("rows", grid);
798     var row;
800     for each (let [row_class, row_label, row_value] in row_arr) {
801         row = g.element("row", rows, "class", row_class);
802         g.element("label", row,
803                   "value", row_label,
804                   "class", "panel-row-label");
805         g.element("label", row,
806                   "value", row_value,
807                   "class", "panel-row-value");
808     }
809     window.minibuffer.insert_before(p);
811     p.destroy = function () {
812         this.parentNode.removeChild(this);
813     };
815     return p;
819 // read_from_x_primary_selection favors the X PRIMARY SELECTION, when
820 // it exists.  The builtin cmd_paste always uses X CLIPBOARD.  So this
821 // is an auxiliary utility, in case you need to work with the primary
822 // selection.
824 function read_from_x_primary_selection ()
826     // Get clipboard.
827     var clipboard = Components.classes["@mozilla.org/widget/clipboard;1"]
828         .getService(Components.interfaces.nsIClipboard);
830     // Create tranferable that will transfer the text.
831     var trans = Components.classes["@mozilla.org/widget/transferable;1"]
832         .createInstance(Components.interfaces.nsITransferable);
834     trans.addDataFlavor("text/unicode");
835     // If available, use selection clipboard, otherwise global one
836     if (clipboard.supportsSelectionClipboard())
837         clipboard.getData(trans, clipboard.kSelectionClipboard);
838     else
839         clipboard.getData(trans, clipboard.kGlobalClipboard);
841     var data = {};
842     var dataLen = {};
843     trans.getTransferData("text/unicode", data, dataLen);
845     if (data) {
846         data = data.value.QueryInterface(Components.interfaces.nsISupportsString);
847         return data.data.substring(0, dataLen.value / 2);
848     } else {
849         return "";
850     }
853 var user_variables = new string_hashmap();
855 function define_variable(name, default_value, doc) {
856     conkeror[name] = default_value;
857     user_variables.put(name, {
858         default_value: default_value,
859         doc: doc,
860         shortdoc: get_shortdoc_string(doc),
861         source_code_reference: get_caller_source_code_reference() });
865 function register_user_stylesheet(url)
867     var uri = makeURL(url);
868     var sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService);
869     sss.loadAndRegisterSheet(uri, sss.USER_SHEET);
872 function unregister_user_stylesheet(url)
874     var uri = makeURL(url);
875     var sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService);
876     if (sss.sheetRegistered(uri, sss.USER_SHEET))
877         ss.unregisterSheet(uri, sss.USER_SHEET);
880 function predicate_alist_match(alist, key) {
881     for each (let i in alist) {
882         if (i[0](key))
883             return i[1];
884     }
885     return undefined;
889 function get_meta_title(doc) {
890     var title = doc.evaluate("//meta[@name='title']/@content", doc, xpath_lookup_namespace,
891                              Ci.nsIDOMXPathResult.STRING_TYPE , null);
892     if (title && title.stringValue)
893         return title.stringValue;
894     return null;
897 var rdf_service = Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService);
899 const PREFIX_ITEM_URI     = "urn:mozilla:item:";
900 const PREFIX_NS_EM        = "http://www.mozilla.org/2004/em-rdf#";
902 var extension_manager = Cc["@mozilla.org/extensions/manager;1"].getService(Ci.nsIExtensionManager);
904 function get_extension_rdf_property(id, name, type) {
905     var value = extension_manager.datasource.GetTarget(
906         rdf_service.GetResource(PREFIX_ITEM_URI + id),
907         rdf_service.GetResource(PREFIX_NS_EM + name),
908         true);
909     if (value == null)
910         return null;
911     return value.QueryInterface(type || Ci.nsIRDFLiteral).Value;
914 function get_extension_update_item(id) {
915     return extension_manager.getItemForID(id);
918 function extension_info(id) {
919     this.id = id;
921 extension_info.prototype = {
922     // Returns the nsIUpdateItem object associated with this extension
923     get update_item () { return get_extension_update_item(this.id); },
925     get_rdf_property : function (name, type) {
926         return get_extension_rdf_property(this.id, name, type);
927     },
929     // RDF properties
930     get isDisabled () { return this.get_rdf_property("isDisabled"); },
931     get aboutURL () { return this.get_rdf_property("aboutURL"); },
932     get addonID () { return this.get_rdf_property("addonID"); },
933     get availableUpdateURL () { return this.get_rdf_property("availableUpdateURL"); },
934     get availableUpdateVersion () { return this.get_rdf_property("availableUpdateVersion"); },
935     get blocklisted () { return this.get_rdf_property("blocklisted"); },
936     get compatible () { return this.get_rdf_property("compatible"); },
937     get description () { return this.get_rdf_property("description"); },
938     get downloadURL () { return this.get_rdf_property("downloadURL"); },
939     get isDisabled () { return this.get_rdf_property("isDisabled"); },
940     get hidden () { return this.get_rdf_property("hidden"); },
941     get homepageURL () { return this.get_rdf_property("homepageURL"); },
942     get iconURL () { return this.get_rdf_property("iconURL"); },
943     get internalName () { return this.get_rdf_property("internalName"); },
944     get locked () { return this.get_rdf_property("locked"); },
945     get name () { return this.get_rdf_property("name"); },
946     get optionsURL () { return this.get_rdf_property("optionsURL"); },
947     get opType () { return this.get_rdf_property("opType"); },
948     get plugin () { return this.get_rdf_property("plugin"); },
949     get previewImage () { return this.get_rdf_property("previewImage"); },
950     get satisfiesDependencies () { return this.get_rdf_property("satisfiesDependencies"); },
951     get providesUpdatesSecurely () { return this.get_rdf_property("providesUpdatesSecurely"); },
952     get type () { return this.get_rdf_property("type", Ci.nsIRDFInt); },
953     get updateable () { return this.get_rdf_property("updateable"); },
954     get updateURL () { return this.get_rdf_property("updateURL"); },
955     get version () { return this.get_rdf_property("version"); }
958 function extension_is_enabled(id) {
959     var info = new extension_info(id);
960     return info.update_item && (info.isDisabled == "false");