• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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