mirror of
https://github.com/electron/electron.git
synced 2026-02-26 03:01:17 -05:00
Compare commits
200 Commits
v2.0.0-bet
...
v2.0.11
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3f6d86c872 | ||
|
|
bdc9faa083 | ||
|
|
3e35f77da4 | ||
|
|
464f144a2b | ||
|
|
8f92396ed4 | ||
|
|
4e41a79404 | ||
|
|
d3c153e85a | ||
|
|
503b488153 | ||
|
|
005a65da79 | ||
|
|
36da7dcd5f | ||
|
|
0e5f734a1a | ||
|
|
3aeaf10e64 | ||
|
|
d70942190c | ||
|
|
ac400e5cb9 | ||
|
|
333d5fb5d2 | ||
|
|
f2c12ccbf5 | ||
|
|
79af1ea6f1 | ||
|
|
1ed7875b0b | ||
|
|
67a690e536 | ||
|
|
5f3bedd1e0 | ||
|
|
670a875792 | ||
|
|
faf82245dc | ||
|
|
066eeb5b5f | ||
|
|
77ec86b894 | ||
|
|
bf82dc7896 | ||
|
|
b4c5a30469 | ||
|
|
7ed6e2b909 | ||
|
|
8edd18be90 | ||
|
|
3bc9ae7f5b | ||
|
|
760c2327b4 | ||
|
|
fcb5069d24 | ||
|
|
221ab080a1 | ||
|
|
addf069f26 | ||
|
|
80221e52d9 | ||
|
|
3403b4a4de | ||
|
|
a1ac930f4d | ||
|
|
ed8396c6f5 | ||
|
|
a457d8823a | ||
|
|
2d44dcb8be | ||
|
|
85da731867 | ||
|
|
3af5fdb831 | ||
|
|
f1b197acbb | ||
|
|
d483c81887 | ||
|
|
3ef980ae2b | ||
|
|
36e68b46df | ||
|
|
f611dfdb5c | ||
|
|
148d0d8d29 | ||
|
|
79a1382126 | ||
|
|
b0d5ba1996 | ||
|
|
088dc70dae | ||
|
|
ad686cca68 | ||
|
|
48a4b58cc1 | ||
|
|
c1ef824e4c | ||
|
|
a2eb532720 | ||
|
|
0cb53ceb9d | ||
|
|
afe4e610ae | ||
|
|
74d90fbb33 | ||
|
|
f3bd8f6133 | ||
|
|
863c511fbf | ||
|
|
03d8689ded | ||
|
|
ff2bc1d705 | ||
|
|
a1df8befde | ||
|
|
75909685f7 | ||
|
|
2e0a015168 | ||
|
|
740b2797c5 | ||
|
|
5f372f7ecc | ||
|
|
e4f4a1d9f9 | ||
|
|
bdc255fa9e | ||
|
|
e8e542b3e8 | ||
|
|
dd89aa6c77 | ||
|
|
79caff69f5 | ||
|
|
67b10135b6 | ||
|
|
6a86831b7c | ||
|
|
dffd17ab70 | ||
|
|
cf98934dd9 | ||
|
|
2fff138740 | ||
|
|
82bc83c1de | ||
|
|
3a699741da | ||
|
|
237ad9a49d | ||
|
|
45158bdad5 | ||
|
|
cf4861b575 | ||
|
|
a76adba2b3 | ||
|
|
6689dce5ba | ||
|
|
9667b835ca | ||
|
|
58295a3198 | ||
|
|
b60125f782 | ||
|
|
2af6d9ced7 | ||
|
|
664c184fcb | ||
|
|
c125576d48 | ||
|
|
6030146b45 | ||
|
|
17297d85f8 | ||
|
|
65bbf21c08 | ||
|
|
00da6ab43b | ||
|
|
d6d2a46821 | ||
|
|
423bdda1b1 | ||
|
|
849aeced8f | ||
|
|
05a7485880 | ||
|
|
3db1b5a49a | ||
|
|
1c272503c3 | ||
|
|
1ebb8975a8 | ||
|
|
fcf4c9cef1 | ||
|
|
3e5349bf39 | ||
|
|
66988adb0e | ||
|
|
91be3f343f | ||
|
|
475006c10d | ||
|
|
d71a7d89bb | ||
|
|
abcba2b509 | ||
|
|
d06c20f836 | ||
|
|
3ab99663eb | ||
|
|
a253323ea1 | ||
|
|
4abe5a2963 | ||
|
|
aada5fb167 | ||
|
|
4efed0f5ed | ||
|
|
475a1e30d9 | ||
|
|
4aedc2c21a | ||
|
|
71668858db | ||
|
|
2573d52860 | ||
|
|
989c2605b3 | ||
|
|
afcfd473d0 | ||
|
|
1499bafe59 | ||
|
|
419fae76b4 | ||
|
|
c7b85a104a | ||
|
|
c6ea424858 | ||
|
|
ba23c0d600 | ||
|
|
d4e716477e | ||
|
|
34dbe5f176 | ||
|
|
a09fa53d80 | ||
|
|
c140c84b32 | ||
|
|
55ab1d7370 | ||
|
|
cfa247967f | ||
|
|
311f7ac6bb | ||
|
|
52a44facfd | ||
|
|
5acb7a0226 | ||
|
|
afcf94a85c | ||
|
|
c42b468966 | ||
|
|
e0257acdf5 | ||
|
|
b555434aa0 | ||
|
|
9574a4f472 | ||
|
|
2f167ce3d1 | ||
|
|
8655d5e9ae | ||
|
|
2e06e0eccd | ||
|
|
773f08ca43 | ||
|
|
13850b9dff | ||
|
|
1c57c76496 | ||
|
|
e459b38c5d | ||
|
|
9796513b83 | ||
|
|
d3e5f430c7 | ||
|
|
df22eccfc1 | ||
|
|
214c352f71 | ||
|
|
0070637b5a | ||
|
|
72b944f862 | ||
|
|
2fbb371689 | ||
|
|
e2e70e9b1e | ||
|
|
324b769751 | ||
|
|
e1d54d55be | ||
|
|
1d54032ba4 | ||
|
|
c6e4de16de | ||
|
|
f39cc1cc46 | ||
|
|
6af89eb260 | ||
|
|
d33b71cc2d | ||
|
|
d0bbf3fb3c | ||
|
|
289db66fee | ||
|
|
6b90807cb8 | ||
|
|
cf4f078aca | ||
|
|
4eedd1455d | ||
|
|
9c167b63f2 | ||
|
|
d18ab0ca08 | ||
|
|
724cbc967c | ||
|
|
b9d589439f | ||
|
|
f37bc4a9d4 | ||
|
|
597c8964f6 | ||
|
|
652f83fc88 | ||
|
|
d432038aab | ||
|
|
5d8f36c53c | ||
|
|
85dfdd6665 | ||
|
|
de428ebec0 | ||
|
|
c6c49b9e4b | ||
|
|
98495fabfb | ||
|
|
06c33c7e56 | ||
|
|
33aad6ae11 | ||
|
|
6c00b37dd1 | ||
|
|
d209e59c30 | ||
|
|
14f8a2a0e8 | ||
|
|
65e1252da0 | ||
|
|
2903d7608c | ||
|
|
0bc72961ab | ||
|
|
b55a24c025 | ||
|
|
51bca764f7 | ||
|
|
35976a0a07 | ||
|
|
283ab23524 | ||
|
|
2343f7c287 | ||
|
|
8991ad31d8 | ||
|
|
fae6167308 | ||
|
|
bd25a5f453 | ||
|
|
c80021924e | ||
|
|
0cc4584352 | ||
|
|
706f0c436d | ||
|
|
663e1e059b | ||
|
|
433aba34e6 | ||
|
|
bd33e7198e |
@@ -64,13 +64,17 @@ jobs:
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ] && [ "$AUTO_RELEASE" == "true" ]; then
|
||||
echo 'Trying to finish release'
|
||||
node script/release.js --automaticRelease
|
||||
node script/release.js --validateRelease --automaticRelease
|
||||
releaseExitCode=$?
|
||||
if [ $releaseExitCode -eq 0 ]; then
|
||||
echo 'Release successful, now publishing to npm'
|
||||
echo "//registry.npmjs.org/:_authToken=$ELECTRON_NPM_TOKEN" >> ~/.npmrc
|
||||
npm run publish-to-npm
|
||||
echo 'Release has been published to npm'
|
||||
echo 'Release is ready to go; releasing'
|
||||
node script/release.js--automaticRelease
|
||||
if [ $releaseExitCode -eq 0 ]; then
|
||||
echo 'Release successful, now publishing to npm'
|
||||
echo "//registry.npmjs.org/:_authToken=$ELECTRON_NPM_TOKEN" >> ~/.npmrc
|
||||
npm run publish-to-npm
|
||||
echo 'Release has been published to npm'
|
||||
fi
|
||||
else
|
||||
echo 'Release is not complete, skipping publish for now'
|
||||
fi
|
||||
@@ -176,13 +180,17 @@ jobs:
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ] && [ "$AUTO_RELEASE" == "true" ]; then
|
||||
echo 'Trying to finish release'
|
||||
node script/release.js --automaticRelease
|
||||
node script/release.js --validateRelease --automaticRelease
|
||||
releaseExitCode=$?
|
||||
if [ $releaseExitCode -eq 0 ]; then
|
||||
echo 'Release successful, now publishing to npm'
|
||||
echo "//registry.npmjs.org/:_authToken=$ELECTRON_NPM_TOKEN" >> ~/.npmrc
|
||||
npm run publish-to-npm
|
||||
echo 'Release has been published to npm'
|
||||
echo 'Release is ready to go; releasing'
|
||||
node script/release.js--automaticRelease
|
||||
if [ $releaseExitCode -eq 0 ]; then
|
||||
echo 'Release successful, now publishing to npm'
|
||||
echo "//registry.npmjs.org/:_authToken=$ELECTRON_NPM_TOKEN" >> ~/.npmrc
|
||||
npm run publish-to-npm
|
||||
echo 'Release has been published to npm'
|
||||
fi
|
||||
else
|
||||
echo 'Release is not complete, skipping publish for now'
|
||||
fi
|
||||
@@ -292,13 +300,17 @@ jobs:
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ] && [ "$AUTO_RELEASE" == "true" ]; then
|
||||
echo 'Trying to finish release'
|
||||
node script/release.js --automaticRelease
|
||||
node script/release.js --validateRelease --automaticRelease
|
||||
releaseExitCode=$?
|
||||
if [ $releaseExitCode -eq 0 ]; then
|
||||
echo 'Release successful, now publishing to npm'
|
||||
echo "//registry.npmjs.org/:_authToken=$ELECTRON_NPM_TOKEN" >> ~/.npmrc
|
||||
npm run publish-to-npm
|
||||
echo 'Release has been published to npm'
|
||||
echo 'Release is ready to go; releasing'
|
||||
node script/release.js--automaticRelease
|
||||
if [ $releaseExitCode -eq 0 ]; then
|
||||
echo 'Release successful, now publishing to npm'
|
||||
echo "//registry.npmjs.org/:_authToken=$ELECTRON_NPM_TOKEN" >> ~/.npmrc
|
||||
npm run publish-to-npm
|
||||
echo 'Release has been published to npm'
|
||||
fi
|
||||
else
|
||||
echo 'Release is not complete, skipping publish for now'
|
||||
fi
|
||||
@@ -391,13 +403,17 @@ jobs:
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ] && [ "$AUTO_RELEASE" == "true" ]; then
|
||||
echo 'Trying to finish release'
|
||||
node script/release.js --automaticRelease
|
||||
node script/release.js --validateRelease --automaticRelease
|
||||
releaseExitCode=$?
|
||||
if [ $releaseExitCode -eq 0 ]; then
|
||||
echo 'Release successful, now publishing to npm'
|
||||
echo "//registry.npmjs.org/:_authToken=$ELECTRON_NPM_TOKEN" >> ~/.npmrc
|
||||
npm run publish-to-npm
|
||||
echo 'Release has been published to npm'
|
||||
echo 'Release is ready to go; releasing'
|
||||
node script/release.js--automaticRelease
|
||||
if [ $releaseExitCode -eq 0 ]; then
|
||||
echo 'Release successful, now publishing to npm'
|
||||
echo "//registry.npmjs.org/:_authToken=$ELECTRON_NPM_TOKEN" >> ~/.npmrc
|
||||
npm run publish-to-npm
|
||||
echo 'Release has been published to npm'
|
||||
fi
|
||||
else
|
||||
echo 'Release is not complete, skipping publish for now'
|
||||
fi
|
||||
@@ -472,13 +488,17 @@ jobs:
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ] && [ "$AUTO_RELEASE" == "true" ]; then
|
||||
echo 'Trying to finish release'
|
||||
node script/release.js --automaticRelease
|
||||
node script/release.js --validateRelease --automaticRelease
|
||||
releaseExitCode=$?
|
||||
if [ $releaseExitCode -eq 0 ]; then
|
||||
echo 'Release successful, now publishing to npm'
|
||||
echo "//registry.npmjs.org/:_authToken=$ELECTRON_NPM_TOKEN" >> ~/.npmrc
|
||||
npm run publish-to-npm
|
||||
echo 'Release has been published to npm'
|
||||
echo 'Release is ready to go; releasing'
|
||||
node script/release.js--automaticRelease
|
||||
if [ $releaseExitCode -eq 0 ]; then
|
||||
echo 'Release successful, now publishing to npm'
|
||||
echo "//registry.npmjs.org/:_authToken=$ELECTRON_NPM_TOKEN" >> ~/.npmrc
|
||||
npm run publish-to-npm
|
||||
echo 'Release has been published to npm'
|
||||
fi
|
||||
else
|
||||
echo 'Release is not complete, skipping publish for now'
|
||||
fi
|
||||
@@ -519,6 +539,201 @@ jobs:
|
||||
- store_artifacts:
|
||||
path: out/electron-api.json
|
||||
|
||||
electron-osx-x64:
|
||||
environment:
|
||||
TARGET_ARCH: x64
|
||||
macos:
|
||||
xcode: "9.0"
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Reclaim disk space
|
||||
command: |
|
||||
df -h
|
||||
sudo rm -rf /Library/Developer/CoreSimulator
|
||||
df -h
|
||||
sysctl -n hw.ncpu
|
||||
- run:
|
||||
name: Check for release
|
||||
command: |
|
||||
if [ -n "${RUN_RELEASE_BUILD}" ]; then
|
||||
echo 'release build triggered from api'
|
||||
echo 'export ELECTRON_RELEASE=1 TRIGGERED_BY_API=1' >> $BASH_ENV
|
||||
fi
|
||||
- run:
|
||||
name: Bootstrap
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ]; then
|
||||
echo 'Bootstrapping Electron for release build'
|
||||
script/bootstrap.py --target_arch=$TARGET_ARCH
|
||||
else
|
||||
echo 'Bootstrapping Electron for debug build'
|
||||
script/bootstrap.py --target_arch=$TARGET_ARCH --dev
|
||||
fi
|
||||
- run: npm run lint
|
||||
- run:
|
||||
name: Build
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ]; then
|
||||
echo 'Building Electron for release'
|
||||
script/build.py -c R
|
||||
else
|
||||
echo 'Building Electron for debug'
|
||||
script/build.py -c D
|
||||
fi
|
||||
- run:
|
||||
name: Create distribution
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ]; then
|
||||
echo 'Creating Electron release distribution'
|
||||
script/create-dist.py
|
||||
else
|
||||
echo 'Skipping create distribution because build is not for release'
|
||||
fi
|
||||
- run:
|
||||
name: Upload distribution
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ] && [ "$TRIGGERED_BY_API" != "1" ]; then
|
||||
echo 'Uploading Electron release distribution to github releases'
|
||||
script/upload.py
|
||||
elif [ "$ELECTRON_RELEASE" == "1" ] && [ "$TRIGGERED_BY_API" == "1" ]; then
|
||||
echo 'Uploading Electron release distribution to s3'
|
||||
script/upload.py --upload_to_s3
|
||||
else
|
||||
echo 'Skipping upload distribution because build is not for release'
|
||||
fi
|
||||
- run:
|
||||
name: Test
|
||||
environment:
|
||||
MOCHA_FILE: junit/test-results.xml
|
||||
MOCHA_REPORTER: mocha-junit-reporter
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" != "1" ]; then
|
||||
echo 'Testing Electron debug build'
|
||||
mkdir junit
|
||||
script/test.py --ci --rebuild_native_modules
|
||||
else
|
||||
echo 'Skipping testing on release build'
|
||||
fi
|
||||
- run:
|
||||
name: Verify FFmpeg
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" != "1" ]; then
|
||||
echo 'Verifying ffmpeg on debug build'
|
||||
script/verify-ffmpeg.py
|
||||
else
|
||||
echo 'Skipping verify ffmpeg on release build'
|
||||
fi
|
||||
- run:
|
||||
name: Generate Typescript Definitions
|
||||
command: npm run create-typescript-definitions
|
||||
- store_test_results:
|
||||
path: junit
|
||||
- store_artifacts:
|
||||
path: junit
|
||||
- store_artifacts:
|
||||
path: out/electron.d.ts
|
||||
- store_artifacts:
|
||||
path: out/electron-api.json
|
||||
|
||||
electron-mas-x64:
|
||||
environment:
|
||||
TARGET_ARCH: x64
|
||||
MAS_BUILD: 1
|
||||
macos:
|
||||
xcode: "9.0"
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Reclaim disk space
|
||||
command: |
|
||||
df -h
|
||||
sudo rm -rf /Library/Developer/CoreSimulator
|
||||
df -h
|
||||
sysctl -n hw.ncpu
|
||||
- run:
|
||||
name: Check for release
|
||||
command: |
|
||||
if [ -n "${RUN_RELEASE_BUILD}" ]; then
|
||||
echo 'release build triggered from api'
|
||||
echo 'export ELECTRON_RELEASE=1 TRIGGERED_BY_API=1' >> $BASH_ENV
|
||||
fi
|
||||
- run:
|
||||
name: Bootstrap
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ]; then
|
||||
echo 'Bootstrapping Electron for release build'
|
||||
script/bootstrap.py --target_arch=$TARGET_ARCH
|
||||
else
|
||||
echo 'Bootstrapping Electron for debug build'
|
||||
script/bootstrap.py --target_arch=$TARGET_ARCH --dev
|
||||
fi
|
||||
- run: npm run lint
|
||||
- run:
|
||||
name: Build
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ]; then
|
||||
echo 'Building Electron for release'
|
||||
script/build.py -c R
|
||||
else
|
||||
echo 'Building Electron for debug'
|
||||
script/build.py -c D
|
||||
fi
|
||||
- run:
|
||||
name: Create distribution
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ]; then
|
||||
echo 'Creating Electron release distribution'
|
||||
script/create-dist.py
|
||||
else
|
||||
echo 'Skipping create distribution because build is not for release'
|
||||
fi
|
||||
- run:
|
||||
name: Upload distribution
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ] && [ "$TRIGGERED_BY_API" != "1" ]; then
|
||||
echo 'Uploading Electron release distribution to github releases'
|
||||
script/upload.py
|
||||
elif [ "$ELECTRON_RELEASE" == "1" ] && [ "$TRIGGERED_BY_API" == "1" ]; then
|
||||
echo 'Uploading Electron release distribution to s3'
|
||||
script/upload.py --upload_to_s3
|
||||
else
|
||||
echo 'Skipping upload distribution because build is not for release'
|
||||
fi
|
||||
- run:
|
||||
name: Test
|
||||
environment:
|
||||
MOCHA_FILE: junit/test-results.xml
|
||||
MOCHA_REPORTER: mocha-junit-reporter
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" != "1" ]; then
|
||||
echo 'Testing Electron debug build'
|
||||
mkdir junit
|
||||
script/test.py --ci --rebuild_native_modules
|
||||
else
|
||||
echo 'Skipping testing on release build'
|
||||
fi
|
||||
- run:
|
||||
name: Verify FFmpeg
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" != "1" ]; then
|
||||
echo 'Verifying ffmpeg on debug build'
|
||||
script/verify-ffmpeg.py
|
||||
else
|
||||
echo 'Skipping verify ffmpeg on release build'
|
||||
fi
|
||||
- run:
|
||||
name: Generate Typescript Definitions
|
||||
command: npm run create-typescript-definitions
|
||||
- store_test_results:
|
||||
path: junit
|
||||
- store_artifacts:
|
||||
path: junit
|
||||
- store_artifacts:
|
||||
path: out/electron.d.ts
|
||||
- store_artifacts:
|
||||
path: out/electron-api.json
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
build-arm:
|
||||
@@ -537,5 +752,11 @@ workflows:
|
||||
jobs:
|
||||
- electron-linux-ia32
|
||||
build-x64:
|
||||
jobs:
|
||||
- electron-linux-x64
|
||||
jobs:
|
||||
- electron-linux-x64
|
||||
build-osx-x64:
|
||||
jobs:
|
||||
- electron-osx-x64
|
||||
build-mas-x64:
|
||||
jobs:
|
||||
- electron-mas-x64
|
||||
|
||||
7
.env.example
Normal file
7
.env.example
Normal file
@@ -0,0 +1,7 @@
|
||||
# These env vars are only necessary for creating Electron releases.
|
||||
# See docs/development/releasing.md
|
||||
|
||||
APPVEYOR_TOKEN=
|
||||
CIRCLE_TOKEN=
|
||||
ELECTRON_GITHUB_TOKEN=
|
||||
VSTS_TOKEN=
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -43,6 +43,8 @@
|
||||
/vendor/llvm/
|
||||
/vendor/npm/
|
||||
/vendor/python_26/
|
||||
/vendor/native_mksnapshot
|
||||
/vendor/LICENSES.chromium.html
|
||||
node_modules/
|
||||
SHASUMS256.txt
|
||||
**/package-lock.json
|
||||
|
||||
@@ -29,13 +29,8 @@ RUN apt-get update && apt-get install -y\
|
||||
wget \
|
||||
xvfb
|
||||
|
||||
# Install node.js
|
||||
RUN curl -sL https://deb.nodesource.com/setup_6.x | bash -
|
||||
RUN apt-get update && apt-get install -y nodejs
|
||||
|
||||
ADD tools/xvfb-init.sh /etc/init.d/xvfb
|
||||
RUN chmod a+x /etc/init.d/xvfb
|
||||
ADD tools/run-electron.sh /run-electron.sh
|
||||
RUN chmod a+x /run-electron.sh
|
||||
|
||||
CMD sh /run-electron.sh
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
pipeline {
|
||||
agent {
|
||||
docker {
|
||||
image 'electronbuilds/arm64v8:0.0.1'
|
||||
image 'electronbuilds/arm64v8:0.0.2'
|
||||
args '--privileged'
|
||||
}
|
||||
}
|
||||
|
||||
18
README.md
18
README.md
@@ -89,22 +89,8 @@ Find documentation translations in [electron/electron-i18n](https://github.com/e
|
||||
|
||||
## Community
|
||||
|
||||
You can ask questions and interact with the community in the following
|
||||
locations:
|
||||
- [`electron`](https://discuss.atom.io/c/electron) category on the Atom
|
||||
forums
|
||||
- `#atom-shell` channel on Freenode
|
||||
- [`Atom`](https://atom-slack.herokuapp.com) channel on Slack
|
||||
- [`electron-ru`](https://telegram.me/electron_ru) *(Russian)*
|
||||
- [`electron-br`](https://electron-br.slack.com) *(Brazilian Portuguese)*
|
||||
- [`electron-kr`](https://electron-kr.github.io/electron-kr) *(Korean)*
|
||||
- [`electron-jp`](https://electron-jp.slack.com) *(Japanese)*
|
||||
- [`electron-tr`](https://electron-tr.herokuapp.com) *(Turkish)*
|
||||
- [`electron-id`](https://electron-id.slack.com) *(Indonesia)*
|
||||
- [`electron-pl`](https://electronpl.github.io) *(Poland)*
|
||||
|
||||
Check out [awesome-electron](https://github.com/sindresorhus/awesome-electron)
|
||||
for a community maintained list of useful example apps, tools and resources.
|
||||
Info on reporting bugs, getting help, finding third-party tools and sample apps,
|
||||
and more can be found in the [support document](docs/tutorial/support.md#finding-support).
|
||||
|
||||
## License
|
||||
|
||||
|
||||
69
appveyor.yml
Normal file
69
appveyor.yml
Normal file
@@ -0,0 +1,69 @@
|
||||
build_cloud: electron-16
|
||||
image: electron-16-vs2015
|
||||
build_script:
|
||||
- ps: >-
|
||||
if($env:SKIP_GYP_BUILD -eq "true") {
|
||||
Write-warning "Skipping debug build for older branch"; Exit-AppveyorBuild
|
||||
} elseif(($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME -split "/")[0] -eq ($env:APPVEYOR_REPO_NAME -split "/")[0]) {
|
||||
Write-warning "Skipping PR build for branch"; Exit-AppveyorBuild
|
||||
} else {
|
||||
Add-Path "$env:ProgramFiles (x86)\Windows Kits\10\Debuggers\x64"
|
||||
$env:path = "$env:ProgramFiles (x86)\Windows Kits\10\Debuggers\x64;$env:path"
|
||||
if($env:APPVEYOR_SCHEDULED_BUILD -eq 'True') {
|
||||
$env:RUN_RELEASE_BUILD = "1"
|
||||
}
|
||||
$Message = (git log --format=%B -n 1 HEAD) | Out-String
|
||||
if ((Test-Path Env:\RUN_RELEASE_BUILD)) {
|
||||
$env:ELECTRON_RELEASE = '1'
|
||||
Write-Output "release build triggered from api"
|
||||
}
|
||||
if ((Test-Path Env:\ELECTRON_RELEASE)) {
|
||||
Write-Output "Running release build"
|
||||
python script\bootstrap.py --target_arch=$env:TARGET_ARCH
|
||||
python script\build.py -c R
|
||||
python script\create-dist.py
|
||||
} else {
|
||||
Write-Output "Running debug build"
|
||||
python script\bootstrap.py --target_arch=$env:TARGET_ARCH --dev
|
||||
python script\build.py -c D
|
||||
}
|
||||
if ($? -ne 'True') {
|
||||
throw "Build failed with exit code $?"
|
||||
} else {
|
||||
"Build succeeded."
|
||||
}
|
||||
Push-AppveyorArtifact out
|
||||
}
|
||||
test_script:
|
||||
- ps: >-
|
||||
if (Test-Path Env:\ELECTRON_RELEASE) {
|
||||
Write-Output "Skipping tests for release build"
|
||||
} else {
|
||||
Write-Output "Running tests for debug build"
|
||||
python script\test.py --ci --rebuild_native_modules
|
||||
if ($LASTEXITCODE -ne '0') {
|
||||
throw "Tests failed with exit code $LASTEXITCODE"
|
||||
} else {
|
||||
Write-Output "Tests succeeded."
|
||||
}
|
||||
python script\verify-ffmpeg.py
|
||||
if ($LASTEXITCODE -ne '0') {
|
||||
throw "Verify ffmpeg failed with exit code $LASTEXITCODE"
|
||||
} else {
|
||||
"Verify ffmpeg succeeded."
|
||||
}
|
||||
}
|
||||
artifacts:
|
||||
- path: test-results.xml
|
||||
name: test-results.xml
|
||||
deploy_script:
|
||||
- ps: >-
|
||||
if (Test-Path Env:\ELECTRON_RELEASE) {
|
||||
if (Test-Path Env:\RUN_RELEASE_BUILD) {
|
||||
Write-Output "Uploading Electron release distribution to s3"
|
||||
& python script\upload.py --upload_to_s3
|
||||
} else {
|
||||
Write-Output "Uploading Electron release distribution to github releases"
|
||||
& python script\upload.py
|
||||
}
|
||||
}
|
||||
@@ -43,12 +43,12 @@ bool IsUrlArg(const base::CommandLine::CharType* arg) {
|
||||
* Update the list by pasting the following command into bash
|
||||
* in libchromiumcontent/src/:
|
||||
|
||||
(find ./ -name "*switches.cc" | \
|
||||
xargs grep -P --no-filename "\"\S+\";" | \
|
||||
perl -pe 's|^.*?"(\S+)";| "$1",|'; \
|
||||
(find ./ \( -name "*switches.cc" -o -name "*switch_list.h" \) | \
|
||||
xargs grep -P --no-filename '"\S+"[);]$' | \
|
||||
perl -pe 's|^.*?"(\S+)"[);]$| "$1",|'; \
|
||||
echo ' "inspect",'; \
|
||||
echo ' "inspect-brk",') | \
|
||||
LANG=C sort | \
|
||||
LANG="C" sort | \
|
||||
uniq > blacklist-switches.txt
|
||||
|
||||
*/
|
||||
@@ -62,7 +62,10 @@ const char* kBlacklist[] = {
|
||||
"/prefetch:8",
|
||||
"0",
|
||||
"?",
|
||||
"BlacklistOnly",
|
||||
"ChromeOSMemoryPressureHandling",
|
||||
"Disabled",
|
||||
"OnlineCheckOnly",
|
||||
"SafeSites",
|
||||
"accept-resource-provider",
|
||||
"account-consistency",
|
||||
@@ -72,7 +75,6 @@ const char* kBlacklist[] = {
|
||||
"aggressive",
|
||||
"aggressive-cache-discard",
|
||||
"aggressive-tab-discard",
|
||||
"all",
|
||||
"all-toolchains",
|
||||
"allarticles",
|
||||
"allow-cross-origin-auth-prompt",
|
||||
@@ -113,7 +115,6 @@ const char* kBlacklist[] = {
|
||||
"always-on",
|
||||
"always-use-complex-text",
|
||||
"alwaystrue",
|
||||
"amd-switchable",
|
||||
"android-fonts-path",
|
||||
"android-stderr-port",
|
||||
"android-stdin-port",
|
||||
@@ -141,11 +142,12 @@ const char* kBlacklist[] = {
|
||||
"arc-transition-migration-required",
|
||||
"args",
|
||||
"artifacts-dir",
|
||||
"ash-animate-from-boot-splash-screen",
|
||||
"ash-constrain-pointer-to-root",
|
||||
"ash-copy-host-background-at-boot",
|
||||
"ash-debug-shortcuts",
|
||||
"ash-dev-shortcuts",
|
||||
"ash-disable-smooth-screen-rotation",
|
||||
"ash-disable-tablet-autohide-titlebars",
|
||||
"ash-disable-touch-exploration-mode",
|
||||
"ash-enable-magnifier-key-scroller",
|
||||
"ash-enable-mirrored-screen",
|
||||
@@ -174,8 +176,6 @@ const char* kBlacklist[] = {
|
||||
"autoplay-policy",
|
||||
"blink-settings",
|
||||
"bootstrap",
|
||||
"browser",
|
||||
"browser-startup-dialog",
|
||||
"browser-subprocess-path",
|
||||
"browser-test",
|
||||
"bwsi",
|
||||
@@ -220,6 +220,7 @@ const char* kBlacklist[] = {
|
||||
"crash-test",
|
||||
"crashpad-handler",
|
||||
"create-browser-on-startup-for-tests",
|
||||
"create-default-gl-context",
|
||||
"cros-gaia-api-v1",
|
||||
"cros-region",
|
||||
"cros-regions-mode",
|
||||
@@ -228,7 +229,6 @@ const char* kBlacklist[] = {
|
||||
"custom-devtools-frontend",
|
||||
"custom-launcher-page",
|
||||
"custom_summary",
|
||||
"d3d-support",
|
||||
"d3d11",
|
||||
"d3d9",
|
||||
"daemon",
|
||||
@@ -254,6 +254,7 @@ const char* kBlacklist[] = {
|
||||
"default-wallpaper-is-oem",
|
||||
"default-wallpaper-large",
|
||||
"default-wallpaper-small",
|
||||
"delay-reload-stop-button-change",
|
||||
"demo",
|
||||
"derelict-detection-timeout",
|
||||
"derelict-idle-timeout",
|
||||
@@ -267,7 +268,6 @@ const char* kBlacklist[] = {
|
||||
"diagnostics-format",
|
||||
"diagnostics-recovery",
|
||||
"dice",
|
||||
"dice_fix_auth_errors",
|
||||
"disable",
|
||||
"disable-2d-canvas-clip-aa",
|
||||
"disable-2d-canvas-image-chromium",
|
||||
@@ -289,6 +289,7 @@ const char* kBlacklist[] = {
|
||||
"disable-backgrounding-occluded-windows",
|
||||
"disable-backing-store-limit",
|
||||
"disable-blink-features",
|
||||
"disable-bookmark-reordering",
|
||||
"disable-boot-animation",
|
||||
"disable-breakpad",
|
||||
"disable-browser-task-scheduler",
|
||||
@@ -316,6 +317,7 @@ const char* kBlacklist[] = {
|
||||
"disable-direct-composition",
|
||||
"disable-direct-composition-layers",
|
||||
"disable-directwrite-for-ui",
|
||||
"disable-display-color-calibration",
|
||||
"disable-display-list-2d-canvas",
|
||||
"disable-distance-field-text",
|
||||
"disable-domain-blocking-for-3d-apis",
|
||||
@@ -330,6 +332,7 @@ const char* kBlacklist[] = {
|
||||
"disable-extensions-except",
|
||||
"disable-extensions-file-access-check",
|
||||
"disable-extensions-http-throttling",
|
||||
"disable-fast-web-scroll-view-insets",
|
||||
"disable-features",
|
||||
"disable-field-trial-config",
|
||||
"disable-file-manager-touch-mode",
|
||||
@@ -364,11 +367,14 @@ const char* kBlacklist[] = {
|
||||
"disable-histogram-customizer",
|
||||
"disable-hosted-app-shim-creation",
|
||||
"disable-hosted-apps-in-windows",
|
||||
"disable-http2",
|
||||
"disable-in-process-stack-traces",
|
||||
"disable-infobars",
|
||||
"disable-input-ime-api",
|
||||
"disable-input-view",
|
||||
"disable-ios-password-generation",
|
||||
"disable-ios-password-suggestions",
|
||||
"disable-ios-physical-web",
|
||||
"disable-javascript-harmony-shipping",
|
||||
"disable-kill-after-bad-ipc",
|
||||
"disable-lcd-text",
|
||||
@@ -382,6 +388,7 @@ const char* kBlacklist[] = {
|
||||
"disable-low-end-device-mode",
|
||||
"disable-low-latency-dxva",
|
||||
"disable-low-res-tiling",
|
||||
"disable-lru-snapshot-cache",
|
||||
"disable-mac-overlays",
|
||||
"disable-mac-views-native-app-windows",
|
||||
"disable-machine-cert-request",
|
||||
@@ -398,6 +405,7 @@ const char* kBlacklist[] = {
|
||||
"disable-namespace-sandbox",
|
||||
"disable-native-gpu-memory-buffers",
|
||||
"disable-network-portal-notification",
|
||||
"disable-new-channel-switcher-ui",
|
||||
"disable-new-korean-ime",
|
||||
"disable-new-virtual-keyboard-behavior",
|
||||
"disable-new-zip-unpacker",
|
||||
@@ -417,7 +425,6 @@ const char* kBlacklist[] = {
|
||||
"disable-password-generation",
|
||||
"disable-pepper-3d",
|
||||
"disable-pepper-3d-image-chromium",
|
||||
"disable-per-user-timezone",
|
||||
"disable-permission-action-reporting",
|
||||
"disable-permissions-api",
|
||||
"disable-physical-keyboard-autocorrect",
|
||||
@@ -431,12 +438,15 @@ const char* kBlacklist[] = {
|
||||
"disable-proximity-auth-bluetooth-low-energy-discovery",
|
||||
"disable-pull-to-refresh-effect",
|
||||
"disable-push-api-background-mode",
|
||||
"disable-quic",
|
||||
"disable-reading-from-canvas",
|
||||
"disable-remote-core-animation",
|
||||
"disable-remote-fonts",
|
||||
"disable-remote-playback-api",
|
||||
"disable-renderer-accessibility",
|
||||
"disable-renderer-backgrounding",
|
||||
"disable-renderer-priority-management",
|
||||
"disable-request-mobile-site",
|
||||
"disable-resize-lock",
|
||||
"disable-rgba-4444-textures",
|
||||
"disable-rollback-option",
|
||||
@@ -444,6 +454,7 @@ const char* kBlacklist[] = {
|
||||
"disable-screen-orientation-lock",
|
||||
"disable-search-geolocation-disclosure",
|
||||
"disable-seccomp-filter-sandbox",
|
||||
"disable-settings-window",
|
||||
"disable-setuid-sandbox",
|
||||
"disable-shader-name-hashing",
|
||||
"disable-shared-workers",
|
||||
@@ -457,17 +468,16 @@ const char* kBlacklist[] = {
|
||||
"disable-software-rasterizer",
|
||||
"disable-speech-api",
|
||||
"disable-suggestions-ui",
|
||||
"disable-surface-references",
|
||||
"disable-sync",
|
||||
"disable-sync-app-list",
|
||||
"disable-sync-types",
|
||||
"disable-system-timezone-automatic-detection",
|
||||
"disable-tab-for-desktop-share",
|
||||
"disable-tab-strip-autoscroll-new-tabs",
|
||||
"disable-third-party-keyboard-workaround",
|
||||
"disable-threaded-animation",
|
||||
"disable-threaded-compositing",
|
||||
"disable-threaded-scrolling",
|
||||
"disable-timeouts-for-profiling",
|
||||
"disable-touch-adjustment",
|
||||
"disable-touch-drag-drop",
|
||||
"disable-translate-new-ux",
|
||||
@@ -528,18 +538,16 @@ const char* kBlacklist[] = {
|
||||
"enable-appcontainer",
|
||||
"enable-arc",
|
||||
"enable-arc-oobe-optin",
|
||||
"enable-async-event-targeting",
|
||||
"enable-audio-debug-recordings-from-extension",
|
||||
"enable-audio-focus",
|
||||
"enable-automation",
|
||||
"enable-background-fetch-persistence",
|
||||
"enable-benchmarking",
|
||||
"enable-ble-advertising-in-apps",
|
||||
"enable-blink-features",
|
||||
"enable-bookmark-reordering",
|
||||
"enable-bookmark-undo",
|
||||
"enable-browser-side-navigation",
|
||||
"enable-browser-task-scheduler",
|
||||
"enable-cast-receiver",
|
||||
"enable-checker-imaging",
|
||||
"enable-chromevox-arc-support",
|
||||
"enable-clear-browsing-data-counters",
|
||||
@@ -579,8 +587,8 @@ const char* kBlacklist[] = {
|
||||
"enable-extension-activity-log-testing",
|
||||
"enable-extension-activity-logging",
|
||||
"enable-extension-assets-sharing",
|
||||
"enable-external-drive-rename",
|
||||
"enable-fast-unload",
|
||||
"enable-fast-web-scroll-view-insets",
|
||||
"enable-features",
|
||||
"enable-file-manager-touch-mode",
|
||||
"enable-first-run-ui-transitions",
|
||||
@@ -603,6 +611,7 @@ const char* kBlacklist[] = {
|
||||
"enable-gpu-service-tracing",
|
||||
"enable-hardware-overlays",
|
||||
"enable-harfbuzz-rendertext",
|
||||
"enable-hdr",
|
||||
"enable-heap-profiling",
|
||||
"enable-hosted-app-quit-notification",
|
||||
"enable-hosted-apps-in-windows",
|
||||
@@ -610,9 +619,10 @@ const char* kBlacklist[] = {
|
||||
"enable-hung-renderer-infobar",
|
||||
"enable-inband-text-tracks",
|
||||
"enable-input-ime-api",
|
||||
"enable-instant-tethering",
|
||||
"enable-internal-media-session",
|
||||
"enable-ios-handoff-to-other-devices",
|
||||
"enable-ios-password-generation",
|
||||
"enable-ios-physical-web",
|
||||
"enable-layer-lists",
|
||||
"enable-lcd-text",
|
||||
"enable-leak-detection",
|
||||
@@ -622,9 +632,11 @@ const char* kBlacklist[] = {
|
||||
"enable-longpress-drag-selection",
|
||||
"enable-low-end-device-mode",
|
||||
"enable-low-res-tiling",
|
||||
"enable-lru-snapshot-cache",
|
||||
"enable-mac-views-native-app-windows",
|
||||
"enable-main-frame-before-activation",
|
||||
"enable-md-feedback",
|
||||
"enable-md-policy-page",
|
||||
"enable-media-suspend",
|
||||
"enable-merge-key-char-events",
|
||||
"enable-message-center-always-scroll-up-upon-notification-removal",
|
||||
@@ -645,7 +657,6 @@ const char* kBlacklist[] = {
|
||||
"enable-offer-upload-credit-cards",
|
||||
"enable-offline-auto-reload",
|
||||
"enable-offline-auto-reload-visible-only",
|
||||
"enable-oop-rasterization",
|
||||
"enable-osk-overscroll",
|
||||
"enable-override-bookmarks-ui",
|
||||
"enable-partial-raster",
|
||||
@@ -655,7 +666,6 @@ const char* kBlacklist[] = {
|
||||
"enable-physical-keyboard-autocorrect",
|
||||
"enable-picture-in-picture",
|
||||
"enable-pinch",
|
||||
"enable-pixel-canvas-recording",
|
||||
"enable-pixel-output-in-tests",
|
||||
"enable-plugin-placeholder-testing",
|
||||
"enable-potentially-annoying-security-features",
|
||||
@@ -667,6 +677,8 @@ const char* kBlacklist[] = {
|
||||
"enable-profile-shortcut-manager",
|
||||
"enable-profiling",
|
||||
"enable-push-api-background-mode",
|
||||
"enable-quic",
|
||||
"enable-reader-mode-toolbar-icon",
|
||||
"enable-refresh-token-annotation-request",
|
||||
"enable-request-tablet-site",
|
||||
"enable-rgba-4444-textures",
|
||||
@@ -676,6 +688,7 @@ const char* kBlacklist[] = {
|
||||
"enable-scripts-require-action",
|
||||
"enable-scroll-prediction",
|
||||
"enable-service-manager-tracing",
|
||||
"enable-settings-window",
|
||||
"enable-sgi-video-sync",
|
||||
"enable-signin-promo",
|
||||
"enable-single-click-autofill",
|
||||
@@ -718,6 +731,7 @@ const char* kBlacklist[] = {
|
||||
"enable-translate-new-ux",
|
||||
"enable-ui-devtools",
|
||||
"enable-use-zoom-for-dsf",
|
||||
"enable-user-controlled-alternate-protocol-ports",
|
||||
"enable-user-metrics",
|
||||
"enable-usermedia-screen-capturing",
|
||||
"enable-video-player-chromecast-support",
|
||||
@@ -734,9 +748,8 @@ const char* kBlacklist[] = {
|
||||
"enable-webgl-image-chromium",
|
||||
"enable-webrtc-event-logging-from-extension",
|
||||
"enable-webrtc-srtp-aes-gcm",
|
||||
"enable-webrtc-srtp-encrypted-headers",
|
||||
"enable-webrtc-stun-origin",
|
||||
"enable-webview-variations",
|
||||
"enable-webview-finch",
|
||||
"enable-webvr",
|
||||
"enable-wifi-credential-sync",
|
||||
"enable-win7-webrtc-hw-h264-decoding",
|
||||
@@ -759,8 +772,6 @@ const char* kBlacklist[] = {
|
||||
"enterprise-enrollment-initial-modulus",
|
||||
"enterprise-enrollment-modulus-limit",
|
||||
"error-console",
|
||||
"evaluate-type",
|
||||
"evaluate_capability",
|
||||
"experiment",
|
||||
"explicitly-allowed-ports",
|
||||
"expose-internals-for-testing",
|
||||
@@ -808,7 +819,6 @@ const char* kBlacklist[] = {
|
||||
"force-overlay-fullscreen-video",
|
||||
"force-password-reauth",
|
||||
"force-pnacl-subzero",
|
||||
"force-presentation-receiver-for-testing",
|
||||
"force-renderer-accessibility",
|
||||
"force-show-update-menu-badge",
|
||||
"force-show-update-menu-item",
|
||||
@@ -838,6 +848,7 @@ const char* kBlacklist[] = {
|
||||
"gpu-active-device-id",
|
||||
"gpu-active-vendor-id",
|
||||
"gpu-device-id",
|
||||
"gpu-driver-bug-workarounds",
|
||||
"gpu-driver-date",
|
||||
"gpu-driver-vendor",
|
||||
"gpu-driver-version",
|
||||
@@ -863,7 +874,6 @@ const char* kBlacklist[] = {
|
||||
"gpu-testing-secondary-vendor-ids",
|
||||
"gpu-testing-vendor-id",
|
||||
"gpu-vendor-id",
|
||||
"graphics-buffer-count",
|
||||
"guest-wallpaper-large",
|
||||
"guest-wallpaper-small",
|
||||
"h",
|
||||
@@ -881,6 +891,7 @@ const char* kBlacklist[] = {
|
||||
"host",
|
||||
"host-pairing-oobe",
|
||||
"host-resolver-rules",
|
||||
"host-rules",
|
||||
"icu-data-dir",
|
||||
"ignore-autocomplete-off-autofill",
|
||||
"ignore-autoplay-restrictions",
|
||||
@@ -928,10 +939,6 @@ const char* kBlacklist[] = {
|
||||
"login-manager",
|
||||
"login-profile",
|
||||
"login-user",
|
||||
"loopback-i2s-bits",
|
||||
"loopback-i2s-bus-name",
|
||||
"loopback-i2s-channels",
|
||||
"loopback-i2s-rate-hz",
|
||||
"lso-url",
|
||||
"ltr",
|
||||
"main-frame-resizes-are-orientation-changes",
|
||||
@@ -953,11 +960,11 @@ const char* kBlacklist[] = {
|
||||
"media-cache-size",
|
||||
"mem-pressure-system-reserved-kb",
|
||||
"memlog",
|
||||
"memlog-pipe",
|
||||
"memory-pressure-off",
|
||||
"memory-pressure-thresholds",
|
||||
"memory-pressure-thresholds-mb",
|
||||
"message-center-changes-while-open",
|
||||
"method",
|
||||
"metrics-client-id",
|
||||
"metrics-recording-only",
|
||||
"mhtml-generator-option",
|
||||
@@ -1013,6 +1020,7 @@ const char* kBlacklist[] = {
|
||||
"normal_vibrant",
|
||||
"note-taking-app-ids",
|
||||
"ntp-snippets-add-incomplete",
|
||||
"ntp-switch-to-existing-tab",
|
||||
"null",
|
||||
"num-raster-threads",
|
||||
"oauth2-client-id",
|
||||
@@ -1026,6 +1034,7 @@ const char* kBlacklist[] = {
|
||||
"oobe-timer-interval",
|
||||
"open-ash",
|
||||
"opengraph",
|
||||
"origin-to-force-quic-on",
|
||||
"origin-trial-disabled-features",
|
||||
"origin-trial-disabled-tokens",
|
||||
"origin-trial-public-key",
|
||||
@@ -1058,6 +1067,7 @@ const char* kBlacklist[] = {
|
||||
"ppapi-plugin-launcher",
|
||||
"ppapi-startup-dialog",
|
||||
"ppapi-subpixel-rendering-setting",
|
||||
"prerender-from-omnibox",
|
||||
"previous-app",
|
||||
"primary",
|
||||
"print-to-pdf",
|
||||
@@ -1067,6 +1077,7 @@ const char* kBlacklist[] = {
|
||||
"product-version",
|
||||
"profile-directory",
|
||||
"profiler-timing",
|
||||
"profiling",
|
||||
"profiling-at-start",
|
||||
"profiling-file",
|
||||
"profiling-flush",
|
||||
@@ -1077,8 +1088,10 @@ const char* kBlacklist[] = {
|
||||
"proxy-bypass-list",
|
||||
"proxy-pac-url",
|
||||
"proxy-server",
|
||||
"pull-to-refresh",
|
||||
"q",
|
||||
"quic-connection-options",
|
||||
"quic-max-packet-length",
|
||||
"quic-version",
|
||||
"rdp_desktop_session",
|
||||
"reader-mode-feedback",
|
||||
"reader-mode-heuristics",
|
||||
@@ -1110,7 +1123,6 @@ const char* kBlacklist[] = {
|
||||
"root",
|
||||
"root-layer-scrolls",
|
||||
"rtl",
|
||||
"run-all-compositor-stages-before-draw",
|
||||
"run-layout-test",
|
||||
"runtime-deps-list-file",
|
||||
"safebrowsing-disable-auto-update",
|
||||
@@ -1123,6 +1135,7 @@ const char* kBlacklist[] = {
|
||||
"screenshot",
|
||||
"script-executable",
|
||||
"scripts-require-action",
|
||||
"scroll-end-effect",
|
||||
"search-provider-logo-url",
|
||||
"secondary",
|
||||
"secondary-display-layout",
|
||||
@@ -1169,7 +1182,6 @@ const char* kBlacklist[] = {
|
||||
"skip-reencoding-on-skp-capture",
|
||||
"slow",
|
||||
"slow-connections-only",
|
||||
"slow-down-compositing-scale-factor",
|
||||
"slow-down-raster-scale-factor",
|
||||
"sms-test-messages",
|
||||
"spdy-proxy-auth-fallback",
|
||||
@@ -1192,6 +1204,7 @@ const char* kBlacklist[] = {
|
||||
"started",
|
||||
"stub",
|
||||
"stub-cros-settings",
|
||||
"supports-dual-gpus",
|
||||
"surface",
|
||||
"swiftshader",
|
||||
"swiftshader-webgl",
|
||||
@@ -1208,7 +1221,6 @@ const char* kBlacklist[] = {
|
||||
"system-log-upload-frequency",
|
||||
"tab-management-experiment-type-disabled",
|
||||
"tab-management-experiment-type-elderberry",
|
||||
"task-manager-show-extra-renderers",
|
||||
"task-profiler",
|
||||
"team-drives",
|
||||
"test-auto-update-ui",
|
||||
@@ -1240,7 +1252,6 @@ const char* kBlacklist[] = {
|
||||
"testing-fixed-http-port",
|
||||
"testing-fixed-https-port",
|
||||
"tether-stub",
|
||||
"third-party-doodle-url",
|
||||
"threads",
|
||||
"time",
|
||||
"timeout",
|
||||
@@ -1300,6 +1311,7 @@ const char* kBlacklist[] = {
|
||||
"unsafely-treat-insecure-origin-as-secure",
|
||||
"use-angle",
|
||||
"use-cras",
|
||||
"use-double-buffering",
|
||||
"use-fake-device-for-media-stream",
|
||||
"use-fake-jpeg-decode-accelerator",
|
||||
"use-fake-ui-for-media-stream",
|
||||
@@ -1312,10 +1324,9 @@ const char* kBlacklist[] = {
|
||||
"use-mobile-user-agent",
|
||||
"use-mock-keychain",
|
||||
"use-passthrough-cmd-decoder",
|
||||
"use-skia-renderer",
|
||||
"use-simple-cache-backend",
|
||||
"use-system-default-printer",
|
||||
"use-test-config",
|
||||
"use-viz-hit-test",
|
||||
"user-agent",
|
||||
"user-always-affiliated",
|
||||
"user-data-dir",
|
||||
@@ -1325,8 +1336,6 @@ const char* kBlacklist[] = {
|
||||
"utility-allowed-dir",
|
||||
"utility-cmd-prefix",
|
||||
"utility-run-elevated",
|
||||
"utility-sandbox-type",
|
||||
"utility-startup-dialog",
|
||||
"v",
|
||||
"v2-sandbox",
|
||||
"v2-sandbox-enabled",
|
||||
@@ -1350,6 +1359,7 @@ const char* kBlacklist[] = {
|
||||
"watcher",
|
||||
"waveout-buffers",
|
||||
"webapk-server-url",
|
||||
"webrtc-max-cpu-consumption-percentage",
|
||||
"webrtc-stun-probe-trial",
|
||||
"webview-enable-safebrowsing-support",
|
||||
"webview-sandboxed-renderer",
|
||||
|
||||
@@ -68,8 +68,8 @@ void BrowserView::Init(v8::Isolate* isolate,
|
||||
web_contents_.Reset(isolate, web_contents.ToV8());
|
||||
api_web_contents_ = web_contents.get();
|
||||
|
||||
view_.reset(NativeBrowserView::Create(
|
||||
api_web_contents_->managed_web_contents()->GetView()));
|
||||
view_.reset(
|
||||
NativeBrowserView::Create(api_web_contents_->managed_web_contents()));
|
||||
|
||||
InitWith(isolate, wrapper);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,12 @@
|
||||
|
||||
using content::BrowserThread;
|
||||
|
||||
namespace {
|
||||
|
||||
static scoped_nsobject<NSMenu> applicationMenu_;
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
@@ -135,7 +141,18 @@ void Menu::SetApplicationMenu(Menu* base_menu) {
|
||||
base::scoped_nsobject<AtomMenuController> menu_controller(
|
||||
[[AtomMenuController alloc] initWithModel:menu->model_.get()
|
||||
useDefaultAccelerator:YES]);
|
||||
[NSApp setMainMenu:[menu_controller menu]];
|
||||
|
||||
NSRunLoop* currentRunLoop = [NSRunLoop currentRunLoop];
|
||||
[currentRunLoop cancelPerformSelector:@selector(setMainMenu:)
|
||||
target:NSApp
|
||||
argument:applicationMenu_];
|
||||
applicationMenu_.reset([[menu_controller menu] retain]);
|
||||
[[NSRunLoop currentRunLoop]
|
||||
performSelector:@selector(setMainMenu:)
|
||||
target:NSApp
|
||||
argument:applicationMenu_
|
||||
order:0
|
||||
modes:[NSArray arrayWithObject:NSDefaultRunLoopMode]];
|
||||
|
||||
// Ensure the menu_controller_ is destroyed after main menu is set.
|
||||
menu_controller.swap(menu->menu_controller_);
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include "base/guid.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "base/threading/thread_task_runner_handle.h"
|
||||
#include "brightray/browser/media/media_device_id_salt.h"
|
||||
#include "brightray/browser/net/devtools_network_conditions.h"
|
||||
#include "brightray/browser/net/devtools_network_controller_handle.h"
|
||||
@@ -47,7 +46,6 @@
|
||||
#include "net/http/http_auth_handler_factory.h"
|
||||
#include "net/http/http_auth_preferences.h"
|
||||
#include "net/proxy/proxy_config_service_fixed.h"
|
||||
#include "net/proxy/proxy_service.h"
|
||||
#include "net/url_request/static_http_user_agent_settings.h"
|
||||
#include "net/url_request/url_request_context.h"
|
||||
#include "net/url_request/url_request_context_getter.h"
|
||||
@@ -232,59 +230,6 @@ const char kPersistPrefix[] = "persist:";
|
||||
// Referenced session objects.
|
||||
std::map<uint32_t, v8::Global<v8::Object>> g_sessions;
|
||||
|
||||
class ResolveProxyHelper {
|
||||
public:
|
||||
ResolveProxyHelper(AtomBrowserContext* browser_context,
|
||||
const GURL& url,
|
||||
const Session::ResolveProxyCallback& callback)
|
||||
: callback_(callback),
|
||||
original_thread_(base::ThreadTaskRunnerHandle::Get()) {
|
||||
scoped_refptr<net::URLRequestContextGetter> context_getter =
|
||||
browser_context->url_request_context_getter();
|
||||
context_getter->GetNetworkTaskRunner()->PostTask(
|
||||
FROM_HERE,
|
||||
base::Bind(&ResolveProxyHelper::ResolveProxy,
|
||||
base::Unretained(this), context_getter, url));
|
||||
}
|
||||
|
||||
void OnResolveProxyCompleted(int result) {
|
||||
std::string proxy;
|
||||
if (result == net::OK)
|
||||
proxy = proxy_info_.ToPacString();
|
||||
original_thread_->PostTask(FROM_HERE,
|
||||
base::Bind(callback_, proxy));
|
||||
delete this;
|
||||
}
|
||||
|
||||
private:
|
||||
void ResolveProxy(scoped_refptr<net::URLRequestContextGetter> context_getter,
|
||||
const GURL& url) {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
||||
|
||||
net::ProxyService* proxy_service =
|
||||
context_getter->GetURLRequestContext()->proxy_service();
|
||||
net::CompletionCallback completion_callback =
|
||||
base::Bind(&ResolveProxyHelper::OnResolveProxyCompleted,
|
||||
base::Unretained(this));
|
||||
|
||||
// Start the request.
|
||||
int result = proxy_service->ResolveProxy(
|
||||
url, "GET", &proxy_info_, completion_callback, &pac_req_, nullptr,
|
||||
net::NetLogWithSource());
|
||||
|
||||
// Completed synchronously.
|
||||
if (result != net::ERR_IO_PENDING)
|
||||
completion_callback.Run(result);
|
||||
}
|
||||
|
||||
Session::ResolveProxyCallback callback_;
|
||||
net::ProxyInfo proxy_info_;
|
||||
net::ProxyService::PacRequest* pac_req_;
|
||||
scoped_refptr<base::SingleThreadTaskRunner> original_thread_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ResolveProxyHelper);
|
||||
};
|
||||
|
||||
// Runs the callback in UI thread.
|
||||
void RunCallbackInUI(const base::Callback<void()>& callback) {
|
||||
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
|
||||
@@ -490,8 +435,10 @@ void Session::OnDownloadCreated(content::DownloadManager* manager,
|
||||
}
|
||||
}
|
||||
|
||||
void Session::ResolveProxy(const GURL& url, ResolveProxyCallback callback) {
|
||||
new ResolveProxyHelper(browser_context(), url, callback);
|
||||
void Session::ResolveProxy(
|
||||
const GURL& url,
|
||||
const ResolveProxyHelper::ResolveProxyCallback& callback) {
|
||||
browser_context_->GetResolveProxyHelper()->ResolveProxy(url, callback);
|
||||
}
|
||||
|
||||
template<Session::CacheAction action>
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "atom/browser/atom_blob_reader.h"
|
||||
#include "atom/browser/net/resolve_proxy_helper.h"
|
||||
#include "base/values.h"
|
||||
#include "content/public/browser/download_manager.h"
|
||||
#include "native_mate/handle.h"
|
||||
@@ -39,8 +40,6 @@ namespace api {
|
||||
class Session: public mate::TrackableObject<Session>,
|
||||
public content::DownloadManager::Observer {
|
||||
public:
|
||||
using ResolveProxyCallback = base::Callback<void(std::string)>;
|
||||
|
||||
enum class CacheAction {
|
||||
CLEAR,
|
||||
STATS,
|
||||
@@ -62,7 +61,8 @@ class Session: public mate::TrackableObject<Session>,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
// Methods.
|
||||
void ResolveProxy(const GURL& url, ResolveProxyCallback callback);
|
||||
void ResolveProxy(const GURL& url,
|
||||
const ResolveProxyHelper::ResolveProxyCallback& callback);
|
||||
template<CacheAction action>
|
||||
void DoCacheAction(const net::CompletionCallback& callback);
|
||||
void ClearStorageData(mate::Arguments* args);
|
||||
|
||||
@@ -206,7 +206,7 @@ void Tray::PopUpContextMenu(mate::Arguments* args) {
|
||||
|
||||
void Tray::SetContextMenu(v8::Isolate* isolate, mate::Handle<Menu> menu) {
|
||||
menu_.Reset(isolate, menu.ToV8());
|
||||
tray_icon_->SetContextMenu(menu->model());
|
||||
tray_icon_->SetContextMenu(menu.IsEmpty() ? nullptr : menu->model());
|
||||
}
|
||||
|
||||
gfx::Rect Tray::GetBounds() {
|
||||
|
||||
@@ -113,7 +113,7 @@ struct Converter<atom::SetSizeParams> {
|
||||
return false;
|
||||
bool autosize;
|
||||
if (params.Get("enableAutoSize", &autosize))
|
||||
out->enable_auto_size.reset(new bool(true));
|
||||
out->enable_auto_size.reset(new bool(autosize));
|
||||
gfx::Size size;
|
||||
if (params.Get("min", &size))
|
||||
out->min_size.reset(new gfx::Size(size));
|
||||
@@ -272,6 +272,9 @@ content::ServiceWorkerContext* GetServiceWorkerContext(
|
||||
void OnCapturePageDone(const base::Callback<void(const gfx::Image&)>& callback,
|
||||
const SkBitmap& bitmap,
|
||||
content::ReadbackResponse response) {
|
||||
// Hack to enable transparency in captured image
|
||||
// TODO(nitsakh) Remove hack once fixed in chromium
|
||||
const_cast<SkBitmap&>(bitmap).setAlphaType(kPremul_SkAlphaType);
|
||||
callback.Run(gfx::Image::CreateFrom1xBitmap(bitmap));
|
||||
}
|
||||
|
||||
@@ -1014,13 +1017,17 @@ void WebContents::NavigationEntryCommitted(
|
||||
details.is_same_document, details.did_replace_entry);
|
||||
}
|
||||
|
||||
int64_t WebContents::GetID() const {
|
||||
int64_t process_id = web_contents()->GetRenderProcessHost()->GetID();
|
||||
int64_t routing_id = web_contents()->GetRenderViewHost()->GetRoutingID();
|
||||
int64_t WebContents::GetIDForContents(content::WebContents* web_contents) {
|
||||
int64_t process_id = web_contents->GetRenderProcessHost()->GetID();
|
||||
int64_t routing_id = web_contents->GetMainFrame()->GetRoutingID();
|
||||
int64_t rv = (process_id << 32) + routing_id;
|
||||
return rv;
|
||||
}
|
||||
|
||||
int64_t WebContents::GetID() const {
|
||||
return WebContents::GetIDForContents(web_contents());
|
||||
}
|
||||
|
||||
int WebContents::GetProcessID() const {
|
||||
return web_contents()->GetRenderProcessHost()->GetID();
|
||||
}
|
||||
@@ -1950,9 +1957,7 @@ void WebContents::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("startDrag", &WebContents::StartDrag)
|
||||
.SetMethod("setSize", &WebContents::SetSize)
|
||||
.SetMethod("isGuest", &WebContents::IsGuest)
|
||||
#if defined(ENABLE_OSR)
|
||||
.SetMethod("isOffscreen", &WebContents::IsOffScreen)
|
||||
#endif
|
||||
.SetMethod("startPainting", &WebContents::StartPainting)
|
||||
.SetMethod("stopPainting", &WebContents::StopPainting)
|
||||
.SetMethod("isPainting", &WebContents::IsPainting)
|
||||
|
||||
@@ -79,6 +79,8 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
static int64_t GetIDForContents(content::WebContents* web_contents);
|
||||
|
||||
// Notifies to destroy any guest web contents before destroying self.
|
||||
void DestroyWebContents(bool async);
|
||||
|
||||
|
||||
@@ -893,6 +893,8 @@ void Window::SetBrowserView(v8::Local<v8::Value> value) {
|
||||
window_->SetBrowserView(browser_view->view());
|
||||
browser_view->web_contents()->SetOwnerWindow(window_.get());
|
||||
browser_view_.Reset(isolate(), value);
|
||||
|
||||
window_->UpdateDraggableRegionViews();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include "atom/browser/api/atom_api_app.h"
|
||||
#include "atom/browser/api/atom_api_protocol.h"
|
||||
#include "atom/browser/api/atom_api_web_contents.h"
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/atom_browser_main_parts.h"
|
||||
#include "atom/browser/atom_quota_permission_context.h"
|
||||
@@ -318,6 +319,11 @@ void AtomBrowserClient::AppendExtraCommandLineSwitches(
|
||||
web_contents, command_line);
|
||||
SessionPreferences::AppendExtraCommandLineSwitches(
|
||||
web_contents->GetBrowserContext(), command_line);
|
||||
|
||||
auto context_id = atom::api::WebContents::GetIDForContents(
|
||||
web_contents);
|
||||
command_line->AppendSwitchASCII(switches::kContextId,
|
||||
base::IntToString(context_id));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -442,7 +448,6 @@ void AtomBrowserClient::SiteInstanceDeleting(
|
||||
|
||||
brightray::BrowserMainParts* AtomBrowserClient::OverrideCreateBrowserMainParts(
|
||||
const content::MainFunctionParams&) {
|
||||
v8::V8::Initialize(); // Init V8 before creating main parts.
|
||||
return new AtomBrowserMainParts;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "atom/browser/net/atom_network_delegate.h"
|
||||
#include "atom/browser/net/atom_url_request_job_factory.h"
|
||||
#include "atom/browser/net/http_protocol_handler.h"
|
||||
#include "atom/browser/net/resolve_proxy_helper.h"
|
||||
#include "atom/browser/web_view_manager.h"
|
||||
#include "atom/common/atom_version.h"
|
||||
#include "atom/common/chrome_version.h"
|
||||
@@ -226,6 +227,14 @@ AtomBlobReader* AtomBrowserContext::GetBlobReader() {
|
||||
return blob_reader_.get();
|
||||
}
|
||||
|
||||
ResolveProxyHelper* AtomBrowserContext::GetResolveProxyHelper() {
|
||||
if (!resolve_proxy_helper_.get()) {
|
||||
resolve_proxy_helper_ =
|
||||
base::MakeRefCounted<ResolveProxyHelper>(url_request_context_getter());
|
||||
}
|
||||
return resolve_proxy_helper_.get();
|
||||
}
|
||||
|
||||
// static
|
||||
scoped_refptr<AtomBrowserContext> AtomBrowserContext::From(
|
||||
const std::string& partition, bool in_memory,
|
||||
|
||||
@@ -18,6 +18,7 @@ class AtomBlobReader;
|
||||
class AtomDownloadManagerDelegate;
|
||||
class AtomNetworkDelegate;
|
||||
class AtomPermissionManager;
|
||||
class ResolveProxyHelper;
|
||||
class WebViewManager;
|
||||
|
||||
class AtomBrowserContext : public brightray::BrowserContext {
|
||||
@@ -51,6 +52,8 @@ class AtomBrowserContext : public brightray::BrowserContext {
|
||||
// brightray::BrowserContext:
|
||||
void RegisterPrefs(PrefRegistrySimple* pref_registry) override;
|
||||
|
||||
ResolveProxyHelper* GetResolveProxyHelper();
|
||||
|
||||
AtomBlobReader* GetBlobReader();
|
||||
AtomCookieDelegate* cookie_delegate() const {
|
||||
return cookie_delegate_.get();
|
||||
@@ -62,6 +65,7 @@ class AtomBrowserContext : public brightray::BrowserContext {
|
||||
~AtomBrowserContext() override;
|
||||
|
||||
private:
|
||||
scoped_refptr<ResolveProxyHelper> resolve_proxy_helper_;
|
||||
std::unique_ptr<AtomDownloadManagerDelegate> download_manager_delegate_;
|
||||
std::unique_ptr<WebViewManager> guest_manager_;
|
||||
std::unique_ptr<AtomPermissionManager> permission_manager_;
|
||||
|
||||
@@ -151,6 +151,14 @@ void AtomBrowserMainParts::PostEarlyInitialization() {
|
||||
|
||||
// Wrap the uv loop with global env.
|
||||
node_bindings_->set_uv_env(env);
|
||||
|
||||
// We already initialized the feature list in
|
||||
// brightray::BrowserMainParts::PreEarlyInitialization(), but
|
||||
// the user JS script would not have had a chance to alter the command-line
|
||||
// switches at that point. Lets reinitialize it here to pick up the
|
||||
// command-line changes.
|
||||
base::FeatureList::ClearInstanceForTesting();
|
||||
brightray::BrowserMainParts::InitializeFeatureList();
|
||||
}
|
||||
|
||||
int AtomBrowserMainParts::PreCreateThreads() {
|
||||
|
||||
@@ -77,6 +77,11 @@ bool Browser::RemoveAsDefaultProtocolClient(const std::string& protocol,
|
||||
}
|
||||
}
|
||||
|
||||
// No other app was found set it to none instead of setting it back to itself.
|
||||
if ([identifier isEqualToString:(__bridge NSString*)other]) {
|
||||
other = base::mac::NSToCFCast(@"None");
|
||||
}
|
||||
|
||||
OSStatus return_code = LSSetDefaultHandlerForURLScheme(protocol_cf, other);
|
||||
return return_code == noErr;
|
||||
}
|
||||
|
||||
@@ -7,14 +7,23 @@
|
||||
#include "atom/browser/native_browser_view.h"
|
||||
|
||||
#include "atom/browser/api/atom_api_web_contents.h"
|
||||
#include "brightray/browser/inspectable_web_contents_view.h"
|
||||
#include "brightray/browser/inspectable_web_contents.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
NativeBrowserView::NativeBrowserView(
|
||||
brightray::InspectableWebContentsView* web_contents_view)
|
||||
: web_contents_view_(web_contents_view) {}
|
||||
brightray::InspectableWebContents* inspectable_web_contents)
|
||||
: inspectable_web_contents_(inspectable_web_contents) {}
|
||||
|
||||
NativeBrowserView::~NativeBrowserView() {}
|
||||
|
||||
brightray::InspectableWebContentsView*
|
||||
NativeBrowserView::GetInspectableWebContentsView() {
|
||||
return inspectable_web_contents_->GetView();
|
||||
}
|
||||
|
||||
content::WebContents* NativeBrowserView::GetWebContents() {
|
||||
return inspectable_web_contents_->GetWebContents();
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -9,9 +9,11 @@
|
||||
|
||||
#include "atom/common/draggable_region.h"
|
||||
#include "base/macros.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
#include "third_party/skia/include/core/SkColor.h"
|
||||
|
||||
namespace brightray {
|
||||
class InspectableWebContents;
|
||||
class InspectableWebContentsView;
|
||||
}
|
||||
|
||||
@@ -31,12 +33,15 @@ class NativeBrowserView {
|
||||
virtual ~NativeBrowserView();
|
||||
|
||||
static NativeBrowserView* Create(
|
||||
brightray::InspectableWebContentsView* web_contents_view);
|
||||
brightray::InspectableWebContents* inspectable_web_contents);
|
||||
|
||||
brightray::InspectableWebContentsView* GetInspectableWebContentsView() {
|
||||
return web_contents_view_;
|
||||
brightray::InspectableWebContents* GetInspectableWebContents() {
|
||||
return inspectable_web_contents_;
|
||||
}
|
||||
|
||||
brightray::InspectableWebContentsView* GetInspectableWebContentsView();
|
||||
content::WebContents* GetWebContents();
|
||||
|
||||
virtual void SetAutoResizeFlags(uint8_t flags) = 0;
|
||||
virtual void SetBounds(const gfx::Rect& bounds) = 0;
|
||||
virtual void SetBackgroundColor(SkColor color) = 0;
|
||||
@@ -47,9 +52,9 @@ class NativeBrowserView {
|
||||
|
||||
protected:
|
||||
explicit NativeBrowserView(
|
||||
brightray::InspectableWebContentsView* web_contents_view);
|
||||
brightray::InspectableWebContents* inspectable_web_contents);
|
||||
|
||||
brightray::InspectableWebContentsView* web_contents_view_;
|
||||
brightray::InspectableWebContents* inspectable_web_contents_;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(NativeBrowserView);
|
||||
|
||||
@@ -17,12 +17,13 @@ namespace atom {
|
||||
class NativeBrowserViewMac : public NativeBrowserView {
|
||||
public:
|
||||
explicit NativeBrowserViewMac(
|
||||
brightray::InspectableWebContentsView* web_contents_view);
|
||||
brightray::InspectableWebContents* inspectable_web_contents);
|
||||
~NativeBrowserViewMac() override;
|
||||
|
||||
void SetAutoResizeFlags(uint8_t flags) override;
|
||||
void SetBounds(const gfx::Rect& bounds) override;
|
||||
void SetBackgroundColor(SkColor color) override;
|
||||
|
||||
void UpdateDraggableRegions(
|
||||
const std::vector<gfx::Rect>& system_drag_exclude_areas) override;
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "atom/browser/native_browser_view_mac.h"
|
||||
|
||||
#include "brightray/browser/inspectable_web_contents.h"
|
||||
#include "brightray/browser/inspectable_web_contents_view.h"
|
||||
#include "skia/ext/skia_utils_mac.h"
|
||||
#include "ui/gfx/geometry/rect.h"
|
||||
@@ -156,8 +157,8 @@ const NSAutoresizingMaskOptions kDefaultAutoResizingMask =
|
||||
namespace atom {
|
||||
|
||||
NativeBrowserViewMac::NativeBrowserViewMac(
|
||||
brightray::InspectableWebContentsView* web_contents_view)
|
||||
: NativeBrowserView(web_contents_view) {
|
||||
brightray::InspectableWebContents* inspectable_web_contents)
|
||||
: NativeBrowserView(inspectable_web_contents) {
|
||||
auto* view = GetInspectableWebContentsView()->GetNativeView();
|
||||
view.autoresizingMask = kDefaultAutoResizingMask;
|
||||
}
|
||||
@@ -193,62 +194,46 @@ void NativeBrowserViewMac::SetBackgroundColor(SkColor color) {
|
||||
}
|
||||
|
||||
void NativeBrowserViewMac::UpdateDraggableRegions(
|
||||
const std::vector<gfx::Rect>& system_drag_exclude_areas) {
|
||||
NSView* webView = GetInspectableWebContentsView()->GetNativeView();
|
||||
const std::vector<gfx::Rect>& drag_exclude_rects) {
|
||||
NSView* web_view = GetWebContents()->GetNativeView();
|
||||
NSView* inspectable_view = GetInspectableWebContentsView()->GetNativeView();
|
||||
NSView* window_content_view = inspectable_view.superview;
|
||||
const auto window_content_view_height = NSHeight(window_content_view.bounds);
|
||||
|
||||
NSInteger superViewHeight = NSHeight([webView.superview bounds]);
|
||||
NSInteger webViewHeight = NSHeight([webView bounds]);
|
||||
NSInteger webViewWidth = NSWidth([webView bounds]);
|
||||
NSInteger webViewX = NSMinX([webView frame]);
|
||||
NSInteger webViewY = 0;
|
||||
|
||||
// Apple's NSViews have their coordinate system originate at the bottom left,
|
||||
// meaning that we need to be a bit smarter when it comes to calculating our
|
||||
// current top offset
|
||||
if (webViewHeight > superViewHeight) {
|
||||
webViewY = std::abs(webViewHeight - superViewHeight - (std::abs(NSMinY([webView frame]))));
|
||||
} else {
|
||||
webViewY = superViewHeight - NSMaxY([webView frame]);
|
||||
}
|
||||
|
||||
// Remove all DraggableRegionViews that are added last time.
|
||||
// Note that [webView subviews] returns the view's mutable internal array and
|
||||
// it should be copied to avoid mutating the original array while enumerating
|
||||
// it.
|
||||
base::scoped_nsobject<NSArray> subviews([[webView subviews] copy]);
|
||||
for (NSView* subview in subviews.get())
|
||||
if ([subview isKindOfClass:[DragRegionView class]])
|
||||
// Remove all DragRegionViews that were added last time. Note that we need
|
||||
// to copy the `subviews` array to avoid mutation during iteration.
|
||||
base::scoped_nsobject<NSArray> subviews([[web_view subviews] copy]);
|
||||
for (NSView* subview in subviews.get()) {
|
||||
if ([subview isKindOfClass:[DragRegionView class]]) {
|
||||
[subview removeFromSuperview];
|
||||
}
|
||||
}
|
||||
|
||||
// Create one giant NSView that is draggable.
|
||||
base::scoped_nsobject<NSView> dragRegion(
|
||||
[[DragRegionView alloc] initWithFrame:NSZeroRect]);
|
||||
[dragRegion setFrame:NSMakeRect(0,
|
||||
0,
|
||||
webViewWidth,
|
||||
webViewHeight)];
|
||||
base::scoped_nsobject<NSView> drag_region_view(
|
||||
[[DragRegionView alloc] initWithFrame:web_view.bounds]);
|
||||
[web_view addSubview:drag_region_view];
|
||||
|
||||
// Then, on top of that, add "exclusion zones"
|
||||
for (auto iter = system_drag_exclude_areas.begin();
|
||||
iter != system_drag_exclude_areas.end();
|
||||
++iter) {
|
||||
base::scoped_nsobject<NSView> controlRegion(
|
||||
[[ExcludeDragRegionView alloc] initWithFrame:NSZeroRect]);
|
||||
[controlRegion setFrame:NSMakeRect(iter->x() - webViewX,
|
||||
webViewHeight - iter->bottom() + webViewY,
|
||||
iter->width(),
|
||||
iter->height())];
|
||||
[dragRegion addSubview:controlRegion];
|
||||
}
|
||||
for (const auto& rect : drag_exclude_rects) {
|
||||
const auto window_content_view_exclude_rect =
|
||||
NSMakeRect(rect.x(), window_content_view_height - rect.bottom(),
|
||||
rect.width(), rect.height());
|
||||
const auto drag_region_view_exclude_rect =
|
||||
[window_content_view convertRect:window_content_view_exclude_rect
|
||||
toView:drag_region_view];
|
||||
|
||||
// Add the DragRegion to the WebView
|
||||
[webView addSubview:dragRegion];
|
||||
base::scoped_nsobject<NSView> exclude_drag_region_view(
|
||||
[[ExcludeDragRegionView alloc]
|
||||
initWithFrame:drag_region_view_exclude_rect]);
|
||||
[drag_region_view addSubview:exclude_drag_region_view];
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
NativeBrowserView* NativeBrowserView::Create(
|
||||
brightray::InspectableWebContentsView* web_contents_view) {
|
||||
return new NativeBrowserViewMac(web_contents_view);
|
||||
brightray::InspectableWebContents* inspectable_web_contents) {
|
||||
return new NativeBrowserViewMac(inspectable_web_contents);
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
namespace atom {
|
||||
|
||||
NativeBrowserViewViews::NativeBrowserViewViews(
|
||||
brightray::InspectableWebContentsView* web_contents_view)
|
||||
: NativeBrowserView(web_contents_view) {}
|
||||
brightray::InspectableWebContents* inspectable_web_contents)
|
||||
: NativeBrowserView(inspectable_web_contents) {}
|
||||
|
||||
NativeBrowserViewViews::~NativeBrowserViewViews() {}
|
||||
|
||||
@@ -29,8 +29,8 @@ void NativeBrowserViewViews::SetBackgroundColor(SkColor color) {
|
||||
|
||||
// static
|
||||
NativeBrowserView* NativeBrowserView::Create(
|
||||
brightray::InspectableWebContentsView* web_contents_view) {
|
||||
return new NativeBrowserViewViews(web_contents_view);
|
||||
brightray::InspectableWebContents* inspectable_web_contents) {
|
||||
return new NativeBrowserViewViews(inspectable_web_contents);
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace atom {
|
||||
class NativeBrowserViewViews : public NativeBrowserView {
|
||||
public:
|
||||
explicit NativeBrowserViewViews(
|
||||
brightray::InspectableWebContentsView* web_contents_view);
|
||||
brightray::InspectableWebContents* inspectable_web_contents);
|
||||
~NativeBrowserViewViews() override;
|
||||
|
||||
uint8_t GetAutoResizeFlags() { return auto_resize_flags_; }
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "atom/browser/native_window.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
@@ -47,10 +48,35 @@
|
||||
#include "ui/gfx/font_render_params.h"
|
||||
#endif
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include "ui/base/win/shell.h"
|
||||
#include "ui/display/win/screen_win.h"
|
||||
#endif
|
||||
|
||||
DEFINE_WEB_CONTENTS_USER_DATA_KEY(atom::NativeWindowRelay);
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
#if defined(OS_WIN)
|
||||
gfx::Size GetExpandedWindowSize(const NativeWindow* window, gfx::Size size) {
|
||||
if (!window->transparent() || !ui::win::IsAeroGlassEnabled())
|
||||
return size;
|
||||
|
||||
gfx::Size min_size = display::win::ScreenWin::ScreenToDIPSize(
|
||||
window->GetAcceleratedWidget(), gfx::Size(64, 64));
|
||||
|
||||
// Some AMD drivers can't display windows that are less than 64x64 pixels,
|
||||
// so expand them to be at least that size. http://crbug.com/286609
|
||||
gfx::Size expanded(std::max(size.width(), min_size.width()),
|
||||
std::max(size.height(), min_size.height()));
|
||||
return expanded;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
NativeWindow::NativeWindow(
|
||||
brightray::InspectableWebContents* inspectable_web_contents,
|
||||
const mate::Dictionary& options,
|
||||
@@ -307,6 +333,21 @@ gfx::Size NativeWindow::GetMaximumSize() const {
|
||||
return GetSizeConstraints().GetMaximumSize();
|
||||
}
|
||||
|
||||
gfx::Size NativeWindow::GetContentMinimumSize() const {
|
||||
return GetContentSizeConstraints().GetMinimumSize();
|
||||
}
|
||||
|
||||
gfx::Size NativeWindow::GetContentMaximumSize() const {
|
||||
gfx::Size maximum_size = GetContentSizeConstraints().GetMaximumSize();
|
||||
#if defined(OS_WIN)
|
||||
return GetContentSizeConstraints().HasMaximumSize()
|
||||
? GetExpandedWindowSize(this, maximum_size)
|
||||
: maximum_size;
|
||||
#else
|
||||
return maximum_size;
|
||||
#endif
|
||||
}
|
||||
|
||||
void NativeWindow::SetSheetOffset(const double offsetX, const double offsetY) {
|
||||
sheet_offset_x_ = offsetX;
|
||||
sheet_offset_y_ = offsetY;
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace gfx {
|
||||
class Point;
|
||||
class Rect;
|
||||
class Size;
|
||||
}
|
||||
} // namespace gfx
|
||||
|
||||
namespace mate {
|
||||
class Dictionary;
|
||||
@@ -109,6 +109,8 @@ class NativeWindow : public base::SupportsUserData,
|
||||
virtual gfx::Size GetMinimumSize() const;
|
||||
virtual void SetMaximumSize(const gfx::Size& size);
|
||||
virtual gfx::Size GetMaximumSize() const;
|
||||
virtual gfx::Size GetContentMinimumSize() const;
|
||||
virtual gfx::Size GetContentMaximumSize() const;
|
||||
virtual void SetSheetOffset(const double offsetX, const double offsetY);
|
||||
virtual double GetSheetOffsetX();
|
||||
virtual double GetSheetOffsetY();
|
||||
@@ -160,15 +162,14 @@ class NativeWindow : public base::SupportsUserData,
|
||||
|
||||
// Taskbar/Dock APIs.
|
||||
enum ProgressState {
|
||||
PROGRESS_NONE, // no progress, no marking
|
||||
PROGRESS_INDETERMINATE, // progress, indeterminate
|
||||
PROGRESS_ERROR, // progress, errored (red)
|
||||
PROGRESS_PAUSED, // progress, paused (yellow)
|
||||
PROGRESS_NORMAL, // progress, not marked (green)
|
||||
PROGRESS_NONE, // no progress, no marking
|
||||
PROGRESS_INDETERMINATE, // progress, indeterminate
|
||||
PROGRESS_ERROR, // progress, errored (red)
|
||||
PROGRESS_PAUSED, // progress, paused (yellow)
|
||||
PROGRESS_NORMAL, // progress, not marked (green)
|
||||
};
|
||||
|
||||
virtual void SetProgressBar(double progress,
|
||||
const ProgressState state) = 0;
|
||||
virtual void SetProgressBar(double progress, const ProgressState state) = 0;
|
||||
virtual void SetOverlayIcon(const gfx::Image& overlay,
|
||||
const std::string& description) = 0;
|
||||
|
||||
@@ -230,14 +231,15 @@ class NativeWindow : public base::SupportsUserData,
|
||||
virtual void HandleKeyboardEvent(
|
||||
content::WebContents*,
|
||||
const content::NativeWebKeyboardEvent& event) {}
|
||||
virtual void ShowAutofillPopup(
|
||||
content::RenderFrameHost* frame_host,
|
||||
content::WebContents* web_contents,
|
||||
const gfx::RectF& bounds,
|
||||
const std::vector<base::string16>& values,
|
||||
const std::vector<base::string16>& labels) {}
|
||||
virtual void ShowAutofillPopup(content::RenderFrameHost* frame_host,
|
||||
content::WebContents* web_contents,
|
||||
const gfx::RectF& bounds,
|
||||
const std::vector<base::string16>& values,
|
||||
const std::vector<base::string16>& labels) {}
|
||||
virtual void HideAutofillPopup(content::RenderFrameHost* frame_host) {}
|
||||
|
||||
virtual void UpdateDraggableRegionViews() {}
|
||||
|
||||
// Public API used by platform-dependent delegates and observers to send UI
|
||||
// related notifications.
|
||||
void NotifyWindowClosed();
|
||||
@@ -268,13 +270,11 @@ class NativeWindow : public base::SupportsUserData,
|
||||
const base::DictionaryValue& details);
|
||||
void NotifyNewWindowForTab();
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#if defined(OS_WIN)
|
||||
void NotifyWindowMessage(UINT message, WPARAM w_param, LPARAM l_param);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void AddObserver(NativeWindowObserver* obs) {
|
||||
observers_.AddObserver(obs);
|
||||
}
|
||||
void AddObserver(NativeWindowObserver* obs) { observers_.AddObserver(obs); }
|
||||
void RemoveObserver(NativeWindowObserver* obs) {
|
||||
observers_.RemoveObserver(obs);
|
||||
}
|
||||
@@ -388,11 +388,11 @@ class NativeWindow : public base::SupportsUserData,
|
||||
};
|
||||
|
||||
// This class provides a hook to get a NativeWindow from a WebContents.
|
||||
class NativeWindowRelay :
|
||||
public content::WebContentsUserData<NativeWindowRelay> {
|
||||
class NativeWindowRelay
|
||||
: public content::WebContentsUserData<NativeWindowRelay> {
|
||||
public:
|
||||
explicit NativeWindowRelay(base::WeakPtr<NativeWindow> window)
|
||||
: key(UserDataKey()), window(window) {}
|
||||
: key(UserDataKey()), window(window) {}
|
||||
|
||||
static void* UserDataKey() {
|
||||
return content::WebContentsUserData<NativeWindowRelay>::UserDataKey();
|
||||
|
||||
@@ -127,7 +127,7 @@ class NativeWindowMac : public NativeWindow,
|
||||
content::RenderViewHost* new_host) override;
|
||||
|
||||
// Refresh the DraggableRegion views.
|
||||
void UpdateDraggableRegionViews() {
|
||||
void UpdateDraggableRegionViews() override {
|
||||
UpdateDraggableRegionViews(draggable_regions_);
|
||||
}
|
||||
|
||||
|
||||
@@ -380,6 +380,7 @@ bool ScopedDisableResize::disable_resize_ = false;
|
||||
|
||||
// Set window style to hide the toolbar, otherwise the toolbar will show in
|
||||
// fullscreen mode.
|
||||
[window setTitlebarAppearsTransparent:NO];
|
||||
shell_->SetStyleMask(true, NSFullSizeContentViewWindowMask);
|
||||
}
|
||||
}
|
||||
@@ -397,6 +398,7 @@ bool ScopedDisableResize::disable_resize_ = false;
|
||||
// Turn off the style for toolbar.
|
||||
if (base::mac::IsAtLeastOS10_10() &&
|
||||
shell_->title_bar_style() == atom::NativeWindowMac::HIDDEN_INSET) {
|
||||
[window setTitlebarAppearsTransparent:YES];
|
||||
shell_->SetStyleMask(false, NSFullSizeContentViewWindowMask);
|
||||
}
|
||||
}
|
||||
@@ -728,10 +730,20 @@ enum {
|
||||
|
||||
// Custom window button methods
|
||||
|
||||
- (BOOL)windowShouldClose:(id)sender { return YES; }
|
||||
|
||||
- (void)performClose:(id)sender {
|
||||
if (shell_->title_bar_style() == atom::NativeWindowMac::CUSTOM_BUTTONS_ON_HOVER)
|
||||
if (shell_->title_bar_style() ==
|
||||
atom::NativeWindowMac::CUSTOM_BUTTONS_ON_HOVER) {
|
||||
[[self delegate] windowShouldClose:self];
|
||||
else
|
||||
} else if (shell_->IsSimpleFullScreen()) {
|
||||
if([[self delegate] respondsToSelector:@selector(windowShouldClose:)]) {
|
||||
if(![[self delegate] windowShouldClose:self]) return;
|
||||
} else if([self respondsToSelector:@selector(windowShouldClose:)]) {
|
||||
if(![self windowShouldClose:self]) return;
|
||||
}
|
||||
[self close];
|
||||
} else
|
||||
[super performClose:sender];
|
||||
}
|
||||
|
||||
@@ -1980,25 +1992,20 @@ void NativeWindowMac::UpdateDraggableRegionViews(
|
||||
|
||||
// Draggable regions is implemented by having the whole web view draggable
|
||||
// (mouseDownCanMoveWindow) and overlaying regions that are not draggable.
|
||||
std::vector<gfx::Rect> system_drag_exclude_areas =
|
||||
std::vector<gfx::Rect> drag_exclude_rects =
|
||||
CalculateNonDraggableRegions(regions, webViewWidth, webViewHeight);
|
||||
|
||||
if (browser_view_) {
|
||||
browser_view_->UpdateDraggableRegions(system_drag_exclude_areas);
|
||||
browser_view_->UpdateDraggableRegions(drag_exclude_rects);
|
||||
}
|
||||
|
||||
// Create and add a ControlRegionView for each region that needs to be
|
||||
// excluded from the dragging.
|
||||
for (std::vector<gfx::Rect>::const_iterator iter =
|
||||
system_drag_exclude_areas.begin();
|
||||
iter != system_drag_exclude_areas.end();
|
||||
++iter) {
|
||||
for (const auto& rect : drag_exclude_rects) {
|
||||
base::scoped_nsobject<NSView> controlRegion(
|
||||
[[ControlRegionView alloc] initWithFrame:NSZeroRect]);
|
||||
[controlRegion setFrame:NSMakeRect(iter->x(),
|
||||
webViewHeight - iter->bottom(),
|
||||
iter->width(),
|
||||
iter->height())];
|
||||
[controlRegion setFrame:NSMakeRect(rect.x(), webViewHeight - rect.bottom(),
|
||||
rect.width(), rect.height())];
|
||||
[webView addSubview:controlRegion];
|
||||
}
|
||||
|
||||
|
||||
@@ -1338,7 +1338,7 @@ void NativeWindowViews::HandleKeyboardEvent(
|
||||
if (event.GetType() == blink::WebInputEvent::kRawKeyDown &&
|
||||
!IsAltKey(event) && IsAltModifier(event)) {
|
||||
if (!menu_bar_visible_ &&
|
||||
(menu_bar_->GetAcceleratorIndex(event.windows_key_code) != -1))
|
||||
(menu_bar_->HasAccelerator(event.windows_key_code)))
|
||||
SetMenuBarVisibility(true);
|
||||
menu_bar_->ActivateAccelerator(event.windows_key_code);
|
||||
return;
|
||||
@@ -1446,12 +1446,9 @@ void NativeWindowViews::RegisterAccelerators(AtomMenuModel* menu_model) {
|
||||
|
||||
// Register accelerators with focus manager.
|
||||
accelerator_util::GenerateAcceleratorTable(&accelerator_table_, menu_model);
|
||||
accelerator_util::AcceleratorTable::const_iterator iter;
|
||||
for (iter = accelerator_table_.begin();
|
||||
iter != accelerator_table_.end();
|
||||
++iter) {
|
||||
for (const auto& iter : accelerator_table_) {
|
||||
focus_manager->RegisterAccelerator(
|
||||
iter->first, ui::AcceleratorManager::kNormalPriority, this);
|
||||
iter.first, ui::AcceleratorManager::kNormalPriority, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -241,10 +241,21 @@ void URLRequestAsarJob::FetchMetaInfo(const base::FilePath& file_path,
|
||||
meta_info->is_directory = file_info.is_directory;
|
||||
}
|
||||
}
|
||||
// On Windows GetMimeTypeFromFile() goes to the registry. Thus it should be
|
||||
// done in WorkerPool.
|
||||
meta_info->mime_type_result =
|
||||
net::GetMimeTypeFromFile(file_path, &meta_info->mime_type);
|
||||
|
||||
// We use GetWellKnownMimeTypeFromExtension() to ensure that configurations
|
||||
// that may have been set by other programs on a user's machine don't affect
|
||||
// the mime type returned (in particular, JS should always be
|
||||
// (application/javascript). See https://crbug.com/797712. Using an accurate
|
||||
// mime type is necessary at least for modules and sw, which enforce strict
|
||||
// mime type requirements.
|
||||
// TODO(deepak1556): Revert this when sw support is removed for file scheme.
|
||||
base::FilePath::StringType file_extension = file_path.Extension();
|
||||
if (file_extension.empty()) {
|
||||
meta_info->mime_type_result = false;
|
||||
} else {
|
||||
meta_info->mime_type_result = net::GetWellKnownMimeTypeFromExtension(
|
||||
file_extension.substr(1), &meta_info->mime_type);
|
||||
}
|
||||
}
|
||||
|
||||
void URLRequestAsarJob::DidFetchMetaInfo(const FileMetaInfo* meta_info) {
|
||||
|
||||
85
atom/browser/net/resolve_proxy_helper.cc
Normal file
85
atom/browser/net/resolve_proxy_helper.cc
Normal file
@@ -0,0 +1,85 @@
|
||||
// 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/net/resolve_proxy_helper.h"
|
||||
|
||||
#include "base/threading/thread_task_runner_handle.h"
|
||||
#include "net/url_request/url_request_context.h"
|
||||
#include "net/url_request/url_request_context_getter.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
ResolveProxyHelper::ResolveProxyHelper(net::URLRequestContextGetter* getter)
|
||||
: context_getter_(getter),
|
||||
original_thread_(base::ThreadTaskRunnerHandle::Get()) {}
|
||||
|
||||
ResolveProxyHelper::~ResolveProxyHelper() {
|
||||
// Clear all pending requests if the ProxyService is still alive.
|
||||
pending_requests_.clear();
|
||||
}
|
||||
|
||||
void ResolveProxyHelper::ResolveProxy(const GURL& url,
|
||||
const ResolveProxyCallback& callback) {
|
||||
// Enqueue the pending request.
|
||||
pending_requests_.push_back(PendingRequest(url, callback));
|
||||
|
||||
// If nothing is in progress, start.
|
||||
if (pending_requests_.size() == 1)
|
||||
StartPendingRequest();
|
||||
}
|
||||
|
||||
void ResolveProxyHelper::SendProxyResult(const std::string& proxy) {
|
||||
CHECK(!pending_requests_.empty());
|
||||
|
||||
const auto& completed_request = pending_requests_.front();
|
||||
if (!completed_request.callback.is_null())
|
||||
completed_request.callback.Run(proxy);
|
||||
|
||||
// Clear the current (completed) request.
|
||||
pending_requests_.pop_front();
|
||||
|
||||
// Start the next request.
|
||||
if (!pending_requests_.empty())
|
||||
StartPendingRequest();
|
||||
}
|
||||
|
||||
void ResolveProxyHelper::StartPendingRequest() {
|
||||
auto& request = pending_requests_.front();
|
||||
context_getter_->GetNetworkTaskRunner()->PostTask(
|
||||
FROM_HERE,
|
||||
base::BindOnce(&ResolveProxyHelper::StartPendingRequestInIO,
|
||||
base::Unretained(this), request.url, request.pac_req));
|
||||
}
|
||||
|
||||
void ResolveProxyHelper::OnResolveProxyCompleted(int result) {
|
||||
std::string proxy;
|
||||
if (result == net::OK)
|
||||
proxy = proxy_info_.ToPacString();
|
||||
|
||||
original_thread_->PostTask(
|
||||
FROM_HERE, base::BindOnce(&ResolveProxyHelper::SendProxyResult,
|
||||
base::Unretained(this), proxy));
|
||||
}
|
||||
|
||||
void ResolveProxyHelper::StartPendingRequestInIO(
|
||||
const GURL& url,
|
||||
net::ProxyService::PacRequest* pac_req) {
|
||||
// Verify the request wasn't started yet.
|
||||
DCHECK(nullptr == pac_req);
|
||||
|
||||
auto proxy_service = context_getter_->GetURLRequestContext()->proxy_service();
|
||||
|
||||
// Start the request.
|
||||
int result = proxy_service->ResolveProxy(
|
||||
url, std::string(), &proxy_info_,
|
||||
base::Bind(&ResolveProxyHelper::OnResolveProxyCompleted,
|
||||
base::Unretained(this)),
|
||||
&pac_req, nullptr, net::NetLogWithSource());
|
||||
|
||||
// Completed synchronously.
|
||||
if (result != net::ERR_IO_PENDING)
|
||||
OnResolveProxyCompleted(result);
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
59
atom/browser/net/resolve_proxy_helper.h
Normal file
59
atom/browser/net/resolve_proxy_helper.h
Normal file
@@ -0,0 +1,59 @@
|
||||
// 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_NET_RESOLVE_PROXY_HELPER_H_
|
||||
#define ATOM_BROWSER_NET_RESOLVE_PROXY_HELPER_H_
|
||||
|
||||
#include <deque>
|
||||
#include <string>
|
||||
|
||||
#include "base/memory/ref_counted.h"
|
||||
#include "net/proxy/proxy_service.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
namespace net {
|
||||
class URLRequestContextGetter;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
class ResolveProxyHelper
|
||||
: public base::RefCountedThreadSafe<ResolveProxyHelper> {
|
||||
public:
|
||||
using ResolveProxyCallback = base::Callback<void(std::string)>;
|
||||
explicit ResolveProxyHelper(net::URLRequestContextGetter* getter);
|
||||
|
||||
void ResolveProxy(const GURL& url, const ResolveProxyCallback& callback);
|
||||
|
||||
private:
|
||||
friend class base::RefCountedThreadSafe<ResolveProxyHelper>;
|
||||
struct PendingRequest {
|
||||
public:
|
||||
PendingRequest(const GURL& url, const ResolveProxyCallback& callback)
|
||||
: url(url), callback(callback), pac_req(nullptr) {}
|
||||
|
||||
GURL url;
|
||||
ResolveProxyCallback callback;
|
||||
net::ProxyService::PacRequest* pac_req;
|
||||
};
|
||||
|
||||
~ResolveProxyHelper();
|
||||
|
||||
void StartPendingRequest();
|
||||
void StartPendingRequestInIO(const GURL& request,
|
||||
net::ProxyService::PacRequest* pac_req);
|
||||
void SendProxyResult(const std::string& proxy);
|
||||
void OnResolveProxyCompleted(int result);
|
||||
|
||||
net::ProxyInfo proxy_info_;
|
||||
std::deque<PendingRequest> pending_requests_;
|
||||
scoped_refptr<net::URLRequestContextGetter> context_getter_;
|
||||
scoped_refptr<base::SingleThreadTaskRunner> original_thread_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ResolveProxyHelper);
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_NET_RESOLVE_PROXY_HELPER_H_
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#include "atom/browser/node_debugger.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/command_line.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "libplatform/libplatform.h"
|
||||
@@ -28,10 +30,15 @@ void NodeDebugger::Start(node::NodePlatform* platform) {
|
||||
node::DebugOptions options;
|
||||
for (auto& arg : base::CommandLine::ForCurrentProcess()->argv()) {
|
||||
#if defined(OS_WIN)
|
||||
options.ParseOption("Electron", base::UTF16ToUTF8(arg));
|
||||
const std::string nice_arg = base::UTF16ToUTF8(arg);
|
||||
#else
|
||||
options.ParseOption("Electron", arg);
|
||||
const std::string& nice_arg = arg;
|
||||
#endif
|
||||
// Stop handling arguments after a "--" to be consistent with Chromium
|
||||
if (nice_arg == "--")
|
||||
break;
|
||||
|
||||
options.ParseOption("Electron", nice_arg);
|
||||
}
|
||||
|
||||
if (options.inspector_enabled()) {
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>electron.icns</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>2.0.0</string>
|
||||
<string>2.0.11</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2.0.0</string>
|
||||
<string>2.0.11</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.developer-tools</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
|
||||
@@ -56,8 +56,8 @@ END
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 2,0,0,4
|
||||
PRODUCTVERSION 2,0,0,4
|
||||
FILEVERSION 2,0,11,0
|
||||
PRODUCTVERSION 2,0,11,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@@ -74,12 +74,12 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "GitHub, Inc."
|
||||
VALUE "FileDescription", "Electron"
|
||||
VALUE "FileVersion", "2.0.0"
|
||||
VALUE "FileVersion", "2.0.11"
|
||||
VALUE "InternalName", "electron.exe"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
|
||||
VALUE "OriginalFilename", "electron.exe"
|
||||
VALUE "ProductName", "Electron"
|
||||
VALUE "ProductVersion", "2.0.0"
|
||||
VALUE "ProductVersion", "2.0.11"
|
||||
VALUE "SquirrelAwareVersion", "1"
|
||||
END
|
||||
END
|
||||
|
||||
@@ -91,7 +91,9 @@ bool TriggerAcceleratorTableCommand(AcceleratorTable* table,
|
||||
if (base::ContainsKey(*table, accelerator)) {
|
||||
const accelerator_util::MenuItem& item = (*table)[accelerator];
|
||||
if (item.model->IsEnabledAt(item.position)) {
|
||||
item.model->ActivatedAt(item.position);
|
||||
const auto event_flags =
|
||||
accelerator.MaskOutKeyEventFlags(accelerator.modifiers());
|
||||
item.model->ActivatedAt(item.position, event_flags);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,7 +123,9 @@ static base::scoped_nsobject<NSMenu> recentDocumentsMenuSwap_;
|
||||
[menu_ cancelTracking];
|
||||
isMenuOpen_ = NO;
|
||||
model_->MenuWillClose();
|
||||
closeCallback.Run();
|
||||
if (!closeCallback.is_null()) {
|
||||
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, closeCallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,72 +15,99 @@
|
||||
#include "base/strings/sys_string_conversions.h"
|
||||
|
||||
@interface PopUpButtonHandler : NSObject
|
||||
@property (nonatomic, strong) NSSavePanel *savePanel;
|
||||
@property (nonatomic, strong) NSArray *fileTypes;
|
||||
- (instancetype)initWithPanel:(NSSavePanel *)panel andTypes:(NSArray *)types;
|
||||
|
||||
@property(nonatomic, assign) NSSavePanel* savePanel;
|
||||
@property(nonatomic, strong) NSArray* fileTypesList;
|
||||
|
||||
- (instancetype)initWithPanel:(NSSavePanel*)panel
|
||||
andTypesList:(NSArray*)typesList;
|
||||
- (void)selectFormat:(id)sender;
|
||||
|
||||
@end
|
||||
|
||||
@implementation PopUpButtonHandler
|
||||
- (instancetype)initWithPanel:(NSSavePanel *)panel andTypes:(NSArray *)types {
|
||||
|
||||
- (instancetype)initWithPanel:(NSSavePanel*)panel
|
||||
andTypesList:(NSArray*)typesList {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_savePanel = panel;
|
||||
_fileTypes = types;
|
||||
[self setSavePanel:panel];
|
||||
[self setFileTypesList:typesList];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)selectFormat:(id)sender {
|
||||
NSPopUpButton *button = (NSPopUpButton *)sender;
|
||||
NSPopUpButton* button = (NSPopUpButton*)sender;
|
||||
NSInteger selectedItemIndex = [button indexOfSelectedItem];
|
||||
NSString *nameFieldString = [[self savePanel] nameFieldStringValue];
|
||||
NSString *trimmedNameFieldString = [nameFieldString stringByDeletingPathExtension];
|
||||
NSString *extension = [[self fileTypes] objectAtIndex: selectedItemIndex];
|
||||
NSArray* list = [self fileTypesList];
|
||||
NSArray* fileTypes = [list objectAtIndex:selectedItemIndex];
|
||||
|
||||
NSString *nameFieldStringWithExt = [NSString stringWithFormat:@"%@.%@", trimmedNameFieldString, extension];
|
||||
[[self savePanel] setNameFieldStringValue:nameFieldStringWithExt];
|
||||
[[self savePanel] setAllowedFileTypes:@[extension]];
|
||||
// If we meet a '*' file extension, we allow all the file types and no
|
||||
// need to set the specified file types.
|
||||
if ([fileTypes count] == 0 || [fileTypes containsObject:@"*"])
|
||||
[[self savePanel] setAllowedFileTypes:nil];
|
||||
else
|
||||
[[self savePanel] setAllowedFileTypes:fileTypes];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
// Manages the PopUpButtonHandler.
|
||||
@interface AtomAccessoryView : NSView
|
||||
@end
|
||||
|
||||
@implementation AtomAccessoryView
|
||||
|
||||
- (void)dealloc {
|
||||
auto* popupButton = static_cast<NSPopUpButton*>([[self subviews] objectAtIndex: 1]);
|
||||
[[popupButton target] release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace file_dialog {
|
||||
|
||||
namespace {
|
||||
|
||||
static PopUpButtonHandler *popUpButtonHandler;
|
||||
|
||||
void SetAllowedFileTypes(NSSavePanel* dialog, const Filters& filters) {
|
||||
NSMutableSet* file_type_set = [NSMutableSet set];
|
||||
for (size_t i = 0; i < filters.size(); ++i) {
|
||||
const Filter& filter = filters[i];
|
||||
for (size_t j = 0; j < filter.second.size(); ++j) {
|
||||
// If we meet a '*' file extension, we allow all the file types and no
|
||||
// need to set the specified file types.
|
||||
NSMutableArray* file_types_list = [NSMutableArray array];
|
||||
NSMutableArray* filter_names = [NSMutableArray array];
|
||||
|
||||
if (filter.second[j] == "*") {
|
||||
[dialog setAllowsOtherFileTypes:YES];
|
||||
return;
|
||||
}
|
||||
base::ScopedCFTypeRef<CFStringRef> ext_cf(
|
||||
base::SysUTF8ToCFStringRef(filter.second[j]));
|
||||
// Create array to keep file types and their name.
|
||||
for (const Filter& filter : filters) {
|
||||
NSMutableSet* file_type_set = [NSMutableSet set];
|
||||
base::ScopedCFTypeRef<CFStringRef> name_cf(
|
||||
base::SysUTF8ToCFStringRef(filter.first));
|
||||
[filter_names addObject:base::mac::CFToNSCast(name_cf.get())];
|
||||
for (const std::string& ext : filter.second) {
|
||||
base::ScopedCFTypeRef<CFStringRef> ext_cf(base::SysUTF8ToCFStringRef(ext));
|
||||
[file_type_set addObject:base::mac::CFToNSCast(ext_cf.get())];
|
||||
}
|
||||
[file_types_list addObject:[file_type_set allObjects]];
|
||||
}
|
||||
|
||||
// Passing empty array to setAllowedFileTypes will cause exception.
|
||||
NSArray* file_types = nil;
|
||||
if ([file_type_set count])
|
||||
file_types = [file_type_set allObjects];
|
||||
|
||||
NSUInteger count = [file_types_list count];
|
||||
if (count > 0) {
|
||||
file_types = [[file_types_list objectAtIndex:0] allObjects];
|
||||
// If we meet a '*' file extension, we allow all the file types and no
|
||||
// need to set the specified file types.
|
||||
if ([file_types count] == 0 || [file_types containsObject:@"*"])
|
||||
file_types = nil;
|
||||
}
|
||||
[dialog setAllowedFileTypes:file_types];
|
||||
|
||||
if (!popUpButtonHandler)
|
||||
popUpButtonHandler = [[PopUpButtonHandler alloc] initWithPanel:dialog andTypes:file_types];
|
||||
if (count <= 1)
|
||||
return; // don't add file format picker
|
||||
|
||||
// add file format picker
|
||||
NSView *accessoryView = [[NSView alloc] initWithFrame:NSMakeRect(0.0, 0.0, 200, 32.0)];
|
||||
NSTextField *label = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 60, 22)];
|
||||
// Add file format picker.
|
||||
AtomAccessoryView* accessoryView =
|
||||
[[AtomAccessoryView alloc] initWithFrame:NSMakeRect(0.0, 0.0, 200, 32.0)];
|
||||
NSTextField* label =
|
||||
[[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 60, 22)];
|
||||
|
||||
[label setEditable:NO];
|
||||
[label setStringValue:@"Format:"];
|
||||
@@ -88,15 +115,18 @@ void SetAllowedFileTypes(NSSavePanel* dialog, const Filters& filters) {
|
||||
[label setBezeled:NO];
|
||||
[label setDrawsBackground:NO];
|
||||
|
||||
NSPopUpButton *popupButton = [[NSPopUpButton alloc] initWithFrame:NSMakeRect(50.0, 2, 140, 22.0) pullsDown:NO];
|
||||
[popupButton addItemsWithTitles:file_types];
|
||||
NSPopUpButton* popupButton = [[NSPopUpButton alloc] initWithFrame:NSMakeRect(50.0, 2, 140, 22.0)
|
||||
pullsDown:NO];
|
||||
PopUpButtonHandler* popUpButtonHandler = [[PopUpButtonHandler alloc] initWithPanel:dialog
|
||||
andTypesList:file_types_list];
|
||||
[popupButton addItemsWithTitles:filter_names];
|
||||
[popupButton setTarget:popUpButtonHandler];
|
||||
[popupButton setAction:@selector(selectFormat:)];
|
||||
|
||||
[accessoryView addSubview:label];
|
||||
[accessoryView addSubview:popupButton];
|
||||
[accessoryView addSubview:[label autorelease]];
|
||||
[accessoryView addSubview:[popupButton autorelease]];
|
||||
|
||||
[dialog setAccessoryView:accessoryView];
|
||||
[dialog setAccessoryView:[accessoryView autorelease]];
|
||||
}
|
||||
|
||||
void SetupDialog(NSSavePanel* dialog,
|
||||
@@ -118,6 +148,7 @@ void SetupDialog(NSSavePanel* dialog,
|
||||
NSString* default_dir = nil;
|
||||
NSString* default_filename = nil;
|
||||
if (!settings.default_path.empty()) {
|
||||
base::ThreadRestrictions::ScopedAllowIO allow_io;
|
||||
if (base::DirectoryExists(settings.default_path)) {
|
||||
default_dir = base::SysUTF8ToNSString(settings.default_path.value());
|
||||
} else {
|
||||
@@ -283,8 +314,9 @@ void ShowOpenDialog(const DialogSettings& settings,
|
||||
|
||||
if (!settings.parent_window || !settings.parent_window->GetNativeWindow() ||
|
||||
settings.force_detached) {
|
||||
int chosen = [dialog runModal];
|
||||
OpenDialogCompletion(chosen, dialog, settings, callback);
|
||||
[dialog beginWithCompletionHandler:^(NSInteger chosen) {
|
||||
OpenDialogCompletion(chosen, dialog, settings, callback);
|
||||
}];
|
||||
} else {
|
||||
NSWindow* window = settings.parent_window->GetNativeWindow();
|
||||
[dialog beginSheetModalForWindow:window
|
||||
@@ -343,8 +375,9 @@ void ShowSaveDialog(const DialogSettings& settings,
|
||||
|
||||
if (!settings.parent_window || !settings.parent_window->GetNativeWindow() ||
|
||||
settings.force_detached) {
|
||||
int chosen = [dialog runModal];
|
||||
SaveDialogCompletion(chosen, dialog, settings, callback);
|
||||
[dialog beginWithCompletionHandler:^(NSInteger chosen) {
|
||||
SaveDialogCompletion(chosen, dialog, settings, callback);
|
||||
}];
|
||||
} else {
|
||||
NSWindow* window = settings.parent_window->GetNativeWindow();
|
||||
[dialog beginSheetModalForWindow:window
|
||||
|
||||
@@ -96,11 +96,6 @@ NSAlert* CreateNSAlert(NativeWindow* parent_window,
|
||||
NSArray* ns_buttons = [alert buttons];
|
||||
int button_count = static_cast<int>([ns_buttons count]);
|
||||
|
||||
// Bind cancel id button to escape key if there is more than one button
|
||||
if (button_count > 1 && cancel_id >= 0 && cancel_id < button_count) {
|
||||
[[ns_buttons objectAtIndex:cancel_id] setKeyEquivalent:@"\e"];
|
||||
}
|
||||
|
||||
if (default_id >= 0 && default_id < button_count) {
|
||||
// Focus the button at default_id if the user opted to do so.
|
||||
// The first button added gets set as the default selected.
|
||||
@@ -109,6 +104,11 @@ NSAlert* CreateNSAlert(NativeWindow* parent_window,
|
||||
[[ns_buttons objectAtIndex:default_id] setKeyEquivalent:@"\r"];
|
||||
}
|
||||
|
||||
// Bind cancel id button to escape key if there is more than one button
|
||||
if (button_count > 1 && cancel_id >= 0 && cancel_id < button_count) {
|
||||
[[ns_buttons objectAtIndex:cancel_id] setKeyEquivalent:@"\e"];
|
||||
}
|
||||
|
||||
if (!checkbox_label.empty()) {
|
||||
alert.showsSuppressionButton = YES;
|
||||
alert.suppressionButton.title = base::SysUTF8ToNSString(checkbox_label);
|
||||
|
||||
@@ -40,9 +40,16 @@ const CGFloat kVerticalTitleMargin = 2;
|
||||
|
||||
@implementation StatusItemView
|
||||
|
||||
- (void)dealloc {
|
||||
trayIcon_ = nil;
|
||||
menuController_ = nil;
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (id)initWithImage:(NSImage*)image icon:(atom::TrayIconCocoa*)icon {
|
||||
image_.reset([image copy]);
|
||||
trayIcon_ = icon;
|
||||
menuController_ = nil;
|
||||
highlight_mode_ = atom::TrayIcon::HighlightMode::SELECTION;
|
||||
forceHighlight_ = NO;
|
||||
inMouseEventSequence_ = NO;
|
||||
@@ -85,6 +92,7 @@ const CGFloat kVerticalTitleMargin = 2;
|
||||
trackingArea_.reset();
|
||||
}
|
||||
[[NSStatusBar systemStatusBar] removeStatusItem:statusItem_];
|
||||
[statusItem_ setView:nil];
|
||||
statusItem_.reset();
|
||||
}
|
||||
|
||||
@@ -98,7 +106,7 @@ const CGFloat kVerticalTitleMargin = 2;
|
||||
|
||||
// Draw the system bar background.
|
||||
[statusItem_ drawStatusBarBackgroundInRect:self.bounds
|
||||
withHighlight:[self isHighlighted]];
|
||||
withHighlight:[self shouldHighlight]];
|
||||
|
||||
// Determine which image to use.
|
||||
NSImage* image = image_.get();
|
||||
@@ -230,8 +238,13 @@ const CGFloat kVerticalTitleMargin = 2;
|
||||
return;
|
||||
}
|
||||
|
||||
// check title_ being nil
|
||||
NSString *title = @"";
|
||||
if (title_)
|
||||
title = title_;
|
||||
|
||||
attributedTitle_.reset([[NSMutableAttributedString alloc]
|
||||
initWithString:title_
|
||||
initWithString:title
|
||||
attributes:attributes]);
|
||||
|
||||
//NSFontAttributeName:[NSFont menuBarFontOfSize:0],
|
||||
@@ -384,6 +397,11 @@ const CGFloat kVerticalTitleMargin = 2;
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)setNeedsDisplay:(BOOL)display {
|
||||
[self updateAttributedTitle];
|
||||
[super setNeedsDisplay:display];
|
||||
}
|
||||
|
||||
- (BOOL)shouldHighlight {
|
||||
switch (highlight_mode_) {
|
||||
case atom::TrayIcon::HighlightMode::ALWAYS:
|
||||
@@ -444,11 +462,18 @@ void TrayIconCocoa::SetContextMenu(AtomMenuModel* menu_model) {
|
||||
// Substribe to MenuClosed event.
|
||||
if (menu_model_)
|
||||
menu_model_->RemoveObserver(this);
|
||||
menu_model->AddObserver(this);
|
||||
|
||||
// Create native menu.
|
||||
menu_.reset([[AtomMenuController alloc] initWithModel:menu_model
|
||||
useDefaultAccelerator:NO]);
|
||||
menu_model_ = menu_model;
|
||||
|
||||
if (menu_model) {
|
||||
menu_model->AddObserver(this);
|
||||
// Create native menu.
|
||||
menu_.reset([[AtomMenuController alloc] initWithModel:menu_model
|
||||
useDefaultAccelerator:NO]);
|
||||
} else {
|
||||
menu_.reset();
|
||||
}
|
||||
|
||||
[status_item_view_ setMenuController:menu_.get()];
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "atom/browser/browser.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "brightray/common/application_info.h"
|
||||
#include "chrome/browser/ui/libgtkui/app_indicator_icon.h"
|
||||
#include "chrome/browser/ui/libgtkui/gtk_status_icon.h"
|
||||
#include "ui/gfx/image/image.h"
|
||||
@@ -32,16 +33,17 @@ void TrayIconGtk::SetImage(const gfx::Image& image) {
|
||||
return;
|
||||
}
|
||||
|
||||
base::string16 empty;
|
||||
const auto toolTip = base::UTF8ToUTF16(brightray::GetApplicationName());
|
||||
|
||||
if (libgtkui::AppIndicatorIcon::CouldOpen()) {
|
||||
++indicators_count;
|
||||
icon_.reset(new libgtkui::AppIndicatorIcon(
|
||||
base::StringPrintf(
|
||||
"%s%d", Browser::Get()->GetName().c_str(), indicators_count),
|
||||
image.AsImageSkia(),
|
||||
empty));
|
||||
toolTip));
|
||||
} else {
|
||||
icon_.reset(new libgtkui::Gtk2StatusIcon(image.AsImageSkia(), empty));
|
||||
icon_.reset(new libgtkui::Gtk2StatusIcon(image.AsImageSkia(), toolTip));
|
||||
}
|
||||
icon_->set_delegate(this);
|
||||
}
|
||||
|
||||
@@ -104,11 +104,11 @@ gfx::Size FramelessView::CalculatePreferredSize() const {
|
||||
}
|
||||
|
||||
gfx::Size FramelessView::GetMinimumSize() const {
|
||||
return window_->GetContentSizeConstraints().GetMinimumSize();
|
||||
return window_->GetContentMinimumSize();
|
||||
}
|
||||
|
||||
gfx::Size FramelessView::GetMaximumSize() const {
|
||||
return window_->GetContentSizeConstraints().GetMaximumSize();
|
||||
return window_->GetContentMaximumSize();
|
||||
}
|
||||
|
||||
const char* FramelessView::GetClassName() const {
|
||||
|
||||
@@ -209,7 +209,9 @@ void GlobalMenuBarX11::SetMenu(AtomMenuModel* menu_model) {
|
||||
DbusmenuMenuitem* root_item = menuitem_new();
|
||||
menuitem_property_set(root_item, kPropertyLabel, "Root");
|
||||
menuitem_property_set_bool(root_item, kPropertyVisible, true);
|
||||
BuildMenuFromModel(menu_model, root_item);
|
||||
if (menu_model != nullptr) {
|
||||
BuildMenuFromModel(menu_model, root_item);
|
||||
}
|
||||
|
||||
server_set_root(server_, root_item);
|
||||
g_object_unref(root_item);
|
||||
|
||||
@@ -4,9 +4,8 @@
|
||||
|
||||
#include "atom/browser/ui/views/menu_bar.h"
|
||||
|
||||
#if defined(USE_X11)
|
||||
#include "gtk/gtk.h"
|
||||
#endif
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/ui/views/menu_delegate.h"
|
||||
#include "atom/browser/ui/views/submenu_button.h"
|
||||
@@ -14,54 +13,18 @@
|
||||
#include "ui/views/background.h"
|
||||
#include "ui/views/layout/box_layout.h"
|
||||
|
||||
#if defined(USE_X11)
|
||||
#include "chrome/browser/ui/libgtkui/gtk_util.h"
|
||||
#endif
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include "ui/gfx/color_utils.h"
|
||||
#elif defined(USE_X11)
|
||||
#include "chrome/browser/ui/libgtkui/skia_utils_gtk.h"
|
||||
#endif
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
#if defined(USE_X11)
|
||||
|
||||
SkColor GdkRgbaToSkColor(const GdkRGBA& rgba) {
|
||||
return SkColorSetARGB(rgba.alpha * 255, rgba.red * 255, rgba.green * 255,
|
||||
rgba.blue * 255);
|
||||
}
|
||||
|
||||
SkColor GetStyleContextFgColor(GtkStyleContext* style_context,
|
||||
GtkStateFlags state) {
|
||||
GdkRGBA rgba;
|
||||
gtk_style_context_get_color(style_context, state, &rgba);
|
||||
return GdkRgbaToSkColor(rgba);
|
||||
}
|
||||
|
||||
SkColor GetStyleContextBgColor(GtkStyleContext* style_context,
|
||||
GtkStateFlags state) {
|
||||
GdkRGBA rgba;
|
||||
gtk_style_context_get_background_color(style_context, state, &rgba);
|
||||
return GdkRgbaToSkColor(rgba);
|
||||
}
|
||||
|
||||
void GetMenuBarColor(SkColor* enabled,
|
||||
SkColor* disabled,
|
||||
SkColor* highlight,
|
||||
SkColor* hover,
|
||||
SkColor* background) {
|
||||
GtkWidget* menu_bar = gtk_menu_bar_new();
|
||||
GtkStyleContext* sc = gtk_widget_get_style_context(menu_bar);
|
||||
*enabled = GetStyleContextFgColor(sc, GTK_STATE_FLAG_NORMAL);
|
||||
*disabled = GetStyleContextFgColor(sc, GTK_STATE_FLAG_INSENSITIVE);
|
||||
*highlight = GetStyleContextFgColor(sc, GTK_STATE_FLAG_SELECTED);
|
||||
*hover = GetStyleContextFgColor(sc, GTK_STATE_FLAG_PRELIGHT);
|
||||
*background = GetStyleContextBgColor(sc, GTK_STATE_FLAG_NORMAL);
|
||||
gtk_widget_destroy(GTK_WIDGET(menu_bar));
|
||||
}
|
||||
|
||||
#endif // USE_X11
|
||||
|
||||
const char kViewClassName[] = "ElectronMenuBar";
|
||||
|
||||
// Default color of the menu bar.
|
||||
@@ -71,75 +34,70 @@ const SkColor kDefaultColor = SkColorSetARGB(255, 233, 233, 233);
|
||||
|
||||
MenuBar::MenuBar(NativeWindow* window)
|
||||
: background_color_(kDefaultColor), menu_model_(NULL), window_(window) {
|
||||
UpdateMenuBarColor();
|
||||
RefreshColorCache();
|
||||
UpdateViewColors();
|
||||
SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal));
|
||||
}
|
||||
|
||||
MenuBar::~MenuBar() {}
|
||||
|
||||
void MenuBar::AddedToWidget() {
|
||||
auto fm = GetFocusManager();
|
||||
fm->AddFocusChangeListener(this);
|
||||
// Note that we don't own fm -- this manages the _connection_
|
||||
focus_manager_.reset(fm, [this](views::FocusManager* fm) {
|
||||
fm->RemoveFocusChangeListener(this);
|
||||
});
|
||||
}
|
||||
|
||||
void MenuBar::RemovedFromWidget() {
|
||||
focus_manager_.reset();
|
||||
}
|
||||
|
||||
void MenuBar::SetMenu(AtomMenuModel* model) {
|
||||
menu_model_ = model;
|
||||
RemoveAllChildViews(true);
|
||||
|
||||
for (int i = 0; i < model->GetItemCount(); ++i) {
|
||||
SubmenuButton* button =
|
||||
new SubmenuButton(model->GetLabelAt(i), this, background_color_);
|
||||
button->set_tag(i);
|
||||
|
||||
#if defined(USE_X11)
|
||||
button->SetTextColor(views::Button::STATE_NORMAL, enabled_color_);
|
||||
button->SetTextColor(views::Button::STATE_DISABLED, disabled_color_);
|
||||
button->SetTextColor(views::Button::STATE_PRESSED, highlight_color_);
|
||||
button->SetTextColor(views::Button::STATE_HOVERED, hover_color_);
|
||||
button->SetUnderlineColor(enabled_color_);
|
||||
#elif defined(OS_WIN)
|
||||
button->SetUnderlineColor(color_utils::GetSysSkColor(COLOR_GRAYTEXT));
|
||||
#endif
|
||||
|
||||
AddChildView(button);
|
||||
}
|
||||
RebuildChildren();
|
||||
}
|
||||
|
||||
void MenuBar::SetAcceleratorVisibility(bool visible) {
|
||||
for (int i = 0; i < child_count(); ++i)
|
||||
static_cast<SubmenuButton*>(child_at(i))->SetAcceleratorVisibility(visible);
|
||||
for (auto* child : GetChildrenInZOrder())
|
||||
static_cast<SubmenuButton*>(child)->SetAcceleratorVisibility(visible);
|
||||
}
|
||||
|
||||
int MenuBar::GetAcceleratorIndex(base::char16 key) {
|
||||
for (int i = 0; i < child_count(); ++i) {
|
||||
SubmenuButton* button = static_cast<SubmenuButton*>(child_at(i));
|
||||
if (button->accelerator() == key)
|
||||
return i;
|
||||
MenuBar::View* MenuBar::FindAccelChild(base::char16 key) {
|
||||
for (auto* child : GetChildrenInZOrder()) {
|
||||
if (static_cast<SubmenuButton*>(child)->accelerator() == key)
|
||||
return child;
|
||||
}
|
||||
return -1;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool MenuBar::HasAccelerator(base::char16 key) {
|
||||
return FindAccelChild(key) != nullptr;
|
||||
}
|
||||
|
||||
void MenuBar::ActivateAccelerator(base::char16 key) {
|
||||
int i = GetAcceleratorIndex(key);
|
||||
if (i != -1)
|
||||
static_cast<SubmenuButton*>(child_at(i))->Activate(nullptr);
|
||||
auto child = FindAccelChild(key);
|
||||
if (child)
|
||||
static_cast<SubmenuButton*>(child)->Activate(nullptr);
|
||||
}
|
||||
|
||||
int MenuBar::GetItemCount() const {
|
||||
return menu_model_->GetItemCount();
|
||||
return menu_model_ ? menu_model_->GetItemCount() : 0;
|
||||
}
|
||||
|
||||
bool MenuBar::GetMenuButtonFromScreenPoint(const gfx::Point& point,
|
||||
bool MenuBar::GetMenuButtonFromScreenPoint(const gfx::Point& screenPoint,
|
||||
AtomMenuModel** menu_model,
|
||||
views::MenuButton** button) {
|
||||
gfx::Point location(point);
|
||||
views::View::ConvertPointFromScreen(this, &location);
|
||||
|
||||
if (location.x() < 0 || location.x() >= width() || location.y() < 0 ||
|
||||
location.y() >= height())
|
||||
if (!GetBoundsInScreen().Contains(screenPoint))
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < child_count(); ++i) {
|
||||
views::View* view = child_at(i);
|
||||
if (view->GetMirroredBounds().Contains(location) &&
|
||||
auto children = GetChildrenInZOrder();
|
||||
for (int i = 0, n = children.size(); i < n; ++i) {
|
||||
if (children[i]->GetBoundsInScreen().Contains(screenPoint) &&
|
||||
(menu_model_->GetTypeAt(i) == AtomMenuModel::TYPE_SUBMENU)) {
|
||||
*menu_model = menu_model_->GetSubmenuModelAt(i);
|
||||
*button = static_cast<views::MenuButton*>(view);
|
||||
*button = static_cast<views::MenuButton*>(children[i]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -175,18 +133,75 @@ void MenuBar::OnMenuButtonClicked(views::MenuButton* source,
|
||||
menu_delegate->RunMenu(menu_model_->GetSubmenuModelAt(id), source);
|
||||
}
|
||||
|
||||
void MenuBar::OnNativeThemeChanged(const ui::NativeTheme* theme) {
|
||||
UpdateMenuBarColor();
|
||||
}
|
||||
void MenuBar::RefreshColorCache(const ui::NativeTheme* theme) {
|
||||
if (!theme)
|
||||
theme = ui::NativeTheme::GetInstanceForNativeUi();
|
||||
if (theme) {
|
||||
#if defined(USE_X11)
|
||||
const std::string menubar_selector = "GtkMenuBar#menubar";
|
||||
background_color_ = libgtkui::GetBgColor(menubar_selector);
|
||||
|
||||
void MenuBar::UpdateMenuBarColor() {
|
||||
enabled_color_ = theme->GetSystemColor(
|
||||
ui::NativeTheme::kColorId_EnabledMenuItemForegroundColor);
|
||||
disabled_color_ = theme->GetSystemColor(
|
||||
ui::NativeTheme::kColorId_DisabledMenuItemForegroundColor);
|
||||
#else
|
||||
background_color_ =
|
||||
theme->GetSystemColor(ui::NativeTheme::kColorId_MenuBackgroundColor);
|
||||
#endif
|
||||
}
|
||||
#if defined(OS_WIN)
|
||||
background_color_ = color_utils::GetSysSkColor(COLOR_MENUBAR);
|
||||
#elif defined(USE_X11)
|
||||
GetMenuBarColor(&enabled_color_, &disabled_color_, &highlight_color_,
|
||||
&hover_color_, &background_color_);
|
||||
#endif
|
||||
}
|
||||
|
||||
void MenuBar::OnNativeThemeChanged(const ui::NativeTheme* theme) {
|
||||
RefreshColorCache(theme);
|
||||
UpdateViewColors();
|
||||
}
|
||||
|
||||
void MenuBar::OnDidChangeFocus(View* focused_before, View* focused_now) {
|
||||
// if we've changed focus, update our view
|
||||
const auto had_focus = has_focus_;
|
||||
has_focus_ = focused_now != nullptr;
|
||||
if (has_focus_ != had_focus)
|
||||
UpdateViewColors();
|
||||
}
|
||||
|
||||
void MenuBar::RebuildChildren() {
|
||||
RemoveAllChildViews(true);
|
||||
for (int i = 0, n = GetItemCount(); i < n; ++i) {
|
||||
auto button =
|
||||
new SubmenuButton(menu_model_->GetLabelAt(i), this, background_color_);
|
||||
button->set_tag(i);
|
||||
AddChildView(button);
|
||||
}
|
||||
UpdateViewColors();
|
||||
}
|
||||
|
||||
void MenuBar::UpdateViewColors() {
|
||||
// set menubar background color
|
||||
SetBackground(views::CreateSolidBackground(background_color_));
|
||||
|
||||
// set child colors
|
||||
if (menu_model_ == nullptr)
|
||||
return;
|
||||
#if defined(USE_X11)
|
||||
const auto& textColor = has_focus_ ? enabled_color_ : disabled_color_;
|
||||
for (auto* child : GetChildrenInZOrder()) {
|
||||
auto button = static_cast<SubmenuButton*>(child);
|
||||
button->SetTextColor(views::Button::STATE_NORMAL, textColor);
|
||||
button->SetTextColor(views::Button::STATE_DISABLED, disabled_color_);
|
||||
button->SetTextColor(views::Button::STATE_PRESSED, enabled_color_);
|
||||
button->SetTextColor(views::Button::STATE_HOVERED, textColor);
|
||||
button->SetUnderlineColor(textColor);
|
||||
}
|
||||
#elif defined(OS_WIN)
|
||||
for (auto* child : GetChildrenInZOrder()) {
|
||||
auto button = static_cast<SubmenuButton*>(child);
|
||||
button->SetUnderlineColor(color_utils::GetSysSkColor(COLOR_MENUTEXT));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -5,9 +5,12 @@
|
||||
#ifndef ATOM_BROWSER_UI_VIEWS_MENU_BAR_H_
|
||||
#define ATOM_BROWSER_UI_VIEWS_MENU_BAR_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "atom/browser/ui/atom_menu_model.h"
|
||||
#include "ui/views/controls/button/menu_button_listener.h"
|
||||
#include "ui/views/focus/focus_manager.h"
|
||||
#include "ui/views/view.h"
|
||||
|
||||
namespace views {
|
||||
@@ -19,7 +22,8 @@ namespace atom {
|
||||
class MenuDelegate;
|
||||
|
||||
class MenuBar : public views::View,
|
||||
public views::MenuButtonListener {
|
||||
public views::MenuButtonListener,
|
||||
public views::FocusChangeListener {
|
||||
public:
|
||||
explicit MenuBar(NativeWindow* window);
|
||||
virtual ~MenuBar();
|
||||
@@ -30,9 +34,8 @@ class MenuBar : public views::View,
|
||||
// Shows underline under accelerators.
|
||||
void SetAcceleratorVisibility(bool visible);
|
||||
|
||||
// Returns which submenu has accelerator |key|, -1 would be returned when
|
||||
// there is no matching submenu.
|
||||
int GetAcceleratorIndex(base::char16 key);
|
||||
// Returns true if the submenu has accelerator |key|
|
||||
bool HasAccelerator(base::char16 key);
|
||||
|
||||
// Shows the submenu whose accelerator is |key|.
|
||||
void ActivateAccelerator(base::char16 key);
|
||||
@@ -47,7 +50,9 @@ class MenuBar : public views::View,
|
||||
|
||||
protected:
|
||||
// views::View:
|
||||
void AddedToWidget() override;
|
||||
const char* GetClassName() const override;
|
||||
void RemovedFromWidget() override;
|
||||
|
||||
// views::MenuButtonListener:
|
||||
void OnMenuButtonClicked(views::MenuButton* source,
|
||||
@@ -55,21 +60,29 @@ class MenuBar : public views::View,
|
||||
const ui::Event* event) override;
|
||||
void OnNativeThemeChanged(const ui::NativeTheme* theme) override;
|
||||
|
||||
// views::FocusChangeListener:
|
||||
void OnDidChangeFocus(View* focused_before, View* focused_now) override;
|
||||
void OnWillChangeFocus(View* focused_before, View* focused_now) override {}
|
||||
|
||||
private:
|
||||
void UpdateMenuBarColor();
|
||||
void RebuildChildren();
|
||||
void UpdateViewColors();
|
||||
|
||||
void RefreshColorCache(const ui::NativeTheme* theme = nullptr);
|
||||
SkColor background_color_;
|
||||
|
||||
#if defined(USE_X11)
|
||||
SkColor enabled_color_;
|
||||
SkColor disabled_color_;
|
||||
SkColor highlight_color_;
|
||||
SkColor hover_color_;
|
||||
#endif
|
||||
|
||||
NativeWindow* window_;
|
||||
AtomMenuModel* menu_model_;
|
||||
|
||||
View* FindAccelChild(base::char16 key);
|
||||
|
||||
std::shared_ptr<views::FocusManager> focus_manager_;
|
||||
bool has_focus_ = true;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(MenuBar);
|
||||
};
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ void SubmenuButton::PaintButtonContents(gfx::Canvas* canvas) {
|
||||
|
||||
bool SubmenuButton::GetUnderlinePosition(const base::string16& text,
|
||||
base::char16* accelerator,
|
||||
int* start, int* end) {
|
||||
int* start, int* end) const {
|
||||
int pos, span;
|
||||
base::string16 trimmed = gfx::RemoveAcceleratorChar(text, '&', &pos, &span);
|
||||
if (pos > -1 && span != 0) {
|
||||
@@ -105,7 +105,7 @@ bool SubmenuButton::GetUnderlinePosition(const base::string16& text,
|
||||
}
|
||||
|
||||
void SubmenuButton::GetCharacterPosition(
|
||||
const base::string16& text, int index, int* pos) {
|
||||
const base::string16& text, int index, int* pos) const {
|
||||
int height = 0;
|
||||
gfx::Canvas::SizeStringInt(text.substr(0, index), gfx::FontList(), pos,
|
||||
&height, 0, 0);
|
||||
|
||||
@@ -21,9 +21,6 @@ class SubmenuButton : public views::MenuButton {
|
||||
void SetAcceleratorVisibility(bool visible);
|
||||
void SetUnderlineColor(SkColor color);
|
||||
|
||||
void SetEnabledColor(SkColor color);
|
||||
void SetBackgroundColor(SkColor color);
|
||||
|
||||
base::char16 accelerator() const { return accelerator_; }
|
||||
|
||||
// views::MenuButton:
|
||||
@@ -36,9 +33,9 @@ class SubmenuButton : public views::MenuButton {
|
||||
private:
|
||||
bool GetUnderlinePosition(const base::string16& text,
|
||||
base::char16* accelerator,
|
||||
int* start, int* end);
|
||||
int* start, int* end) const;
|
||||
void GetCharacterPosition(
|
||||
const base::string16& text, int index, int* pos);
|
||||
const base::string16& text, int index, int* pos) const;
|
||||
|
||||
base::char16 accelerator_;
|
||||
|
||||
|
||||
@@ -25,4 +25,11 @@ bool AtomDesktopWindowTreeHostWin::PreHandleMSG(
|
||||
return delegate_->PreHandleMSG(message, w_param, l_param, result);
|
||||
}
|
||||
|
||||
bool AtomDesktopWindowTreeHostWin::HasNativeFrame() const {
|
||||
// Since we never use chromium's titlebar implementation, we can just say
|
||||
// that we use a native titlebar. This will disable the repaint locking when
|
||||
// DWM composition is disabled.
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -27,6 +27,7 @@ class AtomDesktopWindowTreeHostWin : public views::DesktopWindowTreeHostWin {
|
||||
protected:
|
||||
bool PreHandleMSG(
|
||||
UINT message, WPARAM w_param, LPARAM l_param, LRESULT* result) override;
|
||||
bool HasNativeFrame() const override;
|
||||
|
||||
private:
|
||||
MessageHandlerDelegate* delegate_; // weak ref
|
||||
|
||||
@@ -63,8 +63,15 @@ WebContentsPreferences::WebContentsPreferences(
|
||||
SetDefaultBoolIfUndefined("images", true);
|
||||
SetDefaultBoolIfUndefined("textAreasAreResizable", true);
|
||||
SetDefaultBoolIfUndefined("webgl", true);
|
||||
SetDefaultBoolIfUndefined("webSecurity", true);
|
||||
SetDefaultBoolIfUndefined("allowRunningInsecureContent", false);
|
||||
bool webSecurity = true;
|
||||
SetDefaultBoolIfUndefined("webSecurity", webSecurity);
|
||||
// If webSecurity was explicity set to false, let's inherit that into
|
||||
// insecureContent
|
||||
if (web_preferences.Get("webSecurity", &webSecurity) && !webSecurity) {
|
||||
SetDefaultBoolIfUndefined("allowRunningInsecureContent", true);
|
||||
} else {
|
||||
SetDefaultBoolIfUndefined("allowRunningInsecureContent", false);
|
||||
}
|
||||
#if defined(OS_MACOSX)
|
||||
SetDefaultBoolIfUndefined(options::kScrollBounce, false);
|
||||
#endif
|
||||
|
||||
@@ -168,10 +168,10 @@ file_dialog::Filters GetFileTypesFromAcceptType(
|
||||
|
||||
filters.push_back(file_dialog::Filter());
|
||||
|
||||
if (valid_type_count > 1 ||
|
||||
(valid_type_count == 1 && description.empty() && extensions.size() > 1))
|
||||
if (valid_type_count > 1 || (valid_type_count == 1 && description.empty()))
|
||||
description = "Custom Files";
|
||||
|
||||
DCHECK(!description.empty());
|
||||
filters[0].first = description;
|
||||
|
||||
for (const auto& extension : extensions) {
|
||||
@@ -227,6 +227,7 @@ void WebDialogHelper::RunFileChooser(
|
||||
flags |= file_dialog::FILE_DIALOG_MULTI_SELECTIONS;
|
||||
case content::FileChooserParams::Open:
|
||||
flags |= file_dialog::FILE_DIALOG_OPEN_FILE;
|
||||
flags |= file_dialog::FILE_DIALOG_TREAT_PACKAGE_APP_AS_DIRECTORY;
|
||||
break;
|
||||
case content::FileChooserParams::UploadFolder:
|
||||
flags |= file_dialog::FILE_DIALOG_OPEN_DIRECTORY;
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace std {
|
||||
template <typename Type1, typename Type2>
|
||||
struct hash<std::pair<Type1, Type2>> {
|
||||
std::size_t operator()(std::pair<Type1, Type2> value) const {
|
||||
return base::HashInts<Type1, Type2>(value.first, value.second);
|
||||
return base::HashInts(base::Hash(value.first), value.second);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -114,8 +114,9 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
dict.SetMethod("setRemoteCallbackFreer", &atom::RemoteCallbackFreer::BindTo);
|
||||
dict.SetMethod("setRemoteObjectFreer", &atom::RemoteObjectFreer::BindTo);
|
||||
dict.SetMethod("createIDWeakMap", &atom::api::KeyWeakMap<int32_t>::Create);
|
||||
dict.SetMethod("createDoubleIDWeakMap",
|
||||
&atom::api::KeyWeakMap<std::pair<int64_t, int32_t>>::Create);
|
||||
dict.SetMethod(
|
||||
"createDoubleIDWeakMap",
|
||||
&atom::api::KeyWeakMap<std::pair<std::string, int32_t>>::Create);
|
||||
dict.SetMethod("requestGarbageCollectionForTesting",
|
||||
&RequestGarbageCollectionForTesting);
|
||||
dict.SetMethod("isSameOrigin", &IsSameOrigin);
|
||||
|
||||
@@ -15,17 +15,20 @@ namespace atom {
|
||||
// static
|
||||
void RemoteCallbackFreer::BindTo(v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> target,
|
||||
const std::string& context_id,
|
||||
int object_id,
|
||||
content::WebContents* web_contents) {
|
||||
new RemoteCallbackFreer(isolate, target, object_id, web_contents);
|
||||
new RemoteCallbackFreer(isolate, target, context_id, object_id, web_contents);
|
||||
}
|
||||
|
||||
RemoteCallbackFreer::RemoteCallbackFreer(v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> target,
|
||||
const std::string& context_id,
|
||||
int object_id,
|
||||
content::WebContents* web_contents)
|
||||
: ObjectLifeMonitor(isolate, target),
|
||||
content::WebContentsObserver(web_contents),
|
||||
context_id_(context_id),
|
||||
object_id_(object_id) {
|
||||
}
|
||||
|
||||
@@ -36,6 +39,7 @@ void RemoteCallbackFreer::RunDestructor() {
|
||||
base::string16 channel =
|
||||
base::ASCIIToUTF16("ELECTRON_RENDERER_RELEASE_CALLBACK");
|
||||
base::ListValue args;
|
||||
args.AppendString(context_id_);
|
||||
args.AppendInteger(object_id_);
|
||||
auto frame_host = web_contents()->GetMainFrame();
|
||||
if (frame_host) {
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
|
||||
#ifndef ATOM_COMMON_API_REMOTE_CALLBACK_FREER_H_
|
||||
#define ATOM_COMMON_API_REMOTE_CALLBACK_FREER_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "atom/common/api/object_life_monitor.h"
|
||||
#include "content/public/browser/web_contents_observer.h"
|
||||
|
||||
@@ -14,12 +17,14 @@ class RemoteCallbackFreer : public ObjectLifeMonitor,
|
||||
public:
|
||||
static void BindTo(v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> target,
|
||||
const std::string& context_id,
|
||||
int object_id,
|
||||
content::WebContents* web_conents);
|
||||
|
||||
protected:
|
||||
RemoteCallbackFreer(v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> target,
|
||||
const std::string& context_id,
|
||||
int object_id,
|
||||
content::WebContents* web_conents);
|
||||
~RemoteCallbackFreer() override;
|
||||
@@ -30,6 +35,7 @@ class RemoteCallbackFreer : public ObjectLifeMonitor,
|
||||
void RenderViewDeleted(content::RenderViewHost*) override;
|
||||
|
||||
private:
|
||||
std::string context_id_;
|
||||
int object_id_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(RemoteCallbackFreer);
|
||||
|
||||
@@ -27,14 +27,19 @@ content::RenderFrame* GetCurrentRenderFrame() {
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
void RemoteObjectFreer::BindTo(
|
||||
v8::Isolate* isolate, v8::Local<v8::Object> target, int object_id) {
|
||||
new RemoteObjectFreer(isolate, target, object_id);
|
||||
void RemoteObjectFreer::BindTo(v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> target,
|
||||
const std::string& context_id,
|
||||
int object_id) {
|
||||
new RemoteObjectFreer(isolate, target, context_id, object_id);
|
||||
}
|
||||
|
||||
RemoteObjectFreer::RemoteObjectFreer(
|
||||
v8::Isolate* isolate, v8::Local<v8::Object> target, int object_id)
|
||||
RemoteObjectFreer::RemoteObjectFreer(v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> target,
|
||||
const std::string& context_id,
|
||||
int object_id)
|
||||
: ObjectLifeMonitor(isolate, target),
|
||||
context_id_(context_id),
|
||||
object_id_(object_id),
|
||||
routing_id_(MSG_ROUTING_NONE) {
|
||||
content::RenderFrame* render_frame = GetCurrentRenderFrame();
|
||||
@@ -55,6 +60,7 @@ void RemoteObjectFreer::RunDestructor() {
|
||||
base::string16 channel = base::ASCIIToUTF16("ipc-message");
|
||||
base::ListValue args;
|
||||
args.AppendString("ELECTRON_BROWSER_DEREFERENCE");
|
||||
args.AppendString(context_id_);
|
||||
args.AppendInteger(object_id_);
|
||||
render_frame->Send(new AtomFrameHostMsg_Message(render_frame->GetRoutingID(),
|
||||
channel, args));
|
||||
|
||||
@@ -5,23 +5,30 @@
|
||||
#ifndef ATOM_COMMON_API_REMOTE_OBJECT_FREER_H_
|
||||
#define ATOM_COMMON_API_REMOTE_OBJECT_FREER_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "atom/common/api/object_life_monitor.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
class RemoteObjectFreer : public ObjectLifeMonitor {
|
||||
public:
|
||||
static void BindTo(
|
||||
v8::Isolate* isolate, v8::Local<v8::Object> target, int object_id);
|
||||
static void BindTo(v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> target,
|
||||
const std::string& context_id,
|
||||
int object_id);
|
||||
|
||||
protected:
|
||||
RemoteObjectFreer(
|
||||
v8::Isolate* isolate, v8::Local<v8::Object> target, int object_id);
|
||||
RemoteObjectFreer(v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> target,
|
||||
const std::string& context_id,
|
||||
int object_id);
|
||||
~RemoteObjectFreer() override;
|
||||
|
||||
void RunDestructor() override;
|
||||
|
||||
private:
|
||||
std::string context_id_;
|
||||
int object_id_;
|
||||
int routing_id_;
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
|
||||
#define ATOM_MAJOR_VERSION 2
|
||||
#define ATOM_MINOR_VERSION 0
|
||||
#define ATOM_PATCH_VERSION 0
|
||||
#define ATOM_PRE_RELEASE_VERSION -beta.4
|
||||
#define ATOM_PATCH_VERSION 11
|
||||
// #define ATOM_PRE_RELEASE_VERSION
|
||||
|
||||
#ifndef ATOM_STRINGIFY
|
||||
#define ATOM_STRINGIFY(n) ATOM_STRINGIFY_HELPER(n)
|
||||
|
||||
@@ -168,6 +168,7 @@ void NodeBindings::Initialize() {
|
||||
|
||||
// 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
|
||||
node::Init(nullptr, nullptr, nullptr, nullptr);
|
||||
|
||||
#if defined(OS_WIN)
|
||||
|
||||
@@ -178,6 +178,9 @@ const char kAppUserModelId[] = "app-user-model-id";
|
||||
// The application path
|
||||
const char kAppPath[] = "app-path";
|
||||
|
||||
// The context ID for this process
|
||||
const char kContextId[] = "context-id";
|
||||
|
||||
// The command line switch versions of the options.
|
||||
const char kBackgroundColor[] = "background-color";
|
||||
const char kPreloadScript[] = "preload";
|
||||
|
||||
@@ -88,6 +88,7 @@ extern const char kRegisterServiceWorkerSchemes[];
|
||||
extern const char kSecureSchemes[];
|
||||
extern const char kAppUserModelId[];
|
||||
extern const char kAppPath[];
|
||||
extern const char kContextId[];
|
||||
|
||||
extern const char kBackgroundColor[];
|
||||
extern const char kPreloadScript[];
|
||||
|
||||
@@ -152,6 +152,7 @@ double WebFrame::GetZoomFactor() const {
|
||||
|
||||
void WebFrame::SetVisualZoomLevelLimits(double min_level, double max_level) {
|
||||
web_frame_->View()->SetDefaultPageScaleLimits(min_level, max_level);
|
||||
web_frame_->View()->SetIgnoreViewportTagScaleLimits(true);
|
||||
}
|
||||
|
||||
void WebFrame::SetLayoutZoomLevelLimits(double min_level, double max_level) {
|
||||
|
||||
@@ -82,6 +82,8 @@ void AtomRendererClient::RunScriptsAtDocumentEnd(
|
||||
|
||||
void AtomRendererClient::DidCreateScriptContext(
|
||||
v8::Handle<v8::Context> context, content::RenderFrame* render_frame) {
|
||||
RendererClientBase::DidCreateScriptContext(context, render_frame);
|
||||
|
||||
// Only allow node integration for the main frame, unless it is a devtools
|
||||
// extension page.
|
||||
if (!render_frame->IsMainFrame() && !IsDevToolsExtension(render_frame))
|
||||
|
||||
@@ -15,9 +15,11 @@
|
||||
#include "atom/renderer/api/atom_api_renderer_ipc.h"
|
||||
#include "atom/renderer/atom_render_frame_observer.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "chrome/renderer/printing/print_web_view_helper.h"
|
||||
#include "content/public/renderer/render_frame.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "third_party/WebKit/public/web/WebDocument.h"
|
||||
#include "third_party/WebKit/public/web/WebKit.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
@@ -30,6 +32,11 @@ namespace {
|
||||
const std::string kIpcKey = "ipcNative";
|
||||
const std::string kModuleCacheKey = "native-module-cache";
|
||||
|
||||
bool IsDevTools(content::RenderFrame* render_frame) {
|
||||
return render_frame->GetWebFrame()->GetDocument().Url()
|
||||
.ProtocolIs("chrome-devtools");
|
||||
}
|
||||
|
||||
v8::Local<v8::Object> GetModuleCache(v8::Isolate* isolate) {
|
||||
mate::Dictionary global(isolate, isolate->GetCurrentContext()->Global());
|
||||
v8::Local<v8::Value> cache;
|
||||
@@ -146,16 +153,16 @@ void AtomSandboxedRendererClient::RenderViewCreated(
|
||||
|
||||
void AtomSandboxedRendererClient::DidCreateScriptContext(
|
||||
v8::Handle<v8::Context> context, content::RenderFrame* render_frame) {
|
||||
RendererClientBase::DidCreateScriptContext(context, render_frame);
|
||||
|
||||
// Only allow preload for the main frame
|
||||
if (!render_frame->IsMainFrame())
|
||||
// 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))
|
||||
return;
|
||||
|
||||
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
|
||||
std::string preload_script = command_line->GetSwitchValueASCII(
|
||||
base::FilePath preload_script_path = command_line->GetSwitchValuePath(
|
||||
switches::kPreloadScript);
|
||||
if (preload_script.empty())
|
||||
return;
|
||||
|
||||
auto isolate = context->GetIsolate();
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
@@ -180,7 +187,7 @@ void AtomSandboxedRendererClient::DidCreateScriptContext(
|
||||
AddRenderBindings(isolate, binding);
|
||||
v8::Local<v8::Value> args[] = {
|
||||
binding,
|
||||
mate::ConvertToV8(isolate, preload_script)
|
||||
mate::ConvertToV8(isolate, preload_script_path.value())
|
||||
};
|
||||
// Execute the function with proper arguments
|
||||
ignore_result(func->Call(context, v8::Null(isolate), 2, args));
|
||||
|
||||
@@ -19,7 +19,9 @@
|
||||
#include "atom/renderer/preferences_manager.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/memory/ptr_util.h"
|
||||
#include "base/process/process_handle.h"
|
||||
#include "base/strings/string_split.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "chrome/renderer/media/chrome_key_systems.h"
|
||||
#include "chrome/renderer/pepper/pepper_helper.h"
|
||||
#include "chrome/renderer/printing/print_web_view_helper.h"
|
||||
@@ -44,6 +46,14 @@
|
||||
#include <shlobj.h>
|
||||
#endif
|
||||
|
||||
// This is defined in later versions of Chromium, remove this if you see
|
||||
// compiler complaining duplicate defines.
|
||||
#if defined(OS_WIN) || defined(OS_FUCHSIA)
|
||||
#define CrPRIdPid "ld"
|
||||
#else
|
||||
#define CrPRIdPid "d"
|
||||
#endif
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
@@ -78,6 +88,19 @@ RendererClientBase::RendererClientBase() {
|
||||
RendererClientBase::~RendererClientBase() {
|
||||
}
|
||||
|
||||
void RendererClientBase::DidCreateScriptContext(
|
||||
v8::Handle<v8::Context> context,
|
||||
content::RenderFrame* render_frame) {
|
||||
// global.setHidden("contextId", `${processId}-${++nextContextId}`)
|
||||
std::string context_id = base::StringPrintf(
|
||||
"%" CrPRIdPid "-%d", base::GetCurrentProcId(), ++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);
|
||||
}
|
||||
|
||||
void RendererClientBase::AddRenderBindings(
|
||||
v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> binding_object) {
|
||||
|
||||
@@ -21,7 +21,7 @@ class RendererClientBase : public content::ContentRendererClient {
|
||||
virtual ~RendererClientBase();
|
||||
|
||||
virtual void DidCreateScriptContext(
|
||||
v8::Handle<v8::Context> context, content::RenderFrame* render_frame) = 0;
|
||||
v8::Handle<v8::Context> context, content::RenderFrame* render_frame);
|
||||
virtual void WillReleaseScriptContext(
|
||||
v8::Handle<v8::Context> context, content::RenderFrame* render_frame) = 0;
|
||||
virtual void DidClearWindowObject(content::RenderFrame* render_frame);
|
||||
@@ -57,6 +57,9 @@ class RendererClientBase : public content::ContentRendererClient {
|
||||
private:
|
||||
std::unique_ptr<PreferencesManager> preferences_manager_;
|
||||
bool isolated_world_;
|
||||
|
||||
// An increasing ID used for indentifying an V8 context in this process.
|
||||
int next_context_id_ = 0;
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -4,6 +4,13 @@
|
||||
|
||||
#include "atom/utility/atom_content_utility_client.h"
|
||||
|
||||
#include "content/public/common/service_manager_connection.h"
|
||||
#include "content/public/common/simple_connection_filter.h"
|
||||
#include "content/public/utility/utility_thread.h"
|
||||
#include "mojo/public/cpp/bindings/strong_binding.h"
|
||||
#include "net/proxy/mojo_proxy_resolver_factory_impl.h"
|
||||
#include "services/service_manager/public/cpp/binder_registry.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include "base/memory/ptr_util.h"
|
||||
#include "chrome/utility/printing_handler_win.h"
|
||||
@@ -11,6 +18,16 @@
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
void CreateProxyResolverFactory(
|
||||
net::interfaces::ProxyResolverFactoryRequest request) {
|
||||
mojo::MakeStrongBinding(base::MakeUnique<net::MojoProxyResolverFactoryImpl>(),
|
||||
std::move(request));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
AtomContentUtilityClient::AtomContentUtilityClient() {
|
||||
#if defined(OS_WIN)
|
||||
handlers_.push_back(base::MakeUnique<printing::PrintingHandlerWin>());
|
||||
@@ -20,6 +37,23 @@ AtomContentUtilityClient::AtomContentUtilityClient() {
|
||||
AtomContentUtilityClient::~AtomContentUtilityClient() {
|
||||
}
|
||||
|
||||
void AtomContentUtilityClient::UtilityThreadStarted() {
|
||||
content::ServiceManagerConnection* connection =
|
||||
content::ChildThread::Get()->GetServiceManagerConnection();
|
||||
|
||||
// NOTE: Some utility process instances are not connected to the Service
|
||||
// Manager. Nothing left to do in that case.
|
||||
if (!connection)
|
||||
return;
|
||||
|
||||
auto registry = base::MakeUnique<service_manager::BinderRegistry>();
|
||||
registry->AddInterface<net::interfaces::ProxyResolverFactory>(
|
||||
base::Bind(CreateProxyResolverFactory),
|
||||
base::ThreadTaskRunnerHandle::Get());
|
||||
connection->AddConnectionFilter(
|
||||
base::MakeUnique<content::SimpleConnectionFilter>(std::move(registry)));
|
||||
}
|
||||
|
||||
bool AtomContentUtilityClient::OnMessageReceived(
|
||||
const IPC::Message& message) {
|
||||
#if defined(OS_WIN)
|
||||
|
||||
@@ -20,6 +20,7 @@ class AtomContentUtilityClient : public content::ContentUtilityClient {
|
||||
AtomContentUtilityClient();
|
||||
~AtomContentUtilityClient() override;
|
||||
|
||||
void UtilityThreadStarted() override;
|
||||
bool OnMessageReceived(const IPC::Message& message) override;
|
||||
|
||||
private:
|
||||
|
||||
@@ -116,6 +116,8 @@
|
||||
'<(libchromiumcontent_dir)/libcommon.a',
|
||||
# services/device/wake_lock/power_save_blocker/
|
||||
'<(libchromiumcontent_dir)/libpower_save_blocker.a',
|
||||
# net/proxy/mojo_*
|
||||
'<(libchromiumcontent_dir)/libnet_proxy_service.a',
|
||||
# Friends of libpdf.a:
|
||||
# On Linux we have to use "--whole-archive" to include
|
||||
# all symbols, otherwise there will be plenty of
|
||||
@@ -200,6 +202,8 @@
|
||||
'<(libchromiumcontent_dir)/libcommon.a',
|
||||
# services/device/wake_lock/power_save_blocker/
|
||||
'<(libchromiumcontent_dir)/libpower_save_blocker.a',
|
||||
# net/proxy/mojo_*
|
||||
'<(libchromiumcontent_dir)/libnet_proxy_service.a',
|
||||
# Friends of libpdf.a:
|
||||
'<(libchromiumcontent_dir)/libpdf.a',
|
||||
'<(libchromiumcontent_dir)/libppapi_cpp_objects.a',
|
||||
@@ -268,6 +272,20 @@
|
||||
],
|
||||
},
|
||||
}],
|
||||
# In the OSX 10.10 SDK, CoreBluetooth became a top level framework.
|
||||
# Previously, it was nested in IOBluetooth. In order for Chrome to run on
|
||||
# OSes older than OSX 10.10, the top level CoreBluetooth framework must be
|
||||
# weakly linked.
|
||||
['mac_sdk=="10.10" and libchromiumcontent_component==0', {
|
||||
'direct_dependent_settings': {
|
||||
'xcode_settings': {
|
||||
'OTHER_LDFLAGS': [
|
||||
'-weak_framework',
|
||||
'CoreBluetooth',
|
||||
],
|
||||
},
|
||||
},
|
||||
}],
|
||||
]
|
||||
}], # OS=="mac"
|
||||
['OS=="win"', {
|
||||
@@ -296,6 +314,8 @@
|
||||
'<(libchromiumcontent_dir)/common.lib',
|
||||
# services/device/wake_lock/power_save_blocker/
|
||||
'<(libchromiumcontent_dir)/power_save_blocker.lib',
|
||||
# net/proxy/mojo_*
|
||||
'<(libchromiumcontent_dir)/net_proxy_service.lib',
|
||||
# Friends of pdf.lib:
|
||||
'<(libchromiumcontent_dir)/pdf.lib',
|
||||
'<(libchromiumcontent_dir)/ppapi_cpp_objects.lib',
|
||||
|
||||
@@ -100,14 +100,12 @@ BrowserContext::~BrowserContext() {
|
||||
}
|
||||
|
||||
void BrowserContext::InitPrefs() {
|
||||
base::ThreadRestrictions::ScopedAllowIO allow_io;
|
||||
auto prefs_path = GetPath().Append(FILE_PATH_LITERAL("Preferences"));
|
||||
PrefServiceFactory prefs_factory;
|
||||
scoped_refptr<JsonPrefStore> pref_store =
|
||||
base::MakeRefCounted<JsonPrefStore>(prefs_path);
|
||||
{
|
||||
base::ThreadRestrictions::ScopedAllowIO allow_io;
|
||||
pref_store->ReadPrefs(); // Synchronous.
|
||||
}
|
||||
pref_store->ReadPrefs(); // Synchronous.
|
||||
prefs_factory.set_user_prefs(pref_store);
|
||||
|
||||
auto registry = make_scoped_refptr(new PrefRegistrySimple);
|
||||
|
||||
@@ -184,10 +184,20 @@ void OverrideAppLogsPath() {
|
||||
}
|
||||
#endif
|
||||
|
||||
void BrowserMainParts::PreEarlyInitialization() {
|
||||
void BrowserMainParts::InitializeFeatureList() {
|
||||
auto* cmd_line = base::CommandLine::ForCurrentProcess();
|
||||
const auto enable_features =
|
||||
cmd_line->GetSwitchValueASCII(switches::kEnableFeatures);
|
||||
const auto disable_features =
|
||||
cmd_line->GetSwitchValueASCII(switches::kDisableFeatures);
|
||||
|
||||
std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
|
||||
feature_list->InitializeFromCommandLine("", "");
|
||||
feature_list->InitializeFromCommandLine(enable_features, disable_features);
|
||||
base::FeatureList::SetInstance(std::move(feature_list));
|
||||
}
|
||||
|
||||
void BrowserMainParts::PreEarlyInitialization() {
|
||||
InitializeFeatureList();
|
||||
OverrideAppLogsPath();
|
||||
#if defined(USE_X11)
|
||||
views::LinuxUI::SetInstance(BuildGtkUi());
|
||||
|
||||
@@ -46,6 +46,8 @@ class BrowserMainParts : public content::BrowserMainParts {
|
||||
int PreCreateThreads() override;
|
||||
void PostDestroyThreads() override;
|
||||
|
||||
void InitializeFeatureList();
|
||||
|
||||
private:
|
||||
#if defined(OS_MACOSX)
|
||||
void InitializeMainNib();
|
||||
|
||||
@@ -698,6 +698,8 @@ void InspectableWebContentsImpl::WebContentsDestroyed() {
|
||||
for (const auto& pair : pending_requests_)
|
||||
delete pair.first;
|
||||
|
||||
pending_requests_.clear();
|
||||
|
||||
if (view_ && view_->GetDelegate())
|
||||
view_->GetDelegate()->DevToolsClosed();
|
||||
}
|
||||
|
||||
117
brightray/browser/net/chrome_mojo_proxy_resolver_factory.cc
Normal file
117
brightray/browser/net/chrome_mojo_proxy_resolver_factory.cc
Normal file
@@ -0,0 +1,117 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "brightray/browser/net/chrome_mojo_proxy_resolver_factory.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/memory/ptr_util.h"
|
||||
#include "base/memory/singleton.h"
|
||||
#include "base/single_thread_task_runner.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "base/threading/thread_task_runner_handle.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/utility_process_host.h"
|
||||
#include "content/public/browser/utility_process_host_client.h"
|
||||
#include "services/service_manager/public/cpp/interface_provider.h"
|
||||
|
||||
namespace {
|
||||
const int kUtilityProcessIdleTimeoutSeconds = 5;
|
||||
}
|
||||
|
||||
// static
|
||||
ChromeMojoProxyResolverFactory* ChromeMojoProxyResolverFactory::GetInstance() {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
||||
return base::Singleton<
|
||||
ChromeMojoProxyResolverFactory,
|
||||
base::LeakySingletonTraits<ChromeMojoProxyResolverFactory>>::get();
|
||||
}
|
||||
|
||||
ChromeMojoProxyResolverFactory::ChromeMojoProxyResolverFactory() {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
||||
}
|
||||
|
||||
ChromeMojoProxyResolverFactory::~ChromeMojoProxyResolverFactory() {
|
||||
DCHECK(thread_checker_.CalledOnValidThread());
|
||||
}
|
||||
|
||||
std::unique_ptr<base::ScopedClosureRunner>
|
||||
ChromeMojoProxyResolverFactory::CreateResolver(
|
||||
const std::string& pac_script,
|
||||
mojo::InterfaceRequest<net::interfaces::ProxyResolver> req,
|
||||
net::interfaces::ProxyResolverFactoryRequestClientPtr client) {
|
||||
DCHECK(thread_checker_.CalledOnValidThread());
|
||||
if (!resolver_factory_)
|
||||
CreateFactory();
|
||||
|
||||
if (!resolver_factory_) {
|
||||
// If factory creation failed, close |req|'s message pipe, which should
|
||||
// cause a connection error.
|
||||
req = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
idle_timer_.Stop();
|
||||
num_proxy_resolvers_++;
|
||||
resolver_factory_->CreateResolver(pac_script, std::move(req),
|
||||
std::move(client));
|
||||
return base::MakeUnique<base::ScopedClosureRunner>(
|
||||
base::Bind(&ChromeMojoProxyResolverFactory::OnResolverDestroyed,
|
||||
base::Unretained(this)));
|
||||
}
|
||||
|
||||
void ChromeMojoProxyResolverFactory::CreateFactory() {
|
||||
DCHECK(thread_checker_.CalledOnValidThread());
|
||||
DCHECK(!resolver_factory_);
|
||||
DCHECK(!weak_utility_process_host_);
|
||||
|
||||
DVLOG(1) << "Attempting to create utility process for proxy resolver";
|
||||
content::UtilityProcessHost* utility_process_host =
|
||||
content::UtilityProcessHost::Create(
|
||||
scoped_refptr<content::UtilityProcessHostClient>(),
|
||||
base::ThreadTaskRunnerHandle::Get());
|
||||
utility_process_host->SetName(base::ASCIIToUTF16("Electron Proxy Resolver"));
|
||||
bool process_started = utility_process_host->Start();
|
||||
if (process_started) {
|
||||
BindInterface(utility_process_host, &resolver_factory_);
|
||||
weak_utility_process_host_ = utility_process_host->AsWeakPtr();
|
||||
} else {
|
||||
LOG(ERROR) << "Unable to connect to utility process";
|
||||
return;
|
||||
}
|
||||
|
||||
resolver_factory_.set_connection_error_handler(base::Bind(
|
||||
&ChromeMojoProxyResolverFactory::DestroyFactory, base::Unretained(this)));
|
||||
}
|
||||
|
||||
void ChromeMojoProxyResolverFactory::DestroyFactory() {
|
||||
resolver_factory_.reset();
|
||||
delete weak_utility_process_host_.get();
|
||||
weak_utility_process_host_.reset();
|
||||
}
|
||||
|
||||
void ChromeMojoProxyResolverFactory::OnResolverDestroyed() {
|
||||
DCHECK(thread_checker_.CalledOnValidThread());
|
||||
DCHECK_GT(num_proxy_resolvers_, 0u);
|
||||
if (--num_proxy_resolvers_ == 0) {
|
||||
// When all proxy resolvers have been destroyed, the proxy resolver factory
|
||||
// is no longer needed. However, new proxy resolvers may be created
|
||||
// shortly after being destroyed (e.g. due to a network change).
|
||||
//
|
||||
// On desktop, where a utility process is used, if the utility process is
|
||||
// shut down immediately, this would cause unnecessary process churn, so
|
||||
// wait for an idle timeout before shutting down the proxy resolver utility
|
||||
// process.
|
||||
idle_timer_.Start(
|
||||
FROM_HERE,
|
||||
base::TimeDelta::FromSeconds(kUtilityProcessIdleTimeoutSeconds), this,
|
||||
&ChromeMojoProxyResolverFactory::OnIdleTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
void ChromeMojoProxyResolverFactory::OnIdleTimeout() {
|
||||
DCHECK(thread_checker_.CalledOnValidThread());
|
||||
DCHECK_EQ(num_proxy_resolvers_, 0u);
|
||||
DestroyFactory();
|
||||
}
|
||||
73
brightray/browser/net/chrome_mojo_proxy_resolver_factory.h
Normal file
73
brightray/browser/net/chrome_mojo_proxy_resolver_factory.h
Normal file
@@ -0,0 +1,73 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef BRIGHTRAY_BROWSER_NET_CHROME_MOJO_PROXY_RESOLVER_FACTORY_H_
|
||||
#define BRIGHTRAY_BROWSER_NET_CHROME_MOJO_PROXY_RESOLVER_FACTORY_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string>
|
||||
|
||||
#include "base/macros.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/threading/thread_checker.h"
|
||||
#include "base/timer/timer.h"
|
||||
#include "net/proxy/mojo_proxy_resolver_factory.h"
|
||||
|
||||
namespace content {
|
||||
class UtilityProcessHost;
|
||||
}
|
||||
|
||||
namespace base {
|
||||
template <typename Type>
|
||||
struct DefaultSingletonTraits;
|
||||
} // namespace base
|
||||
|
||||
// A factory used to create connections to Mojo proxy resolver services. On
|
||||
// Android, the proxy resolvers will run in the browser process, and on other
|
||||
// platforms, they'll all be run in the same utility process. Utility process
|
||||
// crashes are detected and the utility process is automatically restarted.
|
||||
class ChromeMojoProxyResolverFactory : public net::MojoProxyResolverFactory {
|
||||
public:
|
||||
static ChromeMojoProxyResolverFactory* GetInstance();
|
||||
|
||||
// Overridden from net::MojoProxyResolverFactory:
|
||||
std::unique_ptr<base::ScopedClosureRunner> CreateResolver(
|
||||
const std::string& pac_script,
|
||||
mojo::InterfaceRequest<net::interfaces::ProxyResolver> req,
|
||||
net::interfaces::ProxyResolverFactoryRequestClientPtr client) override;
|
||||
|
||||
private:
|
||||
friend struct base::DefaultSingletonTraits<ChromeMojoProxyResolverFactory>;
|
||||
ChromeMojoProxyResolverFactory();
|
||||
~ChromeMojoProxyResolverFactory() override;
|
||||
|
||||
// Creates the proxy resolver factory. On desktop, creates a new utility
|
||||
// process before creating it out of process. On Android, creates it on the
|
||||
// current thread.
|
||||
void CreateFactory();
|
||||
|
||||
// Destroys |resolver_factory_|.
|
||||
void DestroyFactory();
|
||||
|
||||
// Invoked each time a proxy resolver is destroyed.
|
||||
void OnResolverDestroyed();
|
||||
|
||||
// Invoked once an idle timeout has elapsed after all proxy resolvers are
|
||||
// destroyed.
|
||||
void OnIdleTimeout();
|
||||
|
||||
net::interfaces::ProxyResolverFactoryPtr resolver_factory_;
|
||||
|
||||
base::WeakPtr<content::UtilityProcessHost> weak_utility_process_host_;
|
||||
|
||||
size_t num_proxy_resolvers_ = 0;
|
||||
|
||||
base::OneShotTimer idle_timer_;
|
||||
|
||||
base::ThreadChecker thread_checker_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ChromeMojoProxyResolverFactory);
|
||||
};
|
||||
|
||||
#endif // BRIGHTRAY_BROWSER_NET_CHROME_MOJO_PROXY_RESOLVER_FACTORY_H_
|
||||
@@ -52,8 +52,7 @@ void NetLog::StartLogging() {
|
||||
base::FilePath log_path =
|
||||
command_line->GetSwitchValuePath(switches::kLogNetLog);
|
||||
std::unique_ptr<base::Value> constants(GetConstants());
|
||||
net::NetLogCaptureMode capture_mode =
|
||||
net::NetLogCaptureMode::IncludeCookiesAndCredentials();
|
||||
net::NetLogCaptureMode capture_mode = net::NetLogCaptureMode::Default();
|
||||
|
||||
file_net_log_observer_ =
|
||||
net::FileNetLogObserver::CreateUnbounded(log_path, std::move(constants));
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "base/threading/sequenced_worker_pool.h"
|
||||
#include "base/threading/worker_pool.h"
|
||||
#include "brightray/browser/browser_client.h"
|
||||
#include "brightray/browser/net/chrome_mojo_proxy_resolver_factory.h"
|
||||
#include "brightray/browser/net/devtools_network_controller_handle.h"
|
||||
#include "brightray/browser/net/devtools_network_transaction_factory.h"
|
||||
#include "brightray/browser/net/require_ct_delegate.h"
|
||||
@@ -41,7 +42,7 @@
|
||||
#include "net/proxy/proxy_config_service.h"
|
||||
#include "net/proxy/proxy_script_fetcher_impl.h"
|
||||
#include "net/proxy/proxy_service.h"
|
||||
#include "net/proxy/proxy_service_v8.h"
|
||||
#include "net/proxy/proxy_service_mojo.h"
|
||||
#include "net/ssl/channel_id_service.h"
|
||||
#include "net/ssl/default_channel_id_store.h"
|
||||
#include "net/ssl/ssl_config_service_defaults.h"
|
||||
@@ -229,14 +230,12 @@ net::URLRequestContext* URLRequestContextGetter::GetURLRequestContext() {
|
||||
storage_->set_proxy_service(net::ProxyService::CreateFixed(
|
||||
proxy_config));
|
||||
} else {
|
||||
storage_->set_proxy_service(
|
||||
net::CreateProxyServiceUsingV8ProxyResolver(
|
||||
std::move(proxy_config_service_),
|
||||
new net::ProxyScriptFetcherImpl(url_request_context_.get()),
|
||||
dhcp_factory.Create(url_request_context_.get()),
|
||||
host_resolver.get(),
|
||||
nullptr,
|
||||
url_request_context_->network_delegate()));
|
||||
storage_->set_proxy_service(net::CreateProxyServiceUsingMojoFactory(
|
||||
ChromeMojoProxyResolverFactory::GetInstance(),
|
||||
std::move(proxy_config_service_),
|
||||
new net::ProxyScriptFetcherImpl(url_request_context_.get()),
|
||||
dhcp_factory.Create(url_request_context_.get()), host_resolver.get(),
|
||||
nullptr, url_request_context_->network_delegate()));
|
||||
}
|
||||
|
||||
std::vector<std::string> schemes;
|
||||
|
||||
@@ -63,6 +63,8 @@
|
||||
'browser/net/devtools_network_transaction.h',
|
||||
'browser/net/devtools_network_upload_data_stream.cc',
|
||||
'browser/net/devtools_network_upload_data_stream.h',
|
||||
'browser/net/chrome_mojo_proxy_resolver_factory.cc',
|
||||
'browser/net/chrome_mojo_proxy_resolver_factory.h',
|
||||
'browser/net/require_ct_delegate.cc',
|
||||
'browser/net/require_ct_delegate.h',
|
||||
'browser/net_log.cc',
|
||||
|
||||
@@ -147,6 +147,7 @@
|
||||
'BUILDING_V8_SHARED',
|
||||
'BUILDING_V8_PLATFORM_SHARED',
|
||||
'BUILDING_V8_BASE_SHARED',
|
||||
'NODE_WITHOUT_NODE_OPTIONS',
|
||||
],
|
||||
'conditions': [
|
||||
['OS=="mac" and libchromiumcontent_component==0', {
|
||||
|
||||
@@ -17,7 +17,7 @@ an issue:
|
||||
## Guides
|
||||
|
||||
* [Glossary of Terms](glossary.md)
|
||||
* [Supported Platforms](tutorial/supported-platforms.md)
|
||||
* [Support](tutorial/support.md)
|
||||
* [Security](tutorial/security.md)
|
||||
* [Versioning](tutorial/electron-versioning.md)
|
||||
* [Application Distribution](tutorial/application-distribution.md)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
> Define keyboard shortcuts.
|
||||
|
||||
Accelerators are Strings that can contain multiple modifiers and key codes,
|
||||
Accelerators are Strings that can contain multiple modifiers and a single key code,
|
||||
combined by the `+` character, and are used to define keyboard shortcuts
|
||||
throughout your application.
|
||||
|
||||
|
||||
@@ -64,6 +64,9 @@ terminating the application.
|
||||
then `before-quit` is emitted *after* emitting `close` event on all windows and
|
||||
closing them.
|
||||
|
||||
**Note:** On Windows, this event will not be emitted if the app is closed due
|
||||
to a shutdown/restart of the system or a user logout.
|
||||
|
||||
### Event: 'will-quit'
|
||||
|
||||
Returns:
|
||||
@@ -77,6 +80,9 @@ terminating the application.
|
||||
See the description of the `window-all-closed` event for the differences between
|
||||
the `will-quit` and `window-all-closed` events.
|
||||
|
||||
**Note:** On Windows, this event will not be emitted if the app is closed due
|
||||
to a shutdown/restart of the system or a user logout.
|
||||
|
||||
### Event: 'quit'
|
||||
|
||||
Returns:
|
||||
@@ -86,6 +92,9 @@ Returns:
|
||||
|
||||
Emitted when the application is quitting.
|
||||
|
||||
**Note:** On Windows, this event will not be emitted if the app is closed due
|
||||
to a shutdown/restart of the system or a user logout.
|
||||
|
||||
### Event: 'open-file' _macOS_
|
||||
|
||||
Returns:
|
||||
@@ -356,6 +365,23 @@ assistive technologies, such as screen readers, are enabled or disabled.
|
||||
See https://www.chromium.org/developers/design-documents/accessibility for more
|
||||
details.
|
||||
|
||||
### Event: 'session-created'
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `session` [Session](session.md)
|
||||
|
||||
Emitted when Electron has created a new `session`.
|
||||
|
||||
```javascript
|
||||
const {app} = require('electron')
|
||||
|
||||
app.on('session-created', (event, session) => {
|
||||
console.log(session)
|
||||
})
|
||||
```
|
||||
|
||||
## Methods
|
||||
|
||||
The `app` object has the following methods:
|
||||
@@ -522,8 +548,9 @@ Overrides the current application's name.
|
||||
|
||||
### `app.getLocale()`
|
||||
|
||||
Returns `String` - The current application locale. Possible return values are documented
|
||||
[here](locales.md).
|
||||
Returns `String` - The current application locale. Possible return values are documented [here](locales.md).
|
||||
|
||||
To set the locale, you'll want to use a command line switch at app startup, which may be found [here](https://github.com/electron/electron/blob/master/docs/api/chrome-command-line-switches.md).
|
||||
|
||||
**Note:** When distributing your packaged app, you have to also ship the
|
||||
`locales` folder.
|
||||
|
||||
@@ -202,7 +202,7 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
than screen. Default is `false`.
|
||||
* `backgroundColor` String (optional) - Window's background color as a hexadecimal value,
|
||||
like `#66CD00` or `#FFF` or `#80FFFFFF` (alpha is supported). Default is
|
||||
`#FFF` (white).
|
||||
`#FFF` (white). If `transparent` is set to `true`, only values with transparent (`#00-------`) or opaque (`#FF-----`) alpha values are respected.
|
||||
* `hasShadow` Boolean (optional) - Whether window should have a shadow. This is only
|
||||
implemented on macOS. Default is `true`.
|
||||
* `opacity` Number (optional) - Set the initial opacity of the window, between 0.0 (fully
|
||||
@@ -287,7 +287,7 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
between the web pages even when you specified different values for them,
|
||||
including but not limited to `preload`, `sandbox` and `nodeIntegration`.
|
||||
So it is suggested to use exact same `webPreferences` for web pages with
|
||||
the same `affinity`.
|
||||
the same `affinity`. _This property is experimental_
|
||||
* `zoomFactor` Number (optional) - The default zoom factor of the page, `3.0` represents
|
||||
`300%`. Default is `1.0`.
|
||||
* `javascript` Boolean (optional) - Enables JavaScript support. Default is `true`.
|
||||
@@ -361,7 +361,7 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
script. You can use the `will-attach-webview` event on [webContents](web-contents.md)
|
||||
to strip away the `preload` script and to validate or alter the
|
||||
`<webview>`'s initial settings.
|
||||
* `additionArguments` String[] (optional) - A list of strings that will be appended
|
||||
* `additionalArguments` String[] (optional) - A list of strings that will be appended
|
||||
to `process.argv` in the renderer process of this app. Useful for passing small
|
||||
bits of data down to renderer process preload scripts.
|
||||
|
||||
@@ -1199,7 +1199,7 @@ menu bar.
|
||||
|
||||
* `progress` Double
|
||||
* `options` Object (optional)
|
||||
* `mode` String _Windows_ - Mode for the progress bar. Can be `none`, `normal`, `indeterminate`, `error`, or `paused`.
|
||||
* `mode` String _Windows_ - Mode for the progress bar. Can be `none`, `normal`, `indeterminate`, `error` or `paused`.
|
||||
|
||||
Sets progress value in progress bar. Valid range is [0, 1.0].
|
||||
|
||||
@@ -1216,7 +1216,7 @@ mode set (but with a value within the valid range), `normal` will be assumed.
|
||||
|
||||
#### `win.setOverlayIcon(overlay, description)` _Windows_
|
||||
|
||||
* `overlay` [NativeImage](native-image.md) - the icon to display on the bottom
|
||||
* `overlay` [NativeImage](native-image.md) | null - the icon to display on the bottom
|
||||
right corner of the taskbar icon. If this parameter is `null`, the overlay is
|
||||
cleared
|
||||
* `description` String - a description that will be provided to Accessibility
|
||||
|
||||
@@ -30,7 +30,7 @@ The `inAppPurchase` module has the following methods:
|
||||
|
||||
### `inAppPurchase.canMakePayments()`
|
||||
|
||||
Returns `true` if the user can make a payment and `false` otherwise.
|
||||
Returns `Boolean`, whether a user can make a payment.
|
||||
|
||||
### `inAppPurchase.getReceiptURL()`
|
||||
|
||||
|
||||
@@ -194,7 +194,7 @@ Sets the `image` associated with this tray icon.
|
||||
|
||||
#### `tray.setPressedImage(image)` _macOS_
|
||||
|
||||
* `image` [NativeImage](native-image.md)
|
||||
* `image` ([NativeImage](native-image.md) | String)
|
||||
|
||||
Sets the `image` associated with this tray icon when pressed on macOS.
|
||||
|
||||
@@ -262,7 +262,7 @@ The `position` is only available on Windows, and it is (0, 0) by default.
|
||||
|
||||
#### `tray.setContextMenu(menu)`
|
||||
|
||||
* `menu` Menu
|
||||
* `menu` Menu | null
|
||||
|
||||
Sets the context menu for this icon.
|
||||
|
||||
|
||||
@@ -1367,11 +1367,17 @@ Shows pop-up dictionary that searches the selected word on the page.
|
||||
Set the size of the page. This is only supported for `<webview>` guest contents.
|
||||
|
||||
* `options` Object
|
||||
* `normal` Object (optional) - Normal size of the page. This can be used in
|
||||
* `enableAutoSize` Boolean (optional) - true to make the webview container automatically
|
||||
resize within the bounds specified by the attributes normal, min and max.
|
||||
* `normal` [Size](structures/size.md) (optional) - Normal size of the page. This can be used in
|
||||
combination with the [`disableguestresize`](webview-tag.md#disableguestresize)
|
||||
attribute to manually resize the webview guest contents.
|
||||
* `min` [Size](structures/size.md) (optional) - Minimum size of the page. This can be used in
|
||||
combination with the [`disableguestresize`](webview-tag.md#disableguestresize)
|
||||
attribute to manually resize the webview guest contents.
|
||||
* `max` [Size](structures/size.md) (optional) - Maximium size of the page. This can be used in
|
||||
combination with the [`disableguestresize`](webview-tag.md#disableguestresize)
|
||||
attribute to manually resize the webview guest contents.
|
||||
* `width` Integer
|
||||
* `height` Integer
|
||||
|
||||
#### `contents.isOffscreen()`
|
||||
|
||||
|
||||
@@ -173,6 +173,7 @@ Set the security origin of the isolated world.
|
||||
Returns `Object`:
|
||||
|
||||
* `images` [MemoryUsageDetails](structures/memory-usage-details.md)
|
||||
* `scripts` [MemoryUsageDetails](structures/memory-usage-details.md)
|
||||
* `cssStyleSheets` [MemoryUsageDetails](structures/memory-usage-details.md)
|
||||
* `xslStyleSheets` [MemoryUsageDetails](structures/memory-usage-details.md)
|
||||
* `fonts` [MemoryUsageDetails](structures/memory-usage-details.md)
|
||||
|
||||
@@ -24,7 +24,12 @@ Returns [`BrowserWindowProxy`](browser-window-proxy.md) - Creates a new window
|
||||
and returns an instance of `BrowserWindowProxy` class.
|
||||
|
||||
The `features` string follows the format of standard browser, but each feature
|
||||
has to be a field of `BrowserWindow`'s options.
|
||||
has to be a field of `BrowserWindow`'s options. These are the features you can set via `features` string: `zoomFactor`, `nodeIntegration`, `preload`, `javascript`, `contextIsolation`, `webviewTag`.
|
||||
|
||||
For example:
|
||||
```js
|
||||
window.open('https://github.com', '_blank', 'nodeIntegration=no')
|
||||
```
|
||||
|
||||
**Notes:**
|
||||
|
||||
|
||||
@@ -26,10 +26,9 @@ contribute:
|
||||
|
||||
## Asking for General Help
|
||||
|
||||
Because the level of activity in the `electron/electron` repository is
|
||||
so high, questions or requests for general help using Electron should
|
||||
be directed at the [community slack channel](https://atomio.slack.com)
|
||||
or the [forum](https://discuss.atom.io/c/electron).
|
||||
["Finding Support"](../tutorial/support.md#finding-support) has a
|
||||
list of resources for getting programming help, reporting security issues,
|
||||
contributing, and more. Please use the issue tracker for bugs only!
|
||||
|
||||
## Submitting a Bug Report
|
||||
|
||||
|
||||
@@ -2,11 +2,31 @@
|
||||
|
||||
This document describes the process for releasing a new version of Electron.
|
||||
|
||||
## Set your tokens and environment variables
|
||||
You'll need Electron S3 credentials in order to create and
|
||||
upload an Electron release. Contact a team member for more
|
||||
information.
|
||||
|
||||
There are a handful of `*_TOKEN` environment variables needed by the release
|
||||
scripts. Once you've generated these per-user tokens, you may want to keep
|
||||
them in a local file that you can `source` when starting a release.
|
||||
* `ELECTRON_GITHUB_TOKEN`:
|
||||
Create as described at https://github.com/settings/tokens/new,
|
||||
giving the token repo access scope.
|
||||
* `APPVEYOR_TOKEN`:
|
||||
Create a token from https://windows-ci.electronjs.org/api-token
|
||||
If you don't have an account, ask a team member to add you.
|
||||
* `CIRCLE_TOKEN`:
|
||||
Create a token from "Personal API Tokens" at https://circleci.com/account/api
|
||||
* `VSTS_TOKEN`:
|
||||
Create a Personal Access Token at https://github.visualstudio.com/_usersSettings/tokens
|
||||
with the scope of `Build (read and execute)`.
|
||||
|
||||
## Determine which branch to release from
|
||||
|
||||
- **If releasing beta,** run the scripts below from `master`.
|
||||
- **If releasing a stable version,** run the scripts below from `1-7-x` or
|
||||
`1-6-x`, depending on which version you are releasing for.
|
||||
- **If releasing a stable version,** run the scripts below from the branch
|
||||
you're stabilizing.
|
||||
|
||||
## Find out what version change is needed
|
||||
Run `npm run prepare-release -- --notesOnly` to view auto generated release
|
||||
@@ -14,6 +34,11 @@ notes. The notes generated should help you determine if this is a major, minor,
|
||||
patch, or beta version change. Read the
|
||||
[Version Change Rules](../tutorial/electron-versioning.md#semver) for more information.
|
||||
|
||||
**NB:** If releasing from a branch, e.g. 1-8-x, check out the branch with
|
||||
`git checkout 1-8-x` rather than `git checkout -b remotes/origin/1-8-x`.
|
||||
The scripts need `git rev-parse --abbrev-ref HEAD` to return a short name,
|
||||
e.g. no `remotes/origin/`
|
||||
|
||||
## Run the prepare-release script
|
||||
The prepare release script will do the following:
|
||||
1. Check if a release is already in process and if so it will halt.
|
||||
@@ -55,10 +80,11 @@ npm run prepare-release -- --stable
|
||||
The `prepare-release` script will trigger the builds via API calls.
|
||||
To monitor the build progress, see the following pages:
|
||||
|
||||
- [mac-ci.electronjs.org/blue/organizations/jenkins/electron-mas-x64-release/activity](https://mac-ci.electronjs.org/blue/organizations/jenkins/electron-mas-x64-release/activity) for Mac App Store
|
||||
- [mac-ci.electronjs.org/blue/organizations/jenkins/electron-osx-x64-release/activity](https://mac-ci.electronjs.org/blue/organizations/jenkins/electron-osx-x64-release/activity) for OS X
|
||||
- [circleci.com/gh/electron/electron](https://circleci.com/gh/electron) for Linux
|
||||
- [windows-ci.electronjs.org/project/AppVeyor/electron](https://windows-ci.electronjs.org/project/AppVeyor/electron) for Windows
|
||||
- [electron-release-mas-x64](https://github.visualstudio.com/electron/_build/index?context=allDefinitions&path=%5C&definitionId=19&_a=completed) for MAS builds.
|
||||
- [electron-release-osx-x64](https://github.visualstudio.com/electron/_build/index?context=allDefinitions&path=%5C&definitionId=18&_a=completed) for OSX builds.
|
||||
- [circleci.com/gh/electron/electron](https://circleci.com/gh/electron) for Linux builds.
|
||||
- [windows-ci.electronjs.org/project/AppVeyor/electron-39ng6](https://windows-ci.electronjs.org/project/AppVeyor/electron-39ng6) for Windows 32-bit builds.
|
||||
- [windows-ci.electronjs.org/project/AppVeyor/electron](https://windows-ci.electronjs.org/project/AppVeyor/electron) for Windows 64-bit builds.
|
||||
|
||||
## Compile release notes
|
||||
|
||||
@@ -159,14 +185,15 @@ This release is published to [npm](https://www.npmjs.com/package/electron) under
|
||||
|
||||
## Edit the release draft
|
||||
|
||||
1. Visit [the releases page] and you'll see a new draft release with placeholder release notes.
|
||||
1. Edit the release and add release notes.
|
||||
1. Uncheck the `prerelease` checkbox if you're publishing a stable release; leave it checked for beta releases.
|
||||
1. Click 'Save draft'. **Do not click 'Publish release'!**
|
||||
1. Wait for all builds to pass before proceeding.
|
||||
1. You can run `npm run release -- --validateRelease` to verify that all of the
|
||||
required files have been created for the release.
|
||||
|
||||
1. Visit [the releases page] and you'll see a new draft release with placeholder
|
||||
release notes.
|
||||
2. Edit the release and add release notes.
|
||||
3. Click 'Save draft'. **Do not click 'Publish release'!**
|
||||
4. Wait for all builds to pass before proceeding.
|
||||
5. In the branch, verify that the release's files have been created:
|
||||
```sh
|
||||
$ npm run release -- --validateRelease
|
||||
```
|
||||
|
||||
## Publish the release
|
||||
|
||||
@@ -181,17 +208,68 @@ on Windows by node-gyp to build native modules.
|
||||
5. Validate that all of the required files are present on GitHub and S3 and have
|
||||
the correct checksums as specified in the SHASUMS files.
|
||||
6. Publish the release on GitHub
|
||||
7. Delete the `release` branch.
|
||||
|
||||
## Publish to npm
|
||||
|
||||
Once the publish is successful, run `npm run publish-to-npm` to publish to
|
||||
release to npm.
|
||||
Before publishing to npm, you'll need to log into npm as Electron. Optionally,
|
||||
you may find [npmrc](https://www.npmjs.com/package/npmrc) to be a useful way
|
||||
to keep Electron's profile side-by-side with your own:
|
||||
```sh
|
||||
$ sudo npm install -g npmrc
|
||||
$ npmrc -c electron
|
||||
Removing old .npmrc (default)
|
||||
Activating .npmrc "electron"
|
||||
```
|
||||
|
||||
The Electron account's credentials are kept by GitHub.
|
||||
"Electron - NPM" for the URL "https://www.npmjs.com/login".
|
||||
```sh
|
||||
$ npm login
|
||||
Username: electron
|
||||
Password:
|
||||
Email: (this IS public) electron@github.com
|
||||
```
|
||||
|
||||
Publish the release to npm.
|
||||
```sh
|
||||
$ npm whoami
|
||||
electron
|
||||
$ npm run publish-to-npm
|
||||
```
|
||||
|
||||
[the releases page]: https://github.com/electron/electron/releases
|
||||
[this bump commit]: https://github.com/electron/electron/commit/78ec1b8f89b3886b856377a1756a51617bc33f5a
|
||||
[versioning]: /docs/tutorial/electron-versioning.md
|
||||
|
||||
# Troubleshooting
|
||||
|
||||
## Rerun broken builds
|
||||
|
||||
If a release build fails for some reason, you can use `script/ci-release-build.js` to rerun a release build:
|
||||
|
||||
### Rerun all linux builds:
|
||||
```sh
|
||||
node script/ci-release-build.js --ci=CircleCI --ghRelease TARGET_BRANCH
|
||||
(TARGET_BRANCH) is the branch you are releasing from.
|
||||
```
|
||||
|
||||
### Rerun all macOS builds:
|
||||
```sh
|
||||
node script/ci-release-build.js --ci=VSTS --ghRelease TARGET_BRANCH
|
||||
(TARGET_BRANCH) is the branch you are releasing from.
|
||||
```
|
||||
|
||||
### Rerun all Windows builds:
|
||||
```sh
|
||||
node script/ci-release-build.js --ci=AppVeyor --ghRelease TARGET_BRANCH
|
||||
(TARGET_BRANCH) is the branch you are releasing from.
|
||||
```
|
||||
|
||||
Additionally you can pass a job name to the script to run an individual job, eg:
|
||||
````sh
|
||||
node script/ci-release-build.js --ci=AppVeyor --ghRelease --job=electron-x64 TARGET_BRANCH
|
||||
```
|
||||
|
||||
## Fix missing binaries of a release manually
|
||||
|
||||
In the case of a corrupted release with broken CI machines, we might have to
|
||||
|
||||
94
docs/tutorial/support.md
Normal file
94
docs/tutorial/support.md
Normal file
@@ -0,0 +1,94 @@
|
||||
# Electron Support
|
||||
|
||||
## Finding Support
|
||||
|
||||
If you have a security concern,
|
||||
please see the [security document](../../SECURITY.md).
|
||||
|
||||
If you're looking for programming help,
|
||||
for answers to questions,
|
||||
or to join in discussion with other developers who use Electron,
|
||||
you can interact with the community in these locations:
|
||||
- [`electron`](https://discuss.atom.io/c/electron) category on the Atom
|
||||
forums
|
||||
- `#atom-shell` channel on Freenode
|
||||
- [`Electron`](https://atom-slack.herokuapp.com) channel on Atom's Slack
|
||||
- [`electron-ru`](https://telegram.me/electron_ru) *(Russian)*
|
||||
- [`electron-br`](https://electron-br.slack.com) *(Brazilian Portuguese)*
|
||||
- [`electron-kr`](https://electron-kr.github.io/electron-kr) *(Korean)*
|
||||
- [`electron-jp`](https://electron-jp.slack.com) *(Japanese)*
|
||||
- [`electron-tr`](https://electron-tr.herokuapp.com) *(Turkish)*
|
||||
- [`electron-id`](https://electron-id.slack.com) *(Indonesia)*
|
||||
- [`electron-pl`](https://electronpl.github.io) *(Poland)*
|
||||
|
||||
If you'd like to contribute to Electron,
|
||||
see the [contributing document](../../CONTRIBUTING.md).
|
||||
|
||||
If you've found a bug in a [supported version](#supported-versions) of Electron,
|
||||
please report it with the [issue tracker](../development/issues.md).
|
||||
|
||||
[awesome-electron](https://github.com/sindresorhus/awesome-electron)
|
||||
is a community-maintained list of useful example apps,
|
||||
tools and resources.
|
||||
|
||||
## Supported Versions
|
||||
|
||||
The latest three release branches are supported by the Electron team.
|
||||
For example, if the latest release is 2.0.x, then the 2-0-x series
|
||||
is supported, as are the two previous release series 1-7-x and 1-8-x.
|
||||
|
||||
When a release branch reaches the end of its support cycle, the series
|
||||
will be deprecated in NPM and a final end-of-support release will be
|
||||
made. This release will add a warning to inform that an unsupported
|
||||
version of Electron is in use.
|
||||
|
||||
These steps are to help app developers learn when a branch they're
|
||||
using becomes unsupported, but without being excessively intrusive
|
||||
to end users.
|
||||
|
||||
If an application has exceptional circumstances and needs to stay
|
||||
on an unsupported series of Electron, developers can silence the
|
||||
end-of-support warning by omitting the final release from the app's
|
||||
`package.json` `devDependencies`. For example, since the 1-6-x series
|
||||
ended with an end-of-support 1.6.18 release, developers could choose
|
||||
to stay in the 1-6-x series without warnings with `devDependency` of
|
||||
`"electron": 1.6.0 - 1.6.17`.
|
||||
|
||||
## Supported Platforms
|
||||
|
||||
Following platforms are supported by Electron:
|
||||
|
||||
### macOS
|
||||
|
||||
Only 64bit binaries are provided for macOS, and the minimum macOS version
|
||||
supported is macOS 10.9.
|
||||
|
||||
### Windows
|
||||
|
||||
Windows 7 and later are supported, older operating systems are not supported
|
||||
(and do not work).
|
||||
|
||||
Both `ia32` (`x86`) and `x64` (`amd64`) binaries are provided for Windows.
|
||||
Running Electron apps on Windows for ARM devices is possible by using the
|
||||
ia32 binary.
|
||||
|
||||
### Linux
|
||||
|
||||
The prebuilt `ia32` (`i686`) and `x64` (`amd64`) binaries of Electron are built on
|
||||
Ubuntu 12.04, the `armv7l` binary is built against ARM v7 with hard-float ABI and
|
||||
NEON for Debian Wheezy.
|
||||
|
||||
[Until the release of Electron 2.0][arm-breaking-change], Electron will also
|
||||
continue to release the `armv7l` binary with a simple `arm` suffix. Both binaries
|
||||
are identical.
|
||||
|
||||
Whether the prebuilt binary can run on a distribution depends on whether the
|
||||
distribution includes the libraries that Electron is linked to on the building
|
||||
platform, so only Ubuntu 12.04 is guaranteed to work, but following platforms
|
||||
are also verified to be able to run the prebuilt binaries of Electron:
|
||||
|
||||
* Ubuntu 12.04 and newer
|
||||
* Fedora 21
|
||||
* Debian 8
|
||||
|
||||
[arm-breaking-change]: https://github.com/electron/electron/blob/master/docs/tutorial/planned-breaking-changes.md#duplicate-arm-assets
|
||||
@@ -1,37 +1 @@
|
||||
# Supported Platforms
|
||||
|
||||
Following platforms are supported by Electron:
|
||||
|
||||
### macOS
|
||||
|
||||
Only 64bit binaries are provided for macOS, and the minimum macOS version
|
||||
supported is macOS 10.9.
|
||||
|
||||
### Windows
|
||||
|
||||
Windows 7 and later are supported, older operating systems are not supported
|
||||
(and do not work).
|
||||
|
||||
Both `ia32` (`x86`) and `x64` (`amd64`) binaries are provided for Windows.
|
||||
Please note, the `ARM` version of Windows is not supported for now.
|
||||
|
||||
### Linux
|
||||
|
||||
The prebuilt `ia32` (`i686`) and `x64` (`amd64`) binaries of Electron are built on
|
||||
Ubuntu 12.04, the `armv7l` binary is built against ARM v7 with hard-float ABI and
|
||||
NEON for Debian Wheezy.
|
||||
|
||||
[Until the release of Electron 2.0][arm-breaking-change], Electron will also
|
||||
continue to release the `armv7l` binary with a simple `arm` suffix. Both binaries
|
||||
are identical.
|
||||
|
||||
Whether the prebuilt binary can run on a distribution depends on whether the
|
||||
distribution includes the libraries that Electron is linked to on the building
|
||||
platform, so only Ubuntu 12.04 is guaranteed to work, but following platforms
|
||||
are also verified to be able to run the prebuilt binaries of Electron:
|
||||
|
||||
* Ubuntu 12.04 and later
|
||||
* Fedora 21
|
||||
* Debian 8
|
||||
|
||||
[arm-breaking-change]: https://github.com/electron/electron/blob/master/docs/tutorial/planned-breaking-changes.md#duplicate-arm-assets
|
||||
Moved to [support.md](support.md)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
'product_name%': 'Electron',
|
||||
'company_name%': 'GitHub, Inc',
|
||||
'company_abbr%': 'github',
|
||||
'version%': '2.0.0-beta.4',
|
||||
'version%': '2.0.11',
|
||||
'js2c_input_dir': '<(SHARED_INTERMEDIATE_DIR)/js2c',
|
||||
},
|
||||
'includes': [
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
'lib/renderer/inspector.js',
|
||||
'lib/renderer/override.js',
|
||||
'lib/renderer/security-warnings.js',
|
||||
'lib/renderer/web-frame-init.js',
|
||||
'lib/renderer/window-setup.js',
|
||||
'lib/renderer/web-view/guest-view-internal.js',
|
||||
'lib/renderer/web-view/web-view.js',
|
||||
@@ -273,6 +274,8 @@
|
||||
'atom/browser/net/http_protocol_handler.h',
|
||||
'atom/browser/net/js_asker.cc',
|
||||
'atom/browser/net/js_asker.h',
|
||||
'atom/browser/net/resolve_proxy_helper.cc',
|
||||
'atom/browser/net/resolve_proxy_helper.h',
|
||||
'atom/browser/net/url_request_about_job.cc',
|
||||
'atom/browser/net/url_request_about_job.h',
|
||||
'atom/browser/net/url_request_async_asar_job.cc',
|
||||
|
||||
@@ -133,7 +133,7 @@ BrowserWindow.prototype._init = function () {
|
||||
|
||||
BrowserWindow.getFocusedWindow = () => {
|
||||
for (let window of BrowserWindow.getAllWindows()) {
|
||||
if (window.isFocused()) return window
|
||||
if (window.isFocused() || window.isDevToolsFocused()) return window
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -1,14 +1,20 @@
|
||||
'use strict'
|
||||
|
||||
if (process.platform !== 'darwin') {
|
||||
throw new Error('The inAppPurchase module can only be used on macOS')
|
||||
if (process.platform === 'darwin') {
|
||||
const {EventEmitter} = require('events')
|
||||
const {inAppPurchase, InAppPurchase} = process.atomBinding('in_app_purchase')
|
||||
|
||||
// inAppPurchase is an EventEmitter.
|
||||
Object.setPrototypeOf(InAppPurchase.prototype, EventEmitter.prototype)
|
||||
EventEmitter.call(inAppPurchase)
|
||||
|
||||
module.exports = inAppPurchase
|
||||
} else {
|
||||
module.exports = {
|
||||
purchaseProduct: (productID, quantity, callback) => {
|
||||
throw new Error('The inAppPurchase module can only be used on macOS')
|
||||
},
|
||||
canMakePayments: () => false,
|
||||
getReceiptURL: () => ''
|
||||
}
|
||||
}
|
||||
|
||||
const {EventEmitter} = require('events')
|
||||
const {inAppPurchase, InAppPurchase} = process.atomBinding('in_app_purchase')
|
||||
|
||||
// inAppPurchase is an EventEmitter.
|
||||
Object.setPrototypeOf(InAppPurchase.prototype, EventEmitter.prototype)
|
||||
EventEmitter.call(inAppPurchase)
|
||||
|
||||
module.exports = inAppPurchase
|
||||
|
||||
@@ -20,7 +20,7 @@ const delegate = {
|
||||
getAcceleratorForCommandId: (menu, id, useDefaultAccelerator) => {
|
||||
const command = menu.commandsMap[id]
|
||||
if (!command) return
|
||||
if (command.accelerator) return command.accelerator
|
||||
if (command.accelerator != null) return command.accelerator
|
||||
if (useDefaultAccelerator) return command.getDefaultRoleAccelerator()
|
||||
},
|
||||
executeCommand: (menu, event, id) => {
|
||||
@@ -47,6 +47,9 @@ Menu.prototype._init = function () {
|
||||
}
|
||||
|
||||
Menu.prototype.popup = function (options) {
|
||||
if (options == null || typeof options !== 'object') {
|
||||
throw new TypeError('Options must be an object')
|
||||
}
|
||||
let {window, x, y, positioningItem, callback} = options
|
||||
|
||||
// no callback passed
|
||||
@@ -151,7 +154,7 @@ Menu.setApplicationMenu = function (menu) {
|
||||
}
|
||||
|
||||
Menu.buildFromTemplate = function (template) {
|
||||
if (!(template instanceof Array)) {
|
||||
if (!Array.isArray(template)) {
|
||||
throw new TypeError('Invalid template for Menu')
|
||||
}
|
||||
|
||||
@@ -237,14 +240,19 @@ function indexToInsertByPosition (items, position) {
|
||||
}
|
||||
|
||||
function removeExtraSeparators (items) {
|
||||
// remove invisible items
|
||||
let ret = items.filter(e => e.visible !== false)
|
||||
|
||||
// fold adjacent separators together
|
||||
ret = ret.filter((e, idx, arr) => e.type !== 'separator' || idx === 0 || arr[idx - 1].type !== 'separator')
|
||||
let ret = items.filter((e, idx, arr) => {
|
||||
if (e.visible === false) return true
|
||||
return e.type !== 'separator' || idx === 0 || arr[idx - 1].type !== 'separator'
|
||||
})
|
||||
|
||||
// remove edge separators
|
||||
return ret.filter((e, idx, arr) => e.type !== 'separator' || (idx !== 0 && idx !== arr.length - 1))
|
||||
ret = ret.filter((e, idx, arr) => {
|
||||
if (e.visible === false) return true
|
||||
return e.type !== 'separator' || (idx !== 0 && idx !== arr.length - 1)
|
||||
})
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
function insertItemByType (item, pos) {
|
||||
|
||||
@@ -118,6 +118,18 @@ class TouchBar extends EventEmitter {
|
||||
window.removeListener('closed', removeListeners)
|
||||
window._touchBar = null
|
||||
delete this.windowListeners[id]
|
||||
const unregisterItems = (items) => {
|
||||
for (const item of items) {
|
||||
item.removeListener('change', this.changeListener)
|
||||
if (item.child instanceof TouchBar) {
|
||||
unregisterItems(item.child.ordereredItems)
|
||||
}
|
||||
}
|
||||
}
|
||||
unregisterItems(this.ordereredItems)
|
||||
if (this.escapeItem) {
|
||||
this.escapeItem.removeListener('change', this.changeListener)
|
||||
}
|
||||
}
|
||||
window.once('closed', removeListeners)
|
||||
this.windowListeners[id] = removeListeners
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user