8
8
9
9
#include < utility>
10
10
11
+ #include " base/bind.h"
11
12
#include " base/location.h"
12
13
#include " base/stl_util.h"
13
14
#include " build/build_config.h"
@@ -93,6 +94,9 @@ using ::payments::mojom::blink::PaymentValidationErrorsPtr;
93
94
const char kHasEnrolledInstrumentDebugName [] = " hasEnrolledInstrument" ;
94
95
const char kGooglePayMethod [] = " https://google.com/pay" ;
95
96
const char kAndroidPayMethod [] = " https://android.com/pay" ;
97
+ const char kGooglePlayBillingMethod [] = " https://play.google.com/billing" ;
98
+ const char kUnknownCurrency [] = " ZZZ" ;
99
+ const char kAppStoreBillingLabelPlaceHolder [] = " AppStoreBillingPlaceHolder" ;
96
100
97
101
} // namespace
98
102
@@ -266,6 +270,18 @@ void ValidateShippingOptionOrPaymentItem(const T* item,
266
270
}
267
271
}
268
272
273
+ bool RequestingOnlyAppStoreBillingMethods (
274
+ const Vector<payments::mojom::blink::PaymentMethodDataPtr>& method_data) {
275
+ DCHECK (!method_data.IsEmpty ());
276
+ static const WTF::HashSet<String> app_store_billing_methods = {
277
+ kGooglePlayBillingMethod };
278
+ for (const auto & method : method_data) {
279
+ if (!app_store_billing_methods.Contains (method->supported_method ))
280
+ return false ;
281
+ }
282
+ return true ;
283
+ }
284
+
269
285
void ValidateAndConvertDisplayItems (
270
286
const HeapVector<Member<PaymentItem>>& input,
271
287
const String& item_names,
@@ -504,17 +520,50 @@ void ValidateAndConvertPaymentDetailsBase(const PaymentDetailsBase* input,
504
520
}
505
521
}
506
522
523
+ PaymentItemPtr CreateTotalPlaceHolderForAppStoreBilling (
524
+ ExecutionContext& execution_context) {
525
+ PaymentItemPtr total = payments::mojom::blink::PaymentItem::New ();
526
+ total->label = kAppStoreBillingLabelPlaceHolder ;
527
+ total->amount = payments::mojom::blink::PaymentCurrencyAmount::New ();
528
+ total->amount ->currency = kUnknownCurrency ;
529
+ total->amount ->value = " 0" ;
530
+
531
+ return total;
532
+ }
533
+
507
534
void ValidateAndConvertPaymentDetailsInit (const PaymentDetailsInit* input,
508
535
const PaymentOptions* options,
509
536
PaymentDetailsPtr& output,
510
537
String& shipping_option_output,
538
+ bool ignore_total,
511
539
ExecutionContext& execution_context,
512
540
ExceptionState& exception_state) {
513
- DCHECK (input->hasTotal ());
514
- ValidateAndConvertTotal (input->total (), " total" , output->total ,
515
- execution_context, exception_state);
516
- if (exception_state.HadException ())
517
- return ;
541
+ if (ignore_total) {
542
+ output->total = CreateTotalPlaceHolderForAppStoreBilling (execution_context);
543
+ if (input->hasTotal ()) {
544
+ execution_context.AddConsoleMessage (MakeGarbageCollected<ConsoleMessage>(
545
+ mojom::blink::ConsoleMessageSource::kJavaScript ,
546
+ mojom::blink::ConsoleMessageLevel::kWarning ,
547
+ " Specified total is ignored for in-app purchases with app stores. "
548
+ " User will be shown the total derived from the product identifier." ));
549
+ }
550
+ } else {
551
+ // Whether details (i.e., input) being omitted, null, defined or {} is
552
+ // indistinguishable, so we check all of its attributes to decide whether it
553
+ // has been provided.
554
+ if (!input->hasTotal () && !input->hasId ()) {
555
+ exception_state.ThrowTypeError (" required member details is undefined." );
556
+ return ;
557
+ }
558
+ if (!input->hasTotal ()) {
559
+ exception_state.ThrowTypeError (" required member total is undefined." );
560
+ return ;
561
+ }
562
+ ValidateAndConvertTotal (input->total (), " total" , output->total ,
563
+ execution_context, exception_state);
564
+ if (exception_state.HadException ())
565
+ return ;
566
+ }
518
567
519
568
ValidateAndConvertPaymentDetailsBase (input, options, output,
520
569
shipping_option_output,
@@ -525,19 +574,26 @@ void ValidateAndConvertPaymentDetailsUpdate(const PaymentDetailsUpdate* input,
525
574
const PaymentOptions* options,
526
575
PaymentDetailsPtr& output,
527
576
String& shipping_option_output,
577
+ bool ignore_total,
528
578
ExecutionContext& execution_context,
529
579
ExceptionState& exception_state) {
530
580
ValidateAndConvertPaymentDetailsBase (input, options, output,
531
581
shipping_option_output,
532
582
execution_context, exception_state);
533
583
if (exception_state.HadException ())
534
584
return ;
535
-
536
585
if (input->hasTotal ()) {
537
- ValidateAndConvertTotal (input->total (), " total" , output->total ,
538
- execution_context, exception_state);
539
- if (exception_state.HadException ())
540
- return ;
586
+ DCHECK (!RuntimeEnabledFeatures::PaymentRequestOptionalTotalEnabled () ||
587
+ !ignore_total);
588
+ if (ignore_total) {
589
+ output->total =
590
+ CreateTotalPlaceHolderForAppStoreBilling (execution_context);
591
+ } else {
592
+ ValidateAndConvertTotal (input->total (), " total" , output->total ,
593
+ execution_context, exception_state);
594
+ if (exception_state.HadException ())
595
+ return ;
596
+ }
541
597
}
542
598
543
599
if (input->hasError ()) {
@@ -665,9 +721,9 @@ PaymentRequest* PaymentRequest::Create(
665
721
const HeapVector<Member<PaymentMethodData>>& method_data,
666
722
const PaymentDetailsInit* details,
667
723
ExceptionState& exception_state) {
668
- return MakeGarbageCollected<PaymentRequest>(execution_context, method_data,
669
- details, PaymentOptions::Create (),
670
- exception_state);
724
+ return MakeGarbageCollected<PaymentRequest>(
725
+ execution_context, method_data, details, PaymentOptions::Create (),
726
+ mojo::NullRemote (), exception_state);
671
727
}
672
728
673
729
PaymentRequest* PaymentRequest::Create (
@@ -677,7 +733,8 @@ PaymentRequest* PaymentRequest::Create(
677
733
const PaymentOptions* options,
678
734
ExceptionState& exception_state) {
679
735
return MakeGarbageCollected<PaymentRequest>(
680
- execution_context, method_data, details, options, exception_state);
736
+ execution_context, method_data, details, options, mojo::NullRemote (),
737
+ exception_state);
681
738
}
682
739
683
740
PaymentRequest::~PaymentRequest () = default ;
@@ -982,7 +1039,7 @@ void PaymentRequest::OnUpdatePaymentDetails(
982
1039
PaymentDetailsPtr validated_details =
983
1040
payments::mojom::blink::PaymentDetails::New ();
984
1041
ValidateAndConvertPaymentDetailsUpdate (
985
- details, options_, validated_details, shipping_option_,
1042
+ details, options_, validated_details, shipping_option_, ignore_total_,
986
1043
*GetExecutionContext (), exception_state);
987
1044
if (exception_state.HadException ()) {
988
1045
resolver->Reject (exception_state.GetException ());
@@ -1067,6 +1124,8 @@ PaymentRequest::PaymentRequest(
1067
1124
const HeapVector<Member<PaymentMethodData>>& method_data,
1068
1125
const PaymentDetailsInit* details,
1069
1126
const PaymentOptions* options,
1127
+ mojo::PendingRemote<payments::mojom::blink::PaymentRequest>
1128
+ mock_payment_provider,
1070
1129
ExceptionState& exception_state)
1071
1130
: ExecutionContextLifecycleObserver(execution_context),
1072
1131
options_ (options),
@@ -1081,8 +1140,8 @@ PaymentRequest::PaymentRequest(
1081
1140
this,
1082
1141
&PaymentRequest::OnUpdatePaymentDetailsTimeout),
1083
1142
is_waiting_for_show_promise_to_resolve_(false ) {
1143
+ DCHECK (details);
1084
1144
DCHECK (GetExecutionContext ()->IsSecureContext ());
1085
-
1086
1145
if (!AllowedToUsePaymentRequest (execution_context)) {
1087
1146
exception_state.ThrowSecurityError (
1088
1147
" Must be in a top-level browsing context or an iframe needs to specify "
@@ -1114,9 +1173,12 @@ PaymentRequest::PaymentRequest(
1114
1173
if (exception_state.HadException ())
1115
1174
return ;
1116
1175
1176
+ ignore_total_ =
1177
+ RuntimeEnabledFeatures::PaymentRequestOptionalTotalEnabled () &&
1178
+ RequestingOnlyAppStoreBillingMethods (validated_method_data);
1117
1179
ValidateAndConvertPaymentDetailsInit (details, options_, validated_details,
1118
- shipping_option_, * GetExecutionContext () ,
1119
- exception_state);
1180
+ shipping_option_, ignore_total_ ,
1181
+ * GetExecutionContext (), exception_state);
1120
1182
if (exception_state.HadException ())
1121
1183
return ;
1122
1184
@@ -1143,8 +1205,14 @@ PaymentRequest::PaymentRequest(
1143
1205
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
1144
1206
execution_context->GetTaskRunner (TaskType::kUserInteraction );
1145
1207
1146
- GetFrame ()->GetBrowserInterfaceBroker ().GetInterface (
1147
- payment_provider_.BindNewPipeAndPassReceiver (task_runner));
1208
+ if (mock_payment_provider) {
1209
+ payment_provider_.Bind (
1210
+ std::move (mock_payment_provider),
1211
+ execution_context->GetTaskRunner (TaskType::kMiscPlatformAPI ));
1212
+ } else {
1213
+ GetFrame ()->GetBrowserInterfaceBroker ().GetInterface (
1214
+ payment_provider_.BindNewPipeAndPassReceiver (task_runner));
1215
+ }
1148
1216
payment_provider_.set_disconnect_handler (
1149
1217
WTF::Bind (&PaymentRequest::OnConnectionError, WrapWeakPersistent (this )));
1150
1218
0 commit comments