PaymentRequestParent.cpp (16263B)
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 "PaymentRequestParent.h" 8 9 #include "PaymentRequestData.h" 10 #include "PaymentRequestService.h" 11 #include "mozilla/ipc/InputStreamUtils.h" 12 #include "nsArrayUtils.h" 13 #include "nsCOMPtr.h" 14 #include "nsIPaymentRequestService.h" 15 #include "nsISupportsPrimitives.h" 16 #include "nsServiceManagerUtils.h" 17 18 namespace mozilla::dom { 19 20 PaymentRequestParent::PaymentRequestParent() 21 : mActorAlive(true), mRequestId(u""_ns) {} 22 23 mozilla::ipc::IPCResult PaymentRequestParent::RecvRequestPayment( 24 const IPCPaymentActionRequest& aRequest) { 25 if (!mActorAlive) { 26 return IPC_FAIL_NO_REASON(this); 27 } 28 switch (aRequest.type()) { 29 case IPCPaymentActionRequest::TIPCPaymentCreateActionRequest: { 30 const IPCPaymentCreateActionRequest& request = aRequest; 31 mRequestId = request.requestId(); 32 break; 33 } 34 case IPCPaymentActionRequest::TIPCPaymentCanMakeActionRequest: { 35 const IPCPaymentCanMakeActionRequest& request = aRequest; 36 mRequestId = request.requestId(); 37 break; 38 } 39 case IPCPaymentActionRequest::TIPCPaymentShowActionRequest: { 40 const IPCPaymentShowActionRequest& request = aRequest; 41 mRequestId = request.requestId(); 42 break; 43 } 44 case IPCPaymentActionRequest::TIPCPaymentAbortActionRequest: { 45 const IPCPaymentAbortActionRequest& request = aRequest; 46 mRequestId = request.requestId(); 47 break; 48 } 49 case IPCPaymentActionRequest::TIPCPaymentCompleteActionRequest: { 50 const IPCPaymentCompleteActionRequest& request = aRequest; 51 mRequestId = request.requestId(); 52 break; 53 } 54 case IPCPaymentActionRequest::TIPCPaymentUpdateActionRequest: { 55 const IPCPaymentUpdateActionRequest& request = aRequest; 56 mRequestId = request.requestId(); 57 break; 58 } 59 case IPCPaymentActionRequest::TIPCPaymentCloseActionRequest: { 60 const IPCPaymentCloseActionRequest& request = aRequest; 61 mRequestId = request.requestId(); 62 break; 63 } 64 case IPCPaymentActionRequest::TIPCPaymentRetryActionRequest: { 65 const IPCPaymentRetryActionRequest& request = aRequest; 66 mRequestId = request.requestId(); 67 break; 68 } 69 default: { 70 return IPC_FAIL(this, "Unknown PaymentRequest action type"); 71 } 72 } 73 nsCOMPtr<nsIPaymentRequestService> service = 74 do_GetService(NS_PAYMENT_REQUEST_SERVICE_CONTRACT_ID); 75 MOZ_ASSERT(service); 76 PaymentRequestService* rowService = 77 static_cast<PaymentRequestService*>(service.get()); 78 MOZ_ASSERT(rowService); 79 (void)NS_WARN_IF( 80 NS_FAILED(rowService->RequestPayment(mRequestId, aRequest, this))); 81 return IPC_OK(); 82 } 83 84 nsresult PaymentRequestParent::RespondPayment( 85 nsIPaymentActionResponse* aResponse) { 86 if (!NS_IsMainThread()) { 87 RefPtr<PaymentRequestParent> self = this; 88 nsCOMPtr<nsIPaymentActionResponse> response = aResponse; 89 nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction( 90 "PaymentRequestParent::RespondPayment", 91 [self, response]() { self->RespondPayment(response); }); 92 return NS_DispatchToMainThread(r); 93 } 94 95 if (!mActorAlive) { 96 return NS_ERROR_FAILURE; 97 } 98 uint32_t type; 99 nsresult rv = aResponse->GetType(&type); 100 NS_ENSURE_SUCCESS(rv, rv); 101 nsAutoString requestId; 102 rv = aResponse->GetRequestId(requestId); 103 NS_ENSURE_SUCCESS(rv, rv); 104 switch (type) { 105 case nsIPaymentActionResponse::CANMAKE_ACTION: { 106 nsCOMPtr<nsIPaymentCanMakeActionResponse> response = 107 do_QueryInterface(aResponse); 108 MOZ_ASSERT(response); 109 bool result; 110 rv = response->GetResult(&result); 111 NS_ENSURE_SUCCESS(rv, rv); 112 IPCPaymentCanMakeActionResponse actionResponse(requestId, result); 113 if (!SendRespondPayment(actionResponse)) { 114 return NS_ERROR_FAILURE; 115 } 116 break; 117 } 118 case nsIPaymentActionResponse::SHOW_ACTION: { 119 nsCOMPtr<nsIPaymentShowActionResponse> response = 120 do_QueryInterface(aResponse); 121 MOZ_ASSERT(response); 122 uint32_t acceptStatus; 123 NS_ENSURE_SUCCESS(response->GetAcceptStatus(&acceptStatus), 124 NS_ERROR_FAILURE); 125 nsAutoString methodName; 126 NS_ENSURE_SUCCESS(response->GetMethodName(methodName), NS_ERROR_FAILURE); 127 IPCPaymentResponseData ipcData; 128 if (acceptStatus == nsIPaymentActionResponse::PAYMENT_ACCEPTED) { 129 nsCOMPtr<nsIPaymentResponseData> data; 130 NS_ENSURE_SUCCESS(response->GetData(getter_AddRefs(data)), 131 NS_ERROR_FAILURE); 132 MOZ_ASSERT(data); 133 NS_ENSURE_SUCCESS(SerializeResponseData(ipcData, data), 134 NS_ERROR_FAILURE); 135 } else { 136 ipcData = IPCGeneralResponse(); 137 } 138 139 nsAutoString payerName; 140 NS_ENSURE_SUCCESS(response->GetPayerName(payerName), NS_ERROR_FAILURE); 141 nsAutoString payerEmail; 142 NS_ENSURE_SUCCESS(response->GetPayerEmail(payerEmail), NS_ERROR_FAILURE); 143 nsAutoString payerPhone; 144 NS_ENSURE_SUCCESS(response->GetPayerPhone(payerPhone), NS_ERROR_FAILURE); 145 IPCPaymentShowActionResponse actionResponse( 146 requestId, acceptStatus, methodName, ipcData, payerName, payerEmail, 147 payerPhone); 148 if (!SendRespondPayment(actionResponse)) { 149 return NS_ERROR_FAILURE; 150 } 151 break; 152 } 153 case nsIPaymentActionResponse::ABORT_ACTION: { 154 nsCOMPtr<nsIPaymentAbortActionResponse> response = 155 do_QueryInterface(aResponse); 156 MOZ_ASSERT(response); 157 bool isSucceeded; 158 rv = response->IsSucceeded(&isSucceeded); 159 NS_ENSURE_SUCCESS(rv, rv); 160 IPCPaymentAbortActionResponse actionResponse(requestId, isSucceeded); 161 if (!SendRespondPayment(actionResponse)) { 162 return NS_ERROR_FAILURE; 163 } 164 break; 165 } 166 case nsIPaymentActionResponse::COMPLETE_ACTION: { 167 nsCOMPtr<nsIPaymentCompleteActionResponse> response = 168 do_QueryInterface(aResponse); 169 MOZ_ASSERT(response); 170 bool isCompleted; 171 rv = response->IsCompleted(&isCompleted); 172 NS_ENSURE_SUCCESS(rv, rv); 173 IPCPaymentCompleteActionResponse actionResponse(requestId, isCompleted); 174 if (!SendRespondPayment(actionResponse)) { 175 return NS_ERROR_FAILURE; 176 } 177 break; 178 } 179 default: { 180 return NS_ERROR_FAILURE; 181 } 182 } 183 return NS_OK; 184 } 185 186 nsresult PaymentRequestParent::ChangeShippingAddress( 187 const nsAString& aRequestId, nsIPaymentAddress* aAddress) { 188 if (!NS_IsMainThread()) { 189 RefPtr<PaymentRequestParent> self = this; 190 nsCOMPtr<nsIPaymentAddress> address = aAddress; 191 nsAutoString requestId(aRequestId); 192 nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction( 193 "dom::PaymentRequestParent::ChangeShippingAddress", 194 [self, requestId, address]() { 195 self->ChangeShippingAddress(requestId, address); 196 }); 197 return NS_DispatchToMainThread(r); 198 } 199 if (!mActorAlive) { 200 return NS_ERROR_FAILURE; 201 } 202 203 IPCPaymentAddress ipcAddress; 204 nsresult rv = SerializeAddress(ipcAddress, aAddress); 205 NS_ENSURE_SUCCESS(rv, rv); 206 207 nsAutoString requestId(aRequestId); 208 if (!SendChangeShippingAddress(requestId, ipcAddress)) { 209 return NS_ERROR_FAILURE; 210 } 211 return NS_OK; 212 } 213 214 nsresult PaymentRequestParent::ChangeShippingOption(const nsAString& aRequestId, 215 const nsAString& aOption) { 216 if (!NS_IsMainThread()) { 217 RefPtr<PaymentRequestParent> self = this; 218 nsAutoString requestId(aRequestId); 219 nsAutoString option(aOption); 220 nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction( 221 "dom::PaymentRequestParent::ChangeShippingOption", 222 [self, requestId, option]() { 223 self->ChangeShippingOption(requestId, option); 224 }); 225 return NS_DispatchToMainThread(r); 226 } 227 if (!mActorAlive) { 228 return NS_ERROR_FAILURE; 229 } 230 nsAutoString requestId(aRequestId); 231 nsAutoString option(aOption); 232 if (!SendChangeShippingOption(requestId, option)) { 233 return NS_ERROR_FAILURE; 234 } 235 return NS_OK; 236 } 237 238 nsresult PaymentRequestParent::ChangePayerDetail(const nsAString& aRequestId, 239 const nsAString& aPayerName, 240 const nsAString& aPayerEmail, 241 const nsAString& aPayerPhone) { 242 nsAutoString requestId(aRequestId); 243 nsAutoString payerName(aPayerName); 244 nsAutoString payerEmail(aPayerEmail); 245 nsAutoString payerPhone(aPayerPhone); 246 if (!NS_IsMainThread()) { 247 RefPtr<PaymentRequestParent> self = this; 248 nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction( 249 "dom::PaymentRequestParent::ChangePayerDetail", 250 [self, requestId, payerName, payerEmail, payerPhone]() { 251 self->ChangePayerDetail(requestId, payerName, payerEmail, payerPhone); 252 }); 253 return NS_DispatchToMainThread(r); 254 } 255 if (!mActorAlive) { 256 return NS_ERROR_FAILURE; 257 } 258 if (!SendChangePayerDetail(requestId, payerName, payerEmail, payerPhone)) { 259 return NS_ERROR_FAILURE; 260 } 261 return NS_OK; 262 } 263 264 nsresult PaymentRequestParent::ChangePaymentMethod( 265 const nsAString& aRequestId, const nsAString& aMethodName, 266 nsIMethodChangeDetails* aMethodDetails) { 267 nsAutoString requestId(aRequestId); 268 nsAutoString methodName(aMethodName); 269 nsCOMPtr<nsIMethodChangeDetails> methodDetails(aMethodDetails); 270 if (!NS_IsMainThread()) { 271 RefPtr<PaymentRequestParent> self = this; 272 nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction( 273 "dom::PaymentRequestParent::ChangePaymentMethod", 274 [self, requestId, methodName, methodDetails]() { 275 self->ChangePaymentMethod(requestId, methodName, methodDetails); 276 }); 277 return NS_DispatchToMainThread(r); 278 } 279 if (!mActorAlive) { 280 return NS_ERROR_FAILURE; 281 } 282 283 // Convert nsIMethodChangeDetails to IPCMethodChangeDetails 284 // aMethodChangeDetails can be null 285 IPCMethodChangeDetails ipcChangeDetails; 286 if (aMethodDetails) { 287 uint32_t dataType; 288 NS_ENSURE_SUCCESS(aMethodDetails->GetType(&dataType), NS_ERROR_FAILURE); 289 switch (dataType) { 290 case nsIMethodChangeDetails::GENERAL_DETAILS: { 291 nsCOMPtr<nsIGeneralChangeDetails> details = 292 do_QueryInterface(methodDetails); 293 MOZ_ASSERT(details); 294 IPCGeneralChangeDetails ipcGeneralDetails; 295 NS_ENSURE_SUCCESS(details->GetDetails(ipcGeneralDetails.details()), 296 NS_ERROR_FAILURE); 297 ipcChangeDetails = ipcGeneralDetails; 298 break; 299 } 300 case nsIMethodChangeDetails::BASICCARD_DETAILS: { 301 nsCOMPtr<nsIBasicCardChangeDetails> details = 302 do_QueryInterface(methodDetails); 303 MOZ_ASSERT(details); 304 IPCBasicCardChangeDetails ipcBasicCardDetails; 305 nsCOMPtr<nsIPaymentAddress> address; 306 NS_ENSURE_SUCCESS(details->GetBillingAddress(getter_AddRefs(address)), 307 NS_ERROR_FAILURE); 308 IPCPaymentAddress ipcAddress; 309 NS_ENSURE_SUCCESS(SerializeAddress(ipcAddress, address), 310 NS_ERROR_FAILURE); 311 ipcBasicCardDetails.billingAddress() = ipcAddress; 312 ipcChangeDetails = ipcBasicCardDetails; 313 break; 314 } 315 default: { 316 return NS_ERROR_FAILURE; 317 } 318 } 319 } 320 if (!SendChangePaymentMethod(requestId, methodName, ipcChangeDetails)) { 321 return NS_ERROR_FAILURE; 322 } 323 return NS_OK; 324 } 325 326 mozilla::ipc::IPCResult PaymentRequestParent::Recv__delete__() { 327 mActorAlive = false; 328 return IPC_OK(); 329 } 330 331 void PaymentRequestParent::ActorDestroy(ActorDestroyReason aWhy) { 332 mActorAlive = false; 333 nsCOMPtr<nsIPaymentRequestService> service = 334 do_GetService(NS_PAYMENT_REQUEST_SERVICE_CONTRACT_ID); 335 MOZ_ASSERT(service); 336 if (!mRequestId.Equals(u""_ns)) { 337 nsCOMPtr<nsIPaymentRequest> request; 338 nsresult rv = 339 service->GetPaymentRequestById(mRequestId, getter_AddRefs(request)); 340 if (NS_WARN_IF(NS_FAILED(rv))) { 341 return; 342 } 343 if (!request) { 344 return; 345 } 346 payments::PaymentRequest* rowRequest = 347 static_cast<payments::PaymentRequest*>(request.get()); 348 MOZ_ASSERT(rowRequest); 349 rowRequest->SetIPC(nullptr); 350 } 351 } 352 353 nsresult PaymentRequestParent::SerializeAddress(IPCPaymentAddress& aIPCAddress, 354 nsIPaymentAddress* aAddress) { 355 // address can be nullptr 356 if (!aAddress) { 357 return NS_OK; 358 } 359 nsAutoString country; 360 nsresult rv = aAddress->GetCountry(country); 361 NS_ENSURE_SUCCESS(rv, rv); 362 363 nsCOMPtr<nsIArray> iaddressLine; 364 rv = aAddress->GetAddressLine(getter_AddRefs(iaddressLine)); 365 NS_ENSURE_SUCCESS(rv, rv); 366 367 nsAutoString region; 368 rv = aAddress->GetRegion(region); 369 NS_ENSURE_SUCCESS(rv, rv); 370 371 nsAutoString regionCode; 372 rv = aAddress->GetRegionCode(regionCode); 373 NS_ENSURE_SUCCESS(rv, rv); 374 375 nsAutoString city; 376 rv = aAddress->GetCity(city); 377 NS_ENSURE_SUCCESS(rv, rv); 378 379 nsAutoString dependentLocality; 380 rv = aAddress->GetDependentLocality(dependentLocality); 381 NS_ENSURE_SUCCESS(rv, rv); 382 383 nsAutoString postalCode; 384 rv = aAddress->GetPostalCode(postalCode); 385 NS_ENSURE_SUCCESS(rv, rv); 386 387 nsAutoString sortingCode; 388 rv = aAddress->GetSortingCode(sortingCode); 389 NS_ENSURE_SUCCESS(rv, rv); 390 391 nsAutoString organization; 392 rv = aAddress->GetOrganization(organization); 393 NS_ENSURE_SUCCESS(rv, rv); 394 395 nsAutoString recipient; 396 rv = aAddress->GetRecipient(recipient); 397 NS_ENSURE_SUCCESS(rv, rv); 398 399 nsAutoString phone; 400 rv = aAddress->GetPhone(phone); 401 NS_ENSURE_SUCCESS(rv, rv); 402 403 nsTArray<nsString> addressLine; 404 uint32_t length; 405 rv = iaddressLine->GetLength(&length); 406 NS_ENSURE_SUCCESS(rv, rv); 407 for (uint32_t index = 0; index < length; ++index) { 408 nsCOMPtr<nsISupportsString> iaddress = 409 do_QueryElementAt(iaddressLine, index); 410 MOZ_ASSERT(iaddress); 411 nsAutoString address; 412 rv = iaddress->GetData(address); 413 NS_ENSURE_SUCCESS(rv, rv); 414 addressLine.AppendElement(address); 415 } 416 417 aIPCAddress = IPCPaymentAddress(country, addressLine, region, regionCode, 418 city, dependentLocality, postalCode, 419 sortingCode, organization, recipient, phone); 420 return NS_OK; 421 } 422 423 nsresult PaymentRequestParent::SerializeResponseData( 424 IPCPaymentResponseData& aIPCData, nsIPaymentResponseData* aData) { 425 NS_ENSURE_ARG_POINTER(aData); 426 uint32_t dataType; 427 NS_ENSURE_SUCCESS(aData->GetType(&dataType), NS_ERROR_FAILURE); 428 switch (dataType) { 429 case nsIPaymentResponseData::GENERAL_RESPONSE: { 430 nsCOMPtr<nsIGeneralResponseData> response = do_QueryInterface(aData); 431 MOZ_ASSERT(response); 432 IPCGeneralResponse data; 433 NS_ENSURE_SUCCESS(response->GetData(data.data()), NS_ERROR_FAILURE); 434 aIPCData = data; 435 break; 436 } 437 case nsIPaymentResponseData::BASICCARD_RESPONSE: { 438 nsCOMPtr<nsIBasicCardResponseData> response = do_QueryInterface(aData); 439 MOZ_ASSERT(response); 440 IPCBasicCardResponse data; 441 NS_ENSURE_SUCCESS(response->GetCardholderName(data.cardholderName()), 442 NS_ERROR_FAILURE); 443 NS_ENSURE_SUCCESS(response->GetCardNumber(data.cardNumber()), 444 NS_ERROR_FAILURE); 445 NS_ENSURE_SUCCESS(response->GetExpiryMonth(data.expiryMonth()), 446 NS_ERROR_FAILURE); 447 NS_ENSURE_SUCCESS(response->GetExpiryYear(data.expiryYear()), 448 NS_ERROR_FAILURE); 449 NS_ENSURE_SUCCESS(response->GetCardSecurityCode(data.cardSecurityCode()), 450 NS_ERROR_FAILURE); 451 nsCOMPtr<nsIPaymentAddress> address; 452 NS_ENSURE_SUCCESS(response->GetBillingAddress(getter_AddRefs(address)), 453 NS_ERROR_FAILURE); 454 IPCPaymentAddress ipcAddress; 455 NS_ENSURE_SUCCESS(SerializeAddress(ipcAddress, address), 456 NS_ERROR_FAILURE); 457 data.billingAddress() = ipcAddress; 458 aIPCData = data; 459 break; 460 } 461 default: { 462 return NS_ERROR_FAILURE; 463 } 464 } 465 return NS_OK; 466 } 467 } // namespace mozilla::dom