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
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.
37 function string_hashset() {}
39 string_hashset.prototype = {
40 constructor : string_hashset,
46 contains : function(s) {
47 return (("-" + s) in this);
50 remove : function (s) {
54 for_each : function (f) {
61 iterator : function () {
69 function string_hashmap() {
72 string_hashmap.prototype = {
73 constructor : string_hashmap,
75 put : function(s,value) {
76 this["-" + s] = value;
79 contains : function(s) {
80 return (("-" + s) in this);
83 get : function(s, default_value) {
89 get_put_default : function(s, default_value) {
92 return (this["-" + s] = default_value);
95 remove : function (s) {
99 for_each : function (f) {
100 for (var i in this) {
102 f(i.slice(1), this[i]);
106 for_each_value : function (f) {
107 for (var i in this) {
113 iterator: function (only_keys) {
115 for (let k in Iterator(this, true)) {
120 for (let [k,v] in Iterator(this, false)) {
122 yield [k.slice(1),v];
128 /// Window title formatting
131 * Default tile formatter. The page url is ignored. If there is a
132 * page_title, returns: "Page title - Conkeror". Otherwise, it
133 * returns just: "Conkeror".
135 function default_title_formatter (window)
137 var page_title = window.buffers.current.title;
139 if (page_title && page_title.length > 0)
140 return page_title + " - Conkeror";
145 var title_format_fn = null;
147 function set_window_title (window)
149 window.document.title = title_format_fn(window);
152 function init_window_title ()
154 title_format_fn = default_title_formatter;
156 add_hook("window_initialize_late_hook", set_window_title);
157 add_hook("current_content_buffer_location_change_hook",
159 set_window_title(buffer.window);
161 add_hook("select_buffer_hook", function (buffer) { set_window_title(buffer.window); }, true);
162 add_hook("current_buffer_title_change_hook",
164 set_window_title(buffer.window);
168 init_window_title ();
173 // Put the string on the clipboard
174 function writeToClipboard(str)
176 const gClipboardHelper = Components.classes["@mozilla.org/widget/clipboardhelper;1"]
177 .getService(Components.interfaces.nsIClipboardHelper);
178 gClipboardHelper.copyString(str);
182 function makeURLAbsolute (base, url)
185 var ioService = Components.classes["@mozilla.org/network/io-service;1"]
186 .getService(Components.interfaces.nsIIOService);
187 var baseURI = ioService.newURI(base, null, null);
189 return ioService.newURI (baseURI.resolve (url), null, null).spec;
193 function get_link_location (element)
195 if (element && element.getAttribute("href")) {
196 var loc = element.getAttribute("href");
197 return makeURLAbsolute(element.baseURI, loc);
203 var io_service = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
205 function make_uri(uri, charset, base_uri) {
206 if (uri instanceof Ci.nsIURI)
208 return io_service.newURI(uri, charset, base_uri);
211 var makeURL = make_uri; // until all callers are fixed
213 function makeFileURL(aFile)
215 return io_service.newFileURI(aFile).QueryInterface(Ci.nsIURL);
219 function get_document_content_disposition (document_o)
221 var content_disposition = null;
223 content_disposition =
224 document_o.defaultView
225 .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
226 .getInterface(Components.interfaces.nsIDOMWindowUtils)
227 .getDocumentMetadata("content-disposition");
229 return content_disposition;
233 function set_focus_no_scroll(window, element)
235 window.document.commandDispatcher.suppressFocusScroll = true;
237 window.document.commandDispatcher.suppressFocusScroll = false;
240 function do_repeatedly_positive(func, n) {
241 var args = Array.prototype.slice.call(arguments, 2);
243 func.apply(null, args);
246 function do_repeatedly(func, n, positive_args, negative_args) {
248 do func.apply(null, negative_args); while (++n < 0);
250 while (n-- > 0) func.apply(null, positive_args);
253 // remove whitespace from the beginning and end
254 function trim_whitespace (str)
256 var tmp = new String (str);
257 return tmp.replace (/^\s+/, "").replace (/\s+$/, "");
260 function abs_point (node)
265 pt.x = node.offsetLeft;
266 pt.y = node.offsetTop;
267 // find imagemap's coordinates
268 if (node.tagName == "AREA") {
269 var coords = node.getAttribute("coords").split(",");
270 pt.x += Number(coords[0]);
271 pt.y += Number(coords[1]);
274 node = node.offsetParent;
275 // Sometimes this fails, so just return what we got.
277 while (node.tagName != "BODY") {
278 pt.x += node.offsetLeft;
279 pt.y += node.offsetTop;
280 node = node.offsetParent;
284 // while (node.tagName != "BODY") {
285 // alert("okay: " + node + " " + node.tagName + " " + pt.x + " " + pt.y);
286 // node = node.offsetParent;
292 var xul_app_info = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo);
293 var xul_runtime = Cc['@mozilla.org/xre/app-info;1'].getService(Ci.nsIXULRuntime);
298 // possible return values: 'Darwin', 'Linux', 'WINNT', ...
299 return xul_runtime.OS;
302 var default_directory = null;
304 var env = Cc['@mozilla.org/process/environment;1'].getService(Ci.nsIEnvironment);
305 function getenv (variable) {
306 if (env.exists (variable))
307 return env.get(variable);
311 function set_default_directory(directory_s) {
314 if ( get_os() == "WINNT")
316 directory_s = getenv ('USERPROFILE') ||
317 getenv ('HOMEDRIVE') + getenv ('HOMEPATH');
320 directory_s = getenv ('HOME');
324 default_directory = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
325 default_directory.initWithPath (directory_s);
328 set_default_directory();
330 const XHTML_NS = "http://www.w3.org/1999/xhtml";
331 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
332 const MATHML_NS = "http://www.w3.org/1998/Math/MathML";
333 const XLINK_NS = "http://www.w3.org/1999/xlink";
335 function create_XUL(window, tag_name)
337 return window.document.createElementNS(XUL_NS, tag_name);
341 /* Used in calls to XPath evaluate */
342 function xpath_lookup_namespace(prefix) {
343 if (prefix == "xhtml")
352 function method_caller(obj, func) {
354 func.apply(obj, arguments);
358 function shell_quote(str) {
359 var s = str.replace("\"", "\\\"", "g");
360 s = s.replace("$", "\$", "g");
364 function get_window_from_frame(frame) {
366 var window = frame.QueryInterface(Ci.nsIInterfaceRequestor)
367 .getInterface(Ci.nsIWebNavigation)
368 .QueryInterface(Ci.nsIDocShellTreeItem)
370 .QueryInterface(Ci.nsIInterfaceRequestor)
371 .getInterface(Ci.nsIDOMWindow).wrappedJSObject;
372 /* window is now an XPCSafeJSObjectWrapper */
373 window.escape_wrapper(function (w) { window = w; });
374 /* window is now completely unwrapped */
381 function get_buffer_from_frame(window, frame) {
382 var count = window.buffers.count;
383 for (var i = 0; i < count; ++i) {
384 var b = window.buffers.get_buffer(i);
385 if (b.top_frame == frame)
391 var file_locator = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
393 function get_shortdoc_string(doc) {
396 var idx = doc.indexOf("\n");
398 shortdoc = doc.substring(0,idx);
405 var conkeror_source_code_path = null;
407 function source_code_reference(uri, line_number) {
409 this.line_number = line_number;
411 source_code_reference.prototype = {
413 if (this.uri.indexOf(module_uri_prefix) == 0)
414 return this.uri.substring(module_uri_prefix.length);
419 var file_uri_prefix = "file://";
420 if (this.uri.indexOf(file_uri_prefix) == 0)
421 return this.uri.substring(file_uri_prefix.length);
426 if (conkeror_source_code_path != null) {
427 var module_name = this.module_name;
428 if (module_name != null)
429 return "file://" + conkeror_source_code_path + "/modules/" + module_name;
434 open_in_editor : function() {
435 yield open_with_external_editor(this.best_uri, $line = this.line_number);
439 var get_caller_source_code_reference_ignored_functions = {};
441 function get_caller_source_code_reference(extra_frames_back) {
442 /* Skip at least this function itself and whoever called it (and
443 * more if the caller wants to be skipped). */
444 var frames_to_skip = 2;
445 if (extra_frames_back != null)
446 frames_to_skip += extra_frames_back;
448 for (let f = Components.stack; f != null; f = f.caller) {
449 if (frames_to_skip > 0) {
453 if (get_caller_source_code_reference_ignored_functions[f.name])
455 return new source_code_reference(f.filename, f.lineNumber);
461 function ignore_function_for_get_caller_source_code_reference(func_name) {
462 get_caller_source_code_reference_ignored_functions[func_name] = 1;
465 require_later("external-editor.js");
467 function dom_generator(document, ns) {
468 this.document = document;
471 dom_generator.prototype = {
472 element : function(tag, parent) {
473 var node = this.document.createElementNS(this.ns, tag);
475 if (parent != null && (parent instanceof Ci.nsIDOMNode)) {
476 parent.appendChild(node);
479 for (; i < arguments.length; i += 2)
480 node.setAttribute(arguments[i], arguments[i+1]);
484 text : function(str, parent) {
485 var node = this.document.createTextNode(str);
487 parent.appendChild(node);
492 stylesheet_link : function(href, parent) {
493 var node = this.element("link");
494 node.setAttribute("rel", "stylesheet");
495 node.setAttribute("type", "text/css");
496 node.setAttribute("href", href);
498 parent.appendChild(node);
503 add_stylesheet : function (url) {
504 var head = this.document.documentElement.firstChild;
505 this.stylesheet_link(url, head);
510 * Generates a QueryInterface function suitable for an implemenation
511 * of an XPCOM interface. Unlike XPCOMUtils, this uses the Function
512 * constructor to generate a slightly more efficient version. The
513 * arguments can be either Strings or elements of
514 * Components.interfaces.
516 function generate_QI() {
517 var args = Array.prototype.slice.call(arguments).map(String).concat(["nsISupports"]);
519 Array.prototype.map.call(args,
521 "iid.equals(Components.interfaces." + x + ")")
523 ") return this; throw Components.results.NS_ERROR_NO_INTERFACE;";
524 return new Function("iid", fstr);
527 function set_branch_pref(branch, name, value) {
528 if (typeof(value) == "string") {
529 branch.setCharPref(name, value);
530 } else if (typeof(value) == "number") {
531 branch.setIntPref(name, value);
532 } else if (typeof(value) == "boolean") {
533 branch.setBoolPref(name, value);
537 function default_pref(name, value) {
538 var branch = preferences.getDefaultBranch(null);
539 set_branch_pref(branch, name, value);
542 function user_pref(name, value) {
543 var branch = preferences.getBranch(null);
544 set_branch_pref(branch, name, value);
547 function get_branch_pref(branch, name) {
548 switch (branch.getPrefType(name)) {
549 case branch.PREF_STRING:
550 return branch.getCharPref(name);
551 case branch.PREF_INT:
552 return branch.getIntPref(name);
553 case branch.PREF_BOOL:
554 return branch.getBoolPref(name);
560 function get_localized_pref(name) {
562 return preferences.getBranch(null).getComplexValue(name, Ci.nsIPrefLocalizedString).data;
568 function get_pref(name) {
569 var branch = preferences.getBranch(null);
570 return get_branch_pref(branch, name);
573 function get_default_pref(name) {
574 var branch = preferences.getDefaultBranch(null);
575 return get_branch_pref(branch, name);
578 function clear_pref(name) {
579 var branch = preferences.getBranch(null);
580 return branch.clearUserPref(name);
583 function pref_has_user_value(name) {
584 var branch = preferences.getBranch(null);
585 return branch.prefHasUserValue(name);
588 function pref_has_default_value(name) {
589 var branch = preferences.getDefaultBranch(null);
590 return branch.prefHasUserValue(name);
593 function session_pref (name, value) {
594 try { clear_pref (name); }
596 return default_pref (name, value);
599 const LOCALE_PREF = "general.useragent.locale";
601 function get_locale() {
602 return get_localized_pref(LOCALE_PREF) || get_pref(LOCALE_PREF);
605 const USER_AGENT_OVERRIDE_PREF = "general.useragent.override";
607 function set_user_agent(str) {
608 session_pref(USER_AGENT_OVERRIDE_PREF, str);
611 function define_builtin_commands(prefix, do_command_function, toggle_mark, mark_active_predicate) {
613 // Specify a docstring
614 function D(cmd, docstring) {
615 var o = new String(cmd);
620 // Specify a forward/reverse pair
623 o.is_reverse_pair = true;
627 // Specify a movement/select command pair.
628 function S(command, movement, select) {
629 var o = [movement, select];
631 o.is_move_select_pair = true;
635 var builtin_commands = [
636 S(D("beginning-of-line", "Move or extend the selection to the beginning of the current line."),
637 D("cmd_beginLine", "Move point to the beginning of the current line."),
638 D("cmd_selectBeginLine", "Extend selection to the beginning of the current line.")),
639 S(D("end-of-line", "Move or extend the selection to the end of the current line."),
640 D("cmd_endLine", "Move point to the end of the current line."),
641 D("cmd_selectEndLine", "Extend selection to the end of the current line.")),
642 D("cmd_copy", "Copy the selection into the clipboard."),
644 D("cmd_cut", "Cut the selection into the clipboard."),
646 D("cmd_deleteToBeginningOfLine", "Delete to the beginning of the current line."),
647 D("cmd_deleteToEndOfLine", "Delete to the end of the current line."),
648 S(D("beginning-of-first-line", "Move or extend the selection to the beginning of the first line."),
649 D("cmd_moveTop", "Move point to the beginning of the first line."),
650 D("cmd_selectTop", "Extend selection to the beginning of the first line.")),
651 S(D("end-of-last-line", "Move or extend the selection to the end of the last line."),
652 D("cmd_moveBottom", "Move point to the end of the last line."),
653 D("cmd_selectBottom", "Extend selection to the end of the last line.")),
654 D("cmd_selectAll", "Select all."),
655 "cmd_scrollBeginLine",
657 D("cmd_scrollTop", "Scroll to the top of the buffer."),
658 D("cmd_scrollBottom", "Scroll to the bottom of the buffer.")];
660 var builtin_commands_with_count = [
661 R(S(D("forward-char", "Move or extend the selection forward one character."),
662 D("cmd_charNext", "Move point forward one character."),
663 D("cmd_selectCharNext", "Extend selection forward one character.")),
664 S(D("backward-char", "Move or extend the selection backward one character."),
665 D("cmd_charPrevious", "Move point backward one character."),
666 D("cmd_selectCharPrevious", "Extend selection backward one character."))),
667 R(D("cmd_deleteCharForward", "Delete the following character."),
668 D("cmd_deleteCharBackward", "Delete the previous character.")),
669 R(D("cmd_deleteWordForward", "Delete the following word."),
670 D("cmd_deleteWordBackward", "Delete the previous word.")),
671 R(S(D("forward-line", "Move or extend the selection forward one line."),
672 D("cmd_lineNext", "Move point forward one line."),
673 "cmd_selectLineNext", "Extend selection forward one line."),
674 S(D("backward-line", "Move or extend the selection backward one line."),
675 D("cmd_linePrevious", "Move point backward one line."),
676 D("cmd_selectLinePrevious", "Extend selection backward one line."))),
677 R(S(D("forward-page", "Move or extend the selection forward one page."),
678 D("cmd_movePageDown", "Move point forward one page."),
679 D("cmd_selectPageDown", "Extend selection forward one page.")),
680 S(D("backward-page", "Move or extend the selection backward one page."),
681 D("cmd_movePageUp", "Move point backward one page."),
682 D("cmd_selectPageUp", "Extend selection backward one page."))),
683 R(D("cmd_undo", "Undo last editing action."),
684 D("cmd_redo", "Redo last editing action.")),
685 R(S(D("forward-word", "Move or extend the selection forward one word."),
686 D("cmd_wordNext", "Move point forward one word."),
687 D("cmd_selectWordNext", "Extend selection forward one word.")),
688 S(D("backward-word", "Move or extend the selection backward one word."),
689 D("cmd_wordPrevious", "Move point backward one word."),
690 D("cmd_selectWordPrevious", "Extend selection backward one word."))),
691 R(D("cmd_scrollPageUp", "Scroll up one page."),
692 D("cmd_scrollPageDown", "Scroll down one page.")),
693 R(D("cmd_scrollLineUp", "Scroll up one line."),
694 D("cmd_scrollLineDown", "Scroll down one line.")),
695 R(D("cmd_scrollLeft", "Scroll left."),
696 D("cmd_scrollRight", "Scroll right.")),
697 D("cmd_paste", "Insert the contents of the clipboard.")];
699 interactive(prefix + "set-mark",
700 "Toggle whether the mark is active.\n" +
701 "When the mark is active, movement commands affect the selection.",
704 function doc_for_builtin(c) {
708 return s + "Run the built-in command " + c + ".";
711 function define_simple_command(c) {
712 interactive(prefix + c, doc_for_builtin(c), function (I) { do_command_function(I, c); });
715 function get_move_select_doc_string(c) {
716 return c.command.doc +
717 "\nSpecifically, if the mark is inactive, runs `" + prefix + c[0] + "'. " +
718 "Otherwise, runs `" + prefix + c[1] + "'.\n" +
719 "To toggle whether the mark is active, use `" + prefix + "set-mark'.";
722 for each (let c_temp in builtin_commands) {
724 if (c.is_move_select_pair) {
725 interactive(prefix + c.command, get_move_select_doc_string(c), function (I) {
726 do_command_function(I, mark_active_predicate(I) ? c[1] : c[0]);
728 define_simple_command(c[0]);
729 define_simple_command(c[1]);
732 define_simple_command(c);
735 function get_reverse_pair_doc_string(main_doc, alt_command) {
736 return main_doc + "\n" +
737 "The prefix argument specifies a repeat count for this command. " +
738 "If the count is negative, `" + prefix + alt_command + "' is performed instead with " +
739 "a corresponding positive repeat count.";
742 function define_simple_reverse_pair(a, b) {
743 interactive(prefix + a, get_reverse_pair_doc_string(doc_for_builtin(a), b),
745 do_repeatedly(do_command_function, I.p, [I, a], [I, b]);
747 interactive(prefix + b, get_reverse_pair_doc_string(doc_for_builtin(b), a),
749 do_repeatedly(do_command_function, I.p, [I, b], [I, a]);
753 for each (let c_temp in builtin_commands_with_count)
756 if (c.is_reverse_pair) {
757 if (c[0].is_move_select_pair) {
758 interactive(prefix + c[0].command, get_reverse_pair_doc_string(get_move_select_doc_string(c[0]),
761 var idx = mark_active_predicate(I) ? 1 : 0;
762 do_repeatedly(do_command_function, I.p, [I, c[0][idx]], [I, c[1][idx]]);
764 interactive(prefix + c[1].command, get_reverse_pair_doc_string(get_move_select_doc_string(c[1]),
767 var idx = mark_active_predicate(I) ? 1 : 0;
768 do_repeatedly(do_command_function, I.p, [I, c[1][idx]], [I, c[0][idx]]);
770 define_simple_reverse_pair(c[0][0], c[1][0]);
771 define_simple_reverse_pair(c[0][1], c[1][1]);
773 define_simple_reverse_pair(c[0], c[1]);
775 let doc = doc_for_builtin(c) +
776 "\nThe prefix argument specifies a positive repeat count for this command.";
777 interactive(prefix + c, doc, function (I) {
778 do_repeatedly_positive(do_command_function, I.p, I, c);
784 var observer_service = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
786 function abort(str) {
787 var e = new Error(str);
788 e.__proto__ = abort.prototype;
791 abort.prototype.__proto__ = Error.prototype;
794 function get_temporary_file(name) {
797 var file = file_locator.get("TmpD", Ci.nsIFile);
799 // Create the file now to ensure that no exploits are possible
800 file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0600);
805 /* FIXME: This should be moved somewhere else, perhaps. */
806 function create_info_panel(window, panel_class, row_arr) {
807 /* Show information panel above minibuffer */
809 var g = new dom_generator(window.document, XUL_NS);
811 var p = g.element("vbox", "class", "panel " + panel_class, "flex", "0");
812 var grid = g.element("grid", p);
813 var cols = g.element("columns", grid);
814 g.element("column", cols, "flex", "0");
815 g.element("column", cols, "flex", "1");
817 var rows = g.element("rows", grid);
820 for each (let [row_class, row_label, row_value] in row_arr) {
821 row = g.element("row", rows, "class", row_class);
822 g.element("label", row,
824 "class", "panel-row-label");
825 g.element("label", row,
827 "class", "panel-row-value");
829 window.minibuffer.insert_before(p);
831 p.destroy = function () {
832 this.parentNode.removeChild(this);
839 // read_from_x_primary_selection favors the X PRIMARY SELECTION, when
840 // it exists. The builtin cmd_paste always uses X CLIPBOARD. So this
841 // is an auxiliary utility, in case you need to work with the primary
844 function read_from_x_primary_selection ()
847 var clipboard = Components.classes["@mozilla.org/widget/clipboard;1"]
848 .getService(Components.interfaces.nsIClipboard);
850 // Create tranferable that will transfer the text.
851 var trans = Components.classes["@mozilla.org/widget/transferable;1"]
852 .createInstance(Components.interfaces.nsITransferable);
854 trans.addDataFlavor("text/unicode");
855 // If available, use selection clipboard, otherwise global one
856 if (clipboard.supportsSelectionClipboard())
857 clipboard.getData(trans, clipboard.kSelectionClipboard);
859 clipboard.getData(trans, clipboard.kGlobalClipboard);
863 trans.getTransferData("text/unicode", data, dataLen);
866 data = data.value.QueryInterface(Components.interfaces.nsISupportsString);
867 return data.data.substring(0, dataLen.value / 2);
873 var user_variables = new string_hashmap();
875 function define_variable(name, default_value, doc) {
876 conkeror[name] = default_value;
877 user_variables.put(name, {
878 default_value: default_value,
880 shortdoc: get_shortdoc_string(doc),
881 source_code_reference: get_caller_source_code_reference() });
885 function register_user_stylesheet(url)
887 var uri = makeURL(url);
888 var sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService);
889 sss.loadAndRegisterSheet(uri, sss.USER_SHEET);
892 function unregister_user_stylesheet(url)
894 var uri = makeURL(url);
895 var sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService);
896 if (sss.sheetRegistered(uri, sss.USER_SHEET))
897 ss.unregisterSheet(uri, sss.USER_SHEET);
900 function predicate_alist_match(alist, key) {
901 for each (let i in alist) {
909 function get_meta_title(doc) {
910 var title = doc.evaluate("//meta[@name='title']/@content", doc, xpath_lookup_namespace,
911 Ci.nsIDOMXPathResult.STRING_TYPE , null);
912 if (title && title.stringValue)
913 return title.stringValue;
917 var rdf_service = Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService);
919 const PREFIX_ITEM_URI = "urn:mozilla:item:";
920 const PREFIX_NS_EM = "http://www.mozilla.org/2004/em-rdf#";
922 var extension_manager = Cc["@mozilla.org/extensions/manager;1"].getService(Ci.nsIExtensionManager);
924 function get_extension_rdf_property(id, name, type) {
925 var value = extension_manager.datasource.GetTarget(
926 rdf_service.GetResource(PREFIX_ITEM_URI + id),
927 rdf_service.GetResource(PREFIX_NS_EM + name),
931 return value.QueryInterface(type || Ci.nsIRDFLiteral).Value;
934 function get_extension_update_item(id) {
935 return extension_manager.getItemForID(id);
938 function extension_info(id) {
941 extension_info.prototype = {
942 // Returns the nsIUpdateItem object associated with this extension
943 get update_item () { return get_extension_update_item(this.id); },
945 get_rdf_property : function (name, type) {
946 return get_extension_rdf_property(this.id, name, type);
950 get isDisabled () { return this.get_rdf_property("isDisabled"); },
951 get aboutURL () { return this.get_rdf_property("aboutURL"); },
952 get addonID () { return this.get_rdf_property("addonID"); },
953 get availableUpdateURL () { return this.get_rdf_property("availableUpdateURL"); },
954 get availableUpdateVersion () { return this.get_rdf_property("availableUpdateVersion"); },
955 get blocklisted () { return this.get_rdf_property("blocklisted"); },
956 get compatible () { return this.get_rdf_property("compatible"); },
957 get description () { return this.get_rdf_property("description"); },
958 get downloadURL () { return this.get_rdf_property("downloadURL"); },
959 get isDisabled () { return this.get_rdf_property("isDisabled"); },
960 get hidden () { return this.get_rdf_property("hidden"); },
961 get homepageURL () { return this.get_rdf_property("homepageURL"); },
962 get iconURL () { return this.get_rdf_property("iconURL"); },
963 get internalName () { return this.get_rdf_property("internalName"); },
964 get locked () { return this.get_rdf_property("locked"); },
965 get name () { return this.get_rdf_property("name"); },
966 get optionsURL () { return this.get_rdf_property("optionsURL"); },
967 get opType () { return this.get_rdf_property("opType"); },
968 get plugin () { return this.get_rdf_property("plugin"); },
969 get previewImage () { return this.get_rdf_property("previewImage"); },
970 get satisfiesDependencies () { return this.get_rdf_property("satisfiesDependencies"); },
971 get providesUpdatesSecurely () { return this.get_rdf_property("providesUpdatesSecurely"); },
972 get type () { return this.get_rdf_property("type", Ci.nsIRDFInt); },
973 get updateable () { return this.get_rdf_property("updateable"); },
974 get updateURL () { return this.get_rdf_property("updateURL"); },
975 get version () { return this.get_rdf_property("version"); }
978 function extension_is_enabled(id) {
979 var info = new extension_info(id);
980 return info.update_item && (info.isDisabled == "false");
983 function for_each_frame(root_frame, callback, start_with) {
985 callback(start_with);
990 for (let i = 0; i < f.frames.length; ++i) {
997 // Co-routine version of for_each_frame
998 function co_for_each_frame(root_frame, callback, start_with) {
1000 yield callback(start_with);
1001 function helper(f) {
1002 if (f == start_with)
1005 for (let i = 0; i < f.frames.length; ++i) {
1006 yield helper(f.frames[i]);
1009 yield helper(root_frame);
1012 function xml_http_request() {
1013 return Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest).QueryInterface(Ci.nsIJSXMLHttpRequest).QueryInterface(Ci.nsIDOMEventTarget);
1016 var xml_http_request_load_listener = {
1017 // nsIBadCertListener2
1018 notifyCertProblem: function SSLL_certProblem(socketInfo, status, targetSite) {
1022 // nsISSLErrorListener
1023 notifySSLError: function SSLL_SSLError(socketInfo, error, targetSite) {
1027 // nsIInterfaceRequestor
1028 getInterface: function SSLL_getInterface(iid) {
1029 return this.QueryInterface(iid);
1034 // FIXME: array comprehension used here to hack around the lack of
1035 // Ci.nsISSLErrorListener in 2007 versions of xulrunner 1.9pre.
1036 // make it a simple generateQI when xulrunner is more stable.
1037 QueryInterface: XPCOMUtils.generateQI (
1038 [i for each (i in [Ci.nsIBadCertListener2,
1039 Ci.nsISSLErrorListener,
1040 Ci.nsIInterfaceRequestor])
1045 define_keywords("$user", "$password", "$override_mime_type", "$headers");
1046 function send_http_request(lspec) {
1047 keywords(arguments, $user = undefined, $password = undefined,
1048 $override_mime_type = undefined, $headers = undefined);
1049 var req = xml_http_request();
1050 var cc = yield CONTINUATION;
1051 req.onreadystatechange = function () {
1052 if (req.readyState != 4)
1057 if (arguments.$override_mime_type)
1058 req.overrideMimeType(arguments.$override_mime_type);
1060 var post_data = load_spec_raw_post_data(lspec);
1062 var method = post_data ? "POST" : "GET";
1064 req.open(method, load_spec_uri_string(lspec), true, arguments.$user, arguments.$password);
1065 req.channel.notificationCallbacks = xml_http_request_load_listener;
1067 for each (let [name,value] in arguments.$headers) {
1068 req.setRequestHeader(name, value);
1072 req.setRequestHeader("Content-Type", load_spec_request_mime_type(lspec));
1073 req.send(post_data);
1084 // Let the caller access the status and reponse data
1085 yield co_return(req);
1089 var JSON = ("@mozilla.org/dom/json;1" in Cc) && Cc["@mozilla.org/dom/json;1"].createInstance(Ci.nsIJSON);