From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jeremy Apthorp <nornagon@nornagon.net>
Date: Tue, 12 Nov 2019 11:50:16 -0800
Subject: add TrustedAuthClient to URLLoaderFactory

This allows intercepting authentication requests for the 'net' module.
Without this, the 'login' event for electron.net.ClientRequest can't be
implemented, because the existing path checks for the presence of a
WebContents, and cancels the authentication if there's no WebContents
available, which there isn't in the case of the 'net' module.

diff --git a/services/network/public/mojom/network_context.mojom b/services/network/public/mojom/network_context.mojom
index a46aab1db2de282e0ff3561a98bad1dac659b67a..31ce9719f63c564baf88e48c7494e030cf9d148c 100644
--- a/services/network/public/mojom/network_context.mojom
+++ b/services/network/public/mojom/network_context.mojom
@@ -159,6 +159,25 @@ struct HttpAuthStaticNetworkContextParams {
      = DefaultCredentials.ALLOW_DEFAULT_CREDENTIALS;
 };
 
+interface TrustedAuthClient {
+  OnAuthRequired(
+      mojo_base.mojom.UnguessableToken? window_id,
+      uint32 process_id,
+      uint32 routing_id,
+      uint32 request_id,
+      url.mojom.Url url,
+      bool first_auth_attempt,
+      AuthChallengeInfo auth_info,
+      URLResponseHead? head,
+      pending_remote<AuthChallengeResponder> auth_challenge_responder);
+};
+interface TrustedURLLoaderAuthClient {
+  // When a new URLLoader is created, this will be called to pass a
+  // corresponding |auth_client|.
+  OnLoaderCreated(int32 request_id,
+                  pending_receiver<TrustedAuthClient> auth_client);
+};
+
 interface CertVerifierClient {
   Verify(
     int32 default_error,
@@ -603,6 +622,8 @@ struct URLLoaderFactoryParams {
   // interface. This still respects the per-context block lists.
   CorsOriginAccessPatterns? factory_bound_access_patterns;
 
+  pending_remote<TrustedURLLoaderAuthClient>? auth_client;
+
   // Key used to isolate shared network resources like the cache.
   NetworkIsolationKey? network_isolation_key;
 
diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc
index 3dc126f94737cbf7f01afcfe21e108b93b630b27..9ee5cd1bf6aefa28c2a58c648736f857383485e4 100644
--- a/services/network/url_loader.cc
+++ b/services/network/url_loader.cc
@@ -487,6 +487,7 @@ URLLoader::URLLoader(
     base::WeakPtr<KeepaliveStatisticsRecorder> keepalive_statistics_recorder,
     base::WeakPtr<NetworkUsageAccumulator> network_usage_accumulator,
     mojom::TrustedURLLoaderHeaderClient* url_loader_header_client,
+    mojom::TrustedURLLoaderAuthClient* url_loader_auth_client,
     mojom::OriginPolicyManager* origin_policy_manager,
     std::unique_ptr<TrustTokenRequestHelper> trust_token_helper)
     : url_request_context_(url_request_context),
@@ -543,6 +544,11 @@ URLLoader::URLLoader(
     header_client_.set_disconnect_handler(
         base::BindOnce(&URLLoader::OnMojoDisconnect, base::Unretained(this)));
   }
+  if (url_loader_auth_client) {
+    url_loader_auth_client->OnLoaderCreated(request_id_, auth_client_.BindNewPipeAndPassReceiver());
+    auth_client_.set_disconnect_handler(
+        base::BindOnce(&URLLoader::OnMojoDisconnect, base::Unretained(this)));
+  }
   if (want_raw_headers_) {
     options_ |= mojom::kURLLoadOptionSendSSLInfoWithResponse |
                 mojom::kURLLoadOptionSendSSLInfoForCertificateError;
@@ -1012,7 +1018,7 @@ void URLLoader::OnReceivedRedirect(net::URLRequest* url_request,
 
 void URLLoader::OnAuthRequired(net::URLRequest* url_request,
                                const net::AuthChallengeInfo& auth_info) {
-  if (!network_context_client_) {
+  if (!network_context_client_ && !auth_client_) {
     OnAuthCredentials(base::nullopt);
     return;
   }
@@ -1028,11 +1034,20 @@ void URLLoader::OnAuthRequired(net::URLRequest* url_request,
   if (url_request->response_headers())
     head->headers = url_request->response_headers();
   head->auth_challenge_info = auth_info;
-  network_context_client_->OnAuthRequired(
-      fetch_window_id_, factory_params_->process_id, render_frame_id_,
-      request_id_, url_request_->url(), first_auth_attempt_, auth_info,
-      std::move(head),
-      auth_challenge_responder_receiver_.BindNewPipeAndPassRemote());
+
+  if (auth_client_) {
+    auth_client_->OnAuthRequired(
+        fetch_window_id_, factory_params_->process_id, render_frame_id_,
+        request_id_, url_request_->url(), first_auth_attempt_, auth_info,
+        std::move(head),
+        auth_challenge_responder_receiver_.BindNewPipeAndPassRemote());
+  } else {
+    network_context_client_->OnAuthRequired(
+        fetch_window_id_, factory_params_->process_id, render_frame_id_,
+        request_id_, url_request_->url(), first_auth_attempt_, auth_info,
+        std::move(head),
+        auth_challenge_responder_receiver_.BindNewPipeAndPassRemote());
+  }
 
   auth_challenge_responder_receiver_.set_disconnect_handler(
       base::BindOnce(&URLLoader::DeleteSelf, base::Unretained(this)));
diff --git a/services/network/url_loader.h b/services/network/url_loader.h
index 9098fa1e35f8935c4c8183dac294fada6a0c113c..ab20b4fce4bc79f69cf1dea1989ceb817ab04fe6 100644
--- a/services/network/url_loader.h
+++ b/services/network/url_loader.h
@@ -111,6 +111,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader
       base::WeakPtr<KeepaliveStatisticsRecorder> keepalive_statistics_recorder,
       base::WeakPtr<NetworkUsageAccumulator> network_usage_accumulator,
       mojom::TrustedURLLoaderHeaderClient* url_loader_header_client,
+      mojom::TrustedURLLoaderAuthClient* url_loader_auth_client,
       mojom::OriginPolicyManager* origin_policy_manager,
       std::unique_ptr<TrustTokenRequestHelper> trust_token_helper);
   ~URLLoader() override;
@@ -422,6 +423,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader
   base::Optional<base::UnguessableToken> fetch_window_id_;
 
   mojo::Remote<mojom::TrustedHeaderClient> header_client_;
+  mojo::Remote<mojom::TrustedAuthClient> auth_client_;
 
   std::unique_ptr<FileOpenerForUpload> file_opener_for_upload_;
 
diff --git a/services/network/url_loader_factory.cc b/services/network/url_loader_factory.cc
index f17117db6f2ad140d797fad6a40fcd241c9538dd..a65a15d29df7a0667db56bbd768ef85aaff71d3d 100644
--- a/services/network/url_loader_factory.cc
+++ b/services/network/url_loader_factory.cc
@@ -66,6 +66,7 @@ URLLoaderFactory::URLLoaderFactory(
       resource_scheduler_client_(std::move(resource_scheduler_client)),
       header_client_(std::move(params_->header_client)),
       coep_reporter_(std::move(params_->coep_reporter)),
+      auth_client_(std::move(params_->auth_client)),
       cors_url_loader_factory_(cors_url_loader_factory) {
   DCHECK(context);
   DCHECK_NE(mojom::kInvalidProcessId, params_->process_id);
@@ -209,6 +210,7 @@ void URLLoaderFactory::CreateLoaderAndStart(
       std::move(keepalive_statistics_recorder),
       std::move(network_usage_accumulator),
       header_client_.is_bound() ? header_client_.get() : nullptr,
+      auth_client_.is_bound() ? auth_client_.get() : nullptr,
       context_->origin_policy_manager(), nullptr /* trust_token_helper */);
   cors_url_loader_factory_->OnLoaderCreated(std::move(loader));
 }
diff --git a/services/network/url_loader_factory.h b/services/network/url_loader_factory.h
index 1a623585035487de061ba6476914992ea2f7ac88..caa19dcd4b99296e50f8e22bfc92a70ba14473d1 100644
--- a/services/network/url_loader_factory.h
+++ b/services/network/url_loader_factory.h
@@ -74,6 +74,7 @@ class URLLoaderFactory : public mojom::URLLoaderFactory {
   scoped_refptr<ResourceSchedulerClient> resource_scheduler_client_;
   mojo::Remote<mojom::TrustedURLLoaderHeaderClient> header_client_;
   mojo::Remote<mojom::CrossOriginEmbedderPolicyReporter> coep_reporter_;
+  mojo::Remote<mojom::TrustedURLLoaderAuthClient> auth_client_;
 
   // |cors_url_loader_factory_| owns this.
   cors::CorsURLLoaderFactory* cors_url_loader_factory_;
