fix: implement 'login' event for net.ClientRequest (#21096)
This commit is contained in:
parent
878ab916d2
commit
4f1536479e
16 changed files with 445 additions and 38 deletions
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <utility>
|
||||
|
||||
#include "base/containers/id_map.h"
|
||||
#include "gin/handle.h"
|
||||
#include "mojo/public/cpp/bindings/receiver_set.h"
|
||||
#include "mojo/public/cpp/system/string_data_source.h"
|
||||
|
@ -13,6 +14,7 @@
|
|||
#include "services/network/public/mojom/chunked_data_pipe_getter.mojom.h"
|
||||
#include "shell/browser/api/atom_api_session.h"
|
||||
#include "shell/browser/atom_browser_context.h"
|
||||
#include "shell/common/gin_converters/callback_converter.h"
|
||||
#include "shell/common/gin_converters/gurl_converter.h"
|
||||
#include "shell/common/gin_converters/net_converter.h"
|
||||
#include "shell/common/gin_helper/dictionary.h"
|
||||
|
@ -51,6 +53,11 @@ namespace api {
|
|||
|
||||
namespace {
|
||||
|
||||
base::IDMap<URLRequest*>& GetAllRequests() {
|
||||
static base::NoDestructor<base::IDMap<URLRequest*>> s_all_requests;
|
||||
return *s_all_requests;
|
||||
}
|
||||
|
||||
// Network state for request and response.
|
||||
enum State {
|
||||
STATE_STARTED = 1 << 0,
|
||||
|
@ -166,7 +173,9 @@ class ChunkedDataPipeGetter : public UploadDataPipeGetter,
|
|||
mojo::ReceiverSet<network::mojom::ChunkedDataPipeGetter> receiver_set_;
|
||||
};
|
||||
|
||||
URLRequest::URLRequest(gin::Arguments* args) : weak_factory_(this) {
|
||||
URLRequest::URLRequest(gin::Arguments* args)
|
||||
: id_(GetAllRequests().Add(this)), weak_factory_(this) {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||
request_ = std::make_unique<network::ResourceRequest>();
|
||||
gin_helper::Dictionary dict;
|
||||
if (args->GetNext(&dict)) {
|
||||
|
@ -176,6 +185,8 @@ URLRequest::URLRequest(gin::Arguments* args) : weak_factory_(this) {
|
|||
request_->redirect_mode = redirect_mode_;
|
||||
}
|
||||
|
||||
request_->render_frame_id = id_;
|
||||
|
||||
std::string partition;
|
||||
gin::Handle<api::Session> session;
|
||||
if (!dict.Get("session", &session)) {
|
||||
|
@ -192,6 +203,38 @@ URLRequest::URLRequest(gin::Arguments* args) : weak_factory_(this) {
|
|||
|
||||
URLRequest::~URLRequest() = default;
|
||||
|
||||
URLRequest* URLRequest::FromID(uint32_t id) {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||
return GetAllRequests().Lookup(id);
|
||||
}
|
||||
|
||||
void URLRequest::OnAuthRequired(
|
||||
const GURL& url,
|
||||
bool first_auth_attempt,
|
||||
net::AuthChallengeInfo auth_info,
|
||||
network::mojom::URLResponseHeadPtr head,
|
||||
mojo::PendingRemote<network::mojom::AuthChallengeResponder>
|
||||
auth_challenge_responder) {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||
mojo::Remote<network::mojom::AuthChallengeResponder> auth_responder(
|
||||
std::move(auth_challenge_responder));
|
||||
auth_responder.set_disconnect_handler(
|
||||
base::BindOnce(&URLRequest::Cancel, weak_factory_.GetWeakPtr()));
|
||||
auto cb = base::BindOnce(
|
||||
[](mojo::Remote<network::mojom::AuthChallengeResponder> auth_responder,
|
||||
gin::Arguments* args) {
|
||||
base::string16 username_str, password_str;
|
||||
if (!args->GetNext(&username_str) || !args->GetNext(&password_str)) {
|
||||
auth_responder->OnAuthCredentials(base::nullopt);
|
||||
return;
|
||||
}
|
||||
auth_responder->OnAuthCredentials(
|
||||
net::AuthCredentials(username_str, password_str));
|
||||
},
|
||||
std::move(auth_responder));
|
||||
Emit("login", auth_info, base::AdaptCallbackForRepeating(std::move(cb)));
|
||||
}
|
||||
|
||||
bool URLRequest::NotStarted() const {
|
||||
return request_state_ == 0;
|
||||
}
|
||||
|
@ -512,11 +555,12 @@ void URLRequest::EmitError(EventType type, base::StringPiece message) {
|
|||
}
|
||||
|
||||
template <typename... Args>
|
||||
void URLRequest::EmitEvent(EventType type, Args... args) {
|
||||
void URLRequest::EmitEvent(EventType type, Args&&... args) {
|
||||
const char* method =
|
||||
type == EventType::kRequest ? "_emitRequestEvent" : "_emitResponseEvent";
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
gin_helper::CustomEmit(isolate(), GetWrapper(), method, args...);
|
||||
gin_helper::CustomEmit(isolate(), GetWrapper(), method,
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "services/network/public/cpp/simple_url_loader.h"
|
||||
#include "services/network/public/cpp/simple_url_loader_stream_consumer.h"
|
||||
#include "services/network/public/mojom/data_pipe_getter.mojom.h"
|
||||
#include "services/network/public/mojom/network_context.mojom.h"
|
||||
#include "shell/common/gin_helper/event_emitter.h"
|
||||
|
||||
namespace electron {
|
||||
|
@ -32,6 +33,15 @@ class URLRequest : public gin_helper::EventEmitter<URLRequest>,
|
|||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
static URLRequest* FromID(uint32_t id);
|
||||
|
||||
void OnAuthRequired(
|
||||
const GURL& url,
|
||||
bool first_auth_attempt,
|
||||
net::AuthChallengeInfo auth_info,
|
||||
network::mojom::URLResponseHeadPtr head,
|
||||
mojo::PendingRemote<network::mojom::AuthChallengeResponder>
|
||||
auth_challenge_responder);
|
||||
|
||||
protected:
|
||||
explicit URLRequest(gin::Arguments* args);
|
||||
|
@ -89,7 +99,7 @@ class URLRequest : public gin_helper::EventEmitter<URLRequest>,
|
|||
};
|
||||
void EmitError(EventType type, base::StringPiece error);
|
||||
template <typename... Args>
|
||||
void EmitEvent(EventType type, Args... args);
|
||||
void EmitEvent(EventType type, Args&&... args);
|
||||
|
||||
std::unique_ptr<network::ResourceRequest> request_;
|
||||
std::unique_ptr<network::SimpleURLLoader> loader_;
|
||||
|
@ -132,6 +142,8 @@ class URLRequest : public gin_helper::EventEmitter<URLRequest>,
|
|||
// Used by pin/unpin to manage lifetime.
|
||||
v8::Global<v8::Object> wrapper_;
|
||||
|
||||
uint32_t id_;
|
||||
|
||||
base::WeakPtrFactory<URLRequest> weak_factory_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(URLRequest);
|
||||
|
|
|
@ -28,10 +28,12 @@
|
|||
#include "content/browser/blob_storage/chrome_blob_storage_context.h" // nogncheck
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/storage_partition.h"
|
||||
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
|
||||
#include "net/base/escape.h"
|
||||
#include "services/network/public/cpp/features.h"
|
||||
#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
|
||||
#include "services/network/public/mojom/network_context.mojom.h"
|
||||
#include "shell/browser/api/atom_api_url_request.h"
|
||||
#include "shell/browser/atom_browser_client.h"
|
||||
#include "shell/browser/atom_browser_main_parts.h"
|
||||
#include "shell/browser/atom_download_manager_delegate.h"
|
||||
|
@ -325,6 +327,7 @@ AtomBrowserContext::GetURLLoaderFactory() {
|
|||
network::mojom::URLLoaderFactoryParamsPtr params =
|
||||
network::mojom::URLLoaderFactoryParams::New();
|
||||
params->header_client = std::move(header_client);
|
||||
params->auth_client = auth_client_.BindNewPipeAndPassRemote();
|
||||
params->process_id = network::mojom::kBrowserProcessId;
|
||||
params->is_trusted = true;
|
||||
params->is_corb_enabled = false;
|
||||
|
@ -342,6 +345,39 @@ AtomBrowserContext::GetURLLoaderFactory() {
|
|||
return url_loader_factory_;
|
||||
}
|
||||
|
||||
class AuthResponder : public network::mojom::TrustedAuthClient {
|
||||
public:
|
||||
AuthResponder() {}
|
||||
~AuthResponder() override = default;
|
||||
|
||||
private:
|
||||
void OnAuthRequired(
|
||||
const base::Optional<::base::UnguessableToken>& window_id,
|
||||
uint32_t process_id,
|
||||
uint32_t routing_id,
|
||||
uint32_t request_id,
|
||||
const ::GURL& url,
|
||||
bool first_auth_attempt,
|
||||
const ::net::AuthChallengeInfo& auth_info,
|
||||
::network::mojom::URLResponseHeadPtr head,
|
||||
mojo::PendingRemote<network::mojom::AuthChallengeResponder>
|
||||
auth_challenge_responder) override {
|
||||
api::URLRequest* url_request = api::URLRequest::FromID(routing_id);
|
||||
if (url_request) {
|
||||
url_request->OnAuthRequired(url, first_auth_attempt, auth_info,
|
||||
std::move(head),
|
||||
std::move(auth_challenge_responder));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void AtomBrowserContext::OnLoaderCreated(
|
||||
int32_t request_id,
|
||||
mojo::PendingReceiver<network::mojom::TrustedAuthClient> auth_client) {
|
||||
mojo::MakeSelfOwnedReceiver(std::make_unique<AuthResponder>(),
|
||||
std::move(auth_client));
|
||||
}
|
||||
|
||||
content::PushMessagingService* AtomBrowserContext::GetPushMessagingService() {
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "content/public/browser/browser_context.h"
|
||||
#include "content/public/browser/resource_context.h"
|
||||
#include "electron/buildflags/buildflags.h"
|
||||
#include "services/network/public/mojom/network_context.mojom.h"
|
||||
#include "services/network/public/mojom/url_loader_factory.mojom.h"
|
||||
#include "shell/browser/media/media_device_id_salt.h"
|
||||
|
||||
|
@ -50,7 +51,8 @@ class WebViewManager;
|
|||
|
||||
class AtomBrowserContext
|
||||
: public base::RefCountedDeleteOnSequence<AtomBrowserContext>,
|
||||
public content::BrowserContext {
|
||||
public content::BrowserContext,
|
||||
public network::mojom::TrustedURLLoaderAuthClient {
|
||||
public:
|
||||
// partition_id => browser_context
|
||||
struct PartitionKey {
|
||||
|
@ -149,6 +151,10 @@ class AtomBrowserContext
|
|||
friend class base::RefCountedDeleteOnSequence<AtomBrowserContext>;
|
||||
friend class base::DeleteHelper<AtomBrowserContext>;
|
||||
|
||||
void OnLoaderCreated(int32_t request_id,
|
||||
mojo::PendingReceiver<network::mojom::TrustedAuthClient>
|
||||
header_client) override;
|
||||
|
||||
// Initialize pref registry.
|
||||
void InitPrefs();
|
||||
|
||||
|
@ -185,6 +191,7 @@ class AtomBrowserContext
|
|||
|
||||
// Shared URLLoaderFactory.
|
||||
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
|
||||
mojo::Receiver<network::mojom::TrustedURLLoaderAuthClient> auth_client_{this};
|
||||
|
||||
base::WeakPtrFactory<AtomBrowserContext> weak_factory_;
|
||||
|
||||
|
|
|
@ -10,9 +10,12 @@
|
|||
#include <vector>
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "base/strings/string16.h"
|
||||
#include "gin/arguments.h"
|
||||
#include "gin/dictionary.h"
|
||||
#include "shell/browser/api/atom_api_web_contents.h"
|
||||
#include "shell/common/gin_converters/callback_converter.h"
|
||||
#include "shell/common/gin_converters/gurl_converter.h"
|
||||
#include "shell/common/gin_converters/net_converter.h"
|
||||
#include "shell/common/gin_converters/value_converter.h"
|
||||
|
||||
|
@ -57,7 +60,7 @@ void LoginHandler::EmitEvent(
|
|||
v8::HandleScope scope(isolate);
|
||||
|
||||
auto details = gin::Dictionary::CreateEmpty(isolate);
|
||||
details.Set("url", url.spec());
|
||||
details.Set("url", url);
|
||||
|
||||
// These parameters aren't documented, and I'm not sure that they're useful,
|
||||
// but we might as well stick 'em on the details object. If it turns out they
|
||||
|
@ -70,17 +73,23 @@ void LoginHandler::EmitEvent(
|
|||
api_web_contents->Emit("login", std::move(details), auth_info,
|
||||
base::BindOnce(&LoginHandler::CallbackFromJS,
|
||||
weak_factory_.GetWeakPtr()));
|
||||
if (!default_prevented) {
|
||||
if (!default_prevented && auth_required_callback_) {
|
||||
std::move(auth_required_callback_).Run(base::nullopt);
|
||||
}
|
||||
}
|
||||
|
||||
LoginHandler::~LoginHandler() = default;
|
||||
|
||||
void LoginHandler::CallbackFromJS(base::string16 username,
|
||||
base::string16 password) {
|
||||
std::move(auth_required_callback_)
|
||||
.Run(net::AuthCredentials(username, password));
|
||||
void LoginHandler::CallbackFromJS(gin::Arguments* args) {
|
||||
if (auth_required_callback_) {
|
||||
base::string16 username, password;
|
||||
if (!args->GetNext(&username) || !args->GetNext(&password)) {
|
||||
std::move(auth_required_callback_).Run(base::nullopt);
|
||||
return;
|
||||
}
|
||||
std::move(auth_required_callback_)
|
||||
.Run(net::AuthCredentials(username, password));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace electron
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#ifndef SHELL_BROWSER_LOGIN_HANDLER_H_
|
||||
#define SHELL_BROWSER_LOGIN_HANDLER_H_
|
||||
|
||||
#include "base/strings/string16.h"
|
||||
#include "base/values.h"
|
||||
#include "content/public/browser/content_browser_client.h"
|
||||
#include "content/public/browser/login_delegate.h"
|
||||
|
@ -15,6 +14,10 @@ namespace content {
|
|||
class WebContents;
|
||||
}
|
||||
|
||||
namespace gin {
|
||||
class Arguments;
|
||||
}
|
||||
|
||||
namespace electron {
|
||||
|
||||
// Handles HTTP basic auth.
|
||||
|
@ -36,7 +39,7 @@ class LoginHandler : public content::LoginDelegate,
|
|||
const GURL& url,
|
||||
scoped_refptr<net::HttpResponseHeaders> response_headers,
|
||||
bool first_auth_attempt);
|
||||
void CallbackFromJS(base::string16 username, base::string16 password);
|
||||
void CallbackFromJS(gin::Arguments* args);
|
||||
|
||||
LoginAuthRequiredCallback auth_required_callback_;
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include "base/task/post_task.h"
|
||||
#include "content/public/browser/file_url_loader.h"
|
||||
#include "mojo/public/cpp/bindings/receiver.h"
|
||||
#include "mojo/public/cpp/bindings/strong_binding.h"
|
||||
#include "mojo/public/cpp/system/data_pipe_producer.h"
|
||||
#include "mojo/public/cpp/system/file_data_source.h"
|
||||
#include "net/base/filename_util.h"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue