blob: ef75d3cb4899115d7ad530fcae762c83f7a6bc35 [file] [log] [blame]
// Copyright 2017 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 "third_party/blink/public/common/loader/url_loader_factory_bundle.h"
#include <utility>
#include "base/notreached.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "url/gurl.h"
namespace blink {
namespace {
template <typename TKey>
void BindPendingRemoteMapToRemoteMap(
std::map<TKey, mojo::Remote<network::mojom::URLLoaderFactory>>* target,
std::map<TKey, mojo::PendingRemote<network::mojom::URLLoaderFactory>>
input) {
for (auto& it : input) {
const TKey& key = it.first;
mojo::PendingRemote<network::mojom::URLLoaderFactory>& pending_factory =
it.second;
if ((*target)[key].is_bound())
(*target)[key].reset();
if (pending_factory) // pending_factory.is_valid().
(*target)[key].Bind(std::move(pending_factory));
}
}
} // namespace
PendingURLLoaderFactoryBundle::PendingURLLoaderFactoryBundle() = default;
PendingURLLoaderFactoryBundle::PendingURLLoaderFactoryBundle(
mojo::PendingRemote<network::mojom::URLLoaderFactory>
pending_default_factory,
SchemeMap pending_scheme_specific_factories,
OriginMap pending_isolated_world_factories,
bool bypass_redirect_checks)
: pending_default_factory_(std::move(pending_default_factory)),
pending_scheme_specific_factories_(
std::move(pending_scheme_specific_factories)),
pending_isolated_world_factories_(
std::move(pending_isolated_world_factories)),
bypass_redirect_checks_(bypass_redirect_checks) {}
PendingURLLoaderFactoryBundle::~PendingURLLoaderFactoryBundle() = default;
scoped_refptr<network::SharedURLLoaderFactory>
PendingURLLoaderFactoryBundle::CreateFactory() {
auto other = std::make_unique<PendingURLLoaderFactoryBundle>();
other->pending_default_factory_ = std::move(pending_default_factory_);
other->pending_appcache_factory_ = std::move(pending_appcache_factory_);
other->pending_scheme_specific_factories_ =
std::move(pending_scheme_specific_factories_);
other->pending_isolated_world_factories_ =
std::move(pending_isolated_world_factories_);
other->bypass_redirect_checks_ = bypass_redirect_checks_;
return base::MakeRefCounted<URLLoaderFactoryBundle>(std::move(other));
}
// -----------------------------------------------------------------------------
URLLoaderFactoryBundle::URLLoaderFactoryBundle() = default;
URLLoaderFactoryBundle::URLLoaderFactoryBundle(
std::unique_ptr<PendingURLLoaderFactoryBundle> pending_factory) {
Update(std::move(pending_factory));
}
URLLoaderFactoryBundle::~URLLoaderFactoryBundle() = default;
network::mojom::URLLoaderFactory* URLLoaderFactoryBundle::GetFactory(
const network::ResourceRequest& request) {
auto it = scheme_specific_factories_.find(request.url.scheme());
if (it != scheme_specific_factories_.end())
return it->second.get();
if (request.isolated_world_origin.has_value()) {
auto it2 =
isolated_world_factories_.find(request.isolated_world_origin.value());
if (it2 != isolated_world_factories_.end())
return it2->second.get();
}
// AppCache factory must be used if it's given.
if (appcache_factory_)
return appcache_factory_.get();
return default_factory_.is_bound() ? default_factory_.get() : nullptr;
}
void URLLoaderFactoryBundle::CreateLoaderAndStart(
mojo::PendingReceiver<network::mojom::URLLoader> loader,
int32_t routing_id,
int32_t request_id,
uint32_t options,
const network::ResourceRequest& request,
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
network::mojom::URLLoaderFactory* factory_ptr = GetFactory(request);
factory_ptr->CreateLoaderAndStart(std::move(loader), routing_id, request_id,
options, request, std::move(client),
traffic_annotation);
}
void URLLoaderFactoryBundle::Clone(
mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver) {
NOTREACHED();
}
std::unique_ptr<network::PendingSharedURLLoaderFactory>
URLLoaderFactoryBundle::Clone() {
mojo::PendingRemote<network::mojom::URLLoaderFactory> pending_default_factory;
if (default_factory_) {
default_factory_->Clone(
pending_default_factory.InitWithNewPipeAndPassReceiver());
}
auto pending_factories =
std::make_unique<blink::PendingURLLoaderFactoryBundle>(
std::move(pending_default_factory),
CloneRemoteMapToPendingRemoteMap(scheme_specific_factories_),
CloneRemoteMapToPendingRemoteMap(isolated_world_factories_),
bypass_redirect_checks_);
if (appcache_factory_) {
appcache_factory_->Clone(pending_factories->pending_appcache_factory()
.InitWithNewPipeAndPassReceiver());
}
return pending_factories;
}
bool URLLoaderFactoryBundle::BypassRedirectChecks() const {
return bypass_redirect_checks_;
}
void URLLoaderFactoryBundle::Update(
std::unique_ptr<PendingURLLoaderFactoryBundle> pending_factories) {
if (pending_factories->pending_default_factory()) {
default_factory_.reset();
default_factory_.Bind(
std::move(pending_factories->pending_default_factory()));
}
if (pending_factories->pending_appcache_factory()) {
appcache_factory_.reset();
appcache_factory_.Bind(
std::move(pending_factories->pending_appcache_factory()));
}
BindPendingRemoteMapToRemoteMap(
&scheme_specific_factories_,
std::move(pending_factories->pending_scheme_specific_factories()));
BindPendingRemoteMapToRemoteMap(
&isolated_world_factories_,
std::move(pending_factories->pending_isolated_world_factories()));
bypass_redirect_checks_ = pending_factories->bypass_redirect_checks();
}
} // namespace blink