Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim:set ts=2 sw=2 sts=2 et cindent: */
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/ipc/InputStreamUtils.h"
8 : #include "nsArrayUtils.h"
9 : #include "nsCOMPtr.h"
10 : #include "nsIMutableArray.h"
11 : #include "nsIPaymentRequestService.h"
12 : #include "nsISupportsPrimitives.h"
13 : #include "nsServiceManagerUtils.h"
14 : #include "PaymentRequestData.h"
15 : #include "PaymentRequestParent.h"
16 :
17 : namespace mozilla {
18 : namespace dom {
19 :
20 0 : NS_IMPL_ISUPPORTS(PaymentRequestParent, nsIPaymentActionCallback)
21 :
22 0 : PaymentRequestParent::PaymentRequestParent(uint64_t aTabId)
23 : : mActorAlived(true)
24 0 : , mTabId(aTabId)
25 : {
26 0 : }
27 :
28 : mozilla::ipc::IPCResult
29 0 : PaymentRequestParent::RecvRequestPayment(const IPCPaymentActionRequest& aRequest)
30 : {
31 0 : if (!mActorAlived) {
32 0 : return IPC_FAIL_NO_REASON(this);
33 : }
34 0 : nsCOMPtr<nsIPaymentActionRequest> action;
35 0 : nsCOMPtr<nsIPaymentActionCallback> callback = do_QueryInterface(this);
36 0 : MOZ_ASSERT(callback);
37 : nsresult rv;
38 0 : switch (aRequest.type()) {
39 : case IPCPaymentActionRequest::TIPCPaymentCreateActionRequest: {
40 0 : const IPCPaymentCreateActionRequest& request = aRequest;
41 :
42 0 : nsCOMPtr<nsIMutableArray> methodData = do_CreateInstance(NS_ARRAY_CONTRACTID);
43 0 : MOZ_ASSERT(methodData);
44 0 : for (IPCPaymentMethodData data : request.methodData()) {
45 0 : nsCOMPtr<nsIPaymentMethodData> method;
46 0 : rv = payments::PaymentMethodData::Create(data, getter_AddRefs(method));
47 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
48 0 : return IPC_FAIL_NO_REASON(this);
49 : }
50 0 : rv = methodData->AppendElement(method, false);
51 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
52 0 : return IPC_FAIL_NO_REASON(this);
53 : }
54 : }
55 :
56 0 : nsCOMPtr<nsIPaymentDetails> details;
57 0 : rv = payments::PaymentDetails::Create(request.details(), getter_AddRefs(details));
58 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
59 0 : return IPC_FAIL_NO_REASON(this);
60 : }
61 :
62 0 : nsCOMPtr<nsIPaymentOptions> options;
63 0 : rv = payments::PaymentOptions::Create(request.options(), getter_AddRefs(options));
64 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
65 0 : return IPC_FAIL_NO_REASON(this);
66 : }
67 :
68 : nsCOMPtr<nsIPaymentCreateActionRequest> createAction =
69 0 : do_CreateInstance(NS_PAYMENT_CREATE_ACTION_REQUEST_CONTRACT_ID);
70 0 : if (NS_WARN_IF(!createAction)) {
71 0 : return IPC_FAIL_NO_REASON(this);
72 : }
73 0 : rv = createAction->InitRequest(request.requestId(),
74 : callback,
75 : mTabId,
76 : methodData,
77 : details,
78 0 : options);
79 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
80 0 : return IPC_FAIL_NO_REASON(this);
81 : }
82 :
83 0 : action = do_QueryInterface(createAction);
84 0 : MOZ_ASSERT(action);
85 0 : break;
86 : }
87 : case IPCPaymentActionRequest::TIPCPaymentCanMakeActionRequest: {
88 0 : const IPCPaymentCanMakeActionRequest& request = aRequest;
89 0 : rv = CreateActionRequest(request.requestId(),
90 : nsIPaymentActionRequest::CANMAKE_ACTION,
91 0 : getter_AddRefs(action));
92 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
93 0 : return IPC_FAIL_NO_REASON(this);
94 : }
95 0 : break;
96 : }
97 : case IPCPaymentActionRequest::TIPCPaymentShowActionRequest: {
98 0 : const IPCPaymentShowActionRequest& request = aRequest;
99 0 : rv = CreateActionRequest(request.requestId(),
100 : nsIPaymentActionRequest::SHOW_ACTION,
101 0 : getter_AddRefs(action));
102 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
103 0 : return IPC_FAIL_NO_REASON(this);
104 : }
105 0 : break;
106 : }
107 : case IPCPaymentActionRequest::TIPCPaymentAbortActionRequest: {
108 0 : const IPCPaymentAbortActionRequest& request = aRequest;
109 0 : rv = CreateActionRequest(request.requestId(),
110 : nsIPaymentActionRequest::ABORT_ACTION,
111 0 : getter_AddRefs(action));
112 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
113 0 : return IPC_FAIL_NO_REASON(this);
114 : }
115 0 : break;
116 : }
117 : case IPCPaymentActionRequest::TIPCPaymentCompleteActionRequest: {
118 0 : const IPCPaymentCompleteActionRequest& request = aRequest;
119 : nsCOMPtr<nsIPaymentCompleteActionRequest> completeAction =
120 0 : do_CreateInstance(NS_PAYMENT_COMPLETE_ACTION_REQUEST_CONTRACT_ID);
121 0 : rv = completeAction->InitRequest(request.requestId(),
122 : callback,
123 0 : request.completeStatus());
124 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
125 0 : return IPC_FAIL_NO_REASON(this);
126 : }
127 0 : action = do_QueryInterface(completeAction);
128 0 : MOZ_ASSERT(action);
129 0 : break;
130 : }
131 : case IPCPaymentActionRequest::TIPCPaymentUpdateActionRequest: {
132 0 : const IPCPaymentUpdateActionRequest& request = aRequest;
133 :
134 0 : nsCOMPtr<nsIPaymentDetails> details;
135 0 : rv = payments::PaymentDetails::Create(request.details(), getter_AddRefs(details));
136 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
137 0 : return IPC_FAIL_NO_REASON(this);
138 : }
139 :
140 : nsCOMPtr<nsIPaymentUpdateActionRequest> updateAction =
141 0 : do_CreateInstance(NS_PAYMENT_UPDATE_ACTION_REQUEST_CONTRACT_ID);
142 0 : rv = updateAction->InitRequest(request.requestId(),
143 : callback,
144 0 : details);
145 0 : action = do_QueryInterface(updateAction);
146 0 : MOZ_ASSERT(action);
147 0 : break;
148 : }
149 : default: {
150 0 : return IPC_FAIL(this, "Unexpected request type");
151 : }
152 : }
153 : nsCOMPtr<nsIPaymentRequestService> service =
154 0 : do_GetService(NS_PAYMENT_REQUEST_SERVICE_CONTRACT_ID);
155 0 : MOZ_ASSERT(service);
156 0 : rv = service->RequestPayment(action);
157 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
158 0 : return IPC_FAIL_NO_REASON(this);
159 : }
160 0 : return IPC_OK();
161 : }
162 :
163 : NS_IMETHODIMP
164 0 : PaymentRequestParent::RespondPayment(nsIPaymentActionResponse* aResponse)
165 : {
166 0 : if (!NS_IsMainThread()) {
167 0 : nsCOMPtr<nsIPaymentActionCallback> self = do_QueryInterface(this);
168 0 : MOZ_ASSERT(self);
169 0 : nsCOMPtr<nsIPaymentActionResponse> response = aResponse;
170 0 : nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction("PaymentRequestParent::RespondPayment",
171 0 : [self, response] ()
172 : {
173 0 : self->RespondPayment(response);
174 0 : });
175 0 : return NS_DispatchToMainThread(r);
176 : }
177 :
178 0 : if (!mActorAlived) {
179 0 : return NS_ERROR_FAILURE;
180 : }
181 : uint32_t type;
182 0 : nsresult rv = aResponse->GetType(&type);
183 0 : NS_ENSURE_SUCCESS(rv, rv);
184 0 : nsAutoString requestId;
185 0 : rv = aResponse->GetRequestId(requestId);
186 0 : NS_ENSURE_SUCCESS(rv, rv);
187 0 : switch (type) {
188 : case nsIPaymentActionResponse::CANMAKE_ACTION: {
189 0 : nsCOMPtr<nsIPaymentCanMakeActionResponse> response = do_QueryInterface(aResponse);
190 0 : MOZ_ASSERT(response);
191 : bool result;
192 0 : rv = response->GetResult(&result);
193 0 : NS_ENSURE_SUCCESS(rv, rv);
194 0 : IPCPaymentCanMakeActionResponse actionResponse(requestId, result);
195 0 : if (!SendRespondPayment(actionResponse)) {
196 0 : return NS_ERROR_FAILURE;
197 : }
198 0 : break;
199 : }
200 : case nsIPaymentActionResponse::SHOW_ACTION: {
201 : nsCOMPtr<nsIPaymentShowActionResponse> response =
202 0 : do_QueryInterface(aResponse);
203 0 : MOZ_ASSERT(response);
204 : bool isAccepted;
205 0 : NS_ENSURE_SUCCESS(response->IsAccepted(&isAccepted), NS_ERROR_FAILURE);
206 0 : nsAutoString methodName;
207 0 : NS_ENSURE_SUCCESS(response->GetMethodName(methodName), NS_ERROR_FAILURE);
208 0 : nsAutoString data;
209 0 : NS_ENSURE_SUCCESS(response->GetData(data), NS_ERROR_FAILURE);
210 0 : nsAutoString payerName;
211 0 : NS_ENSURE_SUCCESS(response->GetPayerName(payerName), NS_ERROR_FAILURE);
212 0 : nsAutoString payerEmail;
213 0 : NS_ENSURE_SUCCESS(response->GetPayerEmail(payerEmail), NS_ERROR_FAILURE);
214 0 : nsAutoString payerPhone;
215 0 : NS_ENSURE_SUCCESS(response->GetPayerPhone(payerPhone), NS_ERROR_FAILURE);
216 : IPCPaymentShowActionResponse actionResponse(requestId,
217 : isAccepted,
218 : methodName,
219 : data,
220 : payerName,
221 : payerEmail,
222 0 : payerPhone);
223 0 : if (!SendRespondPayment(actionResponse)) {
224 0 : return NS_ERROR_FAILURE;
225 : }
226 0 : break;
227 : }
228 : case nsIPaymentActionResponse::ABORT_ACTION: {
229 : nsCOMPtr<nsIPaymentAbortActionResponse> response =
230 0 : do_QueryInterface(aResponse);
231 0 : MOZ_ASSERT(response);
232 : bool isSucceeded;
233 0 : rv = response->IsSucceeded(&isSucceeded);
234 0 : NS_ENSURE_SUCCESS(rv, rv);
235 0 : IPCPaymentAbortActionResponse actionResponse(requestId, isSucceeded);
236 0 : if (!SendRespondPayment(actionResponse)) {
237 0 : return NS_ERROR_FAILURE;
238 : }
239 0 : break;
240 : }
241 : case nsIPaymentActionResponse::COMPLETE_ACTION: {
242 : nsCOMPtr<nsIPaymentCompleteActionResponse> response =
243 0 : do_QueryInterface(aResponse);
244 0 : MOZ_ASSERT(response);
245 : bool isCompleted;
246 0 : rv = response->IsCompleted(&isCompleted);
247 0 : NS_ENSURE_SUCCESS(rv, rv);
248 0 : IPCPaymentCompleteActionResponse actionResponse(requestId, isCompleted);
249 0 : if (!SendRespondPayment(actionResponse)) {
250 0 : return NS_ERROR_FAILURE;
251 : }
252 0 : break;
253 : }
254 : default: {
255 0 : return NS_ERROR_FAILURE;
256 : }
257 : }
258 0 : return NS_OK;
259 : }
260 :
261 : NS_IMETHODIMP
262 0 : PaymentRequestParent::ChangeShippingAddress(const nsAString& aRequestId,
263 : nsIPaymentAddress* aAddress)
264 : {
265 0 : if (!NS_IsMainThread()) {
266 0 : nsCOMPtr<nsIPaymentActionCallback> self = this;
267 0 : nsCOMPtr<nsIPaymentAddress> address = aAddress;
268 0 : nsAutoString requestId(aRequestId);
269 0 : nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction("dom::PaymentRequestParent::ChangeShippingAddress",
270 0 : [self, requestId, address] ()
271 : {
272 0 : self->ChangeShippingAddress(requestId, address);
273 0 : });
274 0 : return NS_DispatchToMainThread(r);
275 : }
276 0 : if (!mActorAlived) {
277 0 : return NS_ERROR_FAILURE;
278 : }
279 0 : nsAutoString country;
280 0 : nsresult rv = aAddress->GetCountry(country);
281 0 : NS_ENSURE_SUCCESS(rv, rv);
282 :
283 0 : nsCOMPtr<nsIArray> iaddressLine;
284 0 : rv = aAddress->GetAddressLine(getter_AddRefs(iaddressLine));
285 0 : NS_ENSURE_SUCCESS(rv, rv);
286 :
287 0 : nsAutoString region;
288 0 : rv = aAddress->GetRegion(region);
289 0 : NS_ENSURE_SUCCESS(rv, rv);
290 :
291 0 : nsAutoString city;
292 0 : rv = aAddress->GetCity(city);
293 0 : NS_ENSURE_SUCCESS(rv, rv);
294 :
295 0 : nsAutoString dependentLocality;
296 0 : rv = aAddress->GetDependentLocality(dependentLocality);
297 0 : NS_ENSURE_SUCCESS(rv, rv);
298 :
299 0 : nsAutoString postalCode;
300 0 : rv = aAddress->GetPostalCode(postalCode);
301 0 : NS_ENSURE_SUCCESS(rv, rv);
302 :
303 0 : nsAutoString sortingCode;
304 0 : rv = aAddress->GetSortingCode(sortingCode);
305 0 : NS_ENSURE_SUCCESS(rv, rv);
306 :
307 0 : nsAutoString languageCode;
308 0 : rv = aAddress->GetLanguageCode(languageCode);
309 0 : NS_ENSURE_SUCCESS(rv, rv);
310 :
311 0 : nsAutoString organization;
312 0 : rv = aAddress->GetOrganization(organization);
313 0 : NS_ENSURE_SUCCESS(rv, rv);
314 :
315 0 : nsAutoString recipient;
316 0 : rv = aAddress->GetRecipient(recipient);
317 0 : NS_ENSURE_SUCCESS(rv, rv);
318 :
319 0 : nsAutoString phone;
320 0 : rv = aAddress->GetPhone(phone);
321 0 : NS_ENSURE_SUCCESS(rv, rv);
322 :
323 0 : nsTArray<nsString> addressLine;
324 : uint32_t length;
325 0 : rv = iaddressLine->GetLength(&length);
326 0 : NS_ENSURE_SUCCESS(rv, rv);
327 0 : for (uint32_t index = 0; index < length; ++index) {
328 0 : nsCOMPtr<nsISupportsString> iaddress = do_QueryElementAt(iaddressLine, index);
329 0 : MOZ_ASSERT(iaddress);
330 0 : nsAutoString address;
331 0 : rv = iaddress->GetData(address);
332 0 : NS_ENSURE_SUCCESS(rv, rv);
333 0 : addressLine.AppendElement(address);
334 : }
335 :
336 : IPCPaymentAddress ipcAddress(country, addressLine, region, city,
337 : dependentLocality, postalCode, sortingCode,
338 0 : languageCode, organization, recipient, phone);
339 :
340 0 : nsAutoString requestId(aRequestId);
341 0 : if (!SendChangeShippingAddress(requestId, ipcAddress)) {
342 0 : return NS_ERROR_FAILURE;
343 : }
344 0 : return NS_OK;
345 : }
346 :
347 : NS_IMETHODIMP
348 0 : PaymentRequestParent::ChangeShippingOption(const nsAString& aRequestId,
349 : const nsAString& aOption)
350 : {
351 0 : if (!NS_IsMainThread()) {
352 0 : nsCOMPtr<nsIPaymentActionCallback> self = this;
353 0 : nsAutoString requestId(aRequestId);
354 0 : nsAutoString option(aOption);
355 0 : nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction("dom::PaymentRequestParent::ChangeShippingOption",
356 0 : [self, requestId, option] ()
357 : {
358 0 : self->ChangeShippingOption(requestId, option);
359 0 : });
360 0 : return NS_DispatchToMainThread(r);
361 : }
362 0 : if (!mActorAlived) {
363 0 : return NS_ERROR_FAILURE;
364 : }
365 0 : nsAutoString requestId(aRequestId);
366 0 : nsAutoString option(aOption);
367 0 : if (!SendChangeShippingOption(requestId, option)) {
368 0 : return NS_ERROR_FAILURE;
369 : }
370 0 : return NS_OK;
371 : }
372 :
373 : mozilla::ipc::IPCResult
374 0 : PaymentRequestParent::Recv__delete__()
375 : {
376 0 : mActorAlived = false;
377 0 : return IPC_OK();
378 : }
379 :
380 : void
381 0 : PaymentRequestParent::ActorDestroy(ActorDestroyReason aWhy)
382 : {
383 0 : mActorAlived = false;
384 : nsCOMPtr<nsIPaymentRequestService> service =
385 0 : do_GetService(NS_PAYMENT_REQUEST_SERVICE_CONTRACT_ID);
386 0 : MOZ_ASSERT(service);
387 0 : nsCOMPtr<nsIPaymentActionCallback> callback = do_QueryInterface(this);
388 0 : MOZ_ASSERT(callback);
389 0 : nsresult rv = service->RemoveActionCallback(callback);
390 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
391 0 : MOZ_ASSERT(false);
392 : }
393 0 : }
394 :
395 : nsresult
396 0 : PaymentRequestParent::CreateActionRequest(const nsAString& aRequestId,
397 : uint32_t aActionType,
398 : nsIPaymentActionRequest** aAction)
399 : {
400 0 : NS_ENSURE_ARG_POINTER(aAction);
401 : nsCOMPtr<nsIPaymentActionRequest> action =
402 0 : do_CreateInstance(NS_PAYMENT_ACTION_REQUEST_CONTRACT_ID);
403 0 : MOZ_ASSERT(action);
404 0 : nsCOMPtr<nsIPaymentActionCallback> callback = do_QueryInterface(this);
405 0 : MOZ_ASSERT(callback);
406 0 : nsresult rv = action->Init(aRequestId, aActionType, callback);
407 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
408 0 : return rv;
409 : }
410 0 : action.forget(aAction);
411 0 : return NS_OK;
412 : }
413 :
414 : } // end of namespace dom
415 : } // end of namespace mozilla
|