blob: d4cee381ebd2e02692194ae60eb334cc82dc9f14 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/loader/signed_exchange_handler.h"
#include "base/feature_list.h"
#include "content/public/common/content_features.h"
#include "mojo/public/cpp/system/string_data_pipe_producer.h"
#include "net/http/http_response_headers.h"
#include "services/network/public/cpp/resource_response.h"
#include "services/network/public/cpp/url_loader_completion_status.h"
namespace content {
namespace {
constexpr size_t kPipeSizeForSignedResponseBody = 65536;
} // namespace
SignedExchangeHandler::SignedExchangeHandler(
mojo::ScopedDataPipeConsumerHandle body)
: body_(std::move(body)) {
DCHECK(base::FeatureList::IsEnabled(features::kSignedHTTPExchange));
}
SignedExchangeHandler::~SignedExchangeHandler() = default;
void SignedExchangeHandler::GetHTTPExchange(
ExchangeFoundCallback found_callback,
ExchangeFinishedCallback finish_callback) {
DCHECK(!found_callback_);
DCHECK(!finish_callback_);
found_callback_ = std::move(found_callback);
finish_callback_ = std::move(finish_callback);
drainer_.reset(new mojo::common::DataPipeDrainer(this, std::move(body_)));
}
void SignedExchangeHandler::OnDataAvailable(const void* data,
size_t num_bytes) {
original_body_string_.append(static_cast<const char*>(data), num_bytes);
}
void SignedExchangeHandler::OnDataComplete() {
if (!found_callback_)
return;
// TODO(https://crbug.com/80374): Get the request url by parsing CBOR format.
GURL request_url = GURL("https://example.com/test.html");
// TODO(https://crbug.com/80374): Get the request method by parsing CBOR
// format.
std::string request_method = "GET";
// TODO(https://crbug.com/80374): Get the payload by parsing CBOR format.
std::string payload = original_body_string_;
original_body_string_.clear();
// TODO(https://crbug.com/80374): Get more headers by parsing CBOR.
scoped_refptr<net::HttpResponseHeaders> headers(
new net::HttpResponseHeaders("HTTP/1.1 200 OK"));
network::ResourceResponseHead resource_response;
resource_response.headers = headers;
resource_response.mime_type = "text/html";
// TODO(https://crbug.com/80374): Get the certificate by parsing CBOR and
// verify.
base::Optional<net::SSLInfo> ssl_info;
mojo::DataPipe pipe(kPipeSizeForSignedResponseBody);
// TODO(https://crbug.com/80374): Write the error handling code. This could
// fail.
DCHECK(pipe.consumer_handle.is_valid());
mojo::ScopedDataPipeConsumerHandle response_body =
std::move(pipe.consumer_handle);
std::move(found_callback_)
.Run(request_url, request_method, resource_response, std::move(ssl_info),
std::move(response_body));
data_producer_ = std::make_unique<mojo::StringDataPipeProducer>(
std::move(pipe.producer_handle));
data_producer_->Write(payload,
base::BindOnce(&SignedExchangeHandler::OnDataWritten,
base::Unretained(this)));
}
void SignedExchangeHandler::OnDataWritten(MojoResult result) {
data_producer_.reset();
std::move(finish_callback_)
.Run(network::URLLoaderCompletionStatus(
result == MOJO_RESULT_OK ? net::OK : net::ERR_FAILED));
}
} // namespace content