blob: d01f8f282535a7f8e8efb964d666be8a5f04c6fe [file] [log] [blame]
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/public/test/slow_http_response.h"
#include <utility>
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/strings/string_split.h"
#include "base/task/bind_post_task.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/bind.h"
#include "net/base/test_completion_callback.h"
#include "net/http/http_status_code.h"
#include "net/test/embedded_test_server/http_response.h"
namespace content {
const char SlowHttpResponse::kSlowResponseUrl[] = "/slow-response";
const char SlowHttpResponse::kFinishSlowResponseUrl[] = "/slow-response-finish";
const int SlowHttpResponse::kFirstResponsePartSize = 1024 * 35;
const int SlowHttpResponse::kSecondResponsePartSize = 1024 * 10;
// static
SlowHttpResponse::GotRequestCallback
SlowHttpResponse::FinishResponseImmediately() {
return base::BindOnce(
[](base::OnceClosure start_response, base::OnceClosure finish_response) {
std::move(start_response).Run();
std::move(finish_response).Run();
});
}
// static
SlowHttpResponse::GotRequestCallback SlowHttpResponse::NoResponse() {
return base::DoNothing();
}
SlowHttpResponse::SlowHttpResponse(GotRequestCallback got_request)
: main_thread_(base::SingleThreadTaskRunner::GetCurrentDefault()),
got_request_(std::move(got_request)) {}
SlowHttpResponse::~SlowHttpResponse() = default;
base::StringPairs SlowHttpResponse::ResponseHeaders() {
return {{"Content-type", "text/html"}};
}
std::pair<net::HttpStatusCode, std::string> SlowHttpResponse::StatusLine() {
return {net::HTTP_OK, "OK"};
}
void SlowHttpResponse::SendResponse(
base::WeakPtr<HttpResponseDelegate> delegate) {
// Construct the headers here so subclasses can override them. Then we will
// bind them into the async task which sends them in the response.
auto [status, status_reason] = StatusLine();
base::StringPairs headers = ResponseHeaders();
headers.emplace_back("Cache-Control", "no-store");
// SendResponse() runs off the test's main thread so we must have these tasks
// post back from the test's main thread to this thread.
auto task_runner = base::SingleThreadTaskRunner::GetCurrentDefault();
auto send_headers = base::BindPostTask(
task_runner, base::BindOnce(&HttpResponseDelegate::SendResponseHeaders,
delegate, status, status_reason, headers));
auto send_first_part = base::BindPostTask(
task_runner, base::BindOnce(&HttpResponseDelegate::SendContents, delegate,
std::string(kFirstResponsePartSize, '*'),
base::DoNothing()));
auto send_second_part = base::BindPostTask(
task_runner,
base::BindOnce(&HttpResponseDelegate::SendContentsAndFinish, delegate,
std::string(kSecondResponsePartSize, '*')));
// We run both `send_headers` and `send_first_part` when the test asks
// us to start the response, but as separate tasks.
base::OnceClosure start_response =
std::move(send_headers).Then(std::move(send_first_part));
base::OnceClosure finish_response = std::move(send_second_part);
// SendResponse() runs off the test's main thread so we must post task the
// test's `got_request_` callback to the main thread.
main_thread_->PostTask(FROM_HERE, base::BindOnce(std::move(got_request_),
std::move(start_response),
std::move(finish_response)));
}
} // namespace content