mirror of
https://github.com/electron/electron.git
synced 2026-02-19 03:14:51 -05:00
Compare commits
171 Commits
fix-codesp
...
v4.0.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e8d4a07137 | ||
|
|
d9a920e19a | ||
|
|
c1031f6faf | ||
|
|
366bc82c8f | ||
|
|
dec66ea7d7 | ||
|
|
3021870de4 | ||
|
|
3bd1243aed | ||
|
|
4ad3a39f1d | ||
|
|
b41722fa08 | ||
|
|
99a9f8a01b | ||
|
|
00534ebea4 | ||
|
|
64deb36efc | ||
|
|
a4ed644dd9 | ||
|
|
01f3107528 | ||
|
|
70ebebf07f | ||
|
|
8ac5da5110 | ||
|
|
aa781277c6 | ||
|
|
284b5671f8 | ||
|
|
39dffbfc89 | ||
|
|
d8ab2c7b1c | ||
|
|
8b37e62717 | ||
|
|
53e4cdf30a | ||
|
|
428a2b5ad5 | ||
|
|
4fe595652f | ||
|
|
67902822af | ||
|
|
5f70bae579 | ||
|
|
87bed0b52f | ||
|
|
020457f09b | ||
|
|
91a52f7268 | ||
|
|
9dc6a587ed | ||
|
|
7828ea0805 | ||
|
|
e2925fd1e7 | ||
|
|
60894aac06 | ||
|
|
f451ce6416 | ||
|
|
a67408e875 | ||
|
|
3c859a5554 | ||
|
|
49a564ecaa | ||
|
|
bcc8a274f8 | ||
|
|
3276ebf65d | ||
|
|
3056868515 | ||
|
|
87455600d0 | ||
|
|
907ab93042 | ||
|
|
d5f432b746 | ||
|
|
d3b1f1ebc4 | ||
|
|
3e5038a674 | ||
|
|
23498bd612 | ||
|
|
c5fd12c12e | ||
|
|
646a7af997 | ||
|
|
fd18171553 | ||
|
|
2b833da9b9 | ||
|
|
682e3e32eb | ||
|
|
639c07a9c8 | ||
|
|
c5e3b6350e | ||
|
|
6fdbfdb835 | ||
|
|
85ece0a605 | ||
|
|
797338095c | ||
|
|
43be9e9ed3 | ||
|
|
a7bc01b96b | ||
|
|
03e98a0b76 | ||
|
|
6e4ca8b787 | ||
|
|
33254c5bcc | ||
|
|
7be10d50f4 | ||
|
|
0bb8ddaeeb | ||
|
|
98d9e1c0a3 | ||
|
|
7cc7d4a360 | ||
|
|
64874660e1 | ||
|
|
2d0b80cf57 | ||
|
|
c45ac5108e | ||
|
|
b488b413f0 | ||
|
|
802e2fae8a | ||
|
|
f331b9234d | ||
|
|
83414457ea | ||
|
|
d488baa67f | ||
|
|
cbc0f452b3 | ||
|
|
915fc3d62d | ||
|
|
fec42919ed | ||
|
|
43e8dd7997 | ||
|
|
3846a1b663 | ||
|
|
08d80295d7 | ||
|
|
127ad9252e | ||
|
|
f43920e436 | ||
|
|
62c0f842ae | ||
|
|
acea9d1576 | ||
|
|
8e31642530 | ||
|
|
91533574c7 | ||
|
|
eef05cba6a | ||
|
|
7e63ca603d | ||
|
|
2b7f854a83 | ||
|
|
d07115e1dc | ||
|
|
c268fd872c | ||
|
|
2ac5f33cf8 | ||
|
|
deac580f1a | ||
|
|
a5fa18767a | ||
|
|
3e4d77109a | ||
|
|
081af07892 | ||
|
|
d1c48456e9 | ||
|
|
282829c076 | ||
|
|
6e759e0852 | ||
|
|
74bd220436 | ||
|
|
d16304f2fb | ||
|
|
ac1bfb2337 | ||
|
|
436b9a2ee1 | ||
|
|
9625faeede | ||
|
|
8d4573f289 | ||
|
|
041773c6bc | ||
|
|
a51ad1f956 | ||
|
|
3a4c20b154 | ||
|
|
b2d4c519f8 | ||
|
|
86e35e6221 | ||
|
|
17b80ebb9c | ||
|
|
a313aaea72 | ||
|
|
11ebf5c990 | ||
|
|
daa0be56c9 | ||
|
|
e026e9aa82 | ||
|
|
fdfcd3cf12 | ||
|
|
f8450daa14 | ||
|
|
f68d59d1a3 | ||
|
|
b8bc25665f | ||
|
|
9a5915995e | ||
|
|
4844af489a | ||
|
|
fd4d0320cd | ||
|
|
57153ead89 | ||
|
|
e113ec78ec | ||
|
|
8a90bbf7ba | ||
|
|
cd1c9c8a45 | ||
|
|
6ba390e68a | ||
|
|
b77f41420b | ||
|
|
372fa4cdd0 | ||
|
|
435ca8cff3 | ||
|
|
f30c382d41 | ||
|
|
f88a06df84 | ||
|
|
96a4fce100 | ||
|
|
85b0f254be | ||
|
|
9ac4611075 | ||
|
|
6c18908333 | ||
|
|
f2ca4c11c8 | ||
|
|
7ab6073cdb | ||
|
|
b57d12583f | ||
|
|
3cd67db581 | ||
|
|
630bc64f2f | ||
|
|
a2b4458046 | ||
|
|
fd205a1577 | ||
|
|
1ff102e54a | ||
|
|
d525083d75 | ||
|
|
f1a8483349 | ||
|
|
5fbf1f9a54 | ||
|
|
838f108821 | ||
|
|
df70487f80 | ||
|
|
0c09199f77 | ||
|
|
6281e4ef0b | ||
|
|
abbf9c3ca3 | ||
|
|
b4f4ce1b84 | ||
|
|
5f83e07748 | ||
|
|
203b41fe2e | ||
|
|
c16b34539a | ||
|
|
446275c85a | ||
|
|
1adce9413a | ||
|
|
3ee697b258 | ||
|
|
6e30d855ba | ||
|
|
948fc6f612 | ||
|
|
8c2d16f031 | ||
|
|
11486b99a4 | ||
|
|
ebb2c53c3d | ||
|
|
8094f1a3f0 | ||
|
|
b7f20f1878 | ||
|
|
e9e0219ae8 | ||
|
|
24b809f2bc | ||
|
|
cfbb22b380 | ||
|
|
f9ae1aa999 | ||
|
|
f1ec2237e7 | ||
|
|
35df516e28 |
@@ -1,3 +1,12 @@
|
||||
# The config expects the following environment variables to be set:
|
||||
# - "SLACK_WEBHOOK" Slack hook URL to send notifications.
|
||||
#
|
||||
# The publishing scripts expect access tokens to be defined as env vars,
|
||||
# but those are not covered here.
|
||||
#
|
||||
# CircleCI docs on variables:
|
||||
# https://circleci.com/docs/2.0/env-vars/
|
||||
|
||||
# Build machines configs.
|
||||
docker-image: &docker-image
|
||||
docker:
|
||||
@@ -145,6 +154,7 @@ step-install-nodejs-on-mac: &step-install-nodejs-on-mac
|
||||
if [ "`uname`" == "Darwin" ]; then
|
||||
brew update
|
||||
brew install node@10
|
||||
echo 'export PATH="/usr/local/opt/node@10/bin:$PATH"' >> $BASH_ENV
|
||||
fi
|
||||
|
||||
step-gn-gen-default: &step-gn-gen-default
|
||||
@@ -233,6 +243,7 @@ step-persist-data-for-tests: &step-persist-data-for-tests
|
||||
|
||||
# Build artifacts
|
||||
- src/out/Default/dist.zip
|
||||
- src/out/Default/mksnapshot.zip
|
||||
- src/out/Default/gen/node_headers
|
||||
|
||||
step-electron-dist-unzip: &step-electron-dist-unzip
|
||||
@@ -244,6 +255,13 @@ step-electron-dist-unzip: &step-electron-dist-unzip
|
||||
# TODO(alexeykuzmin): Remove '-o' when it's no longer needed.
|
||||
unzip -o dist.zip
|
||||
|
||||
step-mksnapshot-unzip: &step-mksnapshot-unzip
|
||||
run:
|
||||
name: Unzip mksnapshot.zip
|
||||
command: |
|
||||
cd src/out/Default
|
||||
unzip -o mksnapshot.zip
|
||||
|
||||
step-ffmpeg-gn-gen: &step-ffmpeg-gn-gen
|
||||
run:
|
||||
name: ffmpeg GN gen
|
||||
@@ -272,6 +290,13 @@ step-ffmpeg-store: &step-ffmpeg-store
|
||||
path: src/out/ffmpeg/ffmpeg.zip
|
||||
destination: ffmpeg.zip
|
||||
|
||||
step-verify-mksnapshot: &step-verify-mksnapshot
|
||||
run:
|
||||
name: Verify mksnapshot
|
||||
command: |
|
||||
cd src
|
||||
python electron/script/verify-mksnapshot.py --source-root "$PWD" --build-dir out/Default
|
||||
|
||||
step-setup-linux-for-headless-testing: &step-setup-linux-for-headless-testing
|
||||
run:
|
||||
name: Setup for headless testing
|
||||
@@ -311,20 +336,30 @@ step-mksnapshot-store: &step-mksnapshot-store
|
||||
path: src/out/Default/mksnapshot.zip
|
||||
destination: mksnapshot.zip
|
||||
|
||||
step-generate-breakpad-symbols: &step-generate-breakpad-symbols
|
||||
step-build-dump-syms: &step-build-dump-syms
|
||||
run:
|
||||
name: Generate breakpad symbols
|
||||
environment:
|
||||
# TODO(alexeykuzmin): Explicitly pass an out folder path to the scripts.
|
||||
ELECTRON_OUT_DIR: Default
|
||||
name: Build dump_syms binary
|
||||
command: |
|
||||
cd src
|
||||
|
||||
# Build needed dump_syms executable
|
||||
ninja -C out/Default third_party/breakpad:dump_syms
|
||||
|
||||
electron/script/dump-symbols.py -d "$PWD/out/Default/electron.breakpad.syms"
|
||||
electron/script/zip-symbols.py
|
||||
step-generate-breakpad-symbols: &step-generate-breakpad-symbols
|
||||
run:
|
||||
name: Generate breakpad symbols
|
||||
command: |
|
||||
cd src
|
||||
export BUILD_PATH="$PWD/out/Default"
|
||||
export DEST_PATH="$BUILD_PATH/breakpad_symbols"
|
||||
electron/script/dump-symbols.py -b $BUILD_PATH -d $DEST_PATH -v
|
||||
|
||||
step-zip-symbols: &step-zip-symbols
|
||||
run:
|
||||
name: Zip symbols
|
||||
command: |
|
||||
cd src
|
||||
export BUILD_PATH="$PWD/out/Default"
|
||||
electron/script/zip-symbols.py -b $BUILD_PATH
|
||||
|
||||
step-maybe-native-mksnapshot-gn-gen: &step-maybe-native-mksnapshot-gn-gen
|
||||
run:
|
||||
@@ -332,7 +367,7 @@ step-maybe-native-mksnapshot-gn-gen: &step-maybe-native-mksnapshot-gn-gen
|
||||
command: |
|
||||
if [ "$BUILD_NATIVE_MKSNAPSHOT" == "1" ]; then
|
||||
cd src
|
||||
gn gen out/native_mksnapshot --args='import("//electron/build/args/native_mksnapshot.gn") cc_wrapper="'"$SCCACHE_PATH"'" v8_snapshot_toolchain="'"$MKSNAPSHOT_TOOLCHAIN"'"'" $GN_EXTRA_ARGS"
|
||||
gn gen out/native_mksnapshot --args='import("'$GN_CONFIG'") cc_wrapper="'"$SCCACHE_PATH"'" v8_snapshot_toolchain="'"$MKSNAPSHOT_TOOLCHAIN"'"'" $GN_EXTRA_ARGS"
|
||||
else
|
||||
echo 'Skipping native mksnapshot GN gen for non arm build'
|
||||
fi
|
||||
@@ -453,12 +488,29 @@ steps-electron-build-for-tests: &steps-electron-build-for-tests
|
||||
|
||||
- *step-show-sccache-stats
|
||||
|
||||
# mksnapshot
|
||||
- *step-mksnapshot-build
|
||||
- *step-mksnapshot-store
|
||||
|
||||
# native_mksnapshot
|
||||
- *step-maybe-native-mksnapshot-gn-gen
|
||||
- *step-maybe-native-mksnapshot-build
|
||||
- *step-maybe-native-mksnapshot-strip
|
||||
- *step-maybe-native-mksnapshot-store
|
||||
|
||||
# ffmpeg
|
||||
- *step-ffmpeg-gn-gen
|
||||
- *step-ffmpeg-build
|
||||
- *step-ffmpeg-store
|
||||
|
||||
# Save all data needed for a further tests run.
|
||||
- *step-persist-data-for-tests
|
||||
|
||||
# Breakpad symbols.
|
||||
# TODO(alexeykuzmin): We should do it only in nightly builds.
|
||||
- *step-build-dump-syms
|
||||
- *step-generate-breakpad-symbols
|
||||
- *step-zip-symbols
|
||||
|
||||
# Trigger tests on arm hardware if needed
|
||||
- *step-maybe-trigger-arm-test
|
||||
@@ -479,7 +531,9 @@ steps-electron-build-for-publish: &steps-electron-build-for-publish
|
||||
- *step-maybe-electron-dist-strip
|
||||
- *step-electron-dist-build
|
||||
- *step-electron-dist-store
|
||||
- *step-build-dump-syms
|
||||
- *step-generate-breakpad-symbols
|
||||
- *step-zip-symbols
|
||||
|
||||
# mksnapshot
|
||||
- *step-mksnapshot-build
|
||||
@@ -594,12 +648,25 @@ steps-verify-ffmpeg: &steps-verify-ffmpeg
|
||||
- *step-verify-ffmpeg
|
||||
- *step-maybe-notify-slack-failure
|
||||
|
||||
steps-verify-mksnapshot: &steps-verify-mksnapshot
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- *step-depot-tools-add-to-path
|
||||
- *step-electron-dist-unzip
|
||||
- *step-mksnapshot-unzip
|
||||
- *step-setup-linux-for-headless-testing
|
||||
|
||||
- *step-verify-mksnapshot
|
||||
- *step-maybe-notify-slack-failure
|
||||
|
||||
steps-tests: &steps-tests
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- *step-depot-tools-add-to-path
|
||||
- *step-electron-dist-unzip
|
||||
- *step-mksnapshot-unzip
|
||||
- *step-setup-linux-for-headless-testing
|
||||
- *step-install-nodejs-on-mac
|
||||
|
||||
@@ -625,6 +692,8 @@ steps-tests: &steps-tests
|
||||
- store_test_results:
|
||||
path: src/junit
|
||||
|
||||
- *step-verify-mksnapshot
|
||||
|
||||
- *step-maybe-notify-slack-failure
|
||||
|
||||
# Mac build are different in a few ways:
|
||||
@@ -665,6 +734,8 @@ steps-build-mac: &steps-build-mac
|
||||
# to store all gn's dependencies and configs.
|
||||
- *step-verify-ffmpeg
|
||||
|
||||
- *step-verify-mksnapshot
|
||||
|
||||
# Node.js headers for tests
|
||||
- *step-nodejs-headers-build
|
||||
|
||||
@@ -696,8 +767,10 @@ jobs:
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
|
||||
<<: *steps-checkout
|
||||
|
||||
linux-x64-checkout:
|
||||
linux-checkout-for-native-tests:
|
||||
<<: *machine-linux-2xlarge
|
||||
environment:
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_pyyaml=True'
|
||||
<<: *steps-checkout
|
||||
|
||||
# Layer 2: Builds.
|
||||
@@ -850,6 +923,7 @@ jobs:
|
||||
<<: *machine-linux-medium
|
||||
environment:
|
||||
<<: *env-arm
|
||||
<<: *env-release-build
|
||||
<<: *env-enable-sccache
|
||||
<<: *env-send-slack-notifications
|
||||
<<: *steps-native-mksnapshot-build
|
||||
@@ -909,6 +983,7 @@ jobs:
|
||||
<<: *machine-linux-medium
|
||||
environment:
|
||||
<<: *env-arm64
|
||||
<<: *env-release-build
|
||||
<<: *env-enable-sccache
|
||||
<<: *env-send-slack-notifications
|
||||
<<: *steps-native-mksnapshot-build
|
||||
@@ -968,6 +1043,13 @@ jobs:
|
||||
<<: *env-send-slack-notifications
|
||||
<<: *steps-verify-ffmpeg
|
||||
|
||||
linux-x64-verify-mksnapshot:
|
||||
<<: *machine-linux-medium
|
||||
environment:
|
||||
<<: *env-headless-testing
|
||||
<<: *env-send-slack-notifications
|
||||
<<: *steps-verify-mksnapshot
|
||||
|
||||
linux-ia32-testing-tests:
|
||||
<<: *machine-linux-medium
|
||||
environment:
|
||||
@@ -992,6 +1074,14 @@ jobs:
|
||||
<<: *env-send-slack-notifications
|
||||
<<: *steps-verify-ffmpeg
|
||||
|
||||
linux-ia32-verify-mksnapshot:
|
||||
<<: *machine-linux-medium
|
||||
environment:
|
||||
<<: *env-ia32
|
||||
<<: *env-headless-testing
|
||||
<<: *env-send-slack-notifications
|
||||
<<: *steps-verify-mksnapshot
|
||||
|
||||
osx-testing-tests:
|
||||
<<: *machine-mac
|
||||
environment:
|
||||
@@ -1114,6 +1204,9 @@ workflows:
|
||||
requires:
|
||||
- linux-x64-release
|
||||
- linux-x64-ffmpeg
|
||||
- linux-x64-verify-mksnapshot:
|
||||
requires:
|
||||
- linux-x64-release
|
||||
- linux-x64-chromedriver:
|
||||
requires:
|
||||
- linux-checkout
|
||||
@@ -1138,6 +1231,9 @@ workflows:
|
||||
requires:
|
||||
- linux-ia32-release
|
||||
- linux-ia32-ffmpeg
|
||||
- linux-ia32-verify-mksnapshot:
|
||||
requires:
|
||||
- linux-ia32-release
|
||||
- linux-ia32-chromedriver:
|
||||
requires:
|
||||
- linux-checkout
|
||||
@@ -1199,15 +1295,15 @@ workflows:
|
||||
- master
|
||||
- *chromium-upgrade-branches
|
||||
jobs:
|
||||
- linux-x64-checkout
|
||||
- linux-checkout-for-native-tests
|
||||
|
||||
# TODO(alexeykuzmin): Enable it back.
|
||||
# Tons of crashes right now, see
|
||||
# https://circleci.com/gh/electron/electron/67463
|
||||
# - linux-x64-browsertests:
|
||||
# requires:
|
||||
# - linux-x64-checkout
|
||||
# - linux-checkout-for-native-tests
|
||||
|
||||
- linux-x64-unittests:
|
||||
requires:
|
||||
- linux-x64-checkout
|
||||
- linux-checkout-for-native-tests
|
||||
|
||||
45
BUILD.gn
45
BUILD.gn
@@ -558,6 +558,7 @@ if (is_mac) {
|
||||
sources = filenames.framework_sources
|
||||
|
||||
libs = [
|
||||
"AVFoundation.framework",
|
||||
"Carbon.framework",
|
||||
"QuartzCore.framework",
|
||||
"Quartz.framework",
|
||||
@@ -635,13 +636,44 @@ if (is_mac) {
|
||||
"$root_out_dir/$electron_login_helper_name.app",
|
||||
]
|
||||
outputs = [
|
||||
"{{bundle_contents_dir}}/Library/LoginItems",
|
||||
"{{bundle_contents_dir}}/Library/LoginItems/{{source_file_part}}",
|
||||
]
|
||||
}
|
||||
|
||||
action("electron_app_lproj_dirs") {
|
||||
outputs = []
|
||||
|
||||
foreach(locale, locales_as_mac_outputs) {
|
||||
outputs += [ "$target_gen_dir/app_infoplist_strings/$locale.lproj" ]
|
||||
}
|
||||
script = "build/mac/make_locale_dirs.py"
|
||||
args = rebase_path(outputs)
|
||||
}
|
||||
|
||||
foreach(locale, locales_as_mac_outputs) {
|
||||
bundle_data("electron_app_strings_${locale}_bundle_data") {
|
||||
sources = [
|
||||
"$target_gen_dir/app_infoplist_strings/$locale.lproj",
|
||||
]
|
||||
outputs = [
|
||||
"{{bundle_resources_dir}}/$locale.lproj",
|
||||
]
|
||||
public_deps = [
|
||||
":electron_app_lproj_dirs",
|
||||
]
|
||||
}
|
||||
}
|
||||
group("electron_app_strings_bundle_data") {
|
||||
public_deps = []
|
||||
foreach(locale, locales_as_mac_outputs) {
|
||||
public_deps += [ ":electron_app_strings_${locale}_bundle_data" ]
|
||||
}
|
||||
}
|
||||
|
||||
bundle_data("electron_app_resources") {
|
||||
public_deps = [
|
||||
":app2asar",
|
||||
":electron_app_strings_bundle_data",
|
||||
":js2asar",
|
||||
]
|
||||
sources = [
|
||||
@@ -750,6 +782,16 @@ if (is_mac) {
|
||||
"/DELAYLOAD:api-ms-win-core-winrt-l1-1-0.dll",
|
||||
"/DELAYLOAD:api-ms-win-core-winrt-string-l1-1-0.dll",
|
||||
]
|
||||
|
||||
# This is to support renaming of electron.exe. node-gyp has hard-coded
|
||||
# executable names which it will recognise as node. This module definition
|
||||
# file claims that the electron executable is in fact named "node.exe",
|
||||
# which is one of the executable names that node-gyp recognizes.
|
||||
# See https://github.com/nodejs/node-gyp/commit/52ceec3a6d15de3a8f385f43dbe5ecf5456ad07a
|
||||
ldflags += [ "/DEF:" + rebase_path("build/electron.def", root_build_dir) ]
|
||||
inputs = [
|
||||
"build/electron.def",
|
||||
]
|
||||
}
|
||||
if (is_linux) {
|
||||
ldflags = [ "-pie" ]
|
||||
@@ -925,6 +967,7 @@ dist_zip("electron_chromedriver_zip") {
|
||||
dist_zip("electron_mksnapshot_zip") {
|
||||
data_deps = [
|
||||
"//v8:mksnapshot($v8_snapshot_toolchain)",
|
||||
"//tools/v8_context_snapshot:v8_context_snapshot_generator",
|
||||
":licenses",
|
||||
]
|
||||
outputs = [
|
||||
|
||||
36
DEPS
36
DEPS
@@ -12,7 +12,7 @@ vars = {
|
||||
'chromium_version':
|
||||
'69.0.3497.106',
|
||||
'node_version':
|
||||
'5654c276d0497ff9a0bb0d7550b9073b2e2e7d3f',
|
||||
'4d44266b78256449dd6ae86e419e3ec07257b569',
|
||||
|
||||
'boto_version': 'f7574aa6cc2c819430c1f05e9a1a1a666ef8169b',
|
||||
'pyyaml_version': '3.12',
|
||||
@@ -24,9 +24,19 @@ vars = {
|
||||
'requests_git': 'https://github.com/kennethreitz',
|
||||
'yaml_git': 'https://github.com/yaml',
|
||||
|
||||
# To be able to build clean Chromium from sources.
|
||||
'apply_patches': True,
|
||||
|
||||
# Python interface to Amazon Web Services. Is used for releases only.
|
||||
'checkout_boto': False,
|
||||
|
||||
# To allow in-house builds to checkout those manually.
|
||||
'checkout_chromium': True,
|
||||
'checkout_node': True,
|
||||
|
||||
# It's only needed to parse the native tests configurations.
|
||||
'checkout_pyyaml': False,
|
||||
|
||||
# Python "requests" module is used for releases only.
|
||||
'checkout_requests': False,
|
||||
|
||||
@@ -49,12 +59,18 @@ vars = {
|
||||
}
|
||||
|
||||
deps = {
|
||||
'src':
|
||||
(Var("chromium_git")) + '/chromium/src.git@' + (Var("chromium_version")),
|
||||
'src/third_party/electron_node':
|
||||
(Var("electron_git")) + '/node.git@' + (Var("node_version")),
|
||||
'src/electron/vendor/pyyaml':
|
||||
(Var("yaml_git")) + '/pyyaml.git@' + (Var("pyyaml_version")),
|
||||
'src': {
|
||||
'url': (Var("chromium_git")) + '/chromium/src.git@' + (Var("chromium_version")),
|
||||
'condition': 'checkout_chromium',
|
||||
},
|
||||
'src/third_party/electron_node': {
|
||||
'url': (Var("electron_git")) + '/node.git@' + (Var("node_version")),
|
||||
'condition': 'checkout_node',
|
||||
},
|
||||
'src/electron/vendor/pyyaml': {
|
||||
'url': (Var("yaml_git")) + '/pyyaml.git@' + (Var("pyyaml_version")),
|
||||
'condition': 'checkout_pyyaml',
|
||||
},
|
||||
'src/electron/vendor/boto': {
|
||||
'url': Var('boto_git') + '/boto.git' + '@' + Var('boto_version'),
|
||||
'condition': 'checkout_boto',
|
||||
@@ -68,12 +84,12 @@ deps = {
|
||||
hooks = [
|
||||
{
|
||||
'name': 'patch_chromium',
|
||||
'condition': 'checkout_chromium and apply_patches',
|
||||
'pattern': 'src/electron',
|
||||
'action': [
|
||||
'python',
|
||||
'src/electron/script/apply-patches',
|
||||
'--project-root=.',
|
||||
'--commit',
|
||||
'src/electron/script/apply_all_patches.py',
|
||||
'src/electron/patches/common/config.json',
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
31
appveyor.yml
31
appveyor.yml
@@ -1,3 +1,28 @@
|
||||
# The config expects the following environment variables to be set:
|
||||
# - "GN_CONFIG" Build type. One of {'debug', 'testing', 'release'}.
|
||||
# - "GN_EXTRA_ARGS" Additional gn arguments for a build config,
|
||||
# e.g. 'target_cpu="x86"' to build for a 32bit platform.
|
||||
# https://gn.googlesource.com/gn/+/master/docs/reference.md#target_cpu
|
||||
# Don't forget to set up "NPM_CONFIG_ARCH" and "TARGET_ARCH" accordningly
|
||||
# if you pass a custom value for 'target_cpu'.
|
||||
# - "ELECTRON_RELEASE" Set it to '1' upload binaries on success.
|
||||
# - "NPM_CONFIG_ARCH" E.g. 'x86'. Is used to build native Node.js modules.
|
||||
# Must match 'target_cpu' passed to "GN_EXTRA_ARGS" and "TARGET_ARCH" value.
|
||||
# - "TARGET_ARCH" Choose from {'ia32', 'x64', 'arm', 'arm64', 'mips64el'}.
|
||||
# Is used in some publishing scripts, but does NOT affect the Electron binary.
|
||||
# Must match 'target_cpu' passed to "GN_EXTRA_ARGS" and "NPM_CONFIG_ARCH" value.
|
||||
# - "UPLOAD_TO_S3" Set it to '1' upload a release to the S3 bucket.
|
||||
# Otherwise the release will be uploaded to the Github Releases.
|
||||
# (The value is only checked if "ELECTRON_RELEASE" is defined.)
|
||||
#
|
||||
# The publishing scripts expect access tokens to be defined as env vars,
|
||||
# but those are not covered here.
|
||||
#
|
||||
# AppVeyor docs on variables:
|
||||
# https://www.appveyor.com/docs/environment-variables/
|
||||
# https://www.appveyor.com/docs/build-configuration/#secure-variables
|
||||
# https://www.appveyor.com/docs/build-configuration/#custom-environment-variables
|
||||
|
||||
version: 1.0.{build}
|
||||
build_cloud: libcc-20
|
||||
image: libcc-20-vs2017-15.7.4
|
||||
@@ -29,7 +54,8 @@ build_script:
|
||||
"https://github.com/electron/electron"
|
||||
- gclient sync --with_branch_heads --with_tags
|
||||
- cd src
|
||||
- gn gen out/Default "--args=import(\"//electron/build/args/%GN_CONFIG%.gn\") %GN_EXTRA_ARGS%"
|
||||
- ps: $env:BUILD_CONFIG_PATH="//electron/build/args/%GN_CONFIG%.gn"
|
||||
- gn gen out/Default "--args=import(\"%BUILD_CONFIG_PATH%\") %GN_EXTRA_ARGS%"
|
||||
- ninja -C out/Default electron:electron_app
|
||||
- gn gen out/ffmpeg "--args=import(\"//electron/build/args/ffmpeg.gn\") %GN_EXTRA_ARGS%"
|
||||
- ninja -C out/ffmpeg electron:electron_ffmpeg_zip
|
||||
@@ -44,7 +70,7 @@ build_script:
|
||||
if ($env:GN_CONFIG -eq 'release') {
|
||||
ninja -C out/Default third_party/breakpad:dump_syms
|
||||
}
|
||||
- if "%GN_CONFIG%"=="release" ( python electron\script\dump-symbols.py -d %cd%\out\Default\electron.breakpad.syms -v)
|
||||
- if "%GN_CONFIG%"=="release" ( python electron\script\dump-symbols.py -d %cd%\out\Default\breakpad_symbols -v)
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -eq 'release') {
|
||||
python electron\script\zip-symbols.py
|
||||
@@ -56,6 +82,7 @@ test_script:
|
||||
$env:RUN_TESTS="true"
|
||||
}
|
||||
- if "%RUN_TESTS%"=="true" ( echo Verifying non proprietary ffmpeg & python electron\script\verify-ffmpeg.py --build-dir out\Default --source-root %cd% --ffmpeg-path out\ffmpeg )
|
||||
- if "%RUN_TESTS%"=="true" ( echo Verifying mksnapshot & python electron\script\verify-mksnapshot.py --build-dir out\Default --source-root %cd% )
|
||||
- ps: >-
|
||||
if ($env:RUN_TESTS -eq 'true') {
|
||||
New-Item .\out\Default\gen\node_headers\Release -Type directory
|
||||
|
||||
@@ -24,10 +24,14 @@
|
||||
#include "base/win/windows_version.h"
|
||||
#include "content/public/app/sandbox_helper_win.h"
|
||||
#include "sandbox/win/src/sandbox_types.h"
|
||||
#elif defined(OS_LINUX) // defined(OS_WIN)
|
||||
#elif defined(OS_LINUX) // defined(OS_WIN)
|
||||
#include <unistd.h>
|
||||
#include <cstdio>
|
||||
#include "atom/app/atom_main_delegate.h" // NOLINT
|
||||
#include "content/public/app/content_main.h"
|
||||
#else // defined(OS_LINUX)
|
||||
#include <unistd.h>
|
||||
#include <cstdio>
|
||||
#include "atom/app/atom_library_main.h"
|
||||
#endif // defined(OS_MACOSX)
|
||||
|
||||
@@ -54,6 +58,25 @@ bool IsEnvSet(const char* name) {
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(OS_POSIX)
|
||||
void FixStdioStreams() {
|
||||
// libuv may mark stdin/stdout/stderr as close-on-exec, which interferes
|
||||
// with chromium's subprocess spawning. As a workaround, we detect if these
|
||||
// streams are closed on startup, and reopen them as /dev/null if necessary.
|
||||
// Otherwise, an unrelated file descriptor will be assigned as stdout/stderr
|
||||
// which may cause various errors when attempting to write to them.
|
||||
//
|
||||
// For details see https://github.com/libuv/libuv/issues/2062
|
||||
struct stat st;
|
||||
if (fstat(STDIN_FILENO, &st) < 0 && errno == EBADF)
|
||||
ignore_result(freopen("/dev/null", "r", stdin));
|
||||
if (fstat(STDOUT_FILENO, &st) < 0 && errno == EBADF)
|
||||
ignore_result(freopen("/dev/null", "w", stdout));
|
||||
if (fstat(STDERR_FILENO, &st) < 0 && errno == EBADF)
|
||||
ignore_result(freopen("/dev/null", "w", stderr));
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
#if defined(OS_WIN)
|
||||
@@ -155,6 +178,8 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
|
||||
#elif defined(OS_LINUX) // defined(OS_WIN)
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
FixStdioStreams();
|
||||
|
||||
#if BUILDFLAG(ENABLE_RUN_AS_NODE)
|
||||
if (IsEnvSet(kRunAsNode)) {
|
||||
base::i18n::InitializeICU();
|
||||
@@ -174,6 +199,8 @@ int main(int argc, char* argv[]) {
|
||||
#else // defined(OS_LINUX)
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
FixStdioStreams();
|
||||
|
||||
#if BUILDFLAG(ENABLE_RUN_AS_NODE)
|
||||
if (IsEnvSet(kRunAsNode)) {
|
||||
return AtomInitializeICUandStartNode(argc, argv);
|
||||
|
||||
@@ -1173,7 +1173,7 @@ v8::Local<v8::Promise> App::GetGPUInfo(v8::Isolate* isolate,
|
||||
|
||||
auto* const info_mgr = GPUInfoManager::GetInstance();
|
||||
if (info_type == "complete") {
|
||||
#if defined(OS_WIN)
|
||||
#if defined(OS_WIN) || defined(OS_MACOSX)
|
||||
info_mgr->FetchCompleteInfo(promise);
|
||||
#else
|
||||
info_mgr->FetchBasicInfo(promise);
|
||||
@@ -1284,6 +1284,8 @@ void App::BuildPrototype(v8::Isolate* isolate,
|
||||
base::Bind(&Browser::UpdateCurrentActivity, browser))
|
||||
.SetMethod("setAboutPanelOptions",
|
||||
base::Bind(&Browser::SetAboutPanelOptions, browser))
|
||||
.SetMethod("showAboutPanel",
|
||||
base::Bind(&Browser::ShowAboutPanel, browser))
|
||||
#endif
|
||||
#if defined(OS_WIN)
|
||||
.SetMethod("setUserTasks", base::Bind(&Browser::SetUserTasks, browser))
|
||||
|
||||
@@ -66,6 +66,7 @@ void BrowserView::Init(v8::Isolate* isolate,
|
||||
|
||||
web_contents_.Reset(isolate, web_contents.ToV8());
|
||||
api_web_contents_ = web_contents.get();
|
||||
Observe(web_contents->web_contents());
|
||||
|
||||
view_.reset(
|
||||
NativeBrowserView::Create(api_web_contents_->managed_web_contents()));
|
||||
@@ -74,7 +75,16 @@ void BrowserView::Init(v8::Isolate* isolate,
|
||||
}
|
||||
|
||||
BrowserView::~BrowserView() {
|
||||
api_web_contents_->DestroyWebContents(true /* async */);
|
||||
if (api_web_contents_) { // destroy() is called
|
||||
// Destroy WebContents asynchronously unless app is shutting down,
|
||||
// because destroy() might be called inside WebContents's event handler.
|
||||
api_web_contents_->DestroyWebContents(!Browser::Get()->is_shutting_down());
|
||||
}
|
||||
}
|
||||
|
||||
void BrowserView::WebContentsDestroyed() {
|
||||
api_web_contents_ = nullptr;
|
||||
web_contents_.Reset();
|
||||
}
|
||||
|
||||
// static
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "atom/browser/native_browser_view.h"
|
||||
#include "content/public/browser/web_contents_observer.h"
|
||||
#include "native_mate/handle.h"
|
||||
|
||||
namespace gfx {
|
||||
@@ -29,7 +30,8 @@ namespace api {
|
||||
|
||||
class WebContents;
|
||||
|
||||
class BrowserView : public mate::TrackableObject<BrowserView> {
|
||||
class BrowserView : public mate::TrackableObject<BrowserView>,
|
||||
public content::WebContentsObserver {
|
||||
public:
|
||||
static mate::WrappableBase* New(mate::Arguments* args);
|
||||
|
||||
@@ -47,6 +49,9 @@ class BrowserView : public mate::TrackableObject<BrowserView> {
|
||||
const mate::Dictionary& options);
|
||||
~BrowserView() override;
|
||||
|
||||
// content::WebContentsObserver:
|
||||
void WebContentsDestroyed() override;
|
||||
|
||||
private:
|
||||
void Init(v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> wrapper,
|
||||
|
||||
@@ -385,7 +385,9 @@ void BrowserWindow::Cleanup() {
|
||||
if (host)
|
||||
host->GetWidget()->RemoveInputEventObserver(this);
|
||||
|
||||
api_web_contents_->DestroyWebContents(true /* async */);
|
||||
// Destroy WebContents asynchronously unless app is shutting down,
|
||||
// because destroy() might be called inside WebContents's event handler.
|
||||
api_web_contents_->DestroyWebContents(!Browser::Get()->is_shutting_down());
|
||||
Observe(nullptr);
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,12 @@ void BrowserWindow::OverrideNSWindowContentView(
|
||||
NSView* webView = iwc->GetView()->GetNativeView();
|
||||
NSView* contentView = [window()->GetNativeWindow() contentView];
|
||||
[webView setFrame:[contentView bounds]];
|
||||
[contentView addSubview:webView];
|
||||
|
||||
// ensure that buttons view is floated to top of view hierarchy
|
||||
NSArray* subviews = [contentView subviews];
|
||||
NSView* last = subviews.lastObject;
|
||||
[contentView addSubview:webView positioned:NSWindowBelow relativeTo:last];
|
||||
|
||||
[contentView viewDidMoveToWindow];
|
||||
}
|
||||
|
||||
|
||||
26
atom/browser/api/atom_api_event.cc
Normal file
26
atom/browser/api/atom_api_event.cc
Normal file
@@ -0,0 +1,26 @@
|
||||
// Copyright (c) 2018 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/event_emitter.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
namespace {
|
||||
|
||||
v8::Local<v8::Object> CreateWithSender(v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> sender) {
|
||||
return mate::internal::CreateJSEvent(isolate, sender, nullptr, nullptr);
|
||||
}
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
mate::Dictionary dict(context->GetIsolate(), exports);
|
||||
dict.SetMethod("createWithSender", &CreateWithSender);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_event, Initialize)
|
||||
@@ -41,6 +41,8 @@ void Menu::AfterInit(v8::Isolate* isolate) {
|
||||
delegate.Get("isCommandIdEnabled", &is_enabled_);
|
||||
delegate.Get("isCommandIdVisible", &is_visible_);
|
||||
delegate.Get("getAcceleratorForCommandId", &get_accelerator_);
|
||||
delegate.Get("shouldRegisterAcceleratorForCommandId",
|
||||
&should_register_accelerator_);
|
||||
delegate.Get("executeCommand", &execute_command_);
|
||||
delegate.Get("menuWillShow", &menu_will_show_);
|
||||
}
|
||||
@@ -74,6 +76,12 @@ bool Menu::GetAcceleratorForCommandIdWithParams(
|
||||
return mate::ConvertFromV8(isolate(), val, accelerator);
|
||||
}
|
||||
|
||||
bool Menu::ShouldRegisterAcceleratorForCommandId(int command_id) const {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
return should_register_accelerator_.Run(GetWrapper(), command_id);
|
||||
}
|
||||
|
||||
void Menu::ExecuteCommand(int command_id, int flags) {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
@@ -155,6 +163,12 @@ base::string16 Menu::GetSublabelAt(int index) const {
|
||||
return model_->GetSublabelAt(index);
|
||||
}
|
||||
|
||||
base::string16 Menu::GetAcceleratorTextAt(int index) const {
|
||||
ui::Accelerator accelerator;
|
||||
model_->GetAcceleratorAtWithParams(index, true, &accelerator);
|
||||
return accelerator.GetShortcutText();
|
||||
}
|
||||
|
||||
bool Menu::IsItemCheckedAt(int index) const {
|
||||
return model_->IsItemCheckedAt(index);
|
||||
}
|
||||
@@ -195,6 +209,7 @@ void Menu::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("getCommandIdAt", &Menu::GetCommandIdAt)
|
||||
.SetMethod("getLabelAt", &Menu::GetLabelAt)
|
||||
.SetMethod("getSublabelAt", &Menu::GetSublabelAt)
|
||||
.SetMethod("getAcceleratorTextAt", &Menu::GetAcceleratorTextAt)
|
||||
.SetMethod("isItemCheckedAt", &Menu::IsItemCheckedAt)
|
||||
.SetMethod("isEnabledAt", &Menu::IsEnabledAt)
|
||||
.SetMethod("isVisibleAt", &Menu::IsVisibleAt)
|
||||
|
||||
@@ -51,6 +51,7 @@ class Menu : public mate::TrackableObject<Menu>,
|
||||
int command_id,
|
||||
bool use_default_accelerator,
|
||||
ui::Accelerator* accelerator) const override;
|
||||
bool ShouldRegisterAcceleratorForCommandId(int command_id) const override;
|
||||
void ExecuteCommand(int command_id, int event_flags) override;
|
||||
void MenuWillShow(ui::SimpleMenuModel* source) override;
|
||||
|
||||
@@ -91,6 +92,7 @@ class Menu : public mate::TrackableObject<Menu>,
|
||||
int GetCommandIdAt(int index) const;
|
||||
base::string16 GetLabelAt(int index) const;
|
||||
base::string16 GetSublabelAt(int index) const;
|
||||
base::string16 GetAcceleratorTextAt(int index) const;
|
||||
bool IsItemCheckedAt(int index) const;
|
||||
bool IsEnabledAt(int index) const;
|
||||
bool IsVisibleAt(int index) const;
|
||||
@@ -101,6 +103,7 @@ class Menu : public mate::TrackableObject<Menu>,
|
||||
base::Callback<bool(v8::Local<v8::Value>, int)> is_visible_;
|
||||
base::Callback<v8::Local<v8::Value>(v8::Local<v8::Value>, int, bool)>
|
||||
get_accelerator_;
|
||||
base::Callback<bool(v8::Local<v8::Value>, int)> should_register_accelerator_;
|
||||
base::Callback<void(v8::Local<v8::Value>, v8::Local<v8::Value>, int)>
|
||||
execute_command_;
|
||||
base::Callback<void(v8::Local<v8::Value>)> menu_will_show_;
|
||||
|
||||
@@ -83,6 +83,9 @@ void SystemPreferences::BuildPrototype(
|
||||
&SystemPreferences::GetAppLevelAppearance)
|
||||
.SetMethod("setAppLevelAppearance",
|
||||
&SystemPreferences::SetAppLevelAppearance)
|
||||
.SetMethod("getMediaAccessStatus",
|
||||
&SystemPreferences::GetMediaAccessStatus)
|
||||
.SetMethod("askForMediaAccess", &SystemPreferences::AskForMediaAccess)
|
||||
#endif
|
||||
.SetMethod("isInvertedColorScheme",
|
||||
&SystemPreferences::IsInvertedColorScheme)
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/api/event_emitter.h"
|
||||
#include "atom/common/promise_util.h"
|
||||
#include "base/callback.h"
|
||||
#include "base/values.h"
|
||||
#include "native_mate/handle.h"
|
||||
@@ -90,6 +91,13 @@ class SystemPreferences : public mate::EventEmitter<SystemPreferences>
|
||||
void RemoveUserDefault(const std::string& name);
|
||||
bool IsSwipeTrackingFromScrollEventsEnabled();
|
||||
|
||||
// TODO(codebytere): Write tests for these methods once we
|
||||
// are running tests on a Mojave machine
|
||||
std::string GetMediaAccessStatus(const std::string& media_type,
|
||||
mate::Arguments* args);
|
||||
v8::Local<v8::Promise> AskForMediaAccess(v8::Isolate* isolate,
|
||||
const std::string& media_type);
|
||||
|
||||
// TODO(MarshallOfSound): Write tests for these methods once we
|
||||
// are running tests on a Mojave machine
|
||||
v8::Local<v8::Value> GetEffectiveAppearance(v8::Isolate* isolate);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <map>
|
||||
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#include "atom/browser/mac/atom_application.h"
|
||||
@@ -78,6 +79,31 @@ int g_next_id = 0;
|
||||
// The map to convert |id| to |int|.
|
||||
std::map<int, id> g_id_map;
|
||||
|
||||
AVMediaType ParseMediaType(const std::string& media_type) {
|
||||
if (media_type == "camera") {
|
||||
return AVMediaTypeVideo;
|
||||
} else if (media_type == "microphone") {
|
||||
return AVMediaTypeAudio;
|
||||
} else {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
std::string ConvertAuthorizationStatus(AVAuthorizationStatusMac status) {
|
||||
switch (status) {
|
||||
case AVAuthorizationStatusNotDeterminedMac:
|
||||
return "not-determined";
|
||||
case AVAuthorizationStatusRestrictedMac:
|
||||
return "restricted";
|
||||
case AVAuthorizationStatusDeniedMac:
|
||||
return "denied";
|
||||
case AVAuthorizationStatusAuthorizedMac:
|
||||
return "granted";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void SystemPreferences::PostNotification(
|
||||
@@ -360,6 +386,47 @@ void SystemPreferences::SetUserDefault(const std::string& name,
|
||||
}
|
||||
}
|
||||
|
||||
std::string SystemPreferences::GetMediaAccessStatus(
|
||||
const std::string& media_type,
|
||||
mate::Arguments* args) {
|
||||
if (auto type = ParseMediaType(media_type)) {
|
||||
if (@available(macOS 10.14, *)) {
|
||||
return ConvertAuthorizationStatus(
|
||||
[AVCaptureDevice authorizationStatusForMediaType:type]);
|
||||
} else {
|
||||
// access always allowed pre-10.14 Mojave
|
||||
return ConvertAuthorizationStatus(AVAuthorizationStatusAuthorizedMac);
|
||||
}
|
||||
} else {
|
||||
args->ThrowError("Invalid media type");
|
||||
return std::string();
|
||||
}
|
||||
}
|
||||
|
||||
v8::Local<v8::Promise> SystemPreferences::AskForMediaAccess(
|
||||
v8::Isolate* isolate,
|
||||
const std::string& media_type) {
|
||||
scoped_refptr<util::Promise> promise = new util::Promise(isolate);
|
||||
|
||||
if (auto type = ParseMediaType(media_type)) {
|
||||
if (@available(macOS 10.14, *)) {
|
||||
[AVCaptureDevice requestAccessForMediaType:type
|
||||
completionHandler:^(BOOL granted) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
promise->Resolve(!!granted);
|
||||
});
|
||||
}];
|
||||
} else {
|
||||
// access always allowed pre-10.14 Mojave
|
||||
promise->Resolve(true);
|
||||
}
|
||||
} else {
|
||||
promise->RejectWithErrorMessage("Invalid media type");
|
||||
}
|
||||
|
||||
return promise->GetHandle();
|
||||
}
|
||||
|
||||
void SystemPreferences::RemoveUserDefault(const std::string& name) {
|
||||
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
|
||||
[defaults removeObjectForKey:base::SysUTF8ToNSString(name)];
|
||||
|
||||
@@ -691,8 +691,11 @@ void TopLevelWindow::SetBrowserView(v8::Local<v8::Value> value) {
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> TopLevelWindow::GetNativeWindowHandle() {
|
||||
gfx::AcceleratedWidget handle = window_->GetAcceleratedWidget();
|
||||
return ToBuffer(isolate(), static_cast<void*>(&handle), sizeof(handle));
|
||||
// TODO(MarshallOfSound): Replace once
|
||||
// https://chromium-review.googlesource.com/c/chromium/src/+/1253094/ has
|
||||
// landed
|
||||
auto handle = window_->GetNativeWindowHandlePointer();
|
||||
return ToBuffer(isolate(), std::get<0>(handle), std::get<1>(handle));
|
||||
}
|
||||
|
||||
void TopLevelWindow::SetProgressBar(double progress, mate::Arguments* args) {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "atom/browser/atom_browser_main_parts.h"
|
||||
#include "atom/browser/atom_javascript_dialog_manager.h"
|
||||
#include "atom/browser/atom_navigation_throttle.h"
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/browser/child_web_contents_tracker.h"
|
||||
#include "atom/browser/lib/bluetooth_chooser.h"
|
||||
#include "atom/browser/native_window.h"
|
||||
@@ -480,14 +481,25 @@ WebContents::~WebContents() {
|
||||
RenderViewDeleted(web_contents()->GetRenderViewHost());
|
||||
|
||||
if (type_ == WEB_VIEW) {
|
||||
// For webview simply destroy the WebContents immediately.
|
||||
// TODO(zcbenz): Add an internal API for webview instead of using
|
||||
// destroy(), so we don't have to add a special branch here.
|
||||
DestroyWebContents(false /* async */);
|
||||
} else if (type_ == BROWSER_WINDOW && owner_window()) {
|
||||
// For BrowserWindow we should close the window and clean up everything
|
||||
// before WebContents is destroyed.
|
||||
for (ExtendedWebContentsObserver& observer : observers_)
|
||||
observer.OnCloseContents();
|
||||
// BrowserWindow destroys WebContents asynchronously, manually emit the
|
||||
// destroyed event here.
|
||||
WebContentsDestroyed();
|
||||
} else if (Browser::Get()->is_shutting_down()) {
|
||||
// Destroy WebContents directly when app is shutting down.
|
||||
DestroyWebContents(false /* async */);
|
||||
} else {
|
||||
if (type_ == BROWSER_WINDOW && owner_window()) {
|
||||
for (ExtendedWebContentsObserver& observer : observers_)
|
||||
observer.OnCloseContents();
|
||||
} else {
|
||||
DestroyWebContents(true /* async */);
|
||||
}
|
||||
// Destroy WebContents asynchronously unless app is shutting down,
|
||||
// because destroy() might be called inside WebContents's event handler.
|
||||
DestroyWebContents(true /* async */);
|
||||
// The WebContentsDestroyed will not be called automatically because we
|
||||
// destroy the webContents in the next tick. So we have to manually
|
||||
// call it here to make sure "destroyed" event is emitted.
|
||||
@@ -814,8 +826,10 @@ void WebContents::DidChangeThemeColor(SkColor theme_color) {
|
||||
|
||||
void WebContents::DocumentLoadedInFrame(
|
||||
content::RenderFrameHost* render_frame_host) {
|
||||
if (!render_frame_host->GetParent())
|
||||
if (!render_frame_host->GetParent()) {
|
||||
is_dom_ready_ = true;
|
||||
Emit("dom-ready");
|
||||
}
|
||||
}
|
||||
|
||||
void WebContents::DidFinishLoad(content::RenderFrameHost* render_frame_host,
|
||||
@@ -842,6 +856,7 @@ void WebContents::DidFailLoad(content::RenderFrameHost* render_frame_host,
|
||||
}
|
||||
|
||||
void WebContents::DidStartLoading() {
|
||||
is_dom_ready_ = false;
|
||||
Emit("did-start-loading");
|
||||
}
|
||||
|
||||
@@ -1099,6 +1114,37 @@ void WebContents::NavigationEntryCommitted(
|
||||
details.is_same_document, details.did_replace_entry);
|
||||
}
|
||||
|
||||
void WebContents::SetBackgroundThrottling(bool allowed) {
|
||||
background_throttling_ = allowed;
|
||||
|
||||
const auto* contents = web_contents();
|
||||
if (!contents) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto* render_view_host = contents->GetRenderViewHost();
|
||||
if (!render_view_host) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto* render_process_host = render_view_host->GetProcess();
|
||||
if (!render_process_host) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* render_widget_host_impl = content::RenderWidgetHostImpl::FromID(
|
||||
render_process_host->GetID(), render_view_host->GetRoutingID());
|
||||
if (!render_widget_host_impl) {
|
||||
return;
|
||||
}
|
||||
|
||||
render_widget_host_impl->disable_hidden_ = !background_throttling_;
|
||||
|
||||
if (render_widget_host_impl->is_hidden()) {
|
||||
render_widget_host_impl->WasShown(false);
|
||||
}
|
||||
}
|
||||
|
||||
int WebContents::GetProcessID() const {
|
||||
return web_contents()->GetMainFrame()->GetProcess()->GetID();
|
||||
}
|
||||
@@ -1422,6 +1468,10 @@ bool WebContents::IsCurrentlyAudible() {
|
||||
return web_contents()->IsCurrentlyAudible();
|
||||
}
|
||||
|
||||
bool WebContents::IsDOMReady() const {
|
||||
return is_dom_ready_;
|
||||
}
|
||||
|
||||
void WebContents::Print(mate::Arguments* args) {
|
||||
PrintSettings settings = {false, false, base::string16()};
|
||||
if (args->Length() >= 1 && !args->GetNext(&settings)) {
|
||||
@@ -1889,6 +1939,13 @@ v8::Local<v8::Value> WebContents::GetLastWebPreferences(
|
||||
return mate::ConvertToV8(isolate, *web_preferences->last_preference());
|
||||
}
|
||||
|
||||
bool WebContents::IsRemoteModuleEnabled() const {
|
||||
if (auto* web_preferences = WebContentsPreferences::From(web_contents())) {
|
||||
return web_preferences->IsRemoteModuleEnabled();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> WebContents::GetOwnerBrowserWindow() const {
|
||||
if (owner_window())
|
||||
return BrowserWindow::From(isolate(), owner_window());
|
||||
@@ -1989,6 +2046,8 @@ void WebContents::BuildPrototype(v8::Isolate* isolate,
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "WebContents"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.MakeDestroyable()
|
||||
.SetMethod("setBackgroundThrottling",
|
||||
&WebContents::SetBackgroundThrottling)
|
||||
.SetMethod("getProcessId", &WebContents::GetProcessID)
|
||||
.SetMethod("getOSProcessId", &WebContents::GetOSProcessID)
|
||||
.SetMethod("equal", &WebContents::Equal)
|
||||
@@ -2019,6 +2078,7 @@ void WebContents::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("setAudioMuted", &WebContents::SetAudioMuted)
|
||||
.SetMethod("isAudioMuted", &WebContents::IsAudioMuted)
|
||||
.SetMethod("isCurrentlyAudible", &WebContents::IsCurrentlyAudible)
|
||||
.SetMethod("isDomReady", &WebContents::IsDOMReady)
|
||||
.SetMethod("undo", &WebContents::Undo)
|
||||
.SetMethod("redo", &WebContents::Redo)
|
||||
.SetMethod("cut", &WebContents::Cut)
|
||||
@@ -2030,7 +2090,7 @@ void WebContents::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("unselect", &WebContents::Unselect)
|
||||
.SetMethod("replace", &WebContents::Replace)
|
||||
.SetMethod("replaceMisspelling", &WebContents::ReplaceMisspelling)
|
||||
.SetMethod("findInPage", &WebContents::FindInPage)
|
||||
.SetMethod("_findInPage", &WebContents::FindInPage)
|
||||
.SetMethod("stopFindInPage", &WebContents::StopFindInPage)
|
||||
.SetMethod("focus", &WebContents::Focus)
|
||||
.SetMethod("isFocused", &WebContents::IsFocused)
|
||||
@@ -2059,6 +2119,7 @@ void WebContents::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("_getPreloadPath", &WebContents::GetPreloadPath)
|
||||
.SetMethod("getWebPreferences", &WebContents::GetWebPreferences)
|
||||
.SetMethod("getLastWebPreferences", &WebContents::GetLastWebPreferences)
|
||||
.SetMethod("_isRemoteModuleEnabled", &WebContents::IsRemoteModuleEnabled)
|
||||
.SetMethod("getOwnerBrowserWindow", &WebContents::GetOwnerBrowserWindow)
|
||||
.SetMethod("hasServiceWorker", &WebContents::HasServiceWorker)
|
||||
.SetMethod("unregisterServiceWorker",
|
||||
|
||||
@@ -51,7 +51,6 @@ class WebViewGuestDelegate;
|
||||
class FrameSubscriber;
|
||||
|
||||
#if BUILDFLAG(ENABLE_OSR)
|
||||
class OffScreenWebContentsView;
|
||||
class OffScreenRenderWidgetHostView;
|
||||
#endif
|
||||
|
||||
@@ -99,9 +98,22 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
// Notifies to destroy any guest web contents before destroying self.
|
||||
// Destroy the managed content::WebContents instance.
|
||||
//
|
||||
// Note: The |async| should only be |true| when users are expecting to use the
|
||||
// webContents immediately after the call. Always pass |false| if you are not
|
||||
// sure.
|
||||
// See https://github.com/electron/electron/issues/8930.
|
||||
//
|
||||
// Note: When destroying a webContents member inside a destructor, the |async|
|
||||
// should always be |false|, otherwise the destroy task might be delayed after
|
||||
// normal shutdown procedure, resulting in an assertion.
|
||||
// The normal pattern for calling this method in destructor is:
|
||||
// api_web_contents_->DestroyWebContents(!Browser::Get()->is_shutting_down())
|
||||
// See https://github.com/electron/electron/issues/15133.
|
||||
void DestroyWebContents(bool async);
|
||||
|
||||
void SetBackgroundThrottling(bool allowed);
|
||||
int GetProcessID() const;
|
||||
base::ProcessId GetOSProcessID() const;
|
||||
Type GetType() const;
|
||||
@@ -142,6 +154,7 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
void SetAudioMuted(bool muted);
|
||||
bool IsAudioMuted();
|
||||
bool IsCurrentlyAudible();
|
||||
bool IsDOMReady() const;
|
||||
void Print(mate::Arguments* args);
|
||||
std::vector<printing::PrinterBasicInfo> GetPrinterList();
|
||||
void SetEmbedder(const WebContents* embedder);
|
||||
@@ -249,6 +262,8 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
v8::Local<v8::Value> GetWebPreferences(v8::Isolate* isolate) const;
|
||||
v8::Local<v8::Value> GetLastWebPreferences(v8::Isolate* isolate) const;
|
||||
|
||||
bool IsRemoteModuleEnabled() const;
|
||||
|
||||
// Returns the owner window.
|
||||
v8::Local<v8::Value> GetOwnerBrowserWindow() const;
|
||||
|
||||
@@ -424,7 +439,7 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
uint32_t GetNextRequestId() { return ++request_id_; }
|
||||
|
||||
#if BUILDFLAG(ENABLE_OSR)
|
||||
OffScreenWebContentsView* GetOffScreenWebContentsView() const;
|
||||
OffScreenWebContentsView* GetOffScreenWebContentsView() const override;
|
||||
OffScreenRenderWidgetHostView* GetOffScreenRenderWidgetHostView() const;
|
||||
#endif
|
||||
|
||||
@@ -491,6 +506,9 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
// Whether to enable devtools.
|
||||
bool enable_devtools_ = true;
|
||||
|
||||
// Whether page's document is ready.
|
||||
bool is_dom_ready_ = false;
|
||||
|
||||
// Observers of this WebContents.
|
||||
base::ObserverList<ExtendedWebContentsObserver> observers_;
|
||||
|
||||
|
||||
@@ -17,15 +17,23 @@ namespace atom {
|
||||
namespace api {
|
||||
|
||||
OffScreenWebContentsView* WebContents::GetOffScreenWebContentsView() const {
|
||||
const auto* impl =
|
||||
static_cast<const content::WebContentsImpl*>(web_contents());
|
||||
return static_cast<OffScreenWebContentsView*>(impl->GetView());
|
||||
if (IsOffScreen()) {
|
||||
const auto* impl =
|
||||
static_cast<const content::WebContentsImpl*>(web_contents());
|
||||
return static_cast<OffScreenWebContentsView*>(impl->GetView());
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
OffScreenRenderWidgetHostView* WebContents::GetOffScreenRenderWidgetHostView()
|
||||
const {
|
||||
return static_cast<OffScreenRenderWidgetHostView*>(
|
||||
web_contents()->GetRenderWidgetHostView());
|
||||
if (IsOffScreen()) {
|
||||
return static_cast<OffScreenRenderWidgetHostView*>(
|
||||
web_contents()->GetRenderWidgetHostView());
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "atom/browser/api/atom_api_web_contents_view.h"
|
||||
|
||||
#include "atom/browser/api/atom_api_web_contents.h"
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/common/api/constructor.h"
|
||||
#include "brightray/browser/inspectable_web_contents_view.h"
|
||||
#include "content/public/browser/web_contents_user_data.h"
|
||||
@@ -64,8 +65,11 @@ WebContentsView::WebContentsView(v8::Isolate* isolate,
|
||||
}
|
||||
|
||||
WebContentsView::~WebContentsView() {
|
||||
if (api_web_contents_)
|
||||
api_web_contents_->DestroyWebContents(false /* async */);
|
||||
if (api_web_contents_) { // destroy() is called
|
||||
// Destroy WebContents asynchronously unless app is shutting down,
|
||||
// because destroy() might be called inside WebContents's event handler.
|
||||
api_web_contents_->DestroyWebContents(!Browser::Get()->is_shutting_down());
|
||||
}
|
||||
}
|
||||
|
||||
void WebContentsView::WebContentsDestroyed() {
|
||||
|
||||
@@ -26,11 +26,12 @@ GPUInfoManager::~GPUInfoManager() {
|
||||
|
||||
// Based on
|
||||
// https://chromium.googlesource.com/chromium/src.git/+/69.0.3497.106/content/browser/gpu/gpu_data_manager_impl_private.cc#838
|
||||
bool GPUInfoManager::NeedsCompleteGpuInfoCollection() {
|
||||
#if defined(OS_WIN)
|
||||
const auto& gpu_info = gpu_data_manager_->GetGPUInfo();
|
||||
return (gpu_info.dx_diagnostics.values.empty() &&
|
||||
gpu_info.dx_diagnostics.children.empty());
|
||||
bool GPUInfoManager::NeedsCompleteGpuInfoCollection() const {
|
||||
#if defined(OS_MACOSX)
|
||||
return gpu_data_manager_->GetGPUInfo().gl_vendor.empty();
|
||||
#elif defined(OS_WIN)
|
||||
return (gpu_data_manager_->GetGPUInfo().dx_diagnostics.values.empty() &&
|
||||
gpu_data_manager_->GetGPUInfo().dx_diagnostics.children.empty());
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
|
||||
@@ -24,7 +24,7 @@ class GPUInfoManager : public content::GpuDataManagerObserver {
|
||||
|
||||
GPUInfoManager();
|
||||
~GPUInfoManager() override;
|
||||
bool NeedsCompleteGpuInfoCollection();
|
||||
bool NeedsCompleteGpuInfoCollection() const;
|
||||
void FetchCompleteInfo(scoped_refptr<util::Promise> promise);
|
||||
void FetchBasicInfo(scoped_refptr<util::Promise> promise);
|
||||
void OnGpuInfoUpdate() override;
|
||||
|
||||
@@ -172,28 +172,34 @@ bool AtomBrowserClient::ShouldCreateNewSiteInstance(
|
||||
void AtomBrowserClient::AddProcessPreferences(
|
||||
int process_id,
|
||||
AtomBrowserClient::ProcessPreferences prefs) {
|
||||
base::AutoLock auto_lock(process_preferences_lock_);
|
||||
process_preferences_[process_id] = prefs;
|
||||
}
|
||||
|
||||
void AtomBrowserClient::RemoveProcessPreferences(int process_id) {
|
||||
base::AutoLock auto_lock(process_preferences_lock_);
|
||||
process_preferences_.erase(process_id);
|
||||
}
|
||||
|
||||
bool AtomBrowserClient::IsProcessObserved(int process_id) {
|
||||
base::AutoLock auto_lock(process_preferences_lock_);
|
||||
return process_preferences_.find(process_id) != process_preferences_.end();
|
||||
}
|
||||
|
||||
bool AtomBrowserClient::IsRendererSandboxed(int process_id) {
|
||||
base::AutoLock auto_lock(process_preferences_lock_);
|
||||
auto it = process_preferences_.find(process_id);
|
||||
return it != process_preferences_.end() && it->second.sandbox;
|
||||
}
|
||||
|
||||
bool AtomBrowserClient::RendererUsesNativeWindowOpen(int process_id) {
|
||||
base::AutoLock auto_lock(process_preferences_lock_);
|
||||
auto it = process_preferences_.find(process_id);
|
||||
return it != process_preferences_.end() && it->second.native_window_open;
|
||||
}
|
||||
|
||||
bool AtomBrowserClient::RendererDisablesPopups(int process_id) {
|
||||
base::AutoLock auto_lock(process_preferences_lock_);
|
||||
auto it = process_preferences_.find(process_id);
|
||||
return it != process_preferences_.end() && it->second.disable_popups;
|
||||
}
|
||||
@@ -217,6 +223,8 @@ void AtomBrowserClient::RenderProcessWillLaunch(
|
||||
prefs.native_window_open =
|
||||
web_preferences->IsEnabled(options::kNativeWindowOpen);
|
||||
prefs.disable_popups = web_preferences->IsEnabled("disablePopups");
|
||||
prefs.web_security = web_preferences->IsEnabled(options::kWebSecurity,
|
||||
true /* default value */);
|
||||
}
|
||||
AddProcessPreferences(host->GetID(), prefs);
|
||||
// ensure the ProcessPreferences is removed later
|
||||
@@ -656,4 +664,11 @@ AtomBrowserClient::CreateThrottlesForNavigation(
|
||||
return throttles;
|
||||
}
|
||||
|
||||
bool AtomBrowserClient::ShouldBypassCORB(int render_process_id) {
|
||||
// This is called on the network thread.
|
||||
base::AutoLock auto_lock(process_preferences_lock_);
|
||||
auto it = process_preferences_.find(render_process_id);
|
||||
return it != process_preferences_.end() && !it->second.web_security;
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -11,7 +11,9 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/synchronization/lock.h"
|
||||
#include "brightray/browser/browser_client.h"
|
||||
#include "content/public/browser/content_browser_client.h"
|
||||
#include "content/public/browser/render_process_host_observer.h"
|
||||
#include "net/ssl/client_cert_identity.h"
|
||||
|
||||
@@ -124,6 +126,7 @@ class AtomBrowserClient : public brightray::BrowserClient,
|
||||
void WebNotificationAllowed(
|
||||
int render_process_id,
|
||||
const base::Callback<void(bool, bool)>& callback) override;
|
||||
bool ShouldBypassCORB(int render_process_id) override;
|
||||
|
||||
// content::RenderProcessHostObserver:
|
||||
void RenderProcessHostDestroyed(content::RenderProcessHost* host) override;
|
||||
@@ -145,6 +148,7 @@ class AtomBrowserClient : public brightray::BrowserClient,
|
||||
bool sandbox = false;
|
||||
bool native_window_open = false;
|
||||
bool disable_popups = false;
|
||||
bool web_security = true;
|
||||
};
|
||||
|
||||
bool ShouldCreateNewSiteInstance(content::RenderFrameHost* render_frame_host,
|
||||
@@ -161,7 +165,6 @@ class AtomBrowserClient : public brightray::BrowserClient,
|
||||
// pending_render_process => web contents.
|
||||
std::map<int, content::WebContents*> pending_processes_;
|
||||
|
||||
std::map<int, ProcessPreferences> process_preferences_;
|
||||
std::map<int, base::ProcessId> render_process_host_pids_;
|
||||
|
||||
// list of site per affinity. weak_ptr to prevent instance locking
|
||||
@@ -172,6 +175,9 @@ class AtomBrowserClient : public brightray::BrowserClient,
|
||||
|
||||
Delegate* delegate_ = nullptr;
|
||||
|
||||
base::Lock process_preferences_lock_;
|
||||
std::map<int, ProcessPreferences> process_preferences_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomBrowserClient);
|
||||
};
|
||||
|
||||
|
||||
@@ -253,6 +253,7 @@ void AtomBrowserMainParts::PreMainMessageLoopRun() {
|
||||
}
|
||||
|
||||
bool AtomBrowserMainParts::MainMessageLoopRun(int* result_code) {
|
||||
js_env_->OnMessageLoopCreated();
|
||||
exit_code_ = result_code;
|
||||
return brightray::BrowserMainParts::MainMessageLoopRun(result_code);
|
||||
}
|
||||
|
||||
@@ -217,14 +217,74 @@ Browser::LoginItemSettings Browser::GetLoginItemSettings(
|
||||
return settings;
|
||||
}
|
||||
|
||||
// copied from GetLoginItemForApp in base/mac/mac_util.mm
|
||||
LSSharedFileListItemRef GetLoginItemForApp() {
|
||||
base::ScopedCFTypeRef<LSSharedFileListRef> login_items(
|
||||
LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL));
|
||||
if (!login_items.get()) {
|
||||
LOG(ERROR) << "Couldn't get a Login Items list.";
|
||||
return NULL;
|
||||
}
|
||||
base::scoped_nsobject<NSArray> login_items_array(
|
||||
base::mac::CFToNSCast(LSSharedFileListCopySnapshot(login_items, NULL)));
|
||||
NSURL* url = [NSURL fileURLWithPath:[base::mac::MainBundle() bundlePath]];
|
||||
for (NSUInteger i = 0; i < [login_items_array count]; ++i) {
|
||||
LSSharedFileListItemRef item =
|
||||
reinterpret_cast<LSSharedFileListItemRef>(login_items_array[i]);
|
||||
CFURLRef item_url_ref = NULL;
|
||||
if (LSSharedFileListItemResolve(item, 0, &item_url_ref, NULL) == noErr &&
|
||||
item_url_ref) {
|
||||
base::ScopedCFTypeRef<CFURLRef> item_url(item_url_ref);
|
||||
if (CFEqual(item_url, url)) {
|
||||
CFRetain(item);
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void RemoveFromLoginItems() {
|
||||
base::ScopedCFTypeRef<LSSharedFileListRef> list(
|
||||
LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL));
|
||||
if (!list) {
|
||||
LOG(ERROR) << "Unable to access shared file list";
|
||||
return;
|
||||
}
|
||||
|
||||
if (GetLoginItemForApp() != NULL) {
|
||||
base::scoped_nsobject<NSArray> login_items_array(
|
||||
base::mac::CFToNSCast(LSSharedFileListCopySnapshot(list, NULL)));
|
||||
|
||||
if (!login_items_array) {
|
||||
LOG(ERROR) << "No items in list of auto-loaded apps";
|
||||
return;
|
||||
}
|
||||
|
||||
for (NSUInteger i = 0; i < [login_items_array count]; ++i) {
|
||||
LSSharedFileListItemRef item =
|
||||
reinterpret_cast<LSSharedFileListItemRef>(login_items_array[i]);
|
||||
CFURLRef url_ref = NULL;
|
||||
if (LSSharedFileListItemResolve(item, 0, &url_ref, NULL) == noErr &&
|
||||
item) {
|
||||
base::ScopedCFTypeRef<CFURLRef> url(url_ref);
|
||||
if ([[base::mac::CFToNSCast(url.get()) path]
|
||||
hasPrefix:[[NSBundle mainBundle] bundlePath]])
|
||||
LSSharedFileListItemRemove(list, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Browser::SetLoginItemSettings(LoginItemSettings settings) {
|
||||
#if defined(MAS_BUILD)
|
||||
platform_util::SetLoginItemEnabled(settings.open_at_login);
|
||||
#else
|
||||
if (settings.open_at_login)
|
||||
base::mac::AddToLoginItems(settings.open_as_hidden);
|
||||
else
|
||||
base::mac::RemoveFromLoginItems();
|
||||
else {
|
||||
RemoveFromLoginItems();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "components/prefs/scoped_user_pref_update.h"
|
||||
#include "components/security_state/content/content_utils.h"
|
||||
#include "components/security_state/core/security_state.h"
|
||||
#include "content/browser/renderer_host/render_widget_host_view_base.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/child_process_security_policy.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
@@ -39,6 +40,10 @@
|
||||
#include "content/public/browser/security_style_explanations.h"
|
||||
#include "storage/browser/fileapi/isolated_context.h"
|
||||
|
||||
#if BUILDFLAG(ENABLE_OSR)
|
||||
#include "atom/browser/osr/osr_web_contents_view.h"
|
||||
#endif
|
||||
|
||||
using content::BrowserThread;
|
||||
|
||||
namespace atom {
|
||||
@@ -201,6 +206,11 @@ void CommonWebContentsDelegate::SetOwnerWindow(
|
||||
web_contents->RemoveUserData(
|
||||
NativeWindowRelay::kNativeWindowRelayUserDataKey);
|
||||
}
|
||||
#if BUILDFLAG(ENABLE_OSR)
|
||||
auto* osr_wcv = GetOffScreenWebContentsView();
|
||||
if (osr_wcv)
|
||||
osr_wcv->SetNativeWindow(owner_window);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CommonWebContentsDelegate::ResetManagedWebContents(bool async) {
|
||||
@@ -236,6 +246,13 @@ content::WebContents* CommonWebContentsDelegate::GetDevToolsWebContents()
|
||||
return web_contents_->GetDevToolsWebContents();
|
||||
}
|
||||
|
||||
#if BUILDFLAG(ENABLE_OSR)
|
||||
OffScreenWebContentsView*
|
||||
CommonWebContentsDelegate::GetOffScreenWebContentsView() const {
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
content::WebContents* CommonWebContentsDelegate::OpenURLFromTab(
|
||||
content::WebContents* source,
|
||||
const content::OpenURLParams& params) {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "brightray/browser/inspectable_web_contents_view_delegate.h"
|
||||
#include "chrome/browser/devtools/devtools_file_system_indexer.h"
|
||||
#include "content/public/browser/web_contents_delegate.h"
|
||||
#include "electron/buildflags/buildflags.h"
|
||||
|
||||
#if defined(TOOLKIT_VIEWS) && !defined(OS_MACOSX)
|
||||
#include "atom/browser/ui/autofill_popup.h"
|
||||
@@ -31,6 +32,10 @@ class AtomBrowserContext;
|
||||
class NativeWindow;
|
||||
class WebDialogHelper;
|
||||
|
||||
#if BUILDFLAG(ENABLE_OSR)
|
||||
class OffScreenWebContentsView;
|
||||
#endif
|
||||
|
||||
class CommonWebContentsDelegate
|
||||
: public content::WebContentsDelegate,
|
||||
public brightray::InspectableWebContentsDelegate,
|
||||
@@ -65,6 +70,10 @@ class CommonWebContentsDelegate
|
||||
bool is_html_fullscreen() const { return html_fullscreen_; }
|
||||
|
||||
protected:
|
||||
#if BUILDFLAG(ENABLE_OSR)
|
||||
virtual OffScreenWebContentsView* GetOffScreenWebContentsView() const;
|
||||
#endif
|
||||
|
||||
// content::WebContentsDelegate:
|
||||
content::WebContents* OpenURLFromTab(
|
||||
content::WebContents* source,
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/microtasks_runner.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/message_loop/message_loop.h"
|
||||
#include "base/task_scheduler/initialization_util.h"
|
||||
@@ -62,7 +63,15 @@ v8::Isolate* JavascriptEnvironment::Initialize(uv_loop_t* event_loop) {
|
||||
return isolate;
|
||||
}
|
||||
|
||||
void JavascriptEnvironment::OnMessageLoopCreated() {
|
||||
DCHECK(!microtasks_runner_);
|
||||
microtasks_runner_.reset(new MicrotasksRunner(isolate()));
|
||||
base::MessageLoopCurrent::Get()->AddTaskObserver(microtasks_runner_.get());
|
||||
}
|
||||
|
||||
void JavascriptEnvironment::OnMessageLoopDestroying() {
|
||||
DCHECK(microtasks_runner_);
|
||||
base::MessageLoopCurrent::Get()->RemoveTaskObserver(microtasks_runner_.get());
|
||||
platform_->UnregisterIsolate(isolate_);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#ifndef ATOM_BROWSER_JAVASCRIPT_ENVIRONMENT_H_
|
||||
#define ATOM_BROWSER_JAVASCRIPT_ENVIRONMENT_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "base/macros.h"
|
||||
#include "gin/public/isolate_holder.h"
|
||||
#include "uv.h" // NOLINT(build/include)
|
||||
@@ -16,12 +18,14 @@ class MultiIsolatePlatform;
|
||||
|
||||
namespace atom {
|
||||
|
||||
class MicrotasksRunner;
|
||||
// Manage the V8 isolate and context automatically.
|
||||
class JavascriptEnvironment {
|
||||
public:
|
||||
explicit JavascriptEnvironment(uv_loop_t* event_loop);
|
||||
~JavascriptEnvironment();
|
||||
|
||||
void OnMessageLoopCreated();
|
||||
void OnMessageLoopDestroying();
|
||||
|
||||
node::MultiIsolatePlatform* platform() const { return platform_; }
|
||||
@@ -43,6 +47,8 @@ class JavascriptEnvironment {
|
||||
v8::Global<v8::Context> context_;
|
||||
v8::Context::Scope context_scope_;
|
||||
|
||||
std::unique_ptr<MicrotasksRunner> microtasks_runner_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(JavascriptEnvironment);
|
||||
};
|
||||
|
||||
|
||||
@@ -63,16 +63,17 @@ void BluetoothChooser::ShowDiscoveryState(DiscoveryState state) {
|
||||
event_handler_.Run(Event::CANCELLED, "");
|
||||
break;
|
||||
case DiscoveryState::IDLE:
|
||||
if (device_list_.empty()) {
|
||||
if (device_map_.empty()) {
|
||||
auto event =
|
||||
++num_retries_ > kMaxScanRetries ? Event::CANCELLED : Event::RESCAN;
|
||||
event_handler_.Run(event, "");
|
||||
} else {
|
||||
bool prevent_default = api_web_contents_->Emit(
|
||||
"select-bluetooth-device", device_list_,
|
||||
"select-bluetooth-device", GetDeviceList(),
|
||||
base::Bind(&OnDeviceChosen, event_handler_));
|
||||
if (!prevent_default) {
|
||||
auto device_id = device_list_[0].device_id;
|
||||
auto it = device_map_.begin();
|
||||
auto device_id = it->first;
|
||||
event_handler_.Run(Event::SELECTED, device_id);
|
||||
}
|
||||
}
|
||||
@@ -88,29 +89,40 @@ void BluetoothChooser::AddOrUpdateDevice(const std::string& device_id,
|
||||
bool is_gatt_connected,
|
||||
bool is_paired,
|
||||
int signal_strength_level) {
|
||||
DeviceInfo info = {device_id, device_name};
|
||||
device_list_.push_back(info);
|
||||
|
||||
// Emit a select-bluetooth-device handler to allow for user to listen for
|
||||
// bluetooth device found.
|
||||
bool prevent_default =
|
||||
api_web_contents_->Emit("select-bluetooth-device", device_list_,
|
||||
base::Bind(&OnDeviceChosen, event_handler_));
|
||||
|
||||
// If emit not implimented select first device that matches the filters
|
||||
// provided.
|
||||
if (!prevent_default) {
|
||||
event_handler_.Run(Event::SELECTED, device_id);
|
||||
bool changed = false;
|
||||
auto entry = device_map_.find(device_id);
|
||||
if (entry == device_map_.end()) {
|
||||
device_map_[device_id] = device_name;
|
||||
changed = true;
|
||||
} else if (should_update_name) {
|
||||
entry->second = device_name;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
void BluetoothChooser::RemoveDevice(const std::string& device_id) {
|
||||
for (auto it = device_list_.begin(); it != device_list_.end(); ++it) {
|
||||
if (it->device_id == device_id) {
|
||||
device_list_.erase(it);
|
||||
return;
|
||||
if (changed) {
|
||||
// Emit a select-bluetooth-device handler to allow for user to listen for
|
||||
// bluetooth device found.
|
||||
bool prevent_default =
|
||||
api_web_contents_->Emit("select-bluetooth-device", GetDeviceList(),
|
||||
base::Bind(&OnDeviceChosen, event_handler_));
|
||||
|
||||
// If emit not implimented select first device that matches the filters
|
||||
// provided.
|
||||
if (!prevent_default) {
|
||||
event_handler_.Run(Event::SELECTED, device_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<atom::BluetoothChooser::DeviceInfo>
|
||||
BluetoothChooser::GetDeviceList() {
|
||||
std::vector<atom::BluetoothChooser::DeviceInfo> vec;
|
||||
for (const auto& it : device_map_) {
|
||||
DeviceInfo info = {it.first, it.second};
|
||||
vec.push_back(info);
|
||||
}
|
||||
|
||||
return vec;
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#ifndef ATOM_BROWSER_LIB_BLUETOOTH_CHOOSER_H_
|
||||
#define ATOM_BROWSER_LIB_BLUETOOTH_CHOOSER_H_
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -33,10 +34,10 @@ class BluetoothChooser : public content::BluetoothChooser {
|
||||
bool is_gatt_connected,
|
||||
bool is_paired,
|
||||
int signal_strength_level) override;
|
||||
void RemoveDevice(const std::string& device_id);
|
||||
std::vector<DeviceInfo> GetDeviceList();
|
||||
|
||||
private:
|
||||
std::vector<DeviceInfo> device_list_;
|
||||
std::map<std::string, base::string16> device_map_;
|
||||
api::WebContents* api_web_contents_;
|
||||
EventHandler event_handler_;
|
||||
int num_retries_ = 0;
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
#include "base/mac/scoped_nsobject.h"
|
||||
#include "base/mac/scoped_sending_event.h"
|
||||
|
||||
// Forward Declare Appareance APIs
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
|
||||
// Forward Declare Appearance APIs
|
||||
@interface NSApplication (HighSierraSDK)
|
||||
@property(copy, readonly)
|
||||
NSAppearance* effectiveAppearance API_AVAILABLE(macosx(10.14));
|
||||
@@ -14,6 +16,27 @@
|
||||
- (void)setAppearance:(NSAppearance*)appearance API_AVAILABLE(macosx(10.14));
|
||||
@end
|
||||
|
||||
// forward declare Access APIs
|
||||
typedef NSString* AVMediaType NS_EXTENSIBLE_STRING_ENUM;
|
||||
|
||||
AVF_EXPORT AVMediaType const AVMediaTypeVideo;
|
||||
AVF_EXPORT AVMediaType const AVMediaTypeAudio;
|
||||
|
||||
typedef NS_ENUM(NSInteger, AVAuthorizationStatusMac) {
|
||||
AVAuthorizationStatusNotDeterminedMac = 0,
|
||||
AVAuthorizationStatusRestrictedMac = 1,
|
||||
AVAuthorizationStatusDeniedMac = 2,
|
||||
AVAuthorizationStatusAuthorizedMac = 3,
|
||||
};
|
||||
|
||||
@interface AVCaptureDevice (MojaveSDK)
|
||||
+ (void)requestAccessForMediaType:(AVMediaType)mediaType
|
||||
completionHandler:(void (^)(BOOL granted))handler
|
||||
API_AVAILABLE(macosx(10.14));
|
||||
+ (AVAuthorizationStatusMac)authorizationStatusForMediaType:
|
||||
(AVMediaType)mediaType API_AVAILABLE(macosx(10.14));
|
||||
@end
|
||||
|
||||
extern "C" {
|
||||
#if !defined(MAC_OS_X_VERSION_10_14) || \
|
||||
MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_14
|
||||
|
||||
@@ -167,7 +167,7 @@ void FinishTransactionByDate(const std::string& date) {
|
||||
std::string GetReceiptURL() {
|
||||
NSURL* receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
|
||||
if (receiptURL != nil) {
|
||||
return [[receiptURL absoluteString] UTF8String];
|
||||
return std::string([[receiptURL path] UTF8String]);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
|
||||
20
atom/browser/microtasks_runner.cc
Normal file
20
atom/browser/microtasks_runner.cc
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
// Copyright (c) 2018 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/microtasks_runner.h"
|
||||
#include "v8/include/v8.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
MicrotasksRunner::MicrotasksRunner(v8::Isolate* isolate) : isolate_(isolate) {}
|
||||
|
||||
void MicrotasksRunner::WillProcessTask(const base::PendingTask& pending_task) {}
|
||||
|
||||
void MicrotasksRunner::DidProcessTask(const base::PendingTask& pending_task) {
|
||||
v8::Isolate::Scope scope(isolate_);
|
||||
v8::MicrotasksScope::PerformCheckpoint(isolate_);
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
36
atom/browser/microtasks_runner.h
Normal file
36
atom/browser/microtasks_runner.h
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) 2018 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_MICROTASKS_RUNNER_H_
|
||||
#define ATOM_BROWSER_MICROTASKS_RUNNER_H_
|
||||
|
||||
#include "base/message_loop/message_loop.h"
|
||||
|
||||
namespace v8 {
|
||||
class Isolate;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
// Microtasks like promise resolution, are run at the end of the current
|
||||
// task. This class implements a task observer that runs tells v8 to run them.
|
||||
// Microtasks runner implementation is based on the EndOfTaskRunner in blink.
|
||||
// Node follows the kExplicit MicrotasksPolicy, and we do the same in browser
|
||||
// process. Hence, we need to have this task observer to flush the queued
|
||||
// microtasks.
|
||||
class MicrotasksRunner : public base::MessageLoop::TaskObserver {
|
||||
public:
|
||||
explicit MicrotasksRunner(v8::Isolate* isolate);
|
||||
|
||||
// base::MessageLoop::TaskObserver
|
||||
void WillProcessTask(const base::PendingTask& pending_task) override;
|
||||
void DidProcessTask(const base::PendingTask& pending_task) override;
|
||||
|
||||
private:
|
||||
v8::Isolate* isolate_;
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_MICROTASKS_RUNNER_H_
|
||||
@@ -29,6 +29,7 @@ void NativeBrowserViewViews::SetBounds(const gfx::Rect& bounds) {
|
||||
void NativeBrowserViewViews::SetBackgroundColor(SkColor color) {
|
||||
auto* view = GetInspectableWebContentsView()->GetView();
|
||||
view->SetBackground(views::CreateSolidBackground(color));
|
||||
view->SchedulePaint();
|
||||
}
|
||||
|
||||
// static
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/browser/native_window_observer.h"
|
||||
@@ -152,6 +153,7 @@ class NativeWindow : public base::SupportsUserData,
|
||||
virtual gfx::NativeView GetNativeView() const = 0;
|
||||
virtual gfx::NativeWindow GetNativeWindow() const = 0;
|
||||
virtual gfx::AcceleratedWidget GetAcceleratedWidget() const = 0;
|
||||
virtual std::tuple<void*, int> GetNativeWindowHandlePointer() const = 0;
|
||||
|
||||
// Taskbar/Dock APIs.
|
||||
enum ProgressState {
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/browser/native_window.h"
|
||||
@@ -106,6 +107,7 @@ class NativeWindowMac : public NativeWindow {
|
||||
gfx::NativeView GetNativeView() const override;
|
||||
gfx::NativeWindow GetNativeWindow() const override;
|
||||
gfx::AcceleratedWidget GetAcceleratedWidget() const override;
|
||||
std::tuple<void*, int> GetNativeWindowHandlePointer() const override;
|
||||
void SetProgressBar(double progress, const ProgressState state) override;
|
||||
void SetOverlayIcon(const gfx::Image& overlay,
|
||||
const std::string& description) override;
|
||||
|
||||
@@ -76,9 +76,6 @@
|
||||
NSButton* miniaturize_button =
|
||||
[NSWindow standardWindowButton:NSWindowMiniaturizeButton
|
||||
forStyleMask:NSWindowStyleMaskTitled];
|
||||
NSButton* zoom_button =
|
||||
[NSWindow standardWindowButton:NSWindowZoomButton
|
||||
forStyleMask:NSWindowStyleMaskTitled];
|
||||
|
||||
CGFloat x = 0;
|
||||
const CGFloat space_between = 20;
|
||||
@@ -91,11 +88,7 @@
|
||||
x += space_between;
|
||||
[self addSubview:miniaturize_button];
|
||||
|
||||
[zoom_button setFrameOrigin:NSMakePoint(x, 0)];
|
||||
x += space_between;
|
||||
[self addSubview:zoom_button];
|
||||
|
||||
const auto last_button_frame = zoom_button.frame;
|
||||
const auto last_button_frame = miniaturize_button.frame;
|
||||
[self setFrameSize:NSMakeSize(last_button_frame.origin.x +
|
||||
last_button_frame.size.width,
|
||||
last_button_frame.size.height)];
|
||||
@@ -341,6 +334,9 @@ NativeWindowMac::NativeWindowMac(const mate::Dictionary& options,
|
||||
if (!useStandardWindow || transparent() || !has_frame()) {
|
||||
styleMask |= NSTexturedBackgroundWindowMask;
|
||||
}
|
||||
if (resizable_) {
|
||||
styleMask |= NSResizableWindowMask;
|
||||
}
|
||||
|
||||
// Create views::Widget and assign window_ with it.
|
||||
// TODO(zcbenz): Get rid of the window_ in future.
|
||||
@@ -514,6 +510,11 @@ void NativeWindowMac::Close() {
|
||||
}
|
||||
|
||||
void NativeWindowMac::CloseImmediately() {
|
||||
// Retain the child window before closing it. If the last reference to the
|
||||
// NSWindow goes away inside -[NSWindow close], then bad stuff can happen.
|
||||
// See e.g. http://crbug.com/616701.
|
||||
base::scoped_nsobject<NSWindow> child_window(window_,
|
||||
base::scoped_policy::RETAIN);
|
||||
[window_ close];
|
||||
}
|
||||
|
||||
@@ -585,13 +586,13 @@ bool NativeWindowMac::IsEnabled() {
|
||||
|
||||
void NativeWindowMac::SetEnabled(bool enable) {
|
||||
if (enable) {
|
||||
[window_ endSheet:[window_ attachedSheet]];
|
||||
} else {
|
||||
[window_ beginSheet:window_
|
||||
completionHandler:^(NSModalResponse returnCode) {
|
||||
NSLog(@"modal enabled");
|
||||
return;
|
||||
}];
|
||||
} else {
|
||||
[window_ endSheet:[window_ attachedSheet]];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1101,6 +1102,11 @@ gfx::AcceleratedWidget NativeWindowMac::GetAcceleratedWidget() const {
|
||||
return gfx::kNullAcceleratedWidget;
|
||||
}
|
||||
|
||||
std::tuple<void*, int> NativeWindowMac::GetNativeWindowHandlePointer() const {
|
||||
NSView* view = [window_ contentView];
|
||||
return std::make_tuple(static_cast<void*>(view), sizeof(view));
|
||||
}
|
||||
|
||||
void NativeWindowMac::SetProgressBar(double progress,
|
||||
const NativeWindow::ProgressState state) {
|
||||
NSDockTile* dock_tile = [NSApp dockTile];
|
||||
@@ -1394,6 +1400,8 @@ void NativeWindowMac::AddContentViewLayers() {
|
||||
if (title_bar_style_ == CUSTOM_BUTTONS_ON_HOVER) {
|
||||
buttons_view_.reset(
|
||||
[[CustomWindowButtonView alloc] initWithFrame:NSZeroRect]);
|
||||
// NSWindowStyleMaskFullSizeContentView does not work with zoom button
|
||||
SetFullScreenable(false);
|
||||
[[window_ contentView] addSubview:buttons_view_];
|
||||
} else {
|
||||
if (title_bar_style_ != NORMAL) {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#endif
|
||||
|
||||
#include <memory>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@@ -344,7 +345,7 @@ bool NativeWindowViews::IsFocused() {
|
||||
void NativeWindowViews::Show() {
|
||||
if (is_modal() && NativeWindow::parent() &&
|
||||
!widget()->native_widget_private()->IsVisible())
|
||||
NativeWindow::parent()->SetEnabled(false);
|
||||
static_cast<NativeWindowViews*>(parent())->IncrementChildModals();
|
||||
|
||||
widget()->native_widget_private()->ShowWithWindowState(GetRestoredState());
|
||||
|
||||
@@ -369,7 +370,7 @@ void NativeWindowViews::ShowInactive() {
|
||||
|
||||
void NativeWindowViews::Hide() {
|
||||
if (is_modal() && NativeWindow::parent())
|
||||
NativeWindow::parent()->SetEnabled(true);
|
||||
static_cast<NativeWindowViews*>(parent())->DecrementChildModals();
|
||||
|
||||
widget()->Hide();
|
||||
|
||||
@@ -393,16 +394,34 @@ bool NativeWindowViews::IsEnabled() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void NativeWindowViews::IncrementChildModals() {
|
||||
num_modal_children_++;
|
||||
SetEnabledInternal(ShouldBeEnabled());
|
||||
}
|
||||
|
||||
void NativeWindowViews::DecrementChildModals() {
|
||||
if (num_modal_children_ > 0) {
|
||||
num_modal_children_--;
|
||||
}
|
||||
SetEnabledInternal(ShouldBeEnabled());
|
||||
}
|
||||
|
||||
void NativeWindowViews::SetEnabled(bool enable) {
|
||||
// Handle multiple calls of SetEnabled correctly.
|
||||
if (enable) {
|
||||
--disable_count_;
|
||||
if (disable_count_ != 0)
|
||||
return;
|
||||
} else {
|
||||
++disable_count_;
|
||||
if (disable_count_ != 1)
|
||||
return;
|
||||
if (enable != is_enabled_) {
|
||||
is_enabled_ = enable;
|
||||
SetEnabledInternal(ShouldBeEnabled());
|
||||
}
|
||||
}
|
||||
|
||||
bool NativeWindowViews::ShouldBeEnabled() {
|
||||
return is_enabled_ && (num_modal_children_ == 0);
|
||||
}
|
||||
|
||||
void NativeWindowViews::SetEnabledInternal(bool enable) {
|
||||
if (enable && IsEnabled()) {
|
||||
return;
|
||||
} else if (!enable && !IsEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(OS_WIN)
|
||||
@@ -881,14 +900,18 @@ void NativeWindowViews::SetFocusable(bool focusable) {
|
||||
|
||||
void NativeWindowViews::SetMenu(AtomMenuModel* menu_model) {
|
||||
#if defined(USE_X11)
|
||||
if (menu_model == nullptr)
|
||||
if (menu_model == nullptr) {
|
||||
global_menu_bar_.reset();
|
||||
root_view_->UnregisterAcceleratorsWithFocusManager();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!global_menu_bar_ && ShouldUseGlobalMenuBar())
|
||||
global_menu_bar_.reset(new GlobalMenuBarX11(this));
|
||||
|
||||
// Use global application menu bar when possible.
|
||||
if (global_menu_bar_ && global_menu_bar_->IsServerStarted()) {
|
||||
root_view_->RegisterAcceleratorsWithFocusManager(menu_model);
|
||||
global_menu_bar_->SetMenu(menu_model);
|
||||
return;
|
||||
}
|
||||
@@ -1034,6 +1057,11 @@ gfx::AcceleratedWidget NativeWindowViews::GetAcceleratedWidget() const {
|
||||
return GetNativeWindow()->GetHost()->GetAcceleratedWidget();
|
||||
}
|
||||
|
||||
std::tuple<void*, int> NativeWindowViews::GetNativeWindowHandlePointer() const {
|
||||
gfx::AcceleratedWidget handle = GetAcceleratedWidget();
|
||||
return std::make_tuple(static_cast<void*>(&handle), sizeof(handle));
|
||||
}
|
||||
|
||||
gfx::Rect NativeWindowViews::ContentBoundsToWindowBounds(
|
||||
const gfx::Rect& bounds) const {
|
||||
if (!has_frame())
|
||||
@@ -1161,10 +1189,10 @@ void NativeWindowViews::OnWidgetBoundsChanged(views::Widget* changed_widget,
|
||||
}
|
||||
|
||||
void NativeWindowViews::DeleteDelegate() {
|
||||
if (is_modal() && NativeWindow::parent()) {
|
||||
auto* parent = NativeWindow::parent();
|
||||
if (is_modal() && this->parent()) {
|
||||
auto* parent = this->parent();
|
||||
// Enable parent window after current window gets closed.
|
||||
parent->SetEnabled(true);
|
||||
static_cast<NativeWindowViews*>(parent)->DecrementChildModals();
|
||||
// Focus on parent window.
|
||||
parent->Focus(true);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
#include "ui/views/widget/widget_observer.h"
|
||||
|
||||
@@ -128,12 +129,16 @@ class NativeWindowViews : public NativeWindow,
|
||||
bool IsVisibleOnAllWorkspaces() override;
|
||||
|
||||
gfx::AcceleratedWidget GetAcceleratedWidget() const override;
|
||||
std::tuple<void*, int> GetNativeWindowHandlePointer() const override;
|
||||
|
||||
gfx::Rect ContentBoundsToWindowBounds(const gfx::Rect& bounds) const override;
|
||||
gfx::Rect WindowBoundsToContentBounds(const gfx::Rect& bounds) const override;
|
||||
|
||||
void UpdateDraggableRegions(std::unique_ptr<SkRegion> region);
|
||||
|
||||
void IncrementChildModals();
|
||||
void DecrementChildModals();
|
||||
|
||||
#if defined(OS_WIN)
|
||||
void SetIcon(HICON small_icon, HICON app_icon);
|
||||
#elif defined(USE_X11)
|
||||
@@ -190,6 +195,10 @@ class NativeWindowViews : public NativeWindow,
|
||||
LPARAM l_param);
|
||||
#endif
|
||||
|
||||
// Enable/disable:
|
||||
bool ShouldBeEnabled();
|
||||
void SetEnabledInternal(bool enabled);
|
||||
|
||||
// NativeWindow:
|
||||
void HandleKeyboardEvent(
|
||||
content::WebContents*,
|
||||
@@ -273,8 +282,11 @@ class NativeWindowViews : public NativeWindow,
|
||||
// has to been explicitly provided.
|
||||
std::unique_ptr<SkRegion> draggable_region_; // used in custom drag.
|
||||
|
||||
// How many times the Disable has been called.
|
||||
int disable_count_ = 0;
|
||||
// Whether the window should be enabled based on user calls to SetEnabled()
|
||||
bool is_enabled_ = true;
|
||||
// How many modal children this window has;
|
||||
// used to determine enabled state
|
||||
unsigned int num_modal_children_ = 0;
|
||||
|
||||
bool use_content_size_ = false;
|
||||
bool movable_ = true;
|
||||
|
||||
@@ -97,6 +97,9 @@ network::mojom::NetworkContextParamsPtr CreateDefaultNetworkContextParams(
|
||||
base_path.Append(chrome::kChannelIDFilename);
|
||||
network_context_params->restore_old_session_cookies = false;
|
||||
network_context_params->persist_session_cookies = false;
|
||||
// TODO(deepak1556): Matches the existing behavior https://git.io/fxHMl,
|
||||
// enable encryption as a followup.
|
||||
network_context_params->enable_encrypted_cookies = false;
|
||||
}
|
||||
// TODO(deepak1556): Decide the stand on chrome ct policy and
|
||||
// enable it.
|
||||
@@ -299,6 +302,11 @@ void URLRequestContextGetter::NotifyContextShuttingDown(
|
||||
std::unique_ptr<ResourceContext> resource_context) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
||||
|
||||
// todo(brenca): remove once C70 lands
|
||||
if (url_request_context_ && url_request_context_->cookie_store()) {
|
||||
url_request_context_->cookie_store()->FlushStore(base::NullCallback());
|
||||
}
|
||||
|
||||
context_shutting_down_ = true;
|
||||
resource_context.reset();
|
||||
net::URLRequestContextGetter::NotifyContextShuttingDown();
|
||||
|
||||
@@ -153,13 +153,17 @@ void URLRequestStreamJob::OnData(std::vector<char>&& buffer) { // NOLINT
|
||||
if (pending_buf_) {
|
||||
int len = BufferCopy(&write_buffer_, pending_buf_.get(), pending_buf_size_);
|
||||
write_buffer_.erase(write_buffer_.begin(), write_buffer_.begin() + len);
|
||||
pending_buf_ = nullptr;
|
||||
pending_buf_size_ = 0;
|
||||
ReadRawDataComplete(len);
|
||||
}
|
||||
}
|
||||
|
||||
void URLRequestStreamJob::OnEnd() {
|
||||
ended_ = true;
|
||||
ReadRawDataComplete(0);
|
||||
if (pending_buf_) {
|
||||
ReadRawDataComplete(0);
|
||||
}
|
||||
}
|
||||
|
||||
void URLRequestStreamJob::OnError(int error) {
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "components/viz/common/frame_sinks/delay_based_time_source.h"
|
||||
#include "components/viz/common/gl_helper.h"
|
||||
#include "components/viz/common/quads/render_pass.h"
|
||||
#include "content/browser/renderer_host/cursor_manager.h"
|
||||
#include "content/browser/renderer_host/render_widget_host_delegate.h"
|
||||
#include "content/browser/renderer_host/render_widget_host_impl.h"
|
||||
#include "content/common/view_messages.h"
|
||||
@@ -31,6 +32,7 @@
|
||||
#include "ui/compositor/compositor.h"
|
||||
#include "ui/compositor/layer.h"
|
||||
#include "ui/compositor/layer_type.h"
|
||||
#include "ui/display/screen.h"
|
||||
#include "ui/events/base_event_utils.h"
|
||||
#include "ui/events/event_constants.h"
|
||||
#include "ui/gfx/canvas.h"
|
||||
@@ -255,18 +257,17 @@ OffScreenRenderWidgetHostView::OffScreenRenderWidgetHostView(
|
||||
const OnPaintCallback& callback,
|
||||
content::RenderWidgetHost* host,
|
||||
OffScreenRenderWidgetHostView* parent_host_view,
|
||||
NativeWindow* native_window)
|
||||
gfx::Size initial_size)
|
||||
: content::RenderWidgetHostViewBase(host),
|
||||
render_widget_host_(content::RenderWidgetHostImpl::From(host)),
|
||||
parent_host_view_(parent_host_view),
|
||||
native_window_(native_window),
|
||||
transparent_(transparent),
|
||||
callback_(callback),
|
||||
frame_rate_(frame_rate),
|
||||
scale_factor_(kDefaultScaleFactor),
|
||||
size_(native_window->GetSize()),
|
||||
size_(initial_size),
|
||||
painting_(painting),
|
||||
is_showing_(!render_widget_host_->is_hidden()),
|
||||
cursor_manager_(new content::CursorManager(this)),
|
||||
mouse_wheel_phase_handler_(this),
|
||||
weak_ptr_factory_(this) {
|
||||
DCHECK(render_widget_host_);
|
||||
@@ -280,6 +281,8 @@ OffScreenRenderWidgetHostView::OffScreenRenderWidgetHostView(
|
||||
root_layer_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR));
|
||||
#endif
|
||||
|
||||
current_device_scale_factor_ = kDefaultScaleFactor;
|
||||
|
||||
local_surface_id_ = local_surface_id_allocator_.GenerateId();
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
@@ -308,17 +311,12 @@ OffScreenRenderWidgetHostView::OffScreenRenderWidgetHostView(
|
||||
#endif
|
||||
GetCompositor()->SetDelegate(this);
|
||||
|
||||
native_window_->AddObserver(this);
|
||||
|
||||
ResizeRootLayer(false);
|
||||
render_widget_host_->SetView(this);
|
||||
InstallTransparency();
|
||||
}
|
||||
|
||||
OffScreenRenderWidgetHostView::~OffScreenRenderWidgetHostView() {
|
||||
if (native_window_)
|
||||
native_window_->RemoveObserver(this);
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
if (is_showing_)
|
||||
browser_compositor_->SetRenderWidgetHostIsHidden(true);
|
||||
@@ -349,17 +347,6 @@ OffScreenRenderWidgetHostView::CreateBrowserAccessibilityManager(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::OnWindowResize() {
|
||||
// In offscreen mode call RenderWidgetHostView's SetSize explicitly
|
||||
auto size = native_window_->GetSize();
|
||||
SetSize(size);
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::OnWindowClosed() {
|
||||
native_window_->RemoveObserver(this);
|
||||
native_window_ = nullptr;
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::OnBeginFrameTimerTick() {
|
||||
const base::TimeTicks frame_time = base::TimeTicks::Now();
|
||||
const base::TimeDelta vsync_period =
|
||||
@@ -445,12 +432,12 @@ void OffScreenRenderWidgetHostView::Show() {
|
||||
browser_compositor_->SetRenderWidgetHostIsHidden(false);
|
||||
#else
|
||||
delegated_frame_host_->SetCompositor(compositor_.get());
|
||||
delegated_frame_host_->WasShown(
|
||||
GetLocalSurfaceId(), GetRootLayer()->bounds().size(), ui::LatencyInfo());
|
||||
delegated_frame_host_->WasShown(GetLocalSurfaceId(),
|
||||
GetRootLayer()->bounds().size(), false);
|
||||
#endif
|
||||
|
||||
if (render_widget_host_)
|
||||
render_widget_host_->WasShown(ui::LatencyInfo());
|
||||
render_widget_host_->WasShown(false);
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::Hide() {
|
||||
@@ -628,6 +615,10 @@ void OffScreenRenderWidgetHostView::InitAsFullscreen(
|
||||
|
||||
void OffScreenRenderWidgetHostView::UpdateCursor(const content::WebCursor&) {}
|
||||
|
||||
content::CursorManager* OffScreenRenderWidgetHostView::GetCursorManager() {
|
||||
return cursor_manager_.get();
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::SetIsLoading(bool loading) {}
|
||||
|
||||
void OffScreenRenderWidgetHostView::TextInputStateChanged(
|
||||
@@ -691,7 +682,7 @@ void OffScreenRenderWidgetHostView::GetScreenInfo(
|
||||
screen_info->depth = 24;
|
||||
screen_info->depth_per_component = 8;
|
||||
screen_info->orientation_angle = 0;
|
||||
screen_info->device_scale_factor = 1.0;
|
||||
screen_info->device_scale_factor = current_device_scale_factor_;
|
||||
screen_info->orientation_type =
|
||||
content::SCREEN_ORIENTATION_VALUES_LANDSCAPE_PRIMARY;
|
||||
screen_info->rect = gfx::Rect(size_);
|
||||
@@ -724,11 +715,8 @@ void OffScreenRenderWidgetHostView::ImeCompositionRangeChanged(
|
||||
|
||||
gfx::Size OffScreenRenderWidgetHostView::GetCompositorViewportPixelSize()
|
||||
const {
|
||||
return gfx::ScaleToCeiledSize(GetRequestedRendererSize(), scale_factor_);
|
||||
}
|
||||
|
||||
gfx::Size OffScreenRenderWidgetHostView::GetRequestedRendererSize() const {
|
||||
return GetDelegatedFrameHost()->GetRequestedRendererSize();
|
||||
return gfx::ScaleToCeiledSize(GetRequestedRendererSize(),
|
||||
current_device_scale_factor_);
|
||||
}
|
||||
|
||||
content::RenderWidgetHostViewBase*
|
||||
@@ -749,7 +737,7 @@ OffScreenRenderWidgetHostView::CreateViewForWidget(
|
||||
|
||||
return new OffScreenRenderWidgetHostView(
|
||||
transparent_, true, embedder_host_view->GetFrameRate(), callback_,
|
||||
render_widget_host, embedder_host_view, native_window_);
|
||||
render_widget_host, embedder_host_view, size());
|
||||
}
|
||||
|
||||
#if !defined(OS_MACOSX)
|
||||
@@ -783,13 +771,14 @@ void OffScreenRenderWidgetHostView::DidReceiveFirstFrameAfterNavigation() {
|
||||
render_widget_host_->DidReceiveFirstFrameAfterNavigation();
|
||||
}
|
||||
|
||||
viz::LocalSurfaceId OffScreenRenderWidgetHostView::GetLocalSurfaceId() const {
|
||||
const viz::LocalSurfaceId& OffScreenRenderWidgetHostView::GetLocalSurfaceId()
|
||||
const {
|
||||
return local_surface_id_;
|
||||
}
|
||||
|
||||
#endif // !defined(OS_MACOSX)
|
||||
|
||||
viz::FrameSinkId OffScreenRenderWidgetHostView::GetFrameSinkId() {
|
||||
const viz::FrameSinkId& OffScreenRenderWidgetHostView::GetFrameSinkId() const {
|
||||
return GetDelegatedFrameHost()->frame_sink_id();
|
||||
}
|
||||
|
||||
@@ -809,14 +798,15 @@ bool OffScreenRenderWidgetHostView::TransformPointToLocalCoordSpaceLegacy(
|
||||
gfx::PointF* transformed_point) {
|
||||
// Transformations use physical pixels rather than DIP, so conversion
|
||||
// is necessary.
|
||||
gfx::PointF point_in_pixels = gfx::ConvertPointToPixel(scale_factor_, point);
|
||||
gfx::PointF point_in_pixels =
|
||||
gfx::ConvertPointToPixel(current_device_scale_factor_, point);
|
||||
if (!GetDelegatedFrameHost()->TransformPointToLocalCoordSpaceLegacy(
|
||||
point_in_pixels, original_surface, transformed_point)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*transformed_point =
|
||||
gfx::ConvertPointToDIP(scale_factor_, *transformed_point);
|
||||
gfx::ConvertPointToDIP(current_device_scale_factor_, *transformed_point);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -897,8 +887,8 @@ void OffScreenRenderWidgetHostView::RegisterGuestViewFrameSwappedCallback(
|
||||
|
||||
void OffScreenRenderWidgetHostView::OnGuestViewFrameSwapped(
|
||||
content::RenderWidgetHostViewGuest* guest_host_view) {
|
||||
InvalidateBounds(
|
||||
gfx::ConvertRectToPixel(scale_factor_, guest_host_view->GetViewBounds()));
|
||||
InvalidateBounds(gfx::ConvertRectToPixel(current_device_scale_factor_,
|
||||
guest_host_view->GetViewBounds()));
|
||||
|
||||
RegisterGuestViewFrameSwappedCallback(guest_host_view);
|
||||
}
|
||||
@@ -959,23 +949,32 @@ void OffScreenRenderWidgetHostView::OnPaint(const gfx::Rect& damage_rect,
|
||||
} else {
|
||||
gfx::Rect damage(damage_rect);
|
||||
|
||||
gfx::Size size = GetViewBounds().size();
|
||||
gfx::Size size_in_pixels = gfx::ConvertSizeToPixel(
|
||||
current_device_scale_factor_, GetViewBounds().size());
|
||||
|
||||
SkBitmap backing;
|
||||
backing.allocN32Pixels(size.width(), size.height(), false);
|
||||
backing.allocN32Pixels(size_in_pixels.width(), size_in_pixels.height(),
|
||||
false);
|
||||
SkCanvas canvas(backing);
|
||||
|
||||
canvas.writePixels(bitmap, 0, 0);
|
||||
|
||||
if (popup_host_view_ && popup_bitmap_.get()) {
|
||||
gfx::Rect pos = popup_host_view_->popup_position_;
|
||||
damage.Union(pos);
|
||||
canvas.writePixels(*popup_bitmap_.get(), pos.x(), pos.y());
|
||||
gfx::Rect rect = popup_host_view_->popup_position_;
|
||||
gfx::Point origin_in_pixels =
|
||||
gfx::ConvertPointToPixel(current_device_scale_factor_, rect.origin());
|
||||
damage.Union(rect);
|
||||
canvas.writePixels(*popup_bitmap_.get(), origin_in_pixels.x(),
|
||||
origin_in_pixels.y());
|
||||
}
|
||||
|
||||
for (auto* proxy_view : proxy_views_) {
|
||||
gfx::Rect pos = proxy_view->GetBounds();
|
||||
damage.Union(pos);
|
||||
canvas.writePixels(*proxy_view->GetBitmap(), pos.x(), pos.y());
|
||||
gfx::Rect rect = proxy_view->GetBounds();
|
||||
gfx::Point origin_in_pixels =
|
||||
gfx::ConvertPointToPixel(current_device_scale_factor_, rect.origin());
|
||||
damage.Union(rect);
|
||||
canvas.writePixels(*proxy_view->GetBitmap(), origin_in_pixels.x(),
|
||||
origin_in_pixels.y());
|
||||
}
|
||||
|
||||
damage.Intersect(GetViewBounds());
|
||||
@@ -1029,7 +1028,7 @@ void OffScreenRenderWidgetHostView::SynchronizeVisualProperties() {
|
||||
ResizeRootLayer(false);
|
||||
if (render_widget_host_)
|
||||
render_widget_host_->SynchronizeVisualProperties();
|
||||
GetDelegatedFrameHost()->SynchronizeVisualProperties(
|
||||
GetDelegatedFrameHost()->EmbedSurface(
|
||||
local_surface_id_, size_, cc::DeadlinePolicy::UseDefaultDeadline());
|
||||
}
|
||||
|
||||
@@ -1243,8 +1242,13 @@ void OffScreenRenderWidgetHostView::InvalidateBounds(const gfx::Rect& bounds) {
|
||||
void OffScreenRenderWidgetHostView::ResizeRootLayer(bool force) {
|
||||
SetupFrameRate(false);
|
||||
|
||||
const float compositorScaleFactor = GetCompositor()->device_scale_factor();
|
||||
const bool scaleFactorDidChange = (compositorScaleFactor != scale_factor_);
|
||||
display::Display display =
|
||||
display::Screen::GetScreen()->GetDisplayNearestView(GetNativeView());
|
||||
const float scaleFactor = display.device_scale_factor();
|
||||
const bool scaleFactorDidChange =
|
||||
(scaleFactor != current_device_scale_factor_);
|
||||
|
||||
current_device_scale_factor_ = scaleFactor;
|
||||
|
||||
gfx::Size size;
|
||||
if (!IsPopupWidget())
|
||||
@@ -1257,19 +1261,19 @@ void OffScreenRenderWidgetHostView::ResizeRootLayer(bool force) {
|
||||
return;
|
||||
|
||||
const gfx::Size& size_in_pixels =
|
||||
gfx::ConvertSizeToPixel(scale_factor_, size);
|
||||
gfx::ConvertSizeToPixel(current_device_scale_factor_, size);
|
||||
|
||||
local_surface_id_ = local_surface_id_allocator_.GenerateId();
|
||||
|
||||
GetRootLayer()->SetBounds(gfx::Rect(size));
|
||||
GetCompositor()->SetScaleAndSize(scale_factor_, size_in_pixels,
|
||||
GetCompositor()->SetScaleAndSize(current_device_scale_factor_, size_in_pixels,
|
||||
local_surface_id_);
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
bool resized = UpdateNSViewAndDisplay();
|
||||
#else
|
||||
bool resized = true;
|
||||
GetDelegatedFrameHost()->SynchronizeVisualProperties(
|
||||
GetDelegatedFrameHost()->EmbedSurface(
|
||||
local_surface_id_, size, cc::DeadlinePolicy::UseDefaultDeadline());
|
||||
#endif
|
||||
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "atom/browser/native_window_observer.h"
|
||||
#include "atom/browser/osr/osr_output_device.h"
|
||||
#include "atom/browser/osr/osr_view_proxy.h"
|
||||
#include "base/process/kill.h"
|
||||
@@ -57,6 +55,10 @@ class NSWindow;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace content {
|
||||
class CursorManager;
|
||||
} // namespace content
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomCopyFrameGenerator;
|
||||
@@ -71,7 +73,6 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
|
||||
#if !defined(OS_MACOSX)
|
||||
public content::DelegatedFrameHostClient,
|
||||
#endif
|
||||
public NativeWindowObserver,
|
||||
public OffscreenViewProxyObserver {
|
||||
public:
|
||||
OffScreenRenderWidgetHostView(bool transparent,
|
||||
@@ -80,7 +81,7 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
|
||||
const OnPaintCallback& callback,
|
||||
content::RenderWidgetHost* render_widget_host,
|
||||
OffScreenRenderWidgetHostView* parent_host_view,
|
||||
NativeWindow* native_window);
|
||||
gfx::Size initial_size);
|
||||
~OffScreenRenderWidgetHostView() override;
|
||||
|
||||
content::BrowserAccessibilityManager* CreateBrowserAccessibilityManager(
|
||||
@@ -141,6 +142,7 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
|
||||
void RenderProcessGone(base::TerminationStatus, int) override;
|
||||
void Destroy(void) override;
|
||||
void SetTooltipText(const base::string16&) override;
|
||||
content::CursorManager* GetCursorManager() override;
|
||||
void SelectionBoundsChanged(
|
||||
const ViewHostMsg_SelectionBounds_Params&) override;
|
||||
void CopyFromSurface(
|
||||
@@ -156,7 +158,11 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
|
||||
void ImeCompositionRangeChanged(const gfx::Range&,
|
||||
const std::vector<gfx::Rect>&) override;
|
||||
gfx::Size GetCompositorViewportPixelSize() const override;
|
||||
gfx::Size GetRequestedRendererSize() const override;
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
viz::ScopedSurfaceIdAllocator DidUpdateVisualProperties(
|
||||
const cc::RenderFrameMetadata& metadata) override;
|
||||
#endif
|
||||
|
||||
content::RenderWidgetHostViewBase* CreateViewForWidget(
|
||||
content::RenderWidgetHost*,
|
||||
@@ -175,8 +181,8 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
|
||||
void DidReceiveFirstFrameAfterNavigation() override;
|
||||
#endif // !defined(OS_MACOSX)
|
||||
|
||||
viz::LocalSurfaceId GetLocalSurfaceId() const override;
|
||||
viz::FrameSinkId GetFrameSinkId() override;
|
||||
const viz::LocalSurfaceId& GetLocalSurfaceId() const override;
|
||||
const viz::FrameSinkId& GetFrameSinkId() const override;
|
||||
|
||||
void DidNavigate() override;
|
||||
|
||||
@@ -196,10 +202,6 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
|
||||
|
||||
bool InstallTransparency();
|
||||
|
||||
// NativeWindowObserver:
|
||||
void OnWindowResize() override;
|
||||
void OnWindowClosed() override;
|
||||
|
||||
void OnBeginFrameTimerTick();
|
||||
void SendBeginFrame(base::TimeTicks frame_time, base::TimeDelta vsync_period);
|
||||
|
||||
@@ -259,9 +261,8 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
|
||||
content::RenderWidgetHostImpl* render_widget_host() const {
|
||||
return render_widget_host_;
|
||||
}
|
||||
NativeWindow* window() const { return native_window_; }
|
||||
|
||||
gfx::Size size() const { return size_; }
|
||||
float scale_factor() const { return scale_factor_; }
|
||||
|
||||
void set_popup_host_view(OffScreenRenderWidgetHostView* popup_view) {
|
||||
popup_host_view_ = popup_view;
|
||||
@@ -272,6 +273,12 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
|
||||
}
|
||||
|
||||
private:
|
||||
#if defined(OS_MACOSX)
|
||||
display::Display GetDisplay();
|
||||
void OnDidUpdateVisualPropertiesComplete(
|
||||
const cc::RenderFrameMetadata& metadata);
|
||||
#endif
|
||||
|
||||
void SetupFrameRate(bool force);
|
||||
void ResizeRootLayer(bool force);
|
||||
|
||||
@@ -291,7 +298,6 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
|
||||
std::set<OffScreenRenderWidgetHostView*> guest_host_views_;
|
||||
std::set<OffscreenViewProxy*> proxy_views_;
|
||||
|
||||
NativeWindow* native_window_;
|
||||
OffScreenOutputDevice* software_output_device_ = nullptr;
|
||||
|
||||
const bool transparent_;
|
||||
@@ -303,7 +309,6 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
|
||||
|
||||
base::Time last_time_ = base::Time::Now();
|
||||
|
||||
float scale_factor_;
|
||||
gfx::Vector2dF last_scroll_offset_;
|
||||
gfx::Size size_;
|
||||
bool painting_;
|
||||
@@ -324,6 +329,8 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
|
||||
std::unique_ptr<ui::Compositor> compositor_;
|
||||
std::unique_ptr<content::DelegatedFrameHost> delegated_frame_host_;
|
||||
|
||||
std::unique_ptr<content::CursorManager> cursor_manager_;
|
||||
|
||||
std::unique_ptr<AtomCopyFrameGenerator> copy_frame_generator_;
|
||||
std::unique_ptr<AtomBeginFrameTimer> begin_frame_timer_;
|
||||
|
||||
|
||||
@@ -11,21 +11,13 @@
|
||||
#include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
|
||||
#include "ui/display/screen.h"
|
||||
|
||||
namespace {
|
||||
|
||||
display::Display GetDisplay() {
|
||||
return display::Screen::GetScreen()->GetDisplayNearestView(nullptr);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace atom {
|
||||
|
||||
class MacHelper : public content::BrowserCompositorMacClient,
|
||||
public ui::AcceleratedWidgetMacNSView {
|
||||
public:
|
||||
explicit MacHelper(OffScreenRenderWidgetHostView* view) : view_(view) {
|
||||
[this->AcceleratedWidgetGetNSView() setWantsLayer:YES];
|
||||
[view_->GetNativeView() setWantsLayer:YES];
|
||||
}
|
||||
|
||||
virtual ~MacHelper() {}
|
||||
@@ -48,11 +40,6 @@ class MacHelper : public content::BrowserCompositorMacClient,
|
||||
view_->render_widget_host()->DidProcessFrame(frame_token);
|
||||
}
|
||||
|
||||
// ui::AcceleratedWidgetMacNSView:
|
||||
NSView* AcceleratedWidgetGetNSView() const override {
|
||||
return [view_->window()->GetNativeWindow() contentView];
|
||||
}
|
||||
|
||||
void AcceleratedWidgetCALayerParamsUpdated() override {}
|
||||
|
||||
void DidReceiveFirstFrameAfterNavigation() override {
|
||||
@@ -61,7 +48,22 @@ class MacHelper : public content::BrowserCompositorMacClient,
|
||||
|
||||
void DestroyCompositorForShutdown() override {}
|
||||
|
||||
bool SynchronizeVisualProperties() override {
|
||||
bool SynchronizeVisualProperties(
|
||||
const base::Optional<viz::LocalSurfaceId>&
|
||||
child_allocated_local_surface_id) override {
|
||||
auto* browser_compositor = view_->browser_compositor();
|
||||
if (child_allocated_local_surface_id) {
|
||||
browser_compositor->UpdateRendererLocalSurfaceIdFromChild(
|
||||
*child_allocated_local_surface_id);
|
||||
} else {
|
||||
browser_compositor->AllocateNewRendererLocalSurfaceId();
|
||||
}
|
||||
|
||||
if (auto* host = browser_compositor->GetDelegatedFrameHost()) {
|
||||
host->EmbedSurface(browser_compositor->GetRendererLocalSurfaceId(),
|
||||
browser_compositor->GetRendererSize(),
|
||||
cc::DeadlinePolicy::UseDefaultDeadline());
|
||||
}
|
||||
return view_->render_widget_host()->SynchronizeVisualProperties();
|
||||
}
|
||||
|
||||
@@ -90,8 +92,8 @@ void OffScreenRenderWidgetHostView::CreatePlatformWidget(
|
||||
bool is_guest_view_hack) {
|
||||
mac_helper_ = new MacHelper(this);
|
||||
browser_compositor_.reset(new content::BrowserCompositorMac(
|
||||
mac_helper_, mac_helper_, render_widget_host_->is_hidden(), true,
|
||||
GetDisplay(), AllocateFrameSinkId(is_guest_view_hack)));
|
||||
mac_helper_, mac_helper_, render_widget_host_->is_hidden(), GetDisplay(),
|
||||
AllocateFrameSinkId(is_guest_view_hack)));
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::DestroyPlatformWidget() {
|
||||
@@ -99,7 +101,48 @@ void OffScreenRenderWidgetHostView::DestroyPlatformWidget() {
|
||||
delete mac_helper_;
|
||||
}
|
||||
|
||||
viz::LocalSurfaceId OffScreenRenderWidgetHostView::GetLocalSurfaceId() const {
|
||||
viz::ScopedSurfaceIdAllocator
|
||||
OffScreenRenderWidgetHostView::DidUpdateVisualProperties(
|
||||
const cc::RenderFrameMetadata& metadata) {
|
||||
base::OnceCallback<void()> allocation_task = base::BindOnce(
|
||||
base::IgnoreResult(
|
||||
&OffScreenRenderWidgetHostView::OnDidUpdateVisualPropertiesComplete),
|
||||
weak_ptr_factory_.GetWeakPtr(), metadata);
|
||||
return browser_compositor_->GetScopedRendererSurfaceIdAllocator(
|
||||
std::move(allocation_task));
|
||||
}
|
||||
|
||||
display::Display OffScreenRenderWidgetHostView::GetDisplay() {
|
||||
content::ScreenInfo screen_info;
|
||||
GetScreenInfo(&screen_info);
|
||||
|
||||
// Start with a reasonable display representation.
|
||||
display::Display display =
|
||||
display::Screen::GetScreen()->GetDisplayNearestView(nullptr);
|
||||
|
||||
// Populate attributes based on |screen_info|.
|
||||
display.set_bounds(screen_info.rect);
|
||||
display.set_work_area(screen_info.available_rect);
|
||||
display.set_device_scale_factor(screen_info.device_scale_factor);
|
||||
display.set_color_space(screen_info.color_space);
|
||||
display.set_color_depth(screen_info.depth);
|
||||
display.set_depth_per_component(screen_info.depth_per_component);
|
||||
display.set_is_monochrome(screen_info.is_monochrome);
|
||||
display.SetRotationAsDegree(screen_info.orientation_angle);
|
||||
|
||||
return display;
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::OnDidUpdateVisualPropertiesComplete(
|
||||
const cc::RenderFrameMetadata& metadata) {
|
||||
DCHECK_EQ(current_device_scale_factor_, metadata.device_scale_factor);
|
||||
browser_compositor_->SynchronizeVisualProperties(
|
||||
metadata.device_scale_factor, metadata.viewport_size_in_pixels,
|
||||
metadata.local_surface_id.value_or(viz::LocalSurfaceId()));
|
||||
}
|
||||
|
||||
const viz::LocalSurfaceId& OffScreenRenderWidgetHostView::GetLocalSurfaceId()
|
||||
const {
|
||||
return browser_compositor_->GetRendererLocalSurfaceId();
|
||||
}
|
||||
|
||||
|
||||
@@ -15,13 +15,16 @@ namespace atom {
|
||||
OffScreenWebContentsView::OffScreenWebContentsView(
|
||||
bool transparent,
|
||||
const OnPaintCallback& callback)
|
||||
: transparent_(transparent), callback_(callback) {
|
||||
: native_window_(nullptr), transparent_(transparent), callback_(callback) {
|
||||
#if defined(OS_MACOSX)
|
||||
PlatformCreate();
|
||||
#endif
|
||||
}
|
||||
|
||||
OffScreenWebContentsView::~OffScreenWebContentsView() {
|
||||
if (native_window_)
|
||||
native_window_->RemoveObserver(this);
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
PlatformDestroy();
|
||||
#endif
|
||||
@@ -34,35 +37,52 @@ void OffScreenWebContentsView::SetWebContents(
|
||||
RenderViewCreated(web_contents_->GetRenderViewHost());
|
||||
}
|
||||
|
||||
void OffScreenWebContentsView::SetNativeWindow(NativeWindow* window) {
|
||||
if (native_window_)
|
||||
native_window_->RemoveObserver(this);
|
||||
|
||||
native_window_ = window;
|
||||
|
||||
if (native_window_)
|
||||
native_window_->AddObserver(this);
|
||||
|
||||
OnWindowResize();
|
||||
}
|
||||
|
||||
void OffScreenWebContentsView::OnWindowResize() {
|
||||
// In offscreen mode call RenderWidgetHostView's SetSize explicitly
|
||||
if (GetView())
|
||||
GetView()->SetSize(GetSize());
|
||||
}
|
||||
|
||||
void OffScreenWebContentsView::OnWindowClosed() {
|
||||
if (native_window_) {
|
||||
native_window_->RemoveObserver(this);
|
||||
native_window_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
gfx::Size OffScreenWebContentsView::GetSize() {
|
||||
return native_window_ ? native_window_->GetSize() : gfx::Size();
|
||||
}
|
||||
|
||||
#if !defined(OS_MACOSX)
|
||||
gfx::NativeView OffScreenWebContentsView::GetNativeView() const {
|
||||
if (!web_contents_)
|
||||
if (!native_window_)
|
||||
return gfx::NativeView();
|
||||
|
||||
auto* relay = NativeWindowRelay::FromWebContents(web_contents_);
|
||||
if (!relay)
|
||||
return gfx::NativeView();
|
||||
return relay->window->GetNativeView();
|
||||
return native_window_->GetNativeView();
|
||||
}
|
||||
|
||||
gfx::NativeView OffScreenWebContentsView::GetContentNativeView() const {
|
||||
if (!web_contents_)
|
||||
if (!native_window_)
|
||||
return gfx::NativeView();
|
||||
|
||||
auto* relay = NativeWindowRelay::FromWebContents(web_contents_);
|
||||
if (!relay)
|
||||
return gfx::NativeView();
|
||||
return relay->window->GetNativeView();
|
||||
return native_window_->GetNativeView();
|
||||
}
|
||||
|
||||
gfx::NativeWindow OffScreenWebContentsView::GetTopLevelNativeWindow() const {
|
||||
if (!web_contents_)
|
||||
if (!native_window_)
|
||||
return gfx::NativeWindow();
|
||||
|
||||
auto* relay = NativeWindowRelay::FromWebContents(web_contents_);
|
||||
if (!relay)
|
||||
return gfx::NativeWindow();
|
||||
return relay->window->GetNativeWindow();
|
||||
return native_window_->GetNativeWindow();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -102,17 +122,14 @@ OffScreenWebContentsView::CreateViewForWidget(
|
||||
render_widget_host->GetView());
|
||||
}
|
||||
|
||||
auto* relay = NativeWindowRelay::FromWebContents(web_contents_);
|
||||
return new OffScreenRenderWidgetHostView(
|
||||
transparent_, painting_, GetFrameRate(), callback_, render_widget_host,
|
||||
nullptr, relay->window.get());
|
||||
nullptr, GetSize());
|
||||
}
|
||||
|
||||
content::RenderWidgetHostViewBase*
|
||||
OffScreenWebContentsView::CreateViewForPopupWidget(
|
||||
content::RenderWidgetHost* render_widget_host) {
|
||||
auto* relay = NativeWindowRelay::FromWebContents(web_contents_);
|
||||
|
||||
content::WebContentsImpl* web_contents_impl =
|
||||
static_cast<content::WebContentsImpl*>(web_contents_);
|
||||
|
||||
@@ -123,9 +140,9 @@ OffScreenWebContentsView::CreateViewForPopupWidget(
|
||||
->GetRenderWidgetHostView()
|
||||
: web_contents_impl->GetRenderWidgetHostView());
|
||||
|
||||
return new OffScreenRenderWidgetHostView(
|
||||
transparent_, true, view->GetFrameRate(), callback_, render_widget_host,
|
||||
view, relay->window.get());
|
||||
return new OffScreenRenderWidgetHostView(transparent_, true,
|
||||
view->GetFrameRate(), callback_,
|
||||
render_widget_host, view, GetSize());
|
||||
}
|
||||
|
||||
void OffScreenWebContentsView::SetPageTitle(const base::string16& title) {}
|
||||
@@ -140,8 +157,11 @@ void OffScreenWebContentsView::RenderViewCreated(
|
||||
#endif
|
||||
}
|
||||
|
||||
void OffScreenWebContentsView::RenderViewSwappedIn(
|
||||
content::RenderViewHost* host) {}
|
||||
void OffScreenWebContentsView::RenderViewReady() {}
|
||||
|
||||
void OffScreenWebContentsView::RenderViewHostChanged(
|
||||
content::RenderViewHost* old_host,
|
||||
content::RenderViewHost* new_host) {}
|
||||
|
||||
void OffScreenWebContentsView::SetOverscrollControllerEnabled(bool enabled) {}
|
||||
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
#ifndef ATOM_BROWSER_OSR_OSR_WEB_CONTENTS_VIEW_H_
|
||||
#define ATOM_BROWSER_OSR_OSR_WEB_CONTENTS_VIEW_H_
|
||||
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "atom/browser/native_window_observer.h"
|
||||
|
||||
#include "atom/browser/osr/osr_render_widget_host_view.h"
|
||||
#include "content/browser/renderer_host/render_view_host_delegate_view.h"
|
||||
#include "content/browser/web_contents/web_contents_view.h"
|
||||
@@ -21,12 +24,20 @@ class OffScreenView;
|
||||
namespace atom {
|
||||
|
||||
class OffScreenWebContentsView : public content::WebContentsView,
|
||||
public content::RenderViewHostDelegateView {
|
||||
public content::RenderViewHostDelegateView,
|
||||
public NativeWindowObserver {
|
||||
public:
|
||||
OffScreenWebContentsView(bool transparent, const OnPaintCallback& callback);
|
||||
~OffScreenWebContentsView() override;
|
||||
|
||||
void SetWebContents(content::WebContents*);
|
||||
void SetNativeWindow(NativeWindow* window);
|
||||
|
||||
// NativeWindowObserver:
|
||||
void OnWindowResize() override;
|
||||
void OnWindowClosed() override;
|
||||
|
||||
gfx::Size GetSize();
|
||||
|
||||
// content::WebContentsView:
|
||||
gfx::NativeView GetNativeView() const override;
|
||||
@@ -50,7 +61,9 @@ class OffScreenWebContentsView : public content::WebContentsView,
|
||||
content::RenderWidgetHost* render_widget_host) override;
|
||||
void SetPageTitle(const base::string16& title) override;
|
||||
void RenderViewCreated(content::RenderViewHost* host) override;
|
||||
void RenderViewSwappedIn(content::RenderViewHost* host) override;
|
||||
void RenderViewReady() override;
|
||||
void RenderViewHostChanged(content::RenderViewHost* old_host,
|
||||
content::RenderViewHost* new_host) override;
|
||||
void SetOverscrollControllerEnabled(bool enabled) override;
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
@@ -82,6 +95,8 @@ class OffScreenWebContentsView : public content::WebContentsView,
|
||||
|
||||
OffScreenRenderWidgetHostView* GetView() const;
|
||||
|
||||
NativeWindow* native_window_;
|
||||
|
||||
const bool transparent_;
|
||||
bool painting_ = true;
|
||||
int frame_rate_ = 60;
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.developer-tools</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.9.0</string>
|
||||
<string>10.10.0</string>
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
|
||||
@@ -50,8 +50,8 @@ END
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 4,0,0,20181010
|
||||
PRODUCTVERSION 4,0,0,20181010
|
||||
FILEVERSION 4,0,0,9
|
||||
PRODUCTVERSION 4,0,0,9
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
||||
@@ -77,9 +77,11 @@ void GenerateAcceleratorTable(AcceleratorTable* table,
|
||||
GenerateAcceleratorTable(table, submodel);
|
||||
} else {
|
||||
ui::Accelerator accelerator;
|
||||
if (model->GetAcceleratorAtWithParams(i, true, &accelerator)) {
|
||||
MenuItem item = {i, model};
|
||||
(*table)[accelerator] = item;
|
||||
if (model->ShouldRegisterAcceleratorAt(i)) {
|
||||
if (model->GetAcceleratorAtWithParams(i, true, &accelerator)) {
|
||||
MenuItem item = {i, model};
|
||||
(*table)[accelerator] = item;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,14 @@ bool AtomMenuModel::GetAcceleratorAtWithParams(
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AtomMenuModel::ShouldRegisterAcceleratorAt(int index) const {
|
||||
if (delegate_) {
|
||||
return delegate_->ShouldRegisterAcceleratorForCommandId(
|
||||
GetCommandIdAt(index));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void AtomMenuModel::MenuWillClose() {
|
||||
ui::SimpleMenuModel::MenuWillClose();
|
||||
for (Observer& observer : observers_) {
|
||||
|
||||
@@ -23,6 +23,9 @@ class AtomMenuModel : public ui::SimpleMenuModel {
|
||||
bool use_default_accelerator,
|
||||
ui::Accelerator* accelerator) const = 0;
|
||||
|
||||
virtual bool ShouldRegisterAcceleratorForCommandId(
|
||||
int command_id) const = 0;
|
||||
|
||||
private:
|
||||
// ui::SimpleMenuModel::Delegate:
|
||||
bool GetAcceleratorForCommandId(
|
||||
@@ -52,6 +55,7 @@ class AtomMenuModel : public ui::SimpleMenuModel {
|
||||
bool GetAcceleratorAtWithParams(int index,
|
||||
bool use_default_accelerator,
|
||||
ui::Accelerator* accelerator) const;
|
||||
bool ShouldRegisterAcceleratorAt(int index) const;
|
||||
|
||||
// ui::SimpleMenuModel:
|
||||
void MenuWillClose() override;
|
||||
|
||||
@@ -208,7 +208,17 @@ static base::scoped_nsobject<NSMenu> recentDocumentsMenuSwap_;
|
||||
|
||||
base::string16 role = model->GetRoleAt(index);
|
||||
atom::AtomMenuModel::ItemType type = model->GetTypeAt(index);
|
||||
if (type == atom::AtomMenuModel::TYPE_SUBMENU) {
|
||||
|
||||
if (role == base::ASCIIToUTF16("services")) {
|
||||
base::string16 title = base::ASCIIToUTF16("Services");
|
||||
NSString* label = l10n_util::FixUpWindowsStyleLabel(title);
|
||||
|
||||
[item setTarget:nil];
|
||||
[item setAction:nil];
|
||||
NSMenu* submenu = [[NSMenu alloc] initWithTitle:label];
|
||||
[item setSubmenu:submenu];
|
||||
[NSApp setServicesMenu:submenu];
|
||||
} else if (type == atom::AtomMenuModel::TYPE_SUBMENU) {
|
||||
// Recursively build a submenu from the sub-model at this index.
|
||||
[item setTarget:nil];
|
||||
[item setAction:nil];
|
||||
@@ -223,8 +233,6 @@ static base::scoped_nsobject<NSMenu> recentDocumentsMenuSwap_;
|
||||
[NSApp setWindowsMenu:submenu];
|
||||
else if (role == base::ASCIIToUTF16("help"))
|
||||
[NSApp setHelpMenu:submenu];
|
||||
else if (role == base::ASCIIToUTF16("services"))
|
||||
[NSApp setServicesMenu:submenu];
|
||||
else if (role == base::ASCIIToUTF16("recentdocuments"))
|
||||
[self replaceSubmenuShowingRecentDocuments:item];
|
||||
} else {
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "atom/browser/ui/cocoa/atom_preview_item.h"
|
||||
#include "atom/browser/ui/cocoa/atom_touch_bar.h"
|
||||
#include "base/mac/mac_util.h"
|
||||
#include "ui/views/cocoa/bridged_native_widget.h"
|
||||
#include "ui/views/widget/native_widget_mac.h"
|
||||
|
||||
@implementation AtomNSWindowDelegate
|
||||
@@ -246,7 +247,10 @@
|
||||
// Clears the delegate when window is going to be closed, since EL Capitan it
|
||||
// is possible that the methods of delegate would get called after the window
|
||||
// has been closed.
|
||||
[shell_->GetNativeWindow() setDelegate:nil];
|
||||
views::BridgedNativeWidget* bridged_view =
|
||||
views::NativeWidgetMac::GetBridgeForNativeWindow(
|
||||
shell_->GetNativeWindow());
|
||||
bridged_view->OnWindowWillClose();
|
||||
}
|
||||
|
||||
- (BOOL)windowShouldClose:(id)window {
|
||||
|
||||
@@ -94,10 +94,14 @@ class FileChooserDialog {
|
||||
}
|
||||
|
||||
void SetupProperties(int properties) {
|
||||
if (properties & FILE_DIALOG_MULTI_SELECTIONS)
|
||||
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog()), TRUE);
|
||||
if (properties & FILE_DIALOG_SHOW_HIDDEN_FILES)
|
||||
g_object_set(dialog(), "show-hidden", TRUE, NULL);
|
||||
const auto hasProp = [properties](FileDialogProperty prop) {
|
||||
return gboolean((properties & prop) != 0);
|
||||
};
|
||||
auto* file_chooser = GTK_FILE_CHOOSER(dialog());
|
||||
gtk_file_chooser_set_select_multiple(file_chooser,
|
||||
hasProp(FILE_DIALOG_MULTI_SELECTIONS));
|
||||
gtk_file_chooser_set_show_hidden(file_chooser,
|
||||
hasProp(FILE_DIALOG_SHOW_HIDDEN_FILES));
|
||||
}
|
||||
|
||||
void RunAsynchronous() {
|
||||
|
||||
@@ -40,7 +40,8 @@ class GtkMessageBox : public NativeWindowObserver {
|
||||
const std::string& message,
|
||||
const std::string& detail,
|
||||
const std::string& checkbox_label,
|
||||
bool checkbox_checked)
|
||||
bool checkbox_checked,
|
||||
const gfx::ImageSkia& icon)
|
||||
: cancel_id_(cancel_id),
|
||||
parent_(static_cast<NativeWindow*>(parent_window)) {
|
||||
// Create dialog.
|
||||
@@ -56,6 +57,21 @@ class GtkMessageBox : public NativeWindowObserver {
|
||||
if (!title.empty())
|
||||
gtk_window_set_title(GTK_WINDOW(dialog_), title.c_str());
|
||||
|
||||
if (!icon.isNull()) {
|
||||
// No easy way to obtain this programmatically, but GTK+'s docs
|
||||
// define GTK_ICON_SIZE_DIALOG to be 48 pixels
|
||||
static constexpr int pixel_width = 48;
|
||||
static constexpr int pixel_height = 48;
|
||||
GdkPixbuf* pixbuf = libgtkui::GdkPixbufFromSkBitmap(*icon.bitmap());
|
||||
GdkPixbuf* scaled_pixbuf = gdk_pixbuf_scale_simple(
|
||||
pixbuf, pixel_width, pixel_height, GDK_INTERP_BILINEAR);
|
||||
GtkWidget* w = gtk_image_new_from_pixbuf(scaled_pixbuf);
|
||||
gtk_message_dialog_set_image(GTK_MESSAGE_DIALOG(dialog_), w);
|
||||
gtk_widget_show(w);
|
||||
g_clear_pointer(&scaled_pixbuf, gdk_pixbuf_unref);
|
||||
g_clear_pointer(&pixbuf, gdk_pixbuf_unref);
|
||||
}
|
||||
|
||||
if (!checkbox_label.empty()) {
|
||||
GtkWidget* message_area =
|
||||
gtk_message_dialog_get_message_area(GTK_MESSAGE_DIALOG(dialog_));
|
||||
@@ -66,15 +82,15 @@ class GtkMessageBox : public NativeWindowObserver {
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button),
|
||||
checkbox_checked);
|
||||
gtk_container_add(GTK_CONTAINER(message_area), check_button);
|
||||
gtk_widget_show(check_button);
|
||||
}
|
||||
|
||||
// Add buttons.
|
||||
GtkDialog* dialog = GTK_DIALOG(dialog_);
|
||||
for (size_t i = 0; i < buttons.size(); ++i) {
|
||||
GtkWidget* button = gtk_dialog_add_button(
|
||||
GTK_DIALOG(dialog_), TranslateToStock(i, buttons[i]), i);
|
||||
if (static_cast<int>(i) == default_id)
|
||||
gtk_widget_grab_focus(button);
|
||||
gtk_dialog_add_button(dialog, TranslateToStock(i, buttons[i]), i);
|
||||
}
|
||||
gtk_dialog_set_default_response(dialog, default_id);
|
||||
|
||||
// Parent window.
|
||||
if (parent_) {
|
||||
@@ -122,7 +138,7 @@ class GtkMessageBox : public NativeWindowObserver {
|
||||
}
|
||||
|
||||
void Show() {
|
||||
gtk_widget_show_all(dialog_);
|
||||
gtk_widget_show(dialog_);
|
||||
// We need to call gtk_window_present after making the widgets visible to
|
||||
// make sure window gets correctly raised and gets focus.
|
||||
int time = ui::X11EventSource::GetInstance()->GetTimestamp();
|
||||
@@ -195,9 +211,9 @@ int ShowMessageBox(NativeWindow* parent,
|
||||
const std::string& title,
|
||||
const std::string& message,
|
||||
const std::string& detail,
|
||||
const gfx::ImageSkia& /*icon*/) {
|
||||
const gfx::ImageSkia& icon) {
|
||||
return GtkMessageBox(parent, type, buttons, default_id, cancel_id, title,
|
||||
message, detail, "", false)
|
||||
message, detail, "", false, icon)
|
||||
.RunSynchronous();
|
||||
}
|
||||
|
||||
@@ -212,10 +228,10 @@ void ShowMessageBox(NativeWindow* parent,
|
||||
const std::string& detail,
|
||||
const std::string& checkbox_label,
|
||||
bool checkbox_checked,
|
||||
const gfx::ImageSkia& /*icon*/,
|
||||
const gfx::ImageSkia& icon,
|
||||
const MessageBoxCallback& callback) {
|
||||
(new GtkMessageBox(parent, type, buttons, default_id, cancel_id, title,
|
||||
message, detail, checkbox_label, checkbox_checked))
|
||||
message, detail, checkbox_label, checkbox_checked, icon))
|
||||
->RunAsynchronous(callback);
|
||||
}
|
||||
|
||||
@@ -223,7 +239,8 @@ void ShowErrorBox(const base::string16& title, const base::string16& content) {
|
||||
if (Browser::Get()->is_ready()) {
|
||||
GtkMessageBox(nullptr, MESSAGE_BOX_TYPE_ERROR, {"OK"}, -1, 0, "Error",
|
||||
base::UTF16ToUTF8(title).c_str(),
|
||||
base::UTF16ToUTF8(content).c_str(), "", false)
|
||||
base::UTF16ToUTF8(content).c_str(), "", false,
|
||||
gfx::ImageSkia())
|
||||
.RunSynchronous();
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
|
||||
@@ -44,15 +44,14 @@ RootView::~RootView() {}
|
||||
void RootView::SetMenu(AtomMenuModel* menu_model) {
|
||||
if (menu_model == nullptr) {
|
||||
// Remove accelerators
|
||||
accelerator_table_.clear();
|
||||
GetFocusManager()->UnregisterAccelerators(this);
|
||||
UnregisterAcceleratorsWithFocusManager();
|
||||
// and menu bar.
|
||||
SetMenuBarVisibility(false);
|
||||
menu_bar_.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
RegisterAccelerators(menu_model);
|
||||
RegisterAcceleratorsWithFocusManager(menu_model);
|
||||
|
||||
// Do not show menu bar in frameless window.
|
||||
if (!window_->has_frame())
|
||||
@@ -178,12 +177,13 @@ bool RootView::AcceleratorPressed(const ui::Accelerator& accelerator) {
|
||||
accelerator);
|
||||
}
|
||||
|
||||
void RootView::RegisterAccelerators(AtomMenuModel* menu_model) {
|
||||
void RootView::RegisterAcceleratorsWithFocusManager(AtomMenuModel* menu_model) {
|
||||
if (!menu_model)
|
||||
return;
|
||||
// Clear previous accelerators.
|
||||
views::FocusManager* focus_manager = GetFocusManager();
|
||||
accelerator_table_.clear();
|
||||
focus_manager->UnregisterAccelerators(this);
|
||||
UnregisterAcceleratorsWithFocusManager();
|
||||
|
||||
views::FocusManager* focus_manager = GetFocusManager();
|
||||
// Register accelerators with focus manager.
|
||||
accelerator_util::GenerateAcceleratorTable(&accelerator_table_, menu_model);
|
||||
for (const auto& iter : accelerator_table_) {
|
||||
@@ -192,4 +192,10 @@ void RootView::RegisterAccelerators(AtomMenuModel* menu_model) {
|
||||
}
|
||||
}
|
||||
|
||||
void RootView::UnregisterAcceleratorsWithFocusManager() {
|
||||
views::FocusManager* focus_manager = GetFocusManager();
|
||||
accelerator_table_.clear();
|
||||
focus_manager->UnregisterAccelerators(this);
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -34,6 +34,10 @@ class RootView : public views::View {
|
||||
bool IsMenuBarVisible() const;
|
||||
void HandleKeyEvent(const content::NativeWebKeyboardEvent& event);
|
||||
void ResetAltState();
|
||||
void RestoreFocus();
|
||||
// Register/Unregister accelerators supported by the menu model.
|
||||
void RegisterAcceleratorsWithFocusManager(AtomMenuModel* menu_model);
|
||||
void UnregisterAcceleratorsWithFocusManager();
|
||||
|
||||
// views::View:
|
||||
void Layout() override;
|
||||
@@ -42,9 +46,6 @@ class RootView : public views::View {
|
||||
bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
|
||||
|
||||
private:
|
||||
// Register accelerators supported by the menu model.
|
||||
void RegisterAccelerators(AtomMenuModel* menu_model);
|
||||
|
||||
// Parent window, weak ref.
|
||||
NativeWindow* window_;
|
||||
|
||||
|
||||
@@ -171,6 +171,10 @@ bool WebContentsPreferences::GetPreference(const base::StringPiece& name,
|
||||
return GetAsString(&preference_, name, value);
|
||||
}
|
||||
|
||||
bool WebContentsPreferences::IsRemoteModuleEnabled() const {
|
||||
return IsEnabled(options::kEnableRemoteModule, true);
|
||||
}
|
||||
|
||||
bool WebContentsPreferences::GetPreloadPath(
|
||||
base::FilePath::StringType* path) const {
|
||||
DCHECK(path);
|
||||
@@ -267,6 +271,10 @@ void WebContentsPreferences::AppendCommandLineSwitches(
|
||||
}
|
||||
}
|
||||
|
||||
// Whether to enable the remote module
|
||||
if (!IsRemoteModuleEnabled())
|
||||
command_line->AppendSwitch(switches::kDisableRemoteModule);
|
||||
|
||||
// Run Electron APIs and preload script in isolated world
|
||||
if (IsEnabled(options::kContextIsolation))
|
||||
command_line->AppendSwitch(switches::kContextIsolation);
|
||||
@@ -397,6 +405,8 @@ void WebContentsPreferences::OverrideWebkitPrefs(
|
||||
std::string encoding;
|
||||
if (GetAsString(&preference_, "defaultEncoding", &encoding))
|
||||
prefs->default_encoding = encoding;
|
||||
|
||||
prefs->node_integration = IsEnabled(options::kNodeIntegration);
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -55,6 +55,9 @@ class WebContentsPreferences
|
||||
// Return true if the particular preference value exists.
|
||||
bool GetPreference(const base::StringPiece& name, std::string* value) const;
|
||||
|
||||
// Whether to enable the remote module
|
||||
bool IsRemoteModuleEnabled() const;
|
||||
|
||||
// Returns the preload script path.
|
||||
bool GetPreloadPath(base::FilePath::StringType* path) const;
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#define ATOM_MINOR_VERSION 0
|
||||
#define ATOM_PATCH_VERSION 0
|
||||
// clang-format off
|
||||
#define ATOM_PRE_RELEASE_VERSION -nightly.20181010
|
||||
#define ATOM_PRE_RELEASE_VERSION -beta.9
|
||||
// clang-format on
|
||||
|
||||
#ifndef ATOM_STRINGIFY
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/common/api/event_emitter_caller.h"
|
||||
@@ -18,6 +19,7 @@
|
||||
#include "base/environment.h"
|
||||
#include "base/path_service.h"
|
||||
#include "base/run_loop.h"
|
||||
#include "base/strings/string_split.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "base/threading/thread_task_runner_handle.h"
|
||||
#include "base/trace_event/trace_event.h"
|
||||
@@ -36,6 +38,7 @@
|
||||
V(atom_browser_debugger) \
|
||||
V(atom_browser_dialog) \
|
||||
V(atom_browser_download_item) \
|
||||
V(atom_browser_event) \
|
||||
V(atom_browser_global_shortcut) \
|
||||
V(atom_browser_in_app_purchase) \
|
||||
V(atom_browser_menu) \
|
||||
@@ -213,19 +216,73 @@ void NodeBindings::Initialize() {
|
||||
// Explicitly register electron's builtin modules.
|
||||
RegisterBuiltinModules();
|
||||
|
||||
// Init node.
|
||||
// (we assume node::Init would not modify the parameters under embedded mode).
|
||||
// NOTE: If you change this line, please ping @codebytere or @MarshallOfSound
|
||||
int argc = 0;
|
||||
// pass non-null program name to argv so it doesn't crash
|
||||
// trying to index into a nullptr
|
||||
int argc = 1;
|
||||
int exec_argc = 0;
|
||||
const char** argv = nullptr;
|
||||
const char* prog_name = "electron";
|
||||
const char** argv = &prog_name;
|
||||
const char** exec_argv = nullptr;
|
||||
|
||||
std::unique_ptr<base::Environment> env(base::Environment::Create());
|
||||
if (env->HasVar("NODE_OPTIONS")) {
|
||||
base::FilePath exe_path;
|
||||
base::PathService::Get(base::FILE_EXE, &exe_path);
|
||||
#if defined(OS_WIN)
|
||||
std::string path = base::UTF16ToUTF8(exe_path.value());
|
||||
#else
|
||||
std::string path = exe_path.value();
|
||||
#endif
|
||||
std::transform(path.begin(), path.end(), path.begin(), ::tolower);
|
||||
|
||||
#if defined(OS_WIN)
|
||||
const bool is_packaged_app = path == "electron.exe";
|
||||
#else
|
||||
const bool is_packaged_app = path == "electron";
|
||||
#endif
|
||||
|
||||
// explicitly disallow NODE_OPTIONS in packaged apps
|
||||
if (is_packaged_app) {
|
||||
LOG(WARNING) << "NODE_OPTIONs are not supported in packaged apps";
|
||||
env->SetVar("NODE_OPTIONS", "");
|
||||
} else {
|
||||
const std::vector<std::string> disallowed = {
|
||||
"--openssl-config", "--use-bundled-ca", "--use-openssl-ca",
|
||||
"--force-fips", "--enable-fips"};
|
||||
|
||||
std::string options;
|
||||
env->GetVar("NODE_OPTIONS", &options);
|
||||
std::vector<std::string> parts = base::SplitString(
|
||||
options, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
|
||||
|
||||
// parse passed options for unsupported options
|
||||
// and remove them from the options list
|
||||
std::string new_options = options;
|
||||
for (const auto& disallow : disallowed) {
|
||||
for (const auto& part : parts) {
|
||||
if (part.find(disallow) != std::string::npos) {
|
||||
LOG(WARNING) << "The NODE_OPTION" << disallow
|
||||
<< "is not supported in Electron";
|
||||
new_options.erase(new_options.find(part), part.length());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// overwrite new NODE_OPTIONS without unsupported variables
|
||||
if (new_options != options)
|
||||
env->SetVar("NODE_OPTIONS", new_options);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(codebytere): this is going to be deprecated in the near future
|
||||
// in favor of Init(std::vector<std::string>* argv,
|
||||
// std::vector<std::string>* exec_argv)
|
||||
node::Init(&argc, argv, &exec_argc, &exec_argv);
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// uv_init overrides error mode to suppress the default crash dialog, bring
|
||||
// it back if user wants to show it.
|
||||
std::unique_ptr<base::Environment> env(base::Environment::Create());
|
||||
if (browser_env_ == BROWSER || env->HasVar("ELECTRON_DEFAULT_ERROR_MODE"))
|
||||
SetErrorMode(GetErrorMode() & ~SEM_NOGPFAULTERRORBOX);
|
||||
#endif
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#undef NO_RETURN
|
||||
#undef LIKELY
|
||||
#undef arraysize
|
||||
#undef debug_string // This is defined in macOS 10.9 SDK in AssertMacros.h.
|
||||
#undef debug_string // This is defined in macOS SDK in AssertMacros.h.
|
||||
#include "env-inl.h"
|
||||
#include "env.h"
|
||||
#include "node.h"
|
||||
|
||||
@@ -110,6 +110,9 @@ const char kPreloadURL[] = "preloadURL";
|
||||
// Enable the node integration.
|
||||
const char kNodeIntegration[] = "nodeIntegration";
|
||||
|
||||
// Enable the remote module
|
||||
const char kEnableRemoteModule[] = "enableRemoteModule";
|
||||
|
||||
// Enable context isolation of Electron APIs and preload script
|
||||
const char kContextIsolation[] = "contextIsolation";
|
||||
|
||||
@@ -193,6 +196,7 @@ const char kBackgroundColor[] = "background-color";
|
||||
const char kPreloadScript[] = "preload";
|
||||
const char kPreloadScripts[] = "preload-scripts";
|
||||
const char kNodeIntegration[] = "node-integration";
|
||||
const char kDisableRemoteModule[] = "disable-remote-module";
|
||||
const char kContextIsolation[] = "context-isolation";
|
||||
const char kGuestInstanceID[] = "guest-instance-id";
|
||||
const char kOpenerID[] = "opener-id";
|
||||
|
||||
@@ -58,6 +58,7 @@ extern const char kZoomFactor[];
|
||||
extern const char kPreloadScript[];
|
||||
extern const char kPreloadURL[];
|
||||
extern const char kNodeIntegration[];
|
||||
extern const char kEnableRemoteModule[];
|
||||
extern const char kContextIsolation[];
|
||||
extern const char kGuestInstanceID[];
|
||||
extern const char kExperimentalFeatures[];
|
||||
@@ -97,6 +98,7 @@ extern const char kBackgroundColor[];
|
||||
extern const char kPreloadScript[];
|
||||
extern const char kPreloadScripts[];
|
||||
extern const char kNodeIntegration[];
|
||||
extern const char kDisableRemoteModule[];
|
||||
extern const char kContextIsolation[];
|
||||
extern const char kGuestInstanceID[];
|
||||
extern const char kOpenerID[];
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "url/gurl.h"
|
||||
|
||||
#define ELECTRON_TRASH "ELECTRON_TRASH"
|
||||
#define ELECTRON_DEFAULT_TRASH "gvfs-trash"
|
||||
#define ELECTRON_DEFAULT_TRASH "gio"
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -125,12 +125,13 @@ bool MoveItemToTrash(const base::FilePath& full_path) {
|
||||
} else if (trash.compare("trash-cli") == 0) {
|
||||
argv.push_back("trash-put");
|
||||
argv.push_back(full_path.value());
|
||||
} else if (trash.compare("gio") == 0) {
|
||||
argv.push_back("gio");
|
||||
argv.push_back("trash");
|
||||
} else if (trash.compare("gvfs-trash") == 0) {
|
||||
// retain support for deprecated gvfs-trash
|
||||
argv.push_back("gvfs-trash");
|
||||
argv.push_back(full_path.value());
|
||||
} else {
|
||||
argv.push_back(ELECTRON_DEFAULT_TRASH);
|
||||
argv.push_back("trash");
|
||||
argv.push_back(full_path.value());
|
||||
}
|
||||
return XDGUtilV(argv, true);
|
||||
|
||||
@@ -21,8 +21,7 @@ v8::Maybe<bool> Promise::RejectWithErrorMessage(const std::string& string) {
|
||||
v8::Local<v8::String> error_message =
|
||||
v8::String::NewFromUtf8(isolate(), string.c_str());
|
||||
v8::Local<v8::Value> error = v8::Exception::Error(error_message);
|
||||
return GetInner()->Reject(isolate()->GetCurrentContext(),
|
||||
mate::ConvertToV8(isolate(), error));
|
||||
return Reject(error);
|
||||
}
|
||||
|
||||
v8::Local<v8::Promise> Promise::GetHandle() const {
|
||||
|
||||
@@ -32,6 +32,8 @@ class Promise : public base::RefCounted<Promise> {
|
||||
v8::Undefined(isolate()));
|
||||
}
|
||||
|
||||
// Promise resolution is a microtask
|
||||
// We use the MicrotasksRunner to trigger the running of pending microtasks
|
||||
template <typename T>
|
||||
v8::Maybe<bool> Resolve(const T& value) {
|
||||
return GetInner()->Resolve(isolate()->GetCurrentContext(),
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "atom/renderer/atom_render_frame_observer.h"
|
||||
#include "atom/renderer/web_worker_observer.h"
|
||||
#include "base/command_line.h"
|
||||
#include "content/public/common/web_preferences.h"
|
||||
#include "content/public/renderer/render_frame.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "third_party/blink/public/web/web_document.h"
|
||||
@@ -86,6 +87,15 @@ void AtomRendererClient::DidCreateScriptContext(
|
||||
if (!render_frame->IsMainFrame() && !IsDevToolsExtension(render_frame))
|
||||
return;
|
||||
|
||||
// Don't allow node integration if this is a child window and it does not have
|
||||
// node integration enabled. Otherwise we would have memory leak in the child
|
||||
// window since we don't clean up node environments.
|
||||
//
|
||||
// TODO(zcbenz): We shouldn't allow node integration even for the top frame.
|
||||
if (!render_frame->GetWebkitPreferences().node_integration &&
|
||||
render_frame->GetWebFrame()->Opener())
|
||||
return;
|
||||
|
||||
injected_frames_.insert(render_frame);
|
||||
|
||||
// Prepare the node bindings.
|
||||
|
||||
@@ -39,6 +39,11 @@ bool IsDevTools(content::RenderFrame* render_frame) {
|
||||
"chrome-devtools");
|
||||
}
|
||||
|
||||
bool IsDevToolsExtension(content::RenderFrame* render_frame) {
|
||||
return render_frame->GetWebFrame()->GetDocument().Url().ProtocolIs(
|
||||
"chrome-extension");
|
||||
}
|
||||
|
||||
v8::Local<v8::Object> GetModuleCache(v8::Isolate* isolate) {
|
||||
mate::Dictionary global(isolate, isolate->GetCurrentContext()->Global());
|
||||
v8::Local<v8::Value> cache;
|
||||
@@ -198,7 +203,8 @@ void AtomSandboxedRendererClient::DidCreateScriptContext(
|
||||
|
||||
// Only allow preload for the main frame or
|
||||
// For devtools we still want to run the preload_bundle script
|
||||
if (!render_frame->IsMainFrame() && !IsDevTools(render_frame))
|
||||
if (!render_frame->IsMainFrame() && !IsDevTools(render_frame) &&
|
||||
!IsDevToolsExtension(render_frame))
|
||||
return;
|
||||
|
||||
auto* isolate = context->GetIsolate();
|
||||
|
||||
@@ -71,6 +71,15 @@ std::vector<std::string> ParseSchemesCLISwitch(base::CommandLine* command_line,
|
||||
base::SPLIT_WANT_NONEMPTY);
|
||||
}
|
||||
|
||||
void SetHiddenValue(v8::Handle<v8::Context> context,
|
||||
const base::StringPiece& key,
|
||||
v8::Local<v8::Value> value) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
v8::Local<v8::Private> privateKey =
|
||||
v8::Private::ForApi(isolate, mate::StringToV8(isolate, key));
|
||||
context->Global()->SetPrivate(context, privateKey, value);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
RendererClientBase::RendererClientBase() {
|
||||
@@ -100,10 +109,13 @@ void RendererClientBase::DidCreateScriptContext(
|
||||
auto context_id = base::StringPrintf(
|
||||
"%s-%" PRId64, renderer_client_id_.c_str(), ++next_context_id_);
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
v8::Local<v8::String> key = mate::StringToSymbol(isolate, "contextId");
|
||||
v8::Local<v8::Private> private_key = v8::Private::ForApi(isolate, key);
|
||||
v8::Local<v8::Value> value = mate::ConvertToV8(isolate, context_id);
|
||||
context->Global()->SetPrivate(context, private_key, value);
|
||||
SetHiddenValue(context, "contextId", mate::ConvertToV8(isolate, context_id));
|
||||
|
||||
auto* command_line = base::CommandLine::ForCurrentProcess();
|
||||
bool enableRemoteModule =
|
||||
!command_line->HasSwitch(switches::kDisableRemoteModule);
|
||||
SetHiddenValue(context, "enableRemoteModule",
|
||||
mate::ConvertToV8(isolate, enableRemoteModule));
|
||||
}
|
||||
|
||||
void RendererClientBase::AddRenderBindings(
|
||||
@@ -177,22 +189,26 @@ void RendererClientBase::RenderFrameCreated(
|
||||
blink::WebSecurityPolicy::AddOriginAccessWhitelistEntry(
|
||||
GURL(kPdfViewerUIOrigin), "file", "", true);
|
||||
#endif // BUILDFLAG(ENABLE_PDF_VIEWER)
|
||||
|
||||
content::RenderView* render_view = render_frame->GetRenderView();
|
||||
if (render_frame->IsMainFrame() && render_view) {
|
||||
blink::WebFrameWidget* web_frame_widget = render_view->GetWebFrameWidget();
|
||||
if (web_frame_widget) {
|
||||
base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
|
||||
if (cmd->HasSwitch(switches::kGuestInstanceID)) { // webview.
|
||||
web_frame_widget->SetBaseBackgroundColor(SK_ColorTRANSPARENT);
|
||||
} else { // normal window.
|
||||
std::string name = cmd->GetSwitchValueASCII(switches::kBackgroundColor);
|
||||
SkColor color =
|
||||
name.empty() ? SK_ColorTRANSPARENT : ParseHexColor(name);
|
||||
web_frame_widget->SetBaseBackgroundColor(color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RendererClientBase::RenderViewCreated(content::RenderView* render_view) {
|
||||
new AtomRenderViewObserver(render_view);
|
||||
blink::WebFrameWidget* web_frame_widget = render_view->GetWebFrameWidget();
|
||||
if (!web_frame_widget)
|
||||
return;
|
||||
|
||||
base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
|
||||
if (cmd->HasSwitch(switches::kGuestInstanceID)) { // webview.
|
||||
web_frame_widget->SetBaseBackgroundColor(SK_ColorTRANSPARENT);
|
||||
} else { // normal window.
|
||||
std::string name = cmd->GetSwitchValueASCII(switches::kBackgroundColor);
|
||||
SkColor color = name.empty() ? SK_ColorTRANSPARENT : ParseHexColor(name);
|
||||
web_frame_widget->SetBaseBackgroundColor(color);
|
||||
}
|
||||
}
|
||||
|
||||
void RendererClientBase::DidClearWindowObject(
|
||||
|
||||
@@ -514,8 +514,9 @@ void InspectableWebContentsImpl::ShowItemInFolder(
|
||||
const std::string& file_system_path) {
|
||||
if (file_system_path.empty())
|
||||
return;
|
||||
|
||||
base::FilePath path = base::FilePath::FromUTF8Unsafe(file_system_path);
|
||||
platform_util::ShowItemInFolder(path);
|
||||
platform_util::OpenItem(path);
|
||||
}
|
||||
|
||||
void InspectableWebContentsImpl::SaveToFile(const std::string& url,
|
||||
|
||||
@@ -4,6 +4,7 @@ root_extra_deps = [ "//electron" ]
|
||||
|
||||
v8_promise_internal_field_count = 1
|
||||
v8_typed_array_max_size_in_heap = 0
|
||||
v8_embedder_string = "-electron.0"
|
||||
|
||||
enable_cdm_host_verification = false
|
||||
enable_extensions = false
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
import("release.gn")
|
||||
v8_enable_i18n_support = false
|
||||
6
build/electron.def
Normal file
6
build/electron.def
Normal file
@@ -0,0 +1,6 @@
|
||||
; This is to support renaming of electron.exe. node-gyp has hard-coded
|
||||
; executable names which it will recognise as node. This module definition
|
||||
; file claims that the electron executable is in fact named "node.exe",
|
||||
; which is one of the executable names that node-gyp recognizes.
|
||||
; See https://github.com/nodejs/node-gyp/commit/52ceec3a6d15de3a8f385f43dbe5ecf5456ad07a
|
||||
NAME node.exe
|
||||
27
build/mac/make_locale_dirs.py
Normal file
27
build/mac/make_locale_dirs.py
Normal file
@@ -0,0 +1,27 @@
|
||||
# usage: make_locale_dirs.py locale_dir [...]
|
||||
#
|
||||
# This script is intended to create empty locale directories (.lproj) in a
|
||||
# Cocoa .app bundle. The presence of these empty directories is sufficient to
|
||||
# convince Cocoa that the application supports the named localization, even if
|
||||
# an InfoPlist.strings file is not provided. Chrome uses these empty locale
|
||||
# directoires for its helper executable bundles, which do not otherwise
|
||||
# require any direct Cocoa locale support.
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
def main(args):
|
||||
for dirname in args:
|
||||
try:
|
||||
os.makedirs(dirname)
|
||||
except OSError as e:
|
||||
if e.errno == os.errno.EEXIST:
|
||||
# It's OK if it already exists
|
||||
pass
|
||||
else:
|
||||
raise
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.argv[1:])
|
||||
19
build/zip.py
19
build/zip.py
@@ -10,15 +10,26 @@ EXTENSIONS_TO_SKIP = [
|
||||
|
||||
PATHS_TO_SKIP = [
|
||||
'angledata', #Skipping because it is an output of //ui/gl that we don't need
|
||||
'swiftshader', #Skipping because it is an output of //ui/gl that we don't need
|
||||
'./libVkLayer_', #Skipping because these are outputs that we don't need
|
||||
'./VkLayerLayer_', #Skipping because these are outputs that we don't need
|
||||
|
||||
# //chrome/browser:resources depends on this via
|
||||
# //chrome/browser/resources/ssl/ssl_error_assistant, but we don't need to
|
||||
# ship it.
|
||||
'pyproto',
|
||||
]
|
||||
|
||||
def skip_path(dep):
|
||||
def skip_path(dep, dist_zip, target_cpu):
|
||||
# Skip specific paths and extensions as well as the following special case:
|
||||
# snapshot_blob.bin is a dependency of mksnapshot.zip because
|
||||
# v8_context_generator needs it, but this file does not get generated for arm
|
||||
# and arm 64 binaries of mksnapshot since they are built on x64 hardware.
|
||||
# Consumers of arm and arm64 mksnapshot can generate snapshot_blob.bin
|
||||
# themselves by running mksnapshot.
|
||||
should_skip = (
|
||||
any(dep.startswith(path) for path in PATHS_TO_SKIP) or
|
||||
any(dep.endswith(ext) for ext in EXTENSIONS_TO_SKIP))
|
||||
any(dep.endswith(ext) for ext in EXTENSIONS_TO_SKIP) or
|
||||
('arm' in target_cpu and dist_zip == 'mksnapshot.zip' and dep == 'snapshot_blob.bin'))
|
||||
if should_skip:
|
||||
print("Skipping {}".format(dep))
|
||||
return should_skip
|
||||
@@ -43,7 +54,7 @@ def main(argv):
|
||||
else:
|
||||
with zipfile.ZipFile(dist_zip, 'w', zipfile.ZIP_DEFLATED) as z:
|
||||
for dep in dist_files:
|
||||
if skip_path(dep):
|
||||
if skip_path(dep, dist_zip, target_cpu):
|
||||
continue
|
||||
if os.path.isdir(dep):
|
||||
for root, dirs, files in os.walk(dep):
|
||||
|
||||
@@ -8,7 +8,7 @@ declare_args() {
|
||||
# Allow running Electron as a node binary.
|
||||
enable_run_as_node = true
|
||||
|
||||
enable_osr = false
|
||||
enable_osr = true
|
||||
|
||||
enable_view_api = false
|
||||
|
||||
|
||||
@@ -123,8 +123,7 @@ const setDefaultApplicationMenu = () => {
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
role: 'services',
|
||||
submenu: []
|
||||
role: 'services'
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
|
||||
@@ -369,7 +369,6 @@ details.
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `session` [Session](session.md)
|
||||
|
||||
Emitted when Electron has created a new `session`.
|
||||
@@ -399,6 +398,30 @@ non-minimized.
|
||||
This event is guaranteed to be emitted after the `ready` event of `app`
|
||||
gets emitted.
|
||||
|
||||
### Event: 'remote-require'
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `webContents` [WebContents](web-contents.md)
|
||||
* `moduleName` String
|
||||
|
||||
Emitted when `remote.require()` is called in the renderer process of `webContents`.
|
||||
Calling `event.preventDefault()` will prevent the module from being returned.
|
||||
Custom value can be returned by setting `event.returnValue`.
|
||||
|
||||
### Event: 'remote-get-global'
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `webContents` [WebContents](web-contents.md)
|
||||
* `globalName` String
|
||||
|
||||
Emitted when `remote.getGlobal()` is called in the renderer process of `webContents`.
|
||||
Calling `event.preventDefault()` will prevent the global from being returned.
|
||||
Custom value can be returned by setting `event.returnValue`.
|
||||
|
||||
## Methods
|
||||
|
||||
The `app` object has the following methods:
|
||||
@@ -995,7 +1018,7 @@ Returns `Object`:
|
||||
the app as a login item. Defaults to `false`.
|
||||
* `openAsHidden` Boolean (optional) _macOS_ - `true` to open the app as hidden. Defaults to
|
||||
`false`. The user can edit this setting from the System Preferences so
|
||||
`app.getLoginItemStatus().wasOpenedAsHidden` should be checked when the app
|
||||
`app.getLoginItemSettings().wasOpenedAsHidden` should be checked when the app
|
||||
is opened to know the current value. This setting is not available on [MAS builds][mas-builds].
|
||||
* `path` String (optional) _Windows_ - The executable to launch at login.
|
||||
Defaults to `process.execPath`.
|
||||
@@ -1041,6 +1064,11 @@ details. Disabled by default.
|
||||
|
||||
**Note:** Rendering accessibility tree can significantly affect the performance of your app. It should not be enabled by default.
|
||||
|
||||
### `app.showAboutPanel()` _macOS_
|
||||
|
||||
Show the about panel with the values defined in the app's
|
||||
`.plist` file or with the options set via `app.setAboutPanelOptions(options)`.
|
||||
|
||||
### `app.setAboutPanelOptions(options)` _macOS_
|
||||
|
||||
* `options` Object
|
||||
|
||||
@@ -18,6 +18,13 @@ The following `webPreferences` option default values are deprecated in favor of
|
||||
| `nodeIntegration` | `true` | `false` |
|
||||
| `webviewTag` | `nodeIntegration` if set else `true` | `false` |
|
||||
|
||||
## `nativeWindowOpen`
|
||||
|
||||
Child windows opened with the `nativeWindowOpen` option will always have Node.js integration disabled.
|
||||
|
||||
## `webContents.findInPage(text[, options])`
|
||||
|
||||
`wordStart` and `medialCapitalAsWordStart` options are removed.
|
||||
|
||||
# Planned Breaking API Changes (4.0)
|
||||
|
||||
@@ -32,7 +39,7 @@ app.makeSingleInstance(function (argv, cwd) {
|
||||
})
|
||||
// Replace with
|
||||
app.requestSingleInstanceLock()
|
||||
app.on('second-instance', function (argv, cwd) {
|
||||
app.on('second-instance', function (event, argv, cwd) {
|
||||
|
||||
})
|
||||
```
|
||||
@@ -54,6 +61,14 @@ app.getGPUInfo('complete')
|
||||
app.getGPUInfo('basic')
|
||||
```
|
||||
|
||||
## `win_delay_load_hook`
|
||||
|
||||
When building native modules for windows, the `win_delay_load_hook` variable in
|
||||
the module's `binding.gyp` must be true (which is the default). If this hook is
|
||||
not present, then the native module will fail to load on Windows, with an error
|
||||
message like `Cannot find module`. See the [native module
|
||||
guide](/docs/tutorial/using-native-node-modules.md) for more.
|
||||
|
||||
|
||||
# Breaking API Changes (3.0)
|
||||
|
||||
|
||||
@@ -2,9 +2,6 @@
|
||||
|
||||
> Create and control views.
|
||||
|
||||
**Note:** The BrowserView API is currently experimental and may change or be
|
||||
removed in future Electron releases.
|
||||
|
||||
Process: [Main](../glossary.md#main-process)
|
||||
|
||||
A `BrowserView` can be used to embed additional web content into a
|
||||
|
||||
@@ -222,11 +222,11 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
the top left.
|
||||
* `hiddenInset` - Results in a hidden title bar with an alternative look
|
||||
where the traffic light buttons are slightly more inset from the window edge.
|
||||
* `customButtonsOnHover` Boolean (optional) - Draw custom close, minimize,
|
||||
and full screen buttons on macOS frameless windows. These buttons will not
|
||||
display unless hovered over in the top left of the window. These custom
|
||||
buttons prevent issues with mouse events that occur with the standard
|
||||
window toolbar buttons. **Note:** This option is currently experimental.
|
||||
* `customButtonsOnHover` Boolean (optional) - Draw custom close,
|
||||
and minimize buttons on macOS frameless windows. These buttons will not display
|
||||
unless hovered over in the top left of the window. These custom buttons prevent
|
||||
issues with mouse events that occur with the standard window toolbar buttons.
|
||||
**Note:** This option is currently experimental.
|
||||
* `fullscreenWindowTitle` Boolean (optional) - Shows the title in the
|
||||
title bar in full screen mode on macOS for all `titleBarStyle` options.
|
||||
Default is `false`.
|
||||
@@ -270,6 +270,8 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
are more limited. Read more about the option [here](sandbox-option.md).
|
||||
**Note:** This option is currently experimental and may change or be
|
||||
removed in future Electron releases.
|
||||
* `enableRemoteModule` Boolean (optional) - Whether to enable the [`remote`](remote.md) module.
|
||||
Default is `true`.
|
||||
* `session` [Session](session.md#class-session) (optional) - Sets the session used by the
|
||||
page. Instead of passing the Session object directly, you can also choose to
|
||||
use the `partition` option instead, which accepts a partition string. When
|
||||
@@ -349,8 +351,10 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
Console tab. **Note:** This option is currently experimental and may
|
||||
change or be removed in future Electron releases.
|
||||
* `nativeWindowOpen` Boolean (optional) - Whether to use native
|
||||
`window.open()`. Defaults to `false`. **Note:** This option is currently
|
||||
experimental.
|
||||
`window.open()`. If set to `true`, the `webPreferences` of child window
|
||||
will always be the same with parent window, regardless of the parameters
|
||||
passed to `window.open()`. Defaults to `false`. **Note:** This option is
|
||||
currently experimental.
|
||||
* `webviewTag` Boolean (optional) - Whether to enable the [`<webview>` tag](webview-tag.md).
|
||||
Defaults to the value of the `nodeIntegration` option. **Note:** The
|
||||
`preload` script configured for the `<webview>` will have node integration
|
||||
@@ -893,7 +897,18 @@ Closes the currently open [Quick Look][quick-look] panel.
|
||||
* `bounds` [Rectangle](structures/rectangle.md)
|
||||
* `animate` Boolean (optional) _macOS_
|
||||
|
||||
Resizes and moves the window to the supplied bounds
|
||||
Resizes and moves the window to the supplied bounds. Any properties that are not supplied will default to their current values.
|
||||
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
const win = new BrowserWindow()
|
||||
// set all bounds properties
|
||||
win.setBounds({ x: 440, y: 225, width: 800, height: 600 })
|
||||
// set a single bounds property
|
||||
win.setBounds({ width: 200 })
|
||||
// { x: 440, y: 225, width: 200, height: 600 }
|
||||
console.log(win.getBounds())
|
||||
```
|
||||
|
||||
#### `win.getBounds()`
|
||||
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
|
||||
Process: [Main](../glossary.md#main-process), [Renderer](../glossary.md#renderer-process)
|
||||
|
||||
In the renderer process context it depends on the [`remote`](remote.md) module on Linux,
|
||||
it is therefore not available when this module is disabled.
|
||||
|
||||
The following example shows how to write a string to the clipboard:
|
||||
|
||||
```javascript
|
||||
|
||||
@@ -24,6 +24,28 @@ Windows console example:
|
||||
The following environment variables are intended primarily for use at runtime
|
||||
in packaged Electron applications.
|
||||
|
||||
### `NODE_OPTIONS`
|
||||
|
||||
Electron includes support for a subset of Node's [`NODE_OPTIONS`](https://nodejs.org/api/cli.html#cli_node_options_options). The majority are supported with the exception of those which conflict with Chromium's use of BoringSSL.
|
||||
|
||||
Example:
|
||||
|
||||
```sh
|
||||
export NODE_OPTIONS="--no-warnings --max-old-space-size=2048"
|
||||
```
|
||||
|
||||
Unsupported options are:
|
||||
|
||||
```sh
|
||||
--use-bundled-ca
|
||||
--force-fips
|
||||
--enable-fips
|
||||
--openssl-config
|
||||
--use-openssl-ca
|
||||
```
|
||||
|
||||
`NODE_OPTIONS` are explicitly disallowed in packaged apps.
|
||||
|
||||
### `GOOGLE_API_KEY`
|
||||
|
||||
Electron includes a hardcoded API key for making requests to Google's geocoding
|
||||
@@ -58,6 +80,16 @@ Don't attach to the current console session.
|
||||
|
||||
Don't use the global menu bar on Linux.
|
||||
|
||||
### `ELECTRON_TRASH` _Linux_
|
||||
|
||||
Set the trash implementation on Linux. Default is `gio`.
|
||||
|
||||
Options:
|
||||
* `gvfs-trash`
|
||||
* `trash-cli`
|
||||
* `kioclient5`
|
||||
* `kioclient`
|
||||
|
||||
## Development Variables
|
||||
|
||||
The following environment variables are intended primarily for development and
|
||||
|
||||
@@ -21,11 +21,10 @@ win.show()
|
||||
|
||||
### Alternatives on macOS
|
||||
|
||||
On macOS 10.9 Mavericks and newer, there's an alternative way to specify
|
||||
a chromeless window. Instead of setting `frame` to `false` which disables
|
||||
both the titlebar and window controls, you may want to have the title bar
|
||||
hidden and your content extend to the full window size, yet still preserve
|
||||
the window controls ("traffic lights") for standard window actions.
|
||||
There's an alternative way to specify a chromeless window.
|
||||
Instead of setting `frame` to `false` which disables both the titlebar and window controls,
|
||||
you may want to have the title bar hidden and your content extend to the full window size,
|
||||
yet still preserve the window controls ("traffic lights") for standard window actions.
|
||||
You can do so by specifying the `titleBarStyle` option:
|
||||
|
||||
#### `hidden`
|
||||
@@ -50,10 +49,12 @@ win.show()
|
||||
|
||||
#### `customButtonsOnHover`
|
||||
|
||||
Uses custom drawn close, miniaturize, and fullscreen buttons that display
|
||||
when hovering in the top left of the window. These custom buttons prevent issues
|
||||
with mouse events that occur with the standard window toolbar buttons. This
|
||||
option is only applicable for frameless windows.
|
||||
Uses custom drawn close, and miniaturize buttons that display
|
||||
when hovering in the top left of the window. The fullscreen button
|
||||
is not available due to restrictions of frameless windows as they
|
||||
interface with Apple's MacOS window masks. These custom buttons prevent
|
||||
issues with mouse events that occur with the standard window toolbar buttons.
|
||||
This option is only applicable for frameless windows.
|
||||
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
|
||||
@@ -74,13 +74,13 @@ and replies by setting `event.returnValue`.
|
||||
**Note:** Sending a synchronous message will block the whole renderer process,
|
||||
unless you know what you are doing you should never use it.
|
||||
|
||||
### `ipcRenderer.sendTo(windowId, channel, [, arg1][, arg2][, ...])`
|
||||
### `ipcRenderer.sendTo(webContentsId, channel, [, arg1][, arg2][, ...])`
|
||||
|
||||
* `windowId` Number
|
||||
* `webContentsId` Number
|
||||
* `channel` String
|
||||
* `...args` any[]
|
||||
|
||||
Sends a message to a window with `windowid` via `channel`.
|
||||
Sends a message to a window with `webContentsId` via `channel`.
|
||||
|
||||
### `ipcRenderer.sendToHost(channel[, arg1][, arg2][, ...])`
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@ See [`Menu`](menu.md) for examples.
|
||||
* `visible` Boolean (optional) - If false, the menu item will be entirely hidden.
|
||||
* `checked` Boolean (optional) - Should only be specified for `checkbox` or `radio` type
|
||||
menu items.
|
||||
* `registerAccelerator` Boolean (optional) - If false, the accelerator won't be registered
|
||||
with the system, but it will still be displayed. Defaults to true.
|
||||
* `submenu` (MenuItemConstructorOptions[] | [Menu](menu.md)) (optional) - Should be specified
|
||||
for `submenu` type menu items. If `submenu` is specified, the `type: 'submenu'` can be omitted.
|
||||
If the value is not a [`Menu`](menu.md) then it will be automatically converted to one using
|
||||
@@ -108,6 +110,8 @@ When specifying a `role` on macOS, `label` and `accelerator` are the only
|
||||
options that will affect the menu item. All other options will be ignored.
|
||||
Lowercase `role`, e.g. `toggledevtools`, is still supported.
|
||||
|
||||
**Nota Bene:** The `enabled` and `visibility` properties are not available for top-level menu items in the tray on MacOS.
|
||||
|
||||
### Instance Properties
|
||||
|
||||
The following properties are available on instances of `MenuItem`:
|
||||
|
||||
@@ -204,7 +204,7 @@ if (process.platform === 'darwin') {
|
||||
submenu: [
|
||||
{ role: 'about' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'services', submenu: [] },
|
||||
{ role: 'services' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'hide' },
|
||||
{ role: 'hideothers' },
|
||||
|
||||
@@ -169,6 +169,7 @@ should be called with either a `String` or an object that has the `data`,
|
||||
* `handler` Function
|
||||
* `request` Object
|
||||
* `url` String
|
||||
* `headers` Object
|
||||
* `referrer` String
|
||||
* `method` String
|
||||
* `uploadData` [UploadData[]](structures/upload-data.md)
|
||||
@@ -329,6 +330,7 @@ which sends a `Buffer` as a response.
|
||||
* `handler` Function
|
||||
* `request` Object
|
||||
* `url` String
|
||||
* `headers` Object
|
||||
* `referrer` String
|
||||
* `method` String
|
||||
* `uploadData` [UploadData[]](structures/upload-data.md)
|
||||
|
||||
@@ -24,6 +24,10 @@ win.loadURL('https://github.com')
|
||||
**Note:** For the reverse (access the renderer process from the main process),
|
||||
you can use [webContents.executeJavaScript](web-contents.md#contentsexecutejavascriptcode-usergesture-callback).
|
||||
|
||||
**Note:** The remote module can be disabled for security reasons in the following contexts:
|
||||
- [`BrowserWindow`](browser-window.md) - by setting the `enableRemoteModule` option to `false`.
|
||||
- [`<webview>`](webview-tag.md) - by setting the `enableremotemodule` attribute to `false`.
|
||||
|
||||
## Remote Objects
|
||||
|
||||
Each object (including functions) returned by the `remote` module represents an
|
||||
@@ -180,7 +184,7 @@ belongs.
|
||||
**Note:** Do not use `removeAllListeners` on [`BrowserWindow`](browser-window.md).
|
||||
Use of this can remove all [`blur`](https://developer.mozilla.org/en-US/docs/Web/Events/blur)
|
||||
listeners, disable click events on touch bar buttons, and other unintended
|
||||
consequences.
|
||||
consequences.
|
||||
|
||||
### `remote.getCurrentWebContents()`
|
||||
|
||||
|
||||
@@ -7,6 +7,9 @@ Process: [Main](../glossary.md#main-process), [Renderer](../glossary.md#renderer
|
||||
You cannot require or use this module until the `ready` event of the `app`
|
||||
module is emitted.
|
||||
|
||||
In the renderer process context it depends on the [`remote`](remote.md) module,
|
||||
it is therefore not available when this module is disabled.
|
||||
|
||||
`screen` is an [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter).
|
||||
|
||||
**Note:** In the renderer / DevTools, `window.screen` is a reserved DOM
|
||||
|
||||
@@ -83,6 +83,8 @@ that contains the user information dictionary sent along with the notification.
|
||||
* `callback` Function
|
||||
* `event` String
|
||||
* `userInfo` Object
|
||||
|
||||
Returns `Number` - The ID of this subscription
|
||||
|
||||
Subscribes to native notifications of macOS, `callback` will be called with
|
||||
`callback(event, userInfo)` when the corresponding `event` happens. The
|
||||
@@ -106,6 +108,8 @@ example values of `event` are:
|
||||
* `callback` Function
|
||||
* `event` String
|
||||
* `userInfo` Object
|
||||
|
||||
Returns `Number` - The ID of this subscription
|
||||
|
||||
Same as `subscribeNotification`, but uses `NSNotificationCenter` for local defaults.
|
||||
This is necessary for events such as `NSUserDefaultsDidChangeNotification`.
|
||||
@@ -298,7 +302,6 @@ using `electron-packager` or `electron-forge` just set the `enableDarwinDarkMode
|
||||
packager option to `true`. See the [Electron Packager API](https://github.com/electron-userland/electron-packager/blob/master/docs/api.md#darwindarkmodesupport)
|
||||
for more details.
|
||||
|
||||
|
||||
### `systemPreferences.getAppLevelAppearance()` _macOS_
|
||||
|
||||
Returns `String` | `null` - Can be `dark`, `light` or `unknown`.
|
||||
@@ -313,3 +316,21 @@ You can use the `setAppLevelAppearance` API to set this value.
|
||||
|
||||
Sets the appearance setting for your application, this should override the
|
||||
system default and override the value of `getEffectiveAppearance`.
|
||||
|
||||
### `systemPreferences.getMediaAccessStatus(mediaType)` _macOS_
|
||||
|
||||
* `mediaType` String - `microphone` or `camera`.
|
||||
|
||||
Returns `String` - Can be `not-determined`, `granted`, `denied`, `restricted` or `unknown`.
|
||||
|
||||
This user consent was not required until macOS 10.14 Mojave, so this method will always return `granted` if your system is running 10.13 High Sierra or lower.
|
||||
|
||||
### `systemPreferences.askForMediaAccess(mediaType)` _macOS_
|
||||
|
||||
* `mediaType` String - the type of media being requested; can be `microphone`, `camera`.
|
||||
|
||||
Returns `Promise<Boolean>` - A promise that resolves with `true` if consent was granted and `false` if it was denied. If an invalid `mediaType` is passed, the promise will be rejected. If an access request was denied and later is changed through the System Preferences pane, a restart of the app will be required for the new permissions to take effect. If access has already been requested and denied, it _must_ be changed through the preference pane; an alert will not pop up and the promise will resolve with the existing access status.
|
||||
|
||||
**Important:** In order to properly leverage this API, you [must set](https://developer.apple.com/documentation/avfoundation/cameras_and_media_capture/requesting_authorization_for_media_capture_on_macos?language=objc) the `NSMicrophoneUsageDescription` and `NSCameraUsageDescription` strings in your app's `Info.plist` file. The values for these keys will be used to populate the permission dialogs so that the user will be properly informed as to the purpose of the permission request. See [Electron Application Distribution](https://electronjs.org/docs/tutorial/application-distribution#macos) for more information about how to set these in the context of Electron.
|
||||
|
||||
This user consent was not required until macOS 10.14 Mojave, so this method will always return `true` if your system is running 10.13 High Sierra or lower.
|
||||
@@ -663,6 +663,28 @@ Returns:
|
||||
Emitted when the associated window logs a console message. Will not be emitted
|
||||
for windows with *offscreen rendering* enabled.
|
||||
|
||||
#### Event: 'remote-require'
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `moduleName` String
|
||||
|
||||
Emitted when `remote.require()` is called in the renderer process.
|
||||
Calling `event.preventDefault()` will prevent the module from being returned.
|
||||
Custom value can be returned by setting `event.returnValue`.
|
||||
|
||||
#### Event: 'remote-get-global'
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `globalName` String
|
||||
|
||||
Emitted when `remote.getGlobal()` is called in the renderer process.
|
||||
Calling `event.preventDefault()` will prevent the global from being returned.
|
||||
Custom value can be returned by setting `event.returnValue`.
|
||||
|
||||
### Instance Methods
|
||||
|
||||
#### `contents.loadURL(url[, options])`
|
||||
@@ -994,9 +1016,9 @@ Inserts `text` to the focused element.
|
||||
defaults to `false`.
|
||||
* `matchCase` Boolean (optional) - Whether search should be case-sensitive,
|
||||
defaults to `false`.
|
||||
* `wordStart` Boolean (optional) - Whether to look only at the start of words.
|
||||
* `wordStart` Boolean (optional) (Deprecated) - Whether to look only at the start of words.
|
||||
defaults to `false`.
|
||||
* `medialCapitalAsWordStart` Boolean (optional) - When combined with `wordStart`,
|
||||
* `medialCapitalAsWordStart` Boolean (optional) (Deprecated) - When combined with `wordStart`,
|
||||
accepts a match in the middle of a word if the match begins with an
|
||||
uppercase letter followed by a lowercase or non-letter.
|
||||
Accepts several other intra-word matches, defaults to `false`.
|
||||
@@ -1084,7 +1106,7 @@ Use `page-break-before: always; ` CSS style to force to print to a new page.
|
||||
* `options` Object
|
||||
* `marginsType` Integer (optional) - Specifies the type of margins to use. Uses 0 for
|
||||
default margin, 1 for no margin, and 2 for minimum margin.
|
||||
* `pageSize` String (optional) - Specify page size of the generated PDF. Can be `A3`,
|
||||
* `pageSize` String | Size (optional) - Specify page size of the generated PDF. Can be `A3`,
|
||||
`A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height`
|
||||
and `width` in microns.
|
||||
* `printBackground` Boolean (optional) - Whether to print CSS backgrounds.
|
||||
@@ -1505,6 +1527,13 @@ Returns `Promise<void>` - Indicates whether the snapshot has been created succes
|
||||
|
||||
Takes a V8 heap snapshot and saves it to `filePath`.
|
||||
|
||||
#### `contents.setBackgroundThrottling(allowed)`
|
||||
|
||||
* `allowed` Boolean
|
||||
|
||||
Controls whether or not this WebContents will throttle animations and timers
|
||||
when the page becomes backgrounded. This also affects the Page Visibility API.
|
||||
|
||||
### Instance Properties
|
||||
|
||||
#### `contents.id`
|
||||
|
||||
@@ -126,6 +126,15 @@ integration and can use node APIs like `require` and `process` to access low
|
||||
level system resources. Node integration is disabled by default in the guest
|
||||
page.
|
||||
|
||||
### `enableremotemodule`
|
||||
|
||||
```html
|
||||
<webview src="http://www.google.com/" enableremotemodule="false"></webview>
|
||||
```
|
||||
|
||||
When this attribute is `false` the guest page in `webview` will not have access
|
||||
to the [`remote`](remote.md) module. The remote module is avaiable by default.
|
||||
|
||||
### `plugins`
|
||||
|
||||
```html
|
||||
@@ -517,7 +526,7 @@ Prints `webview`'s web page. Same as `webContents.print([options])`.
|
||||
* `options` Object
|
||||
* `marginsType` Integer (optional) - Specifies the type of margins to use. Uses 0 for
|
||||
default margin, 1 for no margin, and 2 for minimum margin.
|
||||
* `pageSize` String (optional) - Specify page size of the generated PDF. Can be `A3`,
|
||||
* `pageSize` String | Size (optional) - Specify page size of the generated PDF. Can be `A3`,
|
||||
`A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height`
|
||||
and `width` in microns.
|
||||
* `printBackground` Boolean (optional) - Whether to print CSS backgrounds.
|
||||
@@ -613,6 +622,9 @@ Shows pop-up dictionary that searches the selected word on the page.
|
||||
Returns [`WebContents`](web-contents.md) - The web contents associated with
|
||||
this `webview`.
|
||||
|
||||
It depends on the [`remote`](remote.md) module,
|
||||
it is therefore not available when this module is disabled.
|
||||
|
||||
## DOM events
|
||||
|
||||
The following DOM events are available to the `webview` tag:
|
||||
|
||||
@@ -7,7 +7,7 @@ rudimentary understanding of your operating system's command line client.
|
||||
|
||||
## Setting up macOS
|
||||
|
||||
> Electron supports Mac OS X 10.9 (and all versions named macOS) and up. Apple
|
||||
> Electron supports macOS 10.10 (Yosemite) and up. Apple
|
||||
does not allow running macOS in virtual machines unless the host computer is
|
||||
already an Apple computer, so if you find yourself in need of a Mac, consider
|
||||
using a cloud service that rents access to Macs (like [MacInCloud][macincloud]
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user