1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "content/browser/url_loader_factory_params_helper.h"
6 
7 #include "base/command_line.h"
8 #include "base/optional.h"
9 #include "content/browser/child_process_security_policy_impl.h"
10 #include "content/browser/frame_host/render_frame_host_impl.h"
11 #include "content/browser/site_instance_impl.h"
12 #include "content/public/browser/content_browser_client.h"
13 #include "content/public/browser/render_process_host.h"
14 #include "content/public/browser/render_view_host.h"
15 #include "content/public/common/content_client.h"
16 #include "content/public/common/content_switches.h"
17 #include "content/public/common/url_constants.h"
18 #include "content/public/common/web_preferences.h"
19 #include "services/network/public/mojom/cross_origin_embedder_policy.mojom.h"
20 #include "services/network/public/mojom/network_context.mojom.h"
21 
22 namespace content {
23 
24 namespace {
25 
26 // Helper used by the public URLLoaderFactoryParamsHelper::Create... methods.
27 //
28 // |origin| is the origin that will use the URLLoaderFactory.
29 // |origin| is typically the same as the origin in
30 // network::ResourceRequest::request_initiator, except when
31 // |is_for_isolated_world|.  See also the doc comment for
32 // extensions::URLLoaderFactoryManager::CreateFactory.
33 //
34 // TODO(kinuko, lukasza): https://crbug.com/891872: Make
35 // |request_initiator_site_lock| non-optional, once
36 // URLLoaderFactoryParamsHelper::CreateForRendererProcess is removed.
CreateParams(RenderProcessHost * process,const url::Origin & origin,const base::Optional<url::Origin> & request_initiator_site_lock,const base::Optional<url::Origin> & top_frame_origin,bool is_trusted,const base::Optional<base::UnguessableToken> & top_frame_token,const base::Optional<net::NetworkIsolationKey> & network_isolation_key,network::mojom::ClientSecurityStatePtr client_security_state,mojo::PendingRemote<network::mojom::CrossOriginEmbedderPolicyReporter> coep_reporter,bool allow_universal_access_from_file_urls,bool is_for_isolated_world)37 network::mojom::URLLoaderFactoryParamsPtr CreateParams(
38     RenderProcessHost* process,
39     const url::Origin& origin,
40     const base::Optional<url::Origin>& request_initiator_site_lock,
41     const base::Optional<url::Origin>& top_frame_origin,
42     bool is_trusted,
43     const base::Optional<base::UnguessableToken>& top_frame_token,
44     const base::Optional<net::NetworkIsolationKey>& network_isolation_key,
45     network::mojom::ClientSecurityStatePtr client_security_state,
46     mojo::PendingRemote<network::mojom::CrossOriginEmbedderPolicyReporter>
47         coep_reporter,
48     bool allow_universal_access_from_file_urls,
49     bool is_for_isolated_world) {
50   DCHECK(process);
51 
52   // "chrome-guest://..." is never used as a main or isolated world origin.
53   DCHECK_NE(kGuestScheme, origin.scheme());
54   DCHECK(!request_initiator_site_lock.has_value() ||
55          request_initiator_site_lock->scheme() != kGuestScheme);
56 
57   network::mojom::URLLoaderFactoryParamsPtr params =
58       network::mojom::URLLoaderFactoryParams::New();
59 
60   params->process_id = process->GetID();
61   params->request_initiator_site_lock = request_initiator_site_lock;
62   params->top_frame_origin = top_frame_origin;
63 
64   params->is_trusted = is_trusted;
65   params->top_frame_id = top_frame_token;
66   params->network_isolation_key = network_isolation_key;
67 
68   params->disable_web_security =
69       base::CommandLine::ForCurrentProcess()->HasSwitch(
70           switches::kDisableWebSecurity);
71   params->client_security_state = std::move(client_security_state);
72   params->coep_reporter = std::move(coep_reporter);
73 
74   if (params->disable_web_security) {
75     // --disable-web-security also disables Cross-Origin Read Blocking (CORB).
76     params->is_corb_enabled = false;
77   } else if (allow_universal_access_from_file_urls &&
78              origin.scheme() == url::kFileScheme) {
79     // allow_universal_access_from_file_urls disables CORB (via
80     // |is_corb_enabled|) and CORS (via |disable_web_security|) for requests
81     // made from a file: |origin|.
82     params->is_corb_enabled = false;
83     params->disable_web_security = true;
84   } else {
85     params->is_corb_enabled = true;
86   }
87 
88   GetContentClient()->browser()->OverrideURLLoaderFactoryParams(
89       process->GetBrowserContext(), origin, is_for_isolated_world,
90       params.get());
91 
92   return params;
93 }
94 
95 }  // namespace
96 
97 // static
98 network::mojom::URLLoaderFactoryParamsPtr
CreateForFrame(RenderFrameHostImpl * frame,const url::Origin & frame_origin,network::mojom::ClientSecurityStatePtr client_security_state,mojo::PendingRemote<network::mojom::CrossOriginEmbedderPolicyReporter> coep_reporter,RenderProcessHost * process)99 URLLoaderFactoryParamsHelper::CreateForFrame(
100     RenderFrameHostImpl* frame,
101     const url::Origin& frame_origin,
102     network::mojom::ClientSecurityStatePtr client_security_state,
103     mojo::PendingRemote<network::mojom::CrossOriginEmbedderPolicyReporter>
104         coep_reporter,
105     RenderProcessHost* process) {
106   return CreateParams(
107       process,
108       frame_origin,  // origin
109       frame_origin,  // request_initiator_site_lock
110       // top_frame_origin
111       frame->ComputeTopFrameOrigin(frame_origin),
112       false,  // is_trusted
113       frame->GetTopFrameToken(), frame->GetNetworkIsolationKey(),
114       std::move(client_security_state), std::move(coep_reporter),
115       frame->GetRenderViewHost()
116           ->GetWebkitPreferences()
117           .allow_universal_access_from_file_urls,
118       false);  // is_for_isolated_world
119 }
120 
121 // static
122 network::mojom::URLLoaderFactoryParamsPtr
CreateForIsolatedWorld(RenderFrameHostImpl * frame,const url::Origin & isolated_world_origin,const url::Origin & main_world_origin,network::mojom::ClientSecurityStatePtr client_security_state)123 URLLoaderFactoryParamsHelper::CreateForIsolatedWorld(
124     RenderFrameHostImpl* frame,
125     const url::Origin& isolated_world_origin,
126     const url::Origin& main_world_origin,
127     network::mojom::ClientSecurityStatePtr client_security_state) {
128   return CreateParams(frame->GetProcess(),
129                       isolated_world_origin,  // origin
130                       main_world_origin,      // request_initiator_site_lock
131                       base::nullopt,          // top_frame_origin
132                       false,                  // is_trusted
133                       frame->GetTopFrameToken(),
134                       frame->GetNetworkIsolationKey(),
135                       std::move(client_security_state),
136                       mojo::NullRemote(),  // coep_reporter
137                       frame->GetRenderViewHost()
138                           ->GetWebkitPreferences()
139                           .allow_universal_access_from_file_urls,
140                       true);  // is_for_isolated_world
141 }
142 
143 network::mojom::URLLoaderFactoryParamsPtr
CreateForPrefetch(RenderFrameHostImpl * frame,network::mojom::ClientSecurityStatePtr client_security_state)144 URLLoaderFactoryParamsHelper::CreateForPrefetch(
145     RenderFrameHostImpl* frame,
146     network::mojom::ClientSecurityStatePtr client_security_state) {
147   // The factory client |is_trusted| to control the |network_isolation_key| in
148   // each separate request (rather than forcing the client to use the key
149   // specified in URLLoaderFactoryParams).
150   const url::Origin& frame_origin = frame->GetLastCommittedOrigin();
151   return CreateParams(frame->GetProcess(),
152                       frame_origin,  // origin
153                       frame_origin,  // request_initiator_site_lock
154                       // top_frame_origin
155                       frame->ComputeTopFrameOrigin(frame_origin),
156                       true,  // is_trusted
157                       frame->GetTopFrameToken(),
158                       base::nullopt,  // network_isolation_key
159                       std::move(client_security_state),
160                       mojo::NullRemote(),  // coep_reporter
161                       frame->GetRenderViewHost()
162                           ->GetWebkitPreferences()
163                           .allow_universal_access_from_file_urls,
164                       false);  // is_for_isolated_world
165 }
166 
167 // static
168 network::mojom::URLLoaderFactoryParamsPtr
CreateForWorker(RenderProcessHost * process,const url::Origin & request_initiator,const net::NetworkIsolationKey & network_isolation_key,mojo::PendingRemote<network::mojom::CrossOriginEmbedderPolicyReporter> coep_reporter)169 URLLoaderFactoryParamsHelper::CreateForWorker(
170     RenderProcessHost* process,
171     const url::Origin& request_initiator,
172     const net::NetworkIsolationKey& network_isolation_key,
173     mojo::PendingRemote<network::mojom::CrossOriginEmbedderPolicyReporter>
174         coep_reporter) {
175   return CreateParams(process,
176                       request_initiator,  // origin
177                       request_initiator,  // request_initiator_site_lock
178                       base::nullopt,      // top_frame_origin
179                       false,              // is_trusted
180                       base::nullopt,      // top_frame_token
181                       network_isolation_key,
182                       nullptr,  // client_security_state
183                       std::move(coep_reporter),
184                       false,   // allow_universal_access_from_file_urls
185                       false);  // is_for_isolated_world
186 }
187 
188 // static
189 network::mojom::URLLoaderFactoryParamsPtr
CreateForRendererProcess(RenderProcessHost * process)190 URLLoaderFactoryParamsHelper::CreateForRendererProcess(
191     RenderProcessHost* process) {
192   // Attempt to use the process lock as |request_initiator_site_lock|.
193   base::Optional<url::Origin> request_initiator_site_lock;
194   auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
195   GURL process_lock = policy->GetOriginLock(process->GetID());
196   if (process_lock.is_valid()) {
197     request_initiator_site_lock =
198         SiteInstanceImpl::GetRequestInitiatorSiteLock(process_lock);
199   }
200 
201   // Since this function is about to get deprecated (crbug.com/891872), it
202   // should be fine to not add support for network isolation thus sending empty
203   // key.
204   //
205   // We may not be able to allow powerful APIs such as memory measurement APIs
206   // (see https://crbug.com/887967) without removing this call.
207   base::Optional<net::NetworkIsolationKey> network_isolation_key =
208       base::nullopt;
209   base::Optional<base::UnguessableToken> top_frame_token = base::nullopt;
210 
211   return CreateParams(
212       process,
213       url::Origin(),                // origin
214       request_initiator_site_lock,  // request_initiator_site_lock
215       base::nullopt,                // top_frame_origin
216       false,                        // is_trusted
217       top_frame_token, network_isolation_key,
218       nullptr,             // client_security_state
219       mojo::NullRemote(),  // coep_reporter
220       false,               // allow_universal_access_from_file_urls
221       false);              // is_for_isolated_world
222 }
223 
224 }  // namespace content
225