Bug 1522181 - multiple external protocol URL blocker behind pref, r=smaug

This commit is contained in:
Andrea Marchesini 2019-01-24 06:31:41 +01:00
Родитель e2b193a67c
Коммит 0ae3238ccd
3 изменённых файлов: 60 добавлений и 39 удалений

Просмотреть файл

@ -9640,29 +9640,32 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
aContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME,
"DoURILoad thinks this is a frame and InternalLoad does not");
// Only allow URLs able to return data in iframes.
bool doesNotReturnData = false;
NS_URIChainHasFlags(aLoadState->URI(),
nsIProtocolHandler::URI_DOES_NOT_RETURN_DATA,
&doesNotReturnData);
if (doesNotReturnData) {
bool popupBlocked = true;
if (StaticPrefs::dom_block_external_protocol_in_iframes()) {
// Only allow URLs able to return data in iframes.
bool doesNotReturnData = false;
NS_URIChainHasFlags(aLoadState->URI(),
nsIProtocolHandler::URI_DOES_NOT_RETURN_DATA,
&doesNotReturnData);
if (doesNotReturnData) {
bool popupBlocked = true;
// Let's consider external protocols as popups and let's check if the page
// is allowed to open them without abuse regardless of allowed events
if (PopupBlocker::GetPopupControlState() <= PopupBlocker::openBlocked) {
popupBlocked = !PopupBlocker::TryUsePopupOpeningToken();
} else {
nsCOMPtr<nsINode> loadingNode =
mScriptGlobal->AsOuter()->GetFrameElementInternal();
if (loadingNode) {
popupBlocked = !PopupBlocker::CanShowPopupByPermission(
loadingNode->NodePrincipal());
// Let's consider external protocols as popups and let's check if the
// page is allowed to open them without abuse regardless of allowed
// events
if (PopupBlocker::GetPopupControlState() <= PopupBlocker::openBlocked) {
popupBlocked = !PopupBlocker::TryUsePopupOpeningToken();
} else {
nsCOMPtr<nsINode> loadingNode =
mScriptGlobal->AsOuter()->GetFrameElementInternal();
if (loadingNode) {
popupBlocked = !PopupBlocker::CanShowPopupByPermission(
loadingNode->NodePrincipal());
}
}
}
if (popupBlocked) {
return NS_ERROR_UNKNOWN_PROTOCOL;
if (popupBlocked) {
return NS_ERROR_UNKNOWN_PROTOCOL;
}
}
}

Просмотреть файл

@ -10,30 +10,35 @@
<div id='foo'><a href='#'>Click here to test this issue</a></div>
<script>
SimpleTest.waitForExplicitFinish();
let foo = document.getElementById('foo');
foo.addEventListener('click', _ => {
is(ChromeUtils.getPopupControlState(), "openAllowed", "Click events allow popups");
ok(!ChromeUtils.isPopupTokenUnused(), "Popup token has not been used yet");
for (let i = 0; i < 10; ++i) {
let ifr = document.createElement('iframe');
ifr.src = "foo+bar:all_good";
document.body.appendChild(ifr);
function next() {
let foo = document.getElementById('foo');
foo.addEventListener('click', _ => {
is(ChromeUtils.getPopupControlState(), "openAllowed", "Click events allow popups");
ok(ChromeUtils.isPopupTokenUnused(), "Popup token has been used!");
}
ok(!ChromeUtils.isPopupTokenUnused(), "Popup token has not been used yet");
SimpleTest.finish();
for (let i = 0; i < 10; ++i) {
let ifr = document.createElement('iframe');
ifr.src = "foo+bar:all_good";
document.body.appendChild(ifr);
}, {once: true});
is(ChromeUtils.getPopupControlState(), "openAllowed", "Click events allow popups");
ok(ChromeUtils.isPopupTokenUnused(), "Popup token has been used!");
}
setTimeout(_ => {
sendMouseEvent({type:'click'}, 'foo');
}, 0);
SimpleTest.finish();
}, {once: true});
setTimeout(_ => {
sendMouseEvent({type:'click'}, 'foo');
}, 0);
}
SpecialPowers.pushPrefEnv({'set': [
['dom.block_external_protocol_in_iframes', true],
]}, next);
SimpleTest.waitForExplicitFinish();
</script>
</body>
</html>

Просмотреть файл

@ -456,6 +456,19 @@ VARCACHE_PREF(
RelaxedAtomicBool, false
)
// Block multiple external protocol URLs in iframes per single event.
#ifdef NIGHTLY_BUILD
#define PREF_VALUE true
#else
#define PREF_VALUE false
#endif
VARCACHE_PREF(
"dom.block_external_protocol_in_iframes",
dom_block_external_protocol_in_iframes,
bool, PREF_VALUE
)
#undef PREF_VALUE
// Block multiple window.open() per single event.
VARCACHE_PREF(
"dom.block_multiple_popups",