[Payment Request] show() should only be called with user activation
authoraestes@apple.com <aestes@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 3 Nov 2017 16:35:59 +0000 (16:35 +0000)
committeraestes@apple.com <aestes@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 3 Nov 2017 16:35:59 +0000 (16:35 +0000)
https://bugs.webkit.org/show_bug.cgi?id=179056

Reviewed by Sam Weinig.

Source/WebCore:

Updated existing tests to call PaymentRequest.show() with user activation.

* Modules/paymentrequest/PaymentRequest.cpp:
(WebCore::PaymentRequest::show):

LayoutTests:

* http/tests/paymentrequest/payment-address-attributes-and-toJSON-method.https.html:
* http/tests/paymentrequest/payment-request-canmakepayment-method.https.html:
* http/tests/paymentrequest/payment-request-change-shipping-address.https.html:
* http/tests/paymentrequest/payment-request-change-shipping-option.https.html:
* http/tests/paymentrequest/payment-request-show-method.https.html:
* http/tests/paymentrequest/payment-response-complete-method.https.html:
* http/tests/paymentrequest/payment-response-methodName-attribute.https.html:
* http/tests/paymentrequest/payment-response-payerEmail-attribute.https.html:
* http/tests/paymentrequest/payment-response-payerName-attribute.https.html:
* http/tests/paymentrequest/payment-response-payerPhone-attribute.https.html:
* http/tests/paymentrequest/resources/helpers.js:
(async.getPaymentRequestResponse):
* http/tests/paymentrequest/updateWith-method-pmi-handling.https.html:
* http/tests/resources/payment-request.js: Added.
(activateThen):
* http/tests/ssl/applepay/ApplePayMerchantValidationEvent.https.html:
* http/tests/ssl/applepay/ApplePayPaymentMethodUpdateEvent.https.html:
* http/tests/ssl/applepay/PaymentRequest.https.html:
* resources/ui-helper.js:
(window.UIHelper.activateElement):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@224402 268f45cc-cd09-0410-ab3c-d52691b4dbfc

20 files changed:
LayoutTests/ChangeLog
LayoutTests/http/tests/paymentrequest/payment-address-attributes-and-toJSON-method.https.html
LayoutTests/http/tests/paymentrequest/payment-request-canmakepayment-method.https.html
LayoutTests/http/tests/paymentrequest/payment-request-change-shipping-address.https.html
LayoutTests/http/tests/paymentrequest/payment-request-change-shipping-option.https.html
LayoutTests/http/tests/paymentrequest/payment-request-show-method.https.html
LayoutTests/http/tests/paymentrequest/payment-response-complete-method.https.html
LayoutTests/http/tests/paymentrequest/payment-response-methodName-attribute.https.html
LayoutTests/http/tests/paymentrequest/payment-response-payerEmail-attribute.https.html
LayoutTests/http/tests/paymentrequest/payment-response-payerName-attribute.https.html
LayoutTests/http/tests/paymentrequest/payment-response-payerPhone-attribute.https.html
LayoutTests/http/tests/paymentrequest/resources/helpers.js
LayoutTests/http/tests/paymentrequest/updateWith-method-pmi-handling.https.html
LayoutTests/http/tests/resources/payment-request.js [new file with mode: 0644]
LayoutTests/http/tests/ssl/applepay/ApplePayMerchantValidationEvent.https.html
LayoutTests/http/tests/ssl/applepay/ApplePayPaymentMethodUpdateEvent.https.html
LayoutTests/http/tests/ssl/applepay/PaymentRequest.https.html
LayoutTests/resources/ui-helper.js
Source/WebCore/ChangeLog
Source/WebCore/Modules/paymentrequest/PaymentRequest.cpp

