blob: 5476802f60469ad0aeba7844d876d17f014626af [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"
Tarun Bansal98260cd2018-02-17 07:52:2311#include "base/feature_list.h"
Emily Starkb09f19a2017-11-22 22:41:4712#include "base/metrics/histogram_macros.h"
Ken Rockot314714c2017-11-05 23:36:2413#include "base/task_scheduler/post_task.h"
yzshen0f278522017-05-01 17:10:2214#include "base/trace_event/trace_event.h"
Min Qinda0ed2062018-02-23 22:00:5315#include "components/download/public/common/download_stats.h"
anantae3f159a2017-05-11 23:40:0716#include "content/browser/appcache/appcache_navigation_handle.h"
Matt Falkenhagend2867e82018-07-04 08:26:3817#include "content/browser/appcache/appcache_navigation_handle_core.h"
anantaa2c8ec62017-06-09 23:44:0518#include "content/browser/appcache/appcache_request_handler.h"
ananta5149d8e2017-04-21 00:01:3719#include "content/browser/blob_storage/chrome_blob_storage_context.h"
Andrey Kosyakov8d49c5062018-03-15 19:50:4920#include "content/browser/devtools/render_frame_devtools_agent_host.h"
Ken Rockot314714c2017-11-05 23:36:2421#include "content/browser/file_url_loader_factory.h"
Chris Mumford942075ad2018-05-19 00:22:0422#include "content/browser/fileapi/file_system_url_loader_factory.h"
jam8c4edd02017-05-06 18:50:3323#include "content/browser/frame_host/frame_tree_node.h"
scottmg69985212017-04-12 16:47:2824#include "content/browser/frame_host/navigation_request_info.h"
Kinuko Yasuda7f3e1722018-03-26 08:58:5825#include "content/browser/loader/navigation_loader_interceptor.h"
scottmg95feea52017-04-12 17:51:3326#include "content/browser/loader/navigation_url_loader_delegate.h"
arthursonzogni2695d04d2017-12-12 08:39:0127#include "content/browser/loader/resource_dispatcher_host_impl.h"
arthursonzogni40db5f52018-01-08 16:38:4928#include "content/browser/loader/resource_request_info_impl.h"
scottmgd2021c92017-05-15 16:58:0529#include "content/browser/resource_context_impl.h"
30#include "content/browser/service_worker/service_worker_navigation_handle.h"
31#include "content/browser/service_worker/service_worker_navigation_handle_core.h"
32#include "content/browser/service_worker/service_worker_request_handler.h"
jamc1905862017-05-16 14:45:3033#include "content/browser/storage_partition_impl.h"
34#include "content/browser/url_loader_factory_getter.h"
scottmgd2021c92017-05-15 16:58:0535#include "content/browser/web_contents/web_contents_impl.h"
Kouhei Ueno958c5f482018-03-19 08:20:3836#include "content/browser/web_package/signed_exchange_consts.h"
Kunihiko Sakamotoe6aa22e2018-06-15 03:26:5537#include "content/browser/web_package/signed_exchange_request_handler.h"
Tsuyoshi Horob85801592018-02-19 22:18:0738#include "content/browser/web_package/signed_exchange_url_loader_factory_for_non_network_service.h"
Tsuyoshi Horo46f5fff2018-05-10 12:33:3539#include "content/browser/web_package/signed_exchange_utils.h"
jam1a97290b2017-05-09 04:30:5040#include "content/browser/webui/url_data_manager_backend.h"
Chris Mumfordbae8a742018-03-01 23:02:2341#include "content/browser/webui/web_ui_url_loader_factory_internal.h"
Kinuko Yasuda250577c2017-10-29 02:51:2442#include "content/common/navigation_subresource_loader_params.h"
Matt Menkea294b092018-07-06 17:53:3243#include "content/common/net/record_load_histograms.h"
Makoto Shimazu44c2c3232018-03-30 01:10:2044#include "content/common/service_worker/service_worker_utils.h"
yzshenefcb7c72017-06-16 23:12:3045#include "content/common/throttling_url_loader.h"
jamc1905862017-05-16 14:45:3046#include "content/public/browser/browser_context.h"
scottmg95feea52017-04-12 17:51:3347#include "content/public/browser/browser_thread.h"
yzshenefcb7c72017-06-16 23:12:3048#include "content/public/browser/content_browser_client.h"
Robbie McElratha5adc4e2018-07-03 23:53:0949#include "content/public/browser/download_utils.h"
scottmgefb697302017-04-12 22:37:3050#include "content/public/browser/global_request_id.h"
Dmitry Skiba7e8c7e22018-01-04 21:04:1851#include "content/public/browser/navigation_data.h"
scottmg69985212017-04-12 16:47:2852#include "content/public/browser/navigation_ui_data.h"
John Abd-El-Malek3ebdff862018-04-23 18:57:2153#include "content/public/browser/plugin_service.h"
arthursonzogni40db5f52018-01-08 16:38:4954#include "content/public/browser/resource_dispatcher_host_delegate.h"
scottmgefb697302017-04-12 22:37:3055#include "content/public/browser/ssl_status.h"
Jian Li18e29242018-05-10 22:25:1256#include "content/public/browser/url_loader_request_interceptor.h"
arthursonzogni2695d04d2017-12-12 08:39:0157#include "content/public/common/content_features.h"
ananta5149d8e2017-04-21 00:01:3758#include "content/public/common/referrer.h"
jam8c4edd02017-05-06 18:50:3359#include "content/public/common/url_constants.h"
Ken Rockot314714c2017-11-05 23:36:2460#include "content/public/common/url_utils.h"
John Abd-El-Malek3ebdff862018-04-23 18:57:2161#include "content/public/common/webplugininfo.h"
ananta5149d8e2017-04-21 00:01:3762#include "net/base/load_flags.h"
Min Qin37db5102017-09-13 21:21:2563#include "net/http/http_content_disposition.h"
Chong Zhang7607f1f2018-06-01 20:52:2064#include "net/http/http_request_headers.h"
rhalavati4cda417b2017-06-12 11:00:2465#include "net/traffic_annotation/network_traffic_annotation.h"
Tsuyoshi Horo9e2ec4df2017-10-16 15:15:5566#include "net/url_request/redirect_util.h"
Daniel Bratell0dfa6282017-11-08 10:12:2367#include "net/url_request/url_request.h"
scottmg69985212017-04-12 16:47:2868#include "net/url_request/url_request_context.h"
Tsuyoshi Horo70014ad2018-02-14 11:20:1469#include "net/url_request/url_request_context_getter.h"
John Abd-El-Malek3ebdff862018-04-23 18:57:2170#include "ppapi/buildflags/buildflags.h"
John Abd-El-Malek89c02ae2018-02-01 01:56:1971#include "services/network/loader_util.h"
Yutaka Hiranod8789f92018-01-30 09:59:5172#include "services/network/public/cpp/features.h"
Antonio Gomes9cdc09a2018-05-07 23:24:2673#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
74#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
Ken Rockot54311e62018-02-10 19:01:5275#include "services/network/public/mojom/request_context_frame_type.mojom.h"
76#include "services/network/public/mojom/url_loader_factory.mojom.h"
yzshenefcb7c72017-06-16 23:12:3077#include "services/service_manager/public/cpp/connector.h"
John Abd-El-Malek3ebdff862018-04-23 18:57:2178#include "third_party/blink/public/common/mime_util/mime_util.h"
scottmg69985212017-04-12 16:47:2879
80namespace content {
81
jambcc67882017-04-28 18:20:0982namespace {
yzshenfa5e57202017-05-02 21:24:1383
Jian Li18e29242018-05-10 22:25:1284class NavigationLoaderInterceptorBrowserContainer
85 : public NavigationLoaderInterceptor {
86 public:
87 explicit NavigationLoaderInterceptorBrowserContainer(
88 std::unique_ptr<URLLoaderRequestInterceptor> browser_interceptor)
89 : browser_interceptor_(std::move(browser_interceptor)) {}
90
91 ~NavigationLoaderInterceptorBrowserContainer() override = default;
92
93 void MaybeCreateLoader(const network::ResourceRequest& resource_request,
94 ResourceContext* resource_context,
95 LoaderCallback callback) override {
96 browser_interceptor_->MaybeCreateLoader(resource_request, resource_context,
97 std::move(callback));
98 }
99
100 private:
101 std::unique_ptr<URLLoaderRequestInterceptor> browser_interceptor_;
102};
103
John Abd-El-Malekdb3a13b2018-05-01 17:52:02104// Only used on the IO thread.
arthursonzogni1fd60e62018-05-09 15:57:32105base::LazyInstance<NavigationURLLoaderImpl::BeginNavigationInterceptor>::Leaky
John Abd-El-Malekdb3a13b2018-05-01 17:52:02106 g_interceptor = LAZY_INSTANCE_INITIALIZER;
107
Kinuko Yasuda7f3e1722018-03-26 08:58:58108// Returns true if interception by NavigationLoaderInterceptors is enabled.
Tsuyoshi Horo46f5fff2018-05-10 12:33:35109// Both ServiceWorkerServicification and SignedExchange require the loader
110// interception. So even if NetworkService is not enabled, returns true when one
111// of them is enabled.
Kinuko Yasuda7f3e1722018-03-26 08:58:58112bool IsLoaderInterceptionEnabled() {
Yutaka Hiranod8789f92018-01-30 09:59:51113 return base::FeatureList::IsEnabled(network::features::kNetworkService) ||
Tsuyoshi Horo46f5fff2018-05-10 12:33:35114 ServiceWorkerUtils::IsServicificationEnabled() ||
115 signed_exchange_utils::IsSignedExchangeHandlingEnabled();
Tsuyoshi Horob8d512a2018-01-25 17:01:59116}
117
ananta2e65213d2017-05-19 04:08:24118// Request ID for browser initiated requests. We start at -2 on the same lines
119// as ResourceDispatcherHostImpl.
120int g_next_request_id = -2;
arthursonzogni40db5f52018-01-08 16:38:49121GlobalRequestID MakeGlobalRequestID() {
122 return GlobalRequestID(-1, g_next_request_id--);
123}
ananta2e65213d2017-05-19 04:08:24124
Emily Starkb09f19a2017-11-22 22:41:47125size_t GetCertificateChainsSizeInKB(const net::SSLInfo& ssl_info) {
126 base::Pickle cert_pickle;
127 ssl_info.cert->Persist(&cert_pickle);
128 base::Pickle unverified_cert_pickle;
129 ssl_info.unverified_cert->Persist(&unverified_cert_pickle);
130 return (cert_pickle.size() + unverified_cert_pickle.size()) / 1000;
131}
132
scottmgd2021c92017-05-15 16:58:05133WebContents* GetWebContentsFromFrameTreeNodeID(int frame_tree_node_id) {
134 DCHECK_CURRENTLY_ON(BrowserThread::UI);
135 FrameTreeNode* frame_tree_node =
136 FrameTreeNode::GloballyFindByID(frame_tree_node_id);
137 if (!frame_tree_node)
138 return nullptr;
ananta5149d8e2017-04-21 00:01:37139
scottmgd2021c92017-05-15 16:58:05140 return WebContentsImpl::FromFrameTreeNode(frame_tree_node);
141}
142
Daniel Bratellcf0b485c2017-11-09 22:42:50143const net::NetworkTrafficAnnotationTag kNavigationUrlLoaderTrafficAnnotation =
Ramin Halavatie99206e92017-06-23 05:02:50144 net::DefineNetworkTrafficAnnotation("navigation_url_loader", R"(
Ramin Halavati7b5ce1c2017-07-03 09:13:09145 semantics {
146 sender: "Navigation URL Loader"
147 description:
148 "This request is issued by a main frame navigation to fetch the "
149 "content of the page that is being navigated to."
150 trigger:
151 "Navigating Chrome (by clicking on a link, bookmark, history item, "
152 "using session restore, etc)."
153 data:
154 "Arbitrary site-controlled data can be included in the URL, HTTP "
155 "headers, and request body. Requests may include cookies and "
156 "site-specific credentials."
157 destination: WEBSITE
158 }
159 policy {
Ramin Halavati3b979782017-07-21 11:40:26160 cookies_allowed: YES
Ramin Halavati7b5ce1c2017-07-03 09:13:09161 cookies_store: "user"
162 setting: "This feature cannot be disabled."
Ramin Halavati386daa62017-08-17 10:41:59163 chrome_policy {
164 URLBlacklist {
165 URLBlacklist: { entries: '*' }
166 }
167 }
168 chrome_policy {
169 URLWhitelist {
170 URLWhitelist { }
171 }
172 }
173 }
174 comments:
175 "Chrome would be unable to navigate to websites without this type of "
176 "request. Using either URLBlacklist or URLWhitelist policies (or a "
177 "combination of both) limits the scope of these requests."
178 )");
Ramin Halavatie99206e92017-06-23 05:02:50179
Tsuyoshi Horob8d512a2018-01-25 17:01:59180std::unique_ptr<network::ResourceRequest> CreateResourceRequest(
181 NavigationRequestInfo* request_info,
182 int frame_tree_node_id,
183 bool allow_download) {
184 // TODO(scottmg): Port over stuff from RDHI::BeginNavigationRequest() here.
185 auto new_request = std::make_unique<network::ResourceRequest>();
186
187 new_request->method = request_info->common_params.method;
188 new_request->url = request_info->common_params.url;
189 new_request->site_for_cookies = request_info->site_for_cookies;
Tarun Bansal98260cd2018-02-17 07:52:23190
191 net::RequestPriority net_priority = net::HIGHEST;
192 if (!request_info->is_main_frame &&
193 base::FeatureList::IsEnabled(features::kLowPriorityIframes)) {
194 net_priority = net::LOWEST;
195 }
196 new_request->priority = net_priority;
197
Tsuyoshi Horob8d512a2018-01-25 17:01:59198 new_request->render_frame_id = frame_tree_node_id;
199
200 // The code below to set fields like request_initiator, referrer, etc has
201 // been copied from ResourceDispatcherHostImpl. We did not refactor the
202 // common code into a function, because RDHI uses accessor functions on the
203 // URLRequest class to set these fields. whereas we use ResourceRequest here.
204 new_request->request_initiator = request_info->begin_params->initiator_origin;
205 new_request->referrer = request_info->common_params.referrer.url;
206 new_request->referrer_policy = Referrer::ReferrerPolicyForUrlRequest(
207 request_info->common_params.referrer.policy);
208 new_request->headers.AddHeadersFromString(
209 request_info->begin_params->headers);
Kouhei Ueno958c5f482018-03-19 08:20:38210
211 std::string accept_value = network::kFrameAcceptHeader;
Tsuyoshi Horo46f5fff2018-05-10 12:33:35212 // TODO(https://crbug.com/840704): Decide whether the Accept header should
213 // advertise the state of kSignedHTTPExchangeOriginTrial before starting the
214 // Origin-Trial.
215 if (signed_exchange_utils::IsSignedExchangeHandlingEnabled()) {
Kouhei Ueno958c5f482018-03-19 08:20:38216 DCHECK(!accept_value.empty());
217 accept_value.append(kAcceptHeaderSignedExchangeSuffix);
218 }
219
220 new_request->headers.SetHeader(network::kAcceptHeader, accept_value);
Tsuyoshi Horob8d512a2018-01-25 17:01:59221
222 new_request->resource_type = request_info->is_main_frame
223 ? RESOURCE_TYPE_MAIN_FRAME
224 : RESOURCE_TYPE_SUB_FRAME;
225 if (request_info->is_main_frame)
226 new_request->update_first_party_url_on_redirect = true;
227
228 int load_flags = request_info->begin_params->load_flags;
Tsuyoshi Horob8d512a2018-01-25 17:01:59229 if (request_info->is_main_frame)
230 load_flags |= net::LOAD_MAIN_FRAME_DEPRECATED;
231
232 // Sync loads should have maximum priority and should be the only
233 // requests that have the ignore limits flag set.
234 DCHECK(!(load_flags & net::LOAD_IGNORE_LIMITS));
235
236 new_request->load_flags = load_flags;
237
238 new_request->request_body = request_info->common_params.post_data.get();
239 new_request->report_raw_headers = request_info->report_raw_headers;
240 new_request->allow_download = allow_download;
241 new_request->enable_load_timing = true;
242
243 new_request->fetch_request_mode = network::mojom::FetchRequestMode::kNavigate;
244 new_request->fetch_credentials_mode =
245 network::mojom::FetchCredentialsMode::kInclude;
246 new_request->fetch_redirect_mode = network::mojom::FetchRedirectMode::kManual;
Yutaka Hirano4b9b7a7f2018-03-07 14:35:15247 new_request->fetch_request_context_type =
248 request_info->begin_params->request_context_type;
Carlos ILa54c59a2018-06-11 19:43:03249 new_request->upgrade_if_insecure = request_info->upgrade_if_insecure;
Tsuyoshi Horoc1ab7122018-06-19 05:48:13250 new_request->throttling_profile_id = request_info->devtools_frame_token;
Tsuyoshi Horob8d512a2018-01-25 17:01:59251 return new_request;
252}
253
Makoto Shimazu44c2c3232018-03-30 01:10:20254// Used only when NetworkService is disabled but IsLoaderInterceptionEnabled()
255// is true.
256std::unique_ptr<NavigationRequestInfo> CreateNavigationRequestInfoForRedirect(
257 const NavigationRequestInfo& previous_request_info,
258 const network::ResourceRequest& updated_resource_request) {
259 DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
260 DCHECK(IsLoaderInterceptionEnabled());
261
262 CommonNavigationParams new_common_params =
263 previous_request_info.common_params;
264 new_common_params.url = updated_resource_request.url;
265 new_common_params.referrer =
Makoto Shimazue8019fb2018-06-26 03:54:31266 Referrer(updated_resource_request.referrer,
Makoto Shimazu44c2c3232018-03-30 01:10:20267 Referrer::NetReferrerPolicyToBlinkReferrerPolicy(
268 updated_resource_request.referrer_policy));
269 new_common_params.method = updated_resource_request.method;
270 new_common_params.post_data = updated_resource_request.request_body;
Makoto Shimazu44c2c3232018-03-30 01:10:20271
272 mojom::BeginNavigationParamsPtr new_begin_params =
273 previous_request_info.begin_params.Clone();
274 new_begin_params->headers = updated_resource_request.headers.ToString();
275
276 return std::make_unique<NavigationRequestInfo>(
277 std::move(new_common_params), std::move(new_begin_params),
278 updated_resource_request.site_for_cookies,
279 previous_request_info.is_main_frame,
280 previous_request_info.parent_is_main_frame,
281 previous_request_info.are_ancestors_secure,
282 previous_request_info.frame_tree_node_id,
283 previous_request_info.is_for_guests_only,
284 previous_request_info.report_raw_headers,
Marijn Kruisselbrink07bf59d52018-04-03 21:50:25285 previous_request_info.is_prerendering,
Carlos ILa54c59a2018-06-11 19:43:03286 previous_request_info.upgrade_if_insecure,
Tsuyoshi Horo32b51f12018-05-09 17:58:46287 nullptr /* blob_url_loader_factory */,
Tsuyoshi Horoc1ab7122018-06-19 05:48:13288 previous_request_info.devtools_navigation_token,
289 previous_request_info.devtools_frame_token);
Makoto Shimazu44c2c3232018-03-30 01:10:20290}
291
John Abd-El-Maleka67add82018-03-09 18:22:01292// Called for requests that we don't have a URLLoaderFactory for.
293void UnknownSchemeCallback(bool handled_externally,
294 network::mojom::URLLoaderRequest request,
295 network::mojom::URLLoaderClientPtr client) {
296 client->OnComplete(network::URLLoaderCompletionStatus(
297 handled_externally ? net::ERR_ABORTED : net::ERR_UNKNOWN_URL_SCHEME));
298}
299
yzshenfa5e57202017-05-02 21:24:13300} // namespace
301
kinuko69732972017-05-29 08:50:07302// Kept around during the lifetime of the navigation request, and is
303// responsible for dispatching a ResourceRequest to the appropriate
kinukod8b13e212017-06-07 06:59:26304// URLLoader. In order to get the right URLLoader it builds a vector
Kinuko Yasuda7f3e1722018-03-26 08:58:58305// of NavigationLoaderInterceptors and successively calls MaybeCreateLoader
kinukod8b13e212017-06-07 06:59:26306// on each until the request is successfully handled. The same sequence
307// may be performed multiple times when redirects happen.
Alex Clarke1e08882b32017-10-06 14:22:40308// TODO(michaeln): Expose this class and add more unittests.
arthursonzogni1fd60e62018-05-09 15:57:32309class NavigationURLLoaderImpl::URLLoaderRequestController
John Abd-El-Malekb165dc52018-01-18 17:12:18310 : public network::mojom::URLLoaderClient {
kinuko69732972017-05-29 08:50:07311 public:
jam9354af82017-06-03 21:59:41312 URLLoaderRequestController(
Kinuko Yasuda7f3e1722018-03-26 08:58:58313 std::vector<std::unique_ptr<NavigationLoaderInterceptor>>
314 initial_interceptors,
John Abd-El-Malek1df61792018-01-12 20:40:45315 std::unique_ptr<network::ResourceRequest> resource_request,
jam9354af82017-06-03 21:59:41316 ResourceContext* resource_context,
arthursonzogni40db5f52018-01-08 16:38:49317 const GURL& url,
Ken Rockota0dfaca12018-02-15 07:26:25318 network::mojom::URLLoaderFactoryRequest proxied_factory_request,
319 network::mojom::URLLoaderFactoryPtrInfo proxied_factory_info,
John Abd-El-Maleka67add82018-03-09 18:22:01320 std::set<std::string> known_schemes,
arthursonzogni1fd60e62018-05-09 15:57:32321 const base::WeakPtr<NavigationURLLoaderImpl>& owner)
Kinuko Yasuda7f3e1722018-03-26 08:58:58322 : interceptors_(std::move(initial_interceptors)),
Alex Clarke1e08882b32017-10-06 14:22:40323 resource_request_(std::move(resource_request)),
kinuko69732972017-05-29 08:50:07324 resource_context_(resource_context),
arthursonzogni40db5f52018-01-08 16:38:49325 url_(url),
anantab9800e52017-07-29 18:04:13326 owner_(owner),
arthursonzogni2695d04d2017-12-12 08:39:01327 response_loader_binding_(this),
Ken Rockota0dfaca12018-02-15 07:26:25328 proxied_factory_request_(std::move(proxied_factory_request)),
329 proxied_factory_info_(std::move(proxied_factory_info)),
John Abd-El-Maleka67add82018-03-09 18:22:01330 known_schemes_(std::move(known_schemes)),
arthursonzogni2695d04d2017-12-12 08:39:01331 weak_factory_(this) {}
kinuko69732972017-05-29 08:50:07332
yzshenefcb7c72017-06-16 23:12:30333 ~URLLoaderRequestController() override {
kinuko69732972017-05-29 08:50:07334 DCHECK_CURRENTLY_ON(BrowserThread::IO);
Matt Menkea294b092018-07-06 17:53:32335
336 // If neither OnCompleted nor OnReceivedResponse has been invoked, the
337 // request was canceled before receiving a response, so log a cancellation.
338 // Results after receiving a non-error response are logged in the renderer,
339 // if the request is passed to one. If it's a download, or not passed to a
340 // renderer for some other reason, results will not be logged for the
341 // request. The net::OK check may not be necessary - the case where OK is
342 // received without receiving any headers looks broken, anyways.
343 if (!received_response_ && (!status_ || status_->error_code != net::OK)) {
344 RecordLoadHistograms(url_, resource_request_->resource_type,
345 status_ ? status_->error_code : net::ERR_ABORTED);
346 }
kinuko69732972017-05-29 08:50:07347 }
348
arthursonzognib521c6a2018-01-08 12:23:40349 static uint32_t GetURLLoaderOptions(bool is_main_frame) {
John Abd-El-Malekb165dc52018-01-18 17:12:18350 uint32_t options = network::mojom::kURLLoadOptionSendSSLInfoWithResponse;
arthursonzognib521c6a2018-01-08 12:23:40351 if (is_main_frame)
John Abd-El-Malekb165dc52018-01-18 17:12:18352 options |= network::mojom::kURLLoadOptionSendSSLInfoForCertificateError;
arthursonzognib521c6a2018-01-08 12:23:40353
Yutaka Hiranod8789f92018-01-30 09:59:51354 if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
John Abd-El-Malekb165dc52018-01-18 17:12:18355 options |= network::mojom::kURLLoadOptionSniffMimeType;
arthursonzognib521c6a2018-01-08 12:23:40356 } else {
357 // TODO(arthursonzogni): This is a temporary option. Remove this as soon
358 // as the InterceptingResourceHandler is removed.
359 // See https://crbug.com/791049.
John Abd-El-Malekb165dc52018-01-18 17:12:18360 options |= network::mojom::kURLLoadOptionPauseOnResponseStarted;
arthursonzognib521c6a2018-01-08 12:23:40361 }
362
363 return options;
364 }
365
Makoto Shimazu44c2c3232018-03-30 01:10:20366 SingleRequestURLLoaderFactory::RequestHandler
367 CreateDefaultRequestHandlerForNonNetworkService(
368 net::URLRequestContextGetter* url_request_context_getter,
369 storage::FileSystemContext* upload_file_system_context,
370 ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
Makoto Shimazu684a5ad2018-05-29 08:20:50371 AppCacheNavigationHandleCore* appcache_handle_core,
372 bool was_request_intercepted) const {
Matt Falkenhagenf03034d92018-07-06 06:50:43373 // Temporary CHECKs for https://crbug.com/857005.
374 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
375 CHECK(started_);
Matt Falkenhagend2867e82018-07-04 08:26:38376 if (appcache_handle_core)
377 appcache_handle_core->AddDefaultFactoryRunToDebugLog(
378 was_request_intercepted);
Makoto Shimazu44c2c3232018-03-30 01:10:20379 return base::BindOnce(
380 &URLLoaderRequestController::CreateNonNetworkServiceURLLoader,
381 weak_factory_.GetWeakPtr(),
382 base::Unretained(url_request_context_getter),
383 base::Unretained(upload_file_system_context),
384 std::make_unique<NavigationRequestInfo>(*request_info_),
Makoto Shimazu684a5ad2018-05-29 08:20:50385 // If the request has already been intercepted, the request should not
386 // be intercepted again.
387 // S13nServiceWorker: Requests are intercepted by S13nServiceWorker
388 // before the default request handler when needed, so we never need to
389 // pass |service_worker_navigation_handle_core| here.
390 base::Unretained(ServiceWorkerUtils::IsServicificationEnabled() ||
391 was_request_intercepted
392 ? nullptr
393 : service_worker_navigation_handle_core),
394 base::Unretained(was_request_intercepted ? nullptr
395 : appcache_handle_core));
Makoto Shimazu44c2c3232018-03-30 01:10:20396 }
397
arthursonzogni2695d04d2017-12-12 08:39:01398 void CreateNonNetworkServiceURLLoader(
399 net::URLRequestContextGetter* url_request_context_getter,
400 storage::FileSystemContext* upload_file_system_context,
401 std::unique_ptr<NavigationRequestInfo> request_info,
arthursonzogni2695d04d2017-12-12 08:39:01402 ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
403 AppCacheNavigationHandleCore* appcache_handle_core,
John Abd-El-Malekb165dc52018-01-18 17:12:18404 network::mojom::URLLoaderRequest url_loader,
405 network::mojom::URLLoaderClientPtr url_loader_client) {
Yutaka Hiranod8789f92018-01-30 09:59:51406 DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
arthursonzogni2695d04d2017-12-12 08:39:01407 DCHECK_CURRENTLY_ON(BrowserThread::IO);
408
Matt Falkenhagend2867e82018-07-04 08:26:38409 if (appcache_handle_core)
410 appcache_handle_core->AddCreateURLLoaderToDebugLog();
411
Tsuyoshi Horob8d512a2018-01-25 17:01:59412 default_loader_used_ = true;
Tsuyoshi Horo46f5fff2018-05-10 12:33:35413 if (signed_exchange_utils::IsSignedExchangeHandlingEnabled()) {
Kinuko Yasudabe4ad292018-07-06 01:33:39414 DCHECK(!network_loader_factory_);
Tsuyoshi Horo561163b2018-03-27 03:11:23415 // It is safe to pass the callback of CreateURLLoaderThrottles with the
Tsuyoshi Horo70014ad2018-02-14 11:20:14416 // unretained |this|, because the passed callback will be used by a
417 // SignedExchangeHandler which is indirectly owned by |this| until its
418 // header is verified and parsed, that's where the getter is used.
Kunihiko Sakamotoe6aa22e2018-06-15 03:26:55419 interceptors_.push_back(std::make_unique<SignedExchangeRequestHandler>(
Tsuyoshi Horo70014ad2018-02-14 11:20:14420 url::Origin::Create(request_info->common_params.url),
Tsuyoshi Horo32b51f12018-05-09 17:58:46421 request_info->common_params.url,
Kinuko Yasuda32a25652018-02-19 08:14:25422 GetURLLoaderOptions(request_info->is_main_frame),
Tsuyoshi Horocdbb4902018-04-12 06:09:14423 request_info->frame_tree_node_id,
Tsuyoshi Horo32b51f12018-05-09 17:58:46424 request_info->devtools_navigation_token,
Tsuyoshi Horob8d381182018-06-19 10:07:29425 request_info->devtools_frame_token, request_info->report_raw_headers,
Tsuyoshi Horo6e6782d2018-06-07 02:32:47426 request_info->begin_params->load_flags,
Tsuyoshi Horo70014ad2018-02-14 11:20:14427 base::MakeRefCounted<
428 SignedExchangeURLLoaderFactoryForNonNetworkService>(
429 resource_context_, url_request_context_getter),
430 base::BindRepeating(
431 &URLLoaderRequestController::CreateURLLoaderThrottles,
Tsuyoshi Horof7702192018-03-07 15:00:36432 base::Unretained(this)),
433 url_request_context_getter));
Tsuyoshi Horob8d512a2018-01-25 17:01:59434 }
435
John Abd-El-Malekdb3a13b2018-05-01 17:52:02436 uint32_t options = GetURLLoaderOptions(request_info->is_main_frame);
437
438 bool intercepted = false;
439 if (g_interceptor.Get()) {
440 intercepted = g_interceptor.Get().Run(
441 &url_loader, frame_tree_node_id_, 0 /* request_id */, options,
442 *resource_request_.get(), &url_loader_client,
443 net::MutableNetworkTrafficAnnotationTag(
444 kNavigationUrlLoaderTrafficAnnotation));
445 }
446
arthursonzogni2695d04d2017-12-12 08:39:01447 // The ResourceDispatcherHostImpl can be null in unit tests.
John Abd-El-Malekdb3a13b2018-05-01 17:52:02448 if (!intercepted && ResourceDispatcherHostImpl::Get()) {
arthursonzogni2695d04d2017-12-12 08:39:01449 ResourceDispatcherHostImpl::Get()->BeginNavigationRequest(
450 resource_context_, url_request_context_getter->GetURLRequestContext(),
451 upload_file_system_context, *request_info,
arthursonzogni662d723c2018-04-24 16:13:22452 std::move(navigation_ui_data_), std::move(url_loader_client),
arthursonzogni2695d04d2017-12-12 08:39:01453 std::move(url_loader), service_worker_navigation_handle_core,
Makoto Shimazuff60c1412018-06-19 06:17:33454 appcache_handle_core, options, global_request_id_);
arthursonzogni2695d04d2017-12-12 08:39:01455 }
456
457 // TODO(arthursonzogni): Detect when the ResourceDispatcherHost didn't
458 // create a URLLoader. When it doesn't, do not send OnRequestStarted().
459 BrowserThread::PostTask(
460 BrowserThread::UI, FROM_HERE,
arthursonzogni1fd60e62018-05-09 15:57:32461 base::BindOnce(&NavigationURLLoaderImpl::OnRequestStarted, owner_,
462 base::TimeTicks::Now()));
arthursonzogni2695d04d2017-12-12 08:39:01463 }
464
465 // TODO(arthursonzogni): See if this could eventually be unified with Start().
466 void StartWithoutNetworkService(
467 net::URLRequestContextGetter* url_request_context_getter,
468 storage::FileSystemContext* upload_file_system_context,
469 ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
470 AppCacheNavigationHandleCore* appcache_handle_core,
471 std::unique_ptr<NavigationRequestInfo> request_info,
472 std::unique_ptr<NavigationUIData> navigation_ui_data) {
Matt Falkenhagenf03034d92018-07-06 06:50:43473 // Temporary CHECKs for https://crbug.com/857005.
474 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
475 CHECK(!started_);
476 CHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
Matt Falkenhagend2867e82018-07-04 08:26:38477 if (appcache_handle_core)
478 appcache_handle_core->AddNavigationStartToDebugLog();
479
arthursonzogni2695d04d2017-12-12 08:39:01480 started_ = true;
Makoto Shimazu44c2c3232018-03-30 01:10:20481 request_info_ = std::move(request_info);
482 frame_tree_node_id_ = request_info_->frame_tree_node_id;
Yuzhu Shencb3011f62018-02-08 02:51:50483 web_contents_getter_ = base::BindRepeating(
Yuzhu Shen9508fc72018-02-08 23:18:59484 &GetWebContentsFromFrameTreeNodeID, frame_tree_node_id_);
Makoto Shimazu44c2c3232018-03-30 01:10:20485 navigation_ui_data_ = std::move(navigation_ui_data);
Makoto Shimazuff60c1412018-06-19 06:17:33486 // The ResourceDispatcherHostImpl can be null in unit tests.
487 ResourceDispatcherHostImpl* rph = ResourceDispatcherHostImpl::Get();
488 if (rph)
489 global_request_id_ = rph->MakeGlobalRequestID();
490
Makoto Shimazu44c2c3232018-03-30 01:10:20491 default_request_handler_factory_ = base::BindRepeating(
492 &URLLoaderRequestController::
493 CreateDefaultRequestHandlerForNonNetworkService,
494 // base::Unretained(this) is safe since
495 // |default_request_handler_factory_| could be called only from |this|.
496 base::Unretained(this), base::Unretained(url_request_context_getter),
497 base::Unretained(upload_file_system_context),
arthursonzogni2695d04d2017-12-12 08:39:01498 base::Unretained(service_worker_navigation_handle_core),
499 base::Unretained(appcache_handle_core));
500
Marijn Kruisselbrink8a7fd102018-06-05 17:30:39501 // Requests to Blob scheme won't get redirected to/from other schemes
502 // or be intercepted, so we just let it go here.
503 if (request_info_->common_params.url.SchemeIsBlob() &&
504 request_info_->blob_url_loader_factory) {
505 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
506 network::SharedURLLoaderFactory::Create(
507 std::move(request_info_->blob_url_loader_factory)),
508 CreateURLLoaderThrottles(), -1 /* routing_id */, 0 /* request_id? */,
509 network::mojom::kURLLoadOptionNone, resource_request_.get(), this,
510 kNavigationUrlLoaderTrafficAnnotation,
511 base::ThreadTaskRunnerHandle::Get());
512 return;
513 }
514
Makoto Shimazu44c2c3232018-03-30 01:10:20515 // If S13nServiceWorker is disabled, just use
516 // |default_request_handler_factory_| and return. The non network service
517 // request handling goes through ResourceDispatcherHost which has legacy
518 // hooks for service worker (ServiceWorkerRequestInterceptor), so no service
519 // worker interception is needed here.
520 if (!ServiceWorkerUtils::IsServicificationEnabled() ||
521 !service_worker_navigation_handle_core) {
522 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
523 base::MakeRefCounted<SingleRequestURLLoaderFactory>(
Makoto Shimazu684a5ad2018-05-29 08:20:50524 default_request_handler_factory_.Run(
525 false /* was_request_intercepted */)),
Makoto Shimazu44c2c3232018-03-30 01:10:20526 CreateURLLoaderThrottles(), -1 /* routing_id */, 0 /* request_id */,
527 network::mojom::kURLLoadOptionNone, resource_request_.get(),
528 this /* client */, kNavigationUrlLoaderTrafficAnnotation,
529 base::ThreadTaskRunnerHandle::Get());
530 return;
531 }
532
533 // Otherwise, if S13nServiceWorker is enabled, create an interceptor so
534 // S13nServiceWorker has a chance to intercept the request.
535 std::unique_ptr<NavigationLoaderInterceptor> service_worker_interceptor =
536 CreateServiceWorkerInterceptor(*request_info_,
537 service_worker_navigation_handle_core);
538 // If an interceptor is not created for some reasons (e.g. the origin is not
539 // secure), we no longer have to go through the rest of the network service
540 // code.
541 if (!service_worker_interceptor) {
542 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
543 base::MakeRefCounted<SingleRequestURLLoaderFactory>(
Makoto Shimazu684a5ad2018-05-29 08:20:50544 default_request_handler_factory_.Run(
545 false /* was_request_intercepted */)),
Makoto Shimazu44c2c3232018-03-30 01:10:20546 CreateURLLoaderThrottles(), -1 /* routing_id */, 0 /* request_id */,
547 network::mojom::kURLLoadOptionNone, resource_request_.get(),
548 this /* client */, kNavigationUrlLoaderTrafficAnnotation,
549 base::ThreadTaskRunnerHandle::Get());
550 return;
551 }
552
553 interceptors_.push_back(std::move(service_worker_interceptor));
554
Makoto Shimazu44c2c3232018-03-30 01:10:20555 Restart();
arthursonzogni2695d04d2017-12-12 08:39:01556 }
557
kinuko69732972017-05-29 08:50:07558 void Start(
Tsuyoshi Horo70014ad2018-02-14 11:20:14559 net::URLRequestContextGetter* url_request_context_getter,
Kinuko Yasudabe4ad292018-07-06 01:33:39560 std::unique_ptr<network::SharedURLLoaderFactoryInfo>
561 network_loader_factory_info,
kinuko69732972017-05-29 08:50:07562 ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
563 AppCacheNavigationHandleCore* appcache_handle_core,
564 std::unique_ptr<NavigationRequestInfo> request_info,
John Abd-El-Malekeb1a5382018-01-05 16:58:00565 std::unique_ptr<NavigationUIData> navigation_ui_data,
John Abd-El-Malekb165dc52018-01-18 17:12:18566 network::mojom::URLLoaderFactoryPtrInfo factory_for_webui,
John Abd-El-Malek576c6132017-11-04 00:33:58567 int frame_tree_node_id,
kinuko69732972017-05-29 08:50:07568 std::unique_ptr<service_manager::Connector> connector) {
Matt Falkenhagenf03034d92018-07-06 06:50:43569 // Temporary CHECKs for https://crbug.com/857005.
570 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
571 CHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
572 CHECK(!started_);
arthursonzogni40db5f52018-01-08 16:38:49573 global_request_id_ = MakeGlobalRequestID();
John Abd-El-Malek576c6132017-11-04 00:33:58574 frame_tree_node_id_ = frame_tree_node_id;
Alex Clarke1e08882b32017-10-06 14:22:40575 started_ = true;
John Abd-El-Malek576c6132017-11-04 00:33:58576 web_contents_getter_ =
577 base::Bind(&GetWebContentsFromFrameTreeNodeID, frame_tree_node_id);
John Abd-El-Malekeb1a5382018-01-05 16:58:00578 navigation_ui_data_ = std::move(navigation_ui_data);
kinuko69732972017-05-29 08:50:07579
Kinuko Yasudabe4ad292018-07-06 01:33:39580 DCHECK(network_loader_factory_info);
581 network_loader_factory_ = network::SharedURLLoaderFactory::Create(
582 std::move(network_loader_factory_info));
583
kinuko69732972017-05-29 08:50:07584 if (resource_request_->request_body) {
mmenkeed44e6c2017-06-28 21:13:32585 GetBodyBlobDataHandles(resource_request_->request_body.get(),
586 resource_context_, &blob_handles_);
kinuko69732972017-05-29 08:50:07587 }
588
589 // Requests to WebUI scheme won't get redirected to/from other schemes
590 // or be intercepted, so we just let it go here.
591 if (factory_for_webui.is_valid()) {
yzshenefcb7c72017-06-16 23:12:30592 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
Antonio Gomes9cdc09a2018-05-07 23:24:26593 base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
Yuzhu Shend87986f2018-01-17 22:16:37594 std::move(factory_for_webui)),
Ken Rockot5f734e32018-06-13 01:41:03595 CreateURLLoaderThrottles(), 0 /* routing_id */,
596 global_request_id_.request_id, network::mojom::kURLLoadOptionNone,
597 resource_request_.get(), this, kNavigationUrlLoaderTrafficAnnotation,
Hajime Hoshif5ef35262017-11-28 19:13:00598 base::ThreadTaskRunnerHandle::Get());
kinuko69732972017-05-29 08:50:07599 return;
600 }
601
Marijn Kruisselbrink07bf59d52018-04-03 21:50:25602 // Requests to Blob scheme won't get redirected to/from other schemes
603 // or be intercepted, so we just let it go here.
604 if (request_info->common_params.url.SchemeIsBlob() &&
605 request_info->blob_url_loader_factory) {
606 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
607 network::SharedURLLoaderFactory::Create(
608 std::move(request_info->blob_url_loader_factory)),
Ken Rockot5f734e32018-06-13 01:41:03609 CreateURLLoaderThrottles(), 0 /* routing_id */,
610 global_request_id_.request_id, network::mojom::kURLLoadOptionNone,
611 resource_request_.get(), this, kNavigationUrlLoaderTrafficAnnotation,
Marijn Kruisselbrink07bf59d52018-04-03 21:50:25612 base::ThreadTaskRunnerHandle::Get());
613 return;
614 }
615
kinuko69732972017-05-29 08:50:07616 if (service_worker_navigation_handle_core) {
Kinuko Yasuda7f3e1722018-03-26 08:58:58617 std::unique_ptr<NavigationLoaderInterceptor> service_worker_interceptor =
Makoto Shimazu44c2c3232018-03-30 01:10:20618 CreateServiceWorkerInterceptor(*request_info,
619 service_worker_navigation_handle_core);
Kinuko Yasuda7f3e1722018-03-26 08:58:58620 if (service_worker_interceptor)
621 interceptors_.push_back(std::move(service_worker_interceptor));
kinuko69732972017-05-29 08:50:07622 }
623
624 if (appcache_handle_core) {
Kinuko Yasuda7f3e1722018-03-26 08:58:58625 std::unique_ptr<NavigationLoaderInterceptor> appcache_interceptor =
anantaa2c8ec62017-06-09 23:44:05626 AppCacheRequestHandler::InitializeForNavigationNetworkService(
anantae60d1d42017-06-20 04:16:27627 *resource_request_, appcache_handle_core,
Kinuko Yasudabe4ad292018-07-06 01:33:39628 network_loader_factory_);
Kinuko Yasuda7f3e1722018-03-26 08:58:58629 if (appcache_interceptor)
630 interceptors_.push_back(std::move(appcache_interceptor));
kinuko69732972017-05-29 08:50:07631 }
632
Tsuyoshi Horo46f5fff2018-05-10 12:33:35633 if (signed_exchange_utils::IsSignedExchangeHandlingEnabled()) {
Kunihiko Sakamotoe9a0502c2018-06-06 09:29:51634 // Signed Exchange is currently disabled when Network Service is enabled
Kunihiko Sakamotoe6aa22e2018-06-15 03:26:55635 // (https://crbug.com/849935), but still create
636 // SignedExchangeRequestHandler in order to show error message (and
637 // devtools warning) to users.
Kunihiko Sakamotoe9a0502c2018-06-06 09:29:51638
Tsuyoshi Horo561163b2018-03-27 03:11:23639 // It is safe to pass the callback of CreateURLLoaderThrottles with the
Tsuyoshi Horo70014ad2018-02-14 11:20:14640 // unretained |this|, because the passed callback will be used by a
641 // SignedExchangeHandler which is indirectly owned by |this| until its
642 // header is verified and parsed, that's where the getter is used.
Kunihiko Sakamotoe6aa22e2018-06-15 03:26:55643 interceptors_.push_back(std::make_unique<SignedExchangeRequestHandler>(
Tsuyoshi Horo70014ad2018-02-14 11:20:14644 url::Origin::Create(request_info->common_params.url),
Tsuyoshi Horo32b51f12018-05-09 17:58:46645 request_info->common_params.url,
Kinuko Yasuda32a25652018-02-19 08:14:25646 GetURLLoaderOptions(request_info->is_main_frame),
Tsuyoshi Horocdbb4902018-04-12 06:09:14647 request_info->frame_tree_node_id,
Tsuyoshi Horo32b51f12018-05-09 17:58:46648 request_info->devtools_navigation_token,
Tsuyoshi Horob8d381182018-06-19 10:07:29649 request_info->devtools_frame_token, request_info->report_raw_headers,
Kinuko Yasudabe4ad292018-07-06 01:33:39650 request_info->begin_params->load_flags, network_loader_factory_,
Tsuyoshi Horo70014ad2018-02-14 11:20:14651 base::BindRepeating(
652 &URLLoaderRequestController::CreateURLLoaderThrottles,
Tsuyoshi Horof7702192018-03-07 15:00:36653 base::Unretained(this)),
654 url_request_context_getter));
Tsuyoshi Horob8d512a2018-01-25 17:01:59655 }
656
Jian Li18e29242018-05-10 22:25:12657 std::vector<std::unique_ptr<URLLoaderRequestInterceptor>>
658 browser_interceptors = GetContentClient()
659 ->browser()
660 ->WillCreateURLLoaderRequestInterceptors(
661 navigation_ui_data_.get(),
662 request_info->frame_tree_node_id);
663 if (!browser_interceptors.empty()) {
664 for (auto& browser_interceptor : browser_interceptors) {
665 interceptors_.push_back(
666 std::make_unique<NavigationLoaderInterceptorBrowserContainer>(
667 std::move(browser_interceptor)));
668 }
669 }
670
yzshenefcb7c72017-06-16 23:12:30671 Restart();
kinuko69732972017-05-29 08:50:07672 }
673
Michael Nordman2431f5f2017-09-13 04:58:15674 // This could be called multiple times to follow a chain of redirects.
yzshenefcb7c72017-06-16 23:12:30675 void Restart() {
Kinuko Yasuda7f3e1722018-03-26 08:58:58676 DCHECK(IsLoaderInterceptionEnabled());
Tsuyoshi Horo5204c872017-09-21 16:28:17677 // Clear |url_loader_| if it's not the default one (network). This allows
678 // the restarted request to use a new loader, instead of, e.g., reusing the
679 // AppCache or service worker loader. For an optimization, we keep and reuse
Kinuko Yasuda7f3e1722018-03-26 08:58:58680 // the default url loader if the all |interceptors_| doesn't handle the
Tsuyoshi Horo5204c872017-09-21 16:28:17681 // redirected request.
682 if (!default_loader_used_)
683 url_loader_.reset();
Kinuko Yasuda7f3e1722018-03-26 08:58:58684 interceptor_index_ = 0;
anantab9800e52017-07-29 18:04:13685 received_response_ = false;
Kinuko Yasuda7f3e1722018-03-26 08:58:58686 MaybeStartLoader(nullptr /* interceptor */,
687 {} /* single_request_handler */);
kinuko69732972017-05-29 08:50:07688 }
689
Kinuko Yasuda7f3e1722018-03-26 08:58:58690 // |interceptor| is non-null if this is called by one of the interceptors
691 // (via a LoaderCallback).
692 // |single_request_handler| is the RequestHandler given by the |interceptor|,
693 // non-null if the interceptor wants to handle the request.
Ken Rockot387ddd5a2018-01-30 19:18:40694 void MaybeStartLoader(
Kinuko Yasuda7f3e1722018-03-26 08:58:58695 NavigationLoaderInterceptor* interceptor,
Ken Rockot387ddd5a2018-01-30 19:18:40696 SingleRequestURLLoaderFactory::RequestHandler single_request_handler) {
Matt Falkenhagenf03034d92018-07-06 06:50:43697 // Temporary CHECKs for https://crbug.com/857005.
698 CHECK(IsLoaderInterceptionEnabled());
699 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
700 CHECK(started_);
Ken Rockot387ddd5a2018-01-30 19:18:40701 if (single_request_handler) {
Kinuko Yasuda7f3e1722018-03-26 08:58:58702 // |interceptor| wants to handle the request with
703 // |single_request_handler|.
704 DCHECK(interceptor);
Michael Nordman2431f5f2017-09-13 04:58:15705 default_loader_used_ = false;
yzshenefcb7c72017-06-16 23:12:30706 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
Ken Rockot387ddd5a2018-01-30 19:18:40707 base::MakeRefCounted<SingleRequestURLLoaderFactory>(
708 std::move(single_request_handler)),
Ken Rockot5f734e32018-06-13 01:41:03709 CreateURLLoaderThrottles(), frame_tree_node_id_,
710 global_request_id_.request_id, network::mojom::kURLLoadOptionNone,
711 resource_request_.get(), this, kNavigationUrlLoaderTrafficAnnotation,
Hajime Hoshif5ef35262017-11-28 19:13:00712 base::ThreadTaskRunnerHandle::Get());
anantae60d1d42017-06-20 04:16:27713
Kinuko Yasuda250577c2017-10-29 02:51:24714 subresource_loader_params_ =
Kinuko Yasuda7f3e1722018-03-26 08:58:58715 interceptor->MaybeCreateSubresourceLoaderParams();
Kinuko Yasuda8757204a2017-11-04 07:50:13716
kinuko69732972017-05-29 08:50:07717 return;
718 }
719
Kinuko Yasuda7f3e1722018-03-26 08:58:58720 // Before falling back to the next interceptor, see if |interceptor| still
721 // wants to give additional info to the frame for subresource loading. In
722 // that case we will just fall back to the default loader (i.e. won't go on
723 // to the next interceptors) but send the subresource_loader_params to the
724 // child process. This is necessary for correctness in the cases where, e.g.
725 // there's a controlling ServiceWorker that doesn't handle main resource
726 // loading, but may still want to control the page and/or handle subresource
727 // loading. In that case we want to skip AppCache.
728 if (interceptor) {
Kinuko Yasuda8757204a2017-11-04 07:50:13729 subresource_loader_params_ =
Kinuko Yasuda7f3e1722018-03-26 08:58:58730 interceptor->MaybeCreateSubresourceLoaderParams();
Kinuko Yasuda8757204a2017-11-04 07:50:13731
732 // If non-null |subresource_loader_params_| is returned, make sure
Kinuko Yasuda7f3e1722018-03-26 08:58:58733 // we skip the next interceptors.
Kinuko Yasuda8757204a2017-11-04 07:50:13734 if (subresource_loader_params_)
Kinuko Yasuda7f3e1722018-03-26 08:58:58735 interceptor_index_ = interceptors_.size();
Kinuko Yasuda8757204a2017-11-04 07:50:13736 }
737
Kinuko Yasuda7f3e1722018-03-26 08:58:58738 // See if the next interceptor wants to handle the request.
739 if (interceptor_index_ < interceptors_.size()) {
740 auto* next_interceptor = interceptors_[interceptor_index_++].get();
741 next_interceptor->MaybeCreateLoader(
kinuko69732972017-05-29 08:50:07742 *resource_request_, resource_context_,
743 base::BindOnce(&URLLoaderRequestController::MaybeStartLoader,
Kinuko Yasuda7f3e1722018-03-26 08:58:58744 base::Unretained(this), next_interceptor));
kinuko69732972017-05-29 08:50:07745 return;
746 }
747
Kinuko Yasuda7f3e1722018-03-26 08:58:58748 // If we already have the default |url_loader_| we must come here after
749 // a redirect. No interceptors wanted to intercept the redirected request,
750 // so let it just follow the redirect.
Michael Nordman2431f5f2017-09-13 04:58:15751 if (url_loader_) {
752 DCHECK(!redirect_info_.new_url.is_empty());
Chong Zhang7607f1f2018-06-01 20:52:20753 url_loader_->FollowRedirect(
754 std::move(url_loader_modified_request_headers_));
Michael Nordman2431f5f2017-09-13 04:58:15755 return;
756 }
757
Ken Rockota0dfaca12018-02-15 07:26:25758 // TODO(https://crbug.com/796425): We temporarily wrap raw
759 // mojom::URLLoaderFactory pointers into SharedURLLoaderFactory. Need to
760 // further refactor the factory getters to avoid this.
Chong Zhangb7c8d1ce2018-03-13 19:14:11761 scoped_refptr<network::SharedURLLoaderFactory> factory;
Kinuko Yasuda7f3e1722018-03-26 08:58:58762 DCHECK_EQ(interceptors_.size(), interceptor_index_);
Makoto Shimazu44c2c3232018-03-30 01:10:20763
764 // If NetworkService is not enabled (which means we come here because one of
765 // the loader interceptors is enabled), use the default request handler
766 // instead of going through the NetworkService path.
767 if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
768 DCHECK(!interceptors_.empty());
769 DCHECK(default_request_handler_factory_);
Makoto Shimazu684a5ad2018-05-29 08:20:50770 // The only way to come here is to enable ServiceWorkerServicification
771 // without NetworkService. We know that the service worker's request
772 // interceptor has already intercepted and decided not to handle the
773 // request.
774 DCHECK(ServiceWorkerUtils::IsServicificationEnabled());
Makoto Shimazu44c2c3232018-03-30 01:10:20775 default_loader_used_ = true;
776 // Update |request_info_| when following a redirect.
777 if (url_chain_.size() > 0) {
778 request_info_ = CreateNavigationRequestInfoForRedirect(
779 *request_info_, *resource_request_);
780 }
Makoto Shimazu684a5ad2018-05-29 08:20:50781 // When |subresource_loader_params_| has its value, the request should not
782 // be intercepted by any other interceptors since it means that a request
783 // interceptor already intercepted the request and it attached its info to
784 // the request.
Makoto Shimazu44c2c3232018-03-30 01:10:20785 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
786 base::MakeRefCounted<SingleRequestURLLoaderFactory>(
Makoto Shimazu684a5ad2018-05-29 08:20:50787 default_request_handler_factory_.Run(
788 subresource_loader_params_.has_value()
789 /* was_request_intercepted */)),
Ken Rockot5f734e32018-06-13 01:41:03790 CreateURLLoaderThrottles(), frame_tree_node_id_,
791 global_request_id_.request_id, network::mojom::kURLLoadOptionNone,
792 resource_request_.get(), this /* client */,
793 kNavigationUrlLoaderTrafficAnnotation,
Makoto Shimazu44c2c3232018-03-30 01:10:20794 base::ThreadTaskRunnerHandle::Get());
795 return;
796 }
797
Marijn Kruisselbrink0c87e6e2018-06-22 22:57:39798 if (!IsURLHandledByNetworkService(resource_request_->url) &&
799 !resource_request_->url.SchemeIs(url::kDataScheme)) {
John Abd-El-Maleka67add82018-03-09 18:22:01800 if (known_schemes_.find(resource_request_->url.scheme()) ==
801 known_schemes_.end()) {
802 bool handled = GetContentClient()->browser()->HandleExternalProtocol(
803 resource_request_->url, web_contents_getter_,
804 ChildProcessHost::kInvalidUniqueID, navigation_ui_data_.get(),
805 resource_request_->resource_type == RESOURCE_TYPE_MAIN_FRAME,
806 static_cast<ui::PageTransition>(resource_request_->transition_type),
807 resource_request_->has_user_gesture);
808 factory = base::MakeRefCounted<SingleRequestURLLoaderFactory>(
809 base::BindOnce(UnknownSchemeCallback, handled));
810 } else {
811 network::mojom::URLLoaderFactoryPtr& non_network_factory =
812 non_network_url_loader_factories_[resource_request_->url.scheme()];
813 if (!non_network_factory.is_bound()) {
814 BrowserThread::PostTask(
815 BrowserThread::UI, FROM_HERE,
arthursonzogni1fd60e62018-05-09 15:57:32816 base::BindOnce(&NavigationURLLoaderImpl ::
John Abd-El-Maleka67add82018-03-09 18:22:01817 BindNonNetworkURLLoaderFactoryRequest,
818 owner_, frame_tree_node_id_,
819 resource_request_->url,
820 mojo::MakeRequest(&non_network_factory)));
821 }
Antonio Gomes9cdc09a2018-05-07 23:24:26822 factory =
823 base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
824 non_network_factory.get());
Ken Rockot314714c2017-11-05 23:36:24825 }
jam9354af82017-06-03 21:59:41826 } else {
anantab9800e52017-07-29 18:04:13827 default_loader_used_ = true;
Ken Rockota0dfaca12018-02-15 07:26:25828
829 // NOTE: We only support embedders proxying network-service-bound requests
Kinuko Yasuda7f3e1722018-03-26 08:58:58830 // not handled by NavigationLoaderInterceptors above (e.g. Service Worker
831 // or AppCache). Hence this code is only reachable when one of the above
832 // interceptors isn't used and the URL is either a data URL or has a
833 // scheme which is handled by the network service. We explicitly avoid
834 // proxying the data URL case here.
Ken Rockota0dfaca12018-02-15 07:26:25835 if (proxied_factory_request_.is_pending() &&
836 !resource_request_->url.SchemeIs(url::kDataScheme)) {
837 DCHECK(proxied_factory_info_.is_valid());
Chong Zhang70432e32018-03-07 04:43:52838 // We don't worry about reconnection since it's a single navigation.
Kinuko Yasudabe4ad292018-07-06 01:33:39839 network_loader_factory_->Clone(std::move(proxied_factory_request_));
Antonio Gomes9cdc09a2018-05-07 23:24:26840 factory = base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
Ken Rockota0dfaca12018-02-15 07:26:25841 std::move(proxied_factory_info_));
842 } else {
Kinuko Yasudabe4ad292018-07-06 01:33:39843 factory = network_loader_factory_;
Ken Rockota0dfaca12018-02-15 07:26:25844 }
jam9354af82017-06-03 21:59:41845 }
Min Qin83d07872017-10-26 23:22:41846 url_chain_.push_back(resource_request_->url);
arthursonzognib521c6a2018-01-08 12:23:40847 uint32_t options = GetURLLoaderOptions(resource_request_->resource_type ==
848 RESOURCE_TYPE_MAIN_FRAME);
yzshenefcb7c72017-06-16 23:12:30849 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
Ken Rockota0dfaca12018-02-15 07:26:25850 factory, CreateURLLoaderThrottles(), frame_tree_node_id_,
Ken Rockot5f734e32018-06-13 01:41:03851 global_request_id_.request_id, options, resource_request_.get(), this,
Tsuyoshi Horo70014ad2018-02-14 11:20:14852 kNavigationUrlLoaderTrafficAnnotation,
Hajime Hoshif5ef35262017-11-28 19:13:00853 base::ThreadTaskRunnerHandle::Get());
kinuko69732972017-05-29 08:50:07854 }
855
Chong Zhang7607f1f2018-06-01 20:52:20856 void FollowRedirect(
857 const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
yzshenefcb7c72017-06-16 23:12:30858 DCHECK_CURRENTLY_ON(BrowserThread::IO);
Michael Nordman2431f5f2017-09-13 04:58:15859 DCHECK(!redirect_info_.new_url.is_empty());
arthursonzogni2695d04d2017-12-12 08:39:01860
Kinuko Yasuda7f3e1722018-03-26 08:58:58861 if (!IsLoaderInterceptionEnabled()) {
Chong Zhang7607f1f2018-06-01 20:52:20862 url_loader_->FollowRedirect(modified_request_headers);
arthursonzogni2695d04d2017-12-12 08:39:01863 return;
864 }
anantab9800e52017-07-29 18:04:13865
Kinuko Yasuda7f3e1722018-03-26 08:58:58866 // Update |resource_request_| and call Restart to give our |interceptors_| a
867 // chance at handling the new location. If no interceptor wants to take
868 // over, we'll use the existing url_loader to follow the redirect, see
869 // MaybeStartLoader.
Michael Nordman2431f5f2017-09-13 04:58:15870 // TODO(michaeln): This is still WIP and is based on URLRequest::Redirect,
871 // there likely remains more to be done.
872 // a. For subframe navigations, the Origin header may need to be modified
873 // differently?
874 // b. How should redirect_info_.referred_token_binding_host be handled?
Michael Nordman2431f5f2017-09-13 04:58:15875
Tsuyoshi Horo9e2ec4df2017-10-16 15:15:55876 bool should_clear_upload = false;
877 net::RedirectUtil::UpdateHttpRequest(
878 resource_request_->url, resource_request_->method, redirect_info_,
Chong Zhang7607f1f2018-06-01 20:52:20879 modified_request_headers, &resource_request_->headers,
880 &should_clear_upload);
Tsuyoshi Horo9e2ec4df2017-10-16 15:15:55881 if (should_clear_upload) {
Michael Nordman2431f5f2017-09-13 04:58:15882 // The request body is no longer applicable.
883 resource_request_->request_body = nullptr;
884 blob_handles_.clear();
885 }
886
Michael Nordman2431f5f2017-09-13 04:58:15887 resource_request_->url = redirect_info_.new_url;
Tsuyoshi Horo9e2ec4df2017-10-16 15:15:55888 resource_request_->method = redirect_info_.new_method;
Michael Nordman2431f5f2017-09-13 04:58:15889 resource_request_->site_for_cookies = redirect_info_.new_site_for_cookies;
890 resource_request_->referrer = GURL(redirect_info_.new_referrer);
John Abd-El-Malekb77d22fb72017-12-22 17:34:48891 resource_request_->referrer_policy = redirect_info_.new_referrer_policy;
Min Qin83d07872017-10-26 23:22:41892 url_chain_.push_back(redirect_info_.new_url);
Michael Nordman2431f5f2017-09-13 04:58:15893
Chong Zhang7607f1f2018-06-01 20:52:20894 // Need to cache modified headers for |url_loader_| since it doesn't use
895 // |resource_request_| during redirect.
896 url_loader_modified_request_headers_ = modified_request_headers;
897
Michael Nordman2431f5f2017-09-13 04:58:15898 Restart();
yzshenefcb7c72017-06-16 23:12:30899 }
900
Kinuko Yasuda250577c2017-10-29 02:51:24901 base::Optional<SubresourceLoaderParams> TakeSubresourceLoaderParams() {
902 return std::move(subresource_loader_params_);
anantae60d1d42017-06-20 04:16:27903 }
904
kinuko69732972017-05-29 08:50:07905 private:
John Abd-El-Malekb165dc52018-01-18 17:12:18906 // network::mojom::URLLoaderClient implementation:
Marijn Kruisselbrink9ebd7ba2018-06-11 23:18:04907 void OnReceiveResponse(const network::ResourceResponseHead& head) override {
anantab9800e52017-07-29 18:04:13908 received_response_ = true;
arthursonzogni2695d04d2017-12-12 08:39:01909
anantab9800e52017-07-29 18:04:13910 // If the default loader (network) was used to handle the URL load request
Kinuko Yasuda7f3e1722018-03-26 08:58:58911 // we need to see if the interceptors want to potentially create a new
912 // loader for the response. e.g. AppCache.
anantab9800e52017-07-29 18:04:13913 if (MaybeCreateLoaderForResponse(head))
914 return;
arthursonzogni3a4ca9f2017-12-07 17:58:34915
John Abd-El-Malekb165dc52018-01-18 17:12:18916 network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints;
John Abd-El-Malekecc6f5f2018-03-02 18:47:39917
918 // Currently only plugin handlers may intercept the response. Don't treat
919 // the response as download if it has been handled by plugins.
920 bool response_intercepted = false;
arthursonzogni3a4ca9f2017-12-07 17:58:34921 if (url_loader_) {
922 url_loader_client_endpoints = url_loader_->Unbind();
John Abd-El-Malekecc6f5f2018-03-02 18:47:39923 response_intercepted = url_loader_->response_intercepted();
arthursonzogni3a4ca9f2017-12-07 17:58:34924 } else {
John Abd-El-Malekb165dc52018-01-18 17:12:18925 url_loader_client_endpoints =
926 network::mojom::URLLoaderClientEndpoints::New(
927 response_url_loader_.PassInterface(),
928 response_loader_binding_.Unbind());
arthursonzogni3a4ca9f2017-12-07 17:58:34929 }
930
arthursonzogni40db5f52018-01-08 16:38:49931 bool is_download;
932 bool is_stream;
933 std::unique_ptr<NavigationData> cloned_navigation_data;
Kinuko Yasuda7f3e1722018-03-26 08:58:58934 if (IsLoaderInterceptionEnabled()) {
Robbie McElratha5adc4e2018-07-03 23:53:09935 bool must_download = download_utils::MustDownload(
Jochen Eisinger7678c8ac2018-05-07 15:47:34936 url_, head.headers.get(), head.mime_type);
John Abd-El-Malek3ebdff862018-04-23 18:57:21937 bool known_mime_type = blink::IsSupportedMimeType(head.mime_type);
938
939#if BUILDFLAG(ENABLE_PLUGINS)
940 if (!response_intercepted && !must_download && !known_mime_type) {
941 CheckPluginAndContinueOnReceiveResponse(
Marijn Kruisselbrink9ebd7ba2018-06-11 23:18:04942 head, std::move(url_loader_client_endpoints),
John Abd-El-Malek3ebdff862018-04-23 18:57:21943 std::vector<WebPluginInfo>());
944 return;
945 }
946#endif
947
948 is_download =
949 !response_intercepted && (must_download || !known_mime_type);
arthursonzogni40db5f52018-01-08 16:38:49950 is_stream = false;
951 } else {
952 ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get();
953 net::URLRequest* url_request = rdh->GetURLRequest(global_request_id_);
arthursonzognib1de19fa2018-04-03 19:55:10954
955 // The |url_request| maybe have been removed from the resource dispatcher
John Abd-El-Malek739997242018-05-01 19:48:25956 // host during the time it took for OnReceiveResponse() to be received.
957 if (url_request) {
958 ResourceRequestInfoImpl* info =
959 ResourceRequestInfoImpl::ForRequest(url_request);
960 is_download = !response_intercepted && info->IsDownload();
961 is_stream = info->is_stream();
962 if (rdh->delegate()) {
963 NavigationData* navigation_data =
964 rdh->delegate()->GetNavigationData(url_request);
arthursonzognib1de19fa2018-04-03 19:55:10965
John Abd-El-Malek739997242018-05-01 19:48:25966 // Clone the embedder's NavigationData before moving it to the UI
967 // thread.
968 if (navigation_data)
969 cloned_navigation_data = navigation_data->Clone();
970 }
arthursonzogni40db5f52018-01-08 16:38:49971
John Abd-El-Malek739997242018-05-01 19:48:25972 // This is similar to what is done in
973 // ServiceWorkerControlleeHandler::MaybeCreateSubresourceLoaderParams().
974 // It takes the matching ControllerServiceWorkerInfo (if any) associated
975 // with the request. It will be sent to the renderer process and used to
976 // intercept requests.
977 // TODO(arthursonzogni): This is needed only for the
978 // non-S13nServiceWorker case. The S13nServiceWorker case is still not
979 // supported without the NetworkService. This block needs to be updated
980 // once support for it will be added.
981 ServiceWorkerProviderHost* sw_provider_host =
982 ServiceWorkerRequestHandler::GetProviderHost(url_request);
983 if (sw_provider_host && sw_provider_host->controller()) {
984 subresource_loader_params_ = SubresourceLoaderParams();
985 subresource_loader_params_->controller_service_worker_info =
986 mojom::ControllerServiceWorkerInfo::New();
Matt Falkenhagen98515e972018-06-20 08:12:48987 subresource_loader_params_->controller_service_worker_info->mode =
988 sw_provider_host->GetControllerMode();
Richardbc7bb1c72018-06-13 09:01:49989 base::WeakPtr<ServiceWorkerObjectHost> sw_object_host =
990 sw_provider_host->GetOrCreateServiceWorkerObjectHost(
Han Leone80f5c9a2018-05-12 04:22:36991 sw_provider_host->controller());
Richardbc7bb1c72018-06-13 09:01:49992 if (sw_object_host) {
993 subresource_loader_params_->controller_service_worker_object_host =
994 sw_object_host;
Han Leone80f5c9a2018-05-12 04:22:36995 subresource_loader_params_->controller_service_worker_info
Richardbc7bb1c72018-06-13 09:01:49996 ->object_info = sw_object_host->CreateIncompleteObjectInfo();
Han Leone80f5c9a2018-05-12 04:22:36997 }
John Abd-El-Malek739997242018-05-01 19:48:25998 }
999 } else {
1000 is_download = is_stream = false;
arthursonzognib950d902018-02-08 09:27:131001 }
arthursonzogni40db5f52018-01-08 16:38:491002 }
1003
Marijn Kruisselbrink9ebd7ba2018-06-11 23:18:041004 CallOnReceivedResponse(head, std::move(url_loader_client_endpoints),
John Abd-El-Malek3ebdff862018-04-23 18:57:211005 std::move(cloned_navigation_data), is_download,
1006 is_stream);
1007 }
1008
1009#if BUILDFLAG(ENABLE_PLUGINS)
1010 void CheckPluginAndContinueOnReceiveResponse(
1011 const network::ResourceResponseHead& head,
John Abd-El-Malek3ebdff862018-04-23 18:57:211012 network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
1013 const std::vector<WebPluginInfo>& plugins) {
1014 bool stale;
1015 WebPluginInfo plugin;
1016 // It's ok to pass -1 for the render process and frame ID since that's
1017 // only used for plugin overridding. We don't actually care if we get an
1018 // overridden plugin or not, since all we care about is the presence of a
1019 // plugin. Note that this is what the MimeSniffingResourceHandler code
1020 // path does as well for navigations.
1021 bool has_plugin = PluginService::GetInstance()->GetPluginInfo(
1022 -1 /* render_process_id */, -1 /* render_frame_id */, resource_context_,
1023 resource_request_->url, url::Origin(), head.mime_type,
1024 false /* allow_wildcard */, &stale, &plugin, nullptr);
1025
1026 if (stale) {
1027 // Refresh the plugins asynchronously.
1028 PluginService::GetInstance()->GetPlugins(base::BindOnce(
1029 &URLLoaderRequestController::CheckPluginAndContinueOnReceiveResponse,
Marijn Kruisselbrink9ebd7ba2018-06-11 23:18:041030 weak_factory_.GetWeakPtr(), head,
John Abd-El-Malek3ebdff862018-04-23 18:57:211031 std::move(url_loader_client_endpoints)));
1032 return;
1033 }
1034
1035 bool is_download =
1036 !has_plugin &&
1037 (!head.headers || head.headers->response_code() / 100 == 2);
1038
Marijn Kruisselbrink9ebd7ba2018-06-11 23:18:041039 CallOnReceivedResponse(head, std::move(url_loader_client_endpoints),
1040 nullptr, is_download, false /* is_stream */);
John Abd-El-Malek3ebdff862018-04-23 18:57:211041 }
1042#endif
1043
1044 void CallOnReceivedResponse(
1045 const network::ResourceResponseHead& head,
John Abd-El-Malek3ebdff862018-04-23 18:57:211046 network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
1047 std::unique_ptr<NavigationData> cloned_navigation_data,
1048 bool is_download,
1049 bool is_stream) {
1050 scoped_refptr<network::ResourceResponse> response(
1051 new network::ResourceResponse());
1052 response->head = head;
1053
Andrey Kosyakova924c8b2017-08-18 17:37:231054 // Make a copy of the ResourceResponse before it is passed to another
1055 // thread.
1056 //
1057 // TODO(davidben): This copy could be avoided if ResourceResponse weren't
1058 // reference counted and the loader stack passed unique ownership of the
1059 // response. https://crbug.com/416050
yzshenefcb7c72017-06-16 23:12:301060 BrowserThread::PostTask(
1061 BrowserThread::UI, FROM_HERE,
arthursonzogni1fd60e62018-05-09 15:57:321062 base::BindOnce(&NavigationURLLoaderImpl::OnReceiveResponse, owner_,
1063 response->DeepCopy(),
arthursonzogni40db5f52018-01-08 16:38:491064 std::move(url_loader_client_endpoints),
Andrey Kosyakov87cd9252018-03-27 16:58:271065 std::move(cloned_navigation_data), global_request_id_,
Marijn Kruisselbrink9ebd7ba2018-06-11 23:18:041066 is_download, is_stream));
yzshenefcb7c72017-06-16 23:12:301067 }
1068
1069 void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
John Abd-El-Malek46248032018-01-17 19:11:231070 const network::ResourceResponseHead& head) override {
Michael Nordman2431f5f2017-09-13 04:58:151071 if (--redirect_limit_ == 0) {
Takashi Toyoshimaaa278662017-11-20 11:11:261072 OnComplete(
1073 network::URLLoaderCompletionStatus(net::ERR_TOO_MANY_REDIRECTS));
Michael Nordman2431f5f2017-09-13 04:58:151074 return;
1075 }
1076
1077 // Store the redirect_info for later use in FollowRedirect where we give
Kinuko Yasuda7f3e1722018-03-26 08:58:581078 // our interceptors_ a chance to intercept the request for the new location.
Michael Nordman2431f5f2017-09-13 04:58:151079 redirect_info_ = redirect_info;
1080
John Abd-El-Malek46248032018-01-17 19:11:231081 scoped_refptr<network::ResourceResponse> response(
1082 new network::ResourceResponse());
Andrey Kosyakova924c8b2017-08-18 17:37:231083 response->head = head;
arthursonzogni40db5f52018-01-08 16:38:491084 url_ = redirect_info.new_url;
Andrey Kosyakova924c8b2017-08-18 17:37:231085
1086 // Make a copy of the ResourceResponse before it is passed to another
1087 // thread.
1088 //
1089 // TODO(davidben): This copy could be avoided if ResourceResponse weren't
1090 // reference counted and the loader stack passed unique ownership of the
1091 // response. https://crbug.com/416050
yzshenefcb7c72017-06-16 23:12:301092 BrowserThread::PostTask(
1093 BrowserThread::UI, FROM_HERE,
arthursonzogni1fd60e62018-05-09 15:57:321094 base::BindOnce(&NavigationURLLoaderImpl::OnReceiveRedirect, owner_,
1095 redirect_info, response->DeepCopy()));
yzshenefcb7c72017-06-16 23:12:301096 }
1097
yzshenefcb7c72017-06-16 23:12:301098 void OnUploadProgress(int64_t current_position,
1099 int64_t total_size,
1100 OnUploadProgressCallback callback) override {}
yzshenefcb7c72017-06-16 23:12:301101 void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override {}
yzshenefcb7c72017-06-16 23:12:301102 void OnTransferSizeUpdated(int32_t transfer_size_diff) override {}
1103
arthursonzogni3a4ca9f2017-12-07 17:58:341104 void OnStartLoadingResponseBody(mojo::ScopedDataPipeConsumerHandle) override {
1105 // Not reached. At this point, the loader and client endpoints must have
1106 // been unbound and forwarded to the renderer.
1107 CHECK(false);
yzshenefcb7c72017-06-16 23:12:301108 }
1109
Takashi Toyoshimaaa278662017-11-20 11:11:261110 void OnComplete(const network::URLLoaderCompletionStatus& status) override {
Emily Starkb09f19a2017-11-22 22:41:471111 UMA_HISTOGRAM_BOOLEAN(
arthursonzognie70c4a042018-05-02 15:49:101112 "Navigation.URLLoaderNetworkService.OnCompleteHasSSLInfo",
Emily Starkb09f19a2017-11-22 22:41:471113 status.ssl_info.has_value());
1114 if (status.ssl_info.has_value()) {
1115 UMA_HISTOGRAM_MEMORY_KB(
1116 "Navigation.URLLoaderNetworkService.OnCompleteCertificateChainsSize",
1117 GetCertificateChainsSizeInKB(status.ssl_info.value()));
1118 }
1119
Takashi Toyoshima8f988532017-11-13 07:32:371120 if (status.error_code != net::OK && !received_response_) {
anantab9800e52017-07-29 18:04:131121 // If the default loader (network) was used to handle the URL load
Kinuko Yasuda7f3e1722018-03-26 08:58:581122 // request we need to see if the interceptors want to potentially create a
anantab9800e52017-07-29 18:04:131123 // new loader for the response. e.g. AppCache.
John Abd-El-Malek46248032018-01-17 19:11:231124 if (MaybeCreateLoaderForResponse(network::ResourceResponseHead()))
anantab9800e52017-07-29 18:04:131125 return;
1126 }
Takashi Toyoshima8f988532017-11-13 07:32:371127 status_ = status;
arthursonzogni2695d04d2017-12-12 08:39:011128
yzshenefcb7c72017-06-16 23:12:301129 BrowserThread::PostTask(
1130 BrowserThread::UI, FROM_HERE,
arthursonzogni1fd60e62018-05-09 15:57:321131 base::BindOnce(&NavigationURLLoaderImpl::OnComplete, owner_, status));
yzshenefcb7c72017-06-16 23:12:301132 }
1133
Kinuko Yasuda7f3e1722018-03-26 08:58:581134 // Returns true if an interceptor wants to handle the response, i.e. return a
Michael Nordman2431f5f2017-09-13 04:58:151135 // different response. For e.g. AppCache may have fallback content.
John Abd-El-Malek46248032018-01-17 19:11:231136 bool MaybeCreateLoaderForResponse(
1137 const network::ResourceResponseHead& response) {
Kinuko Yasuda7f3e1722018-03-26 08:58:581138 if (!IsLoaderInterceptionEnabled())
arthursonzogni2695d04d2017-12-12 08:39:011139 return false;
1140
anantab9800e52017-07-29 18:04:131141 if (!default_loader_used_)
1142 return false;
1143
Kinuko Yasuda7f3e1722018-03-26 08:58:581144 for (auto& interceptor : interceptors_) {
John Abd-El-Malekb165dc52018-01-18 17:12:181145 network::mojom::URLLoaderClientRequest response_client_request;
Kinuko Yasuda7f3e1722018-03-26 08:58:581146 if (interceptor->MaybeCreateLoaderForResponse(
1147 response, &response_url_loader_, &response_client_request,
1148 url_loader_.get())) {
Michael Nordman2431f5f2017-09-13 04:58:151149 response_loader_binding_.Bind(std::move(response_client_request));
1150 default_loader_used_ = false;
1151 url_loader_.reset();
anantab9800e52017-07-29 18:04:131152 return true;
1153 }
1154 }
1155 return false;
1156 }
1157
Tsuyoshi Horo70014ad2018-02-14 11:20:141158 std::vector<std::unique_ptr<content::URLLoaderThrottle>>
1159 CreateURLLoaderThrottles() {
1160 return GetContentClient()->browser()->CreateURLLoaderThrottles(
1161 *resource_request_, resource_context_, web_contents_getter_,
1162 navigation_ui_data_.get(), frame_tree_node_id_);
1163 }
1164
Makoto Shimazu44c2c3232018-03-30 01:10:201165 std::unique_ptr<NavigationLoaderInterceptor> CreateServiceWorkerInterceptor(
1166 const NavigationRequestInfo& request_info,
1167 ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core)
1168 const {
1169 const ResourceType resource_type = request_info.is_main_frame
1170 ? RESOURCE_TYPE_MAIN_FRAME
1171 : RESOURCE_TYPE_SUB_FRAME;
1172 network::mojom::RequestContextFrameType frame_type =
1173 request_info.is_main_frame
1174 ? network::mojom::RequestContextFrameType::kTopLevel
1175 : network::mojom::RequestContextFrameType::kNested;
1176 storage::BlobStorageContext* blob_storage_context = GetBlobStorageContext(
1177 GetChromeBlobStorageContextForResourceContext(resource_context_));
1178 return ServiceWorkerRequestHandler::InitializeForNavigationNetworkService(
1179 *resource_request_, resource_context_,
1180 service_worker_navigation_handle_core, blob_storage_context,
1181 request_info.begin_params->skip_service_worker, resource_type,
1182 request_info.begin_params->request_context_type, frame_type,
1183 request_info.are_ancestors_secure, request_info.common_params.post_data,
1184 web_contents_getter_);
1185 }
1186
Kinuko Yasuda7f3e1722018-03-26 08:58:581187 std::vector<std::unique_ptr<NavigationLoaderInterceptor>> interceptors_;
1188 size_t interceptor_index_ = 0;
kinuko69732972017-05-29 08:50:071189
John Abd-El-Malek1df61792018-01-12 20:40:451190 std::unique_ptr<network::ResourceRequest> resource_request_;
Makoto Shimazu44c2c3232018-03-30 01:10:201191 // Non-NetworkService: |request_info_| is updated along with
1192 // |resource_request_| on redirects.
1193 std::unique_ptr<NavigationRequestInfo> request_info_;
John Abd-El-Malek576c6132017-11-04 00:33:581194 int frame_tree_node_id_ = 0;
arthursonzogni40db5f52018-01-08 16:38:491195 GlobalRequestID global_request_id_;
Michael Nordman2431f5f2017-09-13 04:58:151196 net::RedirectInfo redirect_info_;
Daniel Bratell0dfa6282017-11-08 10:12:231197 int redirect_limit_ = net::URLRequest::kMaxRedirects;
kinuko69732972017-05-29 08:50:071198 ResourceContext* resource_context_;
yzshenefcb7c72017-06-16 23:12:301199 base::Callback<WebContents*()> web_contents_getter_;
John Abd-El-Malekeb1a5382018-01-05 16:58:001200 std::unique_ptr<NavigationUIData> navigation_ui_data_;
Kinuko Yasudabe4ad292018-07-06 01:33:391201 scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory_;
arthursonzogni2695d04d2017-12-12 08:39:011202
yzshenefcb7c72017-06-16 23:12:301203 std::unique_ptr<ThrottlingURLLoader> url_loader_;
arthursonzogni2695d04d2017-12-12 08:39:011204
Chong Zhang7607f1f2018-06-01 20:52:201205 // Caches the modified request headers provided by clients during redirect,
1206 // will be consumed by next |url_loader_->FollowRedirect()|.
1207 base::Optional<net::HttpRequestHeaders> url_loader_modified_request_headers_;
1208
mmenkeed44e6c2017-06-28 21:13:321209 BlobHandles blob_handles_;
Min Qin83d07872017-10-26 23:22:411210 std::vector<GURL> url_chain_;
kinuko69732972017-05-29 08:50:071211
arthursonzogni40db5f52018-01-08 16:38:491212 // Current URL that is being navigated, updated after redirection.
1213 GURL url_;
1214
anantae60d1d42017-06-20 04:16:271215 // Currently used by the AppCache loader to pass its factory to the
1216 // renderer which enables it to handle subresources.
Kinuko Yasuda250577c2017-10-29 02:51:241217 base::Optional<SubresourceLoaderParams> subresource_loader_params_;
anantae60d1d42017-06-20 04:16:271218
mmenkeed44e6c2017-06-28 21:13:321219 // This is referenced only on the UI thread.
arthursonzogni1fd60e62018-05-09 15:57:321220 base::WeakPtr<NavigationURLLoaderImpl> owner_;
mmenkeed44e6c2017-06-28 21:13:321221
anantab9800e52017-07-29 18:04:131222 // Set to true if the default URLLoader (network service) was used for the
1223 // current navigation.
1224 bool default_loader_used_ = false;
1225
1226 // URLLoaderClient binding for loaders created for responses received from the
1227 // network loader.
John Abd-El-Malekb165dc52018-01-18 17:12:181228 mojo::Binding<network::mojom::URLLoaderClient> response_loader_binding_;
anantab9800e52017-07-29 18:04:131229
1230 // URLLoader instance for response loaders, i.e loaders created for handing
1231 // responses received from the network URLLoader.
John Abd-El-Malekb165dc52018-01-18 17:12:181232 network::mojom::URLLoaderPtr response_url_loader_;
anantab9800e52017-07-29 18:04:131233
1234 // Set to true if we receive a valid response from a URLLoader, i.e.
1235 // URLLoaderClient::OnReceivedResponse() is called.
1236 bool received_response_ = false;
1237
Alex Clarke1e08882b32017-10-06 14:22:401238 bool started_ = false;
1239
Ken Rockot314714c2017-11-05 23:36:241240 // Lazily initialized and used in the case of non-network resource
1241 // navigations. Keyed by URL scheme.
John Abd-El-Malekb165dc52018-01-18 17:12:181242 std::map<std::string, network::mojom::URLLoaderFactoryPtr>
Ken Rockot314714c2017-11-05 23:36:241243 non_network_url_loader_factories_;
1244
Makoto Shimazu44c2c3232018-03-30 01:10:201245 // Non-NetworkService:
1246 // Generator of a request handler for sending request to the network. This
1247 // captures all of parameters to create a
1248 // SingleRequestURLLoaderFactory::RequestHandler. Used only when
1249 // NetworkService is disabled but IsLoaderInterceptionEnabled() is true.
Makoto Shimazu684a5ad2018-05-29 08:20:501250 // Set |was_request_intercepted| to true if the request was intercepted by an
1251 // interceptor and the request is falling back to the network. In that case,
1252 // any interceptors won't intercept the request.
1253 base::RepeatingCallback<SingleRequestURLLoaderFactory::RequestHandler(
1254 bool /* was_request_intercepted */)>
Makoto Shimazu44c2c3232018-03-30 01:10:201255 default_request_handler_factory_;
1256
Min Qin40b72172017-09-27 00:19:171257 // The completion status if it has been received. This is needed to handle
1258 // the case that the response is intercepted by download, and OnComplete() is
1259 // already called while we are transferring the |url_loader_| and response
1260 // body to download code.
Takashi Toyoshimaaa278662017-11-20 11:11:261261 base::Optional<network::URLLoaderCompletionStatus> status_;
Min Qin40b72172017-09-27 00:19:171262
Ken Rockota0dfaca12018-02-15 07:26:251263 // Before creating this URLLoaderRequestController on UI thread, the embedder
1264 // may have elected to proxy the URLLoaderFactory request, in which case these
1265 // fields will contain input (info) and output (request) endpoints for the
1266 // proxy. If this controller is handling a request for which proxying is
1267 // supported, requests will be plumbed through these endpoints.
1268 //
1269 // Note that these are only used for requests that go to the Network Service.
1270 network::mojom::URLLoaderFactoryRequest proxied_factory_request_;
1271 network::mojom::URLLoaderFactoryPtrInfo proxied_factory_info_;
1272
John Abd-El-Maleka67add82018-03-09 18:22:011273 // The schemes that this loader can use. For anything else we'll try external
1274 // protocol handlers.
1275 std::set<std::string> known_schemes_;
1276
Makoto Shimazu44c2c3232018-03-30 01:10:201277 mutable base::WeakPtrFactory<URLLoaderRequestController> weak_factory_;
arthursonzogni2695d04d2017-12-12 08:39:011278
kinuko69732972017-05-29 08:50:071279 DISALLOW_COPY_AND_ASSIGN(URLLoaderRequestController);
1280};
1281
Min Qin75ed6df2017-12-01 20:39:151282// TODO(https://crbug.com/790734): pass |navigation_ui_data| along with the
1283// request so that it could be modified.
arthursonzogni1fd60e62018-05-09 15:57:321284NavigationURLLoaderImpl::NavigationURLLoaderImpl(
scottmg69985212017-04-12 16:47:281285 ResourceContext* resource_context,
1286 StoragePartition* storage_partition,
1287 std::unique_ptr<NavigationRequestInfo> request_info,
1288 std::unique_ptr<NavigationUIData> navigation_ui_data,
scottmgd2021c92017-05-15 16:58:051289 ServiceWorkerNavigationHandle* service_worker_navigation_handle,
scottmg69985212017-04-12 16:47:281290 AppCacheNavigationHandle* appcache_handle,
Alex Clarke1e08882b32017-10-06 14:22:401291 NavigationURLLoaderDelegate* delegate,
Kinuko Yasuda7f3e1722018-03-26 08:58:581292 std::vector<std::unique_ptr<NavigationLoaderInterceptor>>
1293 initial_interceptors)
Min Qin37db5102017-09-13 21:21:251294 : delegate_(delegate),
1295 allow_download_(request_info->common_params.allow_download),
1296 weak_factory_(this) {
scottmg95feea52017-04-12 17:51:331297 DCHECK_CURRENTLY_ON(BrowserThread::UI);
John Abd-El-Malekfcb2ecf2017-11-15 23:15:301298 int frame_tree_node_id = request_info->frame_tree_node_id;
ananta5149d8e2017-04-21 00:01:371299
yzshen0f278522017-05-01 17:10:221300 TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP1(
1301 "navigation", "Navigation timeToResponseStarted", this,
kinuko69732972017-05-29 08:50:071302 request_info->common_params.navigation_start, "FrameTreeNode id",
John Abd-El-Malekfcb2ecf2017-11-15 23:15:301303 frame_tree_node_id);
yzshen0f278522017-05-01 17:10:221304
arthursonzogni2695d04d2017-12-12 08:39:011305 ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core =
1306 service_worker_navigation_handle
1307 ? service_worker_navigation_handle->core()
1308 : nullptr;
1309
1310 AppCacheNavigationHandleCore* appcache_handle_core =
1311 appcache_handle ? appcache_handle->core() : nullptr;
1312
Yuzhu Shencb3011f62018-02-08 02:51:501313 std::unique_ptr<network::ResourceRequest> new_request = CreateResourceRequest(
1314 request_info.get(), frame_tree_node_id, allow_download_);
Yutaka Hirano61e41b3c2018-05-31 05:31:061315 new_request->transition_type = request_info->common_params.transition;
Tsuyoshi Horob8d512a2018-01-25 17:01:591316
Yutaka Hiranod8789f92018-01-30 09:59:511317 if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
arthursonzogni2695d04d2017-12-12 08:39:011318 DCHECK(!request_controller_);
1319 request_controller_ = std::make_unique<URLLoaderRequestController>(
Kinuko Yasuda7f3e1722018-03-26 08:58:581320 /* initial_interceptors = */
1321 std::vector<std::unique_ptr<NavigationLoaderInterceptor>>(),
Tsuyoshi Horob8d512a2018-01-25 17:01:591322 std::move(new_request), resource_context,
arthursonzogni40db5f52018-01-08 16:38:491323 request_info->common_params.url,
Ken Rockota0dfaca12018-02-15 07:26:251324 /* proxied_url_loader_factory_request */ nullptr,
John Abd-El-Maleka67add82018-03-09 18:22:011325 /* proxied_url_loader_factory_info */ nullptr, std::set<std::string>(),
arthursonzogni40db5f52018-01-08 16:38:491326 weak_factory_.GetWeakPtr());
arthursonzogni2695d04d2017-12-12 08:39:011327
1328 BrowserThread::PostTask(
1329 BrowserThread::IO, FROM_HERE,
1330 base::BindOnce(
1331 &URLLoaderRequestController::StartWithoutNetworkService,
1332 base::Unretained(request_controller_.get()),
Tsuyoshi Horo70014ad2018-02-14 11:20:141333 base::RetainedRef(storage_partition->GetURLRequestContext()),
arthursonzogni2695d04d2017-12-12 08:39:011334 base::Unretained(storage_partition->GetFileSystemContext()),
1335 base::Unretained(service_worker_navigation_handle_core),
tzikccf160c2018-02-20 12:43:131336 base::Unretained(appcache_handle_core), std::move(request_info),
1337 std::move(navigation_ui_data)));
arthursonzogni2695d04d2017-12-12 08:39:011338 return;
1339 }
1340
scottmgd2021c92017-05-15 16:58:051341 // Check if a web UI scheme wants to handle this request.
Ken Rockot6414c4d92017-11-08 19:58:321342 FrameTreeNode* frame_tree_node =
1343 FrameTreeNode::GloballyFindByID(frame_tree_node_id);
John Abd-El-Malekb165dc52018-01-18 17:12:181344 network::mojom::URLLoaderFactoryPtrInfo factory_for_webui;
scottmgd2021c92017-05-15 16:58:051345 const auto& schemes = URLDataManagerBackend::GetWebUISchemes();
John Abd-El-Malekbb0bc8e2017-11-11 01:08:151346 std::string scheme = new_request->url.scheme();
1347 if (std::find(schemes.begin(), schemes.end(), scheme) != schemes.end()) {
Chris Mumfordbae8a742018-03-01 23:02:231348 factory_for_webui = CreateWebUIURLLoaderBinding(
1349 frame_tree_node->current_frame_host(), scheme)
1350 .PassInterface();
ananta5149d8e2017-04-21 00:01:371351 }
scottmgd2021c92017-05-15 16:58:051352
Ken Rockota0dfaca12018-02-15 07:26:251353 network::mojom::URLLoaderFactoryPtrInfo proxied_factory_info;
1354 network::mojom::URLLoaderFactoryRequest proxied_factory_request;
Chris Mumford942075ad2018-05-19 00:22:041355 auto* partition = static_cast<StoragePartitionImpl*>(storage_partition);
Ken Rockota0dfaca12018-02-15 07:26:251356 if (frame_tree_node) {
1357 // |frame_tree_node| may be null in some unit test environments.
1358 GetContentClient()
1359 ->browser()
1360 ->RegisterNonNetworkNavigationURLLoaderFactories(
John Abd-El-Malekea006302018-05-10 05:50:461361 frame_tree_node_id, &non_network_url_loader_factories_);
Ken Rockota0dfaca12018-02-15 07:26:251362
1363 // The embedder may want to proxy all network-bound URLLoaderFactory
1364 // requests that it can. If it elects to do so, we'll pass its proxy
1365 // endpoints off to the URLLoaderRequestController where wthey will be
1366 // connected if the request type supports proxying.
1367 network::mojom::URLLoaderFactoryPtrInfo factory_info;
1368 auto factory_request = mojo::MakeRequest(&factory_info);
Andrey Kosyakov8d49c5062018-03-15 19:50:491369 bool use_proxy = GetContentClient()->browser()->WillCreateURLLoaderFactory(
Ken Rockot428b1d62018-06-06 17:12:211370 partition->browser_context(), frame_tree_node->current_frame_host(),
1371 true /* is_navigation */, &factory_request);
Andrey Kosyakov8d49c5062018-03-15 19:50:491372 if (RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory(
Jochen Eisingercdc12d12018-05-08 15:07:471373 frame_tree_node->current_frame_host(), true, false,
1374 &factory_request)) {
Andrey Kosyakov8d49c5062018-03-15 19:50:491375 use_proxy = true;
1376 }
1377 if (use_proxy) {
Ken Rockota0dfaca12018-02-15 07:26:251378 proxied_factory_request = std::move(factory_request);
1379 proxied_factory_info = std::move(factory_info);
1380 }
Chris Mumford942075ad2018-05-19 00:22:041381
1382 const std::string storage_domain;
1383 non_network_url_loader_factories_[url::kFileSystemScheme] =
1384 CreateFileSystemURLLoaderFactory(frame_tree_node->current_frame_host(),
1385 /*is_navigation=*/true,
1386 partition->GetFileSystemContext(),
1387 storage_domain);
Ken Rockota0dfaca12018-02-15 07:26:251388 }
1389
John Abd-El-Maleka67add82018-03-09 18:22:011390 non_network_url_loader_factories_[url::kFileScheme] =
1391 std::make_unique<FileURLLoaderFactory>(
1392 partition->browser_context()->GetPath(),
1393 base::CreateSequencedTaskRunnerWithTraits(
1394 {base::MayBlock(), base::TaskPriority::BACKGROUND,
1395 base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}));
1396 std::set<std::string> known_schemes;
1397 for (auto& iter : non_network_url_loader_factories_)
1398 known_schemes.insert(iter.first);
1399
kinuko69732972017-05-29 08:50:071400 DCHECK(!request_controller_);
Jeremy Roman04f27c372017-10-27 15:20:551401 request_controller_ = std::make_unique<URLLoaderRequestController>(
Kinuko Yasuda7f3e1722018-03-26 08:58:581402 std::move(initial_interceptors), std::move(new_request), resource_context,
Kinuko Yasudabe4ad292018-07-06 01:33:391403 request_info->common_params.url, std::move(proxied_factory_request),
1404 std::move(proxied_factory_info), std::move(known_schemes),
1405 weak_factory_.GetWeakPtr());
scottmgd2021c92017-05-15 16:58:051406 BrowserThread::PostTask(
1407 BrowserThread::IO, FROM_HERE,
Ken Rockot387ddd5a2018-01-30 19:18:401408 base::BindOnce(
1409 &URLLoaderRequestController::Start,
1410 base::Unretained(request_controller_.get()),
Tsuyoshi Horo70014ad2018-02-14 11:20:141411 base::RetainedRef(storage_partition->GetURLRequestContext()),
Kinuko Yasudabe4ad292018-07-06 01:33:391412 partition->url_loader_factory_getter()->GetNetworkFactoryInfo(),
Ken Rockot387ddd5a2018-01-30 19:18:401413 service_worker_navigation_handle_core, appcache_handle_core,
1414 std::move(request_info), std::move(navigation_ui_data),
1415 std::move(factory_for_webui), frame_tree_node_id,
1416 ServiceManagerConnection::GetForProcess()->GetConnector()->Clone()));
scottmg69985212017-04-12 16:47:281417}
1418
arthursonzogni1fd60e62018-05-09 15:57:321419NavigationURLLoaderImpl::~NavigationURLLoaderImpl() {
kinuko69732972017-05-29 08:50:071420 BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE,
1421 request_controller_.release());
1422}
scottmg69985212017-04-12 16:47:281423
Chong Zhang7607f1f2018-06-01 20:52:201424void NavigationURLLoaderImpl::FollowRedirect(
Jun Cai605ff0e72018-06-12 22:29:201425 const base::Optional<std::vector<std::string>>&
1426 to_be_removed_request_headers,
Chong Zhang7607f1f2018-06-01 20:52:201427 const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
yzshenefcb7c72017-06-16 23:12:301428 BrowserThread::PostTask(
1429 BrowserThread::IO, FROM_HERE,
tzik0f14f192017-08-15 02:43:331430 base::BindOnce(&URLLoaderRequestController::FollowRedirect,
Chong Zhang7607f1f2018-06-01 20:52:201431 base::Unretained(request_controller_.get()),
1432 modified_request_headers));
scottmg95feea52017-04-12 17:51:331433}
scottmg69985212017-04-12 16:47:281434
arthursonzogni1fd60e62018-05-09 15:57:321435void NavigationURLLoaderImpl::ProceedWithResponse() {}
scottmg69985212017-04-12 16:47:281436
arthursonzogni1fd60e62018-05-09 15:57:321437void NavigationURLLoaderImpl::OnReceiveResponse(
John Abd-El-Malek46248032018-01-17 19:11:231438 scoped_refptr<network::ResourceResponse> response,
John Abd-El-Malekb165dc52018-01-18 17:12:181439 network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
arthursonzogni40db5f52018-01-08 16:38:491440 std::unique_ptr<NavigationData> navigation_data,
1441 const GlobalRequestID& global_request_id,
1442 bool is_download,
Marijn Kruisselbrink9ebd7ba2018-06-11 23:18:041443 bool is_stream) {
arthursonzogni3a4ca9f2017-12-07 17:58:341444 TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", this,
arthursonzogni1fd60e62018-05-09 15:57:321445 "&NavigationURLLoaderImpl", this, "success", true);
arthursonzogni3a4ca9f2017-12-07 17:58:341446
scottmgefb697302017-04-12 22:37:301447 // TODO(scottmg): This needs to do more of what
arthursonzogni3a4ca9f2017-12-07 17:58:341448 // NavigationResourceHandler::OnResponseStarted() does.
arthursonzogni3a4ca9f2017-12-07 17:58:341449
arthursonzogni3a4ca9f2017-12-07 17:58:341450 delegate_->OnResponseStarted(
arthursonzognif34adf092018-04-24 17:06:131451 std::move(response), std::move(url_loader_client_endpoints),
Andrey Kosyakov87cd9252018-03-27 16:58:271452 std::move(navigation_data), global_request_id,
arthursonzogni40db5f52018-01-08 16:38:491453 allow_download_ && is_download, is_stream,
arthursonzogni3a4ca9f2017-12-07 17:58:341454 request_controller_->TakeSubresourceLoaderParams());
scottmg95feea52017-04-12 17:51:331455}
scottmg69985212017-04-12 16:47:281456
arthursonzogni1fd60e62018-05-09 15:57:321457void NavigationURLLoaderImpl::OnReceiveRedirect(
scottmg69985212017-04-12 16:47:281458 const net::RedirectInfo& redirect_info,
John Abd-El-Malek46248032018-01-17 19:11:231459 scoped_refptr<network::ResourceResponse> response) {
scottmg95feea52017-04-12 17:51:331460 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Andrey Kosyakova924c8b2017-08-18 17:37:231461 delegate_->OnRequestRedirected(redirect_info, std::move(response));
scottmg95feea52017-04-12 17:51:331462}
scottmg69985212017-04-12 16:47:281463
arthursonzogni1fd60e62018-05-09 15:57:321464void NavigationURLLoaderImpl::OnComplete(
Takashi Toyoshimaaa278662017-11-20 11:11:261465 const network::URLLoaderCompletionStatus& status) {
Takashi Toyoshima8f988532017-11-13 07:32:371466 if (status.error_code == net::OK)
John Abd-El-Malekb906d282017-08-31 19:36:431467 return;
1468
1469 TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", this,
arthursonzogni1fd60e62018-05-09 15:57:321470 "&NavigationURLLoaderImpl", this, "success", false);
Lucas Garron0efab6d2017-08-30 22:28:511471
Johannes Henkel6a43fef2018-05-17 18:41:521472 delegate_->OnRequestFailed(status);
yzshen384441de2017-04-19 23:26:141473}
scottmg69985212017-04-12 16:47:281474
arthursonzogni1fd60e62018-05-09 15:57:321475void NavigationURLLoaderImpl::SetBeginNavigationInterceptorForTesting(
John Abd-El-Malekdb3a13b2018-05-01 17:52:021476 const BeginNavigationInterceptor& interceptor) {
1477 DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::IO) ||
1478 BrowserThread::CurrentlyOn(BrowserThread::IO));
1479 DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
1480 g_interceptor.Get() = interceptor;
1481}
1482
arthursonzogni1fd60e62018-05-09 15:57:321483void NavigationURLLoaderImpl::OnRequestStarted(base::TimeTicks timestamp) {
arthursonzogni2695d04d2017-12-12 08:39:011484 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1485 delegate_->OnRequestStarted(timestamp);
1486}
1487
arthursonzogni1fd60e62018-05-09 15:57:321488void NavigationURLLoaderImpl::BindNonNetworkURLLoaderFactoryRequest(
Ken Rockota0dfaca12018-02-15 07:26:251489 int frame_tree_node_id,
Ken Rockot314714c2017-11-05 23:36:241490 const GURL& url,
John Abd-El-Malekb165dc52018-01-18 17:12:181491 network::mojom::URLLoaderFactoryRequest factory) {
Ken Rockot314714c2017-11-05 23:36:241492 auto it = non_network_url_loader_factories_.find(url.scheme());
1493 if (it == non_network_url_loader_factories_.end()) {
1494 DVLOG(1) << "Ignoring request with unknown scheme: " << url.spec();
1495 return;
1496 }
Ken Rockota0dfaca12018-02-15 07:26:251497 FrameTreeNode* frame_tree_node =
1498 FrameTreeNode::GloballyFindByID(frame_tree_node_id);
Ken Rockot428b1d62018-06-06 17:12:211499 auto* frame = frame_tree_node->current_frame_host();
Ken Rockota0dfaca12018-02-15 07:26:251500 GetContentClient()->browser()->WillCreateURLLoaderFactory(
Ken Rockot428b1d62018-06-06 17:12:211501 frame->GetSiteInstance()->GetBrowserContext(), frame,
1502 true /* is_navigation */, &factory);
Ken Rockot314714c2017-11-05 23:36:241503 it->second->Clone(std::move(factory));
1504}
1505
scottmg69985212017-04-12 16:47:281506} // namespace content