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