Bug 718203: don't allow drops of javascript: URIs on the home button, r=enndeakin, sr=bz

--HG--
extra : transplant_source : %ADP%C0%F8%8D%C4%A2v%BC%E5ZM%FC%D6BB%B7A%1E%07
This commit is contained in:
Gavin Sharp 2012-01-30 17:58:30 -08:00
parent f1e0ed635f
commit c2834860a5
8 changed files with 117 additions and 19 deletions

View File

@ -3136,13 +3136,17 @@ var browserDragAndDrop = {
}
},
drop: function (aEvent, aName) Services.droppedLinkHandler.dropLink(aEvent, aName)
drop: function (aEvent, aName, aDisallowInherit) {
return Services.droppedLinkHandler.dropLink(aEvent, aName, aDisallowInherit);
}
};
var homeButtonObserver = {
onDrop: function (aEvent)
{
setTimeout(openHomeDialog, 0, browserDragAndDrop.drop(aEvent, { }));
// disallow setting home pages that inherit the principal
let url = browserDragAndDrop.drop(aEvent, {}, true);
setTimeout(openHomeDialog, 0, url);
},
onDragOver: function (aEvent)

View File

@ -182,6 +182,7 @@ _BROWSER_FILES = \
browser_bug719271.js \
browser_canonizeURL.js \
browser_findbarClose.js \
browser_homeDrop.js \
browser_keywordBookmarklets.js \
browser_contextSearchTabPosition.js \
browser_ctrlTab.js \

View File

@ -0,0 +1,77 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
function test() {
waitForExplicitFinish();
// Open a new tab, since starting a drag from the home button activates it and
// we don't want to interfere with future tests by loading the home page.
let newTab = gBrowser.selectedTab = gBrowser.addTab();
registerCleanupFunction(function () {
gBrowser.removeTab(newTab);
});
let scriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"].
getService(Ci.mozIJSSubScriptLoader);
let chromeUtils = {};
scriptLoader.loadSubScript("chrome://mochikit/content/tests/SimpleTest/ChromeUtils.js", chromeUtils);
let homeButton = document.getElementById("home-button");
ok(homeButton, "home button present");
let dialogListener = new WindowListener("chrome://global/content/commonDialog.xul", function (domwindow) {
ok(true, "dialog appeared in response to home button drop");
domwindow.document.documentElement.cancelDialog();
Services.wm.removeListener(dialogListener);
// Now trigger the invalid URI test
executeSoon(function () {
let consoleListener = {
observe: function (m) {
if (m.message.indexOf("NS_ERROR_DOM_BAD_URI") > -1) {
Services.console.unregisterListener(consoleListener);
ok(true, "drop was blocked");
executeSoon(finish);
}
}
}
Services.console.registerListener(consoleListener);
// The drop handler throws an exception when dragging URIs that inherit
// principal, e.g. javascript:
expectUncaughtException();
chromeUtils.synthesizeDrop(homeButton, homeButton, [[{type: "text/plain", data: "javascript:8888"}]], "copy", window, EventUtils);
})
});
Services.wm.addListener(dialogListener);
chromeUtils.synthesizeDrop(homeButton, homeButton, [[{type: "text/plain", data: "http://mochi.test:8888/"}]], "copy", window, EventUtils);
}
function WindowListener(aURL, aCallback) {
this.callback = aCallback;
this.url = aURL;
}
WindowListener.prototype = {
onOpenWindow: function(aXULWindow) {
var domwindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindow);
var self = this;
domwindow.addEventListener("load", function() {
domwindow.removeEventListener("load", arguments.callee, false);
ok(true, "domwindow.document.location.href: " + domwindow.document.location.href);
if (domwindow.document.location.href != self.url)
return;
// Allow other window load listeners to execute before passing to callback
executeSoon(function() {
self.callback(domwindow);
});
}, false);
},
onCloseWindow: function(aXULWindow) {},
onWindowTitleChange: function(aXULWindow, aNewTitle) {}
}

View File

@ -130,8 +130,11 @@ function triggerCommand(aClick, aEvent) {
gURLBar.value = TEST_VALUE;
gURLBar.focus();
if (aClick)
if (aClick) {
is(gURLBar.getAttribute("pageproxystate"), "invalid",
"page proxy state must be invalid for go button to be visible");
EventUtils.synthesizeMouseAtCenter(gGoButton, aEvent);
}
else
EventUtils.synthesizeKey("VK_RETURN", aEvent);
}

View File

