in libcef/browser/net_service/browser_urlrequest_impl.cc [245:403]
void ContinueOnOriginatingThread(
int32_t request_id,
scoped_refptr<net_service::URLLoaderFactoryGetter> loader_factory_getter,
mojo::PendingRemote<network::mojom::URLLoaderNetworkServiceObserver>
url_loader_network_observer) {
DCHECK(CalledOnValidThread());
// The request may have been canceled.
if (!url_request_)
return;
if (!loader_factory_getter) {
// Cancel the request immediately.
Cancel();
return;
}
DCHECK_EQ(status_, UR_IO_PENDING);
loader_factory_getter_ = loader_factory_getter;
const int request_flags = request_->GetFlags();
// Create the URLLoaderFactory and bind to this thread.
auto loader_factory = loader_factory_getter_->GetURLLoaderFactory();
auto resource_request = std::make_unique<network::ResourceRequest>();
static_cast<CefRequestImpl*>(request_.get())
->Get(resource_request.get(), false);
// Behave the same as a subresource load.
resource_request->resource_type =
static_cast<int>(blink::mojom::ResourceType::kSubResource);
// Set the origin to match the request.
const GURL& url = GURL(request_->GetURL().ToString());
resource_request->request_initiator = url::Origin::Create(url);
if (request_flags & UR_FLAG_ALLOW_STORED_CREDENTIALS) {
// Include SameSite cookies.
resource_request->site_for_cookies =
net::SiteForCookies::FromOrigin(*resource_request->request_initiator);
}
if (url_loader_network_observer) {
resource_request->trusted_params =
network::ResourceRequest::TrustedParams();
resource_request->trusted_params->url_loader_network_observer =
std::move(url_loader_network_observer);
}
// SimpleURLLoader is picky about the body contents. Try to populate them
// correctly below.
auto request_body = resource_request->request_body;
resource_request->request_body = nullptr;
std::string content_type;
std::string method = resource_request->method;
if (request_body) {
if (method == "GET" || method == "HEAD") {
// Fix the method value to allow a request body.
method = "POST";
resource_request->method = method;
request_->SetReadOnly(false);
request_->SetMethod(method);
request_->SetReadOnly(true);
}
resource_request->headers.GetHeader(net::HttpRequestHeaders::kContentType,
&content_type);
}
loader_ = network::SimpleURLLoader::Create(std::move(resource_request),
MISSING_TRAFFIC_ANNOTATION);
// Associate the request with |request_id|.
request_id_ = request_id;
loader_->SetRequestID(request_id);
g_manager.Get().Add(request_id, url_request_, client_);
if (request_body) {
if (request_body->elements()->size() == 1) {
const auto& element = (*request_body->elements())[0];
if (element.type() == network::DataElement::Tag::kFile) {
const auto& file_element = element.As<network::DataElementFile>();
if (content_type.empty()) {
const auto& extension = file_element.path().Extension();
if (!extension.empty()) {
// Requests should not block on the disk! On POSIX this goes to
// disk. http://code.google.com/p/chromium/issues/detail?id=59849
base::ThreadRestrictions::ScopedAllowIO allow_io;
// Also remove the leading period.
net::GetMimeTypeFromExtension(extension.substr(1), &content_type);
}
}
loader_->AttachFileForUpload(file_element.path(), content_type);
} else if (element.type() == network::DataElement::Tag::kBytes) {
const auto& bytes_element = element.As<network::DataElementBytes>();
const auto& bytes = bytes_element.bytes();
if (content_type.empty()) {
content_type = net_service::kContentTypeApplicationFormURLEncoded;
}
loader_->AttachStringForUpload(
std::string(bytes_element.AsStringPiece()), content_type);
if (request_flags & UR_FLAG_REPORT_UPLOAD_PROGRESS) {
// Report the expected upload data size.
upload_data_size_ = bytes.size();
}
} else {
NOTIMPLEMENTED() << "Unsupported element type: "
<< static_cast<int>(element.type());
}
} else if (request_body->elements()->size() > 1) {
NOTIMPLEMENTED() << "Multi-part form data is not supported";
}
}
// Allow delivery of non-2xx response bodies.
loader_->SetAllowHttpErrorResults(true);
if (!(request_flags & UR_FLAG_NO_RETRY_ON_5XX)) {
// Allow 2 retries on 5xx response or network change.
// TODO(network): Consider exposing configuration of max retries and/or
// RETRY_ON_NETWORK_CHANGE as a separate flag.
loader_->SetRetryOptions(
2, network::SimpleURLLoader::RETRY_ON_5XX |
network::SimpleURLLoader::RETRY_ON_NETWORK_CHANGE);
}
if (request_flags & UR_FLAG_STOP_ON_REDIRECT) {
// The request will be canceled in OnRedirect.
loader_->SetOnRedirectCallback(
base::BindRepeating(&CefBrowserURLRequest::Context::OnRedirect,
weak_ptr_factory_.GetWeakPtr()));
}
if (request_flags & UR_FLAG_REPORT_UPLOAD_PROGRESS) {
loader_->SetOnUploadProgressCallback(
base::BindRepeating(&CefBrowserURLRequest::Context::OnUploadProgress,
weak_ptr_factory_.GetWeakPtr()));
}
if ((request_flags & UR_FLAG_NO_DOWNLOAD_DATA) || method == "HEAD") {
loader_->DownloadHeadersOnly(
loader_factory.get(),
base::BindOnce(&CefBrowserURLRequest::Context::OnHeadersOnly,
weak_ptr_factory_.GetWeakPtr()));
} else {
loader_->SetOnResponseStartedCallback(
base::BindOnce(&CefBrowserURLRequest::Context::OnResponseStarted,
weak_ptr_factory_.GetWeakPtr()));
loader_->SetOnDownloadProgressCallback(base::BindRepeating(
&CefBrowserURLRequest::Context::OnDownloadProgress,
weak_ptr_factory_.GetWeakPtr()));
loader_->DownloadAsStream(loader_factory.get(), this);
}
}