Title: [236552] trunk
Revision
236552
Author
[email protected]
Date
2018-09-27 09:44:49 -0700 (Thu, 27 Sep 2018)

Log Message

[Apple Pay] Support granular errors in PaymentDetailsUpdate
https://bugs.webkit.org/show_bug.cgi?id=189938

Reviewed by Youenn Fablet.

Source/WebCore:

Implemented the shippingAddressErrors, payerErrors, and paymentMethodErrors properties on
PaymentDetailsUpdate, as specified in the Payment Request API W3C Editor's Draft of
26 September 2018.

When these errors are specified in a PaymentDetailsUpdate, map them to PaymentErrors. For
shippingAddressErrors and payerErrors, we use the "shippingContactInvalid" code and a
contact field that matches the shippingAddressError or payerError property specified.

For paymentMethodErrors, we interpret this as a sequence of ApplePayErrors, which are
converted to PaymentErrors as in Apple Pay JS.

Tests: http/tests/ssl/applepay/ApplePayShippingAddressChangeEventErrors.https.html
       http/tests/ssl/applepay/ApplePayShippingAddressChangeEventErrorsV3.https.html

* DerivedSources.make: Removed some tabs and added new .idl files.
* Modules/applepay/ApplePayError.idl: Moved ApplePayErrorCode and ApplePayErrorContactField
into their own .idl files so they can be used in MockPaymentError.
* Modules/applepay/ApplePayErrorCode.h: Added.
* Modules/applepay/ApplePayErrorCode.idl: Added.
* Modules/applepay/ApplePayErrorContactField.h: Added.
* Modules/applepay/ApplePayErrorContactField.idl: Added.

* Modules/applepay/paymentrequest/ApplePayPaymentHandler.cpp:
(WebCore::appendShippingContactInvalidError): Appended a "shippingContactInvalid"
PaymentError to errors if the message is non-null.
(WebCore::ApplePayPaymentHandler::computeErrors const):
(WebCore::ApplePayPaymentHandler::detailsUpdated):
(WebCore::ApplePayPaymentHandler::shippingAddressUpdated): Computed a vector of PaymentErrors
based on shippingAddressErrors, payerErrors, and paymentMethodErrors.

* Modules/applepay/paymentrequest/ApplePayPaymentHandler.h:

* Modules/paymentrequest/PaymentDetailsUpdate.h:
* Modules/paymentrequest/PaymentDetailsUpdate.idl: Defined shippingAddressErrors,
payerErrors, and paymentMethodErrors.

* Modules/paymentrequest/PaymentHandler.h:
* Modules/paymentrequest/PaymentRequest.cpp:
(WebCore::PaymentRequest::paymentMethodChanged):
(WebCore::PaymentRequest::settleDetailsPromise): Passed shippingAddressErrors, payerErrors,
and paymentMethodErrors to the payment handler.

* SourcesCocoa.txt:
* WebCore.xcodeproj/project.pbxproj:

* testing/MockPaymentCoordinator.cpp:
(WebCore::MockPaymentCoordinator::completeShippingContactSelection): Stored errors in m_errors.
* testing/MockPaymentCoordinator.h:
* testing/MockPaymentCoordinator.idl: Added an errors attribute.

* testing/MockPaymentError.h: Added.
* testing/MockPaymentError.idl: Added.

LayoutTests:

* http/tests/resources/payment-request.js:
(validPaymentDetails):
(updateDetailsOnShippingAddressChange):
* http/tests/ssl/applepay/ApplePayShippingAddressChangeEventErrors.https-expected.txt: Added.
* http/tests/ssl/applepay/ApplePayShippingAddressChangeEventErrors.https.html: Added.
* http/tests/ssl/applepay/ApplePayShippingAddressChangeEventErrorsV3.https-expected.txt: Added.
* http/tests/ssl/applepay/ApplePayShippingAddressChangeEventErrorsV3.https.html: Added.
* platform/mac-wk2/TestExpectations:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (236551 => 236552)


--- trunk/LayoutTests/ChangeLog	2018-09-27 16:34:34 UTC (rev 236551)
+++ trunk/LayoutTests/ChangeLog	2018-09-27 16:44:49 UTC (rev 236552)
@@ -1,3 +1,19 @@
+2018-09-27  Andy Estes  <[email protected]>
+
+        [Apple Pay] Support granular errors in PaymentDetailsUpdate
+        https://bugs.webkit.org/show_bug.cgi?id=189938
+
+        Reviewed by Youenn Fablet.
+
+        * http/tests/resources/payment-request.js:
+        (validPaymentDetails):
+        (updateDetailsOnShippingAddressChange):
+        * http/tests/ssl/applepay/ApplePayShippingAddressChangeEventErrors.https-expected.txt: Added.
+        * http/tests/ssl/applepay/ApplePayShippingAddressChangeEventErrors.https.html: Added.
+        * http/tests/ssl/applepay/ApplePayShippingAddressChangeEventErrorsV3.https-expected.txt: Added.
+        * http/tests/ssl/applepay/ApplePayShippingAddressChangeEventErrorsV3.https.html: Added.
+        * platform/mac-wk2/TestExpectations:
+
 2018-09-27  Chris Dumez  <[email protected]>
 
         document.open() should not propagate URLs to non-fully active documents

Modified: trunk/LayoutTests/http/tests/resources/payment-request.js (236551 => 236552)


--- trunk/LayoutTests/http/tests/resources/payment-request.js	2018-09-27 16:34:34 UTC (rev 236551)
+++ trunk/LayoutTests/http/tests/resources/payment-request.js	2018-09-27 16:44:49 UTC (rev 236552)
@@ -18,3 +18,60 @@
         await activateThen(() => func(t));
     }, name);
 }
+
+function validPaymentMethod()
+{
+    return {
+        supportedMethods: 'https://apple.com/apple-pay',
+        data: {
+            version: 2,
+            merchantIdentifier: '',
+            countryCode: 'US',
+            supportedNetworks: ['visa', 'masterCard'],
+            merchantCapabilities: ['supports3DS'],
+        },
+    }
+}
+
+function validPaymentDetails()
+{
+    return {
+        total: {
+            label: 'Total',
+            amount: {
+                currency: 'USD',
+                value: '10.00',
+            },
+        },
+        displayItems: [{
+            label: 'Item',
+            amount: {
+                currency: 'USD',
+                value: '10.00',
+            },
+        }],
+    }
+}
+
+function updateDetailsOnShippingAddressChange(paymentDetailsInit, paymentOptions, detailsUpdate)
+{
+    return new Promise((resolve, reject) => {
+        activateThen(() => {
+            var request = new PaymentRequest([validPaymentMethod()], paymentDetailsInit, paymentOptions);
+            request._onmerchantvalidation_ = (event) => {
+                event.complete({ });
+            };
+            request._onshippingaddresschange_ = (event) => {
+                var detailsUpdatePromise = new Promise((resolve, reject) => {
+                    resolve(detailsUpdate);
+                });
+                event.updateWith(detailsUpdatePromise);
+                detailsUpdatePromise.then(() => {
+                    resolve();
+                    request.abort();
+                });
+            };
+            request.show().catch(error => error);
+        });
+    });
+}

Added: trunk/LayoutTests/http/tests/ssl/applepay/ApplePayShippingAddressChangeEventErrors.https-expected.txt (0 => 236552)


