blob: 5a593181dca95683307f6ab437d60fa3a2268263 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "modules/payments/PaymentRequestRespondWithObserver.h"
#include <v8.h>
#include "bindings/core/v8/ScriptValue.h"
#include "bindings/core/v8/V8BindingForCore.h"
#include "bindings/modules/v8/V8PaymentAppResponse.h"
#include "core/dom/ExecutionContext.h"
#include "core/inspector/ConsoleMessage.h"
#include "modules/payments/PaymentAppResponse.h"
#include "modules/serviceworkers/ServiceWorkerGlobalScopeClient.h"
#include "modules/serviceworkers/WaitUntilObserver.h"
#include "public/platform/modules/payments/WebPaymentAppResponse.h"
namespace blink {
namespace {
// Returns the error message to let the developer know about the reason of the
// unusual failures.
const String GetMessageForResponseError(WebServiceWorkerResponseError error) {
String error_message =
"The respondWith() was rejected in PaymentRequestEvent: ";
switch (error) {
case kWebServiceWorkerResponseErrorPromiseRejected:
error_message = error_message + "the promise was rejected.";
break;
case kWebServiceWorkerResponseErrorDefaultPrevented:
error_message =
error_message +
"preventDefault() was called without calling respondWith().";
break;
case kWebServiceWorkerResponseErrorNoV8Instance:
error_message = error_message +
"an object that was not a PaymentResponse was passed to "
"respondWith().";
break;
case kWebServiceWorkerResponseErrorResponseTypeError:
error_message = error_message +
"the promise was resolved with an error response object.";
break;
case kWebServiceWorkerResponseErrorUnknown:
error_message = error_message + "an unexpected error occurred.";
break;
case kWebServiceWorkerResponseErrorResponseTypeOpaque:
case kWebServiceWorkerResponseErrorResponseTypeNotBasicOrDefault:
case kWebServiceWorkerResponseErrorBodyUsed:
case kWebServiceWorkerResponseErrorResponseTypeOpaqueForClientRequest:
case kWebServiceWorkerResponseErrorResponseTypeOpaqueRedirect:
case kWebServiceWorkerResponseErrorBodyLocked:
case kWebServiceWorkerResponseErrorNoForeignFetchResponse:
case kWebServiceWorkerResponseErrorForeignFetchHeadersWithoutOrigin:
case kWebServiceWorkerResponseErrorForeignFetchMismatchedOrigin:
case kWebServiceWorkerResponseErrorRedirectedResponseForNotFollowRequest:
NOTREACHED();
error_message = error_message + "an unexpected error occurred.";
break;
}
return error_message;
}
} // namespace
PaymentRequestRespondWithObserver::~PaymentRequestRespondWithObserver() {}
PaymentRequestRespondWithObserver* PaymentRequestRespondWithObserver::Create(
ExecutionContext* context,
int event_id,
WaitUntilObserver* observer) {
return new PaymentRequestRespondWithObserver(context, event_id, observer);
}
void PaymentRequestRespondWithObserver::OnResponseRejected(
WebServiceWorkerResponseError error) {
DCHECK(GetExecutionContext());
GetExecutionContext()->AddConsoleMessage(
ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel,
GetMessageForResponseError(error)));
WebPaymentAppResponse web_data;
ServiceWorkerGlobalScopeClient::From(GetExecutionContext())
->RespondToPaymentRequestEvent(event_id_, web_data, event_dispatch_time_);
}
void PaymentRequestRespondWithObserver::OnResponseFulfilled(
const ScriptValue& value) {
DCHECK(GetExecutionContext());
ExceptionState exception_state(value.GetIsolate(),
ExceptionState::kUnknownContext,
"PaymentRequestEvent", "respondWith");
PaymentAppResponse response = ScriptValue::To<PaymentAppResponse>(
ToIsolate(GetExecutionContext()), value, exception_state);
if (exception_state.HadException()) {
exception_state.ClearException();
OnResponseRejected(kWebServiceWorkerResponseErrorNoV8Instance);
return;
}
WebPaymentAppResponse web_data;
web_data.method_name = response.methodName();
v8::Local<v8::String> details_value;
if (!v8::JSON::Stringify(response.details().GetContext(),
response.details().V8Value().As<v8::Object>())
.ToLocal(&details_value)) {
OnResponseRejected(kWebServiceWorkerResponseErrorUnknown);
return;
}
web_data.stringified_details = ToCoreString(details_value);
ServiceWorkerGlobalScopeClient::From(GetExecutionContext())
->RespondToPaymentRequestEvent(event_id_, web_data, event_dispatch_time_);
}
void PaymentRequestRespondWithObserver::OnNoResponse() {
DCHECK(GetExecutionContext());
ServiceWorkerGlobalScopeClient::From(GetExecutionContext())
->RespondToPaymentRequestEvent(event_id_, WebPaymentAppResponse(),
event_dispatch_time_);
}
PaymentRequestRespondWithObserver::PaymentRequestRespondWithObserver(
ExecutionContext* context,
int event_id,
WaitUntilObserver* observer)
: RespondWithObserver(context, event_id, observer) {}
DEFINE_TRACE(PaymentRequestRespondWithObserver) {
RespondWithObserver::Trace(visitor);
}
} // namespace blink