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 "PaymentResponse.h"
28
29#if ENABLE(PAYMENT_REQUEST)
30
31#include "NotImplemented.h"
32#include "PaymentRequest.h"
33#include <wtf/IsoMallocInlines.h>
34#include <wtf/RunLoop.h>
35
36namespace WebCore {
37
38WTF_MAKE_ISO_ALLOCATED_IMPL(PaymentResponse);
39
40PaymentResponse::PaymentResponse(ScriptExecutionContext* context, PaymentRequest& request)
41 : ActiveDOMObject { context }
42 , m_request { makeWeakPtr(request) }
43{
44 suspendIfNeeded();
45}
46
47void PaymentResponse::finishConstruction()
48{
49 ASSERT(!hasPendingActivity());
50 m_pendingActivity = makePendingActivity(*this);
51}
52
53PaymentResponse::~PaymentResponse()
54{
55 ASSERT(!hasPendingActivity());
56 ASSERT(!hasRetryPromise());
57}
58
59void PaymentResponse::setDetailsFunction(DetailsFunction&& detailsFunction)
60{
61 m_detailsFunction = WTFMove(detailsFunction);
62 m_cachedDetails = { };
63}
64
65void PaymentResponse::complete(Optional<PaymentComplete>&& result, DOMPromiseDeferred<void>&& promise)
66{
67 if (m_state == State::Stopped || !m_request) {
68 promise.reject(Exception { AbortError });
69 return;
70 }
71
72 if (m_state == State::Completed || m_retryPromise) {
73 promise.reject(Exception { InvalidStateError });
74 return;
75 }
76
77 ASSERT(hasPendingActivity());
78 ASSERT(m_state == State::Created);
79 m_pendingActivity = nullptr;
80 m_state = State::Completed;
81
82 promise.settle(m_request->complete(WTFMove(result)));
83}
84
85void PaymentResponse::retry(PaymentValidationErrors&& errors, DOMPromiseDeferred<void>&& promise)
86{
87 if (m_state == State::Stopped || !m_request) {
88 promise.reject(Exception { AbortError });
89 return;
90 }
91
92 if (m_state == State::Completed || m_retryPromise) {
93 promise.reject(Exception { InvalidStateError });
94 return;
95 }
96
97 ASSERT(hasPendingActivity());
98 ASSERT(m_state == State::Created);
99
100 auto exception = m_request->retry(WTFMove(errors));
101 if (exception.hasException()) {
102 promise.reject(exception.releaseException());
103 return;
104 }
105
106 m_retryPromise = WTFMove(promise);
107}
108
109void PaymentResponse::abortWithException(Exception&& exception)
110{
111 settleRetryPromise(WTFMove(exception));
112 m_pendingActivity = nullptr;
113 m_state = State::Completed;
114}
115
116void PaymentResponse::settleRetryPromise(ExceptionOr<void>&& result)
117{
118 if (!m_retryPromise)
119 return;
120
121 ASSERT(hasPendingActivity());
122 ASSERT(m_state == State::Created);
123 std::exchange(m_retryPromise, WTF::nullopt)->settle(WTFMove(result));
124}
125
126bool PaymentResponse::canSuspendForDocumentSuspension() const
127{
128 ASSERT(m_state != State::Stopped);
129 return !hasPendingActivity();
130}
131
132void PaymentResponse::stop()
133{
134 settleRetryPromise(Exception { AbortError });
135 m_pendingActivity = nullptr;
136 m_state = State::Stopped;
137}
138
139} // namespace WebCore
140
141#endif // ENABLE(PAYMENT_REQUEST)
142