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

Side by Side Diff: chrome/browser/safe_browsing/malware_details_cache.cc

Issue 6611023: The optional Malware Details also collects HTTP cache information. See design... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 9 months 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
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 // Implementation of the MalwareDetails class.
6
7 #include "chrome/browser/safe_browsing/malware_details.h"
8
9 #include "base/callback.h"
10 #include "base/lazy_instance.h"
11 #include "base/md5.h"
12 #include "chrome/browser/net/chrome_url_request_context.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/safe_browsing/malware_details_cache.h"
15 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
16 #include "chrome/browser/safe_browsing/report.pb.h"
17 #include "chrome/common/net/url_request_context_getter.h"
18 #include "content/browser/browser_thread.h"
19 #include "net/base/io_buffer.h"
20 #include "net/disk_cache/disk_cache.h"
21 #include "net/http/http_cache.h"
22 #include "net/http/http_response_headers.h"
23 #include "net/http/http_response_info.h"
24
25 using safe_browsing::ClientMalwareReportRequest;
26
27 // Only send small files for now, a better strategy would use the size
28 // of the whole report and the user's bandwidth.
29 static const int kMaxBodySize = 1024;
30
31 MalwareDetailsCacheCollector::MalwareDetailsCacheCollector():
32 cache_state_(STATE_NONE),
33 ALLOW_THIS_IN_INITIALIZER_LIST(
34 cache_callback_(this , &MalwareDetailsCacheCollector::CacheLoop)),
35 ALLOW_THIS_IN_INITIALIZER_LIST(
36 entry_callback_(
37 new net::CancelableCompletionCallback<MalwareDetailsCacheCollector>(
38 this, &MalwareDetailsCacheCollector::CacheLoop))) {
39 }
40
41 MalwareDetailsCacheCollector::~MalwareDetailsCacheCollector() {
42 }
43
44 // We modify |resources|, so it must remain alive.
45 void MalwareDetailsCacheCollector::StartCacheCollection(
46 URLRequestContextGetter* request_context_getter,
47 safe_browsing::ResourceMap* resources,
48 MalwareDetailsCacheCollectorCallback* callback) {
49 // Start the data collection from the HTTP cache.
50 DVLOG(1) << "Getting disk_cache data for all urls...";
51 request_context_getter_ = request_context_getter;
52 resources_ = resources;
53 resources_it_ = resources_->begin();
54 cache_state_ = STATE_OPEN_CACHE;
55 callback_ = callback;
56
57 AddRef(); // The cache calls are asynchronous.
58
59 // Post a task in the message loop, so the callers don't need to
60 // check if we call their callback immediately.
61 BrowserThread::PostTask(
62 BrowserThread::IO, FROM_HERE,
63 NewRunnableMethod(
64 this, &MalwareDetailsCacheCollector::CacheLoop, net::OK));
65 }
66
67 bool MalwareDetailsCacheCollector::InProgress() {
68 return cache_state_ != STATE_NONE;
69 }
70
71 // The IO thread loop. Called once the DOM details are callected,
72 // and then is passed to all the cache lookups as a callback.
73 void MalwareDetailsCacheCollector::CacheLoop(int result) {
74 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
75 DCHECK(cache_state_ != STATE_NONE);
76
77 int rv = result;
78 do {
79 DVLOG(1) << "cache_state_:" << cache_state_;
80 CacheState state = cache_state_;
81 cache_state_ = STATE_NONE;
82 switch (state) {
83 case STATE_OPEN_CACHE:
84 rv = DoOpenCache();
85 break;
86 case STATE_OPEN_CACHE_COMPLETE:
87 rv = DoOpenCacheComplete(rv);
88 break;
89 case STATE_OPEN_ENTRY:
90 rv = DoOpenEntry();
91 break;
92 case STATE_OPEN_ENTRY_COMPLETE:
93 rv = DoOpenEntryComplete(rv);
94 break;
95 case STATE_READ_RESPONSE:
96 rv = DoReadResponse();
97 break;
98 case STATE_READ_RESPONSE_COMPLETE:
99 rv = DoReadResponseComplete(rv);
100 break;
101 case STATE_READ_DATA:
102 rv = DoReadData();
103 break;
104 case STATE_READ_DATA_COMPLETE:
105 rv = DoReadDataComplete(rv);
106 break;
107 default:
108 NOTREACHED() << "Bad state:" << state;
109 rv = net::ERR_FAILED;
110 break;
111 }
112 } while (rv != net::ERR_IO_PENDING && cache_state_ != STATE_NONE);
113
114 if (rv != net::ERR_IO_PENDING) {
115 DVLOG(1) << "CacheIO done.";
116 DoCacheDone(rv);
117 }
118 }
119
120 net::URLRequestContext* MalwareDetailsCacheCollector::GetURLRequestContext() {
121 if (!request_context_getter_) {
122 DVLOG(1) << "Missing request context getter";
123 return NULL;
124 }
125 return request_context_getter_->GetURLRequestContext();
126 }
127
128 int MalwareDetailsCacheCollector::DoOpenCache() {
129 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
130 cache_state_ = STATE_OPEN_CACHE_COMPLETE;
131
132 net::URLRequestContext* context = GetURLRequestContext();
133 if (!context) {
134 LOG(ERROR) << "Could not get URLRequestContext";
135 cache_state_ = STATE_NONE;
136 return net::ERR_FAILED;
137 }
138
139 if (!context->http_transaction_factory()) {
140 DVLOG(1) << "Could not get HTTP transaction factory";
141 cache_state_ = STATE_NONE;
142 return net::ERR_FAILED;
143 }
144
145 net::HttpCache* http_cache =
146 context->http_transaction_factory()->GetCache();
147 if (!http_cache) {
148 DVLOG(1) << "Could not get http cache";
149 cache_state_ = STATE_NONE;
150 return net::ERR_FAILED;
151 }
152
153 return http_cache->GetBackend(&cache_, &cache_callback_);
154 }
155
156 int MalwareDetailsCacheCollector::DoOpenCacheComplete(int result) {
157 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
158 cache_state_ = STATE_OPEN_ENTRY;
159
160 if (result == net::ERR_FAILED || !cache_) {
161 LOG(ERROR) << "Could not get disk cache";
162 cache_state_ = STATE_NONE;
163 return net::ERR_FAILED;
164 }
165
166 return net::OK;
167 }
168
169 int MalwareDetailsCacheCollector::DoOpenEntry() {
170 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
171 cache_state_ = STATE_OPEN_ENTRY_COMPLETE;
172
173 if (resources_it_ == resources_->end()) {
174 cache_state_ = STATE_NONE;
175 return net::OK;
176 }
177
178 entry_ = NULL; // Reset the entry.
179 return cache_->OpenEntry(resources_it_->first, &entry_, &cache_callback_);
180 }
181
182 int MalwareDetailsCacheCollector::DoOpenEntryComplete(int rv) {
183 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
184 cache_state_ = STATE_READ_RESPONSE;
185 return net::OK;
186 }
187
188 int MalwareDetailsCacheCollector::DoReadResponse() {
189 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
190 cache_state_ = STATE_READ_RESPONSE_COMPLETE;
191 // entry_callback_->AddRef();
192
193 if (!entry_) { // No entry in the cache for this url.
194 return net::OK;
195 }
196
197 // net::HttpCache::kResponseInfoIndex = 0.
198 buf_len_ = entry_->GetDataSize(0);
199 if (!buf_len_) {
200 DVLOG(1) << "Empty response";
201 return buf_len_;
202 }
203
204 buf_ = new net::IOBuffer(buf_len_);
205 return entry_->ReadData(0, 0, buf_, buf_len_, entry_callback_);
206 }
207
208 int MalwareDetailsCacheCollector::DoReadResponseComplete(int result) {
209 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
210 cache_state_ = STATE_READ_DATA;
211 // entry_callback_->Release();
212
213 if (!entry_ || !result || result != buf_len_) {
214 DVLOG(1) << "No entry";
215 } else {
216 linked_ptr<ClientMalwareReportRequest::Resource>
217 pb_resource = resources_it_->second;
218 net::HttpResponseInfo response;
219 bool truncated;
220 if (net::HttpCache::ParseResponseInfo(buf_->data(), buf_len_, &response,
221 &truncated)) {
222 if (!truncated) {
223 if (response.headers) {
224 ClientMalwareReportRequest::HTTPResponse* pb_response =
225 pb_resource->mutable_response();
226 pb_response->mutable_firstline()->set_code(
227 response.headers->response_code());
228 void* iter = NULL;
229 std::string name, value;
230 while (response.headers->EnumerateHeaderLines(&iter, &name, &value)) {
231 // Strip any Set-Cookie headers.
232 if (LowerCaseEqualsASCII(name, "set-cookie")) {
233 continue;
234 }
235 ClientMalwareReportRequest::HTTPHeader* pb_header =
236 pb_response->add_headers();
237 pb_header->set_name(name);
238 pb_header->set_value(value);
239 }
240 } else {
241 DVLOG(1) << "Missing response headers.";
242 }
243 } else {
244 DVLOG(1) << "Response truncated";
245 }
246 } else {
247 LOG(ERROR) << "Could not parse HTTP cache entry";
248 }
249 }
250
251 return net::OK;
252 }
253
254 int MalwareDetailsCacheCollector::DoReadData() {
255 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
256 cache_state_ = STATE_READ_DATA_COMPLETE;
257 // entry_callback_->AddRef();
258
259 if (!entry_) { // No entry in the cache for this url.
260 return net::OK;
261 }
262
263 // net::HttpCache::kResponseContentIndex = 1.
264 buf_len_ = entry_->GetDataSize(1);
265 if (!buf_len_) {
266 DVLOG(1) << "Empty data";
267 return buf_len_;
268 }
269
270 buf_ = new net::IOBuffer(buf_len_);
271 return entry_->ReadData(1, 0, buf_, buf_len_, entry_callback_);
272 }
273
274 int MalwareDetailsCacheCollector::DoReadDataComplete(int result) {
275 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
276 cache_state_ = STATE_OPEN_ENTRY;
277 // entry_callback_->Release();
278
279 if (entry_ && result && result == buf_len_) {
280 linked_ptr<ClientMalwareReportRequest::Resource>
281 pb_resource = resources_it_->second;
282 ClientMalwareReportRequest::HTTPResponse* pb_response =
283 pb_resource->mutable_response();
284 if (buf_len_ <= kMaxBodySize) { // Only send small bodies for now.
285 pb_response->set_body(buf_->data(), buf_len_);
286 }
287 pb_response->set_bodylength(buf_len_);
288 MD5Digest digest;
289 MD5Sum(buf_->data(), buf_len_, &digest);
290 pb_response->set_bodydigest(MD5DigestToBase16(digest));
291 entry_->Close();
292 }
293
294 ++resources_it_; // Advance to the next entry.
295 return net::OK;
296 }
297
298 void MalwareDetailsCacheCollector::DoCacheDone(int result) {
299 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
300 callback_->Run(result); // Runs MalwareDetails::OnCacheCollectionReady.
301
302 Release();
303 // We are now deleted.
304 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698