blob: 912fc258519d0f0023ed983743d339c5546c9a96 [file] [log] [blame]
mathpf709499d2017-01-09 20:48:361// 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
5#include "components/payments/payment_request.h"
6
tmartino68c0a272017-01-19 17:44:087#include "base/memory/ptr_util.h"
anthonyvd045303a2017-01-17 22:19:198#include "components/autofill/core/browser/personal_data_manager.h"
mathpf709499d2017-01-09 20:48:369#include "components/payments/payment_details_validation.h"
10#include "components/payments/payment_request_delegate.h"
11#include "components/payments/payment_request_web_contents_manager.h"
12#include "content/public/browser/browser_thread.h"
13#include "content/public/browser/web_contents.h"
14
15namespace payments {
16
17PaymentRequest::PaymentRequest(
18 content::WebContents* web_contents,
19 std::unique_ptr<PaymentRequestDelegate> delegate,
20 PaymentRequestWebContentsManager* manager,
21 mojo::InterfaceRequest<payments::mojom::PaymentRequest> request)
22 : web_contents_(web_contents),
23 delegate_(std::move(delegate)),
24 manager_(manager),
25 binding_(this, std::move(request)) {
mathpf4bc50e2017-01-24 05:17:5026 // OnConnectionTerminated will be called when the Mojo pipe is closed. This
27 // will happen as a result of many renderer-side events (both successful and
28 // erroneous in nature).
29 // TODO(crbug.com/683636): Investigate using
30 // set_connection_error_with_reason_handler with Binding::CloseWithReason.
31 binding_.set_connection_error_handler(base::Bind(
32 &PaymentRequest::OnConnectionTerminated, base::Unretained(this)));
mathpf709499d2017-01-09 20:48:3633}
34
35PaymentRequest::~PaymentRequest() {}
36
37void PaymentRequest::Init(
38 payments::mojom::PaymentRequestClientPtr client,
39 std::vector<payments::mojom::PaymentMethodDataPtr> methodData,
40 payments::mojom::PaymentDetailsPtr details,
41 payments::mojom::PaymentOptionsPtr options) {
42 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
43 std::string error;
44 if (!payments::validatePaymentDetails(details, &error)) {
45 LOG(ERROR) << error;
mathpf4bc50e2017-01-24 05:17:5046 OnConnectionTerminated();
mathpf709499d2017-01-09 20:48:3647 return;
48 }
49 client_ = std::move(client);
50 details_ = std::move(details);
51}
52
53void PaymentRequest::Show() {
tmartino8ce922852017-01-09 22:23:1054 if (!client_.is_bound() || !binding_.is_bound()) {
mathpf4bc50e2017-01-24 05:17:5055 LOG(ERROR) << "Attempted Show(), but binding(s) missing.";
56 OnConnectionTerminated();
tmartino8ce922852017-01-09 22:23:1057 return;
58 }
mathpf4bc50e2017-01-24 05:17:5059 delegate_->ShowDialog(this);
mathpf709499d2017-01-09 20:48:3660}
61
mathpf4bc50e2017-01-24 05:17:5062void PaymentRequest::Abort() {
63 // The API user has decided to abort. We return a successful abort message to
64 // the renderer, which closes the Mojo message pipe, which triggers
65 // PaymentRequest::OnConnectionTerminated, which destroys this object.
66 if (client_.is_bound())
67 client_->OnAbort(true /* aborted_successfully */);
68}
69
70void PaymentRequest::UserCancelled() {
71 // If |client_| is not bound, then the object is already being destroyed as
72 // a result of a renderer event.
73 if (!client_.is_bound())
74 return;
75
76 // This sends an error to the renderer, which informs the API user.
mathpf709499d2017-01-09 20:48:3677 client_->OnError(payments::mojom::PaymentErrorReason::USER_CANCEL);
mathpf4bc50e2017-01-24 05:17:5078
79 // We close all bindings and ask to be destroyed.
80 client_.reset();
81 binding_.Close();
82 manager_->DestroyRequest(this);
mathpf709499d2017-01-09 20:48:3683}
84
mathpf4bc50e2017-01-24 05:17:5085void PaymentRequest::OnConnectionTerminated() {
86 // We are here because of a browser-side error, or likely as a result of the
87 // connection_error_handler on |binding_|, which can mean that the renderer
88 // has decided to close the pipe for various reasons (see all uses of
89 // PaymentRequest::clearResolversAndCloseMojoConnection() in Blink). We close
90 // the binding and the dialog, and ask to be deleted.
91 client_.reset();
mathpf709499d2017-01-09 20:48:3692 binding_.Close();
mathpf4bc50e2017-01-24 05:17:5093 delegate_->CloseDialog();
mathpf709499d2017-01-09 20:48:3694 manager_->DestroyRequest(this);
95}
96
mathp6758be032017-01-13 04:49:5097CurrencyFormatter* PaymentRequest::GetOrCreateCurrencyFormatter(
98 const std::string& currency_code,
99 const base::Optional<std::string> currency_system,
100 const std::string& locale_name) {
101 if (!currency_formatter_) {
102 currency_formatter_.reset(
103 new CurrencyFormatter(currency_code, currency_system, locale_name));
104 }
mathp6758be032017-01-13 04:49:50105 return currency_formatter_.get();
106}
107
tmartino68c0a272017-01-19 17:44:08108autofill::AutofillProfile* PaymentRequest::GetCurrentlySelectedProfile() {
109 // TODO(tmartino): Implement more sophisticated algorithm for populating
110 // this when it starts empty.
111 if (!profile_) {
112 autofill::PersonalDataManager* data_manager =
113 delegate_->GetPersonalDataManager();
114 auto profiles = data_manager->GetProfiles();
115 if (!profiles.empty())
116 profile_ = base::MakeUnique<autofill::AutofillProfile>(*profiles[0]);
117 }
118 return profile_ ? profile_.get() : nullptr;
119}
120
anthonyvd045303a2017-01-17 22:19:19121autofill::CreditCard* PaymentRequest::GetCurrentlySelectedCreditCard() {
122 // TODO(anthonyvd): Change this code to prioritize server cards and implement
123 // a way to modify this function's return value.
124 autofill::PersonalDataManager* data_manager =
125 delegate_->GetPersonalDataManager();
126
127 const std::vector<autofill::CreditCard*> cards =
128 data_manager->GetCreditCardsToSuggest();
129
130 auto first_complete_card = std::find_if(
131 cards.begin(),
132 cards.end(),
133 [] (autofill::CreditCard* card) {
134 return card->IsValid();
135 });
136
137 return first_complete_card == cards.end() ? nullptr : *first_complete_card;
138}
139
mathpf709499d2017-01-09 20:48:36140} // namespace payments