mirror of
https://github.com/electron/electron.git
synced 2026-02-26 03:01:17 -05:00
Compare commits
69 Commits
v40.1.0
...
roller/nod
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
893faf4f04 | ||
|
|
2d12f059b4 | ||
|
|
f715930d49 | ||
|
|
477fe8566e | ||
|
|
a9837ed476 | ||
|
|
1f7269f482 | ||
|
|
2813b89824 | ||
|
|
a4560db9f0 | ||
|
|
adfc062313 | ||
|
|
8dc34b4b25 | ||
|
|
6cc5ad763d | ||
|
|
4c5637c687 | ||
|
|
0d71ed0f29 | ||
|
|
fc63000ee7 | ||
|
|
8d41dbe65f | ||
|
|
f3b90cc91c | ||
|
|
a78a8cd30c | ||
|
|
2511f78120 | ||
|
|
f711af1080 | ||
|
|
616026ce1c | ||
|
|
ada2c4e072 | ||
|
|
1a76e35971 | ||
|
|
3d475716f4 | ||
|
|
c7a033dd06 | ||
|
|
2ff6e7e042 | ||
|
|
3302c4dbd8 | ||
|
|
76ce7a7ca0 | ||
|
|
4237bcbc4c | ||
|
|
c81c505fea | ||
|
|
638dd2221a | ||
|
|
8ec629e871 | ||
|
|
ba487e914d | ||
|
|
4cd269a752 | ||
|
|
201be32e0f | ||
|
|
11f60f3520 | ||
|
|
530c16aab5 | ||
|
|
e0a61a58ef | ||
|
|
fdd31a7aa4 | ||
|
|
cb0727f88c | ||
|
|
21c6e4e8a0 | ||
|
|
bf4746c7c9 | ||
|
|
091c5db763 | ||
|
|
ee64692287 | ||
|
|
0bc0553af7 | ||
|
|
51beb04c10 | ||
|
|
45a6bfbae9 | ||
|
|
53982a2c3a | ||
|
|
713b24db80 | ||
|
|
f63f875ee0 | ||
|
|
8cd558f439 | ||
|
|
94b18a54d0 | ||
|
|
394d4cf60c | ||
|
|
96db5b9734 | ||
|
|
75e4f83f87 | ||
|
|
4e124f2b22 | ||
|
|
04f4bcdb78 | ||
|
|
d5eed2bca6 | ||
|
|
0e901ca04c | ||
|
|
af272ec773 | ||
|
|
f6df2854ff | ||
|
|
f5dbe3212b | ||
|
|
ef048c48f9 | ||
|
|
f8c5bb541f | ||
|
|
3d4ce3d39b | ||
|
|
ed8493c5b1 | ||
|
|
457598a261 | ||
|
|
c18096cdf1 | ||
|
|
04901ad77e | ||
|
|
cd00dcbafd |
8
.github/actions/build-electron/action.yml
vendored
8
.github/actions/build-electron/action.yml
vendored
@@ -95,7 +95,7 @@ runs:
|
||||
# Upload build stats to Datadog
|
||||
if ($env:DD_API_KEY) {
|
||||
try {
|
||||
npx node electron\script\build-stats.mjs out\Default\siso.exe.INFO --upload-stats
|
||||
npx node electron\script\build-stats.mjs out\Default\siso.exe.INFO --upload-stats ; $LASTEXITCODE = 0
|
||||
} catch {
|
||||
Write-Host "Build stats upload failed, continuing..."
|
||||
}
|
||||
@@ -216,6 +216,7 @@ runs:
|
||||
- name: Publish Electron Dist ${{ inputs.step-suffix }}
|
||||
if: ${{ inputs.is-release == 'true' }}
|
||||
shell: bash
|
||||
id: github-upload
|
||||
run: |
|
||||
rm -rf src/out/Default/obj
|
||||
cd src/electron
|
||||
@@ -226,6 +227,11 @@ runs:
|
||||
echo 'Uploading Electron release distribution to GitHub releases'
|
||||
script/release/uploaders/upload.py --verbose
|
||||
fi
|
||||
- name: Generate artifact attestation
|
||||
if: ${{ inputs.is-release == 'true' }}
|
||||
uses: actions/attest-build-provenance@96278af6caaf10aea03fd8d33a09a777ca52d62f # v3.2.0
|
||||
with:
|
||||
subject-path: ${{ steps.github-upload.outputs.UPLOADED_PATHS }}
|
||||
- name: Generate siso report
|
||||
if: ${{ inputs.target-platform != 'win' && !cancelled() }}
|
||||
shell: bash
|
||||
|
||||
@@ -15,7 +15,7 @@ runs:
|
||||
git config --global core.preloadindex true
|
||||
git config --global core.longpaths true
|
||||
fi
|
||||
export BUILD_TOOLS_SHA=4430e4a505e0f4fa2a41b707a10a36f780bbdd26
|
||||
export BUILD_TOOLS_SHA=a0cc95a1884a631559bcca0c948465b725d9295a
|
||||
npm i -g @electron/build-tools
|
||||
# Update depot_tools to ensure python
|
||||
e d update_depot_tools
|
||||
|
||||
122
.github/copilot-instructions.md
vendored
Normal file
122
.github/copilot-instructions.md
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
# Copilot Instructions for Electron
|
||||
|
||||
## Build System
|
||||
|
||||
Electron uses `@electron/build-tools` (`e` CLI). Install with `npm i -g @electron/build-tools`.
|
||||
|
||||
```bash
|
||||
e sync # Fetch sources and apply patches
|
||||
e build # Build Electron (GN + Ninja)
|
||||
e build -k 999 # Build, continuing through errors
|
||||
e start # Run built Electron
|
||||
e start --version # Verify Electron launches
|
||||
e test # Run full test suite
|
||||
e debug # Run in debugger (lldb on macOS, gdb on Linux)
|
||||
```
|
||||
|
||||
### Linting
|
||||
|
||||
```bash
|
||||
npm run lint # Run all linters (JS, C++, Python, GN, docs)
|
||||
npm run lint:js # JavaScript/TypeScript only
|
||||
npm run lint:clang-format # C++ formatting only
|
||||
npm run lint:cpp # C++ linting only
|
||||
npm run lint:docs # Documentation only
|
||||
```
|
||||
|
||||
### Running a Single Test
|
||||
|
||||
```bash
|
||||
npm run test -- -g "pattern" # Run tests matching a regex pattern
|
||||
# Example: npm run test -- -g "ipc"
|
||||
```
|
||||
|
||||
### Running a Single Node.js Test
|
||||
|
||||
```bash
|
||||
node script/node-spec-runner.js parallel/test-crypto-keygen
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
Electron embeds Chromium (rendering) and Node.js (backend) to enable desktop apps with web technologies. The parent directory (`../`) is the Chromium source tree.
|
||||
|
||||
### Process Model
|
||||
|
||||
Electron has two primary process types, mirroring Chromium:
|
||||
|
||||
- **Main process** (`shell/browser/` + `lib/browser/`): Controls app lifecycle, creates windows, system APIs
|
||||
- **Renderer process** (`shell/renderer/` + `lib/renderer/`): Runs web content in BrowserWindows
|
||||
|
||||
### Native ↔ JavaScript Bridge
|
||||
|
||||
Each API is implemented as a C++/JS pair:
|
||||
|
||||
- C++ side: `shell/browser/api/electron_api_{name}.cc/.h` — uses `gin::Wrappable` and `ObjectTemplateBuilder`
|
||||
- JS side: `lib/browser/api/{name}.ts` — exports the module, registered in `lib/browser/api/module-list.ts`
|
||||
- Binding: `NODE_LINKED_BINDING_CONTEXT_AWARE(electron_browser_{name}, Initialize)` in C++ and registered in `shell/common/node_bindings.cc`
|
||||
- Type declaration: `typings/internal-ambient.d.ts` maps `process._linkedBinding('electron_browser_{name}')`
|
||||
|
||||
### Patches System
|
||||
|
||||
Electron patches upstream dependencies (Chromium, Node.js, V8, etc.) rather than forking them. Patches live in `patches/` organized by target, with `patches/config.json` mapping directories to repos.
|
||||
|
||||
```text
|
||||
patches/{target}/*.patch → [e sync] → target repo commits
|
||||
← [e patches] ←
|
||||
```
|
||||
|
||||
Key rules:
|
||||
|
||||
- Fix existing patches rather than creating new ones
|
||||
- Preserve original authorship in TODO comments — never change `TODO(name)` assignees
|
||||
- Each patch commit message must explain why the patch exists
|
||||
- After modifying patches, run `e patches {target}` to export
|
||||
|
||||
When working on the `roller/chromium/main` branch for Chromium upgrades, use `e sync --3` for 3-way merge conflict resolution.
|
||||
|
||||
## Conventions
|
||||
|
||||
### File Naming
|
||||
|
||||
- JS/TS files: kebab-case (`file-name.ts`)
|
||||
- C++ files: snake_case with `electron_api_` prefix (`electron_api_safe_storage.cc`)
|
||||
- Test files: `api-{module-name}-spec.ts` in `spec/`
|
||||
- Source file lists are maintained in `filenames.gni` (with platform-specific sections)
|
||||
|
||||
### JavaScript/TypeScript
|
||||
|
||||
- Semicolons required (`"semi": ["error", "always"]`)
|
||||
- `const` and `let` only (no `var`)
|
||||
- Arrow functions preferred
|
||||
- Import order enforced: `@electron/internal` → `@electron` → `electron` → external → builtin → relative
|
||||
- API naming: `PascalCase` for classes (`BrowserWindow`), `camelCase` for module APIs (`globalShortcut`)
|
||||
- Prefer getters/setters over jQuery-style `.text([text])` patterns
|
||||
|
||||
### C++
|
||||
|
||||
- Follows Chromium coding style, enforced by `clang-format` and `clang-tidy`
|
||||
- Uses Chromium abstractions (`base::`, `content::`, etc.)
|
||||
- Header guards: `#ifndef ELECTRON_SHELL_BROWSER_API_ELECTRON_API_{NAME}_H_`
|
||||
- Platform-specific files: `_mac.mm`, `_win.cc`, `_linux.cc`
|
||||
|
||||
### Testing
|
||||
|
||||
- Framework: Mocha + Chai + Sinon
|
||||
- Test helpers in `spec/lib/` (e.g., `spec-helpers.ts`, `window-helpers.ts`)
|
||||
- Use `defer()` from spec-helpers for cleanup, `closeAllWindows()` for window teardown
|
||||
- Tests import from `electron/main` or `electron/renderer`
|
||||
|
||||
### Documentation
|
||||
|
||||
- API docs in `docs/api/` as Markdown, parsed by `@electron/docs-parser` to generate `electron.d.ts`
|
||||
- API history tracked via YAML blocks in HTML comments within doc files
|
||||
- Docs must pass `npm run lint:docs`
|
||||
|
||||
### Build Configuration
|
||||
|
||||
- `BUILD.gn`: Main GN build config
|
||||
- `buildflags/buildflags.gni`: Feature flags (PDF viewer, extensions, spellchecker)
|
||||
- `build/args/`: Build argument profiles (`testing.gn`, `release.gn`, `all.gn`)
|
||||
- `DEPS`: Dependency versions and checkout paths
|
||||
- `chromium_src/`: Chromium source file overrides (compiled instead of originals)
|
||||
16
.github/problem-matchers/markdownlint.json
vendored
Normal file
16
.github/problem-matchers/markdownlint.json
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "markdownlint",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^(.+):(\\d+):(\\d+)\\s+(.*)$",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"column": 3,
|
||||
"message": 4
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
73
.github/workflows/apply-patches.yml
vendored
Normal file
73
.github/workflows/apply-patches.yml
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
name: Apply Patches
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
permissions: {}
|
||||
|
||||
concurrency:
|
||||
group: apply-patches-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
setup:
|
||||
if: github.repository == 'electron/electron'
|
||||
runs-on: ubuntu-slim
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
outputs:
|
||||
has-patches: ${{ steps.filter.outputs.patches }}
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
persist-credentials: false
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
# Use dorny/paths-filter instead of the path filter under the on: pull_request: block
|
||||
# so that the output can be used to conditionally run the apply-patches job, which lets
|
||||
# the job be marked as a required status check (conditional skip counts as a success).
|
||||
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
||||
id: filter
|
||||
with:
|
||||
filters: |
|
||||
patches:
|
||||
- DEPS
|
||||
- 'patches/**'
|
||||
|
||||
apply-patches:
|
||||
needs: setup
|
||||
if: ${{ needs.setup.outputs.has-patches == 'true' }}
|
||||
runs-on: electron-arc-centralus-linux-amd64-32core
|
||||
permissions:
|
||||
contents: read
|
||||
container:
|
||||
image: ghcr.io/electron/build:a82b87d7a4f5ff0cab61405f8151ac4cf4942aeb
|
||||
options: --user root
|
||||
volumes:
|
||||
- /mnt/cross-instance-cache:/mnt/cross-instance-cache
|
||||
- /var/run/sas:/var/run/sas
|
||||
env:
|
||||
CHROMIUM_GIT_COOKIE: ${{ secrets.CHROMIUM_GIT_COOKIE }}
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
|
||||
steps:
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
path: src/electron
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
ref: ${{ github.event.pull_request.base.ref }}
|
||||
- name: Merge PR HEAD
|
||||
working-directory: src/electron
|
||||
env:
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
run: |
|
||||
git config user.email "electron@github.com"
|
||||
git config user.name "Electron Bot"
|
||||
git fetch origin refs/pull/${PR_NUMBER}/head
|
||||
git merge --squash FETCH_HEAD
|
||||
git commit -n -m "Squashed commits"
|
||||
- name: Checkout & Sync & Save
|
||||
uses: ./src/electron/.github/actions/checkout
|
||||
with:
|
||||
target-platform: linux
|
||||
39
.github/workflows/build.yml
vendored
39
.github/workflows/build.yml
vendored
@@ -56,7 +56,6 @@ jobs:
|
||||
src: ${{ steps.filter.outputs.src }}
|
||||
build-image-sha: ${{ steps.set-output.outputs.build-image-sha }}
|
||||
docs-only: ${{ steps.set-output.outputs.docs-only }}
|
||||
has-patches: ${{ steps.filter.outputs.patches }}
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
|
||||
with:
|
||||
@@ -73,9 +72,6 @@ jobs:
|
||||
- CODE_OF_CONDUCT.md
|
||||
src:
|
||||
- '!docs/**'
|
||||
patches:
|
||||
- DEPS
|
||||
- 'patches/**'
|
||||
- name: Set Outputs for Build Image SHA & Docs Only
|
||||
id: set-output
|
||||
run: |
|
||||
@@ -108,41 +104,6 @@ jobs:
|
||||
container: '{"image":"ghcr.io/electron/build:${{ needs.checkout-linux.outputs.build-image-sha }}","options":"--user root","volumes":["/mnt/cross-instance-cache:/mnt/cross-instance-cache"]}'
|
||||
secrets: inherit
|
||||
|
||||
# Apply Patches Job
|
||||
apply-patches:
|
||||
needs: setup
|
||||
if: ${{ needs.setup.outputs.has-patches == 'true' }}
|
||||
runs-on: electron-arc-centralus-linux-amd64-32core
|
||||
permissions:
|
||||
contents: read
|
||||
container:
|
||||
image: ghcr.io/electron/build:${{ needs.setup.outputs.build-image-sha }}
|
||||
options: --user root
|
||||
volumes:
|
||||
- /mnt/cross-instance-cache:/mnt/cross-instance-cache
|
||||
- /var/run/sas:/var/run/sas
|
||||
env:
|
||||
CHROMIUM_GIT_COOKIE: ${{ secrets.CHROMIUM_GIT_COOKIE }}
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
|
||||
steps:
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
|
||||
with:
|
||||
path: src/electron
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Rebase onto Base Branch
|
||||
working-directory: src/electron
|
||||
run: |
|
||||
git config user.email "electron@github.com"
|
||||
git config user.name "Electron Bot"
|
||||
git fetch origin ${{ github.event.pull_request.base.ref }}
|
||||
git rebase origin/${{ github.event.pull_request.base.ref }}
|
||||
- name: Checkout & Sync & Save
|
||||
uses: ./src/electron/.github/actions/checkout
|
||||
with:
|
||||
target-platform: linux
|
||||
|
||||
# Checkout Jobs
|
||||
checkout-macos:
|
||||
needs: setup
|
||||
|
||||
15
.github/workflows/linux-publish.yml
vendored
15
.github/workflows/linux-publish.yml
vendored
@@ -43,9 +43,12 @@ jobs:
|
||||
uses: ./src/electron/.github/actions/checkout
|
||||
|
||||
publish-x64:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-build.yml
|
||||
uses: ./.github/workflows/pipeline-segment-electron-publish.yml
|
||||
permissions:
|
||||
artifact-metadata: write
|
||||
attestations: write
|
||||
contents: read
|
||||
id-token: write
|
||||
needs: checkout-linux
|
||||
with:
|
||||
environment: production-release
|
||||
@@ -60,9 +63,12 @@ jobs:
|
||||
secrets: inherit
|
||||
|
||||
publish-arm:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-build.yml
|
||||
uses: ./.github/workflows/pipeline-segment-electron-publish.yml
|
||||
permissions:
|
||||
artifact-metadata: write
|
||||
attestations: write
|
||||
contents: read
|
||||
id-token: write
|
||||
needs: checkout-linux
|
||||
with:
|
||||
environment: production-release
|
||||
@@ -77,9 +83,12 @@ jobs:
|
||||
secrets: inherit
|
||||
|
||||
publish-arm64:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-build.yml
|
||||
uses: ./.github/workflows/pipeline-segment-electron-publish.yml
|
||||
permissions:
|
||||
artifact-metadata: write
|
||||
attestations: write
|
||||
contents: read
|
||||
id-token: write
|
||||
needs: checkout-linux
|
||||
with:
|
||||
environment: production-release
|
||||
|
||||
20
.github/workflows/macos-publish.yml
vendored
20
.github/workflows/macos-publish.yml
vendored
@@ -47,9 +47,12 @@ jobs:
|
||||
target-platform: macos
|
||||
|
||||
publish-x64-darwin:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-build.yml
|
||||
uses: ./.github/workflows/pipeline-segment-electron-publish.yml
|
||||
permissions:
|
||||
artifact-metadata: write
|
||||
attestations: write
|
||||
contents: read
|
||||
id-token: write
|
||||
needs: checkout-macos
|
||||
with:
|
||||
environment: production-release
|
||||
@@ -64,9 +67,12 @@ jobs:
|
||||
secrets: inherit
|
||||
|
||||
publish-x64-mas:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-build.yml
|
||||
uses: ./.github/workflows/pipeline-segment-electron-publish.yml
|
||||
permissions:
|
||||
artifact-metadata: write
|
||||
attestations: write
|
||||
contents: read
|
||||
id-token: write
|
||||
needs: checkout-macos
|
||||
with:
|
||||
environment: production-release
|
||||
@@ -81,9 +87,12 @@ jobs:
|
||||
secrets: inherit
|
||||
|
||||
publish-arm64-darwin:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-build.yml
|
||||
uses: ./.github/workflows/pipeline-segment-electron-publish.yml
|
||||
permissions:
|
||||
artifact-metadata: write
|
||||
attestations: write
|
||||
contents: read
|
||||
id-token: write
|
||||
needs: checkout-macos
|
||||
with:
|
||||
environment: production-release
|
||||
@@ -98,9 +107,12 @@ jobs:
|
||||
secrets: inherit
|
||||
|
||||
publish-arm64-mas:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-build.yml
|
||||
uses: ./.github/workflows/pipeline-segment-electron-publish.yml
|
||||
permissions:
|
||||
artifact-metadata: write
|
||||
attestations: write
|
||||
contents: read
|
||||
id-token: write
|
||||
needs: checkout-macos
|
||||
with:
|
||||
environment: production-release
|
||||
|
||||
12
.github/workflows/pipeline-electron-lint.yml
vendored
12
.github/workflows/pipeline-electron-lint.yml
vendored
@@ -65,9 +65,11 @@ jobs:
|
||||
curl -sL "https://chromium.googlesource.com/chromium/src/+/${chromium_revision}/buildtools/DEPS?format=TEXT" | base64 -d > src/buildtools/DEPS
|
||||
|
||||
gclient sync --spec="solutions=[{'name':'src/buildtools','url':None,'deps_file':'DEPS','custom_vars':{'process_deps':True},'managed':False}]"
|
||||
- name: Add ESLint problem matcher
|
||||
- name: Add problem matchers
|
||||
shell: bash
|
||||
run: echo "::add-matcher::src/electron/.github/problem-matchers/eslint-stylish.json"
|
||||
run: |
|
||||
echo "::add-matcher::src/electron/.github/problem-matchers/eslint-stylish.json"
|
||||
echo "::add-matcher::src/electron/.github/problem-matchers/markdownlint.json"
|
||||
- name: Run Lint
|
||||
shell: bash
|
||||
run: |
|
||||
@@ -85,4 +87,8 @@ jobs:
|
||||
run: |
|
||||
cd src/electron
|
||||
node script/yarn.js tsc -p tsconfig.script.json
|
||||
|
||||
- name: Check GHA Workflows
|
||||
shell: bash
|
||||
run: |
|
||||
cd src/electron
|
||||
node script/copy-pipeline-segment-publish.js --check
|
||||
|
||||
237
.github/workflows/pipeline-segment-electron-publish.yml
vendored
Normal file
237
.github/workflows/pipeline-segment-electron-publish.yml
vendored
Normal file
@@ -0,0 +1,237 @@
|
||||
# AUTOGENERATED FILE - DO NOT EDIT MANUALLY
|
||||
# ONLY EDIT .github/workflows/pipeline-segment-electron-build.yml
|
||||
|
||||
name: Pipeline Segment - Electron Build
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
environment:
|
||||
description: using the production or testing environment
|
||||
required: false
|
||||
type: string
|
||||
target-platform:
|
||||
type: string
|
||||
description: Platform to run on, can be macos, win or linux
|
||||
required: true
|
||||
target-arch:
|
||||
type: string
|
||||
description: Arch to build for, can be x64, arm64, ia32 or arm
|
||||
required: true
|
||||
target-variant:
|
||||
type: string
|
||||
description: Variant to build for, no effect on non-macOS target platforms. Can
|
||||
be darwin, mas or all.
|
||||
default: all
|
||||
build-runs-on:
|
||||
type: string
|
||||
description: What host to run the build
|
||||
required: true
|
||||
build-container:
|
||||
type: string
|
||||
description: JSON container information for aks runs-on
|
||||
required: false
|
||||
default: '{"image":null}'
|
||||
is-release:
|
||||
description: Whether this build job is a release job
|
||||
required: true
|
||||
type: boolean
|
||||
default: false
|
||||
gn-build-type:
|
||||
description: The gn build type - testing or release
|
||||
required: true
|
||||
type: string
|
||||
default: testing
|
||||
generate-symbols:
|
||||
description: Whether or not to generate symbols
|
||||
required: true
|
||||
type: boolean
|
||||
default: false
|
||||
upload-to-storage:
|
||||
description: Whether or not to upload build artifacts to external storage
|
||||
required: true
|
||||
type: string
|
||||
default: "0"
|
||||
is-asan:
|
||||
description: Building the Address Sanitizer (ASan) Linux build
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
enable-ssh:
|
||||
description: Enable SSH debugging
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
permissions: {}
|
||||
concurrency:
|
||||
group: electron-build-${{ inputs.target-platform }}-${{ inputs.target-arch
|
||||
}}-${{ inputs.target-variant }}-${{ inputs.is-asan }}-${{
|
||||
github.ref_protected == true && github.run_id || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref_protected != true }}
|
||||
env:
|
||||
CHROMIUM_GIT_COOKIE: ${{ secrets.CHROMIUM_GIT_COOKIE }}
|
||||
CHROMIUM_GIT_COOKIE_WINDOWS_STRING: ${{ secrets.CHROMIUM_GIT_COOKIE_WINDOWS_STRING }}
|
||||
DD_API_KEY: ${{ secrets.DD_API_KEY }}
|
||||
ELECTRON_ARTIFACTS_BLOB_STORAGE: ${{ secrets.ELECTRON_ARTIFACTS_BLOB_STORAGE }}
|
||||
ELECTRON_RBE_JWT: ${{ secrets.ELECTRON_RBE_JWT }}
|
||||
SUDOWOODO_EXCHANGE_URL: ${{ secrets.SUDOWOODO_EXCHANGE_URL }}
|
||||
SUDOWOODO_EXCHANGE_TOKEN: ${{ secrets.SUDOWOODO_EXCHANGE_TOKEN }}
|
||||
GCLIENT_EXTRA_ARGS: ${{ inputs.target-platform == 'macos' &&
|
||||
'--custom-var=checkout_mac=True --custom-var=host_os=mac' ||
|
||||
inputs.target-platform == 'win' && '--custom-var=checkout_win=True' ||
|
||||
'--custom-var=checkout_arm=True --custom-var=checkout_arm64=True' }}
|
||||
ELECTRON_OUT_DIR: Default
|
||||
ACTIONS_STEP_DEBUG: ${{ secrets.ACTIONS_STEP_DEBUG }}
|
||||
jobs:
|
||||
build:
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
runs-on: ${{ inputs.build-runs-on }}
|
||||
permissions:
|
||||
artifact-metadata: write
|
||||
attestations: write
|
||||
contents: read
|
||||
id-token: write
|
||||
container: ${{ fromJSON(inputs.build-container) }}
|
||||
environment: ${{ inputs.environment }}
|
||||
env:
|
||||
TARGET_ARCH: ${{ inputs.target-arch }}
|
||||
TARGET_PLATFORM: ${{ inputs.target-platform }}
|
||||
steps:
|
||||
- name: Create src dir
|
||||
run: |
|
||||
mkdir src
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
|
||||
with:
|
||||
path: src/electron
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Setup SSH Debugging
|
||||
if: ${{ inputs.target-platform == 'macos' && (inputs.enable-ssh ||
|
||||
env.ACTIONS_STEP_DEBUG == 'true') }}
|
||||
uses: ./src/electron/.github/actions/ssh-debug
|
||||
with:
|
||||
tunnel: "true"
|
||||
env:
|
||||
CLOUDFLARE_TUNNEL_CERT: ${{ secrets.CLOUDFLARE_TUNNEL_CERT }}
|
||||
CLOUDFLARE_TUNNEL_HOSTNAME: ${{ vars.CLOUDFLARE_TUNNEL_HOSTNAME }}
|
||||
CLOUDFLARE_USER_CA_CERT: ${{ secrets.CLOUDFLARE_USER_CA_CERT }}
|
||||
AUTHORIZED_USERS: ${{ secrets.SSH_DEBUG_AUTHORIZED_USERS }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Free up space (macOS)
|
||||
if: ${{ inputs.target-platform == 'macos' }}
|
||||
uses: ./src/electron/.github/actions/free-space-macos
|
||||
- name: Check disk space after freeing up space
|
||||
if: ${{ inputs.target-platform == 'macos' }}
|
||||
run: df -h
|
||||
- name: Setup Node.js/npm
|
||||
if: ${{ inputs.target-platform == 'macos' }}
|
||||
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903
|
||||
with:
|
||||
node-version: 20.19.x
|
||||
cache: yarn
|
||||
cache-dependency-path: src/electron/yarn.lock
|
||||
- name: Install Dependencies
|
||||
uses: ./src/electron/.github/actions/install-dependencies
|
||||
- name: Install AZCopy
|
||||
if: ${{ inputs.target-platform == 'macos' }}
|
||||
run: brew install azcopy
|
||||
- name: Set GN_EXTRA_ARGS for Linux
|
||||
if: ${{ inputs.target-platform == 'linux' }}
|
||||
run: >
|
||||
if [ "${{ inputs.target-arch }}" = "arm" ]; then
|
||||
if [ "${{ inputs.is-release }}" = true ]; then
|
||||
GN_EXTRA_ARGS='target_cpu="arm" build_tflite_with_xnnpack=false symbol_level=1'
|
||||
else
|
||||
GN_EXTRA_ARGS='target_cpu="arm" build_tflite_with_xnnpack=false'
|
||||
fi
|
||||
elif [ "${{ inputs.target-arch }}" = "arm64" ]; then
|
||||
GN_EXTRA_ARGS='target_cpu="arm64" fatal_linker_warnings=false enable_linux_installer=false'
|
||||
elif [ "${{ inputs.is-asan }}" = true ]; then
|
||||
GN_EXTRA_ARGS='is_asan=true'
|
||||
fi
|
||||
|
||||
echo "GN_EXTRA_ARGS=$GN_EXTRA_ARGS" >> $GITHUB_ENV
|
||||
- name: Set Chromium Git Cookie
|
||||
uses: ./src/electron/.github/actions/set-chromium-cookie
|
||||
- name: Install Build Tools
|
||||
uses: ./src/electron/.github/actions/install-build-tools
|
||||
- name: Generate DEPS Hash
|
||||
run: |
|
||||
node src/electron/script/generate-deps-hash.js
|
||||
DEPSHASH=v1-src-cache-$(cat src/electron/.depshash)
|
||||
echo "DEPSHASH=$DEPSHASH" >> $GITHUB_ENV
|
||||
echo "CACHE_PATH=$DEPSHASH.tar" >> $GITHUB_ENV
|
||||
- name: Restore src cache via AZCopy
|
||||
if: ${{ inputs.target-platform != 'linux' }}
|
||||
uses: ./src/electron/.github/actions/restore-cache-azcopy
|
||||
with:
|
||||
target-platform: ${{ inputs.target-platform }}
|
||||
- name: Restore src cache via AKS
|
||||
if: ${{ inputs.target-platform == 'linux' }}
|
||||
uses: ./src/electron/.github/actions/restore-cache-aks
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
|
||||
with:
|
||||
path: src/electron
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Fix Sync
|
||||
if: ${{ inputs.target-platform != 'linux' }}
|
||||
uses: ./src/electron/.github/actions/fix-sync
|
||||
with:
|
||||
target-platform: ${{ inputs.target-platform }}
|
||||
env:
|
||||
ELECTRON_DEPOT_TOOLS_DISABLE_LOG: true
|
||||
- name: Init Build Tools
|
||||
run: >
|
||||
e init -f --root=$(pwd) --out=Default ${{ inputs.gn-build-type }}
|
||||
--import ${{ inputs.gn-build-type }} --target-cpu ${{
|
||||
inputs.target-arch }} --remote-build siso
|
||||
- name: Run Electron Only Hooks
|
||||
run: |
|
||||
e d gclient runhooks --spec="solutions=[{'name':'src/electron','url':None,'deps_file':'DEPS','custom_vars':{'process_deps':False},'managed':False}]"
|
||||
- name: Regenerate DEPS Hash
|
||||
run: >
|
||||
(cd src/electron && git checkout .) && node
|
||||
src/electron/script/generate-deps-hash.js
|
||||
|
||||
echo "DEPSHASH=$(cat src/electron/.depshash)" >> $GITHUB_ENV
|
||||
- name: Add CHROMIUM_BUILDTOOLS_PATH to env
|
||||
run: echo "CHROMIUM_BUILDTOOLS_PATH=$(pwd)/src/buildtools" >> $GITHUB_ENV
|
||||
- name: Free up space (macOS)
|
||||
if: ${{ inputs.target-platform == 'macos' }}
|
||||
uses: ./src/electron/.github/actions/free-space-macos
|
||||
- name: Build Electron
|
||||
if: ${{ inputs.target-platform != 'macos' || (inputs.target-variant == 'all' ||
|
||||
inputs.target-variant == 'darwin') }}
|
||||
uses: ./src/electron/.github/actions/build-electron
|
||||
with:
|
||||
target-arch: ${{ inputs.target-arch }}
|
||||
target-platform: ${{ inputs.target-platform }}
|
||||
artifact-platform: ${{ inputs.target-platform == 'macos' && 'darwin' ||
|
||||
inputs.target-platform }}
|
||||
is-release: ${{ inputs.is-release }}
|
||||
generate-symbols: ${{ inputs.generate-symbols }}
|
||||
upload-to-storage: ${{ inputs.upload-to-storage }}
|
||||
is-asan: ${{ inputs.is-asan }}
|
||||
- name: Set GN_EXTRA_ARGS for MAS Build
|
||||
if: ${{ inputs.target-platform == 'macos' && (inputs.target-variant == 'all' ||
|
||||
inputs.target-variant == 'mas') }}
|
||||
run: |
|
||||
echo "MAS_BUILD=true" >> $GITHUB_ENV
|
||||
GN_EXTRA_ARGS='is_mas_build=true'
|
||||
echo "GN_EXTRA_ARGS=$GN_EXTRA_ARGS" >> $GITHUB_ENV
|
||||
- name: Build Electron (MAS)
|
||||
if: ${{ inputs.target-platform == 'macos' && (inputs.target-variant == 'all' ||
|
||||
inputs.target-variant == 'mas') }}
|
||||
uses: ./src/electron/.github/actions/build-electron
|
||||
with:
|
||||
target-arch: ${{ inputs.target-arch }}
|
||||
target-platform: ${{ inputs.target-platform }}
|
||||
artifact-platform: mas
|
||||
is-release: ${{ inputs.is-release }}
|
||||
generate-symbols: ${{ inputs.generate-symbols }}
|
||||
upload-to-storage: ${{ inputs.upload-to-storage }}
|
||||
step-suffix: (mas)
|
||||
28
.github/workflows/rerun-apply-patches.yml
vendored
28
.github/workflows/rerun-apply-patches.yml
vendored
@@ -15,8 +15,9 @@ jobs:
|
||||
rerun-apply-patches:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
actions: write
|
||||
checks: read
|
||||
contents: read
|
||||
pull-requests: read
|
||||
steps:
|
||||
- name: Find PRs and Rerun Apply Patches
|
||||
@@ -33,21 +34,21 @@ jobs:
|
||||
PR_NUMBER=$(echo "$pr" | jq -r '.number')
|
||||
echo "Processing PR #${PR_NUMBER}"
|
||||
|
||||
# Find the apply-patches job check for this PR
|
||||
CHECK=$(gh pr checks "$PR_NUMBER" --json link,name,state,workflow --jq '[.[] | select(.workflow == "Build" and .name == "apply-patches")] | first')
|
||||
# Find the Apply Patches workflow check for this PR
|
||||
CHECK=$(gh pr view "$PR_NUMBER" --json statusCheckRollup --jq '[.statusCheckRollup[] | select(.workflowName == "Apply Patches" and .name == "apply-patches")] | first')
|
||||
|
||||
if [ -z "$CHECK" ] || [ "$CHECK" = "null" ]; then
|
||||
echo " No apply-patches job found for PR #${PR_NUMBER}"
|
||||
echo " No Apply Patches workflow found for PR #${PR_NUMBER}"
|
||||
continue
|
||||
fi
|
||||
|
||||
STATE=$(echo "$CHECK" | jq -r '.state')
|
||||
if [ "$STATE" = "SKIPPED" ]; then
|
||||
CONCLUSION=$(echo "$CHECK" | jq -r '.conclusion')
|
||||
if [ "$CONCLUSION" = "SKIPPED" ]; then
|
||||
echo " apply-patches job was skipped for PR #${PR_NUMBER} (no patches)"
|
||||
continue
|
||||
fi
|
||||
|
||||
LINK=$(echo "$CHECK" | jq -r '.link')
|
||||
LINK=$(echo "$CHECK" | jq -r '.detailsUrl')
|
||||
|
||||
# Extract the run ID from the link (format: .../runs/RUN_ID/job/JOB_ID)
|
||||
RUN_ID=$(echo "$LINK" | grep -oE 'runs/[0-9]+' | cut -d'/' -f2)
|
||||
@@ -57,13 +58,14 @@ jobs:
|
||||
continue
|
||||
fi
|
||||
|
||||
# Get the job database ID for the apply-patches job
|
||||
JOB_ID=$(gh run view "$RUN_ID" --json jobs --jq '.jobs[] | select(.name == "apply-patches") | .databaseId')
|
||||
# Check if the workflow is currently in progress
|
||||
RUN_STATUS=$(gh run view "$RUN_ID" --json status --jq '.status')
|
||||
|
||||
if [ -z "$JOB_ID" ]; then
|
||||
echo " Could not find apply-patches job ID for run: ${RUN_ID}"
|
||||
continue
|
||||
if [ "$RUN_STATUS" = "in_progress" ] || [ "$RUN_STATUS" = "queued" ] || [ "$RUN_STATUS" = "waiting" ]; then
|
||||
echo " Workflow run ${RUN_ID} is ${RUN_STATUS}, cancelling..."
|
||||
gh run cancel "$RUN_ID" --force
|
||||
gh run watch "$RUN_ID"
|
||||
fi
|
||||
|
||||
gh run rerun "$RUN_ID" --job "$JOB_ID"
|
||||
gh run rerun "$RUN_ID"
|
||||
done
|
||||
|
||||
39
.github/workflows/update-website-docs.yml
vendored
Normal file
39
.github/workflows/update-website-docs.yml
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
name: Update Website Docs
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
update-website-docs:
|
||||
name: Update Website Docs
|
||||
runs-on: ubuntu-latest
|
||||
environment: website-docs-updater
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write # needed for secret-service-action
|
||||
steps:
|
||||
- name: Get GitHub App token
|
||||
id: secret-service
|
||||
uses: electron/secret-service-action@3476425e8b30555aac15b1b7096938e254b0e155 # v1.0.0
|
||||
- name: Check if this release is the latest
|
||||
id: check-if-latest-release
|
||||
env:
|
||||
GH_REPO: electron/electron
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
LATEST_RELEASE_TAG="$(gh release view --json tagName --jq '.tagName')"
|
||||
if [ "$LATEST_RELEASE_TAG" = "${GITHUB_REF#refs/tags/}" ]; then
|
||||
echo "isLatestRelease=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "isLatestRelease=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
- name: Trigger website docs update
|
||||
if: ${{ steps.check-if-latest-release.outputs.isLatestRelease == 'true' }}
|
||||
env:
|
||||
GH_REPO: electron/website
|
||||
GH_TOKEN: ${{ fromJSON(steps.secret-service.outputs.secrets).WEBSITE_DOCS_UPDATER_APP_TOKEN }}
|
||||
run: |
|
||||
gh workflow run update-docs.yml -f sha=$GITHUB_SHA
|
||||
15
.github/workflows/windows-publish.yml
vendored
15
.github/workflows/windows-publish.yml
vendored
@@ -51,9 +51,12 @@ jobs:
|
||||
target-platform: win
|
||||
|
||||
publish-x64-win:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-build.yml
|
||||
uses: ./.github/workflows/pipeline-segment-electron-publish.yml
|
||||
permissions:
|
||||
artifact-metadata: write
|
||||
attestations: write
|
||||
contents: read
|
||||
id-token: write
|
||||
needs: checkout-windows
|
||||
with:
|
||||
environment: production-release
|
||||
@@ -67,9 +70,12 @@ jobs:
|
||||
secrets: inherit
|
||||
|
||||
publish-arm64-win:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-build.yml
|
||||
uses: ./.github/workflows/pipeline-segment-electron-publish.yml
|
||||
permissions:
|
||||
artifact-metadata: write
|
||||
attestations: write
|
||||
contents: read
|
||||
id-token: write
|
||||
needs: checkout-windows
|
||||
with:
|
||||
environment: production-release
|
||||
@@ -83,9 +89,12 @@ jobs:
|
||||
secrets: inherit
|
||||
|
||||
publish-x86-win:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-build.yml
|
||||
uses: ./.github/workflows/pipeline-segment-electron-publish.yml
|
||||
permissions:
|
||||
artifact-metadata: write
|
||||
attestations: write
|
||||
contents: read
|
||||
id-token: write
|
||||
needs: checkout-windows
|
||||
with:
|
||||
environment: production-release
|
||||
|
||||
4
DEPS
4
DEPS
@@ -2,9 +2,9 @@ gclient_gn_args_from = 'src'
|
||||
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'144.0.7559.96',
|
||||
'144.0.7559.225',
|
||||
'node_version':
|
||||
'v24.11.1',
|
||||
'v24.14.0',
|
||||
'nan_version':
|
||||
'675cefebca42410733da8a454c8d9391fcebfbc2',
|
||||
'squirrel.mac_version':
|
||||
|
||||
@@ -250,7 +250,9 @@ Returns:
|
||||
|
||||
Emitted when the user clicks the native macOS new tab button. The new
|
||||
tab button is only visible if the current `BrowserWindow` has a
|
||||
`tabbingIdentifier`
|
||||
`tabbingIdentifier`.
|
||||
|
||||
You must create a window in this handler in order for macOS tabbing to work as expected.
|
||||
|
||||
### Event: 'browser-window-blur'
|
||||
|
||||
@@ -632,7 +634,7 @@ Returns `string` - The current application directory.
|
||||
Returns `string` - A path to a special directory or file associated with `name`. On
|
||||
failure, an `Error` is thrown.
|
||||
|
||||
If `app.getPath('logs')` is called without called `app.setAppLogsPath()` being called first, a default log directory will be created equivalent to calling `app.setAppLogsPath()` without a `path` parameter.
|
||||
If `app.getPath('logs')` is called without calling `app.setAppLogsPath()` being called first, a default log directory will be created equivalent to calling `app.setAppLogsPath()` without a `path` parameter.
|
||||
|
||||
### `app.getFileIcon(path[, options])`
|
||||
|
||||
@@ -647,7 +649,7 @@ Returns `Promise<NativeImage>` - fulfilled with the app's icon, which is a [Nati
|
||||
|
||||
Fetches a path's associated icon.
|
||||
|
||||
On _Windows_, there a 2 kinds of icons:
|
||||
On _Windows_, there are 2 kinds of icons:
|
||||
|
||||
* Icons associated with certain file extensions, like `.mp3`, `.png`, etc.
|
||||
* Icons inside the file itself, like `.exe`, `.dll`, `.ico`.
|
||||
@@ -763,7 +765,7 @@ app.getPreferredSystemLanguages() // ['fr-CA', 'en-US', 'zh-Hans-FI', 'es-419']
|
||||
|
||||
Both the available languages and regions and the possible return values differ between the two operating systems.
|
||||
|
||||
As can be seen with the example above, on Windows, it is possible that a preferred system language has no country code, and that one of the preferred system languages corresponds with the language used for the regional format. On macOS, the region serves more as a default country code: the user doesn't need to have Finnish as a preferred language to use Finland as the region,and the country code `FI` is used as the country code for preferred system languages that do not have associated countries in the language name.
|
||||
As can be seen with the example above, on Windows, it is possible that a preferred system language has no country code, and that one of the preferred system languages corresponds with the language used for the regional format. On macOS, the region serves more as a default country code: the user doesn't need to have Finnish as a preferred language to use Finland as the region, and the country code `FI` is used as the country code for preferred system languages that do not have associated countries in the language name.
|
||||
|
||||
### `app.addRecentDocument(path)` _macOS_ _Windows_
|
||||
|
||||
@@ -1121,6 +1123,19 @@ Updates the current activity if its type matches `type`, merging the entries fro
|
||||
|
||||
Changes the [Application User Model ID][app-user-model-id] to `id`.
|
||||
|
||||
### `app.setToastActivatorCLSID(id)` _Windows_
|
||||
|
||||
* `id` string
|
||||
|
||||
Changes the [Toast Activator CLSID][toast-activator-clsid] to `id`. If one is not set via this method, it will be randomly generated for the app.
|
||||
|
||||
* The value must be a valid GUID/CLSID in one of the following forms:
|
||||
* Canonical brace-wrapped: `{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}` (preferred)
|
||||
* Canonical without braces: `XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX` (braces will be added automatically)
|
||||
* Hex digits are case-insensitive.
|
||||
|
||||
This method should be called early (before showing notifications) so the value is baked into the registration/shortcut. Supplying an empty string or an unparsable value throws and leaves the existing (or generated) CLSID unchanged. If this method is never called, a random CLSID is generated once per run and exposed via `app.toastActivatorCLSID`.
|
||||
|
||||
### `app.setActivationPolicy(policy)` _macOS_
|
||||
|
||||
* `policy` string - Can be 'regular', 'accessory', or 'prohibited'.
|
||||
@@ -1225,7 +1240,7 @@ Returns `boolean` - whether hardware acceleration is currently enabled.
|
||||
### `app.disableDomainBlockingFor3DAPIs()`
|
||||
|
||||
By default, Chromium disables 3D APIs (e.g. WebGL) until restart on a per
|
||||
domain basis if the GPU processes crashes too frequently. This function
|
||||
domain basis if the GPU process crashes too frequently. This function
|
||||
disables that behavior.
|
||||
|
||||
This method can only be called before app is ready.
|
||||
@@ -1284,6 +1299,8 @@ For `infoType` equal to `basic`:
|
||||
|
||||
Using `basic` should be preferred if only basic information like `vendorId` or `deviceId` is needed.
|
||||
|
||||
Promise is rejected if the GPU is completely disabled, i.e. no hardware and software implementations are available.
|
||||
|
||||
### `app.setBadgeCount([count])` _Linux_ _macOS_
|
||||
|
||||
* `count` Integer (optional) - If a value is provided, set the badge to the provided value otherwise, on macOS, display a plain white dot (e.g. unknown number of notifications). On Linux, if a value is not provided the badge will not display.
|
||||
@@ -1314,7 +1331,7 @@ Returns `boolean` - Whether the current desktop environment is Unity launcher.
|
||||
### `app.getLoginItemSettings([options])` _macOS_ _Windows_
|
||||
|
||||
* `options` Object (optional)
|
||||
* `type` string (optional) _macOS_ - Can be one of `mainAppService`, `agentService`, `daemonService`, or `loginItemService`. Defaults to `mainAppService`. Only available on macOS 13 and up. See [app.setLoginItemSettings](app.md#appsetloginitemsettingssettings-macos-windows) for more information about each type.
|
||||
* `type` string (optional) _macOS_ - Can be `mainAppService`, `agentService`, `daemonService`, or `loginItemService`. Defaults to `mainAppService`. Only available on macOS 13 and up. See [app.setLoginItemSettings](app.md#appsetloginitemsettingssettings-macos-windows) for more information about each type.
|
||||
* `serviceName` string (optional) _macOS_ - The name of the service. Required if `type` is non-default. Only available on macOS 13 and up.
|
||||
* `path` string (optional) _Windows_ - The executable path to compare against. Defaults to `process.execPath`.
|
||||
* `args` string[] (optional) _Windows_ - The command-line arguments to compare against. Defaults to an empty array.
|
||||
@@ -1329,13 +1346,13 @@ Returns `Object`:
|
||||
* `wasOpenedAtLogin` boolean _macOS_ - `true` if the app was opened at login automatically.
|
||||
* `wasOpenedAsHidden` boolean _macOS_ _Deprecated_ - `true` if the app was opened as a hidden login item. This indicates that the app should not open any windows at startup. This setting is not available on [MAS builds][mas-builds] or on macOS 13 and up.
|
||||
* `restoreState` boolean _macOS_ _Deprecated_ - `true` if the app was opened as a login item that should restore the state from the previous session. This indicates that the app should restore the windows that were open the last time the app was closed. This setting is not available on [MAS builds][mas-builds] or on macOS 13 and up.
|
||||
* `status` string _macOS_ - can be one of `not-registered`, `enabled`, `requires-approval`, or `not-found`.
|
||||
* `status` string _macOS_ - can be `not-registered`, `enabled`, `requires-approval`, or `not-found`.
|
||||
* `executableWillLaunchAtLogin` boolean _Windows_ - `true` if app is set to open at login and its run key is not deactivated. This differs from `openAtLogin` as it ignores the `args` option, this property will be true if the given executable would be launched at login with **any** arguments.
|
||||
* `launchItems` Object[] _Windows_
|
||||
* `name` string _Windows_ - name value of a registry entry.
|
||||
* `path` string _Windows_ - The executable to an app that corresponds to a registry entry.
|
||||
* `args` string[] _Windows_ - the command-line arguments to pass to the executable.
|
||||
* `scope` string _Windows_ - one of `user` or `machine`. Indicates whether the registry entry is under `HKEY_CURRENT USER` or `HKEY_LOCAL_MACHINE`.
|
||||
* `scope` string _Windows_ - can be `user` or `machine`. Indicates whether the registry entry is under `HKEY_CURRENT USER` or `HKEY_LOCAL_MACHINE`.
|
||||
* `enabled` boolean _Windows_ - `true` if the app registry key is startup approved and therefore shows as `enabled` in Task Manager and Windows settings.
|
||||
|
||||
### `app.setLoginItemSettings(settings)` _macOS_ _Windows_
|
||||
@@ -1701,8 +1718,13 @@ platforms) that allows you to perform actions on your app icon in the user's doc
|
||||
|
||||
A `boolean` property that returns `true` if the app is packaged, `false` otherwise. For many apps, this property can be used to distinguish development and production environments.
|
||||
|
||||
### `app.toastActivatorCLSID` _Windows_ _Readonly_
|
||||
|
||||
A `string` property that returns the app's [Toast Activator CLSID][toast-activator-clsid].
|
||||
|
||||
[tasks]:https://learn.microsoft.com/en-us/windows/win32/shell/taskbar-extensions#tasks
|
||||
[app-user-model-id]: https://learn.microsoft.com/en-us/windows/win32/shell/appids
|
||||
[toast-activator-clsid]: https://learn.microsoft.com/en-us/windows/win32/properties/props-system-appusermodel-toastactivatorclsid
|
||||
[electron-forge]: https://www.electronforge.io/
|
||||
[electron-packager]: https://github.com/electron/packager
|
||||
[CFBundleURLTypes]: https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/TP40009249-102207-TPXREF115
|
||||
|
||||
@@ -32,9 +32,19 @@ update process. Apps that need to disable ATS can add the
|
||||
|
||||
### Windows
|
||||
|
||||
On Windows, you have to install your app into a user's machine before you can
|
||||
use the `autoUpdater`, so it is recommended that you use
|
||||
[electron-winstaller][installer-lib] or [Electron Forge's Squirrel.Windows maker][electron-forge-lib] to generate a Windows installer.
|
||||
On Windows, the `autoUpdater` module automatically selects the appropriate update mechanism
|
||||
based on how your app is packaged:
|
||||
|
||||
* **MSIX packages**: If your app is running as an MSIX package (created with [electron-windows-msix][msix-lib] and detected via [`process.windowsStore`](process.md#processwindowsstore-readonly)),
|
||||
the module uses the MSIX updater, which supports direct MSIX file links and JSON update feeds.
|
||||
* **Squirrel.Windows**: For apps installed via traditional installers (created with
|
||||
[electron-winstaller][installer-lib] or [Electron Forge's Squirrel.Windows maker][electron-forge-lib]),
|
||||
the module uses Squirrel.Windows for updates.
|
||||
|
||||
You don't need to configure which updater to use; Electron automatically detects the packaging
|
||||
format and uses the appropriate one.
|
||||
|
||||
#### Squirrel.Windows
|
||||
|
||||
Apps built with Squirrel.Windows will trigger [custom launch events](https://github.com/Squirrel/Squirrel.Windows/blob/51f5e2cb01add79280a53d51e8d0cfa20f8c9f9f/docs/using/custom-squirrel-events-non-cs.md#application-startup-commands)
|
||||
that must be handled by your Electron application to ensure proper setup and teardown.
|
||||
@@ -55,6 +65,14 @@ The installer generated with Squirrel.Windows will create a shortcut icon with a
|
||||
same ID for your app with `app.setAppUserModelId` API, otherwise Windows will
|
||||
not be able to pin your app properly in task bar.
|
||||
|
||||
#### MSIX Packages
|
||||
|
||||
When your app is packaged as an MSIX, the `autoUpdater` module provides additional
|
||||
functionality:
|
||||
|
||||
* Use the `allowAnyVersion` option in `setFeedURL()` to allow updates to older versions (downgrades)
|
||||
* Support for direct MSIX file links or JSON update feeds (similar to Squirrel.Mac format)
|
||||
|
||||
## Events
|
||||
|
||||
The `autoUpdater` object emits the following events:
|
||||
@@ -92,7 +110,7 @@ Returns:
|
||||
|
||||
Emitted when an update has been downloaded.
|
||||
|
||||
On Windows only `releaseName` is available.
|
||||
With Squirrel.Windows only `releaseName` is available.
|
||||
|
||||
> [!NOTE]
|
||||
> It is not strictly necessary to handle this event. A successfully
|
||||
@@ -128,10 +146,12 @@ changes:
|
||||
-->
|
||||
|
||||
* `options` Object
|
||||
* `url` string
|
||||
* `url` string - The update server URL. For _Windows_ MSIX, this can be either a direct link to an MSIX file (e.g., `https://example.com/update.msix`) or a JSON endpoint that returns update information (see the [Squirrel.Mac][squirrel-mac] README for more information).
|
||||
* `headers` Record\<string, string\> (optional) _macOS_ - HTTP request headers.
|
||||
* `serverType` string (optional) _macOS_ - Can be `json` or `default`, see the [Squirrel.Mac][squirrel-mac]
|
||||
README for more information.
|
||||
* `allowAnyVersion` boolean (optional) _Windows_ - If `true`, allows downgrades to older versions for MSIX packages.
|
||||
Defaults to `false`.
|
||||
|
||||
Sets the `url` and initialize the auto updater.
|
||||
|
||||
@@ -168,3 +188,4 @@ closed.
|
||||
[electron-forge-lib]: https://www.electronforge.io/config/makers/squirrel.windows
|
||||
[app-user-model-id]: https://learn.microsoft.com/en-us/windows/win32/shell/appids
|
||||
[event-emitter]: https://nodejs.org/api/events.html#events_class_eventemitter
|
||||
[msix-lib]: https://github.com/electron-userland/electron-windows-msix
|
||||
|
||||
@@ -351,7 +351,11 @@ Emitted when the window has closed a sheet.
|
||||
|
||||
#### Event: 'new-window-for-tab' _macOS_
|
||||
|
||||
Emitted when the native new tab button is clicked.
|
||||
Emitted when the user clicks the native macOS new tab button. The new
|
||||
tab button is only visible if the current `BrowserWindow` has a
|
||||
`tabbingIdentifier`.
|
||||
|
||||
You must create a window in this handler in order for macOS tabbing to work as expected.
|
||||
|
||||
#### Event: 'system-context-menu' _Windows_ _Linux_
|
||||
|
||||
@@ -756,6 +760,9 @@ Returns [`Rectangle`](structures/rectangle.md) - The `bounds` of the window as `
|
||||
> [!NOTE]
|
||||
> On macOS, the y-coordinate value returned will be at minimum the [Tray](tray.md) height. For example, calling `win.setBounds({ x: 25, y: 20, width: 800, height: 600 })` with a tray height of 38 means that `win.getBounds()` will return `{ x: 25, y: 38, width: 800, height: 600 }`.
|
||||
|
||||
> [!NOTE]
|
||||
> On Wayland, this method will return `{ x: 0, y: 0, ... }` as introspecting or programmatically changing the global window coordinates is prohibited.
|
||||
|
||||
#### `win.getBackgroundColor()`
|
||||
|
||||
Returns `string` - Gets the background color of the window in Hex (`#RRGGBB`) format.
|
||||
@@ -969,6 +976,9 @@ Moves window to `x` and `y`.
|
||||
|
||||
Returns `Integer[]` - Contains the window's current position.
|
||||
|
||||
> [!NOTE]
|
||||
> On Wayland, this method will return `[0, 0]` as introspecting or programmatically changing the global window coordinates is prohibited.
|
||||
|
||||
#### `win.setTitle(title)`
|
||||
|
||||
* `title` string
|
||||
@@ -1043,7 +1053,7 @@ under this mode apps can choose to optimize their UI for tablets, such as
|
||||
enlarging the titlebar and hiding titlebar buttons.
|
||||
|
||||
This API returns whether the window is in tablet mode, and the `resize` event
|
||||
can be be used to listen to changes to tablet mode.
|
||||
can be used to listen to changes to tablet mode.
|
||||
|
||||
#### `win.getMediaSourceId()`
|
||||
|
||||
|
||||
@@ -431,7 +431,11 @@ Emitted when the window has closed a sheet.
|
||||
|
||||
#### Event: 'new-window-for-tab' _macOS_
|
||||
|
||||
Emitted when the native new tab button is clicked.
|
||||
Emitted when the user clicks the native macOS new tab button. The new
|
||||
tab button is only visible if the current `BrowserWindow` has a
|
||||
`tabbingIdentifier`.
|
||||
|
||||
You must create a window in this handler in order for macOS tabbing to work as expected.
|
||||
|
||||
#### Event: 'system-context-menu' _Windows_ _Linux_
|
||||
|
||||
@@ -849,6 +853,9 @@ Returns [`Rectangle`](structures/rectangle.md) - The `bounds` of the window as `
|
||||
> [!NOTE]
|
||||
> On macOS, the y-coordinate value returned will be at minimum the [Tray](tray.md) height. For example, calling `win.setBounds({ x: 25, y: 20, width: 800, height: 600 })` with a tray height of 38 means that `win.getBounds()` will return `{ x: 25, y: 38, width: 800, height: 600 }`.
|
||||
|
||||
> [!NOTE]
|
||||
> On Wayland, this method will return `{ x: 0, y: 0, ... }` as introspecting or programmatically changing the global window coordinates is prohibited.
|
||||
|
||||
#### `win.getBackgroundColor()`
|
||||
|
||||
Returns `string` - Gets the background color of the window in Hex (`#RRGGBB`) format.
|
||||
@@ -1062,6 +1069,9 @@ Moves window to `x` and `y`.
|
||||
|
||||
Returns `Integer[]` - Contains the window's current position.
|
||||
|
||||
> [!NOTE]
|
||||
> On Wayland, this method will return `[0, 0]` as introspecting or programmatically changing the global window coordinates is prohibited.
|
||||
|
||||
#### `win.setTitle(title)`
|
||||
|
||||
* `title` string
|
||||
@@ -1134,7 +1144,7 @@ under this mode apps can choose to optimize their UI for tablets, such as
|
||||
enlarging the titlebar and hiding titlebar buttons.
|
||||
|
||||
This API returns whether the window is in tablet mode, and the `resize` event
|
||||
can be be used to listen to changes to tablet mode.
|
||||
can be used to listen to changes to tablet mode.
|
||||
|
||||
#### `win.getMediaSourceId()`
|
||||
|
||||
|
||||
@@ -264,7 +264,7 @@ will not be allowed. The `finish` event is emitted just after the end operation.
|
||||
Cancels an ongoing HTTP transaction. If the request has already emitted the
|
||||
`close` event, the abort operation will have no effect. Otherwise an ongoing
|
||||
event will emit `abort` and `close` events. Additionally, if there is an ongoing
|
||||
response object,it will emit the `aborted` event.
|
||||
response object, it will emit the `aborted` event.
|
||||
|
||||
#### `request.followRedirect()`
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
Process: [Main](../glossary.md#main-process), [Renderer](../glossary.md#renderer-process) _Deprecated_ (non-sandboxed only)
|
||||
|
||||
> [!NOTE]
|
||||
> Using the `clipoard` API from the renderer process is deprecated.
|
||||
> Using the `clipboard` API from the renderer process is deprecated.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> If you want to call this API from a renderer process,
|
||||
|
||||
@@ -168,7 +168,7 @@ Enables net log events to be saved and writes them to `path`.
|
||||
Sets the verbosity of logging when used together with `--enable-logging`.
|
||||
`N` should be one of [Chrome's LogSeverities][severities].
|
||||
|
||||
Note that two complimentary logging mechanisms in Chromium -- `LOG()`
|
||||
Note that two complementary logging mechanisms in Chromium -- `LOG()`
|
||||
and `VLOG()` -- are controlled by different switches. `--log-level`
|
||||
controls `LOG()` messages, while `--v` and `--vmodule` control `VLOG()`
|
||||
messages. So you may want to use a combination of these three switches
|
||||
@@ -366,6 +366,13 @@ Keep in mind that standalone switches can sometimes be split into individual fea
|
||||
|
||||
Finally, you'll need to ensure that the version of Chromium in Electron matches the version of the browser you're using to cross-reference the switches.
|
||||
|
||||
### Chromium features relevant to Electron apps
|
||||
|
||||
* `AlwaysLogLOAFURL`: enables script attribution for
|
||||
[`long-animation-frame`](https://developer.mozilla.org/en-US/docs/Web/API/Performance_API/Long_animation_frame_timing)
|
||||
`PerformanceObserver` events for non-http(s), non-data, non-blob URLs (such as `file:` or custom
|
||||
protocol URLs).
|
||||
|
||||
[app]: app.md
|
||||
[append-switch]: command-line.md#commandlineappendswitchswitch-value
|
||||
[debugging-main-process]: ../tutorial/debugging-main-process.md
|
||||
|
||||
@@ -49,7 +49,7 @@ Use the `system-ui` keyword to match the smoothness to the OS design language.
|
||||
| Value: | `60%` | `0%` |
|
||||
| Example: |  |  |
|
||||
|
||||
### Controlling availibility
|
||||
### Controlling availability
|
||||
|
||||
This CSS rule can be disabled using the Blink feature flag `ElectronCSSCornerSmoothing`.
|
||||
|
||||
|
||||
@@ -94,18 +94,45 @@ The `desktopCapturer` module has the following methods:
|
||||
Returns `Promise<DesktopCapturerSource[]>` - Resolves with an array of [`DesktopCapturerSource`](structures/desktop-capturer-source.md) objects, each `DesktopCapturerSource` represents a screen or an individual window that can be captured.
|
||||
|
||||
> [!NOTE]
|
||||
> Capturing the screen contents requires user consent on macOS 10.15 Catalina or higher,
|
||||
> which can detected by [`systemPreferences.getMediaAccessStatus`][].
|
||||
|
||||
> * Capturing audio requires `NSAudioCaptureUsageDescription` Info.plist key on macOS 14.2 Sonoma and higher - [read more](#macos-versions-142-or-higher).
|
||||
> * Capturing the screen contents requires user consent on macOS 10.15 Catalina or higher, which can detected by [`systemPreferences.getMediaAccessStatus`][].
|
||||
|
||||
[`navigator.mediaDevices.getUserMedia`]: https://developer.mozilla.org/en/docs/Web/API/MediaDevices/getUserMedia
|
||||
[`systemPreferences.getMediaAccessStatus`]: system-preferences.md#systempreferencesgetmediaaccessstatusmediatype-windows-macos
|
||||
|
||||
## Caveats
|
||||
|
||||
### Linux
|
||||
|
||||
`desktopCapturer.getSources(options)` only returns a single source on Linux when using Pipewire.
|
||||
|
||||
PipeWire supports a single capture for both screens and windows. If you request the window and screen type, the selected source will be returned as a window capture.
|
||||
|
||||
`navigator.mediaDevices.getUserMedia` does not work on macOS for audio capture due to a fundamental limitation whereby apps that want to access the system's audio require a [signed kernel extension](https://developer.apple.com/library/archive/documentation/Security/Conceptual/System_Integrity_Protection_Guide/KernelExtensions/KernelExtensions.html). Chromium, and by extension Electron, does not provide this.
|
||||
---
|
||||
|
||||
It is possible to circumvent this limitation by capturing system audio with another macOS app like Soundflower and passing it through a virtual audio input device. This virtual device can then be queried with `navigator.mediaDevices.getUserMedia`.
|
||||
### MacOS versions 14.2 or higher
|
||||
|
||||
`NSAudioCaptureUsageDescription` Info.plist key must be added in-order for audio to be captured by `desktopCapturer`. If instead you are running electron from another program like a terminal or IDE then that parent program must contain the Info.plist key.
|
||||
|
||||
This is in order to facillitate use of Apple's new [CoreAudio Tap API](https://developer.apple.com/documentation/CoreAudio/capturing-system-audio-with-core-audio-taps#Configure-the-sample-code-project) by Chromium.
|
||||
|
||||
> [!WARNING]
|
||||
> Failure of `desktopCapturer` to start an audio stream due to `NSAudioCaptureUsageDescription` permission not present will still create a dead audio stream however no warnings or errors are displayed.
|
||||
|
||||
As of electron `v39.0.0-beta.4` Chromium [made Apple's new `CoreAudio Tap API` the default](https://source.chromium.org/chromium/chromium/src/+/ad17e8f8b93d5f34891b06085d373a668918255e) for desktop audio capture. There is no fallback to the older `Screen & System Audio Recording` permissions system even if [CoreAudio Tap API](https://developer.apple.com/documentation/CoreAudio/capturing-system-audio-with-core-audio-taps) stream creation fails.
|
||||
|
||||
If you need to continue using `Screen & System Audio Recording` permissions for `desktopCapturer` on macOS versions 14.2 and later, you can apply a chromium feature flag to force use of that older permissions system:
|
||||
|
||||
```js
|
||||
// main.js (right beneath your require/import statments)
|
||||
app.commandLine.appendSwitch('disable-features', 'MacCatapLoopbackAudioForScreenShare')
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### MacOS versions 12.7.6 or lower
|
||||
|
||||
`navigator.mediaDevices.getUserMedia` does not work on macOS versions 12.7.6 and prior for audio capture due to a fundamental limitation whereby apps that want to access the system's audio require a [signed kernel extension](https://developer.apple.com/library/archive/documentation/Security/Conceptual/System_Integrity_Protection_Guide/KernelExtensions/KernelExtensions.html). Chromium, and by extension Electron, does not provide this. Only in macOS 13 and onwards does Apple provide APIs to capture desktop audio without the need for a signed kernel extension.
|
||||
|
||||
It is possible to circumvent this limitation by capturing system audio with another macOS app like [BlackHole](https://existential.audio/blackhole/) or [Soundflower](https://rogueamoeba.com/freebies/soundflower/) and passing it through a virtual audio input device. This virtual device can then be queried with `navigator.mediaDevices.getUserMedia`.
|
||||
|
||||
@@ -344,7 +344,7 @@ Displays a modal dialog that shows an error message.
|
||||
|
||||
This API can be called safely before the `ready` event the `app` module emits,
|
||||
it is usually used to report errors in early stage of startup. If called
|
||||
before the app `ready`event on Linux, the message will be emitted to stderr,
|
||||
before the app `ready` event on Linux, the message will be emitted to stderr,
|
||||
and no GUI dialog will appear.
|
||||
|
||||
### `dialog.showCertificateTrustDialog([window, ]options)` _macOS_ _Windows_
|
||||
|
||||
@@ -159,6 +159,22 @@ Notification activated (com.github.Electron:notification:EAF7B87C-A113-43D7-8E76
|
||||
Notification replied to (com.github.Electron:notification:EAF7B87C-A113-43D7-8E76-F88EC9D73D44)
|
||||
```
|
||||
|
||||
### `ELECTRON_DEBUG_MSIX_UPDATER`
|
||||
|
||||
Adds extra logs to MSIX updater operations on Windows to aid in debugging. Extra logging will be displayed when MSIX update operations are initiated, including package updates, package registration, and restart registration. This helps diagnose issues with MSIX package updates and deployments.
|
||||
|
||||
Sample output:
|
||||
|
||||
```sh
|
||||
UpdateMsix called with URI: https://example.com/app.msix
|
||||
DoUpdateMsix: Starting
|
||||
Calling AddPackageByUriAsync... URI: https://example.com/app.msix
|
||||
Update options - deferRegistration: true, developerMode: false, forceShutdown: false, forceTargetShutdown: false, forceUpdateFromAnyVersion: false
|
||||
Waiting for deployment...
|
||||
Deployment finished.
|
||||
MSIX Deployment completed.
|
||||
```
|
||||
|
||||
### `ELECTRON_LOG_ASAR_READS`
|
||||
|
||||
When Electron reads from an ASAR file, log the read offset and file path to
|
||||
|
||||
@@ -34,7 +34,7 @@ Returns:
|
||||
* `error` Error - Typically holds an error string identifying failure root cause.
|
||||
|
||||
Emitted when an error was encountered while streaming response data events. For
|
||||
instance, if the server closes the underlying while the response is still
|
||||
instance, if the server closes the underlying connection while the response is still
|
||||
streaming, an `error` event will be emitted on the response object and a `close`
|
||||
event will subsequently follow on the request object.
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ A `string` (optional) indicating the item's role, if set. Can be `undo`, `redo`,
|
||||
|
||||
#### `menuItem.accelerator`
|
||||
|
||||
An `Accelerator` (optional) indicating the item's accelerator, if set.
|
||||
An `Accelerator | null` indicating the item's accelerator, if set.
|
||||
|
||||
#### `menuItem.userAccelerator` _Readonly_ _macOS_
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ indicate which letter should get a generated accelerator. For example, using
|
||||
opens the associated menu. The indicated character in the button label then gets an
|
||||
underline, and the `&` character is not displayed on the button label.
|
||||
|
||||
In order to escape the `&` character in an item name, add a proceeding `&`. For example, `&&File` would result in `&File` displayed on the button label.
|
||||
In order to escape the `&` character in an item name, add a preceding `&`. For example, `&&File` would result in `&File` displayed on the button label.
|
||||
|
||||
Passing `null` will suppress the default menu. On Windows and Linux,
|
||||
this has the additional effect of removing the menu bar from the window.
|
||||
|
||||
@@ -83,4 +83,4 @@ Currently, Windows high contrast is the only system setting that triggers forced
|
||||
|
||||
### `nativeTheme.prefersReducedTransparency` _Readonly_
|
||||
|
||||
A `boolean` that indicates the whether the user has chosen via system accessibility settings to reduce transparency at the OS level.
|
||||
A `boolean` that indicates whether the user has chosen via system accessibility settings to reduce transparency at the OS level.
|
||||
|
||||
@@ -67,6 +67,22 @@ Emitted when the notification is shown to the user. Note that this event can be
|
||||
multiple times as a notification can be shown multiple times through the
|
||||
`show()` method.
|
||||
|
||||
```js
|
||||
const { Notification, app } = require('electron')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const n = new Notification({
|
||||
title: 'Title!',
|
||||
subtitle: 'Subtitle!',
|
||||
body: 'Body!'
|
||||
})
|
||||
|
||||
n.on('show', () => console.log('Notification shown!'))
|
||||
|
||||
n.show()
|
||||
})
|
||||
```
|
||||
|
||||
#### Event: 'click'
|
||||
|
||||
Returns:
|
||||
@@ -75,6 +91,22 @@ Returns:
|
||||
|
||||
Emitted when the notification is clicked by the user.
|
||||
|
||||
```js
|
||||
const { Notification, app } = require('electron')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const n = new Notification({
|
||||
title: 'Title!',
|
||||
subtitle: 'Subtitle!',
|
||||
body: 'Body!'
|
||||
})
|
||||
|
||||
n.on('click', () => console.log('Notification clicked!'))
|
||||
|
||||
n.show()
|
||||
})
|
||||
```
|
||||
|
||||
#### Event: 'close'
|
||||
|
||||
Returns:
|
||||
@@ -88,21 +120,85 @@ is closed.
|
||||
|
||||
On Windows, the `close` event can be emitted in one of three ways: programmatic dismissal with `notification.close()`, by the user closing the notification, or via system timeout. If a notification is in the Action Center after the initial `close` event is emitted, a call to `notification.close()` will remove the notification from the action center but the `close` event will not be emitted again.
|
||||
|
||||
#### Event: 'reply' _macOS_
|
||||
```js
|
||||
const { Notification, app } = require('electron')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const n = new Notification({
|
||||
title: 'Title!',
|
||||
subtitle: 'Subtitle!',
|
||||
body: 'Body!'
|
||||
})
|
||||
|
||||
n.on('close', () => console.log('Notification closed!'))
|
||||
|
||||
n.show()
|
||||
})
|
||||
```
|
||||
|
||||
#### Event: 'reply' _macOS_ _Windows_
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `reply` string - The string the user entered into the inline reply field.
|
||||
* `details` Event\<\>
|
||||
* `reply` string - The string the user entered into the inline reply field.
|
||||
* `reply` string _Deprecated_
|
||||
|
||||
Emitted when the user clicks the "Reply" button on a notification with `hasReply: true`.
|
||||
|
||||
#### Event: 'action' _macOS_
|
||||
```js
|
||||
const { Notification, app } = require('electron')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const n = new Notification({
|
||||
title: 'Send a Message',
|
||||
body: 'Body Text',
|
||||
hasReply: true,
|
||||
replyPlaceholder: 'Message text...'
|
||||
})
|
||||
|
||||
n.on('reply', (e, reply) => console.log(`User replied: ${reply}`))
|
||||
n.on('click', () => console.log('Notification clicked'))
|
||||
|
||||
n.show()
|
||||
})
|
||||
```
|
||||
|
||||
#### Event: 'action' _macOS_ _Windows_
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `index` number - The index of the action that was activated.
|
||||
* `details` Event\<\>
|
||||
* `actionIndex` number - The index of the action that was activated.
|
||||
* `selectionIndex` number _Windows_ - The index of the selected item, if one was chosen. -1 if none was chosen.
|
||||
* `actionIndex` number _Deprecated_
|
||||
* `selectionIndex` number _Windows_ _Deprecated_
|
||||
|
||||
```js
|
||||
const { Notification, app } = require('electron')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const items = ['One', 'Two', 'Three']
|
||||
const n = new Notification({
|
||||
title: 'Choose an Action!',
|
||||
actions: [
|
||||
{ type: 'button', text: 'Action 1' },
|
||||
{ type: 'button', text: 'Action 2' },
|
||||
{ type: 'selection', text: 'Apply', items }
|
||||
]
|
||||
})
|
||||
|
||||
n.on('click', () => console.log('Notification clicked'))
|
||||
n.on('action', (e) => {
|
||||
console.log(`User triggered action at index: ${e.actionIndex}`)
|
||||
if (e.selectionIndex > -1) {
|
||||
console.log(`User chose selection item '${items[e.selectionIndex]}'`)
|
||||
}
|
||||
})
|
||||
|
||||
n.show()
|
||||
})
|
||||
```
|
||||
|
||||
#### Event: 'failed' _Windows_
|
||||
|
||||
@@ -113,6 +209,22 @@ Returns:
|
||||
|
||||
Emitted when an error is encountered while creating and showing the native notification.
|
||||
|
||||
```js
|
||||
const { Notification, app } = require('electron')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const n = new Notification({
|
||||
title: 'Bad Action'
|
||||
})
|
||||
|
||||
n.on('failed', (e, err) => {
|
||||
console.log('Notification failed: ', err)
|
||||
})
|
||||
|
||||
n.show()
|
||||
})
|
||||
```
|
||||
|
||||
### Instance Methods
|
||||
|
||||
Objects created with the `new Notification()` constructor have the following instance methods:
|
||||
@@ -126,12 +238,42 @@ call this method before the OS will display it.
|
||||
If the notification has been shown before, this method will dismiss the previously
|
||||
shown notification and create a new one with identical properties.
|
||||
|
||||
```js
|
||||
const { Notification, app } = require('electron')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const n = new Notification({
|
||||
title: 'Title!',
|
||||
subtitle: 'Subtitle!',
|
||||
body: 'Body!'
|
||||
})
|
||||
|
||||
n.show()
|
||||
})
|
||||
```
|
||||
|
||||
#### `notification.close()`
|
||||
|
||||
Dismisses the notification.
|
||||
|
||||
On Windows, calling `notification.close()` while the notification is visible on screen will dismiss the notification and remove it from the Action Center. If `notification.close()` is called after the notification is no longer visible on screen, calling `notification.close()` will try remove it from the Action Center.
|
||||
|
||||
```js
|
||||
const { Notification, app } = require('electron')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const n = new Notification({
|
||||
title: 'Title!',
|
||||
subtitle: 'Subtitle!',
|
||||
body: 'Body!'
|
||||
})
|
||||
|
||||
n.show()
|
||||
|
||||
setTimeout(() => n.close(), 5000)
|
||||
})
|
||||
```
|
||||
|
||||
### Instance Properties
|
||||
|
||||
#### `notification.title`
|
||||
|
||||
@@ -99,13 +99,13 @@ property is used instead of the `--throw-deprecation` command line flag.
|
||||
|
||||
A `boolean` that controls whether or not deprecations printed to `stderr` include
|
||||
their stack trace. Setting this to `true` will print stack traces for deprecations.
|
||||
This property is instead of the `--trace-deprecation` command line flag.
|
||||
This property is used instead of the `--trace-deprecation` command line flag.
|
||||
|
||||
### `process.traceProcessWarnings`
|
||||
|
||||
A `boolean` that controls whether or not process warnings printed to `stderr` include
|
||||
their stack trace. Setting this to `true` will print stack traces for process warnings
|
||||
(including deprecations). This property is instead of the `--trace-warnings` command
|
||||
(including deprecations). This property is used instead of the `--trace-warnings` command
|
||||
line flag.
|
||||
|
||||
### `process.type` _Readonly_
|
||||
@@ -128,8 +128,8 @@ A `string` representing Electron's version string.
|
||||
|
||||
### `process.windowsStore` _Readonly_
|
||||
|
||||
A `boolean`. If the app is running as a Windows Store app (appx), this property is `true`,
|
||||
for otherwise it is `undefined`.
|
||||
A `boolean`. If the app is running as an MSIX package (including AppX for Windows Store),
|
||||
this property is `true`, otherwise it is `undefined`.
|
||||
|
||||
### `process.contextId` _Readonly_
|
||||
|
||||
|
||||
@@ -1216,7 +1216,7 @@ function createWindow () {
|
||||
|
||||
mainWindow.webContents.session.setBluetoothPairingHandler((details, callback) => {
|
||||
bluetoothPinCallback = callback
|
||||
// Send a IPC message to the renderer to prompt the user to confirm the pairing.
|
||||
// Send an IPC message to the renderer to prompt the user to confirm the pairing.
|
||||
// Note that this will require logic in the renderer to handle this message and
|
||||
// display a prompt to the user.
|
||||
mainWindow.webContents.send('bluetooth-pairing-request', details)
|
||||
@@ -1264,7 +1264,7 @@ session.defaultSession.allowNTLMCredentialsForDomains('*')
|
||||
|
||||
Overrides the `userAgent` and `acceptLanguages` for this session.
|
||||
|
||||
The `acceptLanguages` must a comma separated ordered list of language codes, for
|
||||
The `acceptLanguages` must be a comma separated ordered list of language codes, for
|
||||
example `"en-US,fr,de,ko,zh-CN,ja"`.
|
||||
|
||||
This doesn't affect existing `WebContents`, and each `WebContents` can use
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# sharedTexture
|
||||
|
||||
> Import shared textures into Electron and converts platform specific handles into [`VideoFrame`](https://developer.mozilla.org/en-US/docs/Web/API/VideoFrame). Supports all Web rendering systems, and can be transferred across Electron processes. Read [here](https://github.com/electron/electron/blob/main/shell/common/api/shared_texture/README.md) for more information.
|
||||
> Import shared textures into Electron and converts platform specific handles into [`VideoFrame`](https://developer.mozilla.org/en-US/docs/Web/API/VideoFrame). Supports all Web rendering systems, and can be transferred across Electron processes. Read [here](../../shell/common/api/shared_texture/README.md) for more information.
|
||||
|
||||
Process: [Main](../glossary.md#main-process), [Renderer](../glossary.md#renderer-process)
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* `depthPerComponent` number - The number of bits per color component.
|
||||
* `detected` boolean - `true` if the display is detected by the system.
|
||||
* `displayFrequency` number - The display refresh rate.
|
||||
* `id` number - Unique identifier associated with the display. A value of of -1 means the display is invalid or the correct `id` is not yet known, and a value of -10 means the display is a virtual display assigned to a unified desktop.
|
||||
* `id` number - Unique identifier associated with the display. A value of -1 means the display is invalid or the correct `id` is not yet known, and a value of -10 means the display is a virtual display assigned to a unified desktop.
|
||||
* `internal` boolean - `true` for an internal display and `false` for an external display.
|
||||
* `label` string - User-friendly label, determined by the platform.
|
||||
* `maximumCursorSize` [Size](size.md) - Maximum cursor size in native pixels.
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
# NotificationAction Object
|
||||
|
||||
* `type` string - The type of action, can be `button`.
|
||||
* `type` string - The type of action, can be `button` or `selection`. `selection` is only supported on Windows.
|
||||
* `text` string (optional) - The label for the given action.
|
||||
* `items` string[] (optional) _Windows_ - The list of items for the `selection` action `type`.
|
||||
|
||||
## Platform / Action Support
|
||||
|
||||
| Action Type | Platform Support | Usage of `text` | Default `text` | Limitations |
|
||||
|-------------|------------------|-----------------|----------------|-------------|
|
||||
| `button` | macOS | Used as the label for the button | "Show" (or a localized string by system default if first of such `button`, otherwise empty) | Only the first one is used. If multiple are provided, those beyond the first will be listed as additional actions (displayed when mouse active over the action button). Any such action also is incompatible with `hasReply` and will be ignored if `hasReply` is `true`. |
|
||||
| `button` | macOS, Windows | Used as the label for the button | "Show" on macOS (localized) if first `button`, otherwise empty; Windows uses provided `text` | macOS: Only the first one is used as primary; others shown as additional actions (hover). Incompatible with `hasReply` (beyond first ignored). |
|
||||
| `selection` | Windows | Used as the label for the submit button for the selection menu | "Select" | Requires an `items` array property specifying option labels. Emits the `action` event with `(index, selectedIndex)` where `selectedIndex` is the chosen option (>= 0). Ignored on platforms that do not support selection actions. |
|
||||
|
||||
### Button support on macOS
|
||||
|
||||
@@ -15,6 +17,37 @@ In order for extra notification buttons to work on macOS your app must meet the
|
||||
following criteria.
|
||||
|
||||
* App is signed
|
||||
* App has it's `NSUserNotificationAlertStyle` set to `alert` in the `Info.plist`.
|
||||
* App has its `NSUserNotificationAlertStyle` set to `alert` in the `Info.plist`.
|
||||
|
||||
If either of these requirements are not met the button won't appear.
|
||||
|
||||
### Selection support on Windows
|
||||
|
||||
To add a selection (combo box) style action, include an action with `type: 'selection'`, a `text` label for the submit button, and an `items` array of strings:
|
||||
|
||||
```js
|
||||
const { Notification, app } = require('electron')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const items = ['One', 'Two', 'Three']
|
||||
const n = new Notification({
|
||||
title: 'Choose an option',
|
||||
actions: [{
|
||||
type: 'selection',
|
||||
text: 'Apply',
|
||||
items
|
||||
}]
|
||||
})
|
||||
|
||||
n.on('action', (e) => {
|
||||
console.log(`User triggered action at index: ${e.actionIndex}`)
|
||||
if (e.selectionIndex > 0) {
|
||||
console.log(`User chose selection item '${items[e.selectionIndex]}'`)
|
||||
}
|
||||
})
|
||||
|
||||
n.show()
|
||||
})
|
||||
```
|
||||
|
||||
When the user activates the selection action, the notification's `action` event will be emitted with two parameters: `actionIndex` (the action's index in the `actions` array) and `selectedIndex` (the zero-based index of the chosen item, or `-1` if unavailable). On non-Windows platforms selection actions are ignored.
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* `bgra` - 32bpp BGRA (byte-order), 1 plane.
|
||||
* `rgba` - 32bpp RGBA (byte-order), 1 plane.
|
||||
* `rgbaf16` - Half float RGBA, 1 plane.
|
||||
* `nv12` - 12bpp with Y plane followed by a 2x2 interleaved UV plane.
|
||||
* `colorSpace` [ColorSpace](color-space.md) (optional) - The color space of the texture.
|
||||
* `codedSize` [Size](size.md) - The full dimensions of the shared texture.
|
||||
* `visibleRect` [Rectangle](rectangle.md) (optional) - A subsection of [0, 0, codedSize.width, codedSize.height]. In common cases, it is the full section area.
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
* `javascript` boolean (optional) - Enables JavaScript support. Default is `true`.
|
||||
* `webSecurity` boolean (optional) - When `false`, it will disable the
|
||||
same-origin policy (usually using testing websites by people), and set
|
||||
`allowRunningInsecureContent` to `true` if this options has not been set
|
||||
`allowRunningInsecureContent` to `true` if this option has not been set
|
||||
by user. Default is `true`.
|
||||
* `allowRunningInsecureContent` boolean (optional) - Allow an https page to run
|
||||
JavaScript, CSS or plugins from http URLs. Default is `false`.
|
||||
@@ -156,6 +156,8 @@
|
||||
`WebContents` when the preferred size changes. Default is `false`.
|
||||
* `transparent` boolean (optional) - Whether to enable background transparency for the guest page. Default is `true`. **Note:** The guest page's text and background colors are derived from the [color scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/color-scheme) of its root element. When transparency is enabled, the text color will still change accordingly but the background will remain transparent.
|
||||
* `enableDeprecatedPaste` boolean (optional) _Deprecated_ - Whether to enable the `paste` [execCommand](https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand). Default is `false`.
|
||||
* `focusOnNavigation` boolean (optional) - Whether to focus the WebContents
|
||||
when navigating. Default is `true`.
|
||||
|
||||
[chrome-content-scripts]: https://developer.chrome.com/extensions/content_scripts#execution-environment
|
||||
[runtime-enabled-features]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/platform/runtime_enabled_features.json5
|
||||
|
||||
@@ -36,6 +36,12 @@ Process: [Main](../glossary.md#main-process)<br />
|
||||
`com.apple.security.cs.allow-unsigned-executable-memory` entitlements. This will allow the utility process
|
||||
to load unsigned libraries. Unless you specifically need this capability, it is best to leave this disabled.
|
||||
Default is `false`.
|
||||
* `disclaim` boolean (optional) _macOS_ - With this flag, the utility process will disclaim
|
||||
responsibility for the child process. This causes the operating system to consider the child
|
||||
process as a separate entity for purposes of security policies like Transparency, Consent, and
|
||||
Control (TCC). When responsibility is disclaimed, the parent process will not be attributed
|
||||
for any TCC requests initiated by the child process. This is useful when launching processes
|
||||
that run third-party or otherwise untrusted code. Default is `false`.
|
||||
* `respondToAuthRequestsFromMainProcess` boolean (optional) - With this flag, all HTTP 401 and 407 network
|
||||
requests created via the [net module](net.md) will allow responding to them via the
|
||||
[`app#login`](app.md#event-login) event in the main process instead of the default
|
||||
|
||||
@@ -383,7 +383,7 @@ Emitted after a server side redirect occurs during navigation. For example a 30
|
||||
redirect.
|
||||
|
||||
This event cannot be prevented, if you want to prevent redirects you should
|
||||
checkout out the `will-redirect` event above.
|
||||
check out the `will-redirect` event above.
|
||||
|
||||
#### Event: 'did-navigate'
|
||||
|
||||
@@ -933,7 +933,7 @@ copying data between CPU and GPU memory, with Chromium's hardware acceleration s
|
||||
Only a limited number of textures can exist at the same time, so it's important that you call `texture.release()` as soon as you're done with the texture.
|
||||
By managing the texture lifecycle by yourself, you can safely pass the `texture.textureInfo` to other processes through IPC.
|
||||
|
||||
More details can be found in the [offscreen rendering tutorial](../tutorial/offscreen-rendering.md). To learn about how to handle the texture in native code, refer to [offscreen rendering's code documentation.](https://github.com/electron/electron/blob/main/shell/browser/osr/README.md).
|
||||
More details can be found in the [offscreen rendering tutorial](../tutorial/offscreen-rendering.md). To learn about how to handle the texture in native code, refer to [offscreen rendering's code documentation.](../../shell/browser/osr/README.md).
|
||||
|
||||
```js
|
||||
const { BrowserWindow } = require('electron')
|
||||
@@ -1465,7 +1465,7 @@ Ignore application menu shortcuts while this web contents is focused.
|
||||
without a recognized 'action' value will result in a console error and have
|
||||
the same effect as returning `{action: 'deny'}`.
|
||||
|
||||
Called before creating a window a new window is requested by the renderer, e.g.
|
||||
Called before creating a window when a new window is requested by the renderer, e.g.
|
||||
by `window.open()`, a link with `target="_blank"`, shift+clicking on a link, or
|
||||
submitting a form with `<form target="_blank">`. See
|
||||
[`window.open()`](window-open.md) for more details and how to use this in
|
||||
@@ -2168,7 +2168,7 @@ Returns `boolean` - If _offscreen rendering_ is enabled returns whether it is cu
|
||||
* `fps` Integer
|
||||
|
||||
If _offscreen rendering_ is enabled sets the frame rate to the specified number.
|
||||
Only values between 1 and 240 are accepted.
|
||||
When `webPreferences.offscreen.useSharedTexture` is `false` only values between 1 and 240 are accepted.
|
||||
|
||||
#### `contents.getFrameRate()`
|
||||
|
||||
@@ -2369,7 +2369,7 @@ instance that might own this `WebContents`.
|
||||
|
||||
#### `contents.devToolsWebContents` _Readonly_
|
||||
|
||||
A `WebContents | null` property that represents the of DevTools `WebContents` associated with a given `WebContents`.
|
||||
A `WebContents | null` property that represents the DevTools `WebContents` associated with a given `WebContents`.
|
||||
|
||||
> [!NOTE]
|
||||
> Users should never store this object because it may become `null`
|
||||
|
||||
@@ -50,6 +50,22 @@ webContents.setWindowOpenHandler((details) => {
|
||||
})
|
||||
```
|
||||
|
||||
### Behavior Changed: `NSAudioCaptureUsageDescription` should be included in your app's Info.plist file to use `desktopCapturer` (🍏 macOS ≥14.2)
|
||||
|
||||
Per [Chromium update](https://source.chromium.org/chromium/chromium/src/+/ad17e8f8b93d5f34891b06085d373a668918255e) which enables Apple's newer [CoreAudio Tap API](https://developer.apple.com/documentation/CoreAudio/capturing-system-audio-with-core-audio-taps#Configure-the-sample-code-project) by default, you now must have `NSAudioCaptureUsageDescription` defined in your `Info.plist` to use `desktopCapturer`.
|
||||
|
||||
Electron's `desktopCapturer` will create a dead audio stream if the new permission is absent however no errors or warnings will occur. This is partially a side-effect of Chromium not falling back to the older `Screen & System Audio Recording` permissions system if the new system fails.
|
||||
|
||||
To restore previous behavior:
|
||||
|
||||
```js
|
||||
// main.js (right beneath your require/import statments)
|
||||
app.commandLine.appendSwitch(
|
||||
'disable-features',
|
||||
'MacCatapLoopbackAudioForScreenShare'
|
||||
)
|
||||
```
|
||||
|
||||
### Behavior Changed: shared texture OSR `paint` event data structure
|
||||
|
||||
When using shared texture offscreen rendering feature, the `paint` event now emits a more structured object.
|
||||
@@ -68,7 +84,7 @@ Users can force XWayland by passing `--ozone-platform=x11`.
|
||||
### Removed: `ORIGINAL_XDG_CURRENT_DESKTOP` environment variable
|
||||
|
||||
Previously, Electron changed the value of `XDG_CURRENT_DESKTOP` internally to `Unity`, and stored the original name of the desktop session
|
||||
in a separate variable. `XDG_CURRENT_DESKTOP` is no longer overriden and now reflects the actual desktop environment.
|
||||
in a separate variable. `XDG_CURRENT_DESKTOP` is no longer overridden and now reflects the actual desktop environment.
|
||||
|
||||
### Removed: macOS 11 support
|
||||
|
||||
@@ -149,7 +165,7 @@ window is not currently visible.
|
||||
|
||||
`app.commandLine` was only meant to handle chromium switches (which aren't case-sensitive) and switches passed via `app.commandLine` will not be passed down to any of the child processes.
|
||||
|
||||
If you were using `app.commandLine` to control the behavior of the main process, you should do this via `process.argv`.
|
||||
If you were using `app.commandLine` to control the behavior of the main process, you should do this via `process.argv`.
|
||||
|
||||
### Deprecated: `NativeImage.getBitmap()`
|
||||
|
||||
@@ -179,7 +195,7 @@ from upstream Chromium.
|
||||
### Deprecated: `null` value for `session` property in `ProtocolResponse`
|
||||
|
||||
Previously, setting the ProtocolResponse.session property to `null`
|
||||
Would create a random independent session. This is no longer supported.
|
||||
would create a random independent session. This is no longer supported.
|
||||
|
||||
Using single-purpose sessions here is discouraged due to overhead costs;
|
||||
however, old code that needs to preserve this behavior can emulate it by
|
||||
@@ -190,7 +206,7 @@ and then using it in `ProtocolResponse.session`.
|
||||
|
||||
When calling `Session.clearStorageData(options)`, the `options.quota`
|
||||
property is deprecated. Since the `syncable` type was removed, there
|
||||
is only type left -- `'temporary'` -- so specifying it is unnecessary.
|
||||
is only one type left -- `'temporary'` -- so specifying it is unnecessary.
|
||||
|
||||
### Deprecated: Extension methods and events on `session`
|
||||
|
||||
@@ -519,7 +535,7 @@ more information.
|
||||
|
||||
### Removed: The `--disable-color-correct-rendering` switch
|
||||
|
||||
This switch was never formally documented but it's removal is being noted here regardless. Chromium itself now has better support for color spaces so this flag should not be needed.
|
||||
This switch was never formally documented but its removal is being noted here regardless. Chromium itself now has better support for color spaces so this flag should not be needed.
|
||||
|
||||
### Behavior Changed: `BrowserView.setAutoResize` behavior on macOS
|
||||
|
||||
@@ -1210,7 +1226,7 @@ more details.
|
||||
|
||||
### API Changed: `webContents.printToPDF()`
|
||||
|
||||
`webContents.printToPDF()` has been modified to conform to [`Page.printToPDF`](https://chromedevtools.github.io/devtools-protocol/tot/Page/#method-printToPDF) in the Chrome DevTools Protocol. This has been changes in order to
|
||||
`webContents.printToPDF()` has been modified to conform to [`Page.printToPDF`](https://chromedevtools.github.io/devtools-protocol/tot/Page/#method-printToPDF) in the Chrome DevTools Protocol. This has been changed in order to
|
||||
address changes upstream that made our previous implementation untenable and rife with bugs.
|
||||
|
||||
**Arguments Changed**
|
||||
|
||||
@@ -41,7 +41,7 @@ e init --root=~/electron --bootstrap testing
|
||||
```
|
||||
|
||||
The `--bootstrap` flag also runs `e sync` (synchronizes source code branches from
|
||||
[`DEPS`](https://github.com/electron/electron/blob/main/DEPS) using
|
||||
[`DEPS`](../../DEPS) using
|
||||
[`gclient`](https://chromium.googlesource.com/chromium/tools/depot_tools.git/+/HEAD/README.gclient.md))
|
||||
and `e build` (compiles the Electron binary into the `${root}/src/out` folder).
|
||||
|
||||
@@ -63,7 +63,7 @@ Some quick tips on building once your checkout is set up:
|
||||
* **Updating your checkout:** Run git commands such as `git checkout <branch>` and `git pull` from `${root}/src/electron`.
|
||||
Whenever you update your commit `HEAD`, make sure to `e sync` before `e build` to sync dependencies
|
||||
such as Chromium and Node.js. This is especially relevant because the Chromium version in
|
||||
[`DEPS`](https://github.com/electron/electron/blob/main/DEPS) changes frequently.
|
||||
[`DEPS`](../../DEPS) changes frequently.
|
||||
* **Rebuilding:** When making changes to code in `${root}/src/electron/` in a local branch, you only need to re-run `e build`.
|
||||
* **Adding patches:** When contributing changes in `${root}/src/` outside of `${root}/src/electron/`, you need to do so
|
||||
via Electron's [patch system](./patches.md). The `e patches` command can export all relevant patches to
|
||||
@@ -98,7 +98,7 @@ Project configurations can be found in the `.gn` and `.gni` files in the `electr
|
||||
|
||||
The following `gn` files contain the main rules for building Electron:
|
||||
|
||||
* [`BUILD.gn`](https://github.com/electron/electron/blob/main/BUILD.gn) defines how Electron itself
|
||||
* [`BUILD.gn`](../../BUILD.gn) defines how Electron itself
|
||||
is built and includes the default configurations for linking with Chromium.
|
||||
* [`build/args/{testing,release,all}.gn`](https://github.com/electron/electron/tree/main/build/args)
|
||||
contain the default build arguments for building Electron.
|
||||
|
||||
@@ -40,7 +40,7 @@ If you are on arm64 architecture, the build script may be pointing to the wrong
|
||||
|
||||
### Certificates fail to verify
|
||||
|
||||
installing [`certifi`](https://pypi.org/project/certifi/) will fix the following error:
|
||||
Installing [`certifi`](https://pypi.org/project/certifi/) will fix the following error:
|
||||
|
||||
```sh
|
||||
________ running 'python3 src/tools/clang/scripts/update.py' in '/Users/<user>/electron'
|
||||
|
||||
@@ -6,7 +6,7 @@ This is not a comprehensive end-all guide to creating an Electron Browser API, r
|
||||
|
||||
## Add your files to Electron's project configuration
|
||||
|
||||
Electron uses [GN](https://gn.googlesource.com/gn) as a meta build system to generate files for its compiler, [Ninja](https://ninja-build.org/). This means that in order to tell Electron to compile your code, we have to add your API's code and header file names into [`filenames.gni`](https://github.com/electron/electron/blob/main/filenames.gni).
|
||||
Electron uses [GN](https://gn.googlesource.com/gn) as a meta build system to generate files for its compiler, [Ninja](https://ninja-build.org/). This means that in order to tell Electron to compile your code, we have to add your API's code and header file names into [`filenames.gni`](../../filenames.gni).
|
||||
|
||||
You will need to append your API file names alphabetically into the appropriate files like so:
|
||||
|
||||
@@ -127,7 +127,7 @@ void Initialize(v8::Local<v8::Object> exports,
|
||||
|
||||
## Link your Electron API with Node
|
||||
|
||||
In the [`typings/internal-ambient.d.ts`](https://github.com/electron/electron/blob/main/typings/internal-ambient.d.ts) file, we need to append a new property onto the `Process` interface like so:
|
||||
In the [`typings/internal-ambient.d.ts`](../../typings/internal-ambient.d.ts) file, we need to append a new property onto the `Process` interface like so:
|
||||
|
||||
```ts title='typings/internal-ambient.d.ts' @ts-nocheck
|
||||
interface Process {
|
||||
@@ -141,7 +141,7 @@ At the very bottom of your `api_name.cc` file:
|
||||
NODE_LINKED_BINDING_CONTEXT_AWARE(electron_browser_{api_name},Initialize)
|
||||
```
|
||||
|
||||
In your [`shell/common/node_bindings.cc`](https://github.com/electron/electron/blob/main/shell/common/node_bindings.cc) file, add your node binding name to Electron's built-in modules.
|
||||
In your [`shell/common/node_bindings.cc`](../../shell/common/node_bindings.cc) file, add your node binding name to Electron's built-in modules.
|
||||
|
||||
```cpp title='shell/common/node_bindings.cc'
|
||||
#define ELECTRON_BROWSER_MODULES(V) \
|
||||
@@ -159,7 +159,7 @@ We will need to create a new TypeScript file in the path that follows:
|
||||
|
||||
`"lib/browser/api/{electron_browser_{api_name}}.ts"`
|
||||
|
||||
An example of the contents of this file can be found [here](https://github.com/electron/electron/blob/main/lib/browser/api/native-theme.ts).
|
||||
An example of the contents of this file can be found [here](../../lib/browser/api/native-theme.ts).
|
||||
|
||||
### Expose your module to TypeScript
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ with breakpoints inside Electron's source code.
|
||||
format.
|
||||
|
||||
* **ProcMon**: The [free SysInternals tool][sys-internals] allows you to inspect
|
||||
a processes parameters, file handles, and registry operations.
|
||||
a process's parameters, file handles, and registry operations.
|
||||
|
||||
## Attaching to and Debugging Electron
|
||||
|
||||
|
||||
@@ -185,7 +185,7 @@ $ git push origin my-branch
|
||||
### Step 9: Opening the Pull Request
|
||||
|
||||
From within GitHub, opening a new pull request will present you with a template
|
||||
that should be filled out. It can be found [here](https://github.com/electron/electron/blob/main/.github/PULL_REQUEST_TEMPLATE.md).
|
||||
that should be filled out. It can be found [here](../../.github/PULL_REQUEST_TEMPLATE.md).
|
||||
|
||||
If you do not adequately complete this template, your PR may be delayed in being merged as maintainers
|
||||
seek more information or clarify ambiguities.
|
||||
@@ -218,8 +218,7 @@ seem unfamiliar, refer to this
|
||||
|
||||
#### Approval and Request Changes Workflow
|
||||
|
||||
All pull requests require approval from a
|
||||
[Code Owner](https://github.com/electron/electron/blob/main/.github/CODEOWNERS)
|
||||
All pull requests require approval from a [Code Owner](../../.github/CODEOWNERS)
|
||||
of the area you modified in order to land. Whenever a maintainer reviews a pull
|
||||
request they may request changes. These may be small, such as fixing a typo, or
|
||||
may involve substantive changes. Such requests are intended to be helpful, but
|
||||
|
||||
@@ -10,11 +10,11 @@ to understand the source code better.
|
||||
## Project structure
|
||||
|
||||
Electron is a complex project containing multiple upstream dependencies, which are tracked in source
|
||||
control via the [`DEPS`](https://github.com/electron/electron/blob/main/DEPS) file. When
|
||||
control via the [`DEPS`](../../DEPS) file. When
|
||||
[initializing a local Electron checkout](./build-instructions-gn.md), Electron's source code is just one
|
||||
of many nested folders within the project root.
|
||||
|
||||
The project contains a single `src` folder that corresponds a specific git checkout of
|
||||
The project contains a single `src` folder that corresponds to a specific git checkout of
|
||||
[Chromium's `src` folder](https://source.chromium.org/chromium/chromium/src). In addition, Electron's
|
||||
repository code is contained in `src/electron` (with its own nested git repository), and other
|
||||
Electron-specific third-party dependencies (e.g. [nan](https://github.com/nodejs/nan) or
|
||||
|
||||
@@ -17,7 +17,7 @@ style, run `npm run lint`, which will run a variety of linting checks
|
||||
against your changes depending on which areas of the code they touch.
|
||||
|
||||
Many of these checks are included as precommit hooks, so it's likely
|
||||
you error would be caught at commit time.
|
||||
your error would be caught at commit time.
|
||||
|
||||
## Unit Tests
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ dependency tree from `node_modules`).
|
||||
|
||||
### ASAR integrity
|
||||
|
||||
ASAR integrity is an security feature that validates the contents of your app's
|
||||
ASAR integrity is a security feature that validates the contents of your app's
|
||||
ASAR archives at runtime. When enabled, your Electron app will verify the
|
||||
header hash of its ASAR archive on runtime. If no hash is present or if there is a mismatch in the
|
||||
hashes, the app will forcefully terminate.
|
||||
@@ -137,9 +137,9 @@ See also: [code signing](#code-signing)
|
||||
|
||||
### OSR
|
||||
|
||||
OSR (offscreen rendering) can be used for loading heavy page in
|
||||
OSR (offscreen rendering) can be used for loading a heavy page in
|
||||
background and then displaying it after (it will be much faster).
|
||||
It allows you to render page without showing it on screen.
|
||||
It allows you to render a page without showing it on screen.
|
||||
|
||||
For more information, read the [Offscreen Rendering][] tutorial.
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ hide_title: false
|
||||
---
|
||||
|
||||
After creating an [application distribution](application-distribution.md), the
|
||||
app's source code are usually bundled into an [ASAR archive](https://github.com/electron/asar),
|
||||
app's source code is usually bundled into an [ASAR archive](https://github.com/electron/asar),
|
||||
which is a simple extensive archive format designed for Electron apps. By bundling the app
|
||||
we can mitigate issues around long path names on Windows, speed up `require` and conceal your source
|
||||
code from cursory inspection.
|
||||
@@ -134,7 +134,7 @@ underlying system calls, Electron will extract the needed file into a
|
||||
temporary file and pass the path of the temporary file to the APIs to make them
|
||||
work. This adds a little overhead for those APIs.
|
||||
|
||||
APIs that requires extra unpacking are:
|
||||
APIs that require extra unpacking are:
|
||||
|
||||
* `child_process.execFile`
|
||||
* `child_process.execFileSync`
|
||||
|
||||
@@ -15,6 +15,14 @@ Currently, ASAR integrity checking is supported on:
|
||||
* macOS as of `electron>=16.0.0`
|
||||
* Windows as of `electron>=30.0.0`
|
||||
|
||||
> [!NOTE]
|
||||
> ASAR integrity is fully supported in Mac App Store (MAS) builds and is recommended
|
||||
> as a best practice. While MAS-installed applications have their `Resources/` folder
|
||||
> protected by the system (owned by root), ASAR integrity still provides an additional
|
||||
> layer of security. It is especially important if you use Electron's MAS build but
|
||||
> distribute your app through channels other than the Mac App Store (such as direct
|
||||
> download), since those installations won't have the system-level read-only protections.
|
||||
|
||||
In order to enable ASAR integrity checking, you also need to ensure that your `app.asar` file
|
||||
was generated by a version of the `@electron/asar` npm package that supports ASAR integrity.
|
||||
|
||||
@@ -24,7 +32,7 @@ All versions of `@electron/asar` support ASAR integrity.
|
||||
## How it works
|
||||
|
||||
Each ASAR archive contains a JSON string header. The header format includes an `integrity` object
|
||||
that contain a hex encoded hash of the entire archive as well as an array of hex encoded hashes for each
|
||||
that contains a hex encoded hash of the entire archive as well as an array of hex encoded hashes for each
|
||||
block of `blockSize` bytes.
|
||||
|
||||
```json
|
||||
|
||||
@@ -203,7 +203,7 @@ test('launch app', async () => {
|
||||
})
|
||||
```
|
||||
|
||||
After that, you will access to an instance of Playwright's `ElectronApp` class. This
|
||||
After that, you will have access to an instance of Playwright's `ElectronApp` class. This
|
||||
is a powerful class that has access to main process modules for example:
|
||||
|
||||
```js {5-10} @ts-nocheck
|
||||
@@ -237,7 +237,7 @@ test('save screenshot', async () => {
|
||||
})
|
||||
```
|
||||
|
||||
Putting all this together using the Playwright test-runner, let's create a `example.spec.js`
|
||||
Putting all this together using the Playwright test-runner, let's create an `example.spec.js`
|
||||
test file with a single test and assertion:
|
||||
|
||||
```js title='example.spec.js' @ts-nocheck
|
||||
@@ -377,7 +377,7 @@ class TestDriver {
|
||||
module.exports = { TestDriver }
|
||||
```
|
||||
|
||||
In your app code, can then write a simple handler to receive RPC calls:
|
||||
In your app code, you can then write a simple handler to receive RPC calls:
|
||||
|
||||
```js title='main.js'
|
||||
const METHODS = {
|
||||
|
||||
@@ -17,7 +17,7 @@ run them, users need to go through multiple advanced and manual steps.
|
||||
|
||||
If you are building an Electron app that you intend to package and distribute,
|
||||
it should be code signed. The Electron ecosystem tooling makes codesigning your
|
||||
apps straightforward - this documentation explains how sign your apps on both
|
||||
apps straightforward - this documentation explains how to sign your apps on both
|
||||
Windows and macOS.
|
||||
|
||||
## Signing & notarizing macOS builds
|
||||
@@ -210,7 +210,7 @@ const msiCreator = new MSICreator({
|
||||
const supportBinaries = await msiCreator.create()
|
||||
|
||||
// 🆕 Step 2a: optionally sign support binaries if you
|
||||
// sign you binaries as part of of your packaging script
|
||||
// sign your binaries as part of your packaging script
|
||||
for (const binary of supportBinaries) {
|
||||
// Binaries are the new stub executable and optionally
|
||||
// the Squirrel auto updater.
|
||||
@@ -238,6 +238,20 @@ with 3+ years of verifiable business history and to individual developers in the
|
||||
Microsoft is looking to make the program more widely available. If you're reading this at a
|
||||
later point, it could make sense to check if the eligibility criteria have changed.
|
||||
|
||||
#### Using `jsign` for Azure Trusted Signing
|
||||
|
||||
For developers on Linux or macOS, [`jsign`](https://ebourg.github.io/jsign/) can be used to sign Windows apps via Azure Trusted Signing. Example usage:
|
||||
|
||||
```bash
|
||||
jsign --storetype TRUSTEDSIGNING \
|
||||
--keystore https://eus.codesigning.azure.net/ \
|
||||
--storepass $AZURE_ACCESS_TOKEN \
|
||||
--alias trusted-sign-acct/AppName \
|
||||
--tsaurl http://timestamp.acs.microsoft.com/ \
|
||||
--tsmode RFC3161 \
|
||||
--replace <file>
|
||||
```
|
||||
|
||||
#### Using Electron Forge
|
||||
|
||||
Electron Forge is the recommended way to sign your app as well as your `Squirrel.Windows`
|
||||
|
||||
@@ -110,7 +110,7 @@ const win = new BrowserWindow({
|
||||
#### Show and hide the traffic lights programmatically _macOS_
|
||||
|
||||
You can also show and hide the traffic lights programmatically from the main process.
|
||||
The `win.setWindowButtonVisibility` forces traffic lights to be show or hidden depending
|
||||
The `win.setWindowButtonVisibility` forces traffic lights to be shown or hidden depending
|
||||
on the value of its boolean parameter.
|
||||
|
||||
```js title='main.js'
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
By default, windows are dragged using the title bar provided by the OS chrome. Apps
|
||||
that remove the default title bar need to use the `app-region` CSS property to define
|
||||
specific areas that can be used to drag the window. Setting `app-region: drag` marks
|
||||
a rectagular area as draggable.
|
||||
a rectangular area as draggable.
|
||||
|
||||
It is important to note that draggable areas ignore all pointer events. For example,
|
||||
a button element that overlaps a draggable region will not emit mouse clicks or mouse
|
||||
enter/exit events within that overlapping area. Setting `app-region: no-drag` reenables
|
||||
pointer events by excluding a rectagular area from a draggable region.
|
||||
pointer events by excluding a rectangular area from a draggable region.
|
||||
|
||||
To make the whole window draggable, you can add `app-region: drag` as
|
||||
`body`'s style:
|
||||
|
||||
@@ -29,7 +29,7 @@ be updated accordingly.
|
||||
In macOS 10.14 Mojave, Apple introduced a new [system-wide dark mode][system-wide-dark-mode]
|
||||
for all macOS computers. If your Electron app has a dark mode, you can make it
|
||||
follow the system-wide dark mode setting using
|
||||
[the `nativeTheme` api](../api/native-theme.md).
|
||||
[the `nativeTheme` API](../api/native-theme.md).
|
||||
|
||||
In macOS 10.15 Catalina, Apple introduced a new "automatic" dark mode option
|
||||
for all macOS computers. In order for the `nativeTheme.shouldUseDarkColors` and
|
||||
|
||||
@@ -197,4 +197,4 @@ Somewhere in the Electron binary, there will be a sequence of bytes that look li
|
||||
|
||||
To flip a fuse, you find its position in the fuse wire and change it to "0" or "1" depending on the state you'd like.
|
||||
|
||||
You can view the current schema [here](https://github.com/electron/electron/blob/main/build/fuses/fuses.json5).
|
||||
You can view the current schema [here](../../build/fuses/fuses.json5).
|
||||
|
||||
@@ -171,7 +171,7 @@ sections.
|
||||
|
||||
In the main process, we'll be creating a `handleFileOpen()` function that calls
|
||||
`dialog.showOpenDialog` and returns the value of the file path selected by the user. This function
|
||||
is used as a callback whenever an `ipcRender.invoke` message is sent through the `dialog:openFile`
|
||||
is used as a callback whenever an `ipcRenderer.invoke` message is sent through the `dialog:openFile`
|
||||
channel from the renderer process. The return value is then returned as a Promise to the original
|
||||
`invoke` call.
|
||||
|
||||
@@ -446,7 +446,7 @@ After loading the preload script, your renderer process should have access to th
|
||||
We don't directly expose the whole `ipcRenderer.on` API for [security reasons][]. Make sure to
|
||||
limit the renderer's access to Electron APIs as much as possible.
|
||||
Also don't just pass the callback to `ipcRenderer.on` as this will leak `ipcRenderer` via `event.sender`.
|
||||
Use a custom handler that invoke the `callback` only with the desired arguments.
|
||||
Use a custom handler that invokes the `callback` only with the desired arguments.
|
||||
:::
|
||||
|
||||
:::info
|
||||
|
||||
@@ -10,7 +10,7 @@ hide_title: false
|
||||
## Accelerators
|
||||
|
||||
Accelerators are strings that can be used to represent keyboard shortcuts throughout your Electron.
|
||||
These strings can contain multiple modifiers keys and a single key code joined by the `+` character.
|
||||
These strings can contain multiple modifier keys and a single key code joined by the `+` character.
|
||||
|
||||
> [!NOTE]
|
||||
> Accelerators are **case-insensitive**.
|
||||
|
||||
@@ -62,9 +62,9 @@ const createWindow = () => {
|
||||
}
|
||||
```
|
||||
|
||||
In this next step, we will create our `BrowserWindow` and tell our application how to handle an event in which an external protocol is clicked.
|
||||
In this next step, we will create our `BrowserWindow` and tell our application how to handle an event in which an external protocol is clicked.
|
||||
|
||||
This code will be different in Windows and Linux compared to MacOS. This is due to both platforms emitting the `second-instance` event rather than the `open-url` event and Windows requiring additional code in order to open the contents of the protocol link within the same Electron instance. Read more about this [here](../api/app.md#apprequestsingleinstancelockadditionaldata).
|
||||
This code will be different in Windows and Linux compared to macOS. This is due to both platforms emitting the `second-instance` event rather than the `open-url` event and Windows requiring additional code in order to open the contents of the protocol link within the same Electron instance. Read more about this [here](../api/app.md#apprequestsingleinstancelockadditionaldata).
|
||||
|
||||
#### Windows and Linux code:
|
||||
|
||||
@@ -91,7 +91,7 @@ if (!gotTheLock) {
|
||||
}
|
||||
```
|
||||
|
||||
#### MacOS code:
|
||||
#### macOS code:
|
||||
|
||||
```js @ts-type={createWindow:()=>void}
|
||||
// This method will be called when Electron has finished
|
||||
|
||||
@@ -65,7 +65,7 @@ The full list of certificate types can be found
|
||||
Apps signed with "Apple Development" and "Apple Distribution" certificates can
|
||||
only run under [App Sandbox][app-sandboxing], so they must use the MAS build of
|
||||
Electron. However, the "Developer ID Application" certificate does not have this
|
||||
restrictions, so apps signed with it can use either the normal build or the MAS
|
||||
restriction, so apps signed with it can use either the normal build or the MAS
|
||||
build of Electron.
|
||||
|
||||
#### Legacy certificate names
|
||||
@@ -208,7 +208,7 @@ signAsync({
|
||||
After signing the app with the "Apple Distribution" certificate, you can
|
||||
continue to submit it to Mac App Store.
|
||||
|
||||
However, this guide do not ensure your app will be approved by Apple; you
|
||||
However, this guide does not ensure your app will be approved by Apple; you
|
||||
still need to read Apple's [Submitting Your App][submitting-your-app] guide on
|
||||
how to meet the Mac App Store requirements.
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ Electron application, and this property only exists on macOS.
|
||||
One of the main uses for your app's Dock icon is to expose additional app menus. The Dock menu is
|
||||
triggered by right-clicking or <kbd>Ctrl</kbd>-clicking the app icon. By default, the app's Dock menu
|
||||
will come with system-provided window management utilities, including the ability to show all windows,
|
||||
hide the app, and switch betweeen different open windows.
|
||||
hide the app, and switch between different open windows.
|
||||
|
||||
To set an app-defined custom Dock menu, pass any [Menu](../api/menu.md) instance into the
|
||||
[`dock.setMenu`](../api/dock.md#docksetmenumenu-macos) API.
|
||||
|
||||
@@ -200,7 +200,7 @@ macOS has a number of platform-specific menu roles available. Many of these map
|
||||
|
||||
* `recentDocuments` - The submenu is an "Open Recent" menu.
|
||||
* `clearRecentDocuments` - Map to the [`clearRecentDocuments`](https://developer.apple.com/documentation/appkit/nsdocumentcontroller/clearrecentdocuments(_:)) action.
|
||||
* `shareMenu` - The submenu is [share menu][ShareMenu]. The `sharingItem` property must also be set to indicate the item to share.
|
||||
* `shareMenu` - The submenu is [share menu](../api/share-menu.md). The `sharingItem` property must also be set to indicate the item to share.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> When specifying a `role` on macOS, `label` and `accelerator` are the only
|
||||
|
||||
@@ -1339,7 +1339,7 @@ For developers wanting to learn more, you can refer to the [official N-API docum
|
||||
|
||||
### Putting `cpp_addon.cc` together
|
||||
|
||||
We've now finished the bridge part our addon - that is, the code that's most concerned with being the bridge between your JavaScript and C++ code (and by contrast, less so actually interacting with the operating system or GTK). After adding all the sections above, your `src/cpp_addon.cc` should look like this:
|
||||
We've now finished the bridge part of our addon - that is, the code that's most concerned with being the bridge between your JavaScript and C++ code (and by contrast, less so actually interacting with the operating system or GTK). After adding all the sections above, your `src/cpp_addon.cc` should look like this:
|
||||
|
||||
```cpp title='src/cpp_addon.cc'
|
||||
#include <napi.h>
|
||||
|
||||
@@ -4,13 +4,13 @@ This tutorial builds on the [general introduction to Native Code and Electron](.
|
||||
|
||||
Specifically, we'll be integrating with two commonly used native Windows libraries:
|
||||
|
||||
* `comctl32.lib`, which contains common controls and user interface components. It provides various UI elements like buttons, scrollbars, toolbars, status bars, progress bars, and tree views. As far as GUI development on Windows goes, this library is very low-level and basic - more modern frameworks like WinUI or WPF are advanced and alternatives but require a lot more C++ and Windows version considerations than are useful for this tutorial. This way, we can avoid the many perils of building native interfaces for multiple Windows versions!
|
||||
* `comctl32.lib`, which contains common controls and user interface components. It provides various UI elements like buttons, scrollbars, toolbars, status bars, progress bars, and tree views. As far as GUI development on Windows goes, this library is very low-level and basic - more modern frameworks like WinUI or WPF are more advanced alternatives but require a lot more C++ and Windows version considerations than are useful for this tutorial. This way, we can avoid the many perils of building native interfaces for multiple Windows versions!
|
||||
* `shcore.lib`, a library that provides high-DPI awareness functionality and other Shell-related features around managing displays and UI elements.
|
||||
|
||||
This tutorial will be most useful to those who already have some familiarity with native C++ GUI development on Windows. You should have experience with basic window classes and procedures, like `WNDCLASSEXW` and `WindowProc` functions. You should also be familiar with the Windows message loop, which is the heart of any native application - our code will be using `GetMessage`, `TranslateMessage`, and `DispatchMessage` to handle messages. Lastly, we'll be using (but not explaining) standard Win32 controls like `WC_EDITW` or `WC_BUTTONW`.
|
||||
|
||||
> [!NOTE]
|
||||
> If you're not familiar with C++ GUI development on Windows, we recommend Microsoft's excellent documentation and guides, particular for beginners. "[Get Started with Win32 and C++](https://learn.microsoft.com/en-us/windows/win32/learnwin32/learn-to-program-for-windows)" is a great introduction.
|
||||
> If you're not familiar with C++ GUI development on Windows, we recommend Microsoft's excellent documentation and guides, particularly for beginners. "[Get Started with Win32 and C++](https://learn.microsoft.com/en-us/windows/win32/learnwin32/learn-to-program-for-windows)" is a great introduction.
|
||||
|
||||
## Requirements
|
||||
|
||||
@@ -1333,7 +1333,7 @@ npm run build
|
||||
|
||||
## Conclusion
|
||||
|
||||
You've now built a complete native Node.js addon for Windows using C++ and the Win32 API. Some of things we've done here are:
|
||||
You've now built a complete native Node.js addon for Windows using C++ and the Win32 API. Some of the things we've done here are:
|
||||
|
||||
1. Creating a native Windows GUI from C++
|
||||
2. Implementing a Todo list application with Add, Edit, and Delete functionality
|
||||
|
||||
@@ -1167,7 +1167,7 @@ The approach demonstrated here allows you to:
|
||||
* Setting up bidirectional communication using callbacks and events
|
||||
* Configuring a custom build process to compile Swift code
|
||||
|
||||
For more information on developing with Swift and Swift, refer to Apple's developer documentation:
|
||||
For more information on developing with Swift and SwiftUI, refer to Apple's developer documentation:
|
||||
|
||||
* [Swift Programming Language](https://developer.apple.com/swift/)
|
||||
* [SwiftUI Framework](https://developer.apple.com/documentation/swiftui)
|
||||
|
||||
@@ -14,7 +14,7 @@ _Notes_:
|
||||
* There are two rendering modes that can be used (see the section below) and only
|
||||
the dirty area is passed to the `paint` event to be more efficient.
|
||||
* You can stop/continue the rendering as well as set the frame rate.
|
||||
* When `webPreferences.offscreen.useSharedTexture` is not `true`, the maximum frame rate is 240 because greater values bring only performance
|
||||
* When `webPreferences.offscreen.useSharedTexture` is `false`, the maximum frame rate is 240 because greater values bring only performance
|
||||
losses with no benefits.
|
||||
* When nothing is happening on a webpage, no frames are generated.
|
||||
* An offscreen window is always created as a
|
||||
@@ -36,8 +36,8 @@ setting.
|
||||
This is an advanced feature requiring a native node module to work with your own code.
|
||||
The frames are directly copied in GPU textures, thus this mode is very fast because
|
||||
there's no CPU-GPU memory copies overhead, and you can directly import the shared
|
||||
texture to your own rendering program. You can read more details at
|
||||
[here](https://github.com/electron/electron/blob/main/shell/browser/osr/README.md).
|
||||
texture to your own rendering program. You can read more details
|
||||
[here](../../shell/common/api/shared_texture/README.md).
|
||||
|
||||
2. Use CPU shared memory bitmap
|
||||
|
||||
|
||||
@@ -294,7 +294,7 @@ particularly useful if users complain about your app sometimes "stuttering".
|
||||
|
||||
Generally speaking, all advice for building performant web apps for modern
|
||||
browsers apply to Electron's renderers, too. The two primary tools at your
|
||||
disposal are currently `requestIdleCallback()` for small operations and
|
||||
disposal are currently `requestIdleCallback()` for small operations and
|
||||
`Web Workers` for long-running operations.
|
||||
|
||||
_`requestIdleCallback()`_ allows developers to queue up a function to be
|
||||
@@ -360,7 +360,7 @@ turning into a desktop application. As web developers, we are used to loading
|
||||
resources from a variety of content delivery networks. Now that you are
|
||||
shipping a proper desktop application, attempt to "cut the cord" where possible
|
||||
and avoid letting your users wait for resources that never change and could
|
||||
easily be included in your app.
|
||||
easily be included in your app.
|
||||
|
||||
A typical example is Google Fonts. Many developers make use of Google's
|
||||
impressive collection of free fonts, which comes with a content delivery
|
||||
|
||||
@@ -113,7 +113,7 @@ For a full list of Electron's main process modules, check out our API documentat
|
||||
|
||||
Each Electron app spawns a separate renderer process for each open `BrowserWindow`
|
||||
(and each web embed). As its name implies, a renderer is responsible for
|
||||
_rendering_ web content. For all intents and purposes, code ran in renderer processes
|
||||
_rendering_ web content. For all intents and purposes, code run in renderer processes
|
||||
should behave according to web standards (insofar as Chromium does, at least).
|
||||
|
||||
Therefore, all user interfaces and app functionality within a single browser
|
||||
|
||||
@@ -9,7 +9,7 @@ toc_max_heading_level: 3
|
||||
|
||||
:::info Reporting security issues
|
||||
For information on how to properly disclose an Electron vulnerability,
|
||||
see [SECURITY.md](https://github.com/electron/electron/blob/main/SECURITY.md).
|
||||
see [SECURITY.md](../../SECURITY.md).
|
||||
|
||||
For upstream Chromium vulnerabilities: Electron keeps up to date with alternating
|
||||
Chromium releases. For more information, see the
|
||||
@@ -771,7 +771,7 @@ ipcMain.handle('get-secrets', (e) => {
|
||||
})
|
||||
|
||||
function validateSender (frame) {
|
||||
// Value the host of the URL using an actual URL parser and an allowlist
|
||||
// Validate the host of the URL using an actual URL parser and an allowlist
|
||||
if ((new URL(frame.url)).host === 'electronjs.org') return true
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
* For information on supported releases, see the [Electron Releases](./electron-timelines.md) doc.
|
||||
* For community support on Electron, see the [Community page](https://www.electronjs.org/community).
|
||||
* For platform support info, see the [README](https://github.com/electron/electron/blob/main/README.md).
|
||||
* For platform support info, see the [README](../../README.md).
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
Being based on Chromium, Electron requires a display driver to function.
|
||||
If Chromium can't find a display driver, Electron will fail to launch -
|
||||
and therefore not executing any of your tests, regardless of how you are running
|
||||
them. Testing Electron-based apps on Travis, CircleCI, Jenkins or similar Systems
|
||||
and therefore not execute any of your tests, regardless of how you are running
|
||||
them. Testing Electron-based apps on Travis, CircleCI, Jenkins or similar systems
|
||||
requires therefore a little bit of configuration. In essence, we need to use
|
||||
a virtual display driver.
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ following JSON format:
|
||||
"updateTo": {
|
||||
"version": "1.2.1",
|
||||
"pub_date": "2023-09-18T12:29:53+01:00",
|
||||
"notes": "Theses are some release notes innit",
|
||||
"notes": "These are some release notes innit",
|
||||
"name": "1.2.1",
|
||||
"url": "https://mycompany.example.com/myapp/releases/myrelease"
|
||||
}
|
||||
@@ -54,7 +54,7 @@ following JSON format:
|
||||
"updateTo": {
|
||||
"version": "1.2.3",
|
||||
"pub_date": "2024-09-18T12:29:53+01:00",
|
||||
"notes": "Theses are some more release notes innit",
|
||||
"notes": "These are some more release notes innit",
|
||||
"name": "1.2.3",
|
||||
"url": "https://mycompany.example.com/myapp/releases/myrelease3"
|
||||
}
|
||||
@@ -307,7 +307,7 @@ app update. All other properties in the object are optional.
|
||||
{
|
||||
"url": "https://your-static.storage/your-app-1.2.3-darwin.zip",
|
||||
"name": "1.2.3",
|
||||
"notes": "Theses are some release notes innit",
|
||||
"notes": "These are some release notes innit",
|
||||
"pub_date": "2024-09-18T12:29:53+01:00"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -149,7 +149,7 @@ for an example delay-load hook if you're implementing your own.
|
||||
native Node modules with prebuilt binaries for multiple versions of Node
|
||||
and Electron.
|
||||
|
||||
If the `prebuild`-powered module provide binaries for the usage in Electron,
|
||||
If the `prebuild`-powered module provides binaries for the usage in Electron,
|
||||
make sure to omit `--build-from-source` and the `npm_config_build_from_source`
|
||||
environment variable in order to take full advantage of the prebuilt binaries.
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ To test your app, use a Windows on Arm device running Windows 10 (version 1903 o
|
||||
|
||||
### Node.js/node-gyp
|
||||
|
||||
[Node.js v12.9.0 or later is recommended.](https://nodejs.org/en/) If updating to a new version of Node is undesirable, you can instead [update npm's copy of node-gyp manually](https://github.com/nodejs/node-gyp/wiki/Updating-npm's-bundled-node-gyp) to version 5.0.2 or later, which contains the required changes to compile native modules for Arm.
|
||||
[Node.js v12.9.0 or later is recommended.](https://nodejs.org/en/) If updating to a new version of Node is undesirable, you can instead [update npm's copy of node-gyp manually](https://github.com/nodejs/node-gyp/wiki/Updating-npm's-bundled-node-gyp) to version 5.0.2 or later, which contains the required changes to compile native modules for Arm.
|
||||
|
||||
### Visual Studio 2017
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ system.
|
||||
|
||||
Before running the CLI for the first time, you will have to setup the "Windows Desktop App
|
||||
Converter". This will take a few minutes, but don't worry - you only have to do
|
||||
this once. Download and Desktop App Converter from [here][app-converter].
|
||||
this once. Download the Desktop App Converter from [here][app-converter].
|
||||
You will receive two files: `DesktopAppConverter.zip` and `BaseImage-14316.wim`.
|
||||
|
||||
1. Unzip `DesktopAppConverter.zip`. From an elevated PowerShell (opened with
|
||||
|
||||
@@ -30,7 +30,7 @@ If you want to focus on building a great product without debugging a weird quirk
|
||||
|
||||
Whatever provider or customer data you need to interact with, they will have probably thought of an integration path with the web. Depending on your technology choice, embedding a YouTube video either takes 30 seconds or requires you to hire a team devoted to streaming and hardware-accelerated video decoding. In the case of YouTube, using anything other than the provided players is actually against their terms and conditions, so you’ll likely embed a browser frame before you implement your own video streaming decoder.
|
||||
|
||||
There will be virtually no platform where your app cannot run if you build it with web technologies. Virtually all devices with a display—be that an ATM, a car infotainment system, a smart TV, a fridge, or a Nintendo Switch—come with means to display web technologies. The web is safe bet if you want to be cross-platform.
|
||||
There will be virtually no platform where your app cannot run if you build it with web technologies. Virtually all devices with a display—be that an ATM, a car infotainment system, a smart TV, a fridge, or a Nintendo Switch—come with means to display web technologies. The web is a safe bet if you want to be cross-platform.
|
||||
|
||||
### Ubiquity
|
||||
|
||||
@@ -59,7 +59,7 @@ What does all of that mean for you, a developer, in practice?
|
||||
|
||||
### Stability, security, performance
|
||||
|
||||
Electron delivers the best experience on all target platforms (macOS, Windows, Linux) by bundling the latest version of Chromium, V8, and Node.js directly with the application binary. When it comes to running and rendering web content with upmost stability, security, and performance, we currently believe that stack to be “best in class”.
|
||||
Electron delivers the best experience on all target platforms (macOS, Windows, Linux) by bundling the latest version of Chromium, V8, and Node.js directly with the application binary. When it comes to running and rendering web content with utmost stability, security, and performance, we currently believe that stack to be “best in class”.
|
||||
|
||||
#### Why bundle anything at all
|
||||
|
||||
|
||||
@@ -230,8 +230,10 @@ auto_filenames = {
|
||||
browser_bundle_deps = [
|
||||
"lib/browser/api/app.ts",
|
||||
"lib/browser/api/auto-updater.ts",
|
||||
"lib/browser/api/auto-updater/auto-updater-msix.ts",
|
||||
"lib/browser/api/auto-updater/auto-updater-native.ts",
|
||||
"lib/browser/api/auto-updater/auto-updater-win.ts",
|
||||
"lib/browser/api/auto-updater/msix-update-win.ts",
|
||||
"lib/browser/api/auto-updater/squirrel-update-win.ts",
|
||||
"lib/browser/api/base-window.ts",
|
||||
"lib/browser/api/browser-view.ts",
|
||||
|
||||
@@ -79,6 +79,8 @@ filenames = {
|
||||
"shell/browser/notifications/win/notification_presenter_win.h",
|
||||
"shell/browser/notifications/win/windows_toast_notification.cc",
|
||||
"shell/browser/notifications/win/windows_toast_notification.h",
|
||||
"shell/browser/notifications/win/windows_toast_activator.cc",
|
||||
"shell/browser/notifications/win/windows_toast_activator.h",
|
||||
"shell/browser/relauncher_win.cc",
|
||||
"shell/browser/ui/certificate_trust_win.cc",
|
||||
"shell/browser/ui/file_dialog_win.cc",
|
||||
@@ -277,6 +279,8 @@ filenames = {
|
||||
"shell/browser/api/electron_api_in_app_purchase.h",
|
||||
"shell/browser/api/electron_api_menu.cc",
|
||||
"shell/browser/api/electron_api_menu.h",
|
||||
"shell/browser/api/electron_api_msix_updater.cc",
|
||||
"shell/browser/api/electron_api_msix_updater.h",
|
||||
"shell/browser/api/electron_api_native_theme.cc",
|
||||
"shell/browser/api/electron_api_native_theme.h",
|
||||
"shell/browser/api/electron_api_net_log.cc",
|
||||
@@ -589,6 +593,7 @@ filenames = {
|
||||
"shell/common/electron_command_line.cc",
|
||||
"shell/common/electron_command_line.h",
|
||||
"shell/common/electron_constants.h",
|
||||
"shell/common/electron_paths.cc",
|
||||
"shell/common/electron_paths.h",
|
||||
"shell/common/gin_converters/accelerator_converter.cc",
|
||||
"shell/common/gin_converters/accelerator_converter.h",
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
if (process.platform === 'win32') {
|
||||
module.exports = require('./auto-updater/auto-updater-win');
|
||||
// windowsStore indicates whether the app is running as a packaged app (MSIX), even outside of the store
|
||||
if (process.windowsStore) {
|
||||
module.exports = require('./auto-updater/auto-updater-msix');
|
||||
} else {
|
||||
module.exports = require('./auto-updater/auto-updater-win');
|
||||
}
|
||||
} else {
|
||||
module.exports = require('./auto-updater/auto-updater-native');
|
||||
}
|
||||
|
||||
449
lib/browser/api/auto-updater/auto-updater-msix.ts
Normal file
449
lib/browser/api/auto-updater/auto-updater-msix.ts
Normal file
@@ -0,0 +1,449 @@
|
||||
import * as msixUpdate from '@electron/internal/browser/api/auto-updater/msix-update-win';
|
||||
|
||||
import { app, net } from 'electron/main';
|
||||
|
||||
import { EventEmitter } from 'events';
|
||||
|
||||
interface UpdateInfo {
|
||||
ok: boolean; // False if error encountered
|
||||
available?: boolean; // True if the update is available, false if not
|
||||
updateUrl?: string; // The URL of the update
|
||||
releaseNotes?: string; // The release notes of the update
|
||||
releaseName?: string; // The release name of the update
|
||||
releaseDate?: Date; // The release date of the update
|
||||
}
|
||||
|
||||
interface MSIXPackageInfo {
|
||||
id: string;
|
||||
familyName: string;
|
||||
developmentMode: boolean;
|
||||
version: string;
|
||||
signatureKind: 'developer' | 'enterprise' | 'none' | 'store' | 'system';
|
||||
appInstallerUri?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for updating an MSIX package.
|
||||
* Used with `updateMsix()` to control how the package update behaves.
|
||||
*
|
||||
* These options correspond to the Windows.Management.Deployment.AddPackageOptions class properties.
|
||||
*
|
||||
* @see https://learn.microsoft.com/en-us/uwp/api/windows.management.deployment.addpackageoptions?view=winrt-26100
|
||||
*/
|
||||
export interface UpdateMsixOptions {
|
||||
/**
|
||||
* Gets or sets a value that indicates whether to delay registration of the main package
|
||||
* or dependency packages if the packages are currently in use.
|
||||
*
|
||||
* Corresponds to `AddPackageOptions.DeferRegistrationWhenPackagesAreInUse`
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
deferRegistration?: boolean;
|
||||
|
||||
/**
|
||||
* Gets or sets a value that indicates whether the app is installed in developer mode.
|
||||
* When set, the app is installed in development mode which allows for a more rapid
|
||||
* development cycle. The BlockMap.xml, [Content_Types].xml, and digital signature
|
||||
* files are not required for app installation.
|
||||
*
|
||||
* Corresponds to `AddPackageOptions.DeveloperMode`
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
developerMode?: boolean;
|
||||
|
||||
/**
|
||||
* Gets or sets a value that indicates whether the processes associated with the package
|
||||
* will be shut down forcibly so that registration can continue if the package, or any
|
||||
* package that depends on the package, is currently in use.
|
||||
*
|
||||
* Corresponds to `AddPackageOptions.ForceAppShutdown`
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
forceShutdown?: boolean;
|
||||
|
||||
/**
|
||||
* Gets or sets a value that indicates whether the processes associated with the package
|
||||
* will be shut down forcibly so that registration can continue if the package is
|
||||
* currently in use.
|
||||
*
|
||||
* Corresponds to `AddPackageOptions.ForceTargetAppShutdown`
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
forceTargetShutdown?: boolean;
|
||||
|
||||
/**
|
||||
* Gets or sets a value that indicates whether to force a specific version of a package
|
||||
* to be added, regardless of if a higher version is already added.
|
||||
*
|
||||
* Corresponds to `AddPackageOptions.ForceUpdateFromAnyVersion`
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
forceUpdateFromAnyVersion?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for registering an MSIX package.
|
||||
* Used with `registerPackage()` to control how the package registration behaves.
|
||||
*
|
||||
* These options correspond to the Windows.Management.Deployment.DeploymentOptions enum.
|
||||
*
|
||||
* @see https://learn.microsoft.com/en-us/uwp/api/windows.management.deployment.deploymentoptions?view=winrt-26100
|
||||
*/
|
||||
interface RegisterPackageOptions {
|
||||
/**
|
||||
* Force shutdown of the application if it's currently running.
|
||||
* If this package, or any package that depends on this package, is currently in use,
|
||||
* the processes associated with the package are shut down forcibly so that registration can continue.
|
||||
*
|
||||
* Corresponds to `DeploymentOptions.ForceApplicationShutdown` (value: 1)
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
forceShutdown?: boolean;
|
||||
|
||||
/**
|
||||
* Force shutdown of the target application if it's currently running.
|
||||
* If this package is currently in use, the processes associated with the package
|
||||
* are shut down forcibly so that registration can continue.
|
||||
*
|
||||
* Corresponds to `DeploymentOptions.ForceTargetApplicationShutdown` (value: 64)
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
forceTargetShutdown?: boolean;
|
||||
|
||||
/**
|
||||
* Force a specific version of a package to be staged/registered, regardless of if
|
||||
* a higher version is already staged/registered.
|
||||
*
|
||||
* Corresponds to `DeploymentOptions.ForceUpdateFromAnyVersion` (value: 262144)
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
forceUpdateFromAnyVersion?: boolean;
|
||||
}
|
||||
|
||||
class AutoUpdater extends EventEmitter implements Electron.AutoUpdater {
|
||||
updateAvailable: boolean = false;
|
||||
updateURL: string | null = null;
|
||||
updateHeaders: Record<string, string> | null = null;
|
||||
allowAnyVersion: boolean = false;
|
||||
|
||||
// Private: Validate that the URL points to an MSIX file (following redirects)
|
||||
private async validateMsixUrl (url: string): Promise<void> {
|
||||
try {
|
||||
// Make a HEAD request to follow redirects and get the final URL
|
||||
const response = await net.fetch(url, {
|
||||
method: 'HEAD',
|
||||
headers: this.updateHeaders ? new Headers(this.updateHeaders) : undefined,
|
||||
redirect: 'follow' // Follow redirects to get the final URL
|
||||
});
|
||||
|
||||
// Get the final URL after redirects (response.url contains the final URL)
|
||||
const finalUrl = response.url || url;
|
||||
const urlObj = new URL(finalUrl);
|
||||
const pathname = urlObj.pathname.toLowerCase();
|
||||
|
||||
// Check if final URL ends with .msix or .msixbundle extension
|
||||
const hasMsixExtension = pathname.endsWith('.msix') || pathname.endsWith('.msixbundle');
|
||||
|
||||
if (!hasMsixExtension) {
|
||||
throw new Error(`Update URL does not point to an MSIX file. Expected .msix or .msixbundle extension, got final URL: ${finalUrl}`);
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof TypeError) {
|
||||
throw new Error(`Invalid MSIX URL: ${url}`);
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Private: Check if URL is a direct MSIX file (following redirects)
|
||||
private async isDirectMsixUrl (url: string, emitError: boolean = false): Promise<boolean> {
|
||||
try {
|
||||
await this.validateMsixUrl(url);
|
||||
return true;
|
||||
} catch (error) {
|
||||
if (emitError) {
|
||||
this.emitError(error as Error);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Supports both versioning (x.y.z) and Windows version format (x.y.z.a)
|
||||
// Returns: 1 if v1 > v2, -1 if v1 < v2, 0 if v1 === v2
|
||||
private compareVersions (v1: string, v2: string): number {
|
||||
const parts1 = v1.split('.').map(part => {
|
||||
const parsed = parseInt(part, 10);
|
||||
return isNaN(parsed) ? 0 : parsed;
|
||||
});
|
||||
const parts2 = v2.split('.').map(part => {
|
||||
const parsed = parseInt(part, 10);
|
||||
return isNaN(parsed) ? 0 : parsed;
|
||||
});
|
||||
|
||||
const maxLength = Math.max(parts1.length, parts2.length);
|
||||
|
||||
for (let i = 0; i < maxLength; i++) {
|
||||
const part1 = parts1[i] ?? 0;
|
||||
const part2 = parts2[i] ?? 0;
|
||||
|
||||
if (part1 > part2) return 1;
|
||||
if (part1 < part2) return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Private: Parse the static releases array format
|
||||
// This is a static JSON file containing all releases
|
||||
private parseStaticReleasFile (json: any, currentVersion: string): { ok: boolean; available: boolean; url?: string; name?: string; notes?: string; pub_date?: string } {
|
||||
if (!Array.isArray(json.releases) || !json.currentRelease || typeof json.currentRelease !== 'string') {
|
||||
this.emitError(new Error('Invalid releases format. Expected \'releases\' array and \'currentRelease\' string.'));
|
||||
return { ok: false, available: false };
|
||||
}
|
||||
|
||||
// Use currentRelease property to determine if update is available
|
||||
const currentReleaseVersion = json.currentRelease;
|
||||
|
||||
// Compare current version with currentRelease
|
||||
const versionComparison = this.compareVersions(currentReleaseVersion, currentVersion);
|
||||
|
||||
// If versions match, we're up to date
|
||||
if (versionComparison === 0) {
|
||||
return { ok: true, available: false };
|
||||
}
|
||||
|
||||
// If currentRelease is older than current version, check allowAnyVersion
|
||||
if (versionComparison < 0) {
|
||||
// If allowAnyVersion is true, allow downgrades
|
||||
if (this.allowAnyVersion) {
|
||||
// Continue to find the release entry for downgrade
|
||||
} else {
|
||||
return { ok: true, available: false };
|
||||
}
|
||||
}
|
||||
|
||||
// currentRelease is newer, find the release entry
|
||||
const releaseEntry = json.releases.find((r: any) => r.version === currentReleaseVersion);
|
||||
|
||||
if (!releaseEntry || !releaseEntry.updateTo) {
|
||||
this.emitError(new Error(`Release entry for version '${currentReleaseVersion}' not found or missing 'updateTo' property.`));
|
||||
return { ok: false, available: false };
|
||||
}
|
||||
|
||||
const updateTo = releaseEntry.updateTo;
|
||||
|
||||
if (!updateTo.url) {
|
||||
this.emitError(new Error(`Invalid release entry. 'updateTo.url' is missing for version ${currentReleaseVersion}.`));
|
||||
return { ok: false, available: false };
|
||||
}
|
||||
|
||||
return {
|
||||
ok: true,
|
||||
available: true,
|
||||
url: updateTo.url,
|
||||
name: updateTo.name,
|
||||
notes: updateTo.notes,
|
||||
pub_date: updateTo.pub_date
|
||||
};
|
||||
}
|
||||
|
||||
private parseDynamicReleasFile (json: any): { ok: boolean; available: boolean; url?: string; name?: string; notes?: string; pub_date?: string } {
|
||||
if (!json.url) {
|
||||
this.emitError(new Error('Invalid releases format. Expected \'url\' string property.'));
|
||||
return { ok: false, available: false };
|
||||
}
|
||||
return { ok: true, available: true, url: json.url, name: json.name, notes: json.notes, pub_date: json.pub_date };
|
||||
}
|
||||
|
||||
private async fetchSquirrelJson (url: string) {
|
||||
const headers: Record<string, string> = {
|
||||
...this.updateHeaders,
|
||||
Accept: 'application/json' // Always set Accept header, overriding any user-provided Accept
|
||||
};
|
||||
const response = await net.fetch(url, {
|
||||
headers
|
||||
});
|
||||
|
||||
if (response.status === 204) {
|
||||
return { ok: true, available: false };
|
||||
} else if (response.status === 200) {
|
||||
const updateJson = await response.json();
|
||||
|
||||
// Check if this is the static releases array format
|
||||
if (Array.isArray(updateJson.releases)) {
|
||||
// Get current package version
|
||||
const packageInfo = msixUpdate.getPackageInfo();
|
||||
const currentVersion = packageInfo.version;
|
||||
|
||||
if (!currentVersion) {
|
||||
this.emitError(new Error('Cannot determine current package version.'));
|
||||
return { ok: false, available: false };
|
||||
}
|
||||
|
||||
return this.parseStaticReleasFile(updateJson, currentVersion);
|
||||
} else {
|
||||
// Dynamic format: server returns JSON with update info for current version
|
||||
return this.parseDynamicReleasFile(updateJson);
|
||||
}
|
||||
} else {
|
||||
this.emitError(new Error(`Unexpected response status: ${response.status}`));
|
||||
return { ok: false, available: false };
|
||||
}
|
||||
}
|
||||
|
||||
private async getUpdateInfo (url: string): Promise<UpdateInfo> {
|
||||
if (url && await this.isDirectMsixUrl(url)) {
|
||||
return { ok: true, available: true, updateUrl: url, releaseDate: new Date() };
|
||||
} else {
|
||||
const updateJson = await this.fetchSquirrelJson(url);
|
||||
if (!updateJson.ok) {
|
||||
return { ok: false };
|
||||
} else if (updateJson.ok && !updateJson.available) {
|
||||
return { ok: true, available: false };
|
||||
} else {
|
||||
// updateJson.ok && updateJson.available must be true here
|
||||
// Parse the publication date if present (ISO 8601 format)
|
||||
let releaseDate: Date | null = null;
|
||||
if (updateJson.pub_date) {
|
||||
releaseDate = new Date(updateJson.pub_date);
|
||||
}
|
||||
|
||||
const updateUrl = updateJson.url ?? '';
|
||||
const releaseNotes = updateJson.notes ?? '';
|
||||
const releaseName = updateJson.name ?? '';
|
||||
releaseDate = releaseDate ?? new Date();
|
||||
|
||||
if (!await this.isDirectMsixUrl(updateUrl, true)) {
|
||||
return { ok: false };
|
||||
} else {
|
||||
return {
|
||||
ok: true,
|
||||
available: true,
|
||||
updateUrl,
|
||||
releaseNotes,
|
||||
releaseName,
|
||||
releaseDate
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getFeedURL () {
|
||||
return this.updateURL ?? '';
|
||||
}
|
||||
|
||||
setFeedURL (options: { url: string; headers?: Record<string, string>; allowAnyVersion?: boolean } | string) {
|
||||
let updateURL: string;
|
||||
let headers: Record<string, string> | undefined;
|
||||
let allowAnyVersion: boolean | undefined;
|
||||
if (typeof options === 'object') {
|
||||
if (typeof options.url === 'string') {
|
||||
updateURL = options.url;
|
||||
headers = options.headers;
|
||||
allowAnyVersion = options.allowAnyVersion;
|
||||
} else {
|
||||
throw new TypeError('Expected options object to contain a \'url\' string property in setFeedUrl call');
|
||||
}
|
||||
} else if (typeof options === 'string') {
|
||||
updateURL = options;
|
||||
} else {
|
||||
throw new TypeError('Expected an options object with a \'url\' property to be provided');
|
||||
}
|
||||
this.updateURL = updateURL;
|
||||
this.updateHeaders = headers ?? null;
|
||||
this.allowAnyVersion = allowAnyVersion ?? false;
|
||||
}
|
||||
|
||||
getPackageInfo (): MSIXPackageInfo {
|
||||
return msixUpdate.getPackageInfo() as MSIXPackageInfo;
|
||||
}
|
||||
|
||||
async checkForUpdates () {
|
||||
const url = this.updateURL;
|
||||
if (!url) {
|
||||
return this.emitError(new Error('Update URL is not set'));
|
||||
}
|
||||
|
||||
// Check if running in MSIX package
|
||||
const packageInfo = msixUpdate.getPackageInfo();
|
||||
if (!packageInfo.familyName) {
|
||||
return this.emitError(new Error('MSIX updates are not supported'));
|
||||
}
|
||||
|
||||
// If appInstallerUri is set, Windows App Installer manages updates automatically
|
||||
// Prevent updates here to avoid conflicts
|
||||
if (packageInfo.appInstallerUri) {
|
||||
return this.emitError(new Error('Auto-updates are managed by Windows App Installer. Updates are not allowed when installed via Application Manifest.'));
|
||||
}
|
||||
|
||||
this.emit('checking-for-update');
|
||||
try {
|
||||
const msixUrlInfo = await this.getUpdateInfo(url);
|
||||
if (!msixUrlInfo.ok) {
|
||||
return this.emitError(new Error('Invalid update or MSIX URL. See previous errors.'));
|
||||
}
|
||||
|
||||
if (!msixUrlInfo.available) {
|
||||
this.emit('update-not-available');
|
||||
} else {
|
||||
this.updateAvailable = true;
|
||||
this.emit('update-available');
|
||||
await msixUpdate.updateMsix(msixUrlInfo.updateUrl, {
|
||||
deferRegistration: true,
|
||||
developerMode: false,
|
||||
forceShutdown: false,
|
||||
forceTargetShutdown: false,
|
||||
forceUpdateFromAnyVersion: this.allowAnyVersion
|
||||
} as UpdateMsixOptions);
|
||||
|
||||
this.emit('update-downloaded', {}, msixUrlInfo.releaseNotes, msixUrlInfo.releaseName, msixUrlInfo.releaseDate, msixUrlInfo.updateUrl, () => {
|
||||
this.quitAndInstall();
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
this.emitError(error as Error);
|
||||
}
|
||||
}
|
||||
|
||||
async quitAndInstall () {
|
||||
if (!this.updateAvailable) {
|
||||
this.emitError(new Error('No update available, can\'t quit and install'));
|
||||
app.quit();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Get package info to get family name
|
||||
const packageInfo = msixUpdate.getPackageInfo();
|
||||
if (!packageInfo.familyName) {
|
||||
return this.emitError(new Error('MSIX updates are not supported'));
|
||||
}
|
||||
|
||||
msixUpdate.registerRestartOnUpdate('');
|
||||
this.emit('before-quit-for-update');
|
||||
// force shutdown of the application and register the package to be installed on restart
|
||||
await msixUpdate.registerPackage(packageInfo.familyName, {
|
||||
forceShutdown: true
|
||||
} as RegisterPackageOptions);
|
||||
} catch (error) {
|
||||
this.emitError(error as Error);
|
||||
}
|
||||
}
|
||||
|
||||
// Private: Emit both error object and message, this is to keep compatibility
|
||||
// with Old APIs.
|
||||
emitError (error: Error) {
|
||||
this.emit('error', error, error.message);
|
||||
}
|
||||
}
|
||||
|
||||
export default new AutoUpdater();
|
||||
@@ -20,6 +20,11 @@ class AutoUpdater extends EventEmitter implements Electron.AutoUpdater {
|
||||
return this.updateURL ?? '';
|
||||
}
|
||||
|
||||
getPackageInfo () {
|
||||
// Squirrel-based Windows apps don't have MSIX package information
|
||||
return undefined;
|
||||
}
|
||||
|
||||
setFeedURL (options: { url: string } | string) {
|
||||
let updateURL: string;
|
||||
if (typeof options === 'object') {
|
||||
|
||||
4
lib/browser/api/auto-updater/msix-update-win.ts
Normal file
4
lib/browser/api/auto-updater/msix-update-win.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
const { updateMsix, registerPackage, registerRestartOnUpdate, getPackageInfo } =
|
||||
process._linkedBinding('electron_browser_msix_updater');
|
||||
|
||||
export { updateMsix, registerPackage, registerRestartOnUpdate, getPackageInfo };
|
||||
@@ -353,6 +353,7 @@ export function shouldOverrideCheckStatus (role: RoleId) {
|
||||
|
||||
export function getDefaultAccelerator (role: RoleId) {
|
||||
if (hasRole(role)) return roleList[role].accelerator;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function shouldRegisterAccelerator (role: RoleId) {
|
||||
|
||||
@@ -25,7 +25,7 @@ const MenuItem = function (this: any, options: any) {
|
||||
|
||||
this.overrideReadOnlyProperty('type', roles.getDefaultType(this.role));
|
||||
this.overrideReadOnlyProperty('role');
|
||||
this.overrideReadOnlyProperty('accelerator');
|
||||
this.overrideReadOnlyProperty('accelerator', roles.getDefaultAccelerator(this.role));
|
||||
this.overrideReadOnlyProperty('icon');
|
||||
this.overrideReadOnlyProperty('submenu');
|
||||
|
||||
|
||||
11
package.json
11
package.json
@@ -10,7 +10,7 @@
|
||||
"@electron/docs-parser": "^2.0.0",
|
||||
"@electron/fiddle-core": "^1.3.4",
|
||||
"@electron/github-app-auth": "^3.2.0",
|
||||
"@electron/lint-roller": "^3.1.2",
|
||||
"@electron/lint-roller": "^3.2.0",
|
||||
"@electron/typescript-definitions": "^9.1.5",
|
||||
"@octokit/rest": "^20.1.2",
|
||||
"@primer/octicons": "^10.0.0",
|
||||
@@ -57,7 +57,8 @@
|
||||
"url": "^0.11.4",
|
||||
"webpack": "^5.95.0",
|
||||
"webpack-cli": "^6.0.1",
|
||||
"wrapper-webpack-plugin": "^2.2.0"
|
||||
"wrapper-webpack-plugin": "^2.2.0",
|
||||
"yaml": "^2.8.1"
|
||||
},
|
||||
"private": true,
|
||||
"scripts": {
|
||||
@@ -73,7 +74,7 @@
|
||||
"lint:gn": "node ./script/lint.js --gn",
|
||||
"lint:docs": "remark docs -qf && npm run lint:js-in-markdown && npm run create-typescript-definitions && npm run lint:ts-check-js-in-markdown && npm run lint:docs-fiddles && npm run lint:docs-relative-links && npm run lint:markdown && npm run lint:api-history",
|
||||
"lint:docs-fiddles": "standard \"docs/fiddles/**/*.js\"",
|
||||
"lint:docs-relative-links": "lint-roller-markdown-links --root docs \"**/*.md\"",
|
||||
"lint:docs-relative-links": "lint-roller-markdown-links --resource-root . --root docs \"**/*.md\"",
|
||||
"lint:markdown": "node ./script/lint.js --md",
|
||||
"lint:ts-check-js-in-markdown": "lint-roller-markdown-ts-check --root docs \"**/*.md\" --ignore \"breaking-changes.md\"",
|
||||
"lint:js-in-markdown": "lint-roller-markdown-standard --root docs \"**/*.md\"",
|
||||
@@ -132,6 +133,10 @@
|
||||
"DEPS": [
|
||||
"node script/gen-hunspell-filenames.js",
|
||||
"node script/gen-libc++-filenames.js"
|
||||
],
|
||||
".github/workflows/pipeline-segment-electron-build.yml": [
|
||||
"node script/copy-pipeline-segment-publish.js",
|
||||
"git add .github/workflows/pipeline-segment-electron-publish.yml"
|
||||
]
|
||||
},
|
||||
"resolutions": {
|
||||
|
||||
@@ -144,3 +144,7 @@ fix_check_for_file_existence_before_setting_mtime.patch
|
||||
viz_create_isbufferqueuesupportedandenabled.patch
|
||||
viz_fix_visual_artifacts_while_resizing_window_with_dcomp.patch
|
||||
fix_os_crypt_async_cookie_encryption.patch
|
||||
graphite_handle_out_of_order_recording_errors.patch
|
||||
move_wayland_pointer_lock_overrides_to_common_code.patch
|
||||
loaf_add_feature_to_enable_sourceurl_for_all_protocols.patch
|
||||
fix_update_dbus_signal_signature_for_xdg_globalshortcuts_portal.patch
|
||||
|
||||
@@ -9,6 +9,8 @@ Subject: feat: configure launch options for service process
|
||||
Allows configuring base::LaunchOptions::handles_to_inherit, base::LaunchOptions::stdout_handle,
|
||||
base::LaunchOptions::stderr_handle and base::LaunchOptions::feedback_cursor_off when launching
|
||||
the child process.
|
||||
- Mac:
|
||||
Allows configuring base::LaunchOptions::disclaim_responsibility when launching the child process.
|
||||
- All:
|
||||
Allows configuring base::LauncOptions::current_directory, base::LaunchOptions::enviroment
|
||||
and base::LaunchOptions::clear_environment.
|
||||
@@ -165,10 +167,10 @@ index 0791b5317fc6846389f65f93734ae5e816d04623..71df2459fd759a75be573449accd3a4d
|
||||
FinishStartSandboxedProcessOnLauncherThread,
|
||||
this));
|
||||
diff --git a/content/browser/service_host/service_process_host_impl.cc b/content/browser/service_host/service_process_host_impl.cc
|
||||
index d9c14f91747bde0e76056d7f2f2ada166e67f994..53be16879777a3b9bef58ead5f7e420c1bf6acbe 100644
|
||||
index d9c14f91747bde0e76056d7f2f2ada166e67f994..09335acac17f526fb8d8e42e4b2d993b11045786 100644
|
||||
--- a/content/browser/service_host/service_process_host_impl.cc
|
||||
+++ b/content/browser/service_host/service_process_host_impl.cc
|
||||
@@ -69,6 +69,17 @@ void LaunchServiceProcess(mojo::GenericPendingReceiver receiver,
|
||||
@@ -69,6 +69,21 @@ void LaunchServiceProcess(mojo::GenericPendingReceiver receiver,
|
||||
utility_options.WithGpuClientAllowed();
|
||||
}
|
||||
|
||||
@@ -179,6 +181,10 @@ index d9c14f91747bde0e76056d7f2f2ada166e67f994..53be16879777a3b9bef58ead5f7e420c
|
||||
+#elif BUILDFLAG(IS_POSIX)
|
||||
+ utility_options.WithAdditionalFds(std::move(service_options.fds_to_remap));
|
||||
+#endif
|
||||
+#if BUILDFLAG(IS_MAC)
|
||||
+ utility_options.WithDisclaimResponsibility(
|
||||
+ service_options.disclaim_responsibility);
|
||||
+#endif
|
||||
+ utility_options.WithCurrentDirectory(service_options.current_directory);
|
||||
+ utility_options.WithEnvironment(service_options.environment,
|
||||
+ service_options.clear_environment);
|
||||
@@ -187,7 +193,7 @@ index d9c14f91747bde0e76056d7f2f2ada166e67f994..53be16879777a3b9bef58ead5f7e420c
|
||||
|
||||
UtilityProcessHost::Start(std::move(utility_options),
|
||||
diff --git a/content/browser/service_host/utility_process_host.cc b/content/browser/service_host/utility_process_host.cc
|
||||
index c798b3394db7638e38613a016c2dbb0bfcf54d03..1298ea85a176db2150a4101afc205745f32eb8f5 100644
|
||||
index c798b3394db7638e38613a016c2dbb0bfcf54d03..e90c8a9b2ac7d17fe7e5e814fd6eb3333f440bbe 100644
|
||||
--- a/content/browser/service_host/utility_process_host.cc
|
||||
+++ b/content/browser/service_host/utility_process_host.cc
|
||||
@@ -241,13 +241,13 @@ UtilityProcessHost::Options& UtilityProcessHost::Options::WithFileToPreload(
|
||||
@@ -207,7 +213,7 @@ index c798b3394db7638e38613a016c2dbb0bfcf54d03..1298ea85a176db2150a4101afc205745
|
||||
|
||||
#if BUILDFLAG(USE_ZYGOTE)
|
||||
UtilityProcessHost::Options& UtilityProcessHost::Options::WithZygoteForTesting(
|
||||
@@ -257,6 +257,36 @@ UtilityProcessHost::Options& UtilityProcessHost::Options::WithZygoteForTesting(
|
||||
@@ -257,6 +257,45 @@ UtilityProcessHost::Options& UtilityProcessHost::Options::WithZygoteForTesting(
|
||||
}
|
||||
#endif // BUILDFLAG(USE_ZYGOTE)
|
||||
|
||||
@@ -240,11 +246,20 @@ index c798b3394db7638e38613a016c2dbb0bfcf54d03..1298ea85a176db2150a4101afc205745
|
||||
+ return *this;
|
||||
+}
|
||||
+#endif // BUILDFLAG(IS_WIN)
|
||||
+
|
||||
+#if BUILDFLAG(IS_MAC)
|
||||
+UtilityProcessHost::Options&
|
||||
+UtilityProcessHost::Options::WithDisclaimResponsibility(
|
||||
+ bool disclaim_responsibility) {
|
||||
+ disclaim_responsibility_ = disclaim_responsibility;
|
||||
+ return *this;
|
||||
+}
|
||||
+#endif // BUILDFLAG(IS_MAC)
|
||||
+
|
||||
UtilityProcessHost::Options&
|
||||
UtilityProcessHost::Options::WithBoundReceiverOnChildProcessForTesting(
|
||||
mojo::GenericPendingReceiver receiver) {
|
||||
@@ -520,9 +550,26 @@ bool UtilityProcessHost::StartProcess() {
|
||||
@@ -520,9 +559,30 @@ bool UtilityProcessHost::StartProcess() {
|
||||
}
|
||||
#endif // BUILDFLAG(ENABLE_GPU_CHANNEL_MEDIA_CAPTURE) && !BUILDFLAG(IS_WIN)
|
||||
|
||||
@@ -269,11 +284,15 @@ index c798b3394db7638e38613a016c2dbb0bfcf54d03..1298ea85a176db2150a4101afc205745
|
||||
+#if BUILDFLAG(IS_WIN)
|
||||
+ delegate->SetFeedbackCursorOff(options_.feedback_cursor_off_);
|
||||
+#endif // BUILDFLAG(IS_WIN)
|
||||
+
|
||||
+#if BUILDFLAG(IS_MAC)
|
||||
+ delegate->SetDisclaimResponsibility(options_.disclaim_responsibility_);
|
||||
+#endif // BUILDFLAG(IS_MAC)
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
if (!options_.preload_libraries_.empty()) {
|
||||
diff --git a/content/browser/service_host/utility_process_host.h b/content/browser/service_host/utility_process_host.h
|
||||
index dfdcb66d65f07f4543703396eb529a6ec02b3f4a..d731211d727f6e96533a058106c13f339263712d 100644
|
||||
index dfdcb66d65f07f4543703396eb529a6ec02b3f4a..96c0cadf5caf5bf27f2a767c43f0f1da04298800 100644
|
||||
--- a/content/browser/service_host/utility_process_host.h
|
||||
+++ b/content/browser/service_host/utility_process_host.h
|
||||
@@ -30,6 +30,7 @@
|
||||
@@ -284,7 +303,7 @@ index dfdcb66d65f07f4543703396eb529a6ec02b3f4a..d731211d727f6e96533a058106c13f33
|
||||
#endif // BUILDFLAG(IS_WIN)
|
||||
|
||||
namespace base {
|
||||
@@ -133,14 +134,31 @@ class CONTENT_EXPORT UtilityProcessHost final
|
||||
@@ -133,14 +134,36 @@ class CONTENT_EXPORT UtilityProcessHost final
|
||||
std::variant<base::FilePath, base::ScopedFD> file);
|
||||
#endif
|
||||
|
||||
@@ -315,11 +334,16 @@ index dfdcb66d65f07f4543703396eb529a6ec02b3f4a..d731211d727f6e96533a058106c13f33
|
||||
+ // Specifies if the process should trigger mouse cursor feedback.
|
||||
+ Options& WithFeedbackCursorOff(bool feedback_cursor_off);
|
||||
+#endif // BUILDFLAG(IS_WIN)
|
||||
+
|
||||
+#if BUILDFLAG(IS_MAC)
|
||||
+ // Specifies if the process should disclaim TCC responsibility.
|
||||
+ Options& WithDisclaimResponsibility(bool disclaim_responsibility);
|
||||
+#endif // BUILDFLAG(IS_MAC)
|
||||
+
|
||||
// Requests that the process bind a receiving pipe targeting the interface
|
||||
// named by `receiver`. Calls to this method generally end up in
|
||||
// `ChildThreadImpl::OnBindReceiver()` and the option is used for testing
|
||||
@@ -184,6 +202,27 @@ class CONTENT_EXPORT UtilityProcessHost final
|
||||
@@ -184,6 +207,32 @@ class CONTENT_EXPORT UtilityProcessHost final
|
||||
std::optional<raw_ptr<ZygoteCommunication>> zygote_for_testing_;
|
||||
#endif // BUILDFLAG(USE_ZYGOTE)
|
||||
|
||||
@@ -343,12 +367,17 @@ index dfdcb66d65f07f4543703396eb529a6ec02b3f4a..d731211d727f6e96533a058106c13f33
|
||||
+ // Specifies if the process should trigger mouse cursor feedback.
|
||||
+ bool feedback_cursor_off_ = false;
|
||||
+#endif // BUILDFLAG(IS_WIN)
|
||||
+
|
||||
+#if BUILDFLAG(IS_MAC)
|
||||
+ // Specifies if the process should disclaim TCC responsibility.
|
||||
+ bool disclaim_responsibility_ = false;
|
||||
+#endif // BUILDFLAG(IS_MAC)
|
||||
+
|
||||
#if BUILDFLAG(ENABLE_GPU_CHANNEL_MEDIA_CAPTURE)
|
||||
// Whether or not to bind viz::mojom::Gpu to the utility process.
|
||||
bool allowed_gpu_;
|
||||
diff --git a/content/browser/service_host/utility_sandbox_delegate.cc b/content/browser/service_host/utility_sandbox_delegate.cc
|
||||
index ada7034c8926c276ea1c7ebf8242c61b0a993c39..b852d40936f1e876681a00f2eb57c9077a086a1d 100644
|
||||
index ada7034c8926c276ea1c7ebf8242c61b0a993c39..aec3de8bd0c18666b33147779cad68c6b41fe1fe 100644
|
||||
--- a/content/browser/service_host/utility_sandbox_delegate.cc
|
||||
+++ b/content/browser/service_host/utility_sandbox_delegate.cc
|
||||
@@ -39,17 +39,19 @@ UtilitySandboxedProcessLauncherDelegate::
|
||||
@@ -406,8 +435,24 @@ index ada7034c8926c276ea1c7ebf8242c61b0a993c39..b852d40936f1e876681a00f2eb57c907
|
||||
|
||||
#if BUILDFLAG(USE_ZYGOTE)
|
||||
ZygoteCommunication* UtilitySandboxedProcessLauncherDelegate::GetZygote() {
|
||||
@@ -189,6 +208,15 @@ UtilitySandboxedProcessLauncherDelegate::GetProcessRequirement() {
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
+
|
||||
+void UtilitySandboxedProcessLauncherDelegate::SetDisclaimResponsibility(
|
||||
+ bool disclaim_responsibility) {
|
||||
+ disclaim_responsibility_ = disclaim_responsibility;
|
||||
+}
|
||||
+
|
||||
+bool UtilitySandboxedProcessLauncherDelegate::DisclaimResponsibility() {
|
||||
+ return disclaim_responsibility_;
|
||||
+}
|
||||
#endif // BUILDFLAG(IS_MAC)
|
||||
|
||||
} // namespace content
|
||||
diff --git a/content/browser/service_host/utility_sandbox_delegate.h b/content/browser/service_host/utility_sandbox_delegate.h
|
||||
index f2e8c1d62c1cb1677f618b584ed401685b03034b..7c47ec471e4676365cf3e023808983cb3e7a18d0 100644
|
||||
index f2e8c1d62c1cb1677f618b584ed401685b03034b..00a20885092bd299e817685dd18c3971b25f721b 100644
|
||||
--- a/content/browser/service_host/utility_sandbox_delegate.h
|
||||
+++ b/content/browser/service_host/utility_sandbox_delegate.h
|
||||
@@ -36,7 +36,9 @@ class CONTENT_EXPORT UtilitySandboxedProcessLauncherDelegate
|
||||
@@ -438,7 +483,12 @@ index f2e8c1d62c1cb1677f618b584ed401685b03034b..7c47ec471e4676365cf3e023808983cb
|
||||
|
||||
#if BUILDFLAG(USE_ZYGOTE)
|
||||
void SetZygote(ZygoteCommunication* handle);
|
||||
@@ -77,9 +84,7 @@ class CONTENT_EXPORT UtilitySandboxedProcessLauncherDelegate
|
||||
@@ -74,12 +81,12 @@ class CONTENT_EXPORT UtilitySandboxedProcessLauncherDelegate
|
||||
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
std::optional<base::mac::ProcessRequirement> GetProcessRequirement() override;
|
||||
+ void SetDisclaimResponsibility(bool disclaim_responsibility);
|
||||
+ bool DisclaimResponsibility() override;
|
||||
#endif // BUILDFLAG(IS_MAC)
|
||||
|
||||
private:
|
||||
@@ -448,7 +498,7 @@ index f2e8c1d62c1cb1677f618b584ed401685b03034b..7c47ec471e4676365cf3e023808983cb
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
// Adds preload-libraries to the delegate blob for utility_main() to access
|
||||
@@ -95,12 +100,17 @@ class CONTENT_EXPORT UtilitySandboxedProcessLauncherDelegate
|
||||
@@ -95,12 +102,20 @@ class CONTENT_EXPORT UtilitySandboxedProcessLauncherDelegate
|
||||
std::optional<raw_ptr<ZygoteCommunication>> zygote_;
|
||||
#endif // BUILDFLAG(USE_ZYGOTE)
|
||||
|
||||
@@ -463,6 +513,9 @@ index f2e8c1d62c1cb1677f618b584ed401685b03034b..7c47ec471e4676365cf3e023808983cb
|
||||
+#if BUILDFLAG(IS_WIN)
|
||||
+ bool feedback_cursor_off_ = false;
|
||||
+#endif // BUILDFLAG(IS_WIN)
|
||||
+#if BUILDFLAG(IS_MAC)
|
||||
+ bool disclaim_responsibility_ = false;
|
||||
+#endif // BUILDFLAG(IS_MAC)
|
||||
};
|
||||
} // namespace content
|
||||
|
||||
@@ -489,10 +542,10 @@ index 39c96d4423b24695eee86353057cfeed19318b57..31b343d97b7672294644041c9bb1a4cd
|
||||
}
|
||||
|
||||
diff --git a/content/public/browser/service_process_host.cc b/content/public/browser/service_process_host.cc
|
||||
index d1bc550a891979e2d41d8d5b18a2f9287468e460..5fcac7a8493e5065f80303067a04f59e7c4509ef 100644
|
||||
index d1bc550a891979e2d41d8d5b18a2f9287468e460..5d255f628788bc8b40d8df0039b08c06ffec8730 100644
|
||||
--- a/content/public/browser/service_process_host.cc
|
||||
+++ b/content/public/browser/service_process_host.cc
|
||||
@@ -53,12 +53,53 @@ ServiceProcessHost::Options::WithExtraCommandLineSwitches(
|
||||
@@ -53,12 +53,62 @@ ServiceProcessHost::Options::WithExtraCommandLineSwitches(
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -542,12 +595,21 @@ index d1bc550a891979e2d41d8d5b18a2f9287468e460..5fcac7a8493e5065f80303067a04f59e
|
||||
+ return *this;
|
||||
+}
|
||||
+#endif // #if BUILDFLAG(IS_WIN)
|
||||
+
|
||||
+#if BUILDFLAG(IS_MAC)
|
||||
+ServiceProcessHost::Options&
|
||||
+ServiceProcessHost::Options::WithDisclaimResponsibility(
|
||||
+ bool should_disclaim_responsibility) {
|
||||
+ disclaim_responsibility = should_disclaim_responsibility;
|
||||
+ return *this;
|
||||
+}
|
||||
+#endif // BUILDFLAG(IS_MAC)
|
||||
+
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
ServiceProcessHost::Options&
|
||||
ServiceProcessHost::Options::WithPreloadedLibraries(
|
||||
diff --git a/content/public/browser/service_process_host.h b/content/public/browser/service_process_host.h
|
||||
index 0062d2cb6634b8b29977a0312516b1b13936b40a..611a52e908f4cb70fbe5628e220a082e45320b70 100644
|
||||
index 0062d2cb6634b8b29977a0312516b1b13936b40a..888ff36d70c83010f1f45e9eeb2dd6b573158db5 100644
|
||||
--- a/content/public/browser/service_process_host.h
|
||||
+++ b/content/public/browser/service_process_host.h
|
||||
@@ -14,6 +14,7 @@
|
||||
@@ -569,7 +631,7 @@ index 0062d2cb6634b8b29977a0312516b1b13936b40a..611a52e908f4cb70fbe5628e220a082e
|
||||
namespace base {
|
||||
class Process;
|
||||
} // namespace base
|
||||
@@ -94,11 +99,35 @@ class CONTENT_EXPORT ServiceProcessHost {
|
||||
@@ -94,11 +99,40 @@ class CONTENT_EXPORT ServiceProcessHost {
|
||||
// Specifies extra command line switches to append before launch.
|
||||
Options& WithExtraCommandLineSwitches(std::vector<std::string> switches);
|
||||
|
||||
@@ -601,11 +663,16 @@ index 0062d2cb6634b8b29977a0312516b1b13936b40a..611a52e908f4cb70fbe5628e220a082e
|
||||
+ // Specifies if the process should trigger mouse cursor feedback.
|
||||
+ Options& WithFeedbackCursorOff(bool feedback_cursor_off);
|
||||
+#endif // #if BUILDFLAG(IS_WIN)
|
||||
+
|
||||
+#if BUILDFLAG(IS_MAC)
|
||||
+ // Specifies if the process should disclaim TCC responsibility.
|
||||
+ Options& WithDisclaimResponsibility(bool disclaim_responsibility);
|
||||
+#endif // BUILDFLAG(IS_MAC)
|
||||
+
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
// Specifies libraries to preload before the sandbox is locked down. Paths
|
||||
// should be absolute paths. Libraries will be preloaded before sandbox
|
||||
@@ -127,11 +156,23 @@ class CONTENT_EXPORT ServiceProcessHost {
|
||||
@@ -127,11 +161,26 @@ class CONTENT_EXPORT ServiceProcessHost {
|
||||
std::optional<GURL> site;
|
||||
std::optional<int> child_flags;
|
||||
std::vector<std::string> extra_switches;
|
||||
@@ -626,6 +693,9 @@ index 0062d2cb6634b8b29977a0312516b1b13936b40a..611a52e908f4cb70fbe5628e220a082e
|
||||
+#if BUILDFLAG(IS_WIN)
|
||||
+ bool feedback_cursor_off = false;
|
||||
+#endif // BUILDFLAG(IS_WIN)
|
||||
+#if BUILDFLAG(IS_MAC)
|
||||
+ bool disclaim_responsibility = false;
|
||||
+#endif // BUILDFLAG(IS_MAC)
|
||||
};
|
||||
|
||||
// An interface which can be implemented and registered/unregistered with
|
||||
|
||||
@@ -84,10 +84,10 @@ index 2648adb1cf38ab557b66ffd0e3034b26b04d76d6..98eab587f343f6ca472efc3d4e7b31b2
|
||||
private:
|
||||
const std::string service_interface_name_;
|
||||
diff --git a/content/browser/service_host/utility_process_host.cc b/content/browser/service_host/utility_process_host.cc
|
||||
index 1298ea85a176db2150a4101afc205745f32eb8f5..1668345fb66b5a150b01dc3cce2e7262890a9c66 100644
|
||||
index e90c8a9b2ac7d17fe7e5e814fd6eb3333f440bbe..4e11fbf6b5489acc212256fbedc1b9b2d627f7e4 100644
|
||||
--- a/content/browser/service_host/utility_process_host.cc
|
||||
+++ b/content/browser/service_host/utility_process_host.cc
|
||||
@@ -624,7 +624,7 @@ void UtilityProcessHost::OnProcessCrashed(int exit_code) {
|
||||
@@ -637,7 +637,7 @@ void UtilityProcessHost::OnProcessCrashed(int exit_code) {
|
||||
: Client::CrashType::kPreIpcInitialization;
|
||||
}
|
||||
#endif // BUILDFLAG(IS_WIN)
|
||||
@@ -97,7 +97,7 @@ index 1298ea85a176db2150a4101afc205745f32eb8f5..1668345fb66b5a150b01dc3cce2e7262
|
||||
|
||||
std::optional<std::string> UtilityProcessHost::GetServiceName() {
|
||||
diff --git a/content/browser/service_host/utility_process_host.h b/content/browser/service_host/utility_process_host.h
|
||||
index d731211d727f6e96533a058106c13f339263712d..19e35a0684746d6f5703ac4237de4d8aeddbaa4e 100644
|
||||
index 96c0cadf5caf5bf27f2a767c43f0f1da04298800..5a16fe5c01ae7777064168e8883ec8ec0b82a873 100644
|
||||
--- a/content/browser/service_host/utility_process_host.h
|
||||
+++ b/content/browser/service_host/utility_process_host.h
|
||||
@@ -87,7 +87,7 @@ class CONTENT_EXPORT UtilityProcessHost final
|
||||
|
||||
@@ -28,10 +28,10 @@ The patch should be removed in favor of either:
|
||||
Upstream bug https://bugs.chromium.org/p/chromium/issues/detail?id=1081397.
|
||||
|
||||
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc
|
||||
index 9bdb7c10319be5a6e715a34b29491a06ffe782b1..93e702df43d4c576443cd3efbf9127db2a00693e 100644
|
||||
index a020aa1ddc8ba7f5ecf5a376d00817f7fc61db40..23db0d047187a95cb401629a42fa3baaaf0feb12 100644
|
||||
--- a/content/browser/renderer_host/navigation_request.cc
|
||||
+++ b/content/browser/renderer_host/navigation_request.cc
|
||||
@@ -11514,6 +11514,11 @@ url::Origin NavigationRequest::GetOriginForURLLoaderFactoryUnchecked() {
|
||||
@@ -11515,6 +11515,11 @@ url::Origin NavigationRequest::GetOriginForURLLoaderFactoryUnchecked() {
|
||||
target_rph_id);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ Date: Wed, 28 Jun 2023 21:11:40 +0900
|
||||
Subject: fix: harden blink::ScriptState::MaybeFrom
|
||||
|
||||
NOTE: since https://chromium-review.googlesource.com/c/chromium/src/+/6973697
|
||||
the patch is only needed for 32-bit builds.
|
||||
the patch is only needed for 32-bit builds or builds where the V8 sandbox is disabled.
|
||||
|
||||
This is needed as side effect of https://chromium-review.googlesource.com/c/chromium/src/+/4609446
|
||||
which now gets blink::ExecutionContext from blink::ScriptState
|
||||
@@ -56,18 +56,18 @@ index cecf528475cb832ed1876381878eade582bc83d6..71308b2d963c2d083328aad6be356dc5
|
||||
|
||||
enum EmbedderDataTag : uint16_t {
|
||||
diff --git a/third_party/blink/renderer/platform/bindings/script_state.cc b/third_party/blink/renderer/platform/bindings/script_state.cc
|
||||
index 8b6522c9299bef5ab766795b64a1ba30bc382a12..a714aeb8a62886bedb3820b33b49b1ebdb9c7cc0 100644
|
||||
index 8b6522c9299bef5ab766795b64a1ba30bc382a12..4615dc04a3814a096898a36c7bbeb30f960a8b4d 100644
|
||||
--- a/third_party/blink/renderer/platform/bindings/script_state.cc
|
||||
+++ b/third_party/blink/renderer/platform/bindings/script_state.cc
|
||||
@@ -14,6 +14,12 @@ namespace blink {
|
||||
|
||||
ScriptState::CreateCallback ScriptState::s_create_callback_ = nullptr;
|
||||
|
||||
+#if defined(ARCH_CPU_32_BITS)
|
||||
+#if !defined(V8_ENABLE_SANDBOX)
|
||||
+int const ScriptState::kScriptStateTag = 0x6e6f64;
|
||||
+void* const ScriptState::kScriptStateTagPtr = const_cast<void*>(
|
||||
+ static_cast<const void*>(&ScriptState::kScriptStateTag));
|
||||
+#endif // defined(ARCH_CPU_32_BITS)
|
||||
+#endif // !defined(V8_ENABLE_SANDBOX)
|
||||
+
|
||||
// static
|
||||
void ScriptState::SetCreateCallback(CreateCallback create_callback) {
|
||||
@@ -76,10 +76,10 @@ index 8b6522c9299bef5ab766795b64a1ba30bc382a12..a714aeb8a62886bedb3820b33b49b1eb
|
||||
context_.SetWeak(this, &OnV8ContextCollectedCallback);
|
||||
context->SetAlignedPointerInEmbedderData(kV8ContextPerContextDataIndex, this,
|
||||
gin::kBlinkScriptState);
|
||||
+#if defined(ARCH_CPU_32_BITS)
|
||||
+#if !defined(V8_ENABLE_SANDBOX)
|
||||
+ context->SetAlignedPointerInEmbedderData(
|
||||
+ kV8ContextPerContextDataTagIndex, ScriptState::kScriptStateTagPtr, v8::kEmbedderDataTypeTagDefault);
|
||||
+#endif // defined(ARCH_CPU_32_BITS)
|
||||
+#endif // !defined(V8_ENABLE_SANDBOX)
|
||||
RendererResourceCoordinator::Get()->OnScriptStateCreated(this,
|
||||
execution_context);
|
||||
}
|
||||
@@ -87,15 +87,15 @@ index 8b6522c9299bef5ab766795b64a1ba30bc382a12..a714aeb8a62886bedb3820b33b49b1eb
|
||||
// Cut the reference from V8 context to ScriptState.
|
||||
GetContext()->SetAlignedPointerInEmbedderData(
|
||||
kV8ContextPerContextDataIndex, nullptr, gin::kBlinkScriptState);
|
||||
+#if defined(ARCH_CPU_32_BITS)
|
||||
+#if !defined(V8_ENABLE_SANDBOX)
|
||||
+ GetContext()->SetAlignedPointerInEmbedderData(
|
||||
+ kV8ContextPerContextDataTagIndex, nullptr, v8::kEmbedderDataTypeTagDefault);
|
||||
+#endif // defined(ARCH_CPU_32_BITS)
|
||||
+#endif // !defined(V8_ENABLE_SANDBOX)
|
||||
reference_from_v8_context_.Clear();
|
||||
|
||||
// Cut the reference from ScriptState to V8 context.
|
||||
diff --git a/third_party/blink/renderer/platform/bindings/script_state.h b/third_party/blink/renderer/platform/bindings/script_state.h
|
||||
index 5ccdf26cead17031d510589b74288cbe79692779..bf3023d5305c05c5d92953b5bf5f655f964e5c28 100644
|
||||
index 5ccdf26cead17031d510589b74288cbe79692779..54ede003ebe0a46e624c9d67f7272b8898bbc83e 100644
|
||||
--- a/third_party/blink/renderer/platform/bindings/script_state.h
|
||||
+++ b/third_party/blink/renderer/platform/bindings/script_state.h
|
||||
@@ -6,6 +6,7 @@
|
||||
@@ -110,7 +110,7 @@ index 5ccdf26cead17031d510589b74288cbe79692779..bf3023d5305c05c5d92953b5bf5f655f
|
||||
kV8ContextPerContextDataIndex) {
|
||||
return nullptr;
|
||||
}
|
||||
+#if defined(ARCH_CPU_32_BITS)
|
||||
+#if !defined(V8_ENABLE_SANDBOX)
|
||||
+ if (context->GetNumberOfEmbedderDataFields() <=
|
||||
+ kV8ContextPerContextDataTagIndex ||
|
||||
+ context->GetAlignedPointerFromEmbedderData(
|
||||
@@ -119,7 +119,7 @@ index 5ccdf26cead17031d510589b74288cbe79692779..bf3023d5305c05c5d92953b5bf5f655f
|
||||
+ ScriptState::kScriptStateTagPtr) {
|
||||
+ return nullptr;
|
||||
+ }
|
||||
+#endif // defined(ARCH_CPU_32_BITS)
|
||||
+#endif // !defined(V8_ENABLE_SANDBOX)
|
||||
ScriptState* script_state =
|
||||
static_cast<ScriptState*>(context->GetAlignedPointerFromEmbedderData(
|
||||
isolate, kV8ContextPerContextDataIndex, gin::kBlinkScriptState));
|
||||
@@ -127,13 +127,13 @@ index 5ccdf26cead17031d510589b74288cbe79692779..bf3023d5305c05c5d92953b5bf5f655f
|
||||
static_cast<int>(gin::kPerContextDataStartIndex) +
|
||||
static_cast<int>(gin::kEmbedderBlink);
|
||||
|
||||
+#if defined(ARCH_CPU_32_BITS)
|
||||
+#if !defined(V8_ENABLE_SANDBOX)
|
||||
+ static void* const kScriptStateTagPtr;
|
||||
+ static int const kScriptStateTag;
|
||||
+ static constexpr int kV8ContextPerContextDataTagIndex =
|
||||
+ static_cast<int>(gin::kPerContextDataStartIndex) +
|
||||
+ static_cast<int>(gin::kEmbedderBlinkTag);
|
||||
+#endif // defined(ARCH_CPU_32_BITS)
|
||||
+#endif // !defined(V8_ENABLE_SANDBOX)
|
||||
+
|
||||
// For accessing information about the last script compilation via
|
||||
// internals.idl.
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shelley Vohr <shelley.vohr@gmail.com>
|
||||
Date: Mon, 16 Feb 2026 22:33:57 +0100
|
||||
Subject: fix: update DBus signal signature for XDG GlobalShortcuts portal
|
||||
|
||||
Refs https://chromium-review.googlesource.com/c/chromium/src/+/7143562
|
||||
|
||||
The Activated signal from the XDG GlobalShortcuts portal has signature "osta{sv}",
|
||||
but ConnectToSignal was declared with "ost". The strict ReadMessage parser
|
||||
fails on the extra trailing options vardict. Fix by updating the signature
|
||||
to match the spec.
|
||||
|
||||
This should be upstreamed.
|
||||
|
||||
diff --git a/ui/base/accelerators/global_accelerator_listener/global_accelerator_listener_linux.cc b/ui/base/accelerators/global_accelerator_listener/global_accelerator_listener_linux.cc
|
||||
index 505e59edad7acb41f272f1e323cfd90744e4701b..ead80cfac902a7630cf502b03cb7d2ee048944ac 100644
|
||||
--- a/ui/base/accelerators/global_accelerator_listener/global_accelerator_listener_linux.cc
|
||||
+++ b/ui/base/accelerators/global_accelerator_listener/global_accelerator_listener_linux.cc
|
||||
@@ -78,7 +78,7 @@ void GlobalAcceleratorListenerLinux::OnServiceStarted(bool service_started) {
|
||||
global_shortcuts_proxy_ = bus_->GetObjectProxy(
|
||||
kPortalServiceName, dbus::ObjectPath(kPortalObjectPath));
|
||||
|
||||
- dbus_utils::ConnectToSignal<"ost">(
|
||||
+ dbus_utils::ConnectToSignal<"osta{sv}">(
|
||||
global_shortcuts_proxy_, kGlobalShortcutsInterface, kSignalActivated,
|
||||
base::BindRepeating(&GlobalAcceleratorListenerLinux::OnActivatedSignal,
|
||||
weak_ptr_factory_.GetWeakPtr()),
|
||||
@@ -299,13 +299,14 @@ void GlobalAcceleratorListenerLinux::OnBindShortcuts(
|
||||
}
|
||||
|
||||
void GlobalAcceleratorListenerLinux::OnActivatedSignal(
|
||||
- dbus_utils::ConnectToSignalResultSig<"ost"> result) {
|
||||
+ dbus_utils::ConnectToSignalResultSig<"osta{sv}"> result) {
|
||||
if (!result.has_value()) {
|
||||
LOG(ERROR) << "Failed to parse Activated signal.";
|
||||
return;
|
||||
}
|
||||
|
||||
- auto [session_handle, shortcut_id, timestamp] = std::move(result.value());
|
||||
+ auto [session_handle, shortcut_id, timestamp, options] =
|
||||
+ std::move(result.value());
|
||||
|
||||
// Only process the signal if it comes from our current session.
|
||||
if (!session_proxy_ || session_proxy_->object_path() != session_handle) {
|
||||
diff --git a/ui/base/accelerators/global_accelerator_listener/global_accelerator_listener_linux.h b/ui/base/accelerators/global_accelerator_listener/global_accelerator_listener_linux.h
|
||||
index 3838de75a0a3791f774e2ddedec0f6c7f2f30157..91a205e6c526aa02b46b1590fa427e8875a67280 100644
|
||||
--- a/ui/base/accelerators/global_accelerator_listener/global_accelerator_listener_linux.h
|
||||
+++ b/ui/base/accelerators/global_accelerator_listener/global_accelerator_listener_linux.h
|
||||
@@ -97,7 +97,8 @@ class GlobalAcceleratorListenerLinux : public GlobalAcceleratorListener {
|
||||
base::expected<dbus_xdg::Dictionary, dbus_xdg::ResponseError> results);
|
||||
|
||||
// Callbacks for DBus signals.
|
||||
- void OnActivatedSignal(dbus_utils::ConnectToSignalResultSig<"ost"> result);
|
||||
+ void OnActivatedSignal(
|
||||
+ dbus_utils::ConnectToSignalResultSig<"osta{sv}"> result);
|
||||
|
||||
void OnSignalConnected(const std::string& interface_name,
|
||||
const std::string& signal_name,
|
||||
@@ -0,0 +1,348 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Sunny Sachanandani <sunnyps@chromium.org>
|
||||
Date: Fri, 30 Jan 2026 12:51:05 -0800
|
||||
Subject: [graphite] Handle out of order recording errors
|
||||
|
||||
Explicitly handle out of order recording errors to crash just like async
|
||||
shader compile failed errors. Also, emit the insert status to an UMA
|
||||
histogram at 1% subsampling and log all error statuses at runtime.
|
||||
|
||||
Bug: 458722690
|
||||
Change-Id: Id94657be6ae870dcf8adba71aff216386a6a6964
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7533855
|
||||
Commit-Queue: Sunny Sachanandani <sunnyps@chromium.org>
|
||||
Auto-Submit: Sunny Sachanandani <sunnyps@chromium.org>
|
||||
Reviewed-by: Jonathan Ross <jonross@chromium.org>
|
||||
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
|
||||
Cr-Commit-Position: refs/heads/main@{#1577487}
|
||||
|
||||
diff --git a/gpu/command_buffer/service/graphite_shared_context.cc b/gpu/command_buffer/service/graphite_shared_context.cc
|
||||
index f9a47ac16bddc2352d81f43629d8ce8c2d2b3b99..9856d68f893e4329fda5d002835613161b346bc1 100644
|
||||
--- a/gpu/command_buffer/service/graphite_shared_context.cc
|
||||
+++ b/gpu/command_buffer/service/graphite_shared_context.cc
|
||||
@@ -4,7 +4,10 @@
|
||||
|
||||
#include "gpu/command_buffer/service/graphite_shared_context.h"
|
||||
|
||||
+#include "base/logging.h"
|
||||
#include "base/memory/ptr_util.h"
|
||||
+#include "base/metrics/histogram_macros.h"
|
||||
+#include "base/rand_util.h"
|
||||
#include "base/task/single_thread_task_runner.h"
|
||||
#include "gpu/command_buffer/common/shm_count.h"
|
||||
#include "third_party/skia/include/core/SkColorSpace.h"
|
||||
@@ -14,6 +17,44 @@
|
||||
namespace gpu {
|
||||
|
||||
namespace {
|
||||
+// This is emitted to UMA - values should not be reordered, only appended!
|
||||
+// LINT.IfChange(InsertRecordingStatusUma)
|
||||
+enum class InsertRecordingStatusUma {
|
||||
+ kSuccess,
|
||||
+ kInvalidRecording,
|
||||
+ kPromiseImageInstantiationFailed,
|
||||
+ kAddCommandsFailed,
|
||||
+ kAsyncShaderCompilesFailed,
|
||||
+ kOutOfOrderRecording,
|
||||
+ kMaxValue = kOutOfOrderRecording
|
||||
+};
|
||||
+// LINT.ThenChange(//tools/metrics/histograms/metadata/gpu/enums.xml:GraphiteInsertRecordingStatus)
|
||||
+
|
||||
+InsertRecordingStatusUma InsertRecordingStatusUma(
|
||||
+ skgpu::graphite::InsertStatus insert_status) {
|
||||
+ // InsertStatus almost behaves like an enum class, but not quite since it can
|
||||
+ // convert to both bool and integer types and can't be used in a switch.
|
||||
+ if (insert_status == skgpu::graphite::InsertStatus::kSuccess) {
|
||||
+ return InsertRecordingStatusUma::kSuccess;
|
||||
+ } else if (insert_status ==
|
||||
+ skgpu::graphite::InsertStatus::kInvalidRecording) {
|
||||
+ return InsertRecordingStatusUma::kInvalidRecording;
|
||||
+ } else if (insert_status ==
|
||||
+ skgpu::graphite::InsertStatus::kPromiseImageInstantiationFailed) {
|
||||
+ return InsertRecordingStatusUma::kPromiseImageInstantiationFailed;
|
||||
+ } else if (insert_status ==
|
||||
+ skgpu::graphite::InsertStatus::kAddCommandsFailed) {
|
||||
+ return InsertRecordingStatusUma::kAddCommandsFailed;
|
||||
+ } else if (insert_status ==
|
||||
+ skgpu::graphite::InsertStatus::kAsyncShaderCompilesFailed) {
|
||||
+ return InsertRecordingStatusUma::kAsyncShaderCompilesFailed;
|
||||
+ } else if (insert_status ==
|
||||
+ skgpu::graphite::InsertStatus::kOutOfOrderRecording) {
|
||||
+ return InsertRecordingStatusUma::kOutOfOrderRecording;
|
||||
+ }
|
||||
+ NOTREACHED();
|
||||
+}
|
||||
+
|
||||
struct RecordingContext {
|
||||
skgpu::graphite::GpuFinishedProc old_finished_proc;
|
||||
skgpu::graphite::GpuFinishedContext old_context;
|
||||
@@ -216,20 +257,38 @@ bool GraphiteSharedContext::InsertRecordingImpl(
|
||||
|
||||
auto insert_status = graphite_context_->insertRecording(*info_ptr);
|
||||
|
||||
- // TODO(433845560): Check the kAddCommandsFailed failures.
|
||||
- // Crash only if we're not simulating a failure for testing.
|
||||
const bool simulating_insert_failure =
|
||||
info_ptr->fSimulatedStatus != skgpu::graphite::InsertStatus::kSuccess;
|
||||
|
||||
- // InsertStatus::kAsyncShaderCompilesFailed is also an unrecoverable error for
|
||||
- // which we should also clear the disk shader cache in case the error was due
|
||||
- // to a corrupted cached shader blob.
|
||||
+ // Crash, log, or emit UMA only if we're not simulating a failure for testing.
|
||||
+ if (!simulating_insert_failure) {
|
||||
+ if (base::ShouldRecordSubsampledMetric(0.01)) {
|
||||
+ UMA_HISTOGRAM_ENUMERATION("GPU.Graphite.InsertRecordingStatus",
|
||||
+ InsertRecordingStatusUma(insert_status));
|
||||
+ }
|
||||
+ if (insert_status != skgpu::graphite::InsertStatus::kSuccess) {
|
||||
+ // skgpu::graphite::InsertStatus almost behaves like an enum class, but
|
||||
+ // not quite - it can't be static_cast to an int.
|
||||
+ LOG(ERROR) << "Graphite insertRecording failed with status "
|
||||
+ << static_cast<int>(InsertRecordingStatusUma(insert_status));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // kAsyncShaderCompilesFailed and kOutOfOrderRecording are unrecoverable
|
||||
+ // failures because they cause future recordings to be rendered incorrectly.
|
||||
+ // TODO(433845560): Check the kAddCommandsFailed failures.
|
||||
+ const bool is_unrecoverable_failure =
|
||||
+ insert_status ==
|
||||
+ skgpu::graphite::InsertStatus::kAsyncShaderCompilesFailed ||
|
||||
+ insert_status == skgpu::graphite::InsertStatus::kOutOfOrderRecording;
|
||||
+ // For kAsyncShaderCompilesFailed, we should also clear the disk shader
|
||||
+ // cache in case the error was due to a corrupted cached shader blob.
|
||||
+ std::optional<GpuProcessShmCount::ScopedIncrement> use_shader_cache;
|
||||
if (insert_status ==
|
||||
skgpu::graphite::InsertStatus::kAsyncShaderCompilesFailed) {
|
||||
- GpuProcessShmCount::ScopedIncrement use_shader_cache(
|
||||
- use_shader_cache_shm_count_);
|
||||
- CHECK(simulating_insert_failure);
|
||||
+ use_shader_cache.emplace(use_shader_cache_shm_count_);
|
||||
}
|
||||
+ CHECK(simulating_insert_failure || !is_unrecoverable_failure);
|
||||
|
||||
// All other failure modes are recoverable in the sense that future recordings
|
||||
// will be rendered correctly, so merely return a boolean here so that callers
|
||||
diff --git a/gpu/command_buffer/service/graphite_shared_context_unittest.cc b/gpu/command_buffer/service/graphite_shared_context_unittest.cc
|
||||
index 0de107a9d86ff8217a4c537598f198f313ecf9df..852343ab6804efed962b707b748ddf1920c20ea7 100644
|
||||
--- a/gpu/command_buffer/service/graphite_shared_context_unittest.cc
|
||||
+++ b/gpu/command_buffer/service/graphite_shared_context_unittest.cc
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "base/threading/thread.h"
|
||||
#include "gpu/command_buffer/common/shm_count.h"
|
||||
+#include "gpu/command_buffer/service/skia_utils.h"
|
||||
#include "skia/buildflags.h"
|
||||
#include "testing/gmock/include/gmock/gmock.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
@@ -86,8 +87,7 @@ class GraphiteSharedContextTest : public testing::TestWithParam<bool> {
|
||||
|
||||
wgpu::DeviceDescriptor device_desc = {};
|
||||
|
||||
- wgpu::Device device =
|
||||
- wgpu::Adapter(adapters[0].Get()).CreateDevice(&device_desc);
|
||||
+ auto device = wgpu::Adapter(adapters[0].Get()).CreateDevice(&device_desc);
|
||||
CHECK(device);
|
||||
|
||||
skgpu::graphite::DawnBackendContext backend_context = {};
|
||||
@@ -95,7 +95,11 @@ class GraphiteSharedContextTest : public testing::TestWithParam<bool> {
|
||||
backend_context.fDevice = device;
|
||||
backend_context.fQueue = device.GetQueue();
|
||||
|
||||
- skgpu::graphite::ContextOptions context_options = {};
|
||||
+ // Use the default Graphite context options that Chromium uses e.g. disallow
|
||||
+ // things like out of order recordings.
|
||||
+ gpu::GpuDriverBugWorkarounds workarounds;
|
||||
+ auto context_options = GetDefaultGraphiteContextOptions(workarounds);
|
||||
+
|
||||
graphite_shared_context_ = std::make_unique<GraphiteSharedContext>(
|
||||
skgpu::graphite::ContextFactory::MakeDawn(backend_context,
|
||||
context_options),
|
||||
@@ -133,14 +137,12 @@ TEST_P(GraphiteSharedContextTest, ConcurrentAccess) {
|
||||
auto run_graphite_functions =
|
||||
[](GraphiteSharedContext* graphite_shared_context) {
|
||||
// Call a method that acquires the lock
|
||||
- std::unique_ptr<skgpu::graphite::Recorder> recorder =
|
||||
- graphite_shared_context->makeRecorder();
|
||||
+ auto recorder = graphite_shared_context->makeRecorder();
|
||||
EXPECT_TRUE(recorder);
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
for (int j = 0; j < 10; ++j) {
|
||||
- std::unique_ptr<skgpu::graphite::Recording> recording =
|
||||
- recorder->snap();
|
||||
+ auto recording = recorder->snap();
|
||||
skgpu::graphite::InsertRecordingInfo info = {};
|
||||
info.fRecording = recording.get();
|
||||
EXPECT_TRUE(recording);
|
||||
@@ -172,18 +174,17 @@ TEST_P(GraphiteSharedContextTest, ConcurrentAccess) {
|
||||
}
|
||||
|
||||
TEST_P(GraphiteSharedContextTest, AsyncShaderCompilesFailed) {
|
||||
- std::unique_ptr<skgpu::graphite::Recorder> recorder =
|
||||
- graphite_shared_context_->makeRecorder();
|
||||
+ auto recorder = graphite_shared_context_->makeRecorder();
|
||||
EXPECT_TRUE(recorder);
|
||||
|
||||
auto ii = SkImageInfo::Make(64, 64, kN32_SkColorType, kPremul_SkAlphaType);
|
||||
- sk_sp<SkSurface> surface1 = SkSurfaces::RenderTarget(recorder.get(), ii);
|
||||
+ auto surface1 = SkSurfaces::RenderTarget(recorder.get(), ii);
|
||||
surface1->getCanvas()->clear(SK_ColorRED);
|
||||
|
||||
- sk_sp<SkSurface> surface2 = SkSurfaces::RenderTarget(recorder.get(), ii);
|
||||
+ auto surface2 = SkSurfaces::RenderTarget(recorder.get(), ii);
|
||||
surface2->getCanvas()->drawImage(surface1->makeTemporaryImage(), 0, 0);
|
||||
|
||||
- std::unique_ptr<skgpu::graphite::Recording> recording = recorder->snap();
|
||||
+ auto recording = recorder->snap();
|
||||
EXPECT_TRUE(recording);
|
||||
|
||||
skgpu::graphite::InsertRecordingInfo info = {};
|
||||
@@ -197,19 +198,43 @@ TEST_P(GraphiteSharedContextTest, AsyncShaderCompilesFailed) {
|
||||
EXPECT_FALSE(graphite_shared_context_->insertRecording(info));
|
||||
}
|
||||
|
||||
+TEST_P(GraphiteSharedContextTest, OutOfOrderRecording) {
|
||||
+ auto recorder = graphite_shared_context_->makeRecorder();
|
||||
+ EXPECT_TRUE(recorder);
|
||||
+
|
||||
+ auto ii = SkImageInfo::Make(64, 64, kN32_SkColorType, kPremul_SkAlphaType);
|
||||
+ auto surface1 = SkSurfaces::RenderTarget(recorder.get(), ii);
|
||||
+ surface1->getCanvas()->clear(SK_ColorRED);
|
||||
+ auto recording1 = recorder->snap();
|
||||
+ EXPECT_TRUE(recording1);
|
||||
+
|
||||
+ auto surface2 = SkSurfaces::RenderTarget(recorder.get(), ii);
|
||||
+ surface2->getCanvas()->drawImage(surface1->makeTemporaryImage(), 0, 0);
|
||||
+ auto recording2 = recorder->snap();
|
||||
+ EXPECT_TRUE(recording2);
|
||||
+
|
||||
+ skgpu::graphite::InsertRecordingInfo info = {};
|
||||
+
|
||||
+ info.fRecording = recording2.get();
|
||||
+ graphite_shared_context_->insertRecording(info);
|
||||
+
|
||||
+ info.fRecording = recording1.get();
|
||||
+ EXPECT_DEATH_IF_SUPPORTED(graphite_shared_context_->insertRecording(info),
|
||||
+ "");
|
||||
+}
|
||||
+
|
||||
TEST_P(GraphiteSharedContextTest, AddCommandsFailed) {
|
||||
- std::unique_ptr<skgpu::graphite::Recorder> recorder =
|
||||
- graphite_shared_context_->makeRecorder();
|
||||
+ auto recorder = graphite_shared_context_->makeRecorder();
|
||||
EXPECT_TRUE(recorder);
|
||||
|
||||
auto ii = SkImageInfo::Make(64, 64, kN32_SkColorType, kPremul_SkAlphaType);
|
||||
- sk_sp<SkSurface> surface1 = SkSurfaces::RenderTarget(recorder.get(), ii);
|
||||
+ auto surface1 = SkSurfaces::RenderTarget(recorder.get(), ii);
|
||||
surface1->getCanvas()->clear(SK_ColorRED);
|
||||
|
||||
- sk_sp<SkSurface> surface2 = SkSurfaces::RenderTarget(recorder.get(), ii);
|
||||
+ auto surface2 = SkSurfaces::RenderTarget(recorder.get(), ii);
|
||||
surface2->getCanvas()->drawImage(surface1->makeTemporaryImage(), 0, 0);
|
||||
|
||||
- std::unique_ptr<skgpu::graphite::Recording> recording = recorder->snap();
|
||||
+ auto recording = recorder->snap();
|
||||
EXPECT_TRUE(recording);
|
||||
|
||||
skgpu::graphite::InsertRecordingInfo info = {};
|
||||
@@ -223,39 +248,37 @@ TEST_P(GraphiteSharedContextTest, AddCommandsFailed) {
|
||||
}
|
||||
|
||||
TEST_P(GraphiteSharedContextTest, LowPendingRecordings) {
|
||||
- std::unique_ptr<skgpu::graphite::Recorder> recorder =
|
||||
- graphite_shared_context_->makeRecorder();
|
||||
+ auto recorder = graphite_shared_context_->makeRecorder();
|
||||
EXPECT_TRUE(recorder);
|
||||
|
||||
- std::unique_ptr<skgpu::graphite::Recording> recording = recorder->snap();
|
||||
- EXPECT_TRUE(recording);
|
||||
-
|
||||
- skgpu::graphite::InsertRecordingInfo info = {};
|
||||
- info.fRecording = recording.get();
|
||||
-
|
||||
// No flush is expected if the number of pending recordings is low.
|
||||
EXPECT_CALL(backend_flush_callback_, Flush()).Times(0);
|
||||
|
||||
for (size_t i = 0; i < kMaxPendingRecordings - 1; ++i) {
|
||||
+ auto recording = recorder->snap();
|
||||
+ EXPECT_TRUE(recording);
|
||||
+
|
||||
+ skgpu::graphite::InsertRecordingInfo info = {};
|
||||
+ info.fRecording = recording.get();
|
||||
+
|
||||
EXPECT_TRUE(graphite_shared_context_->insertRecording(info));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(GraphiteSharedContextTest, MaxPendingRecordings) {
|
||||
- std::unique_ptr<skgpu::graphite::Recorder> recorder =
|
||||
- graphite_shared_context_->makeRecorder();
|
||||
+ auto recorder = graphite_shared_context_->makeRecorder();
|
||||
EXPECT_TRUE(recorder);
|
||||
|
||||
- std::unique_ptr<skgpu::graphite::Recording> recording = recorder->snap();
|
||||
- EXPECT_TRUE(recording);
|
||||
-
|
||||
- skgpu::graphite::InsertRecordingInfo info = {};
|
||||
- info.fRecording = recording.get();
|
||||
-
|
||||
// Expect a flush when the number of pending recordings reaches the max.
|
||||
EXPECT_CALL(backend_flush_callback_, Flush()).Times(1);
|
||||
|
||||
for (size_t i = 0; i < kMaxPendingRecordings; ++i) {
|
||||
+ auto recording = recorder->snap();
|
||||
+ EXPECT_TRUE(recording);
|
||||
+
|
||||
+ skgpu::graphite::InsertRecordingInfo info = {};
|
||||
+ info.fRecording = recording.get();
|
||||
+
|
||||
EXPECT_TRUE(graphite_shared_context_->insertRecording(info));
|
||||
}
|
||||
}
|
||||
diff --git a/tools/metrics/histograms/metadata/gpu/enums.xml b/tools/metrics/histograms/metadata/gpu/enums.xml
|
||||
index 659d7721751a10f24dd1cf21b2b67baee17dfd52..91439cd24cc51a8fd762d4d079c56495965c2087 100644
|
||||
--- a/tools/metrics/histograms/metadata/gpu/enums.xml
|
||||
+++ b/tools/metrics/histograms/metadata/gpu/enums.xml
|
||||
@@ -1112,6 +1112,19 @@ Called by update_gpu_driver_bug_workaround_entries.py.-->
|
||||
<int value="10" label="NoKillForGpuProgressInCrashDump"/>
|
||||
</enum>
|
||||
|
||||
+<!-- LINT.IfChange(GraphiteInsertRecordingStatus) -->
|
||||
+
|
||||
+<enum name="GraphiteInsertRecordingStatus">
|
||||
+ <int value="0" label="Success"/>
|
||||
+ <int value="1" label="InvalidRecording"/>
|
||||
+ <int value="2" label="PromiseImageInstantiationFailed"/>
|
||||
+ <int value="3" label="AddCommandsFailed"/>
|
||||
+ <int value="4" label="AsyncShaderCompilesFailed"/>
|
||||
+ <int value="5" label="OutOfOrderRecording"/>
|
||||
+</enum>
|
||||
+
|
||||
+<!-- LINT.ThenChange(//gpu/command_buffer/service/graphite_shared_context.cc:InsertRecordingStatusUma) -->
|
||||
+
|
||||
<enum name="HasDiscreteGpu">
|
||||
<int value="0" label="No"/>
|
||||
<int value="1" label="Yes"/>
|
||||
diff --git a/tools/metrics/histograms/metadata/gpu/histograms.xml b/tools/metrics/histograms/metadata/gpu/histograms.xml
|
||||
index 9524b4f806478ab8be823f9a18f187e8d8449650..df6916ee3d33cc9f0eb665b7506a9302d1cfeb0b 100644
|
||||
--- a/tools/metrics/histograms/metadata/gpu/histograms.xml
|
||||
+++ b/tools/metrics/histograms/metadata/gpu/histograms.xml
|
||||
@@ -1011,6 +1011,16 @@ chromium-metrics-reviews@google.com.
|
||||
</summary>
|
||||
</histogram>
|
||||
|
||||
+<histogram name="Gpu.Graphite.InsertRecordingStatus"
|
||||
+ enum="GraphiteInsertRecordingStatus" expires_after="2026-04-30">
|
||||
+ <owner>sunnyps@chromium.org</owner>
|
||||
+ <owner>michaelludwig@google.com</owner>
|
||||
+ <owner>chrome-gpu-metric-alerts@chromium.org</owner>
|
||||
+ <summary>
|
||||
+ The return value for each Graphite insertRecording call made by Chromium.
|
||||
+ </summary>
|
||||
+</histogram>
|
||||
+
|
||||
<histogram name="GPU.GraphValidation.Duration" units="ms"
|
||||
expires_after="2025-11-15">
|
||||
<owner>vasilyt@chromium.org</owner>
|
||||
@@ -0,0 +1,52 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Niklas Wenzel <dev@nikwen.de>
|
||||
Date: Wed, 4 Feb 2026 06:02:40 -0800
|
||||
Subject: LoAF: Add feature to enable sourceURL for all protocols
|
||||
|
||||
Backports https://crrev.com/c/7510894 (minus the test changes).
|
||||
|
||||
Can be removed when that CL is included via a Chromium roll.
|
||||
|
||||
Change-Id: Id5e58a151b13cc0ac054f4ec237b038255d683fd
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7510894
|
||||
Commit-Queue: Noam Rosenthal <nrosenthal@google.com>
|
||||
Reviewed-by: Dave Tapuska <dtapuska@chromium.org>
|
||||
Reviewed-by: Noam Rosenthal <nrosenthal@google.com>
|
||||
Cr-Commit-Position: refs/heads/main@{#1579397}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/frame/animation_frame_timing_monitor.cc b/third_party/blink/renderer/core/frame/animation_frame_timing_monitor.cc
|
||||
index 0d621b6b397a2f8c33732a7bc1a68830539438be..f0749e9a9db7c5cd6b9d12440800241a14640cdd 100644
|
||||
--- a/third_party/blink/renderer/core/frame/animation_frame_timing_monitor.cc
|
||||
+++ b/third_party/blink/renderer/core/frame/animation_frame_timing_monitor.cc
|
||||
@@ -520,8 +520,15 @@ void AnimationFrameTimingMonitor::Trace(Visitor* visitor) const {
|
||||
visitor->Trace(frame_handling_input_);
|
||||
}
|
||||
|
||||
+BASE_FEATURE(kAlwaysLogLOAFURL, base::FEATURE_DISABLED_BY_DEFAULT);
|
||||
+
|
||||
namespace {
|
||||
+
|
||||
bool ShouldAllowScriptURL(const String& url) {
|
||||
+ if (base::FeatureList::IsEnabled(kAlwaysLogLOAFURL)) {
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
KURL kurl(url);
|
||||
return kurl.ProtocolIsData() || kurl.ProtocolIsInHTTPFamily() ||
|
||||
kurl.ProtocolIs("blob") || kurl.IsEmpty();
|
||||
diff --git a/third_party/blink/renderer/core/frame/animation_frame_timing_monitor.h b/third_party/blink/renderer/core/frame/animation_frame_timing_monitor.h
|
||||
index f2fe39be2db525d89fcd9787c2ae9285babab26d..c395cf39d404f6c4f6f6e23c9fb8dfe92151a7d2 100644
|
||||
--- a/third_party/blink/renderer/core/frame/animation_frame_timing_monitor.h
|
||||
+++ b/third_party/blink/renderer/core/frame/animation_frame_timing_monitor.h
|
||||
@@ -22,6 +22,11 @@ class TimeTicks;
|
||||
|
||||
namespace blink {
|
||||
|
||||
+// When enabled, long-animation-frame events will always include the sourceURL,
|
||||
+// regardless of protocol. This is useful during development when using `file:`
|
||||
+// URLs or custom protocols defined by embedders.
|
||||
+CORE_EXPORT BASE_DECLARE_FEATURE(kAlwaysLogLOAFURL);
|
||||
+
|
||||
class LocalFrame;
|
||||
|
||||
// Monitors long-animation-frame timing (LoAF).
|
||||
@@ -1,13 +1,13 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: deepak1556 <hop2deep@gmail.com>
|
||||
Date: Thu, 7 Apr 2022 20:30:16 +0900
|
||||
Subject: Make gtk::GetLibGdkPixbuf public
|
||||
Subject: Make gtk::GetLibGdkPixbuf and gtk::GetLibGdk public
|
||||
|
||||
Allows embedders to get a handle to the gdk_pixbuf
|
||||
library already loaded in the process.
|
||||
Allows embedders to get handles to the gdk_pixbuf
|
||||
and gdk libraries already loaded in the process.
|
||||
|
||||
diff --git a/ui/gtk/gtk_compat.cc b/ui/gtk/gtk_compat.cc
|
||||
index e05b4f2eb1b22d5a647cb020bae4e4052a2e735c..c06af1c03487fafe76fde3bfa157a7d265e2f3a0 100644
|
||||
index e05b4f2eb1b22d5a647cb020bae4e4052a2e735c..86524a419606bea3e7d090415fda8f2d8ce24df2 100644
|
||||
--- a/ui/gtk/gtk_compat.cc
|
||||
+++ b/ui/gtk/gtk_compat.cc
|
||||
@@ -78,11 +78,6 @@ void* GetLibGio() {
|
||||
@@ -22,7 +22,7 @@ index e05b4f2eb1b22d5a647cb020bae4e4052a2e735c..c06af1c03487fafe76fde3bfa157a7d2
|
||||
void* GetLibGdk3() {
|
||||
static void* libgdk3 = DlOpen("libgdk-3.so.0");
|
||||
return libgdk3;
|
||||
@@ -175,6 +170,11 @@ gfx::Insets InsetsFromGtkBorder(const GtkBorder& border) {
|
||||
@@ -175,6 +170,15 @@ gfx::Insets InsetsFromGtkBorder(const GtkBorder& border) {
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -30,20 +30,27 @@ index e05b4f2eb1b22d5a647cb020bae4e4052a2e735c..c06af1c03487fafe76fde3bfa157a7d2
|
||||
+ static void* libgdk_pixbuf = DlOpen("libgdk_pixbuf-2.0.so.0");
|
||||
+ return libgdk_pixbuf;
|
||||
+}
|
||||
+
|
||||
+void* GetLibGdk() {
|
||||
+ return GtkCheckVersion(4) ? GetLibGtk4() : GetLibGdk3();
|
||||
+}
|
||||
+
|
||||
bool LoadGtk(ui::LinuxUiBackend backend) {
|
||||
static bool loaded = LoadGtkImpl(backend);
|
||||
return loaded;
|
||||
diff --git a/ui/gtk/gtk_compat.h b/ui/gtk/gtk_compat.h
|
||||
index 841e2e8fcdbe2da4aac487badd4d352476e461a2..e458df649546fa3bee10e24f0edac147186cc152 100644
|
||||
index 841e2e8fcdbe2da4aac487badd4d352476e461a2..043c3ab4dde02ca71798034e8cb2b3f2d2677af7 100644
|
||||
--- a/ui/gtk/gtk_compat.h
|
||||
+++ b/ui/gtk/gtk_compat.h
|
||||
@@ -42,6 +42,9 @@ using SkColor = uint32_t;
|
||||
@@ -42,6 +42,12 @@ using SkColor = uint32_t;
|
||||
|
||||
namespace gtk {
|
||||
|
||||
+// Get handle to the currently loaded gdk_pixbuf library in the process.
|
||||
+void* GetLibGdkPixbuf();
|
||||
+
|
||||
+// Get handle to the currently loaded gdk library in the process.
|
||||
+void* GetLibGdk();
|
||||
+
|
||||
// Loads libgtk and related libraries and returns true on success.
|
||||
bool LoadGtk(ui::LinuxUiBackend backend);
|
||||
|
||||
@@ -127,7 +127,7 @@ index 419a051968c58ae5a761708e4d942e8975c70852..a77032dd43f5fcbe29c54b622b34607f
|
||||
|
||||
} // namespace base::mac
|
||||
diff --git a/base/process/launch_mac.cc b/base/process/launch_mac.cc
|
||||
index b63d58da9837ba4d1e4aff8f24f2cd977c5ed02d..8387fd7d2bcf8951b6cc024829c16d970799190c 100644
|
||||
index b63d58da9837ba4d1e4aff8f24f2cd977c5ed02d..49b4c0b69731386ef5a4b7dfb782aa8f4ae09cdd 100644
|
||||
--- a/base/process/launch_mac.cc
|
||||
+++ b/base/process/launch_mac.cc
|
||||
@@ -84,6 +84,10 @@ int posix_spawnattr_set_csm_np(const posix_spawnattr_t*, uint32_t)
|
||||
@@ -181,15 +181,26 @@ index b63d58da9837ba4d1e4aff8f24f2cd977c5ed02d..8387fd7d2bcf8951b6cc024829c16d97
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -301,7 +321,7 @@ Process LaunchProcess(const std::vector<std::string>& argv,
|
||||
@@ -301,16 +321,16 @@ Process LaunchProcess(const std::vector<std::string>& argv,
|
||||
file_actions.Inherit(STDERR_FILENO);
|
||||
}
|
||||
|
||||
-#if BUILDFLAG(IS_MAC)
|
||||
+#if 0
|
||||
+#if !IS_MAS_BUILD()
|
||||
if (options.disclaim_responsibility) {
|
||||
DPSXCHECK(responsibility_spawnattrs_setdisclaim(attr.get(), 1));
|
||||
}
|
||||
+#endif
|
||||
|
||||
EnvironmentMap new_environment_map = options.environment;
|
||||
+#if !IS_MAS_BUILD()
|
||||
MachPortRendezvousServerMac::AddFeatureStateToEnvironment(
|
||||
new_environment_map);
|
||||
-#else
|
||||
- const EnvironmentMap& new_environment_map = options.environment;
|
||||
#endif
|
||||
|
||||
std::vector<char*> argv_cstr;
|
||||
diff --git a/base/process/process_info_mac.mm b/base/process/process_info_mac.mm
|
||||
index e12c1d078147d956a1d9b1bc498c1b1d6fe7b974..233362259dc4e728ed37435e650417647b45a6af 100644
|
||||
--- a/base/process/process_info_mac.mm
|
||||
@@ -505,7 +516,7 @@ index 020050de162705651b4eb8378880cd4eb017d46c..2d3554861a570271d6f9b9a2c8b1de53
|
||||
// The NSWindow used by BridgedNativeWidget. Provides hooks into AppKit that
|
||||
// can only be accomplished by overriding methods.
|
||||
diff --git a/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm b/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
|
||||
index a474e70cf3c10405b6f94f129f5a7312bb81fd73..00f6719bd80c8fdf31f910af3b93b5c6b192912c 100644
|
||||
index a474e70cf3c10405b6f94f129f5a7312bb81fd73..adaff0f3d676eeaef93ac9a4a3b55fc0e572d33b 100644
|
||||
--- a/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
|
||||
+++ b/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
|
||||
@@ -21,6 +21,7 @@
|
||||
@@ -542,7 +553,7 @@ index a474e70cf3c10405b6f94f129f5a7312bb81fd73..00f6719bd80c8fdf31f910af3b93b5c6
|
||||
@end
|
||||
|
||||
struct NSEdgeAndCornerThicknesses {
|
||||
@@ -158,13 +163,17 @@ - (void)cr_mouseDownOnFrameView:(NSEvent*)event;
|
||||
@@ -158,13 +163,30 @@ - (void)cr_mouseDownOnFrameView:(NSEvent*)event;
|
||||
@implementation NSView (CRFrameViewAdditions)
|
||||
// If a mouseDown: falls through to the frame view, turn it into a window drag.
|
||||
- (void)cr_mouseDownOnFrameView:(NSEvent*)event {
|
||||
@@ -550,6 +561,19 @@ index a474e70cf3c10405b6f94f129f5a7312bb81fd73..00f6719bd80c8fdf31f910af3b93b5c6
|
||||
if ([self.window _resizeDirectionForMouseLocation:event.locationInWindow] !=
|
||||
-1)
|
||||
return;
|
||||
+#else
|
||||
+ // For MAS builds, approximate the resize direction check.
|
||||
+ if (self.window.styleMask & NSWindowStyleMaskResizable) {
|
||||
+ constexpr CGFloat kResizeThreshold = 5.0;
|
||||
+ NSPoint location = event.locationInWindow;
|
||||
+ NSRect frame = self.window.frame;
|
||||
+ CGFloat width = NSWidth(frame);
|
||||
+ CGFloat height = NSHeight(frame);
|
||||
+ if (location.x < kResizeThreshold || location.x > width - kResizeThreshold ||
|
||||
+ location.y < kResizeThreshold || location.y > height - kResizeThreshold) {
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+#endif
|
||||
[self.window performWindowDragWithEvent:event];
|
||||
}
|
||||
@@ -560,7 +584,7 @@ index a474e70cf3c10405b6f94f129f5a7312bb81fd73..00f6719bd80c8fdf31f910af3b93b5c6
|
||||
@implementation NativeWidgetMacNSWindowTitledFrame
|
||||
- (void)mouseDown:(NSEvent*)event {
|
||||
if (self.window.isMovable)
|
||||
@@ -192,6 +201,8 @@ - (BOOL)usesCustomDrawing {
|
||||
@@ -192,6 +214,8 @@ - (BOOL)usesCustomDrawing {
|
||||
}
|
||||
@end
|
||||
|
||||
@@ -569,7 +593,7 @@ index a474e70cf3c10405b6f94f129f5a7312bb81fd73..00f6719bd80c8fdf31f910af3b93b5c6
|
||||
@implementation NativeWidgetMacNSWindow {
|
||||
@private
|
||||
CommandDispatcher* __strong _commandDispatcher;
|
||||
@@ -241,6 +252,7 @@ - (instancetype)initWithContentRect:(NSRect)contentRect
|
||||
@@ -241,6 +265,7 @@ - (instancetype)initWithContentRect:(NSRect)contentRect
|
||||
// bubbles and the find bar, but these should not be movable.
|
||||
// Instead, let's push this up to the parent window which should be
|
||||
// the browser.
|
||||
@@ -577,7 +601,7 @@ index a474e70cf3c10405b6f94f129f5a7312bb81fd73..00f6719bd80c8fdf31f910af3b93b5c6
|
||||
- (void)_zoomToScreenEdge:(NSUInteger)edge {
|
||||
if (self.parentWindow) {
|
||||
[self.parentWindow _zoomToScreenEdge:edge];
|
||||
@@ -248,6 +260,7 @@ - (void)_zoomToScreenEdge:(NSUInteger)edge {
|
||||
@@ -248,6 +273,7 @@ - (void)_zoomToScreenEdge:(NSUInteger)edge {
|
||||
[super _zoomToScreenEdge:edge];
|
||||
}
|
||||
}
|
||||
@@ -585,7 +609,7 @@ index a474e70cf3c10405b6f94f129f5a7312bb81fd73..00f6719bd80c8fdf31f910af3b93b5c6
|
||||
|
||||
// This override helps diagnose lifetime issues in crash stacktraces by
|
||||
// inserting a symbol on NativeWidgetMacNSWindow and should be kept even if it
|
||||
@@ -393,6 +406,8 @@ - (NSAccessibilityRole)accessibilityRole {
|
||||
@@ -393,6 +419,8 @@ - (NSAccessibilityRole)accessibilityRole {
|
||||
|
||||
// NSWindow overrides.
|
||||
|
||||
@@ -594,7 +618,7 @@ index a474e70cf3c10405b6f94f129f5a7312bb81fd73..00f6719bd80c8fdf31f910af3b93b5c6
|
||||
+ (Class)frameViewClassForStyleMask:(NSWindowStyleMask)windowStyle {
|
||||
if (windowStyle & NSWindowStyleMaskTitled) {
|
||||
if (Class customFrame = [NativeWidgetMacNSWindowTitledFrame class])
|
||||
@@ -404,6 +419,8 @@ + (Class)frameViewClassForStyleMask:(NSWindowStyleMask)windowStyle {
|
||||
@@ -404,6 +432,8 @@ + (Class)frameViewClassForStyleMask:(NSWindowStyleMask)windowStyle {
|
||||
return [super frameViewClassForStyleMask:windowStyle];
|
||||
}
|
||||
|
||||
@@ -603,7 +627,7 @@ index a474e70cf3c10405b6f94f129f5a7312bb81fd73..00f6719bd80c8fdf31f910af3b93b5c6
|
||||
- (BOOL)_isTitleHidden {
|
||||
bool shouldShowWindowTitle = YES;
|
||||
if (_bridge)
|
||||
@@ -428,12 +445,14 @@ - (BOOL)_usesCustomDrawing {
|
||||
@@ -428,12 +458,14 @@ - (BOOL)_usesCustomDrawing {
|
||||
// if it were valid to set that style for windows, setting the window style
|
||||
// recalculates and re-caches a bunch of stuff, so a surgical override is the
|
||||
// cleanest approach.
|
||||
@@ -618,7 +642,7 @@ index a474e70cf3c10405b6f94f129f5a7312bb81fd73..00f6719bd80c8fdf31f910af3b93b5c6
|
||||
|
||||
+ (void)_getExteriorResizeEdgeThicknesses:
|
||||
(NSEdgeAndCornerThicknesses*)outThicknesses
|
||||
@@ -687,9 +706,11 @@ - (id)archiver:(NSKeyedArchiver*)archiver willEncodeObject:(id)object {
|
||||
@@ -687,9 +719,11 @@ - (id)archiver:(NSKeyedArchiver*)archiver willEncodeObject:(id)object {
|
||||
}
|
||||
|
||||
- (void)saveRestorableState {
|
||||
@@ -630,7 +654,7 @@ index a474e70cf3c10405b6f94f129f5a7312bb81fd73..00f6719bd80c8fdf31f910af3b93b5c6
|
||||
|
||||
// Certain conditions, such as in the Speedometer 3 benchmark, can trigger a
|
||||
// rapid succession of calls to saveRestorableState. If there's no pending
|
||||
@@ -756,6 +777,7 @@ - (void)reallySaveRestorableState {
|
||||
@@ -756,6 +790,7 @@ - (void)reallySaveRestorableState {
|
||||
// affects its restorable state changes.
|
||||
- (void)invalidateRestorableState {
|
||||
[super invalidateRestorableState];
|
||||
@@ -638,7 +662,7 @@ index a474e70cf3c10405b6f94f129f5a7312bb81fd73..00f6719bd80c8fdf31f910af3b93b5c6
|
||||
if ([self _isConsideredOpenForPersistentState]) {
|
||||
if (_willUpdateRestorableState)
|
||||
return;
|
||||
@@ -768,6 +790,7 @@ - (void)invalidateRestorableState {
|
||||
@@ -768,6 +803,7 @@ - (void)invalidateRestorableState {
|
||||
_willUpdateRestorableState = NO;
|
||||
[NSObject cancelPreviousPerformRequestsWithTarget:self];
|
||||
}
|
||||
@@ -646,7 +670,7 @@ index a474e70cf3c10405b6f94f129f5a7312bb81fd73..00f6719bd80c8fdf31f910af3b93b5c6
|
||||
}
|
||||
|
||||
// On newer SDKs, _canMiniaturize respects NSWindowStyleMaskMiniaturizable in
|
||||
@@ -932,6 +955,7 @@ - (void)maybeRemoveTreeFromOrderingGroups {
|
||||
@@ -932,6 +968,7 @@ - (void)maybeRemoveTreeFromOrderingGroups {
|
||||
// Since _removeFromGroups: is not documented it could go away in newer
|
||||
// versions of macOS. If the selector does not exist, DumpWithoutCrashing() so
|
||||
// we hear about the change.
|
||||
@@ -654,7 +678,7 @@ index a474e70cf3c10405b6f94f129f5a7312bb81fd73..00f6719bd80c8fdf31f910af3b93b5c6
|
||||
if (![NSWindow instancesRespondToSelector:@selector(_removeFromGroups:)]) {
|
||||
base::debug::DumpWithoutCrashing();
|
||||
return;
|
||||
@@ -949,6 +973,7 @@ - (void)maybeRemoveTreeFromOrderingGroups {
|
||||
@@ -949,6 +986,7 @@ - (void)maybeRemoveTreeFromOrderingGroups {
|
||||
[currentWindow _removeFromGroups:child];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?V=C3=A4in=C3=B6=20M=C3=A4kel=C3=A4?=
|
||||
<vaino.o.makela@gmail.com>
|
||||
Date: Mon, 5 Jan 2026 11:27:05 -0800
|
||||
Subject: Move Wayland pointer lock overrides to common code
|
||||
|
||||
Since the Wayland-specific pointer lock implementation overrides were
|
||||
placed in Chrome-specific code, they could not be used by other projects
|
||||
depending on Chromium source like Electron, making pointer lock not work
|
||||
on Wayland for them without special care. Moving the function
|
||||
implementations to the more generic DesktopWindowTreeHostLinux class
|
||||
allows Electron to benefit from this code without having to override the
|
||||
functions itself.
|
||||
|
||||
Change-Id: Ideb7dca9fd3dfb491df8f68296ba2d21069901cd
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7362747
|
||||
Reviewed-by: Thomas Anderson <thomasanderson@chromium.org>
|
||||
Reviewed-by: Kramer Ge <fangzhoug@chromium.org>
|
||||
Commit-Queue: Kramer Ge <fangzhoug@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1564501}
|
||||
|
||||
diff --git a/AUTHORS b/AUTHORS
|
||||
index 2384448120f5e5ac6b0315625e897d961bfc19b8..7eb8f26120a23539b0780eb3f7e1d6a7ac52b102 100644
|
||||
--- a/AUTHORS
|
||||
+++ b/AUTHORS
|
||||
@@ -1604,6 +1604,7 @@ Vitaliy Kharin <kvserr@gmail.com>
|
||||
Vivek Galatage <vivek.vg@samsung.com>
|
||||
Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
Volker Sorge <volker.sorge@gmail.com>
|
||||
+Väinö Mäkelä <vaino.o.makela@gmail.com>
|
||||
Waihung Fu <fufranci@amazon.com>
|
||||
wafuwafu13 <mariobaske@i.softbank.jp>
|
||||
Wojciech Bielawski <wojciech.bielawski@gmail.com>
|
||||
diff --git a/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_linux.cc b/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_linux.cc
|
||||
index 87d1f5c0f8f9e286a58e809ae9cfc2b84dd97ed2..e2afae41f0b2fce9eb0428119b66ff09f4811932 100644
|
||||
--- a/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_linux.cc
|
||||
+++ b/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_linux.cc
|
||||
@@ -126,35 +126,6 @@ void BrowserDesktopWindowTreeHostLinux::FrameTypeChanged() {
|
||||
UpdateFrameHints();
|
||||
}
|
||||
|
||||
-bool BrowserDesktopWindowTreeHostLinux::SupportsMouseLock() {
|
||||
- auto* wayland_extension = ui::GetWaylandToplevelExtension(*platform_window());
|
||||
- if (!wayland_extension) {
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- return wayland_extension->SupportsPointerLock();
|
||||
-}
|
||||
-
|
||||
-void BrowserDesktopWindowTreeHostLinux::LockMouse(aura::Window* window) {
|
||||
- DesktopWindowTreeHostLinux::LockMouse(window);
|
||||
-
|
||||
- if (SupportsMouseLock()) {
|
||||
- auto* wayland_extension =
|
||||
- ui::GetWaylandToplevelExtension(*platform_window());
|
||||
- wayland_extension->LockPointer(true /*enabled*/);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-void BrowserDesktopWindowTreeHostLinux::UnlockMouse(aura::Window* window) {
|
||||
- DesktopWindowTreeHostLinux::UnlockMouse(window);
|
||||
-
|
||||
- if (SupportsMouseLock()) {
|
||||
- auto* wayland_extension =
|
||||
- ui::GetWaylandToplevelExtension(*platform_window());
|
||||
- wayland_extension->LockPointer(false /*enabled*/);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
void BrowserDesktopWindowTreeHostLinux::TabDraggingKindChanged(
|
||||
TabDragKind tab_drag_kind) {
|
||||
CHECK(browser_widget_);
|
||||
diff --git a/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_linux.h b/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_linux.h
|
||||
index 01ef9a93657f9401191adb4b8bd17528da790127..12ca597be51480e45acf4490cf6e533c23c30556 100644
|
||||
--- a/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_linux.h
|
||||
+++ b/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_linux.h
|
||||
@@ -80,9 +80,6 @@ class BrowserDesktopWindowTreeHostLinux
|
||||
void CloseNow() override;
|
||||
void Show(ui::mojom::WindowShowState show_state,
|
||||
const gfx::Rect& restore_bounds) override;
|
||||
- bool SupportsMouseLock() override;
|
||||
- void LockMouse(aura::Window* window) override;
|
||||
- void UnlockMouse(aura::Window* window) override;
|
||||
void ClientDestroyedWidget() override;
|
||||
|
||||
// ui::X11ExtensionDelegate:
|
||||
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc
|
||||
index dfc327588c74d43893820a97056780ece2b22de5..1c5c18a8fb57376f53f8659c99384b4919b10db8 100644
|
||||
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc
|
||||
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc
|
||||
@@ -348,6 +348,35 @@ DesktopWindowTreeHostLinux::GetKeyboardLayoutMap() {
|
||||
return WindowTreeHostPlatform::GetKeyboardLayoutMap();
|
||||
}
|
||||
|
||||
+bool DesktopWindowTreeHostLinux::SupportsMouseLock() {
|
||||
+ auto* wayland_extension = ui::GetWaylandToplevelExtension(*platform_window());
|
||||
+ if (!wayland_extension) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return wayland_extension->SupportsPointerLock();
|
||||
+}
|
||||
+
|
||||
+void DesktopWindowTreeHostLinux::LockMouse(aura::Window* window) {
|
||||
+ DesktopWindowTreeHostPlatform::LockMouse(window);
|
||||
+
|
||||
+ if (SupportsMouseLock()) {
|
||||
+ auto* wayland_extension =
|
||||
+ ui::GetWaylandToplevelExtension(*platform_window());
|
||||
+ wayland_extension->LockPointer(true /*enabled*/);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void DesktopWindowTreeHostLinux::UnlockMouse(aura::Window* window) {
|
||||
+ DesktopWindowTreeHostPlatform::UnlockMouse(window);
|
||||
+
|
||||
+ if (SupportsMouseLock()) {
|
||||
+ auto* wayland_extension =
|
||||
+ ui::GetWaylandToplevelExtension(*platform_window());
|
||||
+ wayland_extension->LockPointer(false /*enabled*/);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
void DesktopWindowTreeHostLinux::OnCompleteSwapWithNewSize(
|
||||
const gfx::Size& size) {
|
||||
if (GetX11Extension()) {
|
||||
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h b/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h
|
||||
index 5c57268b37e2acdb30b09dd525a0eefc11f39112..c773bbe351260d958de222cd4e7942d757a53c25 100644
|
||||
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h
|
||||
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h
|
||||
@@ -93,6 +93,11 @@ class VIEWS_EXPORT DesktopWindowTreeHostLinux
|
||||
// DesktopWindowTreeHostPlatform:
|
||||
base::flat_map<std::string, std::string> GetKeyboardLayoutMap() override;
|
||||
|
||||
+ // WindowTreeHost:
|
||||
+ bool SupportsMouseLock() override;
|
||||
+ void LockMouse(aura::Window* window) override;
|
||||
+ void UnlockMouse(aura::Window* window) override;
|
||||
+
|
||||
// Called back by compositor_observer_ if the latter is set.
|
||||
virtual void OnCompleteSwapWithNewSize(const gfx::Size& size);
|
||||
|
||||
@@ -10,10 +10,10 @@ on Windows. We should refactor our code so that this patch isn't
|
||||
necessary.
|
||||
|
||||
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
|
||||
index d326724f7c20983cfe9ec268444028eadd571f71..346eba0c5c5b8e6ffc61a2b00586158b78134c43 100644
|
||||
index 59c516ca84b3e4a5e354fae624a30ef897e2a078..16e5c2f07c0c3f1abbb12496a514f37901d6723a 100644
|
||||
--- a/testing/variations/fieldtrial_testing_config.json
|
||||
+++ b/testing/variations/fieldtrial_testing_config.json
|
||||
@@ -25873,6 +25873,21 @@
|
||||
@@ -25896,6 +25896,21 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
@@ -12,5 +12,6 @@
|
||||
{ "patch_dir": "src/electron/patches/ReactiveObjC", "repo": "src/third_party/squirrel.mac/vendor/ReactiveObjC" },
|
||||
{ "patch_dir": "src/electron/patches/webrtc", "repo": "src/third_party/webrtc" },
|
||||
{ "patch_dir": "src/electron/patches/reclient-configs", "repo": "src/third_party/engflow-reclient-configs" },
|
||||
{ "patch_dir": "src/electron/patches/sqlite", "repo": "src/third_party/sqlite/src" }
|
||||
{ "patch_dir": "src/electron/patches/sqlite", "repo": "src/third_party/sqlite/src" },
|
||||
{ "patch_dir": "src/electron/patches/skia", "repo": "src/third_party/skia" }
|
||||
]
|
||||
|
||||
@@ -28,7 +28,6 @@ fix_adjust_wpt_and_webidl_tests_for_enabled_float16array.patch
|
||||
refactor_attach_cppgc_heap_on_v8_isolate_creation.patch
|
||||
fix_cppgc_initializing_twice.patch
|
||||
fix_expose_readfilesync_override_for_modules.patch
|
||||
fix_array_out-of-bounds_read_in_boyer-moore_search.patch
|
||||
test_accomodate_v8_thenable_stack_trace_change_in_snapshot.patch
|
||||
chore_exclude_electron_node_folder_from_exit-time-destructors.patch
|
||||
api_remove_deprecated_getisolate.patch
|
||||
@@ -36,10 +35,9 @@ fix_redefined_macos_sdk_header_symbols.patch
|
||||
fix_allow_disabling_fetch_in_renderer_and_worker_processes.patch
|
||||
feat_disable_js_source_phase_imports_by_default.patch
|
||||
fix_avoid_external_memory_leak_on_invalid_tls_protocol_versions.patch
|
||||
lib_check_sharedarraybuffer_existence_in_fast-utf8-stream.patch
|
||||
api_delete_deprecated_fields_on_v8_isolate.patch
|
||||
api_promote_deprecation_of_v8_context_and_v8_object_api_methods.patch
|
||||
src_use_cp_utf8_for_wide_file_names_on_win32.patch
|
||||
fix_ensure_traverseparent_bails_on_resource_path_exit.patch
|
||||
reland_temporal_unflag_temporal.patch
|
||||
src_handle_der_decoding_errors_from_system_certificates.patch
|
||||
build_restore_macos_deployment_target_to_12_0.patch
|
||||
fix_generate_config_gypi_needs_to_generate_valid_json.patch
|
||||
|
||||
@@ -6,10 +6,10 @@ Subject: Delete deprecated fields on v8::Isolate
|
||||
https://chromium-review.googlesource.com/c/v8/v8/+/7081397
|
||||
|
||||
diff --git a/src/api/environment.cc b/src/api/environment.cc
|
||||
index ea3e9374c30be92ba5668e33773ffbb2aef55b30..44ba3c42c7a980eee19e1aadcbe7999eefeda989 100644
|
||||
index cfc9b3157d08d62f43e2e5bb01229fe663f3ca61..cce0e1cdc37aa324aa2c52ba134fc1a9a55b10ba 100644
|
||||
--- a/src/api/environment.cc
|
||||
+++ b/src/api/environment.cc
|
||||
@@ -231,8 +231,6 @@ void SetIsolateCreateParamsForNode(Isolate::CreateParams* params) {
|
||||
@@ -218,8 +218,6 @@ void SetIsolateCreateParamsForNode(Isolate::CreateParams* params) {
|
||||
// heap based on the actual physical memory.
|
||||
params->constraints.ConfigureDefaults(total_memory, 0);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user