--- trunk/LayoutTests/http/tests/ssl/applepay/ApplePayShippingAddressChangeEventErrors.https-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/ssl/applepay/ApplePayShippingAddressChangeEventErrors.https-expected.txt	2018-09-27 16:44:49 UTC (rev 236552)
@@ -0,0 +1,75 @@
+Test specifying errors in response to the shippingaddresschange event.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Testing PaymentDetailsUpdate with no errors.
+PASS internals.mockPaymentCoordinator.errors.length is 0
+
+Testing PaymentDetailsUpdate with an error and shipping options.
+PASS internals.mockPaymentCoordinator.errors.length is 0
+
+Testing PaymentDetailsUpdate with an empty error.
+PASS internals.mockPaymentCoordinator.errors.length is 1
+PASS internals.mockPaymentCoordinator.errors[0].code is 'shippingContactInvalid'
+PASS internals.mockPaymentCoordinator.errors[0].message is ''
+PASS internals.mockPaymentCoordinator.errors[0].contactField is undefined
+
+Testing PaymentDetailsUpdate with an error.
+PASS internals.mockPaymentCoordinator.errors.length is 1
+PASS internals.mockPaymentCoordinator.errors[0].code is 'shippingContactInvalid'
+PASS internals.mockPaymentCoordinator.errors[0].message is 'single error'
+PASS internals.mockPaymentCoordinator.errors[0].contactField is undefined
+
+Testing PaymentDetailsUpdate with an error and undefined shipping address errors.
+PASS internals.mockPaymentCoordinator.errors.length is 1
+PASS internals.mockPaymentCoordinator.errors[0].code is 'shippingContactInvalid'
+PASS internals.mockPaymentCoordinator.errors[0].message is 'single error'
+PASS internals.mockPaymentCoordinator.errors[0].contactField is undefined
+
+Testing PaymentDetailsUpdate with shipping address errors.
+PASS internals.mockPaymentCoordinator.errors.length is 8
+PASS internals.mockPaymentCoordinator.errors[0].code is 'shippingContactInvalid'
+PASS internals.mockPaymentCoordinator.errors[0].message is 'error'
+PASS internals.mockPaymentCoordinator.errors[0].contactField is 'addressLines'
+PASS internals.mockPaymentCoordinator.errors[1].code is 'shippingContactInvalid'
+PASS internals.mockPaymentCoordinator.errors[1].message is 'error'
+PASS internals.mockPaymentCoordinator.errors[1].contactField is 'locality'
+PASS internals.mockPaymentCoordinator.errors[2].code is 'shippingContactInvalid'
+PASS internals.mockPaymentCoordinator.errors[2].message is 'error'
+PASS internals.mockPaymentCoordinator.errors[2].contactField is 'country'
+PASS internals.mockPaymentCoordinator.errors[3].code is 'shippingContactInvalid'
+PASS internals.mockPaymentCoordinator.errors[3].message is 'error'
+PASS internals.mockPaymentCoordinator.errors[3].contactField is 'subLocality'
+PASS internals.mockPaymentCoordinator.errors[4].code is 'shippingContactInvalid'
+PASS internals.mockPaymentCoordinator.errors[4].message is 'error'
+PASS internals.mockPaymentCoordinator.errors[4].contactField is 'phoneNumber'
+PASS internals.mockPaymentCoordinator.errors[5].code is 'shippingContactInvalid'
+PASS internals.mockPaymentCoordinator.errors[5].message is 'error'
+PASS internals.mockPaymentCoordinator.errors[5].contactField is 'postalCode'
+PASS internals.mockPaymentCoordinator.errors[6].code is 'shippingContactInvalid'
+PASS internals.mockPaymentCoordinator.errors[6].message is 'error'
+PASS internals.mockPaymentCoordinator.errors[6].contactField is 'name'
+PASS internals.mockPaymentCoordinator.errors[7].code is 'shippingContactInvalid'
+PASS internals.mockPaymentCoordinator.errors[7].message is 'error'
+PASS internals.mockPaymentCoordinator.errors[7].contactField is 'administrativeArea'
+
+Testing PaymentDetailsUpdate with unrequested payer errors.
+PASS internals.mockPaymentCoordinator.errors.length is 0
+
+Testing PaymentDetailsUpdate with payer errors.
+PASS internals.mockPaymentCoordinator.errors.length is 3
+PASS internals.mockPaymentCoordinator.errors[0].code is 'shippingContactInvalid'
+PASS internals.mockPaymentCoordinator.errors[0].message is 'error'
+PASS internals.mockPaymentCoordinator.errors[0].contactField is 'name'
+PASS internals.mockPaymentCoordinator.errors[1].code is 'shippingContactInvalid'
+PASS internals.mockPaymentCoordinator.errors[1].message is 'error'
+PASS internals.mockPaymentCoordinator.errors[1].contactField is 'emailAddress'
+PASS internals.mockPaymentCoordinator.errors[2].code is 'shippingContactInvalid'
+PASS internals.mockPaymentCoordinator.errors[2].message is 'error'
+PASS internals.mockPaymentCoordinator.errors[2].contactField is 'phoneNumber'
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/http/tests/ssl/applepay/ApplePayShippingAddressChangeEventErrors.https.html (0 => 236552)


--- trunk/LayoutTests/http/tests/ssl/applepay/ApplePayShippingAddressChangeEventErrors.https.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/ssl/applepay/ApplePayShippingAddressChangeEventErrors.https.html	2018-09-27 16:44:49 UTC (rev 236552)
@@ -0,0 +1,149 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<script src=""
+<script src=""
+<script src=""
+</head>
+<body>
+<script>
+
+description("Test specifying errors in response to the shippingaddresschange event.");
+
+window.jsTestIsAsync = true;
+
+async function runTests()
+{
+    debug("Testing PaymentDetailsUpdate with no errors.");
+    var details = validPaymentDetails();
+    await updateDetailsOnShippingAddressChange(details, { requestShipping: true }, details);
+    shouldBe("internals.mockPaymentCoordinator.errors.length", "0");
+    debug("");
+
+    debug("Testing PaymentDetailsUpdate with an error and shipping options.");
+    var detailsUpdate = validPaymentDetails();
+    detailsUpdate.error = "single error";
+    detailsUpdate.shippingOptions = [{
+        id: "option1",
+        label: "option 1",
+        amount: {
+            currency: "USD",
+            value: "1.00",
+        },
+    }];
+    await updateDetailsOnShippingAddressChange(validPaymentDetails(), { requestShipping: true }, detailsUpdate);
+    shouldBe("internals.mockPaymentCoordinator.errors.length", "0");
+    debug("");
+
+    debug("Testing PaymentDetailsUpdate with an empty error.");
+    var detailsUpdate = validPaymentDetails();
+    detailsUpdate.error = "";
+    await updateDetailsOnShippingAddressChange(validPaymentDetails(), { requestShipping: true }, detailsUpdate);
+    shouldBe("internals.mockPaymentCoordinator.errors.length", "1");
+    shouldBe("internals.mockPaymentCoordinator.errors[0].code", "'shippingContactInvalid'");
+    shouldBe("internals.mockPaymentCoordinator.errors[0].message", "''");
+    shouldBe("internals.mockPaymentCoordinator.errors[0].contactField", "undefined");
+    debug("");
+
+    debug("Testing PaymentDetailsUpdate with an error.");
+    var detailsUpdate = validPaymentDetails();
+    detailsUpdate.error = "single error";
+    await updateDetailsOnShippingAddressChange(validPaymentDetails(), { requestShipping: true }, detailsUpdate);
+    shouldBe("internals.mockPaymentCoordinator.errors.length", "1");
+    shouldBe("internals.mockPaymentCoordinator.errors[0].code", "'shippingContactInvalid'");
+    shouldBe("internals.mockPaymentCoordinator.errors[0].message", "'single error'");
+    shouldBe("internals.mockPaymentCoordinator.errors[0].contactField", "undefined");
+    debug("");
+
+    debug("Testing PaymentDetailsUpdate with an error and undefined shipping address errors.");
+    var detailsUpdate = validPaymentDetails();
+    detailsUpdate.error = "single error";
+    detailsUpdate.shippingAddressErrors = {
+    };
+    await updateDetailsOnShippingAddressChange(validPaymentDetails(), { requestShipping: true }, detailsUpdate);
+    shouldBe("internals.mockPaymentCoordinator.errors.length", "1");
+    shouldBe("internals.mockPaymentCoordinator.errors[0].code", "'shippingContactInvalid'");
+    shouldBe("internals.mockPaymentCoordinator.errors[0].message", "'single error'");
+    shouldBe("internals.mockPaymentCoordinator.errors[0].contactField", "undefined");
+    debug("");
+
+    debug("Testing PaymentDetailsUpdate with shipping address errors.");
+    var detailsUpdate = validPaymentDetails();
+    detailsUpdate.shippingAddressErrors = {
+        addressLine: "error",
+        city: "error",
+        country: "error",
+        dependentLocality: "error",
+        phone: "error",
+        postalCode: "error",
+        recipient: "error",
+        region: "error",
+    };
+    await updateDetailsOnShippingAddressChange(validPaymentDetails(), { requestShipping: true }, detailsUpdate);
+    shouldBe("internals.mockPaymentCoordinator.errors.length", "8");
+    shouldBe("internals.mockPaymentCoordinator.errors[0].code", "'shippingContactInvalid'");
+    shouldBe("internals.mockPaymentCoordinator.errors[0].message", "'error'");
+    shouldBe("internals.mockPaymentCoordinator.errors[0].contactField", "'addressLines'");
+    shouldBe("internals.mockPaymentCoordinator.errors[1].code", "'shippingContactInvalid'");
+    shouldBe("internals.mockPaymentCoordinator.errors[1].message", "'error'");
+    shouldBe("internals.mockPaymentCoordinator.errors[1].contactField", "'locality'");
+    shouldBe("internals.mockPaymentCoordinator.errors[2].code", "'shippingContactInvalid'");
+    shouldBe("internals.mockPaymentCoordinator.errors[2].message", "'error'");
+    shouldBe("internals.mockPaymentCoordinator.errors[2].contactField", "'country'");
+    shouldBe("internals.mockPaymentCoordinator.errors[3].code", "'shippingContactInvalid'");
+    shouldBe("internals.mockPaymentCoordinator.errors[3].message", "'error'");
+    shouldBe("internals.mockPaymentCoordinator.errors[3].contactField", "'subLocality'");
+    shouldBe("internals.mockPaymentCoordinator.errors[4].code", "'shippingContactInvalid'");
+    shouldBe("internals.mockPaymentCoordinator.errors[4].message", "'error'");
+    shouldBe("internals.mockPaymentCoordinator.errors[4].contactField", "'phoneNumber'");
+    shouldBe("internals.mockPaymentCoordinator.errors[5].code", "'shippingContactInvalid'");
+    shouldBe("internals.mockPaymentCoordinator.errors[5].message", "'error'");
+    shouldBe("internals.mockPaymentCoordinator.errors[5].contactField", "'postalCode'");
+    shouldBe("internals.mockPaymentCoordinator.errors[6].code", "'shippingContactInvalid'");
+    shouldBe("internals.mockPaymentCoordinator.errors[6].message", "'error'");
+    shouldBe("internals.mockPaymentCoordinator.errors[6].contactField", "'name'");
+    shouldBe("internals.mockPaymentCoordinator.errors[7].code", "'shippingContactInvalid'");
+    shouldBe("internals.mockPaymentCoordinator.errors[7].message", "'error'");
+    shouldBe("internals.mockPaymentCoordinator.errors[7].contactField", "'administrativeArea'");
+    debug("");
+
+    debug("Testing PaymentDetailsUpdate with unrequested payer errors.");
+    var detailsUpdate = validPaymentDetails();
+    detailsUpdate.payerErrors = {
+        name: "error",
+        email: "error",
+        phone: "error",
+    };
+    await updateDetailsOnShippingAddressChange(validPaymentDetails(), { }, detailsUpdate);
+    shouldBe("internals.mockPaymentCoordinator.errors.length", "0");
+    debug("");
+
+    debug("Testing PaymentDetailsUpdate with payer errors.");
+    var detailsUpdate = validPaymentDetails();
+    detailsUpdate.payerErrors = {
+        name: "error",
+        email: "error",
+        phone: "error",
+    };
+    await updateDetailsOnShippingAddressChange(validPaymentDetails(), { requestPayerName: true, requestPayerPhone: true, requestPayerEmail: true }, detailsUpdate);
+    shouldBe("internals.mockPaymentCoordinator.errors.length", "3");
+    shouldBe("internals.mockPaymentCoordinator.errors[0].code", "'shippingContactInvalid'");
+    shouldBe("internals.mockPaymentCoordinator.errors[0].message", "'error'");
+    shouldBe("internals.mockPaymentCoordinator.errors[0].contactField", "'name'");
+    shouldBe("internals.mockPaymentCoordinator.errors[1].code", "'shippingContactInvalid'");
+    shouldBe("internals.mockPaymentCoordinator.errors[1].message", "'error'");
+    shouldBe("internals.mockPaymentCoordinator.errors[1].contactField", "'emailAddress'");
+    shouldBe("internals.mockPaymentCoordinator.errors[2].code", "'shippingContactInvalid'");
+    shouldBe("internals.mockPaymentCoordinator.errors[2].message", "'error'");
+    shouldBe("internals.mockPaymentCoordinator.errors[2].contactField", "'phoneNumber'");
+    debug("");
+
+    finishJSTest();
+}
+
+runTests();
+</script>
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/http/tests/ssl/applepay/ApplePayShippingAddressChangeEventErrorsV3.https-expected.txt (0 => 236552)


