Move URL from WebCore to WTF
[WebKit-https.git] / Source / WebKit / UIProcess / ApplePay / WebPaymentCoordinatorProxy.cpp
1 /*
2  * Copyright (C) 2015-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 "WebPaymentCoordinatorProxy.h"
28
29 #if ENABLE(APPLE_PAY)
30
31 #include "WebPageProxy.h"
32 #include "WebPaymentCoordinatorMessages.h"
33 #include "WebPaymentCoordinatorProxyMessages.h"
34 #include "WebProcessProxy.h"
35 #include <WebCore/PaymentAuthorizationStatus.h>
36
37 namespace WebKit {
38
39 static WebPaymentCoordinatorProxy* activePaymentCoordinatorProxy;
40
41 WebPaymentCoordinatorProxy::WebPaymentCoordinatorProxy(WebPageProxy& webPageProxy)
42     : m_webPageProxy(webPageProxy)
43     , m_state(State::Idle)
44     , m_merchantValidationState(MerchantValidationState::Idle)
45 {
46     m_webPageProxy.process().addMessageReceiver(Messages::WebPaymentCoordinatorProxy::messageReceiverName(), m_webPageProxy.pageID(), *this);
47     finishConstruction(*this);
48 }
49
50 WebPaymentCoordinatorProxy::~WebPaymentCoordinatorProxy()
51 {
52     if (activePaymentCoordinatorProxy == this)
53         activePaymentCoordinatorProxy = nullptr;
54
55     if (m_state != State::Idle)
56         hidePaymentUI();
57
58     m_webPageProxy.process().removeMessageReceiver(Messages::WebPaymentCoordinatorProxy::messageReceiverName(), m_webPageProxy.pageID());
59 }
60
61 void WebPaymentCoordinatorProxy::availablePaymentNetworks(Vector<String>& networks)
62 {
63     networks = platformAvailablePaymentNetworks();
64 }
65
66 void WebPaymentCoordinatorProxy::canMakePayments(bool& reply)
67 {
68     reply = platformCanMakePayments();
69 }
70
71 void WebPaymentCoordinatorProxy::canMakePaymentsWithActiveCard(const String& merchantIdentifier, const String& domainName, uint64_t requestID)
72 {
73     auto weakThis = makeWeakPtr(*this);
74     platformCanMakePaymentsWithActiveCard(merchantIdentifier, domainName, [weakThis, requestID](bool canMakePayments) {
75         auto paymentCoordinatorProxy = weakThis.get();
76         if (!paymentCoordinatorProxy)
77             return;
78
79         paymentCoordinatorProxy->m_webPageProxy.send(Messages::WebPaymentCoordinator::CanMakePaymentsWithActiveCardReply(requestID, canMakePayments));
80     });
81 }
82
83 void WebPaymentCoordinatorProxy::openPaymentSetup(const String& merchantIdentifier, const String& domainName, uint64_t requestID)
84 {
85     auto weakThis = makeWeakPtr(*this);
86     platformOpenPaymentSetup(merchantIdentifier, domainName, [weakThis, requestID](bool result) {
87         auto paymentCoordinatorProxy = weakThis.get();
88         if (!paymentCoordinatorProxy)
89             return;
90
91         paymentCoordinatorProxy->m_webPageProxy.send(Messages::WebPaymentCoordinator::OpenPaymentSetupReply(requestID, result));
92     });
93 }
94
95 void WebPaymentCoordinatorProxy::showPaymentUI(const String& originatingURLString, const Vector<String>& linkIconURLStrings, const WebCore::ApplePaySessionPaymentRequest& paymentRequest, bool& result)
96 {
97     // FIXME: Make this a message check.
98     ASSERT(canBegin());
99
100     if (activePaymentCoordinatorProxy) {
101         activePaymentCoordinatorProxy->hidePaymentUI();
102         activePaymentCoordinatorProxy->didCancelPaymentSession();
103     }
104
105     activePaymentCoordinatorProxy = this;
106
107     m_state = State::Activating;
108
109     URL originatingURL(URL(), originatingURLString);
110
111     Vector<URL> linkIconURLs;
112     for (const auto& linkIconURLString : linkIconURLStrings)
113         linkIconURLs.append(URL(URL(), linkIconURLString));
114
115     platformShowPaymentUI(originatingURL, linkIconURLs, paymentRequest, [this](bool result) {
116         ASSERT(m_state == State::Activating);
117         if (!result) {
118             didCancelPaymentSession();
119             return;
120         }
121
122         m_state = State::Active;
123     });
124
125     result = true;
126 }
127
128     
129 void WebPaymentCoordinatorProxy::completeMerchantValidation(const WebCore::PaymentMerchantSession& paymentMerchantSession)
130 {
131     // It's possible that the payment has been canceled already.
132     if (m_state == State::Idle)
133         return;
134
135     // FIXME: This should be a MESSAGE_CHECK.
136     ASSERT(m_merchantValidationState == MerchantValidationState::Validating);
137
138     platformCompleteMerchantValidation(paymentMerchantSession);
139     m_merchantValidationState = MerchantValidationState::ValidationComplete;
140 }
141
142 void WebPaymentCoordinatorProxy::completeShippingMethodSelection(const std::optional<WebCore::ShippingMethodUpdate>& update)
143 {
144     // It's possible that the payment has been canceled already.
145     if (m_state == State::Idle)
146         return;
147
148     // FIXME: This should be a MESSAGE_CHECK.
149     ASSERT(m_state == State::ShippingMethodSelected);
150
151     platformCompleteShippingMethodSelection(update);
152     m_state = State::Active;
153 }
154
155 void WebPaymentCoordinatorProxy::completeShippingContactSelection(const std::optional<WebCore::ShippingContactUpdate>& update)
156 {
157     // It's possible that the payment has been canceled already.
158     if (m_state == State::Idle)
159         return;
160
161     // FIXME: This should be a MESSAGE_CHECK.
162     ASSERT(m_state == State::ShippingContactSelected);
163
164     platformCompleteShippingContactSelection(update);
165     m_state = State::Active;
166 }
167
168 void WebPaymentCoordinatorProxy::completePaymentMethodSelection(const std::optional<WebCore::PaymentMethodUpdate>& update)
169 {
170     // It's possible that the payment has been canceled already.
171     if (m_state == State::Idle)
172         return;
173
174     // FIXME: This should be a MESSAGE_CHECK.
175     ASSERT(m_state == State::PaymentMethodSelected);
176
177     platformCompletePaymentMethodSelection(update);
178     m_state = State::Active;
179 }
180
181 void WebPaymentCoordinatorProxy::completePaymentSession(const std::optional<WebCore::PaymentAuthorizationResult>& result)
182 {
183     // It's possible that the payment has been canceled already.
184     if (!canCompletePayment())
185         return;
186
187     bool isFinalStateResult = WebCore::isFinalStateResult(result);
188
189     platformCompletePaymentSession(result);
190
191     if (!isFinalStateResult) {
192         m_state = State::Active;
193         return;
194     }
195
196     didReachFinalState();
197 }
198
199 void WebPaymentCoordinatorProxy::abortPaymentSession()
200 {
201     // It's possible that the payment has been canceled already.
202     if (!canAbort())
203         return;
204
205     hidePaymentUI();
206
207     didReachFinalState();
208 }
209
210 void WebPaymentCoordinatorProxy::cancelPaymentSession()
211 {
212     if (!canCancel())
213         return;
214
215     hidePaymentUI();
216     didCancelPaymentSession();
217 }
218
219 void WebPaymentCoordinatorProxy::didCancelPaymentSession()
220 {
221     ASSERT(canCancel());
222
223     m_webPageProxy.send(Messages::WebPaymentCoordinator::DidCancelPaymentSession());
224
225     didReachFinalState();
226 }
227
228 void WebPaymentCoordinatorProxy::validateMerchant(const URL& url)
229 {
230     ASSERT(m_merchantValidationState == MerchantValidationState::Idle);
231
232     m_merchantValidationState = MerchantValidationState::Validating;
233     m_webPageProxy.send(Messages::WebPaymentCoordinator::ValidateMerchant(url.string()));
234 }
235
236 void WebPaymentCoordinatorProxy::didAuthorizePayment(const WebCore::Payment& payment)
237 {
238     m_state = State::Authorized;
239     m_webPageProxy.send(Messages::WebPaymentCoordinator::DidAuthorizePayment(payment));
240 }
241
242 void WebPaymentCoordinatorProxy::didSelectShippingMethod(const WebCore::ApplePaySessionPaymentRequest::ShippingMethod& shippingMethod)
243 {
244     ASSERT(m_state == State::Active);
245
246     m_state = State::ShippingMethodSelected;
247     m_webPageProxy.send(Messages::WebPaymentCoordinator::DidSelectShippingMethod(shippingMethod));
248 }
249
250 void WebPaymentCoordinatorProxy::didSelectShippingContact(const WebCore::PaymentContact& shippingContact)
251 {
252     ASSERT(m_state == State::Active);
253
254     m_state = State::ShippingContactSelected;
255     m_webPageProxy.send(Messages::WebPaymentCoordinator::DidSelectShippingContact(shippingContact));
256 }
257
258 void WebPaymentCoordinatorProxy::didSelectPaymentMethod(const WebCore::PaymentMethod& paymentMethod)
259 {
260     ASSERT(m_state == State::Active);
261
262     m_state = State::PaymentMethodSelected;
263     m_webPageProxy.send(Messages::WebPaymentCoordinator::DidSelectPaymentMethod(paymentMethod));
264 }
265
266 bool WebPaymentCoordinatorProxy::canBegin() const
267 {
268     switch (m_state) {
269     case State::Idle:
270         return true;
271
272     case State::Activating:
273     case State::Active:
274     case State::Authorized:
275     case State::ShippingMethodSelected:
276     case State::ShippingContactSelected:
277     case State::PaymentMethodSelected:
278         return false;
279     }
280 }
281
282 bool WebPaymentCoordinatorProxy::canCancel() const
283 {
284     switch (m_state) {
285     case State::Activating:
286     case State::Active:
287     case State::Authorized:
288     case State::ShippingMethodSelected:
289     case State::ShippingContactSelected:
290     case State::PaymentMethodSelected:
291         return true;
292
293     case State::Idle:
294         return false;
295     }
296 }
297
298 bool WebPaymentCoordinatorProxy::canCompletePayment() const
299 {
300     switch (m_state) {
301     case State::Authorized:
302         return true;
303
304     case State::Idle:
305     case State::Activating:
306     case State::Active:
307     case State::ShippingMethodSelected:
308     case State::ShippingContactSelected:
309     case State::PaymentMethodSelected:
310         return false;
311     }
312 }
313
314 bool WebPaymentCoordinatorProxy::canAbort() const
315 {
316     switch (m_state) {
317     case State::Activating:
318     case State::Active:
319     case State::Authorized:
320     case State::ShippingMethodSelected:
321     case State::ShippingContactSelected:
322     case State::PaymentMethodSelected:
323         return true;
324
325     case State::Idle:
326         return false;
327     }
328 }
329
330 void WebPaymentCoordinatorProxy::didReachFinalState()
331 {
332     m_state = State::Idle;
333     m_merchantValidationState = MerchantValidationState::Idle;
334
335     ASSERT(activePaymentCoordinatorProxy == this);
336     activePaymentCoordinatorProxy = nullptr;
337 }
338
339 }
340
341 #endif