blob: 5d4465108c7ee8351be35cee674854f1d35e4859 [file] [log] [blame]
// Copyright 2011 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/proxy_resolution/mock_proxy_resolver.h"
#include <memory>
#include <utility>
#include "base/check.h"
#include "base/ranges/algorithm.h"
namespace net {
MockAsyncProxyResolver::RequestImpl::RequestImpl(std::unique_ptr<Job> job)
: job_(std::move(job)) {
DCHECK(job_);
}
MockAsyncProxyResolver::RequestImpl::~RequestImpl() {
MockAsyncProxyResolver* resolver = job_->Resolver();
// AddCancelledJob will check if request is already cancelled
resolver->AddCancelledJob(std::move(job_));
}
LoadState MockAsyncProxyResolver::RequestImpl::GetLoadState() {
return LOAD_STATE_RESOLVING_PROXY_FOR_URL;
}
MockAsyncProxyResolver::Job::Job(MockAsyncProxyResolver* resolver,
const GURL& url,
ProxyInfo* results,
CompletionOnceCallback callback)
: resolver_(resolver),
url_(url),
results_(results),
callback_(std::move(callback)) {}
MockAsyncProxyResolver::Job::~Job() = default;
void MockAsyncProxyResolver::Job::CompleteNow(int rv) {
CompletionOnceCallback callback = std::move(callback_);
resolver_->RemovePendingJob(this);
std::move(callback).Run(rv);
}
MockAsyncProxyResolver::~MockAsyncProxyResolver() = default;
int MockAsyncProxyResolver::GetProxyForURL(
const GURL& url,
const NetworkAnonymizationKey& network_anonymization_key,
ProxyInfo* results,
CompletionOnceCallback callback,
std::unique_ptr<Request>* request,
const NetLogWithSource& /*net_log*/) {
auto job = std::make_unique<Job>(this, url, results, std::move(callback));
pending_jobs_.push_back(job.get());
*request = std::make_unique<RequestImpl>(std::move(job));
// Test code completes the request by calling job->CompleteNow().
return ERR_IO_PENDING;
}
void MockAsyncProxyResolver::AddCancelledJob(std::unique_ptr<Job> job) {
auto it = base::ranges::find(pending_jobs_, job.get());
// Because this is called always when RequestImpl is destructed,
// we need to check if it is still in pending jobs.
if (it != pending_jobs_.end()) {
cancelled_jobs_.push_back(std::move(job));
pending_jobs_.erase(it);
}
}
void MockAsyncProxyResolver::RemovePendingJob(Job* job) {
DCHECK(job);
auto it = base::ranges::find(pending_jobs_, job);
DCHECK(it != pending_jobs_.end());
pending_jobs_.erase(it);
}
MockAsyncProxyResolver::MockAsyncProxyResolver() = default;
MockAsyncProxyResolverFactory::Request::Request(
MockAsyncProxyResolverFactory* factory,
const scoped_refptr<PacFileData>& script_data,
std::unique_ptr<ProxyResolver>* resolver,
CompletionOnceCallback callback)
: factory_(factory),
script_data_(script_data),
resolver_(resolver),
callback_(std::move(callback)) {}
MockAsyncProxyResolverFactory::Request::~Request() = default;
void MockAsyncProxyResolverFactory::Request::CompleteNow(
int rv,
std::unique_ptr<ProxyResolver> resolver) {
*resolver_ = std::move(resolver);
// RemovePendingRequest may remove the last external reference to |this|.
scoped_refptr<MockAsyncProxyResolverFactory::Request> keep_alive(this);
factory_->RemovePendingRequest(this);
factory_ = nullptr;
std::move(callback_).Run(rv);
}
void MockAsyncProxyResolverFactory::Request::CompleteNowWithForwarder(
int rv,
ProxyResolver* resolver) {
DCHECK(resolver);
CompleteNow(rv, std::make_unique<ForwardingProxyResolver>(resolver));
}
void MockAsyncProxyResolverFactory::Request::FactoryDestroyed() {
factory_ = nullptr;
}
class MockAsyncProxyResolverFactory::Job
: public ProxyResolverFactory::Request {
public:
explicit Job(
const scoped_refptr<MockAsyncProxyResolverFactory::Request>& request)
: request_(request) {}
~Job() override {
if (request_->factory_) {
request_->factory_->cancelled_requests_.push_back(request_);
request_->factory_->RemovePendingRequest(request_.get());
}
}
private:
scoped_refptr<MockAsyncProxyResolverFactory::Request> request_;
};
MockAsyncProxyResolverFactory::MockAsyncProxyResolverFactory(
bool resolvers_expect_pac_bytes)
: ProxyResolverFactory(resolvers_expect_pac_bytes) {
}
int MockAsyncProxyResolverFactory::CreateProxyResolver(
const scoped_refptr<PacFileData>& pac_script,
std::unique_ptr<ProxyResolver>* resolver,
CompletionOnceCallback callback,
std::unique_ptr<ProxyResolverFactory::Request>* request_handle) {
auto request = base::MakeRefCounted<Request>(this, pac_script, resolver,
std::move(callback));
pending_requests_.push_back(request);
*request_handle = std::make_unique<Job>(request);
// Test code completes the request by calling request->CompleteNow().
return ERR_IO_PENDING;
}
void MockAsyncProxyResolverFactory::RemovePendingRequest(Request* request) {
auto it = base::ranges::find(pending_requests_, request);
DCHECK(it != pending_requests_.end());
pending_requests_.erase(it);
}
MockAsyncProxyResolverFactory::~MockAsyncProxyResolverFactory() {
for (auto& request : pending_requests_) {
request->FactoryDestroyed();
}
}
ForwardingProxyResolver::ForwardingProxyResolver(ProxyResolver* impl)
: impl_(impl) {
}
int ForwardingProxyResolver::GetProxyForURL(
const GURL& query_url,
const NetworkAnonymizationKey& network_anonymization_key,
ProxyInfo* results,
CompletionOnceCallback callback,
std::unique_ptr<Request>* request,
const NetLogWithSource& net_log) {
return impl_->GetProxyForURL(query_url, network_anonymization_key, results,
std::move(callback), request, net_log);
}
} // namespace net