@@ -170,6 +170,83 @@ void OnWrite(std::unique_ptr<WriteData> write_data, MojoResult result) {
170170
171171} // namespace
172172
173+ ElectronURLLoaderFactory::RedirectedRequest::RedirectedRequest (
174+ const net::RedirectInfo& redirect_info,
175+ mojo::PendingReceiver<network::mojom::URLLoader> loader_receiver,
176+ int32_t request_id,
177+ uint32_t options,
178+ const network::ResourceRequest& request,
179+ mojo::PendingRemote<network::mojom::URLLoaderClient> client,
180+ const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
181+ mojo::PendingRemote<network::mojom::URLLoaderFactory> target_factory_remote)
182+ : redirect_info_(redirect_info),
183+ request_id_ (request_id),
184+ options_(options),
185+ request_(request),
186+ client_(std::move(client)),
187+ traffic_annotation_(traffic_annotation) {
188+ loader_receiver_.Bind (std::move (loader_receiver));
189+ loader_receiver_.set_disconnect_handler (
190+ base::BindOnce (&ElectronURLLoaderFactory::RedirectedRequest::DeleteThis,
191+ base::Unretained (this )));
192+ target_factory_remote_.Bind (std::move (target_factory_remote));
193+ target_factory_remote_.set_disconnect_handler (base::BindOnce (
194+ &ElectronURLLoaderFactory::RedirectedRequest::OnTargetFactoryError,
195+ base::Unretained (this )));
196+ }
197+
198+ ElectronURLLoaderFactory::RedirectedRequest::~RedirectedRequest () = default ;
199+
200+ void ElectronURLLoaderFactory::RedirectedRequest::FollowRedirect (
201+ const std::vector<std::string>& removed_headers,
202+ const net::HttpRequestHeaders& modified_headers,
203+ const net::HttpRequestHeaders& modified_cors_exempt_headers,
204+ const absl::optional<GURL>& new_url) {
205+ // Update |request_| with info from the redirect, so that it's accurate
206+ // The following references code in WorkerScriptLoader::FollowRedirect
207+ bool should_clear_upload = false ;
208+ net::RedirectUtil::UpdateHttpRequest (
209+ request_.url , request_.method , redirect_info_, removed_headers,
210+ modified_headers, &request_.headers , &should_clear_upload);
211+ request_.cors_exempt_headers .MergeFrom (modified_cors_exempt_headers);
212+ for (const std::string& name : removed_headers)
213+ request_.cors_exempt_headers .RemoveHeader (name);
214+
215+ if (should_clear_upload)
216+ request_.request_body = nullptr ;
217+
218+ request_.url = redirect_info_.new_url ;
219+ request_.method = redirect_info_.new_method ;
220+ request_.site_for_cookies = redirect_info_.new_site_for_cookies ;
221+ request_.referrer = GURL (redirect_info_.new_referrer );
222+ request_.referrer_policy = redirect_info_.new_referrer_policy ;
223+
224+ // Create a new loader to process the redirect and destroy this one
225+ target_factory_remote_->CreateLoaderAndStart (
226+ loader_receiver_.Unbind (), request_id_, options_, request_,
227+ std::move (client_), traffic_annotation_);
228+
229+ DeleteThis ();
230+ }
231+
232+ void ElectronURLLoaderFactory::RedirectedRequest::OnTargetFactoryError () {
233+ // Can't create a new loader at this point, so the request can't continue
234+ mojo::Remote<network::mojom::URLLoaderClient> client_remote (
235+ std::move (client_));
236+ client_remote->OnComplete (
237+ network::URLLoaderCompletionStatus (net::ERR_FAILED));
238+ client_remote.reset ();
239+
240+ DeleteThis ();
241+ }
242+
243+ void ElectronURLLoaderFactory::RedirectedRequest::DeleteThis () {
244+ loader_receiver_.reset ();
245+ target_factory_remote_.reset ();
246+
247+ delete this ;
248+ }
249+
173250// static
174251mojo::PendingRemote<network::mojom::URLLoaderFactory>
175252ElectronURLLoaderFactory::Create (ProtocolType type,
@@ -202,12 +279,18 @@ void ElectronURLLoaderFactory::CreateLoaderAndStart(
202279 mojo::PendingRemote<network::mojom::URLLoaderClient> client,
203280 const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
204281 DCHECK_CURRENTLY_ON (content::BrowserThread::UI);
205- mojo::PendingRemote<network::mojom::URLLoaderFactory> proxy_factory;
282+
283+ // |StartLoading| is used for both intercepted and registered protocols,
284+ // and on redirects it needs a factory to use to create a loader for the
285+ // new request. So in this case, this factory is the target factory.
286+ mojo::PendingRemote<network::mojom::URLLoaderFactory> target_factory;
287+ this ->Clone (target_factory.InitWithNewPipeAndPassReceiver ());
288+
206289 handler_.Run (
207290 request,
208291 base::BindOnce (&ElectronURLLoaderFactory::StartLoading, std::move (loader),
209292 request_id, options, request, std::move (client),
210- traffic_annotation, std::move (proxy_factory ), type_));
293+ traffic_annotation, std::move (target_factory ), type_));
211294}
212295
213296// static
@@ -230,7 +313,7 @@ void ElectronURLLoaderFactory::StartLoading(
230313 const network::ResourceRequest& request,
231314 mojo::PendingRemote<network::mojom::URLLoaderClient> client,
232315 const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
233- mojo::PendingRemote<network::mojom::URLLoaderFactory> proxy_factory ,
316+ mojo::PendingRemote<network::mojom::URLLoaderFactory> target_factory ,
234317 ProtocolType type,
235318 gin::Arguments* args) {
236319 // Send network error when there is no argument passed.
@@ -280,47 +363,22 @@ void ElectronURLLoaderFactory::StartLoading(
280363 request.url .Resolve (location),
281364 net::RedirectUtil::GetReferrerPolicyHeader (head->headers .get ()), false );
282365
283- network::ResourceRequest new_request = request;
284- new_request.method = redirect_info.new_method ;
285- new_request.url = redirect_info.new_url ;
286- new_request.site_for_cookies = redirect_info.new_site_for_cookies ;
287- new_request.referrer = GURL (redirect_info.new_referrer );
288- new_request.referrer_policy = redirect_info.new_referrer_policy ;
289-
290366 DCHECK (client.is_valid ());
291367
292368 mojo::Remote<network::mojom::URLLoaderClient> client_remote (
293369 std::move (client));
294370
295371 client_remote->OnReceiveRedirect (redirect_info, std::move (head));
296372
297- // Unbound client, so it an be passed to sub-methods
298- client = client_remote.Unbind ();
299- // When the redirection comes from an intercepted scheme (which has
300- // |proxy_factory| passed), we ask the proxy factory to create a loader
301- // for new URL, otherwise we call |StartLoadingHttp|, which creates
302- // loader with default factory.
303- //
304- // Note that when handling requests for intercepted scheme, creating loader
305- // with default factory (i.e. calling StartLoadingHttp) would bypass the
306- // ProxyingURLLoaderFactory, we have to explicitly use the proxy factory to
307- // create loader so it is possible to have handlers of intercepted scheme
308- // getting called recursively, which is a behavior expected in protocol
309- // module.
310- //
311- // I'm not sure whether this is an intended behavior in Chromium.
312- if (proxy_factory.is_valid ()) {
313- mojo::Remote<network::mojom::URLLoaderFactory> proxy_factory_remote (
314- std::move (proxy_factory));
315-
316- proxy_factory_remote->CreateLoaderAndStart (
317- std::move (loader), request_id, options, new_request,
318- std::move (client), traffic_annotation);
319- } else {
320- StartLoadingHttp (std::move (loader), new_request, std::move (client),
321- traffic_annotation,
322- gin::Dictionary::CreateEmpty (args->isolate ()));
323- }
373+ // Bind the URLLoader receiver and wait for a FollowRedirect request, or for
374+ // the remote to disconnect, which will happen if the request is aborted.
375+ // That may happen when the redirect is to a different scheme, which will
376+ // cause the URL loader to be destroyed and a new one created using the
377+ // factory for that scheme.
378+ new RedirectedRequest (redirect_info, std::move (loader), request_id, options,
379+ request, client_remote.Unbind (), traffic_annotation,
380+ std::move (target_factory));
381+
324382 return ;
325383 }
326384
@@ -360,7 +418,7 @@ void ElectronURLLoaderFactory::StartLoading(
360418 }
361419 StartLoading (std::move (loader), request_id, options, request,
362420 std::move (client), traffic_annotation,
363- std::move (proxy_factory ), type, args);
421+ std::move (target_factory ), type, args);
364422 break ;
365423 }
366424}
0 commit comments