summaryrefslogtreecommitdiffstats
path: root/components/autofill/content/browser/wallet/wallet_client.h
blob: a76eba40d10ff61ec1b197a631c7391730e00c00 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
// Copyright 2013 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_AUTOFILL_CONTENT_BROWSER_WALLET_WALLET_CLIENT_H_
#define COMPONENTS_AUTOFILL_CONTENT_BROWSER_WALLET_WALLET_CLIENT_H_

#include <queue>
#include <string>
#include <vector>

#include "base/callback.h"  // For base::Closure.
#include "base/memory/ref_counted.h"
#include "base/time/time.h"
#include "base/values.h"
#include "components/autofill/content/browser/autocheckout_statistic.h"
#include "components/autofill/content/browser/wallet/encryption_escrow_client.h"
#include "components/autofill/content/browser/wallet/encryption_escrow_client_observer.h"
#include "components/autofill/content/browser/wallet/full_wallet.h"
#include "components/autofill/content/browser/wallet/wallet_items.h"
#include "components/autofill/core/browser/autofill_manager_delegate.h"
#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/autofill/core/common/autocheckout_status.h"
#include "googleurl/src/gurl.h"
#include "net/url_request/url_fetcher_delegate.h"
#include "testing/gtest/include/gtest/gtest_prod.h"

namespace net {
class URLFetcher;
class URLRequestContextGetter;
}

