From 5aa365b7a93a2879bc200ca0711b7da8dcd0e4b7 Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Wed, 5 Oct 2011 03:52:02 -0400 Subject: [PATCH] Try grabbing Content-Disposition from a HEAD request for the save link completion list. Localify descriptions. --- common/content/commandline.js | 6 ++-- common/locale/en-US/messages.properties | 6 ++++ common/modules/buffer.jsm | 45 ++++++++++++++++++++----- common/modules/util.jsm | 3 ++ 4 files changed, 50 insertions(+), 10 deletions(-) diff --git a/common/content/commandline.js b/common/content/commandline.js index 130fbe24..80bf8ace 100644 --- a/common/content/commandline.js +++ b/common/content/commandline.js @@ -323,7 +323,8 @@ var CommandMode = Class("CommandMode", { open: function CM_open(command) { dactyl.assert(isinstance(this.mode, modes.COMMAND_LINE), - /*L*/"Not opening command line in non-command-line mode."); + /*L*/"Not opening command line in non-command-line mode.", + false); this.messageCount = commandline.messageCount; modes.push(this.mode, this.extendedMode, this.closure); @@ -1201,7 +1202,8 @@ var CommandLine = Module("commandline", { let value = this.editor.selection.focusNode.textContent; this.saveInput(); - this.itemList.updateContext(context); + if (this.itemList.visible) + this.itemList.updateContext(context); if (this.waiting && this.waiting[0] == context) this.select(this.waiting); diff --git a/common/locale/en-US/messages.properties b/common/locale/en-US/messages.properties index abf57886..99d94b3c 100644 --- a/common/locale/en-US/messages.properties +++ b/common/locale/en-US/messages.properties @@ -64,6 +64,12 @@ buffer.noClosed = No matching closed tab buffer.noAlternate = No alternate page buffer.backgroundLoaded = Background tab loaded: %S +buffer.save.altText = Alternate Text +buffer.save.filename = File Name +buffer.save.linkText = Link Text +buffer.save.pageName = Page Name +buffer.save.suggested = Server-suggested Name + # TODO: categorise these buffer.noTitle = [No Title] buffer.noName = [No Name] diff --git a/common/modules/buffer.jsm b/common/modules/buffer.jsm index cff6e072..e3c73a48 100644 --- a/common/modules/buffer.jsm +++ b/common/modules/buffer.jsm @@ -1227,33 +1227,37 @@ var Buffer = Module("Buffer", { let url = node.href || node.src || node.documentURI; let currExt = url.replace(/^.*?(?:\.([a-z0-9]+))?$/i, "$1").toLowerCase(); + let ext = ""; if (isinstance(node, [Ci.nsIDOMDocument, Ci.nsIDOMHTMLImageElement])) { let type = node.contentType || node.QueryInterface(Ci.nsIImageLoadingContent) .getRequest(0).mimeType; if (type === "text/plain") - var ext = "." + (currExt || "txt"); + ext = "." + (currExt || "txt"); else ext = "." + services.mime.getPrimaryExtension(type, currExt); } else if (currExt) ext = "." + currExt; - else - ext = ""; + let re = ext ? RegExp("(\\." + currExt + ")?$", "i") : /$/; var names = []; if (node.title) - names.push([node.title, /*L*/"Page Name"]); + names.push([node.title, + _("buffer.save.pageName")]); if (node.alt) - names.push([node.alt, /*L*/"Alternate Text"]); + names.push([node.alt, + _("buffer.save.altText")]); if (!isinstance(node, Ci.nsIDOMDocument) && node.textContent) - names.push([node.textContent, /*L*/"Link Text"]); + names.push([node.textContent, + _("buffer.save.linkText")]); - names.push([decodeURIComponent(url.replace(/.*?([^\/]*)\/*$/, "$1")), "File Name"]); + names.push([decodeURIComponent(url.replace(/.*?([^\/]*)\/*$/, "$1")), + _("buffer.save.filename")]); return names.filter(function ([leaf, title]) leaf) .map(function ([leaf, title]) [leaf.replace(config.OS.illegalCharacters, encodeURIComponent) @@ -1812,7 +1816,32 @@ var Buffer = Module("Buffer", { completion.savePage = function savePage(context, node) { context.fork("generated", context.filter.replace(/[^/]*$/, "").length, this, function (context) { - context.completions = Buffer.getDefaultNames(node); + context.generate = function () { + this.incomplete = true; + this.completions = Buffer.getDefaultNames(node); + util.httpGet(node.href || node.src || node.documentURI, { + method: "HEAD", + callback: function callback(xhr) { + context.incomplete = false; + try { + if (/filename="(.*?)"/.test(xhr.getResponseHeader("Content-Disposition"))) + context.completions.push([decodeURIComponent(RegExp.$1), _("buffer.save.suggested")]); + } + finally { + context.completions = context.completions.slice(); + } + }, + notificationCallbacks: Class(XPCOM([Ci.nsIChannelEventSink, Ci.nsIInterfaceRequestor]), { + getInterface: function getInterface(iid) this.QueryInterface(iid), + + asyncOnChannelRedirect: util.wrapCallback(function (oldChannel, newChannel, flags, callback) { + if (newChannel instanceof Ci.nsIHttpChannel) + newChannel.requestMethod = "HEAD"; + callback.onRedirectVerifyCallback(Cr.NS_OK); + }) + })() + }); + }; }); }; }, diff --git a/common/modules/util.jsm b/common/modules/util.jsm index a2e7b994..1cd2a6b1 100644 --- a/common/modules/util.jsm +++ b/common/modules/util.jsm @@ -757,6 +757,9 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), if (params.responseType) xmlhttp.responseType = params.responseType; + if (params.notificationCallbacks) + xmlhttp.channel.notificationCallbacks = params.notificationCallbacks; + xmlhttp.send(params.data); return xmlhttp; }