OLD | NEW |
| (Empty) |
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 #include "chrome/browser/autofill/wallet/encryption_escrow_client.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "base/memory/scoped_ptr.h" | |
9 #include "base/string_number_conversions.h" | |
10 #include "base/stringprintf.h" | |
11 #include "base/strings/string_split.h" | |
12 #include "base/utf_string_conversions.h" | |
13 #include "chrome/browser/autofill/wallet/encryption_escrow_client_observer.h" | |
14 #include "chrome/browser/autofill/wallet/instrument.h" | |
15 #include "chrome/browser/autofill/wallet/wallet_service_url.h" | |
16 #include "googleurl/src/gurl.h" | |
17 #include "net/base/escape.h" | |
18 #include "net/http/http_status_code.h" | |
19 #include "net/url_request/url_fetcher.h" | |
20 #include "net/url_request/url_request_context_getter.h" | |
21 | |
22 namespace { | |
23 | |
24 const char kEncryptOtpBodyFormat[] = "cvv=%s:%s"; | |
25 const char kEscrowInstrumentInformationFormat[] = "gid=%s&cardNumber=%s&cvv=%s"; | |
26 const char kEscrowCardVerficationNumberFormat[] = "gid=%s&cvv=%s"; | |
27 const char kApplicationMimeType[] = "application/x-www-form-urlencoded"; | |
28 | |
29 // The maximum number of bits in the one time pad that the server is willing to | |
30 // accept. | |
31 const size_t kMaxBits = 56; | |
32 | |
33 // The minimum number of bits in the one time pad that the server is willing to | |
34 // accept. | |
35 const size_t kMinBits = 40; | |
36 | |
37 } // anonymous namespace | |
38 | |
39 namespace autofill { | |
40 namespace wallet { | |
41 | |
42 EncryptionEscrowClient::EncryptionEscrowClient( | |
43 net::URLRequestContextGetter* context_getter, | |
44 EncryptionEscrowClientObserver* observer) | |
45 : context_getter_(context_getter), | |
46 observer_(observer), | |
47 request_type_(NO_PENDING_REQUEST) { | |
48 DCHECK(context_getter_); | |
49 DCHECK(observer_); | |
50 } | |
51 | |
52 EncryptionEscrowClient::~EncryptionEscrowClient() {} | |
53 | |
54 void EncryptionEscrowClient::EncryptOneTimePad( | |
55 const std::vector<uint8>& one_time_pad) { | |
56 DCHECK_EQ(NO_PENDING_REQUEST, request_type_); | |
57 size_t num_bits = one_time_pad.size() * 8; | |
58 DCHECK_LE(num_bits, kMaxBits); | |
59 DCHECK_GE(num_bits, kMinBits); | |
60 | |
61 request_type_ = ENCRYPT_ONE_TIME_PAD; | |
62 | |
63 std::string post_body = StringPrintf( | |
64 kEncryptOtpBodyFormat, | |
65 base::HexEncode(&num_bits, 1).c_str(), | |
66 base::HexEncode(&(one_time_pad[0]), one_time_pad.size()).c_str()); | |
67 | |
68 MakeRequest(GetEncryptionUrl(), post_body); | |
69 } | |
70 | |
71 void EncryptionEscrowClient::EscrowInstrumentInformation( | |
72 const Instrument& new_instrument, | |
73 const std::string& obfuscated_gaia_id) { | |
74 DCHECK_EQ(NO_PENDING_REQUEST, request_type_); | |
75 request_type_ = ESCROW_INSTRUMENT_INFORMATION; | |
76 | |
77 const std::string& primary_account_number = | |
78 net::EscapeUrlEncodedData( | |
79 UTF16ToUTF8(new_instrument.primary_account_number()), true); | |
80 const std::string& card_verification_number = | |
81 net::EscapeUrlEncodedData( | |
82 UTF16ToUTF8(new_instrument.card_verification_number()), true); | |
83 | |
84 std::string post_body = StringPrintf( | |
85 kEscrowInstrumentInformationFormat, | |
86 obfuscated_gaia_id.c_str(), | |
87 primary_account_number.c_str(), | |
88 card_verification_number.c_str()); | |
89 | |
90 MakeRequest(GetEscrowUrl(), post_body); | |
91 } | |
92 | |
93 void EncryptionEscrowClient::EscrowCardVerificationNumber( | |
94 const std::string& card_verification_number, | |
95 const std::string& obfuscated_gaia_id) { | |
96 DCHECK_EQ(NO_PENDING_REQUEST, request_type_); | |
97 request_type_ = ESCROW_CARD_VERIFICATION_NUMBER; | |
98 | |
99 std::string post_body = StringPrintf( | |
100 kEscrowCardVerficationNumberFormat, | |
101 obfuscated_gaia_id.c_str(), | |
102 card_verification_number.c_str()); | |
103 | |
104 MakeRequest(GetEscrowUrl(), post_body); | |
105 } | |
106 | |
107 void EncryptionEscrowClient::MakeRequest(const GURL& url, | |
108 const std::string& post_body) { | |
109 DCHECK(!request_.get()); | |
110 | |
111 request_.reset(net::URLFetcher::Create( | |
112 1, url, net::URLFetcher::POST, this)); | |
113 request_->SetRequestContext(context_getter_); | |
114 DVLOG(1) << "url=" << url << ", post_body=" << post_body; | |
115 request_->SetUploadData(kApplicationMimeType, post_body); | |
116 request_->Start(); | |
117 } | |
118 | |
119 // TODO(ahutter): Add manual retry logic if it's necessary. | |
120 void EncryptionEscrowClient::OnURLFetchComplete( | |
121 const net::URLFetcher* source) { | |
122 DCHECK(observer_); | |
123 scoped_ptr<net::URLFetcher> old_request = request_.Pass(); | |
124 DCHECK_EQ(source, old_request.get()); | |
125 | |
126 DVLOG(1) << "Got response from " << source->GetOriginalURL(); | |
127 | |
128 RequestType type = request_type_; | |
129 request_type_ = NO_PENDING_REQUEST; | |
130 | |
131 std::string data; | |
132 source->GetResponseAsString(&data); | |
133 DVLOG(1) << "Response body: " << data; | |
134 | |
135 if (source->GetResponseCode() != net::HTTP_OK) { | |
136 observer_->OnNetworkError(source->GetResponseCode()); | |
137 return; | |
138 } | |
139 | |
140 if (data.empty()) { | |
141 HandleMalformedResponse(old_request.get()); | |
142 return; | |
143 } | |
144 | |
145 switch (type) { | |
146 case ENCRYPT_ONE_TIME_PAD: { | |
147 std::vector<std::string> splits; | |
148 // The response from the server should be formatted as | |
149 // "<session material>|<encrypted one time pad>". | |
150 base::SplitString(data, '|', &splits); | |
151 if (splits.size() == 2) | |
152 observer_->OnDidEncryptOneTimePad(splits[1], splits[0]); | |
153 else | |
154 HandleMalformedResponse(old_request.get()); | |
155 break; | |
156 } | |
157 | |
158 case ESCROW_INSTRUMENT_INFORMATION: | |
159 observer_->OnDidEscrowInstrumentInformation(data); | |
160 break; | |
161 | |
162 case ESCROW_CARD_VERIFICATION_NUMBER: | |
163 observer_->OnDidEscrowCardVerificationNumber(data); | |
164 break; | |
165 | |
166 case NO_PENDING_REQUEST: | |
167 NOTREACHED(); | |
168 } | |
169 } | |
170 | |
171 void EncryptionEscrowClient::HandleMalformedResponse(net::URLFetcher* request) { | |
172 // Called to inform exponential backoff logic of the error. | |
173 request->ReceivedContentWasMalformed(); | |
174 observer_->OnMalformedResponse(); | |
175 } | |
176 | |
177 } // namespace wallet | |
178 } // namespace autofill | |
OLD | NEW |