// Copyright 2016 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. #ifndef COMPONENTS_PAYMENTS_CONTENT_PAYMENT_REQUEST_H_ #define COMPONENTS_PAYMENTS_CONTENT_PAYMENT_REQUEST_H_ #include #include #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "components/payments/content/developer_console_logger.h" #include "components/payments/content/payment_handler_host.h" #include "components/payments/content/payment_request_display_manager.h" #include "components/payments/content/payment_request_spec.h" #include "components/payments/content/payment_request_state.h" #include "components/payments/content/service_worker_payment_app.h" #include "components/payments/core/journey_logger.h" #include "content/public/browser/global_routing_id.h" #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/remote.h" #include "third_party/blink/public/mojom/payments/payment_request.mojom.h" #include "url/gurl.h" #include "url/origin.h" namespace content { class RenderFrameHost; class WebContents; } // namespace content namespace payments { class ContentPaymentRequestDelegate; class PaymentRequestWebContentsManager; // This class manages the interaction between the renderer (through the // PaymentRequestClient and Mojo stub implementation) and the desktop Payment UI // (through the PaymentRequestDelegate). The API user (merchant) specification // (supported payment methods, required information, order details) is stored in // PaymentRequestSpec, and the current user selection state (and related data) // is stored in PaymentRequestState. class PaymentRequest : public mojom::PaymentRequest, public PaymentHandlerHost::Delegate, public PaymentRequestSpec::Observer, public PaymentRequestState::Delegate { public: class ObserverForTest { public: virtual void OnCanMakePaymentCalled() = 0; virtual void OnCanMakePaymentReturned() = 0; virtual void OnHasEnrolledInstrumentCalled() = 0; virtual void OnHasEnrolledInstrumentReturned() = 0; virtual void OnShowAppsReady( base::WeakPtr payment_request) {} virtual void OnNotSupportedError() = 0; virtual void OnConnectionTerminated() = 0; virtual void OnAbortCalled() = 0; virtual void OnCompleteCalled() {} protected: virtual ~ObserverForTest() {} }; PaymentRequest(content::RenderFrameHost* render_frame_host, content::WebContents* web_contents, std::unique_ptr delegate, PaymentRequestWebContentsManager* manager, PaymentRequestDisplayManager* display_manager, mojo::PendingReceiver receiver, ObserverForTest* observer_for_testing); ~PaymentRequest() override; // mojom::PaymentRequest void Init(mojo::PendingRemote client, std::vector method_data, mojom::PaymentDetailsPtr details, mojom::PaymentOptionsPtr options) override; void Show(bool is_user_gesture, bool wait_for_updated_details) override; void Retry(mojom::PaymentValidationErrorsPtr errors) override; void UpdateWith(mojom::PaymentDetailsPtr details) override; void OnPaymentDetailsNotUpdated() override; void Abort() override; void Complete(mojom::PaymentComplete result) override; void CanMakePayment() override; void HasEnrolledInstrument(bool per_method_quota) override; // PaymentHandlerHost::Delegate bool ChangePaymentMethod(const std::string& method_name, const std::string& stringified_data) override; bool ChangeShippingOption(const std::string& shipping_option_id) override; bool ChangeShippingAddress( mojom::PaymentAddressPtr shipping_address) override; // PaymentRequestSpec::Observer: void OnSpecUpdated() override {} // PaymentRequestState::Delegate: void OnPaymentResponseAvailable(mojom::PaymentResponsePtr response) override; void OnPaymentResponseError(const std::string& error_message) override; void OnShippingOptionIdSelected(std::string shipping_option_id) override; void OnShippingAddressSelected(mojom::PaymentAddressPtr address) override; void OnPayerInfoSelected(mojom::PayerDetailPtr payer_info) override; // Called when the user explicitly cancelled the flow. Will send a message // to the renderer which will indirectly destroy this object (through // OnConnectionTerminated). void UserCancelled(); // Called when the main frame attached to this PaymentRequest is navigating to // another document, but before the PaymentRequest is destroyed. void DidStartMainFrameNavigationToDifferentDocument(bool is_user_initiated); // As a result of a browser-side error or renderer-initiated mojo channel // closure (e.g. there was an error on the renderer side, or payment was // successful), this method is called. It is responsible for cleaning up, // such as possibly closing the dialog. void OnConnectionTerminated(); // Called when the user clicks on the "Pay" button. void Pay(); // Hide this Payment Request if it's already showing. void HideIfNecessary(); bool IsOffTheRecord() const; // Called when the payment handler requests to open a payment handler window. void OnPaymentHandlerOpenWindowCalled(); content::WebContents* web_contents() { return web_contents_; } bool skipped_payment_request_ui() { return skipped_payment_request_ui_; } bool is_show_user_gesture() const { return is_show_user_gesture_; } PaymentRequestSpec* spec() { return spec_.get(); } PaymentRequestState* state() { return state_.get(); } PaymentRequestSpec* spec() const { return spec_.get(); } PaymentRequestState* state() const { return state_.get(); } private: // Returns true after init() has been called and the mojo connection has been // established. If the mojo connection gets later disconnected, this will // returns false. bool IsInitialized() const; // Returns true after show() has been called and the payment sheet is showing. // If the payment sheet is later hidden, this will return false. bool IsThisPaymentRequestShowing() const; // Returns true when there is exactly one available payment app which can // provide all requested information including shipping address and payer's // contact information whenever needed. bool OnlySingleAppCanProvideAllRequiredInformation() const; // Returns true if this payment request supports skipping the Payment Sheet. // Typically, this means that exactly one payment app can provide requested // information. bool SatisfiesSkipUIConstraints(); // Only records the abort reason if it's the first completion for this Payment // Request. This is necessary since the aborts cascade into one another with // the first one being the most precise. void RecordFirstAbortReason(JourneyLogger::AbortReason completion_status); // The callback for PaymentRequestState::CanMakePayment. void CanMakePaymentCallback(bool can_make_payment); // The callback for PaymentRequestState::HasEnrolledInstrument. Checks for // query quota and may send QUERY_QUOTA_EXCEEDED. void HasEnrolledInstrumentCallback(bool per_method_quota, bool has_enrolled_instrument); // The callback for PaymentRequestState::AreRequestedMethodsSupported. void AreRequestedMethodsSupportedCallback(bool methods_supported, const std::string& error_message); // Sends either HAS_ENROLLED_INSTRUMENT or HAS_NO_ENROLLED_INSTRUMENT to the // renderer, depending on |has_enrolled_instrument| value. Does not check // query quota so never sends QUERY_QUOTA_EXCEEDED. If // |warn_localhost_or_file| is true, then sends // WARNING_HAS_ENROLLED_INSTRUMENT or WARNING_HAS_NO_ENROLLED_INSTRUMENT // version of the values instead. void RespondToHasEnrolledInstrumentQuery(bool has_enrolled_instrument, bool warn_localhost_or_file); void OnAbortResult(bool aborted); content::WebContents* web_contents_; const content::GlobalFrameRoutingId initiator_frame_routing_id_; DeveloperConsoleLogger log_; std::unique_ptr delegate_; // |manager_| owns this PaymentRequest. PaymentRequestWebContentsManager* manager_; PaymentRequestDisplayManager* display_manager_; std::unique_ptr display_handle_; mojo::Receiver receiver_{this}; mojo::Remote client_; std::unique_ptr spec_; std::unique_ptr state_; // The end-point for the payment handler renderer process to call into the // browser process. PaymentHandlerHost payment_handler_host_; // The scheme, host, and port of the top level frame that has invoked // PaymentRequest API as formatted by // url_formatter::FormatUrlForSecurityDisplay(). This is what the user sees in // the address bar. const GURL top_level_origin_; // The scheme, host, and port of the frame that has invoked PaymentRequest API // as formatted by url_formatter::FormatUrlForSecurityDisplay(). This can be // either the main frame or an iframe. const GURL frame_origin_; // The security origin of the frame that has invoked PaymentRequest API. This // can be opaque. Used by security features like 'Sec-Fetch-Site' and // 'Cross-Origin-Resource-Policy'. const url::Origin frame_security_origin_; // May be null, must outlive this object. ObserverForTest* observer_for_testing_; JourneyLogger journey_logger_; // Whether a completion was already recorded for this Payment Request. bool has_recorded_completion_ = false; // Whether PaymentRequest.show() was invoked with a user gesture. bool is_show_user_gesture_ = false; // Whether PaymentRequest.show() was invoked by skipping payment request UI. bool skipped_payment_request_ui_ = false; // Whether PaymentRequest mojo connection has been initialized from the // renderer. bool is_initialized_ = false; // Whether PaymentRequest.show() has been called. bool is_show_called_ = false; // If not empty, use this error message for rejecting PaymentRequest.show(). std::string reject_show_error_message_; base::WeakPtrFactory weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(PaymentRequest); }; } // namespace payments #endif // COMPONENTS_PAYMENTS_CONTENT_PAYMENT_REQUEST_H_