Bug 1324410 - fix dnd to the location bar for plaintext, r=mak
MozReview-Commit-ID: 7md3hnxisDP
--- a/browser/base/content/test/urlbar/browser_dragdropURL.js
+++ b/browser/base/content/test/urlbar/browser_dragdropURL.js
@@ -1,15 +1,38 @@
"use strict";
const TEST_URL = "data:text/html,a test page";
const DRAG_URL = "http://www.example.com/";
+const DRAG_FORBIDDEN_URL = "chrome://browser/content/aboutDialog.xul";
+const DRAG_TEXT = "Firefox is awesome";
+const DRAG_WORD = "Firefox";
-add_task(function* checkURLBarUpdateForDrag() {
+add_task(function* checkDragURL() {
yield BrowserTestUtils.withNewTab(TEST_URL, function* (browser) {
// Have to use something other than the URL bar as a source, so picking the
// downloads button somewhat arbitrarily:
EventUtils.synthesizeDrop(document.getElementById("downloads-button"), gURLBar,
[[{type: "text/plain", data: DRAG_URL}]], "copy", window);
is(gURLBar.value, TEST_URL, "URL bar value should not have changed");
is(gBrowser.selectedBrowser.userTypedValue, null, "Stored URL bar value should not have changed");
});
});
+
+add_task(function* checkDragForbiddenURL() {
+ yield BrowserTestUtils.withNewTab(TEST_URL, function* (browser) {
+ EventUtils.synthesizeDrop(document.getElementById("downloads-button"), gURLBar,
+ [[{type: "text/plain", data: DRAG_FORBIDDEN_URL}]], "copy", window);
+ isnot(gURLBar.value, DRAG_FORBIDDEN_URL, "Shouldn't be allowed to drop forbidden URL on URL bar");
+ });
+});
+
+add_task(function* checkDragText() {
+ yield BrowserTestUtils.withNewTab(TEST_URL, function* (browser) {
+ EventUtils.synthesizeDrop(document.getElementById("downloads-button"), gURLBar,
+ [[{type: "text/plain", data: DRAG_TEXT}]], "copy", window);
+ is(gURLBar.value, DRAG_TEXT, "Dragging normal text should replace the URL bar value");
+
+ EventUtils.synthesizeDrop(document.getElementById("downloads-button"), gURLBar,
+ [[{type: "text/plain", data: DRAG_WORD}]], "copy", window);
+ is(gURLBar.value, DRAG_WORD, "Dragging a single word should replace the URL bar value");
+ });
+});
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -696,65 +696,91 @@ file, You can obtain one at http://mozil
</method>
<method name="_hideURLTooltip">
<body><![CDATA[
this.inputField.removeAttribute("tooltiptext");
]]></body>
</method>
- <method name="_getDroppableLink">
+ <!-- Returns:
+ null if there's a security issue and we should do nothing.
+ a URL object if there is one that we're OK with loading,
+ a text value otherwise.
+ -->
+ <method name="_getDroppableItem">
<parameter name="aEvent"/>
<body><![CDATA[
- let links = browserDragAndDrop.dropLinks(aEvent);
+ let links;
+ try {
+ links = browserDragAndDrop.dropLinks(aEvent);
+ } catch (ex) {
+ // this is possibly a security exception, in which case we should return
+ // null. Always return null because we can't *know* what exception is
+ // being returned.
+ return null;
+ }
// The URL bar automatically handles inputs with newline characters,
// so we can get away with treating text/x-moz-url flavours as text/plain.
if (links.length > 0 && links[0].url) {
aEvent.preventDefault();
let url = links[0].url;
let strippedURL = stripUnsafeProtocolOnPaste(url);
if (strippedURL != url) {
aEvent.stopImmediatePropagation();
return null;
}
+ let urlObj;
try {
- urlSecurityCheck(url,
- gBrowser.contentPrincipal,
- Ci.nsIScriptSecurityManager.DISALLOW_INHERIT_PRINCIPAL);
+ // If this throws, urlSecurityCheck would also throw, as that's what it
+ // does with things that don't pass the IO service's newURI constructor
+ // without fixup. It's conceivable we may want to relax this check in
+ // the future (so e.g. www.foo.com gets fixed up), but not right now.
+ urlObj = new URL(url);
+ // If we succeed, try to pass security checks. If this works, return the
+ // URL object. If the *security checks* fail, return null.
+ try {
+ urlSecurityCheck(url,
+ gBrowser.contentPrincipal,
+ Ci.nsIScriptSecurityManager.DISALLOW_INHERIT_PRINCIPAL);
+ return urlObj;
+ } catch (ex) {
+ return null;
+ }
} catch (ex) {
- return null;
+ // We couldn't make a URL out of this. Continue on, and return text below.
}
- return url;
}
- return null;
+ return aEvent.dataTransfer.getData("text/unicode");
]]></body>
</method>
<method name="onDragOver">
<parameter name="aEvent"/>
<body><![CDATA[
- // We don't need the link here, so we ignore the return value.
- if (!this._getDroppableLink(aEvent)) {
+ if (!this._getDroppableItem(aEvent)) {
aEvent.dataTransfer.dropEffect = "none";
}
]]></body>
</method>
<method name="onDrop">
<parameter name="aEvent"/>
<body><![CDATA[
- let url = this._getDroppableLink(aEvent);
- if (url) {
- this.value = url;
+ let droppedItem = this._getDroppableItem(aEvent);
+ if (droppedItem) {
+ this.value = droppedItem instanceof URL ? droppedItem.href : droppedItem;
SetPageProxyState("invalid");
this.focus();
- this.handleCommand();
- // Force not showing the dropped URI immediately.
- gBrowser.userTypedValue = null;
- URLBarSetURI();
+ if (droppedItem instanceof URL) {
+ this.handleCommand();
+ // Force not showing the dropped URI immediately.
+ gBrowser.userTypedValue = null;
+ URLBarSetURI();
+ }
}
]]></body>
</method>
<method name="_getSelectedValueForClipboard">
<body><![CDATA[
// Grab the actual input field's value, not our value, which could include moz-action:
var inputVal = this.inputField.value;