From 0dcf1d8ffda8900f69e77ffd8217d078723f7c02 Mon Sep 17 00:00:00 2001
From: Kris Maglione
Date: Tue, 14 Dec 2010 23:05:41 -0500
Subject: [PATCH] Completion of certain chrome:, resource:, and about: URLs.
---
common/content/buffer.js | 8 ++--
common/content/completion.js | 10 +++++
common/content/io.js | 72 ++++++++++++++++++++++++++++-----
common/content/modes.js | 16 ++++----
common/content/tabs.js | 2 +-
common/locale/en-US/various.xml | 13 +++---
common/modules/sanitizer.jsm | 21 ++++++----
common/modules/services.jsm | 10 +++--
common/modules/util.jsm | 7 +++-
9 files changed, 118 insertions(+), 41 deletions(-)
diff --git a/common/content/buffer.js b/common/content/buffer.js
index b56c571b..27f2114f 100644
--- a/common/content/buffer.js
+++ b/common/content/buffer.js
@@ -292,7 +292,7 @@ const Buffer = Module("buffer", {
// Workaround for bugs 591425 and 606877, dactyl bug #81
config.browser.mCurrentBrowser.collapsed =
- uri.scheme === "dactyl" && webProgress.isLoadingDocument;
+ uri && uri.scheme === "dactyl" && webProgress.isLoadingDocument;
util.timeout(function () {
autocommands.trigger("LocationChange", { url: buffer.URL });
@@ -480,8 +480,6 @@ const Buffer = Module("buffer", {
*
* @returns {string}
*/
- // FIXME: getSelection() doesn't always preserve line endings, see:
- // https://www.mozdev.org/bugs/show_bug.cgi?id=19303
getCurrentWord: function () {
let win = buffer.focusedFrame || window.content;
let selection = win.getSelection();
@@ -1688,11 +1686,11 @@ const Buffer = Module("buffer", {
// reloading
mappings.add(myModes, ["r"],
"Reload the current web page",
- function () { tabs.reload(config.browser.mCurrentTab, false); });
+ function () { tabs.reload(tabs.getTab(), false); });
mappings.add(myModes, ["R"],
"Reload while skipping the cache",
- function () { tabs.reload(config.browser.mCurrentTab, true); });
+ function () { tabs.reload(tabs.getTab(), true); });
// yanking
mappings.add(myModes, ["Y"],
diff --git a/common/content/completion.js b/common/content/completion.js
index bd5c536e..d5922404 100644
--- a/common/content/completion.js
+++ b/common/content/completion.js
@@ -864,6 +864,16 @@ const Completion = Module("completion", {
if (complete == null)
complete = options["complete"];
+ if (/^about:/.test(context.filter)) {
+ context.fork("about", 6, this, function (context) {
+ context.generate = function () {
+ const PREFIX = "@mozilla.org/network/protocol/about;1?what=";
+ return [[k.substr(PREFIX.length), ""] for (k in Cc) if (k.indexOf(PREFIX) == 0)]
+ }
+ });
+ }
+
+
// Will, and should, throw an error if !(c in opts)
Array.forEach(complete, function (c) {
let completer = completion.urlCompleters[c];
diff --git a/common/content/io.js b/common/content/io.js
index 844b3c2c..3148c30d 100644
--- a/common/content/io.js
+++ b/common/content/io.js
@@ -209,6 +209,18 @@ const IO = Module("io", {
return io.File(file);
},
+ isJarURL: function (url) {
+ try {
+ let uri = util.newURI(url);
+ let channel = services.io.newChannelFromURI(uri);
+ channel.cancel(Cr.NS_BINDING_ABORTED);
+ if (channel instanceof Ci.nsIJARChannel)
+ return channel.QueryInterface(Ci.nsIJARChannel);
+ }
+ catch (e) {}
+ return false;
+ },
+
readHeredoc: function (end) {
return "";
},
@@ -654,7 +666,12 @@ lookup:
completion.file = function file(context, full, dir) {
// dir == "" is expanded inside readDirectory to the current dir
- [dir] = (dir || context.filter).match(/^(?:.*[\/\\])?/);
+ function getDir(str) str.match(/^(?:.*[\/\\])?/)[0];
+ dir = getDir(dir || context.filter);
+
+ let file = util.getFile(dir);
+ if (file && file.exists() && !file.isDirectory())
+ file = file.parent;
if (!full)
context.advance(dir.length);
@@ -677,13 +694,40 @@ lookup:
// context.background = true;
context.key = dir;
- context.generate = function generate_file() {
- try {
- return io.File(dir).readDirectory();
- }
- catch (e) {}
- return [];
- };
+ let channel = io.isJarURL(dir);
+ if (channel)
+ context.generate = function generate_jar() {
+ let uri = channel.URI.QueryInterface(Ci.nsIJARURI);
+ let file = util.getFile(uri.JARFile);
+ if (file) {
+ // let jar = services.zipReader.getZip(file); Crashes.
+ let jar = services.ZipReader(file);
+ try {
+ let path = decodeURI(getDir(uri.JAREntry));
+ return [
+ {
+ isDirectory: function () s.substr(-1) == "/",
+ leafName: /([^\/]*)\/?$/.exec(s)[1]
+ }
+ for (s in iter(jar.findEntries("*"))) if (s.indexOf(path) == 0)
+ ]
+ }
+ finally {
+ jar.close();
+ }
+ }
+ };
+ else
+ context.generate = function generate_file() {
+ try {
+ util.dump(String(file), file && file.path);
+ return io.File(file || dir).readDirectory();
+ }
+ catch (e) {
+ util.reportError(e);
+ }
+ return [];
+ };
};
completion.runtime = function (context) {
@@ -715,7 +759,17 @@ lookup:
};
completion.addUrlCompleter("f", "Local files", function (context, full) {
- if (/^(\.{0,2}|~)\/|^file:/.test(context.filter))
+ let match = /^(chrome:\/\/[^\/]+\/)([^/]*)$/.exec(context.filter);
+ if (match) {
+ context.key = match[1];
+ context.advance(match[1].length);
+ context.generate = function () iter({
+ content: "Chrome content",
+ locale: "Locale-specific content",
+ skin: "Theme-specific content"
+ });
+ }
+ else if (/^(\.{0,2}|~)\/|^file:/.test(context.filter) || util.getFile(context.filter) || io.isJarURL(context.filter))
completion.file(context, full);
});
},
diff --git a/common/content/modes.js b/common/content/modes.js
index 1e66cb1f..4f352bb7 100644
--- a/common/content/modes.js
+++ b/common/content/modes.js
@@ -23,10 +23,8 @@ const Modes = Module("modes", {
this._modeStack = update([], {
pop: function pop() {
- if (this.length <= 1) {
- util.dumpStack("Trying to pop last element in mode stack");
+ if (this.length <= 1)
throw Error("Trying to pop last element in mode stack");
- }
return pop.superapply(this, arguments);
}
});
@@ -47,7 +45,7 @@ const Modes = Module("modes", {
if (selection && !selection.isCollapsed)
selection.collapseToStart();
}
- else
+ else if (stack.pop)
editor.unselectText();
}
});
@@ -96,10 +94,12 @@ const Modes = Module("modes", {
dactyl.focusContent(true);
if (prev.main == modes.NORMAL) {
dactyl.focusContent(true);
- // clear any selection made
- let selection = window.content.getSelection();
- if (selection && !selection.isCollapsed)
- selection.collapseToStart();
+ for (let frame in values(buffer.allFrames())) {
+ // clear any selection made
+ let selection = frame.getSelection();
+ if (selection && !selection.isCollapsed)
+ selection.collapseToStart();
+ }
}
}
diff --git a/common/content/tabs.js b/common/content/tabs.js
index 938b1e65..f2be4187 100644
--- a/common/content/tabs.js
+++ b/common/content/tabs.js
@@ -445,7 +445,7 @@ const Tabs = Module("tabs", {
else {
let index = (count - 1) % matches.length;
if (reverse)
- index = matches.length - count;
+ index = matches.length - index - 1;
tabs.select(matches[index].id, false);
}
},
diff --git a/common/locale/en-US/various.xml b/common/locale/en-US/various.xml
index a491b58c..db65a99e 100644
--- a/common/locale/en-US/various.xml
+++ b/common/locale/en-US/various.xml
@@ -195,10 +195,11 @@
- The following items are cleared regardless of timeframe:
- cache, offlineapps, passwords,
- sessions, sitesettings. Additionally,
- options are never cleared.
+ The following items are always cleared entirely, regardless of
+ timeframe: cache, offlineapps,
+ passwords, sessions, sitesettings.
+ Conversely, options are never cleared unless a host is
+ specified.
@@ -235,7 +236,7 @@
Available actions:
-
+
- unset
- Unset special permissions for host
- allow
- Allow cookies from host
- deny
- Deny cookies from host
@@ -250,7 +251,7 @@
If no action is given, the value of cookies is used.
- :map -b c :cookies
+ :map -b c :cookies
diff --git a/common/modules/sanitizer.jsm b/common/modules/sanitizer.jsm
index cb3226f6..93a8642e 100644
--- a/common/modules/sanitizer.jsm
+++ b/common/modules/sanitizer.jsm
@@ -27,6 +27,9 @@ Range.prototype.contains = function (date)
date == null || (this.min == null || date >= this.min) && (this.max == null || date <= this.max);
Range.prototype.__defineGetter__("isEternity", function () this.max == null && this.min == null);
Range.prototype.__defineGetter__("isSession", function () this.max == null && this.min == sanitizer.sessionStart);
+Range.prototype.__defineGetter__("native", function ()
+ this.isEternity ? null : [range.min || 0, range.max == null ? Number.MAX_VALUE : range.max]);
+
const Item = Class("Item", {
init: function (name) {
@@ -266,7 +269,7 @@ const Sanitizer = Module("sanitizer", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakR
try {
let item = this.items[Sanitizer.argToPref(itemName)];
if (item && !this.itemMap[itemName].override) {
- item.range = range;
+ item.range = range.native;
if ("clear" in item && item.canClear)
item.clear();
}
@@ -369,12 +372,16 @@ const Sanitizer = Module("sanitizer", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakR
let timespan = args["-timespan"] || modules.options["sanitizetimespan"];
- let range = Range(), match = /^(\d+)([mhdw])$/.exec(timespan);
+ let range = Range();
+ let [match, num, unit] = /^(\d+)([mhdw])$/.exec(timespan) || [];
range[args["-older"] ? "max" : "min"] =
- match ? 1000 * (Date.now() - 1000 * parseInt(match[1], 10) * { m: 60, h: 3600, d: 3600 * 24, w: 3600 * 24 * 7 }[match[2]])
+ match ? 1000 * (Date.now() - 1000 * parseInt(num, 10) * { m: 60, h: 3600, d: 3600 * 24, w: 3600 * 24 * 7 }[unit])
: (timespan[0] == "s" ? sanitizer.sessionStart : null);
let items = args.slice();
+ if (args["-host"] && !args.length)
+ args[0] = "all";
+
if (args.bang) {
dactyl.assert(args.length == 0, "E488: Trailing characters");
items = Object.keys(sanitizer.itemMap).filter(
@@ -386,7 +393,7 @@ const Sanitizer = Module("sanitizer", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakR
if (items.indexOf("all") >= 0)
items = Object.keys(sanitizer.itemMap).filter(function (k) items.indexOf(k) === -1);
- sanitizer.range = range;
+ sanitizer.range = range.native;
sanitizer.ignoreTimespan = range.min == null;
sanitizer.sanitizing = true;
if (args["-host"]) {
@@ -412,11 +419,9 @@ const Sanitizer = Module("sanitizer", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakR
{
names: ["-host", "-h"],
description: "Only sanitize items referring to listed host or hosts",
- completer: function (context) {
- let hosts = context.filter.split(",");
- context.advance(context.filter.length - hosts.pop().length);
+ completer: function (context, args) {
context.filters.push(function (item)
- !hosts.some(function (host) util.isSubdomain(item.text, host)));
+ !args["-host"].some(function (host) util.isSubdomain(item.text, host)));
modules.completion.domain(context);
},
type: modules.CommandOption.LIST,
diff --git a/common/modules/services.jsm b/common/modules/services.jsm
index 561d30f1..4199f2ca 100644
--- a/common/modules/services.jsm
+++ b/common/modules/services.jsm
@@ -58,6 +58,7 @@ const Services = Module("Services", {
this.add("versionCompare", "@mozilla.org/xpcom/version-comparator;1", Ci.nsIVersionComparator);
this.add("windowMediator", "@mozilla.org/appshell/window-mediator;1", Ci.nsIWindowMediator);
this.add("windowWatcher", "@mozilla.org/embedcomp/window-watcher;1", Ci.nsIWindowWatcher);
+ this.add("zipReader", "@mozilla.org/libjar/zip-reader-cache;1", Ci.nsIZipReaderCache);
this.addClass("File", "@mozilla.org/file/local;1", Ci.nsILocalFile);
this.addClass("file:", "@mozilla.org/network/protocol;1?name=file", Ci.nsIFileProtocolHandler);
@@ -68,15 +69,18 @@ const Services = Module("Services", {
this.addClass("String", "@mozilla.org/supports-string;1", Ci.nsISupportsString);
this.addClass("Timer", "@mozilla.org/timer;1", Ci.nsITimer);
this.addClass("Xmlhttp", "@mozilla.org/xmlextras/xmlhttprequest;1", Ci.nsIXMLHttpRequest);
+ this.addClass("ZipReader", "@mozilla.org/libjar/zip-reader;1", Ci.nsIZipReader, "open");
this.addClass("ZipWriter", "@mozilla.org/zipwriter;1", Ci.nsIZipWriter);
},
- _create: function (classes, ifaces, meth) {
+ _create: function (classes, ifaces, meth, init, args) {
try {
let res = Cc[classes][meth || "getService"]();
if (!ifaces)
return res.wrappedJSObject;
Array.concat(ifaces).forEach(function (iface) res.QueryInterface(iface));
+ if (init)
+ res[init].apply(res, args);
return res;
}
catch (e) {
@@ -113,9 +117,9 @@ const Services = Module("Services", {
* @param {nsISupports|nsISupports[]} ifaces The interface or array of
* interfaces implemented by this class.
*/
- addClass: function (name, class_, ifaces) {
+ addClass: function (name, class_, ifaces, init) {
const self = this;
- return this[name] = function () self._create(class_, ifaces, "createInstance");
+ return this[name] = function () self._create(class_, ifaces, "createInstance", init, arguments);
},
/**
diff --git a/common/modules/util.jsm b/common/modules/util.jsm
index 7261e780..681a97e5 100644
--- a/common/modules/util.jsm
+++ b/common/modules/util.jsm
@@ -471,7 +471,12 @@ const Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference])
*/
getFile: function getFile(uri) {
if (isString(uri))
- uri = util.newURI(uri);
+ try {
+ uri = util.newURI(uri);
+ }
+ catch (e) {
+ return null;
+ }
if (uri instanceof Ci.nsIFileURL)
return File(uri.QueryInterface(Ci.nsIFileURL).file);