blob: ea9f9f31fa809bd09f6e7a27e3d5ae08f3715dca [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 Horo6e6782d2018-06-07 02:32:47402 request_info->begin_params->load_flags,
Tsuyoshi Horo70014ad2018-02-14 11:20:14403 base::MakeRefCounted<
404 SignedExchangeURLLoaderFactoryForNonNetworkService>(
405 resource_context_, url_request_context_getter),
406 base::BindRepeating(
407 &URLLoaderRequestController::CreateURLLoaderThrottles,
Tsuyoshi Horof7702192018-03-07 15:00:36408 base::Unretained(this)),
409 url_request_context_getter));
Tsuyoshi Horob8d512a2018-01-25 17:01:59410 }
411
John Abd-El-Malekdb3a13b2018-05-01 17:52:02412 uint32_t options = GetURLLoaderOptions(request_info->is_main_frame);
413
414 bool intercepted = false;
415 if (g_interceptor.Get()) {
416 intercepted = g_interceptor.Get().Run(
417 &url_loader, frame_tree_node_id_, 0 /* request_id */, options,
418 *resource_request_.get(), &url_loader_client,
419 net::MutableNetworkTrafficAnnotationTag(
420 kNavigationUrlLoaderTrafficAnnotation));
421 }
422
arthursonzogni2695d04d2017-12-12 08:39:01423 // The ResourceDispatcherHostImpl can be null in unit tests.
John Abd-El-Malekdb3a13b2018-05-01 17:52:02424 if (!intercepted && ResourceDispatcherHostImpl::Get()) {
arthursonzogni2695d04d2017-12-12 08:39:01425 ResourceDispatcherHostImpl::Get()->BeginNavigationRequest(
426 resource_context_, url_request_context_getter->GetURLRequestContext(),
427 upload_file_system_context, *request_info,
arthursonzogni662d723c2018-04-24 16:13:22428 std::move(navigation_ui_data_), std::move(url_loader_client),
arthursonzogni2695d04d2017-12-12 08:39:01429 std::move(url_loader), service_worker_navigation_handle_core,
John Abd-El-Malekdb3a13b2018-05-01 17:52:02430 appcache_handle_core, options, &global_request_id_);
arthursonzogni2695d04d2017-12-12 08:39:01431 }
432
433 // TODO(arthursonzogni): Detect when the ResourceDispatcherHost didn't
434 // create a URLLoader. When it doesn't, do not send OnRequestStarted().
435 BrowserThread::PostTask(
436 BrowserThread::UI, FROM_HERE,
arthursonzogni1fd60e62018-05-09 15:57:32437 base::BindOnce(&NavigationURLLoaderImpl::OnRequestStarted, owner_,
438 base::TimeTicks::Now()));
arthursonzogni2695d04d2017-12-12 08:39:01439 }
440
441 // TODO(arthursonzogni): See if this could eventually be unified with Start().
442 void StartWithoutNetworkService(
443 net::URLRequestContextGetter* url_request_context_getter,
444 storage::FileSystemContext* upload_file_system_context,
445 ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
446 AppCacheNavigationHandleCore* appcache_handle_core,
447 std::unique_ptr<NavigationRequestInfo> request_info,
448 std::unique_ptr<NavigationUIData> navigation_ui_data) {
Yutaka Hiranod8789f92018-01-30 09:59:51449 DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
arthursonzogni2695d04d2017-12-12 08:39:01450 DCHECK_CURRENTLY_ON(BrowserThread::IO);
451 DCHECK(!started_);
452 started_ = true;
Makoto Shimazu44c2c3232018-03-30 01:10:20453 request_info_ = std::move(request_info);
454 frame_tree_node_id_ = request_info_->frame_tree_node_id;
Yuzhu Shencb3011f62018-02-08 02:51:50455 web_contents_getter_ = base::BindRepeating(
Yuzhu Shen9508fc72018-02-08 23:18:59456 &GetWebContentsFromFrameTreeNodeID, frame_tree_node_id_);
Makoto Shimazu44c2c3232018-03-30 01:10:20457 navigation_ui_data_ = std::move(navigation_ui_data);
458 default_request_handler_factory_ = base::BindRepeating(
459 &URLLoaderRequestController::
460 CreateDefaultRequestHandlerForNonNetworkService,
461 // base::Unretained(this) is safe since
462 // |default_request_handler_factory_| could be called only from |this|.
463 base::Unretained(this), base::Unretained(url_request_context_getter),
464 base::Unretained(upload_file_system_context),
arthursonzogni2695d04d2017-12-12 08:39:01465 base::Unretained(service_worker_navigation_handle_core),
466 base::Unretained(appcache_handle_core));
467
Marijn Kruisselbrink8a7fd102018-06-05 17:30:39468 // Requests to Blob scheme won't get redirected to/from other schemes
469 // or be intercepted, so we just let it go here.
470 if (request_info_->common_params.url.SchemeIsBlob() &&
471 request_info_->blob_url_loader_factory) {
472 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
473 network::SharedURLLoaderFactory::Create(
474 std::move(request_info_->blob_url_loader_factory)),
475 CreateURLLoaderThrottles(), -1 /* routing_id */, 0 /* request_id? */,
476 network::mojom::kURLLoadOptionNone, resource_request_.get(), this,
477 kNavigationUrlLoaderTrafficAnnotation,
478 base::ThreadTaskRunnerHandle::Get());
479 return;
480 }
481
Makoto Shimazu44c2c3232018-03-30 01:10:20482 // If S13nServiceWorker is disabled, just use
483 // |default_request_handler_factory_| and return. The non network service
484 // request handling goes through ResourceDispatcherHost which has legacy
485 // hooks for service worker (ServiceWorkerRequestInterceptor), so no service
486 // worker interception is needed here.
487 if (!ServiceWorkerUtils::IsServicificationEnabled() ||
488 !service_worker_navigation_handle_core) {
489 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
490 base::MakeRefCounted<SingleRequestURLLoaderFactory>(
Makoto Shimazu684a5ad2018-05-29 08:20:50491 default_request_handler_factory_.Run(
492 false /* was_request_intercepted */)),
Makoto Shimazu44c2c3232018-03-30 01:10:20493 CreateURLLoaderThrottles(), -1 /* routing_id */, 0 /* request_id */,
494 network::mojom::kURLLoadOptionNone, resource_request_.get(),
495 this /* client */, kNavigationUrlLoaderTrafficAnnotation,
496 base::ThreadTaskRunnerHandle::Get());
497 return;
498 }
499
500 // Otherwise, if S13nServiceWorker is enabled, create an interceptor so
501 // S13nServiceWorker has a chance to intercept the request.
502 std::unique_ptr<NavigationLoaderInterceptor> service_worker_interceptor =
503 CreateServiceWorkerInterceptor(*request_info_,
504 service_worker_navigation_handle_core);
505 // If an interceptor is not created for some reasons (e.g. the origin is not
506 // secure), we no longer have to go through the rest of the network service
507 // code.
508 if (!service_worker_interceptor) {
509 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
510 base::MakeRefCounted<SingleRequestURLLoaderFactory>(
Makoto Shimazu684a5ad2018-05-29 08:20:50511 default_request_handler_factory_.Run(
512 false /* was_request_intercepted */)),
Makoto Shimazu44c2c3232018-03-30 01:10:20513 CreateURLLoaderThrottles(), -1 /* routing_id */, 0 /* request_id */,
514 network::mojom::kURLLoadOptionNone, resource_request_.get(),
515 this /* client */, kNavigationUrlLoaderTrafficAnnotation,
516 base::ThreadTaskRunnerHandle::Get());
517 return;
518 }
519
520 interceptors_.push_back(std::move(service_worker_interceptor));
521
522 // TODO(shimazu): Make sure we have a consistent global id for the
523 // navigation request.
524 global_request_id_ = MakeGlobalRequestID();
525 Restart();
arthursonzogni2695d04d2017-12-12 08:39:01526 }
527
kinuko69732972017-05-29 08:50:07528 void Start(
Tsuyoshi Horo70014ad2018-02-14 11:20:14529 net::URLRequestContextGetter* url_request_context_getter,
kinuko69732972017-05-29 08:50:07530 ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
531 AppCacheNavigationHandleCore* appcache_handle_core,
532 std::unique_ptr<NavigationRequestInfo> request_info,
John Abd-El-Malekeb1a5382018-01-05 16:58:00533 std::unique_ptr<NavigationUIData> navigation_ui_data,
John Abd-El-Malekb165dc52018-01-18 17:12:18534 network::mojom::URLLoaderFactoryPtrInfo factory_for_webui,
John Abd-El-Malek576c6132017-11-04 00:33:58535 int frame_tree_node_id,
kinuko69732972017-05-29 08:50:07536 std::unique_ptr<service_manager::Connector> connector) {
Yutaka Hiranod8789f92018-01-30 09:59:51537 DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
kinuko69732972017-05-29 08:50:07538 DCHECK_CURRENTLY_ON(BrowserThread::IO);
Alex Clarke1e08882b32017-10-06 14:22:40539 DCHECK(!started_);
arthursonzogni40db5f52018-01-08 16:38:49540 global_request_id_ = MakeGlobalRequestID();
John Abd-El-Malek576c6132017-11-04 00:33:58541 frame_tree_node_id_ = frame_tree_node_id;
Alex Clarke1e08882b32017-10-06 14:22:40542 started_ = true;
John Abd-El-Malek576c6132017-11-04 00:33:58543 web_contents_getter_ =
544 base::Bind(&GetWebContentsFromFrameTreeNodeID, frame_tree_node_id);
John Abd-El-Malekeb1a5382018-01-05 16:58:00545 navigation_ui_data_ = std::move(navigation_ui_data);
kinuko69732972017-05-29 08:50:07546
547 if (resource_request_->request_body) {
mmenkeed44e6c2017-06-28 21:13:32548 GetBodyBlobDataHandles(resource_request_->request_body.get(),
549 resource_context_, &blob_handles_);
kinuko69732972017-05-29 08:50:07550 }
551
552 // Requests to WebUI scheme won't get redirected to/from other schemes
553 // or be intercepted, so we just let it go here.
554 if (factory_for_webui.is_valid()) {
yzshenefcb7c72017-06-16 23:12:30555 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
Antonio Gomes9cdc09a2018-05-07 23:24:26556 base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
Yuzhu Shend87986f2018-01-17 22:16:37557 std::move(factory_for_webui)),
Tsuyoshi Horo70014ad2018-02-14 11:20:14558 CreateURLLoaderThrottles(), 0 /* routing_id */, 0 /* request_id? */,
John Abd-El-Malekb165dc52018-01-18 17:12:18559 network::mojom::kURLLoadOptionNone, resource_request_.get(), this,
560 kNavigationUrlLoaderTrafficAnnotation,
Hajime Hoshif5ef35262017-11-28 19:13:00561 base::ThreadTaskRunnerHandle::Get());
kinuko69732972017-05-29 08:50:07562 return;
563 }
564
Marijn Kruisselbrink07bf59d52018-04-03 21:50:25565 // Requests to Blob scheme won't get redirected to/from other schemes
566 // or be intercepted, so we just let it go here.
567 if (request_info->common_params.url.SchemeIsBlob() &&
568 request_info->blob_url_loader_factory) {
569 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
570 network::SharedURLLoaderFactory::Create(
571 std::move(request_info->blob_url_loader_factory)),
Kinuko Yasuda08dd29a2018-05-21 23:45:48572 CreateURLLoaderThrottles(), 0 /* routing_id */, 0 /* request_id? */,
Marijn Kruisselbrink07bf59d52018-04-03 21:50:25573 network::mojom::kURLLoadOptionNone, resource_request_.get(), this,
574 kNavigationUrlLoaderTrafficAnnotation,
575 base::ThreadTaskRunnerHandle::Get());
576 return;
577 }
578
kinuko69732972017-05-29 08:50:07579 if (service_worker_navigation_handle_core) {
Kinuko Yasuda7f3e1722018-03-26 08:58:58580 std::unique_ptr<NavigationLoaderInterceptor> service_worker_interceptor =
Makoto Shimazu44c2c3232018-03-30 01:10:20581 CreateServiceWorkerInterceptor(*request_info,
582 service_worker_navigation_handle_core);
Kinuko Yasuda7f3e1722018-03-26 08:58:58583 if (service_worker_interceptor)
584 interceptors_.push_back(std::move(service_worker_interceptor));
kinuko69732972017-05-29 08:50:07585 }
586
587 if (appcache_handle_core) {
Kinuko Yasuda7f3e1722018-03-26 08:58:58588 std::unique_ptr<NavigationLoaderInterceptor> appcache_interceptor =
anantaa2c8ec62017-06-09 23:44:05589 AppCacheRequestHandler::InitializeForNavigationNetworkService(
anantae60d1d42017-06-20 04:16:27590 *resource_request_, appcache_handle_core,
591 default_url_loader_factory_getter_.get());
Kinuko Yasuda7f3e1722018-03-26 08:58:58592 if (appcache_interceptor)
593 interceptors_.push_back(std::move(appcache_interceptor));
kinuko69732972017-05-29 08:50:07594 }
595
Tsuyoshi Horo46f5fff2018-05-10 12:33:35596 if (signed_exchange_utils::IsSignedExchangeHandlingEnabled()) {
Kunihiko Sakamotoe9a0502c2018-06-06 09:29:51597 // Signed Exchange is currently disabled when Network Service is enabled
598 // (https://crbug.com/849935), but still create WebPackageRequestHandler
599 // in order to show error message (and devtools warning) to users.
600
Tsuyoshi Horo561163b2018-03-27 03:11:23601 // It is safe to pass the callback of CreateURLLoaderThrottles with the
Tsuyoshi Horo70014ad2018-02-14 11:20:14602 // unretained |this|, because the passed callback will be used by a
603 // SignedExchangeHandler which is indirectly owned by |this| until its
604 // header is verified and parsed, that's where the getter is used.
Kinuko Yasuda7f3e1722018-03-26 08:58:58605 interceptors_.push_back(std::make_unique<WebPackageRequestHandler>(
Tsuyoshi Horo70014ad2018-02-14 11:20:14606 url::Origin::Create(request_info->common_params.url),
Tsuyoshi Horo32b51f12018-05-09 17:58:46607 request_info->common_params.url,
Kinuko Yasuda32a25652018-02-19 08:14:25608 GetURLLoaderOptions(request_info->is_main_frame),
Tsuyoshi Horocdbb4902018-04-12 06:09:14609 request_info->frame_tree_node_id,
Tsuyoshi Horo32b51f12018-05-09 17:58:46610 request_info->devtools_navigation_token,
611 request_info->report_raw_headers,
Tsuyoshi Horo6e6782d2018-06-07 02:32:47612 request_info->begin_params->load_flags,
Chong Zhang5271432a2018-03-01 23:31:02613 default_url_loader_factory_getter_->GetNetworkFactory(),
Tsuyoshi Horo70014ad2018-02-14 11:20:14614 base::BindRepeating(
615 &URLLoaderRequestController::CreateURLLoaderThrottles,
Tsuyoshi Horof7702192018-03-07 15:00:36616 base::Unretained(this)),
617 url_request_context_getter));
Tsuyoshi Horob8d512a2018-01-25 17:01:59618 }
619
Jian Li18e29242018-05-10 22:25:12620 std::vector<std::unique_ptr<URLLoaderRequestInterceptor>>
621 browser_interceptors = GetContentClient()
622 ->browser()
623 ->WillCreateURLLoaderRequestInterceptors(
624 navigation_ui_data_.get(),
625 request_info->frame_tree_node_id);
626 if (!browser_interceptors.empty()) {
627 for (auto& browser_interceptor : browser_interceptors) {
628 interceptors_.push_back(
629 std::make_unique<NavigationLoaderInterceptorBrowserContainer>(
630 std::move(browser_interceptor)));
631 }
632 }
633
yzshenefcb7c72017-06-16 23:12:30634 Restart();
kinuko69732972017-05-29 08:50:07635 }
636
Michael Nordman2431f5f2017-09-13 04:58:15637 // This could be called multiple times to follow a chain of redirects.
yzshenefcb7c72017-06-16 23:12:30638 void Restart() {
Kinuko Yasuda7f3e1722018-03-26 08:58:58639 DCHECK(IsLoaderInterceptionEnabled());
Tsuyoshi Horo5204c872017-09-21 16:28:17640 // Clear |url_loader_| if it's not the default one (network). This allows
641 // the restarted request to use a new loader, instead of, e.g., reusing the
642 // AppCache or service worker loader. For an optimization, we keep and reuse
Kinuko Yasuda7f3e1722018-03-26 08:58:58643 // the default url loader if the all |interceptors_| doesn't handle the
Tsuyoshi Horo5204c872017-09-21 16:28:17644 // redirected request.
645 if (!default_loader_used_)
646 url_loader_.reset();
Kinuko Yasuda7f3e1722018-03-26 08:58:58647 interceptor_index_ = 0;
anantab9800e52017-07-29 18:04:13648 received_response_ = false;
Kinuko Yasuda7f3e1722018-03-26 08:58:58649 MaybeStartLoader(nullptr /* interceptor */,
650 {} /* single_request_handler */);
kinuko69732972017-05-29 08:50:07651 }
652
Kinuko Yasuda7f3e1722018-03-26 08:58:58653 // |interceptor| is non-null if this is called by one of the interceptors
654 // (via a LoaderCallback).
655 // |single_request_handler| is the RequestHandler given by the |interceptor|,
656 // non-null if the interceptor wants to handle the request.
Ken Rockot387ddd5a2018-01-30 19:18:40657 void MaybeStartLoader(
Kinuko Yasuda7f3e1722018-03-26 08:58:58658 NavigationLoaderInterceptor* interceptor,
Ken Rockot387ddd5a2018-01-30 19:18:40659 SingleRequestURLLoaderFactory::RequestHandler single_request_handler) {
Kinuko Yasuda7f3e1722018-03-26 08:58:58660 DCHECK(IsLoaderInterceptionEnabled());
Ken Rockot387ddd5a2018-01-30 19:18:40661 if (single_request_handler) {
Kinuko Yasuda7f3e1722018-03-26 08:58:58662 // |interceptor| wants to handle the request with
663 // |single_request_handler|.
664 DCHECK(interceptor);
Michael Nordman2431f5f2017-09-13 04:58:15665 default_loader_used_ = false;
yzshenefcb7c72017-06-16 23:12:30666 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
Ken Rockot387ddd5a2018-01-30 19:18:40667 base::MakeRefCounted<SingleRequestURLLoaderFactory>(
668 std::move(single_request_handler)),
Tsuyoshi Horo70014ad2018-02-14 11:20:14669 CreateURLLoaderThrottles(), frame_tree_node_id_, 0 /* request_id? */,
Ken Rockot387ddd5a2018-01-30 19:18:40670 network::mojom::kURLLoadOptionNone, resource_request_.get(), this,
Hajime Hoshif5ef35262017-11-28 19:13:00671 kNavigationUrlLoaderTrafficAnnotation,
672 base::ThreadTaskRunnerHandle::Get());
anantae60d1d42017-06-20 04:16:27673
Kinuko Yasuda250577c2017-10-29 02:51:24674 subresource_loader_params_ =
Kinuko Yasuda7f3e1722018-03-26 08:58:58675 interceptor->MaybeCreateSubresourceLoaderParams();
Kinuko Yasuda8757204a2017-11-04 07:50:13676
kinuko69732972017-05-29 08:50:07677 return;
678 }
679
Kinuko Yasuda7f3e1722018-03-26 08:58:58680 // Before falling back to the next interceptor, see if |interceptor| still
681 // wants to give additional info to the frame for subresource loading. In
682 // that case we will just fall back to the default loader (i.e. won't go on
683 // to the next interceptors) but send the subresource_loader_params to the
684 // child process. This is necessary for correctness in the cases where, e.g.
685 // there's a controlling ServiceWorker that doesn't handle main resource
686 // loading, but may still want to control the page and/or handle subresource
687 // loading. In that case we want to skip AppCache.
688 if (interceptor) {
Kinuko Yasuda8757204a2017-11-04 07:50:13689 subresource_loader_params_ =
Kinuko Yasuda7f3e1722018-03-26 08:58:58690 interceptor->MaybeCreateSubresourceLoaderParams();
Kinuko Yasuda8757204a2017-11-04 07:50:13691
692 // If non-null |subresource_loader_params_| is returned, make sure
Kinuko Yasuda7f3e1722018-03-26 08:58:58693 // we skip the next interceptors.
Kinuko Yasuda8757204a2017-11-04 07:50:13694 if (subresource_loader_params_)
Kinuko Yasuda7f3e1722018-03-26 08:58:58695 interceptor_index_ = interceptors_.size();
Kinuko Yasuda8757204a2017-11-04 07:50:13696 }
697
Kinuko Yasuda7f3e1722018-03-26 08:58:58698 // See if the next interceptor wants to handle the request.
699 if (interceptor_index_ < interceptors_.size()) {
700 auto* next_interceptor = interceptors_[interceptor_index_++].get();
701 next_interceptor->MaybeCreateLoader(
kinuko69732972017-05-29 08:50:07702 *resource_request_, resource_context_,
703 base::BindOnce(&URLLoaderRequestController::MaybeStartLoader,
Kinuko Yasuda7f3e1722018-03-26 08:58:58704 base::Unretained(this), next_interceptor));
kinuko69732972017-05-29 08:50:07705 return;
706 }
707
Kinuko Yasuda7f3e1722018-03-26 08:58:58708 // If we already have the default |url_loader_| we must come here after
709 // a redirect. No interceptors wanted to intercept the redirected request,
710 // so let it just follow the redirect.
Michael Nordman2431f5f2017-09-13 04:58:15711 if (url_loader_) {
712 DCHECK(!redirect_info_.new_url.is_empty());
Chong Zhang7607f1f2018-06-01 20:52:20713 url_loader_->FollowRedirect(
714 std::move(url_loader_modified_request_headers_));
Michael Nordman2431f5f2017-09-13 04:58:15715 return;
716 }
717
Ken Rockota0dfaca12018-02-15 07:26:25718 // TODO(https://crbug.com/796425): We temporarily wrap raw
719 // mojom::URLLoaderFactory pointers into SharedURLLoaderFactory. Need to
720 // further refactor the factory getters to avoid this.
Chong Zhangb7c8d1ce2018-03-13 19:14:11721 scoped_refptr<network::SharedURLLoaderFactory> factory;
Kinuko Yasuda7f3e1722018-03-26 08:58:58722 DCHECK_EQ(interceptors_.size(), interceptor_index_);
Makoto Shimazu44c2c3232018-03-30 01:10:20723
724 // If NetworkService is not enabled (which means we come here because one of
725 // the loader interceptors is enabled), use the default request handler
726 // instead of going through the NetworkService path.
727 if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
728 DCHECK(!interceptors_.empty());
729 DCHECK(default_request_handler_factory_);
Makoto Shimazu684a5ad2018-05-29 08:20:50730 // The only way to come here is to enable ServiceWorkerServicification
731 // without NetworkService. We know that the service worker's request
732 // interceptor has already intercepted and decided not to handle the
733 // request.
734 DCHECK(ServiceWorkerUtils::IsServicificationEnabled());
Makoto Shimazu44c2c3232018-03-30 01:10:20735 default_loader_used_ = true;
736 // Update |request_info_| when following a redirect.
737 if (url_chain_.size() > 0) {
738 request_info_ = CreateNavigationRequestInfoForRedirect(
739 *request_info_, *resource_request_);
740 }
Makoto Shimazu684a5ad2018-05-29 08:20:50741 // When |subresource_loader_params_| has its value, the request should not
742 // be intercepted by any other interceptors since it means that a request
743 // interceptor already intercepted the request and it attached its info to
744 // the request.
Makoto Shimazu44c2c3232018-03-30 01:10:20745 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
746 base::MakeRefCounted<SingleRequestURLLoaderFactory>(
Makoto Shimazu684a5ad2018-05-29 08:20:50747 default_request_handler_factory_.Run(
748 subresource_loader_params_.has_value()
749 /* was_request_intercepted */)),
Makoto Shimazu44c2c3232018-03-30 01:10:20750 CreateURLLoaderThrottles(), frame_tree_node_id_, 0 /* request_id */,
751 network::mojom::kURLLoadOptionNone, resource_request_.get(),
752 this /* client */, kNavigationUrlLoaderTrafficAnnotation,
753 base::ThreadTaskRunnerHandle::Get());
754 return;
755 }
756
jam9354af82017-06-03 21:59:41757 if (resource_request_->url.SchemeIs(url::kBlobScheme)) {
Antonio Gomes9cdc09a2018-05-07 23:24:26758 factory =
759 base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
760 default_url_loader_factory_getter_->GetBlobFactory());
Ken Rockot314714c2017-11-05 23:36:24761 } else if (!IsURLHandledByNetworkService(resource_request_->url) &&
762 !resource_request_->url.SchemeIs(url::kDataScheme)) {
John Abd-El-Maleka67add82018-03-09 18:22:01763 if (known_schemes_.find(resource_request_->url.scheme()) ==
764 known_schemes_.end()) {
765 bool handled = GetContentClient()->browser()->HandleExternalProtocol(
766 resource_request_->url, web_contents_getter_,
767 ChildProcessHost::kInvalidUniqueID, navigation_ui_data_.get(),
768 resource_request_->resource_type == RESOURCE_TYPE_MAIN_FRAME,
769 static_cast<ui::PageTransition>(resource_request_->transition_type),
770 resource_request_->has_user_gesture);
771 factory = base::MakeRefCounted<SingleRequestURLLoaderFactory>(
772 base::BindOnce(UnknownSchemeCallback, handled));
773 } else {
774 network::mojom::URLLoaderFactoryPtr& non_network_factory =
775 non_network_url_loader_factories_[resource_request_->url.scheme()];
776 if (!non_network_factory.is_bound()) {
777 BrowserThread::PostTask(
778 BrowserThread::UI, FROM_HERE,
arthursonzogni1fd60e62018-05-09 15:57:32779 base::BindOnce(&NavigationURLLoaderImpl ::
John Abd-El-Maleka67add82018-03-09 18:22:01780 BindNonNetworkURLLoaderFactoryRequest,
781 owner_, frame_tree_node_id_,
782 resource_request_->url,
783 mojo::MakeRequest(&non_network_factory)));
784 }
Antonio Gomes9cdc09a2018-05-07 23:24:26785 factory =
786 base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
787 non_network_factory.get());
Ken Rockot314714c2017-11-05 23:36:24788 }
jam9354af82017-06-03 21:59:41789 } else {
anantab9800e52017-07-29 18:04:13790 default_loader_used_ = true;
Ken Rockota0dfaca12018-02-15 07:26:25791
792 // NOTE: We only support embedders proxying network-service-bound requests
Kinuko Yasuda7f3e1722018-03-26 08:58:58793 // not handled by NavigationLoaderInterceptors above (e.g. Service Worker
794 // or AppCache). Hence this code is only reachable when one of the above
795 // interceptors isn't used and the URL is either a data URL or has a
796 // scheme which is handled by the network service. We explicitly avoid
797 // proxying the data URL case here.
Ken Rockota0dfaca12018-02-15 07:26:25798 if (proxied_factory_request_.is_pending() &&
799 !resource_request_->url.SchemeIs(url::kDataScheme)) {
800 DCHECK(proxied_factory_info_.is_valid());
Chong Zhang70432e32018-03-07 04:43:52801 // We don't worry about reconnection since it's a single navigation.
Chong Zhang5271432a2018-03-01 23:31:02802 default_url_loader_factory_getter_->CloneNetworkFactory(
803 std::move(proxied_factory_request_));
Antonio Gomes9cdc09a2018-05-07 23:24:26804 factory = base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
Ken Rockota0dfaca12018-02-15 07:26:25805 std::move(proxied_factory_info_));
806 } else {
Chong Zhang5271432a2018-03-01 23:31:02807 factory = default_url_loader_factory_getter_->GetNetworkFactory();
Ken Rockota0dfaca12018-02-15 07:26:25808 }
jam9354af82017-06-03 21:59:41809 }
Min Qin83d07872017-10-26 23:22:41810 url_chain_.push_back(resource_request_->url);
arthursonzognib521c6a2018-01-08 12:23:40811 uint32_t options = GetURLLoaderOptions(resource_request_->resource_type ==
812 RESOURCE_TYPE_MAIN_FRAME);
yzshenefcb7c72017-06-16 23:12:30813 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
Ken Rockota0dfaca12018-02-15 07:26:25814 factory, CreateURLLoaderThrottles(), frame_tree_node_id_,
815 0 /* request_id? */, options, resource_request_.get(), this,
Tsuyoshi Horo70014ad2018-02-14 11:20:14816 kNavigationUrlLoaderTrafficAnnotation,
Hajime Hoshif5ef35262017-11-28 19:13:00817 base::ThreadTaskRunnerHandle::Get());
kinuko69732972017-05-29 08:50:07818 }
819
Chong Zhang7607f1f2018-06-01 20:52:20820 void FollowRedirect(
821 const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
yzshenefcb7c72017-06-16 23:12:30822 DCHECK_CURRENTLY_ON(BrowserThread::IO);
Michael Nordman2431f5f2017-09-13 04:58:15823 DCHECK(!redirect_info_.new_url.is_empty());
arthursonzogni2695d04d2017-12-12 08:39:01824
Kinuko Yasuda7f3e1722018-03-26 08:58:58825 if (!IsLoaderInterceptionEnabled()) {
Chong Zhang7607f1f2018-06-01 20:52:20826 url_loader_->FollowRedirect(modified_request_headers);
arthursonzogni2695d04d2017-12-12 08:39:01827 return;
828 }
anantab9800e52017-07-29 18:04:13829
Kinuko Yasuda7f3e1722018-03-26 08:58:58830 // Update |resource_request_| and call Restart to give our |interceptors_| a
831 // chance at handling the new location. If no interceptor wants to take
832 // over, we'll use the existing url_loader to follow the redirect, see
833 // MaybeStartLoader.
Michael Nordman2431f5f2017-09-13 04:58:15834 // TODO(michaeln): This is still WIP and is based on URLRequest::Redirect,
835 // there likely remains more to be done.
836 // a. For subframe navigations, the Origin header may need to be modified
837 // differently?
838 // b. How should redirect_info_.referred_token_binding_host be handled?
Michael Nordman2431f5f2017-09-13 04:58:15839
Tsuyoshi Horo9e2ec4df2017-10-16 15:15:55840 bool should_clear_upload = false;
841 net::RedirectUtil::UpdateHttpRequest(
842 resource_request_->url, resource_request_->method, redirect_info_,
Chong Zhang7607f1f2018-06-01 20:52:20843 modified_request_headers, &resource_request_->headers,
844 &should_clear_upload);
Tsuyoshi Horo9e2ec4df2017-10-16 15:15:55845 if (should_clear_upload) {
Michael Nordman2431f5f2017-09-13 04:58:15846 // The request body is no longer applicable.
847 resource_request_->request_body = nullptr;
848 blob_handles_.clear();
849 }
850
Michael Nordman2431f5f2017-09-13 04:58:15851 resource_request_->url = redirect_info_.new_url;
Tsuyoshi Horo9e2ec4df2017-10-16 15:15:55852 resource_request_->method = redirect_info_.new_method;
Michael Nordman2431f5f2017-09-13 04:58:15853 resource_request_->site_for_cookies = redirect_info_.new_site_for_cookies;
854 resource_request_->referrer = GURL(redirect_info_.new_referrer);
John Abd-El-Malekb77d22fb72017-12-22 17:34:48855 resource_request_->referrer_policy = redirect_info_.new_referrer_policy;
Min Qin83d07872017-10-26 23:22:41856 url_chain_.push_back(redirect_info_.new_url);
Michael Nordman2431f5f2017-09-13 04:58:15857
Chong Zhang7607f1f2018-06-01 20:52:20858 // Need to cache modified headers for |url_loader_| since it doesn't use
859 // |resource_request_| during redirect.
860 url_loader_modified_request_headers_ = modified_request_headers;
861
Michael Nordman2431f5f2017-09-13 04:58:15862 Restart();
yzshenefcb7c72017-06-16 23:12:30863 }
864
Kinuko Yasuda250577c2017-10-29 02:51:24865 base::Optional<SubresourceLoaderParams> TakeSubresourceLoaderParams() {
866 return std::move(subresource_loader_params_);
anantae60d1d42017-06-20 04:16:27867 }
868
kinuko69732972017-05-29 08:50:07869 private:
John Abd-El-Malekb165dc52018-01-18 17:12:18870 // network::mojom::URLLoaderClient implementation:
yzshenefcb7c72017-06-16 23:12:30871 void OnReceiveResponse(
John Abd-El-Malek46248032018-01-17 19:11:23872 const network::ResourceResponseHead& head,
John Abd-El-Malekb165dc52018-01-18 17:12:18873 network::mojom::DownloadedTempFilePtr downloaded_file) override {
anantab9800e52017-07-29 18:04:13874 received_response_ = true;
arthursonzogni2695d04d2017-12-12 08:39:01875
anantab9800e52017-07-29 18:04:13876 // If the default loader (network) was used to handle the URL load request
Kinuko Yasuda7f3e1722018-03-26 08:58:58877 // we need to see if the interceptors want to potentially create a new
878 // loader for the response. e.g. AppCache.
anantab9800e52017-07-29 18:04:13879 if (MaybeCreateLoaderForResponse(head))
880 return;
arthursonzogni3a4ca9f2017-12-07 17:58:34881
John Abd-El-Malekb165dc52018-01-18 17:12:18882 network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints;
John Abd-El-Malekecc6f5f2018-03-02 18:47:39883
884 // Currently only plugin handlers may intercept the response. Don't treat
885 // the response as download if it has been handled by plugins.
886 bool response_intercepted = false;
arthursonzogni3a4ca9f2017-12-07 17:58:34887 if (url_loader_) {
888 url_loader_client_endpoints = url_loader_->Unbind();
John Abd-El-Malekecc6f5f2018-03-02 18:47:39889 response_intercepted = url_loader_->response_intercepted();
arthursonzogni3a4ca9f2017-12-07 17:58:34890 } else {
John Abd-El-Malekb165dc52018-01-18 17:12:18891 url_loader_client_endpoints =
892 network::mojom::URLLoaderClientEndpoints::New(
893 response_url_loader_.PassInterface(),
894 response_loader_binding_.Unbind());
arthursonzogni3a4ca9f2017-12-07 17:58:34895 }
896
arthursonzogni40db5f52018-01-08 16:38:49897 bool is_download;
898 bool is_stream;
899 std::unique_ptr<NavigationData> cloned_navigation_data;
Kinuko Yasuda7f3e1722018-03-26 08:58:58900 if (IsLoaderInterceptionEnabled()) {
John Abd-El-Malek3ebdff862018-04-23 18:57:21901 bool must_download = navigation_loader_util::MustDownload(
Jochen Eisinger7678c8ac2018-05-07 15:47:34902 url_, head.headers.get(), head.mime_type);
John Abd-El-Malek3ebdff862018-04-23 18:57:21903 bool known_mime_type = blink::IsSupportedMimeType(head.mime_type);
904
905#if BUILDFLAG(ENABLE_PLUGINS)
906 if (!response_intercepted && !must_download && !known_mime_type) {
907 CheckPluginAndContinueOnReceiveResponse(
908 head, std::move(downloaded_file),
909 std::move(url_loader_client_endpoints),
910 std::vector<WebPluginInfo>());
911 return;
912 }
913#endif
914
915 is_download =
916 !response_intercepted && (must_download || !known_mime_type);
arthursonzogni40db5f52018-01-08 16:38:49917 is_stream = false;
918 } else {
919 ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get();
920 net::URLRequest* url_request = rdh->GetURLRequest(global_request_id_);
arthursonzognib1de19fa2018-04-03 19:55:10921
922 // The |url_request| maybe have been removed from the resource dispatcher
John Abd-El-Malek739997242018-05-01 19:48:25923 // host during the time it took for OnReceiveResponse() to be received.
924 if (url_request) {
925 ResourceRequestInfoImpl* info =
926 ResourceRequestInfoImpl::ForRequest(url_request);
927 is_download = !response_intercepted && info->IsDownload();
928 is_stream = info->is_stream();
929 if (rdh->delegate()) {
930 NavigationData* navigation_data =
931 rdh->delegate()->GetNavigationData(url_request);
arthursonzognib1de19fa2018-04-03 19:55:10932
John Abd-El-Malek739997242018-05-01 19:48:25933 // Clone the embedder's NavigationData before moving it to the UI
934 // thread.
935 if (navigation_data)
936 cloned_navigation_data = navigation_data->Clone();
937 }
arthursonzogni40db5f52018-01-08 16:38:49938
John Abd-El-Malek739997242018-05-01 19:48:25939 // This is similar to what is done in
940 // ServiceWorkerControlleeHandler::MaybeCreateSubresourceLoaderParams().
941 // It takes the matching ControllerServiceWorkerInfo (if any) associated
942 // with the request. It will be sent to the renderer process and used to
943 // intercept requests.
944 // TODO(arthursonzogni): This is needed only for the
945 // non-S13nServiceWorker case. The S13nServiceWorker case is still not
946 // supported without the NetworkService. This block needs to be updated
947 // once support for it will be added.
948 ServiceWorkerProviderHost* sw_provider_host =
949 ServiceWorkerRequestHandler::GetProviderHost(url_request);
950 if (sw_provider_host && sw_provider_host->controller()) {
951 subresource_loader_params_ = SubresourceLoaderParams();
952 subresource_loader_params_->controller_service_worker_info =
953 mojom::ControllerServiceWorkerInfo::New();
Han Leone80f5c9a2018-05-12 04:22:36954 base::WeakPtr<ServiceWorkerHandle> sw_handle =
955 sw_provider_host->GetOrCreateServiceWorkerHandle(
956 sw_provider_host->controller());
957 if (sw_handle) {
958 subresource_loader_params_->controller_service_worker_handle =
959 sw_handle;
960 subresource_loader_params_->controller_service_worker_info
961 ->object_info = sw_handle->CreateIncompleteObjectInfo();
962 }
John Abd-El-Malek739997242018-05-01 19:48:25963 }
964 } else {
965 is_download = is_stream = false;
arthursonzognib950d902018-02-08 09:27:13966 }
arthursonzogni40db5f52018-01-08 16:38:49967 }
968
John Abd-El-Malek3ebdff862018-04-23 18:57:21969 CallOnReceivedResponse(head, std::move(downloaded_file),
970 std::move(url_loader_client_endpoints),
971 std::move(cloned_navigation_data), is_download,
972 is_stream);
973 }
974
975#if BUILDFLAG(ENABLE_PLUGINS)
976 void CheckPluginAndContinueOnReceiveResponse(
977 const network::ResourceResponseHead& head,
978 network::mojom::DownloadedTempFilePtr downloaded_file,
979 network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
980 const std::vector<WebPluginInfo>& plugins) {
981 bool stale;
982 WebPluginInfo plugin;
983 // It's ok to pass -1 for the render process and frame ID since that's
984 // only used for plugin overridding. We don't actually care if we get an
985 // overridden plugin or not, since all we care about is the presence of a
986 // plugin. Note that this is what the MimeSniffingResourceHandler code
987 // path does as well for navigations.
988 bool has_plugin = PluginService::GetInstance()->GetPluginInfo(
989 -1 /* render_process_id */, -1 /* render_frame_id */, resource_context_,
990 resource_request_->url, url::Origin(), head.mime_type,
991 false /* allow_wildcard */, &stale, &plugin, nullptr);
992
993 if (stale) {
994 // Refresh the plugins asynchronously.
995 PluginService::GetInstance()->GetPlugins(base::BindOnce(
996 &URLLoaderRequestController::CheckPluginAndContinueOnReceiveResponse,
997 weak_factory_.GetWeakPtr(), head, std::move(downloaded_file),
998 std::move(url_loader_client_endpoints)));
999 return;
1000 }
1001
1002 bool is_download =
1003 !has_plugin &&
1004 (!head.headers || head.headers->response_code() / 100 == 2);
1005
1006 CallOnReceivedResponse(head, std::move(downloaded_file),
1007 std::move(url_loader_client_endpoints), nullptr,
1008 is_download, false /* is_stream */);
1009 }
1010#endif
1011
1012 void CallOnReceivedResponse(
1013 const network::ResourceResponseHead& head,
1014 network::mojom::DownloadedTempFilePtr downloaded_file,
1015 network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
1016 std::unique_ptr<NavigationData> cloned_navigation_data,
1017 bool is_download,
1018 bool is_stream) {
1019 scoped_refptr<network::ResourceResponse> response(
1020 new network::ResourceResponse());
1021 response->head = head;
1022
Andrey Kosyakova924c8b2017-08-18 17:37:231023 // Make a copy of the ResourceResponse before it is passed to another
1024 // thread.
1025 //
1026 // TODO(davidben): This copy could be avoided if ResourceResponse weren't
1027 // reference counted and the loader stack passed unique ownership of the
1028 // response. https://crbug.com/416050
yzshenefcb7c72017-06-16 23:12:301029 BrowserThread::PostTask(
1030 BrowserThread::UI, FROM_HERE,
arthursonzogni1fd60e62018-05-09 15:57:321031 base::BindOnce(&NavigationURLLoaderImpl::OnReceiveResponse, owner_,
1032 response->DeepCopy(),
arthursonzogni40db5f52018-01-08 16:38:491033 std::move(url_loader_client_endpoints),
Andrey Kosyakov87cd9252018-03-27 16:58:271034 std::move(cloned_navigation_data), global_request_id_,
1035 is_download, is_stream, std::move(downloaded_file)));
yzshenefcb7c72017-06-16 23:12:301036 }
1037
1038 void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
John Abd-El-Malek46248032018-01-17 19:11:231039 const network::ResourceResponseHead& head) override {
Michael Nordman2431f5f2017-09-13 04:58:151040 if (--redirect_limit_ == 0) {
Takashi Toyoshimaaa278662017-11-20 11:11:261041 OnComplete(
1042 network::URLLoaderCompletionStatus(net::ERR_TOO_MANY_REDIRECTS));
Michael Nordman2431f5f2017-09-13 04:58:151043 return;
1044 }
1045
1046 // Store the redirect_info for later use in FollowRedirect where we give
Kinuko Yasuda7f3e1722018-03-26 08:58:581047 // our interceptors_ a chance to intercept the request for the new location.
Michael Nordman2431f5f2017-09-13 04:58:151048 redirect_info_ = redirect_info;
1049
John Abd-El-Malek46248032018-01-17 19:11:231050 scoped_refptr<network::ResourceResponse> response(
1051 new network::ResourceResponse());
Andrey Kosyakova924c8b2017-08-18 17:37:231052 response->head = head;
arthursonzogni40db5f52018-01-08 16:38:491053 url_ = redirect_info.new_url;
Andrey Kosyakova924c8b2017-08-18 17:37:231054
1055 // Make a copy of the ResourceResponse before it is passed to another
1056 // thread.
1057 //
1058 // TODO(davidben): This copy could be avoided if ResourceResponse weren't
1059 // reference counted and the loader stack passed unique ownership of the
1060 // response. https://crbug.com/416050
yzshenefcb7c72017-06-16 23:12:301061 BrowserThread::PostTask(
1062 BrowserThread::UI, FROM_HERE,
arthursonzogni1fd60e62018-05-09 15:57:321063 base::BindOnce(&NavigationURLLoaderImpl::OnReceiveRedirect, owner_,
1064 redirect_info, response->DeepCopy()));
yzshenefcb7c72017-06-16 23:12:301065 }
1066
1067 void OnDataDownloaded(int64_t data_length, int64_t encoded_length) override {}
yzshenefcb7c72017-06-16 23:12:301068 void OnUploadProgress(int64_t current_position,
1069 int64_t total_size,
1070 OnUploadProgressCallback callback) override {}
yzshenefcb7c72017-06-16 23:12:301071 void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override {}
yzshenefcb7c72017-06-16 23:12:301072 void OnTransferSizeUpdated(int32_t transfer_size_diff) override {}
1073
arthursonzogni3a4ca9f2017-12-07 17:58:341074 void OnStartLoadingResponseBody(mojo::ScopedDataPipeConsumerHandle) override {
1075 // Not reached. At this point, the loader and client endpoints must have
1076 // been unbound and forwarded to the renderer.
1077 CHECK(false);
yzshenefcb7c72017-06-16 23:12:301078 }
1079
Takashi Toyoshimaaa278662017-11-20 11:11:261080 void OnComplete(const network::URLLoaderCompletionStatus& status) override {
Emily Starkb09f19a2017-11-22 22:41:471081 UMA_HISTOGRAM_BOOLEAN(
arthursonzognie70c4a042018-05-02 15:49:101082 "Navigation.URLLoaderNetworkService.OnCompleteHasSSLInfo",
Emily Starkb09f19a2017-11-22 22:41:471083 status.ssl_info.has_value());
1084 if (status.ssl_info.has_value()) {
1085 UMA_HISTOGRAM_MEMORY_KB(
1086 "Navigation.URLLoaderNetworkService.OnCompleteCertificateChainsSize",
1087 GetCertificateChainsSizeInKB(status.ssl_info.value()));
1088 }
1089
Takashi Toyoshima8f988532017-11-13 07:32:371090 if (status.error_code != net::OK && !received_response_) {
anantab9800e52017-07-29 18:04:131091 // If the default loader (network) was used to handle the URL load
Kinuko Yasuda7f3e1722018-03-26 08:58:581092 // request we need to see if the interceptors want to potentially create a
anantab9800e52017-07-29 18:04:131093 // new loader for the response. e.g. AppCache.
John Abd-El-Malek46248032018-01-17 19:11:231094 if (MaybeCreateLoaderForResponse(network::ResourceResponseHead()))
anantab9800e52017-07-29 18:04:131095 return;
1096 }
Takashi Toyoshima8f988532017-11-13 07:32:371097 status_ = status;
arthursonzogni2695d04d2017-12-12 08:39:011098
yzshenefcb7c72017-06-16 23:12:301099 BrowserThread::PostTask(
1100 BrowserThread::UI, FROM_HERE,
arthursonzogni1fd60e62018-05-09 15:57:321101 base::BindOnce(&NavigationURLLoaderImpl::OnComplete, owner_, status));
yzshenefcb7c72017-06-16 23:12:301102 }
1103
Kinuko Yasuda7f3e1722018-03-26 08:58:581104 // Returns true if an interceptor wants to handle the response, i.e. return a
Michael Nordman2431f5f2017-09-13 04:58:151105 // different response. For e.g. AppCache may have fallback content.
John Abd-El-Malek46248032018-01-17 19:11:231106 bool MaybeCreateLoaderForResponse(
1107 const network::ResourceResponseHead& response) {
Kinuko Yasuda7f3e1722018-03-26 08:58:581108 if (!IsLoaderInterceptionEnabled())
arthursonzogni2695d04d2017-12-12 08:39:011109 return false;
1110
anantab9800e52017-07-29 18:04:131111 if (!default_loader_used_)
1112 return false;
1113
Kinuko Yasuda7f3e1722018-03-26 08:58:581114 for (auto& interceptor : interceptors_) {
John Abd-El-Malekb165dc52018-01-18 17:12:181115 network::mojom::URLLoaderClientRequest response_client_request;
Kinuko Yasuda7f3e1722018-03-26 08:58:581116 if (interceptor->MaybeCreateLoaderForResponse(
1117 response, &response_url_loader_, &response_client_request,
1118 url_loader_.get())) {
Michael Nordman2431f5f2017-09-13 04:58:151119 response_loader_binding_.Bind(std::move(response_client_request));
1120 default_loader_used_ = false;
1121 url_loader_.reset();
anantab9800e52017-07-29 18:04:131122 return true;
1123 }
1124 }
1125 return false;
1126 }
1127
Tsuyoshi Horo70014ad2018-02-14 11:20:141128 std::vector<std::unique_ptr<content::URLLoaderThrottle>>
1129 CreateURLLoaderThrottles() {
1130 return GetContentClient()->browser()->CreateURLLoaderThrottles(
1131 *resource_request_, resource_context_, web_contents_getter_,
1132 navigation_ui_data_.get(), frame_tree_node_id_);
1133 }
1134
Makoto Shimazu44c2c3232018-03-30 01:10:201135 std::unique_ptr<NavigationLoaderInterceptor> CreateServiceWorkerInterceptor(
1136 const NavigationRequestInfo& request_info,
1137 ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core)
1138 const {
1139 const ResourceType resource_type = request_info.is_main_frame
1140 ? RESOURCE_TYPE_MAIN_FRAME
1141 : RESOURCE_TYPE_SUB_FRAME;
1142 network::mojom::RequestContextFrameType frame_type =
1143 request_info.is_main_frame
1144 ? network::mojom::RequestContextFrameType::kTopLevel
1145 : network::mojom::RequestContextFrameType::kNested;
1146 storage::BlobStorageContext* blob_storage_context = GetBlobStorageContext(
1147 GetChromeBlobStorageContextForResourceContext(resource_context_));
1148 return ServiceWorkerRequestHandler::InitializeForNavigationNetworkService(
1149 *resource_request_, resource_context_,
1150 service_worker_navigation_handle_core, blob_storage_context,
1151 request_info.begin_params->skip_service_worker, resource_type,
1152 request_info.begin_params->request_context_type, frame_type,
1153 request_info.are_ancestors_secure, request_info.common_params.post_data,
1154 web_contents_getter_);
1155 }
1156
Kinuko Yasuda7f3e1722018-03-26 08:58:581157 std::vector<std::unique_ptr<NavigationLoaderInterceptor>> interceptors_;
1158 size_t interceptor_index_ = 0;
kinuko69732972017-05-29 08:50:071159
John Abd-El-Malek1df61792018-01-12 20:40:451160 std::unique_ptr<network::ResourceRequest> resource_request_;
Makoto Shimazu44c2c3232018-03-30 01:10:201161 // Non-NetworkService: |request_info_| is updated along with
1162 // |resource_request_| on redirects.
1163 std::unique_ptr<NavigationRequestInfo> request_info_;
John Abd-El-Malek576c6132017-11-04 00:33:581164 int frame_tree_node_id_ = 0;
arthursonzogni40db5f52018-01-08 16:38:491165 GlobalRequestID global_request_id_;
Michael Nordman2431f5f2017-09-13 04:58:151166 net::RedirectInfo redirect_info_;
Daniel Bratell0dfa6282017-11-08 10:12:231167 int redirect_limit_ = net::URLRequest::kMaxRedirects;
kinuko69732972017-05-29 08:50:071168 ResourceContext* resource_context_;
yzshenefcb7c72017-06-16 23:12:301169 base::Callback<WebContents*()> web_contents_getter_;
John Abd-El-Malekeb1a5382018-01-05 16:58:001170 std::unique_ptr<NavigationUIData> navigation_ui_data_;
anantae60d1d42017-06-20 04:16:271171 scoped_refptr<URLLoaderFactoryGetter> default_url_loader_factory_getter_;
arthursonzogni2695d04d2017-12-12 08:39:011172
yzshenefcb7c72017-06-16 23:12:301173 std::unique_ptr<ThrottlingURLLoader> url_loader_;
arthursonzogni2695d04d2017-12-12 08:39:011174
Chong Zhang7607f1f2018-06-01 20:52:201175 // Caches the modified request headers provided by clients during redirect,
1176 // will be consumed by next |url_loader_->FollowRedirect()|.
1177 base::Optional<net::HttpRequestHeaders> url_loader_modified_request_headers_;
1178
mmenkeed44e6c2017-06-28 21:13:321179 BlobHandles blob_handles_;
Min Qin83d07872017-10-26 23:22:411180 std::vector<GURL> url_chain_;
kinuko69732972017-05-29 08:50:071181
arthursonzogni40db5f52018-01-08 16:38:491182 // Current URL that is being navigated, updated after redirection.
1183 GURL url_;
1184
anantae60d1d42017-06-20 04:16:271185 // Currently used by the AppCache loader to pass its factory to the
1186 // renderer which enables it to handle subresources.
Kinuko Yasuda250577c2017-10-29 02:51:241187 base::Optional<SubresourceLoaderParams> subresource_loader_params_;
anantae60d1d42017-06-20 04:16:271188
mmenkeed44e6c2017-06-28 21:13:321189 // This is referenced only on the UI thread.
arthursonzogni1fd60e62018-05-09 15:57:321190 base::WeakPtr<NavigationURLLoaderImpl> owner_;
mmenkeed44e6c2017-06-28 21:13:321191
anantab9800e52017-07-29 18:04:131192 // Set to true if the default URLLoader (network service) was used for the
1193 // current navigation.
1194 bool default_loader_used_ = false;
1195
1196 // URLLoaderClient binding for loaders created for responses received from the
1197 // network loader.
John Abd-El-Malekb165dc52018-01-18 17:12:181198 mojo::Binding<network::mojom::URLLoaderClient> response_loader_binding_;
anantab9800e52017-07-29 18:04:131199
1200 // URLLoader instance for response loaders, i.e loaders created for handing
1201 // responses received from the network URLLoader.
John Abd-El-Malekb165dc52018-01-18 17:12:181202 network::mojom::URLLoaderPtr response_url_loader_;
anantab9800e52017-07-29 18:04:131203
1204 // Set to true if we receive a valid response from a URLLoader, i.e.
1205 // URLLoaderClient::OnReceivedResponse() is called.
1206 bool received_response_ = false;
1207
Alex Clarke1e08882b32017-10-06 14:22:401208 bool started_ = false;
1209
Ken Rockot314714c2017-11-05 23:36:241210 // Lazily initialized and used in the case of non-network resource
1211 // navigations. Keyed by URL scheme.
John Abd-El-Malekb165dc52018-01-18 17:12:181212 std::map<std::string, network::mojom::URLLoaderFactoryPtr>
Ken Rockot314714c2017-11-05 23:36:241213 non_network_url_loader_factories_;
1214
Makoto Shimazu44c2c3232018-03-30 01:10:201215 // Non-NetworkService:
1216 // Generator of a request handler for sending request to the network. This
1217 // captures all of parameters to create a
1218 // SingleRequestURLLoaderFactory::RequestHandler. Used only when
1219 // NetworkService is disabled but IsLoaderInterceptionEnabled() is true.
Makoto Shimazu684a5ad2018-05-29 08:20:501220 // Set |was_request_intercepted| to true if the request was intercepted by an
1221 // interceptor and the request is falling back to the network. In that case,
1222 // any interceptors won't intercept the request.
1223 base::RepeatingCallback<SingleRequestURLLoaderFactory::RequestHandler(
1224 bool /* was_request_intercepted */)>
Makoto Shimazu44c2c3232018-03-30 01:10:201225 default_request_handler_factory_;
1226
Min Qin40b72172017-09-27 00:19:171227 // The completion status if it has been received. This is needed to handle
1228 // the case that the response is intercepted by download, and OnComplete() is
1229 // already called while we are transferring the |url_loader_| and response
1230 // body to download code.
Takashi Toyoshimaaa278662017-11-20 11:11:261231 base::Optional<network::URLLoaderCompletionStatus> status_;
Min Qin40b72172017-09-27 00:19:171232
Ken Rockota0dfaca12018-02-15 07:26:251233 // Before creating this URLLoaderRequestController on UI thread, the embedder
1234 // may have elected to proxy the URLLoaderFactory request, in which case these
1235 // fields will contain input (info) and output (request) endpoints for the
1236 // proxy. If this controller is handling a request for which proxying is
1237 // supported, requests will be plumbed through these endpoints.
1238 //
1239 // Note that these are only used for requests that go to the Network Service.
1240 network::mojom::URLLoaderFactoryRequest proxied_factory_request_;
1241 network::mojom::URLLoaderFactoryPtrInfo proxied_factory_info_;
1242
John Abd-El-Maleka67add82018-03-09 18:22:011243 // The schemes that this loader can use. For anything else we'll try external
1244 // protocol handlers.
1245 std::set<std::string> known_schemes_;
1246
Makoto Shimazu44c2c3232018-03-30 01:10:201247 mutable base::WeakPtrFactory<URLLoaderRequestController> weak_factory_;
arthursonzogni2695d04d2017-12-12 08:39:011248
kinuko69732972017-05-29 08:50:071249 DISALLOW_COPY_AND_ASSIGN(URLLoaderRequestController);
1250};
1251
Min Qin75ed6df2017-12-01 20:39:151252// TODO(https://crbug.com/790734): pass |navigation_ui_data| along with the
1253// request so that it could be modified.
arthursonzogni1fd60e62018-05-09 15:57:321254NavigationURLLoaderImpl::NavigationURLLoaderImpl(
scottmg69985212017-04-12 16:47:281255 ResourceContext* resource_context,
1256 StoragePartition* storage_partition,
1257 std::unique_ptr<NavigationRequestInfo> request_info,
1258 std::unique_ptr<NavigationUIData> navigation_ui_data,
scottmgd2021c92017-05-15 16:58:051259 ServiceWorkerNavigationHandle* service_worker_navigation_handle,
scottmg69985212017-04-12 16:47:281260 AppCacheNavigationHandle* appcache_handle,
Alex Clarke1e08882b32017-10-06 14:22:401261 NavigationURLLoaderDelegate* delegate,
Kinuko Yasuda7f3e1722018-03-26 08:58:581262 std::vector<std::unique_ptr<NavigationLoaderInterceptor>>
1263 initial_interceptors)
Min Qin37db5102017-09-13 21:21:251264 : delegate_(delegate),
1265 allow_download_(request_info->common_params.allow_download),
1266 weak_factory_(this) {
scottmg95feea52017-04-12 17:51:331267 DCHECK_CURRENTLY_ON(BrowserThread::UI);
John Abd-El-Malekfcb2ecf2017-11-15 23:15:301268 int frame_tree_node_id = request_info->frame_tree_node_id;
ananta5149d8e2017-04-21 00:01:371269
yzshen0f278522017-05-01 17:10:221270 TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP1(
1271 "navigation", "Navigation timeToResponseStarted", this,
kinuko69732972017-05-29 08:50:071272 request_info->common_params.navigation_start, "FrameTreeNode id",
John Abd-El-Malekfcb2ecf2017-11-15 23:15:301273 frame_tree_node_id);
yzshen0f278522017-05-01 17:10:221274
arthursonzogni2695d04d2017-12-12 08:39:011275 ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core =
1276 service_worker_navigation_handle
1277 ? service_worker_navigation_handle->core()
1278 : nullptr;
1279
1280 AppCacheNavigationHandleCore* appcache_handle_core =
1281 appcache_handle ? appcache_handle->core() : nullptr;
1282
Yuzhu Shencb3011f62018-02-08 02:51:501283 std::unique_ptr<network::ResourceRequest> new_request = CreateResourceRequest(
1284 request_info.get(), frame_tree_node_id, allow_download_);
Yutaka Hirano61e41b3c2018-05-31 05:31:061285 new_request->transition_type = request_info->common_params.transition;
Tsuyoshi Horob8d512a2018-01-25 17:01:591286
Yutaka Hiranod8789f92018-01-30 09:59:511287 if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
arthursonzogni2695d04d2017-12-12 08:39:011288 DCHECK(!request_controller_);
1289 request_controller_ = std::make_unique<URLLoaderRequestController>(
Kinuko Yasuda7f3e1722018-03-26 08:58:581290 /* initial_interceptors = */
1291 std::vector<std::unique_ptr<NavigationLoaderInterceptor>>(),
Tsuyoshi Horob8d512a2018-01-25 17:01:591292 std::move(new_request), resource_context,
arthursonzogni40db5f52018-01-08 16:38:491293 /* default_url_factory_getter = */ nullptr,
1294 request_info->common_params.url,
Ken Rockota0dfaca12018-02-15 07:26:251295 /* proxied_url_loader_factory_request */ nullptr,
John Abd-El-Maleka67add82018-03-09 18:22:011296 /* proxied_url_loader_factory_info */ nullptr, std::set<std::string>(),
arthursonzogni40db5f52018-01-08 16:38:491297 weak_factory_.GetWeakPtr());
arthursonzogni2695d04d2017-12-12 08:39:011298
1299 BrowserThread::PostTask(
1300 BrowserThread::IO, FROM_HERE,
1301 base::BindOnce(
1302 &URLLoaderRequestController::StartWithoutNetworkService,
1303 base::Unretained(request_controller_.get()),
Tsuyoshi Horo70014ad2018-02-14 11:20:141304 base::RetainedRef(storage_partition->GetURLRequestContext()),
arthursonzogni2695d04d2017-12-12 08:39:011305 base::Unretained(storage_partition->GetFileSystemContext()),
1306 base::Unretained(service_worker_navigation_handle_core),
tzikccf160c2018-02-20 12:43:131307 base::Unretained(appcache_handle_core), std::move(request_info),
1308 std::move(navigation_ui_data)));
arthursonzogni2695d04d2017-12-12 08:39:011309 return;
1310 }
1311
scottmgd2021c92017-05-15 16:58:051312 // Check if a web UI scheme wants to handle this request.
Ken Rockot6414c4d92017-11-08 19:58:321313 FrameTreeNode* frame_tree_node =
1314 FrameTreeNode::GloballyFindByID(frame_tree_node_id);
John Abd-El-Malekb165dc52018-01-18 17:12:181315 network::mojom::URLLoaderFactoryPtrInfo factory_for_webui;
scottmgd2021c92017-05-15 16:58:051316 const auto& schemes = URLDataManagerBackend::GetWebUISchemes();
John Abd-El-Malekbb0bc8e2017-11-11 01:08:151317 std::string scheme = new_request->url.scheme();
1318 if (std::find(schemes.begin(), schemes.end(), scheme) != schemes.end()) {
Chris Mumfordbae8a742018-03-01 23:02:231319 factory_for_webui = CreateWebUIURLLoaderBinding(
1320 frame_tree_node->current_frame_host(), scheme)
1321 .PassInterface();
ananta5149d8e2017-04-21 00:01:371322 }
scottmgd2021c92017-05-15 16:58:051323
Ken Rockota0dfaca12018-02-15 07:26:251324 network::mojom::URLLoaderFactoryPtrInfo proxied_factory_info;
1325 network::mojom::URLLoaderFactoryRequest proxied_factory_request;
Chris Mumford942075ad2018-05-19 00:22:041326 auto* partition = static_cast<StoragePartitionImpl*>(storage_partition);
Ken Rockota0dfaca12018-02-15 07:26:251327 if (frame_tree_node) {
1328 // |frame_tree_node| may be null in some unit test environments.
1329 GetContentClient()
1330 ->browser()
1331 ->RegisterNonNetworkNavigationURLLoaderFactories(
John Abd-El-Malekea006302018-05-10 05:50:461332 frame_tree_node_id, &non_network_url_loader_factories_);
Ken Rockota0dfaca12018-02-15 07:26:251333
1334 // The embedder may want to proxy all network-bound URLLoaderFactory
1335 // requests that it can. If it elects to do so, we'll pass its proxy
1336 // endpoints off to the URLLoaderRequestController where wthey will be
1337 // connected if the request type supports proxying.
1338 network::mojom::URLLoaderFactoryPtrInfo factory_info;
1339 auto factory_request = mojo::MakeRequest(&factory_info);
Andrey Kosyakov8d49c5062018-03-15 19:50:491340 bool use_proxy = GetContentClient()->browser()->WillCreateURLLoaderFactory(
Ken Rockot428b1d62018-06-06 17:12:211341 partition->browser_context(), frame_tree_node->current_frame_host(),
1342 true /* is_navigation */, &factory_request);
Andrey Kosyakov8d49c5062018-03-15 19:50:491343 if (RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory(
Jochen Eisingercdc12d12018-05-08 15:07:471344 frame_tree_node->current_frame_host(), true, false,
1345 &factory_request)) {
Andrey Kosyakov8d49c5062018-03-15 19:50:491346 use_proxy = true;
1347 }
1348 if (use_proxy) {
Ken Rockota0dfaca12018-02-15 07:26:251349 proxied_factory_request = std::move(factory_request);
1350 proxied_factory_info = std::move(factory_info);
1351 }
Chris Mumford942075ad2018-05-19 00:22:041352
1353 const std::string storage_domain;
1354 non_network_url_loader_factories_[url::kFileSystemScheme] =
1355 CreateFileSystemURLLoaderFactory(frame_tree_node->current_frame_host(),
1356 /*is_navigation=*/true,
1357 partition->GetFileSystemContext(),
1358 storage_domain);
Ken Rockota0dfaca12018-02-15 07:26:251359 }
1360
John Abd-El-Maleka67add82018-03-09 18:22:011361 non_network_url_loader_factories_[url::kFileScheme] =
1362 std::make_unique<FileURLLoaderFactory>(
1363 partition->browser_context()->GetPath(),
1364 base::CreateSequencedTaskRunnerWithTraits(
1365 {base::MayBlock(), base::TaskPriority::BACKGROUND,
1366 base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}));
1367 std::set<std::string> known_schemes;
1368 for (auto& iter : non_network_url_loader_factories_)
1369 known_schemes.insert(iter.first);
1370
kinuko69732972017-05-29 08:50:071371 DCHECK(!request_controller_);
Jeremy Roman04f27c372017-10-27 15:20:551372 request_controller_ = std::make_unique<URLLoaderRequestController>(
Kinuko Yasuda7f3e1722018-03-26 08:58:581373 std::move(initial_interceptors), std::move(new_request), resource_context,
arthursonzogni40db5f52018-01-08 16:38:491374 partition->url_loader_factory_getter(), request_info->common_params.url,
Ken Rockota0dfaca12018-02-15 07:26:251375 std::move(proxied_factory_request), std::move(proxied_factory_info),
John Abd-El-Maleka67add82018-03-09 18:22:011376 std::move(known_schemes), weak_factory_.GetWeakPtr());
scottmgd2021c92017-05-15 16:58:051377 BrowserThread::PostTask(
1378 BrowserThread::IO, FROM_HERE,
Ken Rockot387ddd5a2018-01-30 19:18:401379 base::BindOnce(
1380 &URLLoaderRequestController::Start,
1381 base::Unretained(request_controller_.get()),
Tsuyoshi Horo70014ad2018-02-14 11:20:141382 base::RetainedRef(storage_partition->GetURLRequestContext()),
Ken Rockot387ddd5a2018-01-30 19:18:401383 service_worker_navigation_handle_core, appcache_handle_core,
1384 std::move(request_info), std::move(navigation_ui_data),
1385 std::move(factory_for_webui), frame_tree_node_id,
1386 ServiceManagerConnection::GetForProcess()->GetConnector()->Clone()));
scottmg69985212017-04-12 16:47:281387}
1388
arthursonzogni1fd60e62018-05-09 15:57:321389NavigationURLLoaderImpl::~NavigationURLLoaderImpl() {
kinuko69732972017-05-29 08:50:071390 BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE,
1391 request_controller_.release());
1392}
scottmg69985212017-04-12 16:47:281393
Chong Zhang7607f1f2018-06-01 20:52:201394void NavigationURLLoaderImpl::FollowRedirect(
1395 const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
yzshenefcb7c72017-06-16 23:12:301396 BrowserThread::PostTask(
1397 BrowserThread::IO, FROM_HERE,
tzik0f14f192017-08-15 02:43:331398 base::BindOnce(&URLLoaderRequestController::FollowRedirect,
Chong Zhang7607f1f2018-06-01 20:52:201399 base::Unretained(request_controller_.get()),
1400 modified_request_headers));
scottmg95feea52017-04-12 17:51:331401}
scottmg69985212017-04-12 16:47:281402
arthursonzogni1fd60e62018-05-09 15:57:321403void NavigationURLLoaderImpl::ProceedWithResponse() {}
scottmg69985212017-04-12 16:47:281404
arthursonzogni1fd60e62018-05-09 15:57:321405void NavigationURLLoaderImpl::OnReceiveResponse(
John Abd-El-Malek46248032018-01-17 19:11:231406 scoped_refptr<network::ResourceResponse> response,
John Abd-El-Malekb165dc52018-01-18 17:12:181407 network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
arthursonzogni40db5f52018-01-08 16:38:491408 std::unique_ptr<NavigationData> navigation_data,
1409 const GlobalRequestID& global_request_id,
1410 bool is_download,
1411 bool is_stream,
John Abd-El-Malekb165dc52018-01-18 17:12:181412 network::mojom::DownloadedTempFilePtr downloaded_file) {
arthursonzogni3a4ca9f2017-12-07 17:58:341413 TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", this,
arthursonzogni1fd60e62018-05-09 15:57:321414 "&NavigationURLLoaderImpl", this, "success", true);
arthursonzogni3a4ca9f2017-12-07 17:58:341415
scottmgefb697302017-04-12 22:37:301416 // TODO(scottmg): This needs to do more of what
arthursonzogni3a4ca9f2017-12-07 17:58:341417 // NavigationResourceHandler::OnResponseStarted() does.
arthursonzogni3a4ca9f2017-12-07 17:58:341418
arthursonzogni3a4ca9f2017-12-07 17:58:341419 delegate_->OnResponseStarted(
arthursonzognif34adf092018-04-24 17:06:131420 std::move(response), std::move(url_loader_client_endpoints),
Andrey Kosyakov87cd9252018-03-27 16:58:271421 std::move(navigation_data), global_request_id,
arthursonzogni40db5f52018-01-08 16:38:491422 allow_download_ && is_download, is_stream,
arthursonzogni3a4ca9f2017-12-07 17:58:341423 request_controller_->TakeSubresourceLoaderParams());
scottmg95feea52017-04-12 17:51:331424}
scottmg69985212017-04-12 16:47:281425
arthursonzogni1fd60e62018-05-09 15:57:321426void NavigationURLLoaderImpl::OnReceiveRedirect(
scottmg69985212017-04-12 16:47:281427 const net::RedirectInfo& redirect_info,
John Abd-El-Malek46248032018-01-17 19:11:231428 scoped_refptr<network::ResourceResponse> response) {
scottmg95feea52017-04-12 17:51:331429 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Andrey Kosyakova924c8b2017-08-18 17:37:231430 delegate_->OnRequestRedirected(redirect_info, std::move(response));
scottmg95feea52017-04-12 17:51:331431}
scottmg69985212017-04-12 16:47:281432
arthursonzogni1fd60e62018-05-09 15:57:321433void NavigationURLLoaderImpl::OnComplete(
Takashi Toyoshimaaa278662017-11-20 11:11:261434 const network::URLLoaderCompletionStatus& status) {
Takashi Toyoshima8f988532017-11-13 07:32:371435 if (status.error_code == net::OK)
John Abd-El-Malekb906d282017-08-31 19:36:431436 return;
1437
1438 TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", this,
arthursonzogni1fd60e62018-05-09 15:57:321439 "&NavigationURLLoaderImpl", this, "success", false);
Lucas Garron0efab6d2017-08-30 22:28:511440
Johannes Henkel6a43fef2018-05-17 18:41:521441 delegate_->OnRequestFailed(status);
yzshen384441de2017-04-19 23:26:141442}
scottmg69985212017-04-12 16:47:281443
arthursonzogni1fd60e62018-05-09 15:57:321444void NavigationURLLoaderImpl::SetBeginNavigationInterceptorForTesting(
John Abd-El-Malekdb3a13b2018-05-01 17:52:021445 const BeginNavigationInterceptor& interceptor) {
1446 DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::IO) ||
1447 BrowserThread::CurrentlyOn(BrowserThread::IO));
1448 DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
1449 g_interceptor.Get() = interceptor;
1450}
1451
arthursonzogni1fd60e62018-05-09 15:57:321452void NavigationURLLoaderImpl::OnRequestStarted(base::TimeTicks timestamp) {
arthursonzogni2695d04d2017-12-12 08:39:011453 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1454 delegate_->OnRequestStarted(timestamp);
1455}
1456
arthursonzogni1fd60e62018-05-09 15:57:321457void NavigationURLLoaderImpl::BindNonNetworkURLLoaderFactoryRequest(
Ken Rockota0dfaca12018-02-15 07:26:251458 int frame_tree_node_id,
Ken Rockot314714c2017-11-05 23:36:241459 const GURL& url,
John Abd-El-Malekb165dc52018-01-18 17:12:181460 network::mojom::URLLoaderFactoryRequest factory) {
Ken Rockot314714c2017-11-05 23:36:241461 auto it = non_network_url_loader_factories_.find(url.scheme());
1462 if (it == non_network_url_loader_factories_.end()) {
1463 DVLOG(1) << "Ignoring request with unknown scheme: " << url.spec();
1464 return;
1465 }
Ken Rockota0dfaca12018-02-15 07:26:251466 FrameTreeNode* frame_tree_node =
1467 FrameTreeNode::GloballyFindByID(frame_tree_node_id);
Ken Rockot428b1d62018-06-06 17:12:211468 auto* frame = frame_tree_node->current_frame_host();
Ken Rockota0dfaca12018-02-15 07:26:251469 GetContentClient()->browser()->WillCreateURLLoaderFactory(
Ken Rockot428b1d62018-06-06 17:12:211470 frame->GetSiteInstance()->GetBrowserContext(), frame,
1471 true /* is_navigation */, &factory);
Ken Rockot314714c2017-11-05 23:36:241472 it->second->Clone(std::move(factory));
1473}
1474
scottmg69985212017-04-12 16:47:281475} // namespace content