blob: f4520de1d41c68d1a0162cee6ae531b036621f3e [file] [log] [blame]
scottmg69985212017-04-12 16:47:281// Copyright 2017 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
arthursonzogni1fd60e62018-05-09 15:57:325#include "content/browser/loader/navigation_url_loader_impl.h"
scottmg69985212017-04-12 16:47:286
Gyuyoung Kim637cefb2018-02-03 03:03:217#include <memory>
8
ananta5149d8e2017-04-21 00:01:379#include "base/bind.h"
10#include "base/bind_helpers.h"
Matt Falkenhagen2ba894152018-09-21 08:29:4411#include "base/debug/alias.h"
Tarun Bansal98260cd2018-02-17 07:52:2312#include "base/feature_list.h"
Emily Starkb09f19a2017-11-22 22:41:4713#include "base/metrics/histogram_macros.h"
Matt Menked9cad562018-08-10 21:47:0914#include "base/optional.h"
Matt Falkenhagen2ba894152018-09-21 08:29:4415#include "base/rand_util.h"
qufehdquf9c8433abd2018-07-10 16:57:2716#include "base/stl_util.h"
Gabriel Charette44db1422018-08-06 11:19:3317#include "base/task/post_task.h"
yzshen0f278522017-05-01 17:10:2218#include "base/trace_event/trace_event.h"
Eric Roman80164412018-10-02 22:13:5419#include "build/build_config.h"
Min Qinda0ed2062018-02-23 22:00:5320#include "components/download/public/common/download_stats.h"
anantae3f159a2017-05-11 23:40:0721#include "content/browser/appcache/appcache_navigation_handle.h"
Hiroki Nakagawaff43e4472018-07-26 07:06:4622#include "content/browser/appcache/appcache_navigation_handle_core.h"
anantaa2c8ec62017-06-09 23:44:0523#include "content/browser/appcache/appcache_request_handler.h"
ananta5149d8e2017-04-21 00:01:3724#include "content/browser/blob_storage/chrome_blob_storage_context.h"
Andrey Kosyakov8d49c5062018-03-15 19:50:4925#include "content/browser/devtools/render_frame_devtools_agent_host.h"
Ken Rockot314714c2017-11-05 23:36:2426#include "content/browser/file_url_loader_factory.h"
Chris Mumford942075ad2018-05-19 00:22:0427#include "content/browser/fileapi/file_system_url_loader_factory.h"
jam8c4edd02017-05-06 18:50:3328#include "content/browser/frame_host/frame_tree_node.h"
scottmg69985212017-04-12 16:47:2829#include "content/browser/frame_host/navigation_request_info.h"
Kinuko Yasuda7f3e1722018-03-26 08:58:5830#include "content/browser/loader/navigation_loader_interceptor.h"
scottmg95feea52017-04-12 17:51:3331#include "content/browser/loader/navigation_url_loader_delegate.h"
arthursonzogni2695d04d2017-12-12 08:39:0132#include "content/browser/loader/resource_dispatcher_host_impl.h"
arthursonzogni40db5f52018-01-08 16:38:4933#include "content/browser/loader/resource_request_info_impl.h"
scottmgd2021c92017-05-15 16:58:0534#include "content/browser/resource_context_impl.h"
35#include "content/browser/service_worker/service_worker_navigation_handle.h"
36#include "content/browser/service_worker/service_worker_navigation_handle_core.h"
37#include "content/browser/service_worker/service_worker_request_handler.h"
jamc1905862017-05-16 14:45:3038#include "content/browser/storage_partition_impl.h"
39#include "content/browser/url_loader_factory_getter.h"
scottmgd2021c92017-05-15 16:58:0540#include "content/browser/web_contents/web_contents_impl.h"
Kouhei Ueno958c5f482018-03-19 08:20:3841#include "content/browser/web_package/signed_exchange_consts.h"
Kunihiko Sakamotoe6aa22e2018-06-15 03:26:5542#include "content/browser/web_package/signed_exchange_request_handler.h"
Tsuyoshi Horob85801592018-02-19 22:18:0743#include "content/browser/web_package/signed_exchange_url_loader_factory_for_non_network_service.h"
Tsuyoshi Horo46f5fff2018-05-10 12:33:3544#include "content/browser/web_package/signed_exchange_utils.h"
jam1a97290b2017-05-09 04:30:5045#include "content/browser/webui/url_data_manager_backend.h"
Chris Mumfordbae8a742018-03-01 23:02:2346#include "content/browser/webui/web_ui_url_loader_factory_internal.h"
Makoto Shimazu21950e82018-08-02 12:37:1447#include "content/common/mime_sniffing_throttle.h"
Kinuko Yasuda250577c2017-10-29 02:51:2448#include "content/common/navigation_subresource_loader_params.h"
Matt Menkea294b092018-07-06 17:53:3249#include "content/common/net/record_load_histograms.h"
yzshenefcb7c72017-06-16 23:12:3050#include "content/common/throttling_url_loader.h"
jamc1905862017-05-16 14:45:3051#include "content/public/browser/browser_context.h"
Eric Seckler8652dcd52018-09-20 10:42:2852#include "content/public/browser/browser_task_traits.h"
scottmg95feea52017-04-12 17:51:3353#include "content/public/browser/browser_thread.h"
yzshenefcb7c72017-06-16 23:12:3054#include "content/public/browser/content_browser_client.h"
Robbie McElratha5adc4e2018-07-03 23:53:0955#include "content/public/browser/download_utils.h"
scottmgefb697302017-04-12 22:37:3056#include "content/public/browser/global_request_id.h"
Dmitry Skiba7e8c7e22018-01-04 21:04:1857#include "content/public/browser/navigation_data.h"
scottmg69985212017-04-12 16:47:2858#include "content/public/browser/navigation_ui_data.h"
John Abd-El-Malek3ebdff862018-04-23 18:57:2159#include "content/public/browser/plugin_service.h"
arthursonzogni40db5f52018-01-08 16:38:4960#include "content/public/browser/resource_dispatcher_host_delegate.h"
scottmgefb697302017-04-12 22:37:3061#include "content/public/browser/ssl_status.h"
Jian Li18e29242018-05-10 22:25:1262#include "content/public/browser/url_loader_request_interceptor.h"
arthursonzogni2695d04d2017-12-12 08:39:0163#include "content/public/common/content_features.h"
ananta5149d8e2017-04-21 00:01:3764#include "content/public/common/referrer.h"
jam8c4edd02017-05-06 18:50:3365#include "content/public/common/url_constants.h"
Ken Rockot314714c2017-11-05 23:36:2466#include "content/public/common/url_utils.h"
John Abd-El-Malek3ebdff862018-04-23 18:57:2167#include "content/public/common/webplugininfo.h"
ananta5149d8e2017-04-21 00:01:3768#include "net/base/load_flags.h"
Matt Menked9cad562018-08-10 21:47:0969#include "net/cert/sct_status_flags.h"
70#include "net/cert/signed_certificate_timestamp_and_status.h"
Min Qin37db5102017-09-13 21:21:2571#include "net/http/http_content_disposition.h"
Chong Zhang7607f1f2018-06-01 20:52:2072#include "net/http/http_request_headers.h"
Matt Menke4f8104c2018-10-01 23:42:5273#include "net/http/http_status_code.h"
Matt Menked9cad562018-08-10 21:47:0974#include "net/ssl/ssl_info.h"
rhalavati4cda417b2017-06-12 11:00:2475#include "net/traffic_annotation/network_traffic_annotation.h"
Tsuyoshi Horo9e2ec4df2017-10-16 15:15:5576#include "net/url_request/redirect_util.h"
Daniel Bratell0dfa6282017-11-08 10:12:2377#include "net/url_request/url_request.h"
scottmg69985212017-04-12 16:47:2878#include "net/url_request/url_request_context.h"
Tsuyoshi Horo70014ad2018-02-14 11:20:1479#include "net/url_request/url_request_context_getter.h"
John Abd-El-Malek3ebdff862018-04-23 18:57:2180#include "ppapi/buildflags/buildflags.h"
John Abd-El-Malek89c02ae2018-02-01 01:56:1981#include "services/network/loader_util.h"
Yutaka Hiranod8789f92018-01-30 09:59:5182#include "services/network/public/cpp/features.h"
Antonio Gomes9cdc09a2018-05-07 23:24:2683#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
84#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
Ken Rockot54311e62018-02-10 19:01:5285#include "services/network/public/mojom/request_context_frame_type.mojom.h"
86#include "services/network/public/mojom/url_loader_factory.mojom.h"
yzshenefcb7c72017-06-16 23:12:3087#include "services/service_manager/public/cpp/connector.h"
John Abd-El-Malek3ebdff862018-04-23 18:57:2188#include "third_party/blink/public/common/mime_util/mime_util.h"
Han Leonf1525df2018-07-11 03:47:5989#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
Matt Falkenhagen2ba894152018-09-21 08:29:4490#include "url/gurl.h"
scottmg69985212017-04-12 16:47:2891
Eric Roman80164412018-10-02 22:13:5492#if defined(OS_ANDROID)
93#include "content/browser/android/content_url_loader_factory.h"
94#endif
95
scottmg69985212017-04-12 16:47:2896namespace content {
97
jambcc67882017-04-28 18:20:0998namespace {
yzshenfa5e57202017-05-02 21:24:1399
Jian Li18e29242018-05-10 22:25:12100class NavigationLoaderInterceptorBrowserContainer
101 : public NavigationLoaderInterceptor {
102 public:
103 explicit NavigationLoaderInterceptorBrowserContainer(
104 std::unique_ptr<URLLoaderRequestInterceptor> browser_interceptor)
105 : browser_interceptor_(std::move(browser_interceptor)) {}
106
107 ~NavigationLoaderInterceptorBrowserContainer() override = default;
108
Matt Falkenhagen43765122018-08-22 19:37:22109 void MaybeCreateLoader(
110 const network::ResourceRequest& tentative_resource_request,
111 ResourceContext* resource_context,
112 LoaderCallback callback,
113 FallbackCallback fallback_callback) override {
114 browser_interceptor_->MaybeCreateLoader(
115 tentative_resource_request, resource_context, std::move(callback));
Jian Li18e29242018-05-10 22:25:12116 }
117
118 private:
119 std::unique_ptr<URLLoaderRequestInterceptor> browser_interceptor_;
120};
121
John Abd-El-Malekdb3a13b2018-05-01 17:52:02122// Only used on the IO thread.
arthursonzogni1fd60e62018-05-09 15:57:32123base::LazyInstance<NavigationURLLoaderImpl::BeginNavigationInterceptor>::Leaky
John Abd-El-Malekdb3a13b2018-05-01 17:52:02124 g_interceptor = LAZY_INSTANCE_INITIALIZER;
125
Kinuko Yasuda7f3e1722018-03-26 08:58:58126// Returns true if interception by NavigationLoaderInterceptors is enabled.
Tsuyoshi Horo46f5fff2018-05-10 12:33:35127// Both ServiceWorkerServicification and SignedExchange require the loader
128// interception. So even if NetworkService is not enabled, returns true when one
129// of them is enabled.
Kinuko Yasuda7f3e1722018-03-26 08:58:58130bool IsLoaderInterceptionEnabled() {
Yutaka Hiranod8789f92018-01-30 09:59:51131 return base::FeatureList::IsEnabled(network::features::kNetworkService) ||
Han Leonf1525df2018-07-11 03:47:59132 blink::ServiceWorkerUtils::IsServicificationEnabled() ||
Tsuyoshi Horo46f5fff2018-05-10 12:33:35133 signed_exchange_utils::IsSignedExchangeHandlingEnabled();
Tsuyoshi Horob8d512a2018-01-25 17:01:59134}
135
ananta2e65213d2017-05-19 04:08:24136// Request ID for browser initiated requests. We start at -2 on the same lines
137// as ResourceDispatcherHostImpl.
138int g_next_request_id = -2;
arthursonzogni40db5f52018-01-08 16:38:49139GlobalRequestID MakeGlobalRequestID() {
140 return GlobalRequestID(-1, g_next_request_id--);
141}
ananta2e65213d2017-05-19 04:08:24142
Emily Starkb09f19a2017-11-22 22:41:47143size_t GetCertificateChainsSizeInKB(const net::SSLInfo& ssl_info) {
144 base::Pickle cert_pickle;
145 ssl_info.cert->Persist(&cert_pickle);
146 base::Pickle unverified_cert_pickle;
147 ssl_info.unverified_cert->Persist(&unverified_cert_pickle);
148 return (cert_pickle.size() + unverified_cert_pickle.size()) / 1000;
149}
150
scottmgd2021c92017-05-15 16:58:05151WebContents* GetWebContentsFromFrameTreeNodeID(int frame_tree_node_id) {
152 DCHECK_CURRENTLY_ON(BrowserThread::UI);
153 FrameTreeNode* frame_tree_node =
154 FrameTreeNode::GloballyFindByID(frame_tree_node_id);
155 if (!frame_tree_node)
156 return nullptr;
ananta5149d8e2017-04-21 00:01:37157
scottmgd2021c92017-05-15 16:58:05158 return WebContentsImpl::FromFrameTreeNode(frame_tree_node);
159}
160
Daniel Bratellcf0b485c2017-11-09 22:42:50161const net::NetworkTrafficAnnotationTag kNavigationUrlLoaderTrafficAnnotation =
Ramin Halavatie99206e92017-06-23 05:02:50162 net::DefineNetworkTrafficAnnotation("navigation_url_loader", R"(
Ramin Halavati7b5ce1c2017-07-03 09:13:09163 semantics {
164 sender: "Navigation URL Loader"
165 description:
166 "This request is issued by a main frame navigation to fetch the "
167 "content of the page that is being navigated to."
168 trigger:
169 "Navigating Chrome (by clicking on a link, bookmark, history item, "
170 "using session restore, etc)."
171 data:
172 "Arbitrary site-controlled data can be included in the URL, HTTP "
173 "headers, and request body. Requests may include cookies and "
174 "site-specific credentials."
175 destination: WEBSITE
176 }
177 policy {
Ramin Halavati3b979782017-07-21 11:40:26178 cookies_allowed: YES
Ramin Halavati7b5ce1c2017-07-03 09:13:09179 cookies_store: "user"
180 setting: "This feature cannot be disabled."
Ramin Halavati386daa62017-08-17 10:41:59181 chrome_policy {
182 URLBlacklist {
183 URLBlacklist: { entries: '*' }
184 }
185 }
186 chrome_policy {
187 URLWhitelist {
188 URLWhitelist { }
189 }
190 }
191 }
192 comments:
193 "Chrome would be unable to navigate to websites without this type of "
194 "request. Using either URLBlacklist or URLWhitelist policies (or a "
195 "combination of both) limits the scope of these requests."
196 )");
Ramin Halavatie99206e92017-06-23 05:02:50197
Tsuyoshi Horob8d512a2018-01-25 17:01:59198std::unique_ptr<network::ResourceRequest> CreateResourceRequest(
199 NavigationRequestInfo* request_info,
200 int frame_tree_node_id,
201 bool allow_download) {
202 // TODO(scottmg): Port over stuff from RDHI::BeginNavigationRequest() here.
203 auto new_request = std::make_unique<network::ResourceRequest>();
204
205 new_request->method = request_info->common_params.method;
206 new_request->url = request_info->common_params.url;
207 new_request->site_for_cookies = request_info->site_for_cookies;
Tarun Bansal98260cd2018-02-17 07:52:23208
209 net::RequestPriority net_priority = net::HIGHEST;
210 if (!request_info->is_main_frame &&
211 base::FeatureList::IsEnabled(features::kLowPriorityIframes)) {
212 net_priority = net::LOWEST;
213 }
214 new_request->priority = net_priority;
215
Tsuyoshi Horob8d512a2018-01-25 17:01:59216 new_request->render_frame_id = frame_tree_node_id;
217
218 // The code below to set fields like request_initiator, referrer, etc has
219 // been copied from ResourceDispatcherHostImpl. We did not refactor the
220 // common code into a function, because RDHI uses accessor functions on the
221 // URLRequest class to set these fields. whereas we use ResourceRequest here.
222 new_request->request_initiator = request_info->begin_params->initiator_origin;
223 new_request->referrer = request_info->common_params.referrer.url;
224 new_request->referrer_policy = Referrer::ReferrerPolicyForUrlRequest(
225 request_info->common_params.referrer.policy);
226 new_request->headers.AddHeadersFromString(
227 request_info->begin_params->headers);
Kouhei Ueno958c5f482018-03-19 08:20:38228
229 std::string accept_value = network::kFrameAcceptHeader;
Tsuyoshi Horo6e5bd032018-09-28 13:11:02230 if (signed_exchange_utils::ShouldAdvertiseAcceptHeader(
231 url::Origin::Create(request_info->common_params.url))) {
Kouhei Ueno958c5f482018-03-19 08:20:38232 DCHECK(!accept_value.empty());
233 accept_value.append(kAcceptHeaderSignedExchangeSuffix);
234 }
235
236 new_request->headers.SetHeader(network::kAcceptHeader, accept_value);
Tsuyoshi Horob8d512a2018-01-25 17:01:59237
238 new_request->resource_type = request_info->is_main_frame
239 ? RESOURCE_TYPE_MAIN_FRAME
240 : RESOURCE_TYPE_SUB_FRAME;
241 if (request_info->is_main_frame)
242 new_request->update_first_party_url_on_redirect = true;
243
244 int load_flags = request_info->begin_params->load_flags;
Tsuyoshi Horob8d512a2018-01-25 17:01:59245 if (request_info->is_main_frame)
246 load_flags |= net::LOAD_MAIN_FRAME_DEPRECATED;
247
248 // Sync loads should have maximum priority and should be the only
249 // requests that have the ignore limits flag set.
250 DCHECK(!(load_flags & net::LOAD_IGNORE_LIMITS));
251
252 new_request->load_flags = load_flags;
253
254 new_request->request_body = request_info->common_params.post_data.get();
255 new_request->report_raw_headers = request_info->report_raw_headers;
256 new_request->allow_download = allow_download;
257 new_request->enable_load_timing = true;
258
259 new_request->fetch_request_mode = network::mojom::FetchRequestMode::kNavigate;
260 new_request->fetch_credentials_mode =
261 network::mojom::FetchCredentialsMode::kInclude;
262 new_request->fetch_redirect_mode = network::mojom::FetchRedirectMode::kManual;
Yutaka Hirano4b9b7a7f2018-03-07 14:35:15263 new_request->fetch_request_context_type =
Richard Li01f04032018-09-19 07:45:59264 static_cast<int>(request_info->begin_params->request_context_type);
Carlos ILa54c59a2018-06-11 19:43:03265 new_request->upgrade_if_insecure = request_info->upgrade_if_insecure;
Tsuyoshi Horoc1ab7122018-06-19 05:48:13266 new_request->throttling_profile_id = request_info->devtools_frame_token;
Tsuyoshi Horob8d512a2018-01-25 17:01:59267 return new_request;
268}
269
Makoto Shimazu44c2c3232018-03-30 01:10:20270// Used only when NetworkService is disabled but IsLoaderInterceptionEnabled()
271// is true.
272std::unique_ptr<NavigationRequestInfo> CreateNavigationRequestInfoForRedirect(
273 const NavigationRequestInfo& previous_request_info,
274 const network::ResourceRequest& updated_resource_request) {
275 DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
276 DCHECK(IsLoaderInterceptionEnabled());
277
278 CommonNavigationParams new_common_params =
279 previous_request_info.common_params;
280 new_common_params.url = updated_resource_request.url;
281 new_common_params.referrer =
Makoto Shimazue8019fb2018-06-26 03:54:31282 Referrer(updated_resource_request.referrer,
Makoto Shimazu44c2c3232018-03-30 01:10:20283 Referrer::NetReferrerPolicyToBlinkReferrerPolicy(
284 updated_resource_request.referrer_policy));
285 new_common_params.method = updated_resource_request.method;
286 new_common_params.post_data = updated_resource_request.request_body;
Makoto Shimazu44c2c3232018-03-30 01:10:20287
288 mojom::BeginNavigationParamsPtr new_begin_params =
289 previous_request_info.begin_params.Clone();
290 new_begin_params->headers = updated_resource_request.headers.ToString();
291
292 return std::make_unique<NavigationRequestInfo>(
293 std::move(new_common_params), std::move(new_begin_params),
294 updated_resource_request.site_for_cookies,
295 previous_request_info.is_main_frame,
296 previous_request_info.parent_is_main_frame,
297 previous_request_info.are_ancestors_secure,
298 previous_request_info.frame_tree_node_id,
299 previous_request_info.is_for_guests_only,
300 previous_request_info.report_raw_headers,
Marijn Kruisselbrink07bf59d52018-04-03 21:50:25301 previous_request_info.is_prerendering,
Carlos ILa54c59a2018-06-11 19:43:03302 previous_request_info.upgrade_if_insecure,
Tsuyoshi Horo32b51f12018-05-09 17:58:46303 nullptr /* blob_url_loader_factory */,
Tsuyoshi Horoc1ab7122018-06-19 05:48:13304 previous_request_info.devtools_navigation_token,
305 previous_request_info.devtools_frame_token);
Makoto Shimazu44c2c3232018-03-30 01:10:20306}
307
John Abd-El-Maleka67add82018-03-09 18:22:01308// Called for requests that we don't have a URLLoaderFactory for.
Matt Falkenhagen43765122018-08-22 19:37:22309void UnknownSchemeCallback(
310 bool handled_externally,
311 const network::ResourceRequest& /* resource_request */,
312 network::mojom::URLLoaderRequest request,
313 network::mojom::URLLoaderClientPtr client) {
John Abd-El-Maleka67add82018-03-09 18:22:01314 client->OnComplete(network::URLLoaderCompletionStatus(
315 handled_externally ? net::ERR_ABORTED : net::ERR_UNKNOWN_URL_SCHEME));
316}
317
Clark DuVallbf7722f2018-08-03 18:03:33318// Returns whether this URL can be handled by the default network service
319// URLLoader.
320bool IsURLHandledByDefaultLoader(const GURL& url) {
321 // Data URLs are only handled by the network service if
322 // |enable_data_url_support| is set in NetworkContextParams. This is set to
323 // true for the context used by NavigationURLLoaderImpl, so in addition to
324 // checking whether the URL is handled by the network service, we also need to
325 // check for the data scheme.
326 return IsURLHandledByNetworkService(url) || url.SchemeIs(url::kDataScheme);
327}
328
Chris Mumford90b1a0d2018-09-26 20:10:43329// Determines whether it is safe to redirect from |from_url| to |to_url|.
330bool IsRedirectSafe(const GURL& from_url,
331 const GURL& to_url,
332 ResourceContext* resource_context) {
333 return IsSafeRedirectTarget(from_url, to_url) &&
334 GetContentClient()->browser()->IsSafeRedirectTarget(to_url,
Clark DuVallbf7722f2018-08-03 18:03:33335 resource_context);
336}
337
yzshenfa5e57202017-05-02 21:24:13338} // namespace
339
kinuko69732972017-05-29 08:50:07340// Kept around during the lifetime of the navigation request, and is
341// responsible for dispatching a ResourceRequest to the appropriate
kinukod8b13e212017-06-07 06:59:26342// URLLoader. In order to get the right URLLoader it builds a vector
Kinuko Yasuda7f3e1722018-03-26 08:58:58343// of NavigationLoaderInterceptors and successively calls MaybeCreateLoader
kinukod8b13e212017-06-07 06:59:26344// on each until the request is successfully handled. The same sequence
345// may be performed multiple times when redirects happen.
Alex Clarke1e08882b32017-10-06 14:22:40346// TODO(michaeln): Expose this class and add more unittests.
arthursonzogni1fd60e62018-05-09 15:57:32347class NavigationURLLoaderImpl::URLLoaderRequestController
John Abd-El-Malekb165dc52018-01-18 17:12:18348 : public network::mojom::URLLoaderClient {
kinuko69732972017-05-29 08:50:07349 public:
jam9354af82017-06-03 21:59:41350 URLLoaderRequestController(
Kinuko Yasuda7f3e1722018-03-26 08:58:58351 std::vector<std::unique_ptr<NavigationLoaderInterceptor>>
352 initial_interceptors,
John Abd-El-Malek1df61792018-01-12 20:40:45353 std::unique_ptr<network::ResourceRequest> resource_request,
jam9354af82017-06-03 21:59:41354 ResourceContext* resource_context,
arthursonzogni40db5f52018-01-08 16:38:49355 const GURL& url,
Matt Menked9cad562018-08-10 21:47:09356 bool is_main_frame,
Ken Rockota0dfaca12018-02-15 07:26:25357 network::mojom::URLLoaderFactoryRequest proxied_factory_request,
358 network::mojom::URLLoaderFactoryPtrInfo proxied_factory_info,
John Abd-El-Maleka67add82018-03-09 18:22:01359 std::set<std::string> known_schemes,
Clark DuVallb2680c22018-08-10 15:27:27360 bool bypass_redirect_checks,
arthursonzogni1fd60e62018-05-09 15:57:32361 const base::WeakPtr<NavigationURLLoaderImpl>& owner)
Kinuko Yasuda7f3e1722018-03-26 08:58:58362 : interceptors_(std::move(initial_interceptors)),
Alex Clarke1e08882b32017-10-06 14:22:40363 resource_request_(std::move(resource_request)),
kinuko69732972017-05-29 08:50:07364 resource_context_(resource_context),
arthursonzogni40db5f52018-01-08 16:38:49365 url_(url),
Matt Menked9cad562018-08-10 21:47:09366 is_main_frame_(is_main_frame),
anantab9800e52017-07-29 18:04:13367 owner_(owner),
arthursonzogni2695d04d2017-12-12 08:39:01368 response_loader_binding_(this),
Ken Rockota0dfaca12018-02-15 07:26:25369 proxied_factory_request_(std::move(proxied_factory_request)),
370 proxied_factory_info_(std::move(proxied_factory_info)),
John Abd-El-Maleka67add82018-03-09 18:22:01371 known_schemes_(std::move(known_schemes)),
Clark DuVallb2680c22018-08-10 15:27:27372 bypass_redirect_checks_(bypass_redirect_checks),
arthursonzogni2695d04d2017-12-12 08:39:01373 weak_factory_(this) {}
kinuko69732972017-05-29 08:50:07374
yzshenefcb7c72017-06-16 23:12:30375 ~URLLoaderRequestController() override {
kinuko69732972017-05-29 08:50:07376 DCHECK_CURRENTLY_ON(BrowserThread::IO);
Matt Menkea294b092018-07-06 17:53:32377
378 // If neither OnCompleted nor OnReceivedResponse has been invoked, the
379 // request was canceled before receiving a response, so log a cancellation.
380 // Results after receiving a non-error response are logged in the renderer,
381 // if the request is passed to one. If it's a download, or not passed to a
382 // renderer for some other reason, results will not be logged for the
383 // request. The net::OK check may not be necessary - the case where OK is
384 // received without receiving any headers looks broken, anyways.
385 if (!received_response_ && (!status_ || status_->error_code != net::OK)) {
386 RecordLoadHistograms(url_, resource_request_->resource_type,
387 status_ ? status_->error_code : net::ERR_ABORTED);
388 }
kinuko69732972017-05-29 08:50:07389 }
390
arthursonzognib521c6a2018-01-08 12:23:40391 static uint32_t GetURLLoaderOptions(bool is_main_frame) {
Livvie Lin139bf442018-08-10 00:18:54392 uint32_t options = network::mojom::kURLLoadOptionNone;
Makoto Shimazu34ab40c2018-08-23 04:32:03393
394 // Ensure that Mime sniffing works.
395 options |= network::mojom::kURLLoadOptionSniffMimeType;
396
Livvie Lin139bf442018-08-10 00:18:54397 if (is_main_frame) {
398 // SSLInfo is not needed on subframe responses because users can inspect
399 // only the certificate for the main frame when using the info bubble.
400 options |= network::mojom::kURLLoadOptionSendSSLInfoWithResponse;
John Abd-El-Malekb165dc52018-01-18 17:12:18401 options |= network::mojom::kURLLoadOptionSendSSLInfoForCertificateError;
Livvie Lin139bf442018-08-10 00:18:54402 }
arthursonzognib521c6a2018-01-08 12:23:40403
Makoto Shimazu34ab40c2018-08-23 04:32:03404 if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
arthursonzognib521c6a2018-01-08 12:23:40405 // TODO(arthursonzogni): This is a temporary option. Remove this as soon
406 // as the InterceptingResourceHandler is removed.
407 // See https://crbug.com/791049.
John Abd-El-Malekb165dc52018-01-18 17:12:18408 options |= network::mojom::kURLLoadOptionPauseOnResponseStarted;
arthursonzognib521c6a2018-01-08 12:23:40409 }
410
411 return options;
412 }
413
Makoto Shimazu44c2c3232018-03-30 01:10:20414 SingleRequestURLLoaderFactory::RequestHandler
415 CreateDefaultRequestHandlerForNonNetworkService(
416 net::URLRequestContextGetter* url_request_context_getter,
417 storage::FileSystemContext* upload_file_system_context,
418 ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
Makoto Shimazu684a5ad2018-05-29 08:20:50419 AppCacheNavigationHandleCore* appcache_handle_core,
420 bool was_request_intercepted) const {
Matt Falkenhagen34739112018-07-17 20:36:33421 DCHECK_CURRENTLY_ON(BrowserThread::IO);
422 DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
423 DCHECK(started_);
424
Makoto Shimazu44c2c3232018-03-30 01:10:20425 return base::BindOnce(
426 &URLLoaderRequestController::CreateNonNetworkServiceURLLoader,
427 weak_factory_.GetWeakPtr(),
428 base::Unretained(url_request_context_getter),
429 base::Unretained(upload_file_system_context),
430 std::make_unique<NavigationRequestInfo>(*request_info_),
Makoto Shimazu684a5ad2018-05-29 08:20:50431 // If the request has already been intercepted, the request should not
432 // be intercepted again.
433 // S13nServiceWorker: Requests are intercepted by S13nServiceWorker
434 // before the default request handler when needed, so we never need to
435 // pass |service_worker_navigation_handle_core| here.
Han Leonf1525df2018-07-11 03:47:59436 base::Unretained(
437 blink::ServiceWorkerUtils::IsServicificationEnabled() ||
438 was_request_intercepted
439 ? nullptr
440 : service_worker_navigation_handle_core),
Makoto Shimazu684a5ad2018-05-29 08:20:50441 base::Unretained(was_request_intercepted ? nullptr
442 : appcache_handle_core));
Makoto Shimazu44c2c3232018-03-30 01:10:20443 }
444
arthursonzogni2695d04d2017-12-12 08:39:01445 void CreateNonNetworkServiceURLLoader(
446 net::URLRequestContextGetter* url_request_context_getter,
447 storage::FileSystemContext* upload_file_system_context,
448 std::unique_ptr<NavigationRequestInfo> request_info,
arthursonzogni2695d04d2017-12-12 08:39:01449 ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
450 AppCacheNavigationHandleCore* appcache_handle_core,
Matt Falkenhagen43765122018-08-22 19:37:22451 const network::ResourceRequest& /* resource_request */,
John Abd-El-Malekb165dc52018-01-18 17:12:18452 network::mojom::URLLoaderRequest url_loader,
453 network::mojom::URLLoaderClientPtr url_loader_client) {
Matt Falkenhagen43765122018-08-22 19:37:22454 // |resource_request| is unused here. Its info may not be the same as
455 // |request_info|, because URLLoaderThrottles may have rewritten it. We
456 // don't propagate the fields to |request_info| here because the request
457 // will usually go to ResourceDispatcherHost which does its own request
458 // modification independent of URLLoaderThrottles.
Matt Falkenhagen34739112018-07-17 20:36:33459 DCHECK_CURRENTLY_ON(BrowserThread::IO);
460 DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
461 DCHECK(started_);
Matt Falkenhagend2867e82018-07-04 08:26:38462
Tsuyoshi Horob8d512a2018-01-25 17:01:59463 default_loader_used_ = true;
Tsuyoshi Horo46f5fff2018-05-10 12:33:35464 if (signed_exchange_utils::IsSignedExchangeHandlingEnabled()) {
Matt Falkenhagen43765122018-08-22 19:37:22465 // TODO(falken): Understand and add a comment about why
466 // SignedExchangeRequestHandler is the only interceptor being added here.
Kinuko Yasudabe4ad292018-07-06 01:33:39467 DCHECK(!network_loader_factory_);
Tsuyoshi Horo561163b2018-03-27 03:11:23468 // It is safe to pass the callback of CreateURLLoaderThrottles with the
Tsuyoshi Horo70014ad2018-02-14 11:20:14469 // unretained |this|, because the passed callback will be used by a
470 // SignedExchangeHandler which is indirectly owned by |this| until its
471 // header is verified and parsed, that's where the getter is used.
Kunihiko Sakamotoe6aa22e2018-06-15 03:26:55472 interceptors_.push_back(std::make_unique<SignedExchangeRequestHandler>(
Tsuyoshi Horo70014ad2018-02-14 11:20:14473 url::Origin::Create(request_info->common_params.url),
Tsuyoshi Horo32b51f12018-05-09 17:58:46474 request_info->common_params.url,
Kinuko Yasuda32a25652018-02-19 08:14:25475 GetURLLoaderOptions(request_info->is_main_frame),
Tsuyoshi Horocdbb4902018-04-12 06:09:14476 request_info->frame_tree_node_id,
Tsuyoshi Horo32b51f12018-05-09 17:58:46477 request_info->devtools_navigation_token,
Tsuyoshi Horob8d381182018-06-19 10:07:29478 request_info->devtools_frame_token, request_info->report_raw_headers,
Tsuyoshi Horo6e6782d2018-06-07 02:32:47479 request_info->begin_params->load_flags,
Tsuyoshi Horo70014ad2018-02-14 11:20:14480 base::MakeRefCounted<
481 SignedExchangeURLLoaderFactoryForNonNetworkService>(
482 resource_context_, url_request_context_getter),
483 base::BindRepeating(
484 &URLLoaderRequestController::CreateURLLoaderThrottles,
John Abd-El-Malek9ee2a712018-08-24 19:50:45485 base::Unretained(this))));
Tsuyoshi Horob8d512a2018-01-25 17:01:59486 }
487
John Abd-El-Malekdb3a13b2018-05-01 17:52:02488 uint32_t options = GetURLLoaderOptions(request_info->is_main_frame);
489
490 bool intercepted = false;
491 if (g_interceptor.Get()) {
492 intercepted = g_interceptor.Get().Run(
493 &url_loader, frame_tree_node_id_, 0 /* request_id */, options,
494 *resource_request_.get(), &url_loader_client,
495 net::MutableNetworkTrafficAnnotationTag(
496 kNavigationUrlLoaderTrafficAnnotation));
497 }
498
arthursonzogni2695d04d2017-12-12 08:39:01499 // The ResourceDispatcherHostImpl can be null in unit tests.
John Abd-El-Malekdb3a13b2018-05-01 17:52:02500 if (!intercepted && ResourceDispatcherHostImpl::Get()) {
arthursonzogni2695d04d2017-12-12 08:39:01501 ResourceDispatcherHostImpl::Get()->BeginNavigationRequest(
502 resource_context_, url_request_context_getter->GetURLRequestContext(),
503 upload_file_system_context, *request_info,
arthursonzogni662d723c2018-04-24 16:13:22504 std::move(navigation_ui_data_), std::move(url_loader_client),
arthursonzogni2695d04d2017-12-12 08:39:01505 std::move(url_loader), service_worker_navigation_handle_core,
Makoto Shimazuff60c1412018-06-19 06:17:33506 appcache_handle_core, options, global_request_id_);
arthursonzogni2695d04d2017-12-12 08:39:01507 }
508
509 // TODO(arthursonzogni): Detect when the ResourceDispatcherHost didn't
510 // create a URLLoader. When it doesn't, do not send OnRequestStarted().
Eric Seckler8652dcd52018-09-20 10:42:28511 base::PostTaskWithTraits(
512 FROM_HERE, {BrowserThread::UI},
arthursonzogni1fd60e62018-05-09 15:57:32513 base::BindOnce(&NavigationURLLoaderImpl::OnRequestStarted, owner_,
514 base::TimeTicks::Now()));
arthursonzogni2695d04d2017-12-12 08:39:01515 }
516
517 // TODO(arthursonzogni): See if this could eventually be unified with Start().
518 void StartWithoutNetworkService(
519 net::URLRequestContextGetter* url_request_context_getter,
520 storage::FileSystemContext* upload_file_system_context,
521 ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
522 AppCacheNavigationHandleCore* appcache_handle_core,
523 std::unique_ptr<NavigationRequestInfo> request_info,
524 std::unique_ptr<NavigationUIData> navigation_ui_data) {
Matt Falkenhagen34739112018-07-17 20:36:33525 DCHECK_CURRENTLY_ON(BrowserThread::IO);
526 DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
527 DCHECK(!started_);
arthursonzogni2695d04d2017-12-12 08:39:01528 started_ = true;
Makoto Shimazu44c2c3232018-03-30 01:10:20529 request_info_ = std::move(request_info);
530 frame_tree_node_id_ = request_info_->frame_tree_node_id;
Yuzhu Shencb3011f62018-02-08 02:51:50531 web_contents_getter_ = base::BindRepeating(
Yuzhu Shen9508fc72018-02-08 23:18:59532 &GetWebContentsFromFrameTreeNodeID, frame_tree_node_id_);
Makoto Shimazu44c2c3232018-03-30 01:10:20533 navigation_ui_data_ = std::move(navigation_ui_data);
Makoto Shimazuff60c1412018-06-19 06:17:33534 // The ResourceDispatcherHostImpl can be null in unit tests.
535 ResourceDispatcherHostImpl* rph = ResourceDispatcherHostImpl::Get();
536 if (rph)
537 global_request_id_ = rph->MakeGlobalRequestID();
538
Makoto Shimazu44c2c3232018-03-30 01:10:20539 default_request_handler_factory_ = base::BindRepeating(
540 &URLLoaderRequestController::
541 CreateDefaultRequestHandlerForNonNetworkService,
542 // base::Unretained(this) is safe since
543 // |default_request_handler_factory_| could be called only from |this|.
544 base::Unretained(this), base::Unretained(url_request_context_getter),
545 base::Unretained(upload_file_system_context),
arthursonzogni2695d04d2017-12-12 08:39:01546 base::Unretained(service_worker_navigation_handle_core),
547 base::Unretained(appcache_handle_core));
548
Marijn Kruisselbrink8a7fd102018-06-05 17:30:39549 // Requests to Blob scheme won't get redirected to/from other schemes
550 // or be intercepted, so we just let it go here.
551 if (request_info_->common_params.url.SchemeIsBlob() &&
552 request_info_->blob_url_loader_factory) {
553 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
554 network::SharedURLLoaderFactory::Create(
555 std::move(request_info_->blob_url_loader_factory)),
556 CreateURLLoaderThrottles(), -1 /* routing_id */, 0 /* request_id? */,
557 network::mojom::kURLLoadOptionNone, resource_request_.get(), this,
558 kNavigationUrlLoaderTrafficAnnotation,
559 base::ThreadTaskRunnerHandle::Get());
560 return;
561 }
562
Makoto Shimazu44c2c3232018-03-30 01:10:20563 // If S13nServiceWorker is disabled, just use
564 // |default_request_handler_factory_| and return. The non network service
565 // request handling goes through ResourceDispatcherHost which has legacy
566 // hooks for service worker (ServiceWorkerRequestInterceptor), so no service
567 // worker interception is needed here.
Han Leonf1525df2018-07-11 03:47:59568 if (!blink::ServiceWorkerUtils::IsServicificationEnabled() ||
Makoto Shimazu44c2c3232018-03-30 01:10:20569 !service_worker_navigation_handle_core) {
570 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
571 base::MakeRefCounted<SingleRequestURLLoaderFactory>(
Makoto Shimazu684a5ad2018-05-29 08:20:50572 default_request_handler_factory_.Run(
573 false /* was_request_intercepted */)),
Makoto Shimazu44c2c3232018-03-30 01:10:20574 CreateURLLoaderThrottles(), -1 /* routing_id */, 0 /* request_id */,
575 network::mojom::kURLLoadOptionNone, resource_request_.get(),
576 this /* client */, kNavigationUrlLoaderTrafficAnnotation,
577 base::ThreadTaskRunnerHandle::Get());
578 return;
579 }
580
581 // Otherwise, if S13nServiceWorker is enabled, create an interceptor so
582 // S13nServiceWorker has a chance to intercept the request.
583 std::unique_ptr<NavigationLoaderInterceptor> service_worker_interceptor =
584 CreateServiceWorkerInterceptor(*request_info_,
585 service_worker_navigation_handle_core);
586 // If an interceptor is not created for some reasons (e.g. the origin is not
587 // secure), we no longer have to go through the rest of the network service
588 // code.
589 if (!service_worker_interceptor) {
590 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
591 base::MakeRefCounted<SingleRequestURLLoaderFactory>(
Makoto Shimazu684a5ad2018-05-29 08:20:50592 default_request_handler_factory_.Run(
593 false /* was_request_intercepted */)),
Makoto Shimazu44c2c3232018-03-30 01:10:20594 CreateURLLoaderThrottles(), -1 /* routing_id */, 0 /* request_id */,
595 network::mojom::kURLLoadOptionNone, resource_request_.get(),
596 this /* client */, kNavigationUrlLoaderTrafficAnnotation,
597 base::ThreadTaskRunnerHandle::Get());
598 return;
599 }
600
601 interceptors_.push_back(std::move(service_worker_interceptor));
602
Makoto Shimazu44c2c3232018-03-30 01:10:20603 Restart();
arthursonzogni2695d04d2017-12-12 08:39:01604 }
605
kinuko69732972017-05-29 08:50:07606 void Start(
Kinuko Yasudabe4ad292018-07-06 01:33:39607 std::unique_ptr<network::SharedURLLoaderFactoryInfo>
608 network_loader_factory_info,
kinuko69732972017-05-29 08:50:07609 ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
610 AppCacheNavigationHandleCore* appcache_handle_core,
611 std::unique_ptr<NavigationRequestInfo> request_info,
John Abd-El-Malekeb1a5382018-01-05 16:58:00612 std::unique_ptr<NavigationUIData> navigation_ui_data,
John Abd-El-Malekb165dc52018-01-18 17:12:18613 network::mojom::URLLoaderFactoryPtrInfo factory_for_webui,
John Abd-El-Malek576c6132017-11-04 00:33:58614 int frame_tree_node_id,
kinuko69732972017-05-29 08:50:07615 std::unique_ptr<service_manager::Connector> connector) {
Matt Falkenhagen34739112018-07-17 20:36:33616 DCHECK_CURRENTLY_ON(BrowserThread::IO);
617 DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
618 DCHECK(!started_);
arthursonzogni40db5f52018-01-08 16:38:49619 global_request_id_ = MakeGlobalRequestID();
John Abd-El-Malek576c6132017-11-04 00:33:58620 frame_tree_node_id_ = frame_tree_node_id;
Alex Clarke1e08882b32017-10-06 14:22:40621 started_ = true;
John Abd-El-Malek576c6132017-11-04 00:33:58622 web_contents_getter_ =
623 base::Bind(&GetWebContentsFromFrameTreeNodeID, frame_tree_node_id);
John Abd-El-Malekeb1a5382018-01-05 16:58:00624 navigation_ui_data_ = std::move(navigation_ui_data);
kinuko69732972017-05-29 08:50:07625
John Abd-El-Malekc9dd0b42018-10-09 23:33:47626 base::PostTaskWithTraits(
627 FROM_HERE, {BrowserThread::UI},
628 base::BindOnce(&NavigationURLLoaderImpl::OnRequestStarted, owner_,
629 base::TimeTicks::Now()));
630
Kinuko Yasudabe4ad292018-07-06 01:33:39631 DCHECK(network_loader_factory_info);
632 network_loader_factory_ = network::SharedURLLoaderFactory::Create(
633 std::move(network_loader_factory_info));
634
kinuko69732972017-05-29 08:50:07635 if (resource_request_->request_body) {
mmenkeed44e6c2017-06-28 21:13:32636 GetBodyBlobDataHandles(resource_request_->request_body.get(),
637 resource_context_, &blob_handles_);
kinuko69732972017-05-29 08:50:07638 }
639
640 // Requests to WebUI scheme won't get redirected to/from other schemes
641 // or be intercepted, so we just let it go here.
642 if (factory_for_webui.is_valid()) {
yzshenefcb7c72017-06-16 23:12:30643 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
Antonio Gomes9cdc09a2018-05-07 23:24:26644 base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
Yuzhu Shend87986f2018-01-17 22:16:37645 std::move(factory_for_webui)),
Ken Rockot5f734e32018-06-13 01:41:03646 CreateURLLoaderThrottles(), 0 /* routing_id */,
647 global_request_id_.request_id, network::mojom::kURLLoadOptionNone,
648 resource_request_.get(), this, kNavigationUrlLoaderTrafficAnnotation,
Hajime Hoshif5ef35262017-11-28 19:13:00649 base::ThreadTaskRunnerHandle::Get());
kinuko69732972017-05-29 08:50:07650 return;
651 }
652
Marijn Kruisselbrink07bf59d52018-04-03 21:50:25653 // Requests to Blob scheme won't get redirected to/from other schemes
654 // or be intercepted, so we just let it go here.
655 if (request_info->common_params.url.SchemeIsBlob() &&
656 request_info->blob_url_loader_factory) {
657 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
658 network::SharedURLLoaderFactory::Create(
659 std::move(request_info->blob_url_loader_factory)),
Ken Rockot5f734e32018-06-13 01:41:03660 CreateURLLoaderThrottles(), 0 /* routing_id */,
661 global_request_id_.request_id, network::mojom::kURLLoadOptionNone,
662 resource_request_.get(), this, kNavigationUrlLoaderTrafficAnnotation,
Marijn Kruisselbrink07bf59d52018-04-03 21:50:25663 base::ThreadTaskRunnerHandle::Get());
664 return;
665 }
666
kinuko69732972017-05-29 08:50:07667 if (service_worker_navigation_handle_core) {
Kinuko Yasuda7f3e1722018-03-26 08:58:58668 std::unique_ptr<NavigationLoaderInterceptor> service_worker_interceptor =
Makoto Shimazu44c2c3232018-03-30 01:10:20669 CreateServiceWorkerInterceptor(*request_info,
670 service_worker_navigation_handle_core);
Kinuko Yasuda7f3e1722018-03-26 08:58:58671 if (service_worker_interceptor)
672 interceptors_.push_back(std::move(service_worker_interceptor));
kinuko69732972017-05-29 08:50:07673 }
674
675 if (appcache_handle_core) {
Kinuko Yasuda7f3e1722018-03-26 08:58:58676 std::unique_ptr<NavigationLoaderInterceptor> appcache_interceptor =
Hiroki Nakagawaff43e4472018-07-26 07:06:46677 AppCacheRequestHandler::InitializeForMainResourceNetworkService(
678 *resource_request_, appcache_handle_core->host()->GetWeakPtr(),
Kinuko Yasudabe4ad292018-07-06 01:33:39679 network_loader_factory_);
Kinuko Yasuda7f3e1722018-03-26 08:58:58680 if (appcache_interceptor)
681 interceptors_.push_back(std::move(appcache_interceptor));
kinuko69732972017-05-29 08:50:07682 }
683
Tsuyoshi Horo46f5fff2018-05-10 12:33:35684 if (signed_exchange_utils::IsSignedExchangeHandlingEnabled()) {
Tsuyoshi Horo561163b2018-03-27 03:11:23685 // It is safe to pass the callback of CreateURLLoaderThrottles with the
Tsuyoshi Horo70014ad2018-02-14 11:20:14686 // unretained |this|, because the passed callback will be used by a
687 // SignedExchangeHandler which is indirectly owned by |this| until its
688 // header is verified and parsed, that's where the getter is used.
Kunihiko Sakamotoe6aa22e2018-06-15 03:26:55689 interceptors_.push_back(std::make_unique<SignedExchangeRequestHandler>(
Tsuyoshi Horo70014ad2018-02-14 11:20:14690 url::Origin::Create(request_info->common_params.url),
Tsuyoshi Horo32b51f12018-05-09 17:58:46691 request_info->common_params.url,
Kinuko Yasuda32a25652018-02-19 08:14:25692 GetURLLoaderOptions(request_info->is_main_frame),
Tsuyoshi Horocdbb4902018-04-12 06:09:14693 request_info->frame_tree_node_id,
Tsuyoshi Horo32b51f12018-05-09 17:58:46694 request_info->devtools_navigation_token,
Tsuyoshi Horob8d381182018-06-19 10:07:29695 request_info->devtools_frame_token, request_info->report_raw_headers,
Kinuko Yasudabe4ad292018-07-06 01:33:39696 request_info->begin_params->load_flags, network_loader_factory_,
Tsuyoshi Horo70014ad2018-02-14 11:20:14697 base::BindRepeating(
698 &URLLoaderRequestController::CreateURLLoaderThrottles,
John Abd-El-Malek9ee2a712018-08-24 19:50:45699 base::Unretained(this))));
Tsuyoshi Horob8d512a2018-01-25 17:01:59700 }
701
Jian Li18e29242018-05-10 22:25:12702 std::vector<std::unique_ptr<URLLoaderRequestInterceptor>>
703 browser_interceptors = GetContentClient()
704 ->browser()
705 ->WillCreateURLLoaderRequestInterceptors(
706 navigation_ui_data_.get(),
707 request_info->frame_tree_node_id);
708 if (!browser_interceptors.empty()) {
709 for (auto& browser_interceptor : browser_interceptors) {
710 interceptors_.push_back(
711 std::make_unique<NavigationLoaderInterceptorBrowserContainer>(
712 std::move(browser_interceptor)));
713 }
714 }
715
yzshenefcb7c72017-06-16 23:12:30716 Restart();
kinuko69732972017-05-29 08:50:07717 }
718
Michael Nordman2431f5f2017-09-13 04:58:15719 // This could be called multiple times to follow a chain of redirects.
yzshenefcb7c72017-06-16 23:12:30720 void Restart() {
Kinuko Yasuda7f3e1722018-03-26 08:58:58721 DCHECK(IsLoaderInterceptionEnabled());
Tsuyoshi Horo5204c872017-09-21 16:28:17722 // Clear |url_loader_| if it's not the default one (network). This allows
723 // the restarted request to use a new loader, instead of, e.g., reusing the
724 // AppCache or service worker loader. For an optimization, we keep and reuse
Kinuko Yasuda7f3e1722018-03-26 08:58:58725 // the default url loader if the all |interceptors_| doesn't handle the
Clark DuVallbf7722f2018-08-03 18:03:33726 // redirected request. If the network service is enabled, only certain
727 // schemes are handled by the default URL loader. We need to make sure the
728 // redirected URL is a handled scheme, otherwise reset the loader so the
729 // correct non-network service loader can be used.
730 if (!default_loader_used_ ||
731 (base::FeatureList::IsEnabled(network::features::kNetworkService) &&
732 !IsURLHandledByDefaultLoader(resource_request_->url))) {
Tsuyoshi Horo5204c872017-09-21 16:28:17733 url_loader_.reset();
Clark DuVallbf7722f2018-08-03 18:03:33734 }
Kinuko Yasuda7f3e1722018-03-26 08:58:58735 interceptor_index_ = 0;
anantab9800e52017-07-29 18:04:13736 received_response_ = false;
Kinuko Yasuda7f3e1722018-03-26 08:58:58737 MaybeStartLoader(nullptr /* interceptor */,
738 {} /* single_request_handler */);
kinuko69732972017-05-29 08:50:07739 }
740
Kinuko Yasuda7f3e1722018-03-26 08:58:58741 // |interceptor| is non-null if this is called by one of the interceptors
742 // (via a LoaderCallback).
743 // |single_request_handler| is the RequestHandler given by the |interceptor|,
744 // non-null if the interceptor wants to handle the request.
Ken Rockot387ddd5a2018-01-30 19:18:40745 void MaybeStartLoader(
Kinuko Yasuda7f3e1722018-03-26 08:58:58746 NavigationLoaderInterceptor* interceptor,
Ken Rockot387ddd5a2018-01-30 19:18:40747 SingleRequestURLLoaderFactory::RequestHandler single_request_handler) {
Matt Falkenhagen34739112018-07-17 20:36:33748 DCHECK_CURRENTLY_ON(BrowserThread::IO);
749 DCHECK(IsLoaderInterceptionEnabled());
750 DCHECK(started_);
751
Ken Rockot387ddd5a2018-01-30 19:18:40752 if (single_request_handler) {
Kinuko Yasuda7f3e1722018-03-26 08:58:58753 // |interceptor| wants to handle the request with
754 // |single_request_handler|.
755 DCHECK(interceptor);
Matt Falkenhagen43765122018-08-22 19:37:22756
757 std::vector<std::unique_ptr<URLLoaderThrottle>> throttles =
Makoto Shimazu21950e82018-08-02 12:37:14758 CreateURLLoaderThrottles();
Matt Falkenhagen43765122018-08-22 19:37:22759 // Intercepted requests need MimeSniffingThrottle to do mime sniffing.
760 // Non-intercepted requests usually go through the regular network
761 // URLLoader, which does mime sniffing.
Makoto Shimazu21950e82018-08-02 12:37:14762 throttles.push_back(std::make_unique<MimeSniffingThrottle>());
Matt Falkenhagen43765122018-08-22 19:37:22763
Michael Nordman2431f5f2017-09-13 04:58:15764 default_loader_used_ = false;
yzshenefcb7c72017-06-16 23:12:30765 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
Ken Rockot387ddd5a2018-01-30 19:18:40766 base::MakeRefCounted<SingleRequestURLLoaderFactory>(
767 std::move(single_request_handler)),
Makoto Shimazu21950e82018-08-02 12:37:14768 std::move(throttles), frame_tree_node_id_,
Ken Rockot5f734e32018-06-13 01:41:03769 global_request_id_.request_id, network::mojom::kURLLoadOptionNone,
770 resource_request_.get(), this, kNavigationUrlLoaderTrafficAnnotation,
Hajime Hoshif5ef35262017-11-28 19:13:00771 base::ThreadTaskRunnerHandle::Get());
anantae60d1d42017-06-20 04:16:27772
Kinuko Yasuda250577c2017-10-29 02:51:24773 subresource_loader_params_ =
Kinuko Yasuda7f3e1722018-03-26 08:58:58774 interceptor->MaybeCreateSubresourceLoaderParams();
Kinuko Yasuda8757204a2017-11-04 07:50:13775
kinuko69732972017-05-29 08:50:07776 return;
777 }
778
Kinuko Yasuda7f3e1722018-03-26 08:58:58779 // Before falling back to the next interceptor, see if |interceptor| still
780 // wants to give additional info to the frame for subresource loading. In
781 // that case we will just fall back to the default loader (i.e. won't go on
782 // to the next interceptors) but send the subresource_loader_params to the
783 // child process. This is necessary for correctness in the cases where, e.g.
Matt Falkenhagen43765122018-08-22 19:37:22784 // there's a controlling service worker that doesn't have a fetch event
785 // handler so it doesn't intercept requests. In that case we still want to
786 // skip AppCache.
Kinuko Yasuda7f3e1722018-03-26 08:58:58787 if (interceptor) {
Kinuko Yasuda8757204a2017-11-04 07:50:13788 subresource_loader_params_ =
Kinuko Yasuda7f3e1722018-03-26 08:58:58789 interceptor->MaybeCreateSubresourceLoaderParams();
Kinuko Yasuda8757204a2017-11-04 07:50:13790
791 // If non-null |subresource_loader_params_| is returned, make sure
Kinuko Yasuda7f3e1722018-03-26 08:58:58792 // we skip the next interceptors.
Kinuko Yasuda8757204a2017-11-04 07:50:13793 if (subresource_loader_params_)
Kinuko Yasuda7f3e1722018-03-26 08:58:58794 interceptor_index_ = interceptors_.size();
Kinuko Yasuda8757204a2017-11-04 07:50:13795 }
796
Kinuko Yasuda7f3e1722018-03-26 08:58:58797 // See if the next interceptor wants to handle the request.
798 if (interceptor_index_ < interceptors_.size()) {
799 auto* next_interceptor = interceptors_[interceptor_index_++].get();
800 next_interceptor->MaybeCreateLoader(
kinuko69732972017-05-29 08:50:07801 *resource_request_, resource_context_,
802 base::BindOnce(&URLLoaderRequestController::MaybeStartLoader,
Matt Falkenhagen43765122018-08-22 19:37:22803 base::Unretained(this), next_interceptor),
804 base::BindOnce(
805 &URLLoaderRequestController::FallbackToNonInterceptedRequest,
806 base::Unretained(this)));
kinuko69732972017-05-29 08:50:07807 return;
808 }
809
Matt Falkenhagen43765122018-08-22 19:37:22810 // If we already have the default |url_loader_| we must come here after a
Matt Falkenhagencc3e7e52018-08-28 06:23:48811 // redirect. No interceptors wanted to intercept the redirected request, so
Matt Falkenhagen43765122018-08-22 19:37:22812 // let the loader just follow the redirect.
Michael Nordman2431f5f2017-09-13 04:58:15813 if (url_loader_) {
814 DCHECK(!redirect_info_.new_url.is_empty());
Chong Zhang7607f1f2018-06-01 20:52:20815 url_loader_->FollowRedirect(
816 std::move(url_loader_modified_request_headers_));
Michael Nordman2431f5f2017-09-13 04:58:15817 return;
818 }
819
Matt Falkenhagen43765122018-08-22 19:37:22820 // No interceptors wanted to handle this request.
Matt Falkenhagencc3e7e52018-08-28 06:23:48821 uint32_t options = network::mojom::kURLLoadOptionNone;
822 scoped_refptr<network::SharedURLLoaderFactory> factory =
823 PrepareForNonInterceptedRequest(&options);
824 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
825 std::move(factory), CreateURLLoaderThrottles(), frame_tree_node_id_,
826 global_request_id_.request_id, options, resource_request_.get(),
827 this /* client */, kNavigationUrlLoaderTrafficAnnotation,
828 base::ThreadTaskRunnerHandle::Get());
Matt Falkenhagen43765122018-08-22 19:37:22829 }
Makoto Shimazu44c2c3232018-03-30 01:10:20830
Matt Falkenhagen43765122018-08-22 19:37:22831 // This is the |fallback_callback| passed to
832 // NavigationLoaderInterceptor::MaybeCreateLoader. It allows an interceptor
833 // to initially elect to handle a request, and later decide to fallback to
Kunihiko Sakamoto578a9592018-10-09 03:17:27834 // the default behavior. This is needed for service worker network fallback
835 // and signed exchange (SXG) fallback redirect.
Matt Falkenhagen43765122018-08-22 19:37:22836 void FallbackToNonInterceptedRequest(bool reset_subresource_loader_params) {
837 if (reset_subresource_loader_params)
838 subresource_loader_params_.reset();
839
Matt Falkenhagencc3e7e52018-08-28 06:23:48840 // Non-NetworkService:
841 // Cancel state on ResourceDispatcherHostImpl so it doesn't complain about
842 // reusing the request_id after redirects. Otherwise the following sequence
843 // can happen:
Kunihiko Sakamoto578a9592018-10-09 03:17:27844 // case 1. RDHI Start(request_id) -> Redirect -> SW interception -> SW
845 // fallback to network -> RDHI Start(request_id).
846 // case 2. RDHI Start(request_id) -> SXG interception -> SXG fallback to
847 // network -> RDHI Start(request_id).
Matt Falkenhagencc3e7e52018-08-28 06:23:48848 if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
849 DCHECK(ResourceDispatcherHostImpl::Get());
850 ResourceDispatcherHostImpl::Get()->CancelRequest(
851 global_request_id_.child_id, global_request_id_.request_id);
Matt Falkenhagen43765122018-08-22 19:37:22852 }
853
Matt Falkenhagencc3e7e52018-08-28 06:23:48854 uint32_t options = network::mojom::kURLLoadOptionNone;
855 scoped_refptr<network::SharedURLLoaderFactory> factory =
856 PrepareForNonInterceptedRequest(&options);
Kunihiko Sakamoto578a9592018-10-09 03:17:27857 if (url_loader_) {
858 // |url_loader_| is using the factory for the interceptor that decided to
859 // fallback, so restart it with the non-interceptor factory.
860 url_loader_->RestartWithFactory(std::move(factory), options);
861 } else {
862 // In SXG cases we don't have |url_loader_| because it was reset when the
863 // SXG interceptor intercepted the response in
864 // MaybeCreateLoaderForResponse.
865 DCHECK(response_loader_binding_);
866 response_loader_binding_.Close();
867 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
868 std::move(factory), CreateURLLoaderThrottles(), frame_tree_node_id_,
869 global_request_id_.request_id, options, resource_request_.get(),
870 this /* client */, kNavigationUrlLoaderTrafficAnnotation,
871 base::ThreadTaskRunnerHandle::Get());
872 }
Matt Falkenhagen43765122018-08-22 19:37:22873 }
874
Matt Falkenhagencc3e7e52018-08-28 06:23:48875 scoped_refptr<network::SharedURLLoaderFactory>
876 PrepareForNonInterceptedRequest(uint32_t* out_options) {
Makoto Shimazu44c2c3232018-03-30 01:10:20877 // If NetworkService is not enabled (which means we come here because one of
878 // the loader interceptors is enabled), use the default request handler
879 // instead of going through the NetworkService path.
880 if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
881 DCHECK(!interceptors_.empty());
882 DCHECK(default_request_handler_factory_);
Kunihiko Sakamoto21ab4ad262018-08-21 10:26:21883 // The only way to come here is to enable ServiceWorkerServicification or
884 // SignedExchange without NetworkService. We know that their request
885 // interceptors have already intercepted and decided not to handle the
Makoto Shimazu684a5ad2018-05-29 08:20:50886 // request.
Kunihiko Sakamoto21ab4ad262018-08-21 10:26:21887 DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled() ||
888 signed_exchange_utils::IsSignedExchangeHandlingEnabled());
Makoto Shimazu44c2c3232018-03-30 01:10:20889 default_loader_used_ = true;
890 // Update |request_info_| when following a redirect.
891 if (url_chain_.size() > 0) {
892 request_info_ = CreateNavigationRequestInfoForRedirect(
893 *request_info_, *resource_request_);
894 }
Matt Falkenhagen43765122018-08-22 19:37:22895
Makoto Shimazu684a5ad2018-05-29 08:20:50896 // When |subresource_loader_params_| has its value, the request should not
897 // be intercepted by any other interceptors since it means that a request
898 // interceptor already intercepted the request and it attached its info to
899 // the request.
Matt Falkenhagen43765122018-08-22 19:37:22900 bool was_request_intercepted = subresource_loader_params_.has_value();
901
Matt Falkenhagencc3e7e52018-08-28 06:23:48902 // TODO(falken): Determine whether GetURLLoaderOptions() can be called
903 // here like below. It looks like |default_request_handler_factory_| just
904 // calls that.
905 *out_options = network::mojom::kURLLoadOptionNone;
906 return base::MakeRefCounted<SingleRequestURLLoaderFactory>(
907 default_request_handler_factory_.Run(was_request_intercepted));
Makoto Shimazu44c2c3232018-03-30 01:10:20908 }
909
Matt Falkenhagen43765122018-08-22 19:37:22910 // TODO(https://crbug.com/796425): We temporarily wrap raw
911 // mojom::URLLoaderFactory pointers into SharedURLLoaderFactory. Need to
912 // further refactor the factory getters to avoid this.
913 scoped_refptr<network::SharedURLLoaderFactory> factory;
914
Clark DuVallbf7722f2018-08-03 18:03:33915 if (!IsURLHandledByDefaultLoader(resource_request_->url)) {
John Abd-El-Maleka67add82018-03-09 18:22:01916 if (known_schemes_.find(resource_request_->url.scheme()) ==
917 known_schemes_.end()) {
918 bool handled = GetContentClient()->browser()->HandleExternalProtocol(
919 resource_request_->url, web_contents_getter_,
920 ChildProcessHost::kInvalidUniqueID, navigation_ui_data_.get(),
921 resource_request_->resource_type == RESOURCE_TYPE_MAIN_FRAME,
922 static_cast<ui::PageTransition>(resource_request_->transition_type),
923 resource_request_->has_user_gesture);
924 factory = base::MakeRefCounted<SingleRequestURLLoaderFactory>(
925 base::BindOnce(UnknownSchemeCallback, handled));
926 } else {
927 network::mojom::URLLoaderFactoryPtr& non_network_factory =
928 non_network_url_loader_factories_[resource_request_->url.scheme()];
929 if (!non_network_factory.is_bound()) {
Eric Seckler8652dcd52018-09-20 10:42:28930 base::PostTaskWithTraits(
931 FROM_HERE, {BrowserThread::UI},
arthursonzogni1fd60e62018-05-09 15:57:32932 base::BindOnce(&NavigationURLLoaderImpl ::
John Abd-El-Maleka67add82018-03-09 18:22:01933 BindNonNetworkURLLoaderFactoryRequest,
934 owner_, frame_tree_node_id_,
935 resource_request_->url,
936 mojo::MakeRequest(&non_network_factory)));
937 }
Antonio Gomes9cdc09a2018-05-07 23:24:26938 factory =
939 base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
940 non_network_factory.get());
Ken Rockot314714c2017-11-05 23:36:24941 }
jam9354af82017-06-03 21:59:41942 } else {
anantab9800e52017-07-29 18:04:13943 default_loader_used_ = true;
Ken Rockota0dfaca12018-02-15 07:26:25944
945 // NOTE: We only support embedders proxying network-service-bound requests
Kinuko Yasuda7f3e1722018-03-26 08:58:58946 // not handled by NavigationLoaderInterceptors above (e.g. Service Worker
947 // or AppCache). Hence this code is only reachable when one of the above
948 // interceptors isn't used and the URL is either a data URL or has a
949 // scheme which is handled by the network service. We explicitly avoid
950 // proxying the data URL case here.
Ken Rockota0dfaca12018-02-15 07:26:25951 if (proxied_factory_request_.is_pending() &&
952 !resource_request_->url.SchemeIs(url::kDataScheme)) {
953 DCHECK(proxied_factory_info_.is_valid());
Chong Zhang70432e32018-03-07 04:43:52954 // We don't worry about reconnection since it's a single navigation.
Kinuko Yasudabe4ad292018-07-06 01:33:39955 network_loader_factory_->Clone(std::move(proxied_factory_request_));
Antonio Gomes9cdc09a2018-05-07 23:24:26956 factory = base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
Ken Rockota0dfaca12018-02-15 07:26:25957 std::move(proxied_factory_info_));
958 } else {
Kinuko Yasudabe4ad292018-07-06 01:33:39959 factory = network_loader_factory_;
Ken Rockota0dfaca12018-02-15 07:26:25960 }
jam9354af82017-06-03 21:59:41961 }
Min Qin83d07872017-10-26 23:22:41962 url_chain_.push_back(resource_request_->url);
Matt Falkenhagencc3e7e52018-08-28 06:23:48963 *out_options = GetURLLoaderOptions(resource_request_->resource_type ==
964 RESOURCE_TYPE_MAIN_FRAME);
965 return factory;
kinuko69732972017-05-29 08:50:07966 }
967
Chong Zhang7607f1f2018-06-01 20:52:20968 void FollowRedirect(
969 const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
yzshenefcb7c72017-06-16 23:12:30970 DCHECK_CURRENTLY_ON(BrowserThread::IO);
Michael Nordman2431f5f2017-09-13 04:58:15971 DCHECK(!redirect_info_.new_url.is_empty());
arthursonzogni2695d04d2017-12-12 08:39:01972
Kinuko Yasuda7f3e1722018-03-26 08:58:58973 if (!IsLoaderInterceptionEnabled()) {
Chong Zhang7607f1f2018-06-01 20:52:20974 url_loader_->FollowRedirect(modified_request_headers);
arthursonzogni2695d04d2017-12-12 08:39:01975 return;
976 }
anantab9800e52017-07-29 18:04:13977
Kinuko Yasuda7f3e1722018-03-26 08:58:58978 // Update |resource_request_| and call Restart to give our |interceptors_| a
979 // chance at handling the new location. If no interceptor wants to take
980 // over, we'll use the existing url_loader to follow the redirect, see
981 // MaybeStartLoader.
Michael Nordman2431f5f2017-09-13 04:58:15982 // TODO(michaeln): This is still WIP and is based on URLRequest::Redirect,
983 // there likely remains more to be done.
984 // a. For subframe navigations, the Origin header may need to be modified
985 // differently?
Michael Nordman2431f5f2017-09-13 04:58:15986
Tsuyoshi Horo9e2ec4df2017-10-16 15:15:55987 bool should_clear_upload = false;
988 net::RedirectUtil::UpdateHttpRequest(
989 resource_request_->url, resource_request_->method, redirect_info_,
Chong Zhang7607f1f2018-06-01 20:52:20990 modified_request_headers, &resource_request_->headers,
991 &should_clear_upload);
Tsuyoshi Horo9e2ec4df2017-10-16 15:15:55992 if (should_clear_upload) {
Michael Nordman2431f5f2017-09-13 04:58:15993 // The request body is no longer applicable.
994 resource_request_->request_body = nullptr;
995 blob_handles_.clear();
996 }
997
Michael Nordman2431f5f2017-09-13 04:58:15998 resource_request_->url = redirect_info_.new_url;
Tsuyoshi Horo9e2ec4df2017-10-16 15:15:55999 resource_request_->method = redirect_info_.new_method;
Michael Nordman2431f5f2017-09-13 04:58:151000 resource_request_->site_for_cookies = redirect_info_.new_site_for_cookies;
1001 resource_request_->referrer = GURL(redirect_info_.new_referrer);
John Abd-El-Malekb77d22fb72017-12-22 17:34:481002 resource_request_->referrer_policy = redirect_info_.new_referrer_policy;
Min Qin83d07872017-10-26 23:22:411003 url_chain_.push_back(redirect_info_.new_url);
Michael Nordman2431f5f2017-09-13 04:58:151004
Chong Zhang7607f1f2018-06-01 20:52:201005 // Need to cache modified headers for |url_loader_| since it doesn't use
1006 // |resource_request_| during redirect.
1007 url_loader_modified_request_headers_ = modified_request_headers;
1008
Tsuyoshi Horo6e5bd032018-09-28 13:11:021009 if (signed_exchange_utils::NeedToCheckRedirectedURLForAcceptHeader()) {
1010 // Currently we send the SignedExchange accept header only for the limited
1011 // origins when SignedHTTPExchangeOriginTrial feature is enabled without
1012 // SignedHTTPExchange feature. We need to put the SignedExchange accept
1013 // header on when redirecting to the origins in the OriginList of
1014 // SignedHTTPExchangeAcceptHeader field trial, and need to remove it when
1015 // redirecting to out of the OriginList.
1016 if (!url_loader_modified_request_headers_)
1017 url_loader_modified_request_headers_ = net::HttpRequestHeaders();
1018 std::string accept_value = network::kFrameAcceptHeader;
1019 if (signed_exchange_utils::ShouldAdvertiseAcceptHeader(
1020 url::Origin::Create(resource_request_->url))) {
1021 DCHECK(!accept_value.empty());
1022 accept_value.append(kAcceptHeaderSignedExchangeSuffix);
1023 }
1024 url_loader_modified_request_headers_->SetHeader(network::kAcceptHeader,
1025 accept_value);
1026 resource_request_->headers.SetHeader(network::kAcceptHeader,
1027 accept_value);
1028 }
1029
Michael Nordman2431f5f2017-09-13 04:58:151030 Restart();
yzshenefcb7c72017-06-16 23:12:301031 }
1032
Kinuko Yasuda250577c2017-10-29 02:51:241033 base::Optional<SubresourceLoaderParams> TakeSubresourceLoaderParams() {
1034 return std::move(subresource_loader_params_);
anantae60d1d42017-06-20 04:16:271035 }
1036
kinuko69732972017-05-29 08:50:071037 private:
John Abd-El-Malekb165dc52018-01-18 17:12:181038 // network::mojom::URLLoaderClient implementation:
Marijn Kruisselbrink9ebd7ba2018-06-11 23:18:041039 void OnReceiveResponse(const network::ResourceResponseHead& head) override {
Matt Menked9cad562018-08-10 21:47:091040 // Record the SCT histogram before checking if anything wants to intercept
1041 // the response, so interceptors like AppCache and extensions can't hide
1042 // values from the histograms.
1043 RecordSCTHistogramIfNeeded(head.ssl_info);
1044
anantab9800e52017-07-29 18:04:131045 received_response_ = true;
arthursonzogni2695d04d2017-12-12 08:39:011046
anantab9800e52017-07-29 18:04:131047 // If the default loader (network) was used to handle the URL load request
Kinuko Yasuda7f3e1722018-03-26 08:58:581048 // we need to see if the interceptors want to potentially create a new
1049 // loader for the response. e.g. AppCache.
anantab9800e52017-07-29 18:04:131050 if (MaybeCreateLoaderForResponse(head))
1051 return;
arthursonzogni3a4ca9f2017-12-07 17:58:341052
John Abd-El-Malekb165dc52018-01-18 17:12:181053 network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints;
John Abd-El-Malekecc6f5f2018-03-02 18:47:391054
1055 // Currently only plugin handlers may intercept the response. Don't treat
1056 // the response as download if it has been handled by plugins.
1057 bool response_intercepted = false;
arthursonzogni3a4ca9f2017-12-07 17:58:341058 if (url_loader_) {
1059 url_loader_client_endpoints = url_loader_->Unbind();
John Abd-El-Malekecc6f5f2018-03-02 18:47:391060 response_intercepted = url_loader_->response_intercepted();
arthursonzogni3a4ca9f2017-12-07 17:58:341061 } else {
John Abd-El-Malekb165dc52018-01-18 17:12:181062 url_loader_client_endpoints =
1063 network::mojom::URLLoaderClientEndpoints::New(
1064 response_url_loader_.PassInterface(),
1065 response_loader_binding_.Unbind());
arthursonzogni3a4ca9f2017-12-07 17:58:341066 }
1067
Matt Menke4f8104c2018-10-01 23:42:521068 // 304 responses should abort the navigation, rather than display the page.
1069 // This needs to be after the URLLoader has been moved to
1070 // |url_loader_client_endpoints| in order to abort the request, to avoid
1071 // receiving unexpected call.
1072 if (head.headers &&
1073 head.headers->response_code() == net::HTTP_NOT_MODIFIED) {
1074 OnComplete(network::URLLoaderCompletionStatus(net::ERR_ABORTED));
1075 return;
1076 }
1077
arthursonzogni40db5f52018-01-08 16:38:491078 bool is_download;
1079 bool is_stream;
Ryan Sturm64315a92018-07-20 06:25:281080 // If there is not an explicit PreviewsState set on the request, turn
1081 // Previews off.
1082 PreviewsState previews_state = PREVIEWS_OFF;
arthursonzogni40db5f52018-01-08 16:38:491083 std::unique_ptr<NavigationData> cloned_navigation_data;
Kenichi Ishibashia7175632018-07-30 02:08:351084
Kinuko Yasuda7f3e1722018-03-26 08:58:581085 if (IsLoaderInterceptionEnabled()) {
Robbie McElratha5adc4e2018-07-03 23:53:091086 bool must_download = download_utils::MustDownload(
Jochen Eisinger7678c8ac2018-05-07 15:47:341087 url_, head.headers.get(), head.mime_type);
John Abd-El-Malek3ebdff862018-04-23 18:57:211088 bool known_mime_type = blink::IsSupportedMimeType(head.mime_type);
1089
Matt Menke2bd72d82018-08-03 15:17:181090 bool is_download_if_not_handled_by_plugin =
1091 !response_intercepted && (must_download || !known_mime_type);
1092
John Abd-El-Malek3ebdff862018-04-23 18:57:211093#if BUILDFLAG(ENABLE_PLUGINS)
1094 if (!response_intercepted && !must_download && !known_mime_type) {
1095 CheckPluginAndContinueOnReceiveResponse(
Marijn Kruisselbrink9ebd7ba2018-06-11 23:18:041096 head, std::move(url_loader_client_endpoints),
Matt Menke2bd72d82018-08-03 15:17:181097 is_download_if_not_handled_by_plugin, std::vector<WebPluginInfo>());
John Abd-El-Malek3ebdff862018-04-23 18:57:211098 return;
1099 }
1100#endif
1101
Matt Menke2bd72d82018-08-03 15:17:181102 is_download = is_download_if_not_handled_by_plugin;
arthursonzogni40db5f52018-01-08 16:38:491103 is_stream = false;
arthursonzognib1de19fa2018-04-03 19:55:101104
Kenichi Ishibashia7175632018-07-30 02:08:351105 // If NetworkService is on, or an interceptor handled the request, the
1106 // request doesn't use ResourceDispatcherHost so
1107 // CallOnReceivedResponse and return here.
1108 if (base::FeatureList::IsEnabled(network::features::kNetworkService) ||
1109 !default_loader_used_) {
1110 CallOnReceivedResponse(head, std::move(url_loader_client_endpoints),
1111 std::move(cloned_navigation_data), is_download,
1112 is_stream, previews_state);
1113 return;
arthursonzognib950d902018-02-08 09:27:131114 }
arthursonzogni40db5f52018-01-08 16:38:491115 }
1116
Kenichi Ishibashia7175632018-07-30 02:08:351117 // NetworkService is off and an interceptor didn't handle the request,
1118 // so it went to ResourceDispatcherHost.
1119 ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get();
1120 net::URLRequest* url_request = rdh->GetURLRequest(global_request_id_);
1121
1122 // The |url_request| maybe have been removed from the resource dispatcher
1123 // host during the time it took for OnReceiveResponse() to be received.
1124 if (url_request) {
1125 ResourceRequestInfoImpl* info =
1126 ResourceRequestInfoImpl::ForRequest(url_request);
1127 is_download = !response_intercepted && info->IsDownload();
1128 is_stream = info->is_stream();
1129 previews_state = info->GetPreviewsState();
1130 if (rdh->delegate()) {
1131 NavigationData* navigation_data =
1132 rdh->delegate()->GetNavigationData(url_request);
1133
1134 // Clone the embedder's NavigationData before moving it to the UI
1135 // thread.
1136 if (navigation_data)
1137 cloned_navigation_data = navigation_data->Clone();
1138 }
1139
1140 // non-S13nServiceWorker:
1141 // This is similar to what is done in
1142 // ServiceWorkerControlleeHandler::MaybeCreateSubresourceLoaderParams()
1143 // (which is used when S13nServiceWorker is on). It takes the matching
1144 // ControllerServiceWorkerInfo (if any) associated with the request. It
1145 // will be sent to the renderer process and used to intercept requests.
1146 ServiceWorkerProviderHost* sw_provider_host =
1147 ServiceWorkerRequestHandler::GetProviderHost(url_request);
1148 if (sw_provider_host && sw_provider_host->controller()) {
1149 DCHECK(!blink::ServiceWorkerUtils::IsServicificationEnabled());
1150 subresource_loader_params_ = SubresourceLoaderParams();
1151 subresource_loader_params_->controller_service_worker_info =
1152 mojom::ControllerServiceWorkerInfo::New();
1153 subresource_loader_params_->controller_service_worker_info->mode =
1154 sw_provider_host->GetControllerMode();
1155 base::WeakPtr<ServiceWorkerObjectHost> sw_object_host =
1156 sw_provider_host->GetOrCreateServiceWorkerObjectHost(
1157 sw_provider_host->controller());
1158 if (sw_object_host) {
1159 subresource_loader_params_->controller_service_worker_object_host =
1160 sw_object_host;
1161 subresource_loader_params_->controller_service_worker_info
1162 ->object_info = sw_object_host->CreateIncompleteObjectInfo();
1163 }
1164 }
1165 } else {
1166 is_download = is_stream = false;
1167 }
1168
Marijn Kruisselbrink9ebd7ba2018-06-11 23:18:041169 CallOnReceivedResponse(head, std::move(url_loader_client_endpoints),
John Abd-El-Malek3ebdff862018-04-23 18:57:211170 std::move(cloned_navigation_data), is_download,
Ryan Sturm64315a92018-07-20 06:25:281171 is_stream, previews_state);
John Abd-El-Malek3ebdff862018-04-23 18:57:211172 }
1173
1174#if BUILDFLAG(ENABLE_PLUGINS)
1175 void CheckPluginAndContinueOnReceiveResponse(
1176 const network::ResourceResponseHead& head,
John Abd-El-Malek3ebdff862018-04-23 18:57:211177 network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
Matt Menke2bd72d82018-08-03 15:17:181178 bool is_download_if_not_handled_by_plugin,
John Abd-El-Malek3ebdff862018-04-23 18:57:211179 const std::vector<WebPluginInfo>& plugins) {
1180 bool stale;
1181 WebPluginInfo plugin;
1182 // It's ok to pass -1 for the render process and frame ID since that's
1183 // only used for plugin overridding. We don't actually care if we get an
1184 // overridden plugin or not, since all we care about is the presence of a
1185 // plugin. Note that this is what the MimeSniffingResourceHandler code
1186 // path does as well for navigations.
1187 bool has_plugin = PluginService::GetInstance()->GetPluginInfo(
1188 -1 /* render_process_id */, -1 /* render_frame_id */, resource_context_,
1189 resource_request_->url, url::Origin(), head.mime_type,
1190 false /* allow_wildcard */, &stale, &plugin, nullptr);
1191
1192 if (stale) {
1193 // Refresh the plugins asynchronously.
1194 PluginService::GetInstance()->GetPlugins(base::BindOnce(
1195 &URLLoaderRequestController::CheckPluginAndContinueOnReceiveResponse,
Marijn Kruisselbrink9ebd7ba2018-06-11 23:18:041196 weak_factory_.GetWeakPtr(), head,
Matt Menke2bd72d82018-08-03 15:17:181197 std::move(url_loader_client_endpoints),
1198 is_download_if_not_handled_by_plugin));
John Abd-El-Malek3ebdff862018-04-23 18:57:211199 return;
1200 }
1201
Matt Menke2bd72d82018-08-03 15:17:181202 bool is_download = !has_plugin && is_download_if_not_handled_by_plugin;
John Abd-El-Malek3ebdff862018-04-23 18:57:211203
Marijn Kruisselbrink9ebd7ba2018-06-11 23:18:041204 CallOnReceivedResponse(head, std::move(url_loader_client_endpoints),
Ryan Sturm64315a92018-07-20 06:25:281205 nullptr, is_download, false /* is_stream */,
1206 PREVIEWS_OFF /* previews_state */);
John Abd-El-Malek3ebdff862018-04-23 18:57:211207 }
1208#endif
1209
1210 void CallOnReceivedResponse(
1211 const network::ResourceResponseHead& head,
John Abd-El-Malek3ebdff862018-04-23 18:57:211212 network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
1213 std::unique_ptr<NavigationData> cloned_navigation_data,
1214 bool is_download,
Ryan Sturm64315a92018-07-20 06:25:281215 bool is_stream,
1216 PreviewsState previews_state) {
John Abd-El-Malek3ebdff862018-04-23 18:57:211217 scoped_refptr<network::ResourceResponse> response(
1218 new network::ResourceResponse());
1219 response->head = head;
1220
Andrey Kosyakova924c8b2017-08-18 17:37:231221 // Make a copy of the ResourceResponse before it is passed to another
1222 // thread.
1223 //
1224 // TODO(davidben): This copy could be avoided if ResourceResponse weren't
1225 // reference counted and the loader stack passed unique ownership of the
1226 // response. https://crbug.com/416050
Eric Seckler8652dcd52018-09-20 10:42:281227 base::PostTaskWithTraits(
1228 FROM_HERE, {BrowserThread::UI},
Philip Rogers7178f5c2018-07-09 18:52:591229 base::BindOnce(&NavigationURLLoaderImpl::OnReceiveResponse, owner_,
1230 response->DeepCopy(),
1231 std::move(url_loader_client_endpoints),
1232 std::move(cloned_navigation_data), global_request_id_,
Ryan Sturm64315a92018-07-20 06:25:281233 is_download, is_stream, previews_state));
yzshenefcb7c72017-06-16 23:12:301234 }
1235
1236 void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
John Abd-El-Malek46248032018-01-17 19:11:231237 const network::ResourceResponseHead& head) override {
Clark DuVallb2680c22018-08-10 15:27:271238 if (base::FeatureList::IsEnabled(network::features::kNetworkService) &&
1239 !bypass_redirect_checks_ &&
Chris Mumford90b1a0d2018-09-26 20:10:431240 !IsRedirectSafe(url_, redirect_info.new_url, resource_context_)) {
Clark DuVallb2680c22018-08-10 15:27:271241 OnComplete(network::URLLoaderCompletionStatus(net::ERR_UNSAFE_REDIRECT));
1242 return;
Clark DuVallbf7722f2018-08-03 18:03:331243 }
1244
Michael Nordman2431f5f2017-09-13 04:58:151245 if (--redirect_limit_ == 0) {
Takashi Toyoshimaaa278662017-11-20 11:11:261246 OnComplete(
1247 network::URLLoaderCompletionStatus(net::ERR_TOO_MANY_REDIRECTS));
Michael Nordman2431f5f2017-09-13 04:58:151248 return;
1249 }
1250
1251 // Store the redirect_info for later use in FollowRedirect where we give
Kinuko Yasuda7f3e1722018-03-26 08:58:581252 // our interceptors_ a chance to intercept the request for the new location.
Michael Nordman2431f5f2017-09-13 04:58:151253 redirect_info_ = redirect_info;
1254
John Abd-El-Malek46248032018-01-17 19:11:231255 scoped_refptr<network::ResourceResponse> response(
1256 new network::ResourceResponse());
Andrey Kosyakova924c8b2017-08-18 17:37:231257 response->head = head;
arthursonzogni40db5f52018-01-08 16:38:491258 url_ = redirect_info.new_url;
Andrey Kosyakova924c8b2017-08-18 17:37:231259
1260 // Make a copy of the ResourceResponse before it is passed to another
1261 // thread.
1262 //
1263 // TODO(davidben): This copy could be avoided if ResourceResponse weren't
1264 // reference counted and the loader stack passed unique ownership of the
1265 // response. https://crbug.com/416050
Eric Seckler8652dcd52018-09-20 10:42:281266 base::PostTaskWithTraits(
1267 FROM_HERE, {BrowserThread::UI},
arthursonzogni1fd60e62018-05-09 15:57:321268 base::BindOnce(&NavigationURLLoaderImpl::OnReceiveRedirect, owner_,
1269 redirect_info, response->DeepCopy()));
yzshenefcb7c72017-06-16 23:12:301270 }
1271
yzshenefcb7c72017-06-16 23:12:301272 void OnUploadProgress(int64_t current_position,
1273 int64_t total_size,
1274 OnUploadProgressCallback callback) override {}
yzshenefcb7c72017-06-16 23:12:301275 void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override {}
yzshenefcb7c72017-06-16 23:12:301276 void OnTransferSizeUpdated(int32_t transfer_size_diff) override {}
1277
Philip Rogers7178f5c2018-07-09 18:52:591278 void OnStartLoadingResponseBody(mojo::ScopedDataPipeConsumerHandle) override {
1279 // Not reached. At this point, the loader and client endpoints must have
1280 // been unbound and forwarded to the renderer.
Matt Falkenhagen2ba894152018-09-21 08:29:441281
1282 // TODO(crbug.com/882661): Remove these aliases when the linked bug is
1283 // fixed.
1284 bool received_response = received_response_;
1285 base::debug::Alias(&received_response);
1286 bool default_loader_used = default_loader_used_;
1287 base::debug::Alias(&default_loader_used);
1288 DEBUG_ALIAS_FOR_GURL(url, url_);
1289 size_t chain_size = url_chain_.size();
1290 base::debug::Alias(&chain_size);
1291 GURL url0;
1292 GURL url1;
1293 GURL url2;
1294 GURL url3;
1295 GURL url4;
1296 GURL url5;
1297 if (url_chain_.size() > 0)
1298 url0 = url_chain_[0];
1299 if (url_chain_.size() > 1)
1300 url1 = url_chain_[1];
1301 if (url_chain_.size() > 2)
1302 url2 = url_chain_[2];
1303 if (url_chain_.size() > 3)
1304 url3 = url_chain_[3];
1305 if (url_chain_.size() > 4)
1306 url4 = url_chain_[4];
1307 if (url_chain_.size() > 5)
1308 url5 = url_chain_[5];
1309 DEBUG_ALIAS_FOR_GURL(url0_buf, url0);
1310 DEBUG_ALIAS_FOR_GURL(url1_buf, url1);
1311 DEBUG_ALIAS_FOR_GURL(url2_buf, url2);
1312 DEBUG_ALIAS_FOR_GURL(url3_buf, url3);
1313 DEBUG_ALIAS_FOR_GURL(url4_buf, url4);
1314 DEBUG_ALIAS_FOR_GURL(url5_buf, url5);
Philip Rogers7178f5c2018-07-09 18:52:591315 CHECK(false);
yzshenefcb7c72017-06-16 23:12:301316 }
1317
Takashi Toyoshimaaa278662017-11-20 11:11:261318 void OnComplete(const network::URLLoaderCompletionStatus& status) override {
Matt Menked9cad562018-08-10 21:47:091319 RecordSCTHistogramIfNeeded(status.ssl_info);
1320
Emily Starkb09f19a2017-11-22 22:41:471321 UMA_HISTOGRAM_BOOLEAN(
arthursonzognie70c4a042018-05-02 15:49:101322 "Navigation.URLLoaderNetworkService.OnCompleteHasSSLInfo",
Emily Starkb09f19a2017-11-22 22:41:471323 status.ssl_info.has_value());
1324 if (status.ssl_info.has_value()) {
1325 UMA_HISTOGRAM_MEMORY_KB(
1326 "Navigation.URLLoaderNetworkService.OnCompleteCertificateChainsSize",
1327 GetCertificateChainsSizeInKB(status.ssl_info.value()));
1328 }
1329
Takashi Toyoshima8f988532017-11-13 07:32:371330 if (status.error_code != net::OK && !received_response_) {
anantab9800e52017-07-29 18:04:131331 // If the default loader (network) was used to handle the URL load
Kinuko Yasuda7f3e1722018-03-26 08:58:581332 // request we need to see if the interceptors want to potentially create a
anantab9800e52017-07-29 18:04:131333 // new loader for the response. e.g. AppCache.
John Abd-El-Malek46248032018-01-17 19:11:231334 if (MaybeCreateLoaderForResponse(network::ResourceResponseHead()))
anantab9800e52017-07-29 18:04:131335 return;
1336 }
Takashi Toyoshima8f988532017-11-13 07:32:371337 status_ = status;
arthursonzogni2695d04d2017-12-12 08:39:011338
Eric Seckler8652dcd52018-09-20 10:42:281339 base::PostTaskWithTraits(
1340 FROM_HERE, {BrowserThread::UI},
arthursonzogni1fd60e62018-05-09 15:57:321341 base::BindOnce(&NavigationURLLoaderImpl::OnComplete, owner_, status));
yzshenefcb7c72017-06-16 23:12:301342 }
1343
Kinuko Yasuda7f3e1722018-03-26 08:58:581344 // Returns true if an interceptor wants to handle the response, i.e. return a
Michael Nordman2431f5f2017-09-13 04:58:151345 // different response. For e.g. AppCache may have fallback content.
John Abd-El-Malek46248032018-01-17 19:11:231346 bool MaybeCreateLoaderForResponse(
1347 const network::ResourceResponseHead& response) {
Kinuko Yasuda7f3e1722018-03-26 08:58:581348 if (!IsLoaderInterceptionEnabled())
arthursonzogni2695d04d2017-12-12 08:39:011349 return false;
1350
anantab9800e52017-07-29 18:04:131351 if (!default_loader_used_)
1352 return false;
1353
Kinuko Yasuda7f3e1722018-03-26 08:58:581354 for (auto& interceptor : interceptors_) {
John Abd-El-Malekb165dc52018-01-18 17:12:181355 network::mojom::URLLoaderClientRequest response_client_request;
Kinuko Yasuda7f3e1722018-03-26 08:58:581356 if (interceptor->MaybeCreateLoaderForResponse(
1357 response, &response_url_loader_, &response_client_request,
1358 url_loader_.get())) {
Kunihiko Sakamoto21ab4ad262018-08-21 10:26:211359 if (response_loader_binding_.is_bound())
1360 response_loader_binding_.Close();
Michael Nordman2431f5f2017-09-13 04:58:151361 response_loader_binding_.Bind(std::move(response_client_request));
1362 default_loader_used_ = false;
1363 url_loader_.reset();
anantab9800e52017-07-29 18:04:131364 return true;
1365 }
1366 }
1367 return false;
1368 }
1369
Matt Falkenhagen43765122018-08-22 19:37:221370 std::vector<std::unique_ptr<URLLoaderThrottle>> CreateURLLoaderThrottles() {
Tsuyoshi Horo70014ad2018-02-14 11:20:141371 return GetContentClient()->browser()->CreateURLLoaderThrottles(
1372 *resource_request_, resource_context_, web_contents_getter_,
1373 navigation_ui_data_.get(), frame_tree_node_id_);
1374 }
1375
Makoto Shimazu44c2c3232018-03-30 01:10:201376 std::unique_ptr<NavigationLoaderInterceptor> CreateServiceWorkerInterceptor(
1377 const NavigationRequestInfo& request_info,
1378 ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core)
1379 const {
1380 const ResourceType resource_type = request_info.is_main_frame
1381 ? RESOURCE_TYPE_MAIN_FRAME
1382 : RESOURCE_TYPE_SUB_FRAME;
1383 network::mojom::RequestContextFrameType frame_type =
1384 request_info.is_main_frame
1385 ? network::mojom::RequestContextFrameType::kTopLevel
1386 : network::mojom::RequestContextFrameType::kNested;
1387 storage::BlobStorageContext* blob_storage_context = GetBlobStorageContext(
1388 GetChromeBlobStorageContextForResourceContext(resource_context_));
1389 return ServiceWorkerRequestHandler::InitializeForNavigationNetworkService(
Matt Falkenhagen43765122018-08-22 19:37:221390 resource_request_->url, resource_context_,
Makoto Shimazu44c2c3232018-03-30 01:10:201391 service_worker_navigation_handle_core, blob_storage_context,
1392 request_info.begin_params->skip_service_worker, resource_type,
1393 request_info.begin_params->request_context_type, frame_type,
1394 request_info.are_ancestors_secure, request_info.common_params.post_data,
1395 web_contents_getter_);
1396 }
1397
Matt Menked9cad562018-08-10 21:47:091398 void RecordSCTHistogramIfNeeded(
1399 const base::Optional<net::SSLInfo>& ssl_info) {
1400 if (is_main_frame_ && url_.SchemeIsCryptographic() &&
1401 ssl_info.has_value()) {
1402 int num_valid_scts = 0;
1403 for (const auto& signed_certificate_timestamps :
1404 ssl_info->signed_certificate_timestamps) {
1405 if (signed_certificate_timestamps.status == net::ct::SCT_STATUS_OK)
1406 ++num_valid_scts;
1407 }
1408 UMA_HISTOGRAM_COUNTS_100(
1409 "Net.CertificateTransparency.MainFrameValidSCTCount", num_valid_scts);
1410 }
1411 }
1412
Kinuko Yasuda7f3e1722018-03-26 08:58:581413 std::vector<std::unique_ptr<NavigationLoaderInterceptor>> interceptors_;
1414 size_t interceptor_index_ = 0;
kinuko69732972017-05-29 08:50:071415
John Abd-El-Malek1df61792018-01-12 20:40:451416 std::unique_ptr<network::ResourceRequest> resource_request_;
Makoto Shimazu44c2c3232018-03-30 01:10:201417 // Non-NetworkService: |request_info_| is updated along with
1418 // |resource_request_| on redirects.
1419 std::unique_ptr<NavigationRequestInfo> request_info_;
John Abd-El-Malek576c6132017-11-04 00:33:581420 int frame_tree_node_id_ = 0;
arthursonzogni40db5f52018-01-08 16:38:491421 GlobalRequestID global_request_id_;
Michael Nordman2431f5f2017-09-13 04:58:151422 net::RedirectInfo redirect_info_;
Daniel Bratell0dfa6282017-11-08 10:12:231423 int redirect_limit_ = net::URLRequest::kMaxRedirects;
kinuko69732972017-05-29 08:50:071424 ResourceContext* resource_context_;
yzshenefcb7c72017-06-16 23:12:301425 base::Callback<WebContents*()> web_contents_getter_;
John Abd-El-Malekeb1a5382018-01-05 16:58:001426 std::unique_ptr<NavigationUIData> navigation_ui_data_;
Kinuko Yasudabe4ad292018-07-06 01:33:391427 scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory_;
arthursonzogni2695d04d2017-12-12 08:39:011428
yzshenefcb7c72017-06-16 23:12:301429 std::unique_ptr<ThrottlingURLLoader> url_loader_;
arthursonzogni2695d04d2017-12-12 08:39:011430
Chong Zhang7607f1f2018-06-01 20:52:201431 // Caches the modified request headers provided by clients during redirect,
1432 // will be consumed by next |url_loader_->FollowRedirect()|.
1433 base::Optional<net::HttpRequestHeaders> url_loader_modified_request_headers_;
1434
mmenkeed44e6c2017-06-28 21:13:321435 BlobHandles blob_handles_;
Min Qin83d07872017-10-26 23:22:411436 std::vector<GURL> url_chain_;
kinuko69732972017-05-29 08:50:071437
arthursonzogni40db5f52018-01-08 16:38:491438 // Current URL that is being navigated, updated after redirection.
1439 GURL url_;
1440
Matt Menked9cad562018-08-10 21:47:091441 const bool is_main_frame_;
1442
anantae60d1d42017-06-20 04:16:271443 // Currently used by the AppCache loader to pass its factory to the
1444 // renderer which enables it to handle subresources.
Kinuko Yasuda250577c2017-10-29 02:51:241445 base::Optional<SubresourceLoaderParams> subresource_loader_params_;
anantae60d1d42017-06-20 04:16:271446
mmenkeed44e6c2017-06-28 21:13:321447 // This is referenced only on the UI thread.
arthursonzogni1fd60e62018-05-09 15:57:321448 base::WeakPtr<NavigationURLLoaderImpl> owner_;
mmenkeed44e6c2017-06-28 21:13:321449
anantab9800e52017-07-29 18:04:131450 // Set to true if the default URLLoader (network service) was used for the
1451 // current navigation.
1452 bool default_loader_used_ = false;
1453
1454 // URLLoaderClient binding for loaders created for responses received from the
1455 // network loader.
John Abd-El-Malekb165dc52018-01-18 17:12:181456 mojo::Binding<network::mojom::URLLoaderClient> response_loader_binding_;
anantab9800e52017-07-29 18:04:131457
1458 // URLLoader instance for response loaders, i.e loaders created for handing
1459 // responses received from the network URLLoader.
John Abd-El-Malekb165dc52018-01-18 17:12:181460 network::mojom::URLLoaderPtr response_url_loader_;
anantab9800e52017-07-29 18:04:131461
1462 // Set to true if we receive a valid response from a URLLoader, i.e.
1463 // URLLoaderClient::OnReceivedResponse() is called.
1464 bool received_response_ = false;
1465
Alex Clarke1e08882b32017-10-06 14:22:401466 bool started_ = false;
1467
Ken Rockot314714c2017-11-05 23:36:241468 // Lazily initialized and used in the case of non-network resource
1469 // navigations. Keyed by URL scheme.
John Abd-El-Malekb165dc52018-01-18 17:12:181470 std::map<std::string, network::mojom::URLLoaderFactoryPtr>
Ken Rockot314714c2017-11-05 23:36:241471 non_network_url_loader_factories_;
1472
Makoto Shimazu44c2c3232018-03-30 01:10:201473 // Non-NetworkService:
1474 // Generator of a request handler for sending request to the network. This
1475 // captures all of parameters to create a
1476 // SingleRequestURLLoaderFactory::RequestHandler. Used only when
1477 // NetworkService is disabled but IsLoaderInterceptionEnabled() is true.
Makoto Shimazu684a5ad2018-05-29 08:20:501478 // Set |was_request_intercepted| to true if the request was intercepted by an
1479 // interceptor and the request is falling back to the network. In that case,
1480 // any interceptors won't intercept the request.
1481 base::RepeatingCallback<SingleRequestURLLoaderFactory::RequestHandler(
1482 bool /* was_request_intercepted */)>
Makoto Shimazu44c2c3232018-03-30 01:10:201483 default_request_handler_factory_;
1484
Min Qin40b72172017-09-27 00:19:171485 // The completion status if it has been received. This is needed to handle
1486 // the case that the response is intercepted by download, and OnComplete() is
1487 // already called while we are transferring the |url_loader_| and response
1488 // body to download code.
Takashi Toyoshimaaa278662017-11-20 11:11:261489 base::Optional<network::URLLoaderCompletionStatus> status_;
Min Qin40b72172017-09-27 00:19:171490
Ken Rockota0dfaca12018-02-15 07:26:251491 // Before creating this URLLoaderRequestController on UI thread, the embedder
1492 // may have elected to proxy the URLLoaderFactory request, in which case these
1493 // fields will contain input (info) and output (request) endpoints for the
1494 // proxy. If this controller is handling a request for which proxying is
1495 // supported, requests will be plumbed through these endpoints.
1496 //
1497 // Note that these are only used for requests that go to the Network Service.
1498 network::mojom::URLLoaderFactoryRequest proxied_factory_request_;
1499 network::mojom::URLLoaderFactoryPtrInfo proxied_factory_info_;
1500
John Abd-El-Maleka67add82018-03-09 18:22:011501 // The schemes that this loader can use. For anything else we'll try external
1502 // protocol handlers.
1503 std::set<std::string> known_schemes_;
1504
Clark DuVallb2680c22018-08-10 15:27:271505 // If true, redirect checks will be handled in a proxy, and not here.
1506 bool bypass_redirect_checks_;
Clark DuVallbf7722f2018-08-03 18:03:331507
Makoto Shimazu44c2c3232018-03-30 01:10:201508 mutable base::WeakPtrFactory<URLLoaderRequestController> weak_factory_;
arthursonzogni2695d04d2017-12-12 08:39:011509
kinuko69732972017-05-29 08:50:071510 DISALLOW_COPY_AND_ASSIGN(URLLoaderRequestController);
1511};
1512
Min Qin75ed6df2017-12-01 20:39:151513// TODO(https://crbug.com/790734): pass |navigation_ui_data| along with the
1514// request so that it could be modified.
arthursonzogni1fd60e62018-05-09 15:57:321515NavigationURLLoaderImpl::NavigationURLLoaderImpl(
scottmg69985212017-04-12 16:47:281516 ResourceContext* resource_context,
1517 StoragePartition* storage_partition,
1518 std::unique_ptr<NavigationRequestInfo> request_info,
1519 std::unique_ptr<NavigationUIData> navigation_ui_data,
scottmgd2021c92017-05-15 16:58:051520 ServiceWorkerNavigationHandle* service_worker_navigation_handle,
scottmg69985212017-04-12 16:47:281521 AppCacheNavigationHandle* appcache_handle,
Alex Clarke1e08882b32017-10-06 14:22:401522 NavigationURLLoaderDelegate* delegate,
Kinuko Yasuda7f3e1722018-03-26 08:58:581523 std::vector<std::unique_ptr<NavigationLoaderInterceptor>>
1524 initial_interceptors)
Min Qin37db5102017-09-13 21:21:251525 : delegate_(delegate),
1526 allow_download_(request_info->common_params.allow_download),
1527 weak_factory_(this) {
scottmg95feea52017-04-12 17:51:331528 DCHECK_CURRENTLY_ON(BrowserThread::UI);
John Abd-El-Malekfcb2ecf2017-11-15 23:15:301529 int frame_tree_node_id = request_info->frame_tree_node_id;
ananta5149d8e2017-04-21 00:01:371530
yzshen0f278522017-05-01 17:10:221531 TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP1(
1532 "navigation", "Navigation timeToResponseStarted", this,
kinuko69732972017-05-29 08:50:071533 request_info->common_params.navigation_start, "FrameTreeNode id",
John Abd-El-Malekfcb2ecf2017-11-15 23:15:301534 frame_tree_node_id);
yzshen0f278522017-05-01 17:10:221535
arthursonzogni2695d04d2017-12-12 08:39:011536 ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core =
1537 service_worker_navigation_handle
1538 ? service_worker_navigation_handle->core()
1539 : nullptr;
1540
1541 AppCacheNavigationHandleCore* appcache_handle_core =
1542 appcache_handle ? appcache_handle->core() : nullptr;
1543
Yuzhu Shencb3011f62018-02-08 02:51:501544 std::unique_ptr<network::ResourceRequest> new_request = CreateResourceRequest(
1545 request_info.get(), frame_tree_node_id, allow_download_);
Yutaka Hirano61e41b3c2018-05-31 05:31:061546 new_request->transition_type = request_info->common_params.transition;
Tsuyoshi Horob8d512a2018-01-25 17:01:591547
Yutaka Hiranod8789f92018-01-30 09:59:511548 if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
arthursonzogni2695d04d2017-12-12 08:39:011549 DCHECK(!request_controller_);
1550 request_controller_ = std::make_unique<URLLoaderRequestController>(
Kinuko Yasuda7f3e1722018-03-26 08:58:581551 /* initial_interceptors = */
1552 std::vector<std::unique_ptr<NavigationLoaderInterceptor>>(),
Tsuyoshi Horob8d512a2018-01-25 17:01:591553 std::move(new_request), resource_context,
Matt Menked9cad562018-08-10 21:47:091554 request_info->common_params.url, request_info->is_main_frame,
Ken Rockota0dfaca12018-02-15 07:26:251555 /* proxied_url_loader_factory_request */ nullptr,
John Abd-El-Maleka67add82018-03-09 18:22:011556 /* proxied_url_loader_factory_info */ nullptr, std::set<std::string>(),
Clark DuVallb2680c22018-08-10 15:27:271557 /* bypass_redirect_checks */ false, weak_factory_.GetWeakPtr());
arthursonzogni2695d04d2017-12-12 08:39:011558
Eric Seckler8652dcd52018-09-20 10:42:281559 base::PostTaskWithTraits(
1560 FROM_HERE, {BrowserThread::IO},
arthursonzogni2695d04d2017-12-12 08:39:011561 base::BindOnce(
1562 &URLLoaderRequestController::StartWithoutNetworkService,
1563 base::Unretained(request_controller_.get()),
Tsuyoshi Horo70014ad2018-02-14 11:20:141564 base::RetainedRef(storage_partition->GetURLRequestContext()),
arthursonzogni2695d04d2017-12-12 08:39:011565 base::Unretained(storage_partition->GetFileSystemContext()),
1566 base::Unretained(service_worker_navigation_handle_core),
tzikccf160c2018-02-20 12:43:131567 base::Unretained(appcache_handle_core), std::move(request_info),
1568 std::move(navigation_ui_data)));
arthursonzogni2695d04d2017-12-12 08:39:011569 return;
1570 }
1571
scottmgd2021c92017-05-15 16:58:051572 // Check if a web UI scheme wants to handle this request.
Ken Rockot6414c4d92017-11-08 19:58:321573 FrameTreeNode* frame_tree_node =
1574 FrameTreeNode::GloballyFindByID(frame_tree_node_id);
John Abd-El-Malekb165dc52018-01-18 17:12:181575 network::mojom::URLLoaderFactoryPtrInfo factory_for_webui;
scottmgd2021c92017-05-15 16:58:051576 const auto& schemes = URLDataManagerBackend::GetWebUISchemes();
John Abd-El-Malekbb0bc8e2017-11-11 01:08:151577 std::string scheme = new_request->url.scheme();
qufehdquf9c8433abd2018-07-10 16:57:271578 if (base::ContainsValue(schemes, scheme)) {
Chris Mumfordbae8a742018-03-01 23:02:231579 factory_for_webui = CreateWebUIURLLoaderBinding(
1580 frame_tree_node->current_frame_host(), scheme)
1581 .PassInterface();
ananta5149d8e2017-04-21 00:01:371582 }
scottmgd2021c92017-05-15 16:58:051583
Ken Rockota0dfaca12018-02-15 07:26:251584 network::mojom::URLLoaderFactoryPtrInfo proxied_factory_info;
1585 network::mojom::URLLoaderFactoryRequest proxied_factory_request;
Clark DuVallb2680c22018-08-10 15:27:271586 bool bypass_redirect_checks = false;
Chris Mumford942075ad2018-05-19 00:22:041587 auto* partition = static_cast<StoragePartitionImpl*>(storage_partition);
Ken Rockota0dfaca12018-02-15 07:26:251588 if (frame_tree_node) {
1589 // |frame_tree_node| may be null in some unit test environments.
1590 GetContentClient()
1591 ->browser()
1592 ->RegisterNonNetworkNavigationURLLoaderFactories(
John Abd-El-Malekea006302018-05-10 05:50:461593 frame_tree_node_id, &non_network_url_loader_factories_);
Ken Rockota0dfaca12018-02-15 07:26:251594
Lukasz Anforowicz762733652018-09-28 14:48:261595 // Navigation requests are not associated with any particular
1596 // |network::ResourceRequest::request_initiator| origin - using an opaque
1597 // origin instead.
1598 url::Origin navigation_request_initiator = url::Origin();
Ken Rockota0dfaca12018-02-15 07:26:251599 // The embedder may want to proxy all network-bound URLLoaderFactory
1600 // requests that it can. If it elects to do so, we'll pass its proxy
1601 // endpoints off to the URLLoaderRequestController where wthey will be
1602 // connected if the request type supports proxying.
1603 network::mojom::URLLoaderFactoryPtrInfo factory_info;
1604 auto factory_request = mojo::MakeRequest(&factory_info);
Andrey Kosyakov8d49c5062018-03-15 19:50:491605 bool use_proxy = GetContentClient()->browser()->WillCreateURLLoaderFactory(
Ken Rockot428b1d62018-06-06 17:12:211606 partition->browser_context(), frame_tree_node->current_frame_host(),
Lukasz Anforowicz762733652018-09-28 14:48:261607 true /* is_navigation */, navigation_request_initiator,
1608 &factory_request, &bypass_redirect_checks);
Andrey Kosyakov8d49c5062018-03-15 19:50:491609 if (RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory(
Jochen Eisingercdc12d12018-05-08 15:07:471610 frame_tree_node->current_frame_host(), true, false,
1611 &factory_request)) {
Andrey Kosyakov8d49c5062018-03-15 19:50:491612 use_proxy = true;
1613 }
1614 if (use_proxy) {
Ken Rockota0dfaca12018-02-15 07:26:251615 proxied_factory_request = std::move(factory_request);
1616 proxied_factory_info = std::move(factory_info);
1617 }
Chris Mumford942075ad2018-05-19 00:22:041618
1619 const std::string storage_domain;
1620 non_network_url_loader_factories_[url::kFileSystemScheme] =
1621 CreateFileSystemURLLoaderFactory(frame_tree_node->current_frame_host(),
1622 /*is_navigation=*/true,
1623 partition->GetFileSystemContext(),
1624 storage_domain);
Ken Rockota0dfaca12018-02-15 07:26:251625 }
1626
John Abd-El-Maleka67add82018-03-09 18:22:011627 non_network_url_loader_factories_[url::kFileScheme] =
1628 std::make_unique<FileURLLoaderFactory>(
1629 partition->browser_context()->GetPath(),
1630 base::CreateSequencedTaskRunnerWithTraits(
Gabriel Charetteb10aeeb2018-07-26 20:15:001631 {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
John Abd-El-Maleka67add82018-03-09 18:22:011632 base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}));
Eric Roman80164412018-10-02 22:13:541633
1634#if defined(OS_ANDROID)
1635 non_network_url_loader_factories_[url::kContentScheme] =
1636 std::make_unique<ContentURLLoaderFactory>(
1637 base::CreateSequencedTaskRunnerWithTraits(
1638 {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
1639 base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}));
1640#endif
1641
John Abd-El-Maleka67add82018-03-09 18:22:011642 std::set<std::string> known_schemes;
1643 for (auto& iter : non_network_url_loader_factories_)
1644 known_schemes.insert(iter.first);
1645
kinuko69732972017-05-29 08:50:071646 DCHECK(!request_controller_);
Jeremy Roman04f27c372017-10-27 15:20:551647 request_controller_ = std::make_unique<URLLoaderRequestController>(
Kinuko Yasuda7f3e1722018-03-26 08:58:581648 std::move(initial_interceptors), std::move(new_request), resource_context,
Matt Menked9cad562018-08-10 21:47:091649 request_info->common_params.url, request_info->is_main_frame,
1650 std::move(proxied_factory_request), std::move(proxied_factory_info),
1651 std::move(known_schemes), bypass_redirect_checks,
1652 weak_factory_.GetWeakPtr());
Eric Seckler8652dcd52018-09-20 10:42:281653 base::PostTaskWithTraits(
1654 FROM_HERE, {BrowserThread::IO},
Ken Rockot387ddd5a2018-01-30 19:18:401655 base::BindOnce(
1656 &URLLoaderRequestController::Start,
1657 base::Unretained(request_controller_.get()),
Kinuko Yasudabe4ad292018-07-06 01:33:391658 partition->url_loader_factory_getter()->GetNetworkFactoryInfo(),
Ken Rockot387ddd5a2018-01-30 19:18:401659 service_worker_navigation_handle_core, appcache_handle_core,
1660 std::move(request_info), std::move(navigation_ui_data),
1661 std::move(factory_for_webui), frame_tree_node_id,
1662 ServiceManagerConnection::GetForProcess()->GetConnector()->Clone()));
scottmg69985212017-04-12 16:47:281663}
1664
arthursonzogni1fd60e62018-05-09 15:57:321665NavigationURLLoaderImpl::~NavigationURLLoaderImpl() {
kinuko69732972017-05-29 08:50:071666 BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE,
1667 request_controller_.release());
1668}
scottmg69985212017-04-12 16:47:281669
Chong Zhang7607f1f2018-06-01 20:52:201670void NavigationURLLoaderImpl::FollowRedirect(
Jun Cai605ff0e72018-06-12 22:29:201671 const base::Optional<std::vector<std::string>>&
1672 to_be_removed_request_headers,
Chong Zhang7607f1f2018-06-01 20:52:201673 const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
Eric Seckler8652dcd52018-09-20 10:42:281674 base::PostTaskWithTraits(
1675 FROM_HERE, {BrowserThread::IO},
tzik0f14f192017-08-15 02:43:331676 base::BindOnce(&URLLoaderRequestController::FollowRedirect,
Chong Zhang7607f1f2018-06-01 20:52:201677 base::Unretained(request_controller_.get()),
1678 modified_request_headers));
scottmg95feea52017-04-12 17:51:331679}
scottmg69985212017-04-12 16:47:281680
arthursonzogni1fd60e62018-05-09 15:57:321681void NavigationURLLoaderImpl::ProceedWithResponse() {}
scottmg69985212017-04-12 16:47:281682
arthursonzogni1fd60e62018-05-09 15:57:321683void NavigationURLLoaderImpl::OnReceiveResponse(
John Abd-El-Malek46248032018-01-17 19:11:231684 scoped_refptr<network::ResourceResponse> response,
John Abd-El-Malekb165dc52018-01-18 17:12:181685 network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
arthursonzogni40db5f52018-01-08 16:38:491686 std::unique_ptr<NavigationData> navigation_data,
1687 const GlobalRequestID& global_request_id,
1688 bool is_download,
Ryan Sturm64315a92018-07-20 06:25:281689 bool is_stream,
1690 PreviewsState previews_state) {
arthursonzogni3a4ca9f2017-12-07 17:58:341691 TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", this,
arthursonzogni1fd60e62018-05-09 15:57:321692 "&NavigationURLLoaderImpl", this, "success", true);
arthursonzogni3a4ca9f2017-12-07 17:58:341693
scottmgefb697302017-04-12 22:37:301694 // TODO(scottmg): This needs to do more of what
arthursonzogni3a4ca9f2017-12-07 17:58:341695 // NavigationResourceHandler::OnResponseStarted() does.
arthursonzogni3a4ca9f2017-12-07 17:58:341696
arthursonzogni3a4ca9f2017-12-07 17:58:341697 delegate_->OnResponseStarted(
arthursonzognif34adf092018-04-24 17:06:131698 std::move(response), std::move(url_loader_client_endpoints),
Philip Rogers7178f5c2018-07-09 18:52:591699 std::move(navigation_data), global_request_id,
Ryan Sturm64315a92018-07-20 06:25:281700 allow_download_ && is_download, is_stream, previews_state,
arthursonzogni3a4ca9f2017-12-07 17:58:341701 request_controller_->TakeSubresourceLoaderParams());
scottmg95feea52017-04-12 17:51:331702}
scottmg69985212017-04-12 16:47:281703
arthursonzogni1fd60e62018-05-09 15:57:321704void NavigationURLLoaderImpl::OnReceiveRedirect(
scottmg69985212017-04-12 16:47:281705 const net::RedirectInfo& redirect_info,
John Abd-El-Malek46248032018-01-17 19:11:231706 scoped_refptr<network::ResourceResponse> response) {
scottmg95feea52017-04-12 17:51:331707 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Andrey Kosyakova924c8b2017-08-18 17:37:231708 delegate_->OnRequestRedirected(redirect_info, std::move(response));
scottmg95feea52017-04-12 17:51:331709}
scottmg69985212017-04-12 16:47:281710
arthursonzogni1fd60e62018-05-09 15:57:321711void NavigationURLLoaderImpl::OnComplete(
Takashi Toyoshimaaa278662017-11-20 11:11:261712 const network::URLLoaderCompletionStatus& status) {
Takashi Toyoshima8f988532017-11-13 07:32:371713 if (status.error_code == net::OK)
John Abd-El-Malekb906d282017-08-31 19:36:431714 return;
1715
1716 TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", this,
arthursonzogni1fd60e62018-05-09 15:57:321717 "&NavigationURLLoaderImpl", this, "success", false);
Lucas Garron0efab6d2017-08-30 22:28:511718
Johannes Henkel6a43fef2018-05-17 18:41:521719 delegate_->OnRequestFailed(status);
yzshen384441de2017-04-19 23:26:141720}
scottmg69985212017-04-12 16:47:281721
arthursonzogni1fd60e62018-05-09 15:57:321722void NavigationURLLoaderImpl::SetBeginNavigationInterceptorForTesting(
John Abd-El-Malekdb3a13b2018-05-01 17:52:021723 const BeginNavigationInterceptor& interceptor) {
1724 DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::IO) ||
1725 BrowserThread::CurrentlyOn(BrowserThread::IO));
1726 DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
1727 g_interceptor.Get() = interceptor;
1728}
1729
arthursonzogni1fd60e62018-05-09 15:57:321730void NavigationURLLoaderImpl::OnRequestStarted(base::TimeTicks timestamp) {
arthursonzogni2695d04d2017-12-12 08:39:011731 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1732 delegate_->OnRequestStarted(timestamp);
1733}
1734
arthursonzogni1fd60e62018-05-09 15:57:321735void NavigationURLLoaderImpl::BindNonNetworkURLLoaderFactoryRequest(
Ken Rockota0dfaca12018-02-15 07:26:251736 int frame_tree_node_id,
Ken Rockot314714c2017-11-05 23:36:241737 const GURL& url,
John Abd-El-Malekb165dc52018-01-18 17:12:181738 network::mojom::URLLoaderFactoryRequest factory) {
Ken Rockot314714c2017-11-05 23:36:241739 auto it = non_network_url_loader_factories_.find(url.scheme());
1740 if (it == non_network_url_loader_factories_.end()) {
1741 DVLOG(1) << "Ignoring request with unknown scheme: " << url.spec();
1742 return;
1743 }
Lukasz Anforowicz762733652018-09-28 14:48:261744
1745 // Navigation requests are not associated with any particular
1746 // |network::ResourceRequest::request_initiator| origin - using an opaque
1747 // origin instead.
1748 url::Origin navigation_request_initiator = url::Origin();
1749
Ken Rockota0dfaca12018-02-15 07:26:251750 FrameTreeNode* frame_tree_node =
1751 FrameTreeNode::GloballyFindByID(frame_tree_node_id);
Ken Rockot428b1d62018-06-06 17:12:211752 auto* frame = frame_tree_node->current_frame_host();
Ken Rockota0dfaca12018-02-15 07:26:251753 GetContentClient()->browser()->WillCreateURLLoaderFactory(
Ken Rockot428b1d62018-06-06 17:12:211754 frame->GetSiteInstance()->GetBrowserContext(), frame,
Lukasz Anforowicz762733652018-09-28 14:48:261755 true /* is_navigation */, navigation_request_initiator, &factory,
Clark DuVall8dc4e502018-09-07 01:51:121756 nullptr /* bypass_redirect_checks */);
Ken Rockot314714c2017-11-05 23:36:241757 it->second->Clone(std::move(factory));
1758}
1759
scottmg69985212017-04-12 16:47:281760} // namespace content