krb | 7f6421b | 2016-11-18 17:46:21 | [diff] [blame] | 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 |
| 3 | // found in the LICENSE file. |
| 4 | |
rouslan | 908248c | 2017-02-27 21:30:24 | [diff] [blame] | 5 | #ifndef COMPONENTS_PAYMENTS_CONTENT_PAYMENT_REQUEST_H_ |
| 6 | #define COMPONENTS_PAYMENTS_CONTENT_PAYMENT_REQUEST_H_ |
mathp | f709499d | 2017-01-09 20:48:36 | [diff] [blame] | 7 | |
| 8 | #include <memory> |
tmartino | 68c0a27 | 2017-01-19 17:44:08 | [diff] [blame] | 9 | #include <vector> |
krb | 7f6421b | 2016-11-18 17:46:21 | [diff] [blame] | 10 | |
rouslan | 908248c | 2017-02-27 21:30:24 | [diff] [blame] | 11 | #include "base/macros.h" |
Anthony Vallee-Dubois | dc1dbf1a | 2017-07-17 15:01:13 | [diff] [blame] | 12 | #include "base/memory/weak_ptr.h" |
Rouslan Solomakhin | 2706470 | 2018-12-14 21:15:33 | [diff] [blame] | 13 | #include "components/payments/content/developer_console_logger.h" |
Anthony Vallee-Dubois | c7ae733 | 2017-12-19 20:44:07 | [diff] [blame] | 14 | #include "components/payments/content/payment_request_display_manager.h" |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 15 | #include "components/payments/content/payment_request_spec.h" |
| 16 | #include "components/payments/content/payment_request_state.h" |
sebsg | 20b49d7b | 2017-05-04 20:23:17 | [diff] [blame] | 17 | #include "components/payments/core/journey_logger.h" |
krb | 7f6421b | 2016-11-18 17:46:21 | [diff] [blame] | 18 | #include "mojo/public/cpp/bindings/binding.h" |
rouslan | 8fdbfb24 | 2017-03-15 01:12:49 | [diff] [blame] | 19 | #include "mojo/public/cpp/bindings/interface_request.h" |
Han Leon | abbe7c90 | 2018-08-30 02:08:10 | [diff] [blame] | 20 | #include "third_party/blink/public/mojom/payments/payment_request.mojom.h" |
Rouslan Solomakhin | 6e979ab | 2017-08-30 17:30:39 | [diff] [blame] | 21 | #include "url/gurl.h" |
krb | 7f6421b | 2016-11-18 17:46:21 | [diff] [blame] | 22 | |
| 23 | namespace content { |
rouslan | 69099768 | 2017-05-09 18:07:39 | [diff] [blame] | 24 | class RenderFrameHost; |
krb | 7f6421b | 2016-11-18 17:46:21 | [diff] [blame] | 25 | class WebContents; |
Rouslan Solomakhin | 115f723 | 2017-08-01 15:24:38 | [diff] [blame] | 26 | } // namespace content |
krb | 7f6421b | 2016-11-18 17:46:21 | [diff] [blame] | 27 | |
| 28 | namespace payments { |
| 29 | |
Rouslan Solomakhin | 4eea9bc2 | 2017-10-10 15:18:51 | [diff] [blame] | 30 | class ContentPaymentRequestDelegate; |
mathp | f709499d | 2017-01-09 20:48:36 | [diff] [blame] | 31 | class PaymentRequestWebContentsManager; |
| 32 | |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 33 | // This class manages the interaction between the renderer (through the |
| 34 | // PaymentRequestClient and Mojo stub implementation) and the UI (through the |
| 35 | // PaymentRequestDelegate). The API user (merchant) specification (supported |
| 36 | // payment methods, required information, order details) is stored in |
| 37 | // PaymentRequestSpec, and the current user selection state (and related data) |
| 38 | // is stored in PaymentRequestSpec. |
mathp | 4b85b58 | 2017-03-08 21:07:16 | [diff] [blame] | 39 | class PaymentRequest : public mojom::PaymentRequest, |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 40 | public PaymentRequestSpec::Observer, |
| 41 | public PaymentRequestState::Delegate { |
krb | 7f6421b | 2016-11-18 17:46:21 | [diff] [blame] | 42 | public: |
mathp | 300fa54 | 2017-03-27 19:29:37 | [diff] [blame] | 43 | class ObserverForTest { |
| 44 | public: |
| 45 | virtual void OnCanMakePaymentCalled() = 0; |
gogerald | 8189d52 | 2017-09-15 17:52:18 | [diff] [blame] | 46 | virtual void OnCanMakePaymentReturned() = 0; |
Danyao Wang | ce175bf | 2018-12-21 22:35:58 | [diff] [blame] | 47 | virtual void OnHasEnrolledInstrumentCalled() = 0; |
| 48 | virtual void OnHasEnrolledInstrumentReturned() = 0; |
rouslan | 6e3cf7c6 | 2017-04-17 21:23:28 | [diff] [blame] | 49 | virtual void OnNotSupportedError() = 0; |
rouslan | b28f453 | 2017-05-08 15:41:47 | [diff] [blame] | 50 | virtual void OnConnectionTerminated() = 0; |
Anthony Vallee-Dubois | 6813c144 | 2017-05-17 19:32:56 | [diff] [blame] | 51 | virtual void OnAbortCalled() = 0; |
mathp | 300fa54 | 2017-03-27 19:29:37 | [diff] [blame] | 52 | |
| 53 | protected: |
| 54 | virtual ~ObserverForTest() {} |
| 55 | }; |
| 56 | |
rouslan | 69099768 | 2017-05-09 18:07:39 | [diff] [blame] | 57 | PaymentRequest(content::RenderFrameHost* render_frame_host, |
| 58 | content::WebContents* web_contents, |
Rouslan Solomakhin | 4eea9bc2 | 2017-10-10 15:18:51 | [diff] [blame] | 59 | std::unique_ptr<ContentPaymentRequestDelegate> delegate, |
rouslan | 8fdbfb24 | 2017-03-15 01:12:49 | [diff] [blame] | 60 | PaymentRequestWebContentsManager* manager, |
Anthony Vallee-Dubois | c7ae733 | 2017-12-19 20:44:07 | [diff] [blame] | 61 | PaymentRequestDisplayManager* display_manager, |
mathp | 300fa54 | 2017-03-27 19:29:37 | [diff] [blame] | 62 | mojo::InterfaceRequest<mojom::PaymentRequest> request, |
| 63 | ObserverForTest* observer_for_testing); |
mathp | f709499d | 2017-01-09 20:48:36 | [diff] [blame] | 64 | ~PaymentRequest() override; |
krb | 7f6421b | 2016-11-18 17:46:21 | [diff] [blame] | 65 | |
rouslan | 8fdbfb24 | 2017-03-15 01:12:49 | [diff] [blame] | 66 | // mojom::PaymentRequest |
| 67 | void Init(mojom::PaymentRequestClientPtr client, |
| 68 | std::vector<mojom::PaymentMethodDataPtr> method_data, |
| 69 | mojom::PaymentDetailsPtr details, |
| 70 | mojom::PaymentOptionsPtr options) override; |
Rouslan Solomakhin | 833f851 | 2018-04-03 23:19:25 | [diff] [blame] | 71 | void Show(bool is_user_gesture) override; |
Jinho Bang | be463a2 | 2018-08-02 10:26:50 | [diff] [blame] | 72 | void Retry(mojom::PaymentValidationErrorsPtr errors) override; |
mathp | 151bd31e | 2017-04-03 21:07:24 | [diff] [blame] | 73 | void UpdateWith(mojom::PaymentDetailsPtr details) override; |
Rouslan Solomakhin | a9ff928 | 2017-10-31 21:58:05 | [diff] [blame] | 74 | void NoUpdatedPaymentDetails() override; |
mathp | f4bc50e | 2017-01-24 05:17:50 | [diff] [blame] | 75 | void Abort() override; |
rouslan | 8fdbfb24 | 2017-03-15 01:12:49 | [diff] [blame] | 76 | void Complete(mojom::PaymentComplete result) override; |
mathp | 4b85b58 | 2017-03-08 21:07:16 | [diff] [blame] | 77 | void CanMakePayment() override; |
Rouslan Solomakhin | 5683eb28 | 2019-01-29 18:06:03 | [diff] [blame^] | 78 | void HasEnrolledInstrument(bool per_method_quota) override; |
mathp | 4b85b58 | 2017-03-08 21:07:16 | [diff] [blame] | 79 | |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 80 | // PaymentRequestSpec::Observer: |
mathp | 151bd31e | 2017-04-03 21:07:24 | [diff] [blame] | 81 | void OnSpecUpdated() override {} |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 82 | |
| 83 | // PaymentRequestState::Delegate: |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 84 | void OnPaymentResponseAvailable(mojom::PaymentResponsePtr response) override; |
mathp | 151bd31e | 2017-04-03 21:07:24 | [diff] [blame] | 85 | void OnShippingOptionIdSelected(std::string shipping_option_id) override; |
| 86 | void OnShippingAddressSelected(mojom::PaymentAddressPtr address) override; |
Jinho Bang | bb17815 | 2018-09-13 09:44:43 | [diff] [blame] | 87 | void OnPayerInfoSelected(mojom::PayerDetailPtr payer_info) override; |
krb | 7f6421b | 2016-11-18 17:46:21 | [diff] [blame] | 88 | |
Rouslan Solomakhin | 16ee5520 | 2017-10-03 19:04:42 | [diff] [blame] | 89 | // Called when the user explicitly cancelled the flow. Will send a message |
mathp | f4bc50e | 2017-01-24 05:17:50 | [diff] [blame] | 90 | // to the renderer which will indirectly destroy this object (through |
| 91 | // OnConnectionTerminated). |
| 92 | void UserCancelled(); |
| 93 | |
sebsg | d56b3e42 | 2017-10-20 18:08:08 | [diff] [blame] | 94 | // Called when the main frame attached to this PaymentRequest is navigating to |
| 95 | // another document, but before the PaymentRequest is destroyed. |
| 96 | void DidStartMainFrameNavigationToDifferentDocument(bool is_user_initiated); |
sebsg | 2c8558a | 2017-05-17 18:54:10 | [diff] [blame] | 97 | |
mathp | f4bc50e | 2017-01-24 05:17:50 | [diff] [blame] | 98 | // As a result of a browser-side error or renderer-initiated mojo channel |
| 99 | // closure (e.g. there was an error on the renderer side, or payment was |
| 100 | // successful), this method is called. It is responsible for cleaning up, |
| 101 | // such as possibly closing the dialog. |
| 102 | void OnConnectionTerminated(); |
mathp | 6758be03 | 2017-01-13 04:49:50 | [diff] [blame] | 103 | |
mathp | d4be8de8 | 2017-03-01 00:51:48 | [diff] [blame] | 104 | // Called when the user clicks on the "Pay" button. |
| 105 | void Pay(); |
| 106 | |
Anthony Vallee-Dubois | c7ae733 | 2017-12-19 20:44:07 | [diff] [blame] | 107 | // Hide this Payment Request if it's already showing. |
| 108 | void HideIfNecessary(); |
| 109 | |
Rouslan Solomakhin | d2cae95a | 2018-08-09 00:16:10 | [diff] [blame] | 110 | // Record the "dialog shown" event in the journey logger. |
| 111 | void RecordDialogShownEventInJourneyLogger(); |
| 112 | |
Anthony Vallee-Dubois | 10d131a | 2018-02-22 15:41:04 | [diff] [blame] | 113 | bool IsIncognito() const; |
| 114 | |
anthonyvd | 3d7f972 | 2016-12-07 18:43:54 | [diff] [blame] | 115 | content::WebContents* web_contents() { return web_contents_; } |
| 116 | |
gogerald | 2ddfc64c | 2018-08-23 16:20:21 | [diff] [blame] | 117 | bool skipped_payment_request_ui() { return skipped_payment_request_ui_; } |
| 118 | |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 119 | PaymentRequestSpec* spec() { return spec_.get(); } |
| 120 | PaymentRequestState* state() { return state_.get(); } |
mathp | d4be8de8 | 2017-03-01 00:51:48 | [diff] [blame] | 121 | |
Anthony Vallee-Dubois | 968ae4d | 2018-03-15 16:56:36 | [diff] [blame] | 122 | PaymentRequestSpec* spec() const { return spec_.get(); } |
| 123 | PaymentRequestState* state() const { return state_.get(); } |
| 124 | |
krb | 7f6421b | 2016-11-18 17:46:21 | [diff] [blame] | 125 | private: |
Rouslan Solomakhin | 2706470 | 2018-12-14 21:15:33 | [diff] [blame] | 126 | // Returns true after init() has been called and the mojo connection has been |
| 127 | // established. If the mojo connection gets later disconnected, this will |
| 128 | // returns false. |
| 129 | bool IsInitialized() const; |
| 130 | |
| 131 | // Returns true after show() has been called and the payment sheet is showing. |
| 132 | // If the payment sheet is later hidden, this will return false. |
| 133 | bool IsThisPaymentRequestShowing() const; |
| 134 | |
gogerald | 2ddfc64c | 2018-08-23 16:20:21 | [diff] [blame] | 135 | // Returns true if this payment request supports skipping the Payment Sheet. |
| 136 | // Typically, this means only one payment method is supported, it's a URL |
| 137 | // based method, and no other info is requested from the user. |
| 138 | bool SatisfiesSkipUIConstraints() const; |
| 139 | |
sebsg | fcdd13c | 2017-06-08 15:49:33 | [diff] [blame] | 140 | // Only records the abort reason if it's the first completion for this Payment |
| 141 | // Request. This is necessary since the aborts cascade into one another with |
| 142 | // the first one being the most precise. |
| 143 | void RecordFirstAbortReason(JourneyLogger::AbortReason completion_status); |
sebsg | 2c8558a | 2017-05-17 18:54:10 | [diff] [blame] | 144 | |
gogerald | 0a7ee6c | 2017-11-13 18:23:19 | [diff] [blame] | 145 | // The callback for PaymentRequestState::CanMakePayment. Checks for query |
| 146 | // quota and may send QUERY_QUOTA_EXCEEDED. |
gogerald | 8189d52 | 2017-09-15 17:52:18 | [diff] [blame] | 147 | void CanMakePaymentCallback(bool can_make_payment); |
| 148 | |
Danyao Wang | ce175bf | 2018-12-21 22:35:58 | [diff] [blame] | 149 | // The callback for PaymentRequestState::HasEnrolledInstrument. Checks for |
| 150 | // query quota and may send QUERY_QUOTA_EXCEEDED. |
Rouslan Solomakhin | 5683eb28 | 2019-01-29 18:06:03 | [diff] [blame^] | 151 | void HasEnrolledInstrumentCallback(bool per_method_quota, |
| 152 | bool has_enrolled_instrument); |
Danyao Wang | ce175bf | 2018-12-21 22:35:58 | [diff] [blame] | 153 | |
gogerald | 0a7ee6c | 2017-11-13 18:23:19 | [diff] [blame] | 154 | // The callback for PaymentRequestState::AreRequestedMethodsSupported. |
| 155 | void AreRequestedMethodsSupportedCallback(bool methods_supported); |
| 156 | |
Danyao Wang | ce175bf | 2018-12-21 22:35:58 | [diff] [blame] | 157 | // Sends either HAS_ENROLLED_INSTRUMENT or HAS_NO_ENROLLED_INSTRUMENT to the |
Danyao Wang | 4bc0606a | 2018-12-27 16:54:53 | [diff] [blame] | 158 | // renderer, depending on |has_enrolled_instrument| value. Does not check |
| 159 | // query quota so never sends QUERY_QUOTA_EXCEEDED. If |
| 160 | // |warn_localhost_or_file| is true, then sends |
Danyao Wang | ce175bf | 2018-12-21 22:35:58 | [diff] [blame] | 161 | // WARNING_HAS_ENROLLED_INSTRUMENT or WARNING_HAS_NO_ENROLLED_INSTRUMENT |
| 162 | // version of the values instead. |
| 163 | void RespondToHasEnrolledInstrumentQuery(bool has_enrolled_instrument, |
| 164 | bool warn_localhost_or_file); |
| 165 | |
krb | 7f6421b | 2016-11-18 17:46:21 | [diff] [blame] | 166 | content::WebContents* web_contents_; |
Rouslan Solomakhin | 2706470 | 2018-12-14 21:15:33 | [diff] [blame] | 167 | DeveloperConsoleLogger log_; |
Rouslan Solomakhin | 4eea9bc2 | 2017-10-10 15:18:51 | [diff] [blame] | 168 | std::unique_ptr<ContentPaymentRequestDelegate> delegate_; |
mathp | f709499d | 2017-01-09 20:48:36 | [diff] [blame] | 169 | // |manager_| owns this PaymentRequest. |
| 170 | PaymentRequestWebContentsManager* manager_; |
Anthony Vallee-Dubois | c7ae733 | 2017-12-19 20:44:07 | [diff] [blame] | 171 | PaymentRequestDisplayManager* display_manager_; |
| 172 | std::unique_ptr<PaymentRequestDisplayManager::DisplayHandle> display_handle_; |
rouslan | 8fdbfb24 | 2017-03-15 01:12:49 | [diff] [blame] | 173 | mojo::Binding<mojom::PaymentRequest> binding_; |
| 174 | mojom::PaymentRequestClientPtr client_; |
mathp | d4be8de8 | 2017-03-01 00:51:48 | [diff] [blame] | 175 | |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 176 | std::unique_ptr<PaymentRequestSpec> spec_; |
| 177 | std::unique_ptr<PaymentRequestState> state_; |
anthonyvd | 3d7f972 | 2016-12-07 18:43:54 | [diff] [blame] | 178 | |
Rouslan Solomakhin | 115f723 | 2017-08-01 15:24:38 | [diff] [blame] | 179 | // The RFC 6454 origin of the top level frame that has invoked PaymentRequest |
| 180 | // API. This is what the user sees in the address bar. |
Rouslan Solomakhin | 6e979ab | 2017-08-30 17:30:39 | [diff] [blame] | 181 | const GURL top_level_origin_; |
Rouslan Solomakhin | 115f723 | 2017-08-01 15:24:38 | [diff] [blame] | 182 | |
rouslan | 69099768 | 2017-05-09 18:07:39 | [diff] [blame] | 183 | // The RFC 6454 origin of the frame that has invoked PaymentRequest API. This |
| 184 | // can be either the main frame or an iframe. |
Rouslan Solomakhin | 6e979ab | 2017-08-30 17:30:39 | [diff] [blame] | 185 | const GURL frame_origin_; |
rouslan | 69099768 | 2017-05-09 18:07:39 | [diff] [blame] | 186 | |
mathp | 300fa54 | 2017-03-27 19:29:37 | [diff] [blame] | 187 | // May be null, must outlive this object. |
| 188 | ObserverForTest* observer_for_testing_; |
| 189 | |
sebsg | 20b49d7b | 2017-05-04 20:23:17 | [diff] [blame] | 190 | JourneyLogger journey_logger_; |
| 191 | |
sebsg | fcdd13c | 2017-06-08 15:49:33 | [diff] [blame] | 192 | // Whether a completion was already recorded for this Payment Request. |
| 193 | bool has_recorded_completion_ = false; |
sebsg | 2c8558a | 2017-05-17 18:54:10 | [diff] [blame] | 194 | |
Rouslan Solomakhin | 833f851 | 2018-04-03 23:19:25 | [diff] [blame] | 195 | // Whether PaymentRequest.show() was invoked with a user gesture. |
| 196 | bool is_show_user_gesture_ = false; |
| 197 | |
gogerald | 2ddfc64c | 2018-08-23 16:20:21 | [diff] [blame] | 198 | // Whether PaymentRequest.show() was invoked by skipping payment request UI. |
| 199 | bool skipped_payment_request_ui_ = false; |
| 200 | |
Rouslan Solomakhin | 2706470 | 2018-12-14 21:15:33 | [diff] [blame] | 201 | // Whether PaymentRequest mojo connection has been initialized from the |
| 202 | // renderer. |
| 203 | bool is_initialized_ = false; |
| 204 | |
| 205 | // Whether PaymentRequest.show() has been called. |
| 206 | bool is_show_called_ = false; |
| 207 | |
Anthony Vallee-Dubois | dc1dbf1a | 2017-07-17 15:01:13 | [diff] [blame] | 208 | base::WeakPtrFactory<PaymentRequest> weak_ptr_factory_; |
| 209 | |
mathp | f709499d | 2017-01-09 20:48:36 | [diff] [blame] | 210 | DISALLOW_COPY_AND_ASSIGN(PaymentRequest); |
krb | 7f6421b | 2016-11-18 17:46:21 | [diff] [blame] | 211 | }; |
| 212 | |
| 213 | } // namespace payments |
| 214 | |
rouslan | 908248c | 2017-02-27 21:30:24 | [diff] [blame] | 215 | #endif // COMPONENTS_PAYMENTS_CONTENT_PAYMENT_REQUEST_H_ |