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) {
62 function string_hashmap() {
65 string_hashmap.prototype = {
66 constructor : string_hashmap,
68 put : function(s,value) {
69 this["-" + s] = value;
72 contains : function(s) {
73 return (("-" + s) in this);
76 get : function(s, default_value) {
82 get_put_default : function(s, default_value) {
85 return (this["-" + s] = default_value);
88 remove : function (s) {
92 for_each : function (f) {
95 f(i.slice(1), this[i]);
99 for_each_value : function (f) {
100 for (var i in this) {
106 iterator: function (only_keys) {
108 for (let k in Iterator(this, true)) {
113 for (let [k,v] in Iterator(this, false)) {
115 yield [k.slice(1),v];
121 /// Window title formatting
124 * Default tile formatter. The page url is ignored. If there is a
125 * page_title, returns: "Page title - Conkeror". Otherwise, it
126 * returns just: "Conkeror".
128 function default_title_formatter (window)
130 var page_title = window.buffers.current.title;
132 if (page_title && page_title.length > 0)
133 return page_title + " - Conkeror";
138 var title_format_fn = null;
140 function set_window_title (window)
142 window.document.title = title_format_fn(window);
145 function init_window_title ()
147 title_format_fn = default_title_formatter;
149 add_hook("window_initialize_late_hook", set_window_title);
150 add_hook("current_content_buffer_location_change_hook",
152 set_window_title(buffer.window);
154 add_hook("select_buffer_hook", function (buffer) { set_window_title(buffer.window); }, true);
155 add_hook("current_buffer_title_change_hook",
157 set_window_title(buffer.window);
161 init_window_title ();
166 // Put the string on the clipboard
167 function writeToClipboard(str)
169 const gClipboardHelper = Components.classes["@mozilla.org/widget/clipboardhelper;1"]
170 .getService(Components.interfaces.nsIClipboardHelper);
171 gClipboardHelper.copyString(str);
175 function makeURLAbsolute (base, url)
178 var ioService = Components.classes["@mozilla.org/network/io-service;1"]
179 .getService(Components.interfaces.nsIIOService);
180 var baseURI = ioService.newURI(base, null, null);
182 return ioService.newURI (baseURI.resolve (url), null, null).spec;
186 function get_link_location (element)
188 if (element && element.getAttribute("href")) {
189 var loc = element.getAttribute("href");
190 return makeURLAbsolute(element.baseURI, loc);
196 var io_service = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
198 function make_uri(uri, charset, base_uri) {
199 if (uri instanceof Ci.nsIURI)
201 return io_service.newURI(uri, charset, base_uri);
204 var makeURL = make_uri; // until all callers are fixed
206 function makeFileURL(aFile)
208 return io_service.newFileURI(aFile).QueryInterface(Ci.nsIURL);
212 function get_document_content_disposition (document_o)
214 var content_disposition = null;
216 content_disposition =
217 document_o.defaultView
218 .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
219 .getInterface(Components.interfaces.nsIDOMWindowUtils)
220 .getDocumentMetadata("content-disposition");
222 return content_disposition;
226 function set_focus_no_scroll(window, element)
228 window.document.commandDispatcher.suppressFocusScroll = true;
230 window.document.commandDispatcher.suppressFocusScroll = false;
233 function do_repeatedly_positive(func, n) {
234 var args = Array.prototype.slice.call(arguments, 2);
236 func.apply(null, args);
239 function do_repeatedly(func, n, positive_args, negative_args) {
241 do func.apply(null, negative_args); while (++n < 0);
243 while (n-- > 0) func.apply(null, positive_args);
246 // remove whitespace from the beginning and end
247 function trim_whitespace (str)
249 var tmp = new String (str);
250 return tmp.replace (/^\s+/, "").replace (/\s+$/, "");
253 function abs_point (node)
258 pt.x = node.offsetLeft;
259 pt.y = node.offsetTop;
260 // find imagemap's coordinates
261 if (node.tagName == "AREA") {
262 var coords = node.getAttribute("coords").split(",");
263 pt.x += Number(coords[0]);
264 pt.y += Number(coords[1]);
267 node = node.offsetParent;
268 // Sometimes this fails, so just return what we got.
270 while (node.tagName != "BODY") {
271 pt.x += node.offsetLeft;
272 pt.y += node.offsetTop;
273 node = node.offsetParent;
277 // while (node.tagName != "BODY") {
278 // alert("okay: " + node + " " + node.tagName + " " + pt.x + " " + pt.y);
279 // node = node.offsetParent;
285 var xul_app_info = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo);
286 var xul_runtime = Cc['@mozilla.org/xre/app-info;1'].getService(Ci.nsIXULRuntime);
291 // possible return values: 'Darwin', 'Linux', 'WINNT', ...
292 return xul_runtime.OS;
295 var default_directory = null;
297 var env = Cc['@mozilla.org/process/environment;1'].getService(Ci.nsIEnvironment);
298 function getenv (variable) {
299 if (env.exists (variable))
300 return env.get(variable);
304 function set_default_directory(directory_s) {
307 if ( get_os() == "WINNT")
309 directory_s = getenv ('USERPROFILE') ||
310 getenv ('HOMEDRIVE') + getenv ('HOMEPATH');
313 directory_s = getenv ('HOME');
317 default_directory = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
318 default_directory.initWithPath (directory_s);
321 set_default_directory();
323 const XHTML_NS = "http://www.w3.org/1999/xhtml";
324 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
325 const MATHML_NS = "http://www.w3.org/1998/Math/MathML";
326 const XLINK_NS = "http://www.w3.org/1999/xlink";
328 function create_XUL(window, tag_name)
330 return window.document.createElementNS(XUL_NS, tag_name);
334 /* Used in calls to XPath evaluate */
335 function xpath_lookup_namespace(prefix) {
336 if (prefix == "xhtml")
345 function method_caller(obj, func) {
347 func.apply(obj, arguments);
351 function shell_quote(str) {
352 var s = str.replace("\"", "\\\"", "g");
353 s = s.replace("$", "\$", "g");
357 function get_window_from_frame(frame) {
359 var window = frame.QueryInterface(Ci.nsIInterfaceRequestor)
360 .getInterface(Ci.nsIWebNavigation)
361 .QueryInterface(Ci.nsIDocShellTreeItem)
363 .QueryInterface(Ci.nsIInterfaceRequestor)
364 .getInterface(Ci.nsIDOMWindow).wrappedJSObject;
365 /* window is now an XPCSafeJSObjectWrapper */
366 window.escape_wrapper(function (w) { window = w; });
367 /* window is now completely unwrapped */
374 function get_buffer_from_frame(window, frame) {
375 var count = window.buffers.count;
376 for (var i = 0; i < count; ++i) {
377 var b = window.buffers.get_buffer(i);
378 if (b.top_frame == frame)
384 var file_locator = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
386 function get_shortdoc_string(doc) {
389 var idx = doc.indexOf("\n");
391 shortdoc = doc.substring(0,idx);
398 var conkeror_source_code_path = null;
400 function source_code_reference(uri, line_number) {
402 this.line_number = line_number;
404 source_code_reference.prototype = {
406 if (this.uri.indexOf(module_uri_prefix) == 0)
407 return this.uri.substring(module_uri_prefix.length);
412 var file_uri_prefix = "file://";
413 if (this.uri.indexOf(file_uri_prefix) == 0)
414 return this.uri.substring(file_uri_prefix.length);
419 if (conkeror_source_code_path != null) {
420 var module_name = this.module_name;
421 if (module_name != null)
422 return "file://" + conkeror_source_code_path + "/modules/" + module_name;
427 open_in_editor : function() {
428 yield open_with_external_editor(this.best_uri, $line = this.line_number);
432 var get_caller_source_code_reference_ignored_functions = {};
434 function get_caller_source_code_reference(extra_frames_back) {
435 /* Skip at least this function itself and whoever called it (and
436 * more if the caller wants to be skipped). */
437 var frames_to_skip = 2;
438 if (extra_frames_back != null)
439 frames_to_skip += extra_frames_back;
441 for (let f = Components.stack; f != null; f = f.caller) {
442 if (frames_to_skip > 0) {
446 if (get_caller_source_code_reference_ignored_functions[f.name])
448 return new source_code_reference(f.filename, f.lineNumber);
454 function ignore_function_for_get_caller_source_code_reference(func_name) {
455 get_caller_source_code_reference_ignored_functions[func_name] = 1;
458 require_later("external-editor.js");
460 function dom_generator(document, ns) {
461 this.document = document;
464 dom_generator.prototype = {
465 element : function(tag, parent) {
466 var node = this.document.createElementNS(this.ns, tag);
468 if (parent != null && (parent instanceof Ci.nsIDOMNode)) {
469 parent.appendChild(node);
472 for (; i < arguments.length; i += 2)
473 node.setAttribute(arguments[i], arguments[i+1]);
477 text : function(str, parent) {
478 var node = this.document.createTextNode(str);
480 parent.appendChild(node);
485 stylesheet_link : function(href, parent) {
486 var node = this.element("link");
487 node.setAttribute("rel", "stylesheet");
488 node.setAttribute("type", "text/css");
489 node.setAttribute("href", href);
491 parent.appendChild(node);
496 add_stylesheet : function (url) {
497 var head = this.document.documentElement.firstChild;
498 this.stylesheet_link(url, head);
503 * Generates a QueryInterface function suitable for an implemenation
504 * of an XPCOM interface. Unlike XPCOMUtils, this uses the Function
505 * constructor to generate a slightly more efficient version. The
506 * arguments can be either Strings or elements of
507 * Components.interfaces.
509 function generate_QI() {
510 var args = Array.prototype.slice.call(arguments).map(String).concat(["nsISupports"]);
512 Array.prototype.map.call(args,
514 "iid.equals(Components.interfaces." + x + ")")
516 ") return this; throw Components.results.NS_ERROR_NO_INTERFACE;";
517 return new Function("iid", fstr);
520 function set_branch_pref(branch, name, value) {
521 if (typeof(value) == "string") {
522 branch.setCharPref(name, value);
523 } else if (typeof(value) == "number") {
524 branch.setIntPref(name, value);
525 } else if (typeof(value) == "boolean") {
526 branch.setBoolPref(name, value);
530 function default_pref(name, value) {
531 var branch = preferences.getDefaultBranch(null);
532 set_branch_pref(branch, name, value);
535 function user_pref(name, value) {
536 var branch = preferences.getBranch(null);
537 set_branch_pref(branch, name, value);
540 function get_branch_pref(branch, name) {
541 switch (branch.getPrefType(name)) {
542 case branch.PREF_STRING:
543 return branch.getCharPref(name);
544 case branch.PREF_INT:
545 return branch.getIntPref(name);
546 case branch.PREF_BOOL:
547 return branch.getBoolPref(name);
553 function get_localized_pref(name) {
555 return preferences.getBranch(null).getComplexValue(name, Ci.nsIPrefLocalizedString).data;
561 function get_pref(name) {
562 var branch = preferences.getBranch(null);
563 return get_branch_pref(branch, name);
566 function get_default_pref(name) {
567 var branch = preferences.getDefaultBranch(null);
568 return get_branch_pref(branch, name);
571 function clear_pref(name) {
572 var branch = preferences.getBranch(null);
573 return branch.clearUserPref(name);
576 function pref_has_user_value(name) {
577 var branch = preferences.getBranch(null);
578 return branch.prefHasUserValue(name);
581 function pref_has_default_value(name) {
582 var branch = preferences.getDefaultBranch(null);
583 return branch.prefHasUserValue(name);
586 function session_pref (name, value) {
587 try { clear_pref (name); }
589 return default_pref (name, value);
592 const LOCALE_PREF = "general.useragent.locale";
594 function get_locale() {
595 return get_localized_pref(LOCALE_PREF) || get_pref(LOCALE_PREF);
598 const USER_AGENT_OVERRIDE_PREF = "general.useragent.override";
600 function set_user_agent(str) {
601 session_pref(USER_AGENT_OVERRIDE_PREF, str);
604 function define_builtin_commands(prefix, do_command_function, toggle_mark, mark_active_predicate) {
606 // Specify a docstring
607 function D(cmd, docstring) {
608 var o = new String(cmd);
613 // Specify a forward/reverse pair
616 o.is_reverse_pair = true;
620 // Specify a movement/select command pair.
621 function S(command, movement, select) {
622 var o = [movement, select];
624 o.is_move_select_pair = true;
628 var builtin_commands = [
629 S(D("beginning-of-line", "Move or extend the selection to the beginning of the current line."),
630 D("cmd_beginLine", "Move point to the beginning of the current line."),
631 D("cmd_selectBeginLine", "Extend selection to the beginning of the current line.")),
632 S(D("end-of-line", "Move or extend the selection to the end of the current line."),
633 D("cmd_endLine", "Move point to the end of the current line."),
634 D("cmd_selectEndLine", "Extend selection to the end of the current line.")),
635 D("cmd_copy", "Copy the selection into the clipboard."),
637 D("cmd_cut", "Cut the selection into the clipboard."),
639 D("cmd_deleteToBeginningOfLine", "Delete to the beginning of the current line."),
640 D("cmd_deleteToEndOfLine", "Delete to the end of the current line."),
641 S(D("beginning-of-first-line", "Move or extend the selection to the beginning of the first line."),
642 D("cmd_moveTop", "Move point to the beginning of the first line."),
643 D("cmd_selectTop", "Extend selection to the beginning of the first line.")),
644 S(D("end-of-last-line", "Move or extend the selection to the end of the last line."),
645 D("cmd_moveBottom", "Move point to the end of the last line."),
646 D("cmd_selectBottom", "Extend selection to the end of the last line.")),
647 D("cmd_selectAll", "Select all."),
648 "cmd_scrollBeginLine",
650 D("cmd_scrollTop", "Scroll to the top of the buffer."),
651 D("cmd_scrollBottom", "Scroll to the bottom of the buffer.")];
653 var builtin_commands_with_count = [
654 R(S(D("forward-char", "Move or extend the selection forward one character."),
655 D("cmd_charNext", "Move point forward one character."),
656 D("cmd_selectCharNext", "Extend selection forward one character.")),
657 S(D("backward-char", "Move or extend the selection backward one character."),
658 D("cmd_charPrevious", "Move point backward one character."),
659 D("cmd_selectCharPrevious", "Extend selection backward one character."))),
660 R(D("cmd_deleteCharForward", "Delete the following character."),
661 D("cmd_deleteCharBackward", "Delete the previous character.")),
662 R(D("cmd_deleteWordForward", "Delete the following word."),
663 D("cmd_deleteWordBackward", "Delete the previous word.")),
664 R(S(D("forward-line", "Move or extend the selection forward one line."),
665 D("cmd_lineNext", "Move point forward one line."),
666 "cmd_selectLineNext", "Extend selection forward one line."),
667 S(D("backward-line", "Move or extend the selection backward one line."),
668 D("cmd_linePrevious", "Move point backward one line."),
669 D("cmd_selectLinePrevious", "Extend selection backward one line."))),
670 R(S(D("forward-page", "Move or extend the selection forward one page."),
671 D("cmd_movePageDown", "Move point forward one page."),
672 D("cmd_selectPageDown", "Extend selection forward one page.")),
673 S(D("backward-page", "Move or extend the selection backward one page."),
674 D("cmd_movePageUp", "Move point backward one page."),
675 D("cmd_selectPageUp", "Extend selection backward one page."))),
676 R(D("cmd_undo", "Undo last editing action."),
677 D("cmd_redo", "Redo last editing action.")),
678 R(S(D("forward-word", "Move or extend the selection forward one word."),
679 D("cmd_wordNext", "Move point forward one word."),
680 D("cmd_selectWordNext", "Extend selection forward one word.")),
681 S(D("backward-word", "Move or extend the selection backward one word."),
682 D("cmd_wordPrevious", "Move point backward one word."),
683 D("cmd_selectWordPrevious", "Extend selection backward one word."))),
684 R(D("cmd_scrollPageUp", "Scroll up one page."),
685 D("cmd_scrollPageDown", "Scroll down one page.")),
686 R(D("cmd_scrollLineUp", "Scroll up one line."),
687 D("cmd_scrollLineDown", "Scroll down one line.")),
688 R(D("cmd_scrollLeft", "Scroll left."),
689 D("cmd_scrollRight", "Scroll right.")),
690 D("cmd_paste", "Insert the contents of the clipboard.")];
692 interactive(prefix + "set-mark",
693 "Toggle whether the mark is active.\n" +
694 "When the mark is active, movement commands affect the selection.",
697 function doc_for_builtin(c) {
701 return s + "Run the built-in command " + c + ".";
704 function define_simple_command(c) {
705 interactive(prefix + c, doc_for_builtin(c), function (I) { do_command_function(I, c); });
708 function get_move_select_doc_string(c) {
709 return c.command.doc +
710 "\nSpecifically, if the mark is inactive, runs `" + prefix + c[0] + "'. " +
711 "Otherwise, runs `" + prefix + c[1] + "'.\n" +
712 "To toggle whether the mark is active, use `" + prefix + "set-mark'.";
715 for each (let c_temp in builtin_commands) {
717 if (c.is_move_select_pair) {
718 interactive(prefix + c.command, get_move_select_doc_string(c), function (I) {
719 do_command_function(I, mark_active_predicate(I) ? c[1] : c[0]);
721 define_simple_command(c[0]);
722 define_simple_command(c[1]);
725 define_simple_command(c);
728 function get_reverse_pair_doc_string(main_doc, alt_command) {
729 return main_doc + "\n" +
730 "The prefix argument specifies a repeat count for this command. " +
731 "If the count is negative, `" + prefix + alt_command + "' is performed instead with " +
732 "a corresponding positive repeat count.";
735 function define_simple_reverse_pair(a, b) {
736 interactive(prefix + a, get_reverse_pair_doc_string(doc_for_builtin(a), b),
738 do_repeatedly(do_command_function, I.p, [I, a], [I, b]);
740 interactive(prefix + b, get_reverse_pair_doc_string(doc_for_builtin(b), a),
742 do_repeatedly(do_command_function, I.p, [I, b], [I, a]);
746 for each (let c_temp in builtin_commands_with_count)
749 if (c.is_reverse_pair) {
750 if (c[0].is_move_select_pair) {
751 interactive(prefix + c[0].command, get_reverse_pair_doc_string(get_move_select_doc_string(c[0]),
754 var idx = mark_active_predicate(I) ? 1 : 0;
755 do_repeatedly(do_command_function, I.p, [I, c[0][idx]], [I, c[1][idx]]);
757 interactive(prefix + c[1].command, get_reverse_pair_doc_string(get_move_select_doc_string(c[1]),
760 var idx = mark_active_predicate(I) ? 1 : 0;
761 do_repeatedly(do_command_function, I.p, [I, c[1][idx]], [I, c[0][idx]]);
763 define_simple_reverse_pair(c[0][0], c[1][0]);
764 define_simple_reverse_pair(c[0][1], c[1][1]);
766 define_simple_reverse_pair(c[0], c[1]);
768 let doc = doc_for_builtin(c) +
769 "\nThe prefix argument specifies a positive repeat count for this command.";
770 interactive(prefix + c, doc, function (I) {
771 do_repeatedly_positive(do_command_function, I.p, I, c);
777 var observer_service = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
779 function abort(str) {
780 var e = new Error(str);
781 e.__proto__ = abort.prototype;
784 abort.prototype.__proto__ = Error.prototype;
787 function get_temporary_file(name) {
790 var file = file_locator.get("TmpD", Ci.nsIFile);
792 // Create the file now to ensure that no exploits are possible
793 file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0600);
798 /* FIXME: This should be moved somewhere else, perhaps. */
799 function create_info_panel(window, panel_class, row_arr) {
800 /* Show information panel above minibuffer */
802 var g = new dom_generator(window.document, XUL_NS);
804 var p = g.element("vbox", "class", "panel " + panel_class, "flex", "0");
805 var grid = g.element("grid", p);
806 var cols = g.element("columns", grid);
807 g.element("column", cols, "flex", "0");
808 g.element("column", cols, "flex", "1");
810 var rows = g.element("rows", grid);
813 for each (let [row_class, row_label, row_value] in row_arr) {
814 row = g.element("row", rows, "class", row_class);
815 g.element("label", row,
817 "class", "panel-row-label");
818 g.element("label", row,
820 "class", "panel-row-value");
822 window.minibuffer.insert_before(p);
824 p.destroy = function () {
825 this.parentNode.removeChild(this);
832 // read_from_x_primary_selection favors the X PRIMARY SELECTION, when
833 // it exists. The builtin cmd_paste always uses X CLIPBOARD. So this
834 // is an auxiliary utility, in case you need to work with the primary
837 function read_from_x_primary_selection ()
840 var clipboard = Components.classes["@mozilla.org/widget/clipboard;1"]
841 .getService(Components.interfaces.nsIClipboard);
843 // Create tranferable that will transfer the text.
844 var trans = Components.classes["@mozilla.org/widget/transferable;1"]
845 .createInstance(Components.interfaces.nsITransferable);
847 trans.addDataFlavor("text/unicode");
848 // If available, use selection clipboard, otherwise global one
849 if (clipboard.supportsSelectionClipboard())
850 clipboard.getData(trans, clipboard.kSelectionClipboard);
852 clipboard.getData(trans, clipboard.kGlobalClipboard);
856 trans.getTransferData("text/unicode", data, dataLen);
859 data = data.value.QueryInterface(Components.interfaces.nsISupportsString);
860 return data.data.substring(0, dataLen.value / 2);
866 var user_variables = new string_hashmap();
868 function define_variable(name, default_value, doc) {
869 conkeror[name] = default_value;
870 user_variables.put(name, {
871 default_value: default_value,
873 shortdoc: get_shortdoc_string(doc),
874 source_code_reference: get_caller_source_code_reference() });
878 function register_user_stylesheet(url)
880 var uri = makeURL(url);
881 var sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService);
882 sss.loadAndRegisterSheet(uri, sss.USER_SHEET);
885 function unregister_user_stylesheet(url)
887 var uri = makeURL(url);
888 var sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService);
889 if (sss.sheetRegistered(uri, sss.USER_SHEET))
890 ss.unregisterSheet(uri, sss.USER_SHEET);
893 function predicate_alist_match(alist, key) {
894 for each (let i in alist) {
902 function get_meta_title(doc) {
903 var title = doc.evaluate("//meta[@name='title']/@content", doc, xpath_lookup_namespace,
904 Ci.nsIDOMXPathResult.STRING_TYPE , null);
905 if (title && title.stringValue)
906 return title.stringValue;
910 var rdf_service = Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService);
912 const PREFIX_ITEM_URI = "urn:mozilla:item:";
913 const PREFIX_NS_EM = "http://www.mozilla.org/2004/em-rdf#";
915 var extension_manager = Cc["@mozilla.org/extensions/manager;1"].getService(Ci.nsIExtensionManager);
917 function get_extension_rdf_property(id, name, type) {
918 var value = extension_manager.datasource.GetTarget(
919 rdf_service.GetResource(PREFIX_ITEM_URI + id),
920 rdf_service.GetResource(PREFIX_NS_EM + name),
924 return value.QueryInterface(type || Ci.nsIRDFLiteral).Value;
927 function get_extension_update_item(id) {
928 return extension_manager.getItemForID(id);
931 function extension_info(id) {
934 extension_info.prototype = {
935 // Returns the nsIUpdateItem object associated with this extension
936 get update_item () { return get_extension_update_item(this.id); },
938 get_rdf_property : function (name, type) {
939 return get_extension_rdf_property(this.id, name, type);
943 get isDisabled () { return this.get_rdf_property("isDisabled"); },
944 get aboutURL () { return this.get_rdf_property("aboutURL"); },
945 get addonID () { return this.get_rdf_property("addonID"); },
946 get availableUpdateURL () { return this.get_rdf_property("availableUpdateURL"); },
947 get availableUpdateVersion () { return this.get_rdf_property("availableUpdateVersion"); },
948 get blocklisted () { return this.get_rdf_property("blocklisted"); },
949 get compatible () { return this.get_rdf_property("compatible"); },
950 get description () { return this.get_rdf_property("description"); },
951 get downloadURL () { return this.get_rdf_property("downloadURL"); },
952 get isDisabled () { return this.get_rdf_property("isDisabled"); },
953 get hidden () { return this.get_rdf_property("hidden"); },
954 get homepageURL () { return this.get_rdf_property("homepageURL"); },
955 get iconURL () { return this.get_rdf_property("iconURL"); },
956 get internalName () { return this.get_rdf_property("internalName"); },
957 get locked () { return this.get_rdf_property("locked"); },
958 get name () { return this.get_rdf_property("name"); },
959 get optionsURL () { return this.get_rdf_property("optionsURL"); },
960 get opType () { return this.get_rdf_property("opType"); },
961 get plugin () { return this.get_rdf_property("plugin"); },
962 get previewImage () { return this.get_rdf_property("previewImage"); },
963 get satisfiesDependencies () { return this.get_rdf_property("satisfiesDependencies"); },
964 get providesUpdatesSecurely () { return this.get_rdf_property("providesUpdatesSecurely"); },
965 get type () { return this.get_rdf_property("type", Ci.nsIRDFInt); },
966 get updateable () { return this.get_rdf_property("updateable"); },
967 get updateURL () { return this.get_rdf_property("updateURL"); },
968 get version () { return this.get_rdf_property("version"); }
971 function extension_is_enabled(id) {
972 var info = new extension_info(id);
973 return info.update_item && (info.isDisabled == "false");
976 function for_each_frame(root_frame, callback, start_with) {
978 callback(start_with);
983 for (let i = 0; i < f.frames.length; ++i) {
990 // Co-routine version of for_each_frame
991 function co_for_each_frame(root_frame, callback, start_with) {
993 yield callback(start_with);
998 for (let i = 0; i < f.frames.length; ++i) {
999 yield helper(f.frames[i]);
1002 yield helper(root_frame);
1005 function xml_http_request() {
1006 return Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest).QueryInterface(Ci.nsIJSXMLHttpRequest).QueryInterface(Ci.nsIDOMEventTarget);
1009 var xml_http_request_load_listener = {
1010 // nsIBadCertListener2
1011 notifyCertProblem: function SSLL_certProblem(socketInfo, status, targetSite) {
1015 // nsISSLErrorListener
1016 notifySSLError: function SSLL_SSLError(socketInfo, error, targetSite) {
1020 // nsIInterfaceRequestor
1021 getInterface: function SSLL_getInterface(iid) {
1022 return this.QueryInterface(iid);
1026 QueryInterface: XPCOMUtils.generateQI([Ci.nsIBadCertListener2,
1027 Ci.nsISSLErrorListener,
1028 Ci.nsIInterfaceRequestor])
1032 define_keywords("$user", "$password", "$override_mime_type", "$headers");
1033 function send_http_request(lspec) {
1034 keywords(arguments, $user = undefined, $password = undefined,
1035 $override_mime_type = undefined, $headers = undefined);
1036 var req = xml_http_request();
1037 var cc = yield CONTINUATION;
1038 req.onreadystatechange = function () {
1039 if (req.readyState != 4)
1044 if (arguments.$override_mime_type)
1045 req.overrideMimeType(arguments.$override_mime_type);
1047 var post_data = load_spec_raw_post_data(lspec);
1049 var method = post_data ? "POST" : "GET";
1051 req.open(method, load_spec_uri_string(lspec), true, arguments.$user, arguments.$password);
1052 req.channel.notificationCallbacks = xml_http_request_load_listener;
1054 for each (let [name,value] in arguments.$headers) {
1055 req.setRequestHeader(name, value);
1059 req.setRequestHeader("Content-Type", load_spec_request_mime_type(lspec));
1060 req.send(post_data);
1071 // Let the caller access the status and reponse data
1072 yield co_return(req);
1076 var JSON = ("@mozilla.org/dom/json;1" in Cc) && Cc["@mozilla.org/dom/json;1"].createInstance(Ci.nsIJSON);