mirror of
https://github.com/electron/electron.git
synced 2026-02-26 03:01:17 -05:00
Compare commits
52 Commits
v27.0.0-be
...
v27.0.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6de96fb83b | ||
|
|
cf0e974ce1 | ||
|
|
7e2073226a | ||
|
|
8f370cd2e3 | ||
|
|
82d4e9427f | ||
|
|
f0b742f2d6 | ||
|
|
2bc07b098b | ||
|
|
d95f28c194 | ||
|
|
22ea11175b | ||
|
|
5b44e82eb4 | ||
|
|
4c4a3e7594 | ||
|
|
bf7474d3f4 | ||
|
|
3f142ad039 | ||
|
|
10db23828e | ||
|
|
43ba54e61f | ||
|
|
3fdfcbb5dd | ||
|
|
9e8cba981a | ||
|
|
a85c6cf0e5 | ||
|
|
7e536dfd8e | ||
|
|
7d21d113d2 | ||
|
|
7ed33db12e | ||
|
|
66c4f9cb6f | ||
|
|
a00155dcfc | ||
|
|
3e4adb91c5 | ||
|
|
f63f02fbb2 | ||
|
|
a3a6e8ff26 | ||
|
|
e70a25d5a3 | ||
|
|
8e2cf54f29 | ||
|
|
a3614983de | ||
|
|
686adf9d15 | ||
|
|
25dccaa1b1 | ||
|
|
175cd9111e | ||
|
|
70236258cf | ||
|
|
d0d9011fc9 | ||
|
|
8423a014ed | ||
|
|
4ba1b219a5 | ||
|
|
e721b683bf | ||
|
|
271be9c8e4 | ||
|
|
946df59915 | ||
|
|
77a02d858b | ||
|
|
f648dbe081 | ||
|
|
c572477606 | ||
|
|
3b07ed95a4 | ||
|
|
d689830214 | ||
|
|
e53d5f4949 | ||
|
|
6a59b373a6 | ||
|
|
036a382d66 | ||
|
|
c4a54202b9 | ||
|
|
c128893a4c | ||
|
|
b9e0f097bd | ||
|
|
78a99d673e | ||
|
|
75f5706d6c |
@@ -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 >>
|
||||
@@ -349,7 +359,7 @@ step-setup-goma-for-build: &step-setup-goma-for-build
|
||||
exit 1
|
||||
fi
|
||||
echo 'export GN_GOMA_FILE='`node -e "console.log(require('./src/utils/goma.js').gnFilePath)"` >> $BASH_ENV
|
||||
echo 'export LOCAL_GOMA_DIR='`node -e "console.log(require('./src/utils/goma.js').dir)"` >> $BASH_ENV
|
||||
echo 'export GOMA_DIR='`node -e "console.log(require('./src/utils/goma.js').dir)"` >> $BASH_ENV
|
||||
echo 'export GOMA_FALLBACK_ON_AUTH_FAILURE=true' >> $BASH_ENV
|
||||
cd ..
|
||||
touch "${TMPDIR:=/tmp}"/.goma-ready
|
||||
@@ -744,8 +754,8 @@ step-show-goma-stats: &step-show-goma-stats
|
||||
command: |
|
||||
set +e
|
||||
set +o pipefail
|
||||
$LOCAL_GOMA_DIR/goma_ctl.py stat
|
||||
$LOCAL_GOMA_DIR/diagnose_goma_log.py
|
||||
python3 $GOMA_DIR/goma_ctl.py stat
|
||||
python3 $GOMA_DIR/diagnose_goma_log.py
|
||||
true
|
||||
when: always
|
||||
background: true
|
||||
@@ -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:
|
||||
@@ -1005,15 +1049,6 @@ step-ts-compile: &step-ts-compile
|
||||
done
|
||||
|
||||
# List of all steps.
|
||||
steps-electron-gn-check: &steps-electron-gn-check
|
||||
steps:
|
||||
- *step-setup-goma-for-build
|
||||
- checkout-from-cache
|
||||
- *step-setup-env-for-build
|
||||
- *step-wait-for-goma
|
||||
- *step-gn-gen-default
|
||||
- *step-gn-check
|
||||
|
||||
steps-electron-ts-compile-for-doc-change: &steps-electron-ts-compile-for-doc-change
|
||||
steps:
|
||||
# Checkout - Copied from steps-checkout
|
||||
@@ -1025,11 +1060,92 @@ 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
|
||||
could-be-aks:
|
||||
type: boolean
|
||||
description: Only set this to true on linux hosts
|
||||
steps:
|
||||
- when:
|
||||
condition:
|
||||
or:
|
||||
- equal: [<< parameters.could-be-aks >>, false]
|
||||
- equal: [<< pipeline.parameters.large-linux-executor >>, 2xlarge]
|
||||
steps: << parameters.circle >>
|
||||
- when:
|
||||
condition:
|
||||
and:
|
||||
- equal: [<< parameters.could-be-aks >>, true]
|
||||
- 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..."
|
||||
mkdir -p << parameters.cache_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:
|
||||
type: boolean
|
||||
default: false
|
||||
could-be-aks:
|
||||
type: boolean
|
||||
steps:
|
||||
- run:
|
||||
name: Prepare for cross-OS sync restore
|
||||
@@ -1039,23 +1155,44 @@ 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
|
||||
could-be-aks: << parameters.could-be-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
|
||||
could-be-aks: << parameters.could-be-aks >>
|
||||
- run:
|
||||
name: Fix the src cache restore point on macOS
|
||||
name: Fix the src cache restore point
|
||||
command: |
|
||||
if [ -d "/var/portal/src" ]; then
|
||||
echo Relocating Cache
|
||||
rm -rf src
|
||||
mv /var/portal/src ./
|
||||
fi
|
||||
|
||||
run-gn-check:
|
||||
parameters:
|
||||
could-be-aks:
|
||||
type: boolean
|
||||
steps:
|
||||
- *step-setup-goma-for-build
|
||||
- checkout-from-cache:
|
||||
could-be-aks: << parameters.could-be-aks >>
|
||||
- *step-setup-env-for-build
|
||||
- *step-wait-for-goma
|
||||
- *step-gn-gen-default
|
||||
- *step-gn-check
|
||||
build_and_save_artifacts:
|
||||
parameters:
|
||||
artifact-key:
|
||||
@@ -1169,12 +1306,16 @@ commands:
|
||||
mv_if_exist cross-arch-snapshots src
|
||||
|
||||
checkout-from-cache:
|
||||
parameters:
|
||||
could-be-aks:
|
||||
type: boolean
|
||||
steps:
|
||||
- *step-checkout-electron
|
||||
- *step-depot-tools-get
|
||||
- *step-depot-tools-add-to-path
|
||||
- *step-generate-deps-hash
|
||||
- maybe-restore-portaled-src-cache
|
||||
- maybe-restore-portaled-src-cache:
|
||||
could-be-aks: << parameters.could-be-aks >>
|
||||
- run:
|
||||
name: Ensure src checkout worked
|
||||
command: |
|
||||
@@ -1286,6 +1427,8 @@ commands:
|
||||
after-persist:
|
||||
type: steps
|
||||
default: []
|
||||
could-be-aks:
|
||||
type: boolean
|
||||
steps:
|
||||
- when:
|
||||
condition: << parameters.attach >>
|
||||
@@ -1303,7 +1446,8 @@ commands:
|
||||
- when:
|
||||
condition: << parameters.checkout-and-assume-cache >>
|
||||
steps:
|
||||
- checkout-from-cache
|
||||
- checkout-from-cache:
|
||||
could-be-aks: << parameters.could-be-aks >>
|
||||
- when:
|
||||
condition: << parameters.checkout >>
|
||||
steps:
|
||||
@@ -1319,8 +1463,15 @@ commands:
|
||||
steps:
|
||||
- maybe-restore-portaled-src-cache:
|
||||
halt-if-successful: << parameters.checkout-to-create-src-cache >>
|
||||
- *step-maybe-restore-git-cache
|
||||
could-be-aks: << parameters.could-be-aks >>
|
||||
- aks-specific-step:
|
||||
circle:
|
||||
- *step-maybe-restore-git-cache
|
||||
aks:
|
||||
- *step-maybe-restore-git-cache-aks
|
||||
could-be-aks: << parameters.could-be-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 +1487,12 @@ 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
|
||||
could-be-aks: << parameters.could-be-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 +1542,19 @@ 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
|
||||
could-be-aks: << parameters.could-be-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
|
||||
could-be-aks: << parameters.could-be-aks >>
|
||||
|
||||
- when:
|
||||
condition: << parameters.build >>
|
||||
@@ -1442,6 +1608,18 @@ commands:
|
||||
condition: << parameters.build >>
|
||||
steps:
|
||||
- *step-maybe-notify-slack-failure
|
||||
- when:
|
||||
condition: << parameters.could-be-aks >>
|
||||
steps:
|
||||
- run:
|
||||
name: Wait for active debug sessions
|
||||
command: |
|
||||
while [ -f /var/.ssh-lock ]
|
||||
do
|
||||
sleep 60
|
||||
done
|
||||
no_output_timeout: 2h
|
||||
when: always
|
||||
|
||||
electron-tests:
|
||||
parameters:
|
||||
@@ -1628,7 +1806,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'
|
||||
@@ -1641,6 +1819,7 @@ jobs:
|
||||
checkout-to-create-src-cache: true
|
||||
artifact-key: 'nil'
|
||||
build-type: 'nil'
|
||||
could-be-aks: true
|
||||
|
||||
mac-checkout:
|
||||
executor:
|
||||
@@ -1660,6 +1839,7 @@ jobs:
|
||||
restore-src-cache: false
|
||||
artifact-key: 'nil'
|
||||
build-type: 'nil'
|
||||
could-be-aks: false
|
||||
|
||||
mac-make-src-cache-x64:
|
||||
executor:
|
||||
@@ -1679,6 +1859,7 @@ jobs:
|
||||
checkout-to-create-src-cache: true
|
||||
artifact-key: 'nil'
|
||||
build-type: 'nil'
|
||||
could-be-aks: false
|
||||
|
||||
mac-make-src-cache-arm64:
|
||||
executor:
|
||||
@@ -1698,12 +1879,13 @@ jobs:
|
||||
checkout-to-create-src-cache: true
|
||||
artifact-key: 'nil'
|
||||
build-type: 'nil'
|
||||
could-be-aks: false
|
||||
|
||||
# Layer 2: Builds.
|
||||
linux-x64-testing:
|
||||
executor:
|
||||
name: linux-docker
|
||||
size: electronjs/aks-linux-large
|
||||
size: << pipeline.parameters.large-linux-executor >>
|
||||
environment:
|
||||
<<: *env-global
|
||||
<<: *env-testing-build
|
||||
@@ -1716,11 +1898,12 @@ jobs:
|
||||
checkout-and-assume-cache: true
|
||||
artifact-key: 'linux-x64'
|
||||
build-type: 'Linux'
|
||||
could-be-aks: true
|
||||
|
||||
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
|
||||
@@ -1731,25 +1914,29 @@ jobs:
|
||||
steps:
|
||||
- electron-build:
|
||||
persist: true
|
||||
checkout: true
|
||||
checkout: false
|
||||
checkout-and-assume-cache: true
|
||||
build-nonproprietary-ffmpeg: false
|
||||
artifact-key: 'linux-x64-asan'
|
||||
build-type: 'Linux'
|
||||
could-be-aks: true
|
||||
|
||||
linux-x64-testing-gn-check:
|
||||
executor:
|
||||
name: linux-docker
|
||||
size: medium
|
||||
size: << pipeline.parameters.medium-linux-executor >>
|
||||
environment:
|
||||
<<: *env-linux-medium
|
||||
<<: *env-testing-build
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
|
||||
<<: *steps-electron-gn-check
|
||||
steps:
|
||||
- run-gn-check:
|
||||
could-be-aks: true
|
||||
|
||||
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 +1959,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
|
||||
@@ -1788,11 +1975,12 @@ jobs:
|
||||
checkout-and-assume-cache: true
|
||||
artifact-key: 'linux-arm'
|
||||
build-type: 'Linux ARM'
|
||||
could-be-aks: true
|
||||
|
||||
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 +2005,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
|
||||
@@ -1833,22 +2021,25 @@ jobs:
|
||||
checkout-and-assume-cache: true
|
||||
artifact-key: 'linux-arm64'
|
||||
build-type: 'Linux ARM64'
|
||||
could-be-aks: true
|
||||
|
||||
linux-arm64-testing-gn-check:
|
||||
executor:
|
||||
name: linux-docker
|
||||
size: medium
|
||||
size: << pipeline.parameters.medium-linux-executor >>
|
||||
environment:
|
||||
<<: *env-linux-medium
|
||||
<<: *env-arm64
|
||||
<<: *env-testing-build
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
|
||||
<<: *steps-electron-gn-check
|
||||
steps:
|
||||
- run-gn-check:
|
||||
could-be-aks: true
|
||||
|
||||
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
|
||||
@@ -1903,6 +2094,7 @@ jobs:
|
||||
root: .
|
||||
paths:
|
||||
- generated_artifacts_mas-x64
|
||||
could-be-aks: false
|
||||
|
||||
osx-testing-x64-gn-check:
|
||||
executor:
|
||||
@@ -1912,7 +2104,9 @@ jobs:
|
||||
<<: *env-machine-mac
|
||||
<<: *env-testing-build
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_mac=True --custom-var=host_os=mac'
|
||||
<<: *steps-electron-gn-check
|
||||
steps:
|
||||
- run-gn-check:
|
||||
could-be-aks: false
|
||||
|
||||
osx-publish-x64:
|
||||
executor:
|
||||
@@ -1994,6 +2188,7 @@ jobs:
|
||||
root: .
|
||||
paths:
|
||||
- generated_artifacts_mas-arm64
|
||||
could-be-aks: false
|
||||
|
||||
mas-publish-x64:
|
||||
executor:
|
||||
|
||||
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
DEPS
2
DEPS
@@ -2,7 +2,7 @@ gclient_gn_args_from = 'src'
|
||||
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'118.0.5993.5',
|
||||
'118.0.5993.54',
|
||||
'node_version':
|
||||
'v18.17.1',
|
||||
'nan_version':
|
||||
|
||||
@@ -202,6 +202,10 @@ static_library("chrome") {
|
||||
"//chrome/browser/ui/views/status_icons/status_icon_linux_dbus.cc",
|
||||
"//chrome/browser/ui/views/status_icons/status_icon_linux_dbus.h",
|
||||
]
|
||||
sources += [
|
||||
"//chrome/browser/ui/views/dark_mode_manager_linux.cc",
|
||||
"//chrome/browser/ui/views/dark_mode_manager_linux.h",
|
||||
]
|
||||
public_deps += [
|
||||
"//components/dbus/menu",
|
||||
"//components/dbus/thread_linux",
|
||||
@@ -319,6 +323,34 @@ static_library("chrome") {
|
||||
"//components/pdf/renderer",
|
||||
]
|
||||
}
|
||||
} else {
|
||||
# These are required by the webRequest module.
|
||||
sources += [
|
||||
"//extensions/browser/api/declarative_net_request/request_action.cc",
|
||||
"//extensions/browser/api/declarative_net_request/request_action.h",
|
||||
"//extensions/browser/api/web_request/form_data_parser.cc",
|
||||
"//extensions/browser/api/web_request/form_data_parser.h",
|
||||
"//extensions/browser/api/web_request/upload_data_presenter.cc",
|
||||
"//extensions/browser/api/web_request/upload_data_presenter.h",
|
||||
"//extensions/browser/api/web_request/web_request_api_constants.cc",
|
||||
"//extensions/browser/api/web_request/web_request_api_constants.h",
|
||||
"//extensions/browser/api/web_request/web_request_info.cc",
|
||||
"//extensions/browser/api/web_request/web_request_info.h",
|
||||
"//extensions/browser/api/web_request/web_request_resource_type.cc",
|
||||
"//extensions/browser/api/web_request/web_request_resource_type.h",
|
||||
"//extensions/browser/extension_api_frame_id_map.cc",
|
||||
"//extensions/browser/extension_api_frame_id_map.h",
|
||||
"//extensions/browser/extension_navigation_ui_data.cc",
|
||||
"//extensions/browser/extension_navigation_ui_data.h",
|
||||
"//extensions/browser/extensions_browser_client.cc",
|
||||
"//extensions/browser/extensions_browser_client.h",
|
||||
"//extensions/browser/guest_view/web_view/web_view_renderer_state.cc",
|
||||
"//extensions/browser/guest_view/web_view/web_view_renderer_state.h",
|
||||
]
|
||||
|
||||
public_deps += [
|
||||
"//extensions/browser/api/declarative_net_request/flat:extension_ruleset",
|
||||
]
|
||||
}
|
||||
|
||||
if (!is_mas_build) {
|
||||
|
||||
@@ -505,6 +505,10 @@ events.
|
||||
|
||||
A `Integer` property representing the unique ID of the window. Each ID is unique among all `BrowserWindow` instances of the entire Electron application.
|
||||
|
||||
#### `win.tabbingIdentifier` _macOS_ _Readonly_
|
||||
|
||||
A `string` (optional) property that is equal to the `tabbingIdentifier` passed to the `BrowserWindow` constructor or `undefined` if none was set.
|
||||
|
||||
#### `win.autoHideMenuBar`
|
||||
|
||||
A `boolean` property that determines whether the window menu bar should hide itself automatically. Once set, the menu bar will only show when users press the single `Alt` key.
|
||||
|
||||
@@ -119,4 +119,8 @@ Removes the cookies matching `url` and `name`
|
||||
|
||||
Returns `Promise<void>` - A promise which resolves when the cookie store has been flushed
|
||||
|
||||
Writes any unwritten cookies data to disk.
|
||||
Writes any unwritten cookies data to disk
|
||||
|
||||
Cookies written by any method will not be written to disk immediately, but will be written every 30 seconds or 512 operations
|
||||
|
||||
Calling this method can cause the cookie to be written to disk immediately.
|
||||
|
||||
@@ -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,15 +401,9 @@ Returns an object with system animation settings.
|
||||
|
||||
## Properties
|
||||
|
||||
### `systemPreferences.appLevelAppearance` _macOS_ _Deprecated_
|
||||
### `systemPreferences.accessibilityDisplayShouldReduceTransparency()` _macOS_
|
||||
|
||||
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.
|
||||
A `boolean` property which determines whether the app avoids using semitransparent backgrounds. This maps to [NSWorkspace.accessibilityDisplayShouldReduceTransparency](https://developer.apple.com/documentation/appkit/nsworkspace/1533006-accessibilitydisplayshouldreduce)
|
||||
|
||||
### `systemPreferences.effectiveAppearance` _macOS_ _Readonly_
|
||||
|
||||
|
||||
@@ -61,6 +61,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`
|
||||
@@ -635,6 +670,18 @@ to open synchronously scriptable child windows, among other incompatibilities.
|
||||
See the documentation for [window.open in Electron](api/window-open.md)
|
||||
for more details.
|
||||
|
||||
### Deprecated: `app.runningUnderRosettaTranslation`
|
||||
|
||||
The `app.runningUnderRosettaTranslation` property has been deprecated.
|
||||
Use `app.runningUnderARM64Translation` instead.
|
||||
|
||||
```js
|
||||
// Deprecated
|
||||
console.log(app.runningUnderRosettaTranslation)
|
||||
// Replace with
|
||||
console.log(app.runningUnderARM64Translation)
|
||||
```
|
||||
|
||||
## Planned Breaking API Changes (14.0)
|
||||
|
||||
### Removed: `remote` module
|
||||
|
||||
@@ -12,7 +12,7 @@ check out our [Electron Versioning](./electron-versioning.md) doc.
|
||||
| 27.0.0 | 2023-Aug-17 | 2023-Sep-13 | 2023-Oct-10 | TBD | M118 | TBD | ✅ |
|
||||
| 26.0.0 | 2023-Jun-01 | 2023-Jun-27 | 2023-Aug-15 | 2024-Feb-27 | M116 | v18.16 | ✅ |
|
||||
| 25.0.0 | 2023-Apr-10 | 2023-May-02 | 2023-May-30 | 2024-Jan-02 | M114 | v18.15 | ✅ |
|
||||
| 24.0.0 | 2022-Feb-09 | 2023-Mar-07 | 2023-Apr-04 | 2023-Oct-10 | M112 | v18.14 | ✅ |
|
||||
| 24.0.0 | 2023-Feb-09 | 2023-Mar-07 | 2023-Apr-04 | 2023-Oct-10 | M112 | v18.14 | ✅ |
|
||||
| 23.0.0 | 2022-Dec-01 | 2023-Jan-10 | 2023-Feb-07 | 2023-Aug-15 | M110 | v18.12 | 🚫 |
|
||||
| 22.0.0 | 2022-Sep-29 | 2022-Oct-25 | 2022-Nov-29 | 2023-Oct-10 | M108 | v16.17 | ✅ |
|
||||
| 21.0.0 | 2022-Aug-04 | 2022-Aug-30 | 2022-Sep-27 | 2023-Apr-04 | M106 | v16.16 | 🚫 |
|
||||
|
||||
@@ -228,6 +228,23 @@ channel with a renderer process using [`MessagePort`][]s. An Electron app can
|
||||
always prefer the [UtilityProcess][] API over Node.js [`child_process.fork`][] API when
|
||||
there is need to fork a child process from the main process.
|
||||
|
||||
## Process-specific module aliases (TypeScript)
|
||||
|
||||
Electron's npm package also exports subpaths that contain a subset of
|
||||
Electron's TypeScript type definitions.
|
||||
|
||||
- `electron/main` includes types for all main process modules.
|
||||
- `electron/renderer` includes types for all renderer process modules.
|
||||
- `electron/common` includes types for modules that can run in main and renderer processes.
|
||||
|
||||
These aliases have no impact on runtime, but can be used for typechecking
|
||||
and autocomplete.
|
||||
|
||||
```js title="Usage example"
|
||||
const { app } = require('electron/main')
|
||||
const { shell } = require('electron/common')
|
||||
```
|
||||
|
||||
[window-mdn]: https://developer.mozilla.org/en-US/docs/Web/API/Window
|
||||
[`MessagePort`]: https://developer.mozilla.org/en-US/docs/Web/API/MessagePort
|
||||
[`child_process.fork`]: https://nodejs.org/dist/latest-v16.x/docs/api/child_process.html#child_processforkmodulepath-args-options
|
||||
|
||||
@@ -91,14 +91,14 @@ version: '0.1'
|
||||
summary: Hello World Electron app
|
||||
description: |
|
||||
Simple Hello World Electron app as an example
|
||||
base: core18
|
||||
base: core22
|
||||
confinement: strict
|
||||
grade: stable
|
||||
|
||||
apps:
|
||||
electron-packager-hello-world:
|
||||
command: electron-quick-start/electron-quick-start --no-sandbox
|
||||
extensions: [gnome-3-34]
|
||||
extensions: [gnome]
|
||||
plugs:
|
||||
- browser-support
|
||||
- network
|
||||
@@ -237,6 +237,34 @@ apps:
|
||||
desktop: usr/share/applications/desktop.desktop
|
||||
```
|
||||
|
||||
## Optional: Enabling desktop capture
|
||||
|
||||
Capturing the desktop requires PipeWire library in some Linux configurations that use
|
||||
the Wayland protocol. To bundle PipeWire with your application, ensure that the base
|
||||
snap is set to `core22` or newer. Next, create a part called `pipewire` and add it to
|
||||
the `after` section of your application:
|
||||
|
||||
```yaml
|
||||
pipewire:
|
||||
plugin: nil
|
||||
build-packages: [libpipewire-0.3-dev]
|
||||
stage-packages: [pipewire]
|
||||
prime:
|
||||
- usr/lib/*/pipewire-*
|
||||
- usr/lib/*/spa-*
|
||||
- usr/lib/*/libpipewire*.so*
|
||||
- usr/share/pipewire
|
||||
```
|
||||
|
||||
Finally, configure your application's environment for PipeWire:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
SPA_PLUGIN_DIR: $SNAP/usr/lib/$CRAFT_ARCH_TRIPLET/spa-0.2
|
||||
PIPEWIRE_CONFIG_NAME: $SNAP/usr/share/pipewire/pipewire.conf
|
||||
PIPEWIRE_MODULE_DIR: $SNAP/usr/lib/$CRAFT_ARCH_TRIPLET/pipewire-0.3
|
||||
```
|
||||
|
||||
[snapcraft-syntax]: https://docs.snapcraft.io/build-snaps/syntax
|
||||
[electron-packager]: https://github.com/electron/electron-packager
|
||||
[electron-forge]: https://github.com/electron/forge
|
||||
|
||||
@@ -222,14 +222,26 @@ with CommonJS module syntax:
|
||||
- [app][app], which controls your application's event lifecycle.
|
||||
- [BrowserWindow][browser-window], which creates and manages app windows.
|
||||
|
||||
:::info Capitalization conventions
|
||||
<details><summary>Module capitalization conventions</summary>
|
||||
|
||||
You might have noticed the capitalization difference between the **a**pp
|
||||
and **B**rowser**W**indow modules. Electron follows typical JavaScript conventions here,
|
||||
where PascalCase modules are instantiable class constructors (e.g. BrowserWindow, Tray,
|
||||
Notification) whereas camelCase modules are not instantiable (e.g. app, ipcRenderer, webContents).
|
||||
|
||||
:::
|
||||
</details>
|
||||
|
||||
<details><summary>Typed import aliases</summary>
|
||||
|
||||
For better type checking when writing TypeScript code, you can choose to import
|
||||
main process modules from <code>electron/main</code>.
|
||||
|
||||
```js
|
||||
const { app, BrowserWindow } = require('electron/main')
|
||||
```
|
||||
|
||||
For more information, see the [Process Model docs](../tutorial/process-model.md#process-specific-module-aliases-typescript).
|
||||
</details>
|
||||
|
||||
:::warning ES Modules in Electron
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Buffer } from 'buffer';
|
||||
import { constants } from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as util from 'util';
|
||||
import type * as Crypto from 'crypto';
|
||||
@@ -27,7 +28,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 +40,8 @@ const getOrCreateArchive = (archivePath: string) => {
|
||||
}
|
||||
};
|
||||
|
||||
process._getOrCreateArchive = getOrCreateArchive;
|
||||
|
||||
const asarRe = /\.asar/i;
|
||||
|
||||
// Separate asar package's path from full path.
|
||||
@@ -65,18 +68,22 @@ const gid = process.getgid?.() ?? 0;
|
||||
|
||||
const fakeTime = new Date();
|
||||
|
||||
enum AsarFileType {
|
||||
kFile = (constants as any).UV_DIRENT_FILE,
|
||||
kDirectory = (constants as any).UV_DIRENT_DIR,
|
||||
kLink = (constants as any).UV_DIRENT_LINK,
|
||||
}
|
||||
|
||||
const fileTypeToMode = new Map<AsarFileType, number>([
|
||||
[AsarFileType.kFile, constants.S_IFREG],
|
||||
[AsarFileType.kDirectory, constants.S_IFDIR],
|
||||
[AsarFileType.kLink, constants.S_IFLNK]
|
||||
]);
|
||||
|
||||
const asarStatsToFsStats = function (stats: NodeJS.AsarFileStat) {
|
||||
const { Stats, constants } = require('fs');
|
||||
const { Stats } = require('fs');
|
||||
|
||||
let mode = constants.S_IROTH ^ constants.S_IRGRP ^ constants.S_IRUSR ^ constants.S_IWUSR;
|
||||
|
||||
if (stats.isFile) {
|
||||
mode ^= constants.S_IFREG;
|
||||
} else if (stats.isDirectory) {
|
||||
mode ^= constants.S_IFDIR;
|
||||
} else if (stats.isLink) {
|
||||
mode ^= constants.S_IFLNK;
|
||||
}
|
||||
const mode = constants.S_IROTH | constants.S_IRGRP | constants.S_IRUSR | constants.S_IWUSR | fileTypeToMode.get(stats.type)!;
|
||||
|
||||
return new Stats(
|
||||
1, // dev
|
||||
@@ -239,7 +246,6 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
const logASARAccess = (asarPath: string, filePath: string, offset: number) => {
|
||||
if (!process.env.ELECTRON_LOG_ASAR_READS) return;
|
||||
if (!logFDs.has(asarPath)) {
|
||||
const path = require('path');
|
||||
const logFilename = `${path.basename(asarPath, '.asar')}-access-log.txt`;
|
||||
const logPath = path.join(require('os').tmpdir(), logFilename);
|
||||
logFDs.set(asarPath, fs.openSync(logPath, 'a'));
|
||||
@@ -655,13 +661,7 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
nextTick(callback!, [error]);
|
||||
return;
|
||||
}
|
||||
if (stats.isFile) {
|
||||
dirents.push(new fs.Dirent(file, fs.constants.UV_DIRENT_FILE));
|
||||
} else if (stats.isDirectory) {
|
||||
dirents.push(new fs.Dirent(file, fs.constants.UV_DIRENT_DIR));
|
||||
} else if (stats.isLink) {
|
||||
dirents.push(new fs.Dirent(file, fs.constants.UV_DIRENT_LINK));
|
||||
}
|
||||
dirents.push(new fs.Dirent(file, stats.type));
|
||||
}
|
||||
nextTick(callback!, [null, dirents]);
|
||||
return;
|
||||
@@ -698,13 +698,7 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
if (!stats) {
|
||||
throw createError(AsarError.NOT_FOUND, { asarPath, filePath: childPath });
|
||||
}
|
||||
if (stats.isFile) {
|
||||
dirents.push(new fs.Dirent(file, fs.constants.UV_DIRENT_FILE));
|
||||
} else if (stats.isDirectory) {
|
||||
dirents.push(new fs.Dirent(file, fs.constants.UV_DIRENT_DIR));
|
||||
} else if (stats.isLink) {
|
||||
dirents.push(new fs.Dirent(file, fs.constants.UV_DIRENT_LINK));
|
||||
}
|
||||
dirents.push(new fs.Dirent(file, stats.type));
|
||||
}
|
||||
return dirents;
|
||||
}
|
||||
@@ -755,7 +749,7 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
const stats = archive.stat(filePath);
|
||||
if (!stats) return -34;
|
||||
|
||||
return (stats.isDirectory) ? 1 : 0;
|
||||
return (stats.type === AsarFileType.kDirectory) ? 1 : 0;
|
||||
};
|
||||
|
||||
// Calling mkdir for directory inside asar archive should throw ENOTDIR
|
||||
|
||||
@@ -114,5 +114,11 @@ for (const name of events) {
|
||||
}
|
||||
|
||||
// Deprecation.
|
||||
deprecate.event(app, 'gpu-process-crashed', 'child-process-gone');
|
||||
deprecate.event(app, 'renderer-process-crashed', 'render-process-gone');
|
||||
deprecate.event(app, 'gpu-process-crashed', 'child-process-gone', () => {
|
||||
// the old event is still emitted by App::OnGpuProcessCrashed()
|
||||
return undefined;
|
||||
});
|
||||
|
||||
deprecate.event(app, 'renderer-process-crashed', 'render-process-gone', (event: Electron.Event, webContents: Electron.WebContents, details: Electron.RenderProcessGoneDetails) => {
|
||||
return [event, webContents, details.reason === 'killed'];
|
||||
});
|
||||
|
||||
@@ -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', {
|
||||
|
||||
@@ -337,49 +337,53 @@ WebContents.prototype.printToPDF = async function (options) {
|
||||
// TODO(codebytere): deduplicate argument sanitization by moving rest of
|
||||
// print param logic into new file shared between printToPDF and print
|
||||
WebContents.prototype.print = function (options: ElectronInternal.WebContentsPrintOptions, callback) {
|
||||
if (typeof options === 'object') {
|
||||
const pageSize = options.pageSize ?? 'A4';
|
||||
if (typeof pageSize === 'object') {
|
||||
if (!pageSize.height || !pageSize.width) {
|
||||
throw new Error('height and width properties are required for pageSize');
|
||||
}
|
||||
if (typeof options !== 'object') {
|
||||
throw new Error('webContents.print(): Invalid print settings specified.');
|
||||
}
|
||||
|
||||
// Dimensions in Microns - 1 meter = 10^6 microns
|
||||
const height = Math.ceil(pageSize.height);
|
||||
const width = Math.ceil(pageSize.width);
|
||||
if (!isValidCustomPageSize(width, height)) {
|
||||
throw new Error('height and width properties must be minimum 352 microns.');
|
||||
}
|
||||
const printSettings: Record<string, any> = { ...options };
|
||||
|
||||
options.mediaSize = {
|
||||
name: 'CUSTOM',
|
||||
custom_display_name: 'Custom',
|
||||
height_microns: height,
|
||||
width_microns: width,
|
||||
imageable_area_left_microns: 0,
|
||||
imageable_area_bottom_microns: 0,
|
||||
imageable_area_right_microns: width,
|
||||
imageable_area_top_microns: height
|
||||
};
|
||||
} else if (typeof pageSize === 'string' && PDFPageSizes[pageSize]) {
|
||||
const mediaSize = PDFPageSizes[pageSize];
|
||||
options.mediaSize = {
|
||||
...mediaSize,
|
||||
imageable_area_left_microns: 0,
|
||||
imageable_area_bottom_microns: 0,
|
||||
imageable_area_right_microns: mediaSize.width_microns,
|
||||
imageable_area_top_microns: mediaSize.height_microns
|
||||
};
|
||||
} else {
|
||||
throw new Error(`Unsupported pageSize: ${pageSize}`);
|
||||
const pageSize = options.pageSize ?? 'A4';
|
||||
if (typeof pageSize === 'object') {
|
||||
if (!pageSize.height || !pageSize.width) {
|
||||
throw new Error('height and width properties are required for pageSize');
|
||||
}
|
||||
|
||||
// Dimensions in Microns - 1 meter = 10^6 microns
|
||||
const height = Math.ceil(pageSize.height);
|
||||
const width = Math.ceil(pageSize.width);
|
||||
if (!isValidCustomPageSize(width, height)) {
|
||||
throw new Error('height and width properties must be minimum 352 microns.');
|
||||
}
|
||||
|
||||
printSettings.mediaSize = {
|
||||
name: 'CUSTOM',
|
||||
custom_display_name: 'Custom',
|
||||
height_microns: height,
|
||||
width_microns: width,
|
||||
imageable_area_left_microns: 0,
|
||||
imageable_area_bottom_microns: 0,
|
||||
imageable_area_right_microns: width,
|
||||
imageable_area_top_microns: height
|
||||
};
|
||||
} else if (typeof pageSize === 'string' && PDFPageSizes[pageSize]) {
|
||||
const mediaSize = PDFPageSizes[pageSize];
|
||||
printSettings.mediaSize = {
|
||||
...mediaSize,
|
||||
imageable_area_left_microns: 0,
|
||||
imageable_area_bottom_microns: 0,
|
||||
imageable_area_right_microns: mediaSize.width_microns,
|
||||
imageable_area_top_microns: mediaSize.height_microns
|
||||
};
|
||||
} else {
|
||||
throw new Error(`Unsupported pageSize: ${pageSize}`);
|
||||
}
|
||||
|
||||
if (this._print) {
|
||||
if (callback) {
|
||||
this._print(options, callback);
|
||||
this._print(printSettings, callback);
|
||||
} else {
|
||||
this._print(options);
|
||||
this._print(printSettings);
|
||||
}
|
||||
} else {
|
||||
console.error('Error: Printing feature is disabled.');
|
||||
@@ -653,8 +657,8 @@ WebContents.prototype._init = function () {
|
||||
ipcMain.emit(channel, event, message);
|
||||
});
|
||||
|
||||
this.on('crashed', (event, ...args) => {
|
||||
app.emit('renderer-process-crashed', event, this, ...args);
|
||||
deprecate.event(this, 'crashed', 'render-process-gone', (event: Electron.Event, details: Electron.RenderProcessGoneDetails) => {
|
||||
return [event, details.reason === 'killed'];
|
||||
});
|
||||
|
||||
this.on('render-process-gone', (event, details) => {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -66,14 +66,17 @@ export function renameFunction<T extends Function> (fn: T, newName: string): T {
|
||||
}
|
||||
|
||||
// change the name of an event
|
||||
export function event (emitter: NodeJS.EventEmitter, oldName: string, newName: string) {
|
||||
export function event (emitter: NodeJS.EventEmitter, oldName: string, newName: string, transformer: (...args: any[]) => any[] | undefined = (...args) => args) {
|
||||
const warn = newName.startsWith('-') /* internal event */
|
||||
? warnOnce(`${oldName} event`)
|
||||
: warnOnce(`${oldName} event`, `${newName} event`);
|
||||
return emitter.on(newName, function (this: NodeJS.EventEmitter, ...args) {
|
||||
if (this.listenerCount(oldName) !== 0) {
|
||||
warn();
|
||||
this.emit(oldName, ...args);
|
||||
const transformedArgs = transformer(...args);
|
||||
if (transformedArgs) {
|
||||
this.emit(oldName, ...transformedArgs);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -128,5 +128,7 @@ 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
|
||||
revert_same_party_cookie_attribute_removal.patch
|
||||
|
||||
@@ -33,10 +33,10 @@ index 41ce32113ec2679b76d5a4fd69a7109c832ac7a1..1cd35794bf78f3d92b42634d9494c85a
|
||||
"//base",
|
||||
"//build:branding_buildflags",
|
||||
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
|
||||
index 1a9bff4a3efb7fd802db7ae9696027ee318eb7eb..85d2bc48117c7e41cfa49ea204d2c46f79a1c117 100644
|
||||
index 9ab6c039d18f8759b8d7db9742d3570a7734f893..ae347df7a1b1a48723160787f71cfd1340f430ef 100644
|
||||
--- a/chrome/browser/BUILD.gn
|
||||
+++ b/chrome/browser/BUILD.gn
|
||||
@@ -4723,7 +4723,7 @@ static_library("browser") {
|
||||
@@ -4725,7 +4725,7 @@ static_library("browser") {
|
||||
|
||||
# On Windows, the hashes are embedded in //chrome:chrome_initial rather
|
||||
# than here in :chrome_dll.
|
||||
@@ -46,10 +46,10 @@ index 1a9bff4a3efb7fd802db7ae9696027ee318eb7eb..85d2bc48117c7e41cfa49ea204d2c46f
|
||||
sources += [ "certificate_viewer_stub.cc" ]
|
||||
}
|
||||
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
|
||||
index 6a2501dde4552c2b0d96dd54fc1b94ba1e610b0c..8d3cb67ae6d4fe65cfbb907309af734906b49949 100644
|
||||
index 823cc89dd28ea78e12723fb3ff9389b05192b4ee..67f58bde17e0f2c0bf44139137411e8da60b3601 100644
|
||||
--- a/chrome/test/BUILD.gn
|
||||
+++ b/chrome/test/BUILD.gn
|
||||
@@ -6838,7 +6838,6 @@ test("unit_tests") {
|
||||
@@ -6841,7 +6841,6 @@ test("unit_tests") {
|
||||
|
||||
deps += [
|
||||
"//chrome:other_version",
|
||||
@@ -57,7 +57,7 @@ index 6a2501dde4552c2b0d96dd54fc1b94ba1e610b0c..8d3cb67ae6d4fe65cfbb907309af7349
|
||||
"//chrome//services/util_win:unit_tests",
|
||||
"//chrome/app:chrome_dll_resources",
|
||||
"//chrome/app:win_unit_tests",
|
||||
@@ -6864,6 +6863,10 @@ test("unit_tests") {
|
||||
@@ -6867,6 +6866,10 @@ test("unit_tests") {
|
||||
"//ui/resources",
|
||||
]
|
||||
|
||||
@@ -68,7 +68,7 @@ index 6a2501dde4552c2b0d96dd54fc1b94ba1e610b0c..8d3cb67ae6d4fe65cfbb907309af7349
|
||||
ldflags = [
|
||||
"/DELAYLOAD:api-ms-win-core-winrt-error-l1-1-0.dll",
|
||||
"/DELAYLOAD:api-ms-win-core-winrt-l1-1-0.dll",
|
||||
@@ -7831,7 +7834,6 @@ test("unit_tests") {
|
||||
@@ -7834,7 +7837,6 @@ test("unit_tests") {
|
||||
}
|
||||
|
||||
deps += [
|
||||
@@ -76,7 +76,7 @@ index 6a2501dde4552c2b0d96dd54fc1b94ba1e610b0c..8d3cb67ae6d4fe65cfbb907309af7349
|
||||
"//chrome/browser/apps:icon_standardizer",
|
||||
"//chrome/browser/apps/app_service",
|
||||
"//chrome/browser/apps/app_service:app_registry_cache_waiter",
|
||||
@@ -7918,6 +7920,10 @@ test("unit_tests") {
|
||||
@@ -7921,6 +7923,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 718ad3e088f6730bb00f1e3674effae6c429b9b6..77af941f2dd2d3074f5596cee24be47dc8175434 100644
|
||||
index 368cf7aaffeef5f9796f78a72f13eddb6c44dec9..ade39af8ac41c91d4fd4b9a905ce5d836bea7d87 100644
|
||||
--- a/content/browser/BUILD.gn
|
||||
+++ b/content/browser/BUILD.gn
|
||||
@@ -56,6 +56,7 @@ source_set("browser") {
|
||||
@@ -110,10 +110,10 @@ index b16be8f9992b23ce93d174531f2debd7f18bb436..119038743dc222907cb74c2c3ea34d23
|
||||
|
||||
public_deps = [
|
||||
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
|
||||
index 581571b6bb1a655319b247d7cc85bb2a4dd7db1c..09779610326da207062a59ba572b2d7c13efd26f 100644
|
||||
index 9efe02bc63033f9d2e39a97c95038eb27a1c2f93..1535e9346218c4b0dd71be53e8830b8d299561cc 100644
|
||||
--- a/content/test/BUILD.gn
|
||||
+++ b/content/test/BUILD.gn
|
||||
@@ -480,6 +480,7 @@ static_library("test_support") {
|
||||
@@ -481,6 +481,7 @@ static_library("test_support") {
|
||||
configs += [
|
||||
"//build/config:precompiled_headers",
|
||||
"//v8:external_startup_data",
|
||||
|
||||
@@ -9,7 +9,7 @@ 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 50d873e238b04eb6d461dc929d98dfe171cc491c..586aa87098bd3db10440fe865a02c05e7b3be14f 100644
|
||||
index a1ccfc3c3081dc267414ff0fa52cc6b3e6e06140..9b6ce4a1a495986333a0d173749a9a095c2e5603 100644
|
||||
--- a/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
@@ -8206,6 +8206,7 @@ void RenderFrameHostImpl::CreateNewWindow(
|
||||
|
||||
@@ -6,7 +6,7 @@ Subject: chore: patch out Profile methods in titlebar_config
|
||||
Make this code linkable in Electron by removing Profile references.
|
||||
|
||||
diff --git a/chrome/browser/win/titlebar_config.cc b/chrome/browser/win/titlebar_config.cc
|
||||
index 92d0e8165a264c7ef2701a66e0f7179f0d080f47..b0c91778399f811a5d1b0f208488667cb38459e1 100644
|
||||
index f088a7071b1e0e1e05aee5637484b1dea3e2a6fa..8d411e550f6a8ca1a4070bf5d5719703f90b3dfa 100644
|
||||
--- a/chrome/browser/win/titlebar_config.cc
|
||||
+++ b/chrome/browser/win/titlebar_config.cc
|
||||
@@ -19,8 +19,10 @@ BASE_FEATURE(kWindows11MicaTitlebar,
|
||||
|
||||
@@ -22,7 +22,7 @@ index 42da00a0f473928263df89f11d80830b6986292b..6a556939d0acfbd910ebb0923e198e2f
|
||||
virtual int GetSourceCount() const = 0;
|
||||
virtual const Source& GetSource(int index) const = 0;
|
||||
diff --git a/chrome/browser/media/webrtc/desktop_media_list_base.cc b/chrome/browser/media/webrtc/desktop_media_list_base.cc
|
||||
index 0389599ac786b6abd61ca921347fe12ddd5d0ee7..780927301744ea7312f230cec76a24a33d71f767 100644
|
||||
index 489e6f7b7b0bb52b938a4fc137b983f3330cd4d2..1f2754dae9b81a7d233539a7e4e6ac77b3c5941f 100644
|
||||
--- a/chrome/browser/media/webrtc/desktop_media_list_base.cc
|
||||
+++ b/chrome/browser/media/webrtc/desktop_media_list_base.cc
|
||||
@@ -69,12 +69,12 @@ void DesktopMediaListBase::StartUpdating(DesktopMediaListObserver* observer) {
|
||||
@@ -41,7 +41,7 @@ index 0389599ac786b6abd61ca921347fe12ddd5d0ee7..780927301744ea7312f230cec76a24a3
|
||||
|
||||
int DesktopMediaListBase::GetSourceCount() const {
|
||||
diff --git a/chrome/browser/media/webrtc/desktop_media_list_base.h b/chrome/browser/media/webrtc/desktop_media_list_base.h
|
||||
index b65012985ff1797203160d9e26af17fefee5c244..9ee211fb487007bd37b57cfa7b4ffbe5307af637 100644
|
||||
index 2cd1000b90fb5af464f81ac25b63092b638c6d40..8f18adb5641b3fa5f9defd3490e20a5d86b672e9 100644
|
||||
--- a/chrome/browser/media/webrtc/desktop_media_list_base.h
|
||||
+++ b/chrome/browser/media/webrtc/desktop_media_list_base.h
|
||||
@@ -39,7 +39,7 @@ class DesktopMediaListBase : public DesktopMediaList {
|
||||
@@ -82,10 +82,10 @@ 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 81d4416e270e1a4548866a56222c47cb616385e3..22f55d22b0406f0d1aa642dcea44403ac1636057 100644
|
||||
index c2c7d86ed1f089ca6abbb026b4cf4e2857ef66c1..d65182dbae1447d95230a581943d23ee144d9dbe 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) {
|
||||
@@ -160,7 +160,7 @@ BOOL CALLBACK AllHwndCollector(HWND hwnd, LPARAM param) {
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
BASE_FEATURE(kWindowCaptureMacV2,
|
||||
"WindowCaptureMacV2",
|
||||
@@ -94,7 +94,7 @@ index 81d4416e270e1a4548866a56222c47cb616385e3..22f55d22b0406f0d1aa642dcea44403a
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
@@ -235,7 +235,7 @@ class NativeDesktopMediaList::Worker
|
||||
@@ -244,7 +244,7 @@ class NativeDesktopMediaList::Worker
|
||||
base::WeakPtr<NativeDesktopMediaList> media_list_;
|
||||
|
||||
DesktopMediaList::Type type_;
|
||||
@@ -103,7 +103,7 @@ index 81d4416e270e1a4548866a56222c47cb616385e3..22f55d22b0406f0d1aa642dcea44403a
|
||||
const ThumbnailCapturer::FrameDeliveryMethod frame_delivery_method_;
|
||||
const bool add_current_process_windows_;
|
||||
|
||||
@@ -529,6 +529,12 @@ void NativeDesktopMediaList::Worker::RefreshNextThumbnail() {
|
||||
@@ -531,6 +531,12 @@ void NativeDesktopMediaList::Worker::RefreshNextThumbnail() {
|
||||
FROM_HERE,
|
||||
base::BindOnce(&NativeDesktopMediaList::UpdateNativeThumbnailsFinished,
|
||||
media_list_));
|
||||
@@ -116,7 +116,7 @@ index 81d4416e270e1a4548866a56222c47cb616385e3..22f55d22b0406f0d1aa642dcea44403a
|
||||
}
|
||||
|
||||
void NativeDesktopMediaList::Worker::OnCaptureResult(
|
||||
@@ -935,6 +941,11 @@ void NativeDesktopMediaList::RefreshForVizFrameSinkWindows(
|
||||
@@ -964,6 +970,11 @@ void NativeDesktopMediaList::RefreshForVizFrameSinkWindows(
|
||||
FROM_HERE, base::BindOnce(&Worker::RefreshThumbnails,
|
||||
base::Unretained(worker_.get()),
|
||||
std::move(native_ids), thumbnail_size_));
|
||||
|
||||
@@ -148,7 +148,7 @@ index 6892376fa33d006453977c354734d880a7ef7c91..4cd7b762d5fe1c54f5b06cc0d8f50560
|
||||
}
|
||||
|
||||
diff --git a/third_party/blink/renderer/platform/widget/compositing/layer_tree_settings.cc b/third_party/blink/renderer/platform/widget/compositing/layer_tree_settings.cc
|
||||
index 368105b62e1650255e28cf71fcac2b956e811658..2dbbef93571ff5d41fc70a339d22470fdc5f5529 100644
|
||||
index b35f43f7051c2aabf6a49dd9af6627c9fbb2e99f..688954856aaf12565f4c63b3ffbb5459fe634693 100644
|
||||
--- a/third_party/blink/renderer/platform/widget/compositing/layer_tree_settings.cc
|
||||
+++ b/third_party/blink/renderer/platform/widget/compositing/layer_tree_settings.cc
|
||||
@@ -30,6 +30,7 @@
|
||||
@@ -159,7 +159,7 @@ index 368105b62e1650255e28cf71fcac2b956e811658..2dbbef93571ff5d41fc70a339d22470f
|
||||
#include "ui/native_theme/native_theme_features.h"
|
||||
#include "ui/native_theme/overlay_scrollbar_constants_aura.h"
|
||||
|
||||
@@ -332,6 +333,9 @@ cc::LayerTreeSettings GenerateLayerTreeSettings(
|
||||
@@ -318,6 +319,9 @@ cc::LayerTreeSettings GenerateLayerTreeSettings(
|
||||
settings.main_frame_before_activation_enabled =
|
||||
cmd.HasSwitch(cc::switches::kEnableMainFrameBeforeActivation);
|
||||
|
||||
|
||||
@@ -33,10 +33,10 @@ index 0ab8187b0db8ae6db46d81738f653a2bc4c566f6..de3d55e85c22317f7f9375eb94d0d5d4
|
||||
|
||||
} // namespace net
|
||||
diff --git a/services/network/network_context.cc b/services/network/network_context.cc
|
||||
index cb05975b622eee25217d9f2477c5e53ace017db8..e264713f4361a588e0ec8b4f6f37ab76ad642116 100644
|
||||
index 30c2fb786dac5f38104ecdac170bdd2e76f1ab6f..f857ea2d258a5ee734ec9e0d40696d5feacbf23a 100644
|
||||
--- a/services/network/network_context.cc
|
||||
+++ b/services/network/network_context.cc
|
||||
@@ -1559,6 +1559,13 @@ void NetworkContext::SetNetworkConditions(
|
||||
@@ -1561,6 +1561,13 @@ void NetworkContext::SetNetworkConditions(
|
||||
std::move(network_conditions));
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ index cb05975b622eee25217d9f2477c5e53ace017db8..e264713f4361a588e0ec8b4f6f37ab76
|
||||
// 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 25f9dab24b27ad2b3d6ca01690e9f5c3fea96d32..b230036559cdc44b97b3a5ca5f359a0b4512ccd7 100644
|
||||
index 17ecfd109db3e9dbcc27ec291f6c6021c9b6f0eb..80a75a25595718a2c4e655f75620d18b274b24cd 100644
|
||||
--- a/services/network/network_context.h
|
||||
+++ b/services/network/network_context.h
|
||||
@@ -316,6 +316,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
|
||||
@@ -63,7 +63,7 @@ index 25f9dab24b27ad2b3d6ca01690e9f5c3fea96d32..b230036559cdc44b97b3a5ca5f359a0b
|
||||
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 6ebade992b628fee18d23e5e29d2d7d6190261a7..21039664d38fb228a9319d296276c33de7a0a265 100644
|
||||
index 64a840b13bc6c07112060f48d4f77507eb84994a..7482c19600f48bf7ae4a37ce55ffcbea922b8d42 100644
|
||||
--- a/services/network/public/mojom/network_context.mojom
|
||||
+++ b/services/network/public/mojom/network_context.mojom
|
||||
@@ -1233,6 +1233,9 @@ interface NetworkContext {
|
||||
|
||||
@@ -13,10 +13,10 @@ uses internally for things like menus and devtools.
|
||||
We can remove this patch once it has in some shape been upstreamed.
|
||||
|
||||
diff --git a/ui/native_theme/native_theme.cc b/ui/native_theme/native_theme.cc
|
||||
index f6556e141a76b0766f672bfa5819256e635c60af..06c7ac178cefc149732294ed790f2b7cbb328d34 100644
|
||||
index af49c133fb2b176139263553d2afff33e96a94b1..699c38b2046e267619eef103c83eff258887e0c0 100644
|
||||
--- a/ui/native_theme/native_theme.cc
|
||||
+++ b/ui/native_theme/native_theme.cc
|
||||
@@ -153,6 +153,8 @@ NativeTheme::NativeTheme(bool should_use_dark_colors,
|
||||
@@ -156,6 +156,8 @@ NativeTheme::NativeTheme(bool should_use_dark_colors,
|
||||
NativeTheme::~NativeTheme() = default;
|
||||
|
||||
bool NativeTheme::ShouldUseDarkColors() const {
|
||||
@@ -26,7 +26,7 @@ index f6556e141a76b0766f672bfa5819256e635c60af..06c7ac178cefc149732294ed790f2b7c
|
||||
}
|
||||
|
||||
diff --git a/ui/native_theme/native_theme.h b/ui/native_theme/native_theme.h
|
||||
index 6f51a8ffec973d6c2acacabb951c7cc4e36b639c..889e655fccc115faae932236cc28c6386cf19c1e 100644
|
||||
index 341248a6b15b280c382c965009540fbdb64b0978..c9bead90658ac0e2d503c90c6ce380a318fee457 100644
|
||||
--- a/ui/native_theme/native_theme.h
|
||||
+++ b/ui/native_theme/native_theme.h
|
||||
@@ -433,6 +433,23 @@ class NATIVE_THEME_EXPORT NativeTheme {
|
||||
@@ -53,7 +53,7 @@ index 6f51a8ffec973d6c2acacabb951c7cc4e36b639c..889e655fccc115faae932236cc28c638
|
||||
// Returns a shared instance of the native theme that should be used for web
|
||||
// rendering. Do not use it in a normal application context (i.e. browser).
|
||||
// The returned object should not be deleted by the caller. This function is
|
||||
@@ -643,6 +660,7 @@ class NATIVE_THEME_EXPORT NativeTheme {
|
||||
@@ -654,6 +671,7 @@ class NATIVE_THEME_EXPORT NativeTheme {
|
||||
bool inverted_colors_ = false;
|
||||
PreferredColorScheme preferred_color_scheme_ = PreferredColorScheme::kLight;
|
||||
PreferredContrast preferred_contrast_ = PreferredContrast::kNoPreference;
|
||||
@@ -62,10 +62,10 @@ index 6f51a8ffec973d6c2acacabb951c7cc4e36b639c..889e655fccc115faae932236cc28c638
|
||||
SEQUENCE_CHECKER(sequence_checker_);
|
||||
};
|
||||
diff --git a/ui/native_theme/native_theme_win.cc b/ui/native_theme/native_theme_win.cc
|
||||
index faa15be0b3e08360c702b32968d3b1633038d776..7a6c284143e873b408333fa2052e05863935cb89 100644
|
||||
index 595b7185832126dd3d8ca85c445b835e5969adcb..58c64b98a0f94b0be7e7819999cf81dedf9bbe08 100644
|
||||
--- a/ui/native_theme/native_theme_win.cc
|
||||
+++ b/ui/native_theme/native_theme_win.cc
|
||||
@@ -658,6 +658,8 @@ bool NativeThemeWin::ShouldUseDarkColors() const {
|
||||
@@ -663,6 +663,8 @@ bool NativeThemeWin::ShouldUseDarkColors() const {
|
||||
// ...unless --force-dark-mode was specified in which case caveat emptor.
|
||||
if (InForcedColorsMode() && !IsForcedDarkMode())
|
||||
return false;
|
||||
|
||||
@@ -514,7 +514,7 @@ index 796ae2688436eb07f19909641d1620dd02f10cdb..c9e0eee0b329caf46669b419b1cd10cf
|
||||
waiting_on_draw_ack_ = true;
|
||||
|
||||
diff --git a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc
|
||||
index c70b0af70a68386c5d36833e621dd1b5cdc1522a..17e5c96cbb4ef2f575fd5ba7bd8b0c7bd58da5e7 100644
|
||||
index 1c59eb0cdf1786a19f74f165acc3fb071dcf2fa1..ddb2389f548a8558f79d7cf32ffd6ce0a7751553 100644
|
||||
--- a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc
|
||||
+++ b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc
|
||||
@@ -97,7 +97,8 @@ RootCompositorFrameSinkImpl::Create(
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -17,7 +17,7 @@ policy->CanCommitOriginAndUrl.
|
||||
Upstreamed at https://chromium-review.googlesource.com/c/chromium/src/+/3856266.
|
||||
|
||||
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc
|
||||
index e91fb6b203b55d4937e9f4b4ed8fd5e8efb5aa10..855cb90260de04b90b8bbf4a8733e0869cda551d 100644
|
||||
index 5cf177fc73dd2b3038754b11d23ad637e7709f88..72103151867a9c1154b83da83b52a5b3b7b988ed 100644
|
||||
--- a/content/browser/renderer_host/navigation_request.cc
|
||||
+++ b/content/browser/renderer_host/navigation_request.cc
|
||||
@@ -7543,10 +7543,11 @@ NavigationRequest::GetOriginForURLLoaderFactoryAfterResponseWithDebugInfo() {
|
||||
|
||||
@@ -25,10 +25,10 @@ index c9a13aee1e64f359cd1d5c2e440b4df204420997..7790c311400fc84bfda6c99e1ebd8da7
|
||||
// Returns true if duplex mode is set.
|
||||
bool SetDuplexModeInPrintSettings(mojom::DuplexMode mode);
|
||||
diff --git a/printing/printing_context_mac.mm b/printing/printing_context_mac.mm
|
||||
index ee900c7541af99c61844920433ae39e2648ae90b..59137008aeddc03d60c58a463206dc91a0ef5c1f 100644
|
||||
index 7c9204db9b4c8f36e4c7405e3bd9c8b311753f04..4bff296ea2c55175416aaa778856e6182866664f 100644
|
||||
--- a/printing/printing_context_mac.mm
|
||||
+++ b/printing/printing_context_mac.mm
|
||||
@@ -464,7 +464,8 @@ void ApplySystemPrintDialogData(
|
||||
@@ -473,7 +473,8 @@ void ApplySystemPrintDialogData(
|
||||
!SetCollateInPrintSettings(settings_->collate()) ||
|
||||
!SetDuplexModeInPrintSettings(settings_->duplex_mode()) ||
|
||||
!SetOutputColor(static_cast<int>(settings_->color())) ||
|
||||
@@ -38,7 +38,7 @@ index ee900c7541af99c61844920433ae39e2648ae90b..59137008aeddc03d60c58a463206dc91
|
||||
return OnError();
|
||||
}
|
||||
}
|
||||
@@ -617,6 +618,22 @@ void ApplySystemPrintDialogData(
|
||||
@@ -626,6 +627,22 @@ void ApplySystemPrintDialogData(
|
||||
return PMSetCopies(print_settings, copies, false) == noErr;
|
||||
}
|
||||
|
||||
@@ -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 e270fa36d775333aaa30f1ff0104062c544d1058..e4a6213e19e4f23834802784a43db22c9d02d891 100644
|
||||
index dcabfdab6cc5a0f0a79f797d3660118b780bd110..bcbfeef775e40c1b0c1bbac49dd520e602bc4cb9 100644
|
||||
--- a/ui/gtk/printing/print_dialog_gtk.cc
|
||||
+++ b/ui/gtk/printing/print_dialog_gtk.cc
|
||||
@@ -245,6 +245,24 @@ void PrintDialogGtk::UpdateSettings(
|
||||
@@ -248,6 +248,24 @@ void PrintDialogGtk::UpdateSettings(
|
||||
|
||||
gtk_print_settings_set_n_copies(gtk_settings_, settings->copies());
|
||||
gtk_print_settings_set_collate(gtk_settings_, settings->collate());
|
||||
|
||||
@@ -238,7 +238,7 @@ index 835cce73b7ab8b38c37d3e2650e12303d9d918e3..4460a00497dfaee0ba90cd5d14888055
|
||||
+
|
||||
#endif // UI_BASE_COCOA_REMOTE_ACCESSIBILITY_API_H_
|
||||
diff --git a/ui/views/cocoa/native_widget_mac_ns_window_host.h b/ui/views/cocoa/native_widget_mac_ns_window_host.h
|
||||
index 2daaf2b78b7a60d340c2ff1651f8b5450db4af0f..3080adea0402f9d57cbde5d4350605d463ee5c8e 100644
|
||||
index 6c2761b68d895fb1964e98865dd96cc37226fce0..563ee4da217ff4aabf2ef3452322da9e9ccefe4f 100644
|
||||
--- a/ui/views/cocoa/native_widget_mac_ns_window_host.h
|
||||
+++ b/ui/views/cocoa/native_widget_mac_ns_window_host.h
|
||||
@@ -30,7 +30,9 @@
|
||||
@@ -251,7 +251,7 @@ index 2daaf2b78b7a60d340c2ff1651f8b5450db4af0f..3080adea0402f9d57cbde5d4350605d4
|
||||
@class NSView;
|
||||
|
||||
namespace remote_cocoa {
|
||||
@@ -454,10 +456,12 @@ class VIEWS_EXPORT NativeWidgetMacNSWindowHost
|
||||
@@ -456,10 +458,12 @@ class VIEWS_EXPORT NativeWidgetMacNSWindowHost
|
||||
mojo::AssociatedRemote<remote_cocoa::mojom::NativeWidgetNSWindow>
|
||||
remote_ns_window_remote_;
|
||||
|
||||
@@ -265,10 +265,10 @@ index 2daaf2b78b7a60d340c2ff1651f8b5450db4af0f..3080adea0402f9d57cbde5d4350605d4
|
||||
// Used to force the NSApplication's focused accessibility element to be the
|
||||
// views::Views accessibility tree when the NSView for this is focused.
|
||||
diff --git a/ui/views/cocoa/native_widget_mac_ns_window_host.mm b/ui/views/cocoa/native_widget_mac_ns_window_host.mm
|
||||
index 53bdb4d62294f128b8f4b7bdcddf1052e15f331f..d052f5bb619bf4092810c6d5dd489a38a60026b0 100644
|
||||
index 6e0f07f5e1107341d0232e4a76b7332620315c04..0135aada72ef0c3a85ab8d134462754eb31ad2df 100644
|
||||
--- a/ui/views/cocoa/native_widget_mac_ns_window_host.mm
|
||||
+++ b/ui/views/cocoa/native_widget_mac_ns_window_host.mm
|
||||
@@ -339,7 +339,11 @@ void HandleAccelerator(const ui::Accelerator& accelerator,
|
||||
@@ -352,7 +352,11 @@ void HandleAccelerator(const ui::Accelerator& accelerator,
|
||||
NativeWidgetMacNSWindowHost::GetNativeViewAccessibleForNSView() const {
|
||||
if (in_process_ns_window_bridge_)
|
||||
return in_process_ns_window_bridge_->ns_view();
|
||||
@@ -280,7 +280,7 @@ index 53bdb4d62294f128b8f4b7bdcddf1052e15f331f..d052f5bb619bf4092810c6d5dd489a38
|
||||
}
|
||||
|
||||
gfx::NativeViewAccessible
|
||||
@@ -354,7 +358,11 @@ void HandleAccelerator(const ui::Accelerator& accelerator,
|
||||
@@ -367,7 +371,11 @@ void HandleAccelerator(const ui::Accelerator& accelerator,
|
||||
return [in_process_ns_window_bridge_->ns_view() window];
|
||||
}
|
||||
|
||||
@@ -292,7 +292,7 @@ index 53bdb4d62294f128b8f4b7bdcddf1052e15f331f..d052f5bb619bf4092810c6d5dd489a38
|
||||
}
|
||||
|
||||
remote_cocoa::mojom::NativeWidgetNSWindow*
|
||||
@@ -1353,20 +1361,24 @@ void HandleAccelerator(const ui::Accelerator& accelerator,
|
||||
@@ -1382,20 +1390,24 @@ void HandleAccelerator(const ui::Accelerator& accelerator,
|
||||
void NativeWidgetMacNSWindowHost::SetRemoteAccessibilityTokens(
|
||||
const std::vector<uint8_t>& window_token,
|
||||
const std::vector<uint8_t>& view_token) {
|
||||
|
||||
@@ -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 f076c5dc62ca5975865e3966381257684503eeb8..cb05975b622eee25217d9f2477c5e53ace017db8 100644
|
||||
index a107e19d2aa1cab31c88688904db128e61bcdc5e..30c2fb786dac5f38104ecdac170bdd2e76f1ab6f 100644
|
||||
--- a/services/network/network_context.cc
|
||||
+++ b/services/network/network_context.cc
|
||||
@@ -146,6 +146,11 @@
|
||||
@@ -122,7 +122,7 @@ index f076c5dc62ca5975865e3966381257684503eeb8..cb05975b622eee25217d9f2477c5e53a
|
||||
constexpr uint32_t NetworkContext::kMaxOutstandingRequestsPerProcess;
|
||||
|
||||
NetworkContext::NetworkContextHttpAuthPreferences::
|
||||
@@ -824,6 +922,13 @@ void NetworkContext::SetClient(
|
||||
@@ -826,6 +924,13 @@ void NetworkContext::SetClient(
|
||||
client_.Bind(std::move(client));
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ index f076c5dc62ca5975865e3966381257684503eeb8..cb05975b622eee25217d9f2477c5e53a
|
||||
void NetworkContext::CreateURLLoaderFactory(
|
||||
mojo::PendingReceiver<mojom::URLLoaderFactory> receiver,
|
||||
mojom::URLLoaderFactoryParamsPtr params) {
|
||||
@@ -2383,6 +2488,9 @@ URLRequestContextOwner NetworkContext::MakeURLRequestContext(
|
||||
@@ -2385,6 +2490,9 @@ URLRequestContextOwner NetworkContext::MakeURLRequestContext(
|
||||
std::move(cert_verifier));
|
||||
cert_verifier = base::WrapUnique(cert_verifier_with_trust_anchors_.get());
|
||||
#endif // BUILDFLAG(IS_CHROMEOS)
|
||||
@@ -147,7 +147,7 @@ index f076c5dc62ca5975865e3966381257684503eeb8..cb05975b622eee25217d9f2477c5e53a
|
||||
|
||||
builder.SetCertVerifier(IgnoreErrorsCertVerifier::MaybeWrapCertVerifier(
|
||||
diff --git a/services/network/network_context.h b/services/network/network_context.h
|
||||
index d046d6909a9e648ddc86cbed9cb118d29223155e..25f9dab24b27ad2b3d6ca01690e9f5c3fea96d32 100644
|
||||
index a1ac41b0850de88c3334d7b7aa3bfc470365b873..17ecfd109db3e9dbcc27ec291f6c6021c9b6f0eb 100644
|
||||
--- a/services/network/network_context.h
|
||||
+++ b/services/network/network_context.h
|
||||
@@ -114,6 +114,7 @@ class URLMatcher;
|
||||
@@ -177,7 +177,7 @@ index d046d6909a9e648ddc86cbed9cb118d29223155e..25f9dab24b27ad2b3d6ca01690e9f5c3
|
||||
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 039407080ba9b234b0472afd7d56d44802fd3c0e..6ebade992b628fee18d23e5e29d2d7d6190261a7 100644
|
||||
index 6164ab364a4044b9ca63d78dd5cc8c94ede7894c..64a840b13bc6c07112060f48d4f77507eb84994a 100644
|
||||
--- a/services/network/public/mojom/network_context.mojom
|
||||
+++ b/services/network/public/mojom/network_context.mojom
|
||||
@@ -317,6 +317,17 @@ struct NetworkContextFilePaths {
|
||||
|
||||
@@ -61,10 +61,10 @@ index f1aadfefe2b35ff4f292a04d834679e1c3fe89e9..7cb39e4059719a4fc323586e83aba47d
|
||||
}
|
||||
|
||||
diff --git a/ui/color/win/native_color_mixers_win.cc b/ui/color/win/native_color_mixers_win.cc
|
||||
index d9df0c0be6abf72c4756fb8e0f1e4b8c308a09f3..07ad3bf7e422272f017695c8b0e0aebedb8d8330 100644
|
||||
index a0eb66d2a28b19ee92e2c3c23fd3eff5d64d502d..1d3b62d504884e036365256443c1a1b4f0c796ab 100644
|
||||
--- a/ui/color/win/native_color_mixers_win.cc
|
||||
+++ b/ui/color/win/native_color_mixers_win.cc
|
||||
@@ -202,6 +202,10 @@ void AddNativeUiColorMixer(ColorProvider* provider,
|
||||
@@ -205,6 +205,10 @@ void AddNativeUiColorMixer(ColorProvider* provider,
|
||||
SetAlpha(kColorNotificationInputForeground, gfx::kGoogleGreyAlpha700);
|
||||
mixer[kColorSliderTrack] = AlphaBlend(
|
||||
kColorNativeHighlight, kColorNativeWindow, gfx::kGoogleGreyAlpha400);
|
||||
@@ -75,7 +75,7 @@ index d9df0c0be6abf72c4756fb8e0f1e4b8c308a09f3..07ad3bf7e422272f017695c8b0e0aebe
|
||||
|
||||
// Window Background
|
||||
mixer[kColorBubbleFooterBackground] = {kColorNativeWindow};
|
||||
@@ -211,6 +215,7 @@ void AddNativeUiColorMixer(ColorProvider* provider,
|
||||
@@ -214,6 +218,7 @@ void AddNativeUiColorMixer(ColorProvider* provider,
|
||||
mixer[kColorFrameInactive] = {kColorNativeWindow};
|
||||
mixer[kColorPrimaryBackground] = {kColorNativeWindow};
|
||||
mixer[kColorTooltipBackground] = {kColorNativeWindow};
|
||||
@@ -83,7 +83,7 @@ index d9df0c0be6abf72c4756fb8e0f1e4b8c308a09f3..07ad3bf7e422272f017695c8b0e0aebe
|
||||
|
||||
// Window Text
|
||||
mixer[kColorAlertLowSeverity] = {kColorNativeWindowText};
|
||||
@@ -225,6 +230,7 @@ void AddNativeUiColorMixer(ColorProvider* provider,
|
||||
@@ -228,6 +233,7 @@ void AddNativeUiColorMixer(ColorProvider* provider,
|
||||
mixer[kColorTableGroupingIndicator] = {kColorNativeWindowText};
|
||||
mixer[kColorThrobber] = {kColorNativeWindowText};
|
||||
mixer[kColorTooltipForeground] = {kColorNativeWindowText};
|
||||
@@ -91,7 +91,7 @@ index d9df0c0be6abf72c4756fb8e0f1e4b8c308a09f3..07ad3bf7e422272f017695c8b0e0aebe
|
||||
|
||||
// Hyperlinks
|
||||
mixer[kColorForcedHotlight] = {kColorNativeHotlight};
|
||||
@@ -271,6 +277,7 @@ void AddNativeUiColorMixer(ColorProvider* provider,
|
||||
@@ -274,6 +280,7 @@ void AddNativeUiColorMixer(ColorProvider* provider,
|
||||
mixer[kColorTextfieldForeground] = {kColorNativeBtnText};
|
||||
mixer[kColorTextfieldForegroundPlaceholder] = {kColorNativeBtnText};
|
||||
mixer[kColorTextfieldForegroundDisabled] = {kColorNativeBtnText};
|
||||
|
||||
@@ -706,7 +706,7 @@ index 3f9a514fb41d72c5d06de6ac989f9d7c0513a4e7..0e7ada9df962808dad7caf074a08ebde
|
||||
// Tells the browser printing failed.
|
||||
PrintingFailed(int32 cookie, PrintFailureReason reason);
|
||||
diff --git a/components/printing/renderer/print_render_frame_helper.cc b/components/printing/renderer/print_render_frame_helper.cc
|
||||
index 658a3c59993ac30feaea4d86148ed5adc9dcbdb1..afa788bbefc8f814af9b70ff5b5ebbc86a1777cd 100644
|
||||
index 5a58210461222ed431624bf161b32770c5ae97e6..aec69c525cefd73e50f50883ac0dc8bee94e78c0 100644
|
||||
--- a/components/printing/renderer/print_render_frame_helper.cc
|
||||
+++ b/components/printing/renderer/print_render_frame_helper.cc
|
||||
@@ -45,6 +45,7 @@
|
||||
@@ -717,7 +717,7 @@ index 658a3c59993ac30feaea4d86148ed5adc9dcbdb1..afa788bbefc8f814af9b70ff5b5ebbc8
|
||||
#include "printing/units.h"
|
||||
#include "services/metrics/public/cpp/ukm_source_id.h"
|
||||
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
|
||||
@@ -1322,14 +1323,14 @@ void PrintRenderFrameHelper::ScriptedPrint(bool user_initiated) {
|
||||
@@ -1237,14 +1238,14 @@ void PrintRenderFrameHelper::ScriptedPrint(bool user_initiated) {
|
||||
}
|
||||
|
||||
print_in_progress_ = true;
|
||||
@@ -734,7 +734,7 @@ index 658a3c59993ac30feaea4d86148ed5adc9dcbdb1..afa788bbefc8f814af9b70ff5b5ebbc8
|
||||
if (!weak_this) {
|
||||
return;
|
||||
}
|
||||
@@ -1360,7 +1361,7 @@ void PrintRenderFrameHelper::BindPrintRenderFrameReceiver(
|
||||
@@ -1275,7 +1276,7 @@ void PrintRenderFrameHelper::BindPrintRenderFrameReceiver(
|
||||
receivers_.Add(this, std::move(receiver));
|
||||
}
|
||||
|
||||
@@ -743,7 +743,7 @@ index 658a3c59993ac30feaea4d86148ed5adc9dcbdb1..afa788bbefc8f814af9b70ff5b5ebbc8
|
||||
ScopedIPC scoped_ipc(weak_ptr_factory_.GetWeakPtr());
|
||||
if (ipc_nesting_level_ > kAllowedIpcDepthForPrint)
|
||||
return;
|
||||
@@ -1375,7 +1376,7 @@ void PrintRenderFrameHelper::PrintRequestedPages() {
|
||||
@@ -1290,7 +1291,7 @@ void PrintRenderFrameHelper::PrintRequestedPages() {
|
||||
// plugin node and print that instead.
|
||||
auto plugin = delegate_->GetPdfElement(frame);
|
||||
|
||||
@@ -752,7 +752,7 @@ index 658a3c59993ac30feaea4d86148ed5adc9dcbdb1..afa788bbefc8f814af9b70ff5b5ebbc8
|
||||
|
||||
if (render_frame_gone_) {
|
||||
return;
|
||||
@@ -1462,7 +1463,8 @@ void PrintRenderFrameHelper::PrintForSystemDialog() {
|
||||
@@ -1377,7 +1378,8 @@ void PrintRenderFrameHelper::PrintForSystemDialog() {
|
||||
}
|
||||
|
||||
Print(frame, print_preview_context_.source_node(),
|
||||
@@ -762,7 +762,7 @@ index 658a3c59993ac30feaea4d86148ed5adc9dcbdb1..afa788bbefc8f814af9b70ff5b5ebbc8
|
||||
if (render_frame_gone_) {
|
||||
return;
|
||||
}
|
||||
@@ -1525,6 +1527,8 @@ void PrintRenderFrameHelper::PrintPreview(base::Value::Dict settings) {
|
||||
@@ -1440,6 +1442,8 @@ void PrintRenderFrameHelper::PrintPreview(base::Value::Dict settings) {
|
||||
if (ipc_nesting_level_ > kAllowedIpcDepthForPrint)
|
||||
return;
|
||||
|
||||
@@ -771,7 +771,7 @@ index 658a3c59993ac30feaea4d86148ed5adc9dcbdb1..afa788bbefc8f814af9b70ff5b5ebbc8
|
||||
print_preview_context_.OnPrintPreview();
|
||||
|
||||
#if BUILDFLAG(IS_CHROMEOS_ASH)
|
||||
@@ -2158,7 +2162,8 @@ void PrintRenderFrameHelper::PrintNode(const blink::WebNode& node) {
|
||||
@@ -2065,7 +2069,8 @@ void PrintRenderFrameHelper::PrintNode(const blink::WebNode& node) {
|
||||
}
|
||||
|
||||
Print(duplicate_node.GetDocument().GetFrame(), duplicate_node,
|
||||
@@ -781,7 +781,7 @@ index 658a3c59993ac30feaea4d86148ed5adc9dcbdb1..afa788bbefc8f814af9b70ff5b5ebbc8
|
||||
// Check if `this` is still valid.
|
||||
if (!weak_this) {
|
||||
return;
|
||||
@@ -2174,7 +2179,9 @@ void PrintRenderFrameHelper::PrintNode(const blink::WebNode& node) {
|
||||
@@ -2081,7 +2086,9 @@ void PrintRenderFrameHelper::PrintNode(const blink::WebNode& node) {
|
||||
|
||||
void PrintRenderFrameHelper::Print(blink::WebLocalFrame* frame,
|
||||
const blink::WebNode& node,
|
||||
@@ -792,7 +792,7 @@ index 658a3c59993ac30feaea4d86148ed5adc9dcbdb1..afa788bbefc8f814af9b70ff5b5ebbc8
|
||||
// If still not finished with earlier print request simply ignore.
|
||||
if (prep_frame_view_)
|
||||
return;
|
||||
@@ -2182,7 +2189,7 @@ void PrintRenderFrameHelper::Print(blink::WebLocalFrame* frame,
|
||||
@@ -2089,7 +2096,7 @@ void PrintRenderFrameHelper::Print(blink::WebLocalFrame* frame,
|
||||
FrameReference frame_ref(frame);
|
||||
|
||||
uint32_t expected_page_count = 0;
|
||||
@@ -801,7 +801,7 @@ index 658a3c59993ac30feaea4d86148ed5adc9dcbdb1..afa788bbefc8f814af9b70ff5b5ebbc8
|
||||
DidFinishPrinting(PrintingResult::kFailPrintInit);
|
||||
return; // Failed to init print page settings.
|
||||
}
|
||||
@@ -2201,8 +2208,15 @@ void PrintRenderFrameHelper::Print(blink::WebLocalFrame* frame,
|
||||
@@ -2108,8 +2115,15 @@ void PrintRenderFrameHelper::Print(blink::WebLocalFrame* frame,
|
||||
print_pages_params_->params->print_scaling_option;
|
||||
|
||||
auto self = weak_ptr_factory_.GetWeakPtr();
|
||||
@@ -818,7 +818,7 @@ index 658a3c59993ac30feaea4d86148ed5adc9dcbdb1..afa788bbefc8f814af9b70ff5b5ebbc8
|
||||
// Check if `this` is still valid.
|
||||
if (!self)
|
||||
return;
|
||||
@@ -2446,35 +2460,47 @@ void PrintRenderFrameHelper::IPCProcessed() {
|
||||
@@ -2349,35 +2363,47 @@ void PrintRenderFrameHelper::IPCProcessed() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -876,7 +876,7 @@ index 658a3c59993ac30feaea4d86148ed5adc9dcbdb1..afa788bbefc8f814af9b70ff5b5ebbc8
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2579,7 +2605,7 @@ mojom::PrintPagesParamsPtr PrintRenderFrameHelper::GetPrintSettingsFromUser(
|
||||
@@ -2482,7 +2508,7 @@ mojom::PrintPagesParamsPtr PrintRenderFrameHelper::GetPrintSettingsFromUser(
|
||||
std::move(params),
|
||||
base::BindOnce(
|
||||
[](base::OnceClosure quit_closure, mojom::PrintPagesParamsPtr* output,
|
||||
@@ -886,7 +886,7 @@ index 658a3c59993ac30feaea4d86148ed5adc9dcbdb1..afa788bbefc8f814af9b70ff5b5ebbc8
|
||||
std::move(quit_closure).Run();
|
||||
},
|
||||
diff --git a/components/printing/renderer/print_render_frame_helper.h b/components/printing/renderer/print_render_frame_helper.h
|
||||
index 8d65b7b6440c8e653eb1b3f9c50b40944b7ae61b..eb6b4a42d507ff216fc07328c1907815a082ef19 100644
|
||||
index 5cbb2940f83af329ea38efca5bf3216056269654..8cf783d37589fdca88592eeb9b8cc91b6ae60203 100644
|
||||
--- a/components/printing/renderer/print_render_frame_helper.h
|
||||
+++ b/components/printing/renderer/print_render_frame_helper.h
|
||||
@@ -247,7 +247,7 @@ class PrintRenderFrameHelper
|
||||
@@ -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 89b2e2bd7d6091501756b4d31726c49b00ffd0c7..718ad3e088f6730bb00f1e3674effae6c429b9b6 100644
|
||||
index 755bfcc4ed84f44d0d8bb53615637ccd69a858e7..368cf7aaffeef5f9796f78a72f13eddb6c44dec9 100644
|
||||
--- a/content/browser/BUILD.gn
|
||||
+++ b/content/browser/BUILD.gn
|
||||
@@ -2953,8 +2953,9 @@ source_set("browser") {
|
||||
@@ -2955,8 +2955,9 @@ source_set("browser") {
|
||||
"//ppapi/shared_impl",
|
||||
]
|
||||
|
||||
|
||||
2359
patches/chromium/revert_same_party_cookie_attribute_removal.patch
Normal file
2359
patches/chromium/revert_same_party_cookie_attribute_removal.patch
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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 586aa87098bd3db10440fe865a02c05e7b3be14f..cb372df065f83614ff6c2954035795e67eb69d0c 100644
|
||||
index 9b6ce4a1a495986333a0d173749a9a095c2e5603..7c9773236ada4ac921c73483f82a80b94ae2b129 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(
|
||||
|
||||
0
patches/libvpx/.patches
Normal file
0
patches/libvpx/.patches
Normal file
@@ -42,3 +42,10 @@ fix_isurl_implementation.patch
|
||||
ci_ensure_node_tests_set_electron_run_as_node.patch
|
||||
chore_update_fixtures_errors_force_colors_snapshot.patch
|
||||
fix_assert_module_in_the_renderer_process.patch
|
||||
tls_ensure_tls_sockets_are_closed_if_the_underlying_wrap_closes.patch
|
||||
test_deflake_test-tls-socket-close.patch
|
||||
net_fix_crash_due_to_simultaneous_close_shutdown_on_js_stream.patch
|
||||
net_use_asserts_in_js_socket_stream_to_catch_races_in_future.patch
|
||||
lib_fix_broadcastchannel_initialization_location.patch
|
||||
fix_handle_possible_disabled_sharedarraybuffer.patch
|
||||
win_process_avoid_assert_after_spawning_store_app_4152.patch
|
||||
|
||||
@@ -11,7 +11,7 @@ trying to see whether or not the lines are greyed out. One possibility
|
||||
would be to upstream a changed test that doesn't hardcode line numbers.
|
||||
|
||||
diff --git a/test/fixtures/errors/force_colors.snapshot b/test/fixtures/errors/force_colors.snapshot
|
||||
index 0334a0b4faa3633aa8617b9538873e7f3540513b..28ba4d18fe5e3caf4d904a055550110fd4faa609 100644
|
||||
index 0334a0b4faa3633aa8617b9538873e7f3540513b..fa9989f55980aeddd3fa944318488c0289e3ab6e 100644
|
||||
--- a/test/fixtures/errors/force_colors.snapshot
|
||||
+++ b/test/fixtures/errors/force_colors.snapshot
|
||||
@@ -4,11 +4,12 @@ throw new Error('Should include grayed stack trace')
|
||||
@@ -27,7 +27,7 @@ index 0334a0b4faa3633aa8617b9538873e7f3540513b..28ba4d18fe5e3caf4d904a055550110f
|
||||
+[90m at Object..js (node:internal*modules*cjs*loader:1326:10)[39m
|
||||
+[90m at Module.load (node:internal*modules*cjs*loader:1126:32)[39m
|
||||
+[90m at node:internal*modules*cjs*loader:967:12[39m
|
||||
+[90m at Function._load (node:electron*js2c*asar_bundle:756:32)[39m
|
||||
+[90m at Function._load (node:electron*js2c*asar_bundle:743:32)[39m
|
||||
+[90m at Function.executeUserEntryPoint [as runMain] (node:internal*modules*run_main:96:12)[39m
|
||||
[90m at node:internal*main*run_main_module:23:47[39m
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shelley Vohr <shelley.vohr@gmail.com>
|
||||
Date: Mon, 2 Oct 2023 16:03:43 +0200
|
||||
Subject: fix: handle possible disabled SharedArrayBuffer
|
||||
|
||||
It's possible for SharedArrayBuffer to be disabled with the -no-harmony-sharedarraybuffer
|
||||
flag, and so we should guard uses with a check for potential undefined-ness.
|
||||
|
||||
This should be upstreamed to Node.js.
|
||||
|
||||
diff --git a/lib/internal/crypto/webidl.js b/lib/internal/crypto/webidl.js
|
||||
index 9f5340c223902c5ff61def05e8a4f470b4f328e8..d6dbfa482f9ebff3f99fb810e072cf9a03d1cd4d 100644
|
||||
--- a/lib/internal/crypto/webidl.js
|
||||
+++ b/lib/internal/crypto/webidl.js
|
||||
@@ -183,7 +183,10 @@ function isNonSharedArrayBuffer(V) {
|
||||
return ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, V);
|
||||
}
|
||||
|
||||
+// SharedArrayBuffers can be disabled with --no-harmony-sharedarraybuffer.
|
||||
function isSharedArrayBuffer(V) {
|
||||
+ if (SharedArrayBuffer === undefined)
|
||||
+ return false;
|
||||
return ObjectPrototypeIsPrototypeOf(SharedArrayBuffer.prototype, V);
|
||||
}
|
||||
|
||||
diff --git a/lib/internal/main/worker_thread.js b/lib/internal/main/worker_thread.js
|
||||
index be4d82086199855a10108528b3dacc663b839454..10c33bacc0529e12f52aaf1baf6d42489b2a75a7 100644
|
||||
--- a/lib/internal/main/worker_thread.js
|
||||
+++ b/lib/internal/main/worker_thread.js
|
||||
@@ -108,6 +108,7 @@ port.on('message', (message) => {
|
||||
|
||||
require('internal/worker').assignEnvironmentData(environmentData);
|
||||
|
||||
+ // SharedArrayBuffers can be disabled with --no-harmony-sharedarraybuffer.
|
||||
if (SharedArrayBuffer !== undefined) {
|
||||
// The counter is only passed to the workers created by the main thread,
|
||||
// not to workers created by other workers.
|
||||
@@ -0,0 +1,44 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shelley Vohr <shelley.vohr@gmail.com>
|
||||
Date: Mon, 27 Feb 2023 12:56:15 +0100
|
||||
Subject: lib: fix BroadcastChannel initialization location
|
||||
|
||||
Refs https://github.com/nodejs/node/pull/40532.
|
||||
|
||||
Fixes a bug in the above, wherein BroadcastChannel should have been
|
||||
initialized in bootstrap/browser instead of bootstrap/node. That
|
||||
inadvertently made it such that there was incorrect handling of the
|
||||
DOM vs Node.js implementations of BroadcastChannel.
|
||||
|
||||
This will be upstreamed.
|
||||
|
||||
diff --git a/lib/internal/bootstrap/browser.js b/lib/internal/bootstrap/browser.js
|
||||
index 5be4dd6176482c724455cbbeeaa9680e849a091b..29ccee75d77da072735032f0a25363ac88a023ba 100644
|
||||
--- a/lib/internal/bootstrap/browser.js
|
||||
+++ b/lib/internal/bootstrap/browser.js
|
||||
@@ -12,6 +12,10 @@ const {
|
||||
} = require('internal/util');
|
||||
const config = internalBinding('config');
|
||||
|
||||
+// Non-standard extensions:
|
||||
+const { BroadcastChannel } = require('internal/worker/io');
|
||||
+exposeInterface(globalThis, 'BroadcastChannel', BroadcastChannel);
|
||||
+
|
||||
// https://console.spec.whatwg.org/#console-namespace
|
||||
exposeNamespace(globalThis, 'console',
|
||||
createGlobalConsole());
|
||||
diff --git a/lib/internal/bootstrap/node.js b/lib/internal/bootstrap/node.js
|
||||
index 13ea68c96fd415f976aab0f291a1b7c688db1c58..0ca3de08fffb344c0330ce0f8d28b2d3d0b24350 100644
|
||||
--- a/lib/internal/bootstrap/node.js
|
||||
+++ b/lib/internal/bootstrap/node.js
|
||||
@@ -238,10 +238,6 @@ const {
|
||||
queueMicrotask,
|
||||
} = require('internal/process/task_queues');
|
||||
|
||||
-// Non-standard extensions:
|
||||
-const { BroadcastChannel } = require('internal/worker/io');
|
||||
-exposeInterface(globalThis, 'BroadcastChannel', BroadcastChannel);
|
||||
-
|
||||
defineOperation(globalThis, 'queueMicrotask', queueMicrotask);
|
||||
|
||||
const timers = require('timers');
|
||||
@@ -0,0 +1,171 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tim Perry <pimterry@gmail.com>
|
||||
Date: Thu, 24 Aug 2023 16:05:02 +0100
|
||||
Subject: net: fix crash due to simultaneous close/shutdown on JS Stream
|
||||
Sockets
|
||||
|
||||
A JS stream socket wraps a stream, exposing it as a socket for something
|
||||
on top which needs a socket specifically (e.g. an HTTP server).
|
||||
|
||||
If the internal stream is closed in the same tick as the layer on top
|
||||
attempts to close this stream, the race between doShutdown and doClose
|
||||
results in an uncatchable exception. A similar race can happen with
|
||||
doClose and doWrite.
|
||||
|
||||
It seems legitimate these can happen in parallel, so this resolves that
|
||||
by explicitly detecting and handling that situation: if a close is in
|
||||
progress, both doShutdown & doWrite allow doClose to run
|
||||
finishShutdown/Write for them, cancelling the operation, without trying
|
||||
to use this._handle (which will be null) in the meantime.
|
||||
|
||||
PR-URL: https://github.com/nodejs/node/pull/49400
|
||||
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
|
||||
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
|
||||
|
||||
diff --git a/lib/internal/js_stream_socket.js b/lib/internal/js_stream_socket.js
|
||||
index 8bc19296620b3fd0e5487165743f0f1bc2d342e7..68e1802a63b012b59418b79a0e68de5147543a23 100644
|
||||
--- a/lib/internal/js_stream_socket.js
|
||||
+++ b/lib/internal/js_stream_socket.js
|
||||
@@ -21,6 +21,7 @@ const { ERR_STREAM_WRAP } = require('internal/errors').codes;
|
||||
const kCurrentWriteRequest = Symbol('kCurrentWriteRequest');
|
||||
const kCurrentShutdownRequest = Symbol('kCurrentShutdownRequest');
|
||||
const kPendingShutdownRequest = Symbol('kPendingShutdownRequest');
|
||||
+const kPendingClose = Symbol('kPendingClose');
|
||||
|
||||
function isClosing() { return this[owner_symbol].isClosing(); }
|
||||
|
||||
@@ -94,6 +95,7 @@ class JSStreamSocket extends Socket {
|
||||
this[kCurrentWriteRequest] = null;
|
||||
this[kCurrentShutdownRequest] = null;
|
||||
this[kPendingShutdownRequest] = null;
|
||||
+ this[kPendingClose] = false;
|
||||
this.readable = stream.readable;
|
||||
this.writable = stream.writable;
|
||||
|
||||
@@ -135,10 +137,17 @@ class JSStreamSocket extends Socket {
|
||||
this[kPendingShutdownRequest] = req;
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
assert(this[kCurrentWriteRequest] === null);
|
||||
assert(this[kCurrentShutdownRequest] === null);
|
||||
this[kCurrentShutdownRequest] = req;
|
||||
|
||||
+ if (this[kPendingClose]) {
|
||||
+ // If doClose is pending, the stream & this._handle are gone. We can't do
|
||||
+ // anything. doClose will call finishShutdown with ECANCELED for us shortly.
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
const handle = this._handle;
|
||||
|
||||
process.nextTick(() => {
|
||||
@@ -164,6 +173,13 @@ class JSStreamSocket extends Socket {
|
||||
assert(this[kCurrentWriteRequest] === null);
|
||||
assert(this[kCurrentShutdownRequest] === null);
|
||||
|
||||
+ if (this[kPendingClose]) {
|
||||
+ // If doClose is pending, the stream & this._handle are gone. We can't do
|
||||
+ // anything. doClose will call finishWrite with ECANCELED for us shortly.
|
||||
+ this[kCurrentWriteRequest] = req; // Store req, for doClose to cancel
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
const handle = this._handle;
|
||||
const self = this;
|
||||
|
||||
@@ -217,6 +233,8 @@ class JSStreamSocket extends Socket {
|
||||
}
|
||||
|
||||
doClose(cb) {
|
||||
+ this[kPendingClose] = true;
|
||||
+
|
||||
const handle = this._handle;
|
||||
|
||||
// When sockets of the "net" module destroyed, they will call
|
||||
@@ -234,6 +252,8 @@ class JSStreamSocket extends Socket {
|
||||
this.finishWrite(handle, uv.UV_ECANCELED);
|
||||
this.finishShutdown(handle, uv.UV_ECANCELED);
|
||||
|
||||
+ this[kPendingClose] = false;
|
||||
+
|
||||
cb();
|
||||
});
|
||||
}
|
||||
diff --git a/test/parallel/test-http2-client-connection-tunnelling.js b/test/parallel/test-http2-client-connection-tunnelling.js
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..6e04121ca71ea81f49c7f50ec11d7fac735c80a9
|
||||
--- /dev/null
|
||||
+++ b/test/parallel/test-http2-client-connection-tunnelling.js
|
||||
@@ -0,0 +1,71 @@
|
||||
+'use strict';
|
||||
+
|
||||
+const common = require('../common');
|
||||
+const fixtures = require('../common/fixtures');
|
||||
+if (!common.hasCrypto)
|
||||
+ common.skip('missing crypto');
|
||||
+const assert = require('assert');
|
||||
+const net = require('net');
|
||||
+const tls = require('tls');
|
||||
+const h2 = require('http2');
|
||||
+
|
||||
+// This test sets up an H2 proxy server, and tunnels a request over one of its streams
|
||||
+// back to itself, via TLS, and then closes the TLS connection. On some Node versions
|
||||
+// (v18 & v20 up to 20.5.1) the resulting JS Stream Socket fails to shutdown correctly
|
||||
+// in this case, and crashes due to a null pointer in finishShutdown.
|
||||
+
|
||||
+const tlsOptions = {
|
||||
+ key: fixtures.readKey('agent1-key.pem'),
|
||||
+ cert: fixtures.readKey('agent1-cert.pem'),
|
||||
+ ALPNProtocols: ['h2']
|
||||
+};
|
||||
+
|
||||
+const netServer = net.createServer((socket) => {
|
||||
+ socket.allowHalfOpen = false;
|
||||
+ // ^ This allows us to trigger this reliably, but it's not strictly required
|
||||
+ // for the bug and crash to happen, skipping this just fails elsewhere later.
|
||||
+
|
||||
+ h2Server.emit('connection', socket);
|
||||
+});
|
||||
+
|
||||
+const h2Server = h2.createSecureServer(tlsOptions, (req, res) => {
|
||||
+ res.writeHead(200);
|
||||
+ res.end();
|
||||
+});
|
||||
+
|
||||
+h2Server.on('connect', (req, res) => {
|
||||
+ res.writeHead(200, {});
|
||||
+ netServer.emit('connection', res.stream);
|
||||
+});
|
||||
+
|
||||
+netServer.listen(0, common.mustCall(() => {
|
||||
+ const proxyClient = h2.connect(`https://localhost:${netServer.address().port}`, {
|
||||
+ rejectUnauthorized: false
|
||||
+ });
|
||||
+
|
||||
+ const proxyReq = proxyClient.request({
|
||||
+ ':method': 'CONNECT',
|
||||
+ ':authority': 'example.com:443'
|
||||
+ });
|
||||
+
|
||||
+ proxyReq.on('response', common.mustCall((response) => {
|
||||
+ assert.strictEqual(response[':status'], 200);
|
||||
+
|
||||
+ // Create a TLS socket within the tunnel, and start sending a request:
|
||||
+ const tlsSocket = tls.connect({
|
||||
+ socket: proxyReq,
|
||||
+ ALPNProtocols: ['h2'],
|
||||
+ rejectUnauthorized: false
|
||||
+ });
|
||||
+
|
||||
+ proxyReq.on('close', common.mustCall(() => {
|
||||
+ proxyClient.close();
|
||||
+ netServer.close();
|
||||
+ }));
|
||||
+
|
||||
+ // Forcibly kill the TLS socket
|
||||
+ tlsSocket.destroy();
|
||||
+
|
||||
+ // This results in an async error in affected Node versions, before the 'close' event
|
||||
+ }));
|
||||
+}));
|
||||
@@ -0,0 +1,30 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tim Perry <pimterry@gmail.com>
|
||||
Date: Fri, 25 Aug 2023 14:16:35 +0100
|
||||
Subject: net: use asserts in JS Socket Stream to catch races in future
|
||||
|
||||
PR-URL: https://github.com/nodejs/node/pull/49400
|
||||
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
|
||||
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
|
||||
|
||||
diff --git a/lib/internal/js_stream_socket.js b/lib/internal/js_stream_socket.js
|
||||
index 68e1802a63b012b59418b79a0e68de5147543a23..70d6d03069f3f1e85e66864c6c1e6de6084f5ea6 100644
|
||||
--- a/lib/internal/js_stream_socket.js
|
||||
+++ b/lib/internal/js_stream_socket.js
|
||||
@@ -149,6 +149,7 @@ class JSStreamSocket extends Socket {
|
||||
}
|
||||
|
||||
const handle = this._handle;
|
||||
+ assert(handle !== null);
|
||||
|
||||
process.nextTick(() => {
|
||||
// Ensure that write is dispatched asynchronously.
|
||||
@@ -181,6 +182,8 @@ class JSStreamSocket extends Socket {
|
||||
}
|
||||
|
||||
const handle = this._handle;
|
||||
+ assert(handle !== null);
|
||||
+
|
||||
const self = this;
|
||||
|
||||
let pending = bufs.length;
|
||||
28
patches/node/test_deflake_test-tls-socket-close.patch
Normal file
28
patches/node/test_deflake_test-tls-socket-close.patch
Normal file
@@ -0,0 +1,28 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Luigi Pinca <luigipinca@gmail.com>
|
||||
Date: Wed, 13 Sep 2023 08:04:39 +0200
|
||||
Subject: test: deflake test-tls-socket-close
|
||||
|
||||
Move the check for the destroyed state of the remote socket to the inner
|
||||
`setImmediate()`.
|
||||
|
||||
Refs: https://github.com/nodejs/node/pull/49327#issuecomment-1712525257
|
||||
PR-URL: https://github.com/nodejs/node/pull/49575
|
||||
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
|
||||
Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
|
||||
|
||||
diff --git a/test/parallel/test-tls-socket-close.js b/test/parallel/test-tls-socket-close.js
|
||||
index 667b291309a4c5636a2c658fa8204b32c2e4df46..70af760d53bb4ddab62c99180d505e943ec269f6 100644
|
||||
--- a/test/parallel/test-tls-socket-close.js
|
||||
+++ b/test/parallel/test-tls-socket-close.js
|
||||
@@ -44,9 +44,9 @@ function connectClient(server) {
|
||||
|
||||
setImmediate(() => {
|
||||
assert.strictEqual(netSocket.destroyed, true);
|
||||
- assert.strictEqual(clientTlsSocket.destroyed, true);
|
||||
|
||||
setImmediate(() => {
|
||||
+ assert.strictEqual(clientTlsSocket.destroyed, true);
|
||||
assert.strictEqual(serverTlsSocket.destroyed, true);
|
||||
|
||||
tlsServer.close();
|
||||
@@ -7,10 +7,10 @@ Instead of disabling the tests, flag them as flaky so they still run
|
||||
but don't cause CI failures on flakes.
|
||||
|
||||
diff --git a/test/parallel/parallel.status b/test/parallel/parallel.status
|
||||
index 913ae4b0b10a7d508d864539cf075fa9c2f9362c..985f1c0d0c0c6afc049bf1d89f91412ecf431215 100644
|
||||
index 913ae4b0b10a7d508d864539cf075fa9c2f9362c..0539a599e57d40c5da650dcf5ffe9a67763506e1 100644
|
||||
--- a/test/parallel/parallel.status
|
||||
+++ b/test/parallel/parallel.status
|
||||
@@ -5,6 +5,12 @@ prefix parallel
|
||||
@@ -5,6 +5,13 @@ prefix parallel
|
||||
# sample-test : PASS,FLAKY
|
||||
|
||||
[true] # This section applies to all platforms
|
||||
@@ -20,6 +20,7 @@ index 913ae4b0b10a7d508d864539cf075fa9c2f9362c..985f1c0d0c0c6afc049bf1d89f91412e
|
||||
+test-fetch: PASS, FLAKY
|
||||
+test-cluster-bind-privileged-port: PASS, FLAKY
|
||||
+test-cluster-shared-handle-bind-privileged-port: PASS, FLAKY
|
||||
+test-debugger-random-port-with-inspect-port: PASS, FLAKY
|
||||
|
||||
[$system==win32]
|
||||
# https://github.com/nodejs/node/issues/24497
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tim Perry <1526883+pimterry@users.noreply.github.com>
|
||||
Date: Fri, 1 Sep 2023 09:00:05 +0200
|
||||
Subject: tls: ensure TLS Sockets are closed if the underlying wrap closes
|
||||
|
||||
This fixes a potential segfault, among various other likely-related
|
||||
issues, which all occur because TLSSockets were not informed if their
|
||||
underlying stream was closed in many cases.
|
||||
|
||||
This also significantly modifies an existing TLS test. With this change
|
||||
in place, that test no longer works, as it tries to mess with internals
|
||||
to trigger a race, and those internals are now cleaned up earlier. This
|
||||
test has been simplified to a more general TLS shutdown test.
|
||||
|
||||
PR-URL: https://github.com/nodejs/node/pull/49327
|
||||
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
|
||||
Reviewed-By: Debadree Chatterjee <debadree333@gmail.com>
|
||||
|
||||
diff --git a/lib/_tls_wrap.js b/lib/_tls_wrap.js
|
||||
index 1eff3b3fba8a05d5fade43c6cb00b6621daa8c3d..5bed23e1355e5e5a1965f15ca270fb372f751d66 100644
|
||||
--- a/lib/_tls_wrap.js
|
||||
+++ b/lib/_tls_wrap.js
|
||||
@@ -629,6 +629,9 @@ TLSSocket.prototype._wrapHandle = function(wrap, handle) {
|
||||
defineHandleReading(this, handle);
|
||||
|
||||
this.on('close', onSocketCloseDestroySSL);
|
||||
+ if (wrap) {
|
||||
+ wrap.on('close', () => this.destroy());
|
||||
+ }
|
||||
|
||||
return res;
|
||||
};
|
||||
diff --git a/test/parallel/test-http2-socket-close.js b/test/parallel/test-http2-socket-close.js
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..02db77bcf8480c79c77175ba802f9fe10ffc4efe
|
||||
--- /dev/null
|
||||
+++ b/test/parallel/test-http2-socket-close.js
|
||||
@@ -0,0 +1,67 @@
|
||||
+'use strict';
|
||||
+
|
||||
+const common = require('../common');
|
||||
+const fixtures = require('../common/fixtures');
|
||||
+if (!common.hasCrypto)
|
||||
+ common.skip('missing crypto');
|
||||
+const assert = require('assert');
|
||||
+const net = require('net');
|
||||
+const h2 = require('http2');
|
||||
+
|
||||
+const tlsOptions = {
|
||||
+ key: fixtures.readKey('agent1-key.pem'),
|
||||
+ cert: fixtures.readKey('agent1-cert.pem'),
|
||||
+ ALPNProtocols: ['h2']
|
||||
+};
|
||||
+
|
||||
+// Create a net server that upgrades sockets to HTTP/2 manually, handles the
|
||||
+// request, and then shuts down via a short socket timeout and a longer H2 session
|
||||
+// timeout. This is an unconventional way to shut down a session (the underlying
|
||||
+// socket closing first) but it should work - critically, it shouldn't segfault
|
||||
+// (as it did until Node v20.5.1).
|
||||
+
|
||||
+let serverRawSocket;
|
||||
+let serverH2Session;
|
||||
+
|
||||
+const netServer = net.createServer((socket) => {
|
||||
+ serverRawSocket = socket;
|
||||
+ h2Server.emit('connection', socket);
|
||||
+});
|
||||
+
|
||||
+const h2Server = h2.createSecureServer(tlsOptions, (req, res) => {
|
||||
+ res.writeHead(200);
|
||||
+ res.end();
|
||||
+});
|
||||
+
|
||||
+h2Server.on('session', (session) => {
|
||||
+ serverH2Session = session;
|
||||
+});
|
||||
+
|
||||
+netServer.listen(0, common.mustCall(() => {
|
||||
+ const proxyClient = h2.connect(`https://localhost:${netServer.address().port}`, {
|
||||
+ rejectUnauthorized: false
|
||||
+ });
|
||||
+
|
||||
+ proxyClient.on('close', common.mustCall(() => {
|
||||
+ netServer.close();
|
||||
+ }));
|
||||
+
|
||||
+ const req = proxyClient.request({
|
||||
+ ':method': 'GET',
|
||||
+ ':path': '/'
|
||||
+ });
|
||||
+
|
||||
+ req.on('response', common.mustCall((response) => {
|
||||
+ assert.strictEqual(response[':status'], 200);
|
||||
+
|
||||
+ // Asynchronously shut down the server's connections after the response,
|
||||
+ // but not in the order it typically expects:
|
||||
+ setTimeout(() => {
|
||||
+ serverRawSocket.destroy();
|
||||
+
|
||||
+ setTimeout(() => {
|
||||
+ serverH2Session.close();
|
||||
+ }, 10);
|
||||
+ }, 10);
|
||||
+ }));
|
||||
+}));
|
||||
diff --git a/test/parallel/test-tls-socket-close.js b/test/parallel/test-tls-socket-close.js
|
||||
index 87355cf8d7bd2d07bb0fab59491b68f3963f8809..667b291309a4c5636a2c658fa8204b32c2e4df46 100644
|
||||
--- a/test/parallel/test-tls-socket-close.js
|
||||
+++ b/test/parallel/test-tls-socket-close.js
|
||||
@@ -8,37 +8,18 @@ const tls = require('tls');
|
||||
const net = require('net');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
-// Regression test for https://github.com/nodejs/node/issues/8074
|
||||
-//
|
||||
-// This test has a dependency on the order in which the TCP connection is made,
|
||||
-// and TLS server handshake completes. It assumes those server side events occur
|
||||
-// before the client side write callback, which is not guaranteed by the TLS
|
||||
-// API. It usually passes with TLS1.3, but TLS1.3 didn't exist at the time the
|
||||
-// bug existed.
|
||||
-//
|
||||
-// Pin the test to TLS1.2, since the test shouldn't be changed in a way that
|
||||
-// doesn't trigger a segfault in Node.js 7.7.3:
|
||||
-// https://github.com/nodejs/node/issues/13184#issuecomment-303700377
|
||||
-tls.DEFAULT_MAX_VERSION = 'TLSv1.2';
|
||||
-
|
||||
const key = fixtures.readKey('agent2-key.pem');
|
||||
const cert = fixtures.readKey('agent2-cert.pem');
|
||||
|
||||
-let tlsSocket;
|
||||
-// tls server
|
||||
+let serverTlsSocket;
|
||||
const tlsServer = tls.createServer({ cert, key }, (socket) => {
|
||||
- tlsSocket = socket;
|
||||
- socket.on('error', common.mustCall((error) => {
|
||||
- assert.strictEqual(error.code, 'EINVAL');
|
||||
- tlsServer.close();
|
||||
- netServer.close();
|
||||
- }));
|
||||
+ serverTlsSocket = socket;
|
||||
});
|
||||
|
||||
+// A plain net server, that manually passes connections to the TLS
|
||||
+// server to be upgraded
|
||||
let netSocket;
|
||||
-// plain tcp server
|
||||
const netServer = net.createServer((socket) => {
|
||||
- // If client wants to use tls
|
||||
tlsServer.emit('connection', socket);
|
||||
|
||||
netSocket = socket;
|
||||
@@ -46,35 +27,32 @@ const netServer = net.createServer((socket) => {
|
||||
connectClient(netServer);
|
||||
}));
|
||||
|
||||
+// A client that connects, sends one message, and closes the raw connection:
|
||||
function connectClient(server) {
|
||||
- const tlsConnection = tls.connect({
|
||||
+ const clientTlsSocket = tls.connect({
|
||||
host: 'localhost',
|
||||
port: server.address().port,
|
||||
rejectUnauthorized: false
|
||||
});
|
||||
|
||||
- tlsConnection.write('foo', 'utf8', common.mustCall(() => {
|
||||
+ clientTlsSocket.write('foo', 'utf8', common.mustCall(() => {
|
||||
assert(netSocket);
|
||||
netSocket.setTimeout(common.platformTimeout(10), common.mustCall(() => {
|
||||
- assert(tlsSocket);
|
||||
- // This breaks if TLSSocket is already managing the socket:
|
||||
+ assert(serverTlsSocket);
|
||||
+
|
||||
netSocket.destroy();
|
||||
- const interval = setInterval(() => {
|
||||
- // Checking this way allows us to do the write at a time that causes a
|
||||
- // segmentation fault (not always, but often) in Node.js 7.7.3 and
|
||||
- // earlier. If we instead, for example, wait on the `close` event, then
|
||||
- // it will not segmentation fault, which is what this test is all about.
|
||||
- if (tlsSocket._handle._parent.bytesRead === 0) {
|
||||
- tlsSocket.write('bar');
|
||||
- clearInterval(interval);
|
||||
- }
|
||||
- }, 1);
|
||||
+
|
||||
+ setImmediate(() => {
|
||||
+ assert.strictEqual(netSocket.destroyed, true);
|
||||
+ assert.strictEqual(clientTlsSocket.destroyed, true);
|
||||
+
|
||||
+ setImmediate(() => {
|
||||
+ assert.strictEqual(serverTlsSocket.destroyed, true);
|
||||
+
|
||||
+ tlsServer.close();
|
||||
+ netServer.close();
|
||||
+ });
|
||||
+ });
|
||||
}));
|
||||
}));
|
||||
- tlsConnection.on('error', (e) => {
|
||||
- // Tolerate the occasional ECONNRESET.
|
||||
- // Ref: https://github.com/nodejs/node/issues/13184
|
||||
- if (e.code !== 'ECONNRESET')
|
||||
- throw e;
|
||||
- });
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jameson Nash <vtjnash@gmail.com>
|
||||
Date: Mon, 2 Oct 2023 15:15:18 +0200
|
||||
Subject: win,process: avoid assert after spawning Store app (#4152)
|
||||
|
||||
Make sure this handle is functional. The Windows kernel seems to have a
|
||||
bug that if the first use of AssignProcessToJobObject is for a Windows
|
||||
Store program, subsequent attempts to use the handle with fail with
|
||||
INVALID_PARAMETER (87). This is possilby because all uses of the handle
|
||||
must be for the same Terminal Services session. We can ensure it is
|
||||
tied to our current session now by adding ourself to it. We could
|
||||
remove ourself afterwards, but there doesn't seem to be a reason to.
|
||||
|
||||
Secondly, we start the process suspended so that we can make sure we
|
||||
added it to the job control object before it does anything itself (such
|
||||
as launch more jobs or exit).
|
||||
|
||||
Fixes: https://github.com/JuliaLang/julia/issues/51461
|
||||
|
||||
diff --git a/deps/uv/src/win/process.c b/deps/uv/src/win/process.c
|
||||
index 24c633393fd15dcf87726b174d6b027a969e0f0d..4ad9fec900fa66b0e8c6894701e94f420de903a8 100644
|
||||
--- a/deps/uv/src/win/process.c
|
||||
+++ b/deps/uv/src/win/process.c
|
||||
@@ -102,6 +102,21 @@ static void uv__init_global_job_handle(void) {
|
||||
&info,
|
||||
sizeof info))
|
||||
uv_fatal_error(GetLastError(), "SetInformationJobObject");
|
||||
+
|
||||
+
|
||||
+ if (!AssignProcessToJobObject(uv_global_job_handle_, GetCurrentProcess())) {
|
||||
+ /* Make sure this handle is functional. The Windows kernel has a bug that
|
||||
+ * if the first use of AssignProcessToJobObject is for a Windows Store
|
||||
+ * program, subsequent attempts to use the handle with fail with
|
||||
+ * INVALID_PARAMETER (87). This is possibly because all uses of the handle
|
||||
+ * must be for the same Terminal Services session. We can ensure it is tied
|
||||
+ * to our current session now by adding ourself to it. We could remove
|
||||
+ * ourself afterwards, but there doesn't seem to be a reason to.
|
||||
+ */
|
||||
+ DWORD err = GetLastError();
|
||||
+ if (err != ERROR_ACCESS_DENIED)
|
||||
+ uv_fatal_error(err, "AssignProcessToJobObject");
|
||||
+ }
|
||||
}
|
||||
|
||||
|
||||
@@ -1098,6 +1113,7 @@ int uv_spawn(uv_loop_t* loop,
|
||||
* breakaway.
|
||||
*/
|
||||
process_flags |= DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP;
|
||||
+ process_flags |= CREATE_SUSPENDED;
|
||||
}
|
||||
|
||||
if (!CreateProcessW(application_path,
|
||||
@@ -1115,11 +1131,6 @@ int uv_spawn(uv_loop_t* loop,
|
||||
goto done;
|
||||
}
|
||||
|
||||
- /* Spawn succeeded. Beyond this point, failure is reported asynchronously. */
|
||||
-
|
||||
- process->process_handle = info.hProcess;
|
||||
- process->pid = info.dwProcessId;
|
||||
-
|
||||
/* If the process isn't spawned as detached, assign to the global job object
|
||||
* so windows will kill it when the parent process dies. */
|
||||
if (!(options->flags & UV_PROCESS_DETACHED)) {
|
||||
@@ -1142,6 +1153,19 @@ int uv_spawn(uv_loop_t* loop,
|
||||
}
|
||||
}
|
||||
|
||||
+ if (process_flags & CREATE_SUSPENDED) {
|
||||
+ if (ResumeThread(info.hThread) == ((DWORD)-1)) {
|
||||
+ err = GetLastError();
|
||||
+ TerminateProcess(info.hProcess, 1);
|
||||
+ goto done;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Spawn succeeded. Beyond this point, failure is reported asynchronously. */
|
||||
+
|
||||
+ process->process_handle = info.hProcess;
|
||||
+ process->pid = info.dwProcessId;
|
||||
+
|
||||
/* Set IPC pid to all IPC pipes. */
|
||||
for (i = 0; i < options->stdio_count; i++) {
|
||||
const uv_stdio_container_t* fdopt = &options->stdio[i];
|
||||
@@ -1,2 +1,3 @@
|
||||
fix_fallback_to_x11_capturer_on_wayland.patch
|
||||
fix_mark_pipewire_capturer_as_failed_after_session_is_closed.patch
|
||||
fix_check_pipewire_init_before_creating_generic_capturer.patch
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Athul Iddya <athul@iddya.com>
|
||||
Date: Tue, 12 Sep 2023 22:19:46 -0700
|
||||
Subject: fix: check PipeWire init before creating generic capturer
|
||||
|
||||
Check if PipeWire can be initialized before creating generic capturer.
|
||||
This harmonizes the conditions with the ones used in Linux
|
||||
implementations of DesktopCapturer::CreateRawScreenCapturer and
|
||||
DesktopCapturer::CreateRawWindowCapturer.
|
||||
|
||||
diff --git a/modules/desktop_capture/desktop_capturer.cc b/modules/desktop_capture/desktop_capturer.cc
|
||||
index a52a76c2625cf0a2eae7ab5b841e0bf4ff499d88..099313bc1b4e75ebbe62c30190a068f68bfe5366 100644
|
||||
--- a/modules/desktop_capture/desktop_capturer.cc
|
||||
+++ b/modules/desktop_capture/desktop_capturer.cc
|
||||
@@ -113,7 +113,7 @@ std::unique_ptr<DesktopCapturer> DesktopCapturer::CreateGenericCapturer(
|
||||
std::unique_ptr<DesktopCapturer> capturer;
|
||||
|
||||
#if defined(WEBRTC_USE_PIPEWIRE)
|
||||
- if (options.allow_pipewire() && DesktopCapturer::IsRunningUnderWayland()) {
|
||||
+ if (options.allow_pipewire() && BaseCapturerPipeWire::IsSupported()) {
|
||||
capturer = std::make_unique<BaseCapturerPipeWire>(
|
||||
options, CaptureType::kAnyScreenContent);
|
||||
}
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "base/path_service.h"
|
||||
#include "base/system/sys_info.h"
|
||||
#include "base/values.h"
|
||||
#include "base/win/windows_version.h"
|
||||
#include "chrome/browser/browser_process.h"
|
||||
#include "chrome/browser/icon_manager.h"
|
||||
#include "chrome/common/chrome_features.h"
|
||||
@@ -1478,23 +1479,8 @@ void App::SetUserAgentFallback(const std::string& user_agent) {
|
||||
}
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
|
||||
bool App::IsRunningUnderARM64Translation() const {
|
||||
USHORT processMachine = 0;
|
||||
USHORT nativeMachine = 0;
|
||||
|
||||
auto IsWow64Process2 = reinterpret_cast<decltype(&::IsWow64Process2)>(
|
||||
GetProcAddress(GetModuleHandle(L"kernel32.dll"), "IsWow64Process2"));
|
||||
|
||||
if (IsWow64Process2 == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsWow64Process2(GetCurrentProcess(), &processMachine, &nativeMachine)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return nativeMachine == IMAGE_FILE_MACHINE_ARM64;
|
||||
return base::win::OSInfo::IsRunningEmulatedOnArm64();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -953,6 +953,14 @@ void BaseWindow::AddTabbedWindow(NativeWindow* window,
|
||||
args->ThrowError("AddTabbedWindow cannot be called by a window on itself.");
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> BaseWindow::GetTabbingIdentifier() {
|
||||
auto tabbing_id = window_->GetTabbingIdentifier();
|
||||
if (!tabbing_id.has_value())
|
||||
return v8::Undefined(isolate());
|
||||
|
||||
return gin::ConvertToV8(isolate(), tabbing_id.value());
|
||||
}
|
||||
|
||||
void BaseWindow::SetAutoHideMenuBar(bool auto_hide) {
|
||||
window_->SetAutoHideMenuBar(auto_hide);
|
||||
}
|
||||
@@ -1305,6 +1313,7 @@ void BaseWindow::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("moveTabToNewWindow", &BaseWindow::MoveTabToNewWindow)
|
||||
.SetMethod("toggleTabBar", &BaseWindow::ToggleTabBar)
|
||||
.SetMethod("addTabbedWindow", &BaseWindow::AddTabbedWindow)
|
||||
.SetProperty("tabbingIdentifier", &BaseWindow::GetTabbingIdentifier)
|
||||
.SetMethod("setWindowButtonVisibility",
|
||||
&BaseWindow::SetWindowButtonVisibility)
|
||||
.SetMethod("_getWindowButtonVisibility",
|
||||
|
||||
@@ -198,9 +198,7 @@ class BaseWindow : public gin_helper::TrackableObject<BaseWindow>,
|
||||
bool GetWindowButtonVisibility() const;
|
||||
void SetWindowButtonPosition(absl::optional<gfx::Point> position);
|
||||
absl::optional<gfx::Point> GetWindowButtonPosition() const;
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
bool IsHiddenInMissionControl();
|
||||
void SetHiddenInMissionControl(bool hidden);
|
||||
#endif
|
||||
@@ -215,6 +213,7 @@ class BaseWindow : public gin_helper::TrackableObject<BaseWindow>,
|
||||
void MoveTabToNewWindow();
|
||||
void ToggleTabBar();
|
||||
void AddTabbedWindow(NativeWindow* window, gin_helper::Arguments* args);
|
||||
v8::Local<v8::Value> GetTabbingIdentifier();
|
||||
void SetAutoHideMenuBar(bool auto_hide);
|
||||
bool IsMenuBarAutoHide();
|
||||
void SetMenuBarVisibility(bool visible);
|
||||
|
||||
@@ -43,19 +43,11 @@ BrowserWindow::BrowserWindow(gin::Arguments* args,
|
||||
gin::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.
|
||||
|
||||
@@ -90,16 +90,15 @@ 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)
|
||||
.SetMethod("isTrustedAccessibilityClient",
|
||||
&SystemPreferences::IsTrustedAccessibilityClient)
|
||||
.SetMethod("askForMediaAccess", &SystemPreferences::AskForMediaAccess)
|
||||
.SetProperty(
|
||||
"accessibilityDisplayShouldReduceTransparency",
|
||||
&SystemPreferences::AccessibilityDisplayShouldReduceTransparency)
|
||||
#endif
|
||||
.SetMethod("getAnimationSettings",
|
||||
&SystemPreferences::GetAnimationSettings);
|
||||
|
||||
@@ -96,6 +96,7 @@ class SystemPreferences
|
||||
gin::Arguments* args);
|
||||
void RemoveUserDefault(const std::string& name);
|
||||
bool IsSwipeTrackingFromScrollEventsEnabled();
|
||||
bool AccessibilityDisplayShouldReduceTransparency();
|
||||
|
||||
std::string GetSystemColor(gin_helper::ErrorThrower thrower,
|
||||
const std::string& color);
|
||||
@@ -112,8 +113,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);
|
||||
|
||||
|
||||
@@ -475,14 +475,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];
|
||||
@@ -609,19 +602,9 @@ 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();
|
||||
}
|
||||
bool SystemPreferences::AccessibilityDisplayShouldReduceTransparency() {
|
||||
return [[NSWorkspace sharedWorkspace]
|
||||
accessibilityDisplayShouldReduceTransparency];
|
||||
}
|
||||
|
||||
} // namespace electron::api
|
||||
|
||||
@@ -1726,13 +1726,6 @@ void WebContents::RenderViewDeleted(content::RenderViewHost* render_view_host) {
|
||||
|
||||
void WebContents::PrimaryMainFrameRenderProcessGone(
|
||||
base::TerminationStatus status) {
|
||||
auto weak_this = GetWeakPtr();
|
||||
Emit("crashed", status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED);
|
||||
|
||||
// User might destroy WebContents in the crashed event.
|
||||
if (!weak_this || !web_contents())
|
||||
return;
|
||||
|
||||
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
gin_helper::Dictionary details = gin_helper::Dictionary::CreateEmpty(isolate);
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
#include "crypto/crypto_buildflags.h"
|
||||
#include "electron/buildflags/buildflags.h"
|
||||
#include "electron/shell/common/api/api.mojom.h"
|
||||
#include "extensions/browser/api/messaging/messaging_api_message_filter.h"
|
||||
#include "extensions/browser/extension_navigation_ui_data.h"
|
||||
#include "mojo/public/cpp/bindings/binder_map.h"
|
||||
#include "net/ssl/ssl_cert_request_info.h"
|
||||
#include "net/ssl/ssl_private_key.h"
|
||||
@@ -114,6 +114,7 @@
|
||||
#include "shell/common/options_switches.h"
|
||||
#include "shell/common/platform_util.h"
|
||||
#include "shell/common/thread_restrictions.h"
|
||||
#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
|
||||
#include "third_party/blink/public/common/loader/url_loader_throttle.h"
|
||||
#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
|
||||
#include "third_party/blink/public/common/tokens/tokens.h"
|
||||
@@ -147,6 +148,7 @@
|
||||
#include "content/public/browser/child_process_security_policy.h"
|
||||
#include "content/public/browser/file_url_loader.h"
|
||||
#include "content/public/browser/web_ui_url_loader_factory.h"
|
||||
#include "extensions/browser/api/messaging/messaging_api_message_filter.h"
|
||||
#include "extensions/browser/api/mime_handler_private/mime_handler_private.h"
|
||||
#include "extensions/browser/api/web_request/web_request_api.h"
|
||||
#include "extensions/browser/browser_context_keyed_api_factory.h"
|
||||
@@ -154,7 +156,6 @@
|
||||
#include "extensions/browser/extension_host.h"
|
||||
#include "extensions/browser/extension_message_filter.h"
|
||||
#include "extensions/browser/extension_navigation_throttle.h"
|
||||
#include "extensions/browser/extension_navigation_ui_data.h"
|
||||
#include "extensions/browser/extension_prefs.h"
|
||||
#include "extensions/browser/extension_protocols.h"
|
||||
#include "extensions/browser/extension_registry.h"
|
||||
@@ -172,7 +173,6 @@
|
||||
#include "shell/browser/extensions/electron_extension_message_filter.h"
|
||||
#include "shell/browser/extensions/electron_extension_system.h"
|
||||
#include "shell/browser/extensions/electron_extension_web_contents_observer.h"
|
||||
#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(ENABLE_PLUGINS)
|
||||
@@ -1220,12 +1220,12 @@ void ElectronBrowserClient::
|
||||
protocol_registry->RegisterURLLoaderFactories(factories,
|
||||
false /* allow_file_access */);
|
||||
|
||||
#if BUILDFLAG(ENABLE_EXTENSIONS)
|
||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
factories->emplace(
|
||||
extensions::kExtensionScheme,
|
||||
extensions::CreateExtensionServiceWorkerScriptURLLoaderFactory(
|
||||
browser_context));
|
||||
#endif // BUILDFLAG(ENABLE_EXTENSIONS)
|
||||
#endif // BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
}
|
||||
|
||||
bool ElectronBrowserClient::ShouldTreatURLSchemeAsFirstPartyWhenTopLevel(
|
||||
@@ -1413,9 +1413,10 @@ void ElectronBrowserClient::OverrideURLLoaderFactoryParams(
|
||||
factory_params->disable_web_security = true;
|
||||
}
|
||||
}
|
||||
|
||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
extensions::URLLoaderFactoryManager::OverrideURLLoaderFactoryParams(
|
||||
browser_context, origin, is_for_isolated_world, factory_params);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ElectronBrowserClient::
|
||||
@@ -1473,7 +1474,7 @@ void ElectronBrowserClient::
|
||||
},
|
||||
&render_frame_host));
|
||||
#endif
|
||||
#if BUILDFLAG(ENABLE_EXTENSIONS)
|
||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
associated_registry.AddInterface<extensions::mojom::LocalFrameHost>(
|
||||
base::BindRepeating(
|
||||
[](content::RenderFrameHost* render_frame_host,
|
||||
|
||||
@@ -79,12 +79,12 @@
|
||||
|
||||
#if BUILDFLAG(IS_LINUX)
|
||||
#include "base/environment.h"
|
||||
#include "chrome/browser/ui/views/dark_mode_manager_linux.h"
|
||||
#include "device/bluetooth/bluetooth_adapter_factory.h"
|
||||
#include "device/bluetooth/dbus/dbus_bluez_manager_wrapper_linux.h"
|
||||
#include "electron/electron_gtk_stubs.h"
|
||||
#include "ui/base/cursor/cursor_factory.h"
|
||||
#include "ui/base/ime/linux/linux_input_method_context_factory.h"
|
||||
#include "ui/gfx/color_utils.h"
|
||||
#include "ui/gtk/gtk_compat.h" // nogncheck
|
||||
#include "ui/gtk/gtk_util.h" // nogncheck
|
||||
#include "ui/linux/linux_ui.h"
|
||||
@@ -169,36 +169,8 @@ std::u16string MediaStringProvider(media::MessageId id) {
|
||||
}
|
||||
}
|
||||
|
||||
#if BUILDFLAG(IS_LINUX)
|
||||
// GTK does not provide a way to check if current theme is dark, so we compare
|
||||
// the text and background luminosity to get a result.
|
||||
// This trick comes from FireFox.
|
||||
void UpdateDarkThemeSetting() {
|
||||
float bg = color_utils::GetRelativeLuminance(gtk::GetBgColor("GtkLabel"));
|
||||
float fg = color_utils::GetRelativeLuminance(gtk::GetFgColor("GtkLabel"));
|
||||
bool is_dark = fg > bg;
|
||||
// Pass it to NativeUi theme, which is used by the nativeTheme module and most
|
||||
// places in Electron.
|
||||
ui::NativeTheme::GetInstanceForNativeUi()->set_use_dark_colors(is_dark);
|
||||
// Pass it to Web Theme, to make "prefers-color-scheme" media query work.
|
||||
ui::NativeTheme::GetInstanceForWeb()->set_use_dark_colors(is_dark);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
#if BUILDFLAG(IS_LINUX)
|
||||
class DarkThemeObserver : public ui::NativeThemeObserver {
|
||||
public:
|
||||
DarkThemeObserver() = default;
|
||||
|
||||
// ui::NativeThemeObserver:
|
||||
void OnNativeThemeUpdated(ui::NativeTheme* observed_theme) override {
|
||||
UpdateDarkThemeSetting();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
// static
|
||||
ElectronBrowserMainParts* ElectronBrowserMainParts::self_ = nullptr;
|
||||
|
||||
@@ -432,17 +404,10 @@ void ElectronBrowserMainParts::ToolkitInitialized() {
|
||||
CHECK(electron::IsElectron_gdk_pixbufInitialized())
|
||||
<< "Failed to initialize libgdk_pixbuf-2.0.so.0";
|
||||
|
||||
// Chromium does not respect GTK dark theme setting, but they may change
|
||||
// in future and this code might be no longer needed. Check the Chromium
|
||||
// issue to keep updated:
|
||||
// https://bugs.chromium.org/p/chromium/issues/detail?id=998903
|
||||
UpdateDarkThemeSetting();
|
||||
// Update the native theme when GTK theme changes. The GetNativeTheme
|
||||
// here returns a NativeThemeGtk, which monitors GTK settings.
|
||||
dark_theme_observer_ = std::make_unique<DarkThemeObserver>();
|
||||
auto* linux_ui_theme = ui::LinuxUiTheme::GetForProfile(nullptr);
|
||||
CHECK(linux_ui_theme);
|
||||
linux_ui_theme->GetNativeTheme()->AddObserver(dark_theme_observer_.get());
|
||||
// source theme changes from system settings, including settings portal:
|
||||
// https://flatpak.github.io/xdg-desktop-portal/#gdbus-org.freedesktop.portal.Settings
|
||||
dark_mode_manager_ = std::make_unique<ui::DarkModeManagerLinux>();
|
||||
|
||||
ui::LinuxUi::SetInstance(linux_ui);
|
||||
|
||||
// Cursor theme changes are tracked by LinuxUI (via a CursorThemeManager
|
||||
|
||||
@@ -43,7 +43,8 @@ class Environment;
|
||||
|
||||
namespace ui {
|
||||
class LinuxUiGetter;
|
||||
}
|
||||
class DarkModeManagerLinux;
|
||||
} // namespace ui
|
||||
|
||||
namespace electron {
|
||||
|
||||
@@ -65,10 +66,6 @@ class ViewsDelegate;
|
||||
class ViewsDelegateMac;
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(IS_LINUX)
|
||||
class DarkThemeObserver;
|
||||
#endif
|
||||
|
||||
class ElectronBrowserMainParts : public content::BrowserMainParts {
|
||||
public:
|
||||
ElectronBrowserMainParts();
|
||||
@@ -145,9 +142,7 @@ class ElectronBrowserMainParts : public content::BrowserMainParts {
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(IS_LINUX)
|
||||
// Used to notify the native theme of changes to dark mode.
|
||||
std::unique_ptr<DarkThemeObserver> dark_theme_observer_;
|
||||
|
||||
std::unique_ptr<ui::DarkModeManagerLinux> dark_mode_manager_;
|
||||
std::unique_ptr<ui::LinuxUiGetter> linux_ui_getter_;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -13,15 +13,15 @@
|
||||
#include "chrome/grit/generated_resources.h"
|
||||
#include "components/strings/grit/components_strings.h"
|
||||
#include "components/zoom/page_zoom_constants.h"
|
||||
#include "pdf/buildflags.h"
|
||||
#include "electron/buildflags/buildflags.h"
|
||||
#include "printing/buildflags/buildflags.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
#include "ui/base/webui/web_ui_util.h"
|
||||
|
||||
#if BUILDFLAG(ENABLE_PDF)
|
||||
#if BUILDFLAG(ENABLE_PDF_VIEWER)
|
||||
#include "chrome/browser/pdf/pdf_extension_util.h"
|
||||
#include "pdf/pdf_features.h"
|
||||
#endif // BUILDFLAG(ENABLE_PDF)
|
||||
#endif // BUILDFLAG(ENABLE_PDF_VIEWER)
|
||||
|
||||
// To add a new component to this API, simply:
|
||||
// 1. Add your component to the Component enum in
|
||||
@@ -48,7 +48,7 @@ ExtensionFunction::ResponseAction ResourcesPrivateGetStringsFunction::Run() {
|
||||
|
||||
switch (component) {
|
||||
case api::resources_private::COMPONENT_PDF:
|
||||
#if BUILDFLAG(ENABLE_PDF)
|
||||
#if BUILDFLAG(ENABLE_PDF_VIEWER)
|
||||
pdf_extension_util::AddStrings(
|
||||
pdf_extension_util::PdfViewerContext::kPdfViewer, &dict);
|
||||
pdf_extension_util::AddAdditionalData(true, false, &dict);
|
||||
|
||||
@@ -7,20 +7,27 @@
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "base/command_line.h"
|
||||
#include "base/strings/pattern.h"
|
||||
#include "base/types/expected_macros.h"
|
||||
#include "chrome/common/url_constants.h"
|
||||
#include "components/url_formatter/url_fixer.h"
|
||||
#include "content/public/browser/navigation_entry.h"
|
||||
#include "extensions/browser/extension_api_frame_id_map.h"
|
||||
#include "extensions/browser/extension_prefs.h"
|
||||
#include "extensions/common/error_utils.h"
|
||||
#include "extensions/common/extension_features.h"
|
||||
#include "extensions/common/feature_switch.h"
|
||||
#include "extensions/common/manifest_constants.h"
|
||||
#include "extensions/common/mojom/host_id.mojom.h"
|
||||
#include "extensions/common/permissions/permissions_data.h"
|
||||
#include "extensions/common/switches.h"
|
||||
#include "shell/browser/api/electron_api_web_contents.h"
|
||||
#include "shell/browser/native_window.h"
|
||||
#include "shell/browser/web_contents_zoom_controller.h"
|
||||
#include "shell/browser/window_list.h"
|
||||
#include "shell/common/extensions/api/tabs.h"
|
||||
#include "third_party/blink/public/common/chrome_debug_urls.h"
|
||||
#include "third_party/blink/public/common/page/page_zoom.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
@@ -468,17 +475,25 @@ bool IsKillURL(const GURL& url) {
|
||||
DCHECK(url.IsAboutBlank() || url.IsAboutSrcdoc());
|
||||
#endif
|
||||
|
||||
static const char* const kill_hosts[] = {
|
||||
chrome::kChromeUICrashHost, chrome::kChromeUIDelayedHangUIHost,
|
||||
chrome::kChromeUIHangUIHost, chrome::kChromeUIKillHost,
|
||||
// Disallow common renderer debug URLs.
|
||||
// Note: this would also disallow JavaScript URLs, but we already explicitly
|
||||
// check for those before calling into here from PrepareURLForNavigation.
|
||||
if (blink::IsRendererDebugURL(url)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!url.SchemeIs(content::kChromeUIScheme)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Also disallow a few more hosts which are not covered by the check above.
|
||||
static const char* const kKillHosts[] = {
|
||||
chrome::kChromeUIDelayedHangUIHost, chrome::kChromeUIHangUIHost,
|
||||
chrome::kChromeUIQuitHost, chrome::kChromeUIRestartHost,
|
||||
content::kChromeUIBrowserCrashHost, content::kChromeUIMemoryExhaustHost,
|
||||
};
|
||||
|
||||
if (!url.SchemeIs(content::kChromeUIScheme))
|
||||
return false;
|
||||
|
||||
return base::Contains(kill_hosts, url.host_piece());
|
||||
return base::Contains(kKillHosts, url.host_piece());
|
||||
}
|
||||
|
||||
GURL ResolvePossiblyRelativeURL(const std::string& url_string,
|
||||
@@ -489,10 +504,18 @@ GURL ResolvePossiblyRelativeURL(const std::string& url_string,
|
||||
|
||||
return url;
|
||||
}
|
||||
bool PrepareURLForNavigation(const std::string& url_string,
|
||||
const Extension* extension,
|
||||
GURL* return_url,
|
||||
std::string* error) {
|
||||
|
||||
bool AllowFileAccess(const ExtensionId& extension_id,
|
||||
content::BrowserContext* context) {
|
||||
return base::CommandLine::ForCurrentProcess()->HasSwitch(
|
||||
switches::kDisableExtensionsFileAccessCheck) ||
|
||||
ExtensionPrefs::Get(context)->AllowFileAccess(extension_id);
|
||||
}
|
||||
|
||||
base::expected<GURL, std::string> PrepareURLForNavigation(
|
||||
const std::string& url_string,
|
||||
const Extension* extension,
|
||||
content::BrowserContext* browser_context) {
|
||||
GURL url = ResolvePossiblyRelativeURL(url_string, extension);
|
||||
|
||||
// Ideally, the URL would only be "fixed" for user input (e.g. for URLs
|
||||
@@ -504,34 +527,62 @@ bool PrepareURLForNavigation(const std::string& url_string,
|
||||
// Reject invalid URLs.
|
||||
if (!url.is_valid()) {
|
||||
const char kInvalidUrlError[] = "Invalid url: \"*\".";
|
||||
*error = ErrorUtils::FormatErrorMessage(kInvalidUrlError, url_string);
|
||||
return false;
|
||||
return base::unexpected(
|
||||
ErrorUtils::FormatErrorMessage(kInvalidUrlError, url_string));
|
||||
}
|
||||
|
||||
// Don't let the extension use JavaScript URLs in API triggered navigations.
|
||||
if (url.SchemeIs(url::kJavaScriptScheme)) {
|
||||
const char kJavaScriptUrlsNotAllowedInExtensionNavigations[] =
|
||||
"JavaScript URLs are not allowed in API based extension navigations. "
|
||||
"Use "
|
||||
"chrome.scripting.executeScript instead.";
|
||||
return base::unexpected(kJavaScriptUrlsNotAllowedInExtensionNavigations);
|
||||
}
|
||||
|
||||
// Don't let the extension crash the browser or renderers.
|
||||
if (IsKillURL(url)) {
|
||||
const char kNoCrashBrowserError[] =
|
||||
"I'm sorry. I'm afraid I can't do that.";
|
||||
*error = kNoCrashBrowserError;
|
||||
return false;
|
||||
return base::unexpected(kNoCrashBrowserError);
|
||||
}
|
||||
|
||||
// Don't let the extension navigate directly to devtools scheme pages, unless
|
||||
// they have applicable permissions.
|
||||
if (url.SchemeIs(content::kChromeDevToolsScheme) &&
|
||||
!(extension->permissions_data()->HasAPIPermission(
|
||||
extensions::mojom::APIPermissionID::kDevtools) ||
|
||||
extension->permissions_data()->HasAPIPermission(
|
||||
extensions::mojom::APIPermissionID::kDebugger))) {
|
||||
const char kCannotNavigateToDevtools[] =
|
||||
"Cannot navigate to a devtools:// page without either the devtools or "
|
||||
"debugger permission.";
|
||||
*error = kCannotNavigateToDevtools;
|
||||
return false;
|
||||
if (url.SchemeIs(content::kChromeDevToolsScheme)) {
|
||||
bool has_permission =
|
||||
extension && (extension->permissions_data()->HasAPIPermission(
|
||||
mojom::APIPermissionID::kDevtools) ||
|
||||
extension->permissions_data()->HasAPIPermission(
|
||||
mojom::APIPermissionID::kDebugger));
|
||||
if (!has_permission) {
|
||||
const char kCannotNavigateToDevtools[] =
|
||||
"Cannot navigate to a devtools:// page without either the devtools "
|
||||
"or "
|
||||
"debugger permission.";
|
||||
return base::unexpected(kCannotNavigateToDevtools);
|
||||
}
|
||||
}
|
||||
|
||||
return_url->Swap(&url);
|
||||
return true;
|
||||
// Don't let the extension navigate directly to chrome-untrusted scheme pages.
|
||||
if (url.SchemeIs(content::kChromeUIUntrustedScheme)) {
|
||||
const char kCannotNavigateToChromeUntrusted[] =
|
||||
"Cannot navigate to a chrome-untrusted:// page.";
|
||||
return base::unexpected(kCannotNavigateToChromeUntrusted);
|
||||
}
|
||||
|
||||
// Don't let the extension navigate directly to file scheme pages, unless
|
||||
// they have file access.
|
||||
if (url.SchemeIsFile() &&
|
||||
!AllowFileAccess(extension->id(), browser_context) &&
|
||||
base::FeatureList::IsEnabled(
|
||||
extensions_features::kRestrictFileURLNavigation)) {
|
||||
const char kFileUrlsNotAllowedInExtensionNavigations[] =
|
||||
"Cannot navigate to a file URL without local file access.";
|
||||
return base::unexpected(kFileUrlsNotAllowedInExtensionNavigations);
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
TabsUpdateFunction::TabsUpdateFunction() : web_contents_(nullptr) {}
|
||||
@@ -566,22 +617,14 @@ ExtensionFunction::ResponseAction TabsUpdateFunction::Run() {
|
||||
bool TabsUpdateFunction::UpdateURL(const std::string& url_string,
|
||||
int tab_id,
|
||||
std::string* error) {
|
||||
GURL url;
|
||||
if (!PrepareURLForNavigation(url_string, extension(), &url, error)) {
|
||||
auto url =
|
||||
PrepareURLForNavigation(url_string, extension(), browser_context());
|
||||
if (!url.has_value()) {
|
||||
*error = std::move(url.error());
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool is_javascript_scheme = url.SchemeIs(url::kJavaScriptScheme);
|
||||
// JavaScript URLs are forbidden in chrome.tabs.update().
|
||||
if (is_javascript_scheme) {
|
||||
const char kJavaScriptUrlsNotAllowedInTabsUpdate[] =
|
||||
"JavaScript URLs are not allowed in chrome.tabs.update. Use "
|
||||
"chrome.tabs.executeScript instead.";
|
||||
*error = kJavaScriptUrlsNotAllowedInTabsUpdate;
|
||||
return false;
|
||||
}
|
||||
|
||||
content::NavigationController::LoadURLParams load_params(url);
|
||||
content::NavigationController::LoadURLParams load_params(*url);
|
||||
|
||||
// Treat extension-initiated navigations as renderer-initiated so that the URL
|
||||
// does not show in the omnibox until it commits. This avoids URL spoofs
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "base/containers/contains.h"
|
||||
#include "chrome/common/chrome_features.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
#include "electron/buildflags/buildflags.h"
|
||||
#include "services/device/public/cpp/hid/hid_switches.h"
|
||||
#include "shell/browser/electron_permission_manager.h"
|
||||
#include "shell/browser/hid/hid_chooser_context.h"
|
||||
@@ -19,9 +20,9 @@
|
||||
#include "shell/browser/web_contents_permission_helper.h"
|
||||
#include "third_party/blink/public/common/permissions/permission_utils.h"
|
||||
|
||||
#if BUILDFLAG(ENABLE_EXTENSIONS)
|
||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
#include "extensions/common/constants.h"
|
||||
#endif // BUILDFLAG(ENABLE_EXTENSIONS)
|
||||
#endif // BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -128,14 +129,14 @@ bool ElectronHidDelegate::IsFidoAllowedForOrigin(
|
||||
|
||||
bool ElectronHidDelegate::IsServiceWorkerAllowedForOrigin(
|
||||
const url::Origin& origin) {
|
||||
#if BUILDFLAG(ENABLE_EXTENSIONS)
|
||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
// WebHID is only available on extension service workers with feature flag
|
||||
// enabled for now.
|
||||
if (base::FeatureList::IsEnabled(
|
||||
features::kEnableWebHidOnExtensionServiceWorker) &&
|
||||
origin.scheme() == extensions::kExtensionScheme)
|
||||
return true;
|
||||
#endif // BUILDFLAG(ENABLE_EXTENSIONS)
|
||||
#endif // BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
@@ -98,6 +99,11 @@ NativeWindow::NativeWindow(const gin_helper::Dictionary& options,
|
||||
options.Get(options::kTransparent, &transparent_);
|
||||
options.Get(options::kEnableLargerThanScreen, &enable_larger_than_screen_);
|
||||
options.Get(options::kTitleBarStyle, &title_bar_style_);
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
options.Get(options::kBackgroundMaterial, &background_material_);
|
||||
#elif BUILDFLAG(IS_MAC)
|
||||
options.Get(options::kVibrancyType, &vibrancy_);
|
||||
#endif
|
||||
|
||||
v8::Local<v8::Value> titlebar_overlay;
|
||||
if (options.Get(options::ktitleBarOverlay, &titlebar_overlay)) {
|
||||
@@ -259,13 +265,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);
|
||||
@@ -349,10 +357,14 @@ void NativeWindow::SetContentSizeConstraints(
|
||||
size_constraints_.reset();
|
||||
}
|
||||
|
||||
// Windows/Linux:
|
||||
// The return value of GetContentSizeConstraints will be passed to Chromium
|
||||
// to set min/max sizes of window. Note that we are returning content size
|
||||
// instead of window size because that is what Chromium expects, see the
|
||||
// comment of |WidgetSizeIsClientSize| in Chromium's codebase to learn more.
|
||||
//
|
||||
// macOS:
|
||||
// The min/max sizes are set directly by calling NSWindow's methods.
|
||||
extensions::SizeConstraints NativeWindow::GetContentSizeConstraints() const {
|
||||
if (content_size_constraints_)
|
||||
return *content_size_constraints_;
|
||||
@@ -472,9 +484,17 @@ bool NativeWindow::AddTabbedWindow(NativeWindow* window) {
|
||||
return true; // for non-Mac platforms
|
||||
}
|
||||
|
||||
void NativeWindow::SetVibrancy(const std::string& type) {}
|
||||
absl::optional<std::string> NativeWindow::GetTabbingIdentifier() const {
|
||||
return ""; // for non-Mac platforms
|
||||
}
|
||||
|
||||
void NativeWindow::SetBackgroundMaterial(const std::string& type) {}
|
||||
void NativeWindow::SetVibrancy(const std::string& type) {
|
||||
vibrancy_ = type;
|
||||
}
|
||||
|
||||
void NativeWindow::SetBackgroundMaterial(const std::string& type) {
|
||||
background_material_ = type;
|
||||
}
|
||||
|
||||
void NativeWindow::SetTouchBar(
|
||||
std::vector<gin_helper::PersistentDictionary> items) {}
|
||||
@@ -798,6 +818,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
|
||||
@@ -251,6 +255,7 @@ class NativeWindow : public base::SupportsUserData,
|
||||
virtual void MoveTabToNewWindow();
|
||||
virtual void ToggleTabBar();
|
||||
virtual bool AddTabbedWindow(NativeWindow* window);
|
||||
virtual absl::optional<std::string> GetTabbingIdentifier() const;
|
||||
|
||||
// Toggle the menu bar.
|
||||
virtual void SetAutoHideMenuBar(bool auto_hide);
|
||||
@@ -395,6 +400,8 @@ class NativeWindow : public base::SupportsUserData,
|
||||
void AddDraggableRegionProvider(DraggableRegionProvider* provider);
|
||||
void RemoveDraggableRegionProvider(DraggableRegionProvider* provider);
|
||||
|
||||
bool IsTranslucent() const;
|
||||
|
||||
protected:
|
||||
friend class api::BrowserView;
|
||||
|
||||
@@ -492,6 +499,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};
|
||||
|
||||
@@ -58,6 +58,8 @@ class NativeWindowMac : public NativeWindow,
|
||||
gfx::Rect GetBounds() override;
|
||||
bool IsNormal() override;
|
||||
gfx::Rect GetNormalBounds() override;
|
||||
void SetSizeConstraints(
|
||||
const extensions::SizeConstraints& window_constraints) override;
|
||||
void SetContentSizeConstraints(
|
||||
const extensions::SizeConstraints& size_constraints) override;
|
||||
void SetResizable(bool resizable) override;
|
||||
@@ -143,6 +145,7 @@ class NativeWindowMac : public NativeWindow,
|
||||
void MoveTabToNewWindow() override;
|
||||
void ToggleTabBar() override;
|
||||
bool AddTabbedWindow(NativeWindow* window) override;
|
||||
absl::optional<std::string> GetTabbingIdentifier() const override;
|
||||
void SetAspectRatio(double aspect_ratio,
|
||||
const gfx::Size& extra_size) override;
|
||||
void PreviewFile(const std::string& path,
|
||||
@@ -186,6 +189,9 @@ class NativeWindowMac : public NativeWindow,
|
||||
has_deferred_window_close_ = defer_close;
|
||||
}
|
||||
|
||||
void set_wants_to_be_visible(bool visible) { wants_to_be_visible_ = visible; }
|
||||
bool wants_to_be_visible() const { return wants_to_be_visible_; }
|
||||
|
||||
enum class VisualEffectState {
|
||||
kFollowWindow,
|
||||
kActive,
|
||||
@@ -252,6 +258,10 @@ class NativeWindowMac : public NativeWindow,
|
||||
// transition is complete.
|
||||
bool has_deferred_window_close_ = false;
|
||||
|
||||
// If true, the window is either visible, or wants to be visible but is
|
||||
// currently hidden due to having a hidden parent.
|
||||
bool wants_to_be_visible_ = false;
|
||||
|
||||
NSInteger attention_request_id_ = 0; // identifier from requestUserAttention
|
||||
|
||||
// The presentation options before entering kiosk mode.
|
||||
|
||||
@@ -496,6 +496,8 @@ void NativeWindowMac::Show() {
|
||||
return;
|
||||
}
|
||||
|
||||
set_wants_to_be_visible(true);
|
||||
|
||||
// Reattach the window to the parent to actually show it.
|
||||
if (parent())
|
||||
InternalSetParentWindow(parent(), true);
|
||||
@@ -528,6 +530,10 @@ void NativeWindowMac::Hide() {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the window wants to be visible and has a parent, then the parent may
|
||||
// order it back in (in the period between orderOut: and close).
|
||||
set_wants_to_be_visible(false);
|
||||
|
||||
DetachChildren();
|
||||
|
||||
// Detach the window from the parent before.
|
||||
@@ -663,6 +669,9 @@ void NativeWindowMac::RemoveChildFromParentWindow() {
|
||||
|
||||
void NativeWindowMac::AttachChildren() {
|
||||
for (auto* child : child_windows_) {
|
||||
if (!static_cast<NativeWindowMac*>(child)->wants_to_be_visible())
|
||||
continue;
|
||||
|
||||
auto* child_nswindow = child->GetNativeWindow().GetNativeNSWindow();
|
||||
if ([child_nswindow parentWindow] == window_)
|
||||
continue;
|
||||
@@ -676,8 +685,6 @@ void NativeWindowMac::AttachChildren() {
|
||||
}
|
||||
|
||||
void NativeWindowMac::DetachChildren() {
|
||||
DCHECK(child_windows_.size() == [[window_ childWindows] count]);
|
||||
|
||||
// Hide all children before hiding/minimizing the window.
|
||||
// NativeWidgetNSWindowBridge::NotifyVisibilityChangeDown()
|
||||
// will DCHECK otherwise.
|
||||
@@ -774,6 +781,16 @@ gfx::Rect NativeWindowMac::GetNormalBounds() {
|
||||
// return widget()->GetRestoredBounds();
|
||||
}
|
||||
|
||||
void NativeWindowMac::SetSizeConstraints(
|
||||
const extensions::SizeConstraints& window_constraints) {
|
||||
// Apply the size constraints to NSWindow.
|
||||
if (window_constraints.HasMinimumSize())
|
||||
[window_ setMinSize:window_constraints.GetMinimumSize().ToCGSize()];
|
||||
if (window_constraints.HasMaximumSize())
|
||||
[window_ setMaxSize:window_constraints.GetMaximumSize().ToCGSize()];
|
||||
NativeWindow::SetSizeConstraints(window_constraints);
|
||||
}
|
||||
|
||||
void NativeWindowMac::SetContentSizeConstraints(
|
||||
const extensions::SizeConstraints& size_constraints) {
|
||||
auto convertSize = [this](const gfx::Size& size) {
|
||||
@@ -788,6 +805,7 @@ void NativeWindowMac::SetContentSizeConstraints(
|
||||
}
|
||||
};
|
||||
|
||||
// Apply the size constraints to NSWindow.
|
||||
NSView* content = [window_ contentView];
|
||||
if (size_constraints.HasMinimumSize()) {
|
||||
NSSize min_size = convertSize(size_constraints.GetMinimumSize());
|
||||
@@ -1422,11 +1440,21 @@ void NativeWindowMac::UpdateVibrancyRadii(bool fullscreen) {
|
||||
|
||||
if (vibrantView != nil && !vibrancy_type_.empty()) {
|
||||
const bool no_rounded_corner = !HasStyleMask(NSWindowStyleMaskTitled);
|
||||
if (!has_frame() && !is_modal() && !no_rounded_corner) {
|
||||
const int macos_version = base::mac::MacOSMajorVersion();
|
||||
|
||||
// Modal window corners are rounded on macOS >= 11 or higher if the user
|
||||
// hasn't passed noRoundedCorners.
|
||||
bool should_round_modal =
|
||||
!no_rounded_corner && (macos_version >= 11 ? true : !is_modal());
|
||||
// Nonmodal window corners are rounded if they're frameless and the user
|
||||
// hasn't passed noRoundedCorners.
|
||||
bool should_round_nonmodal = !no_rounded_corner && !has_frame();
|
||||
|
||||
if (should_round_nonmodal || should_round_modal) {
|
||||
CGFloat radius;
|
||||
if (fullscreen) {
|
||||
radius = 0.0f;
|
||||
} else if (@available(macOS 11.0, *)) {
|
||||
} else if (macos_version >= 11) {
|
||||
radius = 9.0f;
|
||||
} else {
|
||||
// Smaller corner radius on versions prior to Big Sur.
|
||||
@@ -1460,6 +1488,8 @@ void NativeWindowMac::UpdateWindowOriginalFrame() {
|
||||
}
|
||||
|
||||
void NativeWindowMac::SetVibrancy(const std::string& type) {
|
||||
NativeWindow::SetVibrancy(type);
|
||||
|
||||
NSVisualEffectView* vibrantView = [window_ vibrantView];
|
||||
|
||||
if (type.empty()) {
|
||||
@@ -1633,6 +1663,13 @@ bool NativeWindowMac::AddTabbedWindow(NativeWindow* window) {
|
||||
return true;
|
||||
}
|
||||
|
||||
absl::optional<std::string> NativeWindowMac::GetTabbingIdentifier() const {
|
||||
if ([window_ tabbingMode] == NSWindowTabbingModeDisallowed)
|
||||
return absl::nullopt;
|
||||
|
||||
return base::SysNSStringToUTF8([window_ tabbingIdentifier]);
|
||||
}
|
||||
|
||||
void NativeWindowMac::SetAspectRatio(double aspect_ratio,
|
||||
const gfx::Size& extra_size) {
|
||||
NativeWindow::SetAspectRatio(aspect_ratio, extra_size);
|
||||
|
||||
@@ -280,12 +280,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;
|
||||
@@ -1453,6 +1453,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)
|
||||
@@ -1464,6 +1466,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
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <wrl/client.h>
|
||||
|
||||
#include "base/win/atl.h" // Must be before UIAutomationCore.h
|
||||
#include "base/win/scoped_handle.h"
|
||||
#include "content/public/browser/browser_accessibility_state.h"
|
||||
#include "shell/browser/browser.h"
|
||||
#include "shell/browser/native_window_views.h"
|
||||
@@ -165,10 +166,41 @@ gfx::ResizeEdge GetWindowResizeEdge(WPARAM param) {
|
||||
}
|
||||
}
|
||||
|
||||
bool IsMutexPresent(const wchar_t* name) {
|
||||
base::win::ScopedHandle mutex_holder(::CreateMutex(nullptr, false, name));
|
||||
return ::GetLastError() == ERROR_ALREADY_EXISTS;
|
||||
}
|
||||
|
||||
bool IsLibraryLoaded(const wchar_t* name) {
|
||||
HMODULE hmodule = nullptr;
|
||||
::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, name,
|
||||
&hmodule);
|
||||
return hmodule != nullptr;
|
||||
}
|
||||
|
||||
// The official way to get screen reader status is to call:
|
||||
// SystemParametersInfo(SPI_GETSCREENREADER) && UiaClientsAreListening()
|
||||
// However it has false positives (for example when user is using touch screens)
|
||||
// and will cause performance issues in some apps.
|
||||
bool IsScreenReaderActive() {
|
||||
UINT screenReader = 0;
|
||||
SystemParametersInfo(SPI_GETSCREENREADER, 0, &screenReader, 0);
|
||||
return screenReader && UiaClientsAreListening();
|
||||
if (IsMutexPresent(L"NarratorRunning"))
|
||||
return true;
|
||||
|
||||
static const wchar_t* names[] = {// NVDA
|
||||
L"nvdaHelperRemote.dll",
|
||||
// JAWS
|
||||
L"jhook.dll",
|
||||
// Window-Eyes
|
||||
L"gwhk64.dll", L"gwmhook.dll",
|
||||
// ZoomText
|
||||
L"AiSquared.Infuser.HookLib.dll"};
|
||||
|
||||
for (auto* name : names) {
|
||||
if (IsLibraryLoaded(name))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
#include "base/containers/contains.h"
|
||||
#include "base/values.h"
|
||||
#include "content/public/common/webplugininfo.h"
|
||||
#include "extensions/buildflags/buildflags.h"
|
||||
#include "electron/buildflags/buildflags.h"
|
||||
#include "url/gurl.h"
|
||||
#include "url/origin.h"
|
||||
|
||||
#if BUILDFLAG(ENABLE_EXTENSIONS)
|
||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
#include "extensions/browser/extension_registry.h"
|
||||
#include "extensions/browser/extension_util.h"
|
||||
#include "extensions/common/constants.h"
|
||||
@@ -36,7 +36,7 @@ base::flat_map<std::string, std::string>
|
||||
PluginUtils::GetMimeTypeToExtensionIdMap(
|
||||
content::BrowserContext* browser_context) {
|
||||
base::flat_map<std::string, std::string> mime_type_to_extension_id_map;
|
||||
#if BUILDFLAG(ENABLE_EXTENSIONS)
|
||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
std::vector<std::string> allowed_extension_ids =
|
||||
MimeTypesHandler::GetMIMETypeAllowlist();
|
||||
// Go through the white-listed extensions and try to use them to intercept
|
||||
|
||||
@@ -262,6 +262,7 @@ using FullScreenTransitionState =
|
||||
[super windowDidMiniaturize:notification];
|
||||
is_minimized_ = true;
|
||||
|
||||
shell_->set_wants_to_be_visible(false);
|
||||
shell_->NotifyWindowMinimize();
|
||||
}
|
||||
|
||||
@@ -269,6 +270,7 @@ using FullScreenTransitionState =
|
||||
[super windowDidDeminiaturize:notification];
|
||||
is_minimized_ = false;
|
||||
|
||||
shell_->set_wants_to_be_visible(true);
|
||||
shell_->AttachChildren();
|
||||
shell_->SetWindowLevel(level_);
|
||||
shell_->NotifyWindowRestore();
|
||||
|
||||
@@ -142,8 +142,11 @@ void InspectableWebContentsViewViews::CloseDevTools() {
|
||||
|
||||
devtools_visible_ = false;
|
||||
if (devtools_window_) {
|
||||
inspectable_web_contents()->SaveDevToolsBounds(
|
||||
devtools_window_->GetWindowBoundsInScreen());
|
||||
auto save_bounds = devtools_window_->IsMinimized()
|
||||
? devtools_window_->GetRestoredBounds()
|
||||
: devtools_window_->GetWindowBoundsInScreen();
|
||||
inspectable_web_contents()->SaveDevToolsBounds(save_bounds);
|
||||
|
||||
devtools_window_.reset();
|
||||
devtools_window_web_view_ = nullptr;
|
||||
devtools_window_delegate_ = nullptr;
|
||||
@@ -216,6 +219,8 @@ const std::u16string InspectableWebContentsViewViews::GetTitle() {
|
||||
void InspectableWebContentsViewViews::Layout() {
|
||||
if (!devtools_web_view_->GetVisible()) {
|
||||
contents_web_view_->SetBoundsRect(GetContentsBounds());
|
||||
// Propagate layout call to all children, for example browser views.
|
||||
View::Layout();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -233,6 +238,9 @@ void InspectableWebContentsViewViews::Layout() {
|
||||
devtools_web_view_->SetBoundsRect(new_devtools_bounds);
|
||||
contents_web_view_->SetBoundsRect(new_contents_bounds);
|
||||
|
||||
// Propagate layout call to all children, for example browser views.
|
||||
View::Layout();
|
||||
|
||||
if (GetDelegate())
|
||||
GetDelegate()->DevToolsResized();
|
||||
}
|
||||
|
||||
@@ -133,4 +133,14 @@ void ElectronDesktopWindowTreeHostWin::OnNativeThemeUpdated(
|
||||
}
|
||||
}
|
||||
|
||||
bool ElectronDesktopWindowTreeHostWin::ShouldWindowContentsBeTransparent()
|
||||
const {
|
||||
// Window should be marked as opaque if no transparency setting has been set,
|
||||
// otherwise videos rendered in the window will trigger a DirectComposition
|
||||
// redraw for every frame.
|
||||
// https://github.com/electron/electron/pull/39895
|
||||
return native_window_view_->GetOpacity() < 1.0 ||
|
||||
native_window_view_->transparent();
|
||||
}
|
||||
|
||||
} // namespace electron
|
||||
|
||||
@@ -40,6 +40,7 @@ class ElectronDesktopWindowTreeHostWin : public views::DesktopWindowTreeHostWin,
|
||||
|
||||
// ui::NativeThemeObserver:
|
||||
void OnNativeThemeUpdated(ui::NativeTheme* observed_theme) override;
|
||||
bool ShouldWindowContentsBeTransparent() const override;
|
||||
|
||||
private:
|
||||
raw_ptr<NativeWindowViews> native_window_view_; // weak ref
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include "base/scoped_observation.h"
|
||||
#include "content/public/browser/render_frame_host.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
#include "extensions/buildflags/buildflags.h"
|
||||
#include "electron/buildflags/buildflags.h"
|
||||
#include "services/device/public/mojom/usb_enumeration_options.mojom.h"
|
||||
#include "shell/browser/electron_permission_manager.h"
|
||||
#include "shell/browser/usb/usb_chooser_context.h"
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "shell/browser/usb/usb_chooser_controller.h"
|
||||
#include "shell/browser/web_contents_permission_helper.h"
|
||||
|
||||
#if BUILDFLAG(ENABLE_EXTENSIONS)
|
||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
#include "base/containers/fixed_flat_set.h"
|
||||
#include "chrome/common/chrome_features.h"
|
||||
#include "extensions/browser/extension_registry.h"
|
||||
@@ -41,7 +41,7 @@ electron::UsbChooserContext* GetChooserContext(
|
||||
browser_context);
|
||||
}
|
||||
|
||||
#if BUILDFLAG(ENABLE_EXTENSIONS)
|
||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
// These extensions can claim the smart card USB class and automatically gain
|
||||
// permissions for devices that have an interface with this class.
|
||||
constexpr auto kSmartCardPrivilegedExtensionIds =
|
||||
@@ -65,12 +65,12 @@ bool DeviceHasInterfaceWithClass(
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif // BUILDFLAG(ENABLE_EXTENSIONS)
|
||||
#endif // BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
|
||||
bool IsDevicePermissionAutoGranted(
|
||||
const url::Origin& origin,
|
||||
const device::mojom::UsbDeviceInfo& device_info) {
|
||||
#if BUILDFLAG(ENABLE_EXTENSIONS)
|
||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
// Note: The `DeviceHasInterfaceWithClass()` call is made after checking the
|
||||
// origin, since that method call is expensive.
|
||||
if (origin.scheme() == extensions::kExtensionScheme &&
|
||||
@@ -79,7 +79,7 @@ bool IsDevicePermissionAutoGranted(
|
||||
device::mojom::kUsbSmartCardClass)) {
|
||||
return true;
|
||||
}
|
||||
#endif // BUILDFLAG(ENABLE_EXTENSIONS)
|
||||
#endif // BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -251,14 +251,14 @@ ElectronUsbDelegate::GetContextObserver(
|
||||
|
||||
bool ElectronUsbDelegate::IsServiceWorkerAllowedForOrigin(
|
||||
const url::Origin& origin) {
|
||||
#if BUILDFLAG(ENABLE_EXTENSIONS)
|
||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
// WebUSB is only available on extension service workers for now.
|
||||
if (base::FeatureList::IsEnabled(
|
||||
features::kEnableWebUsbOnExtensionServiceWorker) &&
|
||||
origin.scheme() == extensions::kExtensionScheme) {
|
||||
return true;
|
||||
}
|
||||
#endif // BUILDFLAG(ENABLE_EXTENSIONS)
|
||||
#endif // BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -289,7 +289,7 @@ void ElectronUsbDelegate::DeleteControllerForFrame(
|
||||
|
||||
bool ElectronUsbDelegate::PageMayUseUsb(content::Page& page) {
|
||||
content::RenderFrameHost& main_rfh = page.GetMainDocument();
|
||||
#if BUILDFLAG(ENABLE_EXTENSIONS)
|
||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
// WebViewGuests have no mechanism to show permission prompts and their
|
||||
// embedder can't grant USB access through its permissionrequest API. Also
|
||||
// since webviews use a separate StoragePartition, they must not gain access
|
||||
@@ -297,7 +297,7 @@ bool ElectronUsbDelegate::PageMayUseUsb(content::Page& page) {
|
||||
if (extensions::WebViewGuest::FromRenderFrameHost(&main_rfh)) {
|
||||
return false;
|
||||
}
|
||||
#endif // BUILDFLAG(ENABLE_EXTENSIONS)
|
||||
#endif // BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
|
||||
// USB permissions are scoped to a BrowserContext instead of a
|
||||
// StoragePartition, so we need to be careful about usage across
|
||||
|
||||
@@ -121,9 +121,7 @@ class Archive : public node::ObjectWrap {
|
||||
gin_helper::Dictionary dict(isolate, v8::Object::New(isolate));
|
||||
dict.Set("size", stats.size);
|
||||
dict.Set("offset", stats.offset);
|
||||
dict.Set("isFile", stats.is_file);
|
||||
dict.Set("isDirectory", stats.is_directory);
|
||||
dict.Set("isLink", stats.is_link);
|
||||
dict.Set("type", static_cast<int>(stats.type));
|
||||
args.GetReturnValue().Set(dict.GetHandle());
|
||||
}
|
||||
|
||||
|
||||
@@ -311,14 +311,12 @@ bool Archive::Stat(const base::FilePath& path, Stats* stats) const {
|
||||
return false;
|
||||
|
||||
if (node->Find("link")) {
|
||||
stats->is_file = false;
|
||||
stats->is_link = true;
|
||||
stats->type = FileType::kLink;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (node->Find("files")) {
|
||||
stats->is_file = false;
|
||||
stats->is_directory = true;
|
||||
stats->type = FileType::kDirectory;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <uv.h>
|
||||
|
||||
#include "base/files/file.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/synchronization/lock.h"
|
||||
@@ -49,11 +51,14 @@ class Archive {
|
||||
absl::optional<IntegrityPayload> integrity;
|
||||
};
|
||||
|
||||
enum class FileType {
|
||||
kFile = UV_DIRENT_FILE,
|
||||
kDirectory = UV_DIRENT_DIR,
|
||||
kLink = UV_DIRENT_LINK,
|
||||
};
|
||||
|
||||
struct Stats : public FileInfo {
|
||||
Stats() : is_file(true), is_directory(false), is_link(false) {}
|
||||
bool is_file;
|
||||
bool is_directory;
|
||||
bool is_link;
|
||||
FileType type = FileType::kFile;
|
||||
};
|
||||
|
||||
explicit Archive(const base::FilePath& path);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -21,13 +21,12 @@ class Locker {
|
||||
Locker(const Locker&) = delete;
|
||||
Locker& operator=(const Locker&) = delete;
|
||||
|
||||
// prevent heap allocation
|
||||
void* operator new(size_t size) = delete;
|
||||
void operator delete(void*, size_t) = 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;
|
||||
const std::unique_ptr<v8::Locker> locker_;
|
||||
};
|
||||
|
||||
} // namespace gin_helper
|
||||
|
||||
@@ -30,7 +30,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 "third_party/blink/renderer/bindings/core/v8/v8_initializer.h" // nogncheck
|
||||
@@ -523,6 +522,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();
|
||||
|
||||
@@ -7,15 +7,15 @@
|
||||
#include <utility>
|
||||
|
||||
#include "content/public/renderer/render_frame.h"
|
||||
#include "extensions/buildflags/buildflags.h"
|
||||
#include "electron/buildflags/buildflags.h"
|
||||
#include "third_party/blink/public/web/web_element.h"
|
||||
#include "third_party/blink/public/web/web_local_frame.h"
|
||||
|
||||
#if BUILDFLAG(ENABLE_EXTENSIONS)
|
||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
#include "chrome/common/pdf_util.h"
|
||||
#include "extensions/common/constants.h"
|
||||
#include "extensions/renderer/guest_view/mime_handler_view/post_message_support.h"
|
||||
#endif // BUILDFLAG(ENABLE_EXTENSIONS)
|
||||
#endif // BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
|
||||
namespace electron {
|
||||
|
||||
@@ -26,14 +26,14 @@ PrintRenderFrameHelperDelegate::~PrintRenderFrameHelperDelegate() = default;
|
||||
// Return the PDF object element if |frame| is the out of process PDF extension.
|
||||
blink::WebElement PrintRenderFrameHelperDelegate::GetPdfElement(
|
||||
blink::WebLocalFrame* frame) {
|
||||
#if BUILDFLAG(ENABLE_EXTENSIONS)
|
||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
if (frame->Parent() &&
|
||||
IsPdfInternalPluginAllowedOrigin(frame->Parent()->GetSecurityOrigin())) {
|
||||
auto plugin_element = frame->GetDocument().QuerySelector("embed");
|
||||
DCHECK(!plugin_element.IsNull());
|
||||
return plugin_element;
|
||||
}
|
||||
#endif // BUILDFLAG(ENABLE_EXTENSIONS)
|
||||
#endif // BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
return blink::WebElement();
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ bool PrintRenderFrameHelperDelegate::IsPrintPreviewEnabled() {
|
||||
|
||||
bool PrintRenderFrameHelperDelegate::OverridePrint(
|
||||
blink::WebLocalFrame* frame) {
|
||||
#if BUILDFLAG(ENABLE_EXTENSIONS)
|
||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
auto* post_message_support =
|
||||
extensions::PostMessageSupport::FromWebLocalFrame(frame);
|
||||
if (post_message_support) {
|
||||
@@ -56,7 +56,7 @@ bool PrintRenderFrameHelperDelegate::OverridePrint(
|
||||
post_message_support->PostMessageFromValue(base::Value(std::move(message)));
|
||||
return true;
|
||||
}
|
||||
#endif // BUILDFLAG(ENABLE_EXTENSIONS)
|
||||
#endif // BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -235,14 +235,6 @@ void RendererClientBase::RenderThreadStarted() {
|
||||
extensions::ExtensionsRendererClient::Set(extensions_renderer_client_.get());
|
||||
|
||||
thread->AddObserver(extensions_renderer_client_->GetDispatcher());
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
|
||||
spellcheck_ = std::make_unique<SpellCheck>(this);
|
||||
#endif
|
||||
|
||||
blink::WebCustomElement::AddEmbedderCustomElementName("webview");
|
||||
blink::WebCustomElement::AddEmbedderCustomElementName("browserplugin");
|
||||
|
||||
WTF::String extension_scheme(extensions::kExtensionScheme);
|
||||
// Extension resources are HTTP-like and safe to expose to the fetch API. The
|
||||
@@ -255,6 +247,14 @@ void RendererClientBase::RenderThreadStarted() {
|
||||
extension_scheme);
|
||||
blink::SchemeRegistry::RegisterURLSchemeAsBypassingContentSecurityPolicy(
|
||||
extension_scheme);
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
|
||||
spellcheck_ = std::make_unique<SpellCheck>(this);
|
||||
#endif
|
||||
|
||||
blink::WebCustomElement::AddEmbedderCustomElementName("webview");
|
||||
blink::WebCustomElement::AddEmbedderCustomElementName("browserplugin");
|
||||
|
||||
std::vector<std::string> fetch_enabled_schemes =
|
||||
ParseSchemesCLISwitch(command_line, switches::kFetchSchemes);
|
||||
|
||||
@@ -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};
|
||||
};
|
||||
|
||||
|
||||
@@ -2066,10 +2066,7 @@ describe('BrowserWindow module', () => {
|
||||
beforeEach(() => {
|
||||
w = new BrowserWindow({ show: false });
|
||||
});
|
||||
afterEach(async () => {
|
||||
await closeWindow(w);
|
||||
w = null as unknown as BrowserWindow;
|
||||
});
|
||||
afterEach(closeAllWindows);
|
||||
|
||||
describe('BrowserWindow.selectPreviousTab()', () => {
|
||||
it('does not throw', () => {
|
||||
@@ -2138,6 +2135,18 @@ describe('BrowserWindow module', () => {
|
||||
}).to.throw('AddTabbedWindow cannot be called by a window on itself.');
|
||||
});
|
||||
});
|
||||
|
||||
describe('BrowserWindow.tabbingIdentifier', () => {
|
||||
it('is undefined if no tabbingIdentifier was set', () => {
|
||||
const w = new BrowserWindow({ show: false });
|
||||
expect(w.tabbingIdentifier).to.be.undefined('tabbingIdentifier');
|
||||
});
|
||||
|
||||
it('returns the window tabbingIdentifier', () => {
|
||||
const w = new BrowserWindow({ show: false, tabbingIdentifier: 'group1' });
|
||||
expect(w.tabbingIdentifier).to.equal('group1');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('autoHideMenuBar state', () => {
|
||||
@@ -4716,7 +4725,27 @@ describe('BrowserWindow module', () => {
|
||||
expect(w.getChildWindows().length).to.equal(0);
|
||||
});
|
||||
|
||||
ifit(process.platform === 'darwin')('child window matches visibility when visibility changes', async () => {
|
||||
ifit(process.platform === 'darwin')('only shows the intended window when a child with siblings is shown', async () => {
|
||||
const w = new BrowserWindow({ show: false });
|
||||
const childOne = new BrowserWindow({ show: false, parent: w });
|
||||
const childTwo = new BrowserWindow({ show: false, parent: w });
|
||||
|
||||
const parentShown = once(w, 'show');
|
||||
w.show();
|
||||
await parentShown;
|
||||
|
||||
expect(childOne.isVisible()).to.be.false('childOne is visible');
|
||||
expect(childTwo.isVisible()).to.be.false('childTwo is visible');
|
||||
|
||||
const childOneShown = once(childOne, 'show');
|
||||
childOne.show();
|
||||
await childOneShown;
|
||||
|
||||
expect(childOne.isVisible()).to.be.true('childOne is not visible');
|
||||
expect(childTwo.isVisible()).to.be.false('childTwo is visible');
|
||||
});
|
||||
|
||||
ifit(process.platform === 'darwin')('child matches parent visibility when parent visibility changes', async () => {
|
||||
const w = new BrowserWindow({ show: false });
|
||||
const c = new BrowserWindow({ show: false, parent: w });
|
||||
|
||||
@@ -4743,7 +4772,7 @@ describe('BrowserWindow module', () => {
|
||||
expect(c.isVisible()).to.be.true('child is visible');
|
||||
});
|
||||
|
||||
ifit(process.platform === 'darwin')('matches child window visibility when visibility changes', async () => {
|
||||
ifit(process.platform === 'darwin')('parent matches child visibility when child visibility changes', async () => {
|
||||
const w = new BrowserWindow({ show: false });
|
||||
const c = new BrowserWindow({ show: false, parent: w });
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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' });
|
||||
@@ -2256,13 +2270,13 @@ describe('webContents module', () => {
|
||||
});
|
||||
|
||||
describe('crashed event', () => {
|
||||
it('does not crash main process when destroying WebContents in it', async () => {
|
||||
it('does not crash main process when destroying WebContents in it', (done) => {
|
||||
const contents = (webContents as typeof ElectronInternal.WebContents).create({ nodeIntegration: true });
|
||||
const crashEvent = once(contents, 'render-process-gone');
|
||||
await contents.loadURL('about:blank');
|
||||
contents.forcefullyCrashRenderer();
|
||||
await crashEvent;
|
||||
contents.destroy();
|
||||
contents.once('crashed', () => {
|
||||
contents.destroy();
|
||||
done();
|
||||
});
|
||||
contents.loadURL('about:blank').then(() => contents.forcefullyCrashRenderer());
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -1039,33 +1039,77 @@ describe('chrome extensions', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('update', async () => {
|
||||
await w.loadURL(url);
|
||||
describe('update', () => {
|
||||
it('can update muted status', async () => {
|
||||
await w.loadURL(url);
|
||||
|
||||
const message = { method: 'update', args: [{ muted: true }] };
|
||||
w.webContents.executeJavaScript(`window.postMessage('${JSON.stringify(message)}', '*')`);
|
||||
const message = { method: 'update', args: [{ muted: true }] };
|
||||
w.webContents.executeJavaScript(`window.postMessage('${JSON.stringify(message)}', '*')`);
|
||||
|
||||
const [,, responseString] = await once(w.webContents, 'console-message');
|
||||
const response = JSON.parse(responseString);
|
||||
const [,, responseString] = await once(w.webContents, 'console-message');
|
||||
const response = JSON.parse(responseString);
|
||||
|
||||
expect(response).to.have.property('url').that.is.a('string');
|
||||
expect(response).to.have.property('title').that.is.a('string');
|
||||
expect(response).to.have.property('active').that.is.a('boolean');
|
||||
expect(response).to.have.property('autoDiscardable').that.is.a('boolean');
|
||||
expect(response).to.have.property('discarded').that.is.a('boolean');
|
||||
expect(response).to.have.property('groupId').that.is.a('number');
|
||||
expect(response).to.have.property('highlighted').that.is.a('boolean');
|
||||
expect(response).to.have.property('id').that.is.a('number');
|
||||
expect(response).to.have.property('incognito').that.is.a('boolean');
|
||||
expect(response).to.have.property('index').that.is.a('number');
|
||||
expect(response).to.have.property('pinned').that.is.a('boolean');
|
||||
expect(response).to.have.property('selected').that.is.a('boolean');
|
||||
expect(response).to.have.property('windowId').that.is.a('number');
|
||||
expect(response).to.have.property('mutedInfo').that.is.a('object');
|
||||
const { mutedInfo } = response;
|
||||
expect(mutedInfo).to.deep.eq({
|
||||
muted: true,
|
||||
reason: 'user'
|
||||
expect(response).to.have.property('mutedInfo').that.is.a('object');
|
||||
const { mutedInfo } = response;
|
||||
expect(mutedInfo).to.deep.eq({
|
||||
muted: true,
|
||||
reason: 'user'
|
||||
});
|
||||
});
|
||||
|
||||
it('fails when navigating to an invalid url', async () => {
|
||||
await w.loadURL(url);
|
||||
|
||||
const message = { method: 'update', args: [{ url: 'chrome://crash' }] };
|
||||
w.webContents.executeJavaScript(`window.postMessage('${JSON.stringify(message)}', '*')`);
|
||||
|
||||
const [,, responseString] = await once(w.webContents, 'console-message');
|
||||
const { error } = JSON.parse(responseString);
|
||||
expect(error).to.eq('I\'m sorry. I\'m afraid I can\'t do that.');
|
||||
});
|
||||
|
||||
it('fails when navigating to prohibited url', async () => {
|
||||
await w.loadURL(url);
|
||||
|
||||
const message = { method: 'update', args: [{ url: 'chrome://crash' }] };
|
||||
w.webContents.executeJavaScript(`window.postMessage('${JSON.stringify(message)}', '*')`);
|
||||
|
||||
const [,, responseString] = await once(w.webContents, 'console-message');
|
||||
const { error } = JSON.parse(responseString);
|
||||
expect(error).to.eq('I\'m sorry. I\'m afraid I can\'t do that.');
|
||||
});
|
||||
|
||||
it('fails when navigating to a devtools url without permission', async () => {
|
||||
await w.loadURL(url);
|
||||
|
||||
const message = { method: 'update', args: [{ url: 'devtools://blah' }] };
|
||||
w.webContents.executeJavaScript(`window.postMessage('${JSON.stringify(message)}', '*')`);
|
||||
|
||||
const [, , responseString] = await once(w.webContents, 'console-message');
|
||||
const { error } = JSON.parse(responseString);
|
||||
expect(error).to.eq('Cannot navigate to a devtools:// page without either the devtools or debugger permission.');
|
||||
});
|
||||
|
||||
it('fails when navigating to a chrome-untrusted url', async () => {
|
||||
await w.loadURL(url);
|
||||
|
||||
const message = { method: 'update', args: [{ url: 'chrome-untrusted://blah' }] };
|
||||
w.webContents.executeJavaScript(`window.postMessage('${JSON.stringify(message)}', '*')`);
|
||||
|
||||
const [, , responseString] = await once(w.webContents, 'console-message');
|
||||
const { error } = JSON.parse(responseString);
|
||||
expect(error).to.eq('Cannot navigate to a chrome-untrusted:// page.');
|
||||
});
|
||||
|
||||
it('fails when navigating to a file url withotut file access', async () => {
|
||||
await w.loadURL(url);
|
||||
|
||||
const message = { method: 'update', args: [{ url: 'file://blah' }] };
|
||||
w.webContents.executeJavaScript(`window.postMessage('${JSON.stringify(message)}', '*')`);
|
||||
|
||||
const [, , responseString] = await once(w.webContents, 'console-message');
|
||||
const { error } = JSON.parse(responseString);
|
||||
expect(error).to.eq('Cannot navigate to a file URL without local file access.');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* global chrome */
|
||||
|
||||
const handleRequest = (request, sender, sendResponse) => {
|
||||
const handleRequest = async (request, sender, sendResponse) => {
|
||||
const { method, args = [] } = request;
|
||||
const tabId = sender.tab.id;
|
||||
|
||||
@@ -53,7 +53,12 @@ const handleRequest = (request, sender, sendResponse) => {
|
||||
|
||||
case 'update': {
|
||||
const [params] = args;
|
||||
chrome.tabs.update(tabId, params).then(sendResponse);
|
||||
try {
|
||||
const response = await chrome.tabs.update(tabId, params);
|
||||
sendResponse(response);
|
||||
} catch (error) {
|
||||
sendResponse({ error: error.message });
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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>
|
||||
|
||||
@@ -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.
|
||||
|
||||
5
typings/internal-ambient.d.ts
vendored
5
typings/internal-ambient.d.ts
vendored
@@ -62,9 +62,7 @@ declare namespace NodeJS {
|
||||
type AsarFileStat = {
|
||||
size: number;
|
||||
offset: number;
|
||||
isFile: boolean;
|
||||
isDirectory: boolean;
|
||||
isLink: boolean;
|
||||
type: number;
|
||||
}
|
||||
|
||||
interface AsarArchive {
|
||||
@@ -244,6 +242,7 @@ declare namespace NodeJS {
|
||||
// Additional properties
|
||||
_firstFileName?: string;
|
||||
_serviceStartupScript: string;
|
||||
_getOrCreateArchive?: (path: string) => NodeJS.AsarArchive | null;
|
||||
|
||||
helperExecPath: string;
|
||||
mainModule?: NodeJS.Module | undefined;
|
||||
|
||||
@@ -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