Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(137)

Side by Side Diff: third_party/WebKit/Source/modules/payments/PaymentRequest.cpp

Issue 2851383002: Verify behavior of PaymentRequest constructor. (Closed)
Patch Set: Comments Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "modules/payments/PaymentRequest.h" 5 #include "modules/payments/PaymentRequest.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <utility> 8 #include <utility>
9 #include "bindings/core/v8/ExceptionState.h" 9 #include "bindings/core/v8/ExceptionState.h"
10 #include "bindings/core/v8/ScriptPromiseResolver.h" 10 #include "bindings/core/v8/ScriptPromiseResolver.h"
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
129 namespace { 129 namespace {
130 130
131 // If the website does not call complete() 60 seconds after show() has been 131 // If the website does not call complete() 60 seconds after show() has been
132 // resolved, then behave as if the website called complete("fail"). 132 // resolved, then behave as if the website called complete("fail").
133 static const int kCompleteTimeoutSeconds = 60; 133 static const int kCompleteTimeoutSeconds = 60;
134 134
135 // Validates ShippingOption or PaymentItem, which happen to have identical 135 // Validates ShippingOption or PaymentItem, which happen to have identical
136 // fields, except for "id", which is present only in ShippingOption. 136 // fields, except for "id", which is present only in ShippingOption.
137 template <typename T> 137 template <typename T>
138 void ValidateShippingOptionOrPaymentItem(const T& item, 138 void ValidateShippingOptionOrPaymentItem(const T& item,
139 const String& item_name,
140 ExecutionContext& execution_context,
139 ExceptionState& exception_state) { 141 ExceptionState& exception_state) {
140 if (!item.hasLabel() || item.label().IsEmpty()) { 142 DCHECK(item.hasLabel());
141 exception_state.ThrowTypeError("Item label required"); 143 DCHECK(item.hasAmount());
144 DCHECK(item.amount().hasValue());
145 DCHECK(item.amount().hasCurrency());
146
147 String error_message;
148 if (!PaymentsValidators::IsValidAmountFormat(item.amount().value(), item_name,
149 &error_message)) {
150 exception_state.ThrowTypeError(error_message);
142 return; 151 return;
143 } 152 }
144 153
145 if (!item.hasAmount()) { 154 if (item.label().IsEmpty()) {
146 exception_state.ThrowTypeError("Currency amount required"); 155 execution_context.AddConsoleMessage(ConsoleMessage::Create(
156 kJSMessageSource, kErrorMessageLevel,
157 "Empty " + item_name + " label may be confusing the user"));
147 return; 158 return;
148 } 159 }
149 160
150 if (!item.amount().hasCurrency()) {
151 exception_state.ThrowTypeError("Currency code required");
152 return;
153 }
154
155 if (!item.amount().hasValue()) {
156 exception_state.ThrowTypeError("Currency value required");
157 return;
158 }
159
160 String error_message;
161 if (!PaymentsValidators::IsValidCurrencyCodeFormat( 161 if (!PaymentsValidators::IsValidCurrencyCodeFormat(
162 item.amount().currency(), item.amount().currencySystem(), 162 item.amount().currency(), item.amount().currencySystem(),
163 &error_message)) { 163 &error_message)) {
164 exception_state.ThrowTypeError(error_message); 164 exception_state.ThrowTypeError(error_message);
165 return; 165 return;
166 } 166 }
167
168 if (!PaymentsValidators::IsValidAmountFormat(item.amount().value(),
169 &error_message)) {
170 exception_state.ThrowTypeError(error_message);
171 return;
172 }
173 } 167 }
174 168
175 void ValidateAndConvertDisplayItems(const HeapVector<PaymentItem>& input, 169 void ValidateAndConvertDisplayItems(const HeapVector<PaymentItem>& input,
170 const String& item_names,
176 Vector<PaymentItemPtr>& output, 171 Vector<PaymentItemPtr>& output,
172 ExecutionContext& execution_context,
177 ExceptionState& exception_state) { 173 ExceptionState& exception_state) {
178 for (const PaymentItem& item : input) { 174 for (const PaymentItem& item : input) {
179 ValidateShippingOptionOrPaymentItem(item, exception_state); 175 ValidateShippingOptionOrPaymentItem(item, item_names, execution_context,
176 exception_state);
180 if (exception_state.HadException()) 177 if (exception_state.HadException())
181 return; 178 return;
182 output.push_back(payments::mojom::blink::PaymentItem::From(item)); 179 output.push_back(payments::mojom::blink::PaymentItem::From(item));
183 } 180 }
184 } 181 }
185 182
186 // Validates and converts |input| shipping options into |output|. Throws an 183 // Validates and converts |input| shipping options into |output|. Throws an
187 // exception if the data is not valid, except for duplicate identifiers, which 184 // exception if the data is not valid, except for duplicate identifiers, which
188 // returns an empty |output| instead of throwing an exception. There's no need 185 // returns an empty |output| instead of throwing an exception. There's no need
189 // to clear |output| when an exception is thrown, because the caller takes care 186 // to clear |output| when an exception is thrown, because the caller takes care
190 // of deleting |output|. 187 // of deleting |output|.
191 void ValidateAndConvertShippingOptions( 188 void ValidateAndConvertShippingOptions(
192 const HeapVector<PaymentShippingOption>& input, 189 const HeapVector<PaymentShippingOption>& input,
193 Vector<PaymentShippingOptionPtr>& output, 190 Vector<PaymentShippingOptionPtr>& output,
191 String& shipping_option_output,
194 ExecutionContext& execution_context, 192 ExecutionContext& execution_context,
195 ExceptionState& exception_state) { 193 ExceptionState& exception_state) {
196 HashSet<String> unique_ids; 194 HashSet<String> unique_ids;
197 for (const PaymentShippingOption& option : input) { 195 for (const PaymentShippingOption& option : input) {
198 if (!option.hasId() || option.id().IsEmpty()) { 196 ValidateShippingOptionOrPaymentItem(option, "shippingOptions",
199 exception_state.ThrowTypeError("ShippingOption id required"); 197 execution_context, exception_state);
198 if (exception_state.HadException())
199 return;
200
201 DCHECK(option.hasId());
202 if (option.id().IsEmpty()) {
203 execution_context.AddConsoleMessage(ConsoleMessage::Create(
204 kJSMessageSource, kWarningMessageLevel,
205 "Empty shipping option ID may be hard to debug"));
200 return; 206 return;
201 } 207 }
202 208
203 if (unique_ids.Contains(option.id())) { 209 if (unique_ids.Contains(option.id())) {
204 execution_context.AddConsoleMessage(ConsoleMessage::Create( 210 execution_context.AddConsoleMessage(ConsoleMessage::Create(
205 kJSMessageSource, kWarningMessageLevel, 211 kJSMessageSource, kWarningMessageLevel,
206 "Duplicate shipping option identifier '" + option.id() + 212 "Duplicate shipping option identifier '" + option.id() +
207 "' is treated as an invalid address indicator.")); 213 "' is treated as an invalid address indicator."));
208 // Clear |output| instead of throwing an exception. 214 // Clear |output| instead of throwing an exception.
209 output.clear(); 215 output.clear();
216 shipping_option_output = String();
210 return; 217 return;
211 } 218 }
212 219
220 if (option.selected())
221 shipping_option_output = option.id();
222
213 unique_ids.insert(option.id()); 223 unique_ids.insert(option.id());
214 224
215 ValidateShippingOptionOrPaymentItem(option, exception_state);
216 if (exception_state.HadException())
217 return;
218
219 output.push_back( 225 output.push_back(
220 payments::mojom::blink::PaymentShippingOption::From(option)); 226 payments::mojom::blink::PaymentShippingOption::From(option));
221 } 227 }
222 } 228 }
223 229
224 void ValidateAndConvertTotal(const PaymentItem& input, 230 void ValidateAndConvertTotal(const PaymentItem& input,
231 const String& item_name,
225 PaymentItemPtr& output, 232 PaymentItemPtr& output,
233 ExecutionContext& execution_context,
226 ExceptionState& exception_state) { 234 ExceptionState& exception_state) {
227 ValidateShippingOptionOrPaymentItem(input, exception_state); 235 ValidateShippingOptionOrPaymentItem(input, item_name, execution_context,
236 exception_state);
228 if (exception_state.HadException()) 237 if (exception_state.HadException())
229 return; 238 return;
230 239
231 if (input.amount().value()[0] == '-') { 240 if (input.amount().value()[0] == '-') {
232 exception_state.ThrowTypeError("Total amount value should be non-negative"); 241 exception_state.ThrowTypeError("Total amount value should be non-negative");
233 return; 242 return;
234 } 243 }
235 244
236 output = payments::mojom::blink::PaymentItem::From(input); 245 output = payments::mojom::blink::PaymentItem::From(input);
237 } 246 }
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
391 } 400 }
392 } 401 }
393 402
394 void StringifyAndParseMethodSpecificData( 403 void StringifyAndParseMethodSpecificData(
395 const Vector<String>& supported_methods, 404 const Vector<String>& supported_methods,
396 const ScriptValue& input, 405 const ScriptValue& input,
397 PaymentMethodDataPtr& output, 406 PaymentMethodDataPtr& output,
398 ExecutionContext& execution_context, 407 ExecutionContext& execution_context,
399 ExceptionState& exception_state) { 408 ExceptionState& exception_state) {
400 DCHECK(!input.IsEmpty()); 409 DCHECK(!input.IsEmpty());
401 if (!input.V8Value()->IsObject() || input.V8Value()->IsArray()) { 410 v8::Local<v8::String> value;
402 exception_state.ThrowTypeError("Data should be a JSON-serializable object"); 411 if (!input.V8Value()->IsObject() ||
412 !v8::JSON::Stringify(input.GetContext(), input.V8Value().As<v8::Object>())
413 .ToLocal(&value)) {
414 exception_state.ThrowTypeError(
415 "Payment method data should be a JSON-serializable object");
403 return; 416 return;
404 } 417 }
405 418
406 v8::Local<v8::String> value;
407 if (!v8::JSON::Stringify(input.GetContext(), input.V8Value().As<v8::Object>())
408 .ToLocal(&value)) {
409 exception_state.ThrowTypeError(
410 "Unable to parse payment method specific data");
411 return;
412 }
413
414 output->stringified_data = 419 output->stringified_data =
415 V8StringToWebCoreString<String>(value, kDoNotExternalize); 420 V8StringToWebCoreString<String>(value, kDoNotExternalize);
416 421
417 // Serialize payment method specific data to be sent to the payment apps. The 422 // Serialize payment method specific data to be sent to the payment apps. The
418 // payment apps are responsible for validating and processing their method 423 // payment apps are responsible for validating and processing their method
419 // data asynchronously. Do not throw exceptions here. 424 // data asynchronously. Do not throw exceptions here.
420 if (supported_methods.Contains("https://android.com/pay") || 425 if (supported_methods.Contains("https://android.com/pay") ||
421 supported_methods.Contains("https://google.com/pay")) { 426 supported_methods.Contains("https://google.com/pay")) {
422 SetAndroidPayMethodData(input, output, exception_state); 427 SetAndroidPayMethodData(input, output, exception_state);
423 if (exception_state.HadException()) 428 if (exception_state.HadException())
424 exception_state.ClearException(); 429 exception_state.ClearException();
425 } 430 }
426 if (RuntimeEnabledFeatures::paymentRequestBasicCardEnabled() && 431 if (RuntimeEnabledFeatures::paymentRequestBasicCardEnabled() &&
427 supported_methods.Contains("basic-card")) { 432 supported_methods.Contains("basic-card")) {
428 SetBasicCardMethodData(input, output, execution_context, exception_state); 433 SetBasicCardMethodData(input, output, execution_context, exception_state);
429 if (exception_state.HadException()) 434 if (exception_state.HadException())
430 exception_state.ClearException(); 435 exception_state.ClearException();
431 } 436 }
432 } 437 }
433 438
434 void ValidateAndConvertPaymentDetailsModifiers( 439 void ValidateAndConvertPaymentDetailsModifiers(
435 const HeapVector<PaymentDetailsModifier>& input, 440 const HeapVector<PaymentDetailsModifier>& input,
436 Vector<PaymentDetailsModifierPtr>& output, 441 Vector<PaymentDetailsModifierPtr>& output,
437 ExecutionContext& execution_context, 442 ExecutionContext& execution_context,
438 ExceptionState& exception_state) { 443 ExceptionState& exception_state) {
439 if (input.IsEmpty()) {
440 exception_state.ThrowTypeError(
441 "Must specify at least one payment details modifier");
442 return;
443 }
444
445 for (const PaymentDetailsModifier& modifier : input) { 444 for (const PaymentDetailsModifier& modifier : input) {
446 output.push_back(payments::mojom::blink::PaymentDetailsModifier::New()); 445 output.push_back(payments::mojom::blink::PaymentDetailsModifier::New());
447 if (modifier.hasTotal()) { 446 if (modifier.hasTotal()) {
448 ValidateAndConvertTotal(modifier.total(), output.back()->total, 447 ValidateAndConvertTotal(modifier.total(), "modifier total",
448 output.back()->total, execution_context,
449 exception_state); 449 exception_state);
450 if (exception_state.HadException()) 450 if (exception_state.HadException())
451 return; 451 return;
452 } 452 }
453 453
454 if (modifier.hasAdditionalDisplayItems()) { 454 if (modifier.hasAdditionalDisplayItems()) {
455 ValidateAndConvertDisplayItems(modifier.additionalDisplayItems(), 455 ValidateAndConvertDisplayItems(modifier.additionalDisplayItems(),
456 "additional display items in modifier",
456 output.back()->additional_display_items, 457 output.back()->additional_display_items,
457 exception_state); 458 execution_context, exception_state);
458 if (exception_state.HadException()) 459 if (exception_state.HadException())
459 return; 460 return;
460 } 461 }
461 462
462 if (modifier.supportedMethods().IsEmpty()) { 463 if (modifier.supportedMethods().IsEmpty()) {
463 exception_state.ThrowTypeError( 464 exception_state.ThrowTypeError(
464 "Must specify at least one payment method identifier"); 465 "Must specify at least one payment method identifier");
465 return; 466 return;
466 } 467 }
467 468
468 output.back()->method_data = 469 output.back()->method_data =
469 payments::mojom::blink::PaymentMethodData::New(); 470 payments::mojom::blink::PaymentMethodData::New();
470 output.back()->method_data->supported_methods = modifier.supportedMethods(); 471 output.back()->method_data->supported_methods = modifier.supportedMethods();
471 472
472 if (modifier.hasData() && !modifier.data().IsEmpty()) { 473 if (modifier.hasData() && !modifier.data().IsEmpty()) {
473 StringifyAndParseMethodSpecificData( 474 StringifyAndParseMethodSpecificData(
474 modifier.supportedMethods(), modifier.data(), 475 modifier.supportedMethods(), modifier.data(),
475 output.back()->method_data, execution_context, exception_state); 476 output.back()->method_data, execution_context, exception_state);
476 } else { 477 } else {
477 output.back()->method_data->stringified_data = ""; 478 output.back()->method_data->stringified_data = "";
478 } 479 }
479 } 480 }
480 } 481 }
481 482
482 String GetSelectedShippingOption(
483 const Vector<PaymentShippingOptionPtr>& shipping_options) {
484 String result;
485 for (const PaymentShippingOptionPtr& shipping_option : shipping_options) {
486 if (shipping_option->selected)
487 result = shipping_option->id;
488 }
489 return result;
490 }
491
492 void ValidateAndConvertPaymentDetailsBase(const PaymentDetailsBase& input, 483 void ValidateAndConvertPaymentDetailsBase(const PaymentDetailsBase& input,
493 bool request_shipping,
494 PaymentDetailsPtr& output, 484 PaymentDetailsPtr& output,
495 String& shipping_option_output, 485 String& shipping_option_output,
496 ExecutionContext& execution_context, 486 ExecutionContext& execution_context,
497 ExceptionState& exception_state) { 487 ExceptionState& exception_state) {
498 if (input.hasDisplayItems()) { 488 if (input.hasDisplayItems()) {
499 ValidateAndConvertDisplayItems(input.displayItems(), output->display_items, 489 ValidateAndConvertDisplayItems(input.displayItems(), "display items",
490 output->display_items, execution_context,
500 exception_state); 491 exception_state);
501 if (exception_state.HadException()) 492 if (exception_state.HadException())
502 return; 493 return;
503 } 494 }
504 495
505 if (input.hasShippingOptions() && request_shipping) { 496 if (input.hasShippingOptions()) {
506 ValidateAndConvertShippingOptions(input.shippingOptions(), 497 ValidateAndConvertShippingOptions(
507 output->shipping_options, 498 input.shippingOptions(), output->shipping_options,
508 execution_context, exception_state); 499 shipping_option_output, execution_context, exception_state);
509 if (exception_state.HadException()) 500 if (exception_state.HadException())
510 return; 501 return;
502 } else {
503 shipping_option_output = String();
511 } 504 }
512 505
513 shipping_option_output = GetSelectedShippingOption(output->shipping_options);
514
515 if (input.hasModifiers()) { 506 if (input.hasModifiers()) {
516 ValidateAndConvertPaymentDetailsModifiers( 507 ValidateAndConvertPaymentDetailsModifiers(
517 input.modifiers(), output->modifiers, execution_context, 508 input.modifiers(), output->modifiers, execution_context,
518 exception_state); 509 exception_state);
519 if (exception_state.HadException()) 510 if (exception_state.HadException())
520 return; 511 return;
521 } 512 }
522 } 513 }
523 514
524 void ValidateAndConvertPaymentDetailsInit(const PaymentDetailsInit& input, 515 void ValidateAndConvertPaymentDetailsInit(const PaymentDetailsInit& input,
525 bool request_shipping,
526 PaymentDetailsPtr& output, 516 PaymentDetailsPtr& output,
527 String& shipping_option_output, 517 String& shipping_option_output,
528 ExecutionContext& execution_context, 518 ExecutionContext& execution_context,
529 ExceptionState& exception_state) { 519 ExceptionState& exception_state) {
530 ValidateAndConvertPaymentDetailsBase(input, request_shipping, output, 520 DCHECK(input.hasTotal());
531 shipping_option_output, 521 ValidateAndConvertTotal(input.total(), "total", output->total,
522 execution_context, exception_state);
523 if (exception_state.HadException())
524 return;
525
526 ValidateAndConvertPaymentDetailsBase(input, output, shipping_option_output,
532 execution_context, exception_state); 527 execution_context, exception_state);
533 if (exception_state.HadException()) 528 if (exception_state.HadException())
534 return; 529 return;
535
536 if (!input.hasTotal()) {
537 exception_state.ThrowTypeError("Must specify total");
538 return;
539 }
540
541 if (input.hasId())
542 output->id = input.id();
543 else
544 output->id = CreateCanonicalUUIDString();
545
546 ValidateAndConvertTotal(input.total(), output->total, exception_state);
547 } 530 }
548 531
549 void ValidateAndConvertPaymentDetailsUpdate(const PaymentDetailsUpdate& input, 532 void ValidateAndConvertPaymentDetailsUpdate(const PaymentDetailsUpdate& input,
550 bool request_shipping,
551 PaymentDetailsPtr& output, 533 PaymentDetailsPtr& output,
552 String& shipping_option_output, 534 String& shipping_option_output,
553 ExecutionContext& execution_context, 535 ExecutionContext& execution_context,
554 ExceptionState& exception_state) { 536 ExceptionState& exception_state) {
555 ValidateAndConvertPaymentDetailsBase(input, request_shipping, output, 537 ValidateAndConvertPaymentDetailsBase(input, output, shipping_option_output,
556 shipping_option_output,
557 execution_context, exception_state); 538 execution_context, exception_state);
558 if (exception_state.HadException()) 539 if (exception_state.HadException())
559 return; 540 return;
560 541
561 if (input.hasTotal()) { 542 if (input.hasTotal()) {
562 ValidateAndConvertTotal(input.total(), output->total, exception_state); 543 ValidateAndConvertTotal(input.total(), "total", output->total,
544 execution_context, exception_state);
563 if (exception_state.HadException()) 545 if (exception_state.HadException())
564 return; 546 return;
565 } 547 }
566 548
567 if (input.hasError() && !input.error().IsNull()) { 549 if (input.hasError() && !input.error().IsNull()) {
568 String error_message; 550 String error_message;
569 if (!PaymentsValidators::IsValidErrorMsgFormat(input.error(), 551 if (!PaymentsValidators::IsValidErrorMsgFormat(input.error(),
570 &error_message)) { 552 &error_message)) {
571 exception_state.ThrowTypeError(error_message); 553 exception_state.ThrowTypeError(error_message);
572 return; 554 return;
573 } 555 }
574 output->error = input.error(); 556 output->error = input.error();
575 } else { 557 } else {
576 output->error = ""; 558 output->error = "";
577 } 559 }
578 } 560 }
579 561
580 void ValidateAndConvertPaymentMethodData( 562 void ValidateAndConvertPaymentMethodData(
581 const HeapVector<PaymentMethodData>& input, 563 const HeapVector<PaymentMethodData>& input,
582 Vector<payments::mojom::blink::PaymentMethodDataPtr>& output, 564 Vector<payments::mojom::blink::PaymentMethodDataPtr>& output,
583 ExecutionContext& execution_context, 565 ExecutionContext& execution_context,
584 ExceptionState& exception_state) { 566 ExceptionState& exception_state) {
585 if (input.IsEmpty()) { 567 if (input.IsEmpty()) {
586 exception_state.ThrowTypeError( 568 exception_state.ThrowTypeError("At least one payment method is required");
587 "Must specify at least one payment method identifier");
588 return; 569 return;
589 } 570 }
590 571
591 for (const PaymentMethodData payment_method_data : input) { 572 for (const PaymentMethodData payment_method_data : input) {
592 if (payment_method_data.supportedMethods().IsEmpty()) { 573 if (payment_method_data.supportedMethods().IsEmpty()) {
593 exception_state.ThrowTypeError( 574 exception_state.ThrowTypeError(
594 "Must specify at least one payment method identifier"); 575 "Each payment method needs to include at least one payment method "
576 "identifier");
595 return; 577 return;
596 } 578 }
597 579
598 output.push_back(payments::mojom::blink::PaymentMethodData::New()); 580 output.push_back(payments::mojom::blink::PaymentMethodData::New());
599 output.back()->supported_methods = payment_method_data.supportedMethods(); 581 output.back()->supported_methods = payment_method_data.supportedMethods();
600 582
601 if (payment_method_data.hasData() && 583 if (payment_method_data.hasData() &&
602 !payment_method_data.data().IsEmpty()) { 584 !payment_method_data.data().IsEmpty()) {
603 StringifyAndParseMethodSpecificData( 585 StringifyAndParseMethodSpecificData(
604 payment_method_data.supportedMethods(), payment_method_data.data(), 586 payment_method_data.supportedMethods(), payment_method_data.data(),
605 output.back(), execution_context, exception_state); 587 output.back(), execution_context, exception_state);
606 } else { 588 } else {
607 output.back()->stringified_data = ""; 589 output.back()->stringified_data = "";
608 } 590 }
609 } 591 }
610 } 592 }
611 593
612 String GetValidShippingType(const String& shipping_type) {
613 static const char* const kValidValues[] = {
614 "shipping", "delivery", "pickup",
615 };
616 for (size_t i = 0; i < arraysize(kValidValues); i++) {
617 if (shipping_type == kValidValues[i])
618 return shipping_type;
619 }
620 return kValidValues[0];
621 }
622
623 bool AllowedToUsePaymentRequest(const Frame* frame) { 594 bool AllowedToUsePaymentRequest(const Frame* frame) {
624 // To determine whether a Document object |document| is allowed to use the 595 // To determine whether a Document object |document| is allowed to use the
625 // feature indicated by attribute name |allowpaymentrequest|, run these steps: 596 // feature indicated by attribute name |allowpaymentrequest|, run these steps:
626 597
627 // 1. If |document| has no browsing context, then return false. 598 // 1. If |document| has no browsing context, then return false.
628 if (!frame) 599 if (!frame)
629 return false; 600 return false;
630 601
631 if (!RuntimeEnabledFeatures::featurePolicyEnabled()) { 602 if (!RuntimeEnabledFeatures::featurePolicyEnabled()) {
632 // 2. If |document|'s browsing context is a top-level browsing context, then 603 // 2. If |document|'s browsing context is a top-level browsing context, then
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
806 if (exception_state.HadException()) { 777 if (exception_state.HadException()) {
807 show_resolver_->Reject( 778 show_resolver_->Reject(
808 DOMException::Create(kSyntaxError, exception_state.Message())); 779 DOMException::Create(kSyntaxError, exception_state.Message()));
809 ClearResolversAndCloseMojoConnection(); 780 ClearResolversAndCloseMojoConnection();
810 return; 781 return;
811 } 782 }
812 783
813 PaymentDetailsPtr validated_details = 784 PaymentDetailsPtr validated_details =
814 payments::mojom::blink::PaymentDetails::New(); 785 payments::mojom::blink::PaymentDetails::New();
815 ValidateAndConvertPaymentDetailsUpdate( 786 ValidateAndConvertPaymentDetailsUpdate(
816 details, options_.requestShipping(), validated_details, shipping_option_, 787 details, validated_details, shipping_option_, *GetExecutionContext(),
817 *GetExecutionContext(), exception_state); 788 exception_state);
818 if (exception_state.HadException()) { 789 if (exception_state.HadException()) {
819 show_resolver_->Reject( 790 show_resolver_->Reject(
820 DOMException::Create(kSyntaxError, exception_state.Message())); 791 DOMException::Create(kSyntaxError, exception_state.Message()));
821 ClearResolversAndCloseMojoConnection(); 792 ClearResolversAndCloseMojoConnection();
822 return; 793 return;
823 } 794 }
824 795
796 if (!options_.requestShipping())
797 validated_details->shipping_options.clear();
798
825 payment_provider_->UpdateWith(std::move(validated_details)); 799 payment_provider_->UpdateWith(std::move(validated_details));
826 } 800 }
827 801
828 void PaymentRequest::OnUpdatePaymentDetailsFailure(const String& error) { 802 void PaymentRequest::OnUpdatePaymentDetailsFailure(const String& error) {
829 if (show_resolver_) 803 if (show_resolver_)
830 show_resolver_->Reject(DOMException::Create(kAbortError, error)); 804 show_resolver_->Reject(DOMException::Create(kAbortError, error));
831 if (complete_resolver_) 805 if (complete_resolver_)
832 complete_resolver_->Reject(DOMException::Create(kAbortError, error)); 806 complete_resolver_->Reject(DOMException::Create(kAbortError, error));
833 ClearResolversAndCloseMojoConnection(); 807 ClearResolversAndCloseMojoConnection();
834 } 808 }
(...skipping 19 matching lines...) Expand all
854 const PaymentDetailsInit& details, 828 const PaymentDetailsInit& details,
855 const PaymentOptions& options, 829 const PaymentOptions& options,
856 ExceptionState& exception_state) 830 ExceptionState& exception_state)
857 : ContextLifecycleObserver(execution_context), 831 : ContextLifecycleObserver(execution_context),
858 options_(options), 832 options_(options),
859 client_binding_(this), 833 client_binding_(this),
860 complete_timer_( 834 complete_timer_(
861 TaskRunnerHelper::Get(TaskType::kMiscPlatformAPI, GetFrame()), 835 TaskRunnerHelper::Get(TaskType::kMiscPlatformAPI, GetFrame()),
862 this, 836 this,
863 &PaymentRequest::OnCompleteTimeout) { 837 &PaymentRequest::OnCompleteTimeout) {
864 Vector<payments::mojom::blink::PaymentMethodDataPtr> validated_method_data;
865 ValidateAndConvertPaymentMethodData(method_data, validated_method_data,
866 *GetExecutionContext(), exception_state);
867 if (exception_state.HadException())
868 return;
869
870 if (!GetExecutionContext()->IsSecureContext()) { 838 if (!GetExecutionContext()->IsSecureContext()) {
871 exception_state.ThrowSecurityError("Must be in a secure context"); 839 exception_state.ThrowSecurityError("Must be in a secure context");
872 return; 840 return;
873 } 841 }
874 842
875 if (!AllowedToUsePaymentRequest(GetFrame())) { 843 if (!AllowedToUsePaymentRequest(GetFrame())) {
876 exception_state.ThrowSecurityError( 844 exception_state.ThrowSecurityError(
877 "Must be in a top-level browsing context or an iframe needs to specify " 845 "Must be in a top-level browsing context or an iframe needs to specify "
878 "'allowpaymentrequest' explicitly"); 846 "'allowpaymentrequest' explicitly");
879 return; 847 return;
880 } 848 }
881 849
882 PaymentDetailsPtr validated_details = 850 PaymentDetailsPtr validated_details =
883 payments::mojom::blink::PaymentDetails::New(); 851 payments::mojom::blink::PaymentDetails::New();
884 ValidateAndConvertPaymentDetailsInit(details, options_.requestShipping(), 852 validated_details->id = id_ =
885 validated_details, shipping_option_, 853 details.hasId() ? details.id() : CreateCanonicalUUIDString();
886 *GetExecutionContext(), exception_state); 854
855 Vector<payments::mojom::blink::PaymentMethodDataPtr> validated_method_data;
856 ValidateAndConvertPaymentMethodData(method_data, validated_method_data,
857 *GetExecutionContext(), exception_state);
887 if (exception_state.HadException()) 858 if (exception_state.HadException())
888 return; 859 return;
889 860
890 id_ = validated_details->id; 861 ValidateAndConvertPaymentDetailsInit(details, validated_details,
862 shipping_option_, *GetExecutionContext(),
863 exception_state);
864 if (exception_state.HadException())
865 return;
891 866
892 if (options_.requestShipping()) 867 if (options_.requestShipping())
893 shipping_type_ = GetValidShippingType(options_.shippingType()); 868 shipping_type_ = options_.shippingType();
869 else
870 validated_details->shipping_options.clear();
871
872 DCHECK(shipping_type_.IsNull() || shipping_type_ == "shipping" ||
873 shipping_type_ == "delivery" || shipping_type_ == "pickup");
894 874
895 GetFrame()->GetInterfaceProvider()->GetInterface( 875 GetFrame()->GetInterfaceProvider()->GetInterface(
896 mojo::MakeRequest(&payment_provider_)); 876 mojo::MakeRequest(&payment_provider_));
897 payment_provider_.set_connection_error_handler(ConvertToBaseCallback( 877 payment_provider_.set_connection_error_handler(ConvertToBaseCallback(
898 WTF::Bind(&PaymentRequest::OnError, WrapWeakPersistent(this), 878 WTF::Bind(&PaymentRequest::OnError, WrapWeakPersistent(this),
899 PaymentErrorReason::UNKNOWN))); 879 PaymentErrorReason::UNKNOWN)));
900 payment_provider_->Init( 880 payment_provider_->Init(
901 client_binding_.CreateInterfacePtrAndBind(), 881 client_binding_.CreateInterfacePtrAndBind(),
902 std::move(validated_method_data), std::move(validated_details), 882 std::move(validated_method_data), std::move(validated_details),
903 payments::mojom::blink::PaymentOptions::From(options_)); 883 payments::mojom::blink::PaymentOptions::From(options_));
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
1089 complete_resolver_.Clear(); 1069 complete_resolver_.Clear();
1090 show_resolver_.Clear(); 1070 show_resolver_.Clear();
1091 abort_resolver_.Clear(); 1071 abort_resolver_.Clear();
1092 can_make_payment_resolver_.Clear(); 1072 can_make_payment_resolver_.Clear();
1093 if (client_binding_.is_bound()) 1073 if (client_binding_.is_bound())
1094 client_binding_.Close(); 1074 client_binding_.Close();
1095 payment_provider_.reset(); 1075 payment_provider_.reset();
1096 } 1076 }
1097 1077
1098 } // namespace blink 1078 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698