PaymentRequestUpdateEvent.cpp (5103B)
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/dom/PaymentRequestUpdateEvent.h" 8 9 #include "mozilla/dom/PaymentRequest.h" 10 #include "mozilla/dom/RootedDictionary.h" 11 12 namespace mozilla::dom { 13 14 NS_IMPL_CYCLE_COLLECTION_INHERITED(PaymentRequestUpdateEvent, Event, mRequest) 15 16 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(PaymentRequestUpdateEvent, Event) 17 NS_IMPL_CYCLE_COLLECTION_TRACE_END 18 19 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PaymentRequestUpdateEvent) 20 NS_INTERFACE_MAP_END_INHERITING(Event) 21 22 NS_IMPL_ADDREF_INHERITED(PaymentRequestUpdateEvent, Event) 23 NS_IMPL_RELEASE_INHERITED(PaymentRequestUpdateEvent, Event) 24 25 already_AddRefed<PaymentRequestUpdateEvent> 26 PaymentRequestUpdateEvent::Constructor( 27 mozilla::dom::EventTarget* aOwner, const nsAString& aType, 28 const PaymentRequestUpdateEventInit& aEventInitDict) { 29 RefPtr<PaymentRequestUpdateEvent> e = new PaymentRequestUpdateEvent(aOwner); 30 bool trusted = e->Init(aOwner); 31 e->InitEvent(aType, aEventInitDict.mBubbles, aEventInitDict.mCancelable); 32 e->SetTrusted(trusted); 33 e->SetComposed(aEventInitDict.mComposed); 34 return e.forget(); 35 } 36 37 already_AddRefed<PaymentRequestUpdateEvent> 38 PaymentRequestUpdateEvent::Constructor( 39 const GlobalObject& aGlobal, const nsAString& aType, 40 const PaymentRequestUpdateEventInit& aEventInitDict) { 41 nsCOMPtr<mozilla::dom::EventTarget> owner = 42 do_QueryInterface(aGlobal.GetAsSupports()); 43 return Constructor(owner, aType, aEventInitDict); 44 } 45 46 PaymentRequestUpdateEvent::PaymentRequestUpdateEvent(EventTarget* aOwner) 47 : Event(aOwner, nullptr, nullptr), 48 mWaitForUpdate(false), 49 mRequest(nullptr) { 50 MOZ_ASSERT(aOwner); 51 } 52 53 void PaymentRequestUpdateEvent::ResolvedCallback(JSContext* aCx, 54 JS::Handle<JS::Value> aValue, 55 ErrorResult& aRv) { 56 MOZ_ASSERT(aCx); 57 MOZ_ASSERT(mRequest); 58 if (!mRequest->InFullyActiveDocument()) { 59 return; 60 } 61 62 if (NS_WARN_IF(!aValue.isObject()) || !mWaitForUpdate) { 63 return; 64 } 65 66 ErrorResult rv; 67 // Converting value to a PaymentDetailsUpdate dictionary 68 RootedDictionary<PaymentDetailsUpdate> details(aCx); 69 if (!details.Init(aCx, aValue)) { 70 rv.StealExceptionFromJSContext(aCx); 71 mRequest->AbortUpdate(rv); 72 return; 73 } 74 75 // Validate and canonicalize the details 76 // requestShipping must be true here. PaymentRequestUpdateEvent is only 77 // dispatched when shippingAddress/shippingOption is changed, and it also 78 // means Options.RequestShipping must be true while creating the corresponding 79 // PaymentRequest. 80 mRequest->IsValidDetailsUpdate(details, true /*aRequestShipping*/, rv); 81 if (rv.Failed()) { 82 mRequest->AbortUpdate(rv); 83 return; 84 } 85 86 // Update the PaymentRequest with the new details 87 mRequest->UpdatePayment(aCx, details, rv); 88 if (rv.Failed()) { 89 mRequest->AbortUpdate(rv); 90 return; 91 } 92 93 mWaitForUpdate = false; 94 mRequest->SetUpdating(false); 95 } 96 97 void PaymentRequestUpdateEvent::RejectedCallback(JSContext* aCx, 98 JS::Handle<JS::Value> aValue, 99 ErrorResult& aRv) { 100 MOZ_ASSERT(mRequest); 101 if (!mRequest->InFullyActiveDocument()) { 102 return; 103 } 104 105 ErrorResult rejectReason; 106 rejectReason.ThrowAbortError( 107 "Details promise for PaymentRequestUpdateEvent.updateWith() is rejected " 108 "by merchant"); 109 mRequest->AbortUpdate(rejectReason); 110 mWaitForUpdate = false; 111 mRequest->SetUpdating(false); 112 } 113 114 void PaymentRequestUpdateEvent::UpdateWith(Promise& aPromise, 115 ErrorResult& aRv) { 116 if (!IsTrusted()) { 117 aRv.ThrowInvalidStateError("Called on an untrusted event"); 118 return; 119 } 120 121 MOZ_ASSERT(mRequest); 122 if (!mRequest->InFullyActiveDocument()) { 123 return; 124 } 125 126 if (mWaitForUpdate || !mRequest->ReadyForUpdate()) { 127 aRv.ThrowInvalidStateError( 128 "The PaymentRequestUpdateEvent is waiting for update"); 129 return; 130 } 131 132 if (!mRequest->ReadyForUpdate()) { 133 aRv.ThrowInvalidStateError( 134 "The PaymentRequest state is not eInteractive or is the PaymentRequest " 135 "is updating"); 136 return; 137 } 138 139 aPromise.AppendNativeHandler(this); 140 141 StopPropagation(); 142 StopImmediatePropagation(); 143 mWaitForUpdate = true; 144 mRequest->SetUpdating(true); 145 } 146 147 void PaymentRequestUpdateEvent::SetRequest(PaymentRequest* aRequest) { 148 MOZ_ASSERT(IsTrusted()); 149 MOZ_ASSERT(!mRequest); 150 MOZ_ASSERT(aRequest); 151 152 mRequest = aRequest; 153 } 154 155 PaymentRequestUpdateEvent::~PaymentRequestUpdateEvent() = default; 156 157 JSObject* PaymentRequestUpdateEvent::WrapObjectInternal( 158 JSContext* aCx, JS::Handle<JSObject*> aGivenProto) { 159 return PaymentRequestUpdateEvent_Binding::Wrap(aCx, this, aGivenProto); 160 } 161 162 } // namespace mozilla::dom