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 0f9d88529021db245fb498dfa339e5327450256a..962dc2d3e8c3976f5088146c9edc0516e41ebeb4 100644
--- a/services/network/public/mojom/network_context.mojom
+++ b/services/network/public/mojom/network_context.mojom
@@ -215,6 +215,25 @@ struct CTPolicy {
   array<string> excluded_legacy_spkis;
 };
 
+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,
@@ -641,6 +660,8 @@ struct URLLoaderFactoryParams {
   // impact because of the extra process hops, so use should be minimized.
   pending_remote<TrustedURLLoaderHeaderClient>? header_client;
 
+  pending_remote<TrustedURLLoaderAuthClient>? auth_client;
+
   // |factory_bound_access_patterns| are used for CORS checks in addition to
   // the per-context allow patterns that is managed via NetworkContext
   // interface. This still respects the per-context block lists.
diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc
index e13745d859ca82ec313c25e1958945a3efeaaa62..0f6ec93b55fcc263f69157d650b20bf34d6a586f 100644
--- a/services/network/url_loader.cc
+++ b/services/network/url_loader.cc
@@ -463,6 +463,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<TrustTokenRequestHelperFactory> trust_token_helper_factory,
     mojo::PendingRemote<mojom::CookieAccessObserver> cookie_observer)
@@ -525,6 +526,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;
@@ -1130,7 +1136,7 @@ void URLLoader::OnAuthRequired(net::URLRequest* url_request,
     // |this| may have been deleted.
     return;
   }
-  if (!network_context_client_) {
+  if (!network_context_client_ && !auth_client_) {
     OnAuthCredentials(base::nullopt);
     return;
   }
@@ -1146,11 +1152,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 70518f42849e5d1d6e1dd0faf4cae866ba39ef09..b081be5d939b17ecaffa85e75ebb012444bb2bf1 100644
--- a/services/network/url_loader.h
+++ b/services/network/url_loader.h
@@ -118,6 +118,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<TrustTokenRequestHelperFactory>
           trust_token_helper_factory,
@@ -481,6 +482,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 75ae8488efa7e5acfda0b21029657b525fa95f86..5dce71ee5efc97f9f63d0b5f236dccdfb05cfc79 100644
--- a/services/network/url_loader_factory.cc
+++ b/services/network/url_loader_factory.cc
@@ -75,6 +75,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),
       cookie_observer_(std::move(params_->cookie_observer)) {
   DCHECK(context);
@@ -254,6 +255,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(), std::move(trust_token_factory),
       std::move(cookie_observer));
 
diff --git a/services/network/url_loader_factory.h b/services/network/url_loader_factory.h
index 182b26816da9e82d83c47c3c73ecfdcf3003b967..903a3ad083201ed85e82169698041152278697fa 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_;
