blob: ec00a97eb2a1c7fa0f71cb724984b9e6d438223b [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/renderer/loader/tracked_child_url_loader_factory_bundle.h"
#include <utility>
#include "base/bind.h"
#include "content/public/renderer/render_thread.h"
namespace content {
TrackedChildPendingURLLoaderFactoryBundle::
TrackedChildPendingURLLoaderFactoryBundle() = default;
TrackedChildPendingURLLoaderFactoryBundle::
TrackedChildPendingURLLoaderFactoryBundle(
mojo::PendingRemote<network::mojom::URLLoaderFactory>
pending_default_factory,
mojo::PendingRemote<network::mojom::URLLoaderFactory>
pending_appcache_factory,
SchemeMap pending_scheme_specific_factories,
OriginMap pending_isolated_world_factories,
mojo::PendingRemote<network::mojom::URLLoaderFactory>
direct_network_factory_remote,
mojo::PendingRemote<network::mojom::URLLoaderFactory>
pending_prefetch_loader_factory,
std::unique_ptr<HostPtrAndTaskRunner> main_thread_host_bundle,
bool bypass_redirect_checks)
: ChildPendingURLLoaderFactoryBundle(
std::move(pending_default_factory),
std::move(pending_appcache_factory),
std::move(pending_scheme_specific_factories),
std::move(pending_isolated_world_factories),
std::move(direct_network_factory_remote),
std::move(pending_prefetch_loader_factory),
bypass_redirect_checks),
main_thread_host_bundle_(std::move(main_thread_host_bundle)) {}
TrackedChildPendingURLLoaderFactoryBundle::
~TrackedChildPendingURLLoaderFactoryBundle() = default;
scoped_refptr<network::SharedURLLoaderFactory>
TrackedChildPendingURLLoaderFactoryBundle::CreateFactory() {
auto other = std::make_unique<TrackedChildPendingURLLoaderFactoryBundle>();
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->direct_network_factory_remote_ =
std::move(direct_network_factory_remote_);
other->pending_prefetch_loader_factory_ =
std::move(pending_prefetch_loader_factory_);
other->main_thread_host_bundle_ = std::move(main_thread_host_bundle_);
other->bypass_redirect_checks_ = bypass_redirect_checks_;
return base::MakeRefCounted<TrackedChildURLLoaderFactoryBundle>(
std::move(other));
}
// -----------------------------------------------------------------------------
TrackedChildURLLoaderFactoryBundle::TrackedChildURLLoaderFactoryBundle(
std::unique_ptr<TrackedChildPendingURLLoaderFactoryBundle>
pending_factories) {
DCHECK(pending_factories->main_thread_host_bundle());
main_thread_host_bundle_ =
std::move(pending_factories->main_thread_host_bundle());
Update(std::move(pending_factories));
AddObserverOnMainThread();
}
TrackedChildURLLoaderFactoryBundle::~TrackedChildURLLoaderFactoryBundle() {
RemoveObserverOnMainThread();
}
std::unique_ptr<network::PendingSharedURLLoaderFactory>
TrackedChildURLLoaderFactoryBundle::Clone() {
auto pending_factories =
base::WrapUnique(static_cast<ChildPendingURLLoaderFactoryBundle*>(
ChildURLLoaderFactoryBundle::Clone().release()));
DCHECK(main_thread_host_bundle_);
auto main_thread_host_bundle_clone = std::make_unique<HostPtrAndTaskRunner>(
main_thread_host_bundle_->first, main_thread_host_bundle_->second);
return std::make_unique<TrackedChildPendingURLLoaderFactoryBundle>(
std::move(pending_factories->pending_default_factory()),
std::move(pending_factories->pending_appcache_factory()),
std::move(pending_factories->pending_scheme_specific_factories()),
std::move(pending_factories->pending_isolated_world_factories()),
std::move(pending_factories->direct_network_factory_remote()),
std::move(pending_factories->pending_prefetch_loader_factory()),
std::move(main_thread_host_bundle_clone),
pending_factories->bypass_redirect_checks());
}
void TrackedChildURLLoaderFactoryBundle::AddObserverOnMainThread() {
DCHECK(main_thread_host_bundle_);
// Required by |SequencedTaskRunnerHandle::Get()| below.
if (!base::SequencedTaskRunnerHandle::IsSet())
return;
main_thread_host_bundle_->second->PostTask(
FROM_HERE,
base::BindOnce(
&HostChildURLLoaderFactoryBundle::AddObserver,
main_thread_host_bundle_->first, base::Unretained(this),
std::make_unique<
HostChildURLLoaderFactoryBundle::ObserverPtrAndTaskRunner>(
AsWeakPtr(), base::SequencedTaskRunnerHandle::Get())));
}
void TrackedChildURLLoaderFactoryBundle::RemoveObserverOnMainThread() {
DCHECK(main_thread_host_bundle_);
main_thread_host_bundle_->second->PostTask(
FROM_HERE,
base::BindOnce(&HostChildURLLoaderFactoryBundle::RemoveObserver,
main_thread_host_bundle_->first, base::Unretained(this)));
}
void TrackedChildURLLoaderFactoryBundle::OnUpdate(
std::unique_ptr<network::PendingSharedURLLoaderFactory> info) {
Update(base::WrapUnique(
static_cast<ChildPendingURLLoaderFactoryBundle*>(info.release())));
}
// -----------------------------------------------------------------------------
HostChildURLLoaderFactoryBundle::HostChildURLLoaderFactoryBundle(
scoped_refptr<base::SequencedTaskRunner> task_runner)
: observer_list_(std::make_unique<ObserverList>()),
task_runner_(std::move(task_runner)) {
DCHECK(RenderThread::Get()) << "HostChildURLLoaderFactoryBundle should live "
"on the main renderer thread";
}
HostChildURLLoaderFactoryBundle::~HostChildURLLoaderFactoryBundle() = default;
std::unique_ptr<network::PendingSharedURLLoaderFactory>
HostChildURLLoaderFactoryBundle::Clone() {
auto pending_factories =
base::WrapUnique(static_cast<ChildPendingURLLoaderFactoryBundle*>(
ChildURLLoaderFactoryBundle::Clone().release()));
DCHECK(base::SequencedTaskRunnerHandle::IsSet());
auto main_thread_host_bundle_clone = std::make_unique<
TrackedChildURLLoaderFactoryBundle::HostPtrAndTaskRunner>(AsWeakPtr(),
task_runner_);
return std::make_unique<TrackedChildPendingURLLoaderFactoryBundle>(
std::move(pending_factories->pending_default_factory()),
std::move(pending_factories->pending_appcache_factory()),
std::move(pending_factories->pending_scheme_specific_factories()),
std::move(pending_factories->pending_isolated_world_factories()),
std::move(pending_factories->direct_network_factory_remote()),
std::move(pending_factories->pending_prefetch_loader_factory()),
std::move(main_thread_host_bundle_clone),
pending_factories->bypass_redirect_checks());
}
std::unique_ptr<network::PendingSharedURLLoaderFactory>
HostChildURLLoaderFactoryBundle::CloneWithoutAppCacheFactory() {
auto pending_factories =
base::WrapUnique(static_cast<ChildPendingURLLoaderFactoryBundle*>(
ChildURLLoaderFactoryBundle::CloneWithoutAppCacheFactory()
.release()));
DCHECK(base::SequencedTaskRunnerHandle::IsSet());
auto main_thread_host_bundle_clone = std::make_unique<
TrackedChildURLLoaderFactoryBundle::HostPtrAndTaskRunner>(AsWeakPtr(),
task_runner_);
return std::make_unique<TrackedChildPendingURLLoaderFactoryBundle>(
std::move(pending_factories->pending_default_factory()),
std::move(pending_factories->pending_appcache_factory()),
std::move(pending_factories->pending_scheme_specific_factories()),
std::move(pending_factories->pending_isolated_world_factories()),
std::move(pending_factories->direct_network_factory_remote()),
std::move(pending_factories->pending_prefetch_loader_factory()),
std::move(main_thread_host_bundle_clone),
pending_factories->bypass_redirect_checks());
}
void HostChildURLLoaderFactoryBundle::UpdateThisAndAllClones(
std::unique_ptr<blink::PendingURLLoaderFactoryBundle> info) {
DCHECK(RenderThread::Get()) << "Should run on the main renderer thread";
DCHECK(observer_list_);
auto partial_bundle = base::MakeRefCounted<ChildURLLoaderFactoryBundle>();
static_cast<blink::URLLoaderFactoryBundle*>(partial_bundle.get())
->Update(std::move(info));
for (const auto& iter : *observer_list_) {
NotifyUpdateOnMainOrWorkerThread(iter.second.get(),
partial_bundle->Clone());
}
Update(partial_bundle->PassInterface());
}
bool HostChildURLLoaderFactoryBundle::IsHostChildURLLoaderFactoryBundle()
const {
return true;
}
void HostChildURLLoaderFactoryBundle::AddObserver(
TrackedChildURLLoaderFactoryBundle* observer,
std::unique_ptr<ObserverPtrAndTaskRunner> observer_info) {
DCHECK(RenderThread::Get()) << "Should run in the main renderer thread";
DCHECK(observer_list_);
(*observer_list_)[observer] = std::move(observer_info);
}
void HostChildURLLoaderFactoryBundle::RemoveObserver(
TrackedChildURLLoaderFactoryBundle* observer) {
DCHECK(RenderThread::Get()) << "Should run in the main renderer thread";
DCHECK(observer_list_);
observer_list_->erase(observer);
}
void HostChildURLLoaderFactoryBundle::NotifyUpdateOnMainOrWorkerThread(
ObserverPtrAndTaskRunner* observer_bundle,
std::unique_ptr<network::PendingSharedURLLoaderFactory> update_info) {
observer_bundle->second->PostTask(
FROM_HERE,
base::BindOnce(&TrackedChildURLLoaderFactoryBundle::OnUpdate,
observer_bundle->first, std::move(update_info)));
}
} // namespace content