index b284509..b356ceb 100644 (file)
@@ -1,3 +1,31 @@
+2017-11-02  Andy Estes  <aestes@apple.com>
+
+        [Payment Request] show() should only be called with user activation
+        https://bugs.webkit.org/show_bug.cgi?id=179056
+
+        Reviewed by Sam Weinig.
+
+        * http/tests/paymentrequest/payment-address-attributes-and-toJSON-method.https.html:
+        * http/tests/paymentrequest/payment-request-canmakepayment-method.https.html:
+        * http/tests/paymentrequest/payment-request-change-shipping-address.https.html:
+        * http/tests/paymentrequest/payment-request-change-shipping-option.https.html:
+        * http/tests/paymentrequest/payment-request-show-method.https.html:
+        * http/tests/paymentrequest/payment-response-complete-method.https.html:
+        * http/tests/paymentrequest/payment-response-methodName-attribute.https.html:
+        * http/tests/paymentrequest/payment-response-payerEmail-attribute.https.html:
+        * http/tests/paymentrequest/payment-response-payerName-attribute.https.html:
+        * http/tests/paymentrequest/payment-response-payerPhone-attribute.https.html:
+        * http/tests/paymentrequest/resources/helpers.js:
+        (async.getPaymentRequestResponse):
+        * http/tests/paymentrequest/updateWith-method-pmi-handling.https.html:
+        * http/tests/resources/payment-request.js: Added.
+        (activateThen):
+        * http/tests/ssl/applepay/ApplePayMerchantValidationEvent.https.html:
+        * http/tests/ssl/applepay/ApplePayPaymentMethodUpdateEvent.https.html:
+        * http/tests/ssl/applepay/PaymentRequest.https.html:
+        * resources/ui-helper.js:
+        (window.UIHelper.activateElement):
+
 2017-11-03  Ms2ger  <Ms2ger@igalia.com>
 
         [WPE] Update Event-timestamp-high-resolution.html expectations.
index a5f080b..0646caa 100644 (file)
@@ -4,6 +4,8 @@
 <title>
   PaymentResponse.prototype.shippingAddress
 </title>
+<script src="/js-test-resources/ui-helper.js"></script>
+<script src="/resources/payment-request.js"></script>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/helpers.js"></script>
index 369ac31..74791c4 100644 (file)
@@ -5,6 +5,8 @@
 <meta charset="utf-8">
 <title>Tests for PaymentRequest.canMakePayment() method</title>
 <link rel="help" href="https://w3c.github.io/browser-payment-api/#show-method">
+<script src="/js-test-resources/ui-helper.js"></script>
+<script src="/resources/payment-request.js"></script>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script>
@@ -49,7 +51,7 @@ promise_test(async t => {
   }
 }, `If request.[[state]] is "created", then return a promise that resolves to true for known method.`);
 
