/src/mozilla-central/dom/payments/PaymentRequestService.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #include "mozilla/ClearOnShutdown.h" |
8 | | #include "mozilla/dom/PaymentRequestParent.h" |
9 | | #include "PaymentRequestService.h" |
10 | | #include "BasicCardPayment.h" |
11 | | #include "nsSimpleEnumerator.h" |
12 | | |
13 | | namespace mozilla { |
14 | | namespace dom { |
15 | | |
16 | | StaticRefPtr<PaymentRequestService> gPaymentService; |
17 | | |
18 | | namespace { |
19 | | |
20 | | class PaymentRequestEnumerator final : public nsSimpleEnumerator |
21 | | { |
22 | | public: |
23 | | NS_DECL_NSISIMPLEENUMERATOR |
24 | | |
25 | | PaymentRequestEnumerator() |
26 | | : mIndex(0) |
27 | 0 | {} |
28 | | |
29 | | const nsID& DefaultInterface() override |
30 | 0 | { |
31 | 0 | return NS_GET_IID(nsIPaymentRequest); |
32 | 0 | } |
33 | | |
34 | | private: |
35 | | ~PaymentRequestEnumerator() override = default; |
36 | | uint32_t mIndex; |
37 | | }; |
38 | | |
39 | | NS_IMETHODIMP |
40 | | PaymentRequestEnumerator::HasMoreElements(bool* aReturn) |
41 | 0 | { |
42 | 0 | NS_ENSURE_ARG_POINTER(aReturn); |
43 | 0 | *aReturn = false; |
44 | 0 | if (NS_WARN_IF(!gPaymentService)) { |
45 | 0 | return NS_ERROR_FAILURE; |
46 | 0 | } |
47 | 0 | RefPtr<PaymentRequestService> service = gPaymentService; |
48 | 0 | *aReturn = mIndex < service->NumPayments(); |
49 | 0 | return NS_OK; |
50 | 0 | } |
51 | | |
52 | | NS_IMETHODIMP |
53 | | PaymentRequestEnumerator::GetNext(nsISupports** aItem) |
54 | 0 | { |
55 | 0 | NS_ENSURE_ARG_POINTER(aItem); |
56 | 0 | if (NS_WARN_IF(!gPaymentService)) { |
57 | 0 | return NS_ERROR_FAILURE; |
58 | 0 | } |
59 | 0 | RefPtr<payments::PaymentRequest> rowRequest = |
60 | 0 | gPaymentService->GetPaymentRequestByIndex(mIndex); |
61 | 0 | if (!rowRequest) { |
62 | 0 | return NS_ERROR_FAILURE; |
63 | 0 | } |
64 | 0 | nsCOMPtr<nsIPaymentRequest> request = do_QueryInterface(rowRequest); |
65 | 0 | mIndex++; |
66 | 0 | request.forget(aItem); |
67 | 0 | return NS_OK; |
68 | 0 | } |
69 | | |
70 | | } // end of anonymous namespace |
71 | | |
72 | | /* PaymentRequestService */ |
73 | | |
74 | | NS_IMPL_ISUPPORTS(PaymentRequestService, |
75 | | nsIPaymentRequestService) |
76 | | |
77 | | already_AddRefed<PaymentRequestService> |
78 | | PaymentRequestService::GetSingleton() |
79 | 0 | { |
80 | 0 | MOZ_ASSERT(NS_IsMainThread()); |
81 | 0 | if (!gPaymentService) { |
82 | 0 | gPaymentService = new PaymentRequestService(); |
83 | 0 | ClearOnShutdown(&gPaymentService); |
84 | 0 | } |
85 | 0 | RefPtr<PaymentRequestService> service = gPaymentService; |
86 | 0 | return service.forget(); |
87 | 0 | } |
88 | | |
89 | | uint32_t |
90 | | PaymentRequestService::NumPayments() const |
91 | 0 | { |
92 | 0 | return mRequestQueue.Length(); |
93 | 0 | } |
94 | | |
95 | | already_AddRefed<payments::PaymentRequest> |
96 | | PaymentRequestService::GetPaymentRequestByIndex(const uint32_t aIndex) |
97 | 0 | { |
98 | 0 | if (aIndex >= mRequestQueue.Length()) { |
99 | 0 | return nullptr; |
100 | 0 | } |
101 | 0 | RefPtr<payments::PaymentRequest> request = mRequestQueue[aIndex]; |
102 | 0 | MOZ_ASSERT(request); |
103 | 0 | return request.forget(); |
104 | 0 | } |
105 | | |
106 | | NS_IMETHODIMP |
107 | | PaymentRequestService::GetPaymentRequestById(const nsAString& aRequestId, |
108 | | nsIPaymentRequest** aRequest) |
109 | 0 | { |
110 | 0 | NS_ENSURE_ARG_POINTER(aRequest); |
111 | 0 | *aRequest = nullptr; |
112 | 0 | RefPtr<payments::PaymentRequest> rowRequest; |
113 | 0 | nsresult rv = GetPaymentRequestById(aRequestId, getter_AddRefs(rowRequest)); |
114 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
115 | 0 | return rv; |
116 | 0 | } |
117 | 0 | nsCOMPtr<nsIPaymentRequest> request = do_QueryInterface(rowRequest); |
118 | 0 | request.forget(aRequest); |
119 | 0 | return NS_OK; |
120 | 0 | } |
121 | | |
122 | | nsresult |
123 | | PaymentRequestService::GetPaymentRequestById(const nsAString& aRequestId, |
124 | | payments::PaymentRequest** aRequest) |
125 | 0 | { |
126 | 0 | NS_ENSURE_ARG_POINTER(aRequest); |
127 | 0 | *aRequest = nullptr; |
128 | 0 | uint32_t numRequests = mRequestQueue.Length(); |
129 | 0 | for (uint32_t index = 0; index < numRequests; ++index) { |
130 | 0 | RefPtr<payments::PaymentRequest> request = mRequestQueue[index]; |
131 | 0 | MOZ_ASSERT(request); |
132 | 0 | nsAutoString requestId; |
133 | 0 | nsresult rv = request->GetRequestId(requestId); |
134 | 0 | NS_ENSURE_SUCCESS(rv, rv); |
135 | 0 | if (requestId == aRequestId) { |
136 | 0 | request.forget(aRequest); |
137 | 0 | break; |
138 | 0 | } |
139 | 0 | } |
140 | 0 | return NS_OK; |
141 | 0 | } |
142 | | |
143 | | NS_IMETHODIMP |
144 | | PaymentRequestService::Enumerate(nsISimpleEnumerator** aEnumerator) |
145 | 0 | { |
146 | 0 | NS_ENSURE_ARG_POINTER(aEnumerator); |
147 | 0 | nsCOMPtr<nsISimpleEnumerator> enumerator = new PaymentRequestEnumerator(); |
148 | 0 | enumerator.forget(aEnumerator); |
149 | 0 | return NS_OK; |
150 | 0 | } |
151 | | |
152 | | NS_IMETHODIMP |
153 | | PaymentRequestService::Cleanup() |
154 | 0 | { |
155 | 0 | mRequestQueue.Clear(); |
156 | 0 | return NS_OK; |
157 | 0 | } |
158 | | |
159 | | NS_IMETHODIMP |
160 | | PaymentRequestService::SetTestingUIService(nsIPaymentUIService* aUIService) |
161 | 0 | { |
162 | 0 | // aUIService can be nullptr |
163 | 0 | mTestingUIService = aUIService; |
164 | 0 | return NS_OK; |
165 | 0 | } |
166 | | |
167 | | nsresult |
168 | | PaymentRequestService::LaunchUIAction(const nsAString& aRequestId, uint32_t aActionType) |
169 | 0 | { |
170 | 0 | nsCOMPtr<nsIPaymentUIService> uiService; |
171 | 0 | nsresult rv; |
172 | 0 | if (mTestingUIService) { |
173 | 0 | uiService = mTestingUIService; |
174 | 0 | } else { |
175 | 0 | uiService = do_GetService(NS_PAYMENT_UI_SERVICE_CONTRACT_ID, &rv); |
176 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
177 | 0 | return rv; |
178 | 0 | } |
179 | 0 | } |
180 | 0 | switch (aActionType) { |
181 | 0 | case IPCPaymentActionRequest::TIPCPaymentShowActionRequest:{ |
182 | 0 | rv = uiService->ShowPayment(aRequestId); |
183 | 0 | break; |
184 | 0 | } |
185 | 0 | case IPCPaymentActionRequest::TIPCPaymentAbortActionRequest: { |
186 | 0 | rv = uiService->AbortPayment(aRequestId); |
187 | 0 | break; |
188 | 0 | } |
189 | 0 | case IPCPaymentActionRequest::TIPCPaymentCompleteActionRequest: { |
190 | 0 | rv = uiService->CompletePayment(aRequestId); |
191 | 0 | break; |
192 | 0 | } |
193 | 0 | case IPCPaymentActionRequest::TIPCPaymentUpdateActionRequest: { |
194 | 0 | rv = uiService->UpdatePayment(aRequestId); |
195 | 0 | break; |
196 | 0 | } |
197 | 0 | case IPCPaymentActionRequest::TIPCPaymentCloseActionRequest: { |
198 | 0 | rv = uiService->ClosePayment(aRequestId); |
199 | 0 | break; |
200 | 0 | } |
201 | 0 | default : { |
202 | 0 | return NS_ERROR_FAILURE; |
203 | 0 | } |
204 | 0 | } |
205 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
206 | 0 | return rv; |
207 | 0 | } |
208 | 0 | return NS_OK; |
209 | 0 | } |
210 | | |
211 | | nsresult |
212 | | PaymentRequestService::RequestPayment(const nsAString& aRequestId, |
213 | | const IPCPaymentActionRequest& aAction, |
214 | | PaymentRequestParent* aIPC) |
215 | 0 | { |
216 | 0 | NS_ENSURE_ARG_POINTER(aIPC); |
217 | 0 |
|
218 | 0 | nsresult rv = NS_OK; |
219 | 0 | uint32_t type = aAction.type(); |
220 | 0 |
|
221 | 0 | RefPtr<payments::PaymentRequest> request; |
222 | 0 | if (type != IPCPaymentActionRequest::TIPCPaymentCreateActionRequest) { |
223 | 0 | rv = GetPaymentRequestById(aRequestId, getter_AddRefs(request)); |
224 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
225 | 0 | return rv; |
226 | 0 | } |
227 | 0 | if (!request && type != IPCPaymentActionRequest::TIPCPaymentCloseActionRequest) { |
228 | 0 | return NS_ERROR_FAILURE; |
229 | 0 | } |
230 | 0 | if (request) { |
231 | 0 | request->SetIPC(aIPC); |
232 | 0 | } |
233 | 0 | } |
234 | 0 |
|
235 | 0 | switch (type) { |
236 | 0 | case IPCPaymentActionRequest::TIPCPaymentCreateActionRequest: { |
237 | 0 | MOZ_ASSERT(!request); |
238 | 0 | const IPCPaymentCreateActionRequest& action = aAction; |
239 | 0 | uint64_t tabId = aIPC->GetTabId(); |
240 | 0 | nsCOMPtr<nsIMutableArray> methodData = do_CreateInstance(NS_ARRAY_CONTRACTID); |
241 | 0 | MOZ_ASSERT(methodData); |
242 | 0 | for (IPCPaymentMethodData data : action.methodData()) { |
243 | 0 | nsCOMPtr<nsIPaymentMethodData> method; |
244 | 0 | rv = payments::PaymentMethodData::Create(data, getter_AddRefs(method)); |
245 | 0 | NS_ENSURE_SUCCESS(rv, rv); |
246 | 0 | rv = methodData->AppendElement(method); |
247 | 0 | NS_ENSURE_SUCCESS(rv, rv); |
248 | 0 | } |
249 | 0 | nsCOMPtr<nsIPaymentDetails> details; |
250 | 0 | rv = payments::PaymentDetails::Create(action.details(), getter_AddRefs(details)); |
251 | 0 | NS_ENSURE_SUCCESS(rv, rv); |
252 | 0 | nsCOMPtr<nsIPaymentOptions> options; |
253 | 0 | rv = payments::PaymentOptions::Create(action.options(), getter_AddRefs(options)); |
254 | 0 | NS_ENSURE_SUCCESS(rv, rv); |
255 | 0 | RefPtr<payments::PaymentRequest> request = |
256 | 0 | new payments::PaymentRequest(tabId, |
257 | 0 | aRequestId, |
258 | 0 | action.topLevelPrincipal(), |
259 | 0 | methodData, |
260 | 0 | details, |
261 | 0 | options, |
262 | 0 | action.shippingOption()); |
263 | 0 |
|
264 | 0 | if (!mRequestQueue.AppendElement(request, mozilla::fallible)) { |
265 | 0 | return NS_ERROR_OUT_OF_MEMORY; |
266 | 0 | } |
267 | 0 | break; |
268 | 0 | } |
269 | 0 | case IPCPaymentActionRequest::TIPCPaymentCanMakeActionRequest: { |
270 | 0 | nsCOMPtr<nsIPaymentCanMakeActionResponse> canMakeResponse = |
271 | 0 | do_CreateInstance(NS_PAYMENT_CANMAKE_ACTION_RESPONSE_CONTRACT_ID); |
272 | 0 | MOZ_ASSERT(canMakeResponse); |
273 | 0 | rv = canMakeResponse->Init(aRequestId, |
274 | 0 | CanMakePayment(aRequestId)); |
275 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
276 | 0 | return rv; |
277 | 0 | } |
278 | 0 | rv = RespondPayment(canMakeResponse.get()); |
279 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
280 | 0 | return rv; |
281 | 0 | } |
282 | 0 | break; |
283 | 0 | } |
284 | 0 | case IPCPaymentActionRequest::TIPCPaymentShowActionRequest: { |
285 | 0 | rv = ShowPayment(aRequestId); |
286 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
287 | 0 | return rv; |
288 | 0 | } |
289 | 0 | break; |
290 | 0 | } |
291 | 0 | case IPCPaymentActionRequest::TIPCPaymentAbortActionRequest: { |
292 | 0 | MOZ_ASSERT(request); |
293 | 0 | request->SetState(payments::PaymentRequest::eInteractive); |
294 | 0 | rv = LaunchUIAction(aRequestId, type); |
295 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
296 | 0 | return rv; |
297 | 0 | } |
298 | 0 | break; |
299 | 0 | } |
300 | 0 | case IPCPaymentActionRequest::TIPCPaymentCompleteActionRequest: { |
301 | 0 | MOZ_ASSERT(request); |
302 | 0 | const IPCPaymentCompleteActionRequest& action = aAction; |
303 | 0 | request->SetCompleteStatus(action.completeStatus()); |
304 | 0 | rv = LaunchUIAction(aRequestId, type); |
305 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
306 | 0 | return rv; |
307 | 0 | } |
308 | 0 | break; |
309 | 0 | } |
310 | 0 | case IPCPaymentActionRequest::TIPCPaymentUpdateActionRequest: { |
311 | 0 | const IPCPaymentUpdateActionRequest& action = aAction; |
312 | 0 | nsCOMPtr<nsIPaymentDetails> details; |
313 | 0 | rv = payments::PaymentDetails::Create(action.details(), getter_AddRefs(details)); |
314 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
315 | 0 | return rv; |
316 | 0 | } |
317 | 0 | MOZ_ASSERT(request); |
318 | 0 | rv = request->UpdatePaymentDetails(details, action.shippingOption()); |
319 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
320 | 0 | return rv; |
321 | 0 | } |
322 | 0 | |
323 | 0 | // mShowingRequest exists and it equals to the updated PaymentRequest |
324 | 0 | // Call UI::UpdatePayment |
325 | 0 | if (mShowingRequest && mShowingRequest == request) { |
326 | 0 | rv = LaunchUIAction(aRequestId, type); |
327 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
328 | 0 | return rv; |
329 | 0 | } |
330 | 0 | } else { |
331 | 0 | // mShowingRequest does not equal to the updated PaymentRequest, try to |
332 | 0 | // show the updated one. |
333 | 0 | rv = ShowPayment(aRequestId); |
334 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
335 | 0 | return rv; |
336 | 0 | } |
337 | 0 | } |
338 | 0 | break; |
339 | 0 | } |
340 | 0 | case IPCPaymentActionRequest::TIPCPaymentCloseActionRequest: { |
341 | 0 | rv = LaunchUIAction(aRequestId, type); |
342 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
343 | 0 | return rv; |
344 | 0 | } |
345 | 0 | if (mShowingRequest == request) { |
346 | 0 | mShowingRequest = nullptr; |
347 | 0 | } |
348 | 0 | mRequestQueue.RemoveElement(request); |
349 | 0 | break; |
350 | 0 | } |
351 | 0 | case IPCPaymentActionRequest::TIPCPaymentRetryActionRequest: { |
352 | 0 | const IPCPaymentRetryActionRequest& action = aAction; |
353 | 0 | MOZ_ASSERT(request); |
354 | 0 | request->UpdateErrors(action.error(), |
355 | 0 | action.payerErrors(), |
356 | 0 | action.paymentMethodErrors(), |
357 | 0 | action.shippingAddressErrors()); |
358 | 0 | request->SetState(payments::PaymentRequest::eInteractive); |
359 | 0 | MOZ_ASSERT(mShowingRequest == request); |
360 | 0 | rv = LaunchUIAction(aRequestId, |
361 | 0 | IPCPaymentActionRequest::TIPCPaymentUpdateActionRequest); |
362 | 0 | break; |
363 | 0 | } |
364 | 0 | default: { |
365 | 0 | return NS_ERROR_FAILURE; |
366 | 0 | } |
367 | 0 | } |
368 | 0 | return NS_OK; |
369 | 0 | } |
370 | | |
371 | | NS_IMETHODIMP |
372 | | PaymentRequestService::RespondPayment(nsIPaymentActionResponse* aResponse) |
373 | 0 | { |
374 | 0 | NS_ENSURE_ARG_POINTER(aResponse); |
375 | 0 | nsAutoString requestId; |
376 | 0 | nsresult rv = aResponse->GetRequestId(requestId); |
377 | 0 | NS_ENSURE_SUCCESS(rv, rv); |
378 | 0 |
|
379 | 0 | RefPtr<payments::PaymentRequest> request; |
380 | 0 | rv = GetPaymentRequestById(requestId, getter_AddRefs(request)); |
381 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
382 | 0 | return rv; |
383 | 0 | } |
384 | 0 | if (!request) { |
385 | 0 | return NS_ERROR_FAILURE; |
386 | 0 | } |
387 | 0 | uint32_t type; |
388 | 0 | rv = aResponse->GetType(&type); |
389 | 0 | NS_ENSURE_SUCCESS(rv, rv); |
390 | 0 |
|
391 | 0 | // PaymentRequest can only be responded when |
392 | 0 | // 1. the state is eInteractive |
393 | 0 | // 2. the state is eClosed and response type is COMPLETE_ACTION |
394 | 0 | // 3. the state is eCreated and response type is CANMAKE_ACTION |
395 | 0 | payments::PaymentRequest::eState state = request->GetState(); |
396 | 0 | bool canBeResponded = |
397 | 0 | (state == payments::PaymentRequest::eInteractive) || |
398 | 0 | (state == payments::PaymentRequest::eClosed && |
399 | 0 | type == nsIPaymentActionResponse::COMPLETE_ACTION) || |
400 | 0 | (state == payments::PaymentRequest::eCreated && |
401 | 0 | type == nsIPaymentActionResponse::CANMAKE_ACTION); |
402 | 0 | if (!canBeResponded) { |
403 | 0 | return NS_ERROR_FAILURE; |
404 | 0 | } |
405 | 0 | |
406 | 0 | if (!request->GetIPC()) { |
407 | 0 | return NS_ERROR_FAILURE; |
408 | 0 | } |
409 | 0 | rv = request->GetIPC()->RespondPayment(aResponse); |
410 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
411 | 0 | return rv; |
412 | 0 | } |
413 | 0 | |
414 | 0 | // Remove PaymentRequest from mRequestQueue while receive succeeded abort |
415 | 0 | // response or complete response |
416 | 0 | switch (type) { |
417 | 0 | case nsIPaymentActionResponse::ABORT_ACTION: { |
418 | 0 | nsCOMPtr<nsIPaymentAbortActionResponse> response = |
419 | 0 | do_QueryInterface(aResponse); |
420 | 0 | MOZ_ASSERT(response); |
421 | 0 | bool isSucceeded; |
422 | 0 | rv = response->IsSucceeded(&isSucceeded); |
423 | 0 | NS_ENSURE_SUCCESS(rv, rv); |
424 | 0 | mShowingRequest = nullptr; |
425 | 0 | if (isSucceeded) { |
426 | 0 | mRequestQueue.RemoveElement(request); |
427 | 0 | request->SetState(payments::PaymentRequest::eClosed); |
428 | 0 | } |
429 | 0 | break; |
430 | 0 | } |
431 | 0 | case nsIPaymentActionResponse::SHOW_ACTION: { |
432 | 0 | request->SetState(payments::PaymentRequest::eClosed); |
433 | 0 | nsCOMPtr<nsIPaymentShowActionResponse> response = |
434 | 0 | do_QueryInterface(aResponse); |
435 | 0 | MOZ_ASSERT(response); |
436 | 0 | uint32_t acceptStatus; |
437 | 0 | rv = response->GetAcceptStatus(&acceptStatus); |
438 | 0 | NS_ENSURE_SUCCESS(rv, rv); |
439 | 0 | if (acceptStatus != nsIPaymentActionResponse::PAYMENT_ACCEPTED) { |
440 | 0 | // Check if rejecting the showing PaymentRequest. |
441 | 0 | // If yes, set mShowingRequest as nullptr. |
442 | 0 | if (mShowingRequest == request) { |
443 | 0 | mShowingRequest = nullptr; |
444 | 0 | } |
445 | 0 | mRequestQueue.RemoveElement(request); |
446 | 0 | } |
447 | 0 | break; |
448 | 0 | } |
449 | 0 | case nsIPaymentActionResponse::COMPLETE_ACTION: { |
450 | 0 | mShowingRequest = nullptr; |
451 | 0 | mRequestQueue.RemoveElement(request); |
452 | 0 | break; |
453 | 0 | } |
454 | 0 | default: { |
455 | 0 | break; |
456 | 0 | } |
457 | 0 | } |
458 | 0 | return NS_OK; |
459 | 0 | } |
460 | | |
461 | | NS_IMETHODIMP |
462 | | PaymentRequestService::ChangeShippingAddress(const nsAString& aRequestId, |
463 | | nsIPaymentAddress* aAddress) |
464 | 0 | { |
465 | 0 | RefPtr<payments::PaymentRequest> request; |
466 | 0 | nsresult rv = GetPaymentRequestById(aRequestId, getter_AddRefs(request)); |
467 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
468 | 0 | return rv; |
469 | 0 | } |
470 | 0 | if (!request) { |
471 | 0 | return NS_ERROR_FAILURE; |
472 | 0 | } |
473 | 0 | if (request->GetState() != payments::PaymentRequest::eInteractive) { |
474 | 0 | return NS_ERROR_FAILURE; |
475 | 0 | } |
476 | 0 | if (!request->GetIPC()) { |
477 | 0 | return NS_ERROR_FAILURE; |
478 | 0 | } |
479 | 0 | rv = request->GetIPC()->ChangeShippingAddress(aRequestId, aAddress); |
480 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
481 | 0 | return rv; |
482 | 0 | } |
483 | 0 | return NS_OK; |
484 | 0 | } |
485 | | |
486 | | NS_IMETHODIMP |
487 | | PaymentRequestService::ChangeShippingOption(const nsAString& aRequestId, |
488 | | const nsAString& aOption) |
489 | 0 | { |
490 | 0 | RefPtr<payments::PaymentRequest> request; |
491 | 0 | nsresult rv = GetPaymentRequestById(aRequestId, getter_AddRefs(request)); |
492 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
493 | 0 | return rv; |
494 | 0 | } |
495 | 0 | if (!request) { |
496 | 0 | return NS_ERROR_FAILURE; |
497 | 0 | } |
498 | 0 | if (request->GetState() != payments::PaymentRequest::eInteractive) { |
499 | 0 | return NS_ERROR_FAILURE; |
500 | 0 | } |
501 | 0 | if (!request->GetIPC()) { |
502 | 0 | return NS_ERROR_FAILURE; |
503 | 0 | } |
504 | 0 | rv = request->GetIPC()->ChangeShippingOption(aRequestId, aOption); |
505 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
506 | 0 | return rv; |
507 | 0 | } |
508 | 0 | return NS_OK; |
509 | 0 | } |
510 | | |
511 | | bool |
512 | | PaymentRequestService::CanMakePayment(const nsAString& aRequestId) |
513 | 0 | { |
514 | 0 | /* |
515 | 0 | * TODO: Check third party payment app support by traversing all |
516 | 0 | * registered third party payment apps. |
517 | 0 | */ |
518 | 0 | return IsBasicCardPayment(aRequestId); |
519 | 0 | } |
520 | | |
521 | | nsresult |
522 | | PaymentRequestService::ShowPayment(const nsAString& aRequestId) |
523 | 0 | { |
524 | 0 | nsresult rv; |
525 | 0 | RefPtr<payments::PaymentRequest> request; |
526 | 0 | rv = GetPaymentRequestById(aRequestId, getter_AddRefs(request)); |
527 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
528 | 0 | return rv; |
529 | 0 | } |
530 | 0 | MOZ_ASSERT(request); |
531 | 0 | request->SetState(payments::PaymentRequest::eInteractive); |
532 | 0 |
|
533 | 0 | if (mShowingRequest || !CanMakePayment(aRequestId)) { |
534 | 0 | uint32_t responseStatus; |
535 | 0 | if (mShowingRequest) { |
536 | 0 | responseStatus = nsIPaymentActionResponse::PAYMENT_REJECTED; |
537 | 0 | } else { |
538 | 0 | responseStatus = nsIPaymentActionResponse::PAYMENT_NOTSUPPORTED; |
539 | 0 | } |
540 | 0 | nsCOMPtr<nsIPaymentShowActionResponse> showResponse = |
541 | 0 | do_CreateInstance(NS_PAYMENT_SHOW_ACTION_RESPONSE_CONTRACT_ID); |
542 | 0 | MOZ_ASSERT(showResponse); |
543 | 0 | rv = showResponse->Init(aRequestId, |
544 | 0 | responseStatus, |
545 | 0 | EmptyString(), |
546 | 0 | nullptr, |
547 | 0 | EmptyString(), |
548 | 0 | EmptyString(), |
549 | 0 | EmptyString()); |
550 | 0 | rv = RespondPayment(showResponse.get()); |
551 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
552 | 0 | return rv; |
553 | 0 | } |
554 | 0 | } else { |
555 | 0 | mShowingRequest = request; |
556 | 0 | rv = LaunchUIAction(aRequestId, |
557 | 0 | IPCPaymentActionRequest::TIPCPaymentShowActionRequest); |
558 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
559 | 0 | return rv; |
560 | 0 | } |
561 | 0 | } |
562 | 0 | return NS_OK; |
563 | 0 | } |
564 | | |
565 | | bool |
566 | | PaymentRequestService::IsBasicCardPayment(const nsAString& aRequestId) |
567 | 0 | { |
568 | 0 | RefPtr<payments::PaymentRequest> request; |
569 | 0 | nsresult rv = GetPaymentRequestById(aRequestId, getter_AddRefs(request)); |
570 | 0 | NS_ENSURE_SUCCESS(rv, false); |
571 | 0 | nsCOMPtr<nsIArray> methods; |
572 | 0 | rv = request->GetPaymentMethods(getter_AddRefs(methods)); |
573 | 0 | NS_ENSURE_SUCCESS(rv, false); |
574 | 0 | uint32_t length; |
575 | 0 | rv = methods->GetLength(&length); |
576 | 0 | NS_ENSURE_SUCCESS(rv, false); |
577 | 0 | RefPtr<BasicCardService> service = BasicCardService::GetService(); |
578 | 0 | MOZ_ASSERT(service); |
579 | 0 | for (uint32_t index = 0; index < length; ++index) { |
580 | 0 | nsCOMPtr<nsIPaymentMethodData> method = do_QueryElementAt(methods, index); |
581 | 0 | MOZ_ASSERT(method); |
582 | 0 | nsAutoString supportedMethods; |
583 | 0 | rv = method->GetSupportedMethods(supportedMethods); |
584 | 0 | NS_ENSURE_SUCCESS(rv, false); |
585 | 0 | if (service->IsBasicCardPayment(supportedMethods)) { |
586 | 0 | return true; |
587 | 0 | } |
588 | 0 | } |
589 | 0 | return false; |
590 | 0 | } |
591 | | |
592 | | NS_IMETHODIMP |
593 | | PaymentRequestService::ChangePayerDetail(const nsAString& aRequestId, |
594 | | const nsAString& aPayerName, |
595 | | const nsAString& aPayerEmail, |
596 | | const nsAString& aPayerPhone) |
597 | 0 | { |
598 | 0 | RefPtr<payments::PaymentRequest> request; |
599 | 0 | nsresult rv = GetPaymentRequestById(aRequestId, getter_AddRefs(request)); |
600 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
601 | 0 | return rv; |
602 | 0 | } |
603 | 0 | MOZ_ASSERT(request); |
604 | 0 | if (!request->GetIPC()) { |
605 | 0 | return NS_ERROR_FAILURE; |
606 | 0 | } |
607 | 0 | rv = request->GetIPC()->ChangePayerDetail( |
608 | 0 | aRequestId, aPayerName, aPayerEmail, aPayerPhone); |
609 | 0 | if (NS_WARN_IF(NS_FAILED(rv))) { |
610 | 0 | return rv; |
611 | 0 | } |
612 | 0 | return NS_OK; |
613 | 0 | } |
614 | | |
615 | | } // end of namespace dom |
616 | | } // end of namespace mozilla |