Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions 5 docs/api/app.md
Original file line number Diff line number Diff line change
Expand Up @@ -345,9 +345,10 @@ app.on('select-client-certificate', (event, webContents, url, list, callback) =>
Returns:

* `event` Event
* `webContents` [WebContents](web-contents.md)
* `webContents` [WebContents](web-contents.md) (optional)
* `authenticationResponseDetails` Object
* `url` URL
* `pid` number
* `authInfo` Object
* `isProxy` boolean
* `scheme` string
Expand All @@ -358,7 +359,7 @@ Returns:
* `username` string (optional)
* `password` string (optional)

Emitted when `webContents` wants to do basic auth.
Emitted when `webContents` or [Utility process](../glossary.md#utility-process) wants to do basic auth.

The default behavior is to cancel all authentications. To override this you
should prevent the default behavior with `event.preventDefault()` and call
Expand Down
2 changes: 2 additions & 0 deletions 2 docs/api/utility-process.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ Process: [Main](../glossary.md#main-process)<br />
`com.apple.security.cs.allow-unsigned-executable-memory` entitlements. This will allow the utility process
to load unsigned libraries. Unless you specifically need this capability, it is best to leave this disabled.
Default is `false`.
* `respondToAuthRequestsFromMainProcess` boolean (optional) - With this flag, all HTTP 401 and 407 network
requests created via the [net module](net.md) will allow responding to them via the [`app#login`](app.md#event-login) event in the main process instead of the default [`login`](client-request.md#event-login) event on the [`ClientRequest`](client-request.md) object.

Returns [`UtilityProcess`](utility-process.md#class-utilityprocess)

Expand Down
6 changes: 6 additions & 0 deletions 6 docs/breaking-changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ This document uses the following convention to categorize breaking changes:

## Planned Breaking API Changes (33.0)

### Behavior Changed: `webContents` property on `login` on `app`

The `webContents` property in the `login` event from `app` will be `null`
when the event is triggered for requests from the [utility process](api/utility-process.md)
created with `respondToAuthRequestsFromMainProcess` option.

### Deprecated: `systemPreferences.accessibilityDisplayShouldReduceTransparency`

The `systemPreferences.accessibilityDisplayShouldReduceTransparency` property is now deprecated in favor of the new `nativeTheme.prefersReducedTransparency`, which provides identical information and works cross-platform.
Expand Down
2 changes: 2 additions & 0 deletions 2 filenames.gni
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,8 @@ filenames = {
"shell/browser/net/resolve_proxy_helper.h",
"shell/browser/net/system_network_context_manager.cc",
"shell/browser/net/system_network_context_manager.h",
"shell/browser/net/url_loader_network_observer.cc",
"shell/browser/net/url_loader_network_observer.h",
"shell/browser/net/url_pipe_loader.cc",
"shell/browser/net/url_pipe_loader.h",
"shell/browser/net/web_request_api_interface.h",
Expand Down
23 changes: 18 additions & 5 deletions 23 shell/browser/api/electron_api_utility_process.cc
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ UtilityProcessWrapper::UtilityProcessWrapper(
std::map<IOHandle, IOType> stdio,
base::EnvironmentMap env_map,
base::FilePath current_working_directory,
bool use_plugin_helper) {
bool use_plugin_helper,
bool create_network_observer) {
#if BUILDFLAG(IS_WIN)
base::win::ScopedHandle stdout_write(nullptr);
base::win::ScopedHandle stderr_write(nullptr);
Expand Down Expand Up @@ -204,6 +205,11 @@ UtilityProcessWrapper::UtilityProcessWrapper(
loader_params->process_id = pid_;
loader_params->is_orb_enabled = false;
loader_params->is_trusted = true;
if (create_network_observer) {
url_loader_network_observer_.emplace();
loader_params->url_loader_network_observer =
url_loader_network_observer_->Bind();
}
network::mojom::NetworkContext* network_context =
g_browser_process->system_network_context_manager()->GetContext();
network_context->CreateURLLoaderFactory(
Expand All @@ -214,6 +220,8 @@ UtilityProcessWrapper::UtilityProcessWrapper(
network_context->CreateHostResolver(
{}, host_resolver.InitWithNewPipeAndPassReceiver());
params->host_resolver = std::move(host_resolver);
params->use_network_observer_from_url_loader_factory =
create_network_observer;

node_service_remote_->Initialize(std::move(params));
}
Expand All @@ -231,6 +239,9 @@ void UtilityProcessWrapper::OnServiceProcessLaunch(
EmitWithoutEvent("stdout", stdout_read_fd_);
if (stderr_read_fd_ != -1)
EmitWithoutEvent("stderr", stderr_read_fd_);
if (url_loader_network_observer_.has_value()) {
url_loader_network_observer_->set_process_id(pid_);
}
EmitWithoutEvent("spawn");
}

Expand Down Expand Up @@ -379,6 +390,7 @@ gin::Handle<UtilityProcessWrapper> UtilityProcessWrapper::Create(

std::u16string display_name;
bool use_plugin_helper = false;
bool create_network_observer = false;
std::map<IOHandle, IOType> stdio;
base::FilePath current_working_directory;
base::EnvironmentMap env_map;
Expand All @@ -404,6 +416,7 @@ gin::Handle<UtilityProcessWrapper> UtilityProcessWrapper::Create(

opts.Get("serviceName", &display_name);
opts.Get("cwd", &current_working_directory);
opts.Get("respondToAuthRequestsFromMainProcess", &create_network_observer);

std::vector<std::string> stdio_arr{"ignore", "inherit", "inherit"};
opts.Get("stdio", &stdio_arr);
Expand All @@ -424,10 +437,10 @@ gin::Handle<UtilityProcessWrapper> UtilityProcessWrapper::Create(
#endif
}
auto handle = gin::CreateHandle(
args->isolate(),
new UtilityProcessWrapper(std::move(params), display_name,
std::move(stdio), env_map,
current_working_directory, use_plugin_helper));
args->isolate(), new UtilityProcessWrapper(
std::move(params), display_name, std::move(stdio),
env_map, current_working_directory,
use_plugin_helper, create_network_observer));
handle->Pin(args->isolate());
return handle;
}
Expand Down
6 changes: 5 additions & 1 deletion 6 shell/browser/api/electron_api_utility_process.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "shell/browser/event_emitter_mixin.h"
#include "shell/browser/net/url_loader_network_observer.h"
#include "shell/common/gin_helper/pinnable.h"
#include "shell/services/node/public/mojom/node_service.mojom.h"
#include "v8/include/v8.h"
Expand Down Expand Up @@ -64,7 +65,8 @@ class UtilityProcessWrapper
std::map<IOHandle, IOType> stdio,
base::EnvironmentMap env_map,
base::FilePath current_working_directory,
bool use_plugin_helper);
bool use_plugin_helper,
bool create_network_observer);
void OnServiceProcessLaunch(const base::Process& process);
void CloseConnectorPort();

Expand Down Expand Up @@ -99,6 +101,8 @@ class UtilityProcessWrapper
std::unique_ptr<mojo::Connector> connector_;
blink::MessagePortDescriptor host_port_;
mojo::Remote<node::mojom::NodeService> node_service_remote_;
std::optional<electron::URLLoaderNetworkObserver>
url_loader_network_observer_;
base::WeakPtrFactory<UtilityProcessWrapper> weak_factory_{this};
};

Expand Down
4 changes: 2 additions & 2 deletions 4 shell/browser/electron_browser_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1635,8 +1635,8 @@ ElectronBrowserClient::CreateLoginDelegate(
bool first_auth_attempt,
LoginAuthRequiredCallback auth_required_callback) {
return std::make_unique<LoginHandler>(
auth_info, web_contents, is_main_frame, url, response_headers,
first_auth_attempt, std::move(auth_required_callback));
auth_info, web_contents, is_main_frame, base::kNullProcessId, url,
response_headers, first_auth_attempt, std::move(auth_required_callback));
}

std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
Expand Down
40 changes: 27 additions & 13 deletions 40 shell/browser/login_handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "base/task/sequenced_task_runner.h"
#include "gin/arguments.h"
#include "gin/dictionary.h"
#include "shell/browser/api/electron_api_app.h"
#include "shell/browser/api/electron_api_web_contents.h"
#include "shell/browser/javascript_environment.h"
#include "shell/common/gin_converters/callback_converter.h"
Expand All @@ -25,39 +26,44 @@ LoginHandler::LoginHandler(
const net::AuthChallengeInfo& auth_info,
content::WebContents* web_contents,
bool is_main_frame,
base::ProcessId process_id,
const GURL& url,
scoped_refptr<net::HttpResponseHeaders> response_headers,
bool first_auth_attempt,
LoginAuthRequiredCallback auth_required_callback)

: WebContentsObserver(web_contents),
auth_required_callback_(std::move(auth_required_callback)) {
: auth_required_callback_(std::move(auth_required_callback)) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);

base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(&LoginHandler::EmitEvent, weak_factory_.GetWeakPtr(),
auth_info, is_main_frame, url, response_headers,
first_auth_attempt));
auth_info, web_contents, is_main_frame, process_id, url,
response_headers, first_auth_attempt));
}

void LoginHandler::EmitEvent(
net::AuthChallengeInfo auth_info,
content::WebContents* web_contents,
bool is_main_frame,
base::ProcessId process_id,
const GURL& url,
scoped_refptr<net::HttpResponseHeaders> response_headers,
bool first_auth_attempt) {
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
v8::HandleScope scope(isolate);

api::WebContents* api_web_contents = api::WebContents::From(web_contents());
if (!api_web_contents) {
std::move(auth_required_callback_).Run(std::nullopt);
return;
raw_ptr<api::WebContents> api_web_contents = nullptr;
if (web_contents) {
api_web_contents = api::WebContents::From(web_contents);
if (!api_web_contents) {
std::move(auth_required_callback_).Run(std::nullopt);
return;
}
}

auto details = gin::Dictionary::CreateEmpty(isolate);
details.Set("url", url);
details.Set("pid", process_id);

// 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
Expand All @@ -67,10 +73,18 @@ void LoginHandler::EmitEvent(
details.Set("responseHeaders", response_headers.get());

auto weak_this = weak_factory_.GetWeakPtr();
bool default_prevented =
api_web_contents->Emit("login", std::move(details), auth_info,
base::BindOnce(&LoginHandler::CallbackFromJS,
weak_factory_.GetWeakPtr()));
bool default_prevented = false;
if (api_web_contents) {
default_prevented =
api_web_contents->Emit("login", std::move(details), auth_info,
base::BindOnce(&LoginHandler::CallbackFromJS,
weak_factory_.GetWeakPtr()));
} else {
default_prevented =
api::App::Get()->Emit("login", nullptr, std::move(details), auth_info,
base::BindOnce(&LoginHandler::CallbackFromJS,
weak_factory_.GetWeakPtr()));
}
// ⚠️ NB, if CallbackFromJS is called during Emit(), |this| will have been
// deleted. Check the weak ptr before accessing any member variables to
// prevent UAF.
Expand Down
8 changes: 5 additions & 3 deletions 8 shell/browser/login_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
#ifndef ELECTRON_SHELL_BROWSER_LOGIN_HANDLER_H_
#define ELECTRON_SHELL_BROWSER_LOGIN_HANDLER_H_

#include "base/process/process_handle.h"
#include "base/values.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/login_delegate.h"
#include "content/public/browser/web_contents_observer.h"

namespace content {
class WebContents;
Expand All @@ -21,12 +21,12 @@ class Arguments;
namespace electron {

// Handles HTTP basic auth.
class LoginHandler : public content::LoginDelegate,
private content::WebContentsObserver {
class LoginHandler : public content::LoginDelegate {
public:
LoginHandler(const net::AuthChallengeInfo& auth_info,
content::WebContents* web_contents,
bool is_main_frame,
base::ProcessId process_id,
const GURL& url,
scoped_refptr<net::HttpResponseHeaders> response_headers,
bool first_auth_attempt,
Expand All @@ -39,7 +39,9 @@ class LoginHandler : public content::LoginDelegate,

private:
void EmitEvent(net::AuthChallengeInfo auth_info,
content::WebContents* web_contents,
bool is_main_frame,
base::ProcessId process_id,
const GURL& url,
scoped_refptr<net::HttpResponseHeaders> response_headers,
bool first_auth_attempt);
Expand Down
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.