This source file includes following definitions.
- has_started_
- StartCacheCollection
- HasStarted
- OpenEntry
- GetResource
- OnURLFetchComplete
- ReadResponse
- ReadData
- AdvanceEntry
- AllDone
#include "chrome/browser/safe_browsing/malware_details.h"
#include "base/bind.h"
#include "base/lazy_instance.h"
#include "base/md5.h"
#include "base/strings/string_util.h"
#include "chrome/browser/net/chrome_url_request_context.h"
#include "chrome/browser/safe_browsing/malware_details_cache.h"
#include "chrome/browser/safe_browsing/report.pb.h"
#include "chrome/browser/safe_browsing/safe_browsing_service.h"
#include "content/public/browser/browser_thread.h"
#include "net/base/host_port_pair.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/url_fetcher.h"
#include "net/url_request/url_request_context_getter.h"
#include "net/url_request/url_request_status.h"
using content::BrowserThread;
using safe_browsing::ClientMalwareReportRequest;
static const uint32 kMaxBodySizeBytes = 1024;
MalwareDetailsCacheCollector::MalwareDetailsCacheCollector()
: resources_(NULL), result_(NULL), has_started_(false) {}
void MalwareDetailsCacheCollector::StartCacheCollection(
net::URLRequestContextGetter* request_context_getter,
safe_browsing::ResourceMap* resources,
bool* result,
const base::Closure& callback) {
DVLOG(1) << "Getting cache data for all urls...";
request_context_getter_ = request_context_getter;
resources_ = resources;
resources_it_ = resources_->begin();
result_ = result;
callback_ = callback;
has_started_ = true;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&MalwareDetailsCacheCollector::OpenEntry, this));
}
bool MalwareDetailsCacheCollector::HasStarted() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
return has_started_;
}
MalwareDetailsCacheCollector::~MalwareDetailsCacheCollector() {}
void MalwareDetailsCacheCollector::OpenEntry() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DVLOG(1) << "OpenEntry";
if (resources_it_ == resources_->end()) {
AllDone(true);
return;
}
if (!request_context_getter_.get()) {
DVLOG(1) << "Missing request context getter";
AllDone(false);
return;
}
current_fetch_.reset(net::URLFetcher::Create(
GURL(resources_it_->first), net::URLFetcher::GET, this));
current_fetch_->SetRequestContext(request_context_getter_.get());
current_fetch_->SetLoadFlags(net::LOAD_ONLY_FROM_CACHE |
net::LOAD_DO_NOT_SAVE_COOKIES);
current_fetch_->SetAutomaticallyRetryOn5xx(false);
current_fetch_->Start();
}
ClientMalwareReportRequest::Resource* MalwareDetailsCacheCollector::GetResource(
const GURL& url) {
safe_browsing::ResourceMap::iterator it = resources_->find(url.spec());
if (it != resources_->end()) {
return it->second.get();
}
return NULL;
}
void MalwareDetailsCacheCollector::OnURLFetchComplete(
const net::URLFetcher* source) {
DVLOG(1) << "OnUrlFetchComplete";
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(current_fetch_.get());
if (source->GetStatus().status() != net::URLRequestStatus::SUCCESS &&
source->GetStatus().error() == net::ERR_CACHE_MISS) {
DVLOG(1) << "Cache miss for url: " << source->GetURL();
AdvanceEntry();
return;
}
if (source->GetStatus().status() != net::URLRequestStatus::SUCCESS) {
DVLOG(1) << "Unsuccessful fetch: " << source->GetURL();
AdvanceEntry();
return;
}
ClientMalwareReportRequest::Resource* resource =
GetResource(source->GetURL());
if (!resource) {
DVLOG(1) << "Cannot find resource for url:" << source->GetURL();
AdvanceEntry();
return;
}
ReadResponse(resource, source);
std::string data;
source->GetResponseAsString(&data);
ReadData(resource, data);
AdvanceEntry();
}
void MalwareDetailsCacheCollector::ReadResponse(
ClientMalwareReportRequest::Resource* pb_resource,
const net::URLFetcher* source) {
DVLOG(1) << "ReadResponse";
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
net::HttpResponseHeaders* headers = source->GetResponseHeaders();
if (!headers) {
DVLOG(1) << "Missing response headers.";
return;
}
ClientMalwareReportRequest::HTTPResponse* pb_response =
pb_resource->mutable_response();
pb_response->mutable_firstline()->set_code(headers->response_code());
void* iter = NULL;
std::string name, value;
while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
ClientMalwareReportRequest::HTTPHeader* pb_header =
pb_response->add_headers();
pb_header->set_name(name);
if (LowerCaseEqualsASCII(name, "set-cookie")) {
pb_header->set_value("");
} else {
pb_header->set_value(value);
}
}
if (!source->WasFetchedViaProxy()) {
pb_response->set_remote_ip(source->GetSocketAddress().ToString());
}
}
void MalwareDetailsCacheCollector::ReadData(
ClientMalwareReportRequest::Resource* pb_resource,
const std::string& data) {
DVLOG(1) << "ReadData";
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
ClientMalwareReportRequest::HTTPResponse* pb_response =
pb_resource->mutable_response();
if (data.size() <= kMaxBodySizeBytes) {
pb_response->set_body(data);
}
pb_response->set_bodylength(data.size());
base::MD5Digest digest;
base::MD5Sum(data.c_str(), data.size(), &digest);
pb_response->set_bodydigest(base::MD5DigestToBase16(digest));
}
void MalwareDetailsCacheCollector::AdvanceEntry() {
DVLOG(1) << "AdvanceEntry";
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
++resources_it_;
current_fetch_.reset(NULL);
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&MalwareDetailsCacheCollector::OpenEntry, this));
}
void MalwareDetailsCacheCollector::AllDone(bool success) {
DVLOG(1) << "AllDone";
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
*result_ = success;
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, callback_);
callback_.Reset();
}