feat: migrate protocol module to NetworkService (Part 10) (#18464)

* Explicitly call OnReceiveRedirect for redirections

* Better way for detecting redirection

* Create new loader for redirections
This commit is contained in:
Cheng Zhao 2019-05-28 15:08:50 +09:00 committed by GitHub
parent c0c5ebb271
commit 00964b98b9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 62 additions and 13 deletions

View file

@ -121,7 +121,8 @@ network::ResourceResponseHead ToResponseHead(const mate::Dictionary& dict) {
}
// Some apps are passing content-type via headers, which is not accepted
// in NetworkService.
if (iter.first == "content-type" && iter.second.is_string()) {
if (base::ToLowerASCII(iter.first) == "content-type" &&
iter.second.is_string()) {
head.mime_type = iter.second.GetString();
has_content_type = true;
}
@ -176,7 +177,7 @@ void AtomURLLoaderFactory::CreateLoaderAndStart(
request,
base::BindOnce(&AtomURLLoaderFactory::StartLoading, std::move(loader),
routing_id, request_id, options, request,
std::move(client), traffic_annotation, type_));
std::move(client), traffic_annotation, nullptr, type_));
}
void AtomURLLoaderFactory::Clone(
@ -193,6 +194,7 @@ void AtomURLLoaderFactory::StartLoading(
const network::ResourceRequest& request,
network::mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
network::mojom::URLLoaderFactory* proxy_factory,
ProtocolType type,
mate::Arguments* args) {
// Send network error when there is no argument passed.
@ -216,6 +218,43 @@ void AtomURLLoaderFactory::StartLoading(
}
}
network::ResourceResponseHead head = ToResponseHead(dict);
// Handle redirection.
//
// Note that with NetworkService, sending the "Location" header no longer
// automatically redirects the request, we have explicitly create a new loader
// to implement redirection. This is also what Chromium does with WebRequest
// API in WebRequestProxyingURLLoaderFactory.
std::string location;
if (head.headers->IsRedirect(&location)) {
network::ResourceRequest new_request = request;
new_request.url = GURL(location);
// When the redirection comes from an intercepted scheme (which has
// |proxy_factory| passed), we askes the proxy factory to create a loader
// for new URL, otherwise we call |StartLoadingHttp|, which creates
// loader with default factory.
//
// Note that when handling requests for intercepted scheme, creating loader
// with default factory (i.e. calling StartLoadingHttp) would bypass the
// ProxyingURLLoaderFactory, we have to explicitly use the proxy factory to
// create loader so it is possible to have handlers of intercepted scheme
// getting called recursively, which is a behavior expected in protocol
// module.
//
// I'm not sure whether this is an intended behavior in Chromium.
if (proxy_factory) {
proxy_factory->CreateLoaderAndStart(
std::move(loader), routing_id, request_id, options, new_request,
std::move(client), traffic_annotation);
} else {
StartLoadingHttp(std::move(loader), routing_id, request_id, options,
new_request, std::move(client), traffic_annotation,
mate::Dictionary::CreateEmpty(args->isolate()));
}
return;
}
// Some protocol accepts non-object responses.
if (dict.IsEmpty() && ResponseMustBeObject(type)) {
client->OnComplete(
@ -225,21 +264,23 @@ void AtomURLLoaderFactory::StartLoading(
switch (type) {
case ProtocolType::kBuffer:
StartLoadingBuffer(std::move(client), dict);
StartLoadingBuffer(std::move(client), std::move(head), dict);
break;
case ProtocolType::kString:
StartLoadingString(std::move(client), dict, args->isolate(), response);
StartLoadingString(std::move(client), std::move(head), dict,
args->isolate(), response);
break;
case ProtocolType::kFile:
StartLoadingFile(std::move(loader), request, std::move(client), dict,
args->isolate(), response);
StartLoadingFile(std::move(loader), request, std::move(client),
std::move(head), dict, args->isolate(), response);
break;
case ProtocolType::kHttp:
StartLoadingHttp(std::move(loader), routing_id, request_id, options,
request, std::move(client), traffic_annotation, dict);
break;
case ProtocolType::kStream:
StartLoadingStream(std::move(loader), std::move(client), dict);
StartLoadingStream(std::move(loader), std::move(client), std::move(head),
dict);
break;
case ProtocolType::kFree:
ProtocolType type;
@ -248,7 +289,8 @@ void AtomURLLoaderFactory::StartLoading(
return;
}
StartLoading(std::move(loader), routing_id, request_id, options, request,
std::move(client), traffic_annotation, type, args);
std::move(client), traffic_annotation, proxy_factory, type,
args);
break;
}
}
@ -256,6 +298,7 @@ void AtomURLLoaderFactory::StartLoading(
// static
void AtomURLLoaderFactory::StartLoadingBuffer(
network::mojom::URLLoaderClientPtr client,
network::ResourceResponseHead head,
const mate::Dictionary& dict) {
v8::Local<v8::Value> buffer = dict.GetHandle();
dict.Get("data", &buffer);
@ -265,13 +308,14 @@ void AtomURLLoaderFactory::StartLoadingBuffer(
}
SendContents(
std::move(client), ToResponseHead(dict),
std::move(client), std::move(head),
std::string(node::Buffer::Data(buffer), node::Buffer::Length(buffer)));
}
// static
void AtomURLLoaderFactory::StartLoadingString(
network::mojom::URLLoaderClientPtr client,
network::ResourceResponseHead head,
const mate::Dictionary& dict,
v8::Isolate* isolate,
v8::Local<v8::Value> response) {
@ -281,7 +325,7 @@ void AtomURLLoaderFactory::StartLoadingString(
else if (!dict.IsEmpty())
dict.Get("data", &contents);
SendContents(std::move(client), ToResponseHead(dict), std::move(contents));
SendContents(std::move(client), std::move(head), std::move(contents));
}
// static
@ -289,6 +333,7 @@ void AtomURLLoaderFactory::StartLoadingFile(
network::mojom::URLLoaderRequest loader,
network::ResourceRequest request,
network::mojom::URLLoaderClientPtr client,
network::ResourceResponseHead head,
const mate::Dictionary& dict,
v8::Isolate* isolate,
v8::Local<v8::Value> response) {
@ -305,7 +350,6 @@ void AtomURLLoaderFactory::StartLoadingFile(
return;
}
network::ResourceResponseHead head = ToResponseHead(dict);
head.headers->AddHeader(kCORSHeader);
asar::CreateAsarURLLoader(request, std::move(loader), std::move(client),
head.headers);
@ -357,8 +401,8 @@ void AtomURLLoaderFactory::StartLoadingHttp(
void AtomURLLoaderFactory::StartLoadingStream(
network::mojom::URLLoaderRequest loader,
network::mojom::URLLoaderClientPtr client,
network::ResourceResponseHead head,
const mate::Dictionary& dict) {
network::ResourceResponseHead head = ToResponseHead(dict);
v8::Local<v8::Value> stream;
if (!dict.Get("data", &stream)) {
// Assume the opts is already a stream.

View file

@ -59,19 +59,23 @@ class AtomURLLoaderFactory : public network::mojom::URLLoaderFactory {
const network::ResourceRequest& request,
network::mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
network::mojom::URLLoaderFactory* proxy_factory,
ProtocolType type,
mate::Arguments* args);
private:
static void StartLoadingBuffer(network::mojom::URLLoaderClientPtr client,
network::ResourceResponseHead head,
const mate::Dictionary& dict);
static void StartLoadingString(network::mojom::URLLoaderClientPtr client,
network::ResourceResponseHead head,
const mate::Dictionary& dict,
v8::Isolate* isolate,
v8::Local<v8::Value> response);
static void StartLoadingFile(network::mojom::URLLoaderRequest loader,
network::ResourceRequest request,
network::mojom::URLLoaderClientPtr client,
network::ResourceResponseHead head,
const mate::Dictionary& dict,
v8::Isolate* isolate,
v8::Local<v8::Value> response);
@ -86,6 +90,7 @@ class AtomURLLoaderFactory : public network::mojom::URLLoaderFactory {
const mate::Dictionary& dict);
static void StartLoadingStream(network::mojom::URLLoaderRequest loader,
network::mojom::URLLoaderClientPtr client,
network::ResourceResponseHead head,
const mate::Dictionary& dict);
// Helper to send string as response.

View file

@ -43,7 +43,7 @@ void ProxyingURLLoaderFactory::CreateLoaderAndStart(
request, base::BindOnce(&AtomURLLoaderFactory::StartLoading,
std::move(loader), routing_id, request_id,
options, request, std::move(client),
traffic_annotation, it->second.first));
traffic_annotation, this, it->second.first));
return;
}