| // Copyright (c) 2019 The Chromium Embedded Framework Authors. Portions |
| // Copyright (c) 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 "libcef/browser/net_service/url_loader_factory_getter.h" |
| |
| #include "libcef/browser/content_browser_client.h" |
| #include "libcef/browser/thread_util.h" |
| |
| #include "base/threading/thread_task_runner_handle.h" |
| #include "content/browser/devtools/devtools_instrumentation.h" |
| #include "content/browser/frame_host/render_frame_host_impl.h" |
| #include "content/public/browser/storage_partition.h" |
| #include "content/public/common/content_client.h" |
| #include "services/network/public/cpp/shared_url_loader_factory.h" |
| #include "services/network/public/cpp/wrapper_shared_url_loader_factory.h" |
| |
| namespace net_service { |
| |
| // Based on CreateDownloadURLLoaderFactoryGetter from |
| // content/browser/download/download_manager_impl.cc. |
| // static |
| scoped_refptr<URLLoaderFactoryGetter> URLLoaderFactoryGetter::Create( |
| content::RenderFrameHost* render_frame_host, |
| content::BrowserContext* browser_context) { |
| CEF_REQUIRE_UIT(); |
| DCHECK(browser_context); |
| |
| // Call this early because newly created BrowserContexts may need to |
| // initialize additional state, and that should be done on the UI thread |
| // instead of potentially racing with the WillCreateURLLoaderFactory |
| // implementation. |
| auto loader_factory = |
| content::BrowserContext::GetDefaultStoragePartition(browser_context) |
| ->GetURLLoaderFactoryForBrowserProcess(); |
| |
| network::mojom::URLLoaderFactoryPtrInfo proxy_factory_ptr_info; |
| network::mojom::URLLoaderFactoryRequest proxy_factory_request; |
| |
| // Create an intermediate pipe that can be used to proxy the request's |
| // URLLoaderFactory. |
| network::mojom::URLLoaderFactoryPtrInfo maybe_proxy_factory_ptr_info; |
| mojo::PendingReceiver<network::mojom::URLLoaderFactory> |
| maybe_proxy_factory_request = MakeRequest(&maybe_proxy_factory_ptr_info); |
| |
| bool should_proxy = false; |
| int render_process_id = -1; |
| |
| if (render_frame_host) { |
| render_process_id = render_frame_host->GetProcess()->GetID(); |
| |
| // Allow DevTools to potentially inject itself into the proxy pipe. |
| should_proxy = |
| content::devtools_instrumentation::WillCreateURLLoaderFactory( |
| static_cast<content::RenderFrameHostImpl*>(render_frame_host), |
| false /* is_navigation */, false /* is_download */, |
| &maybe_proxy_factory_request, nullptr /* factory_override */); |
| } |
| |
| // Allow the Content embedder to inject itself if it wants to. |
| should_proxy |= CefContentBrowserClient::Get()->WillCreateURLLoaderFactory( |
| browser_context, render_frame_host, render_process_id, |
| content::ContentBrowserClient::URLLoaderFactoryType::kDocumentSubResource, |
| url::Origin(), base::nullopt /* navigation_id */, |
| &maybe_proxy_factory_request, nullptr /* header_client */, |
| nullptr /* bypass_redirect_checks */, nullptr /* disable_secure_dns */, |
| nullptr /* factory_override */); |
| |
| // If anyone above indicated that they care about proxying, pass the |
| // intermediate pipe along to the URLLoaderFactoryGetter. |
| if (should_proxy) { |
| proxy_factory_ptr_info = std::move(maybe_proxy_factory_ptr_info); |
| proxy_factory_request = std::move(maybe_proxy_factory_request); |
| } |
| |
| return base::WrapRefCounted(new URLLoaderFactoryGetter( |
| loader_factory->Clone(), std::move(proxy_factory_ptr_info), |
| std::move(proxy_factory_request))); |
| } |
| |
| // Based on NetworkDownloadURLLoaderFactoryGetter from |
| // content/browser/download/network_download_url_loader_factory_getter.cc. |
| scoped_refptr<network::SharedURLLoaderFactory> |
| URLLoaderFactoryGetter::GetURLLoaderFactory() { |
| // On first call we associate with the current thread. |
| if (!task_runner_) { |
| task_runner_ = base::ThreadTaskRunnerHandle::Get(); |
| } else { |
| DCHECK(task_runner_->RunsTasksInCurrentSequence()); |
| } |
| |
| if (lazy_factory_) |
| return lazy_factory_; |
| |
| // Bind on the current thread. |
| auto loader_factory = |
| network::SharedURLLoaderFactory::Create(std::move(loader_factory_info_)); |
| |
| if (proxy_factory_request_.is_pending()) { |
| loader_factory->Clone(std::move(proxy_factory_request_)); |
| lazy_factory_ = |
| base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>( |
| std::move(proxy_factory_ptr_info_)); |
| } else { |
| lazy_factory_ = loader_factory; |
| } |
| return lazy_factory_; |
| } |
| |
| URLLoaderFactoryGetter::URLLoaderFactoryGetter( |
| std::unique_ptr<network::PendingSharedURLLoaderFactory> loader_factory_info, |
| network::mojom::URLLoaderFactoryPtrInfo proxy_factory_ptr_info, |
| network::mojom::URLLoaderFactoryRequest proxy_factory_request) |
| : loader_factory_info_(std::move(loader_factory_info)), |
| proxy_factory_ptr_info_(std::move(proxy_factory_ptr_info)), |
| proxy_factory_request_(std::move(proxy_factory_request)) {} |
| |
| URLLoaderFactoryGetter::~URLLoaderFactoryGetter() = default; |
| |
| void URLLoaderFactoryGetter::DeleteOnCorrectThread() const { |
| if (task_runner_ && !task_runner_->RunsTasksInCurrentSequence()) { |
| task_runner_->DeleteSoon(FROM_HERE, this); |
| return; |
| } |
| delete this; |
| } |
| |
| } // namespace net_service |