mirror of
https://github.com/electron/electron.git
synced 2026-04-10 03:01:51 -04:00
Compare commits
19 Commits
v24.1.1
...
v25.0.0-ni
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
17ea7f42fc | ||
|
|
d0cf9c4b08 | ||
|
|
fe7c535a3f | ||
|
|
8eee4f2df1 | ||
|
|
4d6f230d21 | ||
|
|
889859df5b | ||
|
|
cb03c6516b | ||
|
|
2e8114aea3 | ||
|
|
a38b711fb1 | ||
|
|
3972073116 | ||
|
|
8c986ff194 | ||
|
|
71944f2c3b | ||
|
|
8b3e498436 | ||
|
|
cf80994729 | ||
|
|
01f1522cbd | ||
|
|
a37f572388 | ||
|
|
3180312595 | ||
|
|
ff60fe25c1 | ||
|
|
12ed401ca2 |
@@ -6,7 +6,7 @@
|
||||
|
||||
version: 1.0.{build}
|
||||
build_cloud: electronhq-16-core
|
||||
image: e-110.0.5451.0
|
||||
image: e-111.0.5560.0-node18
|
||||
environment:
|
||||
GIT_CACHE_PATH: C:\Users\appveyor\libcc_cache
|
||||
ELECTRON_OUT_DIR: Default
|
||||
@@ -16,22 +16,58 @@ environment:
|
||||
GOMA_FALLBACK_ON_AUTH_FAILURE: true
|
||||
DEPOT_TOOLS_WIN_TOOLCHAIN: 0
|
||||
PYTHONIOENCODING: UTF-8
|
||||
# Uncomment these lines and set APPVEYOR_RDP_PASSWORD in project settings to enable RDP before bake begins
|
||||
# install:
|
||||
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
|
||||
# The following lines are needed when baking from a completely new image (eg MicrosoftWindowsServer:WindowsServer:2019-Datacenter:latest via image: base-windows-server2019)
|
||||
# init:
|
||||
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
# - appveyor version
|
||||
# - ps: $ErrorActionPreference = 'Stop'
|
||||
# - ps: 'Write-Host "OS Build: $((Get-CimInstance Win32_OperatingSystem).BuildNumber)"'
|
||||
|
||||
# clone_folder: '%USERPROFILE%\image-bake-scripts'
|
||||
|
||||
# clone_script:
|
||||
# - ps: Invoke-WebRequest "https://github.com/appveyor/build-images/archive/1f90d94e74c8243c909a09b994e527584dfcb838.zip" -OutFile "$env:temp\scripts.zip"
|
||||
# - ps: Expand-Archive -Path "$env:temp\scripts.zip" -DestinationPath "$env:temp\scripts" -Force
|
||||
# - ps: Copy-Item -Path "$env:temp\scripts\build-images-1f90d94e74c8243c909a09b994e527584dfcb838\scripts\Windows\*" -Destination $env:APPVEYOR_BUILD_FOLDER -Recurse
|
||||
|
||||
build_script:
|
||||
# Uncomment/change the following line if the hard drive/partition size needs to change
|
||||
# - ps: Resize-Partition -DriveLetter C -Size (256GB) # ensure initial partition size
|
||||
# The following lines are needed when baking from a completely new image (eg MicrosoftWindowsServer:WindowsServer:2019-Datacenter:latest via image: base-windows-server2019)
|
||||
# - ps: .\init_server.ps1
|
||||
# - ps: .\extend_system_volume.ps1
|
||||
|
||||
# # Restart VM
|
||||
# - ps: Start-Sleep -s 5; Restart-Computer
|
||||
# - ps: Start-Sleep -s 5
|
||||
|
||||
# - appveyor version
|
||||
# - ps: .\install_path_utils.ps1
|
||||
# - ps: .\install_powershell_core.ps1
|
||||
# - ps: .\install_powershell_get.ps1
|
||||
# - ps: .\install_7zip.ps1
|
||||
# - ps: .\install_chocolatey.ps1
|
||||
# - ps: .\install_webpi.ps1
|
||||
# - ps: .\install_nuget.ps1
|
||||
# - ps: .\install_pstools.ps1
|
||||
|
||||
# - ps: .\install_git.ps1
|
||||
# - ps: .\install_git_lfs.ps1
|
||||
|
||||
# # Restart VM
|
||||
# - ps: Start-Sleep -s 5; Restart-Computer
|
||||
# - ps: Start-Sleep -s 5
|
||||
# END LINES FOR COMPLETELY NEW IMAGE
|
||||
|
||||
- git config --global core.longpaths true
|
||||
- cd ..
|
||||
- ps: >-
|
||||
if (-not (Test-Path -Path .\src)) {
|
||||
New-Item -Path .\src -ItemType Directory
|
||||
if (-not (Test-Path -Path C:\projects\src)) {
|
||||
New-Item -Path C:\projects\src -ItemType Directory
|
||||
}
|
||||
- ps: git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
- cd C:\projects\
|
||||
- git clone -q --branch=%APPVEYOR_REPO_BRANCH% https://github.com/electron/electron.git C:\projects\src\electron
|
||||
- git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
- ps: $env:PATH="$pwd\depot_tools;$env:PATH"
|
||||
- update_depot_tools.bat
|
||||
- ps: Move-Item $env:APPVEYOR_BUILD_FOLDER -Destination src\electron
|
||||
# Uncomment the following line if windows deps change
|
||||
# - src\electron\script\setup-win-for-dev.bat
|
||||
- >-
|
||||
@@ -47,20 +83,25 @@ build_script:
|
||||
- ps: cd ..\..
|
||||
- gclient sync --with_branch_heads --with_tags --nohooks
|
||||
- ps: regsvr32 /s "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\DIA SDK\bin\amd64\msdia140.dll"
|
||||
- ps: |
|
||||
$env:appveyor_user = "appveyor"
|
||||
|
||||
$env:appveyor_password = [Guid]::NewGuid().ToString('B')
|
||||
# The following lines are needed when baking from a completely new image (eg MicrosoftWindowsServer:WindowsServer:2019-Datacenter:latest via image: base-windows-server2019)
|
||||
# # Restart VM
|
||||
# - ps: Start-Sleep -s 5; Restart-Computer
|
||||
# - ps: Start-Sleep -s 5
|
||||
|
||||
Set-LocalUser -Name $env:appveyor_user -Password (ConvertTo-SecureString -AsPlainText $env:appveyor_password -Force) -PasswordNeverExpires:$true
|
||||
|
||||
iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/build-images/master/scripts/Windows/enable_autologon.ps1'))
|
||||
# - cd %USERPROFILE%\image-bake-scripts
|
||||
# - appveyor version
|
||||
# - ps: .\optimize_dotnet_runtime.ps1
|
||||
# - ps: .\disable_windows_background_services.ps1
|
||||
# - ps: .\enforce_windows_firewall.ps1
|
||||
# - ps: .\cleanup_windows.ps1
|
||||
# END LINES FOR COMPLETELY NEW IMAGE
|
||||
on_image_bake:
|
||||
- ps: >-
|
||||
echo "Baking image: $env:APPVEYOR_BAKE_IMAGE at dir $PWD"
|
||||
- ps: Remove-Item -Recurse -Force $pwd\depot_tools
|
||||
- ps: Remove-Item -Recurse -Force $pwd\src\electron
|
||||
- ps: Remove-Item -Recurse -Force C:\projects\depot_tools
|
||||
- ps: Remove-Item -Recurse -Force C:\projects\src\electron
|
||||
# Uncomment these lines and set APPVEYOR_RDP_PASSWORD in project settings to enable RDP after bake is done
|
||||
#on_finish:
|
||||
# - ps: >-
|
||||
# $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
# # on_finish:
|
||||
# - ps: >-
|
||||
# $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
@@ -6,7 +6,7 @@
|
||||
# - "GN_CONFIG" Build type. One of {'testing', 'release'}.
|
||||
# - "GN_EXTRA_ARGS" Additional gn arguments for a build config,
|
||||
# e.g. 'target_cpu="x86"' to build for a 32bit platform.
|
||||
# https://gn.googlesource.com/gn/+/master/docs/reference.md#target_cpu
|
||||
# https://gn.googlesource.com/gn/+/main/docs/reference.md#var_target_cpu
|
||||
# Don't forget to set up "NPM_CONFIG_ARCH" and "TARGET_ARCH" accordingly
|
||||
# if you pass a custom value for 'target_cpu'.
|
||||
# - "ELECTRON_RELEASE" Set it to '1' upload binaries on success.
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
version: 1.0.{build}
|
||||
build_cloud: electronhq-16-core
|
||||
image: e-111.0.5518.0
|
||||
image: e-111.0.5560.0-2
|
||||
environment:
|
||||
GIT_CACHE_PATH: C:\Users\appveyor\libcc_cache
|
||||
ELECTRON_OUT_DIR: Default
|
||||
@@ -82,7 +82,7 @@ for:
|
||||
if (Test-Path -Path "$pwd\build-tools") {
|
||||
Remove-Item -Recurse -Force $pwd\build-tools
|
||||
}
|
||||
- ps: git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
- git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
- ps: $env:PATH="$pwd\depot_tools;$env:PATH"
|
||||
- ps: >-
|
||||
if (Test-Path -Path "$pwd\src\electron") {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
# - "GN_CONFIG" Build type. One of {'testing', 'release'}.
|
||||
# - "GN_EXTRA_ARGS" Additional gn arguments for a build config,
|
||||
# e.g. 'target_cpu="x86"' to build for a 32bit platform.
|
||||
# https://gn.googlesource.com/gn/+/master/docs/reference.md#target_cpu
|
||||
# https://gn.googlesource.com/gn/+/main/docs/reference.md#var_target_cpu
|
||||
# Don't forget to set up "NPM_CONFIG_ARCH" and "TARGET_ARCH" accordingly
|
||||
# if you pass a custom value for 'target_cpu'.
|
||||
# - "ELECTRON_RELEASE" Set it to '1' upload binaries on success.
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
version: 1.0.{build}
|
||||
build_cloud: electronhq-16-core
|
||||
image: e-111.0.5560.0
|
||||
image: e-111.0.5560.0-node18
|
||||
environment:
|
||||
GIT_CACHE_PATH: C:\Users\appveyor\libcc_cache
|
||||
ELECTRON_OUT_DIR: Default
|
||||
@@ -80,7 +80,7 @@ for:
|
||||
if (Test-Path -Path "$pwd\build-tools") {
|
||||
Remove-Item -Recurse -Force $pwd\build-tools
|
||||
}
|
||||
- ps: git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
- git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
- ps: $env:PATH="$pwd\depot_tools;$env:PATH"
|
||||
- ps: >-
|
||||
if (Test-Path -Path "$pwd\src\electron") {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
is_electron_build = true
|
||||
root_extra_deps = [ "//electron" ]
|
||||
|
||||
# Registry of NMVs --> https://github.com/nodejs/node/blob/master/doc/abi_version_registry.json
|
||||
# Registry of NMVs --> https://github.com/nodejs/node/blob/main/doc/abi_version_registry.json
|
||||
node_module_version = 114
|
||||
|
||||
v8_promise_internal_field_count = 1
|
||||
|
||||
@@ -1776,7 +1776,7 @@ On macOS it does not remove the focus from the window.
|
||||
|
||||
#### `win.isFocusable()` _macOS_ _Windows_
|
||||
|
||||
Returns whether the window can be focused.
|
||||
Returns `boolean` - Whether the window can be focused.
|
||||
|
||||
#### `win.setParentWindow(parent)`
|
||||
|
||||
@@ -1910,7 +1910,7 @@ removed in future Electron releases.
|
||||
On a Window with Window Controls Overlay already enabled, this method updates
|
||||
the style of the title bar overlay.
|
||||
|
||||
[runtime-enabled-features]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/runtime_enabled_features.json5?l=70
|
||||
[runtime-enabled-features]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/platform/runtime_enabled_features.json5
|
||||
[page-visibility-api]: https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API
|
||||
[quick-look]: https://en.wikipedia.org/wiki/Quick_Look
|
||||
[vibrancy-docs]: https://developer.apple.com/documentation/appkit/nsvisualeffectview?preferredLanguage=objc
|
||||
|
||||
@@ -40,6 +40,8 @@ Open the given file in the desktop's default manner.
|
||||
* `options` Object (optional)
|
||||
* `activate` boolean (optional) _macOS_ - `true` to bring the opened application to the foreground. The default is `true`.
|
||||
* `workingDirectory` string (optional) _Windows_ - The working directory.
|
||||
* `logUsage` boolean (optional) _Windows_ - Indicates a user initiated launch that enables tracking of frequently used programs and other behaviors.
|
||||
The default is `false`.
|
||||
|
||||
Returns `Promise<void>`
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# Event Object extends `GlobalEvent`
|
||||
|
||||
* `preventDefault` VoidFunction
|
||||
@@ -831,7 +831,7 @@ Emitted when the preload script `preloadPath` throws an unhandled exception `err
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `event` [IpcMainEvent](structures/ipc-main-event.md)
|
||||
* `channel` string
|
||||
* `...args` any[]
|
||||
|
||||
@@ -843,7 +843,7 @@ See also [`webContents.ipc`](#contentsipc-readonly), which provides an [`IpcMain
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `event` [IpcMainEvent](structures/ipc-main-event.md)
|
||||
* `channel` string
|
||||
* `...args` any[]
|
||||
|
||||
@@ -1409,8 +1409,8 @@ Returns `Promise<PrinterInfo[]>` - Resolves with a [`PrinterInfo[]`](structures/
|
||||
* `vertical` number (optional) - The vertical dpi.
|
||||
* `header` string (optional) - string to be printed as page header.
|
||||
* `footer` string (optional) - string to be printed as page footer.
|
||||
* `pageSize` string | Size (optional) - Specify page size of the printed document. Can be `A3`,
|
||||
`A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height` and `width`.
|
||||
* `pageSize` string | Size (optional) - Specify page size of the printed document. Can be `A0`, `A1`, `A2`, `A3`,
|
||||
`A4`, `A5`, `A6`, `Legal`, `Letter`, `Tabloid` or an Object containing `height` and `width`.
|
||||
* `callback` Function (optional)
|
||||
* `success` boolean - Indicates success of the print call.
|
||||
* `failureReason` string - Error description called back if the print fails.
|
||||
|
||||
@@ -1001,7 +1001,7 @@ Emitted when DevTools is closed.
|
||||
|
||||
Emitted when DevTools is focused / opened.
|
||||
|
||||
[runtime-enabled-features]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/runtime_enabled_features.json5?l=70
|
||||
[runtime-enabled-features]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/platform/runtime_enabled_features.json5
|
||||
[chrome-webview]: https://developer.chrome.com/docs/extensions/reference/webviewTag/
|
||||
|
||||
### Event: 'context-menu'
|
||||
|
||||
@@ -18,8 +18,8 @@ See also [V8 Development](v8-development.md)
|
||||
|
||||
### Code Resources
|
||||
|
||||
- [Code Search](https://cs.chromium.org/) - Indexed and searchable source code for Chromium and associated projects.
|
||||
- [Source Code](https://cs.chromium.org/chromium/src/) - The source code for Chromium itself.
|
||||
- [Code Search](https://source.chromium.org/chromium) - Indexed and searchable source code for Chromium and associated projects.
|
||||
- [Source Code](https://source.chromium.org/chromium/chromium/src) - The source code for Chromium itself.
|
||||
- [Chromium Review](https://chromium-review.googlesource.com) - The searchable code host which facilitates code reviews for Chromium and related projects.
|
||||
|
||||
### Informational Resources
|
||||
|
||||
@@ -79,7 +79,6 @@ auto_filenames = {
|
||||
"docs/api/structures/custom-scheme.md",
|
||||
"docs/api/structures/desktop-capturer-source.md",
|
||||
"docs/api/structures/display.md",
|
||||
"docs/api/structures/event.md",
|
||||
"docs/api/structures/extension-info.md",
|
||||
"docs/api/structures/extension.md",
|
||||
"docs/api/structures/file-filter.md",
|
||||
|
||||
@@ -267,7 +267,6 @@ filenames = {
|
||||
"shell/browser/api/electron_api_dialog.cc",
|
||||
"shell/browser/api/electron_api_download_item.cc",
|
||||
"shell/browser/api/electron_api_download_item.h",
|
||||
"shell/browser/api/electron_api_event.cc",
|
||||
"shell/browser/api/electron_api_event_emitter.cc",
|
||||
"shell/browser/api/electron_api_event_emitter.h",
|
||||
"shell/browser/api/electron_api_global_shortcut.cc",
|
||||
@@ -320,8 +319,6 @@ filenames = {
|
||||
"shell/browser/api/electron_api_web_request.cc",
|
||||
"shell/browser/api/electron_api_web_request.h",
|
||||
"shell/browser/api/electron_api_web_view_manager.cc",
|
||||
"shell/browser/api/event.cc",
|
||||
"shell/browser/api/event.h",
|
||||
"shell/browser/api/frame_subscriber.cc",
|
||||
"shell/browser/api/frame_subscriber.h",
|
||||
"shell/browser/api/gpu_info_enumerator.cc",
|
||||
@@ -382,7 +379,6 @@ filenames = {
|
||||
"shell/browser/electron_web_contents_utility_handler_impl.h",
|
||||
"shell/browser/electron_web_ui_controller_factory.cc",
|
||||
"shell/browser/electron_web_ui_controller_factory.h",
|
||||
"shell/browser/event_emitter_mixin.cc",
|
||||
"shell/browser/event_emitter_mixin.h",
|
||||
"shell/browser/extended_web_contents_observer.h",
|
||||
"shell/browser/feature_list.cc",
|
||||
@@ -606,10 +602,13 @@ filenames = {
|
||||
"shell/common/gin_helper/dictionary.h",
|
||||
"shell/common/gin_helper/error_thrower.cc",
|
||||
"shell/common/gin_helper/error_thrower.h",
|
||||
"shell/common/gin_helper/event_emitter.cc",
|
||||
"shell/common/gin_helper/event.cc",
|
||||
"shell/common/gin_helper/event.h",
|
||||
"shell/common/gin_helper/event_emitter.h",
|
||||
"shell/common/gin_helper/event_emitter_caller.cc",
|
||||
"shell/common/gin_helper/event_emitter_caller.h",
|
||||
"shell/common/gin_helper/event_emitter_template.cc",
|
||||
"shell/common/gin_helper/event_emitter_template.h",
|
||||
"shell/common/gin_helper/function_template.cc",
|
||||
"shell/common/gin_helper/function_template.h",
|
||||
"shell/common/gin_helper/function_template_extensions.h",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { BaseWindow, WebContents, Event, BrowserView, TouchBar } from 'electron/main';
|
||||
import { BaseWindow, WebContents, BrowserView, TouchBar } from 'electron/main';
|
||||
import type { BrowserWindow as BWT } from 'electron/main';
|
||||
import * as deprecate from '@electron/internal/common/deprecate';
|
||||
const { BrowserWindow } = process._linkedBinding('electron_browser_window') as { BrowserWindow: typeof BWT };
|
||||
@@ -22,10 +22,10 @@ BrowserWindow.prototype._init = function (this: BWT) {
|
||||
};
|
||||
|
||||
// Redirect focus/blur event to app instance too.
|
||||
this.on('blur', (event: Event) => {
|
||||
this.on('blur', (event: Electron.Event) => {
|
||||
app.emit('browser-window-blur', event, this);
|
||||
});
|
||||
this.on('focus', (event: Event) => {
|
||||
this.on('focus', (event: Electron.Event) => {
|
||||
app.emit('browser-window-focus', event, this);
|
||||
});
|
||||
|
||||
@@ -68,8 +68,7 @@ BrowserWindow.prototype._init = function (this: BWT) {
|
||||
});
|
||||
|
||||
// Notify the creation of the window.
|
||||
const event = process._linkedBinding('electron_browser_event').createEmpty();
|
||||
app.emit('browser-window-created', event, this);
|
||||
app.emit('browser-window-created', { preventDefault () {} }, this);
|
||||
|
||||
Object.defineProperty(this, 'devToolsWebContents', {
|
||||
enumerable: true,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as roles from '@electron/internal/browser/api/menu-item-roles';
|
||||
import { Menu, Event, BrowserWindow, WebContents } from 'electron/main';
|
||||
import { Menu, BrowserWindow, WebContents, KeyboardEvent } from 'electron/main';
|
||||
|
||||
let nextCommandId = 0;
|
||||
|
||||
@@ -53,7 +53,7 @@ const MenuItem = function (this: any, options: any) {
|
||||
});
|
||||
|
||||
const click = options.click;
|
||||
this.click = (event: Event, focusedWindow: BrowserWindow, focusedWebContents: WebContents) => {
|
||||
this.click = (event: KeyboardEvent, focusedWindow: BrowserWindow, focusedWebContents: WebContents) => {
|
||||
// Manually flip the checked flags when clicked.
|
||||
if (!roles.shouldOverrideCheckStatus(this.role) &&
|
||||
(this.type === 'checkbox' || this.type === 'radio')) {
|
||||
|
||||
@@ -28,11 +28,47 @@ type PostData = LoadURLOptions['postData']
|
||||
|
||||
// Stock page sizes
|
||||
const PDFPageSizes: Record<string, ElectronInternal.MediaSize> = {
|
||||
A5: {
|
||||
custom_display_name: 'A5',
|
||||
height_microns: 210000,
|
||||
name: 'ISO_A5',
|
||||
width_microns: 148000
|
||||
Letter: {
|
||||
custom_display_name: 'Letter',
|
||||
height_microns: 279400,
|
||||
name: 'NA_LETTER',
|
||||
width_microns: 215900
|
||||
},
|
||||
Legal: {
|
||||
custom_display_name: 'Legal',
|
||||
height_microns: 355600,
|
||||
name: 'NA_LEGAL',
|
||||
width_microns: 215900
|
||||
},
|
||||
Tabloid: {
|
||||
height_microns: 431800,
|
||||
name: 'NA_LEDGER',
|
||||
width_microns: 279400,
|
||||
custom_display_name: 'Tabloid'
|
||||
},
|
||||
A0: {
|
||||
custom_display_name: 'A0',
|
||||
height_microns: 1189000,
|
||||
name: 'ISO_A0',
|
||||
width_microns: 841000
|
||||
},
|
||||
A1: {
|
||||
custom_display_name: 'A1',
|
||||
height_microns: 841000,
|
||||
name: 'ISO_A1',
|
||||
width_microns: 594000
|
||||
},
|
||||
A2: {
|
||||
custom_display_name: 'A2',
|
||||
height_microns: 594000,
|
||||
name: 'ISO_A2',
|
||||
width_microns: 420000
|
||||
},
|
||||
A3: {
|
||||
custom_display_name: 'A3',
|
||||
height_microns: 420000,
|
||||
name: 'ISO_A3',
|
||||
width_microns: 297000
|
||||
},
|
||||
A4: {
|
||||
custom_display_name: 'A4',
|
||||
@@ -41,29 +77,17 @@ const PDFPageSizes: Record<string, ElectronInternal.MediaSize> = {
|
||||
is_default: 'true',
|
||||
width_microns: 210000
|
||||
},
|
||||
A3: {
|
||||
custom_display_name: 'A3',
|
||||
height_microns: 420000,
|
||||
name: 'ISO_A3',
|
||||
width_microns: 297000
|
||||
A5: {
|
||||
custom_display_name: 'A5',
|
||||
height_microns: 210000,
|
||||
name: 'ISO_A5',
|
||||
width_microns: 148000
|
||||
},
|
||||
Legal: {
|
||||
custom_display_name: 'Legal',
|
||||
height_microns: 355600,
|
||||
name: 'NA_LEGAL',
|
||||
width_microns: 215900
|
||||
},
|
||||
Letter: {
|
||||
custom_display_name: 'Letter',
|
||||
height_microns: 279400,
|
||||
name: 'NA_LETTER',
|
||||
width_microns: 215900
|
||||
},
|
||||
Tabloid: {
|
||||
height_microns: 431800,
|
||||
name: 'NA_LEDGER',
|
||||
width_microns: 279400,
|
||||
custom_display_name: 'Tabloid'
|
||||
A6: {
|
||||
custom_display_name: 'A6',
|
||||
height_microns: 148000,
|
||||
name: 'ISO_A6',
|
||||
width_microns: 105000
|
||||
}
|
||||
} as const;
|
||||
|
||||
@@ -524,7 +548,8 @@ const addReplyToEvent = (event: Electron.IpcMainEvent) => {
|
||||
};
|
||||
};
|
||||
|
||||
const addSenderFrameToEvent = (event: Electron.IpcMainEvent | Electron.IpcMainInvokeEvent) => {
|
||||
const addSenderToEvent = (event: Electron.IpcMainEvent | Electron.IpcMainInvokeEvent, sender: Electron.WebContents) => {
|
||||
event.sender = sender;
|
||||
const { processId, frameId } = event;
|
||||
Object.defineProperty(event, 'senderFrame', {
|
||||
get: () => webFrameMain.fromId(processId, frameId)
|
||||
@@ -533,7 +558,7 @@ const addSenderFrameToEvent = (event: Electron.IpcMainEvent | Electron.IpcMainIn
|
||||
|
||||
const addReturnValueToEvent = (event: Electron.IpcMainEvent) => {
|
||||
Object.defineProperty(event, 'returnValue', {
|
||||
set: (value) => event.sendReply(value),
|
||||
set: (value) => event._replyChannel.sendReply(value),
|
||||
get: () => {}
|
||||
});
|
||||
};
|
||||
@@ -574,7 +599,7 @@ WebContents.prototype._init = function () {
|
||||
|
||||
// Dispatch IPC messages to the ipc module.
|
||||
this.on('-ipc-message' as any, function (this: Electron.WebContents, event: Electron.IpcMainEvent, internal: boolean, channel: string, args: any[]) {
|
||||
addSenderFrameToEvent(event);
|
||||
addSenderToEvent(event, this);
|
||||
if (internal) {
|
||||
ipcMainInternal.emit(channel, event, ...args);
|
||||
} else {
|
||||
@@ -587,25 +612,30 @@ WebContents.prototype._init = function () {
|
||||
}
|
||||
});
|
||||
|
||||
this.on('-ipc-invoke' as any, function (event: Electron.IpcMainInvokeEvent, internal: boolean, channel: string, args: any[]) {
|
||||
addSenderFrameToEvent(event);
|
||||
event._reply = (result: any) => event.sendReply({ result });
|
||||
event._throw = (error: Error) => {
|
||||
this.on('-ipc-invoke' as any, async function (this: Electron.WebContents, event: Electron.IpcMainInvokeEvent, internal: boolean, channel: string, args: any[]) {
|
||||
addSenderToEvent(event, this);
|
||||
const replyWithResult = (result: any) => event._replyChannel.sendReply({ result });
|
||||
const replyWithError = (error: Error) => {
|
||||
console.error(`Error occurred in handler for '${channel}':`, error);
|
||||
event.sendReply({ error: error.toString() });
|
||||
event._replyChannel.sendReply({ error: error.toString() });
|
||||
};
|
||||
const maybeWebFrame = getWebFrameForEvent(event);
|
||||
const targets: (ElectronInternal.IpcMainInternal| undefined)[] = internal ? [ipcMainInternal] : [maybeWebFrame?.ipc, ipc, ipcMain];
|
||||
const target = targets.find(target => target && (target as any)._invokeHandlers.has(channel));
|
||||
if (target) {
|
||||
(target as any)._invokeHandlers.get(channel)(event, ...args);
|
||||
const handler = (target as any)._invokeHandlers.get(channel);
|
||||
try {
|
||||
replyWithResult(await Promise.resolve(handler(event, ...args)));
|
||||
} catch (err) {
|
||||
replyWithError(err as Error);
|
||||
}
|
||||
} else {
|
||||
event._throw(`No handler registered for '${channel}'`);
|
||||
replyWithError(new Error(`No handler registered for '${channel}'`));
|
||||
}
|
||||
});
|
||||
|
||||
this.on('-ipc-message-sync' as any, function (this: Electron.WebContents, event: Electron.IpcMainEvent, internal: boolean, channel: string, args: any[]) {
|
||||
addSenderFrameToEvent(event);
|
||||
addSenderToEvent(event, this);
|
||||
addReturnValueToEvent(event);
|
||||
if (internal) {
|
||||
ipcMainInternal.emit(channel, event, ...args);
|
||||
@@ -622,8 +652,8 @@ WebContents.prototype._init = function () {
|
||||
}
|
||||
});
|
||||
|
||||
this.on('-ipc-ports' as any, function (event: Electron.IpcMainEvent, internal: boolean, channel: string, message: any, ports: any[]) {
|
||||
addSenderFrameToEvent(event);
|
||||
this.on('-ipc-ports' as any, function (this: Electron.WebContents, event: Electron.IpcMainEvent, internal: boolean, channel: string, message: any, ports: any[]) {
|
||||
addSenderToEvent(event, this);
|
||||
event.ports = ports.map(p => new MessagePortMain(p));
|
||||
const maybeWebFrame = getWebFrameForEvent(event);
|
||||
maybeWebFrame && maybeWebFrame.ipc.emit(channel, event, message);
|
||||
@@ -651,7 +681,7 @@ WebContents.prototype._init = function () {
|
||||
|
||||
if (this.getType() !== 'remote') {
|
||||
// Make new windows requested by links behave like "window.open".
|
||||
this.on('-new-window' as any, (event: ElectronInternal.Event, url: string, frameName: string, disposition: Electron.HandlerDetails['disposition'],
|
||||
this.on('-new-window' as any, (event: Electron.Event, url: string, frameName: string, disposition: Electron.HandlerDetails['disposition'],
|
||||
rawFeatures: string, referrer: Electron.Referrer, postData: PostData) => {
|
||||
const postBody = postData ? {
|
||||
data: postData,
|
||||
@@ -677,7 +707,7 @@ WebContents.prototype._init = function () {
|
||||
const options = result.browserWindowConstructorOptions;
|
||||
if (!event.defaultPrevented) {
|
||||
openGuestWindow({
|
||||
embedder: event.sender,
|
||||
embedder: this,
|
||||
disposition,
|
||||
referrer,
|
||||
postData,
|
||||
@@ -690,7 +720,7 @@ WebContents.prototype._init = function () {
|
||||
|
||||
let windowOpenOverriddenOptions: BrowserWindowConstructorOptions | null = null;
|
||||
let windowOpenOutlivesOpenerOption: boolean = false;
|
||||
this.on('-will-add-new-contents' as any, (event: ElectronInternal.Event, url: string, frameName: string, rawFeatures: string, disposition: Electron.HandlerDetails['disposition'], referrer: Electron.Referrer, postData: PostData) => {
|
||||
this.on('-will-add-new-contents' as any, (event: Electron.Event, url: string, frameName: string, rawFeatures: string, disposition: Electron.HandlerDetails['disposition'], referrer: Electron.Referrer, postData: PostData) => {
|
||||
const postBody = postData ? {
|
||||
data: postData,
|
||||
...parseContentTypeFormat(postData)
|
||||
@@ -725,7 +755,7 @@ WebContents.prototype._init = function () {
|
||||
} : undefined;
|
||||
const { webPreferences: parsedWebPreferences } = parseFeatures(rawFeatures);
|
||||
const webPreferences = makeWebPreferences({
|
||||
embedder: event.sender,
|
||||
embedder: this,
|
||||
insecureParsedWebPreferences: parsedWebPreferences,
|
||||
secureOverrideWebPreferences
|
||||
});
|
||||
@@ -738,7 +768,7 @@ WebContents.prototype._init = function () {
|
||||
});
|
||||
|
||||
// Create a new browser window for "window.open"
|
||||
this.on('-add-new-contents' as any, (event: ElectronInternal.Event, webContents: Electron.WebContents, disposition: string,
|
||||
this.on('-add-new-contents' as any, (event: Electron.Event, webContents: Electron.WebContents, disposition: string,
|
||||
_userGesture: boolean, _left: number, _top: number, _width: number, _height: number, url: string, frameName: string,
|
||||
referrer: Electron.Referrer, rawFeatures: string, postData: PostData) => {
|
||||
const overriddenOptions = windowOpenOverriddenOptions || undefined;
|
||||
@@ -754,7 +784,7 @@ WebContents.prototype._init = function () {
|
||||
}
|
||||
|
||||
openGuestWindow({
|
||||
embedder: event.sender,
|
||||
embedder: this,
|
||||
guest: webContents,
|
||||
overrideBrowserWindowOptions: overriddenOptions,
|
||||
disposition,
|
||||
@@ -791,8 +821,7 @@ WebContents.prototype._init = function () {
|
||||
}
|
||||
});
|
||||
|
||||
const event = process._linkedBinding('electron_browser_event').createEmpty();
|
||||
app.emit('web-contents-created', event, this);
|
||||
app.emit('web-contents-created', { sender: this, preventDefault () {}, get defaultPrevented () { return false; } }, this);
|
||||
|
||||
// Properties
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ interface GuestInstance {
|
||||
}
|
||||
|
||||
const webViewManager = process._linkedBinding('electron_browser_web_view_manager');
|
||||
const eventBinding = process._linkedBinding('electron_browser_event');
|
||||
const netBinding = process._linkedBinding('electron_browser_net');
|
||||
|
||||
const supportedWebViewEvents = Object.keys(webViewEvents);
|
||||
@@ -82,7 +81,13 @@ function makeLoadURLOptions (params: Record<string, any>) {
|
||||
// Create a new guest instance.
|
||||
const createGuest = function (embedder: Electron.WebContents, embedderFrameId: number, elementInstanceId: number, params: Record<string, any>) {
|
||||
const webPreferences = makeWebPreferences(embedder, params);
|
||||
const event = eventBinding.createWithSender(embedder);
|
||||
const event = {
|
||||
sender: embedder,
|
||||
preventDefault () {
|
||||
this.defaultPrevented = true;
|
||||
},
|
||||
defaultPrevented: false
|
||||
};
|
||||
|
||||
const { instanceId } = params;
|
||||
|
||||
|
||||
@@ -18,13 +18,7 @@ export class IpcMainImpl extends EventEmitter {
|
||||
if (typeof fn !== 'function') {
|
||||
throw new Error(`Expected handler to be a function, but found type '${typeof fn}'`);
|
||||
}
|
||||
this._invokeHandlers.set(method, async (e, ...args) => {
|
||||
try {
|
||||
e._reply(await Promise.resolve(fn(e, ...args)));
|
||||
} catch (err) {
|
||||
e._throw(err as Error);
|
||||
}
|
||||
});
|
||||
this._invokeHandlers.set(method, fn);
|
||||
}
|
||||
|
||||
handleOnce: Electron.IpcMain['handleOnce'] = (method, fn) => {
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
"@azure/storage-blob": "^12.9.0",
|
||||
"@dsanders11/vscode-markdown-languageservice": "^0.3.0-alpha.4",
|
||||
"@electron/asar": "^3.2.1",
|
||||
"@electron/docs-parser": "^1.0.0",
|
||||
"@electron/docs-parser": "^1.1.0",
|
||||
"@electron/fiddle-core": "^1.0.4",
|
||||
"@electron/github-app-auth": "^1.5.0",
|
||||
"@electron/typescript-definitions": "^8.10.0",
|
||||
"@octokit/rest": "^18.0.3",
|
||||
"@electron/typescript-definitions": "^8.14.0",
|
||||
"@octokit/rest": "^19.0.7",
|
||||
"@primer/octicons": "^10.0.0",
|
||||
"@types/basic-auth": "^1.1.3",
|
||||
"@types/busboy": "^1.5.0",
|
||||
|
||||
@@ -134,9 +134,6 @@
|
||||
"parallel/test-webcrypto-export-import-cfrg",
|
||||
"parallel/test-webcrypto-keygen",
|
||||
"parallel/test-webcrypto-sign-verify-eddsa",
|
||||
"parallel/test-worker-debug",
|
||||
"parallel/test-worker-init-failure",
|
||||
"parallel/test-worker-stdio",
|
||||
"parallel/test-zlib-unused-weak",
|
||||
"report/test-report-fatalerror-oomerror-set",
|
||||
"report/test-report-fatalerror-oomerror-directory",
|
||||
|
||||
@@ -14,8 +14,8 @@ const ROLLER_BRANCH_PATTERN = /^roller\/chromium$/;
|
||||
|
||||
const DEFAULT_BUILD_CLOUD_ID = '1598';
|
||||
const DEFAULT_BUILD_CLOUD = 'electronhq-16-core';
|
||||
const DEFAULT_BAKE_BASE_IMAGE = 'e-110.0.5451.0';
|
||||
const DEFAULT_BUILD_IMAGE = 'e-110.0.5451.0';
|
||||
const DEFAULT_BAKE_BASE_IMAGE = 'e-111.0.5560.0-node18';
|
||||
const DEFAULT_BUILD_IMAGE = 'e-111.0.5560.0-node18';
|
||||
|
||||
const appveyorBakeJob = 'electron-bake-image';
|
||||
const appVeyorJobs = {
|
||||
|
||||
@@ -13,6 +13,7 @@ const fs = require('fs');
|
||||
const { execSync } = require('child_process');
|
||||
const got = require('got');
|
||||
const path = require('path');
|
||||
const semver = require('semver');
|
||||
const temp = require('temp').track();
|
||||
const { URL } = require('url');
|
||||
const { BlobServiceClient } = require('@azure/storage-blob');
|
||||
@@ -317,12 +318,23 @@ function saveShaSumFile (checksums, fileName) {
|
||||
}
|
||||
|
||||
async function publishRelease (release) {
|
||||
let makeLatest = false;
|
||||
if (!release.prerelease) {
|
||||
const currentLatest = await octokit.repos.getLatestRelease({
|
||||
owner: 'electron',
|
||||
repo: targetRepo
|
||||
});
|
||||
|
||||
makeLatest = semver.gte(release.tag_name, currentLatest.data.tag_name);
|
||||
}
|
||||
|
||||
return octokit.repos.updateRelease({
|
||||
owner: 'electron',
|
||||
repo: targetRepo,
|
||||
release_id: release.id,
|
||||
tag_name: release.tag_name,
|
||||
draft: false
|
||||
draft: false,
|
||||
make_latest: makeLatest ? 'true' : 'false'
|
||||
}).catch(err => {
|
||||
console.log(`${fail} Error publishing release:`, err);
|
||||
process.exit(1);
|
||||
|
||||
@@ -17,7 +17,8 @@ sys.path.append(
|
||||
|
||||
from zipfile import ZipFile
|
||||
from lib.config import PLATFORM, get_target_arch, \
|
||||
get_zip_name, enable_verbose_mode, get_platform_key
|
||||
get_zip_name, enable_verbose_mode, \
|
||||
is_verbose_mode, get_platform_key
|
||||
from lib.util import get_electron_branding, execute, get_electron_version, \
|
||||
store_artifact, get_electron_exec, get_out_dir, \
|
||||
SRC_DIR, ELECTRON_DIR, TS_NODE
|
||||
@@ -384,6 +385,9 @@ def get_release(version):
|
||||
script_path = os.path.join(
|
||||
ELECTRON_DIR, 'script', 'release', 'find-github-release.js')
|
||||
release_info = execute(['node', script_path, version])
|
||||
if is_verbose_mode():
|
||||
print('Release info for version: {}:\n'.format(version))
|
||||
print(release_info)
|
||||
release = json.loads(release_info)
|
||||
return release
|
||||
|
||||
|
||||
@@ -56,7 +56,8 @@ REM Install Windows SDK
|
||||
choco install windows-sdk-10-version-2104-all
|
||||
|
||||
REM Install nodejs python git and yarn needed dependencies
|
||||
choco install -y nodejs-lts python2 git yarn
|
||||
choco install -y --force nodejs --version=18.12.1
|
||||
choco install -y python2 git yarn
|
||||
choco install python --version 3.7.9
|
||||
call C:\ProgramData\chocolatey\bin\RefreshEnv.cmd
|
||||
SET PATH=C:\Python27\;C:\Python27\Scripts;C:\Python39\;C:\Python39\Scripts;%PATH%
|
||||
|
||||
@@ -260,37 +260,9 @@ int NodeMain(int argc, char* argv[]) {
|
||||
v8::HandleScope scope(isolate);
|
||||
node::LoadEnvironment(env, node::StartExecutionCallback{});
|
||||
|
||||
env->set_trace_sync_io(env->options()->trace_sync_io);
|
||||
|
||||
{
|
||||
v8::SealHandleScope seal(isolate);
|
||||
bool more;
|
||||
env->performance_state()->Mark(
|
||||
node::performance::NODE_PERFORMANCE_MILESTONE_LOOP_START);
|
||||
do {
|
||||
uv_run(env->event_loop(), UV_RUN_DEFAULT);
|
||||
|
||||
gin_env.platform()->DrainTasks(isolate);
|
||||
|
||||
more = uv_loop_alive(env->event_loop());
|
||||
if (more && !env->is_stopping())
|
||||
continue;
|
||||
|
||||
if (!uv_loop_alive(env->event_loop())) {
|
||||
EmitBeforeExit(env);
|
||||
}
|
||||
|
||||
// Emit `beforeExit` if the loop became alive either after emitting
|
||||
// event, or after running some callbacks.
|
||||
more = uv_loop_alive(env->event_loop());
|
||||
} while (more && !env->is_stopping());
|
||||
env->performance_state()->Mark(
|
||||
node::performance::NODE_PERFORMANCE_MILESTONE_LOOP_EXIT);
|
||||
}
|
||||
|
||||
env->set_trace_sync_io(false);
|
||||
|
||||
exit_code = node::EmitExit(env);
|
||||
// Potential reasons we get Nothing here may include: the env
|
||||
// is stopping, or the user hooks process.emit('exit').
|
||||
exit_code = node::SpinEventLoop(env).FromMaybe(1);
|
||||
|
||||
node::ResetStdio();
|
||||
|
||||
|
||||
@@ -112,7 +112,6 @@ BrowserWindow::~BrowserWindow() {
|
||||
api_web_contents_->RemoveObserver(this);
|
||||
// Destroy the WebContents.
|
||||
OnCloseContents();
|
||||
api_web_contents_->Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,6 +139,7 @@ void BrowserWindow::WebContentsDestroyed() {
|
||||
|
||||
void BrowserWindow::OnCloseContents() {
|
||||
BaseWindow::ResetBrowserViews();
|
||||
api_web_contents_->Destroy();
|
||||
}
|
||||
|
||||
void BrowserWindow::OnRendererResponsive(content::RenderProcessHost*) {
|
||||
|
||||
@@ -128,10 +128,10 @@ bool MatchesCookie(const base::Value::Dict& filter,
|
||||
!MatchesDomain(*str, cookie.Domain()))
|
||||
return false;
|
||||
absl::optional<bool> secure_filter = filter.FindBool("secure");
|
||||
if (secure_filter && *secure_filter == cookie.IsSecure())
|
||||
if (secure_filter && *secure_filter != cookie.IsSecure())
|
||||
return false;
|
||||
absl::optional<bool> session_filter = filter.FindBool("session");
|
||||
if (session_filter && *session_filter != !cookie.IsPersistent())
|
||||
if (session_filter && *session_filter == cookie.IsPersistent())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
// Copyright (c) 2018 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "shell/browser/api/event.h"
|
||||
#include "shell/common/gin_helper/dictionary.h"
|
||||
#include "shell/common/gin_helper/event_emitter.h"
|
||||
#include "shell/common/node_includes.h"
|
||||
|
||||
namespace {
|
||||
|
||||
v8::Local<v8::Object> CreateWithSender(v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> sender) {
|
||||
return gin_helper::internal::CreateCustomEvent(isolate, sender);
|
||||
}
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
gin_helper::Dictionary dict(context->GetIsolate(), exports);
|
||||
dict.SetMethod("createWithSender", &CreateWithSender);
|
||||
dict.SetMethod("createEmpty", &gin_helper::Event::Create);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_LINKED_BINDING_CONTEXT_AWARE(electron_browser_event, Initialize)
|
||||
@@ -1178,8 +1178,7 @@ gin::Handle<Session> Session::CreateFrom(
|
||||
// to use partition strings, instead of using the Session object directly.
|
||||
handle->Pin(isolate);
|
||||
|
||||
App::Get()->EmitCustomEvent("session-created",
|
||||
handle.ToV8().As<v8::Object>());
|
||||
App::Get()->EmitWithoutEvent("session-created", handle);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
@@ -97,19 +97,19 @@ void Tray::OnClicked(const gfx::Rect& bounds,
|
||||
int modifiers) {
|
||||
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
||||
v8::HandleScope scope(isolate);
|
||||
EmitCustomEvent("click", CreateEventFromFlags(modifiers), bounds, location);
|
||||
EmitWithoutEvent("click", CreateEventFromFlags(modifiers), bounds, location);
|
||||
}
|
||||
|
||||
void Tray::OnDoubleClicked(const gfx::Rect& bounds, int modifiers) {
|
||||
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
||||
v8::HandleScope scope(isolate);
|
||||
EmitCustomEvent("double-click", CreateEventFromFlags(modifiers), bounds);
|
||||
EmitWithoutEvent("double-click", CreateEventFromFlags(modifiers), bounds);
|
||||
}
|
||||
|
||||
void Tray::OnRightClicked(const gfx::Rect& bounds, int modifiers) {
|
||||
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
||||
v8::HandleScope scope(isolate);
|
||||
EmitCustomEvent("right-click", CreateEventFromFlags(modifiers), bounds);
|
||||
EmitWithoutEvent("right-click", CreateEventFromFlags(modifiers), bounds);
|
||||
}
|
||||
|
||||
void Tray::OnBalloonShow() {
|
||||
@@ -139,31 +139,31 @@ void Tray::OnDropText(const std::string& text) {
|
||||
void Tray::OnMouseEntered(const gfx::Point& location, int modifiers) {
|
||||
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
||||
v8::HandleScope scope(isolate);
|
||||
EmitCustomEvent("mouse-enter", CreateEventFromFlags(modifiers), location);
|
||||
EmitWithoutEvent("mouse-enter", CreateEventFromFlags(modifiers), location);
|
||||
}
|
||||
|
||||
void Tray::OnMouseExited(const gfx::Point& location, int modifiers) {
|
||||
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
||||
v8::HandleScope scope(isolate);
|
||||
EmitCustomEvent("mouse-leave", CreateEventFromFlags(modifiers), location);
|
||||
EmitWithoutEvent("mouse-leave", CreateEventFromFlags(modifiers), location);
|
||||
}
|
||||
|
||||
void Tray::OnMouseMoved(const gfx::Point& location, int modifiers) {
|
||||
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
||||
v8::HandleScope scope(isolate);
|
||||
EmitCustomEvent("mouse-move", CreateEventFromFlags(modifiers), location);
|
||||
EmitWithoutEvent("mouse-move", CreateEventFromFlags(modifiers), location);
|
||||
}
|
||||
|
||||
void Tray::OnMouseUp(const gfx::Point& location, int modifiers) {
|
||||
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
||||
v8::HandleScope scope(isolate);
|
||||
EmitCustomEvent("mouse-up", CreateEventFromFlags(modifiers), location);
|
||||
EmitWithoutEvent("mouse-up", CreateEventFromFlags(modifiers), location);
|
||||
}
|
||||
|
||||
void Tray::OnMouseDown(const gfx::Point& location, int modifiers) {
|
||||
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
||||
v8::HandleScope scope(isolate);
|
||||
EmitCustomEvent("mouse-down", CreateEventFromFlags(modifiers), location);
|
||||
EmitWithoutEvent("mouse-down", CreateEventFromFlags(modifiers), location);
|
||||
}
|
||||
|
||||
void Tray::OnDragEntered() {
|
||||
|
||||
@@ -203,13 +203,13 @@ void UtilityProcessWrapper::OnServiceProcessLaunched(
|
||||
pid_ = process.Pid();
|
||||
GetAllUtilityProcessWrappers().AddWithID(this, pid_);
|
||||
if (stdout_read_fd_ != -1) {
|
||||
EmitWithoutCustomEvent("stdout", stdout_read_fd_);
|
||||
EmitWithoutEvent("stdout", stdout_read_fd_);
|
||||
}
|
||||
if (stderr_read_fd_ != -1) {
|
||||
EmitWithoutCustomEvent("stderr", stderr_read_fd_);
|
||||
EmitWithoutEvent("stderr", stderr_read_fd_);
|
||||
}
|
||||
// Emit 'spawn' event
|
||||
EmitWithoutCustomEvent("spawn");
|
||||
EmitWithoutEvent("spawn");
|
||||
}
|
||||
|
||||
void UtilityProcessWrapper::OnServiceProcessDisconnected(
|
||||
@@ -219,7 +219,7 @@ void UtilityProcessWrapper::OnServiceProcessDisconnected(
|
||||
GetAllUtilityProcessWrappers().Remove(pid_);
|
||||
CloseConnectorPort();
|
||||
// Emit 'exit' event
|
||||
EmitWithoutCustomEvent("exit", error_code);
|
||||
EmitWithoutEvent("exit", error_code);
|
||||
Unpin();
|
||||
}
|
||||
|
||||
@@ -238,7 +238,7 @@ void UtilityProcessWrapper::Shutdown(int exit_code) {
|
||||
node_service_remote_.reset();
|
||||
CloseConnectorPort();
|
||||
// Emit 'exit' event
|
||||
EmitWithoutCustomEvent("exit", exit_code);
|
||||
EmitWithoutEvent("exit", exit_code);
|
||||
Unpin();
|
||||
}
|
||||
|
||||
@@ -311,7 +311,7 @@ bool UtilityProcessWrapper::Accept(mojo::Message* mojo_message) {
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
v8::Local<v8::Value> message_value =
|
||||
electron::DeserializeV8Value(isolate, message);
|
||||
EmitWithoutCustomEvent("message", message_value);
|
||||
EmitWithoutEvent("message", message_value);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1222,7 +1222,9 @@ void WebContents::CloseContents(content::WebContents* source) {
|
||||
for (ExtendedWebContentsObserver& observer : observers_)
|
||||
observer.OnCloseContents();
|
||||
|
||||
Destroy();
|
||||
// If there are observers, OnCloseContents will call Destroy()
|
||||
if (observers_.empty())
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void WebContents::ActivateContents(content::WebContents* source) {
|
||||
@@ -1812,6 +1814,81 @@ void WebContents::OnFirstNonEmptyLayout(
|
||||
}
|
||||
}
|
||||
|
||||
// This object wraps the InvokeCallback so that if it gets GC'd by V8, we can
|
||||
// still call the callback and send an error. Not doing so causes a Mojo DCHECK,
|
||||
// since Mojo requires callbacks to be called before they are destroyed.
|
||||
class ReplyChannel : public gin::Wrappable<ReplyChannel> {
|
||||
public:
|
||||
using InvokeCallback = electron::mojom::ElectronApiIPC::InvokeCallback;
|
||||
static gin::Handle<ReplyChannel> Create(v8::Isolate* isolate,
|
||||
InvokeCallback callback) {
|
||||
return gin::CreateHandle(isolate, new ReplyChannel(std::move(callback)));
|
||||
}
|
||||
|
||||
// gin::Wrappable
|
||||
static gin::WrapperInfo kWrapperInfo;
|
||||
gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) override {
|
||||
return gin::Wrappable<ReplyChannel>::GetObjectTemplateBuilder(isolate)
|
||||
.SetMethod("sendReply", &ReplyChannel::SendReply);
|
||||
}
|
||||
const char* GetTypeName() override { return "ReplyChannel"; }
|
||||
|
||||
private:
|
||||
explicit ReplyChannel(InvokeCallback callback)
|
||||
: callback_(std::move(callback)) {}
|
||||
~ReplyChannel() override {
|
||||
if (callback_) {
|
||||
v8::Isolate* isolate = electron::JavascriptEnvironment::GetIsolate();
|
||||
// If there's no current context, it means we're shutting down, so we
|
||||
// don't need to send an event.
|
||||
if (!isolate->GetCurrentContext().IsEmpty()) {
|
||||
v8::HandleScope scope(isolate);
|
||||
auto message = gin::DataObjectBuilder(isolate)
|
||||
.Set("error", "reply was never sent")
|
||||
.Build();
|
||||
SendReply(isolate, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SendReply(v8::Isolate* isolate, v8::Local<v8::Value> arg) {
|
||||
if (!callback_)
|
||||
return false;
|
||||
blink::CloneableMessage message;
|
||||
if (!gin::ConvertFromV8(isolate, arg, &message)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::move(callback_).Run(std::move(message));
|
||||
return true;
|
||||
}
|
||||
|
||||
InvokeCallback callback_;
|
||||
};
|
||||
|
||||
gin::WrapperInfo ReplyChannel::kWrapperInfo = {gin::kEmbedderNativeGin};
|
||||
|
||||
gin::Handle<gin_helper::internal::Event> WebContents::MakeEventWithSender(
|
||||
v8::Isolate* isolate,
|
||||
content::RenderFrameHost* frame,
|
||||
electron::mojom::ElectronApiIPC::InvokeCallback callback) {
|
||||
v8::Local<v8::Object> wrapper;
|
||||
if (!GetWrapper(isolate).ToLocal(&wrapper))
|
||||
return gin::Handle<gin_helper::internal::Event>();
|
||||
gin::Handle<gin_helper::internal::Event> event =
|
||||
gin_helper::internal::Event::New(isolate);
|
||||
gin_helper::Dictionary dict(isolate, event.ToV8().As<v8::Object>());
|
||||
if (callback)
|
||||
dict.Set("_replyChannel",
|
||||
ReplyChannel::Create(isolate, std::move(callback)));
|
||||
if (frame) {
|
||||
dict.Set("frameId", frame->GetRoutingID());
|
||||
dict.Set("processId", frame->GetProcess()->GetID());
|
||||
}
|
||||
return event;
|
||||
}
|
||||
|
||||
void WebContents::ReceivePostMessage(
|
||||
const std::string& channel,
|
||||
blink::TransferableMessage message,
|
||||
|
||||
@@ -352,20 +352,26 @@ class WebContents : public ExclusiveAccessContext,
|
||||
// this.emit(name, new Event(sender, message), args...);
|
||||
template <typename... Args>
|
||||
bool EmitWithSender(base::StringPiece name,
|
||||
content::RenderFrameHost* sender,
|
||||
content::RenderFrameHost* frame,
|
||||
electron::mojom::ElectronApiIPC::InvokeCallback callback,
|
||||
Args&&... args) {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
v8::Local<v8::Object> wrapper;
|
||||
if (!GetWrapper(isolate).ToLocal(&wrapper))
|
||||
|
||||
gin::Handle<gin_helper::internal::Event> event =
|
||||
MakeEventWithSender(isolate, frame, std::move(callback));
|
||||
if (event.IsEmpty())
|
||||
return false;
|
||||
v8::Local<v8::Object> event = gin_helper::internal::CreateNativeEvent(
|
||||
isolate, wrapper, sender, std::move(callback));
|
||||
return EmitCustomEvent(name, event, std::forward<Args>(args)...);
|
||||
EmitWithoutEvent(name, event, std::forward<Args>(args)...);
|
||||
return event->GetDefaultPrevented();
|
||||
}
|
||||
|
||||
gin::Handle<gin_helper::internal::Event> MakeEventWithSender(
|
||||
v8::Isolate* isolate,
|
||||
content::RenderFrameHost* frame,
|
||||
electron::mojom::ElectronApiIPC::InvokeCallback callback);
|
||||
|
||||
WebContents* embedder() { return embedder_; }
|
||||
|
||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
// Copyright (c) 2014 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "shell/browser/api/event.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "gin/data_object_builder.h"
|
||||
#include "gin/object_template_builder.h"
|
||||
#include "shell/browser/javascript_environment.h"
|
||||
#include "shell/common/gin_converters/blink_converter.h"
|
||||
#include "shell/common/gin_converters/std_converter.h"
|
||||
|
||||
namespace gin_helper {
|
||||
|
||||
gin::WrapperInfo Event::kWrapperInfo = {gin::kEmbedderNativeGin};
|
||||
|
||||
Event::Event() = default;
|
||||
|
||||
Event::~Event() {
|
||||
if (callback_) {
|
||||
v8::Isolate* isolate = electron::JavascriptEnvironment::GetIsolate();
|
||||
// If there's no current context, it means we're shutting down, so we don't
|
||||
// need to send an event.
|
||||
if (!isolate->GetCurrentContext().IsEmpty()) {
|
||||
v8::HandleScope scope(isolate);
|
||||
auto message = gin::DataObjectBuilder(isolate)
|
||||
.Set("error", "reply was never sent")
|
||||
.Build();
|
||||
SendReply(isolate, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Event::SetCallback(InvokeCallback callback) {
|
||||
DCHECK(!callback_);
|
||||
callback_ = std::move(callback);
|
||||
}
|
||||
|
||||
void Event::PreventDefault(v8::Isolate* isolate) {
|
||||
v8::Local<v8::Object> self = GetWrapper(isolate).ToLocalChecked();
|
||||
self->Set(isolate->GetCurrentContext(),
|
||||
gin::StringToV8(isolate, "defaultPrevented"), v8::True(isolate))
|
||||
.Check();
|
||||
}
|
||||
|
||||
bool Event::SendReply(v8::Isolate* isolate, v8::Local<v8::Value> result) {
|
||||
if (!callback_)
|
||||
return false;
|
||||
|
||||
blink::CloneableMessage message;
|
||||
if (!gin::ConvertFromV8(isolate, result, &message)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::move(callback_).Run(std::move(message));
|
||||
return true;
|
||||
}
|
||||
|
||||
gin::ObjectTemplateBuilder Event::GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) {
|
||||
return gin::Wrappable<Event>::GetObjectTemplateBuilder(isolate)
|
||||
.SetMethod("preventDefault", &Event::PreventDefault)
|
||||
.SetMethod("sendReply", &Event::SendReply);
|
||||
}
|
||||
|
||||
const char* Event::GetTypeName() {
|
||||
return "Event";
|
||||
}
|
||||
|
||||
// static
|
||||
gin::Handle<Event> Event::Create(v8::Isolate* isolate) {
|
||||
return gin::CreateHandle(isolate, new Event());
|
||||
}
|
||||
|
||||
} // namespace gin_helper
|
||||
@@ -1,52 +0,0 @@
|
||||
// Copyright (c) 2014 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ELECTRON_SHELL_BROWSER_API_EVENT_H_
|
||||
#define ELECTRON_SHELL_BROWSER_API_EVENT_H_
|
||||
|
||||
#include "electron/shell/common/api/api.mojom.h"
|
||||
#include "gin/handle.h"
|
||||
#include "gin/wrappable.h"
|
||||
|
||||
namespace gin_helper {
|
||||
|
||||
class Event : public gin::Wrappable<Event> {
|
||||
public:
|
||||
using InvokeCallback = electron::mojom::ElectronApiIPC::InvokeCallback;
|
||||
|
||||
static gin::WrapperInfo kWrapperInfo;
|
||||
|
||||
static gin::Handle<Event> Create(v8::Isolate* isolate);
|
||||
|
||||
// Pass the callback to be invoked.
|
||||
void SetCallback(InvokeCallback callback);
|
||||
|
||||
// event.PreventDefault().
|
||||
void PreventDefault(v8::Isolate* isolate);
|
||||
|
||||
// event.sendReply(value), used for replying to synchronous messages and
|
||||
// `invoke` calls.
|
||||
bool SendReply(v8::Isolate* isolate, v8::Local<v8::Value> result);
|
||||
|
||||
// disable copy
|
||||
Event(const Event&) = delete;
|
||||
Event& operator=(const Event&) = delete;
|
||||
|
||||
protected:
|
||||
Event();
|
||||
~Event() override;
|
||||
|
||||
// gin::Wrappable:
|
||||
gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) override;
|
||||
const char* GetTypeName() override;
|
||||
|
||||
private:
|
||||
// Replier for the synchronous messages.
|
||||
InvokeCallback callback_;
|
||||
};
|
||||
|
||||
} // namespace gin_helper
|
||||
|
||||
#endif // ELECTRON_SHELL_BROWSER_API_EVENT_H_
|
||||
@@ -61,7 +61,7 @@ class MessagePort : public gin::Wrappable<MessagePort>, mojo::MessageReceiver {
|
||||
// The blink version of MessagePort uses the very nice "ActiveScriptWrapper"
|
||||
// class, which keeps the object alive through the V8 embedder hooks into the
|
||||
// GC lifecycle: see
|
||||
// https://source.chromium.org/chromium/chromium/src/+/master:third_party/blink/renderer/platform/heap/thread_state.cc;l=258;drc=b892cf58e162a8f66cd76d7472f129fe0fb6a7d1
|
||||
// https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/platform/heap/thread_state.cc;l=258;drc=b892cf58e162a8f66cd76d7472f129fe0fb6a7d1
|
||||
// We do not have that luxury, so we brutishly use v8::Global to accomplish
|
||||
// something similar. Critically, whenever the value of
|
||||
// "HasPendingActivity()" changes, we must call Pin() or Unpin() as
|
||||
|
||||
@@ -561,7 +561,7 @@ void ElectronBrowserMainParts::PostCreateMainMessageLoop() {
|
||||
config->main_thread_runner =
|
||||
base::SingleThreadTaskRunner::GetCurrentDefault();
|
||||
// c.f.
|
||||
// https://source.chromium.org/chromium/chromium/src/+/master:chrome/common/chrome_switches.cc;l=689;drc=9d82515060b9b75fa941986f5db7390299669ef1
|
||||
// https://source.chromium.org/chromium/chromium/src/+/main:chrome/common/chrome_switches.cc;l=689;drc=9d82515060b9b75fa941986f5db7390299669ef1
|
||||
config->should_use_preference =
|
||||
command_line.HasSwitch(::switches::kEnableEncryptionSelection);
|
||||
base::PathService::Get(DIR_SESSION_DATA, &config->user_data_path);
|
||||
|
||||
@@ -7,16 +7,14 @@
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "gin/handle.h"
|
||||
#include "gin/object_template_builder.h"
|
||||
#include "shell/browser/javascript_environment.h"
|
||||
#include "shell/common/gin_helper/event.h"
|
||||
#include "shell/common/gin_helper/event_emitter.h"
|
||||
|
||||
namespace gin_helper {
|
||||
|
||||
namespace internal {
|
||||
v8::Local<v8::FunctionTemplate> GetEventEmitterTemplate(v8::Isolate* isolate);
|
||||
} // namespace internal
|
||||
|
||||
template <typename T>
|
||||
class EventEmitterMixin {
|
||||
public:
|
||||
@@ -33,14 +31,15 @@ class EventEmitterMixin {
|
||||
v8::Local<v8::Object> wrapper;
|
||||
if (!static_cast<T*>(this)->GetWrapper(isolate).ToLocal(&wrapper))
|
||||
return false;
|
||||
v8::Local<v8::Object> event = internal::CreateCustomEvent(isolate, wrapper);
|
||||
return EmitWithEvent(isolate, wrapper, name, event,
|
||||
std::forward<Args>(args)...);
|
||||
gin::Handle<internal::Event> event = internal::Event::New(isolate);
|
||||
gin_helper::EmitEvent(isolate, wrapper, name, event,
|
||||
std::forward<Args>(args)...);
|
||||
return event->GetDefaultPrevented();
|
||||
}
|
||||
|
||||
// this.emit(name, args...);
|
||||
template <typename... Args>
|
||||
void EmitWithoutCustomEvent(base::StringPiece name, Args&&... args) {
|
||||
void EmitWithoutEvent(base::StringPiece name, Args&&... args) {
|
||||
v8::Isolate* isolate = electron::JavascriptEnvironment::GetIsolate();
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
v8::Local<v8::Object> wrapper;
|
||||
@@ -49,20 +48,6 @@ class EventEmitterMixin {
|
||||
gin_helper::EmitEvent(isolate, wrapper, name, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// this.emit(name, event, args...);
|
||||
template <typename... Args>
|
||||
bool EmitCustomEvent(base::StringPiece name,
|
||||
v8::Local<v8::Object> custom_event,
|
||||
Args&&... args) {
|
||||
v8::Isolate* isolate = electron::JavascriptEnvironment::GetIsolate();
|
||||
v8::HandleScope scope(isolate);
|
||||
v8::Local<v8::Object> wrapper;
|
||||
if (!static_cast<T*>(this)->GetWrapper(isolate).ToLocal(&wrapper))
|
||||
return false;
|
||||
return EmitWithEvent(isolate, wrapper, name, custom_event,
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
protected:
|
||||
EventEmitterMixin() = default;
|
||||
|
||||
@@ -82,25 +67,6 @@ class EventEmitterMixin {
|
||||
static_cast<T*>(this)->GetTypeName(),
|
||||
constructor->InstanceTemplate());
|
||||
}
|
||||
|
||||
private:
|
||||
// this.emit(name, event, args...);
|
||||
template <typename... Args>
|
||||
static bool EmitWithEvent(v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> wrapper,
|
||||
base::StringPiece name,
|
||||
v8::Local<v8::Object> event,
|
||||
Args&&... args) {
|
||||
auto context = isolate->GetCurrentContext();
|
||||
gin_helper::EmitEvent(isolate, wrapper, name, event,
|
||||
std::forward<Args>(args)...);
|
||||
v8::Local<v8::Value> defaultPrevented;
|
||||
if (event->Get(context, gin::StringToV8(isolate, "defaultPrevented"))
|
||||
.ToLocal(&defaultPrevented)) {
|
||||
return defaultPrevented->BooleanValue(isolate);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace gin_helper
|
||||
|
||||
@@ -1215,7 +1215,7 @@ content::DesktopMediaID NativeWindowMac::GetDesktopMediaID() const {
|
||||
auto desktop_media_id = content::DesktopMediaID(
|
||||
content::DesktopMediaID::TYPE_WINDOW, GetAcceleratedWidget());
|
||||
// c.f.
|
||||
// https://source.chromium.org/chromium/chromium/src/+/master:chrome/browser/media/webrtc/native_desktop_media_list.cc;l=372?q=kWindowCaptureMacV2&ss=chromium
|
||||
// https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/media/webrtc/native_desktop_media_list.cc;l=775-780;drc=79502ab47f61bff351426f57f576daef02b1a8dc
|
||||
// Refs https://github.com/electron/electron/pull/30507
|
||||
// TODO(deepak1556): Match upstream for `kWindowCaptureMacV2`
|
||||
#if 0
|
||||
|
||||
197
shell/browser/net/electron_url_loader_factory.cc
Executable file → Normal file
197
shell/browser/net/electron_url_loader_factory.cc
Executable file → Normal file
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "shell/browser/net/electron_url_loader_factory.h"
|
||||
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
@@ -81,6 +82,19 @@ bool ResponseMustBeObject(ProtocolType type) {
|
||||
}
|
||||
}
|
||||
|
||||
bool LooksLikeStream(v8::Isolate* isolate, v8::Local<v8::Value> v) {
|
||||
// the stream loader can handle null and undefined as "empty body". Could
|
||||
// probably be more efficient here but this works.
|
||||
if (v->IsNullOrUndefined())
|
||||
return true;
|
||||
if (!v->IsObject())
|
||||
return false;
|
||||
gin_helper::Dictionary dict(isolate, v.As<v8::Object>());
|
||||
v8::Local<v8::Value> method;
|
||||
return dict.Get("on", &method) && method->IsFunction() &&
|
||||
dict.Get("removeListener", &method) && method->IsFunction();
|
||||
}
|
||||
|
||||
// Helper to convert value to Dictionary.
|
||||
gin::Dictionary ToDict(v8::Isolate* isolate, v8::Local<v8::Value> value) {
|
||||
if (!value->IsFunction() && value->IsObject())
|
||||
@@ -390,36 +404,94 @@ void ElectronURLLoaderFactory::StartLoading(
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
// DEPRECATED: Soon only |kFree| will be supported!
|
||||
case ProtocolType::kBuffer:
|
||||
StartLoadingBuffer(std::move(client), std::move(head), dict);
|
||||
break;
|
||||
case ProtocolType::kString:
|
||||
StartLoadingString(std::move(client), std::move(head), dict,
|
||||
args->isolate(), response);
|
||||
break;
|
||||
case ProtocolType::kFile:
|
||||
StartLoadingFile(std::move(loader), request, std::move(client),
|
||||
std::move(head), dict, args->isolate(), response);
|
||||
break;
|
||||
case ProtocolType::kHttp:
|
||||
StartLoadingHttp(std::move(loader), request, std::move(client),
|
||||
traffic_annotation, dict);
|
||||
break;
|
||||
case ProtocolType::kStream:
|
||||
StartLoadingStream(std::move(loader), std::move(client), std::move(head),
|
||||
dict);
|
||||
break;
|
||||
case ProtocolType::kFree:
|
||||
ProtocolType protocol_type;
|
||||
if (!gin::ConvertFromV8(args->isolate(), response, &protocol_type)) {
|
||||
if (response->IsArrayBufferView())
|
||||
StartLoadingBuffer(std::move(client), std::move(head),
|
||||
response.As<v8::ArrayBufferView>());
|
||||
else if (v8::Local<v8::Value> data; !dict.IsEmpty() &&
|
||||
dict.Get("data", &data) &&
|
||||
data->IsArrayBufferView())
|
||||
StartLoadingBuffer(std::move(client), std::move(head),
|
||||
data.As<v8::ArrayBufferView>());
|
||||
else
|
||||
OnComplete(std::move(client), request_id,
|
||||
network::URLLoaderCompletionStatus(net::ERR_FAILED));
|
||||
return;
|
||||
}
|
||||
StartLoading(std::move(loader), request_id, options, request,
|
||||
std::move(client), traffic_annotation,
|
||||
std::move(target_factory), protocol_type, args);
|
||||
break;
|
||||
case ProtocolType::kString: {
|
||||
std::string data;
|
||||
if (gin::ConvertFromV8(args->isolate(), response, &data))
|
||||
SendContents(std::move(client), std::move(head), data);
|
||||
else if (!dict.IsEmpty() && dict.Get("data", &data))
|
||||
SendContents(std::move(client), std::move(head), data);
|
||||
else
|
||||
OnComplete(std::move(client), request_id,
|
||||
network::URLLoaderCompletionStatus(net::ERR_FAILED));
|
||||
break;
|
||||
}
|
||||
case ProtocolType::kFile: {
|
||||
base::FilePath path;
|
||||
if (gin::ConvertFromV8(args->isolate(), response, &path))
|
||||
StartLoadingFile(std::move(client), std::move(loader), std::move(head),
|
||||
request, path, dict);
|
||||
else if (!dict.IsEmpty() && dict.Get("path", &path))
|
||||
StartLoadingFile(std::move(client), std::move(loader), std::move(head),
|
||||
request, path, dict);
|
||||
else
|
||||
OnComplete(std::move(client), request_id,
|
||||
network::URLLoaderCompletionStatus(net::ERR_FAILED));
|
||||
break;
|
||||
}
|
||||
case ProtocolType::kHttp:
|
||||
if (GURL url; !dict.IsEmpty() && dict.Get("url", &url) && url.is_valid())
|
||||
StartLoadingHttp(std::move(client), std::move(loader), request,
|
||||
traffic_annotation, dict);
|
||||
else
|
||||
OnComplete(std::move(client), request_id,
|
||||
network::URLLoaderCompletionStatus(net::ERR_FAILED));
|
||||
break;
|
||||
case ProtocolType::kStream:
|
||||
StartLoadingStream(std::move(client), std::move(loader), std::move(head),
|
||||
dict);
|
||||
break;
|
||||
|
||||
case ProtocolType::kFree: {
|
||||
// Infer the type based on the object given
|
||||
v8::Local<v8::Value> data;
|
||||
if (!dict.IsEmpty() && dict.Has("data"))
|
||||
dict.Get("data", &data);
|
||||
else
|
||||
data = response;
|
||||
|
||||
// |data| can be either a string, a buffer or a stream.
|
||||
if (data->IsArrayBufferView()) {
|
||||
StartLoadingBuffer(std::move(client), std::move(head),
|
||||
data.As<v8::ArrayBufferView>());
|
||||
} else if (data->IsString()) {
|
||||
SendContents(std::move(client), std::move(head),
|
||||
gin::V8ToString(args->isolate(), data));
|
||||
} else if (LooksLikeStream(args->isolate(), data)) {
|
||||
StartLoadingStream(std::move(client), std::move(loader),
|
||||
std::move(head), dict);
|
||||
} else if (!dict.IsEmpty()) {
|
||||
// |data| wasn't specified, so look for |response.url| or
|
||||
// |response.path|.
|
||||
if (GURL url; dict.Get("url", &url))
|
||||
StartLoadingHttp(std::move(client), std::move(loader), request,
|
||||
traffic_annotation, dict);
|
||||
else if (base::FilePath path; dict.Get("path", &path))
|
||||
StartLoadingFile(std::move(client), std::move(loader),
|
||||
std::move(head), request, path, dict);
|
||||
else
|
||||
// Don't know what kind of response this is, so fail.
|
||||
OnComplete(std::move(client), request_id,
|
||||
network::URLLoaderCompletionStatus(net::ERR_FAILED));
|
||||
} else {
|
||||
OnComplete(std::move(client), request_id,
|
||||
network::URLLoaderCompletionStatus(net::ERR_FAILED));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -427,68 +499,25 @@ void ElectronURLLoaderFactory::StartLoading(
|
||||
void ElectronURLLoaderFactory::StartLoadingBuffer(
|
||||
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
|
||||
network::mojom::URLResponseHeadPtr head,
|
||||
const gin_helper::Dictionary& dict) {
|
||||
v8::Local<v8::Value> buffer = dict.GetHandle();
|
||||
dict.Get("data", &buffer);
|
||||
if (!node::Buffer::HasInstance(buffer)) {
|
||||
mojo::Remote<network::mojom::URLLoaderClient> client_remote(
|
||||
std::move(client));
|
||||
client_remote->OnComplete(
|
||||
network::URLLoaderCompletionStatus(net::ERR_FAILED));
|
||||
return;
|
||||
}
|
||||
|
||||
SendContents(
|
||||
std::move(client), std::move(head),
|
||||
std::string(node::Buffer::Data(buffer), node::Buffer::Length(buffer)));
|
||||
}
|
||||
|
||||
// static
|
||||
void ElectronURLLoaderFactory::StartLoadingString(
|
||||
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
|
||||
network::mojom::URLResponseHeadPtr head,
|
||||
const gin_helper::Dictionary& dict,
|
||||
v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> response) {
|
||||
std::string contents;
|
||||
if (response->IsString()) {
|
||||
contents = gin::V8ToString(isolate, response);
|
||||
} else if (!dict.IsEmpty()) {
|
||||
dict.Get("data", &contents);
|
||||
} else {
|
||||
mojo::Remote<network::mojom::URLLoaderClient> client_remote(
|
||||
std::move(client));
|
||||
client_remote->OnComplete(
|
||||
network::URLLoaderCompletionStatus(net::ERR_FAILED));
|
||||
return;
|
||||
}
|
||||
|
||||
SendContents(std::move(client), std::move(head), std::move(contents));
|
||||
v8::Local<v8::ArrayBufferView> buffer) {
|
||||
SendContents(std::move(client), std::move(head),
|
||||
std::string(node::Buffer::Data(buffer.As<v8::Value>()),
|
||||
node::Buffer::Length(buffer.As<v8::Value>())));
|
||||
}
|
||||
|
||||
// static
|
||||
void ElectronURLLoaderFactory::StartLoadingFile(
|
||||
mojo::PendingReceiver<network::mojom::URLLoader> loader,
|
||||
network::ResourceRequest request,
|
||||
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
|
||||
mojo::PendingReceiver<network::mojom::URLLoader> loader,
|
||||
network::mojom::URLResponseHeadPtr head,
|
||||
const gin_helper::Dictionary& dict,
|
||||
v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> response) {
|
||||
base::FilePath path;
|
||||
if (gin::ConvertFromV8(isolate, response, &path)) {
|
||||
request.url = net::FilePathToFileURL(path);
|
||||
} else if (!dict.IsEmpty()) {
|
||||
dict.Get("referrer", &request.referrer);
|
||||
dict.Get("method", &request.method);
|
||||
if (dict.Get("path", &path))
|
||||
request.url = net::FilePathToFileURL(path);
|
||||
} else {
|
||||
mojo::Remote<network::mojom::URLLoaderClient> client_remote(
|
||||
std::move(client));
|
||||
client_remote->OnComplete(
|
||||
network::URLLoaderCompletionStatus(net::ERR_FAILED));
|
||||
return;
|
||||
const network::ResourceRequest& original_request,
|
||||
const base::FilePath& path,
|
||||
const gin_helper::Dictionary& opts) {
|
||||
network::ResourceRequest request = original_request;
|
||||
request.url = net::FilePathToFileURL(path);
|
||||
if (!opts.IsEmpty()) {
|
||||
opts.Get("referrer", &request.referrer);
|
||||
opts.Get("method", &request.method);
|
||||
}
|
||||
|
||||
// Add header to ignore CORS.
|
||||
@@ -499,9 +528,9 @@ void ElectronURLLoaderFactory::StartLoadingFile(
|
||||
|
||||
// static
|
||||
void ElectronURLLoaderFactory::StartLoadingHttp(
|
||||
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
|
||||
mojo::PendingReceiver<network::mojom::URLLoader> loader,
|
||||
const network::ResourceRequest& original_request,
|
||||
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
|
||||
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
|
||||
const gin_helper::Dictionary& dict) {
|
||||
auto request = std::make_unique<network::ResourceRequest>();
|
||||
@@ -543,8 +572,8 @@ void ElectronURLLoaderFactory::StartLoadingHttp(
|
||||
|
||||
// static
|
||||
void ElectronURLLoaderFactory::StartLoadingStream(
|
||||
mojo::PendingReceiver<network::mojom::URLLoader> loader,
|
||||
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
|
||||
mojo::PendingReceiver<network::mojom::URLLoader> loader,
|
||||
network::mojom::URLResponseHeadPtr head,
|
||||
const gin_helper::Dictionary& dict) {
|
||||
v8::Local<v8::Value> stream;
|
||||
|
||||
@@ -135,33 +135,27 @@ class ElectronURLLoaderFactory : public network::SelfDeletingURLLoaderFactory {
|
||||
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
|
||||
int32_t request_id,
|
||||
const network::URLLoaderCompletionStatus& status);
|
||||
|
||||
static void StartLoadingBuffer(
|
||||
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
|
||||
network::mojom::URLResponseHeadPtr head,
|
||||
const gin_helper::Dictionary& dict);
|
||||
static void StartLoadingString(
|
||||
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
|
||||
network::mojom::URLResponseHeadPtr head,
|
||||
const gin_helper::Dictionary& dict,
|
||||
v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> response);
|
||||
v8::Local<v8::ArrayBufferView> buffer);
|
||||
static void StartLoadingFile(
|
||||
mojo::PendingReceiver<network::mojom::URLLoader> loader,
|
||||
network::ResourceRequest request,
|
||||
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
|
||||
mojo::PendingReceiver<network::mojom::URLLoader> loader,
|
||||
network::mojom::URLResponseHeadPtr head,
|
||||
const gin_helper::Dictionary& dict,
|
||||
v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> response);
|
||||
const network::ResourceRequest& original_request,
|
||||
const base::FilePath& path,
|
||||
const gin_helper::Dictionary& opts);
|
||||
static void StartLoadingHttp(
|
||||
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
|
||||
mojo::PendingReceiver<network::mojom::URLLoader> loader,
|
||||
const network::ResourceRequest& original_request,
|
||||
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
|
||||
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
|
||||
const gin_helper::Dictionary& dict);
|
||||
static void StartLoadingStream(
|
||||
mojo::PendingReceiver<network::mojom::URLLoader> loader,
|
||||
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
|
||||
mojo::PendingReceiver<network::mojom::URLLoader> loader,
|
||||
network::mojom::URLResponseHeadPtr head,
|
||||
const gin_helper::Dictionary& dict);
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include "ui/gtk/gtk_compat.h" // nogncheck
|
||||
|
||||
// The following utilities are pulled from
|
||||
// https://source.chromium.org/chromium/chromium/src/+/main:ui/gtk/select_file_dialog_impl_gtk.cc;l=43-74
|
||||
// https://source.chromium.org/chromium/chromium/src/+/main:ui/gtk/select_file_dialog_linux_gtk.cc;l=44-75;drc=a03ba4ca94f75531207c3ea832d6a605cde77394
|
||||
namespace gtk_util {
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -64,6 +64,7 @@ v8::Local<v8::Promise> OpenExternal(const GURL& url, gin::Arguments* args) {
|
||||
if (args->GetNext(&obj)) {
|
||||
obj.Get("activate", &options.activate);
|
||||
obj.Get("workingDirectory", &options.working_dir);
|
||||
obj.Get("logUsage", &options.log_usage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#include "gin/per_isolate_data.h"
|
||||
#include "gin/wrappable.h"
|
||||
#include "shell/browser/event_emitter_mixin.h"
|
||||
#include "shell/common/gin_helper/event_emitter_template.h"
|
||||
#include "shell/common/gin_helper/function_template_extensions.h"
|
||||
|
||||
namespace gin_helper {
|
||||
|
||||
31
shell/common/gin_helper/event.cc
Normal file
31
shell/common/gin_helper/event.cc
Normal file
@@ -0,0 +1,31 @@
|
||||
// Copyright (c) 2023 Salesforce, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "shell/common/gin_helper/event.h"
|
||||
#include "gin/dictionary.h"
|
||||
#include "gin/object_template_builder.h"
|
||||
|
||||
namespace gin_helper::internal {
|
||||
|
||||
// static
|
||||
gin::Handle<Event> Event::New(v8::Isolate* isolate) {
|
||||
return gin::CreateHandle(isolate, new Event());
|
||||
}
|
||||
// static
|
||||
v8::Local<v8::ObjectTemplate> Event::FillObjectTemplate(
|
||||
v8::Isolate* isolate,
|
||||
v8::Local<v8::ObjectTemplate> templ) {
|
||||
return gin::ObjectTemplateBuilder(isolate, "Event", templ)
|
||||
.SetMethod("preventDefault", &Event::PreventDefault)
|
||||
.SetProperty("defaultPrevented", &Event::GetDefaultPrevented)
|
||||
.Build();
|
||||
}
|
||||
|
||||
Event::Event() = default;
|
||||
|
||||
Event::~Event() = default;
|
||||
|
||||
gin::WrapperInfo Event::kWrapperInfo = {gin::kEmbedderNativeGin};
|
||||
|
||||
} // namespace gin_helper::internal
|
||||
48
shell/common/gin_helper/event.h
Normal file
48
shell/common/gin_helper/event.h
Normal file
@@ -0,0 +1,48 @@
|
||||
// Copyright (c) 2023 Salesforce, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ELECTRON_SHELL_COMMON_GIN_HELPER_EVENT_H_
|
||||
#define ELECTRON_SHELL_COMMON_GIN_HELPER_EVENT_H_
|
||||
|
||||
#include "gin/handle.h"
|
||||
#include "gin/wrappable.h"
|
||||
#include "shell/common/gin_helper/constructible.h"
|
||||
|
||||
namespace v8 {
|
||||
class Isolate;
|
||||
template <typename T>
|
||||
class Local;
|
||||
class Object;
|
||||
class ObjectTemplate;
|
||||
} // namespace v8
|
||||
|
||||
namespace gin_helper::internal {
|
||||
|
||||
class Event : public gin::Wrappable<Event>,
|
||||
public gin_helper::Constructible<Event> {
|
||||
public:
|
||||
// gin_helper::Constructible
|
||||
static gin::Handle<Event> New(v8::Isolate* isolate);
|
||||
static v8::Local<v8::ObjectTemplate> FillObjectTemplate(
|
||||
v8::Isolate* isolate,
|
||||
v8::Local<v8::ObjectTemplate> prototype);
|
||||
|
||||
// gin::Wrappable
|
||||
static gin::WrapperInfo kWrapperInfo;
|
||||
|
||||
~Event() override;
|
||||
|
||||
void PreventDefault() { default_prevented_ = true; }
|
||||
|
||||
bool GetDefaultPrevented() { return default_prevented_; }
|
||||
|
||||
private:
|
||||
Event();
|
||||
|
||||
bool default_prevented_ = false;
|
||||
};
|
||||
|
||||
} // namespace gin_helper::internal
|
||||
|
||||
#endif // ELECTRON_SHELL_COMMON_GIN_HELPER_EVENT_H_
|
||||
@@ -1,76 +0,0 @@
|
||||
// Copyright (c) 2019 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "shell/common/gin_helper/event_emitter.h"
|
||||
|
||||
#include "content/public/browser/render_frame_host.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
#include "shell/browser/api/event.h"
|
||||
#include "shell/common/gin_helper/dictionary.h"
|
||||
#include "shell/common/gin_helper/object_template_builder.h"
|
||||
|
||||
namespace gin_helper::internal {
|
||||
|
||||
namespace {
|
||||
|
||||
v8::Persistent<v8::ObjectTemplate> event_template;
|
||||
|
||||
void PreventDefault(gin_helper::Arguments* args) {
|
||||
Dictionary self;
|
||||
if (args->GetHolder(&self))
|
||||
self.Set("defaultPrevented", true);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
v8::Local<v8::Object> CreateCustomEvent(v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> sender,
|
||||
v8::Local<v8::Object> custom_event) {
|
||||
if (event_template.IsEmpty()) {
|
||||
event_template.Reset(
|
||||
isolate,
|
||||
ObjectTemplateBuilder(isolate, v8::ObjectTemplate::New(isolate))
|
||||
.SetMethod("preventDefault", &PreventDefault)
|
||||
.Build());
|
||||
}
|
||||
|
||||
v8::Local<v8::Context> context = isolate->GetCurrentContext();
|
||||
CHECK(!context.IsEmpty());
|
||||
v8::Local<v8::Object> event =
|
||||
v8::Local<v8::ObjectTemplate>::New(isolate, event_template)
|
||||
->NewInstance(context)
|
||||
.ToLocalChecked();
|
||||
if (!sender.IsEmpty())
|
||||
Dictionary(isolate, event).Set("sender", sender);
|
||||
if (!custom_event.IsEmpty())
|
||||
event->SetPrototype(context, custom_event).IsJust();
|
||||
return event;
|
||||
}
|
||||
|
||||
v8::Local<v8::Object> CreateNativeEvent(
|
||||
v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> sender,
|
||||
content::RenderFrameHost* frame,
|
||||
electron::mojom::ElectronApiIPC::MessageSyncCallback callback) {
|
||||
v8::Local<v8::Object> event;
|
||||
if (frame && callback) {
|
||||
gin::Handle<Event> native_event = Event::Create(isolate);
|
||||
native_event->SetCallback(std::move(callback));
|
||||
event = native_event.ToV8().As<v8::Object>();
|
||||
} else {
|
||||
// No need to create native event if we do not need to send reply.
|
||||
event = CreateCustomEvent(isolate);
|
||||
}
|
||||
|
||||
Dictionary dict(isolate, event);
|
||||
dict.Set("sender", sender);
|
||||
// Should always set frameId even when callback is null.
|
||||
if (frame) {
|
||||
dict.Set("frameId", frame->GetRoutingID());
|
||||
dict.Set("processId", frame->GetProcess()->GetID());
|
||||
}
|
||||
return event;
|
||||
}
|
||||
|
||||
} // namespace gin_helper::internal
|
||||
@@ -10,6 +10,8 @@
|
||||
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "electron/shell/common/api/api.mojom.h"
|
||||
#include "gin/handle.h"
|
||||
#include "shell/common/gin_helper/event.h"
|
||||
#include "shell/common/gin_helper/event_emitter_caller.h"
|
||||
#include "shell/common/gin_helper/wrappable.h"
|
||||
|
||||
@@ -19,20 +21,6 @@ class RenderFrameHost;
|
||||
|
||||
namespace gin_helper {
|
||||
|
||||
namespace internal {
|
||||
|
||||
v8::Local<v8::Object> CreateCustomEvent(
|
||||
v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> sender = v8::Local<v8::Object>(),
|
||||
v8::Local<v8::Object> custom_event = v8::Local<v8::Object>());
|
||||
v8::Local<v8::Object> CreateNativeEvent(
|
||||
v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> sender,
|
||||
content::RenderFrameHost* frame,
|
||||
electron::mojom::ElectronApiIPC::MessageSyncCallback callback);
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// Provide helperers to emit event in JavaScript.
|
||||
template <typename T>
|
||||
class EventEmitter : public gin_helper::Wrappable<T> {
|
||||
@@ -48,16 +36,6 @@ class EventEmitter : public gin_helper::Wrappable<T> {
|
||||
return Base::GetWrapper(isolate);
|
||||
}
|
||||
|
||||
// this.emit(name, event, args...);
|
||||
template <typename... Args>
|
||||
bool EmitCustomEvent(base::StringPiece name,
|
||||
v8::Local<v8::Object> event,
|
||||
Args&&... args) {
|
||||
return EmitWithEvent(
|
||||
name, internal::CreateCustomEvent(isolate(), GetWrapper(), event),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// this.emit(name, new Event(), args...);
|
||||
template <typename... Args>
|
||||
bool Emit(base::StringPiece name, Args&&... args) {
|
||||
@@ -65,8 +43,8 @@ class EventEmitter : public gin_helper::Wrappable<T> {
|
||||
v8::Local<v8::Object> wrapper = GetWrapper();
|
||||
if (wrapper.IsEmpty())
|
||||
return false;
|
||||
v8::Local<v8::Object> event =
|
||||
internal::CreateCustomEvent(isolate(), wrapper);
|
||||
gin::Handle<gin_helper::internal::Event> event =
|
||||
internal::Event::New(isolate());
|
||||
return EmitWithEvent(name, event, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
@@ -81,20 +59,14 @@ class EventEmitter : public gin_helper::Wrappable<T> {
|
||||
// this.emit(name, event, args...);
|
||||
template <typename... Args>
|
||||
bool EmitWithEvent(base::StringPiece name,
|
||||
v8::Local<v8::Object> event,
|
||||
gin::Handle<gin_helper::internal::Event> event,
|
||||
Args&&... args) {
|
||||
// It's possible that |this| will be deleted by EmitEvent, so save anything
|
||||
// we need from |this| before calling EmitEvent.
|
||||
auto* isolate = this->isolate();
|
||||
auto context = isolate->GetCurrentContext();
|
||||
gin_helper::EmitEvent(isolate, GetWrapper(), name, event,
|
||||
std::forward<Args>(args)...);
|
||||
v8::Local<v8::Value> defaultPrevented;
|
||||
if (event->Get(context, gin::StringToV8(isolate, "defaultPrevented"))
|
||||
.ToLocal(&defaultPrevented)) {
|
||||
return defaultPrevented->BooleanValue(isolate);
|
||||
}
|
||||
return false;
|
||||
return event->GetDefaultPrevented();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
// Copyright (c) 2019 Slack Technologies, Inc.
|
||||
// Copyright (c) 2023 Salesforce, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "shell/browser/event_emitter_mixin.h"
|
||||
#include "shell/common/gin_helper/event_emitter_template.h"
|
||||
|
||||
#include "gin/public/wrapper_info.h"
|
||||
#include "gin/converter.h"
|
||||
#include "gin/per_isolate_data.h"
|
||||
#include "shell/browser/api/electron_api_event_emitter.h"
|
||||
#include "v8/include/v8-function.h"
|
||||
#include "v8/include/v8-template.h"
|
||||
|
||||
namespace gin_helper::internal {
|
||||
|
||||
19
shell/common/gin_helper/event_emitter_template.h
Normal file
19
shell/common/gin_helper/event_emitter_template.h
Normal file
@@ -0,0 +1,19 @@
|
||||
// Copyright (c) 2023 Salesforce, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ELECTRON_SHELL_COMMON_GIN_HELPER_EVENT_EMITTER_TEMPLATE_H_
|
||||
#define ELECTRON_SHELL_COMMON_GIN_HELPER_EVENT_EMITTER_TEMPLATE_H_
|
||||
|
||||
namespace v8 {
|
||||
class Isolate;
|
||||
template <typename T>
|
||||
class Local;
|
||||
class FunctionTemplate;
|
||||
} // namespace v8
|
||||
|
||||
namespace gin_helper::internal {
|
||||
v8::Local<v8::FunctionTemplate> GetEventEmitterTemplate(v8::Isolate* isolate);
|
||||
}
|
||||
|
||||
#endif // ELECTRON_SHELL_COMMON_GIN_HELPER_EVENT_EMITTER_TEMPLATE_H_
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "shell/common/electron_command_line.h"
|
||||
#include "shell/common/gin_converters/file_path_converter.h"
|
||||
#include "shell/common/gin_helper/dictionary.h"
|
||||
#include "shell/common/gin_helper/event.h"
|
||||
#include "shell/common/gin_helper/event_emitter_caller.h"
|
||||
#include "shell/common/gin_helper/locker.h"
|
||||
#include "shell/common/gin_helper/microtasks_scope.h"
|
||||
@@ -50,7 +51,6 @@
|
||||
V(electron_browser_content_tracing) \
|
||||
V(electron_browser_crash_reporter) \
|
||||
V(electron_browser_dialog) \
|
||||
V(electron_browser_event) \
|
||||
V(electron_browser_event_emitter) \
|
||||
V(electron_browser_global_shortcut) \
|
||||
V(electron_browser_in_app_purchase) \
|
||||
@@ -463,6 +463,9 @@ void NodeBindings::Initialize() {
|
||||
SetErrorMode(GetErrorMode() & ~SEM_NOGPFAULTERRORBOX);
|
||||
#endif
|
||||
|
||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||
gin_helper::internal::Event::GetConstructor(isolate->GetCurrentContext());
|
||||
|
||||
g_is_initialized = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ void OpenPath(const base::FilePath& full_path, OpenCallback callback);
|
||||
struct OpenExternalOptions {
|
||||
bool activate = true;
|
||||
base::FilePath working_dir;
|
||||
bool log_usage = false;
|
||||
};
|
||||
|
||||
// Open the given external protocol URL in the desktop's default manner.
|
||||
|
||||
@@ -246,10 +246,19 @@ std::string OpenExternalOnWorkerThread(
|
||||
L"\"";
|
||||
std::wstring working_dir = options.working_dir.value();
|
||||
|
||||
if (reinterpret_cast<ULONG_PTR>(
|
||||
ShellExecuteW(nullptr, L"open", escaped_url.c_str(), nullptr,
|
||||
working_dir.empty() ? nullptr : working_dir.c_str(),
|
||||
SW_SHOWNORMAL)) <= 32) {
|
||||
SHELLEXECUTEINFO info = {};
|
||||
info.cbSize = sizeof(SHELLEXECUTEINFO);
|
||||
info.fMask = SEE_MASK_NOASYNC | SEE_MASK_FLAG_NO_UI;
|
||||
info.lpVerb = L"open";
|
||||
info.lpFile = escaped_url.c_str();
|
||||
info.lpDirectory = working_dir.empty() ? nullptr : working_dir.c_str();
|
||||
info.nShow = SW_SHOWNORMAL;
|
||||
|
||||
if (options.log_usage) {
|
||||
info.fMask |= SEE_MASK_FLAG_LOG_USAGE;
|
||||
}
|
||||
|
||||
if (!ShellExecuteEx(&info)) {
|
||||
return "Failed to open: " +
|
||||
logging::SystemErrorCodeToString(logging::GetLastSystemErrorCode());
|
||||
}
|
||||
|
||||
@@ -84,8 +84,7 @@ ElectronContentUtilityClient::ElectronContentUtilityClient() = default;
|
||||
ElectronContentUtilityClient::~ElectronContentUtilityClient() = default;
|
||||
|
||||
// The guts of this came from the chromium implementation
|
||||
// https://cs.chromium.org/chromium/src/chrome/utility/
|
||||
// chrome_content_utility_client.cc?sq=package:chromium&dr=CSs&g=0&l=142
|
||||
// https://source.chromium.org/chromium/chromium/src/+/main:chrome/utility/chrome_content_utility_client.cc
|
||||
void ElectronContentUtilityClient::ExposeInterfacesToBrowser(
|
||||
mojo::BinderMap* binders) {
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
|
||||
@@ -80,7 +80,7 @@ describe('dialog module', () => {
|
||||
afterEach(closeAllWindows);
|
||||
|
||||
// parentless message boxes are synchronous on macOS
|
||||
// dangling message boxes on windows cause a DCHECK: https://cs.chromium.org/chromium/src/base/win/message_window.cc?l=68&rcl=7faa4bf236a866d007dc5672c9ce42660e67a6a6
|
||||
// dangling message boxes on windows cause a DCHECK: https://source.chromium.org/chromium/chromium/src/+/main:base/win/message_window.cc;drc=7faa4bf236a866d007dc5672c9ce42660e67a6a6;l=68
|
||||
ifit(process.platform !== 'darwin' && process.platform !== 'win32')('should not throw for a parentless message box', () => {
|
||||
expect(() => {
|
||||
dialog.showMessageBox({ message: 'i am message' });
|
||||
|
||||
@@ -813,6 +813,71 @@ describe('net module', () => {
|
||||
});
|
||||
}
|
||||
|
||||
it('should be able correctly filter out cookies that are secure', async () => {
|
||||
const sess = session.fromPartition(`cookie-tests-${Math.random()}`);
|
||||
|
||||
await Promise.all([
|
||||
sess.cookies.set({
|
||||
url: 'https://electronjs.org',
|
||||
domain: 'electronjs.org',
|
||||
name: 'cookie1',
|
||||
value: '1',
|
||||
secure: true
|
||||
}),
|
||||
sess.cookies.set({
|
||||
url: 'https://electronjs.org',
|
||||
domain: 'electronjs.org',
|
||||
name: 'cookie2',
|
||||
value: '2',
|
||||
secure: false
|
||||
})
|
||||
]);
|
||||
|
||||
const secureCookies = await sess.cookies.get({
|
||||
secure: true
|
||||
});
|
||||
expect(secureCookies).to.have.lengthOf(1);
|
||||
expect(secureCookies[0].name).to.equal('cookie1');
|
||||
|
||||
const cookies = await sess.cookies.get({
|
||||
secure: false
|
||||
});
|
||||
expect(cookies).to.have.lengthOf(1);
|
||||
expect(cookies[0].name).to.equal('cookie2');
|
||||
});
|
||||
|
||||
it('should be able correctly filter out cookies that are session', async () => {
|
||||
const sess = session.fromPartition(`cookie-tests-${Math.random()}`);
|
||||
|
||||
await Promise.all([
|
||||
sess.cookies.set({
|
||||
url: 'https://electronjs.org',
|
||||
domain: 'electronjs.org',
|
||||
name: 'cookie1',
|
||||
value: '1'
|
||||
}),
|
||||
sess.cookies.set({
|
||||
url: 'https://electronjs.org',
|
||||
domain: 'electronjs.org',
|
||||
name: 'cookie2',
|
||||
value: '2',
|
||||
expirationDate: Math.round(Date.now() / 1000) + 10000
|
||||
})
|
||||
]);
|
||||
|
||||
const sessionCookies = await sess.cookies.get({
|
||||
session: true
|
||||
});
|
||||
expect(sessionCookies).to.have.lengthOf(1);
|
||||
expect(sessionCookies[0].name).to.equal('cookie1');
|
||||
|
||||
const cookies = await sess.cookies.get({
|
||||
session: false
|
||||
});
|
||||
expect(cookies).to.have.lengthOf(1);
|
||||
expect(cookies[0].name).to.equal('cookie2');
|
||||
});
|
||||
|
||||
describe('when {"credentials":"omit"}', () => {
|
||||
it('should not send cookies');
|
||||
it('should not store cookies');
|
||||
|
||||
@@ -19,7 +19,6 @@ const fixturesPath = path.resolve(__dirname, 'fixtures');
|
||||
const registerStringProtocol = protocol.registerStringProtocol;
|
||||
const registerBufferProtocol = protocol.registerBufferProtocol;
|
||||
const registerFileProtocol = protocol.registerFileProtocol;
|
||||
const registerHttpProtocol = protocol.registerHttpProtocol;
|
||||
const registerStreamProtocol = protocol.registerStreamProtocol;
|
||||
const interceptStringProtocol = protocol.interceptStringProtocol;
|
||||
const interceptBufferProtocol = protocol.interceptBufferProtocol;
|
||||
@@ -146,366 +145,395 @@ describe('protocol module', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('protocol.registerStringProtocol', () => {
|
||||
it('sends string as response', async () => {
|
||||
registerStringProtocol(protocolName, (request, callback) => callback(text));
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
expect(r.data).to.equal(text);
|
||||
});
|
||||
for (const [registerStringProtocol, name] of [
|
||||
[protocol.registerStringProtocol, 'protocol.registerStringProtocol'] as const,
|
||||
[(protocol as any).registerProtocol as typeof protocol.registerStringProtocol, 'protocol.registerProtocol'] as const
|
||||
]) {
|
||||
describe(name, () => {
|
||||
it('sends string as response', async () => {
|
||||
registerStringProtocol(protocolName, (request, callback) => callback(text));
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
expect(r.data).to.equal(text);
|
||||
});
|
||||
|
||||
it('sets Access-Control-Allow-Origin', async () => {
|
||||
registerStringProtocol(protocolName, (request, callback) => callback(text));
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
expect(r.data).to.equal(text);
|
||||
expect(r.headers).to.have.property('access-control-allow-origin', '*');
|
||||
});
|
||||
it('sets Access-Control-Allow-Origin', async () => {
|
||||
registerStringProtocol(protocolName, (request, callback) => callback(text));
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
expect(r.data).to.equal(text);
|
||||
expect(r.headers).to.have.property('access-control-allow-origin', '*');
|
||||
});
|
||||
|
||||
it('sends object as response', async () => {
|
||||
registerStringProtocol(protocolName, (request, callback) => {
|
||||
callback({
|
||||
data: text,
|
||||
mimeType: 'text/html'
|
||||
it('sends object as response', async () => {
|
||||
registerStringProtocol(protocolName, (request, callback) => {
|
||||
callback({
|
||||
data: text,
|
||||
mimeType: 'text/html'
|
||||
});
|
||||
});
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
expect(r.data).to.equal(text);
|
||||
});
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
expect(r.data).to.equal(text);
|
||||
});
|
||||
|
||||
it('fails when sending object other than string', async () => {
|
||||
const notAString = () => {};
|
||||
registerStringProtocol(protocolName, (request, callback) => callback(notAString as any));
|
||||
await expect(ajax(protocolName + '://fake-host')).to.be.eventually.rejected();
|
||||
it('fails when sending object other than string', async () => {
|
||||
const notAString = () => {};
|
||||
registerStringProtocol(protocolName, (request, callback) => callback(notAString as any));
|
||||
await expect(ajax(protocolName + '://fake-host')).to.be.eventually.rejected();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
describe('protocol.registerBufferProtocol', () => {
|
||||
const buffer = Buffer.from(text);
|
||||
it('sends Buffer as response', async () => {
|
||||
registerBufferProtocol(protocolName, (request, callback) => callback(buffer));
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
expect(r.data).to.equal(text);
|
||||
});
|
||||
for (const [registerBufferProtocol, name] of [
|
||||
[protocol.registerBufferProtocol, 'protocol.registerBufferProtocol'] as const,
|
||||
[(protocol as any).registerProtocol as typeof protocol.registerBufferProtocol, 'protocol.registerProtocol'] as const
|
||||
]) {
|
||||
describe(name, () => {
|
||||
const buffer = Buffer.from(text);
|
||||
it('sends Buffer as response', async () => {
|
||||
registerBufferProtocol(protocolName, (request, callback) => callback(buffer));
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
expect(r.data).to.equal(text);
|
||||
});
|
||||
|
||||
it('sets Access-Control-Allow-Origin', async () => {
|
||||
registerBufferProtocol(protocolName, (request, callback) => callback(buffer));
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
expect(r.data).to.equal(text);
|
||||
expect(r.headers).to.have.property('access-control-allow-origin', '*');
|
||||
});
|
||||
it('sets Access-Control-Allow-Origin', async () => {
|
||||
registerBufferProtocol(protocolName, (request, callback) => callback(buffer));
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
expect(r.data).to.equal(text);
|
||||
expect(r.headers).to.have.property('access-control-allow-origin', '*');
|
||||
});
|
||||
|
||||
it('sends object as response', async () => {
|
||||
registerBufferProtocol(protocolName, (request, callback) => {
|
||||
callback({
|
||||
data: buffer,
|
||||
mimeType: 'text/html'
|
||||
it('sends object as response', async () => {
|
||||
registerBufferProtocol(protocolName, (request, callback) => {
|
||||
callback({
|
||||
data: buffer,
|
||||
mimeType: 'text/html'
|
||||
});
|
||||
});
|
||||
});
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
expect(r.data).to.equal(text);
|
||||
});
|
||||
|
||||
it('fails when sending string', async () => {
|
||||
registerBufferProtocol(protocolName, (request, callback) => callback(text as any));
|
||||
await expect(ajax(protocolName + '://fake-host')).to.be.eventually.rejected();
|
||||
});
|
||||
});
|
||||
|
||||
describe('protocol.registerFileProtocol', () => {
|
||||
const filePath = path.join(fixturesPath, 'test.asar', 'a.asar', 'file1');
|
||||
const fileContent = fs.readFileSync(filePath);
|
||||
const normalPath = path.join(fixturesPath, 'pages', 'a.html');
|
||||
const normalContent = fs.readFileSync(normalPath);
|
||||
|
||||
afterEach(closeAllWindows);
|
||||
|
||||
it('sends file path as response', async () => {
|
||||
registerFileProtocol(protocolName, (request, callback) => callback(filePath));
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
expect(r.data).to.equal(String(fileContent));
|
||||
});
|
||||
|
||||
it('sets Access-Control-Allow-Origin', async () => {
|
||||
registerFileProtocol(protocolName, (request, callback) => callback(filePath));
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
expect(r.data).to.equal(String(fileContent));
|
||||
expect(r.headers).to.have.property('access-control-allow-origin', '*');
|
||||
});
|
||||
|
||||
it('sets custom headers', async () => {
|
||||
registerFileProtocol(protocolName, (request, callback) => callback({
|
||||
path: filePath,
|
||||
headers: { 'X-Great-Header': 'sogreat' }
|
||||
}));
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
expect(r.data).to.equal(String(fileContent));
|
||||
expect(r.headers).to.have.property('x-great-header', 'sogreat');
|
||||
});
|
||||
|
||||
it('can load iframes with custom protocols', (done) => {
|
||||
registerFileProtocol('custom', (request, callback) => {
|
||||
const filename = request.url.substring(9);
|
||||
const p = path.join(__dirname, 'fixtures', 'pages', filename);
|
||||
callback({ path: p });
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
expect(r.data).to.equal(text);
|
||||
});
|
||||
|
||||
const w = new BrowserWindow({
|
||||
show: false,
|
||||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
contextIsolation: false
|
||||
}
|
||||
if (name !== 'protocol.registerProtocol') {
|
||||
it('fails when sending string', async () => {
|
||||
registerBufferProtocol(protocolName, (request, callback) => callback(text as any));
|
||||
await expect(ajax(protocolName + '://fake-host')).to.be.eventually.rejected();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for (const [registerFileProtocol, name] of [
|
||||
[protocol.registerFileProtocol, 'protocol.registerFileProtocol'] as const,
|
||||
[(protocol as any).registerProtocol as typeof protocol.registerFileProtocol, 'protocol.registerProtocol'] as const
|
||||
]) {
|
||||
describe(name, () => {
|
||||
const filePath = path.join(fixturesPath, 'test.asar', 'a.asar', 'file1');
|
||||
const fileContent = fs.readFileSync(filePath);
|
||||
const normalPath = path.join(fixturesPath, 'pages', 'a.html');
|
||||
const normalContent = fs.readFileSync(normalPath);
|
||||
|
||||
afterEach(closeAllWindows);
|
||||
|
||||
if (name === 'protocol.registerFileProtocol') {
|
||||
it('sends file path as response', async () => {
|
||||
registerFileProtocol(protocolName, (request, callback) => callback(filePath));
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
expect(r.data).to.equal(String(fileContent));
|
||||
});
|
||||
}
|
||||
|
||||
it('sets Access-Control-Allow-Origin', async () => {
|
||||
registerFileProtocol(protocolName, (request, callback) => callback({ path: filePath }));
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
expect(r.data).to.equal(String(fileContent));
|
||||
expect(r.headers).to.have.property('access-control-allow-origin', '*');
|
||||
});
|
||||
|
||||
w.loadFile(path.join(__dirname, 'fixtures', 'pages', 'iframe-protocol.html'));
|
||||
ipcMain.once('loaded-iframe-custom-protocol', () => done());
|
||||
});
|
||||
|
||||
it.skip('throws an error when custom headers are invalid', (done) => {
|
||||
registerFileProtocol(protocolName, (request, callback) => {
|
||||
expect(() => callback({
|
||||
it('sets custom headers', async () => {
|
||||
registerFileProtocol(protocolName, (request, callback) => callback({
|
||||
path: filePath,
|
||||
headers: { 'X-Great-Header': (42 as any) }
|
||||
})).to.throw(Error, 'Value of \'X-Great-Header\' header has to be a string');
|
||||
done();
|
||||
headers: { 'X-Great-Header': 'sogreat' }
|
||||
}));
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
expect(r.data).to.equal(String(fileContent));
|
||||
expect(r.headers).to.have.property('x-great-header', 'sogreat');
|
||||
});
|
||||
ajax(protocolName + '://fake-host').catch(() => {});
|
||||
});
|
||||
|
||||
it('sends object as response', async () => {
|
||||
registerFileProtocol(protocolName, (request, callback) => callback({ path: filePath }));
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
expect(r.data).to.equal(String(fileContent));
|
||||
});
|
||||
|
||||
it('can send normal file', async () => {
|
||||
registerFileProtocol(protocolName, (request, callback) => callback(normalPath));
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
expect(r.data).to.equal(String(normalContent));
|
||||
});
|
||||
|
||||
it('fails when sending unexist-file', async () => {
|
||||
const fakeFilePath = path.join(fixturesPath, 'test.asar', 'a.asar', 'not-exist');
|
||||
registerFileProtocol(protocolName, (request, callback) => callback(fakeFilePath));
|
||||
await expect(ajax(protocolName + '://fake-host')).to.be.eventually.rejected();
|
||||
});
|
||||
|
||||
it('fails when sending unsupported content', async () => {
|
||||
registerFileProtocol(protocolName, (request, callback) => callback(new Date() as any));
|
||||
await expect(ajax(protocolName + '://fake-host')).to.be.eventually.rejected();
|
||||
});
|
||||
});
|
||||
|
||||
describe('protocol.registerHttpProtocol', () => {
|
||||
it('sends url as response', async () => {
|
||||
const server = http.createServer((req, res) => {
|
||||
expect(req.headers.accept).to.not.equal('');
|
||||
res.end(text);
|
||||
server.close();
|
||||
});
|
||||
await new Promise<void>(resolve => server.listen(0, '127.0.0.1', resolve));
|
||||
|
||||
const port = (server.address() as AddressInfo).port;
|
||||
const url = 'http://127.0.0.1:' + port;
|
||||
registerHttpProtocol(protocolName, (request, callback) => callback({ url }));
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
expect(r.data).to.equal(text);
|
||||
});
|
||||
|
||||
it('fails when sending invalid url', async () => {
|
||||
registerHttpProtocol(protocolName, (request, callback) => callback({ url: 'url' }));
|
||||
await expect(ajax(protocolName + '://fake-host')).to.be.eventually.rejected();
|
||||
});
|
||||
|
||||
it('fails when sending unsupported content', async () => {
|
||||
registerHttpProtocol(protocolName, (request, callback) => callback(new Date() as any));
|
||||
await expect(ajax(protocolName + '://fake-host')).to.be.eventually.rejected();
|
||||
});
|
||||
|
||||
it('works when target URL redirects', async () => {
|
||||
const server = http.createServer((req, res) => {
|
||||
if (req.url === '/serverRedirect') {
|
||||
res.statusCode = 301;
|
||||
res.setHeader('Location', `http://${req.rawHeaders[1]}`);
|
||||
res.end();
|
||||
} else {
|
||||
res.end(text);
|
||||
}
|
||||
});
|
||||
after(() => server.close());
|
||||
await new Promise<void>(resolve => server.listen(0, '127.0.0.1', resolve));
|
||||
|
||||
const port = (server.address() as AddressInfo).port;
|
||||
const url = `${protocolName}://fake-host`;
|
||||
const redirectURL = `http://127.0.0.1:${port}/serverRedirect`;
|
||||
registerHttpProtocol(protocolName, (request, callback) => callback({ url: redirectURL }));
|
||||
|
||||
const r = await ajax(url);
|
||||
expect(r.data).to.equal(text);
|
||||
});
|
||||
|
||||
it('can access request headers', (done) => {
|
||||
protocol.registerHttpProtocol(protocolName, (request) => {
|
||||
try {
|
||||
expect(request).to.have.property('headers');
|
||||
done();
|
||||
} catch (e) {
|
||||
done(e);
|
||||
}
|
||||
});
|
||||
ajax(protocolName + '://fake-host').catch(() => {});
|
||||
});
|
||||
});
|
||||
|
||||
describe('protocol.registerStreamProtocol', () => {
|
||||
it('sends Stream as response', async () => {
|
||||
registerStreamProtocol(protocolName, (request, callback) => callback(getStream()));
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
expect(r.data).to.equal(text);
|
||||
});
|
||||
|
||||
it('sends object as response', async () => {
|
||||
registerStreamProtocol(protocolName, (request, callback) => callback({ data: getStream() }));
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
expect(r.data).to.equal(text);
|
||||
expect(r.status).to.equal(200);
|
||||
});
|
||||
|
||||
it('sends custom response headers', async () => {
|
||||
registerStreamProtocol(protocolName, (request, callback) => callback({
|
||||
data: getStream(3),
|
||||
headers: {
|
||||
'x-electron': ['a', 'b']
|
||||
}
|
||||
}));
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
expect(r.data).to.equal(text);
|
||||
expect(r.status).to.equal(200);
|
||||
expect(r.headers).to.have.property('x-electron', 'a, b');
|
||||
});
|
||||
|
||||
it('sends custom status code', async () => {
|
||||
registerStreamProtocol(protocolName, (request, callback) => callback({
|
||||
statusCode: 204,
|
||||
data: null as any
|
||||
}));
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
expect(r.data).to.be.empty('data');
|
||||
expect(r.status).to.equal(204);
|
||||
});
|
||||
|
||||
it('receives request headers', async () => {
|
||||
registerStreamProtocol(protocolName, (request, callback) => {
|
||||
callback({
|
||||
headers: {
|
||||
'content-type': 'application/json'
|
||||
},
|
||||
data: getStream(5, JSON.stringify(Object.assign({}, request.headers)))
|
||||
it('can load iframes with custom protocols', (done) => {
|
||||
registerFileProtocol('custom', (request, callback) => {
|
||||
const filename = request.url.substring(9);
|
||||
const p = path.join(__dirname, 'fixtures', 'pages', filename);
|
||||
callback({ path: p });
|
||||
});
|
||||
});
|
||||
const r = await ajax(protocolName + '://fake-host', { headers: { 'x-return-headers': 'yes' } });
|
||||
expect(JSON.parse(r.data)['x-return-headers']).to.equal('yes');
|
||||
});
|
||||
|
||||
it('returns response multiple response headers with the same name', async () => {
|
||||
registerStreamProtocol(protocolName, (request, callback) => {
|
||||
callback({
|
||||
headers: {
|
||||
header1: ['value1', 'value2'],
|
||||
header2: 'value3'
|
||||
},
|
||||
data: getStream()
|
||||
});
|
||||
});
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
// SUBTLE: when the response headers have multiple values it
|
||||
// separates values by ", ". When the response headers are incorrectly
|
||||
// converting an array to a string it separates values by ",".
|
||||
expect(r.headers).to.have.property('header1', 'value1, value2');
|
||||
expect(r.headers).to.have.property('header2', 'value3');
|
||||
});
|
||||
|
||||
it('can handle large responses', async () => {
|
||||
const data = Buffer.alloc(128 * 1024);
|
||||
registerStreamProtocol(protocolName, (request, callback) => {
|
||||
callback(getStream(data.length, data));
|
||||
});
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
expect(r.data).to.have.lengthOf(data.length);
|
||||
});
|
||||
|
||||
it('can handle a stream completing while writing', async () => {
|
||||
function dumbPassthrough () {
|
||||
return new stream.Transform({
|
||||
async transform (chunk, encoding, cb) {
|
||||
cb(null, chunk);
|
||||
const w = new BrowserWindow({
|
||||
show: false,
|
||||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
contextIsolation: false
|
||||
}
|
||||
});
|
||||
}
|
||||
registerStreamProtocol(protocolName, (request, callback) => {
|
||||
callback({
|
||||
statusCode: 200,
|
||||
headers: { 'Content-Type': 'text/plain' },
|
||||
data: getStream(1024 * 1024, Buffer.alloc(1024 * 1024 * 2)).pipe(dumbPassthrough())
|
||||
});
|
||||
});
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
expect(r.data).to.have.lengthOf(1024 * 1024 * 2);
|
||||
});
|
||||
|
||||
it('can handle next-tick scheduling during read calls', async () => {
|
||||
const events = new EventEmitter();
|
||||
function createStream () {
|
||||
const buffers = [
|
||||
Buffer.alloc(65536),
|
||||
Buffer.alloc(65537),
|
||||
Buffer.alloc(39156)
|
||||
];
|
||||
const e = new stream.Readable({ highWaterMark: 0 });
|
||||
e.push(buffers.shift());
|
||||
e._read = function () {
|
||||
process.nextTick(() => this.push(buffers.shift() || null));
|
||||
};
|
||||
e.on('end', function () {
|
||||
events.emit('end');
|
||||
});
|
||||
return e;
|
||||
}
|
||||
registerStreamProtocol(protocolName, (request, callback) => {
|
||||
callback({
|
||||
statusCode: 200,
|
||||
headers: { 'Content-Type': 'text/plain' },
|
||||
data: createStream()
|
||||
});
|
||||
});
|
||||
const hasEndedPromise = emittedOnce(events, 'end');
|
||||
ajax(protocolName + '://fake-host').catch(() => {});
|
||||
await hasEndedPromise;
|
||||
});
|
||||
|
||||
it('destroys response streams when aborted before completion', async () => {
|
||||
const events = new EventEmitter();
|
||||
registerStreamProtocol(protocolName, (request, callback) => {
|
||||
const responseStream = new stream.PassThrough();
|
||||
responseStream.push('data\r\n');
|
||||
responseStream.on('close', () => {
|
||||
events.emit('close');
|
||||
});
|
||||
callback({
|
||||
statusCode: 200,
|
||||
headers: { 'Content-Type': 'text/plain' },
|
||||
data: responseStream
|
||||
});
|
||||
events.emit('respond');
|
||||
w.loadFile(path.join(__dirname, 'fixtures', 'pages', 'iframe-protocol.html'));
|
||||
ipcMain.once('loaded-iframe-custom-protocol', () => done());
|
||||
});
|
||||
|
||||
const hasRespondedPromise = emittedOnce(events, 'respond');
|
||||
const hasClosedPromise = emittedOnce(events, 'close');
|
||||
ajax(protocolName + '://fake-host').catch(() => {});
|
||||
await hasRespondedPromise;
|
||||
await contents.loadFile(path.join(__dirname, 'fixtures', 'pages', 'fetch.html'));
|
||||
await hasClosedPromise;
|
||||
it.skip('throws an error when custom headers are invalid', (done) => {
|
||||
registerFileProtocol(protocolName, (request, callback) => {
|
||||
expect(() => callback({
|
||||
path: filePath,
|
||||
headers: { 'X-Great-Header': (42 as any) }
|
||||
})).to.throw(Error, 'Value of \'X-Great-Header\' header has to be a string');
|
||||
done();
|
||||
});
|
||||
ajax(protocolName + '://fake-host').catch(() => {});
|
||||
});
|
||||
|
||||
it('sends object as response', async () => {
|
||||
registerFileProtocol(protocolName, (request, callback) => callback({ path: filePath }));
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
expect(r.data).to.equal(String(fileContent));
|
||||
});
|
||||
|
||||
it('can send normal file', async () => {
|
||||
registerFileProtocol(protocolName, (request, callback) => callback({ path: normalPath }));
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
expect(r.data).to.equal(String(normalContent));
|
||||
});
|
||||
|
||||
it('fails when sending unexist-file', async () => {
|
||||
const fakeFilePath = path.join(fixturesPath, 'test.asar', 'a.asar', 'not-exist');
|
||||
registerFileProtocol(protocolName, (request, callback) => callback({ path: fakeFilePath }));
|
||||
await expect(ajax(protocolName + '://fake-host')).to.be.eventually.rejected();
|
||||
});
|
||||
|
||||
it('fails when sending unsupported content', async () => {
|
||||
registerFileProtocol(protocolName, (request, callback) => callback(new Date() as any));
|
||||
await expect(ajax(protocolName + '://fake-host')).to.be.eventually.rejected();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
for (const [registerHttpProtocol, name] of [
|
||||
[protocol.registerHttpProtocol, 'protocol.registerHttpProtocol'] as const,
|
||||
[(protocol as any).registerProtocol as typeof protocol.registerHttpProtocol, 'protocol.registerProtocol'] as const
|
||||
]) {
|
||||
describe(name, () => {
|
||||
it('sends url as response', async () => {
|
||||
const server = http.createServer((req, res) => {
|
||||
expect(req.headers.accept).to.not.equal('');
|
||||
res.end(text);
|
||||
server.close();
|
||||
});
|
||||
await new Promise<void>(resolve => server.listen(0, '127.0.0.1', resolve));
|
||||
|
||||
const port = (server.address() as AddressInfo).port;
|
||||
const url = 'http://127.0.0.1:' + port;
|
||||
registerHttpProtocol(protocolName, (request, callback) => callback({ url }));
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
expect(r.data).to.equal(text);
|
||||
});
|
||||
|
||||
it('fails when sending invalid url', async () => {
|
||||
registerHttpProtocol(protocolName, (request, callback) => callback({ url: 'url' }));
|
||||
await expect(ajax(protocolName + '://fake-host')).to.be.eventually.rejected();
|
||||
});
|
||||
|
||||
it('fails when sending unsupported content', async () => {
|
||||
registerHttpProtocol(protocolName, (request, callback) => callback(new Date() as any));
|
||||
await expect(ajax(protocolName + '://fake-host')).to.be.eventually.rejected();
|
||||
});
|
||||
|
||||
it('works when target URL redirects', async () => {
|
||||
const server = http.createServer((req, res) => {
|
||||
if (req.url === '/serverRedirect') {
|
||||
res.statusCode = 301;
|
||||
res.setHeader('Location', `http://${req.rawHeaders[1]}`);
|
||||
res.end();
|
||||
} else {
|
||||
res.end(text);
|
||||
}
|
||||
});
|
||||
after(() => server.close());
|
||||
await new Promise<void>(resolve => server.listen(0, '127.0.0.1', resolve));
|
||||
|
||||
const port = (server.address() as AddressInfo).port;
|
||||
const url = `${protocolName}://fake-host`;
|
||||
const redirectURL = `http://127.0.0.1:${port}/serverRedirect`;
|
||||
registerHttpProtocol(protocolName, (request, callback) => callback({ url: redirectURL }));
|
||||
|
||||
const r = await ajax(url);
|
||||
expect(r.data).to.equal(text);
|
||||
});
|
||||
|
||||
it('can access request headers', (done) => {
|
||||
protocol.registerHttpProtocol(protocolName, (request) => {
|
||||
try {
|
||||
expect(request).to.have.property('headers');
|
||||
done();
|
||||
} catch (e) {
|
||||
done(e);
|
||||
}
|
||||
});
|
||||
ajax(protocolName + '://fake-host').catch(() => {});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
for (const [registerStreamProtocol, name] of [
|
||||
[protocol.registerStreamProtocol, 'protocol.registerStreamProtocol'] as const,
|
||||
[(protocol as any).registerProtocol as typeof protocol.registerStreamProtocol, 'protocol.registerProtocol'] as const
|
||||
]) {
|
||||
describe(name, () => {
|
||||
it('sends Stream as response', async () => {
|
||||
registerStreamProtocol(protocolName, (request, callback) => callback(getStream()));
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
expect(r.data).to.equal(text);
|
||||
});
|
||||
|
||||
it('sends object as response', async () => {
|
||||
registerStreamProtocol(protocolName, (request, callback) => callback({ data: getStream() }));
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
expect(r.data).to.equal(text);
|
||||
expect(r.status).to.equal(200);
|
||||
});
|
||||
|
||||
it('sends custom response headers', async () => {
|
||||
registerStreamProtocol(protocolName, (request, callback) => callback({
|
||||
data: getStream(3),
|
||||
headers: {
|
||||
'x-electron': ['a', 'b']
|
||||
}
|
||||
}));
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
expect(r.data).to.equal(text);
|
||||
expect(r.status).to.equal(200);
|
||||
expect(r.headers).to.have.property('x-electron', 'a, b');
|
||||
});
|
||||
|
||||
it('sends custom status code', async () => {
|
||||
registerStreamProtocol(protocolName, (request, callback) => callback({
|
||||
statusCode: 204,
|
||||
data: null as any
|
||||
}));
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
expect(r.data).to.be.empty('data');
|
||||
expect(r.status).to.equal(204);
|
||||
});
|
||||
|
||||
it('receives request headers', async () => {
|
||||
registerStreamProtocol(protocolName, (request, callback) => {
|
||||
callback({
|
||||
headers: {
|
||||
'content-type': 'application/json'
|
||||
},
|
||||
data: getStream(5, JSON.stringify(Object.assign({}, request.headers)))
|
||||
});
|
||||
});
|
||||
const r = await ajax(protocolName + '://fake-host', { headers: { 'x-return-headers': 'yes' } });
|
||||
expect(JSON.parse(r.data)['x-return-headers']).to.equal('yes');
|
||||
});
|
||||
|
||||
it('returns response multiple response headers with the same name', async () => {
|
||||
registerStreamProtocol(protocolName, (request, callback) => {
|
||||
callback({
|
||||
headers: {
|
||||
header1: ['value1', 'value2'],
|
||||
header2: 'value3'
|
||||
},
|
||||
data: getStream()
|
||||
});
|
||||
});
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
// SUBTLE: when the response headers have multiple values it
|
||||
// separates values by ", ". When the response headers are incorrectly
|
||||
// converting an array to a string it separates values by ",".
|
||||
expect(r.headers).to.have.property('header1', 'value1, value2');
|
||||
expect(r.headers).to.have.property('header2', 'value3');
|
||||
});
|
||||
|
||||
it('can handle large responses', async () => {
|
||||
const data = Buffer.alloc(128 * 1024);
|
||||
registerStreamProtocol(protocolName, (request, callback) => {
|
||||
callback(getStream(data.length, data));
|
||||
});
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
expect(r.data).to.have.lengthOf(data.length);
|
||||
});
|
||||
|
||||
it('can handle a stream completing while writing', async () => {
|
||||
function dumbPassthrough () {
|
||||
return new stream.Transform({
|
||||
async transform (chunk, encoding, cb) {
|
||||
cb(null, chunk);
|
||||
}
|
||||
});
|
||||
}
|
||||
registerStreamProtocol(protocolName, (request, callback) => {
|
||||
callback({
|
||||
statusCode: 200,
|
||||
headers: { 'Content-Type': 'text/plain' },
|
||||
data: getStream(1024 * 1024, Buffer.alloc(1024 * 1024 * 2)).pipe(dumbPassthrough())
|
||||
});
|
||||
});
|
||||
const r = await ajax(protocolName + '://fake-host');
|
||||
expect(r.data).to.have.lengthOf(1024 * 1024 * 2);
|
||||
});
|
||||
|
||||
it('can handle next-tick scheduling during read calls', async () => {
|
||||
const events = new EventEmitter();
|
||||
function createStream () {
|
||||
const buffers = [
|
||||
Buffer.alloc(65536),
|
||||
Buffer.alloc(65537),
|
||||
Buffer.alloc(39156)
|
||||
];
|
||||
const e = new stream.Readable({ highWaterMark: 0 });
|
||||
e.push(buffers.shift());
|
||||
e._read = function () {
|
||||
process.nextTick(() => this.push(buffers.shift() || null));
|
||||
};
|
||||
e.on('end', function () {
|
||||
events.emit('end');
|
||||
});
|
||||
return e;
|
||||
}
|
||||
registerStreamProtocol(protocolName, (request, callback) => {
|
||||
callback({
|
||||
statusCode: 200,
|
||||
headers: { 'Content-Type': 'text/plain' },
|
||||
data: createStream()
|
||||
});
|
||||
});
|
||||
const hasEndedPromise = emittedOnce(events, 'end');
|
||||
ajax(protocolName + '://fake-host').catch(() => {});
|
||||
await hasEndedPromise;
|
||||
});
|
||||
|
||||
it('destroys response streams when aborted before completion', async () => {
|
||||
const events = new EventEmitter();
|
||||
registerStreamProtocol(protocolName, (request, callback) => {
|
||||
const responseStream = new stream.PassThrough();
|
||||
responseStream.push('data\r\n');
|
||||
responseStream.on('close', () => {
|
||||
events.emit('close');
|
||||
});
|
||||
callback({
|
||||
statusCode: 200,
|
||||
headers: { 'Content-Type': 'text/plain' },
|
||||
data: responseStream
|
||||
});
|
||||
events.emit('respond');
|
||||
});
|
||||
|
||||
const hasRespondedPromise = emittedOnce(events, 'respond');
|
||||
const hasClosedPromise = emittedOnce(events, 'close');
|
||||
ajax(protocolName + '://fake-host').catch(() => {});
|
||||
await hasRespondedPromise;
|
||||
await contents.loadFile(path.join(__dirname, 'fixtures', 'pages', 'fetch.html'));
|
||||
await hasClosedPromise;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
describe('protocol.isProtocolRegistered', () => {
|
||||
it('returns false when scheme is not registered', () => {
|
||||
|
||||
@@ -1619,7 +1619,7 @@ describe('webContents module', () => {
|
||||
await w.webContents.loadURL('about:blank');
|
||||
const promise: Promise<[string, string]> = new Promise(resolve => {
|
||||
w.webContents.once('ipc-message-sync', (event, channel, arg) => {
|
||||
event.returnValue = 'foobar' as any;
|
||||
event.returnValue = 'foobar';
|
||||
resolve([channel, arg]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// tslint:disable:ordered-imports curly no-console no-angle-bracket-type-assertion object-literal-sort-keys only-arrow-functions
|
||||
/* eslint-disable */
|
||||
|
||||
import {
|
||||
app,
|
||||
@@ -23,14 +24,13 @@ import {
|
||||
session,
|
||||
systemPreferences,
|
||||
webContents,
|
||||
Event,
|
||||
TouchBar
|
||||
} from 'electron'
|
||||
|
||||
import * as path from 'path'
|
||||
|
||||
// Quick start
|
||||
// https://github.com/electron/electron/blob/master/docs/tutorial/quick-start.md
|
||||
// https://github.com/electron/electron/blob/main/docs/tutorial/quick-start.md
|
||||
|
||||
// Keep a global reference of the window object, if you don't, the window will
|
||||
// be closed automatically when the javascript object is GCed.
|
||||
@@ -318,7 +318,7 @@ app.setAboutPanelOptions({
|
||||
})
|
||||
|
||||
// Online/Offline Event Detection
|
||||
// https://github.com/electron/electron/blob/master/docs/tutorial/online-offline-events.md
|
||||
// https://github.com/electron/electron/blob/main/docs/tutorial/online-offline-events.md
|
||||
|
||||
let onlineStatusWindow: Electron.BrowserWindow
|
||||
|
||||
@@ -328,12 +328,12 @@ app.whenReady().then(() => {
|
||||
})
|
||||
app.on('accessibility-support-changed', (_, enabled) => console.log('accessibility: ' + enabled))
|
||||
|
||||
ipcMain.on('online-status-changed', (event: any, status: any) => {
|
||||
ipcMain.on('online-status-changed', (event, status: any) => {
|
||||
console.log(status)
|
||||
})
|
||||
|
||||
// Synopsis
|
||||
// https://github.com/electron/electron/blob/master/docs/api/synopsis.md
|
||||
// https://github.com/electron/electron/blob/main/docs/api/synopsis.md
|
||||
|
||||
app.whenReady().then(() => {
|
||||
window = new BrowserWindow({
|
||||
@@ -345,14 +345,14 @@ app.whenReady().then(() => {
|
||||
})
|
||||
|
||||
// Supported command line switches
|
||||
// https://github.com/electron/electron/blob/master/docs/api/command-line-switches.md
|
||||
// https://github.com/electron/electron/blob/main/docs/api/command-line-switches.md
|
||||
|
||||
app.commandLine.appendSwitch('remote-debugging-port', '8315')
|
||||
app.commandLine.appendSwitch('host-rules', 'MAP * 127.0.0.1')
|
||||
app.commandLine.appendSwitch('vmodule', 'console=0')
|
||||
|
||||
// systemPreferences
|
||||
// https://github.com/electron/electron/blob/master/docs/api/system-preferences.md
|
||||
// https://github.com/electron/electron/blob/main/docs/api/system-preferences.md
|
||||
|
||||
const browserOptions = {
|
||||
width: 1000,
|
||||
@@ -391,7 +391,7 @@ if (browserOptions.transparent) {
|
||||
}
|
||||
|
||||
// app
|
||||
// https://github.com/electron/electron/blob/master/docs/api/app.md
|
||||
// https://github.com/electron/electron/blob/main/docs/api/app.md
|
||||
|
||||
app.on('certificate-error', function (event, webContents, url, error, certificate, callback) {
|
||||
if (url === 'https://github.com') {
|
||||
@@ -422,7 +422,7 @@ app.relaunch({ args: process.argv.slice(1).concat(['--relaunch']) })
|
||||
app.exit(0)
|
||||
|
||||
// auto-updater
|
||||
// https://github.com/electron/electron/blob/master/docs/api/auto-updater.md
|
||||
// https://github.com/electron/electron/blob/main/docs/api/auto-updater.md
|
||||
|
||||
autoUpdater.setFeedURL({
|
||||
url: 'http://mycompany.com/myapp/latest?version=' + app.getVersion(),
|
||||
@@ -443,7 +443,7 @@ autoUpdater.on('update-downloaded', (event, releaseNotes, releaseName, releaseDa
|
||||
})
|
||||
|
||||
// BrowserWindow
|
||||
// https://github.com/electron/electron/blob/master/docs/api/browser-window.md
|
||||
// https://github.com/electron/electron/blob/main/docs/api/browser-window.md
|
||||
|
||||
let win3 = new BrowserWindow({ width: 800, height: 600, show: false })
|
||||
win3.on('closed', () => {
|
||||
@@ -469,7 +469,7 @@ window.setVibrancy('popover')
|
||||
window.setIcon('/path/to/icon')
|
||||
|
||||
// content-tracing
|
||||
// https://github.com/electron/electron/blob/master/docs/api/content-tracing.md
|
||||
// https://github.com/electron/electron/blob/main/docs/api/content-tracing.md
|
||||
|
||||
const options = {
|
||||
categoryFilter: '*',
|
||||
@@ -486,7 +486,7 @@ contentTracing.startRecording(options).then(() => {
|
||||
})
|
||||
|
||||
// dialog
|
||||
// https://github.com/electron/electron/blob/master/docs/api/dialog.md
|
||||
// https://github.com/electron/electron/blob/main/docs/api/dialog.md
|
||||
|
||||
// variant without browserWindow
|
||||
dialog.showOpenDialogSync({
|
||||
@@ -507,7 +507,7 @@ dialog.showOpenDialog(win3, {
|
||||
})
|
||||
|
||||
// global-shortcut
|
||||
// https://github.com/electron/electron/blob/master/docs/api/global-shortcut.md
|
||||
// https://github.com/electron/electron/blob/main/docs/api/global-shortcut.md
|
||||
|
||||
// Register a 'ctrl+x' shortcut listener.
|
||||
const ret = globalShortcut.register('ctrl+x', () => {
|
||||
@@ -525,7 +525,7 @@ globalShortcut.unregister('ctrl+x')
|
||||
globalShortcut.unregisterAll()
|
||||
|
||||
// ipcMain
|
||||
// https://github.com/electron/electron/blob/master/docs/api/ipc-main-process.md
|
||||
// https://github.com/electron/electron/blob/main/docs/api/ipc-main.md
|
||||
|
||||
ipcMain.on('asynchronous-message', (event, arg: any) => {
|
||||
console.log(arg) // prints "ping"
|
||||
@@ -551,7 +551,7 @@ const winWindows = new BrowserWindow({
|
||||
})
|
||||
|
||||
// menu-item
|
||||
// https://github.com/electron/electron/blob/master/docs/api/menu-item.md
|
||||
// https://github.com/electron/electron/blob/main/docs/api/menu-item.md
|
||||
|
||||
const menuItem = new MenuItem({})
|
||||
|
||||
@@ -561,7 +561,7 @@ menuItem.click = (passedMenuItem: Electron.MenuItem, browserWindow: Electron.Bro
|
||||
}
|
||||
|
||||
// menu
|
||||
// https://github.com/electron/electron/blob/master/docs/api/menu.md
|
||||
// https://github.com/electron/electron/blob/main/docs/api/menu.md
|
||||
|
||||
let menu = new Menu()
|
||||
menu.append(new MenuItem({ label: 'MenuItem1', click: () => { console.log('item 1 clicked') } }))
|
||||
@@ -809,7 +809,7 @@ Menu.buildFromTemplate([
|
||||
])
|
||||
|
||||
// net
|
||||
// https://github.com/electron/electron/blob/master/docs/api/net.md
|
||||
// https://github.com/electron/electron/blob/main/docs/api/net.md
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const request = net.request('https://github.com')
|
||||
@@ -854,7 +854,7 @@ app.whenReady().then(() => {
|
||||
})
|
||||
|
||||
// power-monitor
|
||||
// https://github.com/electron/electron/blob/master/docs/api/power-monitor.md
|
||||
// https://github.com/electron/electron/blob/main/docs/api/power-monitor.md
|
||||
|
||||
app.whenReady().then(() => {
|
||||
powerMonitor.on('suspend', () => {
|
||||
@@ -872,7 +872,7 @@ app.whenReady().then(() => {
|
||||
})
|
||||
|
||||
// power-save-blocker
|
||||
// https://github.com/electron/electron/blob/master/docs/api/power-save-blocker.md
|
||||
// https://github.com/electron/electron/blob/main/docs/api/power-save-blocker.md
|
||||
|
||||
const id = powerSaveBlocker.start('prevent-display-sleep')
|
||||
console.log(powerSaveBlocker.isStarted(id))
|
||||
@@ -880,7 +880,7 @@ console.log(powerSaveBlocker.isStarted(id))
|
||||
powerSaveBlocker.stop(id)
|
||||
|
||||
// protocol
|
||||
// https://github.com/electron/electron/blob/master/docs/api/protocol.md
|
||||
// https://github.com/electron/electron/blob/main/docs/api/protocol.md
|
||||
|
||||
app.whenReady().then(() => {
|
||||
protocol.registerSchemesAsPrivileged([{ scheme: 'https', privileges: { standard: true, allowServiceWorkers: true } }])
|
||||
@@ -907,7 +907,7 @@ app.whenReady().then(() => {
|
||||
})
|
||||
|
||||
// tray
|
||||
// https://github.com/electron/electron/blob/master/docs/api/tray.md
|
||||
// https://github.com/electron/electron/blob/main/docs/api/tray.md
|
||||
|
||||
let appIcon: Electron.Tray = null
|
||||
app.whenReady().then(() => {
|
||||
@@ -950,7 +950,7 @@ app.whenReady().then(() => {
|
||||
})
|
||||
|
||||
// clipboard
|
||||
// https://github.com/electron/electron/blob/master/docs/api/clipboard.md
|
||||
// https://github.com/electron/electron/blob/main/docs/api/clipboard.md
|
||||
|
||||
{
|
||||
let str: string
|
||||
@@ -973,7 +973,7 @@ app.whenReady().then(() => {
|
||||
}
|
||||
|
||||
// crash-reporter
|
||||
// https://github.com/electron/electron/blob/master/docs/api/crash-reporter.md
|
||||
// https://github.com/electron/electron/blob/main/docs/api/crash-reporter.md
|
||||
|
||||
crashReporter.start({
|
||||
productName: 'YourName',
|
||||
@@ -989,7 +989,7 @@ console.log(crashReporter.getLastCrashReport())
|
||||
console.log(crashReporter.getUploadedReports())
|
||||
|
||||
// nativeImage
|
||||
// https://github.com/electron/electron/blob/master/docs/api/native-image.md
|
||||
// https://github.com/electron/electron/blob/main/docs/api/native-image.md
|
||||
|
||||
const appIcon2 = new Tray('/Users/somebody/images/icon.png')
|
||||
const window2 = new BrowserWindow({ icon: '/Users/somebody/images/window.png' })
|
||||
@@ -1000,7 +1000,7 @@ const appIcon4 = new Tray('/Users/somebody/images/icon.png')
|
||||
const image2 = nativeImage.createFromPath('/Users/somebody/images/icon.png')
|
||||
|
||||
// process
|
||||
// https://github.com/electron/electron/blob/master/docs/api/process.md
|
||||
// https://github.com/electron/electron/blob/main/docs/api/process.md
|
||||
|
||||
console.log(process.versions.electron)
|
||||
console.log(process.versions.chrome)
|
||||
@@ -1014,7 +1014,7 @@ process.hang()
|
||||
process.setFdLimit(8192)
|
||||
|
||||
// screen
|
||||
// https://github.com/electron/electron/blob/master/docs/api/screen.md
|
||||
// https://github.com/electron/electron/blob/main/docs/api/screen.md
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const size = screen.getPrimaryDisplay().workAreaSize
|
||||
@@ -1052,7 +1052,7 @@ app.whenReady().then(() => {
|
||||
})
|
||||
|
||||
// shell
|
||||
// https://github.com/electron/electron/blob/master/docs/api/shell.md
|
||||
// https://github.com/electron/electron/blob/main/docs/api/shell.md
|
||||
|
||||
shell.showItemInFolder('/home/user/Desktop/test.txt')
|
||||
shell.trashItem('/home/user/Desktop/test.txt').then(() => {})
|
||||
@@ -1070,7 +1070,7 @@ shell.beep()
|
||||
shell.writeShortcutLink('/home/user/Desktop/shortcut.lnk', 'update', shell.readShortcutLink('/home/user/Desktop/shortcut.lnk'))
|
||||
|
||||
// cookies
|
||||
// https://github.com/electron/electron/blob/master/docs/api/cookies.md
|
||||
// https://github.com/electron/electron/blob/main/docs/api/cookies.md
|
||||
{
|
||||
// Query all cookies.
|
||||
session.defaultSession.cookies.get({})
|
||||
@@ -1100,7 +1100,7 @@ shell.writeShortcutLink('/home/user/Desktop/shortcut.lnk', 'update', shell.readS
|
||||
}
|
||||
|
||||
// session
|
||||
// https://github.com/electron/electron/blob/master/docs/api/session.md
|
||||
// https://github.com/electron/electron/blob/main/docs/api/session.md
|
||||
|
||||
session.defaultSession.on('will-download', (event, item, webContents) => {
|
||||
event.preventDefault()
|
||||
@@ -1197,7 +1197,7 @@ app.whenReady().then(function () {
|
||||
})
|
||||
|
||||
// webContents
|
||||
// https://github.com/electron/electron/blob/master/docs/api/web-contents.md
|
||||
// https://github.com/electron/electron/blob/main/docs/api/web-contents.md
|
||||
|
||||
console.log(webContents.getAllWebContents())
|
||||
console.log(webContents.getFocusedWebContents())
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
import * as fs from 'fs'
|
||||
|
||||
// In renderer process (web page).
|
||||
// https://github.com/electron/electron/blob/master/docs/api/ipc-renderer.md
|
||||
// https://github.com/electron/electron/blob/main/docs/api/ipc-renderer.md
|
||||
console.log(ipcRenderer.sendSync('synchronous-message', 'ping')) // prints "pong"
|
||||
|
||||
ipcRenderer.on('asynchronous-reply', (event, arg: any) => {
|
||||
@@ -22,7 +22,7 @@ ipcRenderer.on('asynchronous-reply', (event, arg: any) => {
|
||||
ipcRenderer.send('asynchronous-message', 'ping')
|
||||
|
||||
// web-frame
|
||||
// https://github.com/electron/electron/blob/master/docs/api/web-frame.md
|
||||
// https://github.com/electron/electron/blob/main/docs/api/web-frame.md
|
||||
|
||||
webFrame.setZoomFactor(2)
|
||||
console.log(webFrame.getZoomFactor())
|
||||
@@ -53,7 +53,7 @@ console.log(webFrame.getResourceUsage())
|
||||
webFrame.clearCache()
|
||||
|
||||
// clipboard
|
||||
// https://github.com/electron/electron/blob/master/docs/api/clipboard.md
|
||||
// https://github.com/electron/electron/blob/main/docs/api/clipboard.md
|
||||
|
||||
clipboard.writeText('Example String')
|
||||
clipboard.writeText('Example String', 'selection')
|
||||
@@ -69,7 +69,7 @@ clipboard.write({
|
||||
})
|
||||
|
||||
// crash-reporter
|
||||
// https://github.com/electron/electron/blob/master/docs/api/crash-reporter.md
|
||||
// https://github.com/electron/electron/blob/main/docs/api/crash-reporter.md
|
||||
|
||||
crashReporter.start({
|
||||
productName: 'YourName',
|
||||
@@ -79,7 +79,7 @@ crashReporter.start({
|
||||
})
|
||||
|
||||
// desktopCapturer
|
||||
// https://github.com/electron/electron/blob/master/docs/api/desktop-capturer.md
|
||||
// https://github.com/electron/electron/blob/main/docs/api/desktop-capturer.md
|
||||
|
||||
desktopCapturer.getSources({ types: ['window', 'screen'] }).then(sources => {
|
||||
for (let i = 0; i < sources.length; ++i) {
|
||||
@@ -111,7 +111,7 @@ function getUserMediaError (error: Error) {
|
||||
}
|
||||
|
||||
// File object
|
||||
// https://github.com/electron/electron/blob/master/docs/api/file-object.md
|
||||
// https://github.com/electron/electron/blob/main/docs/api/file-object.md
|
||||
|
||||
/*
|
||||
<div id="holder">
|
||||
@@ -137,11 +137,11 @@ holder.ondrop = function (e) {
|
||||
}
|
||||
|
||||
// nativeImage
|
||||
// https://github.com/electron/electron/blob/master/docs/api/native-image.md
|
||||
// https://github.com/electron/electron/blob/main/docs/api/native-image.md
|
||||
|
||||
const image = clipboard.readImage()
|
||||
|
||||
// https://github.com/electron/electron/blob/master/docs/api/process.md
|
||||
// https://github.com/electron/electron/blob/main/docs/api/process.md
|
||||
|
||||
// preload.js
|
||||
const _setImmediate = setImmediate
|
||||
@@ -152,12 +152,12 @@ process.once('loaded', function () {
|
||||
})
|
||||
|
||||
// shell
|
||||
// https://github.com/electron/electron/blob/master/docs/api/shell.md
|
||||
// https://github.com/electron/electron/blob/main/docs/api/shell.md
|
||||
|
||||
shell.openExternal('https://github.com').then(() => {})
|
||||
|
||||
// <webview>
|
||||
// https://github.com/electron/electron/blob/master/docs/api/web-view-tag.md
|
||||
// https://github.com/electron/electron/blob/main/docs/api/webview-tag.md
|
||||
|
||||
const webview = document.createElement('webview')
|
||||
webview.loadURL('https://github.com')
|
||||
|
||||
4
typings/internal-ambient.d.ts
vendored
4
typings/internal-ambient.d.ts
vendored
@@ -197,10 +197,6 @@ declare namespace NodeJS {
|
||||
_linkedBinding(name: 'electron_browser_desktop_capturer'): {
|
||||
createDesktopCapturer(): ElectronInternal.DesktopCapturer;
|
||||
};
|
||||
_linkedBinding(name: 'electron_browser_event'): {
|
||||
createWithSender(sender: Electron.WebContents): Electron.Event;
|
||||
createEmpty(): Electron.Event;
|
||||
};
|
||||
_linkedBinding(name: 'electron_browser_event_emitter'): {
|
||||
setEventEmitterPrototype(prototype: Object): void;
|
||||
};
|
||||
|
||||
16
typings/internal-electron.d.ts
vendored
16
typings/internal-electron.d.ts
vendored
@@ -110,7 +110,7 @@ declare namespace Electron {
|
||||
_shouldRegisterAcceleratorForCommandId(id: string): boolean;
|
||||
_getSharingItemForCommandId(id: string): SharingItem | null;
|
||||
_callMenuWillShow(): void;
|
||||
_executeCommand(event: any, id: number): void;
|
||||
_executeCommand(event: KeyboardEvent, id: number): void;
|
||||
_menuWillShow(): void;
|
||||
commandsMap: Record<string, MenuItem>;
|
||||
groupsMap: Record<string, MenuItem[]>;
|
||||
@@ -138,14 +138,16 @@ declare namespace Electron {
|
||||
acceleratorWorksWhenHidden?: boolean;
|
||||
}
|
||||
|
||||
interface IpcMainEvent {
|
||||
interface ReplyChannel {
|
||||
sendReply(value: any): void;
|
||||
}
|
||||
|
||||
interface IpcMainEvent {
|
||||
_replyChannel: ReplyChannel;
|
||||
}
|
||||
|
||||
interface IpcMainInvokeEvent {
|
||||
sendReply(value: any): void;
|
||||
_reply(value: any): void;
|
||||
_throw(error: Error | string): void;
|
||||
_replyChannel: ReplyChannel;
|
||||
}
|
||||
|
||||
class View {}
|
||||
@@ -222,10 +224,6 @@ declare namespace ElectronInternal {
|
||||
once(channel: string, listener: (event: IpcMainInternalEvent, ...args: any[]) => void): this;
|
||||
}
|
||||
|
||||
interface Event extends Electron.Event {
|
||||
sender: WebContents;
|
||||
}
|
||||
|
||||
interface LoadURLOptions extends Electron.LoadURLOptions {
|
||||
reloadIgnoringCache?: boolean;
|
||||
}
|
||||
|
||||
172
yarn.lock
172
yarn.lock
@@ -134,10 +134,10 @@
|
||||
optionalDependencies:
|
||||
"@types/glob" "^7.1.1"
|
||||
|
||||
"@electron/docs-parser@^1.0.0":
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@electron/docs-parser/-/docs-parser-1.0.1.tgz#f9856d00ec1663a0fb6301f55bc674f44c7dc543"
|
||||
integrity sha512-jqUHwo3MWUhWusHtTVpSHTZqWSVuc1sPUfavI5Zwdx64q7qd4phqOPGoxScWS3JthKt7Wydvo/eReIUNDJ0gRg==
|
||||
"@electron/docs-parser@^1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@electron/docs-parser/-/docs-parser-1.1.0.tgz#ba095def41746bde56bee731feaf22272bf0b765"
|
||||
integrity sha512-qrjIKJk8t4/xAYldDVNQgcF8zdAAuG260bzPxdh/xI3p/yddm61bftoct+Tx2crnWFnOfOkr6nGERsDknNiT8A==
|
||||
dependencies:
|
||||
"@types/markdown-it" "^12.0.0"
|
||||
chai "^4.2.0"
|
||||
@@ -187,10 +187,10 @@
|
||||
"@octokit/auth-app" "^3.6.1"
|
||||
"@octokit/rest" "^18.12.0"
|
||||
|
||||
"@electron/typescript-definitions@^8.10.0":
|
||||
version "8.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@electron/typescript-definitions/-/typescript-definitions-8.10.0.tgz#e9cf2b329ec4b0b76947ef751725383a6cf8994d"
|
||||
integrity sha512-FVc2y0GUfxFZDoma0scYiMxkoalle19Fq332fNFGWoCJ9rCj5OUvriewSjPtGBsRuHv2xaMS5MhBuy2/pRuFuQ==
|
||||
"@electron/typescript-definitions@^8.14.0":
|
||||
version "8.14.0"
|
||||
resolved "https://registry.yarnpkg.com/@electron/typescript-definitions/-/typescript-definitions-8.14.0.tgz#a88f74e915317ba943b57ffe499b319d04f01ee3"
|
||||
integrity sha512-J3b4is6L0NB4+r+7s1Hl1YlzaveKnQt1gswadRyMRwb4gFU3VAe2oBMJLOhFRJMs/9PK/Xp+y9QwyC92Tyqe6A==
|
||||
dependencies:
|
||||
"@types/node" "^11.13.7"
|
||||
chalk "^2.4.2"
|
||||
@@ -349,13 +349,6 @@
|
||||
btoa-lite "^1.0.0"
|
||||
universal-user-agent "^6.0.0"
|
||||
|
||||
"@octokit/auth-token@^2.4.0":
|
||||
version "2.4.2"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-2.4.2.tgz#10d0ae979b100fa6b72fa0e8e63e27e6d0dbff8a"
|
||||
integrity sha512-jE/lE/IKIz2v1+/P0u4fJqv0kYwXOTujKemJMFr6FeopsxlIK3+wKDCJGnysg81XID5TgZQbIfuJ5J0lnTiuyQ==
|
||||
dependencies:
|
||||
"@octokit/types" "^5.0.0"
|
||||
|
||||
"@octokit/auth-token@^2.4.4":
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-2.5.0.tgz#27c37ea26c205f28443402477ffd261311f21e36"
|
||||
@@ -363,17 +356,12 @@
|
||||
dependencies:
|
||||
"@octokit/types" "^6.0.3"
|
||||
|
||||
"@octokit/core@^3.0.0":
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/core/-/core-3.1.1.tgz#1856745aa8fb154cf1544a2a1b82586c809c5e66"
|
||||
integrity sha512-cQ2HGrtyNJ1IBxpTP1U5m/FkMAJvgw7d2j1q3c9P0XUuYilEgF6e4naTpsgm4iVcQeOnccZlw7XHRIUBy0ymcg==
|
||||
"@octokit/auth-token@^3.0.0":
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-3.0.3.tgz#ce7e48a3166731f26068d7a7a7996b5da58cbe0c"
|
||||
integrity sha512-/aFM2M4HVDBT/jjDBa84sJniv1t9Gm/rLkalaz9htOm+L+8JMj1k9w0CkUdcxNyNxZPlTxKPVko+m1VlM58ZVA==
|
||||
dependencies:
|
||||
"@octokit/auth-token" "^2.4.0"
|
||||
"@octokit/graphql" "^4.3.1"
|
||||
"@octokit/request" "^5.4.0"
|
||||
"@octokit/types" "^5.0.0"
|
||||
before-after-hook "^2.1.0"
|
||||
universal-user-agent "^6.0.0"
|
||||
"@octokit/types" "^9.0.0"
|
||||
|
||||
"@octokit/core@^3.5.1":
|
||||
version "3.6.0"
|
||||
@@ -388,6 +376,19 @@
|
||||
before-after-hook "^2.2.0"
|
||||
universal-user-agent "^6.0.0"
|
||||
|
||||
"@octokit/core@^4.1.0":
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/core/-/core-4.2.0.tgz#8c253ba9605aca605bc46187c34fcccae6a96648"
|
||||
integrity sha512-AgvDRUg3COpR82P7PBdGZF/NNqGmtMq2NiPqeSsDIeCfYFOZ9gddqWNQHnFdEUf+YwOj4aZYmJnlPp7OXmDIDg==
|
||||
dependencies:
|
||||
"@octokit/auth-token" "^3.0.0"
|
||||
"@octokit/graphql" "^5.0.0"
|
||||
"@octokit/request" "^6.0.0"
|
||||
"@octokit/request-error" "^3.0.0"
|
||||
"@octokit/types" "^9.0.0"
|
||||
before-after-hook "^2.2.0"
|
||||
universal-user-agent "^6.0.0"
|
||||
|
||||
"@octokit/endpoint@^6.0.1":
|
||||
version "6.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-6.0.5.tgz#43a6adee813c5ffd2f719e20cfd14a1fee7c193a"
|
||||
@@ -406,15 +407,6 @@
|
||||
is-plain-object "^5.0.0"
|
||||
universal-user-agent "^6.0.0"
|
||||
|
||||
"@octokit/graphql@^4.3.1":
|
||||
version "4.5.3"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-4.5.3.tgz#d5ff0d4a8a33e98614a2a7359dac98bc285e062f"
|
||||
integrity sha512-JyYvi3j2tOb5ofASEpcg1Advs07H+Ag+I+ez7buuZfNVAmh1IYcDTuxd4gnYH8S2PSGu+f5IdDGxMmkK+5zsdA==
|
||||
dependencies:
|
||||
"@octokit/request" "^5.3.0"
|
||||
"@octokit/types" "^5.0.0"
|
||||
universal-user-agent "^6.0.0"
|
||||
|
||||
"@octokit/graphql@^4.5.8":
|
||||
version "4.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-4.8.0.tgz#664d9b11c0e12112cbf78e10f49a05959aa22cc3"
|
||||
@@ -424,6 +416,15 @@
|
||||
"@octokit/types" "^6.0.3"
|
||||
universal-user-agent "^6.0.0"
|
||||
|
||||
"@octokit/graphql@^5.0.0":
|
||||
version "5.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-5.0.5.tgz#a4cb3ea73f83b861893a6370ee82abb36e81afd2"
|
||||
integrity sha512-Qwfvh3xdqKtIznjX9lz2D458r7dJPP8l6r4GQkIdWQouZwHQK0mVT88uwiU2bdTU2OtT1uOlKpRciUWldpG0yQ==
|
||||
dependencies:
|
||||
"@octokit/request" "^6.0.0"
|
||||
"@octokit/types" "^9.0.0"
|
||||
universal-user-agent "^6.0.0"
|
||||
|
||||
"@octokit/oauth-authorization-url@^4.3.1":
|
||||
version "4.3.3"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/oauth-authorization-url/-/oauth-authorization-url-4.3.3.tgz#6a6ef38f243086fec882b62744f39b517528dfb9"
|
||||
@@ -466,6 +467,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-14.0.0.tgz#949c5019028c93f189abbc2fb42f333290f7134a"
|
||||
integrity sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw==
|
||||
|
||||
"@octokit/openapi-types@^16.0.0":
|
||||
version "16.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-16.0.0.tgz#d92838a6cd9fb4639ca875ddb3437f1045cc625e"
|
||||
integrity sha512-JbFWOqTJVLHZSUUoF4FzAZKYtqdxWu9Z5m2QQnOyEa04fOFljvyh7D3GYKbfuaSWisqehImiVIMG4eyJeP5VEA==
|
||||
|
||||
"@octokit/plugin-paginate-rest@^2.16.8":
|
||||
version "2.21.3"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz#7f12532797775640dbb8224da577da7dc210c87e"
|
||||
@@ -473,31 +479,18 @@
|
||||
dependencies:
|
||||
"@octokit/types" "^6.40.0"
|
||||
|
||||
"@octokit/plugin-paginate-rest@^2.2.0":
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.3.0.tgz#7d1073e56cfd15d3f99dcfe81fa5d2b466f3a6f6"
|
||||
integrity sha512-Ye2ZJreP0ZlqJQz8fz+hXvrEAEYK4ay7br1eDpWzr6j76VXs/gKqxFcH8qRzkB3fo/2xh4Vy9VtGii4ZDc9qlA==
|
||||
"@octokit/plugin-paginate-rest@^6.0.0":
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.0.0.tgz#f34b5a7d9416019126042cd7d7b811e006c0d561"
|
||||
integrity sha512-Sq5VU1PfT6/JyuXPyt04KZNVsFOSBaYOAq2QRZUwzVlI10KFvcbUo8lR258AAQL1Et60b0WuVik+zOWKLuDZxw==
|
||||
dependencies:
|
||||
"@octokit/types" "^5.2.0"
|
||||
|
||||
"@octokit/plugin-request-log@^1.0.0":
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-1.0.0.tgz#eef87a431300f6148c39a7f75f8cfeb218b2547e"
|
||||
integrity sha512-ywoxP68aOT3zHCLgWZgwUJatiENeHE7xJzYjfz8WI0goynp96wETBF+d95b8g/uL4QmS6owPVlaxiz3wyMAzcw==
|
||||
"@octokit/types" "^9.0.0"
|
||||
|
||||
"@octokit/plugin-request-log@^1.0.4":
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz#5e50ed7083a613816b1e4a28aeec5fb7f1462e85"
|
||||
integrity sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==
|
||||
|
||||
"@octokit/plugin-rest-endpoint-methods@4.1.2":
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-4.1.2.tgz#546a8f3e0b514f434a4ad4ef926005f1c81a5a5a"
|
||||
integrity sha512-PTI7wpbGEZ2IR87TVh+TNWaLcgX/RsZQalFbQCq8XxYUrQ36RHyERrHSNXFy5gkWpspUAOYRSV707JJv6BhqJA==
|
||||
dependencies:
|
||||
"@octokit/types" "^5.1.1"
|
||||
deprecation "^2.3.1"
|
||||
|
||||
"@octokit/plugin-rest-endpoint-methods@^5.12.0":
|
||||
version "5.16.2"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz#7ee8bf586df97dd6868cf68f641354e908c25342"
|
||||
@@ -506,14 +499,13 @@
|
||||
"@octokit/types" "^6.39.0"
|
||||
deprecation "^2.3.1"
|
||||
|
||||
"@octokit/request-error@^2.0.0":
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-2.0.2.tgz#0e76b83f5d8fdda1db99027ea5f617c2e6ba9ed0"
|
||||
integrity sha512-2BrmnvVSV1MXQvEkrb9zwzP0wXFNbPJij922kYBTLIlIafukrGOb+ABBT2+c6wZiuyWDH1K1zmjGQ0toN/wMWw==
|
||||
"@octokit/plugin-rest-endpoint-methods@^7.0.0":
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.0.1.tgz#f7ebe18144fd89460f98f35a587b056646e84502"
|
||||
integrity sha512-pnCaLwZBudK5xCdrR823xHGNgqOzRnJ/mpC/76YPpNP7DybdsJtP7mdOwh+wYZxK5jqeQuhu59ogMI4NRlBUvA==
|
||||
dependencies:
|
||||
"@octokit/types" "^5.0.1"
|
||||
deprecation "^2.0.0"
|
||||
once "^1.4.0"
|
||||
"@octokit/types" "^9.0.0"
|
||||
deprecation "^2.3.1"
|
||||
|
||||
"@octokit/request-error@^2.0.5", "@octokit/request-error@^2.1.0":
|
||||
version "2.1.0"
|
||||
@@ -533,20 +525,6 @@
|
||||
deprecation "^2.0.0"
|
||||
once "^1.4.0"
|
||||
|
||||
"@octokit/request@^5.3.0", "@octokit/request@^5.4.0":
|
||||
version "5.4.7"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.4.7.tgz#fd703ee092e0463ceba49ff7a3e61cb4cf8a0fde"
|
||||
integrity sha512-FN22xUDP0i0uF38YMbOfx6TotpcENP5W8yJM1e/LieGXn6IoRxDMnBf7tx5RKSW4xuUZ/1P04NFZy5iY3Rax1A==
|
||||
dependencies:
|
||||
"@octokit/endpoint" "^6.0.1"
|
||||
"@octokit/request-error" "^2.0.0"
|
||||
"@octokit/types" "^5.0.0"
|
||||
deprecation "^2.0.0"
|
||||
is-plain-object "^4.0.0"
|
||||
node-fetch "^2.3.0"
|
||||
once "^1.4.0"
|
||||
universal-user-agent "^6.0.0"
|
||||
|
||||
"@octokit/request@^5.4.14", "@octokit/request@^5.6.0", "@octokit/request@^5.6.3":
|
||||
version "5.6.3"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.6.3.tgz#19a022515a5bba965ac06c9d1334514eb50c48b0"
|
||||
@@ -571,16 +549,6 @@
|
||||
node-fetch "^2.6.7"
|
||||
universal-user-agent "^6.0.0"
|
||||
|
||||
"@octokit/rest@^18.0.3":
|
||||
version "18.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-18.0.3.tgz#96a15ddb3a38dca5de9d75121378d6aa4a234fa5"
|
||||
integrity sha512-GubgemnLvUJlkhouTM2BtX+g/voYT/Mqh0SASGwTnLvSkW1irjt14N911/ABb6m1Hru0TwScOgFgMFggp3igfQ==
|
||||
dependencies:
|
||||
"@octokit/core" "^3.0.0"
|
||||
"@octokit/plugin-paginate-rest" "^2.2.0"
|
||||
"@octokit/plugin-request-log" "^1.0.0"
|
||||
"@octokit/plugin-rest-endpoint-methods" "4.1.2"
|
||||
|
||||
"@octokit/rest@^18.12.0":
|
||||
version "18.12.0"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-18.12.0.tgz#f06bc4952fc87130308d810ca9d00e79f6988881"
|
||||
@@ -591,7 +559,17 @@
|
||||
"@octokit/plugin-request-log" "^1.0.4"
|
||||
"@octokit/plugin-rest-endpoint-methods" "^5.12.0"
|
||||
|
||||
"@octokit/types@^5.0.0", "@octokit/types@^5.0.1", "@octokit/types@^5.1.1", "@octokit/types@^5.2.0":
|
||||
"@octokit/rest@^19.0.7":
|
||||
version "19.0.7"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-19.0.7.tgz#d2e21b4995ab96ae5bfae50b4969da7e04e0bb70"
|
||||
integrity sha512-HRtSfjrWmWVNp2uAkEpQnuGMJsu/+dBr47dRc5QVgsCbnIc1+GFEaoKBWkYG+zjrsHpSqcAElMio+n10c0b5JA==
|
||||
dependencies:
|
||||
"@octokit/core" "^4.1.0"
|
||||
"@octokit/plugin-paginate-rest" "^6.0.0"
|
||||
"@octokit/plugin-request-log" "^1.0.4"
|
||||
"@octokit/plugin-rest-endpoint-methods" "^7.0.0"
|
||||
|
||||
"@octokit/types@^5.0.0":
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/types/-/types-5.2.0.tgz#d075dc23bf293f540739250b6879e2c1be2fc20c"
|
||||
integrity sha512-XjOk9y4m8xTLIKPe1NFxNWBdzA2/z3PFFA/bwf4EoH6oS8hM0Y46mEa4Cb+KCyj/tFDznJFahzQ0Aj3o1FYq4A==
|
||||
@@ -612,6 +590,13 @@
|
||||
dependencies:
|
||||
"@octokit/openapi-types" "^14.0.0"
|
||||
|
||||
"@octokit/types@^9.0.0":
|
||||
version "9.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/types/-/types-9.0.0.tgz#6050db04ddf4188ec92d60e4da1a2ce0633ff635"
|
||||
integrity sha512-LUewfj94xCMH2rbD5YJ+6AQ4AVjFYTgpp6rboWM5T7N3IsIF65SBEOVcYMGAEzO/kKNiNaW4LoWtoThOhH06gw==
|
||||
dependencies:
|
||||
"@octokit/openapi-types" "^16.0.0"
|
||||
|
||||
"@opentelemetry/api@^1.0.1":
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.0.4.tgz#a167e46c10d05a07ab299fc518793b0cff8f6924"
|
||||
@@ -1550,11 +1535,6 @@ base64-js@^1.3.1:
|
||||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
|
||||
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
|
||||
|
||||
before-after-hook@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.1.0.tgz#b6c03487f44e24200dd30ca5e6a1979c5d2fb635"
|
||||
integrity sha512-IWIbu7pMqyw3EAJHzzHbWa85b6oud/yfKYg5rqB5hNE8CeMi3nX+2C2sj0HswfblST86hpVEOAb9x34NZd6P7A==
|
||||
|
||||
before-after-hook@^2.2.0:
|
||||
version "2.2.3"
|
||||
resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.3.tgz#c51e809c81a4e354084422b9b26bad88249c517c"
|
||||
@@ -4608,13 +4588,6 @@ nice-try@^1.0.4:
|
||||
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
|
||||
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
|
||||
|
||||
node-fetch@^2.3.0, node-fetch@^2.6.7:
|
||||
version "2.6.7"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
|
||||
integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==
|
||||
dependencies:
|
||||
whatwg-url "^5.0.0"
|
||||
|
||||
node-fetch@^2.6.1:
|
||||
version "2.6.8"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.8.tgz#a68d30b162bc1d8fd71a367e81b997e1f4d4937e"
|
||||
@@ -4622,6 +4595,13 @@ node-fetch@^2.6.1:
|
||||
dependencies:
|
||||
whatwg-url "^5.0.0"
|
||||
|
||||
node-fetch@^2.6.7:
|
||||
version "2.6.7"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
|
||||
integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==
|
||||
dependencies:
|
||||
whatwg-url "^5.0.0"
|
||||
|
||||
node-releases@^2.0.6:
|
||||
version "2.0.6"
|
||||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503"
|
||||
|
||||
Reference in New Issue
Block a user