Diff
Modified: trunk/LayoutTests/ChangeLog (290197 => 290198)
--- trunk/LayoutTests/ChangeLog 2022-02-19 04:27:39 UTC (rev 290197)
+++ trunk/LayoutTests/ChangeLog 2022-02-19 05:26:41 UTC (rev 290198)
@@ -1,3 +1,43 @@
+2022-02-18 Ben Nham <n...@apple.com>
+
+ Hook up PushManager to permission state
+ https://bugs.webkit.org/show_bug.cgi?id=236739
+
+ Reviewed by Brady Eidson.
+
+ Added tests that make sure that PushManager.permissionState() and PushManager.subscribe()
+ respect the notification permission level for the current origin.
+
+ I made these regular tests rather than WPT tests because the WPT test harness calls
+ grantWebNotificationPermission at the top of its setup script (in testharnessreport.js), and
+ I didn't want to change that for this patch.
+
+ * http/tests/push-api/resources/push-api-test-pre.js: Added.
+ (finishPushAPITest):
+ (waitForState):
+ * http/tests/push-api/resources/subscribe-iframe-cross-origin.html: Added.
+ * http/tests/push-api/resources/subscribe-iframe-same-origin.html: Added.
+ * http/tests/push-api/resources/subscribe-tests.js: Added.
+ (async testServiceWorkerPermissionState):
+ (async testDocumentPermissionState):
+ (async testServiceWorkerSubscribe):
+ (async testDocumentSubscribe):
+ * http/tests/push-api/resources/subscribe-worker.js: Added.
+ (async event):
+ * http/tests/push-api/subscribe-default-permissions-expected.txt: Added.
+ * http/tests/push-api/subscribe-default-permissions-iframe-cross-origin-expected.txt: Added.
+ * http/tests/push-api/subscribe-default-permissions-iframe-cross-origin.html: Added.
+ * http/tests/push-api/subscribe-default-permissions-iframe-same-origin-expected.txt: Added.
+ * http/tests/push-api/subscribe-default-permissions-iframe-same-origin.html: Added.
+ * http/tests/push-api/subscribe-default-permissions.html: Added.
+ * http/tests/push-api/subscribe-deny-permissions-expected.txt: Added.
+ * http/tests/push-api/subscribe-deny-permissions.html: Added.
+ * http/tests/push-api/subscribe-grant-permissions-expected.txt: Added.
+ * http/tests/push-api/subscribe-grant-permissions.html: Added.
+ * platform/gtk/TestExpectations:
+ * platform/mac-wk1/TestExpectations:
+ * platform/win/TestExpectations:
+
2022-02-18 Ryan Haddad <ryanhad...@apple.com>
http/wpt/push-api/onpush-disabled.html fails (incremental build issue?)
Added: trunk/LayoutTests/http/tests/push-api/resources/push-api-test-pre.js (0 => 290198)
--- trunk/LayoutTests/http/tests/push-api/resources/push-api-test-pre.js (rev 0)
+++ trunk/LayoutTests/http/tests/push-api/resources/push-api-test-pre.js 2022-02-19 05:26:41 UTC (rev 290198)
@@ -0,0 +1,49 @@
+if (window.testRunner) {
+ testRunner.dumpAsText();
+ testRunner.waitUntilDone();
+}
+
+function finishPushAPITest()
+{
+ if (typeof window !== 'undefined' && window.parent !== window) {
+ window.parent.postMessage('finishPushAPITest', '*');
+ return;
+ }
+
+ if (window.testRunner)
+ testRunner.notifyDone();
+}
+
+function waitForState(worker, state)
+{
+ if (!worker || worker.state == undefined)
+ return Promise.reject(new Error('wait_for_state must be passed a ServiceWorker'));
+
+ if (worker.state === state)
+ return Promise.resolve(state);
+
+ return new Promise(function(resolve) {
+ worker.addEventListener('statechange', function() {
+ if (worker.state === state)
+ resolve(state);
+ });
+ });
+}
+
+function log(msg)
+{
+ if (typeof window !== 'undefined' && window.parent !== window) {
+ window.parent.postMessage(msg, '*');
+ return;
+ }
+
+ let console = document.getElementById("console");
+ if (!console) {
+ console = document.createElement("div");
+ console.id = "console";
+ document.body.appendChild(console);
+ }
+ let span = document.createElement("span");
+ span.innerHTML = msg + "<br>";
+ console.appendChild(span);
+}
Added: trunk/LayoutTests/http/tests/push-api/resources/subscribe-iframe-cross-origin.html (0 => 290198)
--- trunk/LayoutTests/http/tests/push-api/resources/subscribe-iframe-cross-origin.html (rev 0)
+++ trunk/LayoutTests/http/tests/push-api/resources/subscribe-iframe-cross-origin.html 2022-02-19 05:26:41 UTC (rev 290198)
@@ -0,0 +1,18 @@
+<script src=""
+<script src=""
+<script>
+navigator.serviceWorker.register("subscribe-worker.js", { }).then(async (registration) => {
+ try {
+ await waitForState(registration.installing, "activated");
+ await testServiceWorkerPermissionState(registration, 'prompt');
+ await testDocumentPermissionState(registration, 'prompt');
+ await testServiceWorkerSubscribe(registration, 'NotAllowedError');
+ await testDocumentSubscribe(registration, 'NotAllowedError');
+ } catch (e) {
+ log(`FAIL: unexpected exception ${e}`);
+ } finally {
+ await registration.unregister();
+ finishPushAPITest();
+ }
+});
+</script>
Added: trunk/LayoutTests/http/tests/push-api/resources/subscribe-iframe-same-origin.html (0 => 290198)
--- trunk/LayoutTests/http/tests/push-api/resources/subscribe-iframe-same-origin.html (rev 0)
+++ trunk/LayoutTests/http/tests/push-api/resources/subscribe-iframe-same-origin.html 2022-02-19 05:26:41 UTC (rev 290198)
@@ -0,0 +1,18 @@
+<script src=""
+<script src=""
+<script>
+navigator.serviceWorker.register("subscribe-worker.js", { }).then(async (registration) => {
+ try {
+ await waitForState(registration.installing, "activated");
+ await testServiceWorkerPermissionState(registration, 'prompt');
+ await testDocumentPermissionState(registration, 'prompt');
+ await testServiceWorkerSubscribe(registration, 'NotAllowedError');
+ await testDocumentSubscribe(registration);
+ } catch (e) {
+ log(`FAIL: unexpected exception ${e}`);
+ } finally {
+ await registration.unregister();
+ finishPushAPITest();
+ }
+});
+</script>
Added: trunk/LayoutTests/http/tests/push-api/resources/subscribe-tests.js (0 => 290198)
--- trunk/LayoutTests/http/tests/push-api/resources/subscribe-tests.js (rev 0)
+++ trunk/LayoutTests/http/tests/push-api/resources/subscribe-tests.js 2022-02-19 05:26:41 UTC (rev 290198)
@@ -0,0 +1,71 @@
+const VALID_SERVER_KEY = "BA1Hxzyi1RUM1b5wjxsn7nGxAszw2u61m164i3MrAIxHF6YK5h4SDYic-dRuU_RCPCfA5aq9ojSwk5Y2EmClBPs";
+
+async function testServiceWorkerPermissionState(registration, expected)
+{
+ let promise = new Promise(resolve => navigator.serviceWorker._onmessage_ = resolve);
+ registration.active.postMessage(['permissionState']);
+ let event = await promise;
+ let result = event.data;
+
+ if (result == expected)
+ log(`PASS: service worker permissionState was ${expected}`);
+ else
+ log(`FAIL: service worker permissionState should be ${expected}, but was ${result}`);
+}
+
+async function testDocumentPermissionState(registration, expected)
+{
+ let state = await registration.pushManager.permissionState();
+
+ if (state == expected)
+ log(`PASS: document permissionState was ${expected}`);
+ else
+ log(`FAIL: document permissionState should be ${expected}, but was ${state}`);
+}
+
+async function testServiceWorkerSubscribe(registration, domExceptionName)
+{
+ let expected = domExceptionName ? `error: ${domExceptionName}` : "successful";
+
+ let promise = new Promise(resolve => { navigator.serviceWorker._onmessage_ = resolve; });
+ registration.active.postMessage(['subscribe', VALID_SERVER_KEY]);
+ let event = await promise;
+ let result = event.data;
+
+ if (result == expected)
+ log(`PASS: service worker subscribe was ${expected}`);
+ else
+ log(`FAIL: service worker subscribe should be ${expected}, but was ${result}`);
+}
+
+async function testDocumentSubscribe(registration, domExceptionName)
+{
+ let expected = domExceptionName ? `error: ${domExceptionName}` : "successful";
+ let result = null;
+
+ let subscription = null;
+ try {
+ // With default permissions, PushManager should request permission from TestController.
+ // TestController always calls WKNotificationPermissionRequestAllow so this should succeed.
+ subscription = await registration.pushManager.subscribe({
+ userVisibleOnly: true,
+ applicationServerKey: VALID_SERVER_KEY
+ });
+ result = 'successful';
+ } catch (e) {
+ // Layout tests aren't connected to webpushd, so subscribe is successful if it gets to the
+ // point where we attempt to communicate with webpushd (an AbortError).
+ if (e.name == 'AbortError')
+ result = 'successful';
+ else
+ result = 'error: ' + (e ? e.name : null);
+ }
+
+ if (subscription)
+ await subscription.unsubscribe();
+
+ if (result == expected)
+ log(`PASS: document subscribe was ${expected}`);
+ else
+ log(`FAIL: document subscribe should be ${expected}, but was ${result}`);
+}
\ No newline at end of file
Added: trunk/LayoutTests/http/tests/push-api/resources/subscribe-worker.js (0 => 290198)
--- trunk/LayoutTests/http/tests/push-api/resources/subscribe-worker.js (rev 0)
+++ trunk/LayoutTests/http/tests/push-api/resources/subscribe-worker.js 2022-02-19 05:26:41 UTC (rev 290198)
@@ -0,0 +1,43 @@
+const VALID_SERVER_KEY = "BA1Hxzyi1RUM1b5wjxsn7nGxAszw2u61m164i3MrAIxHF6YK5h4SDYic-dRuU_RCPCfA5aq9ojSwk5Y2EmClBPs";
+
+self.addEventListener('message', async (event) => {
+ let [op, ...args] = event.data;
+
+ if (op == 'permissionState') {
+ try {
+ let state = await self.registration.pushManager.permissionState();
+ event.source.postMessage(state);
+ } catch (e) {
+ event.source.postMessage("error: " + e);
+ }
+ } else if (op == 'subscribe') {
+ let subscription = null;
+ let result = null;
+
+ try {
+ subscription = await self.registration.pushManager.subscribe({
+ userVisibleOnly: true,
+ applicationServerKey: args[0]
+ });
+ if (subscription)
+ result = "successful";
+ else
+ result = "error: null subscription";
+ } catch (e) {
+ if (!e)
+ result = "error: null exception";
+ else if (e.name == 'AbortError')
+ // Layout tests currently aren't connected to webpushd. So if we fail with an AbortError
+ // when trying to connect to webpushd, we count that as a successful subscription for
+ // testing purposes.
+ result = "successful";
+ else
+ result = "error: " + e.name;
+ }
+
+ if (subscription)
+ await subscription.unsubscribe();
+
+ event.source.postMessage(result);
+ }
+});
Added: trunk/LayoutTests/http/tests/push-api/subscribe-default-permissions-expected.txt (0 => 290198)
--- trunk/LayoutTests/http/tests/push-api/subscribe-default-permissions-expected.txt (rev 0)
+++ trunk/LayoutTests/http/tests/push-api/subscribe-default-permissions-expected.txt 2022-02-19 05:26:41 UTC (rev 290198)
@@ -0,0 +1,5 @@
+PASS: service worker permissionState was prompt
+PASS: document permissionState was prompt
+PASS: service worker subscribe was error: NotAllowedError
+PASS: document subscribe was successful
+
Added: trunk/LayoutTests/http/tests/push-api/subscribe-default-permissions-iframe-cross-origin-expected.txt (0 => 290198)
--- trunk/LayoutTests/http/tests/push-api/subscribe-default-permissions-iframe-cross-origin-expected.txt (rev 0)
+++ trunk/LayoutTests/http/tests/push-api/subscribe-default-permissions-iframe-cross-origin-expected.txt 2022-02-19 05:26:41 UTC (rev 290198)
@@ -0,0 +1,6 @@
+
+PASS: service worker permissionState was prompt
+PASS: document permissionState was prompt
+PASS: service worker subscribe was error: NotAllowedError
+PASS: document subscribe was error: NotAllowedError
+
Added: trunk/LayoutTests/http/tests/push-api/subscribe-default-permissions-iframe-cross-origin.html (0 => 290198)
--- trunk/LayoutTests/http/tests/push-api/subscribe-default-permissions-iframe-cross-origin.html (rev 0)
+++ trunk/LayoutTests/http/tests/push-api/subscribe-default-permissions-iframe-cross-origin.html 2022-02-19 05:26:41 UTC (rev 290198)
@@ -0,0 +1,17 @@
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script>
+window._onmessage_ = function(event) {
+ if (event.data == 'finishPushAPITest')
+ finishPushAPITest();
+ else
+ log(event.data);
+};
+</script>
+<iframe src=""
+</iframe>
+</body>
+</html>
Added: trunk/LayoutTests/http/tests/push-api/subscribe-default-permissions-iframe-same-origin-expected.txt (0 => 290198)
--- trunk/LayoutTests/http/tests/push-api/subscribe-default-permissions-iframe-same-origin-expected.txt (rev 0)
+++ trunk/LayoutTests/http/tests/push-api/subscribe-default-permissions-iframe-same-origin-expected.txt 2022-02-19 05:26:41 UTC (rev 290198)
@@ -0,0 +1,6 @@
+
+PASS: service worker permissionState was prompt
+PASS: document permissionState was prompt
+PASS: service worker subscribe was error: NotAllowedError
+PASS: document subscribe was successful
+
Added: trunk/LayoutTests/http/tests/push-api/subscribe-default-permissions-iframe-same-origin.html (0 => 290198)
--- trunk/LayoutTests/http/tests/push-api/subscribe-default-permissions-iframe-same-origin.html (rev 0)
+++ trunk/LayoutTests/http/tests/push-api/subscribe-default-permissions-iframe-same-origin.html 2022-02-19 05:26:41 UTC (rev 290198)
@@ -0,0 +1,17 @@
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script>
+window._onmessage_ = function(event) {
+ if (event.data == 'finishPushAPITest')
+ finishPushAPITest();
+ else
+ log(event.data);
+};
+</script>
+<iframe src=""
+</iframe>
+</body>
+</html>
Added: trunk/LayoutTests/http/tests/push-api/subscribe-default-permissions.html (0 => 290198)
--- trunk/LayoutTests/http/tests/push-api/subscribe-default-permissions.html (rev 0)
+++ trunk/LayoutTests/http/tests/push-api/subscribe-default-permissions.html 2022-02-19 05:26:41 UTC (rev 290198)
@@ -0,0 +1,24 @@
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+<script>
+navigator.serviceWorker.register("resources/subscribe-worker.js", { }).then(async (registration) => {
+ try {
+ await waitForState(registration.installing, "activated");
+ await testServiceWorkerPermissionState(registration, 'prompt');
+ await testDocumentPermissionState(registration, 'prompt');
+ await testServiceWorkerSubscribe(registration, 'NotAllowedError');
+ await testDocumentSubscribe(registration);
+ } catch (e) {
+ log(`FAIL: unexpected exception ${e}`);
+ } finally {
+ await registration.unregister();
+ finishPushAPITest();
+ }
+});
+</script>
+</body>
+</html>
Added: trunk/LayoutTests/http/tests/push-api/subscribe-deny-permissions-expected.txt (0 => 290198)
--- trunk/LayoutTests/http/tests/push-api/subscribe-deny-permissions-expected.txt (rev 0)
+++ trunk/LayoutTests/http/tests/push-api/subscribe-deny-permissions-expected.txt 2022-02-19 05:26:41 UTC (rev 290198)
@@ -0,0 +1,5 @@
+PASS: service worker permissionState was denied
+PASS: document permissionState was denied
+PASS: service worker subscribe was error: NotAllowedError
+PASS: document subscribe was error: NotAllowedError
+
Added: trunk/LayoutTests/http/tests/push-api/subscribe-deny-permissions.html (0 => 290198)
--- trunk/LayoutTests/http/tests/push-api/subscribe-deny-permissions.html (rev 0)
+++ trunk/LayoutTests/http/tests/push-api/subscribe-deny-permissions.html 2022-02-19 05:26:41 UTC (rev 290198)
@@ -0,0 +1,27 @@
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+<script>
+if (window.testRunner)
+ testRunner.denyWebNotificationPermission(window.origin);
+
+navigator.serviceWorker.register("resources/subscribe-worker.js", { }).then(async (registration) => {
+ try {
+ await waitForState(registration.installing, "activated");
+ await testServiceWorkerPermissionState(registration, 'denied');
+ await testDocumentPermissionState(registration, 'denied');
+ await testServiceWorkerSubscribe(registration, 'NotAllowedError');
+ await testDocumentSubscribe(registration, 'NotAllowedError');
+ } catch (e) {
+ log(`FAIL: unexpected exception ${e}`);
+ } finally {
+ await registration.unregister();
+ finishPushAPITest();
+ }
+});
+</script>
+</body>
+</html>
Added: trunk/LayoutTests/http/tests/push-api/subscribe-grant-permissions-expected.txt (0 => 290198)
--- trunk/LayoutTests/http/tests/push-api/subscribe-grant-permissions-expected.txt (rev 0)
+++ trunk/LayoutTests/http/tests/push-api/subscribe-grant-permissions-expected.txt 2022-02-19 05:26:41 UTC (rev 290198)
@@ -0,0 +1,5 @@
+PASS: service worker permissionState was granted
+PASS: document permissionState was granted
+PASS: service worker subscribe was successful
+PASS: document subscribe was successful
+
Added: trunk/LayoutTests/http/tests/push-api/subscribe-grant-permissions.html (0 => 290198)
--- trunk/LayoutTests/http/tests/push-api/subscribe-grant-permissions.html (rev 0)
+++ trunk/LayoutTests/http/tests/push-api/subscribe-grant-permissions.html 2022-02-19 05:26:41 UTC (rev 290198)
@@ -0,0 +1,27 @@
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+<script>
+if (window.testRunner)
+ testRunner.grantWebNotificationPermission(window.origin);
+
+navigator.serviceWorker.register("resources/subscribe-worker.js", { }).then(async (registration) => {
+ try {
+ await waitForState(registration.installing, "activated");
+ await testServiceWorkerPermissionState(registration, 'granted');
+ await testDocumentPermissionState(registration, 'granted');
+ await testServiceWorkerSubscribe(registration);
+ await testDocumentSubscribe(registration);
+ } catch (e) {
+ log(`FAIL: unexpected exception ${e}`);
+ } finally {
+ await registration.unregister();
+ finishPushAPITest();
+ }
+});
+</script>
+</body>
+</html>
Modified: trunk/LayoutTests/platform/gtk/TestExpectations (290197 => 290198)
--- trunk/LayoutTests/platform/gtk/TestExpectations 2022-02-19 04:27:39 UTC (rev 290197)
+++ trunk/LayoutTests/platform/gtk/TestExpectations 2022-02-19 05:26:41 UTC (rev 290198)
@@ -1875,4 +1875,11 @@
imported/w3c/web-platform-tests/css/filter-effects/svg-empty-container-with-filter-content-added.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-with-src-rect.tentative.html [ ImageOnlyFailure ]
[ Release ] imported/w3c/web-platform-tests/html/rendering/replaced-elements/embedded-content/video-controls-vertical-writing-mode.html [ ImageOnlyFailure ]
-imported/w3c/web-platform-tests/xhr/preserve-ua-header-on-redirect.htm [ Failure ]
\ No newline at end of file
+imported/w3c/web-platform-tests/xhr/preserve-ua-header-on-redirect.htm [ Failure ]
+
+# Push subscription tests fail without platform-specific PushCrypto implementations.
+http/tests/push-api/subscribe-default-permissions-iframe-cross-origin.html [ Failure ]
+http/tests/push-api/subscribe-default-permissions-iframe-same-origin.html [ Failure ]
+http/tests/push-api/subscribe-default-permissions.html [ Failure ]
+http/tests/push-api/subscribe-deny-permissions.html [ Failure ]
+http/tests/push-api/subscribe-grant-permissions.html [ Failure ]
Modified: trunk/LayoutTests/platform/mac-wk1/TestExpectations (290197 => 290198)
--- trunk/LayoutTests/platform/mac-wk1/TestExpectations 2022-02-19 04:27:39 UTC (rev 290197)
+++ trunk/LayoutTests/platform/mac-wk1/TestExpectations 2022-02-19 05:26:41 UTC (rev 290198)
@@ -1772,4 +1772,11 @@
[ BigSur+ arm64 ] editing/execCommand/insert-newline-in-quoted-content-crash.html [ Skip ]
[ BigSur+ arm64 ] editing/execCommand/paste-as-quotation-disconnected-paragraph-ancestor-crash.html [ Skip ]
-webkit.org/b/236530 fast/text/otsvg-canvas.html [ ImageOnlyFailure ]
\ No newline at end of file
+webkit.org/b/236530 fast/text/otsvg-canvas.html [ ImageOnlyFailure ]
+
+# Push subscription tests don't work without service worker support.
+http/tests/push-api/subscribe-default-permissions-iframe-cross-origin.html [ Skip ]
+http/tests/push-api/subscribe-default-permissions-iframe-same-origin.html [ Skip ]
+http/tests/push-api/subscribe-default-permissions.html [ Skip ]
+http/tests/push-api/subscribe-deny-permissions.html [ Skip ]
+http/tests/push-api/subscribe-grant-permissions.html [ Skip ]
Modified: trunk/LayoutTests/platform/win/TestExpectations (290197 => 290198)
--- trunk/LayoutTests/platform/win/TestExpectations 2022-02-19 04:27:39 UTC (rev 290197)
+++ trunk/LayoutTests/platform/win/TestExpectations 2022-02-19 05:26:41 UTC (rev 290198)
@@ -4995,3 +4995,10 @@
http/tests/security/contentSecurityPolicy/userAgentShadowDOM/default-src-object-data-url-blocked.html [ Failure ]
http/tests/security/contentSecurityPolicy/userAgentShadowDOM/default-src-object-data-url-blocked2.html [ Failure ]
http/tests/security/contentSecurityPolicy/userAgentShadowDOM/default-src-object-data-url-blocked3.html [ Failure ]
+
+# Push subscription tests fail without platform-specific PushCrypto implementations.
+http/tests/push-api/subscribe-default-permissions-iframe-cross-origin.html [ Failure ]
+http/tests/push-api/subscribe-default-permissions-iframe-same-origin.html [ Failure ]
+http/tests/push-api/subscribe-default-permissions.html [ Failure ]
+http/tests/push-api/subscribe-deny-permissions.html [ Failure ]
+http/tests/push-api/subscribe-grant-permissions.html [ Failure ]
Modified: trunk/Source/WebCore/ChangeLog (290197 => 290198)
--- trunk/Source/WebCore/ChangeLog 2022-02-19 04:27:39 UTC (rev 290197)
+++ trunk/Source/WebCore/ChangeLog 2022-02-19 05:26:41 UTC (rev 290198)
@@ -1,3 +1,32 @@
+2022-02-18 Ben Nham <n...@apple.com>
+
+ Hook up PushManager to permission state
+ https://bugs.webkit.org/show_bug.cgi?id=236739
+
+ Reviewed by Brady Eidson.
+
+ This implements PushManager.permissionState. It returns the same value as
+ Notification.permission through the same mechanism.
+
+ This also makes PushManager.subscribe request permission from the user to show notifications
+ if the permission is in the default state and these requirements are met:
+
+ 1. The caller is a document with the same origin as a top level document. This means that
+ cross-origin iframes cannot request push permissions. This matches Chrome's behavior.
+ 2. The caller cannot be a service worker. This limitation is allowed for by the spec.
+
+ There also needs to be some code added which removes a push subscription if the user deletes
+ the subscription entirely in the UI, for instance when the UIProcess calls
+ WKNotificationManagerProviderDidRemoveNotificationPolicies. That will be handled in a
+ separate patch.
+
+ Covered by new layout tests.
+
+ * Modules/push-api/PushManager.cpp:
+ (WebCore::PushManager::subscribe):
+ (WebCore::PushManager::getSubscription):
+ (WebCore::PushManager::permissionState):
+
2022-02-18 Tim Nguyen <n...@apple.com>
Stop propagating inertness through iframes in Node::deprecatedIsInert()
Modified: trunk/Source/WebCore/Modules/push-api/PushManager.cpp (290197 => 290198)
--- trunk/Source/WebCore/Modules/push-api/PushManager.cpp 2022-02-19 04:27:39 UTC (rev 290197)
+++ trunk/Source/WebCore/Modules/push-api/PushManager.cpp 2022-02-19 05:26:41 UTC (rev 290198)
@@ -28,10 +28,12 @@
#if ENABLE(SERVICE_WORKER)
+#include "DocumentInlines.h"
#include "EventLoop.h"
#include "Exception.h"
#include "JSPushPermissionState.h"
#include "JSPushSubscription.h"
+#include "NotificationClient.h"
#include "PushCrypto.h"
#include "ScriptExecutionContext.h"
#include "ServiceWorkerRegistration.h"
@@ -65,11 +67,11 @@
m_serviceWorkerRegistration.deref();
}
-void PushManager::subscribe(ScriptExecutionContext& scriptExecutionContext, std::optional<PushSubscriptionOptionsInit>&& options, DOMPromiseDeferred<IDLInterface<PushSubscription>>&& promise)
+void PushManager::subscribe(ScriptExecutionContext& context, std::optional<PushSubscriptionOptionsInit>&& options, DOMPromiseDeferred<IDLInterface<PushSubscription>>&& promise)
{
- RELEASE_ASSERT(scriptExecutionContext.isSecureContext());
+ RELEASE_ASSERT(context.isSecureContext());
- scriptExecutionContext.eventLoop().queueTask(TaskSource::Networking, [this, protectedThis = Ref { *this }, options = WTFMove(options), promise = WTFMove(promise)]() mutable {
+ context.eventLoop().queueTask(TaskSource::Networking, [this, protectedThis = Ref { *this }, context = Ref { context }, options = WTFMove(options), promise = WTFMove(promise)]() mutable {
if (!options || !options->userVisibleOnly) {
promise.reject(Exception { NotAllowedError, "Subscribing for push requires userVisibleOnly to be true"_s });
return;
@@ -111,22 +113,68 @@
return;
}
+ auto client = context->notificationClient();
+ auto permission = client ? client->checkPermission(context.ptr()) : NotificationPermission::Denied;
+
+ if (permission == NotificationPermission::Denied) {
+ promise.reject(Exception { NotAllowedError, "User denied push permission"_s });
+ return;
+ }
+
+ if (permission == NotificationPermission::Default && !context->isDocument()) {
+ promise.reject(Exception { NotAllowedError, "User denied push permission"_s });
+ return;
+ }
+
+ if (permission == NotificationPermission::Default) {
+ RELEASE_ASSERT(client);
+ RELEASE_ASSERT(context->isDocument());
+
+ if (!downcast<Document>(context.get()).isSameOriginAsTopDocument()) {
+ promise.reject(Exception { NotAllowedError, "Cannot request permission from cross-origin iframe"_s });
+ return;
+ }
+
+ client->requestPermission(context, [this, protectedThis = WTFMove(protectedThis), keyData = keyDataResult.releaseReturnValue(), promise = WTFMove(promise)](auto permission) mutable {
+ if (permission != NotificationPermission::Granted) {
+ promise.reject(Exception { NotAllowedError, "User denied push permission"_s });
+ return;
+ }
+
+ m_serviceWorkerRegistration.subscribeToPushService(WTFMove(keyData), WTFMove(promise));
+ });
+ return;
+ }
+
+ RELEASE_ASSERT(permission == NotificationPermission::Granted);
m_serviceWorkerRegistration.subscribeToPushService(keyDataResult.releaseReturnValue(), WTFMove(promise));
});
}
-void PushManager::getSubscription(ScriptExecutionContext& scriptExecutionContext, DOMPromiseDeferred<IDLNullable<IDLInterface<PushSubscription>>>&& promise)
+void PushManager::getSubscription(ScriptExecutionContext& context, DOMPromiseDeferred<IDLNullable<IDLInterface<PushSubscription>>>&& promise)
{
- scriptExecutionContext.eventLoop().queueTask(TaskSource::Networking, [this, protectedThis = Ref { *this }, promise = WTFMove(promise)]() mutable {
+ context.eventLoop().queueTask(TaskSource::Networking, [this, protectedThis = Ref { *this }, promise = WTFMove(promise)]() mutable {
m_serviceWorkerRegistration.getPushSubscription(WTFMove(promise));
});
}
-void PushManager::permissionState(ScriptExecutionContext& scriptExecutionContext, std::optional<PushSubscriptionOptionsInit>&& options, DOMPromiseDeferred<IDLEnumeration<PushPermissionState>>&& promise)
+void PushManager::permissionState(ScriptExecutionContext& context, std::optional<PushSubscriptionOptionsInit>&&, DOMPromiseDeferred<IDLEnumeration<PushPermissionState>>&& promise)
{
- UNUSED_PARAM(options);
- scriptExecutionContext.eventLoop().queueTask(TaskSource::Networking, [this, protectedThis = Ref { *this }, promise = WTFMove(promise)]() mutable {
- m_serviceWorkerRegistration.getPushPermissionState(WTFMove(promise));
+ context.eventLoop().queueTask(TaskSource::Networking, [context = Ref { context }, promise = WTFMove(promise)]() mutable {
+ auto client = context->notificationClient();
+ auto permission = client ? client->checkPermission(context.ptr()) : NotificationPermission::Denied;
+
+ switch (permission) {
+ case NotificationPermission::Default:
+ promise.resolve(PushPermissionState::Prompt);
+ break;
+ case NotificationPermission::Granted:
+ promise.resolve(PushPermissionState::Granted);
+ break;
+ default:
+ promise.resolve(PushPermissionState::Denied);
+ break;
+ }
});
}
Modified: trunk/Source/WebKit/ChangeLog (290197 => 290198)
--- trunk/Source/WebKit/ChangeLog 2022-02-19 04:27:39 UTC (rev 290197)
+++ trunk/Source/WebKit/ChangeLog 2022-02-19 05:26:41 UTC (rev 290198)
@@ -1,3 +1,15 @@
+2022-02-18 Ben Nham <n...@apple.com>
+
+ Hook up PushManager to permission state
+ https://bugs.webkit.org/show_bug.cgi?id=236739
+
+ Reviewed by Brady Eidson.
+
+ Update comment explaining why we still have a permission state stub in webpushd.
+
+ * webpushd/WebPushDaemon.mm:
+ (WebPushD::Daemon::getPushPermissionState):
+
2022-02-18 Sihui Liu <sihui_...@apple.com>
Add assertion that no two network sessions share the same storage path
Modified: trunk/Source/WebKit/webpushd/WebPushDaemon.mm (290197 => 290198)
--- trunk/Source/WebKit/webpushd/WebPushDaemon.mm 2022-02-19 04:27:39 UTC (rev 290197)
+++ trunk/Source/WebKit/webpushd/WebPushDaemon.mm 2022-02-19 05:26:41 UTC (rev 290198)
@@ -622,12 +622,10 @@
void Daemon::getPushPermissionState(ClientConnection* connection, const URL& scopeURL, CompletionHandler<void(const Expected<uint8_t, WebCore::ExceptionData>&)>&& replySender)
{
- // FIXME
-#if HAVE(APPLE_PUSH_SERVICE_URL_TOKEN_SUPPORT)
- replySender(static_cast<uint8_t>(WebCore::PushPermissionState::Granted));
-#else
+ // FIXME: This doesn't actually get called right now, since the permission is currently checked
+ // in WebProcess. However, we've left this stub in for now because there is a chance that we
+ // will move the permission check into webpushd when supporting other platforms.
replySender(static_cast<uint8_t>(WebCore::PushPermissionState::Denied));
-#endif
}
ClientConnection* Daemon::toClientConnection(xpc_connection_t connection)
Modified: trunk/Tools/ChangeLog (290197 => 290198)
--- trunk/Tools/ChangeLog 2022-02-19 04:27:39 UTC (rev 290197)
+++ trunk/Tools/ChangeLog 2022-02-19 05:26:41 UTC (rev 290198)
@@ -1,3 +1,14 @@
+2022-02-18 Ben Nham <n...@apple.com>
+
+ Hook up PushManager to permission state
+ https://bugs.webkit.org/show_bug.cgi?id=236739
+
+ Reviewed by Brady Eidson.
+
+ Made the WebPushD API tests work now that subscribe checks for permission.
+
+ * TestWebKitAPI/Tests/WebKitCocoa/WebPushDaemon.mm:
+
2022-02-18 Sihui Liu <sihui_...@apple.com>
Add assertion that no two network session share the same storage path
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WebPushDaemon.mm (290197 => 290198)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WebPushDaemon.mm 2022-02-19 04:27:39 UTC (rev 290197)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WebPushDaemon.mm 2022-02-19 05:26:41 UTC (rev 290198)
@@ -426,6 +426,10 @@
m_notificationMessageHandler = adoptNS([[NotificationScriptMessageHandler alloc] init]);
[[m_configuration userContentController] addScriptMessageHandler:m_notificationMessageHandler.get() name:@"note"];
+
+ m_webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:m_configuration.get()]);
+ m_uiDelegate = adoptNS([[NotificationPermissionDelegate alloc] init]);
+ [m_webView setUIDelegate:m_uiDelegate.get()];
}
void loadRequest(const char* htmlSource, const char* serviceWorkerScriptSource)
@@ -440,7 +444,6 @@
{ "/sw.js", { { { "Content-Type", "application/_javascript_" } }, serviceWorkerScriptSource } }
}, TestWebKitAPI::HTTPServer::Protocol::Http));
- m_webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:m_configuration.get()]);
[m_webView loadRequest:m_server->request()];
}
@@ -456,6 +459,7 @@
RetainPtr<NotificationScriptMessageHandler> m_notificationMessageHandler;
std::unique_ptr<TestWebKitAPI::HTTPServer> m_server;
RetainPtr<WKWebView> m_webView;
+ RetainPtr<id<WKUIDelegatePrivate>> m_uiDelegate;
};
class WebPushDInjectedPushTest : public WebPushDTest {