mirror of
https://github.com/electron/electron.git
synced 2026-02-19 03:14:51 -05:00
Compare commits
39 Commits
try-remove
...
check-mnt
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0627ff8683 | ||
|
|
c82c34835f | ||
|
|
a0844e8c81 | ||
|
|
54c2370e28 | ||
|
|
b75c4bb983 | ||
|
|
f5465f4e47 | ||
|
|
b2726881bd | ||
|
|
fff4a4aa3a | ||
|
|
780d246533 | ||
|
|
e01a307302 | ||
|
|
ce03acb3ce | ||
|
|
621274190d | ||
|
|
200315b507 | ||
|
|
7985af17eb | ||
|
|
31d779ff2f | ||
|
|
d6c04a3787 | ||
|
|
2791474a01 | ||
|
|
f6e8a42c48 | ||
|
|
650ef9a51c | ||
|
|
a1c44a18e2 | ||
|
|
ec9c8476fe | ||
|
|
470a14d8d4 | ||
|
|
5bff0fe342 | ||
|
|
16aec702b4 | ||
|
|
ac040bf734 | ||
|
|
aceb432f45 | ||
|
|
d182794179 | ||
|
|
ab185c058f | ||
|
|
2324c4d8fd | ||
|
|
792037b338 | ||
|
|
0b44f433c8 | ||
|
|
5fa9dee68a | ||
|
|
75bad34131 | ||
|
|
0a064cece9 | ||
|
|
f6e8544ef6 | ||
|
|
029127a8b6 | ||
|
|
e71a56d11e | ||
|
|
65901f4c6a | ||
|
|
feb804cea8 |
@@ -53,7 +53,7 @@ jobs:
|
||||
- path-filtering/set-parameters:
|
||||
base-revision: main
|
||||
mapping: |
|
||||
^((?!docs/).)*$ run-build-mac true
|
||||
^((?!docs/).)*$ run-build-mac false
|
||||
^((?!docs/).)*$ run-build-linux true
|
||||
docs/.* run-docs-only true
|
||||
^((?!docs/).)*$ run-docs-only false
|
||||
@@ -65,6 +65,9 @@ jobs:
|
||||
curl -fLSs https://raw.githubusercontent.com/CircleCI-Public/circleci-cli/main/install.sh | DESTDIR=$CIRCLECI_BINARY bash
|
||||
node build.js
|
||||
name: Pack config.yml
|
||||
- run:
|
||||
name: Set params
|
||||
command: node .circleci/config/params.js
|
||||
- continuation/continue:
|
||||
configuration_path: .circleci/config-staging/built.yml
|
||||
parameters: /tmp/pipeline-parameters.json
|
||||
|
||||
@@ -35,6 +35,16 @@ parameters:
|
||||
default: all
|
||||
enum: ["all", "osx-x64", "osx-arm64", "mas-x64", "mas-arm64"]
|
||||
|
||||
medium-linux-executor:
|
||||
type: enum
|
||||
default: electronjs/aks-linux-medium
|
||||
enum: ["electronjs/aks-linux-medium", "medium"]
|
||||
|
||||
large-linux-executor:
|
||||
type: enum
|
||||
default: electronjs/aks-linux-large
|
||||
enum: ["electronjs/aks-linux-large", "2xlarge"]
|
||||
|
||||
# Executors
|
||||
executors:
|
||||
linux-docker:
|
||||
@@ -42,9 +52,9 @@ executors:
|
||||
size:
|
||||
description: "Docker executor size"
|
||||
type: enum
|
||||
# aks-linux-medium === 8 core (32 core host, shared with other builds)
|
||||
# aks-linux-large === 32 core
|
||||
enum: ["medium", "xlarge", "electronjs/aks-linux-medium", "electronjs/aks-linux-large"]
|
||||
# 2xlarge should not be used directly, use the pipeline param instead
|
||||
enum: ["medium", "electronjs/aks-linux-medium", "xlarge", "electronjs/aks-linux-large", "2xlarge"]
|
||||
docker:
|
||||
- image: ghcr.io/electron/build:e6bebd08a51a0d78ec23e5b3fd7e7c0846412328
|
||||
resource_class: << parameters.size >>
|
||||
@@ -895,14 +905,26 @@ step-touch-sync-done: &step-touch-sync-done
|
||||
step-maybe-restore-src-cache: &step-maybe-restore-src-cache
|
||||
restore_cache:
|
||||
keys:
|
||||
- v16-src-cache-{{ checksum "src/electron/.depshash" }}
|
||||
- v17-src-cache-{{ checksum "src/electron/.depshash" }}
|
||||
name: Restoring src cache
|
||||
step-maybe-restore-src-cache-marker: &step-maybe-restore-src-cache-marker
|
||||
restore_cache:
|
||||
keys:
|
||||
- v16-src-cache-marker-{{ checksum "src/electron/.depshash" }}
|
||||
- v17-src-cache-marker-{{ checksum "src/electron/.depshash" }}
|
||||
name: Restoring src cache marker
|
||||
|
||||
step-maybe-restore-src-cache-aks: &step-maybe-restore-src-cache-aks
|
||||
restore_cache_aks:
|
||||
step-name: Restoring src cache
|
||||
cache_key: v17-src-cache-$(shasum src/electron/.depshash | cut -f1 -d' ')
|
||||
cache_path: /var/portal
|
||||
|
||||
step-maybe-restore-src-cache-marker-aks: &step-maybe-restore-src-cache-marker-aks
|
||||
restore_cache_aks:
|
||||
step-name: Restoring src cache marker
|
||||
cache_key: v17-src-cache-marker-$(shasum src/electron/.depshash | cut -f1 -d' ')
|
||||
cache_path: "."
|
||||
|
||||
# Restore exact or closest git cache based on the hash of DEPS and .circle-sync-done
|
||||
# If the src cache was restored above then this will match an empty cache
|
||||
# If the src cache was not restored above then this will match a close git cache
|
||||
@@ -915,6 +937,12 @@ step-maybe-restore-git-cache: &step-maybe-restore-git-cache
|
||||
- v1-git-cache-{{ checksum "src/electron/.circle-sync-done" }}
|
||||
name: Conditionally restoring git cache
|
||||
|
||||
step-maybe-restore-git-cache-aks: &step-maybe-restore-git-cache-aks
|
||||
restore_cache_aks:
|
||||
step-name: Conditionally restoring git cache (aks)
|
||||
cache_key: v1-git-cache-$(shasum src/electron/.circle-sync-done | cut -f1 -d' ')-$(shasum src/electron/DEPS | cut -f1 -d' ') v1-git-cache-$(shasum src/electron/.circle-sync-done | cut -f1 -d' ')
|
||||
cache_path: git-cache
|
||||
|
||||
step-set-git-cache-path: &step-set-git-cache-path
|
||||
run:
|
||||
name: Set GIT_CACHE_PATH to make gclient to use the cache
|
||||
@@ -932,6 +960,12 @@ step-save-git-cache: &step-save-git-cache
|
||||
key: v1-git-cache-{{ checksum "src/electron/.circle-sync-done" }}-{{ checksum "src/electron/DEPS" }}
|
||||
name: Persisting git cache
|
||||
|
||||
step-save-git-cache-aks: &step-save-git-cache-aks
|
||||
save_cache_aks:
|
||||
step-name: Persisting git cache (AKS)
|
||||
cache_key: v1-git-cache-$(shasum src/electron/.circle-sync-done | cut -f1 -d' ')-$(shasum src/electron/DEPS | cut -f1 -d' ')
|
||||
cache_path: git-cache
|
||||
|
||||
step-run-electron-only-hooks: &step-run-electron-only-hooks
|
||||
run:
|
||||
name: Run Electron Only Hooks
|
||||
@@ -969,7 +1003,7 @@ step-save-src-cache: &step-save-src-cache
|
||||
save_cache:
|
||||
paths:
|
||||
- /var/portal
|
||||
key: v16-src-cache-{{ checksum "/var/portal/src/electron/.depshash" }}
|
||||
key: v17-src-cache-{{ checksum "/var/portal/src/electron/.depshash" }}
|
||||
name: Persisting src cache
|
||||
step-make-src-cache-marker: &step-make-src-cache-marker
|
||||
run:
|
||||
@@ -979,7 +1013,17 @@ step-save-src-cache-marker: &step-save-src-cache-marker
|
||||
save_cache:
|
||||
paths:
|
||||
- .src-cache-marker
|
||||
key: v16-src-cache-marker-{{ checksum "/var/portal/src/electron/.depshash" }}
|
||||
key: v17-src-cache-marker-{{ checksum "/var/portal/src/electron/.depshash" }}
|
||||
step-save-src-cache-aks: &step-save-src-cache-aks
|
||||
save_cache_aks:
|
||||
step-name: Persisting src cache (aks)
|
||||
cache_key: v17-src-cache-$(shasum /var/portal/src/electron/.depshash | cut -f1 -d' ')
|
||||
cache_path: /var/portal
|
||||
step-save-src-cache-marker-aks: &step-save-src-cache-marker-aks
|
||||
save_cache_aks:
|
||||
step-name: Persisting src cache marker (aks)
|
||||
cache_key: v17-src-cache-marker-$(shasum /var/portal/src/electron/.depshash | cut -f1 -d' ')
|
||||
cache_path: .src-cache-marker
|
||||
|
||||
step-maybe-early-exit-no-doc-change: &step-maybe-early-exit-no-doc-change
|
||||
run:
|
||||
@@ -1025,6 +1069,77 @@ steps-electron-ts-compile-for-doc-change: &steps-electron-ts-compile-for-doc-cha
|
||||
|
||||
# Command Aliases
|
||||
commands:
|
||||
aks-specific-step:
|
||||
parameters:
|
||||
circle:
|
||||
type: steps
|
||||
aks:
|
||||
type: steps
|
||||
steps:
|
||||
- when:
|
||||
condition:
|
||||
equal: [<< pipeline.parameters.large-linux-executor >>, xlarge]
|
||||
steps: << parameters.circle >>
|
||||
- when:
|
||||
condition:
|
||||
equal: [<< pipeline.parameters.large-linux-executor >>, electronjs/aks-linux-large]
|
||||
steps: << parameters.aks >>
|
||||
save_cache_aks:
|
||||
parameters:
|
||||
step-name:
|
||||
type: string
|
||||
cache_key:
|
||||
type: string
|
||||
cache_path:
|
||||
type: string
|
||||
steps:
|
||||
- run:
|
||||
name: << parameters.step-name >>
|
||||
command: |
|
||||
cache_key="<< parameters.cache_key >>"
|
||||
final_cache_path=/mnt/cross-instance-cache/${cache_key}.tar
|
||||
echo "Using cache key: $cache_key"
|
||||
echo "Checking path: $final_cache_path"
|
||||
if [ ! -f "$final_cache_path" ]; then
|
||||
echo "Cache key not founding, storing tarball"
|
||||
tmp_container=/mnt/cross-instance-cache/tmp/$CIRCLE_WORKFLOW_JOB_ID
|
||||
tmp_cache_path=$tmp_container/${cache_key}.tar
|
||||
mkdir -p $tmp_container
|
||||
if [ -f "<< parameters.cache_path >>" ]; then
|
||||
tar -cf $tmp_cache_path -C $(dirname << parameters.cache_path >>) ./$(basename << parameters.cache_path >>)
|
||||
else
|
||||
tar -cf $tmp_cache_path -C << parameters.cache_path >>/ ./
|
||||
fi
|
||||
mv -vn $tmp_cache_path $final_cache_path
|
||||
rm -rf $tmp_container
|
||||
else
|
||||
echo "Cache key already exists, skipping.."
|
||||
fi
|
||||
restore_cache_aks:
|
||||
parameters:
|
||||
step-name:
|
||||
type: string
|
||||
cache_key:
|
||||
type: string
|
||||
cache_path:
|
||||
type: string
|
||||
steps:
|
||||
- run:
|
||||
name: << parameters.step-name >>
|
||||
command: |
|
||||
df -h
|
||||
for cache_key in << parameters.cache_key >>; do
|
||||
cache_path=/mnt/cross-instance-cache/${cache_key}.tar
|
||||
echo "Using cache key: $cache_key"
|
||||
echo "Checking path: $cache_path"
|
||||
if [ ! -f "$cache_path" ]; then
|
||||
echo "Cache key not found, nothing to restore..."
|
||||
else
|
||||
echo "Cache key found, restoring to path..."
|
||||
tar -xf /mnt/cross-instance-cache/${cache_key}.tar -C << parameters.cache_path >>/
|
||||
exit 0
|
||||
fi
|
||||
done
|
||||
maybe-restore-portaled-src-cache:
|
||||
parameters:
|
||||
halt-if-successful:
|
||||
@@ -1039,14 +1154,22 @@ commands:
|
||||
- when:
|
||||
condition: << parameters.halt-if-successful >>
|
||||
steps:
|
||||
- *step-maybe-restore-src-cache-marker
|
||||
- aks-specific-step:
|
||||
circle:
|
||||
- *step-maybe-restore-src-cache-marker
|
||||
aks:
|
||||
- *step-maybe-restore-src-cache-marker-aks
|
||||
- run:
|
||||
name: Halt the job early if the src cache exists
|
||||
command: |
|
||||
if [ -f ".src-cache-marker" ]; then
|
||||
circleci-agent step halt
|
||||
fi
|
||||
- *step-maybe-restore-src-cache
|
||||
- aks-specific-step:
|
||||
circle:
|
||||
- *step-maybe-restore-src-cache
|
||||
aks:
|
||||
- *step-maybe-restore-src-cache-aks
|
||||
- run:
|
||||
name: Fix the src cache restore point on macOS
|
||||
command: |
|
||||
@@ -1287,6 +1410,7 @@ commands:
|
||||
type: steps
|
||||
default: []
|
||||
steps:
|
||||
- run: ls -al /mnt
|
||||
- when:
|
||||
condition: << parameters.attach >>
|
||||
steps:
|
||||
@@ -1319,8 +1443,13 @@ commands:
|
||||
steps:
|
||||
- maybe-restore-portaled-src-cache:
|
||||
halt-if-successful: << parameters.checkout-to-create-src-cache >>
|
||||
- *step-maybe-restore-git-cache
|
||||
- aks-specific-step:
|
||||
circle:
|
||||
- *step-maybe-restore-git-cache
|
||||
aks:
|
||||
- *step-maybe-restore-git-cache-aks
|
||||
- *step-set-git-cache-path
|
||||
- *step-fix-known-hosts-linux
|
||||
# This sync call only runs if .circle-sync-done is an EMPTY file
|
||||
- *step-gclient-sync
|
||||
- store_artifacts:
|
||||
@@ -1336,7 +1465,11 @@ commands:
|
||||
- when:
|
||||
condition: << parameters.save-git-cache >>
|
||||
steps:
|
||||
- *step-save-git-cache
|
||||
- aks-specific-step:
|
||||
circle:
|
||||
- *step-save-git-cache
|
||||
aks:
|
||||
- *step-save-git-cache-aks
|
||||
# Mark sync as done _after_ saving the git cache so that it is uploaded
|
||||
# only when the src cache was not present
|
||||
# Their are theoretically two cases for this cache key
|
||||
@@ -1386,9 +1519,17 @@ commands:
|
||||
sudo mkdir -p /var/portal
|
||||
sudo chown -R $(id -u):$(id -g) /var/portal
|
||||
mv ./src /var/portal
|
||||
- *step-save-src-cache
|
||||
- aks-specific-step:
|
||||
circle:
|
||||
- *step-save-src-cache
|
||||
aks:
|
||||
- *step-save-src-cache-aks
|
||||
- *step-make-src-cache-marker
|
||||
- *step-save-src-cache-marker
|
||||
- aks-specific-step:
|
||||
circle:
|
||||
- *step-save-src-cache-marker
|
||||
aks:
|
||||
- *step-save-src-cache-marker-aks
|
||||
|
||||
- when:
|
||||
condition: << parameters.build >>
|
||||
@@ -1628,7 +1769,7 @@ jobs:
|
||||
linux-make-src-cache:
|
||||
executor:
|
||||
name: linux-docker
|
||||
size: xlarge
|
||||
size: << pipeline.parameters.large-linux-executor >>
|
||||
environment:
|
||||
<<: *env-linux-2xlarge
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
|
||||
@@ -1703,7 +1844,7 @@ jobs:
|
||||
linux-x64-testing:
|
||||
executor:
|
||||
name: linux-docker
|
||||
size: electronjs/aks-linux-large
|
||||
size: << pipeline.parameters.large-linux-executor >>
|
||||
environment:
|
||||
<<: *env-global
|
||||
<<: *env-testing-build
|
||||
@@ -1720,7 +1861,7 @@ jobs:
|
||||
linux-x64-testing-asan:
|
||||
executor:
|
||||
name: linux-docker
|
||||
size: electronjs/aks-linux-large
|
||||
size: << pipeline.parameters.large-linux-executor >>
|
||||
environment:
|
||||
<<: *env-global
|
||||
<<: *env-testing-build
|
||||
@@ -1739,7 +1880,7 @@ jobs:
|
||||
linux-x64-testing-gn-check:
|
||||
executor:
|
||||
name: linux-docker
|
||||
size: medium
|
||||
size: << pipeline.parameters.medium-linux-executor >>
|
||||
environment:
|
||||
<<: *env-linux-medium
|
||||
<<: *env-testing-build
|
||||
@@ -1749,7 +1890,7 @@ jobs:
|
||||
linux-x64-publish:
|
||||
executor:
|
||||
name: linux-docker
|
||||
size: electronjs/aks-linux-large
|
||||
size: << pipeline.parameters.large-linux-executor >>
|
||||
environment:
|
||||
<<: *env-linux-2xlarge-release
|
||||
<<: *env-release-build
|
||||
@@ -1772,7 +1913,7 @@ jobs:
|
||||
linux-arm-testing:
|
||||
executor:
|
||||
name: linux-docker
|
||||
size: electronjs/aks-linux-large
|
||||
size: << pipeline.parameters.large-linux-executor >>
|
||||
environment:
|
||||
<<: *env-global
|
||||
<<: *env-arm
|
||||
@@ -1792,7 +1933,7 @@ jobs:
|
||||
linux-arm-publish:
|
||||
executor:
|
||||
name: linux-docker
|
||||
size: electronjs/aks-linux-large
|
||||
size: << pipeline.parameters.large-linux-executor >>
|
||||
environment:
|
||||
<<: *env-linux-2xlarge-release
|
||||
<<: *env-arm
|
||||
@@ -1817,7 +1958,7 @@ jobs:
|
||||
linux-arm64-testing:
|
||||
executor:
|
||||
name: linux-docker
|
||||
size: electronjs/aks-linux-large
|
||||
size: << pipeline.parameters.large-linux-executor >>
|
||||
environment:
|
||||
<<: *env-global
|
||||
<<: *env-arm64
|
||||
@@ -1837,7 +1978,7 @@ jobs:
|
||||
linux-arm64-testing-gn-check:
|
||||
executor:
|
||||
name: linux-docker
|
||||
size: medium
|
||||
size: << pipeline.parameters.medium-linux-executor >>
|
||||
environment:
|
||||
<<: *env-linux-medium
|
||||
<<: *env-arm64
|
||||
@@ -1848,7 +1989,7 @@ jobs:
|
||||
linux-arm64-publish:
|
||||
executor:
|
||||
name: linux-docker
|
||||
size: electronjs/aks-linux-large
|
||||
size: << pipeline.parameters.large-linux-executor >>
|
||||
environment:
|
||||
<<: *env-linux-2xlarge-release
|
||||
<<: *env-arm64
|
||||
|
||||
12
.circleci/config/params.js
Normal file
12
.circleci/config/params.js
Normal file
@@ -0,0 +1,12 @@
|
||||
const fs = require('fs');
|
||||
|
||||
const PARAMS_PATH = '/tmp/pipeline-parameters.json';
|
||||
|
||||
const content = JSON.parse(fs.readFileSync(PARAMS_PATH, 'utf-8'));
|
||||
|
||||
// Choose resource class for linux hosts
|
||||
const currentBranch = process.env.CIRCLE_BRANCH || '';
|
||||
content['large-linux-executor'] = /^pull\/[0-9-]+$/.test(currentBranch) ? '2xlarge' : 'electronjs/aks-linux-large';
|
||||
content['medium-linux-executor'] = /^pull\/[0-9-]+$/.test(currentBranch) ? 'medium' : 'electronjs/aks-linux-medium';
|
||||
|
||||
fs.writeFileSync(PARAMS_PATH, JSON.stringify(content));
|
||||
2
.github/workflows/issue-commented.yml
vendored
2
.github/workflows/issue-commented.yml
vendored
@@ -10,7 +10,7 @@ permissions: {}
|
||||
jobs:
|
||||
issue-commented:
|
||||
name: Remove blocked/need-repro on comment
|
||||
if: ${{ contains(github.event.issue.labels.*.name, 'blocked/need-repro') && !contains(fromJSON('["MEMBER", "OWNER"]'), github.event.comment.author_association) }}
|
||||
if: ${{ contains(github.event.issue.labels.*.name, 'blocked/need-repro') && !contains(fromJSON('["MEMBER", "OWNER"]'), github.event.comment.author_association) && github.event.comment.user.type != "Bot" }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Generate GitHub App token
|
||||
|
||||
2
.github/workflows/issue-labeled.yml
vendored
2
.github/workflows/issue-labeled.yml
vendored
@@ -42,7 +42,7 @@ jobs:
|
||||
GH_REPO: electron/electron
|
||||
run: |
|
||||
set -eo pipefail
|
||||
COMMENT_COUNT=$(gh issue view ${{ github.event.issue.number }} --comments --json comments | jq '[ .comments[] | select(.author.login == "github-actions" or .authorAssociation == "OWNER" or .authorAssociation == "MEMBER") | select(.body | startswith("<!-- blocked/need-repro -->")) ] | length')
|
||||
COMMENT_COUNT=$(gh issue view ${{ github.event.issue.number }} --comments --json comments | jq '[ .comments[] | select(.author.login == "electron-issue-triage" or .authorAssociation == "OWNER" or .authorAssociation == "MEMBER") | select(.body | startswith("<!-- blocked/need-repro -->")) ] | length')
|
||||
if [[ $COMMENT_COUNT -eq 0 ]]; then
|
||||
echo "SHOULD_COMMENT=1" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
2
.github/workflows/issue-unlabeled.yml
vendored
2
.github/workflows/issue-unlabeled.yml
vendored
@@ -10,7 +10,7 @@ permissions:
|
||||
jobs:
|
||||
issue-unlabeled-blocked:
|
||||
name: All blocked/* labels removed
|
||||
if: startsWith(github.event.label.name, 'blocked/')
|
||||
if: startsWith(github.event.label.name, 'blocked/') && github.event.issue.state == 'open'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check for any blocked labels
|
||||
|
||||
2
DEPS
2
DEPS
@@ -2,7 +2,7 @@ gclient_gn_args_from = 'src'
|
||||
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'118.0.5991.0',
|
||||
'118.0.5993.0',
|
||||
'node_version':
|
||||
'v18.17.1',
|
||||
'nan_version':
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
version: 1.0.{build}
|
||||
build_cloud: electronhq-16-core
|
||||
image: e-118.0.5949.0
|
||||
image: e-118.0.5993.0
|
||||
environment:
|
||||
GIT_CACHE_PATH: C:\Users\appveyor\libcc_cache
|
||||
ELECTRON_OUT_DIR: Default
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
version: 1.0.{build}
|
||||
build_cloud: electronhq-16-core
|
||||
image: e-118.0.5949.0
|
||||
image: e-118.0.5993.0
|
||||
environment:
|
||||
GIT_CACHE_PATH: C:\Users\appveyor\libcc_cache
|
||||
ELECTRON_OUT_DIR: Default
|
||||
|
||||
@@ -1647,7 +1647,7 @@ removed in future Electron releases.
|
||||
* `options` Object
|
||||
* `color` String (optional) _Windows_ - The CSS color of the Window Controls Overlay when enabled.
|
||||
* `symbolColor` String (optional) _Windows_ - The CSS color of the symbols on the Window Controls Overlay when enabled.
|
||||
* `height` Integer (optional) _Windows_ - The height of the title bar and Window Controls Overlay in pixels.
|
||||
* `height` Integer (optional) _macOS_ _Windows_ - The height of the title bar and Window Controls Overlay in pixels.
|
||||
|
||||
On a Window with Window Controls Overlay already enabled, this method updates
|
||||
the style of the title bar overlay.
|
||||
|
||||
@@ -273,7 +273,6 @@ This API is only available on macOS 10.14 Mojave or newer.
|
||||
* `window-frame` - Window frame.
|
||||
* `window-text` - Text in windows.
|
||||
* On **macOS**
|
||||
* `alternate-selected-control-text` - The text on a selected surface in a list or table. _Deprecated_
|
||||
* `control-background` - The background of a large interface element, such as a browser or table.
|
||||
* `control` - The surface of a control.
|
||||
* `control-text` -The text of a control that isn’t disabled.
|
||||
@@ -339,21 +338,6 @@ Returns `string` - Can be `dark`, `light` or `unknown`.
|
||||
Gets the macOS appearance setting that is currently applied to your application,
|
||||
maps to [NSApplication.effectiveAppearance](https://developer.apple.com/documentation/appkit/nsapplication/2967171-effectiveappearance?language=objc)
|
||||
|
||||
### `systemPreferences.getAppLevelAppearance()` _macOS_ _Deprecated_
|
||||
|
||||
Returns `string` | `null` - Can be `dark`, `light` or `unknown`.
|
||||
|
||||
Gets the macOS appearance setting that you have declared you want for
|
||||
your application, maps to [NSApplication.appearance](https://developer.apple.com/documentation/appkit/nsapplication/2967170-appearance?language=objc).
|
||||
You can use the `setAppLevelAppearance` API to set this value.
|
||||
|
||||
### `systemPreferences.setAppLevelAppearance(appearance)` _macOS_ _Deprecated_
|
||||
|
||||
* `appearance` string | null - Can be `dark` or `light`
|
||||
|
||||
Sets the appearance setting for your application, this should override the
|
||||
system default and override the value of `getEffectiveAppearance`.
|
||||
|
||||
### `systemPreferences.canPromptTouchID()` _macOS_
|
||||
|
||||
Returns `boolean` - whether or not this device has the ability to use Touch ID.
|
||||
@@ -417,16 +401,6 @@ Returns an object with system animation settings.
|
||||
|
||||
## Properties
|
||||
|
||||
### `systemPreferences.appLevelAppearance` _macOS_ _Deprecated_
|
||||
|
||||
A `string` property that can be `dark`, `light` or `unknown`. It determines the macOS appearance setting for
|
||||
your application. This maps to values in: [NSApplication.appearance](https://developer.apple.com/documentation/appkit/nsapplication/2967170-appearance?language=objc). Setting this will override the
|
||||
system default as well as the value of `getEffectiveAppearance`.
|
||||
|
||||
Possible values that can be set are `dark` and `light`, and possible return values are `dark`, `light`, and `unknown`.
|
||||
|
||||
This property is only available on macOS 10.14 Mojave or newer.
|
||||
|
||||
### `systemPreferences.effectiveAppearance` _macOS_ _Readonly_
|
||||
|
||||
A `string` property that can be `dark`, `light` or `unknown`.
|
||||
|
||||
@@ -107,6 +107,41 @@ w.webContents.getPrintersAsync().then((printers) => {
|
||||
})
|
||||
```
|
||||
|
||||
### Removed: `systemPreferences.{get,set}AppLevelAppearance` and `systemPreferences.appLevelAppearance`
|
||||
|
||||
The `systemPreferences.getAppLevelAppearance` and `systemPreferences.setAppLevelAppearance`
|
||||
methods have been removed, as well as the `systemPreferences.appLevelAppearance` property.
|
||||
Use the `nativeTheme` module instead.
|
||||
|
||||
```js
|
||||
// Removed
|
||||
systemPreferences.getAppLevelAppearance()
|
||||
// Replace with
|
||||
nativeTheme.shouldUseDarkColors
|
||||
|
||||
// Removed
|
||||
systemPreferences.appLevelAppearance
|
||||
// Replace with
|
||||
nativeTheme.shouldUseDarkColors
|
||||
|
||||
// Removed
|
||||
systemPreferences.setAppLevelAppearance('dark')
|
||||
// Replace with
|
||||
nativeTheme.themeSource = 'dark'
|
||||
```
|
||||
|
||||
### Removed: `alternate-selected-control-text` value for `systemPreferences.getColor`
|
||||
|
||||
The `alternate-selected-control-text` value for `systemPreferences.getColor`
|
||||
has been removed. Use `selected-content-background` instead.
|
||||
|
||||
```js
|
||||
// Removed
|
||||
systemPreferences.getColor('alternate-selected-control-text')
|
||||
// Replace with
|
||||
systemPreferences.getColor('selected-content-background')
|
||||
```
|
||||
|
||||
## Planned Breaking API Changes (26.0)
|
||||
|
||||
### Deprecated: `webContents.getPrinters`
|
||||
|
||||
@@ -5,7 +5,7 @@ import type * as Crypto from 'crypto';
|
||||
|
||||
const asar = process._linkedBinding('electron_common_asar');
|
||||
|
||||
const Module = require('module');
|
||||
const Module = require('module') as NodeJS.ModuleInternal;
|
||||
|
||||
const Promise: PromiseConstructor = global.Promise;
|
||||
|
||||
@@ -27,7 +27,7 @@ const cachedArchives = new Map<string, NodeJS.AsarArchive>();
|
||||
const getOrCreateArchive = (archivePath: string) => {
|
||||
const isCached = cachedArchives.has(archivePath);
|
||||
if (isCached) {
|
||||
return cachedArchives.get(archivePath);
|
||||
return cachedArchives.get(archivePath)!;
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -39,6 +39,8 @@ const getOrCreateArchive = (archivePath: string) => {
|
||||
}
|
||||
};
|
||||
|
||||
process._getOrCreateArchive = getOrCreateArchive;
|
||||
|
||||
const asarRe = /\.asar/i;
|
||||
|
||||
const { getValidatedPath } = __non_webpack_require__('internal/fs/utils');
|
||||
|
||||
@@ -33,7 +33,7 @@ const normalizeAccessKey = (text: string) => {
|
||||
// macOS does not have access keys so remove single ampersands
|
||||
// and replace double ampersands with a single ampersand
|
||||
if (process.platform === 'darwin') {
|
||||
return text.replace(/&(&?)/g, '$1');
|
||||
return text.replaceAll(/&(&?)/g, '$1');
|
||||
}
|
||||
|
||||
// Linux uses a single underscore as an access key prefix so escape
|
||||
@@ -41,7 +41,7 @@ const normalizeAccessKey = (text: string) => {
|
||||
// ampersands with a single ampersand, and replace a single ampersand with
|
||||
// a single underscore
|
||||
if (process.platform === 'linux') {
|
||||
return text.replace(/_/g, '__').replace(/&(.?)/g, (match, after) => {
|
||||
return text.replaceAll('_', '__').replaceAll(/&(.?)/g, (match, after) => {
|
||||
if (after === '&') return after;
|
||||
return `_${after}`;
|
||||
});
|
||||
|
||||
@@ -1,33 +1,5 @@
|
||||
import * as deprecate from '@electron/internal/common/deprecate';
|
||||
|
||||
const { systemPreferences } = process._linkedBinding('electron_browser_system_preferences');
|
||||
|
||||
if ('getAppLevelAppearance' in systemPreferences) {
|
||||
const nativeALAGetter = systemPreferences.getAppLevelAppearance;
|
||||
const nativeALASetter = systemPreferences.setAppLevelAppearance;
|
||||
const warnALA = deprecate.warnOnce('appLevelAppearance');
|
||||
const warnALAGetter = deprecate.warnOnce('getAppLevelAppearance function');
|
||||
const warnALASetter = deprecate.warnOnce('setAppLevelAppearance function');
|
||||
Object.defineProperty(systemPreferences, 'appLevelAppearance', {
|
||||
get: () => {
|
||||
warnALA();
|
||||
return nativeALAGetter.call(systemPreferences);
|
||||
},
|
||||
set: (appearance) => {
|
||||
warnALA();
|
||||
nativeALASetter.call(systemPreferences, appearance);
|
||||
}
|
||||
});
|
||||
systemPreferences.getAppLevelAppearance = () => {
|
||||
warnALAGetter();
|
||||
return nativeALAGetter.call(systemPreferences);
|
||||
};
|
||||
systemPreferences.setAppLevelAppearance = (appearance) => {
|
||||
warnALASetter();
|
||||
nativeALASetter.call(systemPreferences, appearance);
|
||||
};
|
||||
}
|
||||
|
||||
if ('getEffectiveAppearance' in systemPreferences) {
|
||||
const nativeEAGetter = systemPreferences.getEffectiveAppearance;
|
||||
Object.defineProperty(systemPreferences, 'effectiveAppearance', {
|
||||
|
||||
@@ -4,7 +4,7 @@ import * as path from 'path';
|
||||
|
||||
import type * as defaultMenuModule from '@electron/internal/browser/default-menu';
|
||||
|
||||
const Module = require('module');
|
||||
const Module = require('module') as NodeJS.ModuleInternal;
|
||||
|
||||
// We modified the original process.argv to let node.js load the init.js,
|
||||
// we need to restore it here.
|
||||
@@ -63,8 +63,8 @@ if (process.platform === 'win32') {
|
||||
|
||||
if (fs.existsSync(updateDotExe)) {
|
||||
const packageDir = path.dirname(path.resolve(updateDotExe));
|
||||
const packageName = path.basename(packageDir).replace(/\s/g, '');
|
||||
const exeName = path.basename(process.execPath).replace(/\.exe$/i, '').replace(/\s/g, '');
|
||||
const packageName = path.basename(packageDir).replaceAll(/\s/g, '');
|
||||
const exeName = path.basename(process.execPath).replace(/\.exe$/i, '').replaceAll(/\s/g, '');
|
||||
|
||||
app.setAppUserModelId(`com.squirrel.${packageName}.${exeName}`);
|
||||
}
|
||||
@@ -84,11 +84,20 @@ const v8Util = process._linkedBinding('electron_common_v8_util');
|
||||
let packagePath = null;
|
||||
let packageJson = null;
|
||||
const searchPaths: string[] = v8Util.getHiddenValue(global, 'appSearchPaths');
|
||||
const searchPathsOnlyLoadASAR: boolean = v8Util.getHiddenValue(global, 'appSearchPathsOnlyLoadASAR');
|
||||
// Borrow the _getOrCreateArchive asar helper
|
||||
const getOrCreateArchive = process._getOrCreateArchive;
|
||||
delete process._getOrCreateArchive;
|
||||
|
||||
if (process.resourcesPath) {
|
||||
for (packagePath of searchPaths) {
|
||||
try {
|
||||
packagePath = path.join(process.resourcesPath, packagePath);
|
||||
if (searchPathsOnlyLoadASAR) {
|
||||
if (!getOrCreateArchive?.(packagePath)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
packageJson = Module._load(path.join(packagePath, 'package.json'));
|
||||
break;
|
||||
} catch {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as path from 'path';
|
||||
|
||||
const Module = require('module');
|
||||
const Module = require('module') as NodeJS.ModuleInternal;
|
||||
|
||||
// We do not want to allow use of the VM module in the renderer process as
|
||||
// it conflicts with Blink's V8::Context internal logic.
|
||||
@@ -10,7 +10,7 @@ if (process.type === 'renderer') {
|
||||
if (request === 'vm') {
|
||||
console.warn('The vm module of Node.js is deprecated in the renderer process and will be removed.');
|
||||
}
|
||||
return _load.apply(this, arguments);
|
||||
return _load.apply(this, arguments as any);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ const originalResolveFilename = Module._resolveFilename;
|
||||
// renderer process regardless of the names, they're superficial for TypeScript
|
||||
// only.
|
||||
const electronModuleNames = new Set(['electron', 'electron/main', 'electron/renderer', 'electron/common']);
|
||||
Module._resolveFilename = function (request: string, parent: NodeModule, isMain: boolean, options?: { paths: Array<string>}) {
|
||||
Module._resolveFilename = function (request, parent, isMain, options) {
|
||||
if (electronModuleNames.has(request)) {
|
||||
return 'electron';
|
||||
} else {
|
||||
|
||||
@@ -5,7 +5,7 @@ import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
|
||||
import type * as ipcRendererInternalModule from '@electron/internal/renderer/ipc-renderer-internal';
|
||||
import type * as ipcRendererUtilsModule from '@electron/internal/renderer/ipc-renderer-internal-utils';
|
||||
|
||||
const Module = require('module');
|
||||
const Module = require('module') as NodeJS.ModuleInternal;
|
||||
|
||||
// Make sure globals like "process" and "global" are always available in preload
|
||||
// scripts even after they are deleted in "loaded" script.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ParentPort } from '@electron/internal/utility/parent-port';
|
||||
const Module = require('module');
|
||||
const Module = require('module') as NodeJS.ModuleInternal;
|
||||
const v8Util = process._linkedBinding('electron_common_v8_util');
|
||||
|
||||
const entryScript: string = v8Util.getHiddenValue(process, '_serviceStartupScript');
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as path from 'path';
|
||||
|
||||
const Module = require('module');
|
||||
const Module = require('module') as NodeJS.ModuleInternal;
|
||||
|
||||
// We modified the original process.argv to let node.js load the
|
||||
// init.js, we need to restore it here.
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"@electron/docs-parser": "^1.1.1",
|
||||
"@electron/fiddle-core": "^1.0.4",
|
||||
"@electron/github-app-auth": "^2.0.0",
|
||||
"@electron/lint-roller": "^1.8.0",
|
||||
"@electron/lint-roller": "^1.9.0",
|
||||
"@electron/typescript-definitions": "^8.14.5",
|
||||
"@octokit/rest": "^19.0.7",
|
||||
"@primer/octicons": "^10.0.0",
|
||||
|
||||
@@ -130,4 +130,6 @@ fix_harden_blink_scriptstate_maybefrom.patch
|
||||
chore_add_buildflag_guard_around_new_include.patch
|
||||
fix_use_delegated_generic_capturer_when_available.patch
|
||||
build_remove_ent_content_analysis_assert.patch
|
||||
fix_activate_background_material_on_windows.patch
|
||||
fix_move_autopipsettingshelper_behind_branding_buildflag.patch
|
||||
revert_remove_the_allowaggressivethrottlingwithwebsocket_feature.patch
|
||||
|
||||
@@ -33,7 +33,7 @@ index 41ce32113ec2679b76d5a4fd69a7109c832ac7a1..1cd35794bf78f3d92b42634d9494c85a
|
||||
"//base",
|
||||
"//build:branding_buildflags",
|
||||
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
|
||||
index 5cce9134fabf566ec968d5738242b3dc13f2f54c..0e8ca7b1762571f57372a937630004252f396ae7 100644
|
||||
index 1a9bff4a3efb7fd802db7ae9696027ee318eb7eb..85d2bc48117c7e41cfa49ea204d2c46f79a1c117 100644
|
||||
--- a/chrome/browser/BUILD.gn
|
||||
+++ b/chrome/browser/BUILD.gn
|
||||
@@ -4723,7 +4723,7 @@ static_library("browser") {
|
||||
@@ -46,10 +46,10 @@ index 5cce9134fabf566ec968d5738242b3dc13f2f54c..0e8ca7b1762571f57372a93763000425
|
||||
sources += [ "certificate_viewer_stub.cc" ]
|
||||
}
|
||||
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
|
||||
index 513932b71a19d8f0a8196faf2ef14c2a7a996229..0b16b410606d2dcb8f8013755f079a209c8ba3a4 100644
|
||||
index 6a2501dde4552c2b0d96dd54fc1b94ba1e610b0c..8d3cb67ae6d4fe65cfbb907309af734906b49949 100644
|
||||
--- a/chrome/test/BUILD.gn
|
||||
+++ b/chrome/test/BUILD.gn
|
||||
@@ -6833,7 +6833,6 @@ test("unit_tests") {
|
||||
@@ -6838,7 +6838,6 @@ test("unit_tests") {
|
||||
|
||||
deps += [
|
||||
"//chrome:other_version",
|
||||
@@ -57,7 +57,7 @@ index 513932b71a19d8f0a8196faf2ef14c2a7a996229..0b16b410606d2dcb8f8013755f079a20
|
||||
"//chrome//services/util_win:unit_tests",
|
||||
"//chrome/app:chrome_dll_resources",
|
||||
"//chrome/app:win_unit_tests",
|
||||
@@ -6859,6 +6858,10 @@ test("unit_tests") {
|
||||
@@ -6864,6 +6863,10 @@ test("unit_tests") {
|
||||
"//ui/resources",
|
||||
]
|
||||
|
||||
@@ -68,7 +68,7 @@ index 513932b71a19d8f0a8196faf2ef14c2a7a996229..0b16b410606d2dcb8f8013755f079a20
|
||||
ldflags = [
|
||||
"/DELAYLOAD:api-ms-win-core-winrt-error-l1-1-0.dll",
|
||||
"/DELAYLOAD:api-ms-win-core-winrt-l1-1-0.dll",
|
||||
@@ -7826,7 +7829,6 @@ test("unit_tests") {
|
||||
@@ -7831,7 +7834,6 @@ test("unit_tests") {
|
||||
}
|
||||
|
||||
deps += [
|
||||
@@ -76,7 +76,7 @@ index 513932b71a19d8f0a8196faf2ef14c2a7a996229..0b16b410606d2dcb8f8013755f079a20
|
||||
"//chrome/browser/apps:icon_standardizer",
|
||||
"//chrome/browser/apps/app_service",
|
||||
"//chrome/browser/apps/app_service:app_registry_cache_waiter",
|
||||
@@ -7913,6 +7915,10 @@ test("unit_tests") {
|
||||
@@ -7918,6 +7920,10 @@ test("unit_tests") {
|
||||
"//ui/webui/resources/js/browser_command:mojo_bindings",
|
||||
]
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ index 729753a72edd761ec831f79828742a26f9dd2417..45858456c9c8c82870c41b0edd1359d1
|
||||
|
||||
if (is_win) {
|
||||
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
|
||||
index e0d55a859061f029e5298599bf2d9345674ecb34..74f977ca68b566d4c2859d71fabbe112555d1d91 100644
|
||||
index 718ad3e088f6730bb00f1e3674effae6c429b9b6..77af941f2dd2d3074f5596cee24be47dc8175434 100644
|
||||
--- a/content/browser/BUILD.gn
|
||||
+++ b/content/browser/BUILD.gn
|
||||
@@ -56,6 +56,7 @@ source_set("browser") {
|
||||
@@ -86,10 +86,10 @@ index e0d55a859061f029e5298599bf2d9345674ecb34..74f977ca68b566d4c2859d71fabbe112
|
||||
libs = []
|
||||
frameworks = []
|
||||
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn
|
||||
index dce27cfa39b52e39a95cee658584ed80ab1953ef..366edd2e86edcdbb30ae4c0fa952b5d9aab38f8a 100644
|
||||
index 9c9f6d58a8e5c1ed14eb60c722667d1a24d2c6fa..34979dbbd84da86db079b423967ab8b775b47c52 100644
|
||||
--- a/content/common/BUILD.gn
|
||||
+++ b/content/common/BUILD.gn
|
||||
@@ -174,6 +174,7 @@ source_set("common") {
|
||||
@@ -176,6 +176,7 @@ source_set("common") {
|
||||
"//content:content_implementation",
|
||||
"//build/config:precompiled_headers",
|
||||
]
|
||||
@@ -110,7 +110,7 @@ index b16be8f9992b23ce93d174531f2debd7f18bb436..119038743dc222907cb74c2c3ea34d23
|
||||
|
||||
public_deps = [
|
||||
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
|
||||
index 8fbd09e0305b22114c2cc2534a43622cf660bb23..39951971e29c374aa705eab8c921f73e56d428c8 100644
|
||||
index 581571b6bb1a655319b247d7cc85bb2a4dd7db1c..09779610326da207062a59ba572b2d7c13efd26f 100644
|
||||
--- a/content/test/BUILD.gn
|
||||
+++ b/content/test/BUILD.gn
|
||||
@@ -480,6 +480,7 @@ static_library("test_support") {
|
||||
|
||||
@@ -9,10 +9,10 @@ potentially prevent a window from being created.
|
||||
TODO(loc): this patch is currently broken.
|
||||
|
||||
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
index 6646263a52601e5283d2a2bb924945acacfff702..e2303fbb80ccc7d76d6a949678608c6a55ea411d 100644
|
||||
index 50d873e238b04eb6d461dc929d98dfe171cc491c..586aa87098bd3db10440fe865a02c05e7b3be14f 100644
|
||||
--- a/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
@@ -8208,6 +8208,7 @@ void RenderFrameHostImpl::CreateNewWindow(
|
||||
@@ -8206,6 +8206,7 @@ void RenderFrameHostImpl::CreateNewWindow(
|
||||
last_committed_origin_, params->window_container_type,
|
||||
params->target_url, params->referrer.To<Referrer>(),
|
||||
params->frame_name, params->disposition, *params->features,
|
||||
@@ -66,10 +66,10 @@ index 3ddc93e18d353d5af31e28f8f8e682ea813db21c..2f1df452ce3617cf845409d01d804932
|
||||
|
||||
// Operation result when the renderer asks the browser to create a new window.
|
||||
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc
|
||||
index 549fa60921444c60b3343fc381fb283ca73f7b6a..c76eb798967426772e8e673f93f223581d2fd00f 100644
|
||||
index a0d56a9a24f22b1fd7a7e7a7ac82adf23a1e27ca..b006271eb9d4eb28aa8342a58d579716ed369281 100644
|
||||
--- a/content/public/browser/content_browser_client.cc
|
||||
+++ b/content/public/browser/content_browser_client.cc
|
||||
@@ -683,6 +683,8 @@ bool ContentBrowserClient::CanCreateWindow(
|
||||
@@ -695,6 +695,8 @@ bool ContentBrowserClient::CanCreateWindow(
|
||||
const std::string& frame_name,
|
||||
WindowOpenDisposition disposition,
|
||||
const blink::mojom::WindowFeatures& features,
|
||||
@@ -79,7 +79,7 @@ index 549fa60921444c60b3343fc381fb283ca73f7b6a..c76eb798967426772e8e673f93f22358
|
||||
bool opener_suppressed,
|
||||
bool* no_javascript_access) {
|
||||
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
|
||||
index 667ba54d54dfccb37540e3eb00c6d1d0a078ff2f..98582da50756470a233dcec6ebd5ad78a172a74c 100644
|
||||
index a6e922be7e68644ad1cfe64462712c0430c6749a..b3fb95c4bc6bfd5559c034ee5c946bd7d5a14050 100644
|
||||
--- a/content/public/browser/content_browser_client.h
|
||||
+++ b/content/public/browser/content_browser_client.h
|
||||
@@ -173,6 +173,7 @@ class NetworkService;
|
||||
@@ -90,7 +90,7 @@ index 667ba54d54dfccb37540e3eb00c6d1d0a078ff2f..98582da50756470a233dcec6ebd5ad78
|
||||
} // namespace network
|
||||
|
||||
namespace sandbox {
|
||||
@@ -1097,6 +1098,8 @@ class CONTENT_EXPORT ContentBrowserClient {
|
||||
@@ -1109,6 +1110,8 @@ class CONTENT_EXPORT ContentBrowserClient {
|
||||
const std::string& frame_name,
|
||||
WindowOpenDisposition disposition,
|
||||
const blink::mojom::WindowFeatures& features,
|
||||
|
||||
@@ -82,7 +82,7 @@ index 33ca7a53dfb6d2c9e3a33f0065a3acd806e82e01..9fdf2e8ff0056ff407015b914c6b03eb
|
||||
const Source& GetSource(int index) const override;
|
||||
DesktopMediaList::Type GetMediaListType() const override;
|
||||
diff --git a/chrome/browser/media/webrtc/native_desktop_media_list.cc b/chrome/browser/media/webrtc/native_desktop_media_list.cc
|
||||
index 9ce1d9acbf2fd4b521905f4e4c2d0bb0d63bb170..20be457034f0636486c0ca560628e554b5792445 100644
|
||||
index 81d4416e270e1a4548866a56222c47cb616385e3..22f55d22b0406f0d1aa642dcea44403ac1636057 100644
|
||||
--- a/chrome/browser/media/webrtc/native_desktop_media_list.cc
|
||||
+++ b/chrome/browser/media/webrtc/native_desktop_media_list.cc
|
||||
@@ -159,7 +159,7 @@ BOOL CALLBACK AllHwndCollector(HWND hwnd, LPARAM param) {
|
||||
|
||||
@@ -33,7 +33,7 @@ index 0ab8187b0db8ae6db46d81738f653a2bc4c566f6..de3d55e85c22317f7f9375eb94d0d5d4
|
||||
|
||||
} // namespace net
|
||||
diff --git a/services/network/network_context.cc b/services/network/network_context.cc
|
||||
index ad246393cbd3eedbd91495fe9d3c3f046ccfb553..e748386cdbeefec2acf2a6054b21eadc0f6a556f 100644
|
||||
index cb05975b622eee25217d9f2477c5e53ace017db8..e264713f4361a588e0ec8b4f6f37ab76ad642116 100644
|
||||
--- a/services/network/network_context.cc
|
||||
+++ b/services/network/network_context.cc
|
||||
@@ -1559,6 +1559,13 @@ void NetworkContext::SetNetworkConditions(
|
||||
@@ -51,7 +51,7 @@ index ad246393cbd3eedbd91495fe9d3c3f046ccfb553..e748386cdbeefec2acf2a6054b21eadc
|
||||
// This may only be called on NetworkContexts created with the constructor
|
||||
// that calls MakeURLRequestContext().
|
||||
diff --git a/services/network/network_context.h b/services/network/network_context.h
|
||||
index 4c0cb2e133d84329ab58eff4f30dc7615516b3ae..8790965cc2ac2f9e77dec85d152e5ce66766c3cd 100644
|
||||
index 25f9dab24b27ad2b3d6ca01690e9f5c3fea96d32..b230036559cdc44b97b3a5ca5f359a0b4512ccd7 100644
|
||||
--- a/services/network/network_context.h
|
||||
+++ b/services/network/network_context.h
|
||||
@@ -316,6 +316,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
|
||||
@@ -63,10 +63,10 @@ index 4c0cb2e133d84329ab58eff4f30dc7615516b3ae..8790965cc2ac2f9e77dec85d152e5ce6
|
||||
void SetEnableReferrers(bool enable_referrers) override;
|
||||
#if BUILDFLAG(IS_CHROMEOS)
|
||||
diff --git a/services/network/public/mojom/network_context.mojom b/services/network/public/mojom/network_context.mojom
|
||||
index 772577a0ed4aeb47bb13dcd27ea38b943a2c0952..d7601f0f1b699984577b0d84a8b60d3dbad0d4fb 100644
|
||||
index 6ebade992b628fee18d23e5e29d2d7d6190261a7..21039664d38fb228a9319d296276c33de7a0a265 100644
|
||||
--- a/services/network/public/mojom/network_context.mojom
|
||||
+++ b/services/network/public/mojom/network_context.mojom
|
||||
@@ -1227,6 +1227,9 @@ interface NetworkContext {
|
||||
@@ -1233,6 +1233,9 @@ interface NetworkContext {
|
||||
SetNetworkConditions(mojo_base.mojom.UnguessableToken throttling_profile_id,
|
||||
NetworkConditions? conditions);
|
||||
|
||||
@@ -77,7 +77,7 @@ index 772577a0ed4aeb47bb13dcd27ea38b943a2c0952..d7601f0f1b699984577b0d84a8b60d3d
|
||||
SetAcceptLanguage(string new_accept_language);
|
||||
|
||||
diff --git a/services/network/test/test_network_context.h b/services/network/test/test_network_context.h
|
||||
index 73fe4ad8d0ff68fdb0d2e556e23284154aaf417b..a097e15a0dd47421bb8e20d1fc8b75967bdf2c6f 100644
|
||||
index 9845739908daada58d620cacf95c2b0fbe80ccfb..40dba78ea2dc740c6f0edd7c896bf8bf16abc51e 100644
|
||||
--- a/services/network/test/test_network_context.h
|
||||
+++ b/services/network/test/test_network_context.h
|
||||
@@ -144,6 +144,7 @@ class TestNetworkContext : public mojom::NetworkContext {
|
||||
|
||||
@@ -6,7 +6,7 @@ Subject: expose V8Initializer::CodeGenerationCheckCallbackInMainThread
|
||||
This is needed to blend Blink and Node's policy for code generation policy.
|
||||
|
||||
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc b/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
|
||||
index c652963d9861c9aa754563c9d282dd5cc72e4e34..3da7200c92ccaf8330d46280e26124c1ad558a76 100644
|
||||
index 9bb1917278452e5b9d00dbb39b44416558987255..20d188f57d5425c5f704b3b03cd27034efb25ea7 100644
|
||||
--- a/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
|
||||
+++ b/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
|
||||
@@ -411,8 +411,9 @@ TrustedTypesCodeGenerationCheck(v8::Local<v8::Context> context,
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: clavin <clavin@electronjs.org>
|
||||
Date: Wed, 30 Aug 2023 18:15:36 -0700
|
||||
Subject: fix: activate background material on windows
|
||||
|
||||
This patch adds a condition to the HWND message handler to allow windows
|
||||
with translucent background materials to become activated.
|
||||
|
||||
This patch likely can't be upstreamed as-is, as Chromium doesn't have
|
||||
this use case in mind currently.
|
||||
|
||||
diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc
|
||||
index 13268bd89c710690eed5296f4b2157e9476f195e..37de479e95d49f4d2b1d8164c9e3f6a7bcd82612 100644
|
||||
--- a/ui/views/win/hwnd_message_handler.cc
|
||||
+++ b/ui/views/win/hwnd_message_handler.cc
|
||||
@@ -1094,7 +1094,7 @@ void HWNDMessageHandler::FrameTypeChanged() {
|
||||
|
||||
void HWNDMessageHandler::PaintAsActiveChanged() {
|
||||
if (!delegate_->HasNonClientView() || !delegate_->CanActivate() ||
|
||||
- !delegate_->HasFrame() ||
|
||||
+ (!delegate_->HasFrame() && !is_translucent_) ||
|
||||
(delegate_->GetFrameMode() == FrameMode::CUSTOM_DRAWN)) {
|
||||
return;
|
||||
}
|
||||
@@ -13,10 +13,10 @@ This patch can be removed should we choose to support chrome.fileSystem
|
||||
or support it enough to fix the crash.
|
||||
|
||||
diff --git a/chrome/browser/resources/pdf/pdf_viewer.ts b/chrome/browser/resources/pdf/pdf_viewer.ts
|
||||
index b68423ffe09246ec7ba2935873774c7c452b5952..936ab4b4e12546ca93da27f264559c97f51509ae 100644
|
||||
index b9d1652cfc2628d1f9f98698e8fddbfbae62b4de..bc93b2d47c061538d30bc886709abcda5f2d6eb0 100644
|
||||
--- a/chrome/browser/resources/pdf/pdf_viewer.ts
|
||||
+++ b/chrome/browser/resources/pdf/pdf_viewer.ts
|
||||
@@ -895,26 +895,12 @@ export class PdfViewerElement extends PdfViewerBaseElement {
|
||||
@@ -898,26 +898,12 @@ export class PdfViewerElement extends PdfViewerBaseElement {
|
||||
dataArray = [result.dataToSave];
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ index b68423ffe09246ec7ba2935873774c7c452b5952..936ab4b4e12546ca93da27f264559c97
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1022,30 +1008,12 @@ export class PdfViewerElement extends PdfViewerBaseElement {
|
||||
@@ -1025,30 +1011,12 @@ export class PdfViewerElement extends PdfViewerBaseElement {
|
||||
fileName = fileName + '.pdf';
|
||||
}
|
||||
|
||||
|
||||
@@ -100,10 +100,10 @@ index 07847521e7217c78480205812a73cc89503c00d2..586e866ca7ec0eb0b573d23e3bd95792
|
||||
} else {
|
||||
// No need to bother, we don't know how many pages are available.
|
||||
diff --git a/ui/gtk/printing/print_dialog_gtk.cc b/ui/gtk/printing/print_dialog_gtk.cc
|
||||
index f3892e3f9ff2557bf604b48a8abc0fc4cbd3df1f..ba57bfc2dcef007dee536be0be6eb64d86532d09 100644
|
||||
index e270fa36d775333aaa30f1ff0104062c544d1058..e4a6213e19e4f23834802784a43db22c9d02d891 100644
|
||||
--- a/ui/gtk/printing/print_dialog_gtk.cc
|
||||
+++ b/ui/gtk/printing/print_dialog_gtk.cc
|
||||
@@ -258,6 +258,24 @@ void PrintDialogGtk::UpdateSettings(
|
||||
@@ -245,6 +245,24 @@ void PrintDialogGtk::UpdateSettings(
|
||||
|
||||
gtk_print_settings_set_n_copies(gtk_settings_, settings->copies());
|
||||
gtk_print_settings_set_collate(gtk_settings_, settings->collate());
|
||||
|
||||
@@ -20,7 +20,7 @@ index 802e0ab8073b0709bd723c4d08eafbefef575592..93a6e16a3fee99c9c9d8e85f2a8e43bf
|
||||
}
|
||||
|
||||
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
|
||||
index 98582da50756470a233dcec6ebd5ad78a172a74c..4179b3bd9825868245ea6431291166f377a6990d 100644
|
||||
index b3fb95c4bc6bfd5559c034ee5c946bd7d5a14050..36f3b03d11aada28be45a75e90054c8996ad0f33 100644
|
||||
--- a/content/public/browser/content_browser_client.h
|
||||
+++ b/content/public/browser/content_browser_client.h
|
||||
@@ -311,6 +311,11 @@ class CONTENT_EXPORT ContentBrowserClient {
|
||||
|
||||
@@ -7,7 +7,7 @@ This adds a callback from the network service that's used to implement
|
||||
session.setCertificateVerifyCallback.
|
||||
|
||||
diff --git a/services/network/network_context.cc b/services/network/network_context.cc
|
||||
index 65b1c1214ee4de50d43d88f880aa578ab45d30ae..ad246393cbd3eedbd91495fe9d3c3f046ccfb553 100644
|
||||
index f076c5dc62ca5975865e3966381257684503eeb8..cb05975b622eee25217d9f2477c5e53ace017db8 100644
|
||||
--- a/services/network/network_context.cc
|
||||
+++ b/services/network/network_context.cc
|
||||
@@ -146,6 +146,11 @@
|
||||
@@ -147,7 +147,7 @@ index 65b1c1214ee4de50d43d88f880aa578ab45d30ae..ad246393cbd3eedbd91495fe9d3c3f04
|
||||
|
||||
builder.SetCertVerifier(IgnoreErrorsCertVerifier::MaybeWrapCertVerifier(
|
||||
diff --git a/services/network/network_context.h b/services/network/network_context.h
|
||||
index ff73db2f2a269de96efb4c762c92e0d3f7514945..4c0cb2e133d84329ab58eff4f30dc7615516b3ae 100644
|
||||
index d046d6909a9e648ddc86cbed9cb118d29223155e..25f9dab24b27ad2b3d6ca01690e9f5c3fea96d32 100644
|
||||
--- a/services/network/network_context.h
|
||||
+++ b/services/network/network_context.h
|
||||
@@ -114,6 +114,7 @@ class URLMatcher;
|
||||
@@ -177,7 +177,7 @@ index ff73db2f2a269de96efb4c762c92e0d3f7514945..4c0cb2e133d84329ab58eff4f30dc761
|
||||
std::unique_ptr<HostResolver> internal_host_resolver_;
|
||||
// Map values set to non-null only if that HostResolver has its own private
|
||||
diff --git a/services/network/public/mojom/network_context.mojom b/services/network/public/mojom/network_context.mojom
|
||||
index 40dfb7fd2ad98b80a3f41c0e8e3d82674339cd9e..772577a0ed4aeb47bb13dcd27ea38b943a2c0952 100644
|
||||
index 039407080ba9b234b0472afd7d56d44802fd3c0e..6ebade992b628fee18d23e5e29d2d7d6190261a7 100644
|
||||
--- a/services/network/public/mojom/network_context.mojom
|
||||
+++ b/services/network/public/mojom/network_context.mojom
|
||||
@@ -317,6 +317,17 @@ struct NetworkContextFilePaths {
|
||||
@@ -198,7 +198,7 @@ index 40dfb7fd2ad98b80a3f41c0e8e3d82674339cd9e..772577a0ed4aeb47bb13dcd27ea38b94
|
||||
// Parameters for constructing a network context.
|
||||
struct NetworkContextParams {
|
||||
// The user agent string.
|
||||
@@ -936,6 +947,9 @@ interface NetworkContext {
|
||||
@@ -942,6 +953,9 @@ interface NetworkContext {
|
||||
// Sets a client for this network context.
|
||||
SetClient(pending_remote<NetworkContextClient> client);
|
||||
|
||||
|
||||
@@ -11,10 +11,10 @@ majority of changes originally come from these PRs:
|
||||
This patch also fixes callback for manual user cancellation and success.
|
||||
|
||||
diff --git a/BUILD.gn b/BUILD.gn
|
||||
index ce097109b6a199de57693481310bbf5fdd948c35..11e5c96c3379375bd320320fc684881013ef0e8f 100644
|
||||
index e8c8a8450ff8325905a76addc262a6fd68f037be..e703690f0f0952d7f97cde04e7c2c786ab1747ec 100644
|
||||
--- a/BUILD.gn
|
||||
+++ b/BUILD.gn
|
||||
@@ -969,7 +969,6 @@ if (is_win) {
|
||||
@@ -973,7 +973,6 @@ if (is_win) {
|
||||
"//media:media_unittests",
|
||||
"//media/midi:midi_unittests",
|
||||
"//net:net_unittests",
|
||||
@@ -22,7 +22,7 @@ index ce097109b6a199de57693481310bbf5fdd948c35..11e5c96c3379375bd320320fc6848810
|
||||
"//sql:sql_unittests",
|
||||
"//third_party/breakpad:symupload($host_toolchain)",
|
||||
"//ui/base:ui_base_unittests",
|
||||
@@ -978,6 +977,10 @@ if (is_win) {
|
||||
@@ -982,6 +981,10 @@ if (is_win) {
|
||||
"//ui/views:views_unittests",
|
||||
"//url:url_unittests",
|
||||
]
|
||||
@@ -927,10 +927,10 @@ index 8d65b7b6440c8e653eb1b3f9c50b40944b7ae61b..eb6b4a42d507ff216fc07328c1907815
|
||||
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
|
||||
// Set options for print preset from source PDF document.
|
||||
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
|
||||
index e861d5b7562cda69a7e113882d22087a2f6cdda9..e0d55a859061f029e5298599bf2d9345674ecb34 100644
|
||||
index 89b2e2bd7d6091501756b4d31726c49b00ffd0c7..718ad3e088f6730bb00f1e3674effae6c429b9b6 100644
|
||||
--- a/content/browser/BUILD.gn
|
||||
+++ b/content/browser/BUILD.gn
|
||||
@@ -2951,8 +2951,9 @@ source_set("browser") {
|
||||
@@ -2953,8 +2953,9 @@ source_set("browser") {
|
||||
"//ppapi/shared_impl",
|
||||
]
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ Subject: refactor: expose HostImportModuleDynamically and
|
||||
This is so that Electron can blend Blink's and Node's implementations of these isolate handlers.
|
||||
|
||||
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc b/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
|
||||
index 3da7200c92ccaf8330d46280e26124c1ad558a76..5ceecd071ca2efd2a7db214b65c4a997ef31d0b0 100644
|
||||
index 20d188f57d5425c5f704b3b03cd27034efb25ea7..ff8de70fe7638f1f4fb2f4839ccf54e22339ba8b 100644
|
||||
--- a/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
|
||||
+++ b/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
|
||||
@@ -578,7 +578,9 @@ bool JavaScriptCompileHintsMagicEnabledCallback(
|
||||
@@ -21,7 +21,7 @@ index 3da7200c92ccaf8330d46280e26124c1ad558a76..5ceecd071ca2efd2a7db214b65c4a997
|
||||
v8::Local<v8::Context> context,
|
||||
v8::Local<v8::Data> v8_host_defined_options,
|
||||
v8::Local<v8::Value> v8_referrer_resource_url,
|
||||
@@ -644,7 +646,7 @@ v8::MaybeLocal<v8::Promise> HostImportModuleDynamically(
|
||||
@@ -653,7 +655,7 @@ v8::MaybeLocal<v8::Promise> HostImportModuleDynamically(
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/C/#hostgetimportmetaproperties
|
||||
@@ -30,7 +30,7 @@ index 3da7200c92ccaf8330d46280e26124c1ad558a76..5ceecd071ca2efd2a7db214b65c4a997
|
||||
v8::Local<v8::Module> module,
|
||||
v8::Local<v8::Object> meta) {
|
||||
ScriptState* script_state = ScriptState::From(context);
|
||||
@@ -671,6 +673,8 @@ void HostGetImportMetaProperties(v8::Local<v8::Context> context,
|
||||
@@ -680,6 +682,8 @@ void HostGetImportMetaProperties(v8::Local<v8::Context> context,
|
||||
meta->CreateDataProperty(context, resolve_key, resolve_value).ToChecked();
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ index 3da7200c92ccaf8330d46280e26124c1ad558a76..5ceecd071ca2efd2a7db214b65c4a997
|
||||
void InitializeV8Common(v8::Isolate* isolate) {
|
||||
// Set up garbage collection before setting up anything else as V8 may trigger
|
||||
// GCs during Blink setup.
|
||||
@@ -690,9 +694,9 @@ void InitializeV8Common(v8::Isolate* isolate) {
|
||||
@@ -699,9 +703,9 @@ void InitializeV8Common(v8::Isolate* isolate) {
|
||||
SharedArrayBufferConstructorEnabledCallback);
|
||||
isolate->SetJavaScriptCompileHintsMagicEnabledCallback(
|
||||
JavaScriptCompileHintsMagicEnabledCallback);
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Attard <samuel.r.attard@gmail.com>
|
||||
Date: Tue, 5 Sep 2023 13:22:31 -0700
|
||||
Subject: Revert "Remove the AllowAggressiveThrottlingWithWebSocket feature."
|
||||
|
||||
This reverts commit 615c1810a187840ffeb04096087efff86edb37de.
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/websockets/websocket_channel_impl.cc b/third_party/blink/renderer/modules/websockets/websocket_channel_impl.cc
|
||||
index d566c1a209aa5b39692fe79dd8b5012a5e053574..90e97f739b3e7ede2fa4ceffb1be5130f651f60b 100644
|
||||
--- a/third_party/blink/renderer/modules/websockets/websocket_channel_impl.cc
|
||||
+++ b/third_party/blink/renderer/modules/websockets/websocket_channel_impl.cc
|
||||
@@ -95,6 +95,17 @@ enum WebSocketOpCode {
|
||||
kOpCodeBinary = 0x2,
|
||||
};
|
||||
|
||||
+// When enabled, a page can be aggressively throttled even if it uses a
|
||||
+// WebSocket. Aggressive throttling does not affect the execution of WebSocket
|
||||
+// event handlers, so there is little reason to disable it on pages using a
|
||||
+// WebSocket.
|
||||
+//
|
||||
+// TODO(crbug.com/1121725): Cleanup this feature in June 2021, when it becomes
|
||||
+// enabled by default on Stable.
|
||||
+BASE_FEATURE(kAllowAggressiveThrottlingWithWebSocket,
|
||||
+ "AllowAggressiveThrottlingWithWebSocket",
|
||||
+ base::FEATURE_ENABLED_BY_DEFAULT);
|
||||
+
|
||||
} // namespace
|
||||
|
||||
void WebSocketChannelImpl::MessageDataDeleter::operator()(char* p) const {
|
||||
@@ -285,7 +296,10 @@ bool WebSocketChannelImpl::Connect(const KURL& url, const String& protocol) {
|
||||
// even if the `WebSocketChannel` is closed.
|
||||
feature_handle_for_scheduler_ = scheduler->RegisterFeature(
|
||||
SchedulingPolicy::Feature::kWebSocket,
|
||||
- SchedulingPolicy{SchedulingPolicy::DisableBackForwardCache()});
|
||||
+ base::FeatureList::IsEnabled(kAllowAggressiveThrottlingWithWebSocket)
|
||||
+ ? SchedulingPolicy{SchedulingPolicy::DisableBackForwardCache()}
|
||||
+ : SchedulingPolicy{SchedulingPolicy::DisableAggressiveThrottling(),
|
||||
+ SchedulingPolicy::DisableBackForwardCache()});
|
||||
scheduler->RegisterStickyFeature(
|
||||
SchedulingPolicy::Feature::kWebSocketSticky,
|
||||
SchedulingPolicy{SchedulingPolicy::DisableBackForwardCache()});
|
||||
@@ -15,7 +15,7 @@ Note that we also need to manually update embedder's
|
||||
`api::WebContents::IsFullscreenForTabOrPending` value.
|
||||
|
||||
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
index e2303fbb80ccc7d76d6a949678608c6a55ea411d..029c90e6f1ea240d2c4f87182351b6c587fbef4b 100644
|
||||
index 586aa87098bd3db10440fe865a02c05e7b3be14f..cb372df065f83614ff6c2954035795e67eb69d0c 100644
|
||||
--- a/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
@@ -7417,6 +7417,17 @@ void RenderFrameHostImpl::EnterFullscreen(
|
||||
|
||||
@@ -26,10 +26,10 @@ index a4130ad4dc8158f8256b55fdd87f577687135626..3139aa65807cee23f0e8dbc85243566e
|
||||
// An empty URL is returned if the URL is not overriden.
|
||||
virtual GURL OverrideFlashEmbedWithHTML(const GURL& url);
|
||||
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc
|
||||
index 0371357fd074162b7569b2075acf0342b1fbd39b..f5cca7df8c6876ea777ee985d77e3a882b0b2776 100644
|
||||
index 3206463a734a864e98a2ccdec14fa1f9a8df776a..8bc668a443fb33cb560e4c9592f53920869166c4 100644
|
||||
--- a/content/renderer/renderer_blink_platform_impl.cc
|
||||
+++ b/content/renderer/renderer_blink_platform_impl.cc
|
||||
@@ -794,6 +794,12 @@ void RendererBlinkPlatformImpl::WillStopWorkerThread() {
|
||||
@@ -795,6 +795,12 @@ void RendererBlinkPlatformImpl::WillStopWorkerThread() {
|
||||
WorkerThreadRegistry::Instance()->WillStopCurrentWorkerThread();
|
||||
}
|
||||
|
||||
|
||||
@@ -35,10 +35,10 @@ index 3139aa65807cee23f0e8dbc85243566ef9de89b9..19707edb1283f2432f3c0059f80fabd5
|
||||
// from the worker thread.
|
||||
virtual void WillDestroyWorkerContextOnWorkerThread(
|
||||
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc
|
||||
index f5cca7df8c6876ea777ee985d77e3a882b0b2776..104be40b57bed8ecdc7e81953810ba79355a6e44 100644
|
||||
index 8bc668a443fb33cb560e4c9592f53920869166c4..8dbadf5b2dc233ea1f298c5ad26d5bf1ed0acc64 100644
|
||||
--- a/content/renderer/renderer_blink_platform_impl.cc
|
||||
+++ b/content/renderer/renderer_blink_platform_impl.cc
|
||||
@@ -806,6 +806,12 @@ void RendererBlinkPlatformImpl::WorkerContextCreated(
|
||||
@@ -807,6 +807,12 @@ void RendererBlinkPlatformImpl::WorkerContextCreated(
|
||||
worker);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,3 +5,4 @@ feat_add_new_squirrel_mac_bundle_installation_method_behind_flag.patch
|
||||
refactor_use_posix_spawn_instead_of_nstask_so_we_can_disclaim_the.patch
|
||||
fix_abort_installation_attempt_at_the_final_mile_if_the_app_is.patch
|
||||
chore_disable_api_deprecation_warnings_in_nskeyedarchiver.patch
|
||||
feat_add_ability_to_prevent_version_downgrades.patch
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Attard <marshallofsound@electronjs.org>
|
||||
Date: Tue, 6 Jun 2023 15:20:38 -0700
|
||||
Subject: feat: add ability to prevent version downgrades
|
||||
|
||||
The ElectronSquirrelPreventDowngrades flag in your Info.plist can enable this feature, it must be set to true. This feature prevents a class of downgrade / freeze issues but has significant drawbacks in that it may break existing apps that delibrately downgrade users via the updater and requires that version strings are exactly A.B.C in order for the version comparison logic to work. Because of this this feature can not (and is not) enabled by default.
|
||||
|
||||
diff --git a/Squirrel/SQRLUpdater.h b/Squirrel/SQRLUpdater.h
|
||||
index b3526b246b3729a7556ca0ec348fdc08825c89ed..87119399e8548e04134d1ee0cd18f85c2ad672c2 100644
|
||||
--- a/Squirrel/SQRLUpdater.h
|
||||
+++ b/Squirrel/SQRLUpdater.h
|
||||
@@ -117,6 +117,10 @@ typedef enum {
|
||||
// documentation for more information.
|
||||
@property (atomic, strong) Class updateClass;
|
||||
|
||||
+// Publicly exposed for testing purposes, compares two version strings to see if it's
|
||||
+// allowed. This assumes that the ElectronSquirrelPreventDowngrades flag is enabled.
|
||||
++ (bool) isVersionAllowedForUpdate:(NSString*)targetVersion from:(NSString*)currentVersion;
|
||||
+
|
||||
// Initializes an updater that will send the given request to check for updates.
|
||||
//
|
||||
// This is the designated initializer for this class.
|
||||
diff --git a/Squirrel/SQRLUpdater.m b/Squirrel/SQRLUpdater.m
|
||||
index 4c703159a2bb0239b7d4e1793a985b5ec2edcfa9..592c7ea51515aab96934e0117df3c8065494fa09 100644
|
||||
--- a/Squirrel/SQRLUpdater.m
|
||||
+++ b/Squirrel/SQRLUpdater.m
|
||||
@@ -42,6 +42,18 @@
|
||||
// followed by a random string of characters.
|
||||
static NSString * const SQRLUpdaterUniqueTemporaryDirectoryPrefix = @"update.";
|
||||
|
||||
+BOOL isVersionStandard(NSString* version) {
|
||||
+ NSCharacterSet *alphaNums = [NSCharacterSet decimalDigitCharacterSet];
|
||||
+
|
||||
+ NSArray* versionParts = [version componentsSeparatedByString:@"."];
|
||||
+ BOOL versionBad = [versionParts count] != 3;
|
||||
+ for (NSString* part in versionParts) {
|
||||
+ versionBad = versionBad || [alphaNums isSupersetOfSet:[NSCharacterSet characterSetWithCharactersInString:part]];
|
||||
+ }
|
||||
+
|
||||
+ return !versionBad;
|
||||
+}
|
||||
+
|
||||
@interface SQRLUpdater ()
|
||||
|
||||
@property (atomic, readwrite) SQRLUpdaterState state;
|
||||
@@ -59,6 +71,8 @@ @interface SQRLUpdater ()
|
||||
// Sends completed or error.
|
||||
@property (nonatomic, strong, readonly) RACSignal *shipItLauncher;
|
||||
|
||||
++ (bool) isVersionAllowedForUpdate:(NSString*)targetVersion from:(NSString*)currentVersion;
|
||||
+
|
||||
// Parses an update model from downloaded data.
|
||||
//
|
||||
// data - JSON data representing an update manifest. This must not be nil.
|
||||
@@ -372,6 +386,10 @@ - (RACDisposable *)startAutomaticChecksWithInterval:(NSTimeInterval)interval {
|
||||
connect];
|
||||
}
|
||||
|
||||
++ (bool) isVersionAllowedForUpdate:(NSString*)targetVersion from:(NSString*)currentVersion {
|
||||
+ return [currentVersion compare:targetVersion options:NSNumericSearch] != NSOrderedDescending;
|
||||
+}
|
||||
+
|
||||
- (RACSignal *)updateFromJSONData:(NSData *)data {
|
||||
NSParameterAssert(data != nil);
|
||||
|
||||
@@ -711,6 +729,50 @@ - (RACSignal *)verifyAndPrepareUpdate:(SQRLUpdate *)update fromBundle:(NSBundle
|
||||
return [[[[self.signature
|
||||
verifyBundleAtURL:updateBundle.bundleURL]
|
||||
then:^{
|
||||
+ NSRunningApplication *currentApplication = NSRunningApplication.currentApplication;
|
||||
+ NSBundle *appBundle = [NSBundle bundleWithURL:currentApplication.bundleURL];
|
||||
+ BOOL preventDowngrades = [[appBundle objectForInfoDictionaryKey:@"ElectronSquirrelPreventDowngrades"] boolValue];
|
||||
+
|
||||
+ if (preventDowngrades == YES) {
|
||||
+ NSString* currentVersion = [appBundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
|
||||
+ NSString* updateVersion = [updateBundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
|
||||
+ if (!currentVersion || !updateVersion) {
|
||||
+ NSDictionary *errorInfo = @{
|
||||
+ NSLocalizedDescriptionKey: NSLocalizedString(@"Cannot update to a bundle with a lower version number", nil),
|
||||
+ NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString(@"The application has ElectronSquirrelPreventDowngrades enabled and is missing a valid version string in either the current bundle or the target bundle", nil),
|
||||
+ };
|
||||
+ NSError *error = [NSError errorWithDomain:SQRLUpdaterErrorDomain code:SQRLUpdaterErrorMissingUpdateBundle userInfo:errorInfo];
|
||||
+ return [RACSignal error:error];
|
||||
+ }
|
||||
+
|
||||
+ if (!isVersionStandard(currentVersion)) {
|
||||
+ NSDictionary *errorInfo = @{
|
||||
+ NSLocalizedDescriptionKey: NSLocalizedString(@"Cannot update to a bundle with a lower version number", nil),
|
||||
+ NSLocalizedRecoverySuggestionErrorKey: [NSString stringWithFormat:NSLocalizedString(@"The application has ElectronSquirrelPreventDowngrades enabled and is trying to update from '%@' which is not a valid version string", nil), currentVersion],
|
||||
+ };
|
||||
+ NSError *error = [NSError errorWithDomain:SQRLUpdaterErrorDomain code:SQRLUpdaterErrorMissingUpdateBundle userInfo:errorInfo];
|
||||
+ return [RACSignal error:error];
|
||||
+ }
|
||||
+
|
||||
+ if (!isVersionStandard(updateVersion)) {
|
||||
+ NSDictionary *errorInfo = @{
|
||||
+ NSLocalizedDescriptionKey: NSLocalizedString(@"Cannot update to a bundle with a lower version number", nil),
|
||||
+ NSLocalizedRecoverySuggestionErrorKey: [NSString stringWithFormat:NSLocalizedString(@"The application has ElectronSquirrelPreventDowngrades enabled and is trying to update to '%@' which is not a valid version string", nil), updateVersion],
|
||||
+ };
|
||||
+ NSError *error = [NSError errorWithDomain:SQRLUpdaterErrorDomain code:SQRLUpdaterErrorMissingUpdateBundle userInfo:errorInfo];
|
||||
+ return [RACSignal error:error];
|
||||
+ }
|
||||
+
|
||||
+ if (![SQRLUpdater isVersionAllowedForUpdate:updateVersion from:currentVersion]) {
|
||||
+ NSDictionary *errorInfo = @{
|
||||
+ NSLocalizedDescriptionKey: NSLocalizedString(@"Cannot update to a bundle with a lower version number", nil),
|
||||
+ NSLocalizedRecoverySuggestionErrorKey: [NSString stringWithFormat:NSLocalizedString(@"The application has ElectronSquirrelPreventDowngrades enabled and is trying to update from '%@' to '%@' which appears to be a downgrade", nil), currentVersion, updateVersion],
|
||||
+ };
|
||||
+ NSError *error = [NSError errorWithDomain:SQRLUpdaterErrorDomain code:SQRLUpdaterErrorMissingUpdateBundle userInfo:errorInfo];
|
||||
+ return [RACSignal error:error];
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
SQRLDownloadedUpdate *downloadedUpdate = [[SQRLDownloadedUpdate alloc] initWithUpdate:update bundle:updateBundle];
|
||||
return [RACSignal return:downloadedUpdate];
|
||||
}]
|
||||
@@ -95,10 +95,6 @@ void AutoUpdater::OnWindowAllClosed() {
|
||||
QuitAndInstall();
|
||||
}
|
||||
|
||||
void AutoUpdater::SetFeedURL(gin::Arguments* args) {
|
||||
auto_updater::AutoUpdater::SetFeedURL(args);
|
||||
}
|
||||
|
||||
void AutoUpdater::QuitAndInstall() {
|
||||
Emit("before-quit-for-update");
|
||||
|
||||
@@ -124,7 +120,11 @@ gin::ObjectTemplateBuilder AutoUpdater::GetObjectTemplateBuilder(
|
||||
isolate)
|
||||
.SetMethod("checkForUpdates", &auto_updater::AutoUpdater::CheckForUpdates)
|
||||
.SetMethod("getFeedURL", &auto_updater::AutoUpdater::GetFeedURL)
|
||||
.SetMethod("setFeedURL", &AutoUpdater::SetFeedURL)
|
||||
.SetMethod("setFeedURL", &auto_updater::AutoUpdater::SetFeedURL)
|
||||
#if DCHECK_IS_ON()
|
||||
.SetMethod("isVersionAllowedForUpdate",
|
||||
&auto_updater::AutoUpdater::IsVersionAllowedForUpdate)
|
||||
#endif
|
||||
.SetMethod("quitAndInstall", &AutoUpdater::QuitAndInstall);
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,6 @@ class AutoUpdater : public gin::Wrappable<AutoUpdater>,
|
||||
|
||||
private:
|
||||
std::string GetFeedURL();
|
||||
void SetFeedURL(gin::Arguments* args);
|
||||
void QuitAndInstall();
|
||||
};
|
||||
|
||||
|
||||
@@ -42,19 +42,11 @@ BrowserWindow::BrowserWindow(gin::Arguments* args,
|
||||
auto web_preferences = gin_helper::Dictionary::CreateEmpty(isolate);
|
||||
options.Get(options::kWebPreferences, &web_preferences);
|
||||
|
||||
bool transparent = false;
|
||||
options.Get(options::kTransparent, &transparent);
|
||||
|
||||
std::string vibrancy_type;
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
options.Get(options::kVibrancyType, &vibrancy_type);
|
||||
#endif
|
||||
|
||||
// Copy the backgroundColor to webContents.
|
||||
std::string color;
|
||||
if (options.Get(options::kBackgroundColor, &color)) {
|
||||
web_preferences.SetHidden(options::kBackgroundColor, color);
|
||||
} else if (!vibrancy_type.empty() || transparent) {
|
||||
} else if (window_->IsTranslucent()) {
|
||||
// If the BrowserWindow is transparent or a vibrancy type has been set,
|
||||
// also propagate transparency to the WebContents unless a separate
|
||||
// backgroundColor has been set.
|
||||
|
||||
@@ -89,10 +89,6 @@ gin::ObjectTemplateBuilder SystemPreferences::GetObjectTemplateBuilder(
|
||||
&SystemPreferences::IsSwipeTrackingFromScrollEventsEnabled)
|
||||
.SetMethod("getEffectiveAppearance",
|
||||
&SystemPreferences::GetEffectiveAppearance)
|
||||
.SetMethod("getAppLevelAppearance",
|
||||
&SystemPreferences::GetAppLevelAppearance)
|
||||
.SetMethod("setAppLevelAppearance",
|
||||
&SystemPreferences::SetAppLevelAppearance)
|
||||
.SetMethod("getSystemColor", &SystemPreferences::GetSystemColor)
|
||||
.SetMethod("canPromptTouchID", &SystemPreferences::CanPromptTouchID)
|
||||
.SetMethod("promptTouchID", &SystemPreferences::PromptTouchID)
|
||||
|
||||
@@ -112,8 +112,6 @@ class SystemPreferences
|
||||
// TODO(MarshallOfSound): Write tests for these methods once we
|
||||
// are running tests on a Mojave machine
|
||||
v8::Local<v8::Value> GetEffectiveAppearance(v8::Isolate* isolate);
|
||||
v8::Local<v8::Value> GetAppLevelAppearance(v8::Isolate* isolate);
|
||||
void SetAppLevelAppearance(gin::Arguments* args);
|
||||
#endif
|
||||
v8::Local<v8::Value> GetAnimationSettings(v8::Isolate* isolate);
|
||||
|
||||
|
||||
@@ -471,14 +471,7 @@ bool SystemPreferences::IsTrustedAccessibilityClient(bool prompt) {
|
||||
std::string SystemPreferences::GetColor(gin_helper::ErrorThrower thrower,
|
||||
const std::string& color) {
|
||||
NSColor* sysColor = nil;
|
||||
if (color == "alternate-selected-control-text") {
|
||||
sysColor = [NSColor alternateSelectedControlTextColor];
|
||||
EmitWarning(
|
||||
node::Environment::GetCurrent(thrower.isolate()),
|
||||
"'alternate-selected-control-text' is deprecated as an input to "
|
||||
"getColor. Use 'selected-content-background' instead.",
|
||||
"electron");
|
||||
} else if (color == "control-background") {
|
||||
if (color == "control-background") {
|
||||
sysColor = [NSColor controlBackgroundColor];
|
||||
} else if (color == "control") {
|
||||
sysColor = [NSColor controlColor];
|
||||
@@ -605,19 +598,4 @@ v8::Local<v8::Value> SystemPreferences::GetEffectiveAppearance(
|
||||
isolate, [NSApplication sharedApplication].effectiveAppearance);
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> SystemPreferences::GetAppLevelAppearance(
|
||||
v8::Isolate* isolate) {
|
||||
return gin::ConvertToV8(isolate,
|
||||
[NSApplication sharedApplication].appearance);
|
||||
}
|
||||
|
||||
void SystemPreferences::SetAppLevelAppearance(gin::Arguments* args) {
|
||||
NSAppearance* appearance;
|
||||
if (args->GetNext(&appearance)) {
|
||||
[[NSApplication sharedApplication] setAppearance:appearance];
|
||||
} else {
|
||||
args->ThrowError();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace electron::api
|
||||
|
||||
@@ -2667,14 +2667,6 @@ void WebContents::OpenDevTools(gin::Arguments* args) {
|
||||
state = "detach";
|
||||
}
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
auto* win = static_cast<NativeWindowViews*>(owner_window());
|
||||
// Force a detached state when WCO is enabled to match Chrome
|
||||
// behavior and prevent occlusion of DevTools.
|
||||
if (win && win->IsWindowControlsOverlayEnabled())
|
||||
state = "detach";
|
||||
#endif
|
||||
|
||||
bool activate = true;
|
||||
std::string title;
|
||||
if (args && args->Length() == 1) {
|
||||
|
||||
@@ -26,6 +26,11 @@ void AutoUpdater::SetFeedURL(gin::Arguments* args) {}
|
||||
void AutoUpdater::CheckForUpdates() {}
|
||||
|
||||
void AutoUpdater::QuitAndInstall() {}
|
||||
|
||||
bool AutoUpdater::IsVersionAllowedForUpdate(const std::string& current_version,
|
||||
const std::string& target_version) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace auto_updater
|
||||
|
||||
@@ -70,6 +70,9 @@ class AutoUpdater {
|
||||
static void CheckForUpdates();
|
||||
static void QuitAndInstall();
|
||||
|
||||
static bool IsVersionAllowedForUpdate(const std::string& current_version,
|
||||
const std::string& target_version);
|
||||
|
||||
private:
|
||||
static Delegate* delegate_;
|
||||
};
|
||||
|
||||
@@ -179,4 +179,11 @@ void AutoUpdater::QuitAndInstall() {
|
||||
}
|
||||
}
|
||||
|
||||
bool AutoUpdater::IsVersionAllowedForUpdate(const std::string& current_version,
|
||||
const std::string& target_version) {
|
||||
return [SQRLUpdater
|
||||
isVersionAllowedForUpdate:base::SysUTF8ToNSString(target_version)
|
||||
from:base::SysUTF8ToNSString(current_version)];
|
||||
}
|
||||
|
||||
} // namespace auto_updater
|
||||
|
||||
@@ -40,13 +40,6 @@ namespace electron {
|
||||
|
||||
namespace {
|
||||
|
||||
bool IsAppRTL() {
|
||||
const std::string& locale = g_browser_process->GetApplicationLocale();
|
||||
base::i18n::TextDirection text_direction =
|
||||
base::i18n::GetTextDirectionForLocaleInStartUp(locale.c_str());
|
||||
return text_direction == base::i18n::RIGHT_TO_LEFT;
|
||||
}
|
||||
|
||||
NSString* GetAppPathForProtocol(const GURL& url) {
|
||||
NSURL* ns_url = [NSURL
|
||||
URLWithString:base::SysUTF8ToNSString(url.possibly_invalid_spec())];
|
||||
|
||||
@@ -49,7 +49,7 @@ class JavascriptEnvironment {
|
||||
const raw_ptr<v8::Isolate> isolate_;
|
||||
|
||||
// depends-on: isolate_
|
||||
v8::Locker locker_;
|
||||
const v8::Locker locker_;
|
||||
|
||||
std::unique_ptr<MicrotasksRunner> microtasks_runner_;
|
||||
};
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "base/values.h"
|
||||
#include "content/public/browser/web_contents_user_data.h"
|
||||
#include "include/core/SkColor.h"
|
||||
#include "shell/browser/browser.h"
|
||||
#include "shell/browser/native_window_features.h"
|
||||
#include "shell/browser/ui/drag_util.h"
|
||||
@@ -259,13 +260,15 @@ void NativeWindow::InitFromOptions(const gin_helper::Dictionary& options) {
|
||||
SetBackgroundMaterial(material);
|
||||
}
|
||||
#endif
|
||||
std::string color;
|
||||
if (options.Get(options::kBackgroundColor, &color)) {
|
||||
SetBackgroundColor(ParseCSSColor(color));
|
||||
} else if (!transparent()) {
|
||||
// For normal window, use white as default background.
|
||||
SetBackgroundColor(SK_ColorWHITE);
|
||||
|
||||
SkColor background_color = SK_ColorWHITE;
|
||||
if (std::string color; options.Get(options::kBackgroundColor, &color)) {
|
||||
background_color = ParseCSSColor(color);
|
||||
} else if (IsTranslucent()) {
|
||||
background_color = SK_ColorTRANSPARENT;
|
||||
}
|
||||
SetBackgroundColor(background_color);
|
||||
|
||||
std::string title(Browser::Get()->GetName());
|
||||
options.Get(options::kTitle, &title);
|
||||
SetTitle(title);
|
||||
@@ -472,9 +475,13 @@ bool NativeWindow::AddTabbedWindow(NativeWindow* window) {
|
||||
return true; // for non-Mac platforms
|
||||
}
|
||||
|
||||
void NativeWindow::SetVibrancy(const std::string& type) {}
|
||||
void NativeWindow::SetVibrancy(const std::string& type) {
|
||||
vibrancy_ = type;
|
||||
}
|
||||
|
||||
void NativeWindow::SetBackgroundMaterial(const std::string& type) {}
|
||||
void NativeWindow::SetBackgroundMaterial(const std::string& type) {
|
||||
background_material_ = type;
|
||||
}
|
||||
|
||||
void NativeWindow::SetTouchBar(
|
||||
std::vector<gin_helper::PersistentDictionary> items) {}
|
||||
@@ -798,6 +805,30 @@ void NativeWindow::HandlePendingFullscreenTransitions() {
|
||||
// static
|
||||
int32_t NativeWindow::next_id_ = 0;
|
||||
|
||||
bool NativeWindow::IsTranslucent() const {
|
||||
// Transparent windows are translucent
|
||||
if (transparent()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
// Windows with vibrancy set are translucent
|
||||
if (!vibrancy().empty()) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
// Windows with certain background materials may be translucent
|
||||
const std::string& bg_material = background_material();
|
||||
if (!bg_material.empty() && bg_material != "none") {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// static
|
||||
void NativeWindowRelay::CreateForWebContents(
|
||||
content::WebContents* web_contents,
|
||||
|
||||
@@ -218,8 +218,12 @@ class NativeWindow : public base::SupportsUserData,
|
||||
virtual void SetAutoHideCursor(bool auto_hide);
|
||||
|
||||
// Vibrancy API
|
||||
const std::string& vibrancy() const { return vibrancy_; }
|
||||
virtual void SetVibrancy(const std::string& type);
|
||||
|
||||
const std::string& background_material() const {
|
||||
return background_material_;
|
||||
}
|
||||
virtual void SetBackgroundMaterial(const std::string& type);
|
||||
|
||||
// Traffic Light API
|
||||
@@ -395,6 +399,8 @@ class NativeWindow : public base::SupportsUserData,
|
||||
void AddDraggableRegionProvider(DraggableRegionProvider* provider);
|
||||
void RemoveDraggableRegionProvider(DraggableRegionProvider* provider);
|
||||
|
||||
bool IsTranslucent() const;
|
||||
|
||||
protected:
|
||||
friend class api::BrowserView;
|
||||
|
||||
@@ -492,6 +498,9 @@ class NativeWindow : public base::SupportsUserData,
|
||||
// Accessible title.
|
||||
std::u16string accessible_title_;
|
||||
|
||||
std::string vibrancy_;
|
||||
std::string background_material_;
|
||||
|
||||
gfx::Rect overlay_rect_;
|
||||
|
||||
base::WeakPtrFactory<NativeWindow> weak_factory_{this};
|
||||
|
||||
@@ -683,9 +683,6 @@ void NativeWindowMac::DetachChildren() {
|
||||
}
|
||||
|
||||
void NativeWindowMac::SetFullScreen(bool fullscreen) {
|
||||
if (!has_frame() && !HasStyleMask(NSWindowStyleMaskTitled))
|
||||
return;
|
||||
|
||||
// [NSWindow -toggleFullScreen] is an asynchronous operation, which means
|
||||
// that it's possible to call it while a fullscreen transition is currently
|
||||
// in process. This can create weird behavior (incl. phantom windows),
|
||||
@@ -718,7 +715,8 @@ void NativeWindowMac::SetFullScreen(bool fullscreen) {
|
||||
? FullScreenTransitionState::kEntering
|
||||
: FullScreenTransitionState::kExiting;
|
||||
|
||||
[window_ toggleFullScreenMode:nil];
|
||||
if (![window_ toggleFullScreenMode:nil])
|
||||
fullscreen_transition_state_ = FullScreenTransitionState::kNone;
|
||||
}
|
||||
|
||||
bool NativeWindowMac::IsFullscreen() const {
|
||||
@@ -1458,6 +1456,8 @@ void NativeWindowMac::UpdateWindowOriginalFrame() {
|
||||
}
|
||||
|
||||
void NativeWindowMac::SetVibrancy(const std::string& type) {
|
||||
NativeWindow::SetVibrancy(type);
|
||||
|
||||
NSVisualEffectView* vibrantView = [window_ vibrantView];
|
||||
|
||||
if (type.empty()) {
|
||||
@@ -1692,6 +1692,9 @@ void NativeWindowMac::NotifyWindowEnterFullScreen() {
|
||||
// Restore the window title under fullscreen mode.
|
||||
if (buttons_proxy_)
|
||||
[window_ setTitleVisibility:NSWindowTitleVisible];
|
||||
|
||||
if (transparent() || !has_frame())
|
||||
[window_ setTitlebarAppearsTransparent:NO];
|
||||
}
|
||||
|
||||
void NativeWindowMac::NotifyWindowLeaveFullScreen() {
|
||||
@@ -1701,6 +1704,9 @@ void NativeWindowMac::NotifyWindowLeaveFullScreen() {
|
||||
[buttons_proxy_ redraw];
|
||||
[buttons_proxy_ setVisible:YES];
|
||||
}
|
||||
|
||||
if (transparent() || !has_frame())
|
||||
[window_ setTitlebarAppearsTransparent:YES];
|
||||
}
|
||||
|
||||
void NativeWindowMac::NotifyWindowWillEnterFullScreen() {
|
||||
|
||||
@@ -284,12 +284,12 @@ NativeWindowViews::NativeWindowViews(const gin_helper::Dictionary& options,
|
||||
params.remove_standard_frame = !has_frame() || has_client_frame();
|
||||
|
||||
// If a client frame, we need to draw our own shadows.
|
||||
if (transparent() || has_client_frame())
|
||||
if (IsTranslucent() || has_client_frame())
|
||||
params.opacity = views::Widget::InitParams::WindowOpacity::kTranslucent;
|
||||
|
||||
// The given window is most likely not rectangular since it uses
|
||||
// transparency and has no standard frame, don't show a shadow for it.
|
||||
if (transparent() && !has_frame())
|
||||
// The given window is most likely not rectangular since it is translucent and
|
||||
// has no standard frame, don't show a shadow for it.
|
||||
if (IsTranslucent() && !has_frame())
|
||||
params.shadow_type = views::Widget::InitParams::ShadowType::kNone;
|
||||
|
||||
bool focusable;
|
||||
@@ -1457,6 +1457,8 @@ bool NativeWindowViews::IsMenuBarVisible() {
|
||||
}
|
||||
|
||||
void NativeWindowViews::SetBackgroundMaterial(const std::string& material) {
|
||||
NativeWindow::SetBackgroundMaterial(material);
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
// DWMWA_USE_HOSTBACKDROPBRUSH is only supported on Windows 11 22H2 and up.
|
||||
if (base::win::GetVersion() < base::win::Version::WIN11_22H2)
|
||||
@@ -1468,6 +1470,20 @@ void NativeWindowViews::SetBackgroundMaterial(const std::string& material) {
|
||||
&backdrop_type, sizeof(backdrop_type));
|
||||
if (FAILED(result))
|
||||
LOG(WARNING) << "Failed to set background material to " << material;
|
||||
|
||||
// For frameless windows with a background material set, we also need to
|
||||
// remove the caption color so it doesn't render a caption bar (since the
|
||||
// window is frameless)
|
||||
COLORREF caption_color = DWMWA_COLOR_DEFAULT;
|
||||
if (backdrop_type != DWMSBT_NONE && backdrop_type != DWMSBT_AUTO &&
|
||||
!has_frame()) {
|
||||
caption_color = DWMWA_COLOR_NONE;
|
||||
}
|
||||
result = DwmSetWindowAttribute(GetAcceleratedWidget(), DWMWA_CAPTION_COLOR,
|
||||
&caption_color, sizeof(caption_color));
|
||||
|
||||
if (FAILED(result))
|
||||
LOG(WARNING) << "Failed to set caption color to transparent";
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ class ScopedDisableResize {
|
||||
- (electron::NativeWindowMac*)shell;
|
||||
- (id)accessibilityFocusedUIElement;
|
||||
- (NSRect)originalContentRectForFrameRect:(NSRect)frameRect;
|
||||
- (void)toggleFullScreenMode:(id)sender;
|
||||
- (BOOL)toggleFullScreenMode:(id)sender;
|
||||
- (NSImage*)_cornerMask;
|
||||
@end
|
||||
|
||||
|
||||
@@ -334,7 +334,10 @@ void SwizzleSwipeWithEvent(NSView* view, SEL swiz_selector) {
|
||||
}
|
||||
}
|
||||
|
||||
- (void)toggleFullScreenMode:(id)sender {
|
||||
- (BOOL)toggleFullScreenMode:(id)sender {
|
||||
if (!shell_->has_frame() && !shell_->HasStyleMask(NSWindowStyleMaskTitled))
|
||||
return NO;
|
||||
|
||||
bool is_simple_fs = shell_->IsSimpleFullScreen();
|
||||
bool always_simple_fs = shell_->always_simple_fullscreen();
|
||||
|
||||
@@ -363,6 +366,8 @@ void SwizzleSwipeWithEvent(NSView* view, SEL swiz_selector) {
|
||||
bool maximizable = shell_->IsMaximizable();
|
||||
shell_->SetMaximizable(maximizable);
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)performMiniaturize:(id)sender {
|
||||
|
||||
@@ -44,11 +44,13 @@
|
||||
#include "services/network/public/cpp/simple_url_loader_stream_consumer.h"
|
||||
#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
|
||||
#include "shell/browser/api/electron_api_web_contents.h"
|
||||
#include "shell/browser/native_window_views.h"
|
||||
#include "shell/browser/net/asar/asar_url_loader_factory.h"
|
||||
#include "shell/browser/protocol_registry.h"
|
||||
#include "shell/browser/ui/inspectable_web_contents_delegate.h"
|
||||
#include "shell/browser/ui/inspectable_web_contents_view.h"
|
||||
#include "shell/browser/ui/inspectable_web_contents_view_delegate.h"
|
||||
#include "shell/common/application_info.h"
|
||||
#include "shell/common/platform_util.h"
|
||||
#include "third_party/blink/public/common/logging/logging_utils.h"
|
||||
#include "third_party/blink/public/common/page/page_zoom.h"
|
||||
@@ -585,6 +587,23 @@ void InspectableWebContents::LoadCompleted() {
|
||||
prefs.FindString("currentDockState");
|
||||
base::RemoveChars(*current_dock_state, "\"", &dock_state_);
|
||||
}
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
auto* api_web_contents = api::WebContents::From(GetWebContents());
|
||||
if (api_web_contents) {
|
||||
auto* win =
|
||||
static_cast<NativeWindowViews*>(api_web_contents->owner_window());
|
||||
// When WCO is enabled, undock the devtools if the current dock
|
||||
// position overlaps with the position of window controls to avoid
|
||||
// broken layout.
|
||||
if (win && win->IsWindowControlsOverlayEnabled()) {
|
||||
if (IsAppRTL() && dock_state_ == "left") {
|
||||
dock_state_ = "undocked";
|
||||
} else if (dock_state_ == "right") {
|
||||
dock_state_ = "undocked";
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
std::u16string javascript = base::UTF8ToUTF16(
|
||||
"UI.DockController.instance().setDockSide(\"" + dock_state_ + "\");");
|
||||
GetDevToolsWebContents()->GetPrimaryMainFrame()->ExecuteJavaScript(
|
||||
|
||||
@@ -4,8 +4,10 @@
|
||||
|
||||
#include "shell/common/application_info.h"
|
||||
|
||||
#include "base/i18n/rtl.h"
|
||||
#include "base/no_destructor.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "chrome/browser/browser_process.h"
|
||||
#include "chrome/common/chrome_version.h"
|
||||
#include "content/public/common/user_agent.h"
|
||||
#include "electron/electron_version.h"
|
||||
@@ -47,4 +49,11 @@ std::string GetApplicationUserAgent() {
|
||||
return content::BuildUserAgentFromProduct(user_agent);
|
||||
}
|
||||
|
||||
bool IsAppRTL() {
|
||||
const std::string& locale = g_browser_process->GetApplicationLocale();
|
||||
base::i18n::TextDirection text_direction =
|
||||
base::i18n::GetTextDirectionForLocaleInStartUp(locale.c_str());
|
||||
return text_direction == base::i18n::RIGHT_TO_LEFT;
|
||||
}
|
||||
|
||||
} // namespace electron
|
||||
|
||||
@@ -25,6 +25,8 @@ std::string GetApplicationVersion();
|
||||
// Returns the user agent of Electron.
|
||||
std::string GetApplicationUserAgent();
|
||||
|
||||
bool IsAppRTL();
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
PCWSTR GetRawAppUserModelID();
|
||||
bool GetAppUserModelID(ScopedHString* app_id);
|
||||
|
||||
@@ -704,9 +704,362 @@
|
||||
}
|
||||
}
|
||||
],
|
||||
// Electron does not yet support tab events - we define them here because otherwise extensions crash when
|
||||
// they try to listen for them.
|
||||
"events": [
|
||||
{
|
||||
"name": "onCreated",
|
||||
"deprecated": "chrome.tabs.onCreated is not current supported in Electron",
|
||||
"type": "function",
|
||||
"description": "Fired when a tab is created. Note that the tab's URL and tab group membership may not be set at the time this event is fired, but you can listen to onUpdated events so as to be notified when a URL is set or the tab is added to a tab group.",
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "Tab",
|
||||
"name": "tab",
|
||||
"description": "Details of the tab that was created."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "onUpdated",
|
||||
"deprecated": "chrome.tabs.onUpdated is not current supported in Electron",
|
||||
"type": "function",
|
||||
"description": "Fired when a tab is updated.",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"name": "tabId",
|
||||
"minimum": 0
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"name": "changeInfo",
|
||||
"description": "Lists the changes to the state of the tab that was updated.",
|
||||
"properties": {
|
||||
"status": {
|
||||
"$ref": "TabStatus",
|
||||
"optional": true,
|
||||
"description": "The tab's loading status."
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"optional": true,
|
||||
"description": "The tab's URL if it has changed."
|
||||
},
|
||||
"groupId": {
|
||||
"type": "integer",
|
||||
"optional": true,
|
||||
"minimum": -1,
|
||||
"description": "The tab's new group."
|
||||
},
|
||||
"pinned": {
|
||||
"type": "boolean",
|
||||
"optional": true,
|
||||
"description": "The tab's new pinned state."
|
||||
},
|
||||
"audible": {
|
||||
"type": "boolean",
|
||||
"optional": true,
|
||||
"description": "The tab's new audible state."
|
||||
},
|
||||
"discarded": {
|
||||
"type": "boolean",
|
||||
"optional": true,
|
||||
"description": "The tab's new discarded state."
|
||||
},
|
||||
"autoDiscardable": {
|
||||
"type": "boolean",
|
||||
"optional": true,
|
||||
"description": "The tab's new auto-discardable state."
|
||||
},
|
||||
"mutedInfo": {
|
||||
"$ref": "MutedInfo",
|
||||
"optional": true,
|
||||
"description": "The tab's new muted state and the reason for the change."
|
||||
},
|
||||
"favIconUrl": {
|
||||
"type": "string",
|
||||
"optional": true,
|
||||
"description": "The tab's new favicon URL."
|
||||
},
|
||||
"title": {
|
||||
"type": "string",
|
||||
"optional": true,
|
||||
"description": "The tab's new title."
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"$ref": "Tab",
|
||||
"name": "tab",
|
||||
"description": "Gives the state of the tab that was updated."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "onMoved",
|
||||
"deprecated": "chrome.tabs.onMoved is not current supported in Electron",
|
||||
"type": "function",
|
||||
"description": "Fired when a tab is moved within a window. Only one move event is fired, representing the tab the user directly moved. Move events are not fired for the other tabs that must move in response to the manually-moved tab. This event is not fired when a tab is moved between windows; for details, see $(ref:tabs.onDetached).",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"name": "tabId",
|
||||
"minimum": 0
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"name": "moveInfo",
|
||||
"properties": {
|
||||
"windowId": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"fromIndex": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"toIndex": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "onSelectionChanged",
|
||||
"deprecated": "chrome.tabs.onSelectionChanged is not current supported in Electron",
|
||||
"type": "function",
|
||||
"description": "Fires when the selected tab in a window changes.",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"name": "tabId",
|
||||
"minimum": 0,
|
||||
"description": "The ID of the tab that has become active."
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"name": "selectInfo",
|
||||
"properties": {
|
||||
"windowId": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"description": "The ID of the window the selected tab changed inside of."
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "onActiveChanged",
|
||||
"deprecated": "chrome.tabs.onActiveChanged is not current supported in Electron",
|
||||
"type": "function",
|
||||
"description": "Fires when the selected tab in a window changes. Note that the tab's URL may not be set at the time this event fired, but you can listen to $(ref:tabs.onUpdated) events so as to be notified when a URL is set.",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"name": "tabId",
|
||||
"minimum": 0,
|
||||
"description": "The ID of the tab that has become active."
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"name": "selectInfo",
|
||||
"properties": {
|
||||
"windowId": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"description": "The ID of the window the selected tab changed inside of."
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "onActivated",
|
||||
"deprecated": "chrome.tabs.onActivated is not current supported in Electron",
|
||||
"type": "function",
|
||||
"description": "Fires when the active tab in a window changes. Note that the tab's URL may not be set at the time this event fired, but you can listen to onUpdated events so as to be notified when a URL is set.",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "object",
|
||||
"name": "activeInfo",
|
||||
"properties": {
|
||||
"tabId": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"description": "The ID of the tab that has become active."
|
||||
},
|
||||
"windowId": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"description": "The ID of the window the active tab changed inside of."
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "onHighlightChanged",
|
||||
"deprecated": "chrome.tabs.onHighlightChanged is not current supported in Electron",
|
||||
"type": "function",
|
||||
"description": "Fired when the highlighted or selected tabs in a window changes.",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "object",
|
||||
"name": "selectInfo",
|
||||
"properties": {
|
||||
"windowId": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"description": "The window whose tabs changed."
|
||||
},
|
||||
"tabIds": {
|
||||
"type": "array",
|
||||
"name": "tabIds",
|
||||
"items": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"description": "All highlighted tabs in the window."
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "onHighlighted",
|
||||
"deprecated": "chrome.tabs.onHighlighted is not current supported in Electron",
|
||||
"type": "function",
|
||||
"description": "Fired when the highlighted or selected tabs in a window changes.",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "object",
|
||||
"name": "highlightInfo",
|
||||
"properties": {
|
||||
"windowId": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"description": "The window whose tabs changed."
|
||||
},
|
||||
"tabIds": {
|
||||
"type": "array",
|
||||
"name": "tabIds",
|
||||
"items": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"description": "All highlighted tabs in the window."
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "onDetached",
|
||||
"deprecated": "chrome.tabs.onDetached is not current supported in Electron",
|
||||
"type": "function",
|
||||
"description": "Fired when a tab is detached from a window; for example, because it was moved between windows.",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"name": "tabId",
|
||||
"minimum": 0
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"name": "detachInfo",
|
||||
"properties": {
|
||||
"oldWindowId": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"oldPosition": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "onAttached",
|
||||
"deprecated": "chrome.tabs.onAttached is not current supported in Electron",
|
||||
"type": "function",
|
||||
"description": "Fired when a tab is attached to a window; for example, because it was moved between windows.",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"name": "tabId",
|
||||
"minimum": 0
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"name": "attachInfo",
|
||||
"properties": {
|
||||
"newWindowId": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"newPosition": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "onRemoved",
|
||||
"deprecated": "chrome.tabs.onRemoved is not current supported in Electron",
|
||||
"type": "function",
|
||||
"description": "Fired when a tab is closed.",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"name": "tabId",
|
||||
"minimum": 0
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"name": "removeInfo",
|
||||
"properties": {
|
||||
"windowId": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"description": "The window whose tab is closed."
|
||||
},
|
||||
"isWindowClosing": {
|
||||
"type": "boolean",
|
||||
"description": "True when the tab was closed because its parent window was closed."
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "onReplaced",
|
||||
"deprecated": "chrome.tabs.onReplaced is not current supported in Electron",
|
||||
"type": "function",
|
||||
"description": "Fired when a tab is replaced with another tab due to prerendering or instant.",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"name": "addedTabId",
|
||||
"minimum": 0
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"name": "removedTabId",
|
||||
"minimum": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "onZoomChange",
|
||||
"deprecated": "chrome.tabs.onZoomChange is not current supported in Electron",
|
||||
"type": "function",
|
||||
"description": "Fired when a tab is zoomed.",
|
||||
"parameters": [
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include "base/containers/fixed_flat_map.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "base/strings/utf_string_conversion_utils.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "gin/converter.h"
|
||||
#include "gin/data_object_builder.h"
|
||||
@@ -275,11 +276,18 @@ bool Converter<blink::WebKeyboardEvent>::FromV8(v8::Isolate* isolate,
|
||||
|
||||
if ((out->GetType() == blink::WebInputEvent::Type::kChar ||
|
||||
out->GetType() == blink::WebInputEvent::Type::kRawKeyDown)) {
|
||||
// If the keyCode is e.g. Space or Plus we want to use the character
|
||||
// instead of the keyCode: ' ' instead of 'Space', '+' instead of 'Plus'.
|
||||
std::string character_str;
|
||||
if (str.size() > 1 && domKey.IsCharacter())
|
||||
base::WriteUnicodeCharacter(domKey.ToCharacter(), &character_str);
|
||||
|
||||
// Make sure to not read beyond the buffer in case some bad code doesn't
|
||||
// NULL-terminate it (this is called from plugins).
|
||||
size_t text_length_cap = blink::WebKeyboardEvent::kTextLengthCap;
|
||||
std::u16string text16 = base::UTF8ToUTF16(str);
|
||||
|
||||
std::u16string text16 = character_str.empty()
|
||||
? base::UTF8ToUTF16(str)
|
||||
: base::UTF8ToUTF16(character_str);
|
||||
std::fill_n(out->text, text_length_cap, 0);
|
||||
std::fill_n(out->unmodified_text, text_length_cap, 0);
|
||||
for (size_t i = 0; i < std::min(text_length_cap - 1, text16.size()); ++i) {
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
#include "shell/common/gin_helper/event_emitter_caller.h"
|
||||
|
||||
#include "shell/common/gin_helper/locker.h"
|
||||
#include "shell/common/gin_helper/microtasks_scope.h"
|
||||
#include "shell/common/node_includes.h"
|
||||
|
||||
|
||||
@@ -8,10 +8,9 @@
|
||||
|
||||
namespace gin_helper {
|
||||
|
||||
Locker::Locker(v8::Isolate* isolate) {
|
||||
if (electron::IsBrowserProcess())
|
||||
locker_ = std::make_unique<v8::Locker>(isolate);
|
||||
}
|
||||
Locker::Locker(v8::Isolate* isolate)
|
||||
: locker_{electron::IsBrowserProcess() ? new v8::Locker{isolate}
|
||||
: nullptr} {}
|
||||
|
||||
Locker::~Locker() = default;
|
||||
|
||||
|
||||
@@ -22,13 +22,7 @@ class Locker {
|
||||
Locker& operator=(const Locker&) = delete;
|
||||
|
||||
private:
|
||||
void* operator new(size_t size);
|
||||
void operator delete(void*, size_t);
|
||||
|
||||
std::unique_ptr<v8::Locker> locker_;
|
||||
|
||||
static bool g_is_browser_process;
|
||||
static bool g_is_renderer_process;
|
||||
const std::unique_ptr<v8::Locker> locker_;
|
||||
};
|
||||
|
||||
} // namespace gin_helper
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
#include "shell/common/gin_helper/dictionary.h"
|
||||
#include "shell/common/gin_helper/event.h"
|
||||
#include "shell/common/gin_helper/event_emitter_caller.h"
|
||||
#include "shell/common/gin_helper/locker.h"
|
||||
#include "shell/common/gin_helper/microtasks_scope.h"
|
||||
#include "shell/common/mac/main_application_bundle.h"
|
||||
#include "shell/common/world_ids.h"
|
||||
@@ -394,21 +393,11 @@ base::FilePath GetResourcesPath() {
|
||||
return exec_path.DirName().Append(FILE_PATH_LITERAL("resources"));
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NodeBindings::NodeBindings(BrowserEnvironment browser_env)
|
||||
: browser_env_(browser_env) {
|
||||
if (browser_env == BrowserEnvironment::kWorker) {
|
||||
uv_loop_init(&worker_loop_);
|
||||
uv_loop_ = &worker_loop_;
|
||||
} else {
|
||||
uv_loop_ = uv_default_loop();
|
||||
}
|
||||
|
||||
// Interrupt embed polling when a handle is started.
|
||||
uv_loop_configure(uv_loop_, UV_LOOP_INTERRUPT_ON_IO_CHANGE);
|
||||
}
|
||||
: browser_env_{browser_env},
|
||||
uv_loop_{InitEventLoop(browser_env, &worker_loop_)} {}
|
||||
|
||||
NodeBindings::~NodeBindings() {
|
||||
// Quit the embed thread.
|
||||
@@ -429,6 +418,24 @@ NodeBindings::~NodeBindings() {
|
||||
stop_and_close_uv_loop(uv_loop_);
|
||||
}
|
||||
|
||||
// static
|
||||
uv_loop_t* NodeBindings::InitEventLoop(BrowserEnvironment browser_env,
|
||||
uv_loop_t* worker_loop) {
|
||||
uv_loop_t* event_loop = nullptr;
|
||||
|
||||
if (browser_env == BrowserEnvironment::kWorker) {
|
||||
uv_loop_init(worker_loop);
|
||||
event_loop = worker_loop;
|
||||
} else {
|
||||
event_loop = uv_default_loop();
|
||||
}
|
||||
|
||||
// Interrupt embed polling when a handle is started.
|
||||
uv_loop_configure(event_loop, UV_LOOP_INTERRUPT_ON_IO_CHANGE);
|
||||
|
||||
return event_loop;
|
||||
}
|
||||
|
||||
void NodeBindings::RegisterBuiltinBindings() {
|
||||
#define V(modname) _register_##modname();
|
||||
if (IsBrowserProcess()) {
|
||||
@@ -578,6 +585,13 @@ std::shared_ptr<node::Environment> NodeBindings::CreateEnvironment(
|
||||
electron::fuses::IsOnlyLoadAppFromAsarEnabled()
|
||||
? app_asar_search_paths
|
||||
: search_paths));
|
||||
context->Global()->SetPrivate(
|
||||
context,
|
||||
v8::Private::ForApi(
|
||||
isolate, gin::ConvertToV8(isolate, "appSearchPathsOnlyLoadASAR")
|
||||
.As<v8::String>()),
|
||||
gin::ConvertToV8(isolate,
|
||||
electron::fuses::IsOnlyLoadAppFromAsarEnabled()));
|
||||
}
|
||||
|
||||
base::FilePath resources_path = GetResourcesPath();
|
||||
|
||||
@@ -132,9 +132,7 @@ class NodeBindings {
|
||||
void set_uv_env(node::Environment* env) { uv_env_ = env; }
|
||||
node::Environment* uv_env() const { return uv_env_; }
|
||||
|
||||
uv_loop_t* uv_loop() const { return uv_loop_; }
|
||||
|
||||
bool in_worker_loop() const { return uv_loop_ == &worker_loop_; }
|
||||
[[nodiscard]] constexpr uv_loop_t* uv_loop() { return uv_loop_; }
|
||||
|
||||
// disable copy
|
||||
NodeBindings(const NodeBindings&) = delete;
|
||||
@@ -150,25 +148,36 @@ class NodeBindings {
|
||||
// Called to poll events in new thread.
|
||||
virtual void PollEvents() = 0;
|
||||
|
||||
// Run the libuv loop for once.
|
||||
void UvRunOnce();
|
||||
|
||||
// Make the main thread run libuv loop.
|
||||
void WakeupMainThread();
|
||||
|
||||
// Interrupt the PollEvents.
|
||||
void WakeupEmbedThread();
|
||||
|
||||
private:
|
||||
static uv_loop_t* InitEventLoop(BrowserEnvironment browser_env,
|
||||
uv_loop_t* worker_loop);
|
||||
|
||||
// Run the libuv loop for once.
|
||||
void UvRunOnce();
|
||||
|
||||
[[nodiscard]] constexpr bool in_worker_loop() const {
|
||||
return browser_env_ == BrowserEnvironment::kWorker;
|
||||
}
|
||||
|
||||
// Which environment we are running.
|
||||
const BrowserEnvironment browser_env_;
|
||||
|
||||
// Loop used when constructed in WORKER mode
|
||||
uv_loop_t worker_loop_;
|
||||
|
||||
// Current thread's libuv loop.
|
||||
// depends-on: worker_loop_
|
||||
const raw_ptr<uv_loop_t> uv_loop_;
|
||||
|
||||
// Current thread's MessageLoop.
|
||||
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
|
||||
|
||||
// Current thread's libuv loop.
|
||||
raw_ptr<uv_loop_t> uv_loop_;
|
||||
|
||||
private:
|
||||
// Choose a reasonable unique index that's higher than any Blink uses
|
||||
// and thus unlikely to collide with an existing index.
|
||||
static constexpr int kElectronContextEmbedderDataIndex =
|
||||
@@ -192,9 +201,6 @@ class NodeBindings {
|
||||
// Whether the libuv loop has ended.
|
||||
bool embed_closed_ = false;
|
||||
|
||||
// Loop used when constructed in WORKER mode
|
||||
uv_loop_t worker_loop_;
|
||||
|
||||
// Dummy handle to make uv's loop not quit.
|
||||
UvHandle<uv_async_t> dummy_uv_handle_;
|
||||
|
||||
|
||||
@@ -10,7 +10,9 @@ namespace electron {
|
||||
|
||||
NodeBindingsLinux::NodeBindingsLinux(BrowserEnvironment browser_env)
|
||||
: NodeBindings(browser_env), epoll_(epoll_create(1)) {
|
||||
int backend_fd = uv_backend_fd(uv_loop_);
|
||||
auto* const event_loop = uv_loop();
|
||||
|
||||
int backend_fd = uv_backend_fd(event_loop);
|
||||
struct epoll_event ev = {0};
|
||||
ev.events = EPOLLIN;
|
||||
ev.data.fd = backend_fd;
|
||||
@@ -18,7 +20,9 @@ NodeBindingsLinux::NodeBindingsLinux(BrowserEnvironment browser_env)
|
||||
}
|
||||
|
||||
void NodeBindingsLinux::PollEvents() {
|
||||
int timeout = uv_backend_timeout(uv_loop_);
|
||||
auto* const event_loop = uv_loop();
|
||||
|
||||
int timeout = uv_backend_timeout(event_loop);
|
||||
|
||||
// Wait for new libuv events.
|
||||
int r;
|
||||
|
||||
@@ -18,15 +18,17 @@ NodeBindingsMac::NodeBindingsMac(BrowserEnvironment browser_env)
|
||||
: NodeBindings(browser_env) {}
|
||||
|
||||
void NodeBindingsMac::PollEvents() {
|
||||
auto* const event_loop = uv_loop();
|
||||
|
||||
struct timeval tv;
|
||||
int timeout = uv_backend_timeout(uv_loop_);
|
||||
int timeout = uv_backend_timeout(event_loop);
|
||||
if (timeout != -1) {
|
||||
tv.tv_sec = timeout / 1000;
|
||||
tv.tv_usec = (timeout % 1000) * 1000;
|
||||
}
|
||||
|
||||
fd_set readset;
|
||||
int fd = uv_backend_fd(uv_loop_);
|
||||
int fd = uv_backend_fd(event_loop);
|
||||
FD_ZERO(&readset);
|
||||
FD_SET(fd, &readset);
|
||||
|
||||
|
||||
@@ -13,34 +13,39 @@ namespace electron {
|
||||
|
||||
NodeBindingsWin::NodeBindingsWin(BrowserEnvironment browser_env)
|
||||
: NodeBindings(browser_env) {
|
||||
auto* const event_loop = uv_loop();
|
||||
|
||||
// on single-core the io comp port NumberOfConcurrentThreads needs to be 2
|
||||
// to avoid cpu pegging likely caused by a busy loop in PollEvents
|
||||
if (base::SysInfo::NumberOfProcessors() == 1) {
|
||||
// the expectation is the uv_loop_ has just been initialized
|
||||
// the expectation is the event_loop has just been initialized
|
||||
// which makes iocp replacement safe
|
||||
CHECK_EQ(0u, uv_loop_->active_handles);
|
||||
CHECK_EQ(0u, uv_loop_->active_reqs.count);
|
||||
CHECK_EQ(0u, event_loop->active_handles);
|
||||
CHECK_EQ(0u, event_loop->active_reqs.count);
|
||||
|
||||
if (uv_loop_->iocp && uv_loop_->iocp != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(uv_loop_->iocp);
|
||||
uv_loop_->iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 2);
|
||||
if (event_loop->iocp && event_loop->iocp != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(event_loop->iocp);
|
||||
event_loop->iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 2);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeBindingsWin::PollEvents() {
|
||||
auto* const event_loop = uv_loop();
|
||||
|
||||
// If there are other kinds of events pending, uv_backend_timeout will
|
||||
// instruct us not to wait.
|
||||
DWORD bytes, timeout;
|
||||
ULONG_PTR key;
|
||||
OVERLAPPED* overlapped;
|
||||
|
||||
timeout = uv_backend_timeout(uv_loop_);
|
||||
timeout = uv_backend_timeout(event_loop);
|
||||
|
||||
GetQueuedCompletionStatus(uv_loop_->iocp, &bytes, &key, &overlapped, timeout);
|
||||
GetQueuedCompletionStatus(event_loop->iocp, &bytes, &key, &overlapped,
|
||||
timeout);
|
||||
|
||||
// Give the event back so libuv can deal with it.
|
||||
if (overlapped != NULL)
|
||||
PostQueuedCompletionStatus(uv_loop_->iocp, bytes, key, overlapped);
|
||||
PostQueuedCompletionStatus(event_loop->iocp, bytes, key, overlapped);
|
||||
}
|
||||
|
||||
// static
|
||||
|
||||
@@ -27,10 +27,10 @@
|
||||
namespace electron {
|
||||
|
||||
ElectronRendererClient::ElectronRendererClient()
|
||||
: node_bindings_(
|
||||
NodeBindings::Create(NodeBindings::BrowserEnvironment::kRenderer)),
|
||||
electron_bindings_(
|
||||
std::make_unique<ElectronBindings>(node_bindings_->uv_loop())) {}
|
||||
: node_bindings_{NodeBindings::Create(
|
||||
NodeBindings::BrowserEnvironment::kRenderer)},
|
||||
electron_bindings_{
|
||||
std::make_unique<ElectronBindings>(node_bindings_->uv_loop())} {}
|
||||
|
||||
ElectronRendererClient::~ElectronRendererClient() = default;
|
||||
|
||||
|
||||
@@ -51,8 +51,8 @@ class ElectronRendererClient : public RendererClientBase {
|
||||
// Whether the node integration has been initialized.
|
||||
bool node_integration_initialized_ = false;
|
||||
|
||||
std::unique_ptr<NodeBindings> node_bindings_;
|
||||
std::unique_ptr<ElectronBindings> electron_bindings_;
|
||||
const std::unique_ptr<NodeBindings> node_bindings_;
|
||||
const std::unique_ptr<ElectronBindings> electron_bindings_;
|
||||
|
||||
// The node::Environment::GetCurrent API does not return nullptr when it
|
||||
// is called for a context without node::Environment, so we have to keep
|
||||
|
||||
@@ -20,10 +20,10 @@ namespace electron {
|
||||
|
||||
NodeService::NodeService(
|
||||
mojo::PendingReceiver<node::mojom::NodeService> receiver)
|
||||
: node_bindings_(
|
||||
NodeBindings::Create(NodeBindings::BrowserEnvironment::kUtility)),
|
||||
electron_bindings_(
|
||||
std::make_unique<ElectronBindings>(node_bindings_->uv_loop())) {
|
||||
: node_bindings_{NodeBindings::Create(
|
||||
NodeBindings::BrowserEnvironment::kUtility)},
|
||||
electron_bindings_{
|
||||
std::make_unique<ElectronBindings>(node_bindings_->uv_loop())} {
|
||||
if (receiver.is_valid())
|
||||
receiver_.Bind(std::move(receiver));
|
||||
}
|
||||
|
||||
@@ -37,10 +37,18 @@ class NodeService : public node::mojom::NodeService {
|
||||
|
||||
private:
|
||||
bool node_env_stopped_ = false;
|
||||
|
||||
const std::unique_ptr<NodeBindings> node_bindings_;
|
||||
|
||||
// depends-on: node_bindings_'s uv_loop
|
||||
const std::unique_ptr<ElectronBindings> electron_bindings_;
|
||||
|
||||
// depends-on: node_bindings_'s uv_loop
|
||||
std::unique_ptr<JavascriptEnvironment> js_env_;
|
||||
std::unique_ptr<NodeBindings> node_bindings_;
|
||||
std::unique_ptr<ElectronBindings> electron_bindings_;
|
||||
|
||||
// depends-on: js_env_'s isolate
|
||||
std::shared_ptr<node::Environment> node_env_;
|
||||
|
||||
mojo::Receiver<node::mojom::NodeService> receiver_{this};
|
||||
};
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import * as psList from 'ps-list';
|
||||
import { AddressInfo } from 'node:net';
|
||||
import { ifdescribe, ifit } from './lib/spec-helpers';
|
||||
import * as uuid from 'uuid';
|
||||
import { systemPreferences } from 'electron';
|
||||
import { autoUpdater, systemPreferences } from 'electron';
|
||||
|
||||
const features = process._linkedBinding('electron_common_features');
|
||||
|
||||
@@ -129,11 +129,13 @@ ifdescribe(process.platform === 'darwin' && !(process.env.CI && process.arch ===
|
||||
|
||||
const cachedZips: Record<string, string> = {};
|
||||
|
||||
const getOrCreateUpdateZipPath = async (version: string, fixture: string, mutateAppPostSign?: {
|
||||
type Mutation = {
|
||||
mutate: (appPath: string) => Promise<void>,
|
||||
mutationKey: string,
|
||||
}) => {
|
||||
const key = `${version}-${fixture}-${mutateAppPostSign?.mutationKey || 'no-mutation'}`;
|
||||
};
|
||||
|
||||
const getOrCreateUpdateZipPath = async (version: string, fixture: string, mutateAppPreSign?: Mutation, mutateAppPostSign?: Mutation) => {
|
||||
const key = `${version}-${fixture}-${mutateAppPreSign?.mutationKey || 'no-pre-mutation'}-${mutateAppPostSign?.mutationKey || 'no-post-mutation'}`;
|
||||
if (!cachedZips[key]) {
|
||||
let updateZipPath: string;
|
||||
await withTempDirectory(async (dir) => {
|
||||
@@ -143,6 +145,12 @@ ifdescribe(process.platform === 'darwin' && !(process.env.CI && process.arch ===
|
||||
appPJPath,
|
||||
(await fs.readFile(appPJPath, 'utf8')).replace('1.0.0', version)
|
||||
);
|
||||
const infoPath = path.resolve(secondAppPath, 'Contents', 'Info.plist');
|
||||
await fs.writeFile(
|
||||
infoPath,
|
||||
(await fs.readFile(infoPath, 'utf8')).replace(/(<key>CFBundleShortVersionString<\/key>\s+<string>)[^<]+/g, `$1${version}`)
|
||||
);
|
||||
await mutateAppPreSign?.mutate(secondAppPath);
|
||||
await signApp(secondAppPath);
|
||||
await mutateAppPostSign?.mutate(secondAppPath);
|
||||
updateZipPath = path.resolve(dir, 'update.zip');
|
||||
@@ -279,16 +287,20 @@ ifdescribe(process.platform === 'darwin' && !(process.env.CI && process.arch ===
|
||||
nextVersion: string;
|
||||
startFixture: string;
|
||||
endFixture: string;
|
||||
mutateAppPostSign?: {
|
||||
mutate: (appPath: string) => Promise<void>,
|
||||
mutationKey: string,
|
||||
}
|
||||
mutateAppPreSign?: Mutation;
|
||||
mutateAppPostSign?: Mutation;
|
||||
}, fn: (appPath: string, zipPath: string) => Promise<void>) => {
|
||||
await withTempDirectory(async (dir) => {
|
||||
const appPath = await copyApp(dir, opts.startFixture);
|
||||
await opts.mutateAppPreSign?.mutate(appPath);
|
||||
const infoPath = path.resolve(appPath, 'Contents', 'Info.plist');
|
||||
await fs.writeFile(
|
||||
infoPath,
|
||||
(await fs.readFile(infoPath, 'utf8')).replace(/(<key>CFBundleShortVersionString<\/key>\s+<string>)[^<]+/g, '$11.0.0')
|
||||
);
|
||||
await signApp(appPath);
|
||||
|
||||
const updateZipPath = await getOrCreateUpdateZipPath(opts.nextVersion, opts.endFixture, opts.mutateAppPostSign);
|
||||
const updateZipPath = await getOrCreateUpdateZipPath(opts.nextVersion, opts.endFixture, opts.mutateAppPreSign, opts.mutateAppPostSign);
|
||||
|
||||
await fn(appPath, updateZipPath);
|
||||
});
|
||||
@@ -335,6 +347,231 @@ ifdescribe(process.platform === 'darwin' && !(process.env.CI && process.arch ===
|
||||
});
|
||||
});
|
||||
|
||||
it('should hit the download endpoint when an update is available and update successfully when the zip is provided even after a different update was staged', async () => {
|
||||
await withUpdatableApp({
|
||||
nextVersion: '2.0.0',
|
||||
startFixture: 'update-stack',
|
||||
endFixture: 'update-stack'
|
||||
}, async (appPath, updateZipPath2) => {
|
||||
await withUpdatableApp({
|
||||
nextVersion: '3.0.0',
|
||||
startFixture: 'update-stack',
|
||||
endFixture: 'update-stack'
|
||||
}, async (_, updateZipPath3) => {
|
||||
let updateCount = 0;
|
||||
server.get('/update-file', (req, res) => {
|
||||
res.download(updateCount > 1 ? updateZipPath3 : updateZipPath2);
|
||||
});
|
||||
server.get('/update-check', (req, res) => {
|
||||
updateCount++;
|
||||
res.json({
|
||||
url: `http://localhost:${port}/update-file`,
|
||||
name: 'My Release Name',
|
||||
notes: 'Theses are some release notes innit',
|
||||
pub_date: (new Date()).toString()
|
||||
});
|
||||
});
|
||||
const relaunchPromise = new Promise<void>((resolve) => {
|
||||
server.get('/update-check/updated/:version', (req, res) => {
|
||||
res.status(204).send();
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
const launchResult = await launchApp(appPath, [`http://localhost:${port}/update-check`]);
|
||||
logOnError(launchResult, () => {
|
||||
expect(launchResult).to.have.property('code', 0);
|
||||
expect(launchResult.out).to.include('Update Downloaded');
|
||||
expect(requests).to.have.lengthOf(4);
|
||||
expect(requests[0]).to.have.property('url', '/update-check');
|
||||
expect(requests[1]).to.have.property('url', '/update-file');
|
||||
expect(requests[0].header('user-agent')).to.include('Electron/');
|
||||
expect(requests[1].header('user-agent')).to.include('Electron/');
|
||||
expect(requests[2]).to.have.property('url', '/update-check');
|
||||
expect(requests[3]).to.have.property('url', '/update-file');
|
||||
expect(requests[2].header('user-agent')).to.include('Electron/');
|
||||
expect(requests[3].header('user-agent')).to.include('Electron/');
|
||||
});
|
||||
|
||||
await relaunchPromise;
|
||||
expect(requests).to.have.lengthOf(5);
|
||||
expect(requests[4].url).to.equal('/update-check/updated/3.0.0');
|
||||
expect(requests[4].header('user-agent')).to.include('Electron/');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should update to lower version numbers', async () => {
|
||||
await withUpdatableApp({
|
||||
nextVersion: '0.0.1',
|
||||
startFixture: 'update',
|
||||
endFixture: 'update'
|
||||
}, async (appPath, updateZipPath) => {
|
||||
server.get('/update-file', (req, res) => {
|
||||
res.download(updateZipPath);
|
||||
});
|
||||
server.get('/update-check', (req, res) => {
|
||||
res.json({
|
||||
url: `http://localhost:${port}/update-file`,
|
||||
name: 'My Release Name',
|
||||
notes: 'Theses are some release notes innit',
|
||||
pub_date: (new Date()).toString()
|
||||
});
|
||||
});
|
||||
const relaunchPromise = new Promise<void>((resolve) => {
|
||||
server.get('/update-check/updated/:version', (req, res) => {
|
||||
res.status(204).send();
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
const launchResult = await launchApp(appPath, [`http://localhost:${port}/update-check`]);
|
||||
logOnError(launchResult, () => {
|
||||
expect(launchResult).to.have.property('code', 0);
|
||||
expect(launchResult.out).to.include('Update Downloaded');
|
||||
expect(requests).to.have.lengthOf(2);
|
||||
expect(requests[0]).to.have.property('url', '/update-check');
|
||||
expect(requests[1]).to.have.property('url', '/update-file');
|
||||
expect(requests[0].header('user-agent')).to.include('Electron/');
|
||||
expect(requests[1].header('user-agent')).to.include('Electron/');
|
||||
});
|
||||
|
||||
await relaunchPromise;
|
||||
expect(requests).to.have.lengthOf(3);
|
||||
expect(requests[2].url).to.equal('/update-check/updated/0.0.1');
|
||||
expect(requests[2].header('user-agent')).to.include('Electron/');
|
||||
});
|
||||
});
|
||||
|
||||
describe('with ElectronSquirrelPreventDowngrades enabled', () => {
|
||||
it('should not update to lower version numbers', async () => {
|
||||
await withUpdatableApp({
|
||||
nextVersion: '0.0.1',
|
||||
startFixture: 'update',
|
||||
endFixture: 'update',
|
||||
mutateAppPreSign: {
|
||||
mutationKey: 'prevent-downgrades',
|
||||
mutate: async (appPath) => {
|
||||
const infoPath = path.resolve(appPath, 'Contents', 'Info.plist');
|
||||
await fs.writeFile(
|
||||
infoPath,
|
||||
(await fs.readFile(infoPath, 'utf8')).replace('<key>NSSupportsAutomaticGraphicsSwitching</key>', '<key>ElectronSquirrelPreventDowngrades</key><true/><key>NSSupportsAutomaticGraphicsSwitching</key>')
|
||||
);
|
||||
}
|
||||
}
|
||||
}, async (appPath, updateZipPath) => {
|
||||
server.get('/update-file', (req, res) => {
|
||||
res.download(updateZipPath);
|
||||
});
|
||||
server.get('/update-check', (req, res) => {
|
||||
res.json({
|
||||
url: `http://localhost:${port}/update-file`,
|
||||
name: 'My Release Name',
|
||||
notes: 'Theses are some release notes innit',
|
||||
pub_date: (new Date()).toString()
|
||||
});
|
||||
});
|
||||
const launchResult = await launchApp(appPath, [`http://localhost:${port}/update-check`]);
|
||||
logOnError(launchResult, () => {
|
||||
expect(launchResult).to.have.property('code', 1);
|
||||
expect(launchResult.out).to.include('Cannot update to a bundle with a lower version number');
|
||||
expect(requests).to.have.lengthOf(2);
|
||||
expect(requests[0]).to.have.property('url', '/update-check');
|
||||
expect(requests[1]).to.have.property('url', '/update-file');
|
||||
expect(requests[0].header('user-agent')).to.include('Electron/');
|
||||
expect(requests[1].header('user-agent')).to.include('Electron/');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should not update to version strings that are not simple Major.Minor.Patch', async () => {
|
||||
await withUpdatableApp({
|
||||
nextVersion: '2.0.0-bad',
|
||||
startFixture: 'update',
|
||||
endFixture: 'update',
|
||||
mutateAppPreSign: {
|
||||
mutationKey: 'prevent-downgrades',
|
||||
mutate: async (appPath) => {
|
||||
const infoPath = path.resolve(appPath, 'Contents', 'Info.plist');
|
||||
await fs.writeFile(
|
||||
infoPath,
|
||||
(await fs.readFile(infoPath, 'utf8')).replace('<key>NSSupportsAutomaticGraphicsSwitching</key>', '<key>ElectronSquirrelPreventDowngrades</key><true/><key>NSSupportsAutomaticGraphicsSwitching</key>')
|
||||
);
|
||||
}
|
||||
}
|
||||
}, async (appPath, updateZipPath) => {
|
||||
server.get('/update-file', (req, res) => {
|
||||
res.download(updateZipPath);
|
||||
});
|
||||
server.get('/update-check', (req, res) => {
|
||||
res.json({
|
||||
url: `http://localhost:${port}/update-file`,
|
||||
name: 'My Release Name',
|
||||
notes: 'Theses are some release notes innit',
|
||||
pub_date: (new Date()).toString()
|
||||
});
|
||||
});
|
||||
const launchResult = await launchApp(appPath, [`http://localhost:${port}/update-check`]);
|
||||
logOnError(launchResult, () => {
|
||||
expect(launchResult).to.have.property('code', 1);
|
||||
expect(launchResult.out).to.include('Cannot update to a bundle with a lower version number');
|
||||
expect(requests).to.have.lengthOf(2);
|
||||
expect(requests[0]).to.have.property('url', '/update-check');
|
||||
expect(requests[1]).to.have.property('url', '/update-file');
|
||||
expect(requests[0].header('user-agent')).to.include('Electron/');
|
||||
expect(requests[1].header('user-agent')).to.include('Electron/');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should still update to higher version numbers', async () => {
|
||||
await withUpdatableApp({
|
||||
nextVersion: '1.0.1',
|
||||
startFixture: 'update',
|
||||
endFixture: 'update'
|
||||
}, async (appPath, updateZipPath) => {
|
||||
server.get('/update-file', (req, res) => {
|
||||
res.download(updateZipPath);
|
||||
});
|
||||
server.get('/update-check', (req, res) => {
|
||||
res.json({
|
||||
url: `http://localhost:${port}/update-file`,
|
||||
name: 'My Release Name',
|
||||
notes: 'Theses are some release notes innit',
|
||||
pub_date: (new Date()).toString()
|
||||
});
|
||||
});
|
||||
const relaunchPromise = new Promise<void>((resolve) => {
|
||||
server.get('/update-check/updated/:version', (req, res) => {
|
||||
res.status(204).send();
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
const launchResult = await launchApp(appPath, [`http://localhost:${port}/update-check`]);
|
||||
logOnError(launchResult, () => {
|
||||
expect(launchResult).to.have.property('code', 0);
|
||||
expect(launchResult.out).to.include('Update Downloaded');
|
||||
expect(requests).to.have.lengthOf(2);
|
||||
expect(requests[0]).to.have.property('url', '/update-check');
|
||||
expect(requests[1]).to.have.property('url', '/update-file');
|
||||
expect(requests[0].header('user-agent')).to.include('Electron/');
|
||||
expect(requests[1].header('user-agent')).to.include('Electron/');
|
||||
});
|
||||
|
||||
await relaunchPromise;
|
||||
expect(requests).to.have.lengthOf(3);
|
||||
expect(requests[2].url).to.equal('/update-check/updated/1.0.1');
|
||||
expect(requests[2].header('user-agent')).to.include('Electron/');
|
||||
});
|
||||
});
|
||||
|
||||
it('should compare version numbers correctly', () => {
|
||||
expect(autoUpdater.isVersionAllowedForUpdate('1.0.0', '2.0.0')).to.equal(true);
|
||||
expect(autoUpdater.isVersionAllowedForUpdate('1.0.1', '1.0.10')).to.equal(true);
|
||||
expect(autoUpdater.isVersionAllowedForUpdate('1.0.10', '1.0.1')).to.equal(false);
|
||||
expect(autoUpdater.isVersionAllowedForUpdate('1.31.1', '1.32.0')).to.equal(true);
|
||||
expect(autoUpdater.isVersionAllowedForUpdate('1.31.1', '0.32.0')).to.equal(false);
|
||||
});
|
||||
});
|
||||
|
||||
it('should abort the update if the application is still running when ShipIt kicks off', async () => {
|
||||
await withUpdatableApp({
|
||||
nextVersion: '2.0.0',
|
||||
|
||||
@@ -3425,7 +3425,7 @@ describe('BrowserWindow module', () => {
|
||||
w.loadURL(pageUrl);
|
||||
const [, url] = await once(ipcMain, 'answer');
|
||||
const expectedUrl = process.platform === 'win32'
|
||||
? 'file:///' + htmlPath.replace(/\\/g, '/')
|
||||
? 'file:///' + htmlPath.replaceAll('\\', '/')
|
||||
: pageUrl;
|
||||
expect(url).to.equal(expectedUrl);
|
||||
});
|
||||
@@ -3475,7 +3475,7 @@ describe('BrowserWindow module', () => {
|
||||
w.loadURL(pageUrl);
|
||||
const [, { url, frameName, options }] = await once(w.webContents, 'did-create-window') as [BrowserWindow, Electron.DidCreateWindowDetails];
|
||||
const expectedUrl = process.platform === 'win32'
|
||||
? 'file:///' + htmlPath.replace(/\\/g, '/')
|
||||
? 'file:///' + htmlPath.replaceAll('\\', '/')
|
||||
: pageUrl;
|
||||
expect(url).to.equal(expectedUrl);
|
||||
expect(frameName).to.equal('popup!');
|
||||
|
||||
@@ -111,7 +111,7 @@ describe('debugger module', () => {
|
||||
it('fires message event', async () => {
|
||||
const url = process.platform !== 'win32'
|
||||
? `file://${path.join(fixtures, 'pages', 'a.html')}`
|
||||
: `file:///${path.join(fixtures, 'pages', 'a.html').replace(/\\/g, '/')}`;
|
||||
: `file:///${path.join(fixtures, 'pages', 'a.html').replaceAll('\\', '/')}`;
|
||||
w.webContents.loadURL(url);
|
||||
w.webContents.debugger.attach();
|
||||
const message = emittedUntil(w.webContents.debugger, 'message',
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import { expect } from 'chai';
|
||||
import { nativeTheme, systemPreferences, BrowserWindow, ipcMain } from 'electron/main';
|
||||
import { nativeTheme, BrowserWindow, ipcMain } from 'electron/main';
|
||||
import { once } from 'node:events';
|
||||
import * as path from 'node:path';
|
||||
import { setTimeout } from 'node:timers/promises';
|
||||
|
||||
import { expectDeprecationMessages } from './lib/deprecate-helpers';
|
||||
import { ifdescribe } from './lib/spec-helpers';
|
||||
import { closeAllWindows } from './lib/window-helpers';
|
||||
|
||||
describe('nativeTheme module', () => {
|
||||
@@ -59,20 +57,6 @@ describe('nativeTheme module', () => {
|
||||
expect(called).to.equal(false);
|
||||
});
|
||||
|
||||
ifdescribe(process.platform === 'darwin')('on macOS', () => {
|
||||
it('should update appLevelAppearance when set', async () => {
|
||||
await expectDeprecationMessages(
|
||||
() => {
|
||||
nativeTheme.themeSource = 'dark';
|
||||
expect(systemPreferences.appLevelAppearance).to.equal('dark');
|
||||
nativeTheme.themeSource = 'light';
|
||||
expect(systemPreferences.appLevelAppearance).to.equal('light');
|
||||
},
|
||||
"(electron) 'appLevelAppearance' is deprecated and will be removed."
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
const getPrefersColorSchemeIsDark = async (w: Electron.BrowserWindow) => {
|
||||
const isDark: boolean = await w.webContents.executeJavaScript(
|
||||
'matchMedia("(prefers-color-scheme: dark)").matches'
|
||||
|
||||
@@ -1128,7 +1128,7 @@ describe('protocol module', () => {
|
||||
protocol.handle('file', (req) => {
|
||||
let file;
|
||||
if (process.platform === 'win32') {
|
||||
file = `file:///${filePath.replace(/\\/g, '/')}`;
|
||||
file = `file:///${filePath.replaceAll('\\', '/')}`;
|
||||
} else {
|
||||
file = `file://${filePath}`;
|
||||
}
|
||||
|
||||
@@ -237,7 +237,7 @@ describe('session module', () => {
|
||||
|
||||
appProcess.stdout.on('data', data => { output += data; });
|
||||
appProcess.on('exit', () => {
|
||||
resolve(output.replace(/(\r\n|\n|\r)/gm, ''));
|
||||
resolve(output.replaceAll(/(\r\n|\n|\r)/gm, ''));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { expect } from 'chai';
|
||||
import { systemPreferences } from 'electron/main';
|
||||
import { expectDeprecationMessages } from './lib/deprecate-helpers';
|
||||
import { ifdescribe } from './lib/spec-helpers';
|
||||
|
||||
describe('systemPreferences module', () => {
|
||||
@@ -215,52 +214,6 @@ describe('systemPreferences module', () => {
|
||||
const sysColor = systemPreferences.getColor(color);
|
||||
expect(sysColor).to.be.a('string');
|
||||
}
|
||||
|
||||
await expectDeprecationMessages(
|
||||
() => {
|
||||
const sysColor = systemPreferences.getColor('alternate-selected-control-text');
|
||||
expect(sysColor).to.be.a('string');
|
||||
},
|
||||
"'alternate-selected-control-text' is deprecated as an input to getColor. Use 'selected-content-background' instead."
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
ifdescribe(process.platform === 'darwin')('systemPreferences.appLevelAppearance', () => {
|
||||
const options = ['dark', 'light', 'unknown', null];
|
||||
describe('with properties', () => {
|
||||
it('returns a valid appearance', () => {
|
||||
const appearance = systemPreferences.appLevelAppearance;
|
||||
expect(options).to.include(appearance);
|
||||
});
|
||||
|
||||
it('can be changed', () => {
|
||||
systemPreferences.appLevelAppearance = 'dark';
|
||||
expect(systemPreferences.appLevelAppearance).to.eql('dark');
|
||||
});
|
||||
});
|
||||
|
||||
describe('with functions', () => {
|
||||
it('returns a valid appearance', async () => {
|
||||
await expectDeprecationMessages(
|
||||
() => {
|
||||
const appearance = systemPreferences.getAppLevelAppearance();
|
||||
expect(options).to.include(appearance);
|
||||
},
|
||||
"(electron) 'getAppLevelAppearance function' is deprecated and will be removed."
|
||||
);
|
||||
});
|
||||
|
||||
it('can be changed', async () => {
|
||||
await expectDeprecationMessages(
|
||||
() => {
|
||||
systemPreferences.setAppLevelAppearance('dark');
|
||||
const appearance = systemPreferences.getAppLevelAppearance();
|
||||
expect(appearance).to.eql('dark');
|
||||
},
|
||||
"(electron) 'setAppLevelAppearance function' is deprecated and will be removed."
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -839,6 +839,20 @@ describe('webContents module', () => {
|
||||
expect(altKey).to.be.false();
|
||||
});
|
||||
|
||||
it('can correctly convert accelerators to key codes', async () => {
|
||||
const keyup = once(ipcMain, 'keyup');
|
||||
w.webContents.sendInputEvent({ keyCode: 'Plus', type: 'char' });
|
||||
w.webContents.sendInputEvent({ keyCode: 'Space', type: 'char' });
|
||||
w.webContents.sendInputEvent({ keyCode: 'Plus', type: 'char' });
|
||||
w.webContents.sendInputEvent({ keyCode: 'Space', type: 'char' });
|
||||
w.webContents.sendInputEvent({ keyCode: 'Plus', type: 'char' });
|
||||
w.webContents.sendInputEvent({ keyCode: 'Plus', type: 'keyUp' });
|
||||
|
||||
await keyup;
|
||||
const inputText = await w.webContents.executeJavaScript('document.getElementById("input").value');
|
||||
expect(inputText).to.equal('+ + +');
|
||||
});
|
||||
|
||||
it('can send char events with modifiers', async () => {
|
||||
const keypress = once(ipcMain, 'keypress');
|
||||
w.webContents.sendInputEvent({ type: 'keyDown', keyCode: 'Z' });
|
||||
|
||||
@@ -181,7 +181,7 @@ describe('webRequest module', () => {
|
||||
callback({ cancel: true });
|
||||
});
|
||||
const fileURL = url.format({
|
||||
pathname: path.join(fixturesPath, 'blank.html').replace(/\\/g, '/'),
|
||||
pathname: path.join(fixturesPath, 'blank.html').replaceAll('\\', '/'),
|
||||
protocol: 'file',
|
||||
slashes: true
|
||||
});
|
||||
@@ -395,7 +395,7 @@ describe('webRequest module', () => {
|
||||
onSendHeadersCalled = true;
|
||||
});
|
||||
await ajax(url.format({
|
||||
pathname: path.join(fixturesPath, 'blank.html').replace(/\\/g, '/'),
|
||||
pathname: path.join(fixturesPath, 'blank.html').replaceAll('\\', '/'),
|
||||
protocol: 'file',
|
||||
slashes: true
|
||||
}));
|
||||
|
||||
@@ -90,7 +90,7 @@ describe('asar package', () => {
|
||||
await w.loadFile(path.join(fixtures, 'workers', 'load_worker.html'));
|
||||
|
||||
const workerUrl = url.format({
|
||||
pathname: path.resolve(fixtures, 'workers', 'workers.asar', 'worker.js').replace(/\\/g, '/'),
|
||||
pathname: path.resolve(fixtures, 'workers', 'workers.asar', 'worker.js').replaceAll('\\', '/'),
|
||||
protocol: 'file',
|
||||
slashes: true
|
||||
});
|
||||
@@ -103,7 +103,7 @@ describe('asar package', () => {
|
||||
await w.loadFile(path.join(fixtures, 'workers', 'load_shared_worker.html'));
|
||||
|
||||
const workerUrl = url.format({
|
||||
pathname: path.resolve(fixtures, 'workers', 'workers.asar', 'shared_worker.js').replace(/\\/g, '/'),
|
||||
pathname: path.resolve(fixtures, 'workers', 'workers.asar', 'shared_worker.js').replaceAll('\\', '/'),
|
||||
protocol: 'file',
|
||||
slashes: true
|
||||
});
|
||||
@@ -1243,7 +1243,7 @@ describe('asar package', function () {
|
||||
const echo = path.join(asarDir, 'echo.asar', 'echo');
|
||||
|
||||
const stdout = await promisify(require(childProcess).exec)('echo ' + echo + ' foo bar');
|
||||
expect(stdout.toString().replace(/\r/g, '')).to.equal(echo + ' foo bar\n');
|
||||
expect(stdout.toString().replaceAll('\r', '')).to.equal(echo + ' foo bar\n');
|
||||
}, [childProcess]);
|
||||
});
|
||||
|
||||
@@ -1252,7 +1252,7 @@ describe('asar package', function () {
|
||||
const echo = path.join(asarDir, 'echo.asar', 'echo');
|
||||
|
||||
const stdout = require(childProcess).execSync('echo ' + echo + ' foo bar');
|
||||
expect(stdout.toString().replace(/\r/g, '')).to.equal(echo + ' foo bar\n');
|
||||
expect(stdout.toString().replaceAll('\r', '')).to.equal(echo + ' foo bar\n');
|
||||
}, [childProcess]);
|
||||
});
|
||||
|
||||
|
||||
@@ -284,7 +284,7 @@ describe('web security', () => {
|
||||
describe('accessing file://', () => {
|
||||
async function loadFile (w: BrowserWindow) {
|
||||
const thisFile = url.format({
|
||||
pathname: __filename.replace(/\\/g, '/'),
|
||||
pathname: __filename.replaceAll('\\', '/'),
|
||||
protocol: 'file',
|
||||
slashes: true
|
||||
});
|
||||
@@ -461,7 +461,7 @@ describe('command line switches', () => {
|
||||
throw new Error(`Process exited with code "${code}" signal "${signal}" output "${output}" stderr "${stderr}"`);
|
||||
}
|
||||
|
||||
output = output.replace(/(\r\n|\n|\r)/gm, '');
|
||||
output = output.replaceAll(/(\r\n|\n|\r)/gm, '');
|
||||
expect(output).to.equal(result);
|
||||
};
|
||||
|
||||
@@ -1050,7 +1050,7 @@ describe('chromium features', () => {
|
||||
it('defines a window.location getter', async () => {
|
||||
let targetURL: string;
|
||||
if (process.platform === 'win32') {
|
||||
targetURL = `file:///${fixturesPath.replace(/\\/g, '/')}/pages/base-page.html`;
|
||||
targetURL = `file:///${fixturesPath.replaceAll('\\', '/')}/pages/base-page.html`;
|
||||
} else {
|
||||
targetURL = `file://${fixturesPath}/pages/base-page.html`;
|
||||
}
|
||||
@@ -1977,7 +1977,7 @@ describe('chromium features', () => {
|
||||
|
||||
ifdescribe(features.isPDFViewerEnabled())('PDF Viewer', () => {
|
||||
const pdfSource = url.format({
|
||||
pathname: path.join(__dirname, 'fixtures', 'cat.pdf').replace(/\\/g, '/'),
|
||||
pathname: path.join(__dirname, 'fixtures', 'cat.pdf').replaceAll('\\', '/'),
|
||||
protocol: 'file',
|
||||
slashes: true
|
||||
});
|
||||
|
||||
57
spec/fixtures/auto-update/update-stack/index.js
vendored
Normal file
57
spec/fixtures/auto-update/update-stack/index.js
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
|
||||
process.on('uncaughtException', (err) => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
const { app, autoUpdater } = require('electron');
|
||||
|
||||
autoUpdater.on('error', (err) => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
const urlPath = path.resolve(__dirname, '../../../../url.txt');
|
||||
let feedUrl = process.argv[1];
|
||||
|
||||
if (feedUrl === 'remain-open') {
|
||||
// Hold the event loop
|
||||
setInterval(() => {});
|
||||
} else {
|
||||
if (!feedUrl || !feedUrl.startsWith('http')) {
|
||||
feedUrl = `${fs.readFileSync(urlPath, 'utf8')}/${app.getVersion()}`;
|
||||
} else {
|
||||
fs.writeFileSync(urlPath, `${feedUrl}/updated`);
|
||||
}
|
||||
|
||||
autoUpdater.setFeedURL({
|
||||
url: feedUrl
|
||||
});
|
||||
|
||||
autoUpdater.checkForUpdates();
|
||||
|
||||
autoUpdater.on('update-available', () => {
|
||||
console.log('Update Available');
|
||||
});
|
||||
|
||||
let updateStackCount = 0;
|
||||
|
||||
autoUpdater.on('update-downloaded', () => {
|
||||
updateStackCount++;
|
||||
console.log('Update Downloaded');
|
||||
if (updateStackCount > 1) {
|
||||
autoUpdater.quitAndInstall();
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
autoUpdater.checkForUpdates();
|
||||
}, 1000);
|
||||
}
|
||||
});
|
||||
|
||||
autoUpdater.on('update-not-available', () => {
|
||||
console.error('No update available');
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
5
spec/fixtures/auto-update/update-stack/package.json
vendored
Normal file
5
spec/fixtures/auto-update/update-stack/package.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "electron-test-update-stack",
|
||||
"version": "1.0.0",
|
||||
"main": "./index.js"
|
||||
}
|
||||
10
spec/fixtures/pages/key-events.html
vendored
10
spec/fixtures/pages/key-events.html
vendored
@@ -1,11 +1,17 @@
|
||||
<html>
|
||||
<body>
|
||||
<input type="text" id="input" autofocus/>
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
document.onkeydown = function (e) {
|
||||
require('electron').ipcRenderer.send('keydown', e.key, e.code, e.keyCode, e.shiftKey, e.ctrlKey, e.altKey)
|
||||
ipcRenderer.send('keydown', e.key, e.code, e.keyCode, e.shiftKey, e.ctrlKey, e.altKey)
|
||||
}
|
||||
document.onkeypress = function (e) {
|
||||
require('electron').ipcRenderer.send('keypress', e.key, e.code, e.keyCode, e.shiftKey, e.ctrlKey, e.altKey)
|
||||
ipcRenderer.send('keypress', e.key, e.code, e.keyCode, e.shiftKey, e.ctrlKey, e.altKey)
|
||||
}
|
||||
document.onkeyup = function (e) {
|
||||
ipcRenderer.send('keyup', e.key, e.code, e.keyCode, e.shiftKey, e.ctrlKey, e.altKey)
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
@@ -7,7 +7,7 @@ import { closeAllWindows } from './lib/window-helpers';
|
||||
import * as childProcess from 'node:child_process';
|
||||
import { once } from 'node:events';
|
||||
|
||||
const Module = require('node:module');
|
||||
const Module = require('node:module') as NodeJS.ModuleInternal;
|
||||
|
||||
const nativeModulesEnabled = !process.env.ELECTRON_SKIP_NATIVE_MODULE_TESTS;
|
||||
|
||||
|
||||
@@ -377,6 +377,14 @@ if (process.platform === 'darwin') {
|
||||
console.log(value);
|
||||
const value2 = systemPreferences.getUserDefault('Foo', 'boolean');
|
||||
console.log(value2);
|
||||
// @ts-expect-error Removed API
|
||||
console.log(systemPreferences.getAppLevelAppearance());
|
||||
// @ts-expect-error Removed API
|
||||
systemPreferences.setAppLevelAppearance('dark');
|
||||
// @ts-expect-error Removed API
|
||||
console.log(systemPreferences.appLevelAppearance);
|
||||
// @ts-expect-error Removed API
|
||||
console.log(systemPreferences.getColor('alternate-selected-control-text'));
|
||||
}
|
||||
|
||||
// Create the window.
|
||||
|
||||
@@ -249,7 +249,7 @@ describe('<webview> tag', function () {
|
||||
});
|
||||
await w.loadURL('about:blank');
|
||||
const src = url.format({
|
||||
pathname: `${fixtures.replace(/\\/g, '/')}/pages/theme-color.html`,
|
||||
pathname: `${fixtures.replaceAll('\\', '/')}/pages/theme-color.html`,
|
||||
protocol: 'file',
|
||||
slashes: true
|
||||
});
|
||||
|
||||
12
typings/internal-ambient.d.ts
vendored
12
typings/internal-ambient.d.ts
vendored
@@ -3,6 +3,17 @@ declare const BUILDFLAG: (flag: boolean) => boolean;
|
||||
declare const ENABLE_VIEWS_API: boolean;
|
||||
|
||||
declare namespace NodeJS {
|
||||
interface ModuleInternal extends NodeJS.Module {
|
||||
new(id: string, parent?: NodeJS.Module | null): NodeJS.Module;
|
||||
_load(request: string, parent?: NodeJS.Module | null, isMain?: boolean): any;
|
||||
_resolveFilename(request: string, parent?: NodeJS.Module | null, isMain?: boolean, options?: { paths: string[] }): string;
|
||||
_preloadModules(requests: string[]): void;
|
||||
_nodeModulePaths(from: string): string[];
|
||||
_extensions: Record<string, (module: NodeJS.Module, filename: string) => any>;
|
||||
_cache: Record<string, NodeJS.Module>;
|
||||
wrapper: [string, string];
|
||||
}
|
||||
|
||||
interface FeaturesBinding {
|
||||
isBuiltinSpellCheckerEnabled(): boolean;
|
||||
isPDFViewerEnabled(): boolean;
|
||||
@@ -243,6 +254,7 @@ declare namespace NodeJS {
|
||||
// Additional properties
|
||||
_firstFileName?: string;
|
||||
_serviceStartupScript: string;
|
||||
_getOrCreateArchive?: (path: string) => NodeJS.AsarArchive | null;
|
||||
|
||||
helperExecPath: string;
|
||||
mainModule?: NodeJS.Module | undefined;
|
||||
|
||||
4
typings/internal-electron.d.ts
vendored
4
typings/internal-electron.d.ts
vendored
@@ -19,6 +19,10 @@ declare namespace Electron {
|
||||
setAppPath(path: string | null): void;
|
||||
}
|
||||
|
||||
interface AutoUpdater {
|
||||
isVersionAllowedForUpdate(currentVersion: string, targetVersion: string): boolean;
|
||||
}
|
||||
|
||||
type TouchBarItemType = NonNullable<Electron.TouchBarConstructorOptions['items']>[0];
|
||||
|
||||
interface BaseWindow {
|
||||
|
||||
14
yarn.lock
14
yarn.lock
@@ -199,10 +199,10 @@
|
||||
"@octokit/auth-app" "^4.0.13"
|
||||
"@octokit/rest" "^19.0.11"
|
||||
|
||||
"@electron/lint-roller@^1.8.0":
|
||||
version "1.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@electron/lint-roller/-/lint-roller-1.8.0.tgz#26c29f2b2b7eaa9429fde04b178d7fdfe9d56da9"
|
||||
integrity sha512-4LKE2SeSM3kdorDoFMzvZBTKvNUPAJl8apH9e1E9Gb5SKhFBZuG9CIJwtPKwtRYiGmBfu/HxoHuGEGkycxM+3Q==
|
||||
"@electron/lint-roller@^1.9.0":
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@electron/lint-roller/-/lint-roller-1.9.0.tgz#784d2b9b7664dc7b696cc57cf6c9e181ea701e76"
|
||||
integrity sha512-DgZJdzSAG19PotTPhWM4Xgt0RDv/nJS1JNKpJdvOUv2AsdU0rIq3kDAzm2AdzIW/AlrOnkpUA1UJNezdIAIA4g==
|
||||
dependencies:
|
||||
"@dsanders11/vscode-markdown-languageservice" "^0.3.0"
|
||||
balanced-match "^2.0.0"
|
||||
@@ -220,9 +220,9 @@
|
||||
vscode-uri "^3.0.7"
|
||||
|
||||
"@electron/typescript-definitions@^8.14.5":
|
||||
version "8.14.5"
|
||||
resolved "https://registry.yarnpkg.com/@electron/typescript-definitions/-/typescript-definitions-8.14.5.tgz#07ffc7dac6008e0f659215e3b88bc0d7c6bc6ece"
|
||||
integrity sha512-68JfMTcj6X7B0dhjhj8lGGnnOlfuiR4f+2UBEtQDYRHfeSuFriKErno3Lh+jAolGSqhw39qr4lLO+FGToVdCew==
|
||||
version "8.14.6"
|
||||
resolved "https://registry.yarnpkg.com/@electron/typescript-definitions/-/typescript-definitions-8.14.6.tgz#78ba1fa8314f06255bb9309791b33c9695ac42ef"
|
||||
integrity sha512-HK70Q3nrp6h4cCxb/P65vFixdJ99vABLIG8TpqU21/fmuHdYboL4zcleWaYhXhU2EwduuOPfORFMrUTdBRc+lw==
|
||||
dependencies:
|
||||
"@types/node" "^11.13.7"
|
||||
chalk "^2.4.2"
|
||||
|
||||
Reference in New Issue
Block a user