blob: 693de31e55f3485696c19fd22750d7d1cda4a177 [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 <map>
#include <set>
#include <string>
#include <vector>
#include "base/macros.h"
#include "base/observer_list.h"
#include "base/strings/string16.h"
#include "components/autofill/core/browser/data_model/credit_card.h"
#include "components/autofill/core/browser/field_types.h"
#include "components/payments/content/initialization_task.h"
#include "components/payments/core/currency_formatter.h"
#include "components/payments/core/payment_options_provider.h"
#include "third_party/blink/public/mojom/payments/payment_request.mojom.h"
#include "url/gurl.h"
namespace payments {
class PaymentInstrument;
// Identifier for the basic card payment method and google-related payment
// methods in the PaymentMethodData.
extern const char kBasicCardMethodName[];
extern const char kGooglePayMethodName[];
extern const char kAndroidPayMethodName[];
// The spec contains all the options that the merchant has specified about this
// Payment Request. It's a (mostly) read-only view, which can be updated in
// certain occasions by the merchant (see API).
// The spec starts out completely initialized when a PaymentRequest object is
// created, but can be placed into uninitialized state if
// was called with a promise. This allows for asynchronous calculation of the
// shopping cart contents, the total, the shipping options, and the modifiers.
// The initialization state is observed by PaymentRequestDialogView for showing
// a "Loading..." spinner.
class PaymentRequestSpec : public PaymentOptionsProvider,
public InitializationTask {
// This enum represents which bit of information was changed to trigger an
// update roundtrip with the website.
enum class UpdateReason {
// Any class call add itself as Observer via AddObserver() and receive
// notification about spec events.
class Observer {
// Called when the website is notified that the user selected shipping
// options or a shipping address. This will be followed by a call to
// OnSpecUpdated or the PaymentRequest being aborted due to a timeout.
virtual void OnStartUpdating(UpdateReason reason) {}
// Called when the provided spec has changed.
virtual void OnSpecUpdated() = 0;
virtual ~Observer() {}
PaymentRequestSpec(mojom::PaymentOptionsPtr options,
mojom::PaymentDetailsPtr details,
std::vector<mojom::PaymentMethodDataPtr> method_data,
PaymentRequestSpec::Observer* observer,
const std::string& app_locale);
~PaymentRequestSpec() override;
// Called when the merchant has new PaymentDetails. Will recompute every spec
// state that depends on |details|.
void UpdateWith(mojom::PaymentDetailsPtr details);
// Called when the merchant calls retry().
void Retry(mojom::PaymentValidationErrorsPtr validation_errors);
// Gets the display string for the general retry error message.
const base::string16& retry_error_message() const {
return retry_error_message_;
// Reset the display string for the general retry error message. This method
// is called in PaymentSheetViewController::ButtonPressed when the user
// interacts. That is, the retry error message is displayed on UI until user
// interaction happens since retry() called.
void reset_retry_error_message() { retry_error_message_.clear(); }
// Gets the display string for the shipping address error for the given
// |type|.
base::string16 GetShippingAddressError(autofill::ServerFieldType type);
// Gets the display string for the payer error for the given |type|.
base::string16 GetPayerError(autofill::ServerFieldType type);
// Returns whether there is a shipping address error message set by merchant.
bool has_shipping_address_error() const;
// Returns whether there is a payer error message set by merchant.
bool has_payer_error() const;
// Recomputes spec based on details.
void RecomputeSpecForDetails();
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
// InitializationTask:
bool IsInitialized() const override;
// PaymentOptionsProvider:
bool request_shipping() const override;
bool request_payer_name() const override;
bool request_payer_phone() const override;
bool request_payer_email() const override;
PaymentShippingType shipping_type() const override;
bool supports_basic_card() const { return !supported_card_networks_.empty(); }
const std::vector<std::string>& supported_card_networks() const {
return supported_card_networks_;
const std::set<std::string>& supported_card_networks_set() const {
return supported_card_networks_set_;
const std::map<std::string, std::set<std::string>>& stringified_method_data()
const {
return stringified_method_data_;
const std::set<autofill::CreditCard::CardType>& supported_card_types_set()
const {
return supported_card_types_set_;
const std::vector<GURL>& url_payment_method_identifiers() const {
return url_payment_method_identifiers_;
const std::set<std::string>& payment_method_identifiers_set() const {
return payment_method_identifiers_set_;
// Returns whether the |method_name| was specified as supported through the
// "basic-card" payment method. If false, it means either the |method_name| is
// not supported at all, or specified directly in supportedMethods.
bool IsMethodSupportedThroughBasicCard(const std::string& method_name);
// Uses CurrencyFormatter to format the value of |currency_amount| with the
// currency symbol for its currency.
base::string16 GetFormattedCurrencyAmount(
const mojom::PaymentCurrencyAmountPtr& currency_amount);
// Uses CurrencyFormatter to get the formatted currency code for
// |currency_amount|'s currency.
std::string GetFormattedCurrencyCode(
const mojom::PaymentCurrencyAmountPtr& currency_amount);
mojom::PaymentShippingOption* selected_shipping_option() const {
return selected_shipping_option_;
// This may contain a non-empty error returned by the merchant. In this case
// PaymentRequestState::selected_shipping_option_error_profile() will contain
// the profile related to the error.
const base::string16& selected_shipping_option_error() const {
return selected_shipping_option_error_;
// Notifies observers that spec is going to be updated due to |reason|. This
// shows a spinner in UI that goes away when merchant calls updateWith() or
// ignores the shipping*change event.
void StartWaitingForUpdateWith(UpdateReason reason);
bool IsMixedCurrency() const;
UpdateReason current_update_reason() const { return current_update_reason_; }
// Returns the total object of this payment request, taking into account the
// applicable modifier for |selected_instrument| if any.
const mojom::PaymentItemPtr& GetTotal(
PaymentInstrument* selected_instrument) const;
// Returns the display items for this payment request, taking into account the
// applicable modifier for |selected_instrument| if any.
std::vector<const mojom::PaymentItemPtr*> GetDisplayItems(
PaymentInstrument* selected_instrument) const;
const std::vector<mojom::PaymentShippingOptionPtr>& GetShippingOptions()
const mojom::PaymentDetails& details() const { return *details_.get(); }
const std::vector<mojom::PaymentMethodDataPtr>& method_data() const {
return method_data_;
// Returns the first applicable modifier in the Payment Request for the
// |selected_instrument|.
const mojom::PaymentDetailsModifierPtr* GetApplicableModifier(
PaymentInstrument* selected_instrument) const;
// Updates the |selected_shipping_option| based on the data passed to this
// payment request by the website. This will set selected_shipping_option_ to
// the last option marked selected in the options array. If merchants provides
// no options or an error message this method is called |after_update| (after
// user changed their shipping address selection), it means the merchant
// doesn't ship to this location. In this case,
// |selected_shipping_option_error_| will be set.
void UpdateSelectedShippingOption(bool after_update);
// Will notify all observers that the spec has changed.
void NotifyOnSpecUpdated();
// Returns the CurrencyFormatter instance for this PaymentRequest.
// |locale_name| should be the result of the browser's GetApplicationLocale().
// Note: Having multiple currencies per PaymentRequest is not supported; hence
// the CurrencyFormatter is cached here.
CurrencyFormatter* GetOrCreateCurrencyFormatter(
const std::string& currency_code,
const std::string& locale_name);
mojom::PaymentOptionsPtr options_;
mojom::PaymentDetailsPtr details_;
std::vector<mojom::PaymentMethodDataPtr> method_data_;
const std::string app_locale_;
// The currently shipping option as specified by the merchant.
mojom::PaymentShippingOption* selected_shipping_option_;
base::string16 selected_shipping_option_error_;
// One currency formatter is instantiated and cached per currency code.
std::map<std::string, CurrencyFormatter> currency_formatters_;
// A list/set of supported basic card networks. The list is used to keep the
// order in which they were specified by the merchant. The set is used for
// fast lookup of supported methods.
std::vector<std::string> supported_card_networks_;
std::set<std::string> supported_card_networks_set_;
std::set<autofill::CreditCard::CardType> supported_card_types_set_;
// Only the set of basic-card specified networks. NOTE: callers should use
// |supported_card_networks_set_| to check merchant support.
std::set<std::string> basic_card_specified_networks_;
// A list of supported url-based payment method identifers specified by the
// merchant. This encompasses one of the two types of payment method
// identifers, the other being standardized payment method identifiers i.e.,
// basic-card.
std::vector<GURL> url_payment_method_identifiers_;
// The set of all payment method identifiers.
std::set<std::string> payment_method_identifiers_set_;
// A mapping of the payment method names to the corresponding JSON-stringified
// payment method specific data.
std::map<std::string, std::set<std::string>> stringified_method_data_;
// The reason why this payment request is waiting for updateWith.
UpdateReason current_update_reason_;
// The |observer_for_testing_| will fire after all the |observers_| have been
// notified.
base::ObserverList<Observer>::Unchecked observers_;
base::string16 retry_error_message_;
mojom::PayerErrorsPtr payer_errors_;
} // namespace payments