This source file includes following definitions.
- ForwardJobFinished
- ForwardJobCanceled
- DoNothing
- callback
- weak_factory_
- StartJob
- CancelJob
- OnJobFinished
- weak_factory_
- CreateFrontend
- StartJob
- CancelJob
- OnURLFetchComplete
- OnURLFetchDownloadProgress
#include "components/policy/core/common/cloud/external_policy_data_fetcher.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/sequenced_task_runner.h"
#include "base/stl_util.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.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"
namespace policy {
namespace {
void ForwardJobFinished(
scoped_refptr<base::SequencedTaskRunner> task_runner,
const ExternalPolicyDataFetcherBackend::FetchCallback& callback,
ExternalPolicyDataFetcher::Job* job,
ExternalPolicyDataFetcher::Result result,
scoped_ptr<std::string> data) {
task_runner->PostTask(FROM_HERE,
base::Bind(callback, job, result, base::Passed(&data)));
}
void ForwardJobCanceled(
scoped_refptr<base::SequencedTaskRunner> task_runner,
const base::Closure& callback) {
task_runner->PostTask(FROM_HERE, callback);
}
void DoNothing(ExternalPolicyDataFetcher::Job* job) {
}
}
struct ExternalPolicyDataFetcher::Job {
Job(const GURL& url,
int64 max_size,
const ExternalPolicyDataFetcherBackend::FetchCallback& callback);
const GURL url;
const int64 max_size;
const ExternalPolicyDataFetcherBackend::FetchCallback callback;
private:
DISALLOW_COPY_AND_ASSIGN(Job);
};
ExternalPolicyDataFetcher::Job::Job(
const GURL& url,
int64 max_size,
const ExternalPolicyDataFetcherBackend::FetchCallback& callback)
: url(url),
max_size(max_size),
callback(callback) {
}
ExternalPolicyDataFetcher::ExternalPolicyDataFetcher(
scoped_refptr<base::SequencedTaskRunner> task_runner,
scoped_refptr<base::SequencedTaskRunner> io_task_runner,
const base::WeakPtr<ExternalPolicyDataFetcherBackend>& backend)
: task_runner_(task_runner),
io_task_runner_(io_task_runner),
backend_(backend),
weak_factory_(this) {
}
ExternalPolicyDataFetcher::~ExternalPolicyDataFetcher() {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
for (JobSet::iterator it = jobs_.begin(); it != jobs_.end(); ++it)
CancelJob(*it);
}
ExternalPolicyDataFetcher::Job* ExternalPolicyDataFetcher::StartJob(
const GURL& url,
int64 max_size,
const FetchCallback& callback) {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
Job* job = new Job(
url, max_size,
base::Bind(&ForwardJobFinished,
task_runner_,
base::Bind(&ExternalPolicyDataFetcher::OnJobFinished,
weak_factory_.GetWeakPtr(),
callback)));
jobs_.insert(job);
io_task_runner_->PostTask(
FROM_HERE,
base::Bind(&ExternalPolicyDataFetcherBackend::StartJob, backend_, job));
return job;
}
void ExternalPolicyDataFetcher::CancelJob(Job* job) {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
DCHECK(jobs_.find(job) != jobs_.end());
jobs_.erase(job);
io_task_runner_->PostTask(
FROM_HERE,
base::Bind(&ExternalPolicyDataFetcherBackend::CancelJob,
backend_,
job,
base::Bind(&ForwardJobCanceled,
task_runner_,
base::Bind(&DoNothing, base::Owned(job)))));
}
void ExternalPolicyDataFetcher::OnJobFinished(const FetchCallback& callback,
Job* job,
Result result,
scoped_ptr<std::string> data) {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
JobSet::iterator it = jobs_.find(job);
if (it == jobs_.end()) {
return;
}
callback.Run(result, data.Pass());
jobs_.erase(it);
delete job;
}
ExternalPolicyDataFetcherBackend::ExternalPolicyDataFetcherBackend(
scoped_refptr<base::SequencedTaskRunner> io_task_runner,
scoped_refptr<net::URLRequestContextGetter> request_context)
: io_task_runner_(io_task_runner),
request_context_(request_context),
last_fetch_id_(-1),
weak_factory_(this) {
}
ExternalPolicyDataFetcherBackend::~ExternalPolicyDataFetcherBackend() {
DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
STLDeleteContainerPairFirstPointers(job_map_.begin(), job_map_.end());
}
scoped_ptr<ExternalPolicyDataFetcher>
ExternalPolicyDataFetcherBackend::CreateFrontend(
scoped_refptr<base::SequencedTaskRunner> task_runner) {
return make_scoped_ptr(new ExternalPolicyDataFetcher(
task_runner, io_task_runner_, weak_factory_.GetWeakPtr()));
}
void ExternalPolicyDataFetcherBackend::StartJob(
ExternalPolicyDataFetcher::Job* job) {
DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
net::URLFetcher* fetcher = net::URLFetcher::Create(
++last_fetch_id_, job->url, net::URLFetcher::GET, this);
fetcher->SetRequestContext(request_context_.get());
fetcher->SetLoadFlags(net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE |
net::LOAD_DO_NOT_SAVE_COOKIES | net::LOAD_IS_DOWNLOAD |
net::LOAD_DO_NOT_SEND_COOKIES |
net::LOAD_DO_NOT_SEND_AUTH_DATA);
fetcher->SetAutomaticallyRetryOnNetworkChanges(3);
fetcher->Start();
job_map_[fetcher] = job;
}
void ExternalPolicyDataFetcherBackend::CancelJob(
ExternalPolicyDataFetcher::Job* job,
const base::Closure& callback) {
DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
for (JobMap::iterator it = job_map_.begin(); it != job_map_.end(); ) {
if (it->second == job) {
delete it->first;
job_map_.erase(it++);
} else {
++it;
}
}
callback.Run();
}
void ExternalPolicyDataFetcherBackend::OnURLFetchComplete(
const net::URLFetcher* source) {
DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
JobMap::iterator it = job_map_.find(const_cast<net::URLFetcher*>(source));
if (it == job_map_.end()) {
NOTREACHED();
return;
}
ExternalPolicyDataFetcher::Result result = ExternalPolicyDataFetcher::SUCCESS;
scoped_ptr<std::string> data;
const net::URLRequestStatus status = it->first->GetStatus();
if (status.error() == net::ERR_CONNECTION_RESET ||
status.error() == net::ERR_TEMPORARILY_THROTTLED) {
result = ExternalPolicyDataFetcher::CONNECTION_INTERRUPTED;
} else if (status.status() != net::URLRequestStatus::SUCCESS) {
result = ExternalPolicyDataFetcher::NETWORK_ERROR;
} else if (source->GetResponseCode() >= 500) {
result = ExternalPolicyDataFetcher::SERVER_ERROR;
} else if (source->GetResponseCode() >= 400) {
result = ExternalPolicyDataFetcher::CLIENT_ERROR;
} else if (source->GetResponseCode() != 200) {
result = ExternalPolicyDataFetcher::HTTP_ERROR;
} else {
data.reset(new std::string);
source->GetResponseAsString(data.get());
if (static_cast<int64>(data->size()) > it->second->max_size) {
data.reset();
result = ExternalPolicyDataFetcher::MAX_SIZE_EXCEEDED;
}
}
ExternalPolicyDataFetcher::Job* job = it->second;
delete it->first;
job_map_.erase(it);
job->callback.Run(job, result, data.Pass());
}
void ExternalPolicyDataFetcherBackend::OnURLFetchDownloadProgress(
const net::URLFetcher* source,
int64 current,
int64 total) {
DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
JobMap::iterator it = job_map_.find(const_cast<net::URLFetcher*>(source));
DCHECK(it != job_map_.end());
if (it == job_map_.end())
return;
if (current > it->second->max_size || total > it->second->max_size) {
ExternalPolicyDataFetcher::Job* job = it->second;
delete it->first;
job_map_.erase(it);
job->callback.Run(job,
ExternalPolicyDataFetcher::MAX_SIZE_EXCEEDED,
scoped_ptr<std::string>());
}
}
}