Bug 1560741 - Part 1: Disallow notification permission requests from cross-origin iframes; r=johannh

Differential Revision: https://phabricator.services.mozilla.com/D41305

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Ehsan Akhgari 2019-08-12 21:38:58 +00:00
parent 7e441e1dd8
commit 64cd489087
7 changed files with 88 additions and 1 deletions

View File

@ -39,6 +39,8 @@
}
async function runTest() {
await SpecialPowers.setBoolPref("dom.webnotifications.allowcrossoriginiframe", true);
// Test programmatic request for persistent storage.
let request = checkPermissionRequest("persistent-storage", false);
navigator.storage.persist();
@ -78,6 +80,8 @@
frameWin.Notification.requestPermission();
});
await request;
await SpecialPowers.clearUserPref("dom.webnotifications.allowcrossoriginiframe");
}
frame.addEventListener("load", function() {

View File

@ -324,6 +324,7 @@ LargeAllocationNotOnlyToplevelInTabGroup=A Large-Allocation header was ignored d
LargeAllocationNonE10S=A Large-Allocation header was ignored due to the document not being loaded out of process.
GeolocationInsecureRequestIsForbidden=A Geolocation request can only be fulfilled in a secure context.
NotificationsInsecureRequestIsForbidden=The Notification permission may only be requested in a secure context.
NotificationsCrossOriginIframeRequestIsForbidden=The Notification permission may only be requested in a top-level document or same-origin iframe.
NotificationsRequireUserGesture=The Notification permission may only be requested from inside a short running user-generated event handler.
# LOCALIZATION NOTE: Do not translate "Large-Allocation", as it is a literal header name.
LargeAllocationNonWin32=This page would be loaded in a new process due to a Large-Allocation header, however Large-Allocation process creation is disabled on non-Win32 platforms.

View File

@ -470,7 +470,9 @@ NS_IMPL_QUERY_INTERFACE_CYCLE_COLLECTION_INHERITED(
NS_IMETHODIMP
NotificationPermissionRequest::Run() {
if (nsContentUtils::IsSystemPrincipal(mPrincipal)) {
bool isSystem = nsContentUtils::IsSystemPrincipal(mPrincipal);
bool blocked = false;
if (isSystem) {
mPermission = NotificationPermission::Granted;
} else {
// File are automatically granted permission.
@ -482,6 +484,7 @@ NotificationPermissionRequest::Run() {
} else if (!StaticPrefs::dom_webnotifications_allowinsecure() &&
!mWindow->IsSecureContext()) {
mPermission = NotificationPermission::Denied;
blocked = true;
nsCOMPtr<Document> doc = mWindow->GetExtantDoc();
if (doc) {
nsContentUtils::ReportToConsole(
@ -509,6 +512,22 @@ NotificationPermissionRequest::Run() {
break;
}
// Check this after checking the prompt prefs to make sure this pref overrides
// those. We rely on this for testing purposes.
if (!isSystem && !blocked &&
!StaticPrefs::dom_webnotifications_allowcrossoriginiframe() &&
!mPrincipal->Subsumes(mTopLevelPrincipal)) {
mPermission = NotificationPermission::Denied;
blocked = true;
nsCOMPtr<Document> doc = mWindow->GetExtantDoc();
if (doc) {
nsContentUtils::ReportToConsole(
nsIScriptError::errorFlag, NS_LITERAL_CSTRING("DOM"), doc,
nsContentUtils::eDOM_PROPERTIES,
"NotificationsCrossOriginIframeRequestIsForbidden");
}
}
if (mPermission != NotificationPermission::Default) {
return DispatchResolvePromise();
}

View File

@ -0,0 +1,4 @@
<!DOCTYPE html>
<html>
<body></body>
</html>

View File

@ -1,12 +1,14 @@
[DEFAULT]
support-files =
blank.html
create_notification.html
MockServices.js
NotificationTest.js
skip-if = toolkit == 'android' && !is_fennec # Bug 1531097
[test_notification_basics.html]
[test_notification_crossorigin_iframe.html]
# This test needs to be run on HTTP (not HTTPS).
[test_notification_insecure_context.html]
[test_notification_storage.html]

View File

@ -0,0 +1,52 @@
<!DOCTYPE HTML>
<html>
<!--
Tests that Notification permissions are denied in cross-origin iframes.
https://bugzilla.mozilla.org/show_bug.cgi?id=1560741
-->
<head>
<title>Notification permission in cross-origin iframes</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
const kBlankURL = "https://example.com/tests/dom/notification/test/mochitest/blank.html";
(async function runTest() {
await SpecialPowers.setBoolPref("notification.prompt.testing", true);
await SpecialPowers.setBoolPref("notification.prompt.testing.allow", true);
await SpecialPowers.setBoolPref("dom.webnotifications.allowinsecure", true);
let iframe = document.createElement("iframe");
iframe.src = kBlankURL;
document.body.appendChild(iframe);
await new Promise(resolve => {
iframe.onload = resolve;
});
const Notif = SpecialPowers.wrap(iframe.contentWindow).Notification;
let response = await Notif.requestPermission();
is(response, "denied", "Denied permission in cross-origin iframe");
await SpecialPowers.pushPrefEnv({"set": [["dom.webnotifications.allowcrossoriginiframe", true]]});
response = await Notif.requestPermission();
is(response, "granted", "Granted permission in cross-origin iframe with pref set");
await SpecialPowers.clearUserPref("notification.prompt.testing");
await SpecialPowers.clearUserPref("notification.prompt.testing.allow");
await SpecialPowers.clearUserPref("dom.webnotifications.allowinsecure");
SimpleTest.finish();
})();
</script>
</pre>
</body>
</html>

View File

@ -2337,6 +2337,11 @@
value: false
mirror: always
- name: dom.webnotifications.allowcrossoriginiframe
type: RelaxedAtomicBool
value: false
mirror: always
- name: dom.webnotifications.enabled
type: RelaxedAtomicBool
value: true