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_client.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    SPENDING_LIMIT_EXCEEDED,            // The desired transaction amount was
84                                        // over Wallet's limit.
85
86    // API errors --------------------------------------------------------------
87    // Request was very malformed or sent to the wrong endpoint.
88    BAD_REQUEST,
89    // API call had missing or invalid parameters.
90    INVALID_PARAMS,
91    // The server API version of the request is no longer supported.
92    UNSUPPORTED_API_VERSION,
93    // The user agent is not supported or a bad Google API key was provided.
94    UNSUPPORTED_USER_AGENT_OR_API_KEY,
95
96    // Server errors -----------------------------------------------------------
97    INTERNAL_ERROR,           // Unknown server side error.
98    SERVICE_UNAVAILABLE,      // Online Wallet is down.
99
100    // Other errors ------------------------------------------------------------
101    MALFORMED_RESPONSE,       // The response from Wallet was malformed.
102    NETWORK_ERROR,            // The response code of the server was something
103                              // other than a 200 or 400.
104
105    UNKNOWN_ERROR,            // Catch all error type.
106  };
107
108  struct FullWalletRequest {
109   public:
110    FullWalletRequest(const std::string& instrument_id,
111                      const std::string& address_id,
112                      const std::string& google_transaction_id,
113                      const std::vector<RiskCapability> risk_capabilities,
114                      bool new_wallet_user);
115    ~FullWalletRequest();
116
117    // The ID of the backing instrument. Should have been selected by the user
118    // in some UI.
119    std::string instrument_id;
120
121    // The ID of the shipping address. Should have been selected by the user
122    // in some UI.
123    std::string address_id;
124
125    // The transaction ID from GetWalletItems.
126    std::string google_transaction_id;
127
128    // The Risk challenges supported by the user of WalletClient
129    std::vector<RiskCapability> risk_capabilities;
130
131    // True if the user does not have Wallet profile.
132    bool new_wallet_user;
133
134   private:
135    DISALLOW_ASSIGN(FullWalletRequest);
136  };
137
138  // |context_getter| is reference counted so it has no lifetime or ownership
139  // requirements. |delegate| must outlive |this|. |source_url| is the url
140  // of the merchant page.
141  WalletClient(net::URLRequestContextGetter* context_getter,
142               WalletClientDelegate* delegate,
143               const GURL& source_url);
144
145  virtual ~WalletClient();
146
147  // GetWalletItems retrieves the user's online wallet. The WalletItems
148  // returned may require additional action such as presenting legal documents
149  // to the user to be accepted.
150  virtual void GetWalletItems(const base::string16& amount,
151                              const base::string16& currency);
152
153  // The GetWalletItems call to the Online Wallet backend may require the user
154  // to accept various legal documents before a FullWallet can be generated.
155  // The |google_transaction_id| is provided in the response to the
156  // GetWalletItems call. If |documents| are empty, |delegate_| will not receive
157  // a corresponding |OnDidAcceptLegalDocuments()| call.
158  virtual void AcceptLegalDocuments(
159      const std::vector<WalletItems::LegalDocument*>& documents,
160      const std::string& google_transaction_id);
161
162  // Authenticates that |card_verification_number| is for the backing instrument
163  // with |instrument_id|. |obfuscated_gaia_id| is used as a key when escrowing
164  // |card_verification_number|. |delegate_| is notified when the request is
165  // complete. Used to respond to Risk challenges.
166  virtual void AuthenticateInstrument(
167      const std::string& instrument_id,
168      const std::string& card_verification_number);
169
170  // GetFullWallet retrieves the a FullWallet for the user.
171  virtual void GetFullWallet(const FullWalletRequest& full_wallet_request);
172
173  // Saves the data in |instrument| and/or |address| to Wallet. |instrument|
174  // does not have to be complete if it's being used to update an existing
175  // instrument, like in the case of expiration date or address only updates.
176  // |reference_instrument| and |reference_address| are the original instrument
177  // and address to be updated on the server (and should be NULL if |instrument|
178  // or |address| are new data).
179  virtual void SaveToWallet(
180      scoped_ptr<Instrument> instrument,
181      scoped_ptr<Address> address,
182      const WalletItems::MaskedInstrument* reference_instrument,
183      const Address* reference_address);
184
185  bool HasRequestInProgress() const;
186
187  // Cancels and clears the current |request_|.
188  void CancelRequest();
189
190  // Sets the user index and cancels any pending requests.
191  void SetUserIndex(size_t user_index);
192  size_t user_index() const { return user_index_; }
193
194 private:
195  FRIEND_TEST_ALL_PREFIXES(WalletClientTest, PendingRequest);
196  FRIEND_TEST_ALL_PREFIXES(WalletClientTest, CancelRequests);
197
198  enum RequestType {
199    NO_REQUEST,
200    ACCEPT_LEGAL_DOCUMENTS,
201    AUTHENTICATE_INSTRUMENT,
202    GET_FULL_WALLET,
203    GET_WALLET_ITEMS,
204    SAVE_TO_WALLET,
205  };
206
207  // Like AcceptLegalDocuments, but takes a vector of document ids.
208  void DoAcceptLegalDocuments(
209      const std::vector<std::string>& document_ids,
210      const std::string& google_transaction_id);
211
212  // Posts |post_body| to |url| with content type |mime_type| and notifies
213  // |delegate_| when the request is complete.
214  void MakeWalletRequest(const GURL& url,
215                         const std::string& post_body,
216                         const std::string& mime_type,
217                         RequestType request_type);
218
219  // Performs bookkeeping tasks for any invalid requests.
220  void HandleMalformedResponse(RequestType request_type,
221                               net::URLFetcher* request);
222  void HandleNetworkError(int response_code);
223  void HandleWalletError(ErrorType error_type);
224
225  // net::URLFetcherDelegate:
226  virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
227
228  // Logs an UMA metric for each of the |required_actions|.
229  void LogRequiredActions(
230      const std::vector<RequiredAction>& required_actions) const;
231
232  // Converts |request_type| to an UMA metric.
233  AutofillMetrics::WalletApiCallMetric RequestTypeToUmaMetric(
234      RequestType request_type) const;
235
236  // The context for the request. Ensures the gdToken cookie is set as a header
237  // in the requests to Online Wallet if it is present.
238  scoped_refptr<net::URLRequestContextGetter> context_getter_;
239
240  // Observer class that has its various On* methods called based on the results
241  // of a request to Online Wallet.
242  WalletClientDelegate* const delegate_;  // must outlive |this|.
243
244  // The index of the user account we're making requests for. The index is into
245  // GAIA's list of signed in users.
246  size_t user_index_;
247
248  // The URL of the page we're making requests on behalf of.
249  GURL source_url_;
250
251  // The current request object.
252  scoped_ptr<net::URLFetcher> request_;
253
254  // The type of the current request. Must be NO_REQUEST for a request
255  // to be initiated as only one request may be running at a given time.
256  RequestType request_type_;
257
258  // The one time pad used for GetFullWallet encryption.
259  std::vector<uint8> one_time_pad_;
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