--- trunk/LayoutTests/http/tests/ssl/applepay/ApplePayShippingAddressChangeEventErrorsV3.https-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/ssl/applepay/ApplePayShippingAddressChangeEventErrorsV3.https-expected.txt	2018-09-27 16:44:49 UTC (rev 236552)
@@ -0,0 +1,24 @@
+Test specifying Apple Pay errors in response to the shippingaddresschange event.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Testing PaymentDetailsUpdate with null payment method errors.
+PASS internals.mockPaymentCoordinator.errors.length is 0
+
+Testing PaymentDetailsUpdate with invalid payment method errors.
+PASS internals.mockPaymentCoordinator.errors.length is 0
+
+Testing PaymentDetailsUpdate with Apple Pay payment method errors.
+PASS internals.mockPaymentCoordinator.errors.length is 2
+PASS internals.mockPaymentCoordinator.errors[0].code is 'addressUnserviceable'
+PASS internals.mockPaymentCoordinator.errors[0].message is ''
+PASS internals.mockPaymentCoordinator.errors[0].contactField is undefined
+PASS internals.mockPaymentCoordinator.errors[1].code is 'shippingContactInvalid'
+PASS internals.mockPaymentCoordinator.errors[1].message is 'Apple Pay error'
+PASS internals.mockPaymentCoordinator.errors[1].contactField is 'phoneticName'
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/http/tests/ssl/applepay/ApplePayShippingAddressChangeEventErrorsV3.https.html (0 => 236552)


--- trunk/LayoutTests/http/tests/ssl/applepay/ApplePayShippingAddressChangeEventErrorsV3.https.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/ssl/applepay/ApplePayShippingAddressChangeEventErrorsV3.https.html	2018-09-27 16:44:49 UTC (rev 236552)
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<script src=""
+<script src=""
+<script src=""
+</head>
+<body>
+<script>
+
+description("Test specifying Apple Pay errors in response to the shippingaddresschange event.");
+
+window.jsTestIsAsync = true;
+
+async function runTests()
+{
+    debug("Testing PaymentDetailsUpdate with null payment method errors.");
+    var detailsUpdate = validPaymentDetails();
+    detailsUpdate.paymentMethodErrors = null;
+    await updateDetailsOnShippingAddressChange(validPaymentDetails(), { }, detailsUpdate);
+    shouldBe("internals.mockPaymentCoordinator.errors.length", "0");
+    debug("");
+
+    debug("Testing PaymentDetailsUpdate with invalid payment method errors.");
+    var detailsUpdate = validPaymentDetails();
+    detailsUpdate.paymentMethodErrors = [
+        { },
+        null,
+        new Promise(() => { }),
+    ];
+    await updateDetailsOnShippingAddressChange(validPaymentDetails(), { }, detailsUpdate);
+    shouldBe("internals.mockPaymentCoordinator.errors.length", "0");
+    debug("");
+
+    debug("Testing PaymentDetailsUpdate with Apple Pay payment method errors.");
+    var detailsUpdate = validPaymentDetails();
+    detailsUpdate.paymentMethodErrors = [
+        new ApplePayError("addressUnserviceable"),
+        new ApplePayError("shippingContactInvalid", "phoneticName", "Apple Pay error"),
+    ];
+    await updateDetailsOnShippingAddressChange(validPaymentDetails(), { }, detailsUpdate);
+    shouldBe("internals.mockPaymentCoordinator.errors.length", "2");
+    shouldBe("internals.mockPaymentCoordinator.errors[0].code", "'addressUnserviceable'");
+    shouldBe("internals.mockPaymentCoordinator.errors[0].message", "''");
+    shouldBe("internals.mockPaymentCoordinator.errors[0].contactField", "undefined");
+    shouldBe("internals.mockPaymentCoordinator.errors[1].code", "'shippingContactInvalid'");
+    shouldBe("internals.mockPaymentCoordinator.errors[1].message", "'Apple Pay error'");
+    shouldBe("internals.mockPaymentCoordinator.errors[1].contactField", "'phoneticName'");
+    debug("");
+
+    finishJSTest();
+}
+
+runTests();
+</script>
+<script src=""
+</body>
+</html>

Modified: trunk/LayoutTests/platform/mac-wk2/TestExpectations (236551 => 236552)


--- trunk/LayoutTests/platform/mac-wk2/TestExpectations	2018-09-27 16:34:34 UTC (rev 236551)
+++ trunk/LayoutTests/platform/mac-wk2/TestExpectations	2018-09-27 16:44:49 UTC (rev 236552)
@@ -26,6 +26,7 @@
 [ Sierra ] http/tests/ssl/applepay/ApplePaySessionV3.html [ Skip ]
 [ Sierra ] http/tests/ssl/applepay/ApplePaySessionV4.html [ Skip ]
 [ Sierra ] http/tests/ssl/applepay/ApplePayRequestShippingContactV3.https.html [ Skip ]
+[ Sierra ] http/tests/ssl/applepay/ApplePayShippingAddressChangeEventErrorsV3.https.html [ Skip ]
 [ HighSierra ] http/tests/ssl/applepay/ApplePayButtonV4.html [ Skip ]
 [ HighSierra ] http/tests/ssl/applepay/ApplePaySessionV4.html [ Skip ]
 
@@ -757,6 +758,7 @@
 [ HighSierra+ ] http/tests/ssl/applepay/ApplePaySessionV3.html [ Pass ]
 [ Mojave+ ] http/tests/ssl/applepay/ApplePaySessionV4.html [ Pass ]
 [ HighSierra+ ] http/tests/ssl/applepay/ApplePayRequestShippingContactV3.https.html [ Pass ]
+[ HighSierra+ ] http/tests/ssl/applepay/ApplePayShippingAddressChangeEventErrorsV3.https.html [ Pass ]
 # <rdar://problem/31634451>
 [ HighSierra+ ] http/tests/resourceLoadStatistics/cookies-with-and-without-user-interaction.html [ Pass ]
 [ HighSierra+ ] http/tests/resourceLoadStatistics/cookie-deletion.html [ Pass ]

Modified: trunk/Source/WebCore/ChangeLog (236551 => 236552)


--- trunk/Source/WebCore/ChangeLog	2018-09-27 16:34:34 UTC (rev 236551)
+++ trunk/Source/WebCore/ChangeLog	2018-09-27 16:44:49 UTC (rev 236552)
@@ -1,3 +1,63 @@
+2018-09-27  Andy Estes  <[email protected]>
+
+        [Apple Pay] Support granular errors in PaymentDetailsUpdate
+        https://bugs.webkit.org/show_bug.cgi?id=189938
+
+        Reviewed by Youenn Fablet.
+
+        Implemented the shippingAddressErrors, payerErrors, and paymentMethodErrors properties on
+        PaymentDetailsUpdate, as specified in the Payment Request API W3C Editor's Draft of
+        26 September 2018.
+
+        When these errors are specified in a PaymentDetailsUpdate, map them to PaymentErrors. For
+        shippingAddressErrors and payerErrors, we use the "shippingContactInvalid" code and a
+        contact field that matches the shippingAddressError or payerError property specified.
+
+        For paymentMethodErrors, we interpret this as a sequence of ApplePayErrors, which are
+        converted to PaymentErrors as in Apple Pay JS.
+
+        Tests: http/tests/ssl/applepay/ApplePayShippingAddressChangeEventErrors.https.html
+               http/tests/ssl/applepay/ApplePayShippingAddressChangeEventErrorsV3.https.html
+
+        * DerivedSources.make: Removed some tabs and added new .idl files.
+        * Modules/applepay/ApplePayError.idl: Moved ApplePayErrorCode and ApplePayErrorContactField
+        into their own .idl files so they can be used in MockPaymentError.
+        * Modules/applepay/ApplePayErrorCode.h: Added.
+        * Modules/applepay/ApplePayErrorCode.idl: Added.
+        * Modules/applepay/ApplePayErrorContactField.h: Added.
+        * Modules/applepay/ApplePayErrorContactField.idl: Added.
+
+        * Modules/applepay/paymentrequest/ApplePayPaymentHandler.cpp:
+        (WebCore::appendShippingContactInvalidError): Appended a "shippingContactInvalid"
+        PaymentError to errors if the message is non-null.
+        (WebCore::ApplePayPaymentHandler::computeErrors const):
+        (WebCore::ApplePayPaymentHandler::detailsUpdated):
+        (WebCore::ApplePayPaymentHandler::shippingAddressUpdated): Computed a vector of PaymentErrors
+        based on shippingAddressErrors, payerErrors, and paymentMethodErrors.
+
+        * Modules/applepay/paymentrequest/ApplePayPaymentHandler.h:
+
+        * Modules/paymentrequest/PaymentDetailsUpdate.h:
+        * Modules/paymentrequest/PaymentDetailsUpdate.idl: Defined shippingAddressErrors,
+        payerErrors, and paymentMethodErrors.
+
+        * Modules/paymentrequest/PaymentHandler.h:
+        * Modules/paymentrequest/PaymentRequest.cpp:
+        (WebCore::PaymentRequest::paymentMethodChanged):
+        (WebCore::PaymentRequest::settleDetailsPromise): Passed shippingAddressErrors, payerErrors,
+        and paymentMethodErrors to the payment handler.
+
+        * SourcesCocoa.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+
+        * testing/MockPaymentCoordinator.cpp:
+        (WebCore::MockPaymentCoordinator::completeShippingContactSelection): Stored errors in m_errors.
+        * testing/MockPaymentCoordinator.h:
+        * testing/MockPaymentCoordinator.idl: Added an errors attribute.
+
+        * testing/MockPaymentError.h: Added.
+        * testing/MockPaymentError.idl: Added.
+
 2018-09-27  Alex Christensen  <[email protected]>
 
         URLWithUserTypedString should return nil for URLs deemed to be invalid by WebCore::URL

Modified: trunk/Source/WebCore/DerivedSources.make (236551 => 236552)


--- trunk/Source/WebCore/DerivedSources.make	2018-09-27 16:34:34 UTC (rev 236551)
+++ trunk/Source/WebCore/DerivedSources.make	2018-09-27 16:44:49 UTC (rev 236552)
@@ -1,4 +1,4 @@
-# Copyright (C) 2006-2017 Apple Inc. All rights reserved.
+# Copyright (C) 2006-2018 Apple Inc. All rights reserved.
 # Copyright (C) 2006 Samuel Weinig <[email protected]>
 # Copyright (C) 2009 Cameron McCormack <[email protected]>
 #
@@ -90,26 +90,28 @@
 JS_BINDING_IDLS = \
     $(WebCore)/Modules/airplay/WebKitPlaybackTargetAvailabilityEvent.idl \
     $(WebCore)/Modules/applepay/ApplePayContactField.idl \
-	$(WebCore)/Modules/applepay/ApplePayError.idl \
+    $(WebCore)/Modules/applepay/ApplePayError.idl \
+    $(WebCore)/Modules/applepay/ApplePayErrorCode.idl \
+    $(WebCore)/Modules/applepay/ApplePayErrorContactField.idl \
     $(WebCore)/Modules/applepay/ApplePayLineItem.idl \
     $(WebCore)/Modules/applepay/ApplePayMerchantCapability.idl \
     $(WebCore)/Modules/applepay/ApplePayPayment.idl \
     $(WebCore)/Modules/applepay/ApplePayPaymentAuthorizedEvent.idl \
-	$(WebCore)/Modules/applepay/ApplePayPaymentAuthorizationResult.idl \
+    $(WebCore)/Modules/applepay/ApplePayPaymentAuthorizationResult.idl \
     $(WebCore)/Modules/applepay/ApplePayPaymentContact.idl \
     $(WebCore)/Modules/applepay/ApplePayPaymentMethod.idl \
     $(WebCore)/Modules/applepay/ApplePayPaymentMethodSelectedEvent.idl \
     $(WebCore)/Modules/applepay/ApplePayPaymentMethodType.idl \
-	$(WebCore)/Modules/applepay/ApplePayPaymentMethodUpdate.idl \
+    $(WebCore)/Modules/applepay/ApplePayPaymentMethodUpdate.idl \
     $(WebCore)/Modules/applepay/ApplePayPaymentPass.idl \
     $(WebCore)/Modules/applepay/ApplePayPaymentRequest.idl \
     $(WebCore)/Modules/applepay/ApplePayRequestBase.idl \
     $(WebCore)/Modules/applepay/ApplePaySession.idl \
     $(WebCore)/Modules/applepay/ApplePayShippingContactSelectedEvent.idl \
-	$(WebCore)/Modules/applepay/ApplePayShippingContactUpdate.idl \
+    $(WebCore)/Modules/applepay/ApplePayShippingContactUpdate.idl \
     $(WebCore)/Modules/applepay/ApplePayShippingMethod.idl \
     $(WebCore)/Modules/applepay/ApplePayShippingMethodSelectedEvent.idl \
-	$(WebCore)/Modules/applepay/ApplePayShippingMethodUpdate.idl \
+    $(WebCore)/Modules/applepay/ApplePayShippingMethodUpdate.idl \
     $(WebCore)/Modules/applepay/ApplePayValidateMerchantEvent.idl \
     $(WebCore)/Modules/applepay/paymentrequest/ApplePayModifier.idl \
     $(WebCore)/Modules/applepay/paymentrequest/ApplePayRequest.idl \
@@ -982,6 +984,7 @@
     $(WebCore)/testing/MockPageOverlay.idl \
     $(WebCore)/testing/MockPaymentAddress.idl \
     $(WebCore)/testing/MockPaymentCoordinator.idl \
+    $(WebCore)/testing/MockPaymentError.idl \
     $(WebCore)/testing/ServiceWorkerInternals.idl \
     $(WebCore)/testing/TypeConversions.idl \
     $(WebCore)/workers/AbstractWorker.idl \

Modified: trunk/Source/WebCore/Modules/applepay/ApplePayError.idl (236551 => 236552)


--- trunk/Source/WebCore/Modules/applepay/ApplePayError.idl	2018-09-27 16:34:34 UTC (rev 236551)
+++ trunk/Source/WebCore/Modules/applepay/ApplePayError.idl	2018-09-27 16:44:49 UTC (rev 236552)
@@ -24,33 +24,6 @@
  */
 
 [
-    Conditional=APPLE_PAY_SESSION_V3,
-] enum ApplePayErrorCode {
-    "unknown",
-    "shippingContactInvalid",
-    "billingContactInvalid",
-    "addressUnserviceable"
-};
-
-[
-    Conditional=APPLE_PAY_SESSION_V3,
-] enum ApplePayErrorContactField {
-    "phoneNumber",
-    "emailAddress",
-    "name",
-    "phoneticName",
-    "postalAddress",
-    "addressLines",
-    "subLocality",
-    "locality",
-    "postalCode",
-    "subAdministrativeArea",
-    "administrativeArea",
-    "country",
-    "countryCode"
-};
-
-[
     Constructor(ApplePayErrorCode errorCode, optional ApplePayErrorContactField contactField, optional DOMString message = ""),
     Conditional=APPLE_PAY_SESSION_V3,
 ] interface ApplePayError {

Copied: trunk/Source/WebCore/Modules/applepay/ApplePayErrorCode.h (from rev 236551, trunk/Source/WebCore/Modules/paymentrequest/PaymentDetailsUpdate.idl) (0 => 236552)


--- trunk/Source/WebCore/Modules/applepay/ApplePayErrorCode.h	                        (rev 0)
+++ trunk/Source/WebCore/Modules/applepay/ApplePayErrorCode.h	2018-09-27 16:44:49 UTC (rev 236552)
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(APPLE_PAY)
+
+#include "ApplePaySessionPaymentRequest.h"
+
+namespace WebCore {
+
+using ApplePayErrorCode = PaymentError::Code;
+
+} // namespace WebCore
+
+#endif // ENABLE(APPLE_PAY)

Copied: trunk/Source/WebCore/Modules/applepay/ApplePayErrorCode.idl (from rev 236551, trunk/Source/WebCore/Modules/paymentrequest/PaymentDetailsUpdate.idl) (0 => 236552)


--- trunk/Source/WebCore/Modules/applepay/ApplePayErrorCode.idl	                        (rev 0)
+++ trunk/Source/WebCore/Modules/applepay/ApplePayErrorCode.idl	2018-09-27 16:44:49 UTC (rev 236552)
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+[
+    Conditional=APPLE_PAY,
+    ExportMacro=WEBCORE_EXPORT,
+] enum ApplePayErrorCode {
+    "unknown",
+    "shippingContactInvalid",
+    "billingContactInvalid",
+    "addressUnserviceable"
+};

Copied: trunk/Source/WebCore/Modules/applepay/ApplePayErrorContactField.h (from rev 236551, trunk/Source/WebCore/Modules/paymentrequest/PaymentDetailsUpdate.idl) (0 => 236552)


--- trunk/Source/WebCore/Modules/applepay/ApplePayErrorContactField.h	                        (rev 0)
+++ trunk/Source/WebCore/Modules/applepay/ApplePayErrorContactField.h	2018-09-27 16:44:49 UTC (rev 236552)
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(APPLE_PAY)
+
+#include "ApplePaySessionPaymentRequest.h"
+
+namespace WebCore {
+
+using ApplePayErrorContactField = PaymentError::ContactField;
+
+} // namespace WebCore
+
+#endif // ENABLE(APPLE_PAY)

Copied: trunk/Source/WebCore/Modules/applepay/ApplePayErrorContactField.idl (from rev 236551, trunk/Source/WebCore/Modules/paymentrequest/PaymentDetailsUpdate.idl) (0 => 236552)


--- trunk/Source/WebCore/Modules/applepay/ApplePayErrorContactField.idl	                        (rev 0)
+++ trunk/Source/WebCore/Modules/applepay/ApplePayErrorContactField.idl	2018-09-27 16:44:49 UTC (rev 236552)
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+[
+    Conditional=APPLE_PAY,
+    ExportMacro=WEBCORE_EXPORT,
+] enum ApplePayErrorContactField {
+    "phoneNumber",
+    "emailAddress",
+    "name",
+    "phoneticName",
+    "postalAddress",
+    "addressLines",
+    "subLocality",
+    "locality",
+    "postalCode",
+    "subAdministrativeArea",
+    "administrativeArea",
+    "country",
+    "countryCode"
+};

Modified: trunk/Source/WebCore/Modules/applepay/paymentrequest/ApplePayPaymentHandler.cpp (236551 => 236552)


--- trunk/Source/WebCore/Modules/applepay/paymentrequest/ApplePayPaymentHandler.cpp	2018-09-27 16:34:34 UTC (rev 236551)
+++ trunk/Source/WebCore/Modules/applepay/paymentrequest/ApplePayPaymentHandler.cpp	2018-09-27 16:44:49 UTC (rev 236552)
@@ -28,6 +28,7 @@
 
 #if ENABLE(APPLE_PAY) && ENABLE(PAYMENT_REQUEST)
 
+#include "AddressErrors.h"
 #include "ApplePayContactField.h"
 #include "ApplePayMerchantCapability.h"
 #include "ApplePayModifier.h"
@@ -36,6 +37,7 @@
 #include "Document.h"
 #include "EventNames.h"
 #include "Frame.h"
+#include "JSApplePayError.h"
 #include "JSApplePayPayment.h"
 #include "JSApplePayPaymentMethod.h"
 #include "JSApplePayRequest.h"
@@ -42,6 +44,7 @@
 #include "LinkIconCollector.h"
 #include "MerchantValidationEvent.h"
 #include "Page.h"
+#include "PayerErrorFields.h"
 #include "Payment.h"
 #include "PaymentAuthorizationStatus.h"
 #include "PaymentContact.h"
@@ -309,14 +312,67 @@
     return ApplePaySessionPaymentRequest::TotalAndLineItems { WTFMove(total), WTFMove(lineItems) };
 }
 
-ExceptionOr<void> ApplePayPaymentHandler::detailsUpdated(PaymentRequest::UpdateReason reason, const String& error)
+static inline void appendShippingContactInvalidError(String&& message, std::optional<PaymentError::ContactField> contactField, Vector<PaymentError>& errors)
 {
+    if (!message.isNull())
+        errors.append({ PaymentError::Code::ShippingContactInvalid, WTFMove(message), WTFMove(contactField) });
+}
+
+Vector<PaymentError> ApplePayPaymentHandler::computeErrors(String&& error, AddressErrors&& addressErrors, PayerErrorFields&& payerErrors, JSC::JSObject* paymentMethodErrors) const
+{
+    Vector<PaymentError> errors;
+
+    auto& options = m_paymentRequest->paymentOptions();
+    using ContactField = PaymentError::ContactField;
+
+    if (options.requestShipping && m_paymentRequest->paymentDetails().shippingOptions.isEmpty()) {
+        appendShippingContactInvalidError(WTFMove(error), std::nullopt, errors);
+        appendShippingContactInvalidError(WTFMove(addressErrors.addressLine), ContactField::AddressLines, errors);
+        appendShippingContactInvalidError(WTFMove(addressErrors.city), ContactField::Locality, errors);
+        appendShippingContactInvalidError(WTFMove(addressErrors.country), ContactField::Country, errors);
+        appendShippingContactInvalidError(WTFMove(addressErrors.dependentLocality), ContactField::SubLocality, errors);
+        appendShippingContactInvalidError(WTFMove(addressErrors.phone), ContactField::PhoneNumber, errors);
+        appendShippingContactInvalidError(WTFMove(addressErrors.postalCode), ContactField::PostalCode, errors);
+        appendShippingContactInvalidError(WTFMove(addressErrors.recipient), ContactField::Name, errors);
+        appendShippingContactInvalidError(WTFMove(addressErrors.region), ContactField::AdministrativeArea, errors);
+    }
+
+    if (options.requestPayerName)
+        appendShippingContactInvalidError(WTFMove(payerErrors.name), ContactField::Name, errors);
+
+    if (options.requestPayerEmail)
+        appendShippingContactInvalidError(WTFMove(payerErrors.email), ContactField::EmailAddress, errors);
+
+    if (options.requestPayerPhone)
+        appendShippingContactInvalidError(WTFMove(payerErrors.phone), ContactField::PhoneNumber, errors);
+
+#if ENABLE(APPLE_PAY_SESSION_V3)
+    if (paymentMethodErrors) {
+        auto& context = *scriptExecutionContext();
+        auto throwScope = DECLARE_THROW_SCOPE(context.vm());
+        auto applePayErrors = convert<IDLSequence<IDLInterface<ApplePayError>>>(*context.execState(), paymentMethodErrors);
+        if (!throwScope.exception()) {
+            for (auto& applePayError : applePayErrors) {
+                if (applePayError)
+                    errors.append({ applePayError->code(), applePayError->message(), applePayError->contactField() });
+            }
+        }
+    }
+#else
+    UNUSED_PARAM(paymentMethodErrors);
+#endif
+
+    return errors;
+}
+
+ExceptionOr<void> ApplePayPaymentHandler::detailsUpdated(PaymentRequest::UpdateReason reason, String&& error, AddressErrors&& addressErrors, PayerErrorFields&& payerErrors, JSC::JSObject* paymentMethodErrors)
+{
     using Reason = PaymentRequest::UpdateReason;
     switch (reason) {
     case Reason::ShowDetailsResolved:
         return { };
     case Reason::ShippingAddressChanged:
-        return shippingAddressUpdated(error);
+        return shippingAddressUpdated(computeErrors(WTFMove(error), WTFMove(addressErrors), WTFMove(payerErrors), paymentMethodErrors));
     case Reason::ShippingOptionChanged:
         return shippingOptionUpdated();
     case Reason::PaymentMethodChanged:
@@ -344,20 +400,14 @@
     return { };
 }
 
-ExceptionOr<void> ApplePayPaymentHandler::shippingAddressUpdated(const String& error)
+ExceptionOr<void> ApplePayPaymentHandler::shippingAddressUpdated(Vector<PaymentError>&& errors)
 {
     ASSERT(m_isUpdating);
     m_isUpdating = false;
 
     ShippingContactUpdate update;
+    update.errors = WTFMove(errors);
 
-    if (m_paymentRequest->paymentOptions().requestShipping && m_paymentRequest->paymentDetails().shippingOptions.isEmpty()) {
-        PaymentError paymentError;
-        paymentError.code = PaymentError::Code::ShippingContactInvalid;
-        paymentError.message = error;
-        update.errors.append(WTFMove(paymentError));
-    }
-
     auto newTotalAndLineItems = computeTotalAndLineItems();
     if (newTotalAndLineItems.hasException())
         return newTotalAndLineItems.releaseException();

Modified: trunk/Source/WebCore/Modules/applepay/paymentrequest/ApplePayPaymentHandler.h (236551 => 236552)


--- trunk/Source/WebCore/Modules/applepay/paymentrequest/ApplePayPaymentHandler.h	2018-09-27 16:34:34 UTC (rev 236551)
+++ trunk/Source/WebCore/Modules/applepay/paymentrequest/ApplePayPaymentHandler.h	2018-09-27 16:44:49 UTC (rev 236552)
@@ -53,8 +53,9 @@
     PaymentCoordinator& paymentCoordinator() const;
 
     ExceptionOr<ApplePaySessionPaymentRequest::TotalAndLineItems> computeTotalAndLineItems();
+    Vector<PaymentError> computeErrors(String&& error, AddressErrors&&, PayerErrorFields&&, JSC::JSObject* paymentMethodErrors) const;
 
-    ExceptionOr<void> shippingAddressUpdated(const String& error);
+    ExceptionOr<void> shippingAddressUpdated(Vector<PaymentError>&& errors);
     ExceptionOr<void> shippingOptionUpdated();
     ExceptionOr<void> paymentMethodUpdated();
 
@@ -63,7 +64,7 @@
     ExceptionOr<void> show() final;
     void hide() final;
     void canMakePayment(WTF::Function<void(bool)>&& completionHandler) final;
-    ExceptionOr<void> detailsUpdated(PaymentRequest::UpdateReason, const String& error) final;
+    ExceptionOr<void> detailsUpdated(PaymentRequest::UpdateReason, String&& error, AddressErrors&&, PayerErrorFields&&, JSC::JSObject* paymentMethodErrors) final;
     ExceptionOr<void> merchantValidationCompleted(JSC::JSValue&&) final;
     void complete(std::optional<PaymentComplete>&&) final;
 

Modified: trunk/Source/WebCore/Modules/paymentrequest/PaymentDetailsUpdate.h (236551 => 236552)


--- trunk/Source/WebCore/Modules/paymentrequest/PaymentDetailsUpdate.h	2018-09-27 16:34:34 UTC (rev 236551)
+++ trunk/Source/WebCore/Modules/paymentrequest/PaymentDetailsUpdate.h	2018-09-27 16:44:49 UTC (rev 236552)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -27,6 +27,8 @@
 
 #if ENABLE(PAYMENT_REQUEST)
 
+#include "AddressErrors.h"
+#include "PayerErrorFields.h"
 #include "PaymentDetailsBase.h"
 #include "PaymentItem.h"
 #include <wtf/text/WTFString.h>
@@ -33,9 +35,12 @@
 
 namespace WebCore {
 
-struct PaymentDetailsUpdate final : public PaymentDetailsBase {
+struct PaymentDetailsUpdate final : PaymentDetailsBase {
     String error;
     PaymentItem total;
+    AddressErrors shippingAddressErrors;
+    PayerErrorFields payerErrors;
+    JSC::Strong<JSC::JSObject> paymentMethodErrors;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/Modules/paymentrequest/PaymentDetailsUpdate.idl (236551 => 236552)


--- trunk/Source/WebCore/Modules/paymentrequest/PaymentDetailsUpdate.idl	2018-09-27 16:34:34 UTC (rev 236551)
+++ trunk/Source/WebCore/Modules/paymentrequest/PaymentDetailsUpdate.idl	2018-09-27 16:44:49 UTC (rev 236552)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -28,4 +28,7 @@
 ] dictionary PaymentDetailsUpdate : PaymentDetailsBase {
     DOMString error;
     PaymentItem total;
+    AddressErrors shippingAddressErrors;
+    PayerErrorFields payerErrors;
+    object paymentMethodErrors;
 };

Modified: trunk/Source/WebCore/Modules/paymentrequest/PaymentHandler.h (236551 => 236552)


--- trunk/Source/WebCore/Modules/paymentrequest/PaymentHandler.h	2018-09-27 16:34:34 UTC (rev 236551)
+++ trunk/Source/WebCore/Modules/paymentrequest/PaymentHandler.h	2018-09-27 16:44:49 UTC (rev 236552)
@@ -38,6 +38,8 @@
 namespace WebCore {
 
 class Document;
+struct AddressErrors;
+struct PayerErrorFields;
 
 class PaymentHandler : public virtual PaymentSessionBase {
 public:
@@ -49,7 +51,7 @@
     virtual ExceptionOr<void> show() = 0;
     virtual void hide() = 0;
     virtual void canMakePayment(WTF::Function<void(bool)>&& completionHandler) = 0;
-    virtual ExceptionOr<void> detailsUpdated(PaymentRequest::UpdateReason, const String& error) = 0;
+    virtual ExceptionOr<void> detailsUpdated(PaymentRequest::UpdateReason, String&& error, AddressErrors&&, PayerErrorFields&&, JSC::JSObject* paymentMethodErrors) = 0;
     virtual ExceptionOr<void> merchantValidationCompleted(JSC::JSValue&&) = 0;
     virtual void complete(std::optional<PaymentComplete>&&) = 0;
 };

Modified: trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.cpp (236551 => 236552)


--- trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.cpp	2018-09-27 16:34:34 UTC (rev 236551)
+++ trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.cpp	2018-09-27 16:44:49 UTC (rev 236552)
@@ -559,7 +559,7 @@
         if (hasEventListeners(eventName))
             dispatchEvent(PaymentMethodChangeEvent::create(eventName, methodName, WTFMove(methodDetailsFunction)));
         else
-            m_activePaymentHandler->detailsUpdated(UpdateReason::PaymentMethodChanged, { });
+            m_activePaymentHandler->detailsUpdated(UpdateReason::PaymentMethodChanged, { }, { }, { }, { });
     });
 }
 
@@ -627,19 +627,19 @@
 
     auto& context = *m_detailsPromise->scriptExecutionContext();
     auto throwScope = DECLARE_THROW_SCOPE(context.vm());
-    auto paymentDetailsUpdate = convertDictionary<PaymentDetailsUpdate>(*context.execState(), m_detailsPromise->result());
+    auto detailsUpdate = convertDictionary<PaymentDetailsUpdate>(*context.execState(), m_detailsPromise->result());
     if (throwScope.exception()) {
         abortWithException(Exception { ExistingExceptionError });
         return;
     }
 
-    auto totalResult = checkAndCanonicalizeTotal(paymentDetailsUpdate.total.amount);
+    auto totalResult = checkAndCanonicalizeTotal(detailsUpdate.total.amount);
     if (totalResult.hasException()) {
         abortWithException(totalResult.releaseException());
         return;
     }
 
-    auto detailsResult = checkAndCanonicalizeDetails(*context.execState(), paymentDetailsUpdate, m_options.requestShipping, ShouldValidatePaymentMethodIdentifier::Yes);
+    auto detailsResult = checkAndCanonicalizeDetails(*context.execState(), detailsUpdate, m_options.requestShipping, ShouldValidatePaymentMethodIdentifier::Yes);
     if (detailsResult.hasException()) {
         abortWithException(detailsResult.releaseException());
         return;
@@ -647,17 +647,17 @@
 
     auto shippingOptionAndModifierData = detailsResult.releaseReturnValue();
 
-    m_details.total = WTFMove(paymentDetailsUpdate.total);
-    m_details.displayItems = WTFMove(paymentDetailsUpdate.displayItems);
+    m_details.total = WTFMove(detailsUpdate.total);
+    m_details.displayItems = WTFMove(detailsUpdate.displayItems);
     if (m_options.requestShipping) {
-        m_details.shippingOptions = WTFMove(paymentDetailsUpdate.shippingOptions);
+        m_details.shippingOptions = WTFMove(detailsUpdate.shippingOptions);
         m_shippingOption = WTFMove(std::get<0>(shippingOptionAndModifierData));
     }
 
-    m_details.modifiers = WTFMove(paymentDetailsUpdate.modifiers);
+    m_details.modifiers = WTFMove(detailsUpdate.modifiers);
     m_serializedModifierData = WTFMove(std::get<1>(shippingOptionAndModifierData));
 
-    auto result = m_activePaymentHandler->detailsUpdated(reason, paymentDetailsUpdate.error);
+    auto result = m_activePaymentHandler->detailsUpdated(reason, WTFMove(detailsUpdate.error), WTFMove(detailsUpdate.shippingAddressErrors), WTFMove(detailsUpdate.payerErrors), detailsUpdate.paymentMethodErrors.get());
     if (result.hasException()) {
         abortWithException(result.releaseException());
         return;

Modified: trunk/Source/WebCore/SourcesCocoa.txt (236551 => 236552)


--- trunk/Source/WebCore/SourcesCocoa.txt	2018-09-27 16:34:34 UTC (rev 236551)
+++ trunk/Source/WebCore/SourcesCocoa.txt	2018-09-27 16:44:49 UTC (rev 236552)
@@ -1,4 +1,4 @@
-// Copyright (C) 2017 Apple Inc. All rights reserved.
+// Copyright (C) 2017-2018 Apple Inc. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions
@@ -587,6 +587,8 @@
 
     JSApplePayContactField.cpp
     JSApplePayError.cpp
+    JSApplePayErrorCode.cpp
+    JSApplePayErrorContactField.cpp
     JSApplePayLineItem.cpp
     JSApplePayMerchantCapability.cpp
     JSApplePayModifier.cpp

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (236551 => 236552)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2018-09-27 16:34:34 UTC (rev 236551)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2018-09-27 16:44:49 UTC (rev 236552)
@@ -2955,6 +2955,13 @@
 		A1AFEDE71F8BFF6D0087013F /* MockPaymentCoordinator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1AFEDE51F8BFF6D0087013F /* MockPaymentCoordinator.cpp */; };
 		A1B5B29E1AAA846E008B6042 /* MockContentFilterSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1B5B29C1AAA846E008B6042 /* MockContentFilterSettings.cpp */; };
 		A1B5B29F1AAA846F008B6042 /* MockContentFilterSettings.h in Headers */ = {isa = PBXBuildFile; fileRef = A1B5B29D1AAA846E008B6042 /* MockContentFilterSettings.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		A1BB859C2159AEA10067E07D /* ApplePayErrorCode.h in Headers */ = {isa = PBXBuildFile; fileRef = A1BB85992159AEA10067E07D /* ApplePayErrorCode.h */; };
+		A1BB85A32159AF570067E07D /* ApplePayErrorContactField.h in Headers */ = {isa = PBXBuildFile; fileRef = A1BB85A02159AF570067E07D /* ApplePayErrorContactField.h */; };
+		A1BB85A92159B02C0067E07D /* MockPaymentError.h in Headers */ = {isa = PBXBuildFile; fileRef = A1BB85A62159B02C0067E07D /* MockPaymentError.h */; };
+		A1BB85B22159B1A10067E07D /* JSApplePayErrorCode.h in Headers */ = {isa = PBXBuildFile; fileRef = A1BB85AE2159B1A00067E07D /* JSApplePayErrorCode.h */; };
+		A1BB85B32159B1A10067E07D /* JSApplePayErrorContactField.h in Headers */ = {isa = PBXBuildFile; fileRef = A1BB85AF2159B1A00067E07D /* JSApplePayErrorContactField.h */; };
+		A1BB85B82159B3A40067E07D /* JSMockPaymentError.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1BB85B42159B3890067E07D /* JSMockPaymentError.cpp */; };
+		A1BB85B92159B3AE0067E07D /* JSMockPaymentError.h in Headers */ = {isa = PBXBuildFile; fileRef = A1BB85B52159B38A0067E07D /* JSMockPaymentError.h */; };
 		A1BF6B821AA96C7D00AF4A8A /* MockContentFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1BF6B801AA96C7D00AF4A8A /* MockContentFilter.cpp */; };
 		A1BF6B831AA96C7D00AF4A8A /* MockContentFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = A1BF6B811AA96C7D00AF4A8A /* MockContentFilter.h */; };
 		A1C1507A1E3F2B3E0032C98C /* PreviewConverter.h in Headers */ = {isa = PBXBuildFile; fileRef = A1C150781E3F2B3E0032C98C /* PreviewConverter.h */; };
@@ -11046,6 +11053,18 @@
 		A1AFEDE51F8BFF6D0087013F /* MockPaymentCoordinator.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = MockPaymentCoordinator.cpp; sourceTree = "<group>"; };
 		A1B5B29C1AAA846E008B6042 /* MockContentFilterSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MockContentFilterSettings.cpp; sourceTree = "<group>"; };
 		A1B5B29D1AAA846E008B6042 /* MockContentFilterSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MockContentFilterSettings.h; sourceTree = "<group>"; };
+		A1BB85992159AEA10067E07D /* ApplePayErrorCode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ApplePayErrorCode.h; sourceTree = "<group>"; };
+		A1BB859B2159AEA10067E07D /* ApplePayErrorCode.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = ApplePayErrorCode.idl; sourceTree = "<group>"; };
+		A1BB85A02159AF570067E07D /* ApplePayErrorContactField.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ApplePayErrorContactField.h; sourceTree = "<group>"; };
+		A1BB85A22159AF570067E07D /* ApplePayErrorContactField.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = ApplePayErrorContactField.idl; sourceTree = "<group>"; };
+		A1BB85A62159B02C0067E07D /* MockPaymentError.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MockPaymentError.h; sourceTree = "<group>"; };
+		A1BB85A82159B02C0067E07D /* MockPaymentError.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = MockPaymentError.idl; sourceTree = "<group>"; };
+		A1BB85AC2159B19F0067E07D /* JSApplePayErrorContactField.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSApplePayErrorContactField.cpp; sourceTree = "<group>"; };
+		A1BB85AD2159B1A00067E07D /* JSApplePayErrorCode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSApplePayErrorCode.cpp; sourceTree = "<group>"; };
+		A1BB85AE2159B1A00067E07D /* JSApplePayErrorCode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSApplePayErrorCode.h; sourceTree = "<group>"; };
+		A1BB85AF2159B1A00067E07D /* JSApplePayErrorContactField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSApplePayErrorContactField.h; sourceTree = "<group>"; };
+		A1BB85B42159B3890067E07D /* JSMockPaymentError.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSMockPaymentError.cpp; sourceTree = "<group>"; };
+		A1BB85B52159B38A0067E07D /* JSMockPaymentError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSMockPaymentError.h; sourceTree = "<group>"; };
 		A1BF6B801AA96C7D00AF4A8A /* MockContentFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MockContentFilter.cpp; sourceTree = "<group>"; };
 		A1BF6B811AA96C7D00AF4A8A /* MockContentFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MockContentFilter.h; sourceTree = "<group>"; };
 		A1C150771E3F2B3E0032C98C /* PreviewConverter.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PreviewConverter.mm; sourceTree = "<group>"; };
@@ -16095,6 +16114,10 @@
 				1ADFDFD51E71D8DF008F5D34 /* ApplePayError.cpp */,
 				1ADFDFD61E71D8DF008F5D34 /* ApplePayError.h */,
 				1ADFDFD71E71D8DF008F5D34 /* ApplePayError.idl */,
+				A1BB85992159AEA10067E07D /* ApplePayErrorCode.h */,
+				A1BB859B2159AEA10067E07D /* ApplePayErrorCode.idl */,
+				A1BB85A02159AF570067E07D /* ApplePayErrorContactField.h */,
+				A1BB85A22159AF570067E07D /* ApplePayErrorContactField.idl */,
 				7C6579E21E00827000E3A27A /* ApplePayLineItem.h */,
 				7C6579E41E0082C800E3A27A /* ApplePayLineItem.idl */,
 				A1DF5AA81F8070D40058A477 /* ApplePayMerchantCapability.cpp */,
@@ -16268,6 +16291,10 @@
 				A1DF5A971F7EC8BF0058A477 /* JSApplePayContactField.h */,
 				1ADFDFE11E71DCA0008F5D34 /* JSApplePayError.cpp */,
 				1ADFDFE21E71DCA0008F5D34 /* JSApplePayError.h */,
+				A1BB85AD2159B1A00067E07D /* JSApplePayErrorCode.cpp */,
+				A1BB85AE2159B1A00067E07D /* JSApplePayErrorCode.h */,
+				A1BB85AC2159B19F0067E07D /* JSApplePayErrorContactField.cpp */,
+				A1BB85AF2159B1A00067E07D /* JSApplePayErrorContactField.h */,
 				7C6579E91E00856600E3A27A /* JSApplePayLineItem.cpp */,
 				7C6579EA1E00856600E3A27A /* JSApplePayLineItem.h */,
 				A1DF5A891F7EC0000058A477 /* JSApplePayMerchantCapability.cpp */,
@@ -17039,6 +17066,8 @@
 				A1AFEDE51F8BFF6D0087013F /* MockPaymentCoordinator.cpp */,
 				A1AFEDE41F8BFF6D0087013F /* MockPaymentCoordinator.h */,
 				A146D3161F99B53D00D29196 /* MockPaymentCoordinator.idl */,
+				A1BB85A62159B02C0067E07D /* MockPaymentError.h */,
+				A1BB85A82159B02C0067E07D /* MockPaymentError.idl */,
 				A1CBEF631F9F11290028DE7C /* MockPaymentMethod.h */,
 				A14061891E2ECA0A0032B34E /* MockPreviewLoaderClient.cpp */,
 				A140618A1E2ECA0A0032B34E /* MockPreviewLoaderClient.h */,
@@ -17079,6 +17108,8 @@
 				A146D31F1F99CA3D00D29196 /* JSMockPaymentAddress.h */,
 				A146D3191F99BCBB00D29196 /* JSMockPaymentCoordinator.cpp */,
 				A146D3181F99BCBA00D29196 /* JSMockPaymentCoordinator.h */,
+				A1BB85B42159B3890067E07D /* JSMockPaymentError.cpp */,
+				A1BB85B52159B38A0067E07D /* JSMockPaymentError.h */,
 				427DA71B13735DFA007C57FB /* JSServiceWorkerInternals.cpp */,
 				427DA71C13735DFA007C57FB /* JSServiceWorkerInternals.h */,
 				EBF5121A1696496C0056BD25 /* JSTypeConversions.cpp */,
@@ -27113,6 +27144,7 @@
 				538EC9341F99B9F7004D22A8 /* JSMockPageOverlay.h in Headers */,
 				A146D3231F99D0EF00D29196 /* JSMockPaymentAddress.h in Headers */,
 				A146D31B1F99BCFB00D29196 /* JSMockPaymentCoordinator.h in Headers */,
+				A1BB85B92159B3AE0067E07D /* JSMockPaymentError.h in Headers */,
 				427DA71E13735DFA007C57FB /* JSServiceWorkerInternals.h in Headers */,
 				EBF5121D1696496C0056BD25 /* JSTypeConversions.h in Headers */,
 				CDC26B41160A8CCE0026757B /* LegacyMockCDM.h in Headers */,
@@ -27207,6 +27239,8 @@
 				93309DD7099E64920056E581 /* AppendNodeCommand.h in Headers */,
 				A1DF5A941F7EC4320058A477 /* ApplePayContactField.h in Headers */,
 				A12C59EE2035FC9B0012236B /* ApplePayError.h in Headers */,
+				A1BB859C2159AEA10067E07D /* ApplePayErrorCode.h in Headers */,
+				A1BB85A32159AF570067E07D /* ApplePayErrorContactField.h in Headers */,
 				7C6579E31E00827000E3A27A /* ApplePayLineItem.h in Headers */,
 				A1DF5A861F7EBDF20058A477 /* ApplePayMerchantCapability.h in Headers */,
 				A1F6CFFF1FE096210018078C /* ApplePayModifier.h in Headers */,
@@ -28554,6 +28588,8 @@
 				71025EDE1F99F1EC004A250C /* JSAnimationTimeline.h in Headers */,
 				A1DF5A991F7EC8C00058A477 /* JSApplePayContactField.h in Headers */,
 				A12C59F920360ACB0012236B /* JSApplePayError.h in Headers */,
+				A1BB85B22159B1A10067E07D /* JSApplePayErrorCode.h in Headers */,
+				A1BB85B32159B1A10067E07D /* JSApplePayErrorContactField.h in Headers */,
 				7C6579F01E00856600E3A27A /* JSApplePayLineItem.h in Headers */,
 				A1DF5A8E1F7EC0020058A477 /* JSApplePayMerchantCapability.h in Headers */,
 				A1F6D0121FE099B40018078C /* JSApplePayModifier.h in Headers */,
@@ -29618,6 +29654,7 @@
 				413CCD4A20DE034F0065A21A /* MockMediaDevice.h in Headers */,
 				CDF2B0131820540600F2B424 /* MockMediaPlayerMediaSource.h in Headers */,
 				CDF2B0151820540600F2B424 /* MockMediaSourcePrivate.h in Headers */,
+				A1BB85A92159B02C0067E07D /* MockPaymentError.h in Headers */,
 				07D6A4F41BED5F8800174146 /* MockRealtimeAudioSource.h in Headers */,
 				4A0FFA9E1AAF5E7E0062803B /* MockRealtimeMediaSourceCenter.h in Headers */,
 				07EE76EC1BE96DB000F89133 /* MockRealtimeVideoSource.h in Headers */,
@@ -31536,6 +31573,7 @@
 				2D4150DE1C1F868C000A3BA2 /* JSMockPageOverlay.cpp in Sources */,
 				A146D3221F99D0EC00D29196 /* JSMockPaymentAddress.cpp in Sources */,
 				A146D31A1F99BCF800D29196 /* JSMockPaymentCoordinator.cpp in Sources */,
+				A1BB85B82159B3A40067E07D /* JSMockPaymentError.cpp in Sources */,
 				427DA71D13735DFA007C57FB /* JSServiceWorkerInternals.cpp in Sources */,
 				EBF5121C1696496C0056BD25 /* JSTypeConversions.cpp in Sources */,
 				CDC26B40160A8CC60026757B /* LegacyMockCDM.cpp in Sources */,

Modified: trunk/Source/WebCore/testing/MockPaymentCoordinator.cpp (236551 => 236552)


--- trunk/Source/WebCore/testing/MockPaymentCoordinator.cpp	2018-09-27 16:34:34 UTC (rev 236551)
+++ trunk/Source/WebCore/testing/MockPaymentCoordinator.cpp	2018-09-27 16:44:49 UTC (rev 236552)
@@ -151,10 +151,13 @@
 
 void MockPaymentCoordinator::completeShippingContactSelection(std::optional<ShippingContactUpdate>&& shippingContactUpdate)
 {
-    if (shippingContactUpdate)
-        updateTotalAndLineItems(shippingContactUpdate->newTotalAndLineItems);
+    if (!shippingContactUpdate)
+        return;
+
+    updateTotalAndLineItems(shippingContactUpdate->newTotalAndLineItems);
+    m_errors = WTFMove(shippingContactUpdate->errors);
 }
-    
+
 void MockPaymentCoordinator::completePaymentMethodSelection(std::optional<PaymentMethodUpdate>&& paymentMethodUpdate)
 {
     if (paymentMethodUpdate)

Modified: trunk/Source/WebCore/testing/MockPaymentCoordinator.h (236551 => 236552)


--- trunk/Source/WebCore/testing/MockPaymentCoordinator.h	2018-09-27 16:34:34 UTC (rev 236551)
+++ trunk/Source/WebCore/testing/MockPaymentCoordinator.h	2018-09-27 16:44:49 UTC (rev 236552)
@@ -29,6 +29,7 @@
 
 #include "ApplePayLineItem.h"
 #include "MockPaymentAddress.h"
+#include "MockPaymentError.h"
 #include "PaymentCoordinatorClient.h"
 #include <wtf/HashSet.h>
 #include <wtf/text/StringHash.h>
@@ -50,6 +51,7 @@
 
     const ApplePayLineItem& total() const { return m_total; }
     const Vector<ApplePayLineItem>& lineItems() const { return m_lineItems; }
+    const Vector<MockPaymentError>& errors() const { return m_errors; }
 
     void ref() const { }
     void deref() const { }
@@ -76,6 +78,7 @@
     ApplePayPaymentContact m_shippingAddress;
     ApplePayLineItem m_total;
     Vector<ApplePayLineItem> m_lineItems;
+    Vector<MockPaymentError> m_errors;
     HashSet<String, ASCIICaseInsensitiveHash> m_availablePaymentNetworks;
 };
 

Modified: trunk/Source/WebCore/testing/MockPaymentCoordinator.idl (236551 => 236552)


--- trunk/Source/WebCore/testing/MockPaymentCoordinator.idl	2018-09-27 16:34:34 UTC (rev 236551)
+++ trunk/Source/WebCore/testing/MockPaymentCoordinator.idl	2018-09-27 16:44:49 UTC (rev 236552)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -35,4 +35,5 @@
 
     readonly attribute ApplePayLineItem total;
     readonly attribute sequence<ApplePayLineItem> lineItems;
+    readonly attribute sequence<MockPaymentError> errors;
 };

Copied: trunk/Source/WebCore/testing/MockPaymentError.h (from rev 236551, trunk/Source/WebCore/Modules/paymentrequest/PaymentDetailsUpdate.idl) (0 => 236552)


--- trunk/Source/WebCore/testing/MockPaymentError.h	                        (rev 0)
+++ trunk/Source/WebCore/testing/MockPaymentError.h	2018-09-27 16:44:49 UTC (rev 236552)
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(APPLE_PAY)
+
+#include "ApplePaySessionPaymentRequest.h"
+
+namespace WebCore {
+
+using MockPaymentError = PaymentError;
+
+} // namespace WebCore
+
+#endif // ENABLE(APPLE_PAY)

Copied: trunk/Source/WebCore/testing/MockPaymentError.idl (from rev 236551, trunk/Source/WebCore/Modules/paymentrequest/PaymentDetailsUpdate.idl) (0 => 236552)


--- trunk/Source/WebCore/testing/MockPaymentError.idl	                        (rev 0)
+++ trunk/Source/WebCore/testing/MockPaymentError.idl	2018-09-27 16:44:49 UTC (rev 236552)
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+[
+    Conditional=APPLE_PAY,
+    JSGenerateToJSObject,
+] dictionary MockPaymentError {
+    required ApplePayErrorCode code;
+    required DOMString message;
+    ApplePayErrorContactField contactField;
+};
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to