blob: 2abfa83c5ed874659bc13117896796c4bf07c88c [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 "chrome/browser/net/chrome_report_sender.h"
#include "base/bind.h"
#include "net/url_request/report_sender.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/simple_url_loader.h"
namespace {
// The value doesn't really matter, as we'll delete the loader once we get the
// response.
static const int kMaxSize = 1024;
using ErrorCallback =
base::OnceCallback<void(int /* net_error */, int /* http_response_code */)>;
// Owns the SimpleURLLoader and will run the appropriate callback and delete
// the loader when the response arrives.
class SimpleURLLoaderOwner {
public:
SimpleURLLoaderOwner(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
std::unique_ptr<network::SimpleURLLoader> loader,
base::OnceClosure success_callback,
ErrorCallback error_callback)
: loader_(std::move(loader)),
success_callback_(std::move(success_callback)),
error_callback_(std::move(error_callback)) {
// We don't care to read the response, and since it can come from untrusted
// endpoints it's better to not buffer. So we'll match net::ReportSender by
// closing the loader as soon as we start getting the response.
loader_->SetOnResponseStartedCallback(base::BindOnce(
&SimpleURLLoaderOwner::OnResponseStarted, base::Unretained(this)));
loader_->DownloadToString(
url_loader_factory.get(),
base::BindOnce(&SimpleURLLoaderOwner::OnURLLoaderComplete,
base::Unretained(this)),
kMaxSize);
}
private:
~SimpleURLLoaderOwner() = default;
void OnResponseStarted(const GURL& final_url,
const network::ResourceResponseHead& response_head) {
OnDone(&response_head, net::OK);
}
void OnURLLoaderComplete(std::unique_ptr<std::string> response_body) {
OnDone(loader_->ResponseInfo(), loader_->NetError());
}
void OnDone(const network::ResourceResponseHead* response_head,
int net_error) {
if (net_error == net::OK) {
if (success_callback_)
std::move(success_callback_).Run();
} else if (error_callback_) {
int response_code = 0;
if (response_head && response_head->headers)
response_code = response_head->headers->response_code();
std::move(error_callback_).Run(loader_->NetError(), response_code);
}
delete this;
}
std::unique_ptr<network::SimpleURLLoader> loader_;
base::OnceClosure success_callback_;
ErrorCallback error_callback_;
};
} // namespace
void SendReport(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
net::NetworkTrafficAnnotationTag traffic_annotation,
const GURL& report_uri,
const std::string& content_type,
const std::string& report,
base::OnceClosure success_callback,
ErrorCallback error_callback) {
auto resource_request = std::make_unique<network::ResourceRequest>();
resource_request->url = report_uri;
resource_request->method = "POST";
resource_request->load_flags = net::ReportSender::kLoadFlags;
auto loader = network::SimpleURLLoader::Create(std::move(resource_request),
traffic_annotation);
loader->AttachStringForUpload(report, content_type);
new SimpleURLLoaderOwner(url_loader_factory, std::move(loader),
std::move(success_callback),
std::move(error_callback));
}