Bug 1497219 - Rejecting PaymentRequest::API calls when the PaymentRequest is not in fully active document. r=baku

PaymentRequest API is not supported when the PaymentRequest is not in the
    fully active document. Adding bool a PaymentRequest::InFullyActiveDocument()
    method to check if the PaymentRequest is in fully active document. This
    method should be called at the start of any PaymentRequest APIs. If the
    PaymentRequest is not in fully active document, ignoring the API call and
    throw the NS_ERROR_DOM_ABORT_ERR if needed.

--HG--
extra : histedit_source : 3e8e4a73f69c639f9cc528afa586af22597ff320
This commit is contained in:
Eden Chuang 2018-12-05 15:01:45 -05:00
parent 181f24ad6b
commit 8d097c92d3
4 changed files with 100 additions and 18 deletions

View File

@ -645,6 +645,11 @@ PaymentRequest::PaymentRequest(nsPIDOMWindowInner* aWindow,
}
already_AddRefed<Promise> PaymentRequest::CanMakePayment(ErrorResult& aRv) {
if (!InFullyActiveDocument()) {
aRv.Throw(NS_ERROR_DOM_ABORT_ERR);
return nullptr;
}
if (mState != eCreated) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return nullptr;
@ -683,9 +688,13 @@ void PaymentRequest::RespondCanMakePayment(bool aResult) {
already_AddRefed<Promise> PaymentRequest::Show(
const Optional<OwningNonNull<Promise>>& aDetailsPromise, ErrorResult& aRv) {
if (!InFullyActiveDocument()) {
aRv.Throw(NS_ERROR_DOM_ABORT_ERR);
return nullptr;
}
nsIGlobalObject* global = GetOwnerGlobal();
nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(global);
MOZ_ASSERT(win);
nsIDocument* doc = win->GetExtantDoc();
if (!EventStateManager::IsHandlingUserInput()) {
@ -699,11 +708,6 @@ already_AddRefed<Promise> PaymentRequest::Show(
}
}
if (!doc || !doc->IsCurrentActiveDocument()) {
aRv.Throw(NS_ERROR_DOM_ABORT_ERR);
return nullptr;
}
if (mState != eCreated) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return nullptr;
@ -792,6 +796,11 @@ void PaymentRequest::RespondComplete() {
}
already_AddRefed<Promise> PaymentRequest::Abort(ErrorResult& aRv) {
if (!InFullyActiveDocument()) {
aRv.Throw(NS_ERROR_DOM_ABORT_ERR);
return nullptr;
}
if (mState != eInteractive) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return nullptr;
@ -872,6 +881,11 @@ nsresult PaymentRequest::UpdatePayment(JSContext* aCx,
}
void PaymentRequest::AbortUpdate(nsresult aRv) {
// perfect ignoring when the document is not fully active.
if (!InFullyActiveDocument()) {
return;
}
MOZ_ASSERT(NS_FAILED(aRv));
if (mState != eInteractive) {
@ -1055,6 +1069,10 @@ void PaymentRequest::SetOptions(const PaymentOptions& aOptions) {
void PaymentRequest::ResolvedCallback(JSContext* aCx,
JS::Handle<JS::Value> aValue) {
if (!InFullyActiveDocument()) {
return;
}
MOZ_ASSERT(aCx);
mUpdating = false;
if (NS_WARN_IF(!aValue.isObject())) {
@ -1084,10 +1102,38 @@ void PaymentRequest::ResolvedCallback(JSContext* aCx,
void PaymentRequest::RejectedCallback(JSContext* aCx,
JS::Handle<JS::Value> aValue) {
if (!InFullyActiveDocument()) {
return;
}
mUpdating = false;
AbortUpdate(NS_ERROR_DOM_ABORT_ERR);
}
bool PaymentRequest::InFullyActiveDocument() {
nsIGlobalObject* global = GetOwnerGlobal();
if (!global) {
return false;
}
nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(global);
nsIDocument* doc = win->GetExtantDoc();
if (!doc || !doc->IsCurrentActiveDocument()) {
return false;
}
// According to the definition of the fully active document, recursive
// checking the parent document are all IsCurrentActiveDocument
nsIDocument* parentDoc = doc->GetParentDocument();
while (parentDoc) {
if (parentDoc && !parentDoc->IsCurrentActiveDocument()) {
return false;
}
parentDoc = parentDoc->GetParentDocument();
}
return true;
}
void PaymentRequest::RegisterActivityObserver() {
if (nsPIDOMWindowInner* window = GetOwner()) {
nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
@ -1114,7 +1160,26 @@ void PaymentRequest::NotifyOwnerDocumentActivityChanged() {
nsIDocument* doc = window->GetExtantDoc();
NS_ENSURE_TRUE_VOID(doc);
if (!doc->IsCurrentActiveDocument()) {
if (!InFullyActiveDocument()) {
if (mState == eInteractive) {
if (mAcceptPromise) {
mAcceptPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
mAcceptPromise = nullptr;
}
if (mResponse) {
mResponse->RejectRetry(NS_ERROR_DOM_ABORT_ERR);
}
if (mAbortPromise) {
mAbortPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
mAbortPromise = nullptr;
}
}
if (mState == eCreated) {
if (mResultPromise) {
mResultPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
mResultPromise = nullptr;
}
}
RefPtr<PaymentRequestManager> mgr = PaymentRequestManager::GetSingleton();
mgr->ClosePayment(this);
}

View File

@ -203,6 +203,8 @@ class PaymentRequest final : public DOMEventTargetHelper,
void ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
void RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
bool InFullyActiveDocument();
IMPL_EVENT_HANDLER(merchantvalidation);
IMPL_EVENT_HANDLER(shippingaddresschange);
IMPL_EVENT_HANDLER(shippingoptionchange);

View File

@ -52,6 +52,9 @@ void PaymentRequestUpdateEvent::ResolvedCallback(JSContext* aCx,
JS::Handle<JS::Value> aValue) {
MOZ_ASSERT(aCx);
MOZ_ASSERT(mRequest);
if (!mRequest->InFullyActiveDocument()) {
return;
}
if (NS_WARN_IF(!aValue.isObject()) || !mWaitForUpdate) {
return;
@ -89,6 +92,9 @@ void PaymentRequestUpdateEvent::ResolvedCallback(JSContext* aCx,
void PaymentRequestUpdateEvent::RejectedCallback(JSContext* aCx,
JS::Handle<JS::Value> aValue) {
MOZ_ASSERT(mRequest);
if (!mRequest->InFullyActiveDocument()) {
return;
}
mRequest->AbortUpdate(NS_ERROR_DOM_ABORT_ERR);
mWaitForUpdate = false;
@ -103,6 +109,9 @@ void PaymentRequestUpdateEvent::UpdateWith(Promise& aPromise,
}
MOZ_ASSERT(mRequest);
if (!mRequest->InFullyActiveDocument()) {
return;
}
if (mWaitForUpdate || !mRequest->ReadyForUpdate()) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);

View File

@ -176,6 +176,12 @@ already_AddRefed<PaymentAddress> PaymentResponse::GetShippingAddress() const {
already_AddRefed<Promise> PaymentResponse::Complete(PaymentComplete result,
ErrorResult& aRv) {
MOZ_ASSERT(mRequest);
if (!mRequest->InFullyActiveDocument()) {
aRv.Throw(NS_ERROR_DOM_ABORT_ERR);
return nullptr;
}
if (mCompleteCalled) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return nullptr;
@ -226,6 +232,12 @@ void PaymentResponse::RespondComplete() {
already_AddRefed<Promise> PaymentResponse::Retry(
JSContext* aCx, const PaymentValidationErrors& aErrors, ErrorResult& aRv) {
MOZ_ASSERT(mRequest);
if (!mRequest->InFullyActiveDocument()) {
aRv.Throw(NS_ERROR_DOM_ABORT_ERR);
return nullptr;
}
nsIGlobalObject* global = GetOwner()->AsGlobal();
ErrorResult errResult;
RefPtr<Promise> promise = Promise::Create(global, errResult);
@ -239,17 +251,6 @@ already_AddRefed<Promise> PaymentResponse::Retry(
mTimer = nullptr;
}
if (NS_WARN_IF(!GetOwner())) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
nsIDocument* doc = GetOwner()->GetExtantDoc();
if (!doc || !doc->IsCurrentActiveDocument()) {
promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
return promise.forget();
}
if (mCompleteCalled || mRetryPromise) {
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
return promise.forget();
@ -413,6 +414,11 @@ nsresult PaymentResponse::ValidatePaymentValidationErrors(
NS_IMETHODIMP
PaymentResponse::Notify(nsITimer* timer) {
mTimer = nullptr;
if (!mRequest->InFullyActiveDocument()) {
return NS_OK;
}
if (mCompleteCalled) {
return NS_OK;
}