Skip to content

Commit

Permalink
[PlayBilling] Total optional on only app-store billing requested
Browse files Browse the repository at this point in the history
Context:
Total is a field in the "new PaymentRequest()" API. It specifies the
amount and currency of the payment request. However, when the merchant
requests for the app-store billing (e.g., Google Play Store billing -
by specifying "https://play.google.com/billing" as the method), the
total field becomes unnecessary. This is because app-stores takes
the total from elsewhere.

Before:
The total field is mandatory for PaymentRequest.

After:
The total field is optional if only app-store methods are requested.
When total field is optional and left out, Chrome would add a total of
amount 0, currency "ZZZ" and label "AppStoreBillingTotalPlaceHolder".

Change:
* Added a RuntimeEnabledFeature: PaymentRequestTotalOptional
* Added an about flag: payment-request-optional-total
* change the optionality of the total field and details field of
PaymentRequest API.

Related Doc:
* Chrome Status: https://www.chromestatus.com/feature/5226111782879232
* Intent to Prototype: https://groups.google.com/a/chromium.org/forum/#!msg/blink-dev/TJVn0Ps9ugA/3unr2Vo8AgAJ
* W3C explainer: w3c/payment-request#912

Bug: 1066531

Change-Id: Id5ad87b9fc452fd41a1ebef066d981737545a235
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2150974
Reviewed-by: Rouslan Solomakhin <rouslan@chromium.org>
Reviewed-by: Yaron Friedman <yfriedman@chromium.org>
Reviewed-by: David Bokan <bokan@chromium.org>
Commit-Queue: Liquan (Max) Gu <maxlg@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#769914}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: f8f56a44e023414f59c86350cea68ae4cf8009aa
  • Loading branch information
maxlgu authored and Commit Bot committed May 19, 2020
1 parent c600b9e commit 7c618ac
Show file tree
Hide file tree
Showing 16 changed files with 508 additions and 25 deletions.
1 change: 1 addition & 0 deletions blink/public/platform/web_runtime_features.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ class WebRuntimeFeatures {
BLINK_PLATFORM_EXPORT static void EnablePagePopup(bool);
BLINK_PLATFORM_EXPORT static void EnablePaymentApp(bool);
BLINK_PLATFORM_EXPORT static void EnablePaymentHandlerMinimalUI(bool);
BLINK_PLATFORM_EXPORT static void EnablePaymentRequestOptionalTotal(bool);
BLINK_PLATFORM_EXPORT static void EnablePaymentRequest(bool);
BLINK_PLATFORM_EXPORT static void EnablePercentBasedScrolling(bool);
BLINK_PLATFORM_EXPORT static void EnablePerformanceManagerInstrumentation(
Expand Down
1 change: 1 addition & 0 deletions blink/renderer/modules/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ jumbo_source_set("unit_tests") {
"payments/payment_address_test.cc",
"payments/payment_event_data_conversion_test.cc",
"payments/payment_request_details_test.cc",
"payments/payment_request_optional_total_test.cc",
"payments/payment_request_test.cc",
"payments/payment_request_update_event_test.cc",
"payments/payment_response_test.cc",
Expand Down
4 changes: 2 additions & 2 deletions blink/renderer/modules/payments/payment_details_init.idl
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// https://w3c.github.io/browser-payment-api/#paymentdetailsinit-dictionary
// https://w3c.github.io/payment-request/#paymentdetailsinit-dictionary

dictionary PaymentDetailsInit : PaymentDetailsBase {
DOMString id;
required PaymentItem total;
PaymentItem total;
};
108 changes: 88 additions & 20 deletions blink/renderer/modules/payments/payment_request.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include <utility>

#include "base/bind.h"
#include "base/location.h"
#include "base/stl_util.h"
#include "build/build_config.h"
Expand Down Expand Up @@ -93,6 +94,9 @@ using ::payments::mojom::blink::PaymentValidationErrorsPtr;
const char kHasEnrolledInstrumentDebugName[] = "hasEnrolledInstrument";
const char kGooglePayMethod[] = "https://google.com/pay";
const char kAndroidPayMethod[] = "https://android.com/pay";
const char kGooglePlayBillingMethod[] = "https://play.google.com/billing";
const char kUnknownCurrency[] = "ZZZ";
const char kAppStoreBillingLabelPlaceHolder[] = "AppStoreBillingPlaceHolder";

} // namespace

Expand Down Expand Up @@ -266,6 +270,18 @@ void ValidateShippingOptionOrPaymentItem(const T* item,
}
}

bool RequestingOnlyAppStoreBillingMethods(
const Vector<payments::mojom::blink::PaymentMethodDataPtr>& method_data) {
DCHECK(!method_data.IsEmpty());
static const WTF::HashSet<String> app_store_billing_methods = {
kGooglePlayBillingMethod};
for (const auto& method : method_data) {
if (!app_store_billing_methods.Contains(method->supported_method))
return false;
}
return true;
}

void ValidateAndConvertDisplayItems(
const HeapVector<Member<PaymentItem>>& input,
const String& item_names,
Expand Down Expand Up @@ -504,17 +520,50 @@ void ValidateAndConvertPaymentDetailsBase(const PaymentDetailsBase* input,
}
}

PaymentItemPtr CreateTotalPlaceHolderForAppStoreBilling(
ExecutionContext& execution_context) {
PaymentItemPtr total = payments::mojom::blink::PaymentItem::New();
total->label = kAppStoreBillingLabelPlaceHolder;
total->amount = payments::mojom::blink::PaymentCurrencyAmount::New();
total->amount->currency = kUnknownCurrency;
total->amount->value = "0";

return total;
}

void ValidateAndConvertPaymentDetailsInit(const PaymentDetailsInit* input,
const PaymentOptions* options,
PaymentDetailsPtr& output,
String& shipping_option_output,
bool ignore_total,
ExecutionContext& execution_context,
ExceptionState& exception_state) {
DCHECK(input->hasTotal());
ValidateAndConvertTotal(input->total(), "total", output->total,
execution_context, exception_state);
if (exception_state.HadException())
return;
if (ignore_total) {
output->total = CreateTotalPlaceHolderForAppStoreBilling(execution_context);
if (input->hasTotal()) {
execution_context.AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
mojom::blink::ConsoleMessageSource::kJavaScript,
mojom::blink::ConsoleMessageLevel::kWarning,
"Specified total is ignored for in-app purchases with app stores. "
"User will be shown the total derived from the product identifier."));
}
} else {
// Whether details (i.e., input) being omitted, null, defined or {} is
// indistinguishable, so we check all of its attributes to decide whether it
// has been provided.
if (!input->hasTotal() && !input->hasId()) {
exception_state.ThrowTypeError("required member details is undefined.");
return;
}
if (!input->hasTotal()) {
exception_state.ThrowTypeError("required member total is undefined.");
return;
}
ValidateAndConvertTotal(input->total(), "total", output->total,
execution_context, exception_state);
if (exception_state.HadException())
return;
}

