1// Copyright 2013 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#ifndef COMPONENTS_AUTOFILL_CONTENT_BROWSER_WALLET_WALLET_CLIENT_H_
6#define COMPONENTS_AUTOFILL_CONTENT_BROWSER_WALLET_WALLET_CLIENT_H_
7
8#include <queue>
9#include <string>
10#include <vector>
11
12#include "base/callback.h"  // For base::Closure.
13#include "base/memory/ref_counted.h"
14#include "base/memory/weak_ptr.h"
15#include "base/time/time.h"
16#include "base/values.h"
17#include "components/autofill/content/browser/wallet/full_wallet.h"
18#include "components/autofill/content/browser/wallet/wallet_items.h"
19#include "components/autofill/core/browser/autofill_manager_delegate.h"
20#include "components/autofill/core/browser/autofill_metrics.h"
21#include "net/url_request/url_fetcher_delegate.h"
22#include "testing/gtest/include/gtest/gtest_prod.h"
23#include "url/gurl.h"
24
25namespace net {
26class URLFetcher;
27class URLRequestContextGetter;
28}
29
30namespace autofill {
31namespace wallet {
32
33class Address;
34class FullWallet;
35class Instrument;
36class WalletClientDelegate;
37
38// WalletClient is responsible for making calls to the Online Wallet backend on
39// the user's behalf. The normal flow for using this class is as follows:
40// 1) GetWalletItems should be called to retrieve the user's Wallet.
41//   a) If the user does not have a Wallet, they must AcceptLegalDocuments and
42//      SaveToWallet to set up their account before continuing.
43//   b) If the user has not accepted the most recent legal documents for
44//      Wallet, they must AcceptLegalDocuments.
45// 2) The user then chooses what instrument and shipping address to use for the
46//    current transaction.
47//   a) If they choose an instrument with a zip code only address, the billing
48//      address will need to be updated using SaveToWallet.
49//   b) The user may also choose to add a new instrument or address using
50//      SaveToWallet.
51// 3) Once the user has selected the backing instrument and shipping address
52//    for this transaction, a FullWallet with the fronting card is generated
53//    using GetFullWallet.
54//   a) GetFullWallet may return a Risk challenge for the user. In that case,
55//      the user will need to verify who they are by authenticating their
56//      chosen backing instrument through AuthenticateInstrument
57//
58// WalletClient is designed so only one request to Online Wallet can be outgoing
59// at any one time. If |HasRequestInProgress()| is true while calling e.g.
60// GetWalletItems(), the request will be queued and started later. Queued
61// requests start in the order they were received.
62
63class WalletClient : public net::URLFetcherDelegate {
64 public:
65  // The Risk challenges supported by users of WalletClient.
66  enum RiskCapability {
67    RELOGIN,
68    VERIFY_CVC,
69  };
70
71  // The type of error returned by Online Wallet.
72  enum ErrorType {
73    // Errors to display to users.
74    BUYER_ACCOUNT_ERROR,                // Risk deny, unsupported country, or
75                                        // account closed.
76    BUYER_LEGAL_ADDRESS_NOT_SUPPORTED,  // User's Buyer Legal Address is
77                                        // unsupported by Online Wallet.
78    UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS,  // User's "know your customer" KYC
79                                           // state is not verified (either
80                                           // KYC_REFER or KYC_FAIL).
81    UNSUPPORTED_MERCHANT,               // Merchant is blacklisted due to
82                                        // compliance violation.
83
84    // API errors.
85    BAD_REQUEST,              // Request was very malformed or sent to the
86                              // wrong endpoint.
87    INVALID_PARAMS,           // API call had missing or invalid parameters.
88    UNSUPPORTED_API_VERSION,  // The server API version of the request is no
89                              // longer supported.
90
91    // Server errors.
92    INTERNAL_ERROR,           // Unknown server side error.
93    SERVICE_UNAVAILABLE,      // Online Wallet is down.
94
95    // Other errors.
96    MALFORMED_RESPONSE,       // The response from Wallet was malformed.
97    NETWORK_ERROR,            // The response code of the server was something
98                              // other than a 200 or 400.
99
100    UNKNOWN_ERROR,            // Catch all error type.
101  };
102
103  struct FullWalletRequest {
104   public:
105    FullWalletRequest(const std::string& instrument_id,
106                      const std::string& address_id,
107                      const std::string& google_transaction_id,
108                      const std::vector<RiskCapability> risk_capabilities,
109                      bool new_wallet_user);
110    ~FullWalletRequest();
111
112    // The ID of the backing instrument. Should have been selected by the user
113    // in some UI.
114    std::string instrument_id;
115
116    // The ID of the shipping address. Should have been selected by the user
117    // in some UI.
118    std::string address_id;
119
120    // The transaction ID from GetWalletItems.
121    std::string google_transaction_id;
122
123    // The Risk challenges supported by the user of WalletClient
124    std::vector<RiskCapability> risk_capabilities;
125
126    // True if the user does not have Wallet profile.
127    bool new_wallet_user;
128
129   private:
130    DISALLOW_ASSIGN(FullWalletRequest);
131  };
132
133  // |context_getter| is reference counted so it has no lifetime or ownership
134  // requirements. |delegate| must outlive |this|. |source_url| is the url
135  // of the merchant page.
136  WalletClient(net::URLRequestContextGetter* context_getter,
137               WalletClientDelegate* delegate,
138               const GURL& source_url);
139
140  virtual ~WalletClient();
141
142  // GetWalletItems retrieves the user's online wallet. The WalletItems
143  // returned may require additional action such as presenting legal documents
144  // to the user to be accepted.
145  virtual void GetWalletItems();
146
147  // The GetWalletItems call to the Online Wallet backend may require the user
148  // to accept various legal documents before a FullWallet can be generated.
149  // The |google_transaction_id| is provided in the response to the
150  // GetWalletItems call. If |documents| are empty, |delegate_| will not receive
151  // a corresponding |OnDidAcceptLegalDocuments()| call.
152  virtual void AcceptLegalDocuments(
153      const std::vector<WalletItems::LegalDocument*>& documents,
154      const std::string& google_transaction_id);
155
156  // Authenticates that |card_verification_number| is for the backing instrument
157  // with |instrument_id|. |obfuscated_gaia_id| is used as a key when escrowing
158  // |card_verification_number|. |delegate_| is notified when the request is
159  // complete. Used to respond to Risk challenges.
160  virtual void AuthenticateInstrument(
161      const std::string& instrument_id,
162      const std::string& card_verification_number);
163
164  // GetFullWallet retrieves the a FullWallet for the user.
165  virtual void GetFullWallet(const FullWalletRequest& full_wallet_request);
166
167  // Saves the data in |instrument| and/or |address| to Wallet. |instrument|
168  // does not have to be complete if it's being used to update an existing
169  // instrument, like in the case of expiration date or address only updates.
170  // |reference_instrument| and |reference_address| are the original instrument
171  // and address to be updated on the server (and should be NULL if |instrument|
172  // or |address| are new data).
173  virtual void SaveToWallet(
174      scoped_ptr<Instrument> instrument,
175      scoped_ptr<Address> address,
176      const WalletItems::MaskedInstrument* reference_instrument,
177      const Address* reference_address);
178
179  bool HasRequestInProgress() const;
180
181  // Cancels and clears the current |request_| and |pending_requests_| (if any).
182  void CancelRequests();
183
184  // Sets the user index and cancels any pending requests.
185  void SetUserIndex(size_t user_index);
186  size_t user_index() const { return user_index_; }
187
188 private:
189  FRIEND_TEST_ALL_PREFIXES(WalletClientTest, PendingRequest);
190  FRIEND_TEST_ALL_PREFIXES(WalletClientTest, CancelRequests);
191
192  enum RequestType {
193    NO_PENDING_REQUEST,
194    ACCEPT_LEGAL_DOCUMENTS,
195    AUTHENTICATE_INSTRUMENT,
196    GET_FULL_WALLET,
197    GET_WALLET_ITEMS,
198    SAVE_TO_WALLET,
199  };
200
201  // Like AcceptLegalDocuments, but takes a vector of document ids.
202  void DoAcceptLegalDocuments(
203      const std::vector<std::string>& document_ids,
204      const std::string& google_transaction_id);
205
206  // Posts |post_body| to |url| with content type |mime_type| and notifies
207  // |delegate_| when the request is complete.
208  void MakeWalletRequest(const GURL& url,
209                         const std::string& post_body,
210                         const std::string& mime_type,
211                         RequestType request_type);
212
213  // Performs bookkeeping tasks for any invalid requests.
214  void HandleMalformedResponse(RequestType request_type,
215                               net::URLFetcher* request);
216  void HandleNetworkError(int response_code);
217  void HandleWalletError(ErrorType error_type);
218
219  // Start the next pending request (if any).
220  void StartNextPendingRequest();
221
222  // net::URLFetcherDelegate:
223  virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
224
225  // Logs an UMA metric for each of the |required_actions|.
226  void LogRequiredActions(
227      const std::vector<RequiredAction>& required_actions) const;
228
229  // Converts |request_type| to an UMA metric.
230  AutofillMetrics::WalletApiCallMetric RequestTypeToUmaMetric(
231      RequestType request_type) const;
232
233  // The context for the request. Ensures the gdToken cookie is set as a header
234  // in the requests to Online Wallet if it is present.
235  scoped_refptr<net::URLRequestContextGetter> context_getter_;
236
237  // Observer class that has its various On* methods called based on the results
238  // of a request to Online Wallet.
239  WalletClientDelegate* const delegate_;  // must outlive |this|.
240
241  // The index of the user account we're making requests for. The index is into
242  // GAIA's list of signed in users.
243  size_t user_index_;
244
245  // The URL of the page we're making requests on behalf of.
246  GURL source_url_;
247
248  // The current request object.
249  scoped_ptr<net::URLFetcher> request_;
250
251  // The type of the current request. Must be NO_PENDING_REQUEST for a request
252  // to be initiated as only one request may be running at a given time.
253  RequestType request_type_;
254
255  // The one time pad used for GetFullWallet encryption.
256  std::vector<uint8> one_time_pad_;
257
258  // Requests that are waiting to be run.
259  std::queue<base::Closure> pending_requests_;
260
261  // When the current request started. Used to track client side latency.
262  base::Time request_started_timestamp_;
263
264  base::WeakPtrFactory<WalletClient> weak_ptr_factory_;
265
266  DISALLOW_COPY_AND_ASSIGN(WalletClient);
267};
268
269}  // namespace wallet
270}  // namespace autofill
271
272#endif  // COMPONENTS_AUTOFILL_CONTENT_BROWSER_WALLET_WALLET_CLIENT_H_
273