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

Use temp files rather than URL arguments for :viewsource!. Also update the statusline on :redraw and add an XPCOM shim class for pseudo-XPCOM objects.

This commit is contained in:
Kris Maglione
2010-10-03 13:44:37 -04:00
parent cbed89d8ba
commit 72b6af3e6b
8 changed files with 123 additions and 25 deletions

View File

@@ -188,6 +188,7 @@ const Browser = Module("browser", {
function () { function () {
window.QueryInterface(Ci.nsIInterfaceRequestor) window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils).redraw(); .getInterface(Ci.nsIDOMWindowUtils).redraw();
statusline.updateUrl();
commandline.clear(); commandline.clear();
}, },
{ argCount: "0" }); { argCount: "0" });

View File

@@ -932,11 +932,12 @@ const Buffer = Module("buffer", {
* @param {boolean} useExternalEditor View the source in the external editor. * @param {boolean} useExternalEditor View the source in the external editor.
*/ */
viewSource: function (url, useExternalEditor) { viewSource: function (url, useExternalEditor) {
url = url || buffer.URI; let doc = tabs.localStore.focusedFrame.document;
if (useExternalEditor) if (useExternalEditor)
editor.editFileExternally(url); this.viewSourceExternally(url || doc);
else { else {
url = url || doc.location.href;
const PREFIX = "view-source:"; const PREFIX = "view-source:";
if (url.indexOf(PREFIX) == 0) if (url.indexOf(PREFIX) == 0)
url = url.substr(PREFIX.length); url = url.substr(PREFIX.length);
@@ -951,6 +952,92 @@ const Buffer = Module("buffer", {
} }
}, },
/**
* Launches an editor to view the source of the given document. The
* contents of the document are saved to a temporary local file and
* removed when the editor returns. This function returns
* immediately.
*
* @param {Document} doc The document to view.
*/
/*
* Derived from code in Mozilla, ©2005 Jason Barnabe,
* Tri-licensed under MPL 1.1/GPL 2.0/LGPL 2.1
* Portions copyright Kris Maglione licensable under the
* MIT license.
*/
viewSourceExternally: Class("viewSourceExternally",
XPCOM([Ci.nsIWebProgressListener, Ci.nsISupportsWeakReference]), {
init: function (doc) {
let url = isString(doc) ? doc : doc.location.href;
let charset = isString(doc) ? null : doc.characterSet;
let webNav = window.getWebNavigation();
try {
webNav = doc.defaultView.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(nsIWebNavigation);
}
catch (e) {}
let descriptor = null;
try {
descriptor = webNav.QueryInterface(Ci.nsIWebPageDescriptor).currentDescriptor;
}
catch (e) {}
let uri = util.newURI(url, charset);
if (uri.scheme == "file")
editor.editFileExternally(uri.QueryInterface(Ci.nsIFileURL).file.path);
else {
if (descriptor) {
// we'll use nsIWebPageDescriptor to get the source because it may
// not have to refetch the file from the server
// XXXbz this is so broken... This code doesn't set up this docshell
// at all correctly; if somehow the view-source stuff managed to
// execute script we'd be in big trouble here, I suspect.
this.docShell = Cc["@mozilla.org/docshell;1"].createInstance(Ci.nsIBaseWindow)
.QueryInterface(Ci.nsIWebNavigation).QueryInterface(Ci.nsIWebPageDescriptor)
.QueryInterface(Ci.nsIWebProgress);
this.docShell.create();
this.docShell.addProgressListener(this, Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
this.docShell.loadPage(descriptor, Ci.nsIWebPageDescriptor.DISPLAY_AS_SOURCE);
}
else {
this.file = io.createTempFile();
var webBrowserPersist = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
.createInstance(Ci.nsIWebBrowserPersist);
webBrowserPersist.persistFlags = Ci.nsIWebBrowserPersist.PERSIST_FLAGS_REPLACE_EXISTING_FILES;
webBrowserPersist.progressListener = this;
webBrowserPersist.saveURI(uri, null, null, null, null, this.file);
}
}
return null;
},
destroy: function() {
if (this.docShell)
this.docShell.destroy();
},
onStateChange: function(progress, request, flag, status) {
// once it's done loading...
if ((flag & Ci.nsIWebProgressListener.STATE_STOP) && status == 0) {
try {
if (this.docShell) {
this.file = io.createTempFile();
this.file.write(this.docShell.document.body.textContent);
}
editor.editFileExternally(this.file.path);
this.file.remove(false);
}
finally {
this.destroy();
}
}
return 0;
}
}),
/** /**
* Increases the zoom level of the current buffer. * Increases the zoom level of the current buffer.
* *

View File

@@ -11,12 +11,13 @@
plugins.contexts = {}; plugins.contexts = {};
function Script(file) { function Script(file) {
let self = plugins.contexts[file.path]; let self = plugins[file.path];
if (self) { if (self) {
if (self.onUnload) if (self.onUnload)
self.onUnload(); self.onUnload();
return self; return self;
} }
else
self = { __proto__: plugins }; self = { __proto__: plugins };
plugins.contexts[file.path] = self; plugins.contexts[file.path] = self;
plugins[file.path] = self; plugins[file.path] = self;
@@ -203,6 +204,8 @@ const IO = Module("io", {
file.append(config.tempFile); file.append(config.tempFile);
file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, parseInt('0600', 8)); file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, parseInt('0600', 8));
Cc["@mozilla.org/uriloader/external-helper-app-service;1"]
.getService(Ci.nsPIExternalAppLauncher).deleteTemporaryFileOnExit(file);
return io.File(file); return io.File(file);
}, },
@@ -657,12 +660,11 @@ lookup:
completion: function () { completion: function () {
completion.charset = function (context) { completion.charset = function (context) {
context.anchored = false; context.anchored = false;
let service = services.get("charset");
context.keys = { context.keys = {
text: util.identity, text: util.identity,
description: function (charset) service.getCharsetTitle(charset) description: services.get("charset").getCharsetTitle
}; };
context.generate = function () iter(service.getDecoderList()); context.generate = function () iter(services.get("charset").getDecoderList());
}; };
completion.directory = function directory(context, full) { completion.directory = function directory(context, full) {

View File

@@ -73,9 +73,7 @@
<p> <p>
View source with an external editor. Opens the source View source with an external editor. Opens the source
code of the current web site with the external editor code of the current web site with the external editor
specified by the <o>editor</o> option. The external specified by the <o>editor</o> option.
editor must be able to download and open files from a
remote URL.
</p> </p>
</description> </description>
</item> </item>

View File

@@ -139,12 +139,11 @@ defineModule("base", {
// sed -n 's/^(const|function) ([a-zA-Z0-9_]+).*/ "\2",/p' base.jsm | sort | fmt // sed -n 's/^(const|function) ([a-zA-Z0-9_]+).*/ "\2",/p' base.jsm | sort | fmt
exports: [ exports: [
"Cc", "Ci", "Class", "Cr", "Cu", "Module", "Object", "Runnable", "Cc", "Ci", "Class", "Cr", "Cu", "Module", "Object", "Runnable",
"Struct", "StructBase", "Timer", "UTF8", "XPCOMUtils", "array", "Struct", "StructBase", "Timer", "UTF8", "XPCOM", "XPCOMUtils", "array",
"call", "callable", "curry", "debuggerProperties", "defineModule", "call", "callable", "curry", "debuggerProperties", "defineModule",
"endModule", "forEach", "isArray", "isGenerator", "isinstance", "endModule", "forEach", "isArray", "isGenerator", "isinstance",
"isObject", "isString", "isSubclass", "iter", "iterAll", "keys", "isObject", "isString", "isSubclass", "iter", "iterAll", "keys",
"memoize", "properties", "requiresMainThread", "set", "update", "memoize", "properties", "requiresMainThread", "set", "update", "values"
"values"
], ],
use: ["services"] use: ["services"]
}); });
@@ -700,6 +699,25 @@ Class.extend = function extend(subclass, superclass, overrides) {
superclass.prototype.constructor = superclass; superclass.prototype.constructor = superclass;
} }
/**
* A base class generator for classes which impliment XPCOM interfaces.
*
* @param {nsIIID|[nsIJSIID]} interfaces The interfaces which the class
* implements.
* @param {Class} superClass A super class. @optional
* @returns {Class}
*/
function XPCOM(interfaces, superClass) {
interfaces = Array.concat(interfaces);
let shim = interfaces.reduce(function (shim, iface) shim.QueryInterface(iface),
Cc["@dactyl.googlecode.com/base/xpc-interface-shim"].createInstance());
let res = Class("XPCOM(" + interfaces + ")", superClass || Class, update(
array([k, v === undefined || callable(v) ? function stub() null : v] for ([k, v] in Iterator(shim))).toObject(),
{ QueryInterface: XPCOMUtils.generateQI(interfaces) }));
shim = interfaces = null;
return res;
}
/** /**
* Memoizes the value of a class property to the falue returned by * Memoizes the value of a class property to the falue returned by
* the passed function the first time the property is accessed. * the passed function the first time the property is accessed.

View File

@@ -24,7 +24,7 @@ const history = services.get("history");
const tagging = services.get("tagging"); const tagging = services.get("tagging");
const name = "bookmark-cache"; const name = "bookmark-cache";
const BookmarkCache = Module("BookmarkCache", { const BookmarkCache = Module("BookmarkCache", XPCOM(Ci.nsINavBookmarkObserver), {
init: function init() { init: function init() {
bookmarks.addObserver(this, false); bookmarks.addObserver(this, false);
}, },
@@ -116,11 +116,6 @@ const BookmarkCache = Module("BookmarkCache", {
return bookmarks; return bookmarks;
}, },
onBeforeItemRemoved: function () {},
onBeginUpdateBatch: function () {},
onEndUpdateBatch: function () {},
onItemVisited: function () {},
onItemMoved: function () {},
onItemAdded: function onItemAdded(itemId, folder, index) { onItemAdded: function onItemAdded(itemId, folder, index) {
if (bookmarks.getItemType(itemId) == bookmarks.TYPE_BOOKMARK) { if (bookmarks.getItemType(itemId) == bookmarks.TYPE_BOOKMARK) {
if (this.isBookmark(itemId)) { if (this.isBookmark(itemId)) {
@@ -147,8 +142,7 @@ const BookmarkCache = Module("BookmarkCache", {
storage.fireEvent(name, "change", { __proto__: bookmark, changed: property }); storage.fireEvent(name, "change", { __proto__: bookmark, changed: property });
} }
} }
}, }
QueryInterface: XPCOMUtils.generateQI([Ci.nsINavBookmarkObserver])
}, { }, {
getFavicon: function getFavicon(uri) { getFavicon: function getFavicon(uri) {
try { try {

View File

@@ -29,7 +29,7 @@ Range.prototype.contains = function (date)
Range.prototype.__defineGetter__("isEternity", function () this.max == null && this.min == null); 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__("isSession", function () this.max == null && this.min == sanitizer.sessionStart);
const Sanitizer = Module("sanitizer", tmp.Sanitizer, { const Sanitizer = Module("sanitizer", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference], tmp.Sanitizer), {
sessionStart: Date.now() * 1000, sessionStart: Date.now() * 1000,
init: function () { init: function () {
@@ -90,8 +90,6 @@ const Sanitizer = Module("sanitizer", tmp.Sanitizer, {
util.addObserver(this); util.addObserver(this);
}, },
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
addItem: function addItem(name, params) { addItem: function addItem(name, params) {
if (params.description) if (params.description)
this.itemDescriptions[name] = params.description; this.itemDescriptions[name] = params.description;

View File

@@ -19,7 +19,7 @@ BUGS:
- :sidebar improvements (:sidebar! Downloads while downloads is open should refocus the sidebar) - :sidebar improvements (:sidebar! Downloads while downloads is open should refocus the sidebar)
- ;s saves the page rather than the image - ;s saves the page rather than the image
- RC file is sourced once per window - RC file is sourced once per window
- :undo seems to be effected by the tabstrip state - :undo seems to be affected by the tabstrip state
- the :help version-information page is no longer generated - the :help version-information page is no longer generated
(recent Mercurial regressions): (recent Mercurial regressions):