Title: [280459] trunk
Revision
280459
Author
drou...@apple.com
Date
2021-07-29 17:28:45 -0700 (Thu, 29 Jul 2021)

Log Message

[Payment Request] `additionalShippingMethods` are not used if a `paymentMethodType` is provided
https://bugs.webkit.org/show_bug.cgi?id=228599
<rdar://problem/81190366>

Reviewed by Andy Estes.

Source/WebCore:

r275169 made it so that `paymentMethodType` is no longer `required` so that `additionalShippingMethods`
can be specified without having to limit it to a specific payment method type. While this
works in theory, WebKit doesn't know about the user's selected payment method type until the
user actually selects a payment method, meaning that until then the `additionalShippingMethods`
are not used. Unfortunately (until now) `PKPaymentRequestPaymentMethodUpdate` did not
support providing a `NSArray<PKShippingMethod *> *`, so there was no way to update the list
of shipping methods when the user changed their selected payment method, meaning that WebKit
would have to wait/rely on the user to change their shipping address _after_ selecting a
payment method in order for `additionalShippingMethods` to take effect.

This also fixes an issue with WebKit's implementation of the W3C Payment Request API by
allowing any generic (i.e. things not specific to Apple Pay) `shippingOptions` provided in
`PaymentDetailsUpdate` to actually be used and update the Apple Pay sheet accordingly.

Test: http/tests/paymentrequest/ApplePayModifier-paymentMethodType.https.html

* Modules/applepay/ApplePayModifier.idl:
* Modules/applepay/ApplePayModifier.h:
* Modules/applepay/ApplePayPaymentMethodUpdate.idl:
* Modules/applepay/ApplePayPaymentMethodUpdate.h:
(WebCore::ApplePayPaymentMethodUpdate::encode const):
(WebCore::ApplePayPaymentMethodUpdate::decode):
* Modules/applepay/ApplePayShippingMethodUpdate.idl:
* Modules/applepay/ApplePayShippingMethodUpdate.h:
(WebCore::ApplePayShippingMethodUpdate::encode const):
(WebCore::ApplePayShippingMethodUpdate::decode):
Add (or wrap existing) `additionalShippingMethods`/`newShippingMethods` properties.

* Modules/applepay/paymentrequest/ApplePayPaymentHandler.cpp:
(WebCore::ApplePayPaymentHandler::computeShippingMethods):
(WebCore::ApplePayPaymentHandler::detailsUpdated):
(WebCore::ApplePayPaymentHandler::shippingOptionUpdated):
(WebCore::ApplePayPaymentHandler::paymentMethodUpdated):
Also call `computeShippingMethods()` and add the result to the update.

* testing/MockPaymentCoordinator.cpp:
(WebCore::MockPaymentCoordinator::completeShippingMethodSelection):
(WebCore::MockPaymentCoordinator::completeShippingContactSelection):
(WebCore::MockPaymentCoordinator::completePaymentMethodSelection):
(WebCore::MockPaymentCoordinator::completeCouponCodeChange):
Support for testing.

Source/WebCore/PAL:

r275169 made it so that `paymentMethodType` is no longer `required` so that `additionalShippingMethods`
can be specified without having to limit it to a specific payment method type. While this
works in theory, WebKit doesn't know about the user's selected payment method type until the
user actually selects a payment method, meaning that until then the `additionalShippingMethods`
are not used. Unfortunately (until now) `PKPaymentRequestPaymentMethodUpdate` did not
support providing a `NSArray<PKShippingMethod *> *`, so there was no way to update the list
of shipping methods when the user changed their selected payment method, meaning that WebKit
would have to wait/rely on the user to change their shipping address _after_ selecting a
payment method in order for `additionalShippingMethods` to take effect.

This also fixes an issue with WebKit's implementation of the W3C Payment Request API by
allowing any generic (i.e. things not specific to Apple Pay) `shippingOptions` provided in
`PaymentDetailsUpdate` to actually be used and update the Apple Pay sheet accordingly.

* pal/spi/cocoa/PassKitSPI.h:
 - add the new `shippingMethods` property on `PKPaymentRequestUpdate`
 - add the existing `errors` property on `PKPaymentRequestPaymentMethodUpdate`

Source/WebKit:

r275169 made it so that `paymentMethodType` is no longer `required` so that `additionalShippingMethods`
can be specified without having to limit it to a specific payment method type. While this
works in theory, WebKit doesn't know about the user's selected payment method type until the
user actually selects a payment method, meaning that until then the `additionalShippingMethods`
are not used. Unfortunately (until now) `PKPaymentRequestPaymentMethodUpdate` did not
support providing a `NSArray<PKShippingMethod *> *`, so there was no way to update the list
of shipping methods when the user changed their selected payment method, meaning that WebKit
would have to wait/rely on the user to change their shipping address _after_ selecting a
payment method in order for `additionalShippingMethods` to take effect.

This also fixes an issue with WebKit's implementation of the W3C Payment Request API by
allowing any generic (i.e. things not specific to Apple Pay) `shippingOptions` provided in
`PaymentDetailsUpdate` to actually be used and update the Apple Pay sheet accordingly.

* Platform/cocoa/PaymentAuthorizationPresenter.mm:
(WebKit::PaymentAuthorizationPresenter::completePaymentMethodSelection):
(WebKit::PaymentAuthorizationPresenter::completeShippingMethodSelection):
Also convert and set the `shippingMethods` on the update.

Source/WTF:

r275169 made it so that `paymentMethodType` is no longer `required` so that `additionalShippingMethods`
can be specified without having to limit it to a specific payment method type. While this
works in theory, WebKit doesn't know about the user's selected payment method type until the
user actually selects a payment method, meaning that until then the `additionalShippingMethods`
are not used. Unfortunately (until now) `PKPaymentRequestPaymentMethodUpdate` did not
support providing a `NSArray<PKShippingMethod *> *`, so there was no way to update the list
of shipping methods when the user changed their selected payment method, meaning that WebKit
would have to wait/rely on the user to change their shipping address _after_ selecting a
payment method in order for `additionalShippingMethods` to take effect.

This also fixes an issue with WebKit's implementation of the W3C Payment Request API by
allowing any generic (i.e. things not specific to Apple Pay) `shippingOptions` provided in
`PaymentDetailsUpdate` to actually be used and update the Apple Pay sheet accordingly.

* wtf/PlatformHave.h:
* wtf/PlatformEnableCocoa.h:
Add new compile flags for PassKit supporting modifying shipping methods with any update.

LayoutTests:

* http/tests/paymentrequest/ApplePayModifier-paymentMethodType.https.html: Added.
* http/tests/paymentrequest/ApplePayModifier-paymentMethodType.https-expected.txt: Added.

* platform/ios-14-wk2/TestExpectations:
* platform/mac-bigsur-wk2/TestExpectations: Added.
Skip on older macOS/iOS since they don't support modifying shipping methods with any update.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (280458 => 280459)


--- trunk/LayoutTests/ChangeLog	2021-07-30 00:14:37 UTC (rev 280458)
+++ trunk/LayoutTests/ChangeLog	2021-07-30 00:28:45 UTC (rev 280459)
@@ -1,3 +1,18 @@
+2021-07-29  Devin Rousso  <drou...@apple.com>
+
+        [Payment Request] `additionalShippingMethods` are not used if a `paymentMethodType` is provided
+        https://bugs.webkit.org/show_bug.cgi?id=228599
+        <rdar://problem/81190366>
+
+        Reviewed by Andy Estes.
+
+        * http/tests/paymentrequest/ApplePayModifier-paymentMethodType.https.html: Added.
+        * http/tests/paymentrequest/ApplePayModifier-paymentMethodType.https-expected.txt: Added.
+
+        * platform/ios-14-wk2/TestExpectations:
+        * platform/mac-bigsur-wk2/TestExpectations: Added.
+        Skip on older macOS/iOS since they don't support modifying shipping methods with any update.
+
 2021-07-29  Eric Hutchison  <ehutchi...@apple.com>
 
         [ Mac wk1 Debug] imported/w3c/web-platform-tests/html/cross-origin-opener-policy/coop-csp-sandbox.https.html.

Added: trunk/LayoutTests/http/tests/paymentrequest/ApplePayModifier-paymentMethodType.https-expected.txt (0 => 280459)


--- trunk/LayoutTests/http/tests/paymentrequest/ApplePayModifier-paymentMethodType.https-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/paymentrequest/ApplePayModifier-paymentMethodType.https-expected.txt	2021-07-30 00:28:45 UTC (rev 280459)
@@ -0,0 +1,7 @@
+
+PASS Should have all additional line items and shipping options if `paymentMethodType` is not provided.
+PASS Should not have any additional line items or shipping options if a non-matching `paymentMethodType` is provided and the user has not chosen a payment method type yet.
+PASS Should not have any additional line items or shipping options if `paymentMethodType` is provided and the user chose a non-matching payment method type.
+PASS Should not have any additional line items or shipping options if a matching `paymentMethodType` is provided and the user has not chosen a payment method type yet.
+PASS Should have all additional line items and shipping options if `paymentMethodType` is provided and the user chose a matching payment method type.
+

Added: trunk/LayoutTests/http/tests/paymentrequest/ApplePayModifier-paymentMethodType.https.html (0 => 280459)


--- trunk/LayoutTests/http/tests/paymentrequest/ApplePayModifier-paymentMethodType.https.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/paymentrequest/ApplePayModifier-paymentMethodType.https.html	2021-07-30 00:28:45 UTC (rev 280459)
@@ -0,0 +1,140 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Tests for providing `paymentMethodType` as part of `ApplePayModifier`.</title>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+<body>
+<script>
+setup({ explicit_done: true, explicit_timeout: true });
+
+const lineItem = {
+    label: "Additional Recurring",
+    amount: "20.00",
+    paymentTiming: "recurring",
+    recurringPaymentStartDate: new Date(0),
+    recurringPaymentIntervalUnit: "year",
+    recurringPaymentIntervalCount: 10,
+    recurringPaymentEndDate: new Date(1),
+};
+
+const shippingMethod = {
+    amount: "10.00",
+    detail: "detail",
+    identifier: "additional-shipping",
+    label: "Additional Shipping",
+    dateComponentsRange: {
+        startDateComponents: { days: 5 },
+        endDateComponents: { days: 10 },
+    },
+};
+
+function validPaymentDetailsWithModifierThatHasPaymentMethodType(paymentMethodType) {
+    let details = validPaymentDetails();
+    details.modifiers = [
+        {
+            supportedMethods: "https://apple.com/apple-pay",
+            data: {
+                paymentMethodType,
+                additionalLineItems: [ lineItem ],
+                additionalShippingMethods: [ shippingMethod ],
+            },
+        },
+    ];
+    return details;
+}
+
+function testPaymentShippingOptionData(description, {simulatePaymentMethodChange, paymentMethodType, expectedAdditionalLineItems, expectedAdditionalShippingMethods}) {
+    user_activation_test(async (test) => {
+        let request = new PaymentRequest([validPaymentMethod()], validPaymentDetailsWithModifierThatHasPaymentMethodType(paymentMethodType), { requestShipping: true });
+        request.addEventListener("merchantvalidation", (event) => {
+            event.complete({ });
+        });
+        request.addEventListener("shippingaddresschange", (event) => {
+            event.updateWith({ });
+
+            if (simulatePaymentMethodChange)
+                internals.mockPaymentCoordinator.changePaymentMethod({ type: "debit" });
+            else
+                internals.mockPaymentCoordinator.acceptPayment();
+        });
+        if (simulatePaymentMethodChange) {
+            request.addEventListener("paymentmethodchange", (event) => {
+                event.updateWith({ });
+
+                internals.mockPaymentCoordinator.acceptPayment();
+            });
+        }
+
+        let response = await request.show();
+
+        let actualLineItems = internals.mockPaymentCoordinator.lineItems;
+        assert_greater_than_equal(actualLineItems.length, expectedAdditionalLineItems.length, `check that there are at least ${expectedAdditionalLineItems.length} line items`);
+        for (let i = 0; i < expectedAdditionalLineItems.length; ++i) {
+            let actualLineItem = actualLineItems[actualLineItems.length - expectedAdditionalLineItems.length + i];
+            let expectedAdditionalLineItem = expectedAdditionalLineItems[i];
+
+            assert_equals(actualLineItem.label, expectedAdditionalLineItem.label, `check that the \`label\` matches for additional line item ${i}`);
+            assert_equals(actualLineItem.amount, expectedAdditionalLineItem.amount, `check that the \`amount\` matches for additional line item ${i}`);
+            assert_equals(actualLineItem.paymentTiming, expectedAdditionalLineItem.paymentTiming, `check that the \`paymentTiming\` matches for additional line item ${i}`);
+            assert_equals(actualLineItem.recurringPaymentStartDate?.getTime(), expectedAdditionalLineItem.recurringPaymentStartDate?.getTime(), `check that the \`recurringPaymentStartDate\` matches for additional line item ${i}`);
+            assert_equals(actualLineItem.recurringPaymentIntervalUnit, expectedAdditionalLineItem.recurringPaymentIntervalUnit, `check that the \`recurringPaymentIntervalUnit\` matches for additional line item ${i}`);
+            assert_equals(actualLineItem.recurringPaymentIntervalCount, expectedAdditionalLineItem.recurringPaymentIntervalCount, `check that the \`recurringPaymentIntervalCount\` matches for additional line item ${i}`);
+            assert_equals(actualLineItem.recurringPaymentEndDate?.getTime(), expectedAdditionalLineItem.recurringPaymentEndDate?.getTime(), `check that the \`recurringPaymentEndDate\` matches for additional line item ${i}`);
+            assert_equals(actualLineItem.deferredPaymentDate?.getTime(), expectedAdditionalLineItem.deferredPaymentDate?.getTime(), `check that the \`deferredPaymentDate\` matches for additional line item ${i}`);
+        }
+
+        let actualShippingMethods = internals.mockPaymentCoordinator.shippingMethods;
+        assert_greater_than_equal(actualShippingMethods.length, expectedAdditionalShippingMethods.length, `check that there are at least ${expectedAdditionalShippingMethods.length} shipping methods`);
+        for (let i = 0; i < expectedAdditionalShippingMethods.length; ++i) {
+            let actualShippingMethod = actualShippingMethods[actualShippingMethods.length - expectedAdditionalShippingMethods.length + i];
+            let expectedAdditionalShippingMethod = expectedAdditionalShippingMethods[i];
+
+            assert_equals(actualShippingMethod.amount, expectedAdditionalShippingMethod.amount, `check that the \`amount\` matches for additional shipping method ${i}`);
+            assert_equals(actualShippingMethod.detail, expectedAdditionalShippingMethod.detail, `check that the \`detail\` matches for additional shipping method ${i}`);
+            assert_equals(actualShippingMethod.identifier, expectedAdditionalShippingMethod.identifier, `check that the \`identifier\` matches for additional shipping method ${i}`);
+            assert_equals(actualShippingMethod.label, expectedAdditionalShippingMethod.label, `check that the \`label\` matches for additional shipping method ${i}`);
+            if (expectedAdditionalShippingMethod.dateComponentsRange)
+                assert_object_equals(actualShippingMethod.dateComponentsRange, expectedAdditionalShippingMethod.dateComponentsRange, `check that the \`dateComponentsRange\` matches for additional shipping method ${i}`);
+            else
+                assert_equals(actualShippingMethod.dateComponentsRange, expectedAdditionalShippingMethod.dateComponentsRange, `check that the \`dateComponentsRange\` matches for additional shipping method ${i}`);
+        }
+
+        await response.complete("success");
+    }, description);
+}
+
+testPaymentShippingOptionData("Should have all additional line items and shipping options if `paymentMethodType` is not provided.", {
+    paymentMethodType: undefined,
+    expectedAdditionalLineItems: [ ],
+    expectedAdditionalShippingMethods: [ ],
+});
+testPaymentShippingOptionData("Should not have any additional line items or shipping options if a non-matching `paymentMethodType` is provided and the user has not chosen a payment method type yet.", {
+    simulatePaymentMethodChange: false,
+    paymentMethodType: "credit",
+    expectedAdditionalLineItems: [ ],
+    expectedAdditionalShippingMethods: [ ],
+});
+testPaymentShippingOptionData("Should not have any additional line items or shipping options if `paymentMethodType` is provided and the user chose a non-matching payment method type.", {
+    simulatePaymentMethodChange: true,
+    paymentMethodType: "credit",
+    expectedAdditionalLineItems: [ ],
+    expectedAdditionalShippingMethods: [ ],
+});
+testPaymentShippingOptionData("Should not have any additional line items or shipping options if a matching `paymentMethodType` is provided and the user has not chosen a payment method type yet.", {
+    simulatePaymentMethodChange: false,
+    paymentMethodType: "debit",
+    expectedAdditionalLineItems: [ ],
+    expectedAdditionalShippingMethods: [ ],
+});
+testPaymentShippingOptionData("Should have all additional line items and shipping options if `paymentMethodType` is provided and the user chose a matching payment method type.", {
+    simulatePaymentMethodChange: true,
+    paymentMethodType: "debit",
+    expectedAdditionalLineItems: [ lineItem ],
+    expectedAdditionalShippingMethods: [ shippingMethod ],
+});
+
+done();
+</script>
+

Modified: trunk/LayoutTests/platform/ios-14-wk2/TestExpectations (280458 => 280459)


--- trunk/LayoutTests/platform/ios-14-wk2/TestExpectations	2021-07-30 00:14:37 UTC (rev 280458)
+++ trunk/LayoutTests/platform/ios-14-wk2/TestExpectations	2021-07-30 00:28:45 UTC (rev 280459)
@@ -7,4 +7,6 @@
 fast/images/text-recognition/mac [ Skip ]
 
 # Accessibility text recognition support tests.
-accessibility/ios-simulator/image-overlay-elements.html [ Skip ]
\ No newline at end of file
+accessibility/ios-simulator/image-overlay-elements.html [ Skip ]
+
+http/tests/paymentrequest/ApplePayModifier-paymentMethodType.https.html [ Skip ]

Added: trunk/LayoutTests/platform/mac-bigsur-wk2/TestExpectations (0 => 280459)


--- trunk/LayoutTests/platform/mac-bigsur-wk2/TestExpectations	                        (rev 0)
+++ trunk/LayoutTests/platform/mac-bigsur-wk2/TestExpectations	2021-07-30 00:28:45 UTC (rev 280459)
@@ -0,0 +1 @@
+http/tests/paymentrequest/ApplePayModifier-paymentMethodType.https.html [ Skip ]

Modified: trunk/Source/WTF/ChangeLog (280458 => 280459)


--- trunk/Source/WTF/ChangeLog	2021-07-30 00:14:37 UTC (rev 280458)
+++ trunk/Source/WTF/ChangeLog	2021-07-30 00:28:45 UTC (rev 280459)
@@ -1,3 +1,29 @@
+2021-07-29  Devin Rousso  <drou...@apple.com>
+
+        [Payment Request] `additionalShippingMethods` are not used if a `paymentMethodType` is provided
+        https://bugs.webkit.org/show_bug.cgi?id=228599
+        <rdar://problem/81190366>
+
+        Reviewed by Andy Estes.
+
+        r275169 made it so that `paymentMethodType` is no longer `required` so that `additionalShippingMethods`
+        can be specified without having to limit it to a specific payment method type. While this
+        works in theory, WebKit doesn't know about the user's selected payment method type until the
+        user actually selects a payment method, meaning that until then the `additionalShippingMethods`
+        are not used. Unfortunately (until now) `PKPaymentRequestPaymentMethodUpdate` did not
+        support providing a `NSArray<PKShippingMethod *> *`, so there was no way to update the list
+        of shipping methods when the user changed their selected payment method, meaning that WebKit
+        would have to wait/rely on the user to change their shipping address _after_ selecting a
+        payment method in order for `additionalShippingMethods` to take effect.
+
+        This also fixes an issue with WebKit's implementation of the W3C Payment Request API by
+        allowing any generic (i.e. things not specific to Apple Pay) `shippingOptions` provided in
+        `PaymentDetailsUpdate` to actually be used and update the Apple Pay sheet accordingly.
+
+        * wtf/PlatformHave.h:
+        * wtf/PlatformEnableCocoa.h:
+        Add new compile flags for PassKit supporting modifying shipping methods with any update.
+
 2021-07-28  Yusuke Suzuki  <ysuz...@apple.com>
 
         [JSC] Yarr should perform BoyerMoore search

Modified: trunk/Source/WTF/wtf/PlatformEnableCocoa.h (280458 => 280459)


--- trunk/Source/WTF/wtf/PlatformEnableCocoa.h	2021-07-30 00:14:37 UTC (rev 280458)
+++ trunk/Source/WTF/wtf/PlatformEnableCocoa.h	2021-07-30 00:28:45 UTC (rev 280459)
@@ -95,6 +95,10 @@
 #define ENABLE_APPLE_PAY_SHIPPING_METHOD_DATE_COMPONENTS_RANGE 1
 #endif
 
+#if !defined(ENABLE_APPLE_PAY_UPDATE_SHIPPING_METHODS_WHEN_CHANGING_LINE_ITEMS) && HAVE(PASSKIT_UPDATE_SHIPPING_METHODS_WHEN_CHANGING_SUMMARY_ITEMS)
+#define ENABLE_APPLE_PAY_UPDATE_SHIPPING_METHODS_WHEN_CHANGING_LINE_ITEMS 1
+#endif
+
 #if !defined(ENABLE_APPLICATION_MANIFEST)
 #define ENABLE_APPLICATION_MANIFEST 1
 #endif

Modified: trunk/Source/WTF/wtf/PlatformHave.h (280458 => 280459)


--- trunk/Source/WTF/wtf/PlatformHave.h	2021-07-30 00:14:37 UTC (rev 280458)
+++ trunk/Source/WTF/wtf/PlatformHave.h	2021-07-30 00:28:45 UTC (rev 280459)
@@ -725,6 +725,7 @@
 #define HAVE_PASSKIT_SHIPPING_METHOD_DATE_COMPONENTS_RANGE 1
 #define HAVE_PASSKIT_COUPON_CODE 1
 #define HAVE_PASSKIT_SHIPPING_CONTACT_EDITING_MODE 1
+#define HAVE_PASSKIT_UPDATE_SHIPPING_METHODS_WHEN_CHANGING_SUMMARY_ITEMS 1
 #endif
 
 #if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500) || PLATFORM(IOS) || PLATFORM(MACCATALYST)

Modified: trunk/Source/WebCore/ChangeLog (280458 => 280459)


--- trunk/Source/WebCore/ChangeLog	2021-07-30 00:14:37 UTC (rev 280458)
+++ trunk/Source/WebCore/ChangeLog	2021-07-30 00:28:45 UTC (rev 280459)
@@ -1,3 +1,53 @@
+2021-07-29  Devin Rousso  <drou...@apple.com>
+
+        [Payment Request] `additionalShippingMethods` are not used if a `paymentMethodType` is provided
+        https://bugs.webkit.org/show_bug.cgi?id=228599
+        <rdar://problem/81190366>
+
+        Reviewed by Andy Estes.
+
+        r275169 made it so that `paymentMethodType` is no longer `required` so that `additionalShippingMethods`
+        can be specified without having to limit it to a specific payment method type. While this
+        works in theory, WebKit doesn't know about the user's selected payment method type until the
+        user actually selects a payment method, meaning that until then the `additionalShippingMethods`
+        are not used. Unfortunately (until now) `PKPaymentRequestPaymentMethodUpdate` did not
+        support providing a `NSArray<PKShippingMethod *> *`, so there was no way to update the list
+        of shipping methods when the user changed their selected payment method, meaning that WebKit
+        would have to wait/rely on the user to change their shipping address _after_ selecting a
+        payment method in order for `additionalShippingMethods` to take effect.
+
+        This also fixes an issue with WebKit's implementation of the W3C Payment Request API by
+        allowing any generic (i.e. things not specific to Apple Pay) `shippingOptions` provided in
+        `PaymentDetailsUpdate` to actually be used and update the Apple Pay sheet accordingly.
+
+        Test: http/tests/paymentrequest/ApplePayModifier-paymentMethodType.https.html
+
+        * Modules/applepay/ApplePayModifier.idl:
+        * Modules/applepay/ApplePayModifier.h:
+        * Modules/applepay/ApplePayPaymentMethodUpdate.idl:
+        * Modules/applepay/ApplePayPaymentMethodUpdate.h:
+        (WebCore::ApplePayPaymentMethodUpdate::encode const):
+        (WebCore::ApplePayPaymentMethodUpdate::decode):
+        * Modules/applepay/ApplePayShippingMethodUpdate.idl:
+        * Modules/applepay/ApplePayShippingMethodUpdate.h:
+        (WebCore::ApplePayShippingMethodUpdate::encode const):
+        (WebCore::ApplePayShippingMethodUpdate::decode):
+        Add (or wrap existing) `additionalShippingMethods`/`newShippingMethods` properties.
+
+        * Modules/applepay/paymentrequest/ApplePayPaymentHandler.cpp:
+        (WebCore::ApplePayPaymentHandler::computeShippingMethods):
+        (WebCore::ApplePayPaymentHandler::detailsUpdated):
+        (WebCore::ApplePayPaymentHandler::shippingOptionUpdated):
+        (WebCore::ApplePayPaymentHandler::paymentMethodUpdated):
+        Also call `computeShippingMethods()` and add the result to the update.
+
+        * testing/MockPaymentCoordinator.cpp:
+        (WebCore::MockPaymentCoordinator::completeShippingMethodSelection):
+        (WebCore::MockPaymentCoordinator::completeShippingContactSelection):
+        (WebCore::MockPaymentCoordinator::completePaymentMethodSelection):
+        (WebCore::MockPaymentCoordinator::completeCouponCodeChange):
+        Support for testing.
+
 2021-07-29  Alex Christensen  <achristen...@webkit.org>
 
         [ Mac ] fast/dom/webtiming-document-open.html is a flaky failure

Modified: trunk/Source/WebCore/Modules/applepay/ApplePayPaymentMethodUpdate.h (280458 => 280459)


--- trunk/Source/WebCore/Modules/applepay/ApplePayPaymentMethodUpdate.h	2021-07-30 00:14:37 UTC (rev 280458)
+++ trunk/Source/WebCore/Modules/applepay/ApplePayPaymentMethodUpdate.h	2021-07-30 00:28:45 UTC (rev 280459)
@@ -28,11 +28,21 @@
 #if ENABLE(APPLE_PAY)
 
 #include "ApplePayDetailsUpdateBase.h"
+#include "ApplePayError.h"
+#include "ApplePayShippingMethod.h"
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
 #include <wtf/text/WTFString.h>
 
 namespace WebCore {
 
 struct ApplePayPaymentMethodUpdate final : public ApplePayDetailsUpdateBase {
+#if ENABLE(APPLE_PAY_UPDATE_SHIPPING_METHODS_WHEN_CHANGING_LINE_ITEMS)
+    Vector<RefPtr<ApplePayError>> errors;
+
+    Vector<ApplePayShippingMethod> newShippingMethods;
+#endif
+
 #if ENABLE(APPLE_PAY_INSTALLMENTS)
     String installmentGroupIdentifier;
 #endif // ENABLE(APPLE_PAY_INSTALLMENTS)
@@ -45,6 +55,10 @@
 void ApplePayPaymentMethodUpdate::encode(Encoder& encoder) const
 {
     ApplePayDetailsUpdateBase::encode(encoder);
+#if ENABLE(APPLE_PAY_UPDATE_SHIPPING_METHODS_WHEN_CHANGING_LINE_ITEMS)
+    encoder << errors;
+    encoder << newShippingMethods;
+#endif
 #if ENABLE(APPLE_PAY_INSTALLMENTS)
     encoder << installmentGroupIdentifier;
 #endif // ENABLE(APPLE_PAY_INSTALLMENTS)
@@ -65,6 +79,11 @@
         return std::nullopt; \
     result.name = WTFMove(*name); \
 
+#if ENABLE(APPLE_PAY_UPDATE_SHIPPING_METHODS_WHEN_CHANGING_LINE_ITEMS)
+    DECODE(errors, Vector<RefPtr<ApplePayError>>)
+    DECODE(newShippingMethods, Vector<ApplePayShippingMethod>)
+#endif
+
 #if ENABLE(APPLE_PAY_INSTALLMENTS)
     DECODE(installmentGroupIdentifier, String)
 #endif // ENABLE(APPLE_PAY_INSTALLMENTS)

Modified: trunk/Source/WebCore/Modules/applepay/ApplePayPaymentMethodUpdate.idl (280458 => 280459)


--- trunk/Source/WebCore/Modules/applepay/ApplePayPaymentMethodUpdate.idl	2021-07-30 00:14:37 UTC (rev 280458)
+++ trunk/Source/WebCore/Modules/applepay/ApplePayPaymentMethodUpdate.idl	2021-07-30 00:28:45 UTC (rev 280459)
@@ -26,5 +26,9 @@
 [
     Conditional=APPLE_PAY,
 ] dictionary ApplePayPaymentMethodUpdate : ApplePayDetailsUpdateBase {
+    [Conditional=APPLE_PAY_UPDATE_SHIPPING_METHODS_WHEN_CHANGING_LINE_ITEMS] sequence<ApplePayError> errors;
+
+    [Conditional=APPLE_PAY_UPDATE_SHIPPING_METHODS_WHEN_CHANGING_LINE_ITEMS] sequence<ApplePayShippingMethod> newShippingMethods;
+
     [Conditional=APPLE_PAY_INSTALLMENTS] DOMString installmentGroupIdentifier;
 };

Modified: trunk/Source/WebCore/Modules/applepay/ApplePayShippingMethodUpdate.h (280458 => 280459)


--- trunk/Source/WebCore/Modules/applepay/ApplePayShippingMethodUpdate.h	2021-07-30 00:14:37 UTC (rev 280458)
+++ trunk/Source/WebCore/Modules/applepay/ApplePayShippingMethodUpdate.h	2021-07-30 00:28:45 UTC (rev 280459)
@@ -28,10 +28,16 @@
 #if ENABLE(APPLE_PAY)
 
 #include "ApplePayDetailsUpdateBase.h"
+#include "ApplePayShippingMethod.h"
+#include <wtf/Vector.h>
 
 namespace WebCore {
 
 struct ApplePayShippingMethodUpdate final : public ApplePayDetailsUpdateBase {
+#if ENABLE(APPLE_PAY_UPDATE_SHIPPING_METHODS_WHEN_CHANGING_LINE_ITEMS)
+    Vector<ApplePayShippingMethod> newShippingMethods;
+#endif
+
     template<class Encoder> void encode(Encoder&) const;
     template<class Decoder> static std::optional<ApplePayShippingMethodUpdate> decode(Decoder&);
 };
@@ -40,6 +46,9 @@
 void ApplePayShippingMethodUpdate::encode(Encoder& encoder) const
 {
     ApplePayDetailsUpdateBase::encode(encoder);
+#if ENABLE(APPLE_PAY_UPDATE_SHIPPING_METHODS_WHEN_CHANGING_LINE_ITEMS)
+    encoder << newShippingMethods;
+#endif
 }
 
 template<class Decoder>
@@ -50,6 +59,19 @@
     if (!result.decodeBase(decoder))
         return std::nullopt;
 
+#define DECODE(name, type) \
+    std::optional<type> name; \
+    decoder >> name; \
+    if (!name) \
+        return std::nullopt; \
+    result.name = WTFMove(*name); \
+
+#if ENABLE(APPLE_PAY_UPDATE_SHIPPING_METHODS_WHEN_CHANGING_LINE_ITEMS)
+    DECODE(newShippingMethods, Vector<ApplePayShippingMethod>)
+#endif
+
+#undef DECODE
+
     return result;
 }
 

Modified: trunk/Source/WebCore/Modules/applepay/ApplePayShippingMethodUpdate.idl (280458 => 280459)


--- trunk/Source/WebCore/Modules/applepay/ApplePayShippingMethodUpdate.idl	2021-07-30 00:14:37 UTC (rev 280458)
+++ trunk/Source/WebCore/Modules/applepay/ApplePayShippingMethodUpdate.idl	2021-07-30 00:28:45 UTC (rev 280459)
@@ -26,4 +26,5 @@
 [
     Conditional=APPLE_PAY,
 ] dictionary ApplePayShippingMethodUpdate : ApplePayDetailsUpdateBase {
+    [Conditional=APPLE_PAY_UPDATE_SHIPPING_METHODS_WHEN_CHANGING_LINE_ITEMS] sequence<ApplePayShippingMethod> newShippingMethods;
 };

Modified: trunk/Source/WebCore/Modules/applepay/paymentrequest/ApplePayModifier.h (280458 => 280459)


--- trunk/Source/WebCore/Modules/applepay/paymentrequest/ApplePayModifier.h	2021-07-30 00:14:37 UTC (rev 280458)
+++ trunk/Source/WebCore/Modules/applepay/paymentrequest/ApplePayModifier.h	2021-07-30 00:28:45 UTC (rev 280459)
@@ -41,7 +41,9 @@
     std::optional<ApplePayPaymentMethodType> paymentMethodType;
     std::optional<ApplePayLineItem> total;
     Vector<ApplePayLineItem> additionalLineItems;
+#if ENABLE(APPLE_PAY_UPDATE_SHIPPING_METHODS_WHEN_CHANGING_LINE_ITEMS)
     Vector<ApplePayShippingMethod> additionalShippingMethods;
+#endif
 
 #if defined(ApplePayModifierAdditions_members)
     ApplePayModifierAdditions_members

Modified: trunk/Source/WebCore/Modules/applepay/paymentrequest/ApplePayModifier.idl (280458 => 280459)


--- trunk/Source/WebCore/Modules/applepay/paymentrequest/ApplePayModifier.idl	2021-07-30 00:14:37 UTC (rev 280458)
+++ trunk/Source/WebCore/Modules/applepay/paymentrequest/ApplePayModifier.idl	2021-07-30 00:28:45 UTC (rev 280459)
@@ -29,5 +29,5 @@
     ApplePayPaymentMethodType paymentMethodType;
     ApplePayLineItem total;
     sequence<ApplePayLineItem> additionalLineItems;
-    sequence<ApplePayShippingMethod> additionalShippingMethods;
+    [Conditional=APPLE_PAY_UPDATE_SHIPPING_METHODS_WHEN_CHANGING_LINE_ITEMS] sequence<ApplePayShippingMethod> additionalShippingMethods;
 };

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


--- trunk/Source/WebCore/Modules/applepay/paymentrequest/ApplePayPaymentHandler.cpp	2021-07-30 00:14:37 UTC (rev 280458)
+++ trunk/Source/WebCore/Modules/applepay/paymentrequest/ApplePayPaymentHandler.cpp	2021-07-30 00:28:45 UTC (rev 280459)
@@ -306,11 +306,13 @@
         }
     }
 
+#if ENABLE(APPLE_PAY_UPDATE_SHIPPING_METHODS_WHEN_CHANGING_LINE_ITEMS)
     auto modifierException = firstApplicableModifier();
     if (modifierException.hasException())
         return modifierException.releaseException();
     if (auto modifierData = modifierException.releaseReturnValue())
         shippingOptions.appendVector(WTFMove(std::get<1>(*modifierData).additionalShippingMethods));
+#endif
 
     return WTFMove(shippingOptions);
 }
@@ -511,7 +513,7 @@
     case Reason::ShippingOptionChanged:
         return shippingOptionUpdated();
     case Reason::PaymentMethodChanged:
-        return paymentMethodUpdated(computeErrors(paymentMethodErrors));
+        return paymentMethodUpdated(computeErrors(WTFMove(error), WTFMove(addressErrors), WTFMove(payerErrors), paymentMethodErrors));
     }
 
     ASSERT_NOT_REACHED();
@@ -574,6 +576,13 @@
 
     ApplePayShippingMethodUpdate update;
 
+#if ENABLE(APPLE_PAY_UPDATE_SHIPPING_METHODS_WHEN_CHANGING_LINE_ITEMS)
+    auto newShippingMethods = computeShippingMethods();
+    if (newShippingMethods.hasException())
+        return newShippingMethods.releaseException();
+    update.newShippingMethods = newShippingMethods.releaseReturnValue();
+#endif
+
     auto newTotalAndLineItems = computeTotalAndLineItems();
     if (newTotalAndLineItems.hasException())
         return newTotalAndLineItems.releaseException();
@@ -617,8 +626,6 @@
         paymentCoordinator().completeCouponCodeChange(WTFMove(update));
         return { };
     }
-#else
-    UNUSED_PARAM(errors);
 #endif // ENABLE(APPLE_PAY_COUPON_CODE)
 
     ASSERT(m_updateState == UpdateState::PaymentMethod);
@@ -626,6 +633,17 @@
 
     ApplePayPaymentMethodUpdate update;
 
+#if ENABLE(APPLE_PAY_UPDATE_SHIPPING_METHODS_WHEN_CHANGING_LINE_ITEMS)
+    update.errors = WTFMove(errors);
+
+    auto newShippingMethods = computeShippingMethods();
+    if (newShippingMethods.hasException())
+        return newShippingMethods.releaseException();
+    update.newShippingMethods = newShippingMethods.releaseReturnValue();
+#else
+    UNUSED_PARAM(errors);
+#endif
+
     auto newTotalAndLineItems = computeTotalAndLineItems();
     if (newTotalAndLineItems.hasException())
         return newTotalAndLineItems.releaseException();

Modified: trunk/Source/WebCore/PAL/ChangeLog (280458 => 280459)


--- trunk/Source/WebCore/PAL/ChangeLog	2021-07-30 00:14:37 UTC (rev 280458)
+++ trunk/Source/WebCore/PAL/ChangeLog	2021-07-30 00:28:45 UTC (rev 280459)
@@ -1,3 +1,29 @@
+2021-07-29  Devin Rousso  <drou...@apple.com>
+
+        [Payment Request] `additionalShippingMethods` are not used if a `paymentMethodType` is provided
+        https://bugs.webkit.org/show_bug.cgi?id=228599
+        <rdar://problem/81190366>
+
+        Reviewed by Andy Estes.
+
+        r275169 made it so that `paymentMethodType` is no longer `required` so that `additionalShippingMethods`
+        can be specified without having to limit it to a specific payment method type. While this
+        works in theory, WebKit doesn't know about the user's selected payment method type until the
+        user actually selects a payment method, meaning that until then the `additionalShippingMethods`
+        are not used. Unfortunately (until now) `PKPaymentRequestPaymentMethodUpdate` did not
+        support providing a `NSArray<PKShippingMethod *> *`, so there was no way to update the list
+        of shipping methods when the user changed their selected payment method, meaning that WebKit
+        would have to wait/rely on the user to change their shipping address _after_ selecting a
+        payment method in order for `additionalShippingMethods` to take effect.
+
+        This also fixes an issue with WebKit's implementation of the W3C Payment Request API by
+        allowing any generic (i.e. things not specific to Apple Pay) `shippingOptions` provided in
+        `PaymentDetailsUpdate` to actually be used and update the Apple Pay sheet accordingly.
+
+        * pal/spi/cocoa/PassKitSPI.h:
+         - add the new `shippingMethods` property on `PKPaymentRequestUpdate`
+         - add the existing `errors` property on `PKPaymentRequestPaymentMethodUpdate`
+
 2021-07-29  Kate Cheney  <katherine_che...@apple.com>
 
         GetIdentifierStringForPreferredVoiceInListWithLocale() is deprecated in Monterey

Modified: trunk/Source/WebCore/PAL/pal/spi/cocoa/PassKitSPI.h (280458 => 280459)


--- trunk/Source/WebCore/PAL/pal/spi/cocoa/PassKitSPI.h	2021-07-30 00:14:37 UTC (rev 280458)
+++ trunk/Source/WebCore/PAL/pal/spi/cocoa/PassKitSPI.h	2021-07-30 00:28:45 UTC (rev 280459)
@@ -449,13 +449,14 @@
 @interface PKPaymentRequestUpdate : NSObject
 - (instancetype)initWithPaymentSummaryItems:(NSArray<PKPaymentSummaryItem *> *)paymentSummaryItems;
 @property (nonatomic, copy) NSArray<PKPaymentSummaryItem *> *paymentSummaryItems;
-#if HAVE(PASSKIT_COUPON_CODE)
+#if HAVE(PASSKIT_UPDATE_SHIPPING_METHODS_WHEN_CHANGING_SUMMARY_ITEMS)
 @property (nonatomic, copy) NSArray<PKShippingMethod *> *shippingMethods;
 #endif
-
 @end
 
 @interface PKPaymentRequestPaymentMethodUpdate : PKPaymentRequestUpdate
+- (instancetype)initWithErrors:(nullable NSArray<NSError *> *)errors paymentSummaryItems:(nonnull NSArray<PKPaymentSummaryItem *> *)summaryItems;
+@property (null_resettable, nonatomic, copy) NSArray<NSError *> *errors;
 @end
 
 @interface PKPaymentRequestShippingContactUpdate : PKPaymentRequestUpdate

Modified: trunk/Source/WebCore/testing/MockPaymentCoordinator.cpp (280458 => 280459)


--- trunk/Source/WebCore/testing/MockPaymentCoordinator.cpp	2021-07-30 00:14:37 UTC (rev 280458)
+++ trunk/Source/WebCore/testing/MockPaymentCoordinator.cpp	2021-07-30 00:28:45 UTC (rev 280459)
@@ -147,6 +147,9 @@
 
     m_total = WTFMove(shippingMethodUpdate->newTotal);
     m_lineItems = WTFMove(shippingMethodUpdate->newLineItems);
+#if ENABLE(APPLE_PAY_UPDATE_SHIPPING_METHODS_WHEN_CHANGING_LINE_ITEMS)
+    m_shippingMethods = WTFMove(shippingMethodUpdate->newShippingMethods);
+#endif
 #if defined(MockPaymentCoordinatorAdditions_completeShippingMethodSelection)
     MockPaymentCoordinatorAdditions_completeShippingMethodSelection
 #endif
@@ -169,8 +172,8 @@
 
     m_total = WTFMove(shippingContactUpdate->newTotal);
     m_lineItems = WTFMove(shippingContactUpdate->newLineItems);
+    m_shippingMethods = WTFMove(shippingContactUpdate->newShippingMethods);
     m_errors = convert(WTFMove(shippingContactUpdate->errors));
-    m_shippingMethods = WTFMove(shippingContactUpdate->newShippingMethods);
 #if defined(MockPaymentCoordinatorAdditions_completeShippingContactSelection)
     MockPaymentCoordinatorAdditions_completeShippingContactSelection
 #endif
@@ -183,6 +186,10 @@
 
     m_total = WTFMove(paymentMethodUpdate->newTotal);
     m_lineItems = WTFMove(paymentMethodUpdate->newLineItems);
+#if ENABLE(APPLE_PAY_UPDATE_SHIPPING_METHODS_WHEN_CHANGING_LINE_ITEMS)
+    m_shippingMethods = WTFMove(paymentMethodUpdate->newShippingMethods);
+    m_errors = convert(WTFMove(paymentMethodUpdate->errors));
+#endif
 #if defined(MockPaymentCoordinatorAdditions_completePaymentMethodSelection)
     MockPaymentCoordinatorAdditions_completePaymentMethodSelection
 #endif
@@ -197,8 +204,8 @@
 
     m_total = WTFMove(couponCodeUpdate->newTotal);
     m_lineItems = WTFMove(couponCodeUpdate->newLineItems);
+    m_shippingMethods = WTFMove(couponCodeUpdate->newShippingMethods);
     m_errors = convert(WTFMove(couponCodeUpdate->errors));
-    m_shippingMethods = WTFMove(couponCodeUpdate->newShippingMethods);
 #if defined(MockPaymentCoordinatorAdditions_completeCouponCodeChange)
     MockPaymentCoordinatorAdditions_completeCouponCodeChange
 #endif

Modified: trunk/Source/WebKit/ChangeLog (280458 => 280459)


--- trunk/Source/WebKit/ChangeLog	2021-07-30 00:14:37 UTC (rev 280458)
+++ trunk/Source/WebKit/ChangeLog	2021-07-30 00:28:45 UTC (rev 280459)
@@ -1,3 +1,30 @@
+2021-07-29  Devin Rousso  <drou...@apple.com>
+
+        [Payment Request] `additionalShippingMethods` are not used if a `paymentMethodType` is provided
+        https://bugs.webkit.org/show_bug.cgi?id=228599
+        <rdar://problem/81190366>
+
+        Reviewed by Andy Estes.
+
+        r275169 made it so that `paymentMethodType` is no longer `required` so that `additionalShippingMethods`
+        can be specified without having to limit it to a specific payment method type. While this
+        works in theory, WebKit doesn't know about the user's selected payment method type until the
+        user actually selects a payment method, meaning that until then the `additionalShippingMethods`
+        are not used. Unfortunately (until now) `PKPaymentRequestPaymentMethodUpdate` did not
+        support providing a `NSArray<PKShippingMethod *> *`, so there was no way to update the list
+        of shipping methods when the user changed their selected payment method, meaning that WebKit
+        would have to wait/rely on the user to change their shipping address _after_ selecting a
+        payment method in order for `additionalShippingMethods` to take effect.
+
+        This also fixes an issue with WebKit's implementation of the W3C Payment Request API by
+        allowing any generic (i.e. things not specific to Apple Pay) `shippingOptions` provided in
+        `PaymentDetailsUpdate` to actually be used and update the Apple Pay sheet accordingly.
+
+        * Platform/cocoa/PaymentAuthorizationPresenter.mm:
+        (WebKit::PaymentAuthorizationPresenter::completePaymentMethodSelection):
+        (WebKit::PaymentAuthorizationPresenter::completeShippingMethodSelection):
+        Also convert and set the `shippingMethods` on the update.
+
 2021-07-29  Kate Cheney  <katherine_che...@apple.com>
 
         REGRESSION (r278877) [Cocoa] WebAuthn stopped working for non-Safari browsers 

Modified: trunk/Source/WebKit/Platform/cocoa/PaymentAuthorizationPresenter.mm (280458 => 280459)


--- trunk/Source/WebKit/Platform/cocoa/PaymentAuthorizationPresenter.mm	2021-07-30 00:14:37 UTC (rev 280458)
+++ trunk/Source/WebKit/Platform/cocoa/PaymentAuthorizationPresenter.mm	2021-07-30 00:28:45 UTC (rev 280459)
@@ -217,6 +217,10 @@
     }
 
     auto paymentMethodUpdate = adoptNS([PAL::allocPKPaymentRequestPaymentMethodUpdateInstance() initWithPaymentSummaryItems:WebCore::platformSummaryItems(WTFMove(update->newTotal), WTFMove(update->newLineItems))]);
+#if HAVE(PASSKIT_UPDATE_SHIPPING_METHODS_WHEN_CHANGING_SUMMARY_ITEMS)
+    [paymentMethodUpdate setErrors:toNSErrors(WTFMove(update->errors)).get()];
+    [paymentMethodUpdate setShippingMethods:toPKShippingMethods(WTFMove(update->newShippingMethods)).get()];
+#endif
 #if HAVE(PASSKIT_INSTALLMENTS) && ENABLE(APPLE_PAY_INSTALLMENTS)
     [paymentMethodUpdate setInstallmentGroupIdentifier:WTFMove(update->installmentGroupIdentifier)];
 #endif // HAVE(PASSKIT_INSTALLMENTS) && ENABLE(APPLE_PAY_INSTALLMENTS)
@@ -260,6 +264,9 @@
     }
 
     auto shippingMethodUpdate = adoptNS([PAL::allocPKPaymentRequestShippingMethodUpdateInstance() initWithPaymentSummaryItems:WebCore::platformSummaryItems(WTFMove(update->newTotal), WTFMove(update->newLineItems))]);
+#if HAVE(PASSKIT_UPDATE_SHIPPING_METHODS_WHEN_CHANGING_SUMMARY_ITEMS)
+    [shippingMethodUpdate setShippingMethods:toPKShippingMethods(WTFMove(update->newShippingMethods)).get()];
+#endif
 #if defined(PaymentAuthorizationPresenterAdditions_completeShippingMethodSelection)
     PaymentAuthorizationPresenterAdditions_completeShippingMethodSelection
 #endif
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to