1 // Copyright (c) 2019 The Chromium Embedded Framework Authors. Portions
2 // Copyright (c) 2018 The Chromium Authors. All rights reserved. Use of this
3 // source code is governed by a BSD-style license that can be found in the
4 // LICENSE file.
5
6 #include "libcef/browser/net_service/url_loader_factory_getter.h"
7
8 #include "libcef/browser/thread_util.h"
9 #include "libcef/common/app_manager.h"
10
11 #include "base/threading/thread_task_runner_handle.h"
12 #include "content/browser/devtools/devtools_instrumentation.h"
13 #include "content/browser/renderer_host/render_frame_host_impl.h"
14 #include "content/public/browser/browser_context.h"
15 #include "content/public/browser/storage_partition.h"
16 #include "content/public/common/content_client.h"
17 #include "services/network/public/cpp/shared_url_loader_factory.h"
18 #include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
19
20 namespace net_service {
21
22 // Based on CreateDownloadURLLoaderFactoryGetter from
23 // content/browser/download/download_manager_impl.cc.
24 // static
Create(content::RenderFrameHost * render_frame_host,content::BrowserContext * browser_context)25 scoped_refptr<URLLoaderFactoryGetter> URLLoaderFactoryGetter::Create(
26 content::RenderFrameHost* render_frame_host,
27 content::BrowserContext* browser_context) {
28 CEF_REQUIRE_UIT();
29 DCHECK(browser_context);
30
31 // Call this early because newly created BrowserContexts may need to
32 // initialize additional state, and that should be done on the UI thread
33 // instead of potentially racing with the WillCreateURLLoaderFactory
34 // implementation.
35 auto loader_factory = browser_context->GetDefaultStoragePartition()
36 ->GetURLLoaderFactoryForBrowserProcess();
37
38 network::mojom::URLLoaderFactoryPtrInfo proxy_factory_ptr_info;
39 network::mojom::URLLoaderFactoryRequest proxy_factory_request;
40
41 // Create an intermediate pipe that can be used to proxy the request's
42 // URLLoaderFactory.
43 network::mojom::URLLoaderFactoryPtrInfo maybe_proxy_factory_ptr_info;
44 mojo::PendingReceiver<network::mojom::URLLoaderFactory>
45 maybe_proxy_factory_request = MakeRequest(&maybe_proxy_factory_ptr_info);
46
47 bool should_proxy = false;
48 int render_process_id = -1;
49
50 if (render_frame_host) {
51 render_process_id = render_frame_host->GetProcess()->GetID();
52
53 // Allow DevTools to potentially inject itself into the proxy pipe.
54 should_proxy =
55 content::devtools_instrumentation::WillCreateURLLoaderFactory(
56 static_cast<content::RenderFrameHostImpl*>(render_frame_host),
57 false /* is_navigation */, false /* is_download */,
58 &maybe_proxy_factory_request, nullptr /* factory_override */);
59 }
60
61 auto browser_client = CefAppManager::Get()->GetContentClient()->browser();
62
63 // Allow the Content embedder to inject itself if it wants to.
64 should_proxy |= browser_client->WillCreateURLLoaderFactory(
65 browser_context, render_frame_host, render_process_id,
66 content::ContentBrowserClient::URLLoaderFactoryType::kDocumentSubResource,
67 url::Origin(), absl::nullopt /* navigation_id */, ukm::SourceIdObj(),
68 &maybe_proxy_factory_request, nullptr /* header_client */,
69 nullptr /* bypass_redirect_checks */, nullptr /* disable_secure_dns */,
70 nullptr /* factory_override */);
71
72 // If anyone above indicated that they care about proxying, pass the
73 // intermediate pipe along to the URLLoaderFactoryGetter.
74 if (should_proxy) {
75 proxy_factory_ptr_info = std::move(maybe_proxy_factory_ptr_info);
76 proxy_factory_request = std::move(maybe_proxy_factory_request);
77 }
78
79 return base::WrapRefCounted(new URLLoaderFactoryGetter(
80 loader_factory->Clone(), std::move(proxy_factory_ptr_info),
81 std::move(proxy_factory_request)));
82 }
83
84 // Based on NetworkDownloadURLLoaderFactoryGetter from
85 // content/browser/download/network_download_url_loader_factory_getter.cc.
86 scoped_refptr<network::SharedURLLoaderFactory>
GetURLLoaderFactory()87 URLLoaderFactoryGetter::GetURLLoaderFactory() {
88 // On first call we associate with the current thread.
89 if (!task_runner_) {
90 task_runner_ = base::ThreadTaskRunnerHandle::Get();
91 } else {
92 DCHECK(task_runner_->RunsTasksInCurrentSequence());
93 }
94
95 if (lazy_factory_)
96 return lazy_factory_;
97
98 // Bind on the current thread.
99 auto loader_factory =
100 network::SharedURLLoaderFactory::Create(std::move(loader_factory_info_));
101
102 if (proxy_factory_request_.is_pending()) {
103 loader_factory->Clone(std::move(proxy_factory_request_));
104 lazy_factory_ =
105 base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
106 std::move(proxy_factory_ptr_info_));
107 } else {
108 lazy_factory_ = loader_factory;
109 }
110 return lazy_factory_;
111 }
112
URLLoaderFactoryGetter(std::unique_ptr<network::PendingSharedURLLoaderFactory> loader_factory_info,network::mojom::URLLoaderFactoryPtrInfo proxy_factory_ptr_info,network::mojom::URLLoaderFactoryRequest proxy_factory_request)113 URLLoaderFactoryGetter::URLLoaderFactoryGetter(
114 std::unique_ptr<network::PendingSharedURLLoaderFactory> loader_factory_info,
115 network::mojom::URLLoaderFactoryPtrInfo proxy_factory_ptr_info,
116 network::mojom::URLLoaderFactoryRequest proxy_factory_request)
117 : loader_factory_info_(std::move(loader_factory_info)),
118 proxy_factory_ptr_info_(std::move(proxy_factory_ptr_info)),
119 proxy_factory_request_(std::move(proxy_factory_request)) {}
120
121 URLLoaderFactoryGetter::~URLLoaderFactoryGetter() = default;
122
DeleteOnCorrectThread() const123 void URLLoaderFactoryGetter::DeleteOnCorrectThread() const {
124 if (task_runner_ && !task_runner_->RunsTasksInCurrentSequence()) {
125 task_runner_->DeleteSoon(FROM_HERE, this);
126 return;
127 }
128 delete this;
129 }
130
131 } // namespace net_service