-promise_test(async t => {
+user_activation_test(async t => {
   const request = new PaymentRequest(defaultMethods, defaultDetails);
   const acceptPromise = request.show(); // Sets state to "interactive"
   const canMakePaymentPromise = request.canMakePayment();
@@ -69,7 +71,7 @@ promise_test(async t => {
   await promise_rejects(t, "InvalidStateError", request.canMakePayment());
 }, `If request.[[state]] is "interactive", then return a promise rejected with an "InvalidStateError" DOMException.`);
 
-promise_test(async t => {
+user_activation_test(async t => {
   const request = new PaymentRequest(defaultMethods, defaultDetails);
   const acceptPromise = request.show(); // The state is now "interactive"
   acceptPromise.catch(() => {}); // no-op, just to silence unhandled rejection in devtools.
index 4bbce49..271206d 100644 (file)
@@ -4,8 +4,11 @@
 <title>Test for PaymentRequest shippingAddress attribute</title>
 <link rel="help" href="https://w3c.github.io/payment-request/#shippingaddress-attribute">
 <link rel="help" href="https://w3c.github.io/payment-request/#onshippingaddresschange-attribute">
+<script src="/js-test-resources/ui-helper.js"></script>
+<script src="/resources/payment-request.js"></script>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<body>
 <script>
 setup({ explicit_done: true, explicit_timeout: true });
 const applePay = Object.freeze({
@@ -51,7 +54,7 @@ function testShippingAddressChange() {
       emailAddress: '',
   };
   internals.mockPaymentCoordinator.setShippingAddress(shippingAddress);
-  promise_test(async t => {
+  user_activation_test(async t => {
     const request = new PaymentRequest(
       validMethods,
       validDetails,
index f574953..b66b4b4 100644 (file)
@@ -6,8 +6,11 @@
 <title>Test for PaymentRequest shippingOption attribute</title>
 <link rel="help" href="https://w3c.github.io/payment-request/#shippingoption-attribute">
 <link rel="help" href="https://w3c.github.io/payment-request/#onshippingoptionchange-attribute">
+<script src="/js-test-resources/ui-helper.js"></script>
+<script src="/resources/payment-request.js"></script>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<body>
 <script>
 setup({ explicit_done: true, explicit_timeout: true });
 const applePay = Object.freeze({
@@ -47,7 +50,7 @@ const requestShipping = Object.freeze({
 });
 
 function testShippingOptionChanged() {
-  promise_test(async t => {
+  user_activation_test(async t => {
     const detailsWithShippingOptions = Object.assign({}, validDetails, {
       shippingOptions: [validShippingOption1, validShippingOption2],
     });
index e3ec4ef..bbac919 100644 (file)
@@ -5,8 +5,11 @@
 <meta charset="utf-8">
 <title>Test for PaymentRequest.show() method</title>
 <link rel="help" href="https://w3c.github.io/browser-payment-api/#show-method">
+<script src="/js-test-resources/ui-helper.js"></script>
+<script src="/resources/payment-request.js"></script>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<body>
 <script>
 'use strict';
 const applePay = Object.freeze({
@@ -40,7 +43,7 @@ test(() => {
 }, "Must be possible to construct a payment request");
 
 
-promise_test(async t => {
+user_activation_test(async t => {
   const request = new PaymentRequest(defaultMethods, defaultDetails);
   const acceptPromise = request.show(); // Sets state to "interactive"
   await promise_rejects(t, "InvalidStateError", request.show());
@@ -48,7 +51,7 @@ promise_test(async t => {
   await promise_rejects(t, "AbortError", acceptPromise);
 }, `Throws if the promise [[state]] is not "created"`);
 
-promise_test(async t => {
+user_activation_test(async t => {
   const request1 = new PaymentRequest(defaultMethods, defaultDetails);
   const request2 = new PaymentRequest(defaultMethods, defaultDetails);
   const acceptPromise1 = request1.show();
@@ -58,7 +61,7 @@ promise_test(async t => {
   await promise_rejects(t, "AbortError", acceptPromise1);
 }, `If the user agent's "payment request is showing" boolean is true, then return a promise rejected with an "AbortError" DOMException.`);
 
-promise_test(async t => {
+user_activation_test(async t => {
   const request = new PaymentRequest(
     [{ supportedMethods: "this-is-not-supported" }],
     defaultDetails);
@@ -66,7 +69,7 @@ promise_test(async t => {
   await promise_rejects(t, "NotSupportedError", acceptPromise);
 }, `If payment method consultation produces no supported method of payment, then return a promise rejected with a "NotSupportedError" DOMException.`);
 
-promise_test(async t => {
+user_activation_test(async t => {
   const request = new PaymentRequest(defaultMethods, defaultDetails);
   const acceptPromise = request.show(); // Sets state to "interactive"
   internals.mockPaymentCoordinator.cancelPayment();
index 5fd6827..5e689ec 100644 (file)
@@ -4,6 +4,8 @@
 <title>
   PaymentResponse.prototype.complete() method
 </title>
+<script src="/js-test-resources/ui-helper.js"></script>
+<script src="/resources/payment-request.js"></script>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/helpers.js"></script>
index 97e89a6..13c6fdd 100644 (file)
@@ -4,6 +4,8 @@
 <title>
   PaymentResponse.prototype.methodName attribute
 </title>
+<script src="/js-test-resources/ui-helper.js"></script>
+<script src="/resources/payment-request.js"></script>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/helpers.js"></script>
index 83fb935..4da935c 100644 (file)
@@ -4,6 +4,8 @@
 <title>
   PaymentResponse.prototype.payerEmail attribute
 </title>
+<script src="/js-test-resources/ui-helper.js"></script>
+<script src="/resources/payment-request.js"></script>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/helpers.js"></script>
index a723b2d..fd1793a 100644 (file)
@@ -4,6 +4,8 @@
 <title>
   PaymentResponse.prototype.payerName attribute
 </title>
+<script src="/js-test-resources/ui-helper.js"></script>
+<script src="/resources/payment-request.js"></script>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/helpers.js"></script>
index 0a40c48..cbdcf6c 100644 (file)
@@ -4,6 +4,8 @@
 <title>
   PaymentResponse.prototype.payerPhone attribute
 </title>
+<script src="/js-test-resources/ui-helper.js"></script>
+<script src="/resources/payment-request.js"></script>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/helpers.js"></script>
index 1161e2c..571a77f 100644 (file)
@@ -98,7 +98,7 @@ async function getPaymentRequestResponse(options, id) {
       ev.complete({});
       internals.mockPaymentCoordinator.acceptPayment();
   };
-  const response = await request.show();
+  const response = await activateThen(() => request.show());
   return { request, response };
 }
 
index 727a6f2..23f3f49 100644 (file)
@@ -3,6 +3,8 @@
 <meta charset="utf-8">
 <title>Test for validity of payment method identifiers when calling updateWith() method</title>
 <link rel="help" href="https://www.w3.org/TR/payment-request/#updatewith()-method">
+<script src="/js-test-resources/ui-helper.js"></script>
+<script src="/resources/payment-request.js"></script>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script>
@@ -62,7 +64,7 @@ function runTest(button, { invalidMethod }) {
           countryCode: 'US',
       },
   });
-  promise_test(async t => {
+  user_activation_test(async t => {
     const request = new PaymentRequest(
       [applePay],
       validDetails,
diff --git a/LayoutTests/http/tests/resources/payment-request.js b/LayoutTests/http/tests/resources/payment-request.js
new file mode 100644 (file)
index 0000000..3b46faf
--- /dev/null
@@ -0,0 +1,20 @@
+function activateThen(completion)
+{
+    return new Promise(resolve => {
+        var button = document.createElement("button");
+        button.style["position"] = "absolute";
+        button.onclick = () => {
+            document.body.removeChild(button);
+            resolve(completion());
+        };
+        document.body.insertBefore(button, document.body.firstChild);
+        UIHelper.activateElement(button);
+    });
+}
+
+function user_activation_test(func, name)
+{
+    promise_test(async t => {
+        await activateThen(() => func(t));
+    }, name);
+}
index 7119ca7..8873041 100644 (file)
@@ -4,6 +4,7 @@
 <meta charset="utf-8">
 <script src="/js-test-resources/ui-helper.js"></script>
 <script src="/resources/js-test-pre.js"></script>
+<script src="/resources/payment-request.js"></script>
 </head>
 <body>
 <script>
@@ -36,10 +37,10 @@ function runTest(test) {
         var paymentRequest = new PaymentRequest([validPaymentMethod()], validPaymentDetails());
         paymentRequest.onapplepayvalidatemerchant = (event) => {
             test(event, paymentRequest);
-            paymentRequest.abort();
+            paymentRequest.abort().catch(() => {});
             resolve();
         };
-        paymentRequest.show().catch(() => {});
+        activateThen(() => paymentRequest.show().catch(() => {}));
     });
 }
 
index 7d4b0ea..6464b99 100644 (file)
@@ -4,6 +4,7 @@
 <meta charset="utf-8">
 <script src="/js-test-resources/ui-helper.js"></script>
 <script src="/resources/js-test-pre.js"></script>
+<script src="/resources/payment-request.js"></script>
 </head>
 <body>
 <script>
@@ -62,9 +63,11 @@ async function go() {
         document.querySelector("button").remove();
         finishJSTest();
     };
-    
-    paymentRequest.show();
-    internals.mockPaymentCoordinator.changePaymentMethod(expectedPaymentMethod);
+
+    activateThen(() => {
+        paymentRequest.show();
+        internals.mockPaymentCoordinator.changePaymentMethod(expectedPaymentMethod);
+    });
 }
 
 window.onload = function() {
index 05f9fb6..e91d172 100644 (file)
@@ -2,7 +2,9 @@
 <html>
 <head>
 <meta charset="utf-8">
-<script src="../../resources/js-test-pre.js"></script>
+<script src="/js-test-resources/ui-helper.js"></script>
+<script src="/resources/js-test-pre.js"></script>
+<script src="/resources/payment-request.js"></script>
 </head>
 <body>
 <script>
@@ -31,23 +33,20 @@ function validPaymentDetails() {
 }
 
 function logAndShouldThrow(setup, test) {
-    debug("SETUP: " + setup)
-    eval(setup)
-    shouldThrow(test)
-    debug("")
-}
-
-function logAndShouldNotThrow(setup, test) {
-    debug("SETUP: " + setup)
-    eval(setup)
-    shouldNotThrow(test)
-    debug("")
+    return activateThen(() => {
+        debug("SETUP: " + setup);
+        eval(setup);
+        shouldThrow(test);
+        debug("");
+    });
 }
 
 function logAndShouldReject(setup, test) {
-    debug("SETUP: " + setup)
-    eval(setup)
-    return shouldReject(test)
+    return activateThen(() => {
+        debug("SETUP: " + setup)
+        eval(setup)
+        return shouldReject(test)
+    });
 }
 
 async function go() {
@@ -145,59 +144,59 @@ async function go() {
 
     debug("Testing PaymentDetails.total")
     debug("")
-    logAndShouldThrow("paymentDetails = validPaymentDetails(); delete paymentDetails.total;", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
-    logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.total = '';", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
-    logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.total = null;", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
-    logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.total = undefined;", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
-    logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.total = 7;", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
-    logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.total = [];", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
-    logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.total = { };", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
-    logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.total = { label: 'label' };", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
-    logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.total = { label: 'label', amount: 'amount' };", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
-    logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.total = { label: 'label', amount: { currency: '', value: '0' } };", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
+    await logAndShouldThrow("paymentDetails = validPaymentDetails(); delete paymentDetails.total;", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
+    await logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.total = '';", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
+    await logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.total = null;", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
+    await logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.total = undefined;", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
+    await logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.total = 7;", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
+    await logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.total = [];", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
+    await logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.total = { };", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
+    await logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.total = { label: 'label' };", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
+    await logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.total = { label: 'label', amount: 'amount' };", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
+    await logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.total = { label: 'label', amount: { currency: '', value: '0' } };", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
     await logAndShouldReject("paymentDetails = validPaymentDetails(); paymentDetails.total = { label: 'label', amount: { currency: 'USD', value: '0' } };", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
     debug("")
-    logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.total = { label: 'label', amount: { currency: 'USD', value:'-10.00'} };", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
+    await logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.total = { label: 'label', amount: { currency: 'USD', value:'-10.00'} };", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
     await logAndShouldReject("paymentDetails = validPaymentDetails(); paymentDetails.total = { label: 'label', amount: { currency: 'USD', value: '10000000000.00' } };", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
     debug("")
 
     debug("Testing PaymentDetails.displayItems")
     debug("");
-    logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.displayItems = '';", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
-    logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.displayItems = null;", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
-    logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.displayItems = 7;", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
-    logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.displayItems = { };", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
-    logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.displayItems = [''];", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
-    logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.displayItems = [null];", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
-    logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.displayItems = [undefined];", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
-    logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.displayItems = [{}];", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
-    logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.displayItems = [{ label: 'label' }];", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
-    logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.displayItems = [{ label: 'label', amount: '' }];", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
-    logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.displayItems = [{ label: 'label', amount: '10.00', type: 'invalid' }];", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
+    await logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.displayItems = '';", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
+    await logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.displayItems = null;", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
+    await logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.displayItems = 7;", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
+    await logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.displayItems = { };", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
+    await logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.displayItems = [''];", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
+    await logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.displayItems = [null];", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
+    await logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.displayItems = [undefined];", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
+    await logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.displayItems = [{}];", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
+    await logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.displayItems = [{ label: 'label' }];", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
+    await logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.displayItems = [{ label: 'label', amount: '' }];", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
+    await logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.displayItems = [{ label: 'label', amount: '10.00', type: 'invalid' }];", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
     await logAndShouldReject("paymentDetails = validPaymentDetails(); paymentDetails.displayItems = [{ label: 'label', amount: { currency: 'EUR', value: '10.00' } }];", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
 
     debug("Testing PaymentDetails.shippingOptions")
     debug("");
-    logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.shippingOptions = '';", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
-    logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.shippingOptions = 'invalid';", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
-    logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.shippingOptions = null;", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
-    logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.shippingOptions = 7;", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
-    logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.shippingOptions = { };", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
-    logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.shippingOptions = [{ }];", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
-    logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.shippingOptions = [{ amount: '', }];", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
-    logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.shippingOptions = [{ amount: '', detail: '' }];", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
-    logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.shippingOptions = [{ amount: '', detail: '', identifier: '' }];", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
-    logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.shippingOptions = [{ amount: '', detail: '', identifier: '', label: '' }];", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
-    logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.shippingOptions = [{ amount: '-1', detail: '', identifier: '', label: '' }];", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
+    await logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.shippingOptions = '';", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
+    await logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.shippingOptions = 'invalid';", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
+    await logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.shippingOptions = null;", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
+    await logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.shippingOptions = 7;", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
+    await logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.shippingOptions = { };", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
+    await logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.shippingOptions = [{ }];", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
+    await logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.shippingOptions = [{ amount: '', }];", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
+    await logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.shippingOptions = [{ amount: '', detail: '' }];", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
+    await logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.shippingOptions = [{ amount: '', detail: '', identifier: '' }];", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
+    await logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.shippingOptions = [{ amount: '', detail: '', identifier: '', label: '' }];", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
+    await logAndShouldThrow("paymentDetails = validPaymentDetails(); paymentDetails.shippingOptions = [{ amount: '-1', detail: '', identifier: '', label: '' }];", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
     await logAndShouldReject("paymentDetails = validPaymentDetails(); paymentDetails.shippingOptions = [{ amount: { currency: 'EUR', value: '10.00' }, id: '', label: '' }];", "request = new PaymentRequest([validPaymentMethod()], paymentDetails); request.show()")
 
     debug("Testing PaymentOptions")
     debug("");
-    logAndShouldThrow("paymentOptions = {}; paymentOptions.shippingType = '';", "new PaymentRequest([validPaymentMethod()], validPaymentDetails(), paymentOptions); request.show()")
-    logAndShouldThrow("paymentOptions = {}; paymentOptions.shippingType = 'invalid';", "new PaymentRequest([validPaymentMethod()], validPaymentDetails(), paymentOptions); request.show()")
-    logAndShouldThrow("paymentOptions = {}; paymentOptions.shippingType = null;", "new PaymentRequest([validPaymentMethod()], validPaymentDetails(), paymentOptions); request.show()")
-    logAndShouldThrow("paymentOptions = {}; paymentOptions.shippingType = 7;", "new PaymentRequest([validPaymentMethod()], validPaymentDetails(), paymentOptions); request.show()")
-    logAndShouldThrow("paymentOptions = {}; paymentOptions.shippingType = { };", "new PaymentRequest([validPaymentMethod()], validPaymentDetails(), paymentOptions); request.show()")
+    await logAndShouldThrow("paymentOptions = {}; paymentOptions.shippingType = '';", "new PaymentRequest([validPaymentMethod()], validPaymentDetails(), paymentOptions); request.show()")
+    await logAndShouldThrow("paymentOptions = {}; paymentOptions.shippingType = 'invalid';", "new PaymentRequest([validPaymentMethod()], validPaymentDetails(), paymentOptions); request.show()")
+    await logAndShouldThrow("paymentOptions = {}; paymentOptions.shippingType = null;", "new PaymentRequest([validPaymentMethod()], validPaymentDetails(), paymentOptions); request.show()")
+    await logAndShouldThrow("paymentOptions = {}; paymentOptions.shippingType = 7;", "new PaymentRequest([validPaymentMethod()], validPaymentDetails(), paymentOptions); request.show()")
+    await logAndShouldThrow("paymentOptions = {}; paymentOptions.shippingType = { };", "new PaymentRequest([validPaymentMethod()], validPaymentDetails(), paymentOptions); request.show()")
 
     document.querySelector("button").remove();
 
index 39d1712..cbc43ae 100644 (file)
@@ -47,6 +47,13 @@ window.UIHelper = class UIHelper {
         });
     }
 
+    static activateElement(element)
+    {
+        const x = element.offsetLeft + element.offsetWidth / 2;
+        const y = element.offsetTop + element.offsetHeight / 2;
+        return UIHelper.activateAt(x, y);
+    }
+
     static keyDown(key)
     {
         if (!this.isWebKit2() || !this.isIOS()) {
index 3580e26..ddf860c 100644 (file)
@@ -1,3 +1,15 @@
+2017-11-02  Andy Estes  <aestes@apple.com>
+
+        [Payment Request] show() should only be called with user activation
+        https://bugs.webkit.org/show_bug.cgi?id=179056
+
+        Reviewed by Sam Weinig.
+
+        Updated existing tests to call PaymentRequest.show() with user activation.
+
+        * Modules/paymentrequest/PaymentRequest.cpp:
+        (WebCore::PaymentRequest::show):
+
 2017-11-03  Daniel Bates  <dabates@apple.com>
 
         Invalidate node list when associated form control element is removed
index 3004486..c1e43cd 100644 (file)
@@ -382,8 +382,10 @@ static ExceptionOr<JSC::JSValue> parse(ScriptExecutionContext& context, const St
 // https://www.w3.org/TR/payment-request/#show()-method
 void PaymentRequest::show(Document& document, ShowPromise&& promise)
 {
-    // FIXME: Reject promise with SecurityError if show() was not triggered by a user gesture.
-    // Find a way to do this without breaking the payment-request web platform tests.
+    if (!UserGestureIndicator::processingUserGesture()) {
+        promise.reject(Exception { SecurityError, "show() must be triggered by user activation." });
+        return;
+    }
 
     if (m_state != State::Created) {
         promise.reject(Exception { InvalidStateError });