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

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

Powered by Google App Engine
This is Rietveld 408576698