namespace autofill {
namespace wallet {

class Address;
class FullWallet;
class Instrument;
class WalletClientDelegate;

// WalletClient is responsible for making calls to the Online Wallet backend on
// the user's behalf. The normal flow for using this class is as follows:
// 1) GetWalletItems should be called to retrieve the user's Wallet.
//   a) If the user does not have a Wallet, they must AcceptLegalDocuments and
//      SaveInstrumentAndAddress before continuing.
//   b) If the user has not accepted the most recent legal documents for
//      Wallet, they must AcceptLegalDocuments.
// 2) The user then chooses what instrument and shipping address to use for the
//    current transaction.
//   a) If they choose an instrument with a zip code only address, the billing
//      address will need to be updated using UpdateInstrument.
//   b) The user may also choose to add a new instrument or address using
//      SaveAddress, SaveInstrument, or SaveInstrumentAndAddress.
// 3) Once the user has selected the backing instrument and shipping address
//    for this transaction, a FullWallet with the fronting card is generated
//    using GetFullWallet.
//   a) GetFullWallet may return a Risk challenge for the user. In that case,
//      the user will need to verify who they are by authenticating their
//      chosen backing instrument through AuthenticateInstrument
// 4) If the user initiated Autocheckout, SendAutocheckoutStatus to notify
//    Online Wallet of the status flow to record various metrics.
//
// WalletClient is designed so only one request to Online Wallet can be outgoing
// at any one time. If |HasRequestInProgress()| is true while calling e.g.
// GetWalletItems(), the request will be queued and started later. Queued
// requests start in the order they were received.

class WalletClient
    : public net::URLFetcherDelegate,
      public EncryptionEscrowClientObserver {
 public:
  // The Risk challenges supported by users of WalletClient.
  enum RiskCapability {
    RELOGIN,
    VERIFY_CVC,
  };

  // The type of error returned by Online Wallet.
  enum ErrorType {
    // Errors to display to users.
    BUYER_ACCOUNT_ERROR,      // Risk deny, unsupported country, or account
                              // closed.

    // API errors.
    BAD_REQUEST,              // Request was very malformed or sent to the
                              // wrong endpoint.
    INVALID_PARAMS,           // API call had missing or invalid parameters.
    UNSUPPORTED_API_VERSION,  // The server API version of the request is no
                              // longer supported.

    // Server errors.
    INTERNAL_ERROR,           // Unknown server side error.
    SERVICE_UNAVAILABLE,      // Online Wallet is down.

    // Other errors.
    MALFORMED_RESPONSE,       // The response from Wallet was malformed.
    NETWORK_ERROR,            // The response code of the server was something
                              // other than a 200 or 400.

    UNKNOWN_ERROR,            // Catch all error type.
  };

  struct FullWalletRequest {
   public:
    FullWalletRequest(const std::string& instrument_id,
                      const std::string& address_id,
                      const GURL& source_url,
                      const std::string& google_transaction_id,
                      const std::vector<RiskCapability> risk_capabilities);
    ~FullWalletRequest();

    // The ID of the backing instrument. Should have been selected by the user
    // in some UI.
    std::string instrument_id;

    // The ID of the shipping address. Should have been selected by the user
    // in some UI.
    std::string address_id;

    // The URL that Online Wallet usage is being initiated on.
    GURL source_url;

    // The transaction ID from GetWalletItems.
    std::string google_transaction_id;

    // The Risk challenges supported by the user of WalletClient
    std::vector<RiskCapability> risk_capabilities;

   private:
    DISALLOW_ASSIGN(FullWalletRequest);
  };

  struct UpdateInstrumentRequest {
   public:
    UpdateInstrumentRequest(const std::string& instrument_id,
                            const GURL& source_url);
    ~UpdateInstrumentRequest();

    // The id of the instrument being modified.
    std::string instrument_id;

    // The new expiration date. If these are set, |card_verification_number| and
    // |obfuscated_gaia_id| must be provided.
    int expiration_month;
    int expiration_year;

    // Used to authenticate the card the user is modifying.
    std::string card_verification_number;

    // Used to key the escrow of |card_verification_number|.
    std::string obfuscated_gaia_id;

    // The url this call is initiated from.
    GURL source_url;

   private:
    DISALLOW_ASSIGN(UpdateInstrumentRequest);
  };

  // |context_getter| is reference counted so it has no lifetime or ownership
  // requirements. |delegate| must outlive |this|.
  WalletClient(net::URLRequestContextGetter* context_getter,
               WalletClientDelegate* delegate);

  virtual ~WalletClient();

  // GetWalletItems retrieves the user's online wallet. The WalletItems
  // returned may require additional action such as presenting legal documents
  // to the user to be accepted.
  virtual void GetWalletItems(const GURL& source_url);

  // The GetWalletItems call to the Online Wallet backend may require the user
  // to accept various legal documents before a FullWallet can be generated.
  // The |google_transaction_id| is provided in the response to the
  // GetWalletItems call. If |documents| are empty, |delegate_| will not receive
  // a corresponding |OnDidAcceptLegalDocuments()| call.
  virtual void AcceptLegalDocuments(
      const std::vector<WalletItems::LegalDocument*>& documents,
      const std::string& google_transaction_id,
      const GURL& source_url);

  // Authenticates that |card_verification_number| is for the backing instrument
  // with |instrument_id|. |obfuscated_gaia_id| is used as a key when escrowing
  // |card_verification_number|. |delegate_| is notified when the request is
  // complete. Used to respond to Risk challenges.
  virtual void AuthenticateInstrument(
      const std::string& instrument_id,
      const std::string& card_verification_number,
      const std::string& obfuscated_gaia_id);

  // GetFullWallet retrieves the a FullWallet for the user.
  virtual void GetFullWallet(const FullWalletRequest& full_wallet_request);

  // SaveAddress saves a new shipping address.
  virtual void SaveAddress(const Address& address, const GURL& source_url);

  // SaveInstrument saves a new instrument.
  virtual void SaveInstrument(const Instrument& instrument,
                              const std::string& obfuscated_gaia_id,
                              const GURL& source_url);

  // SaveInstrumentAndAddress saves a new instrument and address.
  virtual void SaveInstrumentAndAddress(const Instrument& instrument,
                                        const Address& shipping_address,
                                        const std::string& obfuscated_gaia_id,
                                        const GURL& source_url);

  // SendAutocheckoutStatus is used for tracking the success of Autocheckout
  // flows. |status| is the result of the flow, |source_url| is the domain
  // where the purchase occured, and |google_transaction_id| is the same as the
  // one provided by GetWalletItems. |latency_statistics| contain statistics
  // required to measure Autocheckout process.
  void SendAutocheckoutStatus(
      autofill::AutocheckoutStatus status,
      const GURL& source_url,
      const std::vector<AutocheckoutStatistic>& latency_statistics,
      const std::string& google_transaction_id);

  // UpdateAddress updates Online Wallet with the data in |address|.
  virtual void UpdateAddress(const Address& address, const GURL& source_url);

  // Updates Online Wallet with the data in |update_instrument_request| and, if
  // it's provided, |billing_address|.
  virtual void UpdateInstrument(
      const UpdateInstrumentRequest& update_instrument_request,
      scoped_ptr<Address> billing_address);

  bool HasRequestInProgress() const;

  // Cancels and clears the current |request_| and |pending_requests_| (if any).
  void CancelRequests();

 private:
  FRIEND_TEST_ALL_PREFIXES(WalletClientTest, PendingRequest);
  FRIEND_TEST_ALL_PREFIXES(WalletClientTest, CancelRequests);

  enum RequestType {
    NO_PENDING_REQUEST,
    ACCEPT_LEGAL_DOCUMENTS,
    AUTHENTICATE_INSTRUMENT,
    GET_FULL_WALLET,
    GET_WALLET_ITEMS,
    SAVE_ADDRESS,
    SAVE_INSTRUMENT,
    SAVE_INSTRUMENT_AND_ADDRESS,
    SEND_STATUS,
    UPDATE_ADDRESS,
    UPDATE_INSTRUMENT,
  };

  // Like AcceptLegalDocuments, but takes a vector of document ids.
  void DoAcceptLegalDocuments(
      const std::vector<std::string>& document_ids,
      const std::string& google_transaction_id,
      const GURL& source_url);

  // Posts |post_body| to |url| and notifies |delegate_| when the request is
  // complete.
  void MakeWalletRequest(const GURL& url, const std::string& post_body);

  // Performs bookkeeping tasks for any invalid requests.
  void HandleMalformedResponse();
  void HandleNetworkError(int response_code);
  void HandleWalletError(ErrorType error_type);

  // Start the next pending request (if any).
  void StartNextPendingRequest();

  // net::URLFetcherDelegate:
  virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;

  // EncryptionEscrowClientObserver:
  virtual void OnDidEncryptOneTimePad(
      const std::string& encrypted_one_time_pad,
      const std::string& session_material) OVERRIDE;
  virtual void OnDidEscrowInstrumentInformation(
      const std::string& escrow_handle)  OVERRIDE;
  virtual void OnDidEscrowCardVerificationNumber(
      const std::string& escrow_handle) OVERRIDE;
  virtual void OnDidMakeRequest() OVERRIDE;
  virtual void OnNetworkError() OVERRIDE;
  virtual void OnMalformedResponse() OVERRIDE;

  // Logs an UMA metric for each of the |required_actions|.
  void LogRequiredActions(
      const std::vector<RequiredAction>& required_actions) const;

  // Converts |request_type| to an UMA metric.
  AutofillMetrics::WalletApiCallMetric RequestTypeToUmaMetric(
      RequestType request_type) const;

  // The context for the request. Ensures the gdToken cookie is set as a header
  // in the requests to Online Wallet if it is present.
  scoped_refptr<net::URLRequestContextGetter> context_getter_;

  // Observer class that has its various On* methods called based on the results
  // of a request to Online Wallet.
  WalletClientDelegate* const delegate_;  // must outlive |this|.

  // The current request object.
  scoped_ptr<net::URLFetcher> request_;

  // The type of the current request. Must be NO_PENDING_REQUEST for a request
  // to be initiated as only one request may be running at a given time.
  RequestType request_type_;

  // The one time pad used for GetFullWallet encryption.
  std::vector<uint8> one_time_pad_;

  // GetFullWallet requests and requests that alter instruments rely on requests
  // made through the |encryption_escrow_client_| finishing first. The request
  // body is saved here while that those requests are in flight.
  base::DictionaryValue pending_request_body_;

  // Requests that are waiting to be run.
  std::queue<base::Closure> pending_requests_;

  // This client is repsonsible for making encryption and escrow calls to Online
  // Wallet.
  EncryptionEscrowClient encryption_escrow_client_;

  // When the current request started. Used to track client side latency.
  base::Time request_started_timestamp_;

  DISALLOW_COPY_AND_ASSIGN(WalletClient);
};

}  // namespace wallet
}  // namespace autofill

#endif  // COMPONENTS_AUTOFILL_CONTENT_BROWSER_WALLET_WALLET_CLIENT_H_