Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(176)

Side by Side Diff: chrome/browser/autofill/wallet/wallet_data_retriever.cc

Issue 11293078: Integrating Online Wallet into Chrome. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Changes from Dane's review Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 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 "chrome/browser/autofill/wallet/wallet_data_retriever.h"
6
7 #include "base/json/json_reader.h"
8 #include "base/json/json_writer.h"
9 #include "base/logging.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/string_number_conversions.h"
12 #include "base/string_split.h"
13 #include "base/stringprintf.h"
14 #include "base/values.h"
15 #include "chrome/browser/autofill/wallet/cart.h"
16 #include "chrome/browser/autofill/wallet/full_wallet.h"
17 #include "chrome/browser/autofill/wallet/wallet_address.h"
18 #include "chrome/browser/autofill/wallet/wallet_items.h"
19 #include "chrome/browser/autofill/wallet/wallet_service_url.h"
20 #include "googleurl/src/gurl.h"
21 #include "net/http/http_status_code.h"
22 #include "net/url_request/url_fetcher.h"
23 #include "net/url_request/url_fetcher_delegate.h"
24 #include "net/url_request/url_request_context_getter.h"
25
26 namespace {
27 static const char kEncryptOtpBodyFormat[] = "cvv=%s:%s";
28 static const size_t kMaxBits = 63;
29
30 } // end anonymous namespace
31
32 namespace wallet {
33
34 class WalletDataRetriever::Core
35 : public base::RefCountedThreadSafe<WalletDataRetriever::Core>,
36 public net::URLFetcherDelegate {
37 public:
38 explicit Core(net::URLRequestContextGetter* context_getter)
39 : context_getter_(context_getter),
40 delegate_(NULL),
41 request_type_(NO_PENDING_REQUEST) {}
42 void AcceptLegalDocuments(const std::vector<std::string> document_ids,
43 const std::string& google_transaction_id,
44 Delegate* delegate);
45 void EncryptOtp(const void* otp, size_t length, Delegate* delegate);
46 void GetFullWallet(const std::string& instrument_id,
47 const std::string& address_id,
48 const std::string& merchant_domain,
49 const Cart& cart,
50 const std::string& google_transaction_id,
51 const std::string& encrypted_otp,
52 const std::string& session_material,
53 Delegate* delegate);
54 void GetWalletItems(Delegate* delegate);
55 void SendExtendedAutofillStatus(bool success,
56 const std::string& merchant_domain,
57 const std::string& reason,
58 const std::string& google_transaction_id,
59 Delegate* delegate);
60 virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
61 private:
62 friend class base::RefCountedThreadSafe<Core>;
63 std::string GetRiskParams() { return ""; }
Raman Kakilate 2012/11/17 02:28:31 TODO ?
ahutter 2012/11/27 00:46:12 Done.
ahutter 2012/11/27 00:46:12 Done.
64
65 enum RequestType {
66 NO_PENDING_REQUEST,
67 ACCEPT_LEGAL_DOCUMENTS,
68 ENCRYPT_OTP,
69 GET_FULL_WALLET,
70 GET_WALLET_ITEMS,
71 SEND_STATUS,
72 };
73
74 virtual ~Core() {}
75
76 void MakeWalletRequest(const GURL url,
77 const std::string& post_body,
78 WalletDataRetriever::Delegate* delegate,
79 const std::string& content_type = "application/json");
80
81 void HandleResponse(const net::URLFetcher* source,
82 bool* should_retry_request);
83
84 scoped_refptr<net::URLRequestContextGetter> context_getter_;
85 WalletDataRetriever::Delegate* delegate_;
86 scoped_ptr<net::URLFetcher> request_;
87 RequestType request_type_;
88 };
89
90 void WalletDataRetriever::Core::AcceptLegalDocuments(
91 const std::vector<std::string> document_ids,
92 const std::string& google_transaction_id,
93 WalletDataRetriever::Delegate* delegate) {
94 DCHECK_EQ(request_type_, NO_PENDING_REQUEST);
Raman Kakilate 2012/11/17 02:28:31 What happens if this occurs in production, Slow ne
95 request_type_ = ACCEPT_LEGAL_DOCUMENTS;
96 GURL url = GetAcceptLegalDocumentsUrl();
97 DictionaryValue request_dict;
98 request_dict.SetString("api_key", wallet::kApiKey);
99 request_dict.SetString("google_transaction_id", google_transaction_id);
100 ListValue* docs_list = new ListValue();
101 for (std::vector<std::string>::const_iterator it = document_ids.begin();
102 it != document_ids.end();
103 ++it)
104 docs_list->AppendString(*it);
105 request_dict.Set("accepted_legal_document", docs_list);
106
107 std::string post_body;
108 base::JSONWriter::Write(&request_dict, &post_body);
109 MakeWalletRequest(url, post_body, delegate);
110 }
111
112 void WalletDataRetriever::Core::EncryptOtp(
113 const void* otp,
114 size_t length,
115 WalletDataRetriever::Delegate* delegate) {
116 DCHECK_EQ(request_type_, NO_PENDING_REQUEST);
117 request_type_ = ENCRYPT_OTP;
118 GURL url = GetSecureUrl();
119 size_t num_bits = length * 8;
120 CHECK_LT(num_bits, kMaxBits);
Raman Kakilate 2012/11/17 02:28:31 DCHECK ?
ahutter 2012/11/27 00:46:12 Done.
121 std::string post_body = StringPrintf(kEncryptOtpBodyFormat,
122 base::HexEncode(&num_bits, 1).c_str(),
123 base::HexEncode(otp, length).c_str());
124 MakeWalletRequest(url,
125 post_body,
126 delegate,
127 "application/x-www-form-urlencoded");
128 }
129
130 void WalletDataRetriever::Core::GetFullWallet(
131 const std::string& instrument_id,
132 const std::string& address_id,
133 const std::string& merchant_domain,
134 const Cart& cart,
135 const std::string& google_transaction_id,
136 const std::string& encrypted_otp,
137 const std::string& session_material,
138 WalletDataRetriever::Delegate* delegate) {
139 DCHECK_EQ(request_type_, NO_PENDING_REQUEST);
140 request_type_ = GET_FULL_WALLET;
141 GURL url = GetGetFullWalletUrl();
142 DictionaryValue request_dict;
143 request_dict.SetString("api_key", wallet::kApiKey);
144 request_dict.SetString("risk_params", GetRiskParams());
145 request_dict.SetString("selected_instrument_id", instrument_id);
146 request_dict.SetString("selected_address_id", address_id);
147 request_dict.SetString("merchant_domain", merchant_domain);
148 request_dict.SetString("google_transaction_id", google_transaction_id);
149 scoped_ptr<DictionaryValue> cart_dict = cart.ToDictionary();
150 request_dict.Set("cart", cart_dict.release());
151 request_dict.SetString("encrypted_otp", encrypted_otp);
152 request_dict.SetString("session_material", session_material);
153 std::string post_body;
154 base::JSONWriter::Write(&request_dict, &post_body);
155 MakeWalletRequest(url, post_body, delegate);
156 }
157
158 void WalletDataRetriever::Core::GetWalletItems(
159 WalletDataRetriever::Delegate* delegate) {
160 DCHECK_EQ(request_type_, NO_PENDING_REQUEST);
161 request_type_ = GET_WALLET_ITEMS;
162 GURL url = GetGetWalletItemsUrl();
163 DictionaryValue request_dict;
164 request_dict.SetString("api_key", wallet::kApiKey);
165 request_dict.SetString("risk_params", GetRiskParams());
166 std::string post_body;
167 base::JSONWriter::Write(&request_dict, &post_body);
168 MakeWalletRequest(url, post_body, delegate);
169 }
170
171 void WalletDataRetriever::Core::SendExtendedAutofillStatus(
172 bool success,
173 const std::string& merchant_domain,
174 const std::string& reason,
175 const std::string& google_transaction_id,
176 WalletDataRetriever::Delegate* delegate) {
177 DCHECK_EQ(request_type_, NO_PENDING_REQUEST);
178 request_type_ = SEND_STATUS;
179 GURL url = GetSendStatusUrl();
180 DictionaryValue request_dict;
181 request_dict.SetString("api_key", wallet::kApiKey);
182 request_dict.SetBoolean("success", success);
183 request_dict.SetString("hostname", merchant_domain);
184 if (!success)
185 // TODO(ahutter): Probably want to do some checks on reason
186 request_dict.SetString("reason", reason);
187 request_dict.SetString("google_transaction_id", google_transaction_id);
188 std::string post_body;
189 base::JSONWriter::Write(&request_dict, &post_body);
190 MakeWalletRequest(url, post_body, delegate);
191 }
192
193 void WalletDataRetriever::Core::MakeWalletRequest(
194 GURL url,
195 const std::string& post_body,
196 WalletDataRetriever::Delegate* delegate,
197 const std::string& content_type) {
198 DCHECK(!request_.get()) << "Tried to fetch two things at once!";
199 delegate_ = delegate;
200 request_.reset(net::URLFetcher::Create(
201 0, url, net::URLFetcher::POST, this));
202 request_->SetRequestContext(context_getter_);
203 VLOG(1) << "Request body: " << post_body;
204 request_->SetUploadData(content_type, post_body);
205 request_->SetMaxRetries(0);
206 request_->Start();
207 }
208
209
210 void WalletDataRetriever::Core::OnURLFetchComplete(
211 const net::URLFetcher* source) {
212 bool should_retry = false;
213 HandleResponse(source, &should_retry);
214 if (should_retry) {
215 // Explicitly call ReceivedContentWasMalformed() to ensure the current
216 // request gets counted as a failure for calculation of the back-off
217 // period. If it was already a failure by status code, this call will
218 // be ignored.
219 request_->ReceivedContentWasMalformed();
220 // We must set our context_getter_ again because
221 // URLFetcher::Core::RetryOrCompleteUrlFetch resets it to NULL...
222 request_->SetRequestContext(context_getter_);
223 request_->Start();
224 }
225 }
226
227 void WalletDataRetriever::Core::HandleResponse(
228 const net::URLFetcher* source,
229 bool* should_retry_request) {
230 // Keep the URLFetcher object in case we need to reuse it.
231 scoped_ptr<net::URLFetcher> old_request = request_.Pass();
232 DCHECK_EQ(source, old_request.get());
233
234 // HTTP_BAD_REQUEST means the arguments are invalid. No point retrying. We are
235 // done here.
236 if (source->GetResponseCode() == net::HTTP_BAD_REQUEST) {
237 request_type_ = NO_PENDING_REQUEST;
238 delegate_->OnWalletError();
239 return;
240 }
241
242 scoped_ptr<DictionaryValue> response_dict;
243 if (source->GetResponseCode() == net::HTTP_OK) {
244 std::string data;
245 source->GetResponseAsString(&data);
246 VLOG(1) << "Response body: " << data;
247 scoped_ptr<Value> message_value(base::JSONReader::Read(data));
248 if (message_value.get() &&
249 message_value->IsType(Value::TYPE_DICTIONARY)) {
250 response_dict.reset(
251 static_cast<DictionaryValue*>(message_value.release()));
252 }
253 }
254
255 // TODO(ahutter): this condition sucks. needs to be simplified.
256 if (!response_dict.get() &&
257 (!(request_type_ == SEND_STATUS
258 || request_type_ == ACCEPT_LEGAL_DOCUMENTS
259 || request_type_ == ENCRYPT_OTP)
260 || source->GetResponseCode() != net::HTTP_OK)) {
261 if ((source->GetMaxRetries() != -1)) {
262 request_type_ = NO_PENDING_REQUEST;
263 VLOG(1) << "Hitting " << source->GetOriginalURL();
264 delegate_->OnNetworkError(source->GetResponseCode());
265 } else {
266 request_ = old_request.Pass();
267 *should_retry_request = true;
268 }
269 return;
270 }
271
272 RequestType type = request_type_;
273 request_type_ = NO_PENDING_REQUEST;
274
275 switch (type) {
276 case ACCEPT_LEGAL_DOCUMENTS:
277 delegate_->OnAcceptLegalDocuments();
278 break;
279 case ENCRYPT_OTP: {
280 std::string data;
281 source->GetResponseAsString(&data);
282 std::vector<std::string> splits;
283 base::SplitString(data, '|', &splits);
284 if (splits.size() != 2) {
285 delegate_->OnWalletError();
286 } else {
287 delegate_->OnEncryptOtp(splits[1], splits[0]);
288 }
289 break;
290 }
291 case SEND_STATUS:
292 delegate_->OnSendExtendedAutofillStatus();
293 break;
294 case GET_FULL_WALLET: {
295 scoped_ptr<FullWallet> full_wallet(
296 FullWallet::CreateFromDictionary(response_dict.get()));
297 if (full_wallet.get()) {
298 delegate_->OnGetFullWallet(full_wallet.release());
299 } else {
300 delegate_->OnWalletError();
301 }
302 break;
303 }
304 case GET_WALLET_ITEMS: {
305 scoped_ptr<WalletItems> wallet_items(
306 WalletItems::CreateFromDictionary(response_dict.get()));
307 if (wallet_items.get()) {
308 delegate_->OnGetWalletItems(wallet_items.release());
309 } else {
310 delegate_->OnWalletError();
311 }
312 break;
313 }
314 default:
315 NOTREACHED();
316 }
317 }
318
319 WalletDataRetriever::WalletDataRetriever(
320 net::URLRequestContextGetter* context_getter) {
321 core_ = new Core(context_getter);
322 }
323
324 WalletDataRetriever::~WalletDataRetriever() {}
325
326 void WalletDataRetriever::AcceptLegalDocuments(
327 const std::vector<std::string> document_ids,
328 const std::string& google_transaction_id,
329 WalletDataRetriever::Delegate* delegate) {
330 core_->AcceptLegalDocuments(document_ids,
331 google_transaction_id,
332 delegate);
333 }
334
335 void WalletDataRetriever::EncryptOtp(const void* otp,
336 size_t length,
337 WalletDataRetriever::Delegate* delegate) {
338 core_->EncryptOtp(otp, length, delegate);
339 }
340
341 void WalletDataRetriever::GetFullWallet(
342 const std::string& instrument_id,
343 const std::string& address_id,
344 const std::string& merchant_domain,
345 const Cart& cart,
346 const std::string& google_transaction_id,
347 const std::string& encrypted_otp,
348 const std::string& session_material,
349 WalletDataRetriever::Delegate* delegate) {
350 core_->GetFullWallet(instrument_id,
351 address_id,
352 merchant_domain,
353 cart,
354 google_transaction_id,
355 encrypted_otp,
356 session_material,
357 delegate);
358 }
359
360 void WalletDataRetriever::GetWalletItems(
361 WalletDataRetriever::Delegate* delegate) {
362 core_->GetWalletItems(delegate);
363 }
364
365 void WalletDataRetriever::SendExtendedAutofillStatus(
366 bool success,
367 const std::string& merchant_domain,
368 const std::string& reason,
369 const std::string& google_transaction_id,
370 WalletDataRetriever::Delegate* delegate) {
371 core_->SendExtendedAutofillStatus(success,
372 merchant_domain,
373 reason,
374 google_transaction_id,
375 delegate);
376 }
377
378 } // end wallet namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698