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

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, 8 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/safe_browsing/malware_details_cache.h"
14 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
15 #include "chrome/browser/safe_browsing/report.pb.h"
16 #include "content/browser/browser_thread.h"
17 #include "net/base/load_flags.h"
18 #include "net/http/http_response_headers.h"
19 #include "net/url_request/url_request_context_getter.h"
20 #include "net/url_request/url_request_status.h"
21
22 using safe_browsing::ClientMalwareReportRequest;
23
24 // Only send small files for now, a better strategy would use the size
25 // of the whole report and the user's bandwidth.
26 static const uint32 kMaxBodySizeBytes = 1024;
27
28 MalwareDetailsCacheCollector::MalwareDetailsCacheCollector()
29 : has_started_(false),
30 current_fetch_(NULL) {
31 }
32
33 MalwareDetailsCacheCollector::~MalwareDetailsCacheCollector() {
34 }
35
36 void MalwareDetailsCacheCollector::StartCacheCollection(
37 net::URLRequestContextGetter* request_context_getter,
38 safe_browsing::ResourceMap* resources,
39 bool* result,
40 Task* callback) {
41 // Start the data collection from the HTTP cache. We use a URLFetcher
42 // and set the right flags so we only hit the cache.
43 DVLOG(1) << "Getting cache data for all urls...";
44 request_context_getter_ = request_context_getter;
45 resources_ = resources;
46 resources_it_ = resources_->begin();
47 result_ = result;
48 callback_ = callback;
49 has_started_ = true;
50
51 // Post a task in the message loop, so the callers don't need to
52 // check if we call their callback immediately.
53 BrowserThread::PostTask(
54 BrowserThread::IO, FROM_HERE,
55 NewRunnableMethod(this, &MalwareDetailsCacheCollector::OpenEntry));
56 }
57
58 bool MalwareDetailsCacheCollector::HasStarted() {
59 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
60 return has_started_;
61 }
62
63 // Fetch a URL and advance to the next one when done.
64 void MalwareDetailsCacheCollector::OpenEntry() {
65 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
66 DVLOG(1) << "OpenEntry";
67
68 if (resources_it_ == resources_->end()) { // We are done.
69 AllDone(true);
70 return;
71 }
72
73 if (!request_context_getter_) {
74 DVLOG(1) << "Missing request context getter";
75 AllDone(false);
76 return;
77 }
78
79 current_fetch_.reset(new URLFetcher(
80 GURL(resources_it_->first),
81 URLFetcher::GET,
82 this));
83 current_fetch_->set_request_context(request_context_getter_);
84 // Only from cache, and don't save cookies.
85 current_fetch_->set_load_flags(net::LOAD_ONLY_FROM_CACHE |
86 net::LOAD_DO_NOT_SAVE_COOKIES);
87 current_fetch_->set_automatically_retry_on_5xx(false); // No retries.
88 current_fetch_->Start(); // OnURLFetchComplete will be called when done.
89 }
90
91 ClientMalwareReportRequest::Resource* MalwareDetailsCacheCollector::GetResource(
92 const GURL& url) {
93 safe_browsing::ResourceMap::iterator it = resources_->find(url.spec());
94 if (it != resources_->end()) {
95 return it->second.get();
96 }
97 return NULL;
98 }
99
100 void MalwareDetailsCacheCollector::OnURLFetchComplete(
101 const URLFetcher* source,
102 const GURL& url,
103 const net::URLRequestStatus& status,
104 int response_code,
105 const ResponseCookies& cookies,
106 const std::string& data) {
107 DVLOG(1) << "OnUrlFetchComplete";
108 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
109 DCHECK(current_fetch_.get());
110 if (resources_it_->first != url.spec()) {
111 DVLOG(1) << "Mismatching urls (probably a redirect)" <<
112 resources_it_->first << " vs " << url;
113 }
114
115 if (status.status() != net::URLRequestStatus::SUCCESS &&
116 status.os_error() == net::ERR_CACHE_MISS) {
mattm 2011/04/18 02:19:24 do we need a test for status != SUCCESS && os_erro
panayiotis 2011/04/18 17:26:40 Done.
117 // Cache miss, skip this resource.
118 DVLOG(1) << "Cache miss for url: " << url;
119 AdvanceEntry();
120 return;
121 }
122
123 // Set the response headers and body to the right resource, which
124 // might not be the same as the one we asked for.
125 ClientMalwareReportRequest::Resource* resource = GetResource(url);
126 if (!resource) {
127 DVLOG(1) << "Cannot find resource for url:" << url;
128 AdvanceEntry();
129 return;
130 }
131
132 ReadResponse(resource, source);
133 ReadData(resource, data);
134 AdvanceEntry();
135 }
136
137 void MalwareDetailsCacheCollector::ReadResponse(
138 ClientMalwareReportRequest::Resource* pb_resource,
139 const URLFetcher* source) {
140 DVLOG(1) << "ReadResponse";
141 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
142 net::HttpResponseHeaders* headers = source->response_headers();
143 if (!headers) {
144 DVLOG(1) << "Missing response headers.";
145 return;
146 }
147
148 ClientMalwareReportRequest::HTTPResponse* pb_response =
149 pb_resource->mutable_response();
150 pb_response->mutable_firstline()->set_code(headers->response_code());
151 void* iter = NULL;
152 std::string name, value;
153 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
154 ClientMalwareReportRequest::HTTPHeader* pb_header =
155 pb_response->add_headers();
156 pb_header->set_name(name);
157 // Strip any Set-Cookie headers.
158 if (LowerCaseEqualsASCII(name, "set-cookie")) {
159 pb_header->set_value("");
160 } else {
161 pb_header->set_value(value);
162 }
163 }
164 }
165
166 void MalwareDetailsCacheCollector::ReadData(
167 ClientMalwareReportRequest::Resource* pb_resource,
168 const std::string& data) {
169 DVLOG(1) << "ReadData";
170 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
171 ClientMalwareReportRequest::HTTPResponse* pb_response =
172 pb_resource->mutable_response();
173 if (data.size() <= kMaxBodySizeBytes) { // Only send small bodies for now.
174 pb_response->set_body(data);
175 }
176 pb_response->set_bodylength(data.size());
177 MD5Digest digest;
178 MD5Sum(data.c_str(), data.size(), &digest);
179 pb_response->set_bodydigest(MD5DigestToBase16(digest));
180 }
181
182 void MalwareDetailsCacheCollector::AdvanceEntry() {
183 DVLOG(1) << "AdvanceEntry";
184 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
185 // Advance to the next resource.
186 ++resources_it_;
187 current_fetch_.reset(NULL);
188
189 // Create a task so we don't take over the IO thread for too long.
190 BrowserThread::PostTask(
191 BrowserThread::IO, FROM_HERE,
192 NewRunnableMethod(this, &MalwareDetailsCacheCollector::OpenEntry));
193 }
194
195 void MalwareDetailsCacheCollector::AllDone(bool success) {
196 DVLOG(1) << "AllDone";
197 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
198 *result_ = success;
199 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, callback_);
200 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698