Compare commits

..

17 Commits

Author SHA1 Message Date
Charles Kerr
a1ca9a8d55 refactor: DRY in App::SetAppLogPath() (#48452) 2025-10-05 12:32:28 -05:00
Charles Kerr
38e491689a perf: avoid a little extra work in InvokeIpcCallback() (#48456)
perf: two minor perf refactors in InvokeIpcCallback()

1. Allocate the CallbackScope on the stack instead of the heap
2. Skip a redundant call to  node::Environment::GetCurrent()
2025-10-04 21:52:53 -07:00
Niklas Wenzel
6e2be00f0f docs: recommend calling renderer process modules from preload script (#48427) 2025-10-04 18:44:10 +02:00
Charles Kerr
497b5a68a4 docs: clarify optional args in webFrame.executeJavaScript() (#48447) 2025-10-04 09:28:06 -05:00
Kaiichiro Ota
715808ecbe docs: mention that webUtils should be used via preload script (#45861)
* docs: mention that webUtils should be used via preload script

* docs: suppress lint errors

* docs: clarify webUtils usage scope

* docs: exclude potentially dangerous alert() in the example code

* docs: minor change

* docs: minor change

* docs: minor change

* docs: minor change

* docs: minor change

* docs: minor change

* docs: minor change

* docs: minor change

* docs: minor change

* docs: minor change

* docs: make linter happy

* docs: apply suggestion

Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>

* docs: apply suggestion

Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>

* docs: apply suggestion

Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>

* docs: minor change

* docs: minor change

* docs: remove preload line

---------

Co-authored-by: Niklas Wenzel <dev@nikwen.de>
Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2025-10-03 13:07:38 -07:00
Charles Kerr
01cab978f7 refactor: remove gin_helper::Arguments (#48374)
* refactor: make api::Clipboard::GetClipboardBuffer() private

* refactor: move GetClipboadBuffer() into anonymous namespace

* refactor: use gin::Arguments in StopRecording()

* refactor: use gin::Arguments in ImageView::New()

* refactor: use gin::Arguments in AppendSwitch()

* refactor: use gin::Arguments WebContentsView::New()

* refactor: make gin::Arguments arg const in WrappableBase::InitWithArgs()

This makes explicit that we are using it for wrapper + isolate, not the args values

* refactor: remove gin_helper::Arguments arg from ExposeAPI()

refactor: remove gin_helper::Arguments arg from ExposeAPIInWorld()

* refactor: remove gin_helper::Arguments arg from ElectronBindings::GetSystemMemoryInfo()

* refactor: remove gin_helper::Arguments arg from preload_utils::GetBinding()

* refactor: use gin::Arguments in OpenExternal()

* refactor: use gin::Arguments in ExecuteInWorld()

* refactor: use gin::Arguments in ExecuteJavaScript()

* refactor: use gin::Arguments in InvokeNew()

* refactor: use gin::Arguments in ExecuteJavaScriptInIsolatedWorld()

* refactor: remove unused GetNextArgument() marshaller for gin_helper::Arguments

* refactor: remove unused #include gin_helper/arguments.h

* chore: remove unused gin_helper::Arguments

* fixup! refactor: use gin::Arguments in ExecuteJavaScriptInIsolatedWorld()

Xref: https://github.com/electron/electron/pull/48447
2025-10-03 14:10:29 -05:00
zoy
7cb1552614 fix: accentColor set distinguishes the frame (#48405)
* fix: accentColor set distinguishes the frame

* chore: invalid change

* fix: lint
2025-10-03 20:10:18 +02:00
Niklas Wenzel
49c37b4daa docs: update allowed window.open options (#48428) 2025-10-03 01:29:26 +02:00
Robo
37a115b8fd fix: initialze featurelist before parsing features (#48411) 2025-10-03 01:18:14 +02:00
Shelley Vohr
e7e29ea876 fix: snapped window restoring to correct position (#48296) 2025-10-02 18:14:48 +02:00
Erick Zhao
b40a4befd4 docs: fix formatting in asar integrity (#48431) 2025-10-01 22:27:28 -07:00
dependabot[bot]
61a7303531 build(deps): bump github/codeql-action from 3.30.1 to 3.30.5 (#48420)
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.30.1 to 3.30.5.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](f1f6e5f6af...3599b3baa1)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 3.30.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-30 18:36:57 +02:00
Fedor Indutny
6f9cd718c4 fix: runtime JS error that crashes GetPackageJSON (#48293)
We overriden the `GetPackageJSON` in Node.js to let us read files
straight from the ASAR file instead of disk. The override works by
providing a JS method with the limitation that it should not throw a
runtime error. However, this invariant was accidentally violated by
`asar.splitPath` that sometimes contrary to its' TypeScript definition
returned `false`.
2025-09-30 18:32:13 +02:00
Samuel Attard
a95180e080 build: add missing copied tarball to cloudstore paths (#48408)
It's guarunteed that `iojs-*` and `node-*` were the same origin file (we azcopy them) but this was missing in logs and it annoyed me
2025-09-29 11:16:39 -07:00
BILL SHEN
d4a5fdc8fc fix: add missed enum SaveRequestType to PdfViewerPrivate function (#48372)
fix: add missed SaveRequestType enum to PdfViewerPrivate function
2025-09-26 16:34:06 -04:00
avarayr
3a7c6dd4a5 fix: MacOS 26 Tahoe - stop overriding private cornerMask API to fix WindowServer GPU load (#48376)
fix: macOS stop overriding private cornerMask API to fix WindowServer GPU load spike

Electron fetched a custom `_cornerMask` for `ElectronNSWindow` to smooth
vibrancy corners. On macOS 15 (Tahoe) that private hook forces the window
shadow to be rendered from a fully transparent surface, causing the
WindowServer GPU load regression. Remove the `cornerMask` property and
the `_cornerMask` override so we stay on Apple’s default shadow path.
2025-09-26 12:41:16 -07:00
Robo
26e886c517 fix: disable NSAutoFillHeuristicController on macOS 26 (#48379)
Co-authored-by: Keeley Hammond <khammond@slack-corp.com>
2025-09-26 08:40:55 +09:00
47 changed files with 288 additions and 284 deletions

View File

@@ -50,6 +50,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@f1f6e5f6af878fb37288ce1c627459e94dbf7d01 # v3.29.5
uses: github/codeql-action/upload-sarif@3599b3baa15b485a2e49ef411a7a4bb2452e7f93 # v3.29.5
with:
sarif_file: results.sarif

View File

@@ -4,6 +4,12 @@
Process: [Main](../glossary.md#main-process), [Renderer](../glossary.md#renderer-process) (non-sandboxed only)
> [!IMPORTANT]
> If you want to call this API from a renderer process with context isolation enabled,
> place the API call in your preload script and
> [expose](../tutorial/context-isolation.md#after-context-isolation-enabled) it using the
> [`contextBridge`](context-bridge.md) API.
On Linux, there is also a `selection` clipboard. To manipulate it
you need to pass `selection` to each method:

View File

@@ -4,6 +4,12 @@
Process: [Main](../glossary.md#main-process), [Renderer](../glossary.md#renderer-process)
> [!IMPORTANT]
> If you want to call this API from a renderer process with context isolation enabled,
> place the API call in your preload script and
> [expose](../tutorial/context-isolation.md#after-context-isolation-enabled) it using the
> [`contextBridge`](context-bridge.md) API.
The following is an example of setting up Electron to automatically submit
crash reports to a remote server:

View File

@@ -20,6 +20,12 @@ changes:
Process: [Renderer](../glossary.md#renderer-process)
> [!IMPORTANT]
> If you want to call this API from a renderer process with context isolation enabled,
> place the API call in your preload script and
> [expose](../tutorial/context-isolation.md#after-context-isolation-enabled) it using the
> [`contextBridge`](context-bridge.md) API.
The `ipcRenderer` module is an [EventEmitter][event-emitter]. It provides a few
methods so you can send synchronous and asynchronous messages from the render
process (web page) to the main process. You can also receive replies from the

View File

@@ -4,6 +4,12 @@
Process: [Main](../glossary.md#main-process), [Renderer](../glossary.md#renderer-process)
> [!IMPORTANT]
> If you want to call this API from a renderer process with context isolation enabled,
> place the API call in your preload script and
> [expose](../tutorial/context-isolation.md#after-context-isolation-enabled) it using the
> [`contextBridge`](context-bridge.md) API.
The `nativeImage` module provides a unified interface for manipulating
system images. These can be handy if you want to provide multiple scaled
versions of the same icon or take advantage of macOS [template images][template-image].

View File

@@ -4,6 +4,12 @@
Process: [Renderer](../glossary.md#renderer-process)
> [!IMPORTANT]
> If you want to call this API from a renderer process with context isolation enabled,
> place the API call in your preload script and
> [expose](../tutorial/context-isolation.md#after-context-isolation-enabled) it using the
> [`contextBridge`](context-bridge.md) API.
`webFrame` export of the Electron module is an instance of the `WebFrame`
class representing the current frame. Sub-frames can be retrieved by
certain properties and methods (e.g. `webFrame.firstChild`).
@@ -139,7 +145,7 @@ by its key, which is returned from `webFrame.insertCSS(css)`.
Inserts `text` to the focused element.
### `webFrame.executeJavaScript(code[, userGesture, callback])`
### `webFrame.executeJavaScript(code[, userGesture][, callback])`
* `code` string
* `userGesture` boolean (optional) - Default is `false`.
@@ -160,7 +166,7 @@ In the browser window some HTML APIs like `requestFullScreen` can only be
invoked by a gesture from the user. Setting `userGesture` to `true` will remove
this limitation.
### `webFrame.executeJavaScriptInIsolatedWorld(worldId, scripts[, userGesture, callback])`
### `webFrame.executeJavaScriptInIsolatedWorld(worldId, scripts[, userGesture][, callback])`
* `worldId` Integer - The ID of the world to run the javascript
in, `0` is the default main world (where content runs), `999` is the

View File

@@ -4,6 +4,12 @@
Process: [Renderer](../glossary.md#renderer-process)
> [!IMPORTANT]
> If you want to call this API from a renderer process with context isolation enabled,
> place the API call in your preload script and
> [expose](../tutorial/context-isolation.md#after-context-isolation-enabled) it using the
> [`contextBridge`](context-bridge.md) API.
## Methods
The `webUtils` module has the following methods:
@@ -17,11 +23,27 @@ Returns `string` - The file system path that this `File` object points to. In th
This method superseded the previous augmentation to the `File` object with the `path` property. An example is included below.
```js @ts-nocheck
// Before
const oldPath = document.querySelector('input').files[0].path
// After
const { webUtils } = require('electron')
const newPath = webUtils.getPathForFile(document.querySelector('input').files[0])
// Before (renderer)
const oldPath = document.querySelector('input[type=file]').files[0].path
```
```js @ts-nocheck
// After
// Renderer:
const file = document.querySelector('input[type=file]').files[0]
electronApi.doSomethingWithFile(file)
// Preload script:
const { contextBridge, webUtils } = require('electron')
contextBridge.exposeInMainWorld('electronApi', {
doSomethingWithFile (file) {
const path = webUtils.getPathForFile(file)
// Do something with the path, e.g., send it over IPC to the main process.
// It's best not to expose the full file path to the web content if possible.
}
})
```

View File

@@ -39,8 +39,8 @@ consider using `webContents.setWindowOpenHandler` to customize the
BrowserWindow creation.
A subset of [`WebPreferences`](structures/web-preferences.md) can be set directly,
unnested, from the features string: `zoomFactor`, `nodeIntegration`, `preload`,
`javascript`, `contextIsolation`, and `webviewTag`.
unnested, from the features string: `zoomFactor`, `nodeIntegration`, `javascript`,
`contextIsolation`, and `webviewTag`.
For example:

View File

@@ -64,13 +64,10 @@ flipFuses(
)
```
:::tip Fuses in Electron Forge
With Electron Forge, you can configure your app's fuses with
[@electron-forge/plugin-fuses](https://www.electronforge.io/config/plugins/fuses)
in your Forge configuration file.
:::
> [!TIP]
> With Electron Forge, you can configure your app's fuses with
> [@electron-forge/plugin-fuses](https://www.electronforge.io/config/plugins/fuses)
> in your Forge configuration file.
## Providing the header hash
@@ -109,7 +106,7 @@ Valid `algorithm` values are currently `SHA256` only. The `hash` is a hash of th
The `@electron/asar` package exposes a `getRawHeader` method whose result can then be hashed to generate this value
(e.g. using the [`node:crypto`](https://nodejs.org/api/crypto.html) module).
### Windows
#### Windows
When packaging for Windows, you must populate a valid [resource](https://learn.microsoft.com/en-us/windows/win32/menurc/resources)
entry of type `Integrity` and name `ElectronAsar`. The value of this resource should be a JSON encoded dictionary
@@ -125,9 +122,6 @@ in the form included below:
]
```
:::info
For an implementation example, see [`src/resedit.ts`](https://github.com/electron/packager/blob/main/src/resedit.ts)
in the Electron Packager code.
:::
> [!NOTE]
> For an implementation example, see [`src/resedit.ts`](https://github.com/electron/packager/blob/main/src/resedit.ts)
> in the Electron Packager code.

View File

@@ -629,8 +629,6 @@ filenames = {
"shell/common/gin_converters/usb_device_info_converter.h",
"shell/common/gin_converters/value_converter.cc",
"shell/common/gin_converters/value_converter.h",
"shell/common/gin_helper/arguments.cc",
"shell/common/gin_helper/arguments.h",
"shell/common/gin_helper/callback.cc",
"shell/common/gin_helper/callback.h",
"shell/common/gin_helper/cleaned_up_at_exit.cc",

View File

@@ -141,3 +141,4 @@ chore_add_electron_objects_to_wrappablepointertag.patch
chore_expose_isolate_parameter_in_script_lifecycle_observers.patch
revert_partial_remove_unused_prehandlemouseevent.patch
allow_electron_to_depend_on_components_os_crypt_sync.patch
disable_nsautofillheuristiccontroller_on_macos_26.patch

View File

@@ -0,0 +1,53 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Perry <perryuwang@tencent.com>
Date: Wed, 24 Sep 2025 09:56:23 -0700
Subject: Disable NSAutoFillHeuristicController on macOS 26
The reason for this issue is that NSAutoFillHeuristicController is
enabled by default on macOS 26. In pages with <input> tags, browser
process sends synchronized IPC messages to renderer process. At this
point, if the renderer process also sends synchronized IPC messages to
the browser process, it will cause a deadlock.
This bug can be reproduced on many websites. From the perspective of
user experience, we should first disable this feature on macOS 26.
Bug: 446070423, 446481994
Change-Id: I2d3855648980a22678548e373756fc156e28ecd7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6965487
Reviewed-by: Mark Mentovai <mark@chromium.org>
Commit-Queue: Mark Mentovai <mark@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1520058}
diff --git a/content/app/mac_init.mm b/content/app/mac_init.mm
index 603c25a1bd4a11b9dbe57ac6add81647302e63be..963f45a8936850b59013390faf7890bc4215f2d9 100644
--- a/content/app/mac_init.mm
+++ b/content/app/mac_init.mm
@@ -6,6 +6,7 @@
#import <Cocoa/Cocoa.h>
+#include "base/mac/mac_util.h"
#include "content/common/mac/system_policy.h"
namespace content {
@@ -29,6 +30,19 @@ void InitializeMac() {
@"NSAppSleepDisabled" : @YES,
}];
+ if (base::mac::MacOSVersion() >= 26'00'00) {
+ [NSUserDefaults.standardUserDefaults registerDefaults:@{
+ // Disable NSAutoFillHeuristicController on macOS 26. On macOS 26, the
+ // browser process sends synchronized IPC messages to the renderer process
+ // on pages with <input> tags. At this point, if the renderer process
+ // sends a synchronized IPC message to the browser process, it will cause
+ // a deadlock.
+ // https://crbug.com/446070423
+ // https://crbug.com/446481994
+ @"NSAutoFillHeuristicControllerEnabled" : @NO,
+ }];
+ }
+
SetSystemPolicyCrashKeys();
}

View File

@@ -210,8 +210,10 @@ function assetsForVersion (version: string, validatingRelease: boolean) {
const cloudStoreFilePaths = (version: string) => [
`iojs-${version}-headers.tar.gz`,
`iojs-${version}.tar.gz`,
`node-${version}-headers.tar.gz`,
`node-${version}.tar.gz`,
'node.lib',
'arm64/node.lib',
'x64/node.lib',
'win-x64/iojs.lib',
'win-x86/iojs.lib',
@@ -219,7 +221,6 @@ const cloudStoreFilePaths = (version: string) => [
'win-x64/node.lib',
'win-x86/node.lib',
'win-arm64/node.lib',
'arm64/node.lib',
'SHASUMS.txt',
'SHASUMS256.txt'
];

View File

@@ -13,10 +13,12 @@
#include "base/apple/bundle_locations.h"
#include "base/base_switches.h"
#include "base/command_line.h"
#include "base/debug/leak_annotations.h"
#include "base/debug/stack_trace.h"
#include "base/environment.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/metrics/field_trial.h"
#include "base/path_service.h"
#include "base/strings/cstring_view.h"
#include "base/strings/string_number_conversions.cc"
@@ -419,6 +421,11 @@ std::optional<int> ElectronMainDelegate::PreBrowserMain() {
// This is initialized early because the service manager reads some feature
// flags and we need to make sure the feature list is initialized before the
// service manager reads the features.
if (!base::FieldTrialList::GetInstance()) {
base::FieldTrialList* leaked_field_trial_list = new base::FieldTrialList();
ANNOTATE_LEAKING_OBJECT_PTR(leaked_field_trial_list);
std::ignore = leaked_field_trial_list;
}
InitializeFeatureList();
// Initialize mojo core as soon as we have a valid feature list
content::InitializeMojoCore();

View File

@@ -870,28 +870,33 @@ void App::SetAppPath(const base::FilePath& app_path) {
app_path_ = app_path;
}
#if !BUILDFLAG(IS_MAC)
void App::SetAppLogsPath(gin_helper::ErrorThrower thrower,
std::optional<base::FilePath> custom_path) {
if (custom_path.has_value()) {
if (!custom_path->IsAbsolute()) {
thrower.ThrowError("Path must be absolute");
return;
}
{
ScopedAllowBlockingForElectron allow_blocking;
base::PathService::Override(DIR_APP_LOGS, custom_path.value());
}
} else {
base::FilePath path;
if (base::PathService::Get(chrome::DIR_USER_DATA, &path)) {
path = path.Append(base::FilePath::FromUTF8Unsafe("logs"));
{
ScopedAllowBlockingForElectron allow_blocking;
base::PathService::Override(DIR_APP_LOGS, path);
}
}
void App::SetAppLogsPath(gin::Arguments* const args) {
base::FilePath path;
// if caller provided a path, it must be absolute
if (args->GetNext(&path) && !path.IsAbsolute()) {
args->ThrowTypeError("Path must be absolute");
return;
}
// if caller did not provide a path, then use a default one
if (path.empty()) {
path = GetDefaultAppLogPath();
}
ScopedAllowBlockingForElectron allow_blocking;
base::PathService::Override(DIR_APP_LOGS, path);
}
#if !BUILDFLAG(IS_MAC)
// static
// default to `${DIR_USER_DATA}/logs`
base::FilePath App::GetDefaultAppLogPath() {
base::FilePath path;
if (base::PathService::Get(chrome::DIR_USER_DATA, &path)) {
path = path.Append(base::FilePath::FromUTF8Unsafe("logs"));
}
return path;
}
#endif

View File

@@ -178,6 +178,8 @@ class App final : public gin::Wrappable<App>,
const content::ChildProcessTerminationInfo& info) override;
private:
[[nodiscard]] static base::FilePath GetDefaultAppLogPath();
void BrowserChildProcessCrashedOrKilled(
const content::ChildProcessData& data,
const content::ChildProcessTerminationInfo& info);
@@ -190,8 +192,7 @@ class App final : public gin::Wrappable<App>,
const std::string& name = std::string());
void ChildProcessDisconnected(content::ChildProcessId pid);
void SetAppLogsPath(gin_helper::ErrorThrower thrower,
std::optional<base::FilePath> custom_path);
void SetAppLogsPath(gin::Arguments* args);
// Get/Set the pre-defined path in PathService.
base::FilePath GetPath(gin_helper::ErrorThrower thrower,

View File

@@ -17,30 +17,14 @@
namespace electron::api {
void App::SetAppLogsPath(gin_helper::ErrorThrower thrower,
std::optional<base::FilePath> custom_path) {
if (custom_path.has_value()) {
if (!custom_path->IsAbsolute()) {
thrower.ThrowError("Path must be absolute");
return;
}
{
ScopedAllowBlockingForElectron allow_blocking;
base::PathService::Override(DIR_APP_LOGS, custom_path.value());
}
} else {
NSString* bundle_name =
[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];
NSString* logs_path =
[NSString stringWithFormat:@"Library/Logs/%@", bundle_name];
NSString* library_path =
[NSHomeDirectory() stringByAppendingPathComponent:logs_path];
{
ScopedAllowBlockingForElectron allow_blocking;
base::PathService::Override(DIR_APP_LOGS,
base::FilePath([library_path UTF8String]));
}
}
base::FilePath App::GetDefaultAppLogPath() {
NSString* bundle_name =
[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];
NSString* logs_path =
[NSString stringWithFormat:@"Library/Logs/%@", bundle_name];
NSString* library_path =
[NSHomeDirectory() stringByAppendingPathComponent:logs_path];
return base::FilePath{[library_path UTF8String]};
}
void App::SetActivationPolicy(gin_helper::ErrorThrower thrower,

View File

@@ -98,8 +98,8 @@ void StopTracing(gin_helper::Promise<base::FilePath> promise,
}
}
v8::Local<v8::Promise> StopRecording(gin_helper::Arguments* args) {
gin_helper::Promise<base::FilePath> promise(args->isolate());
v8::Local<v8::Promise> StopRecording(gin::Arguments* const args) {
gin_helper::Promise<base::FilePath> promise{args->isolate()};
v8::Local<v8::Promise> handle = promise.GetHandle();
base::FilePath path;

View File

@@ -153,36 +153,37 @@ v8::Local<v8::Function> WebContentsView::GetConstructor(v8::Isolate* isolate) {
}
// static
gin_helper::WrappableBase* WebContentsView::New(gin_helper::Arguments* args) {
gin_helper::WrappableBase* WebContentsView::New(gin::Arguments* const args) {
v8::Isolate* const isolate = args->isolate();
gin_helper::Dictionary web_preferences;
v8::Local<v8::Value> existing_web_contents_value;
{
v8::Local<v8::Value> options_value;
if (args->GetNext(&options_value)) {
gin_helper::Dictionary options;
if (!gin::ConvertFromV8(args->isolate(), options_value, &options)) {
args->ThrowError("options must be an object");
if (!gin::ConvertFromV8(isolate, options_value, &options)) {
args->ThrowTypeError("options must be an object");
return nullptr;
}
v8::Local<v8::Value> web_preferences_value;
if (options.Get("webPreferences", &web_preferences_value)) {
if (!gin::ConvertFromV8(args->isolate(), web_preferences_value,
if (!gin::ConvertFromV8(isolate, web_preferences_value,
&web_preferences)) {
args->ThrowError("options.webPreferences must be an object");
args->ThrowTypeError("options.webPreferences must be an object");
return nullptr;
}
}
if (options.Get("webContents", &existing_web_contents_value)) {
gin_helper::Handle<WebContents> existing_web_contents;
if (!gin::ConvertFromV8(args->isolate(), existing_web_contents_value,
if (!gin::ConvertFromV8(isolate, existing_web_contents_value,
&existing_web_contents)) {
args->ThrowError("options.webContents must be a WebContents");
args->ThrowTypeError("options.webContents must be a WebContents");
return nullptr;
}
if (existing_web_contents->owner_window() != nullptr) {
args->ThrowError(
args->ThrowTypeError(
"options.webContents is already attached to a window");
return nullptr;
}
@@ -191,7 +192,7 @@ gin_helper::WrappableBase* WebContentsView::New(gin_helper::Arguments* args) {
}
if (web_preferences.IsEmpty())
web_preferences = gin_helper::Dictionary::CreateEmpty(args->isolate());
web_preferences = gin_helper::Dictionary::CreateEmpty(isolate);
if (!web_preferences.Has(options::kShow))
web_preferences.Set(options::kShow, false);
@@ -200,10 +201,10 @@ gin_helper::WrappableBase* WebContentsView::New(gin_helper::Arguments* args) {
}
auto web_contents =
WebContents::CreateFromWebPreferences(args->isolate(), web_preferences);
WebContents::CreateFromWebPreferences(isolate, web_preferences);
// Constructor call.
auto* view = new WebContentsView(args->isolate(), web_contents);
auto* view = new WebContentsView{isolate, web_contents};
view->InitWithArgs(args);
return view;
}

View File

@@ -57,7 +57,7 @@ class WebContentsView : public View,
void OnViewRemovedFromWidget(views::View* view) override;
private:
static gin_helper::WrappableBase* New(gin_helper::Arguments* args);
static gin_helper::WrappableBase* New(gin::Arguments* args);
void ApplyBorderRadius();

View File

@@ -25,7 +25,7 @@ void ImageView::SetImage(const gfx::Image& image) {
}
// static
gin_helper::WrappableBase* ImageView::New(gin_helper::Arguments* args) {
gin_helper::WrappableBase* ImageView::New(gin::Arguments* const args) {
// Constructor call.
auto* view = new ImageView();
view->InitWithArgs(args);

View File

@@ -13,8 +13,11 @@ namespace gfx {
class Image;
}
namespace gin_helper {
namespace gin {
class Arguments;
} // namespace gin
namespace gin_helper {
class WrappableBase;
} // namespace gin_helper
@@ -22,7 +25,7 @@ namespace electron::api {
class ImageView : public View {
public:
static gin_helper::WrappableBase* New(gin_helper::Arguments* args);
static gin_helper::WrappableBase* New(gin::Arguments* args);
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype);

View File

@@ -13,13 +13,13 @@
#include "base/task/single_thread_task_runner.h"
#include "base/threading/thread_restrictions.h"
#include "chrome/common/chrome_paths.h"
#include "gin/arguments.h"
#include "shell/browser/browser_observer.h"
#include "shell/browser/electron_browser_main_parts.h"
#include "shell/browser/native_window.h"
#include "shell/browser/window_list.h"
#include "shell/common/application_info.h"
#include "shell/common/gin_converters/login_item_settings_converter.h"
#include "shell/common/gin_helper/arguments.h"
#include "shell/common/thread_restrictions.h"
namespace electron {

View File

@@ -14,7 +14,6 @@
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/i18n/rtl.h"
#include "base/metrics/field_trial.h"
#include "base/nix/xdg_util.h"
#include "base/path_service.h"
#include "base/run_loop.h"
@@ -206,7 +205,6 @@ int ElectronBrowserMainParts::GetExitCode() const {
}
int ElectronBrowserMainParts::PreEarlyInitialization() {
field_trial_list_ = std::make_unique<base::FieldTrialList>();
#if BUILDFLAG(IS_POSIX)
HandleSIGCHLD();
#endif

View File

@@ -19,10 +19,6 @@
class BrowserProcessImpl;
class IconManager;
namespace base {
class FieldTrialList;
}
namespace display {
class Screen;
class ScopedNativeScreen;
@@ -171,7 +167,6 @@ class ElectronBrowserMainParts : public content::BrowserMainParts {
std::unique_ptr<Browser> browser_;
std::unique_ptr<IconManager> icon_manager_;
std::unique_ptr<base::FieldTrialList> field_trial_list_;
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
std::unique_ptr<ElectronExtensionsClient> extensions_client_;

View File

@@ -1333,7 +1333,6 @@ void NativeWindowMac::UpdateVibrancyRadii(bool fullscreen) {
maskImage.capInsets = NSEdgeInsetsMake(radius, radius, radius, radius);
maskImage.resizingMode = NSImageResizingModeStretch;
[vibrantView setMaskImage:maskImage];
[window_ setCornerMask:maskImage];
}
}
}

View File

@@ -35,7 +35,6 @@
#include "shell/browser/window_list.h"
#include "shell/common/electron_constants.h"
#include "shell/common/gin_converters/image_converter.h"
#include "shell/common/gin_helper/arguments.h"
#include "shell/common/gin_helper/dictionary.h"
#include "shell/common/options_switches.h"
#include "ui/aura/window_tree_host.h"

View File

@@ -31,15 +31,15 @@ namespace electron {
namespace {
void SetWindowBorderAndCaptionColor(HWND hwnd, COLORREF color) {
if (base::win::GetVersion() < base::win::Version::WIN11)
return;
void SetWindowBorderAndCaptionColor(HWND hwnd, COLORREF color, bool has_frame) {
HRESULT result;
if (has_frame) {
result =
DwmSetWindowAttribute(hwnd, DWMWA_CAPTION_COLOR, &color, sizeof(color));
HRESULT result =
DwmSetWindowAttribute(hwnd, DWMWA_CAPTION_COLOR, &color, sizeof(color));
if (FAILED(result))
LOG(WARNING) << "Failed to set caption color";
if (FAILED(result))
LOG(WARNING) << "Failed to set caption color";
}
result =
DwmSetWindowAttribute(hwnd, DWMWA_BORDER_COLOR, &color, sizeof(color));
@@ -509,7 +509,7 @@ void NativeWindowViews::HandleSizeEvent(WPARAM w_param, LPARAM l_param) {
WINDOWPLACEMENT wp;
wp.length = sizeof(WINDOWPLACEMENT);
if (GetWindowPlacement(GetAcceleratedWidget(), &wp)) {
if (GetWindowPlacement(GetAcceleratedWidget(), &wp) && !was_snapped_) {
last_normal_placement_bounds_ = gfx::Rect(wp.rcNormalPosition);
}
@@ -518,11 +518,9 @@ void NativeWindowViews::HandleSizeEvent(WPARAM w_param, LPARAM l_param) {
if (w_param == SIZE_MAXIMIZED &&
last_window_state_ != ui::mojom::WindowShowState::kMaximized) {
if (last_window_state_ == ui::mojom::WindowShowState::kMinimized) {
if (was_snapped_) {
SetRoundedCorners(false);
was_snapped_ = false;
}
NotifyWindowRestore();
if (was_snapped_)
was_snapped_ = false;
}
last_window_state_ = ui::mojom::WindowShowState::kMaximized;
NotifyWindowMaximize();
@@ -545,12 +543,10 @@ void NativeWindowViews::HandleSizeEvent(WPARAM w_param, LPARAM l_param) {
last_window_state_ = ui::mojom::WindowShowState::kFullscreen;
NotifyWindowEnterFullScreen();
} else {
if (was_snapped_) {
SetRoundedCorners(false);
was_snapped_ = false;
}
last_window_state_ = ui::mojom::WindowShowState::kNormal;
NotifyWindowRestore();
if (was_snapped_)
was_snapped_ = false;
}
break;
default:
@@ -595,7 +591,8 @@ void NativeWindowViews::UpdateWindowAccentColor(bool active) {
}
COLORREF final_color = border_color.value_or(DWMWA_COLOR_DEFAULT);
SetWindowBorderAndCaptionColor(GetAcceleratedWidget(), final_color);
SetWindowBorderAndCaptionColor(GetAcceleratedWidget(), final_color,
has_frame());
}
void NativeWindowViews::SetAccentColor(

View File

@@ -40,7 +40,6 @@ class ElectronNativeWindowObserver;
@property BOOL disableAutoHideCursor;
@property BOOL disableKeyOrMainWindow;
@property(nonatomic, retain) NSVisualEffectView* vibrantView;
@property(nonatomic, retain) NSImage* cornerMask;
- (id)initWithShell:(electron::NativeWindowMac*)shell
styleMask:(NSUInteger)styleMask;
- (void)cleanup;
@@ -48,7 +47,6 @@ class ElectronNativeWindowObserver;
- (id)accessibilityFocusedUIElement;
- (NSRect)originalContentRectForFrameRect:(NSRect)frameRect;
- (BOOL)toggleFullScreenMode:(id)sender;
- (NSImage*)_cornerMask;
- (void)disableHeadlessMode;
@end

View File

@@ -25,7 +25,6 @@ int ScopedDisableResize::disable_resize_ = 0;
} // namespace electron
@interface NSWindow (PrivateAPI)
- (NSImage*)_cornerMask;
- (int64_t)_resizeDirectionForMouseLocation:(CGPoint)location;
@end
@@ -123,7 +122,6 @@ void SwizzleSwipeWithEvent(NSView* view, SEL swiz_selector) {
@synthesize disableAutoHideCursor;
@synthesize disableKeyOrMainWindow;
@synthesize vibrantView;
@synthesize cornerMask;
- (id)initWithShell:(electron::NativeWindowMac*)shell
styleMask:(NSUInteger)styleMask {
@@ -308,16 +306,6 @@ void SwizzleSwipeWithEvent(NSView* view, SEL swiz_selector) {
return [super validateUserInterfaceItem:item];
}
// By overriding this built-in method the corners of the vibrant view (if set)
// will be smooth.
- (NSImage*)_cornerMask {
if (self.vibrantView != nil) {
return [self cornerMask];
} else {
return [super _cornerMask];
}
}
- (void)disableHeadlessMode {
if (shell_) {
// We initialize the window in headless mode to allow painting before it is

View File

@@ -191,13 +191,15 @@ class Archive : public node::ObjectWrap {
static void SplitPath(const v8::FunctionCallbackInfo<v8::Value>& args) {
auto* isolate = args.GetIsolate();
auto dict = gin_helper::Dictionary::CreateEmpty(isolate);
args.GetReturnValue().Set(dict.GetHandle());
base::FilePath path;
if (!gin::ConvertFromV8(isolate, args[0], &path)) {
args.GetReturnValue().Set(v8::False(isolate));
dict.Set("isAsar", false);
return;
}
auto dict = gin_helper::Dictionary::CreateEmpty(isolate);
base::FilePath asar_path, file_path;
if (asar::GetAsarArchivePath(path, &asar_path, &file_path, true)) {
dict.Set("isAsar", true);
@@ -206,7 +208,6 @@ static void SplitPath(const v8::FunctionCallbackInfo<v8::Value>& args) {
} else {
dict.Set("isAsar", false);
}
args.GetReturnValue().Set(dict.GetHandle());
}
void Initialize(v8::Local<v8::Object> exports,

View File

@@ -29,7 +29,7 @@ base::CommandLine::StringType GetSwitchValue(gin_helper::ErrorThrower thrower,
}
void AppendSwitch(const std::string& switch_string,
gin_helper::Arguments* args) {
gin::Arguments* const args) {
auto switch_str = base::ToLowerASCII(switch_string);
auto* command_line = base::CommandLine::ForCurrentProcess();
if (base::EndsWith(switch_string, "-path",

View File

@@ -55,7 +55,8 @@ void OnOpenFinished(gin_helper::Promise<void> promise,
promise.RejectWithErrorMessage(error);
}
v8::Local<v8::Promise> OpenExternal(const GURL& url, gin::Arguments* args) {
v8::Local<v8::Promise> OpenExternal(const GURL& url,
gin::Arguments* const args) {
gin_helper::Promise<void> promise(args->isolate());
v8::Local<v8::Promise> handle = promise.GetHandle();
@@ -108,7 +109,7 @@ v8::Local<v8::Promise> TrashItem(v8::Isolate* isolate,
#if BUILDFLAG(IS_WIN)
bool WriteShortcutLink(const base::FilePath& shortcut_path,
gin_helper::Arguments* args) {
gin::Arguments* const args) {
base::win::ShortcutOperation operation =
base::win::ShortcutOperation::kCreateAlways;
args->GetNext(&operation);

View File

@@ -21,6 +21,7 @@
#include "shell/common/application_info.h"
#include "shell/common/gin_converters/file_path_converter.h"
#include "shell/common/gin_helper/dictionary.h"
#include "shell/common/gin_helper/error_thrower.h"
#include "shell/common/gin_helper/locker.h"
#include "shell/common/gin_helper/promise.h"
#include "shell/common/heap_snapshot.h"
@@ -163,11 +164,11 @@ v8::Local<v8::Value> ElectronBindings::GetCreationTime(v8::Isolate* isolate) {
// static
v8::Local<v8::Value> ElectronBindings::GetSystemMemoryInfo(
v8::Isolate* isolate,
gin_helper::Arguments* args) {
v8::Isolate* const isolate) {
base::SystemMemoryInfo mem_info;
if (!base::GetSystemMemoryInfo(&mem_info)) {
args->ThrowError("Unable to retrieve system memory information");
gin_helper::ErrorThrower{isolate}.ThrowError(
"Unable to retrieve system memory information");
return v8::Undefined(isolate);
}

View File

@@ -18,7 +18,6 @@ class FilePath;
}
namespace gin_helper {
class Arguments;
class Dictionary;
template <typename T>
class Promise;
@@ -67,8 +66,7 @@ class ElectronBindings {
static void Hang();
static v8::Local<v8::Value> GetHeapStatistics(v8::Isolate* isolate);
static v8::Local<v8::Value> GetCreationTime(v8::Isolate* isolate);
static v8::Local<v8::Value> GetSystemMemoryInfo(v8::Isolate* isolate,
gin_helper::Arguments* args);
static v8::Local<v8::Value> GetSystemMemoryInfo(v8::Isolate* isolate);
static v8::Local<v8::Promise> GetProcessMemoryInfo(v8::Isolate* isolate);
static v8::Local<v8::Value> GetBlinkMemoryInfo(v8::Isolate* isolate);
static v8::Local<v8::Value> GetCPUUsage(base::ProcessMetrics* metrics,

View File

@@ -6,6 +6,15 @@
// functionality that the PDF Viewer needs from outside the PDF plugin. This API
// is exclusively for the PDF Viewer.
namespace pdfViewerPrivate {
// Must match `SaveRequestType` in `pdf/mojom/pdf.mojom` and
// `tools/typescript/definitions/pdf_viewer_private.d.ts`.
enum SaveRequestType {
ANNOTATION,
ORIGINAL,
EDITED,
SEARCHIFIED
};
// Nearly identical to mimeHandlerPrivate.StreamInfo, but without a mime type
// nor a response header field. Those fields are unused by the PDF viewer.
dictionary StreamInfo {
@@ -52,6 +61,13 @@ namespace pdfViewerPrivate {
DOMString url,
IsAllowedLocalFileAccessCallback callback);
// Sends a request to save the PDF to Google Drive if `saveRequestType` is
// set. Otherwise, if `saveRequestType` is not set, the default action is
// to cancel the existing upload.
static void saveToDrive(
optional SaveRequestType saveRequestType,
optional VoidCallback callback);
// Sets the current tab title to `title` for a full-page PDF.
static void setPdfDocumentTitle(
DOMString title,

View File

@@ -1,26 +0,0 @@
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE.chromium file.
#include <string_view>
#include "shell/common/gin_helper/arguments.h"
#include "v8/include/v8-exception.h"
namespace gin_helper {
void Arguments::ThrowError() const {
// Gin advances |next_| counter when conversion fails while we do not, so we
// have to manually advance the counter here to make gin report error with the
// correct index.
const_cast<Arguments*>(this)->Skip();
gin::Arguments::ThrowError();
}
void Arguments::ThrowError(const std::string_view message) const {
isolate()->ThrowException(
v8::Exception::Error(gin::StringToV8(isolate(), message)));
}
} // namespace gin_helper

View File

@@ -1,53 +0,0 @@
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE.chromium file.
#ifndef ELECTRON_SHELL_COMMON_GIN_HELPER_ARGUMENTS_H_
#define ELECTRON_SHELL_COMMON_GIN_HELPER_ARGUMENTS_H_
#include <string_view>
#include "gin/arguments.h"
namespace gin_helper {
// Provides additional APIs to the gin::Arguments class.
class Arguments : public gin::Arguments {
public:
// Get the next argument, if conversion to T fails then state is unchanged.
//
// This is difference from gin::Arguments::GetNext which always advances the
// |next_| counter no matter whether the conversion succeeds.
template <typename T>
bool GetNext(T* out) {
v8::Local<v8::Value> val = PeekNext();
if (val.IsEmpty())
return false;
if (!gin::ConvertFromV8(isolate(), val, out))
return false;
Skip();
return true;
}
// Gin always returns true when converting V8 value to boolean, we do not want
// this behavior when parsing parameters.
bool GetNext(bool* out) {
v8::Local<v8::Value> val = PeekNext();
if (val.IsEmpty() || !val->IsBoolean())
return false;
*out = val->BooleanValue(isolate());
Skip();
return true;
}
// Throw error with custom error message.
void ThrowError() const;
void ThrowError(std::string_view message) const;
private:
// MUST NOT ADD ANY DATA MEMBER.
};
} // namespace gin_helper
#endif // ELECTRON_SHELL_COMMON_GIN_HELPER_ARGUMENTS_H_

View File

@@ -40,7 +40,7 @@ class GinArgumentsToTuple {
// Invoke a callback with arguments extracted from `args`.
template <typename... Types>
WrappableBase* InvokeFactory(
gin::Arguments* args,
gin::Arguments* const args,
const base::RepeatingCallback<WrappableBase*(Types...)>& callback) {
auto [ok, tup] = GinArgumentsToTuple<Types...>::GetArgs(args);
if (!ok)
@@ -52,10 +52,10 @@ WrappableBase* InvokeFactory(
template <typename Sig>
void InvokeNew(const base::RepeatingCallback<Sig>& factory,
v8::Isolate* isolate,
gin_helper::Arguments* args) {
v8::Isolate* const isolate,
gin::Arguments* const args) {
if (!args->IsConstructCall()) {
args->ThrowError("Requires constructor call");
args->ThrowTypeError("Requires constructor call");
return;
}

View File

@@ -13,7 +13,6 @@
#include "base/memory/raw_ptr.h"
#include "gin/arguments.h"
#include "gin/per_isolate_data.h"
#include "shell/common/gin_helper/arguments.h"
#include "shell/common/gin_helper/destroyable.h"
#include "shell/common/gin_helper/error_thrower.h"
#include "v8/include/v8-context.h"
@@ -154,15 +153,6 @@ inline bool GetNextArgument(gin::Arguments* args,
return true;
}
// Electron-specific GetNextArgument that supports the gin_helper::Arguments.
inline bool GetNextArgument(gin::Arguments* args,
const InvokerOptions& invoker_options,
bool is_first,
gin_helper::Arguments** result) {
*result = static_cast<gin_helper::Arguments*>(args);
return true;
}
// For advanced use cases, we allow callers to request the unparsed Arguments
// object and poke around in it directly.
inline bool GetNextArgument(gin::Arguments* args,

View File

@@ -48,7 +48,7 @@ v8::Local<v8::Object> WrappableBase::GetWrapper() const {
return {};
}
void WrappableBase::InitWithArgs(gin::Arguments* args) {
void WrappableBase::InitWithArgs(const gin::Arguments* const args) {
v8::Local<v8::Object> holder;
args->GetHolder(&holder);
InitWith(args->isolate(), holder);

View File

@@ -51,7 +51,7 @@ class WrappableBase {
virtual void InitWith(v8::Isolate* isolate, v8::Local<v8::Object> wrapper);
// Helper to init with arguments.
void InitWithArgs(gin::Arguments* args);
void InitWithArgs(const gin::Arguments* args);
v8::Global<v8::Object> wrapper_; // Weak

View File

@@ -739,14 +739,13 @@ void ExposeAPI(v8::Isolate* isolate,
v8::Isolate* target_isolate,
v8::Local<v8::Context> target_context,
const std::string& key,
v8::Local<v8::Value> api,
gin_helper::Arguments* args) {
v8::Local<v8::Value> api) {
DCHECK(!target_context.IsEmpty());
v8::Context::Scope target_context_scope(target_context);
gin_helper::Dictionary global(target_isolate, target_context->Global());
if (global.Has(key)) {
args->ThrowError(
gin_helper::ErrorThrower{isolate}.ThrowError(
"Cannot bind an API on top of an existing property on the window "
"object");
return;
@@ -813,8 +812,7 @@ v8::MaybeLocal<v8::Context> GetTargetContext(v8::Isolate* isolate,
void ExposeAPIInWorld(v8::Isolate* isolate,
const int world_id,
const std::string& key,
v8::Local<v8::Value> api,
gin_helper::Arguments* args) {
v8::Local<v8::Value> api) {
TRACE_EVENT2("electron", "ContextBridge::ExposeAPIInWorld", "key", key,
"worldId", world_id);
v8::Local<v8::Context> source_context = isolate->GetCurrentContext();
@@ -825,8 +823,7 @@ void ExposeAPIInWorld(v8::Isolate* isolate,
if (maybe_target_context.IsEmpty() || !target_isolate)
return;
v8::Local<v8::Context> target_context = maybe_target_context.ToLocalChecked();
ExposeAPI(isolate, source_context, target_isolate, target_context, key, api,
args);
ExposeAPI(isolate, source_context, target_isolate, target_context, key, api);
}
gin_helper::Dictionary TraceKeyPath(const gin_helper::Dictionary& start,
@@ -923,24 +920,23 @@ bool OverrideGlobalPropertyFromIsolatedWorld(
}
// Serialize script to be executed in the given world.
v8::Local<v8::Value> ExecuteInWorld(v8::Isolate* isolate,
v8::Local<v8::Value> ExecuteInWorld(v8::Isolate* const isolate,
const int world_id,
gin_helper::Arguments* args) {
gin::Arguments* const args) {
// Get context of caller
v8::Local<v8::Context> source_context = isolate->GetCurrentContext();
// Get execution script argument
gin_helper::Dictionary exec_script;
if (args->Length() >= 1 && !args->GetNext(&exec_script)) {
gin_helper::ErrorThrower(args->isolate()).ThrowError("Invalid script");
args->ThrowTypeError("Invalid script");
return v8::Undefined(isolate);
}
// Get "func" from execution script
v8::Local<v8::Function> func;
if (!exec_script.Get("func", &func)) {
gin_helper::ErrorThrower(isolate).ThrowError(
"Function 'func' is required in script");
args->ThrowTypeError("Function 'func' is required in script");
return v8::Undefined(isolate);
}
@@ -949,7 +945,7 @@ v8::Local<v8::Value> ExecuteInWorld(v8::Isolate* isolate,
v8::Local<v8::Value> args_value;
if (exec_script.Get("args", &args_value)) {
if (!args_value->IsArray()) {
gin_helper::ErrorThrower(isolate).ThrowError("'args' must be an array");
args->ThrowTypeError("'args' must be an array");
return v8::Undefined(isolate);
}
args_array = args_value.As<v8::Array>();
@@ -961,7 +957,7 @@ v8::Local<v8::Value> ExecuteInWorld(v8::Isolate* isolate,
v8::Local<v8::String> serialized_function;
if (!func->FunctionProtoToString(isolate->GetCurrentContext())
.ToLocal(&serialized_function)) {
gin_helper::ErrorThrower(isolate).ThrowError(
gin_helper::ErrorThrower{isolate}.ThrowError(
"Failed to serialize function");
return v8::Undefined(isolate);
}

View File

@@ -18,6 +18,7 @@
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_frame_observer.h"
#include "content/public/renderer/render_frame_visitor.h"
#include "gin/arguments.h"
#include "gin/object_template_builder.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#include "shell/common/api/api.mojom.h"
@@ -637,12 +638,11 @@ class WebFrameRenderer final
return !context->GetContentSecurityPolicy()->ShouldCheckEval();
}
v8::Local<v8::Promise> ExecuteJavaScript(gin::Arguments* gin_args,
// webFrame.executeJavaScript(code[, userGesture][, callback])
v8::Local<v8::Promise> ExecuteJavaScript(gin::Arguments* const args,
const std::u16string& code) {
gin_helper::Arguments* args = static_cast<gin_helper::Arguments*>(gin_args);
v8::Isolate* isolate = args->isolate();
gin_helper::Promise<v8::Local<v8::Value>> promise(isolate);
v8::Isolate* const isolate = args->isolate();
gin_helper::Promise<v8::Local<v8::Value>> promise{isolate};
v8::Local<v8::Promise> handle = promise.GetHandle();
content::RenderFrame* render_frame;
@@ -655,10 +655,14 @@ class WebFrameRenderer final
const blink::WebScriptSource source{blink::WebString::FromUTF16(code)};
bool has_user_gesture = false;
args->GetNext(&has_user_gesture);
if (auto next = args->PeekNext(); !next.IsEmpty() && next->IsBoolean()) {
args->GetNext(&has_user_gesture);
}
ScriptExecutionCallback::CompletionCallback completion_callback;
args->GetNext(&completion_callback);
if (auto next = args->PeekNext(); !next.IsEmpty() && next->IsFunction()) {
args->GetNext(&completion_callback);
}
auto* self = new ScriptExecutionCallback(std::move(promise),
std::move(completion_callback));
@@ -679,14 +683,14 @@ class WebFrameRenderer final
return handle;
}
// executeJavaScriptInIsolatedWorld(
// worldId, scripts[, userGesture][, callback])
v8::Local<v8::Promise> ExecuteJavaScriptInIsolatedWorld(
gin::Arguments* gin_args,
int world_id,
gin::Arguments* const args,
const int world_id,
const std::vector<gin_helper::Dictionary>& scripts) {
gin_helper::Arguments* args = static_cast<gin_helper::Arguments*>(gin_args);
v8::Isolate* isolate = args->isolate();
gin_helper::Promise<v8::Local<v8::Value>> promise(isolate);
v8::Isolate* const isolate = args->isolate();
gin_helper::Promise<v8::Local<v8::Value>> promise{isolate};
v8::Local<v8::Promise> handle = promise.GetHandle();
content::RenderFrame* render_frame;
@@ -698,10 +702,14 @@ class WebFrameRenderer final
}
bool has_user_gesture = false;
args->GetNext(&has_user_gesture);
if (auto next = args->PeekNext(); !next.IsEmpty() && next->IsBoolean()) {
args->GetNext(&has_user_gesture);
}
ScriptExecutionCallback::CompletionCallback completion_callback;
args->GetNext(&completion_callback);
if (auto next = args->PeekNext(); !next.IsEmpty() && next->IsFunction()) {
args->GetNext(&completion_callback);
}
std::vector<blink::WebScriptSource> sources;
sources.reserve(scripts.size());

View File

@@ -4,6 +4,8 @@
#include "electron/shell/renderer/electron_ipc_native.h"
#include <optional>
#include "base/trace_event/trace_event.h"
#include "shell/common/gin_converters/blink_converter.h"
#include "shell/common/gin_converters/value_converter.h"
@@ -45,10 +47,9 @@ void InvokeIpcCallback(v8::Isolate* const isolate,
// Only set up the node::CallbackScope if there's a node environment.
// Sandboxed renderers don't have a node environment.
std::unique_ptr<node::CallbackScope> callback_scope;
if (node::Environment::GetCurrent(context)) {
callback_scope = std::make_unique<node::CallbackScope>(
isolate, ipcNative, node::async_context{0, 0});
std::optional<node::CallbackScope> callback_scope;
if (auto* env = node::Environment::GetCurrent(context)) {
callback_scope.emplace(env, ipcNative, node::async_context{0, 0});
}
auto callback_key = gin::ConvertToV8(isolate, callback_name)

View File

@@ -6,7 +6,6 @@
#include "base/process/process.h"
#include "base/strings/strcat.h"
#include "shell/common/gin_helper/arguments.h"
#include "shell/common/gin_helper/dictionary.h"
#include "shell/common/node_includes.h"
#include "v8/include/v8-context.h"
@@ -34,20 +33,19 @@ v8::Local<v8::Object> GetBindingCache(v8::Isolate* isolate) {
// adapted from node.cc
v8::Local<v8::Value> GetBinding(v8::Isolate* isolate,
v8::Local<v8::String> key,
gin_helper::Arguments* margs) {
v8::Local<v8::String> key) {
v8::Local<v8::Object> exports;
std::string binding_key = gin::V8ToString(isolate, key);
const std::string binding_key = gin::V8ToString(isolate, key);
gin_helper::Dictionary cache(isolate, GetBindingCache(isolate));
if (cache.Get(binding_key, &exports)) {
return exports;
}
auto* mod = node::binding::get_linked_module(binding_key.c_str());
auto* const mod = node::binding::get_linked_module(binding_key.c_str());
if (!mod) {
margs->ThrowError(base::StrCat({"No such binding: ", binding_key}));
gin_helper::ErrorThrower{isolate}.ThrowError(
base::StrCat({"No such binding: ", binding_key}));
return exports;
}

View File

@@ -14,8 +14,7 @@ class Arguments;
namespace electron::preload_utils {
v8::Local<v8::Value> GetBinding(v8::Isolate* isolate,
v8::Local<v8::String> key,
gin_helper::Arguments* margs);
v8::Local<v8::String> key);
v8::Local<v8::Value> CreatePreloadScript(v8::Isolate* isolate,
v8::Local<v8::String> source);