blob: 1f6a17eb1dd46774b347a3c27dee7ff2fcf9e6b1 [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"
anantaa2c8ec62017-06-09 23:44:0517#include "content/browser/appcache/appcache_request_handler.h"
ananta5149d8e2017-04-21 00:01:3718#include "content/browser/blob_storage/chrome_blob_storage_context.h"
Andrey Kosyakov8d49c5062018-03-15 19:50:4919#include "content/browser/devtools/render_frame_devtools_agent_host.h"
Ken Rockot314714c2017-11-05 23:36:2420#include "content/browser/file_url_loader_factory.h"
Chris Mumford942075ad2018-05-19 00:22:0421#include "content/browser/fileapi/file_system_url_loader_factory.h"
jam8c4edd02017-05-06 18:50:3322#include "content/browser/frame_host/frame_tree_node.h"
scottmg69985212017-04-12 16:47:2823#include "content/browser/frame_host/navigation_request_info.h"
Kinuko Yasuda7f3e1722018-03-26 08:58:5824#include "content/browser/loader/navigation_loader_interceptor.h"
Andrey Kosyakov52a84812018-04-19 05:36:3925#include "content/browser/loader/navigation_loader_util.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"
Tsuyoshi Horob85801592018-02-19 22:18:0737#include "content/browser/web_package/signed_exchange_url_loader_factory_for_non_network_service.h"
Tsuyoshi Horo46f5fff2018-05-10 12:33:3538#include "content/browser/web_package/signed_exchange_utils.h"
Tsuyoshi Horob85801592018-02-19 22:18:0739#include "content/browser/web_package/web_package_request_handler.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"
Makoto Shimazu44c2c3232018-03-30 01:10:2043#include "content/common/service_worker/service_worker_utils.h"
yzshenefcb7c72017-06-16 23:12:3044#include "content/common/throttling_url_loader.h"
jamc1905862017-05-16 14:45:3045#include "content/public/browser/browser_context.h"
scottmg95feea52017-04-12 17:51:3346#include "content/public/browser/browser_thread.h"
yzshenefcb7c72017-06-16 23:12:3047#include "content/public/browser/content_browser_client.h"
scottmgefb697302017-04-12 22:37:3048#include "content/public/browser/global_request_id.h"
Dmitry Skiba7e8c7e22018-01-04 21:04:1849#include "content/public/browser/navigation_data.h"
scottmg69985212017-04-12 16:47:2850#include "content/public/browser/navigation_ui_data.h"
John Abd-El-Malek3ebdff862018-04-23 18:57:2151#include "content/public/browser/plugin_service.h"
arthursonzogni40db5f52018-01-08 16:38:4952#include "content/public/browser/resource_dispatcher_host_delegate.h"
scottmgefb697302017-04-12 22:37:3053#include "content/public/browser/ssl_status.h"
Jian Li18e29242018-05-10 22:25:1254#include "content/public/browser/url_loader_request_interceptor.h"
arthursonzogni2695d04d2017-12-12 08:39:0155#include "content/public/common/content_features.h"
ananta5149d8e2017-04-21 00:01:3756#include "content/public/common/referrer.h"
jam8c4edd02017-05-06 18:50:3357#include "content/public/common/url_constants.h"
Ken Rockot314714c2017-11-05 23:36:2458#include "content/public/common/url_utils.h"
John Abd-El-Malek3ebdff862018-04-23 18:57:2159#include "content/public/common/webplugininfo.h"
ananta5149d8e2017-04-21 00:01:3760#include "net/base/load_flags.h"
Min Qin37db5102017-09-13 21:21:2561#include "net/http/http_content_disposition.h"
Chong Zhang7607f1f2018-06-01 20:52:2062#include "net/http/http_request_headers.h"
rhalavati4cda417b2017-06-12 11:00:2463#include "net/traffic_annotation/network_traffic_annotation.h"
Tsuyoshi Horo9e2ec4df2017-10-16 15:15:5564#include "net/url_request/redirect_util.h"
Daniel Bratell0dfa6282017-11-08 10:12:2365#include "net/url_request/url_request.h"
scottmg69985212017-04-12 16:47:2866#include "net/url_request/url_request_context.h"
Tsuyoshi Horo70014ad2018-02-14 11:20:1467#include "net/url_request/url_request_context_getter.h"
John Abd-El-Malek3ebdff862018-04-23 18:57:2168#include "ppapi/buildflags/buildflags.h"
John Abd-El-Malek89c02ae2018-02-01 01:56:1969#include "services/network/loader_util.h"
Yutaka Hiranod8789f92018-01-30 09:59:5170#include "services/network/public/cpp/features.h"
Antonio Gomes9cdc09a2018-05-07 23:24:2671#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
72#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
Ken Rockot54311e62018-02-10 19:01:5273#include "services/network/public/mojom/request_context_frame_type.mojom.h"
74#include "services/network/public/mojom/url_loader_factory.mojom.h"
yzshenefcb7c72017-06-16 23:12:3075#include "services/service_manager/public/cpp/connector.h"
John Abd-El-Malek3ebdff862018-04-23 18:57:2176#include "third_party/blink/public/common/mime_util/mime_util.h"
scottmg69985212017-04-12 16:47:2877
78namespace content {
79
jambcc67882017-04-28 18:20:0980namespace {
yzshenfa5e57202017-05-02 21:24:1381
Jian Li18e29242018-05-10 22:25:1282class NavigationLoaderInterceptorBrowserContainer
83 : public NavigationLoaderInterceptor {
84 public:
85 explicit NavigationLoaderInterceptorBrowserContainer(
86 std::unique_ptr<URLLoaderRequestInterceptor> browser_interceptor)
87 : browser_interceptor_(std::move(browser_interceptor)) {}
88
89 ~NavigationLoaderInterceptorBrowserContainer() override = default;
90
91 void MaybeCreateLoader(const network::ResourceRequest& resource_request,
92 ResourceContext* resource_context,
93 LoaderCallback callback) override {
94 browser_interceptor_->MaybeCreateLoader(resource_request, resource_context,
95 std::move(callback));
96 }
97
98 private:
99 std::unique_ptr<URLLoaderRequestInterceptor> browser_interceptor_;
100};
101
John Abd-El-Malekdb3a13b2018-05-01 17:52:02102// Only used on the IO thread.
arthursonzogni1fd60e62018-05-09 15:57:32103base::LazyInstance<NavigationURLLoaderImpl::BeginNavigationInterceptor>::Leaky
John Abd-El-Malekdb3a13b2018-05-01 17:52:02104 g_interceptor = LAZY_INSTANCE_INITIALIZER;
105
Kinuko Yasuda7f3e1722018-03-26 08:58:58106// Returns true if interception by NavigationLoaderInterceptors is enabled.
Tsuyoshi Horo46f5fff2018-05-10 12:33:35107// Both ServiceWorkerServicification and SignedExchange require the loader
108// interception. So even if NetworkService is not enabled, returns true when one
109// of them is enabled.
Kinuko Yasuda7f3e1722018-03-26 08:58:58110bool IsLoaderInterceptionEnabled() {
Yutaka Hiranod8789f92018-01-30 09:59:51111 return base::FeatureList::IsEnabled(network::features::kNetworkService) ||
Tsuyoshi Horo46f5fff2018-05-10 12:33:35112 ServiceWorkerUtils::IsServicificationEnabled() ||
113 signed_exchange_utils::IsSignedExchangeHandlingEnabled();
Tsuyoshi Horob8d512a2018-01-25 17:01:59114}
115
ananta2e65213d2017-05-19 04:08:24116// Request ID for browser initiated requests. We start at -2 on the same lines
117// as ResourceDispatcherHostImpl.
118int g_next_request_id = -2;
arthursonzogni40db5f52018-01-08 16:38:49119GlobalRequestID MakeGlobalRequestID() {
120 return GlobalRequestID(-1, g_next_request_id--);
121}
ananta2e65213d2017-05-19 04:08:24122
Emily Starkb09f19a2017-11-22 22:41:47123size_t GetCertificateChainsSizeInKB(const net::SSLInfo& ssl_info) {
124 base::Pickle cert_pickle;
125 ssl_info.cert->Persist(&cert_pickle);
126 base::Pickle unverified_cert_pickle;
127 ssl_info.unverified_cert->Persist(&unverified_cert_pickle);
128 return (cert_pickle.size() + unverified_cert_pickle.size()) / 1000;
129}
130
scottmgd2021c92017-05-15 16:58:05131WebContents* GetWebContentsFromFrameTreeNodeID(int frame_tree_node_id) {
132 DCHECK_CURRENTLY_ON(BrowserThread::UI);
133 FrameTreeNode* frame_tree_node =
134 FrameTreeNode::GloballyFindByID(frame_tree_node_id);
135 if (!frame_tree_node)
136 return nullptr;
ananta5149d8e2017-04-21 00:01:37137
scottmgd2021c92017-05-15 16:58:05138 return WebContentsImpl::FromFrameTreeNode(frame_tree_node);
139}
140
Daniel Bratellcf0b485c2017-11-09 22:42:50141const net::NetworkTrafficAnnotationTag kNavigationUrlLoaderTrafficAnnotation =
Ramin Halavatie99206e92017-06-23 05:02:50142 net::DefineNetworkTrafficAnnotation("navigation_url_loader", R"(
Ramin Halavati7b5ce1c2017-07-03 09:13:09143 semantics {
144 sender: "Navigation URL Loader"
145 description:
146 "This request is issued by a main frame navigation to fetch the "
147 "content of the page that is being navigated to."
148 trigger:
149 "Navigating Chrome (by clicking on a link, bookmark, history item, "
150 "using session restore, etc)."
151 data:
152 "Arbitrary site-controlled data can be included in the URL, HTTP "
153 "headers, and request body. Requests may include cookies and "
154 "site-specific credentials."
155 destination: WEBSITE
156 }
157 policy {
Ramin Halavati3b979782017-07-21 11:40:26158 cookies_allowed: YES
Ramin Halavati7b5ce1c2017-07-03 09:13:09159 cookies_store: "user"
160 setting: "This feature cannot be disabled."
Ramin Halavati386daa62017-08-17 10:41:59161 chrome_policy {
162 URLBlacklist {
163 URLBlacklist: { entries: '*' }
164 }
165 }
166 chrome_policy {
167 URLWhitelist {
168 URLWhitelist { }
169 }
170 }
171 }
172 comments:
173 "Chrome would be unable to navigate to websites without this type of "
174 "request. Using either URLBlacklist or URLWhitelist policies (or a "
175 "combination of both) limits the scope of these requests."
176 )");
Ramin Halavatie99206e92017-06-23 05:02:50177
Tsuyoshi Horob8d512a2018-01-25 17:01:59178std::unique_ptr<network::ResourceRequest> CreateResourceRequest(
179 NavigationRequestInfo* request_info,
180 int frame_tree_node_id,
181 bool allow_download) {
182 // TODO(scottmg): Port over stuff from RDHI::BeginNavigationRequest() here.
183 auto new_request = std::make_unique<network::ResourceRequest>();
184
185 new_request->method = request_info->common_params.method;
186 new_request->url = request_info->common_params.url;
187 new_request->site_for_cookies = request_info->site_for_cookies;
Tarun Bansal98260cd2018-02-17 07:52:23188
189 net::RequestPriority net_priority = net::HIGHEST;
190 if (!request_info->is_main_frame &&
191 base::FeatureList::IsEnabled(features::kLowPriorityIframes)) {
192 net_priority = net::LOWEST;
193 }
194 new_request->priority = net_priority;
195
Tsuyoshi Horob8d512a2018-01-25 17:01:59196 new_request->render_frame_id = frame_tree_node_id;
197
198 // The code below to set fields like request_initiator, referrer, etc has
199 // been copied from ResourceDispatcherHostImpl. We did not refactor the
200 // common code into a function, because RDHI uses accessor functions on the
201 // URLRequest class to set these fields. whereas we use ResourceRequest here.
202 new_request->request_initiator = request_info->begin_params->initiator_origin;
203 new_request->referrer = request_info->common_params.referrer.url;
204 new_request->referrer_policy = Referrer::ReferrerPolicyForUrlRequest(
205 request_info->common_params.referrer.policy);
206 new_request->headers.AddHeadersFromString(
207 request_info->begin_params->headers);
Kouhei Ueno958c5f482018-03-19 08:20:38208
209 std::string accept_value = network::kFrameAcceptHeader;
Tsuyoshi Horo46f5fff2018-05-10 12:33:35210 // TODO(https://crbug.com/840704): Decide whether the Accept header should
211 // advertise the state of kSignedHTTPExchangeOriginTrial before starting the
212 // Origin-Trial.
213 if (signed_exchange_utils::IsSignedExchangeHandlingEnabled()) {
Kouhei Ueno958c5f482018-03-19 08:20:38214 DCHECK(!accept_value.empty());
215 accept_value.append(kAcceptHeaderSignedExchangeSuffix);
216 }
217
218 new_request->headers.SetHeader(network::kAcceptHeader, accept_value);
Tsuyoshi Horob8d512a2018-01-25 17:01:59219
220 new_request->resource_type = request_info->is_main_frame
221 ? RESOURCE_TYPE_MAIN_FRAME
222 : RESOURCE_TYPE_SUB_FRAME;
223 if (request_info->is_main_frame)
224 new_request->update_first_party_url_on_redirect = true;
225
226 int load_flags = request_info->begin_params->load_flags;
Tsuyoshi Horob8d512a2018-01-25 17:01:59227 if (request_info->is_main_frame)
228 load_flags |= net::LOAD_MAIN_FRAME_DEPRECATED;
229
230 // Sync loads should have maximum priority and should be the only
231 // requests that have the ignore limits flag set.
232 DCHECK(!(load_flags & net::LOAD_IGNORE_LIMITS));
233
234 new_request->load_flags = load_flags;
235
236 new_request->request_body = request_info->common_params.post_data.get();
237 new_request->report_raw_headers = request_info->report_raw_headers;
238 new_request->allow_download = allow_download;
239 new_request->enable_load_timing = true;
240
241 new_request->fetch_request_mode = network::mojom::FetchRequestMode::kNavigate;
242 new_request->fetch_credentials_mode =
243 network::mojom::FetchCredentialsMode::kInclude;
244 new_request->fetch_redirect_mode = network::mojom::FetchRedirectMode::kManual;
Yutaka Hirano4b9b7a7f2018-03-07 14:35:15245 new_request->fetch_request_context_type =
246 request_info->begin_params->request_context_type;
Tsuyoshi Horob8d512a2018-01-25 17:01:59247 return new_request;
248}
249
Makoto Shimazu44c2c3232018-03-30 01:10:20250// Used only when NetworkService is disabled but IsLoaderInterceptionEnabled()
251// is true.
252std::unique_ptr<NavigationRequestInfo> CreateNavigationRequestInfoForRedirect(
253 const NavigationRequestInfo& previous_request_info,
254 const network::ResourceRequest& updated_resource_request) {
255 DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
256 DCHECK(IsLoaderInterceptionEnabled());
257
258 CommonNavigationParams new_common_params =
259 previous_request_info.common_params;
260 new_common_params.url = updated_resource_request.url;
261 new_common_params.referrer =
262 Referrer(updated_resource_request.url,
263 Referrer::NetReferrerPolicyToBlinkReferrerPolicy(
264 updated_resource_request.referrer_policy));
265 new_common_params.method = updated_resource_request.method;
266 new_common_params.post_data = updated_resource_request.request_body;
267 // TODO(shimazu): Set correct base url and history url for a data URL.
268
269 mojom::BeginNavigationParamsPtr new_begin_params =
270 previous_request_info.begin_params.Clone();
271 new_begin_params->headers = updated_resource_request.headers.ToString();
272
273 return std::make_unique<NavigationRequestInfo>(
274 std::move(new_common_params), std::move(new_begin_params),
275 updated_resource_request.site_for_cookies,
276 previous_request_info.is_main_frame,
277 previous_request_info.parent_is_main_frame,
278 previous_request_info.are_ancestors_secure,
279 previous_request_info.frame_tree_node_id,
280 previous_request_info.is_for_guests_only,
281 previous_request_info.report_raw_headers,
Marijn Kruisselbrink07bf59d52018-04-03 21:50:25282 previous_request_info.is_prerendering,
Tsuyoshi Horo32b51f12018-05-09 17:58:46283 nullptr /* blob_url_loader_factory */,
284 previous_request_info.devtools_navigation_token);
Makoto Shimazu44c2c3232018-03-30 01:10:20285}
286
John Abd-El-Maleka67add82018-03-09 18:22:01287// Called for requests that we don't have a URLLoaderFactory for.
288void UnknownSchemeCallback(bool handled_externally,
289 network::mojom::URLLoaderRequest request,
290 network::mojom::URLLoaderClientPtr client) {
291 client->OnComplete(network::URLLoaderCompletionStatus(
292 handled_externally ? net::ERR_ABORTED : net::ERR_UNKNOWN_URL_SCHEME));
293}
294
yzshenfa5e57202017-05-02 21:24:13295} // namespace
296
kinuko69732972017-05-29 08:50:07297// Kept around during the lifetime of the navigation request, and is
298// responsible for dispatching a ResourceRequest to the appropriate
kinukod8b13e212017-06-07 06:59:26299// URLLoader. In order to get the right URLLoader it builds a vector
Kinuko Yasuda7f3e1722018-03-26 08:58:58300// of NavigationLoaderInterceptors and successively calls MaybeCreateLoader
kinukod8b13e212017-06-07 06:59:26301// on each until the request is successfully handled. The same sequence
302// may be performed multiple times when redirects happen.
Alex Clarke1e08882b32017-10-06 14:22:40303// TODO(michaeln): Expose this class and add more unittests.
arthursonzogni1fd60e62018-05-09 15:57:32304class NavigationURLLoaderImpl::URLLoaderRequestController
John Abd-El-Malekb165dc52018-01-18 17:12:18305 : public network::mojom::URLLoaderClient {
kinuko69732972017-05-29 08:50:07306 public:
jam9354af82017-06-03 21:59:41307 URLLoaderRequestController(
Kinuko Yasuda7f3e1722018-03-26 08:58:58308 std::vector<std::unique_ptr<NavigationLoaderInterceptor>>
309 initial_interceptors,
John Abd-El-Malek1df61792018-01-12 20:40:45310 std::unique_ptr<network::ResourceRequest> resource_request,
jam9354af82017-06-03 21:59:41311 ResourceContext* resource_context,
anantae60d1d42017-06-20 04:16:27312 scoped_refptr<URLLoaderFactoryGetter> default_url_loader_factory_getter,
arthursonzogni40db5f52018-01-08 16:38:49313 const GURL& url,
Ken Rockota0dfaca12018-02-15 07:26:25314 network::mojom::URLLoaderFactoryRequest proxied_factory_request,
315 network::mojom::URLLoaderFactoryPtrInfo proxied_factory_info,
John Abd-El-Maleka67add82018-03-09 18:22:01316 std::set<std::string> known_schemes,
arthursonzogni1fd60e62018-05-09 15:57:32317 const base::WeakPtr<NavigationURLLoaderImpl>& owner)
Kinuko Yasuda7f3e1722018-03-26 08:58:58318 : interceptors_(std::move(initial_interceptors)),
Alex Clarke1e08882b32017-10-06 14:22:40319 resource_request_(std::move(resource_request)),
kinuko69732972017-05-29 08:50:07320 resource_context_(resource_context),
anantae60d1d42017-06-20 04:16:27321 default_url_loader_factory_getter_(default_url_loader_factory_getter),
arthursonzogni40db5f52018-01-08 16:38:49322 url_(url),
anantab9800e52017-07-29 18:04:13323 owner_(owner),
arthursonzogni2695d04d2017-12-12 08:39:01324 response_loader_binding_(this),
Ken Rockota0dfaca12018-02-15 07:26:25325 proxied_factory_request_(std::move(proxied_factory_request)),
326 proxied_factory_info_(std::move(proxied_factory_info)),
John Abd-El-Maleka67add82018-03-09 18:22:01327 known_schemes_(std::move(known_schemes)),
arthursonzogni2695d04d2017-12-12 08:39:01328 weak_factory_(this) {}
kinuko69732972017-05-29 08:50:07329
yzshenefcb7c72017-06-16 23:12:30330 ~URLLoaderRequestController() override {
kinuko69732972017-05-29 08:50:07331 DCHECK_CURRENTLY_ON(BrowserThread::IO);
332 }
333
arthursonzognib521c6a2018-01-08 12:23:40334 static uint32_t GetURLLoaderOptions(bool is_main_frame) {
John Abd-El-Malekb165dc52018-01-18 17:12:18335 uint32_t options = network::mojom::kURLLoadOptionSendSSLInfoWithResponse;
arthursonzognib521c6a2018-01-08 12:23:40336 if (is_main_frame)
John Abd-El-Malekb165dc52018-01-18 17:12:18337 options |= network::mojom::kURLLoadOptionSendSSLInfoForCertificateError;
arthursonzognib521c6a2018-01-08 12:23:40338
Yutaka Hiranod8789f92018-01-30 09:59:51339 if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
John Abd-El-Malekb165dc52018-01-18 17:12:18340 options |= network::mojom::kURLLoadOptionSniffMimeType;
arthursonzognib521c6a2018-01-08 12:23:40341 } else {
342 // TODO(arthursonzogni): This is a temporary option. Remove this as soon
343 // as the InterceptingResourceHandler is removed.
344 // See https://crbug.com/791049.
John Abd-El-Malekb165dc52018-01-18 17:12:18345 options |= network::mojom::kURLLoadOptionPauseOnResponseStarted;
arthursonzognib521c6a2018-01-08 12:23:40346 }
347
348 return options;
349 }
350
Makoto Shimazu44c2c3232018-03-30 01:10:20351 SingleRequestURLLoaderFactory::RequestHandler
352 CreateDefaultRequestHandlerForNonNetworkService(
353 net::URLRequestContextGetter* url_request_context_getter,
354 storage::FileSystemContext* upload_file_system_context,
355 ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
Makoto Shimazu684a5ad2018-05-29 08:20:50356 AppCacheNavigationHandleCore* appcache_handle_core,
357 bool was_request_intercepted) const {
Makoto Shimazu44c2c3232018-03-30 01:10:20358 return base::BindOnce(
359 &URLLoaderRequestController::CreateNonNetworkServiceURLLoader,
360 weak_factory_.GetWeakPtr(),
361 base::Unretained(url_request_context_getter),
362 base::Unretained(upload_file_system_context),
363 std::make_unique<NavigationRequestInfo>(*request_info_),
Makoto Shimazu684a5ad2018-05-29 08:20:50364 // If the request has already been intercepted, the request should not
365 // be intercepted again.
366 // S13nServiceWorker: Requests are intercepted by S13nServiceWorker
367 // before the default request handler when needed, so we never need to
368 // pass |service_worker_navigation_handle_core| here.
369 base::Unretained(ServiceWorkerUtils::IsServicificationEnabled() ||
370 was_request_intercepted
371 ? nullptr
372 : service_worker_navigation_handle_core),
373 base::Unretained(was_request_intercepted ? nullptr
374 : appcache_handle_core));
Makoto Shimazu44c2c3232018-03-30 01:10:20375 }
376
arthursonzogni2695d04d2017-12-12 08:39:01377 void CreateNonNetworkServiceURLLoader(
378 net::URLRequestContextGetter* url_request_context_getter,
379 storage::FileSystemContext* upload_file_system_context,
380 std::unique_ptr<NavigationRequestInfo> request_info,
arthursonzogni2695d04d2017-12-12 08:39:01381 ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
382 AppCacheNavigationHandleCore* appcache_handle_core,
John Abd-El-Malekb165dc52018-01-18 17:12:18383 network::mojom::URLLoaderRequest url_loader,
384 network::mojom::URLLoaderClientPtr url_loader_client) {
Yutaka Hiranod8789f92018-01-30 09:59:51385 DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
arthursonzogni2695d04d2017-12-12 08:39:01386 DCHECK_CURRENTLY_ON(BrowserThread::IO);
387
Tsuyoshi Horob8d512a2018-01-25 17:01:59388 default_loader_used_ = true;
Tsuyoshi Horo46f5fff2018-05-10 12:33:35389 if (signed_exchange_utils::IsSignedExchangeHandlingEnabled()) {
Tsuyoshi Horo70014ad2018-02-14 11:20:14390 DCHECK(!default_url_loader_factory_getter_);
Tsuyoshi Horo561163b2018-03-27 03:11:23391 // It is safe to pass the callback of CreateURLLoaderThrottles with the
Tsuyoshi Horo70014ad2018-02-14 11:20:14392 // unretained |this|, because the passed callback will be used by a
393 // SignedExchangeHandler which is indirectly owned by |this| until its
394 // header is verified and parsed, that's where the getter is used.
Kinuko Yasuda7f3e1722018-03-26 08:58:58395 interceptors_.push_back(std::make_unique<WebPackageRequestHandler>(
Tsuyoshi Horo70014ad2018-02-14 11:20:14396 url::Origin::Create(request_info->common_params.url),
Tsuyoshi Horo32b51f12018-05-09 17:58:46397 request_info->common_params.url,
Kinuko Yasuda32a25652018-02-19 08:14:25398 GetURLLoaderOptions(request_info->is_main_frame),
Tsuyoshi Horocdbb4902018-04-12 06:09:14399 request_info->frame_tree_node_id,
Tsuyoshi Horo32b51f12018-05-09 17:58:46400 request_info->devtools_navigation_token,
401 request_info->report_raw_headers,
Tsuyoshi Horo70014ad2018-02-14 11:20:14402 base::MakeRefCounted<
403 SignedExchangeURLLoaderFactoryForNonNetworkService>(
404 resource_context_, url_request_context_getter),
405 base::BindRepeating(
406 &URLLoaderRequestController::CreateURLLoaderThrottles,
Tsuyoshi Horof7702192018-03-07 15:00:36407 base::Unretained(this)),
408 url_request_context_getter));
Tsuyoshi Horob8d512a2018-01-25 17:01:59409 }
410
John Abd-El-Malekdb3a13b2018-05-01 17:52:02411 uint32_t options = GetURLLoaderOptions(request_info->is_main_frame);
412
413 bool intercepted = false;
414 if (g_interceptor.Get()) {
415 intercepted = g_interceptor.Get().Run(
416 &url_loader, frame_tree_node_id_, 0 /* request_id */, options,
417 *resource_request_.get(), &url_loader_client,
418 net::MutableNetworkTrafficAnnotationTag(
419 kNavigationUrlLoaderTrafficAnnotation));
420 }
421
arthursonzogni2695d04d2017-12-12 08:39:01422 // The ResourceDispatcherHostImpl can be null in unit tests.
John Abd-El-Malekdb3a13b2018-05-01 17:52:02423 if (!intercepted && ResourceDispatcherHostImpl::Get()) {
arthursonzogni2695d04d2017-12-12 08:39:01424 ResourceDispatcherHostImpl::Get()->BeginNavigationRequest(
425 resource_context_, url_request_context_getter->GetURLRequestContext(),
426 upload_file_system_context, *request_info,
arthursonzogni662d723c2018-04-24 16:13:22427 std::move(navigation_ui_data_), std::move(url_loader_client),
arthursonzogni2695d04d2017-12-12 08:39:01428 std::move(url_loader), service_worker_navigation_handle_core,
John Abd-El-Malekdb3a13b2018-05-01 17:52:02429 appcache_handle_core, options, &global_request_id_);
arthursonzogni2695d04d2017-12-12 08:39:01430 }
431
432 // TODO(arthursonzogni): Detect when the ResourceDispatcherHost didn't
433 // create a URLLoader. When it doesn't, do not send OnRequestStarted().
434 BrowserThread::PostTask(
435 BrowserThread::UI, FROM_HERE,
arthursonzogni1fd60e62018-05-09 15:57:32436 base::BindOnce(&NavigationURLLoaderImpl::OnRequestStarted, owner_,
437 base::TimeTicks::Now()));
arthursonzogni2695d04d2017-12-12 08:39:01438 }
439
440 // TODO(arthursonzogni): See if this could eventually be unified with Start().
441 void StartWithoutNetworkService(
442 net::URLRequestContextGetter* url_request_context_getter,
443 storage::FileSystemContext* upload_file_system_context,
444 ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
445 AppCacheNavigationHandleCore* appcache_handle_core,
446 std::unique_ptr<NavigationRequestInfo> request_info,
447 std::unique_ptr<NavigationUIData> navigation_ui_data) {
Yutaka Hiranod8789f92018-01-30 09:59:51448 DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
arthursonzogni2695d04d2017-12-12 08:39:01449 DCHECK_CURRENTLY_ON(BrowserThread::IO);
450 DCHECK(!started_);
451 started_ = true;
Makoto Shimazu44c2c3232018-03-30 01:10:20452 request_info_ = std::move(request_info);
453 frame_tree_node_id_ = request_info_->frame_tree_node_id;
Yuzhu Shencb3011f62018-02-08 02:51:50454 web_contents_getter_ = base::BindRepeating(
Yuzhu Shen9508fc72018-02-08 23:18:59455 &GetWebContentsFromFrameTreeNodeID, frame_tree_node_id_);
Makoto Shimazu44c2c3232018-03-30 01:10:20456 navigation_ui_data_ = std::move(navigation_ui_data);
457 default_request_handler_factory_ = base::BindRepeating(
458 &URLLoaderRequestController::
459 CreateDefaultRequestHandlerForNonNetworkService,
460 // base::Unretained(this) is safe since
461 // |default_request_handler_factory_| could be called only from |this|.
462 base::Unretained(this), base::Unretained(url_request_context_getter),
463 base::Unretained(upload_file_system_context),
arthursonzogni2695d04d2017-12-12 08:39:01464 base::Unretained(service_worker_navigation_handle_core),
465 base::Unretained(appcache_handle_core));
466
Makoto Shimazu44c2c3232018-03-30 01:10:20467 // If S13nServiceWorker is disabled, just use
468 // |default_request_handler_factory_| and return. The non network service
469 // request handling goes through ResourceDispatcherHost which has legacy
470 // hooks for service worker (ServiceWorkerRequestInterceptor), so no service
471 // worker interception is needed here.
472 if (!ServiceWorkerUtils::IsServicificationEnabled() ||
473 !service_worker_navigation_handle_core) {
474 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
475 base::MakeRefCounted<SingleRequestURLLoaderFactory>(
Makoto Shimazu684a5ad2018-05-29 08:20:50476 default_request_handler_factory_.Run(
477 false /* was_request_intercepted */)),
Makoto Shimazu44c2c3232018-03-30 01:10:20478 CreateURLLoaderThrottles(), -1 /* routing_id */, 0 /* request_id */,
479 network::mojom::kURLLoadOptionNone, resource_request_.get(),
480 this /* client */, kNavigationUrlLoaderTrafficAnnotation,
481 base::ThreadTaskRunnerHandle::Get());
482 return;
483 }
484
485 // Otherwise, if S13nServiceWorker is enabled, create an interceptor so
486 // S13nServiceWorker has a chance to intercept the request.
487 std::unique_ptr<NavigationLoaderInterceptor> service_worker_interceptor =
488 CreateServiceWorkerInterceptor(*request_info_,
489 service_worker_navigation_handle_core);
490 // If an interceptor is not created for some reasons (e.g. the origin is not
491 // secure), we no longer have to go through the rest of the network service
492 // code.
493 if (!service_worker_interceptor) {
494 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
495 base::MakeRefCounted<SingleRequestURLLoaderFactory>(
Makoto Shimazu684a5ad2018-05-29 08:20:50496 default_request_handler_factory_.Run(
497 false /* was_request_intercepted */)),
Makoto Shimazu44c2c3232018-03-30 01:10:20498 CreateURLLoaderThrottles(), -1 /* routing_id */, 0 /* request_id */,
499 network::mojom::kURLLoadOptionNone, resource_request_.get(),
500 this /* client */, kNavigationUrlLoaderTrafficAnnotation,
501 base::ThreadTaskRunnerHandle::Get());
502 return;
503 }
504
505 interceptors_.push_back(std::move(service_worker_interceptor));
506
507 // TODO(shimazu): Make sure we have a consistent global id for the
508 // navigation request.
509 global_request_id_ = MakeGlobalRequestID();
510 Restart();
arthursonzogni2695d04d2017-12-12 08:39:01511 }
512
kinuko69732972017-05-29 08:50:07513 void Start(
Tsuyoshi Horo70014ad2018-02-14 11:20:14514 net::URLRequestContextGetter* url_request_context_getter,
kinuko69732972017-05-29 08:50:07515 ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
516 AppCacheNavigationHandleCore* appcache_handle_core,
517 std::unique_ptr<NavigationRequestInfo> request_info,
John Abd-El-Malekeb1a5382018-01-05 16:58:00518 std::unique_ptr<NavigationUIData> navigation_ui_data,
John Abd-El-Malekb165dc52018-01-18 17:12:18519 network::mojom::URLLoaderFactoryPtrInfo factory_for_webui,
John Abd-El-Malek576c6132017-11-04 00:33:58520 int frame_tree_node_id,
kinuko69732972017-05-29 08:50:07521 std::unique_ptr<service_manager::Connector> connector) {
Yutaka Hiranod8789f92018-01-30 09:59:51522 DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
kinuko69732972017-05-29 08:50:07523 DCHECK_CURRENTLY_ON(BrowserThread::IO);
Alex Clarke1e08882b32017-10-06 14:22:40524 DCHECK(!started_);
arthursonzogni40db5f52018-01-08 16:38:49525 global_request_id_ = MakeGlobalRequestID();
John Abd-El-Malek576c6132017-11-04 00:33:58526 frame_tree_node_id_ = frame_tree_node_id;
Alex Clarke1e08882b32017-10-06 14:22:40527 started_ = true;
John Abd-El-Malek576c6132017-11-04 00:33:58528 web_contents_getter_ =
529 base::Bind(&GetWebContentsFromFrameTreeNodeID, frame_tree_node_id);
John Abd-El-Malekeb1a5382018-01-05 16:58:00530 navigation_ui_data_ = std::move(navigation_ui_data);
kinuko69732972017-05-29 08:50:07531
532 if (resource_request_->request_body) {
mmenkeed44e6c2017-06-28 21:13:32533 GetBodyBlobDataHandles(resource_request_->request_body.get(),
534 resource_context_, &blob_handles_);
kinuko69732972017-05-29 08:50:07535 }
536
537 // Requests to WebUI scheme won't get redirected to/from other schemes
538 // or be intercepted, so we just let it go here.
539 if (factory_for_webui.is_valid()) {
yzshenefcb7c72017-06-16 23:12:30540 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
Antonio Gomes9cdc09a2018-05-07 23:24:26541 base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
Yuzhu Shend87986f2018-01-17 22:16:37542 std::move(factory_for_webui)),
Tsuyoshi Horo70014ad2018-02-14 11:20:14543 CreateURLLoaderThrottles(), 0 /* routing_id */, 0 /* request_id? */,
John Abd-El-Malekb165dc52018-01-18 17:12:18544 network::mojom::kURLLoadOptionNone, resource_request_.get(), this,
545 kNavigationUrlLoaderTrafficAnnotation,
Hajime Hoshif5ef35262017-11-28 19:13:00546 base::ThreadTaskRunnerHandle::Get());
kinuko69732972017-05-29 08:50:07547 return;
548 }
549
Marijn Kruisselbrink07bf59d52018-04-03 21:50:25550 // Requests to Blob scheme won't get redirected to/from other schemes
551 // or be intercepted, so we just let it go here.
552 if (request_info->common_params.url.SchemeIsBlob() &&
553 request_info->blob_url_loader_factory) {
554 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
555 network::SharedURLLoaderFactory::Create(
556 std::move(request_info->blob_url_loader_factory)),
Kinuko Yasuda08dd29a2018-05-21 23:45:48557 CreateURLLoaderThrottles(), 0 /* routing_id */, 0 /* request_id? */,
Marijn Kruisselbrink07bf59d52018-04-03 21:50:25558 network::mojom::kURLLoadOptionNone, resource_request_.get(), this,
559 kNavigationUrlLoaderTrafficAnnotation,
560 base::ThreadTaskRunnerHandle::Get());
561 return;
562 }
563
kinuko69732972017-05-29 08:50:07564 if (service_worker_navigation_handle_core) {
Kinuko Yasuda7f3e1722018-03-26 08:58:58565 std::unique_ptr<NavigationLoaderInterceptor> service_worker_interceptor =
Makoto Shimazu44c2c3232018-03-30 01:10:20566 CreateServiceWorkerInterceptor(*request_info,
567 service_worker_navigation_handle_core);
Kinuko Yasuda7f3e1722018-03-26 08:58:58568 if (service_worker_interceptor)
569 interceptors_.push_back(std::move(service_worker_interceptor));
kinuko69732972017-05-29 08:50:07570 }
571
572 if (appcache_handle_core) {
Kinuko Yasuda7f3e1722018-03-26 08:58:58573 std::unique_ptr<NavigationLoaderInterceptor> appcache_interceptor =
anantaa2c8ec62017-06-09 23:44:05574 AppCacheRequestHandler::InitializeForNavigationNetworkService(
anantae60d1d42017-06-20 04:16:27575 *resource_request_, appcache_handle_core,
576 default_url_loader_factory_getter_.get());
Kinuko Yasuda7f3e1722018-03-26 08:58:58577 if (appcache_interceptor)
578 interceptors_.push_back(std::move(appcache_interceptor));
kinuko69732972017-05-29 08:50:07579 }
580
Tsuyoshi Horo46f5fff2018-05-10 12:33:35581 if (signed_exchange_utils::IsSignedExchangeHandlingEnabled()) {
Tsuyoshi Horo561163b2018-03-27 03:11:23582 // It is safe to pass the callback of CreateURLLoaderThrottles with the
Tsuyoshi Horo70014ad2018-02-14 11:20:14583 // unretained |this|, because the passed callback will be used by a
584 // SignedExchangeHandler which is indirectly owned by |this| until its
585 // header is verified and parsed, that's where the getter is used.
Kinuko Yasuda7f3e1722018-03-26 08:58:58586 interceptors_.push_back(std::make_unique<WebPackageRequestHandler>(
Tsuyoshi Horo70014ad2018-02-14 11:20:14587 url::Origin::Create(request_info->common_params.url),
Tsuyoshi Horo32b51f12018-05-09 17:58:46588 request_info->common_params.url,
Kinuko Yasuda32a25652018-02-19 08:14:25589 GetURLLoaderOptions(request_info->is_main_frame),
Tsuyoshi Horocdbb4902018-04-12 06:09:14590 request_info->frame_tree_node_id,
Tsuyoshi Horo32b51f12018-05-09 17:58:46591 request_info->devtools_navigation_token,
592 request_info->report_raw_headers,
Chong Zhang5271432a2018-03-01 23:31:02593 default_url_loader_factory_getter_->GetNetworkFactory(),
Tsuyoshi Horo70014ad2018-02-14 11:20:14594 base::BindRepeating(
595 &URLLoaderRequestController::CreateURLLoaderThrottles,
Tsuyoshi Horof7702192018-03-07 15:00:36596 base::Unretained(this)),
597 url_request_context_getter));
Tsuyoshi Horob8d512a2018-01-25 17:01:59598 }
599
Jian Li18e29242018-05-10 22:25:12600 std::vector<std::unique_ptr<URLLoaderRequestInterceptor>>
601 browser_interceptors = GetContentClient()
602 ->browser()
603 ->WillCreateURLLoaderRequestInterceptors(
604 navigation_ui_data_.get(),
605 request_info->frame_tree_node_id);
606 if (!browser_interceptors.empty()) {
607 for (auto& browser_interceptor : browser_interceptors) {
608 interceptors_.push_back(
609 std::make_unique<NavigationLoaderInterceptorBrowserContainer>(
610 std::move(browser_interceptor)));
611 }
612 }
613
yzshenefcb7c72017-06-16 23:12:30614 Restart();
kinuko69732972017-05-29 08:50:07615 }
616
Michael Nordman2431f5f2017-09-13 04:58:15617 // This could be called multiple times to follow a chain of redirects.
yzshenefcb7c72017-06-16 23:12:30618 void Restart() {
Kinuko Yasuda7f3e1722018-03-26 08:58:58619 DCHECK(IsLoaderInterceptionEnabled());
Tsuyoshi Horo5204c872017-09-21 16:28:17620 // Clear |url_loader_| if it's not the default one (network). This allows
621 // the restarted request to use a new loader, instead of, e.g., reusing the
622 // AppCache or service worker loader. For an optimization, we keep and reuse
Kinuko Yasuda7f3e1722018-03-26 08:58:58623 // the default url loader if the all |interceptors_| doesn't handle the
Tsuyoshi Horo5204c872017-09-21 16:28:17624 // redirected request.
625 if (!default_loader_used_)
626 url_loader_.reset();
Kinuko Yasuda7f3e1722018-03-26 08:58:58627 interceptor_index_ = 0;
anantab9800e52017-07-29 18:04:13628 received_response_ = false;
Kinuko Yasuda7f3e1722018-03-26 08:58:58629 MaybeStartLoader(nullptr /* interceptor */,
630 {} /* single_request_handler */);
kinuko69732972017-05-29 08:50:07631 }
632
Kinuko Yasuda7f3e1722018-03-26 08:58:58633 // |interceptor| is non-null if this is called by one of the interceptors
634 // (via a LoaderCallback).
635 // |single_request_handler| is the RequestHandler given by the |interceptor|,
636 // non-null if the interceptor wants to handle the request.
Ken Rockot387ddd5a2018-01-30 19:18:40637 void MaybeStartLoader(
Kinuko Yasuda7f3e1722018-03-26 08:58:58638 NavigationLoaderInterceptor* interceptor,
Ken Rockot387ddd5a2018-01-30 19:18:40639 SingleRequestURLLoaderFactory::RequestHandler single_request_handler) {
Kinuko Yasuda7f3e1722018-03-26 08:58:58640 DCHECK(IsLoaderInterceptionEnabled());
Ken Rockot387ddd5a2018-01-30 19:18:40641 if (single_request_handler) {
Kinuko Yasuda7f3e1722018-03-26 08:58:58642 // |interceptor| wants to handle the request with
643 // |single_request_handler|.
644 DCHECK(interceptor);
Michael Nordman2431f5f2017-09-13 04:58:15645 default_loader_used_ = false;
yzshenefcb7c72017-06-16 23:12:30646 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
Ken Rockot387ddd5a2018-01-30 19:18:40647 base::MakeRefCounted<SingleRequestURLLoaderFactory>(
648 std::move(single_request_handler)),
Tsuyoshi Horo70014ad2018-02-14 11:20:14649 CreateURLLoaderThrottles(), frame_tree_node_id_, 0 /* request_id? */,
Ken Rockot387ddd5a2018-01-30 19:18:40650 network::mojom::kURLLoadOptionNone, resource_request_.get(), this,
Hajime Hoshif5ef35262017-11-28 19:13:00651 kNavigationUrlLoaderTrafficAnnotation,
652 base::ThreadTaskRunnerHandle::Get());
anantae60d1d42017-06-20 04:16:27653
Kinuko Yasuda250577c2017-10-29 02:51:24654 subresource_loader_params_ =
Kinuko Yasuda7f3e1722018-03-26 08:58:58655 interceptor->MaybeCreateSubresourceLoaderParams();
Kinuko Yasuda8757204a2017-11-04 07:50:13656
kinuko69732972017-05-29 08:50:07657 return;
658 }
659
Kinuko Yasuda7f3e1722018-03-26 08:58:58660 // Before falling back to the next interceptor, see if |interceptor| still
661 // wants to give additional info to the frame for subresource loading. In
662 // that case we will just fall back to the default loader (i.e. won't go on
663 // to the next interceptors) but send the subresource_loader_params to the
664 // child process. This is necessary for correctness in the cases where, e.g.
665 // there's a controlling ServiceWorker that doesn't handle main resource
666 // loading, but may still want to control the page and/or handle subresource
667 // loading. In that case we want to skip AppCache.
668 if (interceptor) {
Kinuko Yasuda8757204a2017-11-04 07:50:13669 subresource_loader_params_ =
Kinuko Yasuda7f3e1722018-03-26 08:58:58670 interceptor->MaybeCreateSubresourceLoaderParams();
Kinuko Yasuda8757204a2017-11-04 07:50:13671
672 // If non-null |subresource_loader_params_| is returned, make sure
Kinuko Yasuda7f3e1722018-03-26 08:58:58673 // we skip the next interceptors.
Kinuko Yasuda8757204a2017-11-04 07:50:13674 if (subresource_loader_params_)
Kinuko Yasuda7f3e1722018-03-26 08:58:58675 interceptor_index_ = interceptors_.size();
Kinuko Yasuda8757204a2017-11-04 07:50:13676 }
677
Kinuko Yasuda7f3e1722018-03-26 08:58:58678 // See if the next interceptor wants to handle the request.
679 if (interceptor_index_ < interceptors_.size()) {
680 auto* next_interceptor = interceptors_[interceptor_index_++].get();
681 next_interceptor->MaybeCreateLoader(
kinuko69732972017-05-29 08:50:07682 *resource_request_, resource_context_,
683 base::BindOnce(&URLLoaderRequestController::MaybeStartLoader,
Kinuko Yasuda7f3e1722018-03-26 08:58:58684 base::Unretained(this), next_interceptor));
kinuko69732972017-05-29 08:50:07685 return;
686 }
687
Kinuko Yasuda7f3e1722018-03-26 08:58:58688 // If we already have the default |url_loader_| we must come here after
689 // a redirect. No interceptors wanted to intercept the redirected request,
690 // so let it just follow the redirect.
Michael Nordman2431f5f2017-09-13 04:58:15691 if (url_loader_) {
692 DCHECK(!redirect_info_.new_url.is_empty());
Chong Zhang7607f1f2018-06-01 20:52:20693 url_loader_->FollowRedirect(
694 std::move(url_loader_modified_request_headers_));
Michael Nordman2431f5f2017-09-13 04:58:15695 return;
696 }
697
Ken Rockota0dfaca12018-02-15 07:26:25698 // TODO(https://crbug.com/796425): We temporarily wrap raw
699 // mojom::URLLoaderFactory pointers into SharedURLLoaderFactory. Need to
700 // further refactor the factory getters to avoid this.
Chong Zhangb7c8d1ce2018-03-13 19:14:11701 scoped_refptr<network::SharedURLLoaderFactory> factory;
Kinuko Yasuda7f3e1722018-03-26 08:58:58702 DCHECK_EQ(interceptors_.size(), interceptor_index_);
Makoto Shimazu44c2c3232018-03-30 01:10:20703
704 // If NetworkService is not enabled (which means we come here because one of
705 // the loader interceptors is enabled), use the default request handler
706 // instead of going through the NetworkService path.
707 if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
708 DCHECK(!interceptors_.empty());
709 DCHECK(default_request_handler_factory_);
Makoto Shimazu684a5ad2018-05-29 08:20:50710 // The only way to come here is to enable ServiceWorkerServicification
711 // without NetworkService. We know that the service worker's request
712 // interceptor has already intercepted and decided not to handle the
713 // request.
714 DCHECK(ServiceWorkerUtils::IsServicificationEnabled());
Makoto Shimazu44c2c3232018-03-30 01:10:20715 default_loader_used_ = true;
716 // Update |request_info_| when following a redirect.
717 if (url_chain_.size() > 0) {
718 request_info_ = CreateNavigationRequestInfoForRedirect(
719 *request_info_, *resource_request_);
720 }
Makoto Shimazu684a5ad2018-05-29 08:20:50721 // When |subresource_loader_params_| has its value, the request should not
722 // be intercepted by any other interceptors since it means that a request
723 // interceptor already intercepted the request and it attached its info to
724 // the request.
Makoto Shimazu44c2c3232018-03-30 01:10:20725 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
726 base::MakeRefCounted<SingleRequestURLLoaderFactory>(
Makoto Shimazu684a5ad2018-05-29 08:20:50727 default_request_handler_factory_.Run(
728 subresource_loader_params_.has_value()
729 /* was_request_intercepted */)),
Makoto Shimazu44c2c3232018-03-30 01:10:20730 CreateURLLoaderThrottles(), frame_tree_node_id_, 0 /* request_id */,
731 network::mojom::kURLLoadOptionNone, resource_request_.get(),
732 this /* client */, kNavigationUrlLoaderTrafficAnnotation,
733 base::ThreadTaskRunnerHandle::Get());
734 return;
735 }
736
jam9354af82017-06-03 21:59:41737 if (resource_request_->url.SchemeIs(url::kBlobScheme)) {
Antonio Gomes9cdc09a2018-05-07 23:24:26738 factory =
739 base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
740 default_url_loader_factory_getter_->GetBlobFactory());
Ken Rockot314714c2017-11-05 23:36:24741 } else if (!IsURLHandledByNetworkService(resource_request_->url) &&
742 !resource_request_->url.SchemeIs(url::kDataScheme)) {
John Abd-El-Maleka67add82018-03-09 18:22:01743 if (known_schemes_.find(resource_request_->url.scheme()) ==
744 known_schemes_.end()) {
745 bool handled = GetContentClient()->browser()->HandleExternalProtocol(
746 resource_request_->url, web_contents_getter_,
747 ChildProcessHost::kInvalidUniqueID, navigation_ui_data_.get(),
748 resource_request_->resource_type == RESOURCE_TYPE_MAIN_FRAME,
749 static_cast<ui::PageTransition>(resource_request_->transition_type),
750 resource_request_->has_user_gesture);
751 factory = base::MakeRefCounted<SingleRequestURLLoaderFactory>(
752 base::BindOnce(UnknownSchemeCallback, handled));
753 } else {
754 network::mojom::URLLoaderFactoryPtr& non_network_factory =
755 non_network_url_loader_factories_[resource_request_->url.scheme()];
756 if (!non_network_factory.is_bound()) {
757 BrowserThread::PostTask(
758 BrowserThread::UI, FROM_HERE,
arthursonzogni1fd60e62018-05-09 15:57:32759 base::BindOnce(&NavigationURLLoaderImpl ::
John Abd-El-Maleka67add82018-03-09 18:22:01760 BindNonNetworkURLLoaderFactoryRequest,
761 owner_, frame_tree_node_id_,
762 resource_request_->url,
763 mojo::MakeRequest(&non_network_factory)));
764 }
Antonio Gomes9cdc09a2018-05-07 23:24:26765 factory =
766 base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
767 non_network_factory.get());
Ken Rockot314714c2017-11-05 23:36:24768 }
jam9354af82017-06-03 21:59:41769 } else {
anantab9800e52017-07-29 18:04:13770 default_loader_used_ = true;
Ken Rockota0dfaca12018-02-15 07:26:25771
772 // NOTE: We only support embedders proxying network-service-bound requests
Kinuko Yasuda7f3e1722018-03-26 08:58:58773 // not handled by NavigationLoaderInterceptors above (e.g. Service Worker
774 // or AppCache). Hence this code is only reachable when one of the above
775 // interceptors isn't used and the URL is either a data URL or has a
776 // scheme which is handled by the network service. We explicitly avoid
777 // proxying the data URL case here.
Ken Rockota0dfaca12018-02-15 07:26:25778 if (proxied_factory_request_.is_pending() &&
779 !resource_request_->url.SchemeIs(url::kDataScheme)) {
780 DCHECK(proxied_factory_info_.is_valid());
Chong Zhang70432e32018-03-07 04:43:52781 // We don't worry about reconnection since it's a single navigation.
Chong Zhang5271432a2018-03-01 23:31:02782 default_url_loader_factory_getter_->CloneNetworkFactory(
783 std::move(proxied_factory_request_));
Antonio Gomes9cdc09a2018-05-07 23:24:26784 factory = base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
Ken Rockota0dfaca12018-02-15 07:26:25785 std::move(proxied_factory_info_));
786 } else {
Chong Zhang5271432a2018-03-01 23:31:02787 factory = default_url_loader_factory_getter_->GetNetworkFactory();
Ken Rockota0dfaca12018-02-15 07:26:25788 }
jam9354af82017-06-03 21:59:41789 }
Min Qin83d07872017-10-26 23:22:41790 url_chain_.push_back(resource_request_->url);
arthursonzognib521c6a2018-01-08 12:23:40791 uint32_t options = GetURLLoaderOptions(resource_request_->resource_type ==
792 RESOURCE_TYPE_MAIN_FRAME);
yzshenefcb7c72017-06-16 23:12:30793 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
Ken Rockota0dfaca12018-02-15 07:26:25794 factory, CreateURLLoaderThrottles(), frame_tree_node_id_,
795 0 /* request_id? */, options, resource_request_.get(), this,
Tsuyoshi Horo70014ad2018-02-14 11:20:14796 kNavigationUrlLoaderTrafficAnnotation,
Hajime Hoshif5ef35262017-11-28 19:13:00797 base::ThreadTaskRunnerHandle::Get());
kinuko69732972017-05-29 08:50:07798 }
799
Chong Zhang7607f1f2018-06-01 20:52:20800 void FollowRedirect(
801 const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
yzshenefcb7c72017-06-16 23:12:30802 DCHECK_CURRENTLY_ON(BrowserThread::IO);
Michael Nordman2431f5f2017-09-13 04:58:15803 DCHECK(!redirect_info_.new_url.is_empty());
arthursonzogni2695d04d2017-12-12 08:39:01804
Kinuko Yasuda7f3e1722018-03-26 08:58:58805 if (!IsLoaderInterceptionEnabled()) {
Chong Zhang7607f1f2018-06-01 20:52:20806 url_loader_->FollowRedirect(modified_request_headers);
arthursonzogni2695d04d2017-12-12 08:39:01807 return;
808 }
anantab9800e52017-07-29 18:04:13809
Kinuko Yasuda7f3e1722018-03-26 08:58:58810 // Update |resource_request_| and call Restart to give our |interceptors_| a
811 // chance at handling the new location. If no interceptor wants to take
812 // over, we'll use the existing url_loader to follow the redirect, see
813 // MaybeStartLoader.
Michael Nordman2431f5f2017-09-13 04:58:15814 // TODO(michaeln): This is still WIP and is based on URLRequest::Redirect,
815 // there likely remains more to be done.
816 // a. For subframe navigations, the Origin header may need to be modified
817 // differently?
818 // b. How should redirect_info_.referred_token_binding_host be handled?
Michael Nordman2431f5f2017-09-13 04:58:15819
Tsuyoshi Horo9e2ec4df2017-10-16 15:15:55820 bool should_clear_upload = false;
821 net::RedirectUtil::UpdateHttpRequest(
822 resource_request_->url, resource_request_->method, redirect_info_,
Chong Zhang7607f1f2018-06-01 20:52:20823 modified_request_headers, &resource_request_->headers,
824 &should_clear_upload);
Tsuyoshi Horo9e2ec4df2017-10-16 15:15:55825 if (should_clear_upload) {
Michael Nordman2431f5f2017-09-13 04:58:15826 // The request body is no longer applicable.
827 resource_request_->request_body = nullptr;
828 blob_handles_.clear();
829 }
830
Michael Nordman2431f5f2017-09-13 04:58:15831 resource_request_->url = redirect_info_.new_url;
Tsuyoshi Horo9e2ec4df2017-10-16 15:15:55832 resource_request_->method = redirect_info_.new_method;
Michael Nordman2431f5f2017-09-13 04:58:15833 resource_request_->site_for_cookies = redirect_info_.new_site_for_cookies;
834 resource_request_->referrer = GURL(redirect_info_.new_referrer);
John Abd-El-Malekb77d22fb72017-12-22 17:34:48835 resource_request_->referrer_policy = redirect_info_.new_referrer_policy;
Min Qin83d07872017-10-26 23:22:41836 url_chain_.push_back(redirect_info_.new_url);
Michael Nordman2431f5f2017-09-13 04:58:15837
Chong Zhang7607f1f2018-06-01 20:52:20838 // Need to cache modified headers for |url_loader_| since it doesn't use
839 // |resource_request_| during redirect.
840 url_loader_modified_request_headers_ = modified_request_headers;
841
Michael Nordman2431f5f2017-09-13 04:58:15842 Restart();
yzshenefcb7c72017-06-16 23:12:30843 }
844
Kinuko Yasuda250577c2017-10-29 02:51:24845 base::Optional<SubresourceLoaderParams> TakeSubresourceLoaderParams() {
846 return std::move(subresource_loader_params_);
anantae60d1d42017-06-20 04:16:27847 }
848
kinuko69732972017-05-29 08:50:07849 private:
John Abd-El-Malekb165dc52018-01-18 17:12:18850 // network::mojom::URLLoaderClient implementation:
yzshenefcb7c72017-06-16 23:12:30851 void OnReceiveResponse(
John Abd-El-Malek46248032018-01-17 19:11:23852 const network::ResourceResponseHead& head,
John Abd-El-Malekb165dc52018-01-18 17:12:18853 network::mojom::DownloadedTempFilePtr downloaded_file) override {
anantab9800e52017-07-29 18:04:13854 received_response_ = true;
arthursonzogni2695d04d2017-12-12 08:39:01855
anantab9800e52017-07-29 18:04:13856 // If the default loader (network) was used to handle the URL load request
Kinuko Yasuda7f3e1722018-03-26 08:58:58857 // we need to see if the interceptors want to potentially create a new
858 // loader for the response. e.g. AppCache.
anantab9800e52017-07-29 18:04:13859 if (MaybeCreateLoaderForResponse(head))
860 return;
arthursonzogni3a4ca9f2017-12-07 17:58:34861
John Abd-El-Malekb165dc52018-01-18 17:12:18862 network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints;
John Abd-El-Malekecc6f5f2018-03-02 18:47:39863
864 // Currently only plugin handlers may intercept the response. Don't treat
865 // the response as download if it has been handled by plugins.
866 bool response_intercepted = false;
arthursonzogni3a4ca9f2017-12-07 17:58:34867 if (url_loader_) {
868 url_loader_client_endpoints = url_loader_->Unbind();
John Abd-El-Malekecc6f5f2018-03-02 18:47:39869 response_intercepted = url_loader_->response_intercepted();
arthursonzogni3a4ca9f2017-12-07 17:58:34870 } else {
John Abd-El-Malekb165dc52018-01-18 17:12:18871 url_loader_client_endpoints =
872 network::mojom::URLLoaderClientEndpoints::New(
873 response_url_loader_.PassInterface(),
874 response_loader_binding_.Unbind());
arthursonzogni3a4ca9f2017-12-07 17:58:34875 }
876
arthursonzogni40db5f52018-01-08 16:38:49877 bool is_download;
878 bool is_stream;
879 std::unique_ptr<NavigationData> cloned_navigation_data;
Kinuko Yasuda7f3e1722018-03-26 08:58:58880 if (IsLoaderInterceptionEnabled()) {
John Abd-El-Malek3ebdff862018-04-23 18:57:21881 bool must_download = navigation_loader_util::MustDownload(
Jochen Eisinger7678c8ac2018-05-07 15:47:34882 url_, head.headers.get(), head.mime_type);
John Abd-El-Malek3ebdff862018-04-23 18:57:21883 bool known_mime_type = blink::IsSupportedMimeType(head.mime_type);
884
885#if BUILDFLAG(ENABLE_PLUGINS)
886 if (!response_intercepted && !must_download && !known_mime_type) {
887 CheckPluginAndContinueOnReceiveResponse(
888 head, std::move(downloaded_file),
889 std::move(url_loader_client_endpoints),
890 std::vector<WebPluginInfo>());
891 return;
892 }
893#endif
894
895 is_download =
896 !response_intercepted && (must_download || !known_mime_type);
arthursonzogni40db5f52018-01-08 16:38:49897 is_stream = false;
898 } else {
899 ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get();
900 net::URLRequest* url_request = rdh->GetURLRequest(global_request_id_);
arthursonzognib1de19fa2018-04-03 19:55:10901
902 // The |url_request| maybe have been removed from the resource dispatcher
John Abd-El-Malek739997242018-05-01 19:48:25903 // host during the time it took for OnReceiveResponse() to be received.
904 if (url_request) {
905 ResourceRequestInfoImpl* info =
906 ResourceRequestInfoImpl::ForRequest(url_request);
907 is_download = !response_intercepted && info->IsDownload();
908 is_stream = info->is_stream();
909 if (rdh->delegate()) {
910 NavigationData* navigation_data =
911 rdh->delegate()->GetNavigationData(url_request);
arthursonzognib1de19fa2018-04-03 19:55:10912
John Abd-El-Malek739997242018-05-01 19:48:25913 // Clone the embedder's NavigationData before moving it to the UI
914 // thread.
915 if (navigation_data)
916 cloned_navigation_data = navigation_data->Clone();
917 }
arthursonzogni40db5f52018-01-08 16:38:49918
John Abd-El-Malek739997242018-05-01 19:48:25919 // This is similar to what is done in
920 // ServiceWorkerControlleeHandler::MaybeCreateSubresourceLoaderParams().
921 // It takes the matching ControllerServiceWorkerInfo (if any) associated
922 // with the request. It will be sent to the renderer process and used to
923 // intercept requests.
924 // TODO(arthursonzogni): This is needed only for the
925 // non-S13nServiceWorker case. The S13nServiceWorker case is still not
926 // supported without the NetworkService. This block needs to be updated
927 // once support for it will be added.
928 ServiceWorkerProviderHost* sw_provider_host =
929 ServiceWorkerRequestHandler::GetProviderHost(url_request);
930 if (sw_provider_host && sw_provider_host->controller()) {
931 subresource_loader_params_ = SubresourceLoaderParams();
932 subresource_loader_params_->controller_service_worker_info =
933 mojom::ControllerServiceWorkerInfo::New();
Han Leone80f5c9a2018-05-12 04:22:36934 base::WeakPtr<ServiceWorkerHandle> sw_handle =
935 sw_provider_host->GetOrCreateServiceWorkerHandle(
936 sw_provider_host->controller());
937 if (sw_handle) {
938 subresource_loader_params_->controller_service_worker_handle =
939 sw_handle;
940 subresource_loader_params_->controller_service_worker_info
941 ->object_info = sw_handle->CreateIncompleteObjectInfo();
942 }
John Abd-El-Malek739997242018-05-01 19:48:25943 }
944 } else {
945 is_download = is_stream = false;
arthursonzognib950d902018-02-08 09:27:13946 }
arthursonzogni40db5f52018-01-08 16:38:49947 }
948
John Abd-El-Malek3ebdff862018-04-23 18:57:21949 CallOnReceivedResponse(head, std::move(downloaded_file),
950 std::move(url_loader_client_endpoints),
951 std::move(cloned_navigation_data), is_download,
952 is_stream);
953 }
954
955#if BUILDFLAG(ENABLE_PLUGINS)
956 void CheckPluginAndContinueOnReceiveResponse(
957 const network::ResourceResponseHead& head,
958 network::mojom::DownloadedTempFilePtr downloaded_file,
959 network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
960 const std::vector<WebPluginInfo>& plugins) {
961 bool stale;
962 WebPluginInfo plugin;
963 // It's ok to pass -1 for the render process and frame ID since that's
964 // only used for plugin overridding. We don't actually care if we get an
965 // overridden plugin or not, since all we care about is the presence of a
966 // plugin. Note that this is what the MimeSniffingResourceHandler code
967 // path does as well for navigations.
968 bool has_plugin = PluginService::GetInstance()->GetPluginInfo(
969 -1 /* render_process_id */, -1 /* render_frame_id */, resource_context_,
970 resource_request_->url, url::Origin(), head.mime_type,
971 false /* allow_wildcard */, &stale, &plugin, nullptr);
972
973 if (stale) {
974 // Refresh the plugins asynchronously.
975 PluginService::GetInstance()->GetPlugins(base::BindOnce(
976 &URLLoaderRequestController::CheckPluginAndContinueOnReceiveResponse,
977 weak_factory_.GetWeakPtr(), head, std::move(downloaded_file),
978 std::move(url_loader_client_endpoints)));
979 return;
980 }
981
982 bool is_download =
983 !has_plugin &&
984 (!head.headers || head.headers->response_code() / 100 == 2);
985
986 CallOnReceivedResponse(head, std::move(downloaded_file),
987 std::move(url_loader_client_endpoints), nullptr,
988 is_download, false /* is_stream */);
989 }
990#endif
991
992 void CallOnReceivedResponse(
993 const network::ResourceResponseHead& head,
994 network::mojom::DownloadedTempFilePtr downloaded_file,
995 network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
996 std::unique_ptr<NavigationData> cloned_navigation_data,
997 bool is_download,
998 bool is_stream) {
999 scoped_refptr<network::ResourceResponse> response(
1000 new network::ResourceResponse());
1001 response->head = head;
1002
Andrey Kosyakova924c8b2017-08-18 17:37:231003 // Make a copy of the ResourceResponse before it is passed to another
1004 // thread.
1005 //
1006 // TODO(davidben): This copy could be avoided if ResourceResponse weren't
1007 // reference counted and the loader stack passed unique ownership of the
1008 // response. https://crbug.com/416050
yzshenefcb7c72017-06-16 23:12:301009 BrowserThread::PostTask(
1010 BrowserThread::UI, FROM_HERE,
arthursonzogni1fd60e62018-05-09 15:57:321011 base::BindOnce(&NavigationURLLoaderImpl::OnReceiveResponse, owner_,
1012 response->DeepCopy(),
arthursonzogni40db5f52018-01-08 16:38:491013 std::move(url_loader_client_endpoints),
Andrey Kosyakov87cd9252018-03-27 16:58:271014 std::move(cloned_navigation_data), global_request_id_,
1015 is_download, is_stream, std::move(downloaded_file)));
yzshenefcb7c72017-06-16 23:12:301016 }
1017
1018 void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
John Abd-El-Malek46248032018-01-17 19:11:231019 const network::ResourceResponseHead& head) override {
Michael Nordman2431f5f2017-09-13 04:58:151020 if (--redirect_limit_ == 0) {
Takashi Toyoshimaaa278662017-11-20 11:11:261021 OnComplete(
1022 network::URLLoaderCompletionStatus(net::ERR_TOO_MANY_REDIRECTS));
Michael Nordman2431f5f2017-09-13 04:58:151023 return;
1024 }
1025
1026 // Store the redirect_info for later use in FollowRedirect where we give
Kinuko Yasuda7f3e1722018-03-26 08:58:581027 // our interceptors_ a chance to intercept the request for the new location.
Michael Nordman2431f5f2017-09-13 04:58:151028 redirect_info_ = redirect_info;
1029
John Abd-El-Malek46248032018-01-17 19:11:231030 scoped_refptr<network::ResourceResponse> response(
1031 new network::ResourceResponse());
Andrey Kosyakova924c8b2017-08-18 17:37:231032 response->head = head;
arthursonzogni40db5f52018-01-08 16:38:491033 url_ = redirect_info.new_url;
Andrey Kosyakova924c8b2017-08-18 17:37:231034
1035 // Make a copy of the ResourceResponse before it is passed to another
1036 // thread.
1037 //
1038 // TODO(davidben): This copy could be avoided if ResourceResponse weren't
1039 // reference counted and the loader stack passed unique ownership of the
1040 // response. https://crbug.com/416050
yzshenefcb7c72017-06-16 23:12:301041 BrowserThread::PostTask(
1042 BrowserThread::UI, FROM_HERE,
arthursonzogni1fd60e62018-05-09 15:57:321043 base::BindOnce(&NavigationURLLoaderImpl::OnReceiveRedirect, owner_,
1044 redirect_info, response->DeepCopy()));
yzshenefcb7c72017-06-16 23:12:301045 }
1046
1047 void OnDataDownloaded(int64_t data_length, int64_t encoded_length) override {}
yzshenefcb7c72017-06-16 23:12:301048 void OnUploadProgress(int64_t current_position,
1049 int64_t total_size,
1050 OnUploadProgressCallback callback) override {}
yzshenefcb7c72017-06-16 23:12:301051 void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override {}
yzshenefcb7c72017-06-16 23:12:301052 void OnTransferSizeUpdated(int32_t transfer_size_diff) override {}
1053
arthursonzogni3a4ca9f2017-12-07 17:58:341054 void OnStartLoadingResponseBody(mojo::ScopedDataPipeConsumerHandle) override {
1055 // Not reached. At this point, the loader and client endpoints must have
1056 // been unbound and forwarded to the renderer.
1057 CHECK(false);
yzshenefcb7c72017-06-16 23:12:301058 }
1059
Takashi Toyoshimaaa278662017-11-20 11:11:261060 void OnComplete(const network::URLLoaderCompletionStatus& status) override {
Emily Starkb09f19a2017-11-22 22:41:471061 UMA_HISTOGRAM_BOOLEAN(
arthursonzognie70c4a042018-05-02 15:49:101062 "Navigation.URLLoaderNetworkService.OnCompleteHasSSLInfo",
Emily Starkb09f19a2017-11-22 22:41:471063 status.ssl_info.has_value());
1064 if (status.ssl_info.has_value()) {
1065 UMA_HISTOGRAM_MEMORY_KB(
1066 "Navigation.URLLoaderNetworkService.OnCompleteCertificateChainsSize",
1067 GetCertificateChainsSizeInKB(status.ssl_info.value()));
1068 }
1069
Takashi Toyoshima8f988532017-11-13 07:32:371070 if (status.error_code != net::OK && !received_response_) {
anantab9800e52017-07-29 18:04:131071 // If the default loader (network) was used to handle the URL load
Kinuko Yasuda7f3e1722018-03-26 08:58:581072 // request we need to see if the interceptors want to potentially create a
anantab9800e52017-07-29 18:04:131073 // new loader for the response. e.g. AppCache.
John Abd-El-Malek46248032018-01-17 19:11:231074 if (MaybeCreateLoaderForResponse(network::ResourceResponseHead()))
anantab9800e52017-07-29 18:04:131075 return;
1076 }
Takashi Toyoshima8f988532017-11-13 07:32:371077 status_ = status;
arthursonzogni2695d04d2017-12-12 08:39:011078
yzshenefcb7c72017-06-16 23:12:301079 BrowserThread::PostTask(
1080 BrowserThread::UI, FROM_HERE,
arthursonzogni1fd60e62018-05-09 15:57:321081 base::BindOnce(&NavigationURLLoaderImpl::OnComplete, owner_, status));
yzshenefcb7c72017-06-16 23:12:301082 }
1083
Kinuko Yasuda7f3e1722018-03-26 08:58:581084 // Returns true if an interceptor wants to handle the response, i.e. return a
Michael Nordman2431f5f2017-09-13 04:58:151085 // different response. For e.g. AppCache may have fallback content.
John Abd-El-Malek46248032018-01-17 19:11:231086 bool MaybeCreateLoaderForResponse(
1087 const network::ResourceResponseHead& response) {
Kinuko Yasuda7f3e1722018-03-26 08:58:581088 if (!IsLoaderInterceptionEnabled())
arthursonzogni2695d04d2017-12-12 08:39:011089 return false;
1090
anantab9800e52017-07-29 18:04:131091 if (!default_loader_used_)
1092 return false;
1093
Kinuko Yasuda7f3e1722018-03-26 08:58:581094 for (auto& interceptor : interceptors_) {
John Abd-El-Malekb165dc52018-01-18 17:12:181095 network::mojom::URLLoaderClientRequest response_client_request;
Kinuko Yasuda7f3e1722018-03-26 08:58:581096 if (interceptor->MaybeCreateLoaderForResponse(
1097 response, &response_url_loader_, &response_client_request,
1098 url_loader_.get())) {
Michael Nordman2431f5f2017-09-13 04:58:151099 response_loader_binding_.Bind(std::move(response_client_request));
1100 default_loader_used_ = false;
1101 url_loader_.reset();
anantab9800e52017-07-29 18:04:131102 return true;
1103 }
1104 }
1105 return false;
1106 }
1107
Tsuyoshi Horo70014ad2018-02-14 11:20:141108 std::vector<std::unique_ptr<content::URLLoaderThrottle>>
1109 CreateURLLoaderThrottles() {
1110 return GetContentClient()->browser()->CreateURLLoaderThrottles(
1111 *resource_request_, resource_context_, web_contents_getter_,
1112 navigation_ui_data_.get(), frame_tree_node_id_);
1113 }
1114
Makoto Shimazu44c2c3232018-03-30 01:10:201115 std::unique_ptr<NavigationLoaderInterceptor> CreateServiceWorkerInterceptor(
1116 const NavigationRequestInfo& request_info,
1117 ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core)
1118 const {
1119 const ResourceType resource_type = request_info.is_main_frame
1120 ? RESOURCE_TYPE_MAIN_FRAME
1121 : RESOURCE_TYPE_SUB_FRAME;
1122 network::mojom::RequestContextFrameType frame_type =
1123 request_info.is_main_frame
1124 ? network::mojom::RequestContextFrameType::kTopLevel
1125 : network::mojom::RequestContextFrameType::kNested;
1126 storage::BlobStorageContext* blob_storage_context = GetBlobStorageContext(
1127 GetChromeBlobStorageContextForResourceContext(resource_context_));
1128 return ServiceWorkerRequestHandler::InitializeForNavigationNetworkService(
1129 *resource_request_, resource_context_,
1130 service_worker_navigation_handle_core, blob_storage_context,
1131 request_info.begin_params->skip_service_worker, resource_type,
1132 request_info.begin_params->request_context_type, frame_type,
1133 request_info.are_ancestors_secure, request_info.common_params.post_data,
1134 web_contents_getter_);
1135 }
1136
Kinuko Yasuda7f3e1722018-03-26 08:58:581137 std::vector<std::unique_ptr<NavigationLoaderInterceptor>> interceptors_;
1138 size_t interceptor_index_ = 0;
kinuko69732972017-05-29 08:50:071139
John Abd-El-Malek1df61792018-01-12 20:40:451140 std::unique_ptr<network::ResourceRequest> resource_request_;
Makoto Shimazu44c2c3232018-03-30 01:10:201141 // Non-NetworkService: |request_info_| is updated along with
1142 // |resource_request_| on redirects.
1143 std::unique_ptr<NavigationRequestInfo> request_info_;
John Abd-El-Malek576c6132017-11-04 00:33:581144 int frame_tree_node_id_ = 0;
arthursonzogni40db5f52018-01-08 16:38:491145 GlobalRequestID global_request_id_;
Michael Nordman2431f5f2017-09-13 04:58:151146 net::RedirectInfo redirect_info_;
Daniel Bratell0dfa6282017-11-08 10:12:231147 int redirect_limit_ = net::URLRequest::kMaxRedirects;
kinuko69732972017-05-29 08:50:071148 ResourceContext* resource_context_;
yzshenefcb7c72017-06-16 23:12:301149 base::Callback<WebContents*()> web_contents_getter_;
John Abd-El-Malekeb1a5382018-01-05 16:58:001150 std::unique_ptr<NavigationUIData> navigation_ui_data_;
anantae60d1d42017-06-20 04:16:271151 scoped_refptr<URLLoaderFactoryGetter> default_url_loader_factory_getter_;
arthursonzogni2695d04d2017-12-12 08:39:011152
yzshenefcb7c72017-06-16 23:12:301153 std::unique_ptr<ThrottlingURLLoader> url_loader_;
arthursonzogni2695d04d2017-12-12 08:39:011154
Chong Zhang7607f1f2018-06-01 20:52:201155 // Caches the modified request headers provided by clients during redirect,
1156 // will be consumed by next |url_loader_->FollowRedirect()|.
1157 base::Optional<net::HttpRequestHeaders> url_loader_modified_request_headers_;
1158
mmenkeed44e6c2017-06-28 21:13:321159 BlobHandles blob_handles_;
Min Qin83d07872017-10-26 23:22:411160 std::vector<GURL> url_chain_;
kinuko69732972017-05-29 08:50:071161
arthursonzogni40db5f52018-01-08 16:38:491162 // Current URL that is being navigated, updated after redirection.
1163 GURL url_;
1164
anantae60d1d42017-06-20 04:16:271165 // Currently used by the AppCache loader to pass its factory to the
1166 // renderer which enables it to handle subresources.
Kinuko Yasuda250577c2017-10-29 02:51:241167 base::Optional<SubresourceLoaderParams> subresource_loader_params_;
anantae60d1d42017-06-20 04:16:271168
mmenkeed44e6c2017-06-28 21:13:321169 // This is referenced only on the UI thread.
arthursonzogni1fd60e62018-05-09 15:57:321170 base::WeakPtr<NavigationURLLoaderImpl> owner_;
mmenkeed44e6c2017-06-28 21:13:321171
anantab9800e52017-07-29 18:04:131172 // Set to true if the default URLLoader (network service) was used for the
1173 // current navigation.
1174 bool default_loader_used_ = false;
1175
1176 // URLLoaderClient binding for loaders created for responses received from the
1177 // network loader.
John Abd-El-Malekb165dc52018-01-18 17:12:181178 mojo::Binding<network::mojom::URLLoaderClient> response_loader_binding_;
anantab9800e52017-07-29 18:04:131179
1180 // URLLoader instance for response loaders, i.e loaders created for handing
1181 // responses received from the network URLLoader.
John Abd-El-Malekb165dc52018-01-18 17:12:181182 network::mojom::URLLoaderPtr response_url_loader_;
anantab9800e52017-07-29 18:04:131183
1184 // Set to true if we receive a valid response from a URLLoader, i.e.
1185 // URLLoaderClient::OnReceivedResponse() is called.
1186 bool received_response_ = false;
1187
Alex Clarke1e08882b32017-10-06 14:22:401188 bool started_ = false;
1189
Ken Rockot314714c2017-11-05 23:36:241190 // Lazily initialized and used in the case of non-network resource
1191 // navigations. Keyed by URL scheme.
John Abd-El-Malekb165dc52018-01-18 17:12:181192 std::map<std::string, network::mojom::URLLoaderFactoryPtr>
Ken Rockot314714c2017-11-05 23:36:241193 non_network_url_loader_factories_;
1194
Makoto Shimazu44c2c3232018-03-30 01:10:201195 // Non-NetworkService:
1196 // Generator of a request handler for sending request to the network. This
1197 // captures all of parameters to create a
1198 // SingleRequestURLLoaderFactory::RequestHandler. Used only when
1199 // NetworkService is disabled but IsLoaderInterceptionEnabled() is true.
Makoto Shimazu684a5ad2018-05-29 08:20:501200 // Set |was_request_intercepted| to true if the request was intercepted by an
1201 // interceptor and the request is falling back to the network. In that case,
1202 // any interceptors won't intercept the request.
1203 base::RepeatingCallback<SingleRequestURLLoaderFactory::RequestHandler(
1204 bool /* was_request_intercepted */)>
Makoto Shimazu44c2c3232018-03-30 01:10:201205 default_request_handler_factory_;
1206
Min Qin40b72172017-09-27 00:19:171207 // The completion status if it has been received. This is needed to handle
1208 // the case that the response is intercepted by download, and OnComplete() is
1209 // already called while we are transferring the |url_loader_| and response
1210 // body to download code.
Takashi Toyoshimaaa278662017-11-20 11:11:261211 base::Optional<network::URLLoaderCompletionStatus> status_;
Min Qin40b72172017-09-27 00:19:171212
Ken Rockota0dfaca12018-02-15 07:26:251213 // Before creating this URLLoaderRequestController on UI thread, the embedder
1214 // may have elected to proxy the URLLoaderFactory request, in which case these
1215 // fields will contain input (info) and output (request) endpoints for the
1216 // proxy. If this controller is handling a request for which proxying is
1217 // supported, requests will be plumbed through these endpoints.
1218 //
1219 // Note that these are only used for requests that go to the Network Service.
1220 network::mojom::URLLoaderFactoryRequest proxied_factory_request_;
1221 network::mojom::URLLoaderFactoryPtrInfo proxied_factory_info_;
1222
John Abd-El-Maleka67add82018-03-09 18:22:011223 // The schemes that this loader can use. For anything else we'll try external
1224 // protocol handlers.
1225 std::set<std::string> known_schemes_;
1226
Makoto Shimazu44c2c3232018-03-30 01:10:201227 mutable base::WeakPtrFactory<URLLoaderRequestController> weak_factory_;
arthursonzogni2695d04d2017-12-12 08:39:011228
kinuko69732972017-05-29 08:50:071229 DISALLOW_COPY_AND_ASSIGN(URLLoaderRequestController);
1230};
1231
Min Qin75ed6df2017-12-01 20:39:151232// TODO(https://crbug.com/790734): pass |navigation_ui_data| along with the
1233// request so that it could be modified.
arthursonzogni1fd60e62018-05-09 15:57:321234NavigationURLLoaderImpl::NavigationURLLoaderImpl(
scottmg69985212017-04-12 16:47:281235 ResourceContext* resource_context,
1236 StoragePartition* storage_partition,
1237 std::unique_ptr<NavigationRequestInfo> request_info,
1238 std::unique_ptr<NavigationUIData> navigation_ui_data,
scottmgd2021c92017-05-15 16:58:051239 ServiceWorkerNavigationHandle* service_worker_navigation_handle,
scottmg69985212017-04-12 16:47:281240 AppCacheNavigationHandle* appcache_handle,
Alex Clarke1e08882b32017-10-06 14:22:401241 NavigationURLLoaderDelegate* delegate,
Kinuko Yasuda7f3e1722018-03-26 08:58:581242 std::vector<std::unique_ptr<NavigationLoaderInterceptor>>
1243 initial_interceptors)
Min Qin37db5102017-09-13 21:21:251244 : delegate_(delegate),
1245 allow_download_(request_info->common_params.allow_download),
1246 weak_factory_(this) {
scottmg95feea52017-04-12 17:51:331247 DCHECK_CURRENTLY_ON(BrowserThread::UI);
John Abd-El-Malekfcb2ecf2017-11-15 23:15:301248 int frame_tree_node_id = request_info->frame_tree_node_id;
ananta5149d8e2017-04-21 00:01:371249
yzshen0f278522017-05-01 17:10:221250 TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP1(
1251 "navigation", "Navigation timeToResponseStarted", this,
kinuko69732972017-05-29 08:50:071252 request_info->common_params.navigation_start, "FrameTreeNode id",
John Abd-El-Malekfcb2ecf2017-11-15 23:15:301253 frame_tree_node_id);
yzshen0f278522017-05-01 17:10:221254
arthursonzogni2695d04d2017-12-12 08:39:011255 ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core =
1256 service_worker_navigation_handle
1257 ? service_worker_navigation_handle->core()
1258 : nullptr;
1259
1260 AppCacheNavigationHandleCore* appcache_handle_core =
1261 appcache_handle ? appcache_handle->core() : nullptr;
1262
Yuzhu Shencb3011f62018-02-08 02:51:501263 std::unique_ptr<network::ResourceRequest> new_request = CreateResourceRequest(
1264 request_info.get(), frame_tree_node_id, allow_download_);
Yutaka Hirano61e41b3c2018-05-31 05:31:061265 new_request->transition_type = request_info->common_params.transition;
Tsuyoshi Horob8d512a2018-01-25 17:01:591266
Yutaka Hiranod8789f92018-01-30 09:59:511267 if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
arthursonzogni2695d04d2017-12-12 08:39:011268 DCHECK(!request_controller_);
1269 request_controller_ = std::make_unique<URLLoaderRequestController>(
Kinuko Yasuda7f3e1722018-03-26 08:58:581270 /* initial_interceptors = */
1271 std::vector<std::unique_ptr<NavigationLoaderInterceptor>>(),
Tsuyoshi Horob8d512a2018-01-25 17:01:591272 std::move(new_request), resource_context,
arthursonzogni40db5f52018-01-08 16:38:491273 /* default_url_factory_getter = */ nullptr,
1274 request_info->common_params.url,
Ken Rockota0dfaca12018-02-15 07:26:251275 /* proxied_url_loader_factory_request */ nullptr,
John Abd-El-Maleka67add82018-03-09 18:22:011276 /* proxied_url_loader_factory_info */ nullptr, std::set<std::string>(),
arthursonzogni40db5f52018-01-08 16:38:491277 weak_factory_.GetWeakPtr());
arthursonzogni2695d04d2017-12-12 08:39:011278
1279 BrowserThread::PostTask(
1280 BrowserThread::IO, FROM_HERE,
1281 base::BindOnce(
1282 &URLLoaderRequestController::StartWithoutNetworkService,
1283 base::Unretained(request_controller_.get()),
Tsuyoshi Horo70014ad2018-02-14 11:20:141284 base::RetainedRef(storage_partition->GetURLRequestContext()),
arthursonzogni2695d04d2017-12-12 08:39:011285 base::Unretained(storage_partition->GetFileSystemContext()),
1286 base::Unretained(service_worker_navigation_handle_core),
tzikccf160c2018-02-20 12:43:131287 base::Unretained(appcache_handle_core), std::move(request_info),
1288 std::move(navigation_ui_data)));
arthursonzogni2695d04d2017-12-12 08:39:011289 return;
1290 }
1291
scottmgd2021c92017-05-15 16:58:051292 // Check if a web UI scheme wants to handle this request.
Ken Rockot6414c4d92017-11-08 19:58:321293 FrameTreeNode* frame_tree_node =
1294 FrameTreeNode::GloballyFindByID(frame_tree_node_id);
John Abd-El-Malekb165dc52018-01-18 17:12:181295 network::mojom::URLLoaderFactoryPtrInfo factory_for_webui;
scottmgd2021c92017-05-15 16:58:051296 const auto& schemes = URLDataManagerBackend::GetWebUISchemes();
John Abd-El-Malekbb0bc8e2017-11-11 01:08:151297 std::string scheme = new_request->url.scheme();
1298 if (std::find(schemes.begin(), schemes.end(), scheme) != schemes.end()) {
Chris Mumfordbae8a742018-03-01 23:02:231299 factory_for_webui = CreateWebUIURLLoaderBinding(
1300 frame_tree_node->current_frame_host(), scheme)
1301 .PassInterface();
ananta5149d8e2017-04-21 00:01:371302 }
scottmgd2021c92017-05-15 16:58:051303
Ken Rockota0dfaca12018-02-15 07:26:251304 network::mojom::URLLoaderFactoryPtrInfo proxied_factory_info;
1305 network::mojom::URLLoaderFactoryRequest proxied_factory_request;
Chris Mumford942075ad2018-05-19 00:22:041306 auto* partition = static_cast<StoragePartitionImpl*>(storage_partition);
Ken Rockota0dfaca12018-02-15 07:26:251307 if (frame_tree_node) {
1308 // |frame_tree_node| may be null in some unit test environments.
1309 GetContentClient()
1310 ->browser()
1311 ->RegisterNonNetworkNavigationURLLoaderFactories(
John Abd-El-Malekea006302018-05-10 05:50:461312 frame_tree_node_id, &non_network_url_loader_factories_);
Ken Rockota0dfaca12018-02-15 07:26:251313
1314 // The embedder may want to proxy all network-bound URLLoaderFactory
1315 // requests that it can. If it elects to do so, we'll pass its proxy
1316 // endpoints off to the URLLoaderRequestController where wthey will be
1317 // connected if the request type supports proxying.
1318 network::mojom::URLLoaderFactoryPtrInfo factory_info;
1319 auto factory_request = mojo::MakeRequest(&factory_info);
Andrey Kosyakov8d49c5062018-03-15 19:50:491320 bool use_proxy = GetContentClient()->browser()->WillCreateURLLoaderFactory(
1321 frame_tree_node->current_frame_host(), true /* is_navigation */,
1322 &factory_request);
1323 if (RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory(
Jochen Eisingercdc12d12018-05-08 15:07:471324 frame_tree_node->current_frame_host(), true, false,
1325 &factory_request)) {
Andrey Kosyakov8d49c5062018-03-15 19:50:491326 use_proxy = true;
1327 }
1328 if (use_proxy) {
Ken Rockota0dfaca12018-02-15 07:26:251329 proxied_factory_request = std::move(factory_request);
1330 proxied_factory_info = std::move(factory_info);
1331 }
Chris Mumford942075ad2018-05-19 00:22:041332
1333 const std::string storage_domain;
1334 non_network_url_loader_factories_[url::kFileSystemScheme] =
1335 CreateFileSystemURLLoaderFactory(frame_tree_node->current_frame_host(),
1336 /*is_navigation=*/true,
1337 partition->GetFileSystemContext(),
1338 storage_domain);
Ken Rockota0dfaca12018-02-15 07:26:251339 }
1340
John Abd-El-Maleka67add82018-03-09 18:22:011341 non_network_url_loader_factories_[url::kFileScheme] =
1342 std::make_unique<FileURLLoaderFactory>(
1343 partition->browser_context()->GetPath(),
1344 base::CreateSequencedTaskRunnerWithTraits(
1345 {base::MayBlock(), base::TaskPriority::BACKGROUND,
1346 base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}));
1347 std::set<std::string> known_schemes;
1348 for (auto& iter : non_network_url_loader_factories_)
1349 known_schemes.insert(iter.first);
1350
kinuko69732972017-05-29 08:50:071351 DCHECK(!request_controller_);
Jeremy Roman04f27c372017-10-27 15:20:551352 request_controller_ = std::make_unique<URLLoaderRequestController>(
Kinuko Yasuda7f3e1722018-03-26 08:58:581353 std::move(initial_interceptors), std::move(new_request), resource_context,
arthursonzogni40db5f52018-01-08 16:38:491354 partition->url_loader_factory_getter(), request_info->common_params.url,
Ken Rockota0dfaca12018-02-15 07:26:251355 std::move(proxied_factory_request), std::move(proxied_factory_info),
John Abd-El-Maleka67add82018-03-09 18:22:011356 std::move(known_schemes), weak_factory_.GetWeakPtr());
scottmgd2021c92017-05-15 16:58:051357 BrowserThread::PostTask(
1358 BrowserThread::IO, FROM_HERE,
Ken Rockot387ddd5a2018-01-30 19:18:401359 base::BindOnce(
1360 &URLLoaderRequestController::Start,
1361 base::Unretained(request_controller_.get()),
Tsuyoshi Horo70014ad2018-02-14 11:20:141362 base::RetainedRef(storage_partition->GetURLRequestContext()),
Ken Rockot387ddd5a2018-01-30 19:18:401363 service_worker_navigation_handle_core, appcache_handle_core,
1364 std::move(request_info), std::move(navigation_ui_data),
1365 std::move(factory_for_webui), frame_tree_node_id,
1366 ServiceManagerConnection::GetForProcess()->GetConnector()->Clone()));
scottmg69985212017-04-12 16:47:281367}
1368
arthursonzogni1fd60e62018-05-09 15:57:321369NavigationURLLoaderImpl::~NavigationURLLoaderImpl() {
kinuko69732972017-05-29 08:50:071370 BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE,
1371 request_controller_.release());
1372}
scottmg69985212017-04-12 16:47:281373
Chong Zhang7607f1f2018-06-01 20:52:201374void NavigationURLLoaderImpl::FollowRedirect(
1375 const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
yzshenefcb7c72017-06-16 23:12:301376 BrowserThread::PostTask(
1377 BrowserThread::IO, FROM_HERE,
tzik0f14f192017-08-15 02:43:331378 base::BindOnce(&URLLoaderRequestController::FollowRedirect,
Chong Zhang7607f1f2018-06-01 20:52:201379 base::Unretained(request_controller_.get()),
1380 modified_request_headers));
scottmg95feea52017-04-12 17:51:331381}
scottmg69985212017-04-12 16:47:281382
arthursonzogni1fd60e62018-05-09 15:57:321383void NavigationURLLoaderImpl::ProceedWithResponse() {}
scottmg69985212017-04-12 16:47:281384
arthursonzogni1fd60e62018-05-09 15:57:321385void NavigationURLLoaderImpl::OnReceiveResponse(
John Abd-El-Malek46248032018-01-17 19:11:231386 scoped_refptr<network::ResourceResponse> response,
John Abd-El-Malekb165dc52018-01-18 17:12:181387 network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
arthursonzogni40db5f52018-01-08 16:38:491388 std::unique_ptr<NavigationData> navigation_data,
1389 const GlobalRequestID& global_request_id,
1390 bool is_download,
1391 bool is_stream,
John Abd-El-Malekb165dc52018-01-18 17:12:181392 network::mojom::DownloadedTempFilePtr downloaded_file) {
arthursonzogni3a4ca9f2017-12-07 17:58:341393 TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", this,
arthursonzogni1fd60e62018-05-09 15:57:321394 "&NavigationURLLoaderImpl", this, "success", true);
arthursonzogni3a4ca9f2017-12-07 17:58:341395
scottmgefb697302017-04-12 22:37:301396 // TODO(scottmg): This needs to do more of what
arthursonzogni3a4ca9f2017-12-07 17:58:341397 // NavigationResourceHandler::OnResponseStarted() does.
arthursonzogni3a4ca9f2017-12-07 17:58:341398
arthursonzogni3a4ca9f2017-12-07 17:58:341399 delegate_->OnResponseStarted(
arthursonzognif34adf092018-04-24 17:06:131400 std::move(response), std::move(url_loader_client_endpoints),
Andrey Kosyakov87cd9252018-03-27 16:58:271401 std::move(navigation_data), global_request_id,
arthursonzogni40db5f52018-01-08 16:38:491402 allow_download_ && is_download, is_stream,
arthursonzogni3a4ca9f2017-12-07 17:58:341403 request_controller_->TakeSubresourceLoaderParams());
scottmg95feea52017-04-12 17:51:331404}
scottmg69985212017-04-12 16:47:281405
arthursonzogni1fd60e62018-05-09 15:57:321406void NavigationURLLoaderImpl::OnReceiveRedirect(
scottmg69985212017-04-12 16:47:281407 const net::RedirectInfo& redirect_info,
John Abd-El-Malek46248032018-01-17 19:11:231408 scoped_refptr<network::ResourceResponse> response) {
scottmg95feea52017-04-12 17:51:331409 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Andrey Kosyakova924c8b2017-08-18 17:37:231410 delegate_->OnRequestRedirected(redirect_info, std::move(response));
scottmg95feea52017-04-12 17:51:331411}
scottmg69985212017-04-12 16:47:281412
arthursonzogni1fd60e62018-05-09 15:57:321413void NavigationURLLoaderImpl::OnComplete(
Takashi Toyoshimaaa278662017-11-20 11:11:261414 const network::URLLoaderCompletionStatus& status) {
Takashi Toyoshima8f988532017-11-13 07:32:371415 if (status.error_code == net::OK)
John Abd-El-Malekb906d282017-08-31 19:36:431416 return;
1417
1418 TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", this,
arthursonzogni1fd60e62018-05-09 15:57:321419 "&NavigationURLLoaderImpl", this, "success", false);
Lucas Garron0efab6d2017-08-30 22:28:511420
Johannes Henkel6a43fef2018-05-17 18:41:521421 delegate_->OnRequestFailed(status);
yzshen384441de2017-04-19 23:26:141422}
scottmg69985212017-04-12 16:47:281423
arthursonzogni1fd60e62018-05-09 15:57:321424void NavigationURLLoaderImpl::SetBeginNavigationInterceptorForTesting(
John Abd-El-Malekdb3a13b2018-05-01 17:52:021425 const BeginNavigationInterceptor& interceptor) {
1426 DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::IO) ||
1427 BrowserThread::CurrentlyOn(BrowserThread::IO));
1428 DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
1429 g_interceptor.Get() = interceptor;
1430}
1431
arthursonzogni1fd60e62018-05-09 15:57:321432void NavigationURLLoaderImpl::OnRequestStarted(base::TimeTicks timestamp) {
arthursonzogni2695d04d2017-12-12 08:39:011433 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1434 delegate_->OnRequestStarted(timestamp);
1435}
1436
arthursonzogni1fd60e62018-05-09 15:57:321437void NavigationURLLoaderImpl::BindNonNetworkURLLoaderFactoryRequest(
Ken Rockota0dfaca12018-02-15 07:26:251438 int frame_tree_node_id,
Ken Rockot314714c2017-11-05 23:36:241439 const GURL& url,
John Abd-El-Malekb165dc52018-01-18 17:12:181440 network::mojom::URLLoaderFactoryRequest factory) {
Ken Rockot314714c2017-11-05 23:36:241441 auto it = non_network_url_loader_factories_.find(url.scheme());
1442 if (it == non_network_url_loader_factories_.end()) {
1443 DVLOG(1) << "Ignoring request with unknown scheme: " << url.spec();
1444 return;
1445 }
Ken Rockota0dfaca12018-02-15 07:26:251446 FrameTreeNode* frame_tree_node =
1447 FrameTreeNode::GloballyFindByID(frame_tree_node_id);
1448 GetContentClient()->browser()->WillCreateURLLoaderFactory(
1449 frame_tree_node->current_frame_host(), true /* is_navigation */,
1450 &factory);
Ken Rockot314714c2017-11-05 23:36:241451 it->second->Clone(std::move(factory));
1452}
1453
scottmg69985212017-04-12 16:47:281454} // namespace content