Bug 766654 - Allow pasting of a URL into the Downloads Panel to initiate a download. r=mak.
--- a/browser/components/downloads/content/downloads.js
+++ b/browser/components/downloads/content/downloads.js
@@ -103,16 +103,17 @@ const DownloadsPanel = {
Services.downloads;
// Now that data loading has eventually started, load the required XUL
// elements and initialize our views.
DownloadsOverlayLoader.ensureOverlayLoaded(this.kDownloadsOverlay,
function DP_I_callback() {
DownloadsViewController.initialize();
DownloadsCommon.data.addView(DownloadsView);
+ DownloadsPanel._attachEventListeners();
aCallback();
});
},
/**
* Closes the downloads panel and frees the internal resources related to the
* downloads. The downloads panel can be reopened later, even after this
* function has been called.
@@ -125,16 +126,17 @@ const DownloadsPanel = {
window.removeEventListener("unload", this.onWindowUnload, false);
// Ensure that the panel is closed before shutting down.
this.hidePanel();
DownloadsViewController.terminate();
DownloadsCommon.data.removeView(DownloadsView);
+ this._unattachEventListeners();
this._state = this.kStateUninitialized;
},
//////////////////////////////////////////////////////////////////////////////
//// Panel interface
/**
@@ -270,32 +272,97 @@ const DownloadsPanel = {
BrowserDownloadsUI();
},
//////////////////////////////////////////////////////////////////////////////
//// Internal functions
/**
+ * Attach event listeners to a panel element. These listeners should be
+ * removed in _unattachEventListeners. This is called automatically after the
+ * panel has successfully loaded.
+ */
+ _attachEventListeners: function DP__attachEventListeners()
+ {
+ this.panel.addEventListener("keydown", this._onKeyDown.bind(this), false);
+ },
+
+ /**
+ * Unattach event listeners that were added in _attachEventListeners. This
+ * is called automatically on panel termination.
+ */
+ _unattachEventListeners: function DP__unattachEventListeners()
+ {
+ this.panel.removeEventListener("keydown", this._onKeyDown.bind(this),
+ false);
+ },
+
+ /**
+ * Keydown listener that listens for the accel-V "paste" event. Initiates a
+ * file download if the pasted item can be resolved to a URI.
+ */
+ _onKeyDown: function DP__onKeyDown(aEvent)
+ {
+ let pasting = aEvent.keyCode == Ci.nsIDOMKeyEvent.DOM_VK_V &&
+#ifdef XP_MACOSX
+ aEvent.metaKey;
+#else
+ aEvent.ctrlKey;
+#endif
+
+ if (!pasting) {
+ return;
+ }
+
+ let trans = Cc["@mozilla.org/widget/transferable;1"]
+ .createInstance(Ci.nsITransferable);
+ trans.init(null);
+ let flavors = ["text/x-moz-url", "text/unicode"];
+ flavors.forEach(trans.addDataFlavor);
+ Services.clipboard.getData(trans, Services.clipboard.kGlobalClipboard);
+ // Getting the data or creating the nsIURI might fail
+ try {
+ let data = {};
+ trans.getAnyTransferData({}, data, {});
+ let [url, name] = data.value
+ .QueryInterface(Ci.nsISupportsString)
+ .data
+ .split("\n");
+ if (!url) {
+ return;
+ }
+
+ let uri = Services.io.newURI(url, null, null);
+ saveURL(uri.spec, name || uri.spec, null, true, true,
+ undefined, document);
+ } catch (ex) {}
+ },
+
+ /**
* Move focus to the main element in the downloads panel, unless another
* element in the panel is already focused.
*/
_focusPanel: function DP_focusPanel()
{
// We may be invoked while the panel is still waiting to be shown.
if (this._state != this.kStateShown) {
return;
}
let element = document.commandDispatcher.focusedElement;
while (element && element != this.panel) {
element = element.parentNode;
}
if (!element) {
- DownloadsView.richListBox.focus();
+ if (DownloadsView.richListBox.itemCount > 0) {
+ DownloadsView.richListBox.focus();
+ } else {
+ DownloadsView.downloadsHistory.focus();
+ }
}
},
/**
* Opens the downloads panel when data is ready to be displayed.
*/
_openPopupIfDataReady: function DP_openPopupIfDataReady()
{
--- a/browser/components/downloads/jar.mn
+++ b/browser/components/downloads/jar.mn
@@ -1,11 +1,11 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
browser.jar:
content/browser/downloads/download.xml (content/download.xml)
content/browser/downloads/downloads.css (content/downloads.css)
- content/browser/downloads/downloads.js (content/downloads.js)
+* content/browser/downloads/downloads.js (content/downloads.js)
* content/browser/downloads/downloadsOverlay.xul (content/downloadsOverlay.xul)
content/browser/downloads/indicator.js (content/indicator.js)
content/browser/downloads/indicatorOverlay.xul (content/indicatorOverlay.xul)