ValidateAndConvertPaymentDetailsBase(input, options, output,
shipping_option_output,
Expand All @@ -525,19 +574,26 @@ void ValidateAndConvertPaymentDetailsUpdate(const PaymentDetailsUpdate* input,
const PaymentOptions* options,
PaymentDetailsPtr& output,
String& shipping_option_output,
bool ignore_total,
ExecutionContext& execution_context,
ExceptionState& exception_state) {
ValidateAndConvertPaymentDetailsBase(input, options, output,
shipping_option_output,
execution_context, exception_state);
if (exception_state.HadException())
return;

if (input->hasTotal()) {
ValidateAndConvertTotal(input->total(), "total", output->total,
execution_context, exception_state);
if (exception_state.HadException())
return;
DCHECK(!RuntimeEnabledFeatures::PaymentRequestOptionalTotalEnabled() ||
!ignore_total);
if (ignore_total) {
output->total =
CreateTotalPlaceHolderForAppStoreBilling(execution_context);
} else {
ValidateAndConvertTotal(input->total(), "total", output->total,
execution_context, exception_state);
if (exception_state.HadException())
return;
}
}

if (input->hasError()) {
Expand Down Expand Up @@ -665,9 +721,9 @@ PaymentRequest* PaymentRequest::Create(
const HeapVector<Member<PaymentMethodData>>& method_data,
const PaymentDetailsInit* details,
ExceptionState& exception_state) {
return MakeGarbageCollected<PaymentRequest>(execution_context, method_data,
details, PaymentOptions::Create(),
exception_state);
return MakeGarbageCollected<PaymentRequest>(
execution_context, method_data, details, PaymentOptions::Create(),
mojo::NullRemote(), exception_state);
}

PaymentRequest* PaymentRequest::Create(
Expand All @@ -677,7 +733,8 @@ PaymentRequest* PaymentRequest::Create(
const PaymentOptions* options,
ExceptionState& exception_state) {
return MakeGarbageCollected<PaymentRequest>(
execution_context, method_data, details, options, exception_state);
execution_context, method_data, details, options, mojo::NullRemote(),
exception_state);
}

PaymentRequest::~PaymentRequest() = default;
Expand Down Expand Up @@ -982,7 +1039,7 @@ void PaymentRequest::OnUpdatePaymentDetails(
PaymentDetailsPtr validated_details =
payments::mojom::blink::PaymentDetails::New();
ValidateAndConvertPaymentDetailsUpdate(
details, options_, validated_details, shipping_option_,
details, options_, validated_details, shipping_option_, ignore_total_,
*GetExecutionContext(), exception_state);
if (exception_state.HadException()) {
resolver->Reject(exception_state.GetException());
Expand Down Expand Up @@ -1067,6 +1124,8 @@ PaymentRequest::PaymentRequest(
const HeapVector<Member<PaymentMethodData>>& method_data,
const PaymentDetailsInit* details,
const PaymentOptions* options,
mojo::PendingRemote<payments::mojom::blink::PaymentRequest>
mock_payment_provider,
ExceptionState& exception_state)
: ExecutionContextLifecycleObserver(execution_context),
options_(options),
Expand All @@ -1081,8 +1140,8 @@ PaymentRequest::PaymentRequest(
this,
&PaymentRequest::OnUpdatePaymentDetailsTimeout),
is_waiting_for_show_promise_to_resolve_(false) {
DCHECK(details);
DCHECK(GetExecutionContext()->IsSecureContext());

if (!AllowedToUsePaymentRequest(execution_context)) {
exception_state.ThrowSecurityError(
"Must be in a top-level browsing context or an iframe needs to specify "
Expand Down Expand Up @@ -1114,9 +1173,12 @@ PaymentRequest::PaymentRequest(
if (exception_state.HadException())
return;

ignore_total_ =
RuntimeEnabledFeatures::PaymentRequestOptionalTotalEnabled() &&
RequestingOnlyAppStoreBillingMethods(validated_method_data);
ValidateAndConvertPaymentDetailsInit(details, options_, validated_details,
shipping_option_, *GetExecutionContext(),
exception_state);
shipping_option_, ignore_total_,
*GetExecutionContext(), exception_state);
if (exception_state.HadException())
return;

Expand All @@ -1143,8 +1205,14 @@ PaymentRequest::PaymentRequest(
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
execution_context->GetTaskRunner(TaskType::kUserInteraction);

GetFrame()->GetBrowserInterfaceBroker().GetInterface(
payment_provider_.BindNewPipeAndPassReceiver(task_runner));
if (mock_payment_provider) {
payment_provider_.Bind(
std::move(mock_payment_provider),
execution_context->GetTaskRunner(TaskType::kMiscPlatformAPI));
} else {
GetFrame()->GetBrowserInterfaceBroker().GetInterface(
payment_provider_.BindNewPipeAndPassReceiver(task_runner));
}
payment_provider_.set_disconnect_handler(
WTF::Bind(&PaymentRequest::OnConnectionError, WrapWeakPersistent(this)));

Expand Down
3 changes: 3 additions & 0 deletions blink/renderer/modules/payments/payment_request.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ class MODULES_EXPORT PaymentRequest final
const HeapVector<Member<PaymentMethodData>>&,
const PaymentDetailsInit*,
const PaymentOptions*,
mojo::PendingRemote<payments::mojom::blink::PaymentRequest>
mock_payment_provider,
ExceptionState&);
~PaymentRequest() override;

Expand Down Expand Up @@ -179,6 +181,7 @@ class MODULES_EXPORT PaymentRequest final
TaskRunnerTimer<PaymentRequest> complete_timer_;
TaskRunnerTimer<PaymentRequest> update_payment_details_timer_;
bool is_waiting_for_show_promise_to_resolve_;
bool ignore_total_;

DISALLOW_COPY_AND_ASSIGN(PaymentRequest);
};
Expand Down
2 changes: 1 addition & 1 deletion blink/renderer/modules/payments/payment_request.idl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
Exposed=Window,
ActiveScriptWrappable
] interface PaymentRequest : EventTarget {
[CallWith=ExecutionContext, RaisesException] constructor(sequence<PaymentMethodData> methodData, PaymentDetailsInit details, optional PaymentOptions options = {});
[CallWith=ExecutionContext, RaisesException] constructor(sequence<PaymentMethodData> methodData, optional PaymentDetailsInit details = {}, optional PaymentOptions options = {});
[CallWith=ScriptState, RaisesException, NewObject] Promise<PaymentResponse> show(optional Promise<PaymentDetailsUpdate> detailsPromise);
[CallWith=ScriptState, RaisesException, NewObject] Promise<void> abort();
[CallWith=ScriptState, RaisesException, HighEntropy, Measure, NewObject] Promise<boolean> canMakePayment();
Expand Down
Loading

0 comments on commit 7c618ac

Please sign in to comment.