Commit 2a596430 authored by Jinho Bang's avatar Jinho Bang Committed by Commit Bot

PaymentRequest: Use ScriptValue for details in PaymentResponse

This patch is initiated from this comment[1].
After this patch, the following small bugs are also fixed.
  - The PaymentResponse.details should always return same object.
  - If no details, should return empty object instead of undefined.

[1] https://chromium-review.googlesource.com/c/chromium/src/+/1226774/6/third_party/blink/renderer/modules/payments/payment_method_change_event.h#42

Bug: none
Change-Id: Ib784013fbdedd42d30eb820a82d51ec4d08550f4
Reviewed-on: https://chromium-review.googlesource.com/c/1253862
Commit-Queue: Jinho Bang <jinho.bang@samsung.com>
Reviewed-by: default avatarYuki Shiino <yukishiino@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Reviewed-by: default avatarRouslan Solomakhin <rouslan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#596143}
parent 86172124
...@@ -1222,7 +1222,8 @@ void PaymentRequest::OnPaymentResponse(PaymentResponsePtr response) { ...@@ -1222,7 +1222,8 @@ void PaymentRequest::OnPaymentResponse(PaymentResponsePtr response) {
if (retry_resolver_) { if (retry_resolver_) {
DCHECK(payment_response_); DCHECK(payment_response_);
payment_response_->Update(std::move(response), shipping_address_.Get()); payment_response_->Update(retry_resolver_->GetScriptState(),
std::move(response), shipping_address_.Get());
retry_resolver_->Resolve(); retry_resolver_->Resolve();
// Do not close the mojo connection here. The merchant website should call // Do not close the mojo connection here. The merchant website should call
...@@ -1230,9 +1231,9 @@ void PaymentRequest::OnPaymentResponse(PaymentResponsePtr response) { ...@@ -1230,9 +1231,9 @@ void PaymentRequest::OnPaymentResponse(PaymentResponsePtr response) {
// connection to display a success or failure message to the user. // connection to display a success or failure message to the user.
retry_resolver_.Clear(); retry_resolver_.Clear();
} else if (accept_resolver_) { } else if (accept_resolver_) {
payment_response_ = payment_response_ = new PaymentResponse(accept_resolver_->GetScriptState(),
new PaymentResponse(GetExecutionContext(), std::move(response), std::move(response),
shipping_address_.Get(), this, id_); shipping_address_.Get(), this, id_);
accept_resolver_->Resolve(payment_response_); accept_resolver_->Resolve(payment_response_);
// Do not close the mojo connection here. The merchant website should call // Do not close the mojo connection here. The merchant website should call
......
...@@ -10,20 +10,20 @@ ...@@ -10,20 +10,20 @@
#include "third_party/blink/renderer/modules/payments/payment_state_resolver.h" #include "third_party/blink/renderer/modules/payments/payment_state_resolver.h"
#include "third_party/blink/renderer/modules/payments/payment_validation_errors.h" #include "third_party/blink/renderer/modules/payments/payment_validation_errors.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h" #include "third_party/blink/renderer/platform/wtf/assertions.h"
namespace blink { namespace blink {
PaymentResponse::PaymentResponse( PaymentResponse::PaymentResponse(
ExecutionContext* execution_context, ScriptState* script_state,
payments::mojom::blink::PaymentResponsePtr response, payments::mojom::blink::PaymentResponsePtr response,
PaymentAddress* shipping_address, PaymentAddress* shipping_address,
PaymentStateResolver* payment_state_resolver, PaymentStateResolver* payment_state_resolver,
const String& requestId) const String& request_id)
: ContextLifecycleObserver(execution_context), : ContextLifecycleObserver(ExecutionContext::From(script_state)),
requestId_(requestId), request_id_(request_id),
method_name_(response->method_name), method_name_(response->method_name),
stringified_details_(response->stringified_details),
shipping_address_(shipping_address), shipping_address_(shipping_address),
shipping_option_(response->shipping_option), shipping_option_(response->shipping_option),
payer_name_(response->payer->name), payer_name_(response->payer->name),
...@@ -31,22 +31,24 @@ PaymentResponse::PaymentResponse( ...@@ -31,22 +31,24 @@ PaymentResponse::PaymentResponse(
payer_phone_(response->payer->phone), payer_phone_(response->payer->phone),
payment_state_resolver_(payment_state_resolver) { payment_state_resolver_(payment_state_resolver) {
DCHECK(payment_state_resolver_); DCHECK(payment_state_resolver_);
UpdateDetailsFromJSON(script_state, response->stringified_details);
} }
PaymentResponse::~PaymentResponse() = default; PaymentResponse::~PaymentResponse() = default;
void PaymentResponse::Update( void PaymentResponse::Update(
ScriptState* script_state,
payments::mojom::blink::PaymentResponsePtr response, payments::mojom::blink::PaymentResponsePtr response,
PaymentAddress* shipping_address) { PaymentAddress* shipping_address) {
DCHECK(response); DCHECK(response);
DCHECK(response->payer); DCHECK(response->payer);
method_name_ = response->method_name; method_name_ = response->method_name;
stringified_details_ = response->stringified_details;
shipping_address_ = shipping_address; shipping_address_ = shipping_address;
shipping_option_ = response->shipping_option; shipping_option_ = response->shipping_option;
payer_name_ = response->payer->name; payer_name_ = response->payer->name;
payer_email_ = response->payer->email; payer_email_ = response->payer->email;
payer_phone_ = response->payer->phone; payer_phone_ = response->payer->phone;
UpdateDetailsFromJSON(script_state, response->stringified_details);
} }
void PaymentResponse::UpdatePayerDetail( void PaymentResponse::UpdatePayerDetail(
...@@ -57,11 +59,33 @@ void PaymentResponse::UpdatePayerDetail( ...@@ -57,11 +59,33 @@ void PaymentResponse::UpdatePayerDetail(
payer_phone_ = detail->phone; payer_phone_ = detail->phone;
} }
void PaymentResponse::UpdateDetailsFromJSON(ScriptState* script_state,
const String& json) {
ScriptState::Scope scope(script_state);
if (json.IsEmpty()) {
details_ = V8ObjectBuilder(script_state).GetScriptValue();
return;
}
ExceptionState exception_state(script_state->GetIsolate(),
ExceptionState::kConstructionContext,
"PaymentResponse");
v8::Local<v8::Value> parsed_value =
FromJSONString(script_state->GetIsolate(), script_state->GetContext(),
json, exception_state);
if (exception_state.HadException()) {
exception_state.ClearException();
details_ = V8ObjectBuilder(script_state).GetScriptValue();
return;
}
details_ = ScriptValue(script_state, parsed_value);
}
ScriptValue PaymentResponse::toJSONForBinding(ScriptState* script_state) const { ScriptValue PaymentResponse::toJSONForBinding(ScriptState* script_state) const {
V8ObjectBuilder result(script_state); V8ObjectBuilder result(script_state);
result.AddString("requestId", requestId()); result.AddString("requestId", requestId());
result.AddString("methodName", methodName()); result.AddString("methodName", methodName());
result.Add("details", details(script_state, ASSERT_NO_EXCEPTION)); result.Add("details", details(script_state));
if (shippingAddress()) if (shippingAddress())
result.Add("shippingAddress", result.Add("shippingAddress",
...@@ -77,12 +101,8 @@ ScriptValue PaymentResponse::toJSONForBinding(ScriptState* script_state) const { ...@@ -77,12 +101,8 @@ ScriptValue PaymentResponse::toJSONForBinding(ScriptState* script_state) const {
return result.GetScriptValue(); return result.GetScriptValue();
} }
ScriptValue PaymentResponse::details(ScriptState* script_state, ScriptValue PaymentResponse::details(ScriptState* script_state) const {
ExceptionState& exception_state) const { return ScriptValue(script_state, details_.V8ValueFor(script_state));
return ScriptValue(
script_state,
FromJSONString(script_state->GetIsolate(), script_state->GetContext(),
stringified_details_, exception_state));
} }
ScriptPromise PaymentResponse::complete(ScriptState* script_state, ScriptPromise PaymentResponse::complete(ScriptState* script_state,
......
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
namespace blink { namespace blink {
class ExceptionState;
class PaymentAddress; class PaymentAddress;
class PaymentStateResolver; class PaymentStateResolver;
class PaymentValidationErrors; class PaymentValidationErrors;
...@@ -35,21 +34,24 @@ class MODULES_EXPORT PaymentResponse final ...@@ -35,21 +34,24 @@ class MODULES_EXPORT PaymentResponse final
WTF_MAKE_NONCOPYABLE(PaymentResponse); WTF_MAKE_NONCOPYABLE(PaymentResponse);
public: public:
PaymentResponse(ExecutionContext*, PaymentResponse(ScriptState* script_state,
payments::mojom::blink::PaymentResponsePtr, payments::mojom::blink::PaymentResponsePtr response,
PaymentAddress* shipping_address_, PaymentAddress* shipping_address,
PaymentStateResolver*, PaymentStateResolver* payment_state_resolver,
const String& requestId); const String& request_id);
~PaymentResponse() override; ~PaymentResponse() override;
void Update(payments::mojom::blink::PaymentResponsePtr, PaymentAddress*); void Update(ScriptState* script_state,
payments::mojom::blink::PaymentResponsePtr response,
PaymentAddress* shipping_address);
void UpdatePayerDetail(payments::mojom::blink::PayerDetailPtr); void UpdatePayerDetail(payments::mojom::blink::PayerDetailPtr);
void UpdateDetailsFromJSON(ScriptState* script_state, const String& json);
ScriptValue toJSONForBinding(ScriptState*) const; ScriptValue toJSONForBinding(ScriptState*) const;
const String& requestId() const { return requestId_; } const String& requestId() const { return request_id_; }
const String& methodName() const { return method_name_; } const String& methodName() const { return method_name_; }
ScriptValue details(ScriptState*, ExceptionState&) const; ScriptValue details(ScriptState* script_state) const;
PaymentAddress* shippingAddress() const { return shipping_address_.Get(); } PaymentAddress* shippingAddress() const { return shipping_address_.Get(); }
const String& shippingOption() const { return shipping_option_; } const String& shippingOption() const { return shipping_option_; }
const String& payerName() const { return payer_name_; } const String& payerName() const { return payer_name_; }
...@@ -69,9 +71,9 @@ class MODULES_EXPORT PaymentResponse final ...@@ -69,9 +71,9 @@ class MODULES_EXPORT PaymentResponse final
void Trace(blink::Visitor*) override; void Trace(blink::Visitor*) override;
private: private:
String requestId_; String request_id_;
String method_name_; String method_name_;
String stringified_details_; ScriptValue details_;
Member<PaymentAddress> shipping_address_; Member<PaymentAddress> shipping_address_;
String shipping_option_; String shipping_option_;
String payer_name_; String payer_name_;
......
...@@ -22,7 +22,7 @@ enum PaymentComplete { ...@@ -22,7 +22,7 @@ enum PaymentComplete {
readonly attribute DOMString requestId; readonly attribute DOMString requestId;
readonly attribute DOMString methodName; readonly attribute DOMString methodName;
[CallWith=ScriptState, RaisesException] readonly attribute object details; [CallWith=ScriptState] readonly attribute object details;
readonly attribute PaymentAddress? shippingAddress; readonly attribute PaymentAddress? shippingAddress;
readonly attribute DOMString? shippingOption; readonly attribute DOMString? shippingOption;
readonly attribute DOMString? payerName; readonly attribute DOMString? payerName;
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/bindings/core/v8/script_value.h" #include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h"
#include "third_party/blink/renderer/modules/payments/payment_address.h" #include "third_party/blink/renderer/modules/payments/payment_address.h"
#include "third_party/blink/renderer/modules/payments/payment_state_resolver.h" #include "third_party/blink/renderer/modules/payments/payment_state_resolver.h"
#include "third_party/blink/renderer/modules/payments/payment_test_helper.h" #include "third_party/blink/renderer/modules/payments/payment_test_helper.h"
...@@ -59,8 +60,8 @@ TEST(PaymentResponseTest, DataCopiedOver) { ...@@ -59,8 +60,8 @@ TEST(PaymentResponseTest, DataCopiedOver) {
MockPaymentStateResolver* complete_callback = new MockPaymentStateResolver; MockPaymentStateResolver* complete_callback = new MockPaymentStateResolver;
PaymentResponse* output = PaymentResponse* output =
new PaymentResponse(scope.GetExecutionContext(), std::move(input), new PaymentResponse(scope.GetScriptState(), std::move(input), nullptr,
nullptr, complete_callback, "id"); complete_callback, "id");
EXPECT_EQ("foo", output->methodName()); EXPECT_EQ("foo", output->methodName());
EXPECT_EQ("standardShippingOption", output->shippingOption()); EXPECT_EQ("standardShippingOption", output->shippingOption());
...@@ -69,8 +70,7 @@ TEST(PaymentResponseTest, DataCopiedOver) { ...@@ -69,8 +70,7 @@ TEST(PaymentResponseTest, DataCopiedOver) {
EXPECT_EQ("0123", output->payerPhone()); EXPECT_EQ("0123", output->payerPhone());
EXPECT_EQ("id", output->requestId()); EXPECT_EQ("id", output->requestId());
ScriptValue details = ScriptValue details = output->details(scope.GetScriptState());
output->details(scope.GetScriptState(), scope.GetExceptionState());
ASSERT_FALSE(scope.GetExceptionState().HadException()); ASSERT_FALSE(scope.GetExceptionState().HadException());
ASSERT_TRUE(details.V8Value()->IsObject()); ASSERT_TRUE(details.V8Value()->IsObject());
...@@ -84,20 +84,41 @@ TEST(PaymentResponseTest, DataCopiedOver) { ...@@ -84,20 +84,41 @@ TEST(PaymentResponseTest, DataCopiedOver) {
EXPECT_EQ(123, transaction_id.V8Value().As<v8::Number>()->Value()); EXPECT_EQ(123, transaction_id.V8Value().As<v8::Number>()->Value());
} }
TEST(PaymentResponseTest, PaymentResponseDetailsJSONObject) { TEST(PaymentResponseTest,
PaymentResponseDetailsWithUnexpectedJSONFormatString) {
V8TestingScope scope; V8TestingScope scope;
payments::mojom::blink::PaymentResponsePtr input = payments::mojom::blink::PaymentResponsePtr input =
BuildPaymentResponseForTest(); BuildPaymentResponseForTest();
input->stringified_details = "transactionId"; input->stringified_details = "transactionId";
MockPaymentStateResolver* complete_callback = new MockPaymentStateResolver; MockPaymentStateResolver* complete_callback = new MockPaymentStateResolver;
PaymentResponse* output = PaymentResponse* output =
new PaymentResponse(scope.GetExecutionContext(), std::move(input), new PaymentResponse(scope.GetScriptState(), std::move(input), nullptr,
nullptr, complete_callback, "id"); complete_callback, "id");
ScriptValue details = ScriptValue details = output->details(scope.GetScriptState());
output->details(scope.GetScriptState(), scope.GetExceptionState()); ASSERT_TRUE(details.V8Value()->IsObject());
String stringified_details = ToBlinkString<String>(
v8::JSON::Stringify(scope.GetContext(),
details.V8Value().As<v8::Object>())
.ToLocalChecked(),
kDoNotExternalize);
EXPECT_EQ("{}", stringified_details);
}
ASSERT_TRUE(scope.GetExceptionState().HadException()); TEST(PaymentResponseTest, PaymentResponseDetailsRetrunsTheSameObject) {
V8TestingScope scope;
payments::mojom::blink::PaymentResponsePtr input =
BuildPaymentResponseForTest();
input->method_name = "foo";
input->stringified_details = "{\"transactionId\": 123}";
MockPaymentStateResolver* complete_callback = new MockPaymentStateResolver;
PaymentResponse* output =
new PaymentResponse(scope.GetScriptState(), std::move(input), nullptr,
complete_callback, "id");
EXPECT_EQ(output->details(scope.GetScriptState()),
output->details(scope.GetScriptState()));
} }
TEST(PaymentResponseTest, CompleteCalledWithSuccess) { TEST(PaymentResponseTest, CompleteCalledWithSuccess) {
...@@ -108,8 +129,8 @@ TEST(PaymentResponseTest, CompleteCalledWithSuccess) { ...@@ -108,8 +129,8 @@ TEST(PaymentResponseTest, CompleteCalledWithSuccess) {
input->stringified_details = "{\"transactionId\": 123}"; input->stringified_details = "{\"transactionId\": 123}";
MockPaymentStateResolver* complete_callback = new MockPaymentStateResolver; MockPaymentStateResolver* complete_callback = new MockPaymentStateResolver;
PaymentResponse* output = PaymentResponse* output =
new PaymentResponse(scope.GetExecutionContext(), std::move(input), new PaymentResponse(scope.GetScriptState(), std::move(input), nullptr,
nullptr, complete_callback, "id"); complete_callback, "id");
EXPECT_CALL(*complete_callback, EXPECT_CALL(*complete_callback,
Complete(scope.GetScriptState(), PaymentStateResolver::kSuccess)); Complete(scope.GetScriptState(), PaymentStateResolver::kSuccess));
...@@ -125,8 +146,8 @@ TEST(PaymentResponseTest, CompleteCalledWithFailure) { ...@@ -125,8 +146,8 @@ TEST(PaymentResponseTest, CompleteCalledWithFailure) {
input->stringified_details = "{\"transactionId\": 123}"; input->stringified_details = "{\"transactionId\": 123}";
MockPaymentStateResolver* complete_callback = new MockPaymentStateResolver; MockPaymentStateResolver* complete_callback = new MockPaymentStateResolver;
PaymentResponse* output = PaymentResponse* output =
new PaymentResponse(scope.GetExecutionContext(), std::move(input), new PaymentResponse(scope.GetScriptState(), std::move(input), nullptr,
nullptr, complete_callback, "id"); complete_callback, "id");
EXPECT_CALL(*complete_callback, EXPECT_CALL(*complete_callback,
Complete(scope.GetScriptState(), PaymentStateResolver::kFail)); Complete(scope.GetScriptState(), PaymentStateResolver::kFail));
...@@ -155,8 +176,8 @@ TEST(PaymentResponseTest, JSONSerializerTest) { ...@@ -155,8 +176,8 @@ TEST(PaymentResponseTest, JSONSerializerTest) {
new PaymentAddress(std::move(input->shipping_address)); new PaymentAddress(std::move(input->shipping_address));
PaymentResponse* output = PaymentResponse* output =
new PaymentResponse(scope.GetExecutionContext(), std::move(input), new PaymentResponse(scope.GetScriptState(), std::move(input), address,
address, new MockPaymentStateResolver, "id"); new MockPaymentStateResolver, "id");
ScriptValue json_object = output->toJSONForBinding(scope.GetScriptState()); ScriptValue json_object = output->toJSONForBinding(scope.GetScriptState());
EXPECT_TRUE(json_object.IsObject()); EXPECT_TRUE(json_object.IsObject());
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment