blob: 2e14cf7960f9cfdd78944cc202aa8fccf55232fb [file] [log] [blame]
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/sync/test/fake_server_http_post_provider.h"
#include <utility>
#include "base/functional/bind.h"
#include "base/location.h"
#include "base/task/sequenced_task_runner.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/time.h"
#include "components/sync/test/fake_server.h"
#include "net/base/net_errors.h"
namespace fake_server {
// static
std::atomic_bool FakeServerHttpPostProvider::network_enabled_(true);
FakeServerHttpPostProviderFactory::FakeServerHttpPostProviderFactory(
const base::WeakPtr<FakeServer>& fake_server,
scoped_refptr<base::SequencedTaskRunner> fake_server_task_runner)
: fake_server_(fake_server),
fake_server_task_runner_(fake_server_task_runner) {}
FakeServerHttpPostProviderFactory::~FakeServerHttpPostProviderFactory() =
default;
scoped_refptr<syncer::HttpPostProvider>
FakeServerHttpPostProviderFactory::Create() {
return new FakeServerHttpPostProvider(fake_server_, fake_server_task_runner_);
}
FakeServerHttpPostProvider::FakeServerHttpPostProvider(
const base::WeakPtr<FakeServer>& fake_server,
scoped_refptr<base::SequencedTaskRunner> fake_server_task_runner)
: fake_server_(fake_server),
fake_server_task_runner_(fake_server_task_runner) {}
FakeServerHttpPostProvider::~FakeServerHttpPostProvider() = default;
void FakeServerHttpPostProvider::SetExtraRequestHeaders(
const net::HttpRequestHeaders& headers) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
extra_request_headers_ = headers;
}
void FakeServerHttpPostProvider::SetURL(const GURL& url) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
request_url_ = url;
}
void FakeServerHttpPostProvider::SetPostPayload(const char* content_type,
int content_length,
const char* content) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
request_content_type_.assign(content_type);
request_content_.assign(content, content_length);
}
bool FakeServerHttpPostProvider::MakeSynchronousPost(int* net_error_code,
int* http_status_code) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!network_enabled_) {
response_.clear();
*net_error_code = net::ERR_INTERNET_DISCONNECTED;
*http_status_code = 0;
return false;
}
synchronous_post_completion_.Reset();
aborted_ = false;
// It is assumed that a POST is being made to /command.
int post_status_code = -1;
std::string post_response;
bool result = fake_server_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(
&FakeServerHttpPostProvider::HandleCommandOnFakeServerThread,
base::RetainedRef(this), base::Unretained(&post_status_code),
base::Unretained(&post_response)));
if (!result) {
response_.clear();
*net_error_code = net::ERR_UNEXPECTED;
*http_status_code = 0;
return false;
}
{
base::ScopedAllowBaseSyncPrimitivesForTesting allow_wait;
synchronous_post_completion_.Wait();
}
if (aborted_) {
*net_error_code = net::ERR_ABORTED;
return false;
}
// Zero means success.
*net_error_code = 0;
*http_status_code = post_status_code;
response_ = post_response;
return true;
}
int FakeServerHttpPostProvider::GetResponseContentLength() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return response_.length();
}
const char* FakeServerHttpPostProvider::GetResponseContent() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return response_.c_str();
}
const std::string FakeServerHttpPostProvider::GetResponseHeaderValue(
const std::string& name) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return std::string();
}
void FakeServerHttpPostProvider::Abort() {
// Note: This may be called on any thread, so no `sequence_checker_` here.
// The sync thread could be blocked in MakeSynchronousPost(), waiting
// for HandleCommandOnFakeServerThread() to be processed and completed.
// This causes an immediate unblocking which will be returned as
// net::ERR_ABORTED.
aborted_ = true;
synchronous_post_completion_.Signal();
}
// static
void FakeServerHttpPostProvider::DisableNetwork() {
// Note: This may be called on any thread.
network_enabled_ = false;
}
// static
void FakeServerHttpPostProvider::EnableNetwork() {
// Note: This may be called on any thread.
network_enabled_ = true;
}
void FakeServerHttpPostProvider::HandleCommandOnFakeServerThread(
int* http_status_code,
std::string* response) {
DCHECK(fake_server_task_runner_->RunsTasksInCurrentSequence());
if (!fake_server_) {
// Server destroyed.
Abort();
}
if (aborted_) {
// Command explicitly aborted. |synchronous_post_completion_| has already
// been signalled by the FakeServerHttpPostProvider::Abort call.
return;
}
*http_status_code = fake_server_->HandleCommand(request_content_, response);
synchronous_post_completion_.Signal();
}
} // namespace fake_server