Skip to content

Instantly share code, notes, and snippets.

@wenketel
Forked from yume-chan/downloadEnhancer.uc.js
Created December 5, 2013 10:33
Show Gist options
  • Save wenketel/7803248 to your computer and use it in GitHub Desktop.
Save wenketel/7803248 to your computer and use it in GitHub Desktop.
// ==UserScript==
// @id downloadEnhancer
// @name Download Dialog Enhancer
// @version 1.6
// @namespace simon
// @author Simon Chan
// @description Add copying link, saving as, encoding conversion and renaming functions to download dialog.
// @include chrome://browser/content/browser.xul
// @include chrome://mozapps/content/downloads/unknownContentType.xul
// @run-at document-end
// ==/UserScript==
"use strict;"
if (document.location == "chrome://browser/content/browser.xul") {
const obsService = Cc['@mozilla.org/observer-service;1'].getService(Ci.nsIObserverService);
const RESPONSE_TOPIC = 'http-on-examine-response';
var respObserver = {
observing: false,
observe: function (subject, topic, data) {
try {
let channel = subject.QueryInterface(Ci.nsIHttpChannel);
let header = channel.contentDispositionHeader;
let associatedWindow = channel.notificationCallbacks
.getInterface(Components.interfaces.nsILoadContext)
.associatedWindow;
associatedWindow.localStorage.setItem(channel.URI.spec, header.split("=")[1]);
} catch (ex) { }
},
start: function () {
if (!this.observing) {
obsService.addObserver(this, RESPONSE_TOPIC, false);
this.observing = true;
}
},
stop: function () {
if (this.observing) {
obsService.removeObserver(this, RESPONSE_TOPIC, false);
this.observing = false;
}
}
};
respObserver.start();
addEventListener("beforeunload", function () {
respObserver.stop();
})
}
else if (document.location == "chrome://mozapps/content/downloads/unknownContentType.xul") {
dialog.onBlur = function () { };
var downloadModule = {};
Components.utils.import("resource://gre/modules/DownloadLastDir.jsm", downloadModule);
var saveButton = document.documentElement.getButton("accept");
var copyButton = document.createElement("button");
copyButton.className = "dialog-button";
copyButton.setAttribute("label", "Copy Link");
copyButton.addEventListener("click", function () {
Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper)
.copyString(dialog.mLauncher.source.spec);
});
saveButton.parentNode.insertBefore(copyButton, saveButton);
let orginalString = opener.localStorage.getItem(dialog.mLauncher.source.spec).replace(/[\/:*?"<>|]/g, "");
opener.localStorage.removeItem(dialog.mLauncher.source.spec);
var saveAsButton = document.createElement("button");
saveAsButton.className = "dialog-button";
saveAsButton.setAttribute("label", "Save as...");
saveAsButton.addEventListener("click", function () {
function isUsableDirectory(aDirectory) {
return aDirectory.exists() && aDirectory.isDirectory() &&
aDirectory.isWritable();
}
var bundle = Components.classes["@mozilla.org/intl/stringbundle;1"].
getService(Components.interfaces.nsIStringBundleService).
createBundle("chrome://mozapps/locale/downloads/unknownContentType.properties");
var nsIFilePicker = Components.interfaces.nsIFilePicker;
var picker = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
var windowTitle = bundle.GetStringFromName("saveDialogTitle");
var parent = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindow);
picker.init(parent, windowTitle, nsIFilePicker.modeSave);
let filename = this.mDialog.document.querySelector("#locationtext").value.replace(/[\/:*?"<>|]/g, "")
if (filename.indexOf(".") == -1 && this.mLauncher.MIMEInfo.primaryExtension != "")
filename += "." + this.mLauncher.MIMEInfo.primaryExtension;
var gDownloadLastDir = new downloadModule.DownloadLastDir(parent);
try {
picker.defaultExtension = this.mLauncher.MIMEInfo.primaryExtension;
}
catch (ex) { }
picker.appendFilters(nsIFilePicker.filterAll);
var dnldMgr = Components.classes["@mozilla.org/download-manager;1"]
.getService(Components.interfaces.nsIDownloadManager);
picker.displayDirectory = dnldMgr.userDownloadsDirectory;
gDownloadLastDir.getFileAsync(dialog.mLauncher.source, function LastDirCallback(lastDir) {
if (lastDir && isUsableDirectory(lastDir))
picker.displayDirectory = lastDir;
if (picker.show() == nsIFilePicker.returnCancel) {
return;
}
result = picker.file;
if (result) {
try {
if (result.exists())
result.remove(false);
}
catch (e) { }
var newDir = result.parent.QueryInterface(Components.interfaces.nsILocalFile);
gDownloadLastDir.setFile(dialog.mLauncher.source, newDir);
result = dialog.validateLeafName(newDir, result.leafName, null);
dialog.mLauncher.saveToDisk(result, false);
dialog.onCancel = null;
close();
}
}.bind(this));
});
saveButton.parentNode.insertBefore(saveAsButton, saveButton);
var location = document.querySelector("#location");
var locationText = location.parentNode
.insertBefore(document.createElement("menulist"), location);
locationText.id = "locationtext";
locationText.setAttribute("editable", "true");
locationText.setAttribute("style", "margin-top:-2px;margin-bottom:-3px");
locationText.value = orginalString;
locationText.addEventListener("command", function (e) {
locationText.value = e.target.value;
document.title = "Opening " + e.target.value;
});
let menupopup = locationText.appendChild(document.createElement("menupopup"));
let menuitem = menupopup.appendChild(document.createElement("menuitem"));
menuitem.value = orginalString;
menuitem.label = "Original: " + orginalString;
let converter = Components.classes['@mozilla.org/intl/scriptableunicodeconverter']
.getService(Components.interfaces.nsIScriptableUnicodeConverter);
function createMenuitem(encoding) {
converter.charset = encoding;
let menuitem = menupopup.appendChild(document.createElement("menuitem"));
menuitem.value = converter.ConvertToUnicode(orginalString).replace(/^"(.+)"$/, "$1");
menuitem.label = encoding + ": " + menuitem.value;
}
["GB18030", "BIG5", "Shift-JIS"].forEach(function (item) { createMenuitem(item) });
function toggleState() {
if (dialog.dialogElement("save").selected) {
location.hidden = true;
locationText.hidden = false;
} else {
location.hidden = false;
locationText.hidden = true;
}
}
document.querySelector("#mode").addEventListener("select", toggleState, false);
toggleState();
dialog.notify = function (aTimer) {
if (aTimer == this._showTimer) {
if (!this.mDialog)
this.reallyShow();
else {
document.documentElement.getButton("accept").disabled = false;
this._showTimer = null;
}
}
else if (aTimer == this._saveToDiskTimer) {
var dnldMgr = Components.classes["@mozilla.org/download-manager;1"]
.getService(Components.interfaces.nsIDownloadManager);
let filename = this.mDialog.document.querySelector("#locationtext").value.replace(/[\/:*?"<>|]/g, "")
if (filename.indexOf(".") == -1 && this.mLauncher.MIMEInfo.primaryExtension != "")
filename += "." + this.mLauncher.MIMEInfo.primaryExtension;
var result = this.validateLeafName(dnldMgr.userDownloadsDirectory,
filename, null);
this.mLauncher.saveToDisk(result, false);
this._saveToDiskTimer = null;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment