38241b7d0e649199ee37a3faf5d1e8b013fa8eb0
[WebKit-https.git] / Source / WebCore / testing / MockPaymentCoordinator.cpp
1 /*
2  * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "MockPaymentCoordinator.h"
28
29 #if ENABLE(APPLE_PAY)
30
31 #include "ApplePaySessionPaymentRequest.h"
32 #include "MockPayment.h"
33 #include "MockPaymentContact.h"
34 #include "MockPaymentMethod.h"
35 #include "Page.h"
36 #include "PaymentCoordinator.h"
37 #include <wtf/RunLoop.h>
38 #include <wtf/URL.h>
39
40 namespace WebCore {
41
42 MockPaymentCoordinator::MockPaymentCoordinator(Page& page)
43     : m_page { page }
44 {
45     m_availablePaymentNetworks.add("amex");
46     m_availablePaymentNetworks.add("carteBancaire");
47     m_availablePaymentNetworks.add("chinaUnionPay");
48     m_availablePaymentNetworks.add("discover");
49     m_availablePaymentNetworks.add("interac");
50     m_availablePaymentNetworks.add("jcb");
51     m_availablePaymentNetworks.add("masterCard");
52     m_availablePaymentNetworks.add("privateLabel");
53     m_availablePaymentNetworks.add("visa");
54 }
55
56 bool MockPaymentCoordinator::supportsVersion(unsigned version)
57 {
58     ASSERT(version > 0);
59
60 #if !ENABLE(APPLE_PAY_SESSION_V3)
61     static const unsigned currentVersion = 2;
62 #elif !ENABLE(APPLE_PAY_SESSION_V4)
63     static const unsigned currentVersion = 3;
64 #else
65     static const unsigned currentVersion = 5;
66 #endif
67
68     return version <= currentVersion;
69 }
70
71 Optional<String> MockPaymentCoordinator::validatedPaymentNetwork(const String& paymentNetwork)
72 {
73     auto result = m_availablePaymentNetworks.find(paymentNetwork);
74     if (result == m_availablePaymentNetworks.end())
75         return WTF::nullopt;
76     return *result;
77 }
78
79 bool MockPaymentCoordinator::canMakePayments()
80 {
81     return m_canMakePayments;
82 }
83
84 void MockPaymentCoordinator::canMakePaymentsWithActiveCard(const String&, const String&, Function<void(bool)>&& completionHandler)
85 {
86     RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler), canMakePaymentsWithActiveCard = m_canMakePaymentsWithActiveCard] {
87         completionHandler(canMakePaymentsWithActiveCard);
88     });
89 }
90
91 void MockPaymentCoordinator::openPaymentSetup(const String&, const String&, Function<void(bool)>&& completionHandler)
92 {
93     RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler)] {
94         completionHandler(true);
95     });
96 }
97
98 static uint64_t showCount;
99 static uint64_t hideCount;
100
101 static void dispatchIfShowing(Function<void()>&& function)
102 {
103     ASSERT(showCount > hideCount);
104     RunLoop::main().dispatch([currentShowCount = showCount, function = WTFMove(function)]() {
105         if (showCount > hideCount && showCount == currentShowCount)
106             function();
107     });
108 }
109
110 static Vector<ApplePayShippingMethod> convert(const Vector<ApplePaySessionPaymentRequest::ShippingMethod>& shippingMethods)
111 {
112     return WTF::map(shippingMethods, [] (auto& shippingMethod) {
113         return ApplePayShippingMethod { shippingMethod.label, shippingMethod.detail, shippingMethod.amount, shippingMethod.identifier };
114     });
115 }
116
117 bool MockPaymentCoordinator::showPaymentUI(const URL&, const Vector<URL>&, const ApplePaySessionPaymentRequest& request)
118 {
119     if (request.shippingContact().pkContact())
120         m_shippingAddress = request.shippingContact().toApplePayPaymentContact(request.version());
121     m_shippingMethods = convert(request.shippingMethods());
122
123     ASSERT(showCount == hideCount);
124     ++showCount;
125     dispatchIfShowing([page = &m_page]() {
126         page->paymentCoordinator().validateMerchant({ URL(), "https://webkit.org/"_s });
127     });
128     return true;
129 }
130
131 void MockPaymentCoordinator::completeMerchantValidation(const PaymentMerchantSession&)
132 {
133     dispatchIfShowing([page = &m_page, shippingAddress = m_shippingAddress]() mutable {
134         page->paymentCoordinator().didSelectShippingContact(MockPaymentContact { WTFMove(shippingAddress) });
135     });
136 }
137
138 static ApplePayLineItem convert(const ApplePaySessionPaymentRequest::LineItem& lineItem)
139 {
140     ApplePayLineItem result;
141     result.type = lineItem.type;
142     result.label = lineItem.label;
143     result.amount = lineItem.amount;
144     return result;
145 }
146
147 void MockPaymentCoordinator::updateTotalAndLineItems(const ApplePaySessionPaymentRequest::TotalAndLineItems& totalAndLineItems)
148 {
149     m_total = convert(totalAndLineItems.total);
150     m_lineItems.clear();
151     for (auto& lineItem : totalAndLineItems.lineItems)
152         m_lineItems.append(convert(lineItem));
153 }
154
155 void MockPaymentCoordinator::completeShippingMethodSelection(Optional<ShippingMethodUpdate>&& shippingMethodUpdate)
156 {
157     if (shippingMethodUpdate)
158         updateTotalAndLineItems(shippingMethodUpdate->newTotalAndLineItems);
159 }
160
161 void MockPaymentCoordinator::completeShippingContactSelection(Optional<ShippingContactUpdate>&& shippingContactUpdate)
162 {
163     if (!shippingContactUpdate)
164         return;
165
166     m_shippingMethods = convert(shippingContactUpdate->newShippingMethods);
167     updateTotalAndLineItems(shippingContactUpdate->newTotalAndLineItems);
168     m_errors = WTFMove(shippingContactUpdate->errors);
169 }
170
171 void MockPaymentCoordinator::completePaymentMethodSelection(Optional<PaymentMethodUpdate>&& paymentMethodUpdate)
172 {
173     if (paymentMethodUpdate)
174         updateTotalAndLineItems(paymentMethodUpdate->newTotalAndLineItems);
175 }
176
177 void MockPaymentCoordinator::changeShippingOption(String&& shippingOption)
178 {
179     dispatchIfShowing([page = &m_page, shippingOption = WTFMove(shippingOption)]() mutable {
180         ApplePaySessionPaymentRequest::ShippingMethod shippingMethod;
181         shippingMethod.identifier = WTFMove(shippingOption);
182         page->paymentCoordinator().didSelectShippingMethod(shippingMethod);
183     });
184 }
185
186 void MockPaymentCoordinator::changePaymentMethod(ApplePayPaymentMethod&& paymentMethod)
187 {
188     dispatchIfShowing([page = &m_page, paymentMethod = WTFMove(paymentMethod)]() mutable {
189         page->paymentCoordinator().didSelectPaymentMethod(MockPaymentMethod { WTFMove(paymentMethod) });
190     });
191 }
192
193 void MockPaymentCoordinator::acceptPayment()
194 {
195     dispatchIfShowing([page = &m_page, shippingAddress = m_shippingAddress]() mutable {
196         ApplePayPayment payment;
197         payment.shippingContact = WTFMove(shippingAddress);
198         page->paymentCoordinator().didAuthorizePayment(MockPayment { WTFMove(payment) });
199     });
200 }
201
202 void MockPaymentCoordinator::cancelPayment()
203 {
204     dispatchIfShowing([page = &m_page] {
205         page->paymentCoordinator().didCancelPaymentSession();
206         ++hideCount;
207         ASSERT(showCount == hideCount);
208     });
209 }
210
211 void MockPaymentCoordinator::completePaymentSession(Optional<PaymentAuthorizationResult>&& result)
212 {
213     auto isFinalState = isFinalStateResult(result);
214     m_errors = WTFMove(result->errors);
215
216     if (!isFinalState)
217         return;
218
219     ++hideCount;
220     ASSERT(showCount == hideCount);
221 }
222
223 void MockPaymentCoordinator::abortPaymentSession()
224 {
225     ++hideCount;
226     ASSERT(showCount == hideCount);
227 }
228
229 void MockPaymentCoordinator::cancelPaymentSession()
230 {
231     ++hideCount;
232     ASSERT(showCount == hideCount);
233 }
234
235 void MockPaymentCoordinator::paymentCoordinatorDestroyed()
236 {
237     ASSERT(showCount == hideCount);
238     delete this;
239 }
240
241 } // namespace WebCore
242
243 #endif // ENABLE(APPLE_PAY)