1
0
mirror of https://github.com/gryf/pentadactyl-pm.git synced 2025-12-20 15:57:57 +01:00

Fix some cleanup issues. Better error pages for bad dactyl: URLs. Remove some dead code. Other cleanup.

This commit is contained in:
Kris Maglione
2011-08-21 10:41:46 -04:00
parent ffe138b4e3
commit 5f42595f65
13 changed files with 99 additions and 86 deletions

22
common/bootstrap.js vendored
View File

@@ -32,16 +32,8 @@ const manager = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
const BOOTSTRAP_JSM = "resource://dactyl/bootstrap.jsm"; const BOOTSTRAP_JSM = "resource://dactyl/bootstrap.jsm";
const BOOTSTRAP_CONTRACT = "@dactyl.googlecode.com/base/bootstrap"; const BOOTSTRAP_CONTRACT = "@dactyl.googlecode.com/base/bootstrap";
JSMLoader = JSMLoader || BOOTSTRAP_CONTRACT in Cc && Cc[BOOTSTRAP_CONTRACT].getService().wrappedJSObject.loader;
var JSMLoader = BOOTSTRAP_CONTRACT in Components.classes && var JSMLoader = BOOTSTRAP_CONTRACT in Cc && Cc[BOOTSTRAP_CONTRACT].getService().wrappedJSObject.loader;
Components.classes[BOOTSTRAP_CONTRACT].getService().wrappedJSObject.loader;
// Temporary migration code.
if (!JSMLoader && "@mozilla.org/fuel/application;1" in Components.classes)
JSMLoader = Components.classes["@mozilla.org/fuel/application;1"]
.getService(Components.interfaces.extIApplication)
.storage.get("dactyl.JSMLoader", null);
function reportError(e) { function reportError(e) {
dump("\ndactyl: bootstrap: " + e + "\n" + (e.stack || Error().stack) + "\n"); dump("\ndactyl: bootstrap: " + e + "\n" + (e.stack || Error().stack) + "\n");
@@ -119,7 +111,8 @@ function startup(data, reason) {
}; };
else else
getURI = function getURI(path) getURI = function getURI(path)
Services.io.newURI("jar:" + Services.io.newFileURI(basePath).spec + "!/" + path, null, null); Services.io.newURI("jar:" + Services.io.newFileURI(basePath).spec.replace(/!/g, "%21") + "!" +
"/" + path, null, null);
try { try {
init(); init();
@@ -243,7 +236,7 @@ function init() {
if (!(BOOTSTRAP_CONTRACT in Cc)) if (!(BOOTSTRAP_CONTRACT in Cc))
manager.registerFactory(Components.ID("{f541c8b0-fe26-4621-a30b-e77d21721fb5}"), manager.registerFactory(Components.ID("{f541c8b0-fe26-4621-a30b-e77d21721fb5}"),
String("{f541c8b0-fe26-4621-a30b-e77d21721fb5}"), "{f541c8b0-fe26-4621-a30b-e77d21721fb5}",
BOOTSTRAP_CONTRACT, { BOOTSTRAP_CONTRACT, {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory]), QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory]),
instance: { instance: {
@@ -292,6 +285,12 @@ function shutdown(data, reason) {
} }
} }
function uninstall(data, reason) {
dump("dactyl: bootstrap: uninstall " + reasonToString(reason) + "\n");
if (reason == ADDON_UNINSTALL)
Services.prefs.deleteBranch("extensions.dactyl.");
}
function reasonToString(reason) { function reasonToString(reason) {
for each (let name in ["disable", "downgrade", "enable", for each (let name in ["disable", "downgrade", "enable",
"install", "shutdown", "startup", "install", "shutdown", "startup",
@@ -302,6 +301,5 @@ function reasonToString(reason) {
} }
function install(data, reason) { dump("dactyl: bootstrap: install " + reasonToString(reason) + "\n"); } function install(data, reason) { dump("dactyl: bootstrap: install " + reasonToString(reason) + "\n"); }
function uninstall(data, reason) { dump("dactyl: bootstrap: uninstall " + reasonToString(reason) + "\n"); }
// vim: set fdm=marker sw=4 ts=4 et: // vim: set fdm=marker sw=4 ts=4 et:

View File

@@ -19,7 +19,7 @@ function init() {
Cu.import("resource://dactyl/bootstrap.jsm"); Cu.import("resource://dactyl/bootstrap.jsm");
if (!JSMLoader.initialized) if (!JSMLoader.initialized)
JSMLoader.init(); JSMLoader.init();
Cu.import("resource://dactyl/base.jsm"); JSMLoader.load("base.jsm", global);
require(global, "config"); require(global, "config");
require(global, "util"); require(global, "util");
} }

View File

@@ -56,7 +56,11 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), {
delete window.dactyl; delete window.dactyl;
delete window.liberator; delete window.liberator;
styles.system.add("cleanup-sheet", config.styleableChrome, <![CDATA[
#TabsToolbar tab { display: none; }
]]>);
styles.unregisterSheet("resource://dactyl-skin/dactyl.css"); styles.unregisterSheet("resource://dactyl-skin/dactyl.css");
DOM('#TabsToolbar tab', document).style.display;
}, },
destroy: function () { destroy: function () {

View File

@@ -12,7 +12,6 @@ var StatusLine = Module("statusline", {
init: function init() { init: function init() {
this._statusLine = document.getElementById("status-bar"); this._statusLine = document.getElementById("status-bar");
this.statusBar = document.getElementById("addon-bar") || this._statusLine; this.statusBar = document.getElementById("addon-bar") || this._statusLine;
this.statusBar.collapsed = true;
this.baseGroup = this.statusBar == this._statusLine ? "StatusLine " : ""; this.baseGroup = this.statusBar == this._statusLine ? "StatusLine " : "";
if (this.statusBar.localName == "toolbar") { if (this.statusBar.localName == "toolbar") {

View File

@@ -851,7 +851,7 @@ Class.extend = function extend(subclass, superclass, overrides) {
* property's value. * property's value.
* @returns {Class.Property} * @returns {Class.Property}
*/ */
Class.memoize = function memoize(getter, wait) Class.Memoize = Class.memoize = function Memoize(getter, wait)
Class.Property({ Class.Property({
configurable: true, configurable: true,
enumerable: true, enumerable: true,
@@ -893,6 +893,19 @@ Class.memoize = function memoize(getter, wait)
} }
}); });
/**
* Updates the given object with the object in the target class's
* prototype.
*/
Class.Update = function Update(obj)
Class.Property({
configurable: true,
enumerable: true,
init: function (key, target) {
this.value = update({}, target[key], obj);
}
});
Class.replaceProperty = function replaceProperty(obj, prop, value) { Class.replaceProperty = function replaceProperty(obj, prop, value) {
Object.defineProperty(obj, prop, { configurable: true, enumerable: true, value: value, writable: true }); Object.defineProperty(obj, prop, { configurable: true, enumerable: true, value: value, writable: true });
return value; return value;

View File

@@ -14,11 +14,6 @@ var BOOTSTRAP_CONTRACT = "@dactyl.googlecode.com/base/bootstrap";
var JSMLoader = BOOTSTRAP_CONTRACT in Components.classes && var JSMLoader = BOOTSTRAP_CONTRACT in Components.classes &&
Components.classes[BOOTSTRAP_CONTRACT].getService().wrappedJSObject.loader; Components.classes[BOOTSTRAP_CONTRACT].getService().wrappedJSObject.loader;
if (!JSMLoader && "@mozilla.org/fuel/application;1" in Components.classes)
JSMLoader = Components.classes["@mozilla.org/fuel/application;1"]
.getService(Components.interfaces.extIApplication)
.storage.get("dactyl.JSMLoader", null);
if (JSMLoader && JSMLoader.bump === 6) if (JSMLoader && JSMLoader.bump === 6)
JSMLoader.global = this; JSMLoader.global = this;
else else
@@ -133,6 +128,8 @@ else
purge: function purge() { purge: function purge() {
dump("dactyl: JSMLoader: purge\n"); dump("dactyl: JSMLoader: purge\n");
this.bootstrap = null;
if (Cu.unload) { if (Cu.unload) {
Object.keys(this.modules).reverse().forEach(function (url) { Object.keys(this.modules).reverse().forEach(function (url) {
try { try {

View File

@@ -309,7 +309,7 @@ var ConfigBase = Class("ConfigBase", {
version: Class.memoize(function () { version: Class.memoize(function () {
if (this.VCSPath) if (this.VCSPath)
return io.system(["hg", "-R", this.VCSPath, "log", "-r.", return io.system(["hg", "-R", this.VCSPath, "log", "-r.",
"--template=hg{rev}." + this.branch]).output; "--template=hg{rev}-{branch}"]).output;
return this.addon.version; return this.addon.version;
}), }),
@@ -504,13 +504,6 @@ var ConfigBase = Class("ConfigBase", {
*/ */
host: null, host: null,
/**
* @property {[[]]} An array of application specific mode specifications.
* The values of each mode are passed to modes.addMode during
* dactyl startup.
*/
modes: [],
/** /**
* @property {string} The name of the extension. * @property {string} The name of the extension.
* Required. * Required.

View File

@@ -44,7 +44,7 @@ var Prefs = Module("prefs", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference])
cleanup: function cleanup(reason) { cleanup: function cleanup(reason) {
if (this.defaults != this) if (this.defaults != this)
this.defaults.cleanup(); this.defaults.cleanup(reason);
this._observers = {}; this._observers = {};
if (this.observe) { if (this.observe) {
@@ -62,7 +62,7 @@ var Prefs = Module("prefs", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference])
this.branches.saved.resetBranch(); this.branches.saved.resetBranch();
} }
if (reason == "uninstall" && this == prefs) if (reason == "uninstall")
localPrefs.resetBranch(); localPrefs.resetBranch();
} }
}, },

View File

@@ -12,12 +12,10 @@ defineModule("protocol", {
var systemPrincipal = Cc["@mozilla.org/systemprincipal;1"].getService(Ci.nsIPrincipal); var systemPrincipal = Cc["@mozilla.org/systemprincipal;1"].getService(Ci.nsIPrincipal);
var DNE = "resource://gre/does/not/exist"; function Channel(url, orig, noErrorChannel) {
function Channel(url, orig, noFake) {
try { try {
if (url == null) if (url == null)
return noFake ? null : FakeChannel(orig); return noErrorChannel ? null : NetError(orig);
if (url instanceof Ci.nsIChannel) if (url instanceof Ci.nsIChannel)
return url; return url;
@@ -29,17 +27,28 @@ function Channel(url, orig, noFake) {
return let ([type, data] = url) StringChannel(data, type, orig); return let ([type, data] = url) StringChannel(data, type, orig);
let uri = services.io.newURI(url, null, null); let uri = services.io.newURI(url, null, null);
return (new XMLChannel(uri, null, noFake)).channel; return (new XMLChannel(uri, null, noErrorChannel)).channel;
} }
catch (e) { catch (e) {
util.reportError(e); util.reportError(e);
util.dump(url);
throw e; throw e;
} }
} }
function FakeChannel(orig) { function NetError(orig, error) {
let channel = services.io.newChannel(DNE, null, null); return services.InterfacePointer({
channel.originalURI = orig; QueryInterface: XPCOMUtils.generateQI([Ci.nsIChannel]),
return channel;
name: orig.spec,
URI: orig,
originalURI: orig,
asyncOpen: function () { throw error || Cr.NS_ERROR_FILE_NOT_FOUND },
open: function () { throw error || Cr.NS_ERROR_FILE_NOT_FOUND }
}).data.QueryInterface(Ci.nsIChannel);
} }
function RedirectChannel(to, orig, time) { function RedirectChannel(to, orig, time) {
let html = <html><head><meta http-equiv="Refresh" content={(time || 0) + ";" + to}/></head></html>.toXMLString(); let html = <html><head><meta http-equiv="Refresh" content={(time || 0) + ";" + to}/></head></html>.toXMLString();
@@ -68,7 +77,19 @@ function ProtocolBase() {
this.wrappedJSObject = this; this.wrappedJSObject = this;
this.pages = {}; this.pages = {};
this.providers = {}; this.providers = {
"content": function (uri, path) this.pages[path] || this.contentBase + path,
"data": function (uri) {
var channel = services.io.newChannel(uri.path.replace(/^\/(.*)(?:#.*)?/, "data:$1"),
null, null);
channel.contentCharset = "UTF-8";
channel.owner = systemPrincipal;
channel.originalURI = uri;
return channel;
}
};
} }
ProtocolBase.prototype = { ProtocolBase.prototype = {
get contractID() "@mozilla.org/network/protocol;1?name=" + this.scheme, get contractID() "@mozilla.org/network/protocol;1?name=" + this.scheme,
@@ -92,34 +113,17 @@ ProtocolBase.prototype = {
try { try {
uri.QueryInterface(Ci.nsIURL); uri.QueryInterface(Ci.nsIURL);
let path = decodeURIComponent(uri.filePath.substr(1));
if (uri.host in this.providers) if (uri.host in this.providers)
return Channel(this.providers[uri.host](uri, uri.filePath.substr(1)), uri); return Channel(this.providers[uri.host].call(this, uri, path),
uri);
let path = decodeURIComponent(uri.path.replace(/^\/|#.*/g, "")); return NetError(uri);
switch(uri.host) {
case "content":
return Channel(this.pages[path] || this.contentBase + path, uri);
case "data":
try {
var channel = services.io.newChannel(uri.path.replace(/^\/(.*)(?:#.*)?/, "data:$1"),
null, null);
}
catch (e) {
var error = e;
break;
}
channel.contentCharset = "UTF-8";
channel.owner = systemPrincipal;
channel.originalURI = uri;
return channel;
}
} }
catch (e) { catch (e) {
util.reportError(e); util.reportError(e);
throw e;
} }
if (error)
throw error;
return FakeChannel(uri);
} }
}; };
@@ -131,7 +135,7 @@ function LocaleChannel(pkg, locale, path, orig) {
return channel; return channel;
} }
return FakeChannel(orig); return NetError(orig);
} }
function StringChannel(data, contentType, uri) { function StringChannel(data, contentType, uri) {
@@ -146,13 +150,13 @@ function StringChannel(data, contentType, uri) {
return channel; return channel;
} }
function XMLChannel(uri, contentType, noFake) { function XMLChannel(uri, contentType, noErrorChannel) {
try { try {
var channel = services.io.newChannelFromURI(uri); var channel = services.io.newChannelFromURI(uri);
var channelStream = channel.open(); var channelStream = channel.open();
} }
catch (e) { catch (e) {
this.channel = noFake ? null : FakeChannel(uri); this.channel = noErrorChannel ? null : NetError(uri);
return; return;
} }

View File

@@ -254,12 +254,14 @@ var Styles = Module("Styles", {
this.cleanup(); this.cleanup();
this.allSheets = {}; this.allSheets = {};
services["dactyl:"].providers["style"] = function styleProvider(uri) { update(services["dactyl:"].providers, {
let id = /^\/(\d*)/.exec(uri.path)[1]; "style": function styleProvider(uri, path) {
if (Set.has(styles.allSheets, id)) let id = parseInt(path);
return ["text/css", styles.allSheets[id].fullCSS]; if (Set.has(styles.allSheets, id))
return null; return ["text/css", styles.allSheets[id].fullCSS];
}; return null;
}
});
}, },
cleanup: function cleanup() { cleanup: function cleanup() {

View File

@@ -1589,8 +1589,8 @@ var DOM = Class("DOM", {
attrHooks: array.toObject([ attrHooks: array.toObject([
["", { ["", {
href: { get: function (elem) elem.href }, href: { get: function (elem) elem.href || elem.getAttribute("href") },
src: { get: function (elem) elem.src } src: { get: function (elem) elem.src || elem.getAttribute("src") }
}] }]
]), ]),
@@ -1843,7 +1843,7 @@ var DOM = Class("DOM", {
*/ */
get style() { get style() {
let node = this[0]; let node = this[0];
while (!(node instanceof Ci.nsIDOMElement) && node.parentNode) while (node && !(node instanceof Ci.nsIDOMElement) && node.parentNode)
node = node.parentNode; node = node.parentNode;
try { try {

View File

@@ -21,10 +21,17 @@ var setupTest = function (test) {
function urlTarget(url) Services.io.newChannel(url, null, null).name; function urlTarget(url) Services.io.newChannel(url, null, null).name;
__defineGetter__("doesNotExist", function () { function urlExists(url) {
delete this.doesNotExist; try {
return this.doesNotExist = urlTarget("dactyl://help-tag/non-existent-help-tag-url-thingy"); let chan = Services.io.newChannel(url);
}); chan.open();
try { chan.cancel(Cr.NS_BINDING_ABORTED) } catch (e) {}
return true;
}
catch (e) {
return false;
}
}
const HELP_FILES = ["all", "tutorial", "intro", "starting", "browsing", const HELP_FILES = ["all", "tutorial", "intro", "starting", "browsing",
"buffer", "cmdline", "editing", "options", "pattern", "tabs", "hints", "buffer", "cmdline", "editing", "options", "pattern", "tabs", "hints",
@@ -70,7 +77,7 @@ var testExHelpCommand_PageTagArg_OpensHelpPageContainingTag = function () {
let links = controller.tabs.activeTab.querySelectorAll("a[href^='dactyl:']"); let links = controller.tabs.activeTab.querySelectorAll("a[href^='dactyl:']");
let missing = Array.filter(links, function (link) urlTarget(link.href) === doesNotExist) let missing = Array.filter(links, function (link) urlExists(link.href))
.map(function (link) link.textContent + " -> " + link.href); .map(function (link) link.textContent + " -> " + link.href);
utils.assertEqual("testHelpCommands.assertNoDeadLinks", 0, missing.length, utils.assertEqual("testHelpCommands.assertNoDeadLinks", 0, missing.length,

View File

@@ -18,7 +18,7 @@ var Config = Module("config", ConfigBase, {
Local: function Local(dactyl, modules, window) Local: function Local(dactyl, modules, window)
let ({ config } = modules) ({ let ({ config } = modules) ({
completers: Class.memoize(function () update({ sidebar: "sidebar", window: "window" }, this.__proto__.completers)), completers: Class.Update({ sidebar: "sidebar", window: "window" }),
dialogs: { dialogs: {
about: ["About Firefox", about: ["About Firefox",
@@ -278,7 +278,7 @@ var Config = Module("config", ConfigBase, {
const { CompletionContext, bookmarkcache, completion } = modules; const { CompletionContext, bookmarkcache, completion } = modules;
const { document } = window; const { document } = window;
var searchRunning = null; // only until Firefox fixes https://bugzilla.mozilla.org/show_bug.cgi?id=510589 var searchRunning = null;
completion.location = function location(context) { completion.location = function location(context) {
if (!services.autoCompleteSearch) if (!services.autoCompleteSearch)
return; return;
@@ -349,13 +349,9 @@ var Config = Module("config", ConfigBase, {
"Handled by " + config.host, "Handled by " + config.host,
function () Events.PASS_THROUGH); function () Events.PASS_THROUGH);
}, },
modes: function (dactyl, modules, window) {
const { modes } = modules;
config.modes.forEach(function (mode) { modes.addMode.apply(this, mode); });
},
options: function (dactyl, modules, window) { options: function (dactyl, modules, window) {
modules.options.add(["online"], modules.options.add(["online"],
"Set the 'work offline' option", "Enables or disables offline mode",
"boolean", true, "boolean", true,
{ {
setter: function (value) { setter: function (value) {