diff --git a/common/components/protocols.js b/common/components/protocols.js index 450c346e..2dd50338 100644 --- a/common/components/protocols.js +++ b/common/components/protocols.js @@ -152,8 +152,9 @@ Liberator.prototype = { } }; -var components = [ChromeData, Liberator]; - -function NSGetModule(compMgr, fileSpec) XPCOMUtils.generateModule(components) +if (XPCOMUtils.generateNSGetFactory) + const NSGetFactory = XPCOMUtils.generateNSGetFactory([ChromeData, Liberator]); +else + const NSGetModule = XPCOMUtils.generateNSGetModule([ChromeData, Liberator]); // vim: set fdm=marker sw=4 ts=4 et: diff --git a/common/content/buffer.js b/common/content/buffer.js index 4a6d4266..b73e718f 100644 --- a/common/content/buffer.js +++ b/common/content/buffer.js @@ -1517,7 +1517,7 @@ const Buffer = Module("buffer", { function () { let url = util.readFromClipboard(); liberator.assert(url); - liberator.open(url, { from: "activate", where: liberator.NEW_TAB }); + liberator.open(url, { from: "paste", where: liberator.NEW_TAB }); }); // reloading diff --git a/common/content/commandline.js b/common/content/commandline.js index 8ee48769..78db2968 100644 --- a/common/content/commandline.js +++ b/common/content/commandline.js @@ -1134,7 +1134,7 @@ const CommandLine = Module("commandline", { let str = commandline.command; return str.substring(this.prefix.length, str.length - this.suffix.length); }, - set completion set_completion(completion) { + set completion(completion) { this.previewClear(); // Change the completion text. diff --git a/common/content/hints.js b/common/content/hints.js index 60babe15..ca0037f4 100644 --- a/common/content/hints.js +++ b/common/content/hints.js @@ -47,7 +47,7 @@ const Hints = Module("hints", { t: Mode("Follow hint in a new tab", function (elem) buffer.followLink(elem, liberator.NEW_TAB)), b: Mode("Follow hint in a background tab", function (elem) buffer.followLink(elem, liberator.NEW_BACKGROUND_TAB)), w: Mode("Follow hint in a new window", function (elem) buffer.followLink(elem, liberator.NEW_WINDOW), extended), - F: Mode("Open multiple hints in tabs", followAndReshow), + F: Mode("Open multiple hints in tabs", function (elem) { buffer.followLink(elem, liberator.NEW_BACKGROUND_TAB); hints.show("F") }), O: Mode("Generate an ':open URL' using hint", function (elem, loc) commandline.open(":", "open " + loc, modes.EX)), T: Mode("Generate a ':tabopen URL' using hint", function (elem, loc) commandline.open(":", "tabopen " + loc, modes.EX)), W: Mode("Generate a ':winopen URL' using hint", function (elem, loc) commandline.open(":", "winopen " + loc, modes.EX)), @@ -59,21 +59,6 @@ const Hints = Module("hints", { i: Mode("Show image", function (elem) liberator.open(elem.src), images), I: Mode("Show image in a new tab", function (elem) liberator.open(elem.src, liberator.NEW_TAB), images) }; - - /** - * Follows the specified hint and then reshows all hints. Used to open - * multiple hints in succession. - * - * @param {Node} elem The selected hint. - */ - function followAndReshow(elem) { - buffer.followLink(elem, liberator.NEW_BACKGROUND_TAB); - - // TODO: Maybe we find a *simple* way to keep the hints displayed rather than - // showing them again, or is this short flash actually needed as a "usability - // feature"? --mst - hints.show("F"); - } }, /** @@ -129,7 +114,7 @@ const Hints = Module("hints", { let type = elem.type; - if (elem instanceof HTMLInputElement && /(submit|button|this._reset)/.test(type)) + if (elem instanceof HTMLInputElement && /(submit|button|reset)/.test(type)) return [elem.value, false]; else { for (let [, option] in Iterator(options["hintinputs"].split(","))) { @@ -272,10 +257,6 @@ const Hints = Module("hints", { if (!rect || rect.top > height || rect.bottom < 0 || rect.left > width || rect.right < 0) continue; - rect = elem.getClientRects()[0]; - if (!rect) - continue; - let computedStyle = doc.defaultView.getComputedStyle(elem, null); if (computedStyle.getPropertyValue("visibility") != "visible" || computedStyle.getPropertyValue("display") == "none") continue; @@ -396,7 +377,7 @@ const Hints = Module("hints", { } } - if (config.browser.markupDocumentViewer.authorStyleDisabled) { + if (options["usermode"]) { let css = []; // FIXME: Broken for imgspans. for (let [, { doc: doc }] in Iterator(this._docs)) { diff --git a/common/content/liberator.js b/common/content/liberator.js index 1390a84c..60d68847 100644 --- a/common/content/liberator.js +++ b/common/content/liberator.js @@ -270,7 +270,7 @@ const Liberator = Module("liberator", { let stack = Error().stack.replace(/(?:.*\n){2}/, ""); if (frames != null) [stack] = stack.match(RegExp("(?:.*\n){0," + frames + "}")); - liberator.dump((msg || "Stack") + "\n" + stack); + liberator.dump((msg || "Stack") + "\n" + stack + "\n"); }, /** @@ -769,7 +769,7 @@ const Liberator = Module("liberator", { flags |= Ci.nsIWebNavigation["LOAD_FLAGS_" + flag]; let where = params.where || liberator.CURRENT_TAB; - let background = ("background" in params) ? params.background : params.where == NEW_BACKGROUND_TAB; + let background = ("background" in params) ? params.background : params.where == liberator.NEW_BACKGROUND_TAB; if ("from" in params && liberator.has("tabs")) { if (!('where' in params) && options.get("newtab").has("all", params.from)) where = liberator.NEW_TAB; @@ -1380,19 +1380,89 @@ const Liberator = Module("liberator", { } }); + /////////////////////////////////////////////////////////////////////////// + + if (typeof AddonManager == "undefined") { + modules.AddonManager = { + getInstallForFile: function (file, callback, mimetype) { + callback({ + install: function () { + services.get("extensionManager").installItemFromFile(file, "app-profile"); + } + }); + }, + getAddonById: function (id, callback) { + let addon = id; + if (!isobject(addon)) + addon = services.get("extensionManager").getItemForID(id); + if (!addon) + return callback(null); + + function getRdfProperty(item, property) { + let resource = services.get("rdf").GetResource("urn:mozilla:item:" + item.id); + let value = ""; + + if (resource) { + let target = services.get("extensionManager").datasource.GetTarget(resource, + services.get("rdf").GetResource("http://www.mozilla.org/2004/em-rdf#" + property), true); + if (target && target instanceof Ci.nsIRDFLiteral) + value = target.Value; + } + + return value; + } + + ["aboutURL", "creator", "description", "developers", + "homepageURL", "iconURL", "installDate", "name", + "optionsURL", "releaseNotesURI", "updateDate"].forEach(function (item) { + addon[item] = getRdfProperty(addon, item); + }); + addon.isActive = getRdfProperty(addon, "isDisabled") != "true"; + + addon.uninstall = function () { + services.get("extensionManager").uninstallItem(this.id); + }; + addon.appDisabled = false; + addon.__defineGetter("userDisabled", function() getRdfProperty("userDisabled") == "true"); + addon.__defineSetter__("userDisabled", function(val) { + services.get("extensionManager")[val ? "enableItem" : "disableItem"](this.id); + }); + + return callback(addon); + }, + getAddonsByTypes: function (types, callback) { + let res = []; + for (let [,type] in Iterator(types)) + for (let [,item] in Iterator(services.get("extensionManager") + .getItemList(Ci.nsIUpdateItem["TYPE_" + type.toUpperCase()], {}))) + res.append(this.getAddonById(item)); + return res; + } + }; + + } + + /////////////////////////////////////////////////////////////////////////// + + function callResult(method) { + let args = Array.slice(arguments, 1); + return function (result) { result[method].apply(result, args) }; + } + commands.add(["exta[dd]"], "Install an extension", function (args) { - let file = io.File(args[0]); - - if (file.exists() && file.isReadable() && file.isFile()) - services.get("extensionManager").installItemFromFile(file, "app-profile"); - else { - if (file.exists() && file.isDirectory()) - liberator.echomsg("Cannot install a directory: \"" + file.path + "\"", 0); + let url = args[0]; + let file = io.File(url); + if (!file.exists()) + AddonManager.getInstallForURL(url, callResult("install"), "application/x-xpinstall"); + else if (file.isReadable() && file.isFile()) + AddonManager.getInstallForFile(file, callResult("install"), "application/x-xpinstall"); + else if (file.isDirectory()) + liberator.echomsg("Cannot install a directory: \"" + file.path + "\"", 0); + else liberator.echoerr("E484: Can't open file " + file.path); - } }, { argCount: "1", completer: function (context) { @@ -1406,38 +1476,35 @@ const Liberator = Module("liberator", { { name: "extde[lete]", description: "Uninstall an extension", - action: "uninstallItem" + action: callResult("uninstall") }, { name: "exte[nable]", description: "Enable an extension", - action: "enableItem", - filter: function ({ item: e }) !e.enabled + action: function (addon) addon.userDisabled = false, + filter: function ({ item: e }) e.userDisabled }, { name: "extd[isable]", description: "Disable an extension", - action: "disableItem", - filter: function ({ item: e }) e.enabled + action: function (addon) addon.userDisabled = true, + filter: function ({ item: e }) !e.userDisabled } ].forEach(function (command) { commands.add([command.name], command.description, function (args) { let name = args[0]; - function action(e) { services.get("extensionManager")[command.action](e.id); }; - if (args.bang) - liberator.extensions.forEach(function (e) { action(e); }); - else { - liberator.assert(name, "E471: Argument required"); // XXX + liberator.assert(!name, "E488: Trailing characters"); + else + liberator.assert(name, "E471: Argument required"); - let extension = liberator.getExtension(name); - if (extension) - action(extension); - else - liberator.echoerr("E474: Invalid argument"); - } + AddonManager.getAddonsByTypes(["extension"], function (list) { + if (!args.bang) + list = list.filter(function (extension) extension.name == name); + list.forEach(command.action); + }); }, { argCount: "?", // FIXME: should be "1" bang: true, @@ -1453,19 +1520,21 @@ const Liberator = Module("liberator", { commands.add(["exto[ptions]", "extp[references]"], "Open an extension's preference dialog", function (args) { - let extension = liberator.getExtension(args[0]); - liberator.assert(extension && extension.options, - "E474: Invalid argument"); - if (args.bang) - window.openDialog(extension.options, "_blank", "chrome"); - else - liberator.open(extension.options, { from: "extoptions" }); + AddonManager.getAddonsByTypes(["extension"], function (list) { + list = list.filter(function (extension) extension.name == args[0]); + if (!list.length || !list[0].optionsURL) + liberator.echoerr("E474: Invalid argument"); + else if (args.bang) + window.openDialog(list[0].optionsURL, "_blank", "chrome"); + else + liberator.open(list[0].optionsURL, { from: "extoptions" }); + }); }, { argCount: "1", bang: true, completer: function (context) { completion.extension(context); - context.filters.push(function ({ item: e }) e.options); + context.filters.push(function ({ item: e }) e.isActive && e.optionsURL); }, literal: 0 }); @@ -1474,30 +1543,42 @@ const Liberator = Module("liberator", { commands.add(["extens[ions]"], "List available extensions", function (args) { - let filter = args[0] || ""; - let extensions = liberator.extensions.filter(function (e) e.name.indexOf(filter) >= 0); + AddonManager.getAddonsByTypes(["extension"], function (extensions) { + liberator.dump(extensions); + if (args[0]) + extensions = extensions.filter(function (extension) extension.name.indexOf(args[0]) >= 0); - if (extensions.length > 0) { - let list = template.tabular( - ["Name", "Version", "Status", "Description"], [], - ([template.icon(e, e.name), - e.version, - e.enabled ? enabled - : disabled, - e.description] for ([, e] in Iterator(extensions))) - ); + liberator.dump(extensions); + if (extensions.length > 0) { + let list = template.tabular( + ["Name", "Version", "Status", "Description"], [], + ([template.icon({ icon: e.iconURL }, e.name), + e.version, + (e.isActive ? enabled + : disabled) + + ((e.userDisabled || e.appDisabled) == !e.isActive ? XML() : + <> ({e.userDisabled || e.appDisabled + ? disabled + : enabled} + on restart) + ), + e.description] for ([, e] in Iterator(extensions))) + ); - commandline.echo(list, commandline.HL_NORMAL, commandline.FORCE_MULTILINE); - } - else { - if (filter) - liberator.echoerr("Exxx: No extension matching \"" + filter + "\""); - else - liberator.echoerr("No extensions installed"); - } + commandline.echo(list, commandline.HL_NORMAL, commandline.FORCE_MULTILINE); + } + else { + if (filter) + liberator.echoerr("Exxx: No extension matching \"" + filter + "\""); + else + liberator.echoerr("No extensions installed"); + } + }); }, { argCount: "?" }); + /////////////////////////////////////////////////////////////////////////// + commands.add(["exu[sage]"], "List all Ex commands with a short description", function (args) { Liberator.showHelpIndex("ex-cmd-index", commands, args.bang); }, { @@ -1759,8 +1840,12 @@ const Liberator = Module("liberator", { completion.extension = function extension(context) { context.title = ["Extension"]; context.anchored = false; - context.keys = { text: "name", description: "description", icon: "icon" }, - context.completions = liberator.extensions; + context.keys = { text: "name", description: "description", icon: "iconURL" }, + context.incomplete = true; + AddonManager.getAddonsByTypes(["extension"], function (addons) { + context.incomplete = false; + context.completions = addons; + }); }; completion.help = function help(context, unchunked) { diff --git a/common/content/services.js b/common/content/services.js index 20e73b48..ad056221 100644 --- a/common/content/services.js +++ b/common/content/services.js @@ -47,6 +47,9 @@ const Services = Module("services", { this.addClass("file:", "@mozilla.org/network/protocol;1?name=file", Ci.nsIFileProtocolHandler); this.addClass("find", "@mozilla.org/embedcomp/rangefind;1", Ci.nsIFind); this.addClass("process", "@mozilla.org/process/util;1", Ci.nsIProcess); + + if (!this.get("extensionManager")) + Components.utils.import("resource://gre/modules/AddonManager.jsm", modules); }, _create: function (classes, ifaces, meth) { diff --git a/common/content/tabs.js b/common/content/tabs.js index 6cd4083d..8373b858 100644 --- a/common/content/tabs.js +++ b/common/content/tabs.js @@ -797,14 +797,7 @@ const Tabs = Module("tabs", { commands.add(["tabopen", "t[open]", "tabnew"], "Open one or more URLs in a new tab", function (args) { - let special = args.bang; - args = args.string; - - let where = special ? liberator.NEW_TAB : liberator.NEW_BACKGROUND_TAB; - if (args) - liberator.open(args, { from: "tabopen", where: where }); - else - liberator.open("about:blank", { from: "tabopen", where: where }); + liberator.open(args.string || "about:blank", { from: "tabopen", where: liberator.NEW_TAB, background: args.bang }); }, { bang: true, completer: function (context) completion.url(context), diff --git a/common/content/util.js b/common/content/util.js index 172bbed6..a328ae20 100644 --- a/common/content/util.js +++ b/common/content/util.js @@ -779,7 +779,7 @@ const Util = Module("util", { * @param {Array} ary * @returns {Array} */ - flatten: function flatten(ary) Array.concat.apply([], ary), + flatten: function flatten(ary) ary.length ? Array.concat.apply([], ary) : [], /** * Returns an Iterator for an array's values. diff --git a/vimperator/chrome.manifest b/vimperator/chrome.manifest index 57ebfae3..4890933b 100644 --- a/vimperator/chrome.manifest +++ b/vimperator/chrome.manifest @@ -14,3 +14,16 @@ override chrome://liberator/content/config.js chrome://vimperator/content/conf overlay chrome://browser/content/browser.xul chrome://liberator/content/liberator.xul overlay chrome://browser/content/browser.xul chrome://vimperator/content/vimperator.xul +component components/ + +component {81495d80-89ee-4c36-a88d-ea7c4e5ac63f} components/about-handler.js +contract @mozilla.org/network/protocol/about;1?what=vimperator {81495d80-89ee-4c36-a88d-ea7c4e5ac63f} + +component {16dc34f7-6d22-4aa4-a67f-2921fb5dcb69} components/commandline-handler.js +contract @mozilla.org/commandlinehandler/general-startup;1?type=vimperator {16dc34f7-6d22-4aa4-a67f-2921fb5dcb69} + +component {c1b67a07-18f7-4e13-b361-2edcc35a5a0d} components/protocols.js +contract @mozilla.org/network/protocol;1?name=chrome-data {c1b67a07-18f7-4e13-b361-2edcc35a5a0d} +component {9c8f2530-51c8-4d41-b356-319e0b155c44} components/protocols.js +contract @mozilla.org/network/protocol;1?name=liberator {9c8f2530-51c8-4d41-b356-319e0b155c44} + diff --git a/vimperator/components/about-handler.js b/vimperator/components/about-handler.js index f6a386c0..25dbd492 100644 --- a/vimperator/components/about-handler.js +++ b/vimperator/components/about-handler.js @@ -38,6 +38,9 @@ AboutHandler.prototype = { getURIFlags: function (uri) Ci.nsIAboutModule.ALLOW_SCRIPT, }; -function NSGetModule(compMgr, fileSpec) XPCOMUtils.generateModule([AboutHandler]) +if (XPCOMUtils.generateNSGetFactory) + const NSGetFactory = XPCOMUtils.generateNSGetFactory([AboutHandler]); +else + const NSGetModule = XPCOMUtils.generateNSGetModule([AboutHandler]); // vim: set fdm=marker sw=4 ts=4 et: diff --git a/vimperator/components/commandline-handler.js b/vimperator/components/commandline-handler.js index 5ddb6713..8c23f36d 100644 --- a/vimperator/components/commandline-handler.js +++ b/vimperator/components/commandline-handler.js @@ -43,6 +43,9 @@ CommandLineHandler.prototype = { } }; -function NSGetModule(compMgr, fileSpec) XPCOMUtils.generateModule([CommandLineHandler]) +if (XPCOMUtils.generateNSGetFactory) + const NSGetFactory = XPCOMUtils.generateNSGetFactory([CommandLineHandler]); +else + const NSGetModule = XPCOMUtils.generateNSGetModule([CommandLineHandler]); // vim: set ft=javascript fdm=marker sw=4 ts=4 et: