mirror of
https://github.com/electron/electron.git
synced 2026-02-19 03:14:51 -05:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
16a3a456a6 | ||
|
|
7727b7ecba | ||
|
|
595ed3e128 | ||
|
|
fd52089635 | ||
|
|
77bc03e051 | ||
|
|
9f99f4ed0e | ||
|
|
bc27dc4597 | ||
|
|
9048de7cab | ||
|
|
cef4f6a8e7 | ||
|
|
80a4ea2601 | ||
|
|
0b733793c3 | ||
|
|
2b69b32c1d | ||
|
|
63beca3002 | ||
|
|
4cd78dfccc | ||
|
|
38955998f5 | ||
|
|
572a9b16a1 | ||
|
|
12d9fe3ab7 | ||
|
|
32b64170b9 |
2
DEPS
2
DEPS
@@ -2,7 +2,7 @@ gclient_gn_args_from = 'src'
|
||||
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'106.0.5249.61',
|
||||
'106.0.5249.103',
|
||||
'node_version':
|
||||
'v16.16.0',
|
||||
'nan_version':
|
||||
|
||||
@@ -1 +1 @@
|
||||
21.0.1
|
||||
21.1.1
|
||||
@@ -38,7 +38,7 @@ For more installation options and troubleshooting tips, see
|
||||
|
||||
Each Electron release provides binaries for macOS, Windows, and Linux.
|
||||
|
||||
* macOS (El Capitan and up): Electron provides 64-bit Intel and ARM binaries for macOS. Apple Silicon support was added in Electron 11.
|
||||
* macOS (High Sierra and up): Electron provides 64-bit Intel and ARM binaries for macOS. Apple Silicon support was added in Electron 11.
|
||||
* Windows (Windows 7 and up): Electron provides `ia32` (`x86`), `x64` (`amd64`), and `arm64` binaries for Windows. Windows on ARM support was added in Electron 5.0.8.
|
||||
* Linux: The prebuilt binaries of Electron are built on Ubuntu 20.04. They have also been verified to work on:
|
||||
* Ubuntu 14.04 and newer
|
||||
|
||||
@@ -83,7 +83,6 @@ These individual tutorials expand on topics discussed in the guide above.
|
||||
* Electron Releases & Developer Feedback
|
||||
* [Versioning Policy](tutorial/electron-versioning.md)
|
||||
* [Release Timelines](tutorial/electron-timelines.md)
|
||||
* [Testing Widevine CDM](tutorial/testing-widevine-cdm.md)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -45,6 +45,13 @@ returns `null`.
|
||||
Returns `WebContents` | undefined - A WebContents instance with the given ID, or
|
||||
`undefined` if there is no WebContents associated with the given ID.
|
||||
|
||||
### `webContents.fromFrame(frame)`
|
||||
|
||||
* `frame` WebFrameMain
|
||||
|
||||
Returns `WebContents` | undefined - A WebContents instance with the given WebFrameMain, or
|
||||
`undefined` if there is no WebContents associated with the given WebFrameMain.
|
||||
|
||||
### `webContents.fromDevToolsTargetId(targetId)`
|
||||
|
||||
* `targetId` string - The Chrome DevTools Protocol [TargetID](https://chromedevtools.github.io/devtools-protocol/tot/Target/#type-TargetID) associated with the WebContents instance.
|
||||
@@ -2079,6 +2086,11 @@ when the page becomes backgrounded. This also affects the Page Visibility API.
|
||||
|
||||
A [`WebFrameMain`](web-frame-main.md) property that represents the top frame of the page's frame hierarchy.
|
||||
|
||||
#### `contents.opener` _Readonly_
|
||||
|
||||
A [`WebFrameMain`](web-frame-main.md) property that represents the frame that opened this WebContents, either
|
||||
with open(), or by navigating a link with a target attribute.
|
||||
|
||||
[keyboardevent]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent
|
||||
[event-emitter]: https://nodejs.org/api/events.html#events_class_eventemitter
|
||||
[SCA]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm
|
||||
|
||||
@@ -2,5 +2,5 @@ const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('electronAPI', {
|
||||
bluetoothPairingRequest: (callback) => ipcRenderer.on('bluetooth-pairing-request', callback),
|
||||
bluetoothPairingResponse: (response) => ipcRenderer.send('bluetooth-pairing-respnse', response)
|
||||
bluetoothPairingResponse: (response) => ipcRenderer.send('bluetooth-pairing-response', response)
|
||||
})
|
||||
@@ -1,95 +0,0 @@
|
||||
# Testing Widevine CDM
|
||||
|
||||
In Electron you can use the Widevine CDM library shipped with Chrome browser.
|
||||
|
||||
Widevine Content Decryption Modules (CDMs) are how streaming services protect
|
||||
content using HTML5 video to web browsers without relying on an NPAPI plugin
|
||||
like Flash or Silverlight. Widevine support is an alternative solution for
|
||||
streaming services that currently rely on Silverlight for playback of
|
||||
DRM-protected video content. It will allow websites to show DRM-protected video
|
||||
content in Firefox without the use of NPAPI plugins. The Widevine CDM runs in an
|
||||
open-source CDM sandbox providing better user security than NPAPI plugins.
|
||||
|
||||
#### Note on VMP
|
||||
|
||||
As of [`Electron v1.8.0 (Chrome v59)`](https://electronjs.org/releases#1.8.1),
|
||||
the below steps are may only be some of the necessary steps to enable Widevine;
|
||||
any app on or after that version intending to use the Widevine CDM may need to
|
||||
be signed using a license obtained from [Widevine](https://www.widevine.com/)
|
||||
itself.
|
||||
|
||||
Per [Widevine](https://www.widevine.com/):
|
||||
|
||||
> Chrome 59 (and later) includes support for Verified Media Path (VMP). VMP
|
||||
> provides a method to verify the authenticity of a device platform. For browser
|
||||
> deployments, this will provide an additional signal to determine if a
|
||||
> browser-based implementation is reliable and secure.
|
||||
>
|
||||
> The proxy integration guide has been updated with information about VMP and
|
||||
> how to issue licenses.
|
||||
>
|
||||
> Widevine recommends our browser-based integrations (vendors and browser-based
|
||||
> applications) add support for VMP.
|
||||
|
||||
To enable video playback with this new restriction,
|
||||
[castLabs](https://castlabs.com/open-source/downstream/) has created a
|
||||
[fork](https://github.com/castlabs/electron-releases) that has implemented the
|
||||
necessary changes to enable Widevine to be played in an Electron application if
|
||||
one has obtained the necessary licenses from widevine.
|
||||
|
||||
## Getting the library
|
||||
|
||||
Open `chrome://components/` in Chrome browser, find `Widevine Content Decryption Module`
|
||||
and make sure it is up to date, then you can find the library files from the
|
||||
application directory.
|
||||
|
||||
### On Windows
|
||||
|
||||
The library file `widevinecdm.dll` will be under
|
||||
`Program Files(x86)/Google/Chrome/Application/CHROME_VERSION/WidevineCdm/_platform_specific/win_(x86|x64)/`
|
||||
directory.
|
||||
|
||||
### On macOS
|
||||
|
||||
The library file `libwidevinecdm.dylib` will be under
|
||||
`/Applications/Google Chrome.app/Contents/Versions/CHROME_VERSION/Google Chrome Framework.framework/Versions/A/Libraries/WidevineCdm/_platform_specific/mac_(x86|x64)/`
|
||||
directory.
|
||||
|
||||
**Note:** Make sure that chrome version used by Electron is greater than or
|
||||
equal to the `min_chrome_version` value of Chrome's widevine cdm component.
|
||||
The value can be found in `manifest.json` under `WidevineCdm` directory.
|
||||
|
||||
## Using the library
|
||||
|
||||
After getting the library files, you should pass the path to the file
|
||||
with `--widevine-cdm-path` command line switch, and the library's version
|
||||
with `--widevine-cdm-version` switch. The command line switches have to be
|
||||
passed before the `ready` event of `app` module gets emitted.
|
||||
|
||||
Example code:
|
||||
|
||||
```javascript
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
// You have to pass the directory that contains widevine library here, it is
|
||||
// * `libwidevinecdm.dylib` on macOS,
|
||||
// * `widevinecdm.dll` on Windows.
|
||||
app.commandLine.appendSwitch('widevine-cdm-path', '/path/to/widevine_library')
|
||||
// The version of plugin can be got from `chrome://components` page in Chrome.
|
||||
app.commandLine.appendSwitch('widevine-cdm-version', '1.4.8.866')
|
||||
|
||||
let win = null
|
||||
app.whenReady().then(() => {
|
||||
win = new BrowserWindow()
|
||||
win.show()
|
||||
})
|
||||
```
|
||||
|
||||
## Verifying Widevine CDM support
|
||||
|
||||
To verify whether widevine works, you can use following ways:
|
||||
|
||||
* Open https://shaka-player-demo.appspot.com/ and load a manifest that uses
|
||||
`Widevine`.
|
||||
* Open http://www.dash-player.com/demo/drm-test-area/, check whether the page
|
||||
says `bitdash uses Widevine in your browser`, then play the video.
|
||||
@@ -173,13 +173,13 @@ WebContents.prototype.printToPDF = async function (options) {
|
||||
headerTemplate: '',
|
||||
footerTemplate: '',
|
||||
printBackground: false,
|
||||
scale: 1,
|
||||
scale: 1.0,
|
||||
paperWidth: 8.5,
|
||||
paperHeight: 11,
|
||||
marginTop: 0,
|
||||
marginBottom: 0,
|
||||
marginLeft: 0,
|
||||
marginRight: 0,
|
||||
paperHeight: 11.0,
|
||||
marginTop: 0.0,
|
||||
marginBottom: 0.0,
|
||||
marginLeft: 0.0,
|
||||
marginRight: 0.0,
|
||||
pageRanges: '',
|
||||
preferCSSPageSize: false
|
||||
};
|
||||
@@ -209,7 +209,7 @@ WebContents.prototype.printToPDF = async function (options) {
|
||||
if (typeof options.scale !== 'number') {
|
||||
return Promise.reject(new Error('scale must be a Number'));
|
||||
}
|
||||
printSettings.scaleFactor = options.scale;
|
||||
printSettings.scale = options.scale;
|
||||
}
|
||||
|
||||
const { pageSize } = options;
|
||||
@@ -838,6 +838,10 @@ export function fromId (id: string) {
|
||||
return binding.fromId(id);
|
||||
}
|
||||
|
||||
export function fromFrame (frame: Electron.WebFrameMain) {
|
||||
return binding.fromFrame(frame);
|
||||
}
|
||||
|
||||
export function fromDevToolsTargetId (targetId: string) {
|
||||
return binding.fromDevToolsTargetId(targetId);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "electron",
|
||||
"version": "21.0.1",
|
||||
"version": "21.1.1",
|
||||
"repository": "https://github.com/electron/electron",
|
||||
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
|
||||
"devDependencies": {
|
||||
|
||||
@@ -123,3 +123,5 @@ disable_optimization_guide_for_preconnect_feature.patch
|
||||
fix_the_gn_gen_for_components_segmentation_platform.patch
|
||||
fix_crash_loading_non-standard_schemes_in_iframes.patch
|
||||
create_browser_v8_snapshot_file_name_fuse.patch
|
||||
cherry-pick-c83640db21b5.patch
|
||||
fix_on-screen-keyboard_hides_on_input_blur_in_webview.patch
|
||||
|
||||
122
patches/chromium/cherry-pick-c83640db21b5.patch
Normal file
122
patches/chromium/cherry-pick-c83640db21b5.patch
Normal file
@@ -0,0 +1,122 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Attard <samuel.r.attard@gmail.com>
|
||||
Date: Wed, 5 Oct 2022 06:03:23 +0000
|
||||
Subject: build: set DTSDKBuild correctly when generating plist files
|
||||
|
||||
Currently we set DTSDKBuild to the version of the SDK used to build
|
||||
Chromium. This value is supposed to be the build version (this is
|
||||
what xcode sets it to for instance). We read this value out of the
|
||||
SDK directly and use it instead.
|
||||
|
||||
Change-Id: Ieb7990f13095683ad8c026f027b2605ae39523a4
|
||||
|
||||
diff --git a/build/config/mac/mac_sdk.gni b/build/config/mac/mac_sdk.gni
|
||||
index 43577925d2ef9cd79970d8307104e0abc1756583..0819d4cc1b17f216eae8c1a562b0301ba6298d57 100644
|
||||
--- a/build/config/mac/mac_sdk.gni
|
||||
+++ b/build/config/mac/mac_sdk.gni
|
||||
@@ -40,6 +40,11 @@ declare_args() {
|
||||
# will fail.
|
||||
mac_sdk_official_version = "12.3"
|
||||
|
||||
+ # The SDK build version used when making official builds. This is a single
|
||||
+ # exact version found at "System/Library/CoreServices/SystemVersion.plist"
|
||||
+ # inside the SDK.
|
||||
+ mac_sdk_official_build_version = "21E226"
|
||||
+
|
||||
# Production builds should use hermetic Xcode. If you want to do production
|
||||
# builds with system Xcode to test new SDKs, set this.
|
||||
# Don't set this on any bots.
|
||||
@@ -103,11 +108,13 @@ if (use_system_xcode) {
|
||||
find_sdk_args = [
|
||||
"--print_sdk_path",
|
||||
"--print_bin_path",
|
||||
+ "--print_sdk_build",
|
||||
mac_sdk_min,
|
||||
]
|
||||
find_sdk_lines =
|
||||
exec_script("//build/mac/find_sdk.py", find_sdk_args, "list lines")
|
||||
- mac_sdk_version = find_sdk_lines[2]
|
||||
+ mac_sdk_version = find_sdk_lines[3]
|
||||
+ mac_sdk_build_version = find_sdk_lines[2]
|
||||
if (mac_sdk_path == "") {
|
||||
mac_sdk_path = find_sdk_lines[0]
|
||||
mac_bin_path = find_sdk_lines[1]
|
||||
@@ -116,6 +123,7 @@ if (use_system_xcode) {
|
||||
}
|
||||
} else {
|
||||
mac_sdk_version = mac_sdk_official_version
|
||||
+ mac_sdk_build_version = mac_sdk_official_build_version
|
||||
_dev = _hermetic_xcode_path + "/Contents/Developer"
|
||||
_sdk = "MacOSX${mac_sdk_version}.sdk"
|
||||
mac_sdk_path = _dev + "/Platforms/MacOSX.platform/Developer/SDKs/$_sdk"
|
||||
diff --git a/build/config/mac/rules.gni b/build/config/mac/rules.gni
|
||||
index 03073f830401c4891376a3b59e2e7a870e3d34b7..04d403054c1a83fcbbc70be7cfd239ecbec315d3 100644
|
||||
--- a/build/config/mac/rules.gni
|
||||
+++ b/build/config/mac/rules.gni
|
||||
@@ -41,7 +41,7 @@ template("mac_info_plist") {
|
||||
apple_info_plist(target_name) {
|
||||
format = "xml1"
|
||||
extra_substitutions = [
|
||||
- "MAC_SDK_BUILD=$mac_sdk_version",
|
||||
+ "MAC_SDK_BUILD=$mac_sdk_build_version",
|
||||
"MAC_SDK_NAME=$mac_sdk_name$mac_sdk_version",
|
||||
"MACOSX_DEPLOYMENT_TARGET=$mac_deployment_target",
|
||||
"CHROMIUM_MIN_SYSTEM_VERSION=$mac_min_system_version",
|
||||
diff --git a/build/mac/find_sdk.py b/build/mac/find_sdk.py
|
||||
index d86f3109357a9246d570cb02992dc82552ba7c20..b2400c7e8c70957e364444f509880900ce3b641f 100755
|
||||
--- a/build/mac/find_sdk.py
|
||||
+++ b/build/mac/find_sdk.py
|
||||
@@ -24,6 +24,7 @@ Sample Output:
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
+import plistlib
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
@@ -51,6 +52,9 @@ def main():
|
||||
parser.add_option("--print_bin_path",
|
||||
action="store_true", dest="print_bin_path", default=False,
|
||||
help="Additionally print the path the toolchain bin dir.")
|
||||
+ parser.add_option("--print_sdk_build",
|
||||
+ action="store_true", dest="print_sdk_build", default=False,
|
||||
+ help="Additionally print the build version of the SDK.")
|
||||
options, args = parser.parse_args()
|
||||
if len(args) != 1:
|
||||
parser.error('Please specify a minimum SDK version')
|
||||
@@ -80,20 +84,30 @@ def main():
|
||||
if not sdks:
|
||||
raise Exception('No %s+ SDK found' % min_sdk_version)
|
||||
best_sdk = sorted(sdks, key=parse_version)[0]
|
||||
+ sdk_name = 'MacOSX' + best_sdk + '.sdk'
|
||||
+ sdk_path = os.path.join(sdk_dir, sdk_name)
|
||||
|
||||
if options.print_sdk_path:
|
||||
- sdk_name = 'MacOSX' + best_sdk + '.sdk'
|
||||
- print(os.path.join(sdk_dir, sdk_name))
|
||||
+ print(sdk_path)
|
||||
|
||||
if options.print_bin_path:
|
||||
bin_path = 'Toolchains/XcodeDefault.xctoolchain/usr/bin/'
|
||||
print(os.path.join(dev_dir, bin_path))
|
||||
|
||||
- return best_sdk
|
||||
+ if options.print_sdk_build:
|
||||
+ system_version_plist = os.path.join(sdk_path,
|
||||
+ 'System/Library/CoreServices/SystemVersion.plist')
|
||||
+ with open(system_version_plist, 'rb') as f:
|
||||
+ system_version_info = plistlib.load(f)
|
||||
+ if 'ProductBuildVersion' not in system_version_info:
|
||||
+ raise Exception('Failed to determine ProductBuildVersion' +
|
||||
+ 'for SDK at path %s' % system_version_plist)
|
||||
+ print(system_version_info['ProductBuildVersion'])
|
||||
+
|
||||
+ print(best_sdk)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if sys.platform != 'darwin':
|
||||
raise Exception("This script only runs on Mac")
|
||||
- print(main())
|
||||
- sys.exit(0)
|
||||
+ sys.exit(main())
|
||||
@@ -0,0 +1,59 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Kyrylo Hrechykhin <khrechykhin@microsoft.com>
|
||||
Date: Thu, 6 Oct 2022 18:30:53 +0200
|
||||
Subject: fix: on-screen-keyboard hides on input blur in webview
|
||||
|
||||
Changes introduced by this patch fix issue where OSK does not hide on
|
||||
input rendered inside webview is blurred. This patch should be removed
|
||||
when proper fix in chromium repo is available.
|
||||
|
||||
Note: the issue still occurs if input rendered in webview blurred due
|
||||
to touch outside of webview. It is caused by webview implementation
|
||||
details. Specificaly due to webview has its own tree nodes and focused
|
||||
node does not change in this case.
|
||||
|
||||
chromium-bug: https://crbug.com/1369605
|
||||
|
||||
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame.cc b/content/browser/renderer_host/render_widget_host_view_child_frame.cc
|
||||
index 4e6d62be68d59c8a49159fda4d1e68f101a6f0a3..cfd5a01ea84a1f454a5172da3e96e66a50c82939 100644
|
||||
--- a/content/browser/renderer_host/render_widget_host_view_child_frame.cc
|
||||
+++ b/content/browser/renderer_host/render_widget_host_view_child_frame.cc
|
||||
@@ -992,6 +992,12 @@ RenderWidgetHostViewChildFrame::DidUpdateVisualProperties(
|
||||
return viz::ScopedSurfaceIdAllocator(std::move(allocation_task));
|
||||
}
|
||||
|
||||
+void RenderWidgetHostViewChildFrame::FocusedNodeChanged(
|
||||
+ bool is_editable_node,
|
||||
+ const gfx::Rect& node_bounds_in_screen) {
|
||||
+ NOTREACHED();
|
||||
+}
|
||||
+
|
||||
ui::TextInputType RenderWidgetHostViewChildFrame::GetTextInputType() const {
|
||||
if (!text_input_manager_)
|
||||
return ui::TEXT_INPUT_TYPE_NONE;
|
||||
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame.h b/content/browser/renderer_host/render_widget_host_view_child_frame.h
|
||||
index 70b151bcb8e3b1964d316bf2e169dbe0f28f24c7..c3857298974a0c2761efcd3924587607997e3117 100644
|
||||
--- a/content/browser/renderer_host/render_widget_host_view_child_frame.h
|
||||
+++ b/content/browser/renderer_host/render_widget_host_view_child_frame.h
|
||||
@@ -181,6 +181,8 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
|
||||
void DisableAutoResize(const gfx::Size& new_size) override;
|
||||
viz::ScopedSurfaceIdAllocator DidUpdateVisualProperties(
|
||||
const cc::RenderFrameMetadata& metadata) override;
|
||||
+ void FocusedNodeChanged(bool is_editable_node,
|
||||
+ const gfx::Rect& node_bounds_in_screen) override;
|
||||
|
||||
// RenderFrameMetadataProvider::Observer implementation.
|
||||
void OnRenderFrameMetadataChangedBeforeActivation(
|
||||
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
|
||||
index 74993d461cbd0885a709cf8b663b9c69650aa3cf..940045d9bbb62676811f55f5d30a93a352f43ede 100644
|
||||
--- a/content/browser/web_contents/web_contents_impl.cc
|
||||
+++ b/content/browser/web_contents/web_contents_impl.cc
|
||||
@@ -7928,7 +7928,7 @@ void WebContentsImpl::OnFocusedElementChangedInFrame(
|
||||
"WebContentsImpl::OnFocusedElementChangedInFrame",
|
||||
"render_frame_host", frame);
|
||||
RenderWidgetHostViewBase* root_view =
|
||||
- static_cast<RenderWidgetHostViewBase*>(GetRenderWidgetHostView());
|
||||
+ static_cast<RenderWidgetHostViewBase*>(GetTopLevelRenderWidgetHostView());
|
||||
if (!root_view || !frame->GetView())
|
||||
return;
|
||||
// Convert to screen coordinates from window coordinates by adding the
|
||||
@@ -49,3 +49,4 @@ fix_override_createjob_in_node_platform.patch
|
||||
buffer_fix_atob_input_validation.patch
|
||||
v8_api_advance_api_deprecation.patch
|
||||
enable_-wunqualified-std-cast-call.patch
|
||||
fix_expose_the_built-in_electron_module_via_the_esm_loader.patch
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Attard <sattard@salesforce.com>
|
||||
Date: Thu, 6 Oct 2022 04:09:16 -0700
|
||||
Subject: fix: expose the built-in electron module via the ESM loader
|
||||
|
||||
This allows usage of `import { app } from 'electron'` and `import('electron')` natively in the browser + non-sandboxed renderer
|
||||
|
||||
diff --git a/lib/internal/modules/esm/get_format.js b/lib/internal/modules/esm/get_format.js
|
||||
index 5ae0e17dcfb5e24a1a117c33c4d42891686e693f..619fe6cef3b02eb575410225f41d3e7d51f37b93 100644
|
||||
--- a/lib/internal/modules/esm/get_format.js
|
||||
+++ b/lib/internal/modules/esm/get_format.js
|
||||
@@ -31,6 +31,7 @@ const protocolHandlers = ObjectAssign(ObjectCreate(null), {
|
||||
'http:': getHttpProtocolModuleFormat,
|
||||
'https:': getHttpProtocolModuleFormat,
|
||||
'node:'() { return 'builtin'; },
|
||||
+ 'electron:'() { return 'commonjs'; },
|
||||
});
|
||||
|
||||
function getDataProtocolModuleFormat(parsed) {
|
||||
diff --git a/lib/internal/modules/esm/resolve.js b/lib/internal/modules/esm/resolve.js
|
||||
index 3576f75f0a40a64dceb7e2649b344b83ebc04b39..314fbb78931eef154a1e47c655e2d4bafe11bac3 100644
|
||||
--- a/lib/internal/modules/esm/resolve.js
|
||||
+++ b/lib/internal/modules/esm/resolve.js
|
||||
@@ -888,6 +888,8 @@ function parsePackageName(specifier, base) {
|
||||
return { packageName, packageSubpath, isScoped };
|
||||
}
|
||||
|
||||
+const electronSpecifiers = new SafeSet(['electron', 'electron/main', 'electron/common', 'electron/renderer']);
|
||||
+
|
||||
/**
|
||||
* @param {string} specifier
|
||||
* @param {string | URL | undefined} base
|
||||
@@ -898,6 +900,10 @@ function packageResolve(specifier, base, conditions) {
|
||||
if (NativeModule.canBeRequiredByUsers(specifier))
|
||||
return new URL('node:' + specifier);
|
||||
|
||||
+ if (electronSpecifiers.has(specifier)) {
|
||||
+ return new URL('electron:electron');
|
||||
+ }
|
||||
+
|
||||
const { packageName, packageSubpath, isScoped } =
|
||||
parsePackageName(specifier, base);
|
||||
|
||||
@@ -1099,7 +1105,7 @@ function checkIfDisallowedImport(specifier, parsed, parsedParentURL) {
|
||||
|
||||
function throwIfUnsupportedURLProtocol(url) {
|
||||
if (url.protocol !== 'file:' && url.protocol !== 'data:' &&
|
||||
- url.protocol !== 'node:') {
|
||||
+ url.protocol !== 'node:' && url.protocol !== 'electron:') {
|
||||
throw new ERR_UNSUPPORTED_ESM_URL_SCHEME(url);
|
||||
}
|
||||
}
|
||||
diff --git a/lib/internal/modules/esm/translators.js b/lib/internal/modules/esm/translators.js
|
||||
index d7f4c7edec63d3ce500955a37c6eac00e3e524fd..b97cac53365b121f8e232f0085ff166511c3dda3 100644
|
||||
--- a/lib/internal/modules/esm/translators.js
|
||||
+++ b/lib/internal/modules/esm/translators.js
|
||||
@@ -155,7 +155,7 @@ translators.set('commonjs', async function commonjsStrategy(url, source,
|
||||
|
||||
if (!cjsParse) await initCJSParse();
|
||||
const { module, exportNames } = cjsPreparseModuleExports(filename);
|
||||
- const namesWithDefault = exportNames.has('default') ?
|
||||
+ const namesWithDefault = filename === 'electron' ? ['default', ...Object.keys(module.exports)] : exportNames.has('default') ?
|
||||
[...exportNames] : ['default', ...exportNames];
|
||||
|
||||
return new ModuleWrap(url, undefined, namesWithDefault, function() {
|
||||
@@ -174,7 +174,7 @@ translators.set('commonjs', async function commonjsStrategy(url, source,
|
||||
}
|
||||
}
|
||||
|
||||
- for (const exportName of exportNames) {
|
||||
+ for (const exportName of namesWithDefault) {
|
||||
if (!ObjectPrototypeHasOwnProperty(exports, exportName) ||
|
||||
exportName === 'default')
|
||||
continue;
|
||||
diff --git a/lib/internal/url.js b/lib/internal/url.js
|
||||
index 939374a495856cf2b9c573fa98dc1895eee5e143..c37258ac29e8b7558c1f9a2af7ba6bdd0eab1355 100644
|
||||
--- a/lib/internal/url.js
|
||||
+++ b/lib/internal/url.js
|
||||
@@ -1418,6 +1418,8 @@ function fileURLToPath(path) {
|
||||
path = new URL(path);
|
||||
else if (!isURLInstance(path))
|
||||
throw new ERR_INVALID_ARG_TYPE('path', ['string', 'URL'], path);
|
||||
+ if (path.protocol === 'electron:')
|
||||
+ return 'electron';
|
||||
if (path.protocol !== 'file:')
|
||||
throw new ERR_INVALID_URL_SCHEME('file');
|
||||
return isWindows ? getPathFromURLWin32(path) : getPathFromURLPosix(path);
|
||||
@@ -316,9 +316,6 @@ absl::optional<int> ElectronMainDelegate::BasicStartupComplete() {
|
||||
::switches::kDisableGpuMemoryBufferCompositorResources);
|
||||
#endif
|
||||
|
||||
content_client_ = std::make_unique<ElectronContentClient>();
|
||||
SetContentClient(content_client_.get());
|
||||
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
@@ -437,6 +434,11 @@ base::StringPiece ElectronMainDelegate::GetBrowserV8SnapshotFilename() {
|
||||
return ContentMainDelegate::GetBrowserV8SnapshotFilename();
|
||||
}
|
||||
|
||||
content::ContentClient* ElectronMainDelegate::CreateContentClient() {
|
||||
content_client_ = std::make_unique<ElectronContentClient>();
|
||||
return content_client_.get();
|
||||
}
|
||||
|
||||
content::ContentBrowserClient*
|
||||
ElectronMainDelegate::CreateContentBrowserClient() {
|
||||
browser_client_ = std::make_unique<ElectronBrowserClient>();
|
||||
|
||||
@@ -38,6 +38,7 @@ class ElectronMainDelegate : public content::ContentMainDelegate {
|
||||
void PreSandboxStartup() override;
|
||||
void SandboxInitialized(const std::string& process_type) override;
|
||||
absl::optional<int> PreBrowserMain() override;
|
||||
content::ContentClient* CreateContentClient() override;
|
||||
content::ContentBrowserClient* CreateContentBrowserClient() override;
|
||||
content::ContentGpuClient* CreateContentGpuClient() override;
|
||||
content::ContentRendererClient* CreateContentRendererClient() override;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "shell/browser/api/electron_api_desktop_capturer.h"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
@@ -24,12 +25,125 @@
|
||||
#include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
|
||||
#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
|
||||
|
||||
#if defined(USE_OZONE)
|
||||
#include "ui/ozone/buildflags.h"
|
||||
#if BUILDFLAG(OZONE_PLATFORM_X11)
|
||||
#define USE_OZONE_PLATFORM_X11
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
#include "third_party/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h"
|
||||
#include "third_party/webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h"
|
||||
#include "ui/display/win/display_info.h"
|
||||
#elif BUILDFLAG(IS_LINUX)
|
||||
#if defined(USE_OZONE_PLATFORM_X11)
|
||||
#include "base/logging.h"
|
||||
#include "ui/base/x/x11_display_util.h"
|
||||
#include "ui/base/x/x11_util.h"
|
||||
#include "ui/display/util/edid_parser.h" // nogncheck
|
||||
#include "ui/gfx/x/randr.h"
|
||||
#include "ui/gfx/x/x11_atom_cache.h"
|
||||
#include "ui/gfx/x/xproto_util.h"
|
||||
#endif // defined(USE_OZONE_PLATFORM_X11)
|
||||
#endif // BUILDFLAG(IS_WIN)
|
||||
|
||||
#if BUILDFLAG(IS_LINUX)
|
||||
// Private function in ui/base/x/x11_display_util.cc
|
||||
std::map<x11::RandR::Output, int> GetMonitors(int version,
|
||||
x11::RandR* randr,
|
||||
x11::Window window) {
|
||||
std::map<x11::RandR::Output, int> output_to_monitor;
|
||||
if (version >= 105) {
|
||||
if (auto reply = randr->GetMonitors({window}).Sync()) {
|
||||
for (size_t monitor = 0; monitor < reply->monitors.size(); monitor++) {
|
||||
for (x11::RandR::Output output : reply->monitors[monitor].outputs)
|
||||
output_to_monitor[output] = monitor;
|
||||
}
|
||||
}
|
||||
}
|
||||
return output_to_monitor;
|
||||
}
|
||||
// Get the EDID data from the |output| and stores to |edid|.
|
||||
// Private function in ui/base/x/x11_display_util.cc
|
||||
std::vector<uint8_t> GetEDIDProperty(x11::RandR* randr,
|
||||
x11::RandR::Output output) {
|
||||
constexpr const char kRandrEdidProperty[] = "EDID";
|
||||
auto future = randr->GetOutputProperty(x11::RandR::GetOutputPropertyRequest{
|
||||
.output = output,
|
||||
.property = x11::GetAtom(kRandrEdidProperty),
|
||||
.long_length = 128});
|
||||
auto response = future.Sync();
|
||||
std::vector<uint8_t> edid;
|
||||
if (response && response->format == 8 && response->type != x11::Atom::None)
|
||||
edid = std::move(response->data);
|
||||
return edid;
|
||||
}
|
||||
|
||||
// Find the mapping from monitor name atom to the display identifier
|
||||
// that the screen API uses. Based on the logic in BuildDisplaysFromXRandRInfo
|
||||
// in ui/base/x/x11_display_util.cc
|
||||
std::map<int32_t, uint32_t> MonitorAtomIdToDisplayId() {
|
||||
auto* connection = x11::Connection::Get();
|
||||
auto& randr = connection->randr();
|
||||
auto x_root_window = ui::GetX11RootWindow();
|
||||
int version = ui::GetXrandrVersion();
|
||||
|
||||
std::map<int32_t, uint32_t> monitor_atom_to_display;
|
||||
|
||||
auto resources = randr.GetScreenResourcesCurrent({x_root_window}).Sync();
|
||||
if (!resources) {
|
||||
LOG(ERROR) << "XRandR returned no displays; don't know how to map ids";
|
||||
return monitor_atom_to_display;
|
||||
}
|
||||
|
||||
std::map<x11::RandR::Output, int> output_to_monitor =
|
||||
GetMonitors(version, &randr, x_root_window);
|
||||
auto monitors_reply = randr.GetMonitors({x_root_window}).Sync();
|
||||
|
||||
for (size_t i = 0; i < resources->outputs.size(); i++) {
|
||||
x11::RandR::Output output_id = resources->outputs[i];
|
||||
auto output_info =
|
||||
randr.GetOutputInfo({output_id, resources->config_timestamp}).Sync();
|
||||
if (!output_info)
|
||||
continue;
|
||||
|
||||
if (output_info->connection != x11::RandR::RandRConnection::Connected)
|
||||
continue;
|
||||
|
||||
if (output_info->crtc == static_cast<x11::RandR::Crtc>(0))
|
||||
continue;
|
||||
|
||||
auto crtc =
|
||||
randr.GetCrtcInfo({output_info->crtc, resources->config_timestamp})
|
||||
.Sync();
|
||||
if (!crtc)
|
||||
continue;
|
||||
display::EdidParser edid_parser(
|
||||
GetEDIDProperty(&randr, static_cast<x11::RandR::Output>(output_id)));
|
||||
auto output_32 = static_cast<uint32_t>(output_id);
|
||||
int64_t display_id =
|
||||
output_32 > 0xff ? 0 : edid_parser.GetIndexBasedDisplayId(output_32);
|
||||
// It isn't ideal, but if we can't parse the EDID data, fall back on the
|
||||
// display number.
|
||||
if (!display_id)
|
||||
display_id = i;
|
||||
|
||||
// Find the mapping between output identifier and the monitor name atom
|
||||
// Note this isn't the atom string, but the numeric atom identifier,
|
||||
// since this is what the WebRTC system uses as the display identifier
|
||||
auto output_monitor_iter = output_to_monitor.find(output_id);
|
||||
if (output_monitor_iter != output_to_monitor.end()) {
|
||||
x11::Atom atom =
|
||||
monitors_reply->monitors[output_monitor_iter->second].name;
|
||||
monitor_atom_to_display[static_cast<int32_t>(atom)] = display_id;
|
||||
}
|
||||
}
|
||||
|
||||
return monitor_atom_to_display;
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace gin {
|
||||
|
||||
template <>
|
||||
@@ -178,10 +292,22 @@ void DesktopCapturer::UpdateSourcesList(DesktopMediaList* list) {
|
||||
for (auto& source : screen_sources) {
|
||||
source.display_id = base::NumberToString(source.media_list_source.id.id);
|
||||
}
|
||||
#elif BUILDFLAG(IS_LINUX)
|
||||
#if defined(USE_OZONE_PLATFORM_X11)
|
||||
// On Linux, with X11, the source id is the numeric value of the
|
||||
// display name atom and the display id is either the EDID or the
|
||||
// loop index when that display was found (see
|
||||
// BuildDisplaysFromXRandRInfo in ui/base/x/x11_display_util.cc)
|
||||
std::map<int32_t, uint32_t> monitor_atom_to_display_id =
|
||||
MonitorAtomIdToDisplayId();
|
||||
for (auto& source : screen_sources) {
|
||||
auto display_id_iter =
|
||||
monitor_atom_to_display_id.find(source.media_list_source.id.id);
|
||||
if (display_id_iter != monitor_atom_to_display_id.end())
|
||||
source.display_id = base::NumberToString(display_id_iter->second);
|
||||
}
|
||||
#endif // defined(USE_OZONE_PLATFORM_X11)
|
||||
#endif // BUILDFLAG(IS_WIN)
|
||||
// TODO(ajmacd): Add Linux support. The IDs across APIs differ but Chrome
|
||||
// only supports capturing the entire desktop on Linux. Revisit this if
|
||||
// individual screen support is added.
|
||||
std::move(screen_sources.begin(), screen_sources.end(),
|
||||
std::back_inserter(captured_sources_));
|
||||
}
|
||||
|
||||
@@ -2821,12 +2821,12 @@ v8::Local<v8::Promise> WebContents::PrintToPDF(const base::Value& settings) {
|
||||
settings.GetDict().FindBool("displayHeaderFooter");
|
||||
auto print_background = settings.GetDict().FindBool("shouldPrintBackgrounds");
|
||||
auto scale = settings.GetDict().FindDouble("scale");
|
||||
auto paper_width = settings.GetDict().FindInt("paperWidth");
|
||||
auto paper_height = settings.GetDict().FindInt("paperHeight");
|
||||
auto margin_top = settings.GetDict().FindIntByDottedPath("margins.top");
|
||||
auto margin_bottom = settings.GetDict().FindIntByDottedPath("margins.bottom");
|
||||
auto margin_left = settings.GetDict().FindIntByDottedPath("margins.left");
|
||||
auto margin_right = settings.GetDict().FindIntByDottedPath("margins.right");
|
||||
auto paper_width = settings.GetDict().FindDouble("paperWidth");
|
||||
auto paper_height = settings.GetDict().FindDouble("paperHeight");
|
||||
auto margin_top = settings.GetDict().FindDouble("marginTop");
|
||||
auto margin_bottom = settings.GetDict().FindDouble("marginBottom");
|
||||
auto margin_left = settings.GetDict().FindDouble("marginLeft");
|
||||
auto margin_right = settings.GetDict().FindDouble("marginRight");
|
||||
auto page_ranges = *settings.GetDict().FindString("pageRanges");
|
||||
auto header_template = *settings.GetDict().FindString("headerTemplate");
|
||||
auto footer_template = *settings.GetDict().FindString("footerTemplate");
|
||||
@@ -3435,6 +3435,10 @@ content::RenderFrameHost* WebContents::MainFrame() {
|
||||
return web_contents()->GetPrimaryMainFrame();
|
||||
}
|
||||
|
||||
content::RenderFrameHost* WebContents::Opener() {
|
||||
return web_contents()->GetOpener();
|
||||
}
|
||||
|
||||
void WebContents::NotifyUserActivation() {
|
||||
content::RenderFrameHost* frame = web_contents()->GetPrimaryMainFrame();
|
||||
if (frame)
|
||||
@@ -4045,6 +4049,7 @@ v8::Local<v8::ObjectTemplate> WebContents::FillObjectTemplate(
|
||||
.SetProperty("devToolsWebContents", &WebContents::DevToolsWebContents)
|
||||
.SetProperty("debugger", &WebContents::Debugger)
|
||||
.SetProperty("mainFrame", &WebContents::MainFrame)
|
||||
.SetProperty("opener", &WebContents::Opener)
|
||||
.Build();
|
||||
}
|
||||
|
||||
@@ -4159,6 +4164,7 @@ namespace {
|
||||
|
||||
using electron::api::GetAllWebContents;
|
||||
using electron::api::WebContents;
|
||||
using electron::api::WebFrameMain;
|
||||
|
||||
gin::Handle<WebContents> WebContentsFromID(v8::Isolate* isolate, int32_t id) {
|
||||
WebContents* contents = WebContents::FromID(id);
|
||||
@@ -4166,6 +4172,15 @@ gin::Handle<WebContents> WebContentsFromID(v8::Isolate* isolate, int32_t id) {
|
||||
: gin::Handle<WebContents>();
|
||||
}
|
||||
|
||||
gin::Handle<WebContents> WebContentsFromFrame(v8::Isolate* isolate,
|
||||
WebFrameMain* web_frame) {
|
||||
content::RenderFrameHost* rfh = web_frame->render_frame_host();
|
||||
content::WebContents* source = content::WebContents::FromRenderFrameHost(rfh);
|
||||
WebContents* contents = WebContents::From(source);
|
||||
return contents ? gin::CreateHandle(isolate, contents)
|
||||
: gin::Handle<WebContents>();
|
||||
}
|
||||
|
||||
gin::Handle<WebContents> WebContentsFromDevToolsTargetID(
|
||||
v8::Isolate* isolate,
|
||||
std::string target_id) {
|
||||
@@ -4194,6 +4209,7 @@ void Initialize(v8::Local<v8::Object> exports,
|
||||
gin_helper::Dictionary dict(isolate, exports);
|
||||
dict.Set("WebContents", WebContents::GetConstructor(context));
|
||||
dict.SetMethod("fromId", &WebContentsFromID);
|
||||
dict.SetMethod("fromFrame", &WebContentsFromFrame);
|
||||
dict.SetMethod("fromDevToolsTargetId", &WebContentsFromDevToolsTargetID);
|
||||
dict.SetMethod("getAllWebContents", &GetAllWebContentsAsV8);
|
||||
}
|
||||
|
||||
@@ -332,6 +332,7 @@ class WebContents : public ExclusiveAccessContext,
|
||||
v8::Local<v8::Value> DevToolsWebContents(v8::Isolate* isolate);
|
||||
v8::Local<v8::Value> Debugger(v8::Isolate* isolate);
|
||||
content::RenderFrameHost* MainFrame();
|
||||
content::RenderFrameHost* Opener();
|
||||
|
||||
WebContentsZoomController* GetZoomController() { return zoom_controller_; }
|
||||
|
||||
|
||||
@@ -50,8 +50,8 @@ END
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 21,0,1,0
|
||||
PRODUCTVERSION 21,0,1,0
|
||||
FILEVERSION 21,1,1,0
|
||||
PRODUCTVERSION 21,1,1,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@@ -68,12 +68,12 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "GitHub, Inc."
|
||||
VALUE "FileDescription", "Electron"
|
||||
VALUE "FileVersion", "21.0.1"
|
||||
VALUE "FileVersion", "21.1.1"
|
||||
VALUE "InternalName", "electron.exe"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
|
||||
VALUE "OriginalFilename", "electron.exe"
|
||||
VALUE "ProductName", "Electron"
|
||||
VALUE "ProductVersion", "21.0.1"
|
||||
VALUE "ProductVersion", "21.1.1"
|
||||
VALUE "SquirrelAwareVersion", "1"
|
||||
END
|
||||
END
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
|
||||
- (NSDragOperation)draggingSession:(NSDraggingSession*)session
|
||||
sourceOperationMaskForDraggingContext:(NSDraggingContext)context {
|
||||
return NSDragOperationEvery;
|
||||
return context == NSDraggingContextOutsideApplication ? NSDragOperationCopy
|
||||
: NSDragOperationEvery;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -70,7 +71,7 @@ void DragFileItems(const std::vector<base::FilePath>& files,
|
||||
NSEvent* dragEvent =
|
||||
[NSEvent mouseEventWithType:NSEventTypeLeftMouseDragged
|
||||
location:position
|
||||
modifierFlags:NSEventMaskLeftMouseDragged
|
||||
modifierFlags:0
|
||||
timestamp:eventTime
|
||||
windowNumber:[[native_view window] windowNumber]
|
||||
context:nil
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Modified from chrome/browser/ui/views/frame/windows_10_caption_button.cc
|
||||
// Modified from chrome/browser/ui/views/frame/windows_caption_button.cc
|
||||
|
||||
#include "shell/browser/ui/views/win_caption_button.h"
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ void DrawRect(gfx::Canvas* canvas,
|
||||
|
||||
void DrawRoundRect(gfx::Canvas* canvas,
|
||||
const gfx::Rect& rect,
|
||||
int radius,
|
||||
float radius,
|
||||
const cc::PaintFlags& flags) {
|
||||
gfx::RectF rect_f(rect);
|
||||
float stroke_half_width = flags.getStrokeWidth() / 2;
|
||||
@@ -74,7 +74,7 @@ void WinIconPainter::PaintMaximizeIcon(gfx::Canvas* canvas,
|
||||
void WinIconPainter::PaintRestoreIcon(gfx::Canvas* canvas,
|
||||
const gfx::Rect& symbol_rect,
|
||||
const cc::PaintFlags& flags) {
|
||||
const int separation = std::floor(2 * canvas->image_scale());
|
||||
const int separation = base::ClampFloor(2 * canvas->image_scale());
|
||||
gfx::Rect icon_rect = symbol_rect;
|
||||
icon_rect.Inset(gfx::Insets::TLBR(separation, 0, 0, separation));
|
||||
|
||||
@@ -113,14 +113,14 @@ void Win11IconPainter::PaintMaximizeIcon(gfx::Canvas* canvas,
|
||||
cc::PaintFlags paint_flags = flags;
|
||||
paint_flags.setAntiAlias(true);
|
||||
|
||||
const float corner_radius = 2 * canvas->image_scale();
|
||||
const float corner_radius = canvas->image_scale();
|
||||
DrawRoundRect(canvas, symbol_rect, corner_radius, flags);
|
||||
}
|
||||
|
||||
void Win11IconPainter::PaintRestoreIcon(gfx::Canvas* canvas,
|
||||
const gfx::Rect& symbol_rect,
|
||||
const cc::PaintFlags& flags) {
|
||||
const int separation = std::floor(2 * canvas->image_scale());
|
||||
const int separation = base::ClampFloor(2 * canvas->image_scale());
|
||||
gfx::Rect icon_rect = symbol_rect;
|
||||
icon_rect.Inset(gfx::Insets::TLBR(separation, 0, 0, separation));
|
||||
|
||||
@@ -128,14 +128,11 @@ void Win11IconPainter::PaintRestoreIcon(gfx::Canvas* canvas,
|
||||
paint_flags.setAntiAlias(true);
|
||||
|
||||
// Bottom left ("in front") rounded square.
|
||||
const float bottom_rect_radius = 1 * canvas->image_scale();
|
||||
const float bottom_rect_radius = canvas->image_scale();
|
||||
DrawRoundRect(canvas, icon_rect, bottom_rect_radius, flags);
|
||||
|
||||
// Top right ("behind") top+right edges of rounded square (2.5x).
|
||||
icon_rect.Offset(separation, -separation);
|
||||
// Apply inset to left+bottom edges since we don't draw arcs for those edges
|
||||
constexpr int top_rect_inset = 1;
|
||||
icon_rect.Inset(gfx::Insets::TLBR(0, top_rect_inset, top_rect_inset, 0));
|
||||
|
||||
const float top_rect_radius = 2.5f * canvas->image_scale();
|
||||
DrawRoundRectEdges(canvas, icon_rect, top_rect_radius, flags);
|
||||
|
||||
@@ -492,19 +492,22 @@ node::Environment* NodeBindings::CreateEnvironment(
|
||||
flags |= node::EnvironmentFlags::kNoStartDebugSignalHandler;
|
||||
}
|
||||
|
||||
v8::TryCatch try_catch(isolate);
|
||||
env = node::CreateEnvironment(
|
||||
isolate_data_, context, args, exec_args,
|
||||
static_cast<node::EnvironmentFlags::Flags>(flags));
|
||||
{
|
||||
v8::TryCatch try_catch(isolate);
|
||||
env = node::CreateEnvironment(
|
||||
isolate_data_, context, args, exec_args,
|
||||
static_cast<node::EnvironmentFlags::Flags>(flags));
|
||||
|
||||
if (try_catch.HasCaught()) {
|
||||
std::string err_msg =
|
||||
"Failed to initialize node environment in process: " + process_type;
|
||||
v8::Local<v8::Message> message = try_catch.Message();
|
||||
std::string msg;
|
||||
if (!message.IsEmpty() && gin::ConvertFromV8(isolate, message->Get(), &msg))
|
||||
err_msg += " , with error: " + msg;
|
||||
LOG(ERROR) << err_msg;
|
||||
if (try_catch.HasCaught()) {
|
||||
std::string err_msg =
|
||||
"Failed to initialize node environment in process: " + process_type;
|
||||
v8::Local<v8::Message> message = try_catch.Message();
|
||||
std::string msg;
|
||||
if (!message.IsEmpty() &&
|
||||
gin::ConvertFromV8(isolate, message->Get(), &msg))
|
||||
err_msg += " , with error: " + msg;
|
||||
LOG(ERROR) << err_msg;
|
||||
}
|
||||
}
|
||||
|
||||
DCHECK(env);
|
||||
|
||||
@@ -6,7 +6,7 @@ import * as http from 'http';
|
||||
import { BrowserWindow, ipcMain, webContents, session, WebContents, app, BrowserView } from 'electron/main';
|
||||
import { emittedOnce } from './events-helpers';
|
||||
import { closeAllWindows } from './window-helpers';
|
||||
import { ifdescribe, delay, defer } from './spec-helpers';
|
||||
import { ifdescribe, delay, defer, waitUntil } from './spec-helpers';
|
||||
|
||||
const pdfjs = require('pdfjs-dist');
|
||||
const fixturesPath = path.resolve(__dirname, '..', 'spec', 'fixtures');
|
||||
@@ -46,6 +46,28 @@ describe('webContents module', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('fromFrame()', () => {
|
||||
it('returns WebContents for mainFrame', () => {
|
||||
const contents = (webContents as any).create() as WebContents;
|
||||
expect(webContents.fromFrame(contents.mainFrame)).to.equal(contents);
|
||||
});
|
||||
it('returns undefined for disposed frame', async () => {
|
||||
const contents = (webContents as any).create() as WebContents;
|
||||
const { mainFrame } = contents;
|
||||
contents.destroy();
|
||||
await waitUntil(() => typeof webContents.fromFrame(mainFrame) === 'undefined');
|
||||
});
|
||||
it('throws when passing invalid argument', async () => {
|
||||
let errored = false;
|
||||
try {
|
||||
webContents.fromFrame({} as any);
|
||||
} catch {
|
||||
errored = true;
|
||||
}
|
||||
expect(errored).to.be.true();
|
||||
});
|
||||
});
|
||||
|
||||
describe('fromDevToolsTargetId()', () => {
|
||||
it('returns WebContents for attached DevTools target', async () => {
|
||||
const w = new BrowserWindow({ show: false });
|
||||
@@ -1281,6 +1303,54 @@ describe('webContents module', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('opener api', () => {
|
||||
afterEach(closeAllWindows);
|
||||
it('can get opener with window.open()', async () => {
|
||||
const w = new BrowserWindow({ show: false, webPreferences: { sandbox: true } });
|
||||
await w.loadURL('about:blank');
|
||||
const childPromise = emittedOnce(w.webContents, 'did-create-window');
|
||||
w.webContents.executeJavaScript('window.open("about:blank")', true);
|
||||
const [childWindow] = await childPromise;
|
||||
expect(childWindow.webContents.opener).to.equal(w.webContents.mainFrame);
|
||||
});
|
||||
it('has no opener when using "noopener"', async () => {
|
||||
const w = new BrowserWindow({ show: false, webPreferences: { sandbox: true } });
|
||||
await w.loadURL('about:blank');
|
||||
const childPromise = emittedOnce(w.webContents, 'did-create-window');
|
||||
w.webContents.executeJavaScript('window.open("about:blank", undefined, "noopener")', true);
|
||||
const [childWindow] = await childPromise;
|
||||
expect(childWindow.webContents.opener).to.be.null();
|
||||
});
|
||||
it('can get opener with a[target=_blank][rel=opener]', async () => {
|
||||
const w = new BrowserWindow({ show: false, webPreferences: { sandbox: true } });
|
||||
await w.loadURL('about:blank');
|
||||
const childPromise = emittedOnce(w.webContents, 'did-create-window');
|
||||
w.webContents.executeJavaScript(`(function() {
|
||||
const a = document.createElement('a');
|
||||
a.target = '_blank';
|
||||
a.rel = 'opener';
|
||||
a.href = 'about:blank';
|
||||
a.click();
|
||||
}())`, true);
|
||||
const [childWindow] = await childPromise;
|
||||
expect(childWindow.webContents.opener).to.equal(w.webContents.mainFrame);
|
||||
});
|
||||
it('has no opener with a[target=_blank][rel=noopener]', async () => {
|
||||
const w = new BrowserWindow({ show: false, webPreferences: { sandbox: true } });
|
||||
await w.loadURL('about:blank');
|
||||
const childPromise = emittedOnce(w.webContents, 'did-create-window');
|
||||
w.webContents.executeJavaScript(`(function() {
|
||||
const a = document.createElement('a');
|
||||
a.target = '_blank';
|
||||
a.rel = 'noopener';
|
||||
a.href = 'about:blank';
|
||||
a.click();
|
||||
}())`, true);
|
||||
const [childWindow] = await childPromise;
|
||||
expect(childWindow.webContents.opener).to.be.null();
|
||||
});
|
||||
});
|
||||
|
||||
describe('render view deleted events', () => {
|
||||
let server: http.Server;
|
||||
let serverUrl: string;
|
||||
|
||||
@@ -183,4 +183,16 @@ describe('modules support', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('esm', () => {
|
||||
it('can load the built-in "electron" module via ESM import', async () => {
|
||||
await expect(import('electron')).to.eventually.be.ok();
|
||||
});
|
||||
|
||||
it('the built-in "electron" module loaded via ESM import has the same exports as the CJS module', async () => {
|
||||
const esmElectron = await import('electron');
|
||||
const cjsElectron = require('electron');
|
||||
expect(Object.keys(esmElectron)).to.deep.equal(Object.keys(cjsElectron));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user