Bug 666604 - Allow untrusted events to trigger a link, r=bz

--HG--
extra : rebase_source : e0b8510a039425c17a3d412241aa8f24df05558a
This commit is contained in:
Olli Pettay 2011-06-30 14:52:11 +03:00
parent 48d3be6b3d
commit e5f1a50b21
11 changed files with 169 additions and 23 deletions

View File

@ -1316,10 +1316,13 @@ public:
* @param aIsUserTriggered whether the user triggered the link. This would be
* false for loads from auto XLinks or from the
* click() method if we ever implement it.
* @param aIsTrusted If PR_FALSE, JS Context will be pushed to stack
* when the link is triggered.
*/
static void TriggerLink(nsIContent *aContent, nsPresContext *aPresContext,
nsIURI *aLinkURI, const nsString& aTargetSpec,
PRBool aClick, PRBool aIsUserTriggered);
PRBool aClick, PRBool aIsUserTriggered,
PRBool aIsTrusted);
/**
* Return top-level widget in the parent chain.

View File

@ -4076,7 +4076,8 @@ nsContentUtils::IsSystemPrincipal(nsIPrincipal* aPrincipal)
void
nsContentUtils::TriggerLink(nsIContent *aContent, nsPresContext *aPresContext,
nsIURI *aLinkURI, const nsString &aTargetSpec,
PRBool aClick, PRBool aIsUserTriggered)
PRBool aClick, PRBool aIsUserTriggered,
PRBool aIsTrusted)
{
NS_ASSERTION(aPresContext, "Need a nsPresContext");
NS_PRECONDITION(aLinkURI, "No link URI");
@ -4111,7 +4112,8 @@ nsContentUtils::TriggerLink(nsIContent *aContent, nsPresContext *aPresContext,
// Only pass off the click event if the script security manager says it's ok.
if (NS_SUCCEEDED(proceed)) {
handler->OnLinkClick(aContent, aLinkURI, aTargetSpec.get());
handler->OnLinkClick(aContent, aLinkURI, aTargetSpec.get(), nsnull, nsnull,
aIsTrusted);
}
}

View File

@ -5032,7 +5032,10 @@ nsGenericElement::CheckHandleEventForLinksPrecondition(nsEventChainVisitor& aVis
nsIURI** aURI) const
{
if (aVisitor.mEventStatus == nsEventStatus_eConsumeNoDefault ||
!NS_IS_TRUSTED_EVENT(aVisitor.mEvent) ||
(!NS_IS_TRUSTED_EVENT(aVisitor.mEvent) &&
(aVisitor.mEvent->message != NS_MOUSE_CLICK) &&
(aVisitor.mEvent->message != NS_KEY_PRESS) &&
(aVisitor.mEvent->message != NS_UI_ACTIVATE)) ||
!aVisitor.mPresContext ||
(aVisitor.mEvent->flags & NS_EVENT_FLAG_PREVENT_ANCHOR_ACTIONS)) {
return PR_FALSE;
@ -5078,7 +5081,7 @@ nsGenericElement::PreHandleEventForLinks(nsEventChainPreVisitor& aVisitor)
nsAutoString target;
GetLinkTarget(target);
nsContentUtils::TriggerLink(this, aVisitor.mPresContext, absURI, target,
PR_FALSE, PR_TRUE);
PR_FALSE, PR_TRUE, PR_TRUE);
// Make sure any ancestor links don't also TriggerLink
aVisitor.mEvent->flags |= NS_EVENT_FLAG_PREVENT_ANCHOR_ACTIONS;
}
@ -5181,7 +5184,7 @@ nsGenericElement::PostHandleEventForLinks(nsEventChainPostVisitor& aVisitor)
nsAutoString target;
GetLinkTarget(target);
nsContentUtils::TriggerLink(this, aVisitor.mPresContext, absURI, target,
PR_TRUE, PR_TRUE);
PR_TRUE, PR_TRUE, NS_IS_TRUSTED_EVENT(aVisitor.mEvent));
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
}
}

View File

@ -502,6 +502,7 @@ _TEST_FILES2 = \
somedatas.resource \
somedatas.resource^headers^ \
delayedServerEvents.sjs \
test_bug666604.html \
$(NULL)
_CHROME_FILES = \

View File

@ -0,0 +1,125 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=666604
-->
<head>
<title>Test for Bug 666604</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=666604">Mozilla Bug 666604</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<a href="javascript:activationListener()" id="testlink">test</a>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 666604 **/
SimpleTest.waitForExplicitFinish();
var activationListener;
function dispatchClick(target, ctrl) {
var e = document.createEvent("MouseEvent");
e.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0,
ctrl, false, false, false, 0, null);
target.dispatchEvent(e);
}
function dispatchReturn(target, ctrl) {
var e = document.createEvent("KeyboardEvent");
e.initKeyEvent("keypress", true, true, window, ctrl, false,
false, false, 13, 0);
target.dispatchEvent(e);
}
function dispatchDOMActivate(target) {
var e = document.createEvent("UIEvent");
e.initUIEvent("DOMActivate", true, true, window, 0);
target.dispatchEvent(e);
}
var testlink = document.getElementById("testlink");
function test1() {
activationListener =
function() {
ok(true, "Untrusted click should activate a link");
test2();
}
dispatchClick(testlink, false);
}
function test2() {
activationListener =
function() {
ok(true, "Untrusted return keypress should activate a link");
test3();
}
dispatchReturn(testlink, false);
}
function test3() {
activationListener =
function() {
ok(false, "Untrusted click+ctrl should not activate a link");
test4();
}
dispatchClick(testlink, true);
setTimeout(test4, 1000);
}
function test4() {
activationListener =
function() {
ok(false, "Untrusted return keypress+ctrl should not activate a link");
test5();
}
dispatchReturn(testlink, true);
setTimeout(test5, 1000);
}
function test5() {
activationListener =
function() {
ok(true, "click() should activate a link");
test6();
}
testlink.click();
}
function test6() {
activationListener =
function() {
ok(true, "Untrusted DOMActivate should activate a link");
test7();
}
dispatchDOMActivate(testlink);
}
function test7() {
testlink.href = "javascript:opener.activationListener(); window.close();";
testlink.target = "_blank";
activationListener =
function() {
ok(true, "Click() should activate a link");
setTimeout(test9, 0);
}
testlink.click();
}
function test9() {
SimpleTest.finish();
}
addLoadEvent(test1);
</script>
</pre>
</body>
</html>

View File

@ -11468,17 +11468,21 @@ public:
OnLinkClickEvent(nsDocShell* aHandler, nsIContent* aContent,
nsIURI* aURI,
const PRUnichar* aTargetSpec,
nsIInputStream* aPostDataStream = 0,
nsIInputStream* aHeadersDataStream = 0);
nsIInputStream* aPostDataStream,
nsIInputStream* aHeadersDataStream,
PRBool aIsTrusted);
NS_IMETHOD Run() {
nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(mHandler->mScriptGlobal));
nsAutoPopupStatePusher popupStatePusher(window, mPopupState);
mHandler->OnLinkClickSync(mContent, mURI,
mTargetSpec.get(), mPostDataStream,
mHeadersDataStream,
nsnull, nsnull);
nsCxPusher pusher;
if (mIsTrusted || pusher.Push(mContent)) {
mHandler->OnLinkClickSync(mContent, mURI,
mTargetSpec.get(), mPostDataStream,
mHeadersDataStream,
nsnull, nsnull);
}
return NS_OK;
}
@ -11490,6 +11494,7 @@ private:
nsCOMPtr<nsIInputStream> mHeadersDataStream;
nsCOMPtr<nsIContent> mContent;
PopupControlState mPopupState;
PRBool mIsTrusted;
};
OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler,
@ -11497,13 +11502,15 @@ OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler,
nsIURI* aURI,
const PRUnichar* aTargetSpec,
nsIInputStream* aPostDataStream,
nsIInputStream* aHeadersDataStream)
nsIInputStream* aHeadersDataStream,
PRBool aIsTrusted)
: mHandler(aHandler)
, mURI(aURI)
, mTargetSpec(aTargetSpec)
, mPostDataStream(aPostDataStream)
, mHeadersDataStream(aHeadersDataStream)
, mContent(aContent)
, mIsTrusted(aIsTrusted)
{
nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(mHandler->mScriptGlobal));
@ -11517,7 +11524,8 @@ nsDocShell::OnLinkClick(nsIContent* aContent,
nsIURI* aURI,
const PRUnichar* aTargetSpec,
nsIInputStream* aPostDataStream,
nsIInputStream* aHeadersDataStream)
nsIInputStream* aHeadersDataStream,
PRBool aIsTrusted)
{
NS_ASSERTION(NS_IsMainThread(), "wrong thread");
@ -11545,7 +11553,7 @@ nsDocShell::OnLinkClick(nsIContent* aContent,
nsCOMPtr<nsIRunnable> ev =
new OnLinkClickEvent(this, aContent, aURI, target.get(),
aPostDataStream, aHeadersDataStream);
aPostDataStream, aHeadersDataStream, aIsTrusted);
return NS_DispatchToCurrentThread(ev);
}

View File

@ -234,8 +234,9 @@ public:
NS_IMETHOD OnLinkClick(nsIContent* aContent,
nsIURI* aURI,
const PRUnichar* aTargetSpec,
nsIInputStream* aPostDataStream = 0,
nsIInputStream* aHeadersDataStream = 0);
nsIInputStream* aPostDataStream,
nsIInputStream* aHeadersDataStream,
PRBool aIsTrusted);
NS_IMETHOD OnLinkClickSync(nsIContent* aContent,
nsIURI* aURI,
const PRUnichar* aTargetSpec,

View File

@ -48,7 +48,8 @@ class nsGUIEvent;
// Interface ID for nsILinkHandler
#define NS_ILINKHANDLER_IID \
{ 0x71627c30, 0xd3c5, 0x4ad0,{0xb5, 0x33, 0x6e, 0x01, 0x91, 0xf2, 0x79, 0x32}}
{ 0xd85670a1, 0x224a, 0x4562, \
{ 0x87, 0xa9, 0x43, 0xa5, 0x24, 0xe7, 0xd0, 0x1b } }
/**
* Interface used for handling clicks on links
@ -66,12 +67,14 @@ public:
* string)
* @param aPostDataStream the POST data to send
* @param aHeadersDataStream ???
* @param aIsTrusted PR_FALSE if the triggerer is an untrusted DOM event.
*/
NS_IMETHOD OnLinkClick(nsIContent* aContent,
nsIURI* aURI,
const PRUnichar* aTargetSpec,
nsIInputStream* aPostDataStream = 0,
nsIInputStream* aHeadersDataStream = 0) = 0;
nsIInputStream* aPostDataStream,
nsIInputStream* aHeadersDataStream,
PRBool aIsTrusted) = 0;
/**
* Process a click on a link.

View File

@ -532,7 +532,7 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetURL(const char *aURL,
nsAutoPopupStatePusher popupStatePusher((PopupControlState)blockPopups);
rv = lh->OnLinkClick(mContent, uri, unitarget.get(),
aPostStream, headersDataStream);
aPostStream, headersDataStream, PR_TRUE);
return rv;
}

View File

@ -432,7 +432,7 @@ nsIsIndexFrame::OnSubmit(nsPresContext* aPresContext)
// Now pretend we're triggering a link
nsContentUtils::TriggerLink(mContent, aPresContext, uri,
EmptyString(), PR_TRUE, PR_TRUE);
EmptyString(), PR_TRUE, PR_TRUE, PR_TRUE);
return result;
}

View File

@ -1627,7 +1627,7 @@ nsImageFrame::HandleEvent(nsPresContext* aPresContext,
clicked = PR_TRUE;
}
nsContentUtils::TriggerLink(anchorNode, aPresContext, uri, target,
clicked, PR_TRUE);
clicked, PR_TRUE, PR_TRUE);
}
}
}