@ -39,7 +39,7 @@
interface nsIDOMDragEvent;
interface nsIURI;
[scriptable, uuid(F266B79B-7026-4D2D-B4BD-4F2C6B6C59B4)]
[scriptable, uuid(6B58A5A7-76D0-4E93-AB2E-4DE108683FF8)]
interface nsIDroppedLinkHandler : nsISupports
{
/**
@ -56,15 +56,20 @@ interface nsIDroppedLinkHandler : nsISupports
/**
* Given a drop event aEvent, determines the link being dragged and returns
* it. If a uri is returned the caller can, for instance, load it. If null
* is returned, there is no valid link to be dropped. A
* NS_ERROR_DOM_SECURITY_ERR error will be thrown and the event cancelled if
* is returned, there is no valid link to be dropped.
*
* A NS_ERROR_DOM_SECURITY_ERR error will be thrown and the event cancelled if
* the receiving target should not load the uri for security reasons. This
* will occur if the source of the drag initiated a link for dragging that
* will occur if any of the following conditions are true:
* - the source of the drag initiated a link for dragging that
* it itself cannot access. This prevents a source document from tricking
* the user into a dragging a chrome url for example.
* the user into a dragging a chrome url, for example.
* - aDisallowInherit is true, and the URI being dropped would inherit the
* current document's security context (URI_INHERITS_SECURITY_CONTEXT).
*
* aName is filled in with the link title if it exists, or an empty string
* otherwise.
*/
AString dropLink(in nsIDOMDragEvent aEvent, out AString aName);
AString dropLink(in nsIDOMDragEvent aEvent, out AString aName,
[optional] in boolean aDisallowInherit);
};

View File

@ -50,7 +50,7 @@ ContentAreaDropListener.prototype =
return [ ];
},
_validateURI: function(dataTransfer, uriString)
_validateURI: function(dataTransfer, uriString, disallowInherit)
{
if (!uriString)
return "";
@ -76,11 +76,15 @@ ContentAreaDropListener.prototype =
let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].
getService(Ci.nsIScriptSecurityManager);
let sourceNode = dataTransfer.mozSourceNode;
let flags = secMan.STANDARD;
if (disallowInherit)
flags |= secMan.DISALLOW_INHERIT_PRINCIPAL;
// Use file:/// as the default uri so that drops of file URIs are always allowed
if (sourceNode)
secMan.checkLoadURIStrWithPrincipal(sourceNode.nodePrincipal, uriString, secMan.STANDARD);
secMan.checkLoadURIStrWithPrincipal(sourceNode.nodePrincipal, uriString, flags);
else
secMan.checkLoadURIStr("file:///", uriString, secMan.STANDARD);
secMan.checkLoadURIStr("file:///", uriString, flags);
return uriString;
},
@ -120,7 +124,7 @@ ContentAreaDropListener.prototype =
return true;
},
dropLink: function(aEvent, aName)
dropLink: function(aEvent, aName, aDisallowInherit)
{
aName.value = "";
@ -128,7 +132,7 @@ ContentAreaDropListener.prototype =
let [url, name] = this._getDropURL(dataTransfer);
try {
url = this._validateURI(dataTransfer, url);
url = this._validateURI(dataTransfer, url, aDisallowInherit);
} catch (ex) {
aEvent.stopPropagation();
aEvent.preventDefault();

View File

@ -950,7 +950,7 @@ nsDocShellTreeOwner::HandleEvent(nsIDOMEvent* aEvent)
nsIWebNavigation* webnav = static_cast<nsIWebNavigation *>(mWebBrowser);
nsAutoString link, name;
if (webnav && NS_SUCCEEDED(handler->DropLink(dragEvent, link, name))) {
if (webnav && NS_SUCCEEDED(handler->DropLink(dragEvent, link, false, name))) {
if (!link.IsEmpty()) {
webnav->LoadURI(link.get(), 0, nsnull, nsnull, nsnull);
}

View File

@ -246,8 +246,12 @@ function synthesizeDrop(srcElement, destElement, dragData, dropEffect, aWindow,
// need to use real mouse action
aWindow.addEventListener("dragstart", trapDrag, true);
synthesizeMouseAtCenter(srcElement, { type: "mousedown" }, aWindow);
synthesizeMouse(srcElement, 11, 11, { type: "mousemove" }, aWindow);
synthesizeMouse(srcElement, 20, 20, { type: "mousemove" }, aWindow);
var rect = srcElement.getBoundingClientRect();
var x = rect.width / 2;
var y = rect.height / 2;
synthesizeMouse(srcElement, x, y, { type: "mousemove" }, aWindow);
synthesizeMouse(srcElement, x+10, y+10, { type: "mousemove" }, aWindow);
aWindow.removeEventListener("dragstart", trapDrag, true);
event = aWindow.document.createEvent("DragEvents");