Compare commits

..

53 Commits

Author SHA1 Message Date
John Kleinschmidt
a69a5de12f v1.7.11 2018-01-22 17:24:59 -05:00
Charles Kerr
d2a9ea4684 fix 'npm lint' errors 2018-01-22 15:21:39 -06:00
Aleš Pergl
e7074c5cdb Disallow launching unknown apps via browser client.
CVE-2018-1000006
2018-01-22 14:53:17 -06:00
Cheng Zhao
97349eb30a Merge pull request #11576 from dengyaolong/bugfix/1-7-x/ime-crash
fix mac ime crack
2018-01-18 16:05:23 +09:00
allenliu
f6c915bbb5 fix mac ime crack 2018-01-05 22:06:00 +08:00
John Kleinschmidt
378666668f v1.7.10 2017-12-18 15:23:57 -05:00
John Kleinschmidt
9623329cbd Merge pull request #11427 from electron/prepare-for-release
Preparation for 1.7.10 release
2017-12-18 13:20:31 -05:00
John Kleinschmidt
34b75e5e73 Update to use new release scripts 2017-12-13 11:54:23 -05:00
John Kleinschmidt
c339e576a8 Update libcc 2017-12-13 10:44:20 -05:00
Charles Kerr
c12d88fc30 Merge pull request #11327 from electron/cherry/1-7-x/10540
Cherry #10540
2017-12-04 10:43:49 -06:00
Benjamin Pasero
8f2064d9b7 set iconPosition as optional 2017-12-04 10:04:29 -06:00
Charles Kerr
75ff5d2a45 Merge pull request #11141 from electron/backport-scrubber-width-fix
Backport scrubber width fix to 1-7-x
2017-11-17 14:31:54 -06:00
John Kleinschmidt
87565e25eb Add Jenkinsfile for macOS CI 2017-11-17 10:58:26 -05:00
Samuel Attard
d0c9c4028e Forward declare the scrubber layout 2017-11-17 06:21:36 +11:00
Armagan Amcalar
37f23f6d4e Make ScrubberItem width dynamic
Depending on whether a ScrubberItem has text or an icon, this changeset
calculates the actual width and sizes the TouchBar items accordingly.
Previously, all ScrubberItems, regardless of their content, had a static
width of 50px.

This commit also fixes #10539.
2017-11-17 06:19:19 +11:00
Charles Kerr
4b8f3276b5 Merge pull request #11020 from pfrazee/fix-protocol-crash-error-17x
Fix crash in custom protocols caused by bad callback exec
2017-11-16 09:36:38 -06:00
Charles Kerr
b15c418c54 Merge pull request #10898 from electron/nvidia-high-sierra-17x-fix
Fix rendering issues with Nvidia GPU on High Sierra for 1.7.x
2017-11-13 17:49:30 -06:00
Paul Frazee
d964560990 Fix crash in custom protocols caused by bad callback exec 2017-11-05 12:20:46 -06:00
John Kleinschmidt
66e0e8fdcd Fix rendering issues with Nvidia GPU on High Sierra 2017-10-24 13:48:39 -04:00
John Kleinschmidt
c16498c274 Bump v1.7.9 2017-10-10 15:33:41 -04:00
John Kleinschmidt
62bd339b0d Merge pull request #10743 from electron/crankshaft-fix
Crankshaft RCE fix
2017-10-10 15:04:29 -04:00
John Kleinschmidt
0368460d74 Crankshaft RCE fix 2017-10-10 13:23:31 -04:00
John Kleinschmidt
9386de415a Merge pull request #10687 from electron/circleci-report-testing-results
CircleCI report testing results
2017-10-04 10:41:10 -04:00
John Kleinschmidt
4d3d7aa5fd Improve CircleCI test results 2017-10-04 10:01:09 -04:00
John Kleinschmidt
1d0dfd590b Release process updates for 1-7-x (#10643)
* Add prerelease script

* Update CircleCI for releases

* Rerun builds
2017-09-28 10:48:02 -04:00
Birunthan Mohanathas
5b679cb1eb Merge pull request #10630 from electron/squirrel-avoid-double-update-1-7
Use Squirrel.Windows --checkForUpdate (1.7.x)
2017-09-27 21:20:22 +03:00
J.M
8c28e3b6f1 Use Squirrel.Windows --checkForUpdate
This cherry-picks #10483 to fix #5057.
2017-09-27 20:32:58 +03:00
Birunthan Mohanathas
f786199d2c Merge pull request #10628 from electron/squirrel-mac-bump
Bump external binaries to 1.2.2
2017-09-27 16:06:03 +03:00
Josh Abernathy
acfc24e45e Bump external binaries to 1.2.2 2017-09-27 16:04:05 +03:00
John Kleinschmidt
01ca2252cd Bump v1.7.8 2017-09-24 10:34:18 +09:00
John Kleinschmidt
53db3862c0 Merge pull request #10591 from electron/disable-app-importcertificate-tests
disable flaky app.importCertificate and select-client-certificate tests
2017-09-24 10:25:57 +09:00
John Kleinschmidt
6099ab222e Change GitHub upload to use JS GitHub lib 2017-09-24 10:17:15 +09:00
Zeke Sikelianos
830cc7ecd1 disable select-client-certificate spec 2017-09-24 10:00:34 +09:00
Zeke Sikelianos
eef8ff09e2 disable flaky app.importCertificate tests 2017-09-24 09:49:48 +09:00
Samuel Attard
b15392e1c1 Backporting changes for 1.7.8 (#10586)
* Fix app.makeSingleInstance hanging on posix systems

Wait for the IO thread to be a thing before attempting to listen on the socket

Fixes #9880

* Move OnBrowserReady call to PreMainMessageLoopRun to account for timing issues on macOS

* Woops, how did that happen ;)

* Refactor as per @zcbenz comments

Also fix issue where we run the single instance callback *not* on the UI thread,
this apparently results in a hung process.

* Appease the linting gods

* Create watcher when message loop is ready

* spec: Add test case for app.makeSingleInstance

* Fix missing extension when saving a file without filters

Previously, when triggering the save dialog through e.g. `<a download>`
links (e.g. http://jsfiddle.net/koldev/cW7W5/), the extension was only
saved if Finder was set to show all extensions by default. We now always
display the extension to make sure that it is saved.

If we want to keep the extension hidden, we could also populate the
allowed file types array with the extension from the default filename,
but that would have interfered with how we set the filters.

* Try to make test less flaky

* Try simpler test

* Fix stdout detection

* Try longer timeout on test
2017-09-24 07:27:08 +09:00
John Kleinschmidt
fd1bb3f95d Merge pull request #10585 from electron/turbofan-fix
Apply turbofan-fix
2017-09-23 16:06:34 +09:00
John Kleinschmidt
53eb4d68c5 Apply turbofan-fix 2017-09-23 15:05:15 +09:00
John Kleinschmidt
331a1759d2 Fix CircleCI test step 2017-09-13 11:22:33 -04:00
John Kleinschmidt
b69d76258a Remove arm64 build
Arm64 builds are not built for 1.7.x
2017-09-13 10:50:53 -04:00
John Kleinschmidt
680bf0076b Bump v1.7.7 2017-08-30 13:06:59 -04:00
John Kleinschmidt
d42d856b9a Rerun builds 2017-08-30 09:42:23 -04:00
John Kleinschmidt
e6f6862ae8 Merge pull request #10390 from electron/render_widget_compositor_patch
Backport fix for flickering web contents on large monitors
2017-08-29 21:52:35 -04:00
John Kleinschmidt
44b4cc374b Update to latest build 2017-08-29 21:27:59 -04:00
John Kleinschmidt
9824c88d2d Backport fix for flickering web contents on large monitors 2017-08-29 13:43:02 -04:00
John Kleinschmidt
96bc46c255 Merge pull request #10365 from electron/fix_exit_crash
Fixed crash on process exit on Windows
2017-08-29 11:55:12 -04:00
John Kleinschmidt
873a8902af Merge pull request #10375 from electron/backport-notification-sounds
Backport #10293 (notification-sounds)
2017-08-29 10:52:26 -04:00
John Kleinschmidt
7dac300305 Merge pull request #10377 from electron/backfort-libuv-1419
Backport libuv/libuv#1419
2017-08-29 10:50:32 -04:00
John Kleinschmidt
2a536d2aa2 Merge pull request #10374 from electron/backport-drag-browser-view
Backport #10232 (drag-browser-view)
2017-08-29 09:34:58 -04:00
Cheng Zhao
ccd03c6675 Backport https://github.com/libuv/libuv/pull/1419
win, fs: support unusual reparse points

Allow for running uv_fs_stat and uv_fs_lstat on all reparse points. One
of such points is new OneDrive drive with "files on demand" feature
enabled.
2017-08-29 10:25:45 +09:00
Charlie Hess
5515092944 Merge pull request #10293 from electron/notification-sounds
Add support for soundName in main process notifications
2017-08-28 13:23:27 -07:00
Samuel Attard
fb7661d2d2 Merge pull request #10232 from electron/drag-browser-view
Add -webkit-app-region support to BrowserView
2017-08-28 13:19:09 -07:00
John Kleinschmidt
75b31f0bb6 Add CircleCI 2017-08-28 11:35:30 -04:00
Ales Pergl
cfee5ba8c8 Fixed crash on process exit on Windows 2017-08-28 16:28:07 +02:00
1542 changed files with 76281 additions and 65658 deletions

View File

@@ -1,339 +1,223 @@
build-steps: &build-steps
steps:
- checkout
- run:
name: Install Node.js 10 on MacOS
command: |
if [ "$INSTALL_MACOS_NODE" == "true" ]; then
echo 'Installing Node.js 10 for MacOS'
brew update
brew install node@10
fi
- run:
name: Check for release
command: |
if [ -n "${RUN_RELEASE_BUILD}" ]; then
echo 'release build triggered from api'
echo 'export ELECTRON_RELEASE=1 UPLOAD_TO_S3=1' >> $BASH_ENV
fi
- run:
name: Bootstrap
command: |
if [ "$ELECTRON_RELEASE" == "1" ]; then
echo "Bootstrapping Electron for release build for $TARGET_ARCH"
script/bootstrap.py --target_arch=$TARGET_ARCH
else
echo "Bootstrapping Electron for debug build for $TARGET_ARCH"
script/bootstrap.py --target_arch=$TARGET_ARCH --dev
fi
- run:
name: Lint
command: 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" ] && [ "$UPLOAD_TO_S3" != "1" ]; then
echo 'Uploading Electron release distribution to github releases'
script/upload.py
elif [ "$ELECTRON_RELEASE" == "1" ] && [ "$UPLOAD_TO_S3" == "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: Setup for headless testing
command: |
if [ "$RUN_HEADLESS_TESTS" == "true" ]; then
echo 'Setup for headless testing'
sh -e /etc/init.d/xvfb start
else
echo 'Headless testing not needed'
fi
- run:
name: Test
environment:
MOCHA_FILE: junit/test-results.xml
MOCHA_REPORTER: mocha-junit-reporter
command: |
if [ "$RUN_TESTS" == "true" ]; then
if [ "$ELECTRON_RELEASE" != "1" ]; then
echo 'Testing Electron debug build'
mkdir junit
script/test.py --ci --rebuild_native_modules
else
if [ "$UPLOAD_TO_S3" == "1" ]; then
echo 'Testing Electron release build'
mkdir junit
script/test.py --ci --rebuild_native_modules -c R
else
echo 'Skipping tests on GitHub release'
fi
fi
else
echo 'Skipping tests due to configuration'
fi
- run:
name: Verify FFmpeg
command: |
if [ "$RUN_TESTS" == "true" ]; then
if [ "$ELECTRON_RELEASE" != "1" ]; then
echo 'Verifying ffmpeg on debug build'
script/verify-ffmpeg.py
else
echo 'Verifying ffmpeg on release build'
script/verify-ffmpeg.py -R
fi
else
echo 'Skipping tests due to configuration'
fi
- run:
name: Generate Typescript Definitions
command: |
if [ "$CREATE_TYPESCRIPT_DEFS" == "true" ]; then
npm run create-typescript-definitions
fi
- persist_to_workspace:
root: out
paths:
- "*"
- store_test_results:
path: junit
- store_artifacts:
path: junit
- store_artifacts:
path: out
build-defaults: &build-defaults
docker:
- image: electronbuilds/electron:0.0.8
<<: *build-steps
version: 2
jobs:
electron-linux-arm:
environment:
TARGET_ARCH: arm
<<: *build-defaults
docker:
- image: electronbuilds/electron:0.0.4
environment:
TARGET_ARCH: arm
resource_class: 2xlarge
electron-linux-arm-test:
machine: true
steps:
- attach_workspace:
at: /tmp/workspace/project/out
- checkout
- run:
name: Test in ARM docker container
name: Check for release
command: |
if [ "$ELECTRON_RELEASE" != "1" ]; then
docker run --rm --privileged multiarch/qemu-user-static:register --reset
docker run -it \
--mount type=bind,source=/tmp/workspace,target=/tmp/workspace \
--rm electronbuilds/electronarm7:0.0.5 > version.txt
cat version.txt
if grep -q `script/get-version.py` version.txt; then
echo "Versions match"
else
echo "Versions do not match"
exit 1
fi
else
echo "Skipping test for release build"
if [ -n "${RUN_RELEASE_BUILD}" ]; then
echo 'release build triggered from api'
echo 'export ELECTRON_RELEASE=1 TRIGGERED_BY_API=1' >> $BASH_ENV
fi
electron-linux-arm-release-nightly:
environment:
TARGET_ARCH: arm
RUN_RELEASE_BUILD: true
<<: *build-defaults
resource_class: 2xlarge
electron-linux-arm64:
environment:
TARGET_ARCH: arm64
<<: *build-defaults
resource_class: 2xlarge
electron-linux-arm64-test:
machine: true
steps:
- attach_workspace:
at: /tmp/workspace/project/out
- checkout
- run:
name: Test in ARM64 docker container
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
docker run --rm --privileged multiarch/qemu-user-static:register --reset
docker run -it \
--mount type=bind,source=/tmp/workspace,target=/tmp/workspace \
--rm electronbuilds/electronarm64:0.0.6 > version.txt
cat version.txt
if grep -q `script/get-version.py` version.txt; then
echo "Versions match"
else
echo "Versions do not match"
exit 1
fi
else
echo "Skipping test for release build"
fi
electron-linux-arm64-release-nightly:
environment:
TARGET_ARCH: arm64
RUN_RELEASE_BUILD: true
<<: *build-defaults
resource_class: 2xlarge
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
electron-linux-ia32:
environment:
TARGET_ARCH: ia32
DISPLAY: ':99.0'
RUN_TESTS: true
RUN_HEADLESS_TESTS: true
<<: *build-defaults
docker:
- image: electronbuilds/electron:0.0.4
environment:
TARGET_ARCH: ia32
resource_class: xlarge
electron-linux-ia32-release-nightly:
environment:
TARGET_ARCH: ia32
RUN_RELEASE_BUILD: true
<<: *build-defaults
resource_class: xlarge
electron-linux-mips64el:
environment:
TARGET_ARCH: mips64el
<<: *build-defaults
resource_class: xlarge
steps:
- checkout
- 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
electron-linux-x64:
environment:
TARGET_ARCH: x64
DISPLAY: ':99.0'
RUN_TESTS: true
RUN_HEADLESS_TESTS: true
CREATE_TYPESCRIPT_DEFS: true
<<: *build-defaults
docker:
- image: electronbuilds/electron:0.0.4
environment:
TARGET_ARCH: x64
DISPLAY: ':99.0'
resource_class: xlarge
electron-linux-x64-release-nightly:
environment:
TARGET_ARCH: x64
RUN_RELEASE_BUILD: true
<<: *build-defaults
resource_class: xlarge
electron-osx-x64:
environment:
TARGET_ARCH: x64
RUN_TESTS: true
INSTALL_MACOS_NODE: true
macos:
xcode: "8.3.3"
<<: *build-steps
electron-osx-x64-release-nightly:
environment:
TARGET_ARCH: x64
RUN_RELEASE_BUILD: true
INSTALL_MACOS_NODE: true
macos:
xcode: "8.3.3"
<<: *build-steps
electron-mas-x64:
environment:
TARGET_ARCH: x64
MAS_BUILD: 1
RUN_TESTS: true
INSTALL_MACOS_NODE: true
macos:
xcode: "8.3.3"
<<: *build-steps
electron-mas-x64-release-nightly:
environment:
TARGET_ARCH: x64
MAS_BUILD: 1
RUN_RELEASE_BUILD: true
INSTALL_MACOS_NODE: true
macos:
xcode: "8.3.3"
<<: *build-steps
steps:
- checkout
- run:
name: Setup for headless testing
command: sh -e /etc/init.d/xvfb start
- 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:
jobs:
- electron-linux-arm
- electron-linux-arm-test:
requires:
- electron-linux-arm
build-arm64:
jobs:
- electron-linux-arm64
- electron-linux-arm64-test:
requires:
- electron-linux-arm64
build-ia32:
jobs:
- electron-linux-ia32
build-x64:
jobs:
- electron-linux-x64
build-osx-x64:
jobs:
- electron-osx-x64
build-mas-x64:
jobs:
- electron-mas-x64
nightly-release-test:
triggers:
- schedule:
cron: "0 0 * * *"
filters:
branches:
only:
- master
- 2-0-x
- 1-8-x
- 1-7-x
jobs:
- electron-linux-arm-release-nightly
- electron-linux-arm64-release-nightly
- electron-linux-ia32-release-nightly
- electron-linux-x64-release-nightly
experimental:
notify:
branches:
only:
- master
- 2-0-x
- 1-8-x
- 1-7-x

View File

@@ -1,3 +0,0 @@
*
!tools/xvfb-init.sh
!tools/run-electron.sh

View File

@@ -1,7 +0,0 @@
# These env vars are only necessary for creating Electron releases.
# See docs/development/releasing.md
APPVEYOR_TOKEN=
CIRCLE_TOKEN=
ELECTRON_GITHUB_TOKEN=
VSTS_TOKEN=

21
.github/CODEOWNERS vendored
View File

@@ -1,21 +0,0 @@
# Order is important. The LAST matching pattern has the MOST precedence.
# gitignore style patterns are used, not globs.
# https://help.github.com/articles/about-codeowners
# https://git-scm.com/docs/gitignore
# Everything that falls through the cracks:
* @electron/reviewers
# filename patterns
*browser_view* @electron/browserview
*notification* @electron/notifications
*pdf* @electron/printing
*printing* @electron/printing
*updater* @electron/updater
# directories
/.github/ @electron/electrocats
/default_app/ @electron/docs
/docs/ @electron/docs
/docs-translations/ @electron/i18n
/npm/ @electron/electrocats

View File

@@ -1,32 +0,0 @@
---
name: Bug report
about: Create a report to help us improve Electron
---
* Electron Version:
* Operating System (Platform and Version):
* Last known working Electron version:
**Expected Behavior**
A clear and concise description of what you expected to happen.
**Actual behavior**
A clear and concise description of what actually happened.
**To Reproduce**
Your best chance of getting this bug looked at quickly is to provide a REPOSITORY that can be cloned and run.
You can fork [electron-quick-start](https://github.com/electron/electron-quick-start) and include a link to the branch with your changes.
If you provide a URL, please list the commands required to clone/setup/run your repo e.g.
```sh
$ git clone $YOUR_URL -b $BRANCH
$ npm install
$ npm start || electron .
```
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Additional Information**
Add any other context about the problem here.

View File

@@ -1,17 +0,0 @@
---
name: Feature request
about: Suggest an idea for Electron
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is.
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@@ -1,15 +0,0 @@
<!--
Thank you for your Pull Request. Please provide a description above and review
the requirements below.
Contributors guide: https://github.com/electron/electron/blob/master/CONTRIBUTING.md
-->
##### Checklist
<!-- Remove items that do not apply. For completed items, change [ ] to [x]. -->
- [ ] PR description included and stakeholders cc'd
- [ ] `npm test` passes
- [ ] tests are [changed or added](https://github.com/electron/electron/blob/master/docs/development/testing.md)
- [ ] relevant documentation is changed or added
- [ ] commit messages or PR title follow semantic [commit guidelines](https://github.com/electron/electron/blob/master/docs/development/pull-requests.md#commit-message-guidelines)

53
.github/config.yml vendored
View File

@@ -1,53 +0,0 @@
# Configuration for new-issue-welcome - https://github.com/behaviorbot/new-issue-welcome
# Comment to be posted to on first time issues
newIssueWelcomeComment: |
👋 Thanks for opening your first issue here! If you're reporting a 🐞 bug, please make sure you include steps to reproduce it. We get a lot of issues on this repo, so please be patient and we will get back to you as soon as we can.
To help make it easier for us to investigate your issue, please follow the [contributing guidelines](https://github.com/electron/electron/blob/master/CONTRIBUTING.md).
# Configuration for new-pr-welcome - https://github.com/behaviorbot/new-pr-welcome
# Comment to be posted to on PRs from first time contributors in your repository
newPRWelcomeComment: |
💖 Thanks for opening this pull request! 💖
We use [semantic commit messages](https://github.com/electron/electron/blob/master/docs/development/pull-requests.md#commit-message-guidelines) to streamline the release process. Before your pull request can be merged, you should **update your pull request title** to start with a semantic prefix, OR prefix at least one of your commit messages.
Examples of commit messages with semantic prefixes:
- `fix: don't overwrite prevent_default if default wasn't prevented`
- `feat: add app.isPackaged() method`
- `docs: app.isDefaultProtocolClient is now available on Linux`
Things that will help get your PR across the finish line:
- Follow the JavaScript, C++, and Python [coding style](https://github.com/electron/electron/blob/master/docs/development/coding-style.md).
- Run `npm run lint` locally to catch formatting errors earlier.
- Document any user-facing changes you've made following the [documentation styleguide](https://github.com/electron/electron/blob/master/docs/styleguide.md).
- Include tests when adding/changing behavior.
- Include screenshots and animated GIFs whenever possible.
We get a lot of pull requests on this repo, so please be patient and we will get back to you as soon as we can.
# Configuration for first-pr-merge - https://github.com/behaviorbot/first-pr-merge
# Comment to be posted to on pull requests merged by a first time user
firstPRMergeComment: >
Congrats on merging your first pull request! 🎉🎉🎉
# Configuration for trop - https://github.com/codebytere/trop
watchedProject:
name: Backports
authorizedUsers:
- alexeykuzmin
- ckerr
- codebytere
- deepak1556
- jkleinsc
- MarshallOfSound
- nitsakh
- nornagon
- zcbenz

25
.github/stale.yml vendored
View File

@@ -1,25 +0,0 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 45
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- fixme/bug
- fixme/crash
- fixme/regression
- fixme/security
- blocked
- blocking-stable
- needs-review
# Label to use when marking an issue as stale
staleLabel: stale
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity and is not currently prioritized. It will be closed
in a week if no further activity occurs :)
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: >
If you still think this issue is relevant, please ping a maintainer or
leave a comment!

31
.gitignore vendored
View File

@@ -1,7 +1,6 @@
.DS_Store
.env
.gclient_done
**/.npmrc
.npmrc
.tags*
.vs/
.vscode/
@@ -15,6 +14,7 @@
*.vcxproj.filters
*.vcxproj.user
*.xcodeproj
node_modules/
/.idea/
/brightray/brightray.opensdf
/brightray/brightray.sdf
@@ -23,30 +23,21 @@
/brightray/brightray.v12.suo
/brightray/brightray.vcxproj*
/brightray/brightray.xcodeproj/
/build/
/dist/
/external_binaries/
/out/
/vendor/.gclient
/vendor/debian_jessie_mips64-sysroot/
/vendor/debian_stretch_amd64-sysroot/
/vendor/debian_stretch_arm-sysroot/
/vendor/debian_stretch_arm64-sysroot/
/vendor/debian_stretch_i386-sysroot/
/vendor/gcc-4.8.3-d197-n64-loongson/
/vendor/readme-gcc483-loongson.txt
/vendor/debian_jessie_amd64-sysroot/
/vendor/debian_jessie_arm-sysroot/
/vendor/debian_jessie_arm64-sysroot/
/vendor/debian_jessie_i386-sysroot/
/vendor/debian_wheezy_amd64-sysroot/
/vendor/debian_wheezy_arm-sysroot/
/vendor/debian_wheezy_i386-sysroot/
/vendor/download/
/vendor/llvm-build/
/vendor/llvm/
/vendor/node/deps/node-inspect/.npmrc
/vendor/npm/
/vendor/python_26/
/vendor/native_mksnapshot
/vendor/LICENSES.chromium.html
node_modules/
SHASUMS256.txt
**/yarn.lock
compile_commands.json
.envrc
# npm package
/npm/dist
/npm/path.txt

3
.gitmodules vendored
View File

@@ -7,6 +7,9 @@
[submodule "vendor/breakpad"]
path = vendor/breakpad
url = https://github.com/electron/chromium-breakpad.git
[submodule "vendor/native_mate"]
path = vendor/native_mate
url = https://github.com/electron/native-mate.git
[submodule "vendor/crashpad"]
path = vendor/crashpad
url = https://github.com/electron/crashpad.git

1
.node-version Normal file
View File

@@ -0,0 +1 @@
v7.9.0

View File

@@ -1,6 +0,0 @@
{
"plugins": [
["remark-lint-code-block-style", "fenced"],
["remark-lint-fenced-code-flag"]
]
}

View File

@@ -5,7 +5,7 @@ notifications:
before_install:
- export BOTO_CONFIG=/dev/null
language: node_js
node_js:
- "4"
@@ -22,8 +22,6 @@ matrix:
env: TARGET_ARCH=arm
- os: linux
env: TARGET_ARCH=ia32
- os: linux
env: TARGET_ARCH=arm64
allow_failures:
- os: osx

592
BUILD.gn
View File

@@ -1,592 +0,0 @@
import("//build/config/locales.gni")
import("//tools/grit/repack.gni")
import("build/asar.gni")
import("build/npm.gni")
if (is_mac) {
import("//build/config/mac/rules.gni")
import("//third_party/icu/config.gni")
import("//v8/gni/v8.gni")
}
if (is_linux) {
import("//build/config/linux/pkg_config.gni")
pkg_config("gio_unix") {
packages = [ "gio-unix-2.0" ]
}
}
declare_args() {
electron_project_name = "electron"
electron_product_name = "Electron"
electron_company_name = "GitHub, Inc"
electron_company_abbr = "github"
electron_version = "0.0.0-dev"
enable_desktop_capturer = true
enable_run_as_node = true
enable_osr = true
# Provide a fake location provider for mocking
# the geolocation responses. Disable it if you
# need to test with chromium's location provider.
# Should not be enabled for release build.
enable_fake_location_provider = !is_official_build
}
filenames_gypi = exec_script(
"//build/gypi_to_gn.py",
[
rebase_path("filenames.gypi"),
"--replace=<(SHARED_INTERMEDIATE_DIR)=$target_gen_dir",
],
"scope",
[ "filenames.gypi" ]
)
config("branding") {
defines = [
"ATOM_PRODUCT_NAME=\"$electron_product_name\"",
"ATOM_PROJECT_NAME=\"$electron_project_name\"",
]
}
config("features") {
defines = []
if (enable_desktop_capturer) {
defines += [ "ENABLE_DESKTOP_CAPTURER=1" ]
}
if (enable_run_as_node) {
defines += [ "ENABLE_RUN_AS_NODE=1" ]
}
if (enable_osr) {
defines += [ "ENABLE_OSR=1" ]
}
}
config("native_mate_config") {
include_dirs = [
"//third_party/native_mate",
]
cflags_cc = [
"-Wno-deprecated-declarations",
]
cflags_objcc = cflags_cc
}
source_set("native_mate") {
deps = [
"//base",
"//net",
"//v8:v8_headers",
"build/node",
]
public_configs = [ ":native_mate_config" ]
sources = [
"//third_party/native_mate/native_mate/arguments.cc",
"//third_party/native_mate/native_mate/arguments.h",
"//third_party/native_mate/native_mate/compat.h",
"//third_party/native_mate/native_mate/constructor.h",
"//third_party/native_mate/native_mate/converter.cc",
"//third_party/native_mate/native_mate/converter.h",
"//third_party/native_mate/native_mate/dictionary.cc",
"//third_party/native_mate/native_mate/dictionary.h",
"//third_party/native_mate/native_mate/function_template.cc",
"//third_party/native_mate/native_mate/function_template.h",
"//third_party/native_mate/native_mate/handle.h",
"//third_party/native_mate/native_mate/object_template_builder.cc",
"//third_party/native_mate/native_mate/object_template_builder.h",
"//third_party/native_mate/native_mate/persistent_dictionary.cc",
"//third_party/native_mate/native_mate/persistent_dictionary.h",
"//third_party/native_mate/native_mate/scoped_persistent.h",
"//third_party/native_mate/native_mate/wrappable.cc",
"//third_party/native_mate/native_mate/wrappable.h",
"//third_party/native_mate/native_mate/wrappable_base.h",
]
}
npm_action("atom_browserify_sandbox") {
deps = [ ":atom_js2c_copy" ]
sandbox_args = [
"lib/sandboxed_renderer/init.js",
"-r", "./lib/sandboxed_renderer/api/exports/electron.js:electron",
"-r", "./lib/sandboxed_renderer/api/exports/fs.js:fs",
"-r", "./lib/sandboxed_renderer/api/exports/os.js:os",
"-r", "./lib/sandboxed_renderer/api/exports/path.js:path",
"-r", "./lib/sandboxed_renderer/api/exports/child_process.js:child_process",
]
inputs = [
"lib/sandboxed_renderer/init.js",
"lib/sandboxed_renderer/api/exports/electron.js",
"lib/sandboxed_renderer/api/exports/fs.js",
"lib/sandboxed_renderer/api/exports/os.js",
"lib/sandboxed_renderer/api/exports/path.js",
"lib/sandboxed_renderer/api/exports/child_process.js",
]
outputs = [ "$target_gen_dir/js2c/preload_bundle.js" ]
script = "browserify"
args = sandbox_args + [
"-o", rebase_path(outputs[0])
]
}
npm_action("atom_browserify_isolated") {
deps = [ ":atom_js2c_copy" ]
inputs = [ "lib/isolated_renderer/init.js" ]
outputs = [ "$target_gen_dir/js2c/isolated_bundle.js" ]
script = "browserify"
args = inputs + [
"-o", rebase_path(outputs[0])
]
}
copy("atom_js2c_copy") {
sources = [
"lib/common/asar.js",
"lib/common/asar_init.js",
]
outputs = [ "$target_gen_dir/js2c/{{source_file_part}}" ]
}
action("atom_js2c") {
deps = [
":atom_js2c_copy",
":atom_browserify_sandbox",
":atom_browserify_isolated",
]
js2c_sources = filenames_gypi.js2c_sources
browserify_sources = [
"$target_gen_dir/js2c/isolated_bundle.js",
"$target_gen_dir/js2c/preload_bundle.js",
]
inputs = js2c_sources + browserify_sources
outputs = [ "$target_gen_dir/atom_natives.h" ]
script = "tools/js2c.py"
args = [
rebase_path("//third_party/electron_node")
] + rebase_path(outputs, root_build_dir) + [
rebase_path("$target_gen_dir/js2c", root_build_dir)
]
}
asar("js2asar") {
sources = filenames_gypi.js_sources
outputs = [ "$root_out_dir/resources/electron.asar" ]
root = "lib"
}
asar("app2asar") {
sources = filenames_gypi.default_app_sources
outputs = [ "$root_out_dir/resources/default_app.asar" ]
root = "default_app"
}
group("electron") {
deps = [ ":electron_lib" ]
}
static_library("electron_lib") {
configs += [
"//v8:external_startup_data",
]
public_configs = [
":branding",
":features",
]
deps = [
"//chrome/common:constants",
"//components/cdm/renderer",
"//components/network_session_configurator/common",
"//components/prefs",
"//components/printing/common",
"//components/security_state/content",
"//content/public/browser",
"//device/geolocation",
"//gin",
"//net:net_resources",
"//ppapi/host",
"//ppapi/proxy",
"//ppapi/shared_impl",
"//printing",
"//services/device/wake_lock/power_save_blocker", # TODO: this requires a visibility patch to chromium src
"//skia",
"//third_party/WebKit/public:blink",
"//third_party/boringssl",
"//third_party/crashpad/crashpad/client",
"//third_party/leveldatabase",
"//third_party/libyuv",
"//third_party/webrtc/modules/desktop_capture",
"//third_party/webrtc/modules/desktop_capture:primitives",
"//ui/events:dom_keycode_converter",
"//ui/views",
"//v8",
":atom_js2c",
":native_mate",
"brightray",
"build/node",
]
if (is_mac) {
deps += [
"//ui/accelerated_widget_mac",
"//base/allocator:features",
]
}
if (is_linux) {
deps += [
"//build/config/linux/gtk3",
"//chrome/browser/ui/libgtkui",
"//device/bluetooth",
"//third_party/breakpad:client",
"//ui/events/devices/x11",
"//ui/events/platform/x11",
"//ui/native_theme",
"//ui/views/controls/webview",
"//ui/wm",
]
configs += [ ":gio_unix" ]
}
defines = [
# This is defined in skia/skia_common.gypi.
"SK_SUPPORT_LEGACY_GETTOPDEVICE",
# Disable warnings for g_settings_list_schemas.
"GLIB_DISABLE_DEPRECATION_WARNINGS",
# Import V8 symbols from shared library (node.dll / libnode.so)
"USING_V8_SHARED",
"USING_V8_PLATFORM_SHARED",
"USING_V8_BASE_SHARED",
# Enables SkBitmap size 64 operations
#"SK_SUPPORT_LEGACY_SAFESIZE64", # doesn't seem to be needed to build?
]
include_dirs = [
"chromium_src",
".",
"$target_gen_dir",
# TODO(nornagon): replace usage of SchemeRegistry by an actually exported
# API of blink, then delete this include dir.
"//third_party/WebKit/Source",
# NOTE(nornagon): other chromium files use the full path to include
# crashpad; this is just here for compatibility between GN and GYP, so that
# the #includes can be agnostic about where crashpad is vendored.
"//third_party/crashpad",
]
if (is_linux) {
include_dirs += [
"//third_party/breakpad",
]
}
extra_source_filters = []
if (!is_linux) {
extra_source_filters += [
"*\bx/*",
"*_x11.h",
"*_x11.cc",
"*_gtk.h",
"*_gtk.cc",
]
}
if (!is_win) {
extra_source_filters += [
"*\bwin_*.h",
"*\bwin_*.cc",
]
}
if (is_mac) {
extra_source_filters += [
"*_views.cc",
"*_views.h",
"*\bviews/*",
"*/autofill_popup.cc",
"*/autofill_popup.h",
]
}
set_sources_assignment_filter(sources_assignment_filter + extra_source_filters)
sources = filenames_gypi.lib_sources
set_sources_assignment_filter(sources_assignment_filter)
if (enable_fake_location_provider) {
defines += [
"OVERRIDE_LOCATION_PROVIDER"
]
sources += filenames_gypi.lib_sources_location_provider
}
if (enable_run_as_node) {
sources += [
"atom/app/node_main.cc",
"atom/app/node_main.h",
]
}
if (enable_osr) {
sources += [
"atom/browser/api/atom_api_web_contents_osr.cc",
"atom/browser/osr/osr_output_device.cc",
"atom/browser/osr/osr_output_device.h",
"atom/browser/osr/osr_render_widget_host_view.cc",
"atom/browser/osr/osr_render_widget_host_view.h",
"atom/browser/osr/osr_render_widget_host_view_mac.mm",
"atom/browser/osr/osr_view_proxy.cc",
"atom/browser/osr/osr_view_proxy.h",
"atom/browser/osr/osr_web_contents_view.cc",
"atom/browser/osr/osr_web_contents_view.h",
"atom/browser/osr/osr_web_contents_view_mac.mm",
]
deps += [
"//ui/compositor",
"//components/viz/service",
]
}
if (enable_desktop_capturer) {
sources += [
"atom/browser/api/atom_api_desktop_capturer.cc",
"atom/browser/api/atom_api_desktop_capturer.h",
]
}
if (is_mac) {
libs = [
"Squirrel.framework",
"ReactiveCocoa.framework",
"Mantle.framework",
]
cflags_objcc = [
"-F", rebase_path("external_binaries", root_build_dir)
]
if (true) { # !is_mas_build
# ReactiveCocoa which is used by Squirrel requires using __weak.
cflags_objcc += [ "-fobjc-weak" ]
}
}
if (is_linux) {
sources += filenames_gypi.lib_sources_linux
sources += filenames_gypi.lib_sources_nss
}
}
if (is_mac) {
electron_framework_name = electron_product_name + " Framework"
electron_helper_name = electron_product_name + " Helper"
electron_framework_version = "A"
electron_mac_bundle_id = "com.$electron_company_abbr.$electron_project_name"
mac_xib_bundle_data("electron_xibs") {
sources = [ "atom/common/resources/mac/MainMenu.xib" ]
}
bundle_data("electron_framework_resources") {
public_deps = [
"//content/shell:pak",
":electron_locales",
]
sources = [
"$root_out_dir/content_shell.pak",
]
if (icu_use_data_file) {
sources += [ "$root_out_dir/icudtl.dat" ]
public_deps += [ "//third_party/icu:icudata" ]
}
if (v8_use_external_startup_data) {
sources += [
"$root_out_dir/natives_blob.bin",
"$root_out_dir/snapshot_blob.bin",
]
public_deps += [ "//v8" ]
}
outputs = [
"{{bundle_resources_dir}}/{{source_file_part}}",
]
}
bundle_data("electron_framework_libraries") {
public_deps = [ "build/node" ]
sources = [
"$root_out_dir/libnode.dylib"
]
outputs = [
"{{bundle_contents_dir}}/Libraries/{{source_file_part}}"
]
}
bundle_data("electron_framework_helpers") {
sources = [
"$root_out_dir/crashpad_handler",
]
outputs = [
"{{bundle_resources_dir}}/{{source_file_part}}",
]
public_deps = [
"//third_party/crashpad/crashpad/handler:crashpad_handler",
]
}
mac_framework_bundle("electron_framework") {
output_name = electron_framework_name
framework_version = electron_framework_version
framework_contents = [ "Resources" ]
public_deps = [ ":electron_lib" ]
deps = [
"//base",
"//base:i18n",
":electron_framework_helpers",
":electron_framework_libraries",
":electron_framework_resources",
":electron_xibs",
]
info_plist = "atom/common/resources/mac/Info.plist"
extra_substitutions = [
"ATOM_BUNDLE_ID=$electron_mac_bundle_id.framework",
]
include_dirs = [
".",
]
sources = filenames_gypi.framework_sources
libs = [
"Carbon.framework",
"QuartzCore.framework",
"Quartz.framework",
"Security.framework",
"SecurityInterface.framework",
"ServiceManagement.framework",
"StoreKit.framework",
]
ldflags = [
"-F", rebase_path("external_binaries", root_build_dir),
"-Wl,-install_name,@rpath/$output_name.framework/$output_name",
"-rpath",
"@loader_path/Libraries",
]
if (is_component_build) {
ldflags += [
"-rpath",
"@executable_path/../../../../../.."
]
}
}
mac_app_bundle("electron_helper_app") {
output_name = electron_helper_name
deps = [ ":electron_framework+link" ]
sources = filenames_gypi.app_sources
include_dirs = [ "." ]
info_plist = "atom/renderer/resources/mac/Info.plist"
extra_substitutions = [
"ATOM_BUNDLE_ID=$electron_mac_bundle_id.helper",
]
ldflags = [
"-rpath",
"@executable_path/../../..",
]
}
bundle_data("electron_app_framework_bundle_data") {
sources = [
"$root_out_dir/$electron_framework_name.framework",
"$root_out_dir/$electron_helper_name.app",
"external_binaries/Squirrel.framework",
"external_binaries/ReactiveCocoa.framework",
"external_binaries/Mantle.framework",
]
outputs = [
"{{bundle_contents_dir}}/Frameworks/{{source_file_part}}",
]
public_deps = [
":electron_framework+link",
":electron_helper_app",
]
}
bundle_data("electron_app_resources") {
public_deps = [
":js2asar",
":app2asar",
]
sources = [
"$root_out_dir/resources/electron.asar",
"$root_out_dir/resources/default_app.asar",
]
outputs = [
"{{bundle_resources_dir}}/{{source_file_part}}"
]
}
repack_locales("electron_locales") {
source_patterns = [
"${root_gen_dir}/content/app/strings/content_strings_",
]
deps = [
"//content/app/strings",
]
input_locales = locales
if (is_mac) {
output_locales = locales_as_mac_outputs
} else {
output_locales = locales
}
if (is_mac) {
output_dir = "$root_gen_dir/repack"
copy_data_to_bundle = true
} else {
output_dir = root_out_dir
}
}
mac_app_bundle("electron_app") {
output_name = electron_product_name
sources = filenames_gypi.app_sources
include_dirs = [ "." ]
deps = [
":electron_app_framework_bundle_data",
":electron_app_resources",
]
info_plist = "atom/browser/resources/mac/Info.plist"
extra_substitutions = [
"ATOM_BUNDLE_ID=$electron_mac_bundle_id",
]
ldflags = [
"-rpath",
"@executable_path/../Frameworks",
]
}
}
if (is_linux) {
executable("electron_app") {
output_name = electron_project_name
sources = filenames_gypi.app_sources
include_dirs = [ "." ]
deps = [
":app2asar",
":electron_lib",
":js2asar",
"//build/config:exe_and_shlib_deps",
"//chrome:packed_resources",
"//content/shell:copy_shell_resources",
"//content/shell:pak",
"//third_party/WebKit/public:image_resources",
"//ui/strings",
]
}
}

View File

@@ -1,4 +1,4 @@
# Contributor Covenant Code of Conduct:
# Contributor Covenant Code of Conduct
## Our Pledge
@@ -34,13 +34,13 @@ This Code of Conduct applies both within project spaces and in public spaces whe
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [coc@electronjs.org](mailto:coc@electronjs.org). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [electron@github.com](mailto:electron@github.com). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor-Covenant][homepage], version 1.4, available at [https://contributor-covenant.org/version/1/4][version]
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: https://contributor-covenant.org
[version]: https://contributor-covenant.org/version/1/4/
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

View File

@@ -1,60 +1,79 @@
# Contributing to Electron
:memo: Available Translations: [Korean](https://github.com/electron/electron/tree/master/docs-translations/ko-KR/project/CONTRIBUTING.md) | [Simplified Chinese](https://github.com/electron/electron/tree/master/docs-translations/zh-CN/project/CONTRIBUTING.md) | [Brazilian Portuguese](https://github.com/electron/electron/tree/master/docs-translations/pt-BR/project/CONTRIBUTING.md) | [Dutch](https://github.com/electron/electron/tree/master/docs-translations/nl/project/CONTRIBUTING.md)
:+1::tada: First off, thanks for taking the time to contribute! :tada::+1:
This project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDUCT.md).
By participating, you are expected to uphold this code. Please report unacceptable
behavior to coc@electronjs.org.
behavior to electron@github.com.
The following is a set of guidelines for contributing to Electron.
These are just guidelines, not rules, use your best judgment and feel free to
propose changes to this document in a pull request.
## [Issues](https://electronjs.org/docs/development/issues)
## Submitting Issues
Issues are created [here](https://github.com/electron/electron/issues/new).
* You can create an issue [here](https://github.com/electron/electron/issues/new),
but before doing that please read the notes below and include as many details as
possible with your report. If you can, please include:
* The version of Electron you are using
* The operating system you are using
* If applicable, what you were doing when the issue arose and what you
expected to happen
* Other things that will help resolve your issue:
* Screenshots and animated GIFs
* Error output that appears in your terminal, dev tools or as an alert
* Perform a [cursory search](https://github.com/electron/electron/issues?utf8=✓&q=is%3Aissue+)
to see if a similar issue has already been submitted
* [How to Contribute in Issues](https://electronjs.org/docs/development/issues#how-to-contribute-in-issues)
* [Asking for General Help](https://electronjs.org/docs/development/issues#asking-for-general-help)
* [Submitting a Bug Report](https://electronjs.org/docs/development/issues#submitting-a-bug-report)
* [Triaging a Bug Report](https://electronjs.org/docs/development/issues#triaging-a-bug-report)
* [Resolving a Bug Report](https://electronjs.org/docs/development/issues#resolving-a-bug-report)
## Submitting Pull Requests
### Issue Maintenance and Closure
* If an issue is inactive for 45 days (no activity of any kind), it will be
marked for closure with `stale`.
* If after this label is applied, no further activity occurs in the next 7 days,
the issue will be closed.
* If an issue has been closed and you still feel it's relevant, feel free to
ping a maintainer or add a comment!
* Include screenshots and animated GIFs in your pull request whenever possible.
* Follow the JavaScript, C++, and Python [coding style defined in docs](/docs/development/coding-style.md).
* Write documentation in [Markdown](https://daringfireball.net/projects/markdown).
See the [Documentation Styleguide](/docs/styleguide.md).
* Use short, present tense commit messages. See [Commit Message Styleguide](#git-commit-messages).
## [Pull Requests](https://electronjs.org/docs/development/pull-requests)
## Styleguides
Pull Requests are the way concrete changes are made to the code, documentation,
dependencies, and tools contained in the `electron/electron` repository.
### General Code
* [Setting up your local environment](https://electronjs.org/docs/development/pull-requests#setting-up-your-local-environment)
* [Step 1: Fork](https://electronjs.org/docs/development/pull-requests#step-1-fork)
* [Step 2: Build](https://electronjs.org/docs/development/pull-requests#step-2-build)
* [Step 3: Branch](https://electronjs.org/docs/development/pull-requests#step-3-branch)
* [The Process of Making Changes](https://electronjs.org/docs/development/pull-requests#the-process-of-making-changes)
* [Step 4: Code](https://electronjs.org/docs/development/pull-requests#step-4-code)
* [Step 5: Commit](https://electronjs.org/docs/development/pull-requests#step-5-commit)
* [Commit message guidelines](https://electronjs.org/docs/development/pull-requests#commit-message-guidelines)
* [Step 6: Rebase](https://electronjs.org/docs/development/pull-requests#step-6-rebase)
* [Step 7: Test](https://electronjs.org/docs/development/pull-requests#step-7-test)
* [Step 8: Push](https://electronjs.org/docs/development/pull-requests#step-8-push)
* [Step 8: Opening the Pull Request](https://electronjs.org/docs/development/pull-requests#step-8-opening-the-pull-request)
* [Step 9: Discuss and Update](#step-9-discuss-and-update)
* [Approval and Request Changes Workflow](https://electronjs.org/docs/development/pull-requests#approval-and-request-changes-workflow)
* [Step 10: Landing](https://electronjs.org/docs/development/pull-requests#step-10-landing)
* [Continuous Integration Testing](https://electronjs.org/docs/development/pull-requests#continuous-integration-testing)
* End files with a newline.
* Place requires in the following order:
* Built in Node Modules (such as `path`)
* Built in Electron Modules (such as `ipc`, `app`)
* Local Modules (using relative paths)
* Place class properties in the following order:
* Class methods and properties (methods starting with a `@`)
* Instance methods and properties
* Avoid platform-dependent code:
* Use `path.join()` to concatenate filenames.
* Use `os.tmpdir()` rather than `/tmp` when you need to reference the
temporary directory.
* Using a plain `return` when returning explicitly at the end of a function.
* Not `return null`, `return undefined`, `null`, or `undefined`
## Style Guides
### Git Commit Messages
See [Coding Style](https://electronjs.org/docs/development/coding-style) for information about which standards Electron adheres to in different parts of its codebase.
## Further Reading
For more in-depth guides on developing Electron, see
[/docs/development](/docs/development/README.md)
* Use the present tense ("Add feature" not "Added feature")
* Use the imperative mood ("Move cursor to..." not "Moves cursor to...")
* Limit the first line to 72 characters or less
* Reference issues and pull requests liberally
* When only changing documentation, include `[ci skip]` in the commit description
* Consider starting the commit message with an applicable emoji:
* :art: `:art:` when improving the format/structure of the code
* :racehorse: `:racehorse:` when improving performance
* :non-potable_water: `:non-potable_water:` when plugging memory leaks
* :memo: `:memo:` when writing docs
* :penguin: `:penguin:` when fixing something on Linux
* :apple: `:apple:` when fixing something on macOS
* :checkered_flag: `:checkered_flag:` when fixing something on Windows
* :bug: `:bug:` when fixing a bug
* :fire: `:fire:` when removing code or files
* :green_heart: `:green_heart:` when fixing the CI build
* :white_check_mark: `:white_check_mark:` when adding tests
* :lock: `:lock:` when dealing with security
* :arrow_up: `:arrow_up:` when upgrading dependencies
* :arrow_down: `:arrow_down:` when downgrading dependencies
* :shirt: `:shirt:` when removing linter warnings

73
DEPS
View File

@@ -1,73 +0,0 @@
vars = {
'chromium_version':
'63.0.3239.150',
'libchromiumcontent_revision':
'61d71f3f150c3ff5025560dee254a53313bfbaf6',
'node_version':
'v9.7.0-33-g538a5023af',
'native_mate_revision':
'4cd7d113915de0cc08e9a218be35bff9c7361906',
'chromium_git':
'https://chromium.googlesource.com',
'electron_git':
'https://github.com/electron',
}
deps = {
'src':
(Var("chromium_git")) + '/chromium/src.git@' + (Var("chromium_version")),
'src/libchromiumcontent':
(Var("electron_git")) + '/libchromiumcontent.git@' + (Var("libchromiumcontent_revision")),
'src/third_party/electron_node':
(Var("electron_git")) + '/node.git@' + (Var("node_version")),
'src/third_party/native_mate':
(Var("electron_git")) + '/native-mate.git@' + (Var("native_mate_revision")),
}
hooks = [
{
'action': [
'src/libchromiumcontent/script/apply-patches'
],
'pattern':
'src/libchromiumcontent',
'name':
'patch_chromium'
},
{
'action': [
'src/electron/script/update-external-binaries.py'
],
'pattern':
'src/electron/script/update-external-binaries.py',
'name':
'electron_external_binaries'
},
{
'action': [
'bash',
'-c',
# NOTE(nornagon): this ridiculous {{}} stuff is because these strings get
# variable-substituted twice by gclient.
'echo -e "#\\n{{{{\'variables\':{{{{}}}}}}}}" > src/third_party/electron_node/config.gypi',
],
'pattern': 'src/third_party/electron_node',
'name': 'touch_node_config_gypi'
},
{
'action': [
'bash',
'-c',
'cd src/electron; npm install',
],
'pattern': 'src/electron/package.json',
'name': 'electron_npm_deps'
},
]
recursedeps = [
'src',
'src/libchromiumcontent',
]

View File

@@ -1,24 +0,0 @@
FROM electronbuilds/libchromiumcontent:0.0.4
USER root
# Set up HOME directory
ENV HOME=/home
RUN chmod a+rwx /home
# Install node.js
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash -
RUN apt-get install -y nodejs
# Install wget used by crash reporter
RUN apt-get install -y wget
# Install python-dbusmock
RUN apt-get install -y python-dbusmock
# Install libnotify
RUN apt-get install -y libnotify-bin
# Add xvfb init script
ADD tools/xvfb-init.sh /etc/init.d/xvfb
RUN chmod a+x /etc/init.d/xvfb

View File

@@ -1,35 +0,0 @@
FROM multiarch/debian-debootstrap:arm64-jessie
RUN apt-get update && apt-get install -y\
bison \
build-essential \
clang \
curl \
gperf \
libasound2 \
libasound2-dev \
libcap-dev \
libcups2-dev \
libdbus-1-dev \
libgconf-2-4 \
libgconf2-dev \
libgnome-keyring-dev \
libgtk-3-0 \
libgtk-3-dev \
libnotify-bin \
libnotify-dev \
libnss3 \
libnss3-dev \
libx11-xcb-dev \
libxss1 \
libxtst-dev \
libxtst6 \
python-dbusmock \
wget \
xvfb
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

View File

@@ -1,63 +0,0 @@
FROM arm64v8/ubuntu:16.04
RUN groupadd --gid 1000 builduser \
&& useradd --uid 1000 --gid builduser --shell /bin/bash --create-home builduser
RUN groupadd --gid 114 jenkins \
&& useradd --uid 110 --gid jenkins --shell /bin/bash --create-home jenkins
# Set up TEMP directory
ENV TEMP=/tmp
RUN chmod a+rwx /tmp
RUN apt-get update && apt-get install -y\
bison \
build-essential \
clang \
curl \
gperf \
git \
libasound2 \
libasound2-dev \
libcap-dev \
libcups2-dev \
libdbus-1-dev \
libgconf-2-4 \
libgconf2-dev \
libgnome-keyring-dev \
libgtk2.0-0 \
libgtk2.0-dev \
libgtk-3-0 \
libgtk-3-dev \
libnotify-dev \
libnss3 \
libnss3-dev \
libx11-xcb-dev \
libxss1 \
libxtst-dev \
libxtst6 \
lsb-release \
locales \
ninja \
python-setuptools \
python-pip \
python-dbusmock \
wget \
xvfb
# Install node.js
RUN curl -sL https://deb.nodesource.com/setup_8.x | bash -
RUN apt-get update && apt-get install -y nodejs
# Install crcmod
RUN pip install -U crcmod
ADD tools/xvfb-init.sh /etc/init.d/xvfb
RUN chmod a+x /etc/init.d/xvfb
# Install ninja in /usr/local
RUN cd /usr/local && git clone https://github.com/martine/ninja.git -b v1.5.3
RUN cd /usr/local/ninja && ./configure.py --bootstrap
USER builduser
WORKDIR /home/builduser

View File

@@ -1,36 +0,0 @@
FROM multiarch/debian-debootstrap:armhf-jessie
RUN apt-get update && apt-get install -y\
bison \
build-essential \
clang \
curl \
gperf \
libasound2 \
libasound2-dev \
libcap-dev \
libcups2-dev \
libdbus-1-dev \
libgconf-2-4 \
libgconf2-dev \
libgnome-keyring-dev \
libgtk-3-0 \
libgtk-3-dev \
libnotify-bin \
libnotify-dev \
libnss3 \
libnss3-dev \
libx11-xcb-dev \
libxss1 \
libxtst-dev \
libxtst6 \
python-dbusmock \
git \
wget \
xvfb
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

View File

@@ -1,23 +0,0 @@
FROM electronbuilds/libchromiumcontent:0.0.4
USER root
# Install node.js
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash -
RUN apt-get install -y nodejs
# Install wget used by crash reporter
RUN apt-get install -y wget
# Install python-dbusmock
RUN apt-get install -y python-dbusmock
# Install libnotify
RUN apt-get install -y libnotify-bin
# Add xvfb init script
ADD tools/xvfb-init.sh /etc/init.d/xvfb
RUN chmod a+x /etc/init.d/xvfb
USER builduser
WORKDIR /home/builduser

View File

@@ -10,9 +10,6 @@ Thanks for opening an issue! A few things to keep in mind:
* Electron version:
* Operating system:
<!-- If this used to work -->
* Last known working Electron version:
### Expected behavior
<!-- What do you think should happen? -->

44
Jenkinsfile vendored Normal file
View File

@@ -0,0 +1,44 @@
pipeline {
agent none
stages {
stage('Build') {
parallel {
stage('electron-osx-x64') {
agent {
label 'osx'
}
steps {
sh 'script/bootstrap.py --target_arch=x64 --dev'
sh 'npm run lint'
sh 'script/build.py -c D'
sh 'script/test.py --ci --rebuild_native_modules'
}
post {
always {
cleanWs()
}
}
}
stage('electron-mas-x64') {
agent {
label 'osx'
}
environment {
MAS_BUILD = '1'
}
steps {
sh 'script/bootstrap.py --target_arch=x64 --dev'
sh 'npm run lint'
sh 'script/build.py -c D'
sh 'script/test.py --ci --rebuild_native_modules'
}
post {
always {
cleanWs()
}
}
}
}
}
}
}

View File

@@ -1,4 +1,4 @@
Copyright (c) 2013-2018 GitHub Inc.
Copyright (c) 2013-2017 GitHub Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the

View File

@@ -1,26 +1,24 @@
[![Electron Logo](https://electronjs.org/images/electron-logo.svg)](https://electronjs.org)
[![Electron Logo](https://electron.atom.io/images/electron-logo.svg)](https://electron.atom.io/)
[![CircleCI Build Status](https://circleci.com/gh/electron/electron/tree/master.svg?style=shield)](https://circleci.com/gh/electron/electron/tree/master)
[![AppVeyor Build Status](https://windows-ci.electronjs.org/api/projects/status/nilyf07hcef14dvj/branch/master?svg=true)](https://windows-ci.electronjs.org/project/AppVeyor/electron/branch/master)
[![Travis Build Status](https://travis-ci.org/electron/electron.svg?branch=master)](https://travis-ci.org/electron/electron)
[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/bc56v83355fi3369/branch/master?svg=true)](https://ci.appveyor.com/project/electron-bot/electron/branch/master)
[![devDependency Status](https://david-dm.org/electron/electron/dev-status.svg)](https://david-dm.org/electron/electron?type=dev)
[![Join the Electron Community on Slack](https://atom-slack.herokuapp.com/badge.svg)](https://atom-slack.herokuapp.com/)
[![Join the Electron Community on Slack](http://atom-slack.herokuapp.com/badge.svg)](http://atom-slack.herokuapp.com/)
:memo: Available Translations: 🇨🇳 🇹🇼 🇧🇷 🇪🇸 🇰🇷 🇯🇵 🇷🇺 🇫🇷 🇹🇭 🇳🇱 🇹🇷 🇮🇩 🇺🇦 🇨🇿 🇮🇹.
View these docs in other languages at [electron/i18n](https://github.com/electron/i18n/tree/master/content/).
:memo: Available Translations: [Korean](https://github.com/electron/electron/tree/master/docs-translations/ko-KR/project/README.md) | [Simplified Chinese](https://github.com/electron/electron/tree/master/docs-translations/zh-CN/project/README.md) | [Brazilian Portuguese](https://github.com/electron/electron/tree/master/docs-translations/pt-BR/project/README.md) | [Traditional Chinese](https://github.com/electron/electron/tree/master/docs-translations/zh-TW/project/README.md) | [Spanish](https://github.com/electron/electron/tree/master/docs-translations/es/project/README.md) | [Turkish](https://github.com/electron/electron/tree/master/docs-translations/tr-TR/project/README.md) | [German](https://github.com/electron/electron/tree/master/docs-translations/de-DE/project/README.md)
The Electron framework lets you write cross-platform desktop applications
using JavaScript, HTML and CSS. It is based on [Node.js](https://nodejs.org/) and
[Chromium](https://www.chromium.org) and is used by the [Atom
editor](https://github.com/atom/atom) and many other [apps](https://electronjs.org/apps).
[Chromium](http://www.chromium.org) and is used by the [Atom
editor](https://github.com/atom/atom) and many other [apps](https://electron.atom.io/apps).
Follow [@ElectronJS](https://twitter.com/electronjs) on Twitter for important
announcements.
This project adheres to the Contributor Covenant
This project adheres to the Contributor Covenant
[code of conduct](https://github.com/electron/electron/tree/master/CODE_OF_CONDUCT.md).
By participating, you are expected to uphold this code. Please report unacceptable
behavior to [coc@electronjs.org](mailto:coc@electronjs.org).
behavior to [electron@github.com](mailto:electron@github.com).
## Installation
@@ -29,34 +27,34 @@ The preferred method is to install Electron as a development dependency in your
app:
```sh
npm install electron --save-dev [--save-exact]
npm install electron --save-dev --save-exact
```
The `--save-exact` flag is recommended for Electron prior to version 2, as it does not follow semantic
versioning. As of version 2.0.0, Electron follows semver, so you don't need `--save-exact` flag. For info on how to manage Electron versions in your apps, see
[Electron versioning](docs/tutorial/electron-versioning.md).
The `--save-exact` flag is recommended as Electron does not follow semantic
versioning. For info on how to manage Electron versions in your apps, see
[Electron versioning](https://electron.atom.io/docs/tutorial/electron-versioning/).
For more installation options and troubleshooting tips, see
[installation](docs/tutorial/installation.md).
[installation](https://electron.atom.io/docs/tutorial/installation/).
## Quick start
## Quick Start
Clone and run the
Clone and run the
[electron/electron-quick-start](https://github.com/electron/electron-quick-start)
repository to see a minimal Electron app in action:
```sh
```
git clone https://github.com/electron/electron-quick-start
cd electron-quick-start
npm install
npm start
```
## Resources for learning Electron
## Resources for Learning Electron
- [electronjs.org/docs](https://electronjs.org/docs) - all of Electron's documentation
- [electron.atom.io/docs](http://electron.atom.io/docs) - all of Electron's documentation
- [electron/electron-quick-start](https://github.com/electron/electron-quick-start) - a very basic starter Electron app
- [electronjs.org/community#boilerplates](https://electronjs.org/community#boilerplates) - sample starter apps created by the community
- [electron.atom.io/community/#boilerplates](http://electron.atom.io/community/#boilerplates) - sample starter apps created by the community
- [electron/simple-samples](https://github.com/electron/simple-samples) - small applications with ideas for taking them further
- [electron/electron-api-demos](https://github.com/electron/electron-api-demos) - an Electron app that teaches you how to use Electron
- [hokein/electron-sample-apps](https://github.com/hokein/electron-sample-apps) - small demo apps for the various Electron APIs
@@ -84,12 +82,36 @@ const child = proc.spawn(electron)
## Documentation Translations
Find documentation translations in [electron/i18n](https://github.com/electron/i18n).
- [Brazilian Portuguese](https://github.com/electron/electron/tree/master/docs-translations/pt-BR)
- [Korean](https://github.com/electron/electron/tree/master/docs-translations/ko-KR)
- [Japanese](https://github.com/electron/electron/tree/master/docs-translations/jp)
- [Spanish](https://github.com/electron/electron/tree/master/docs-translations/es)
- [Simplified Chinese](https://github.com/electron/electron/tree/master/docs-translations/zh-CN)
- [Traditional Chinese](https://github.com/electron/electron/tree/master/docs-translations/zh-TW)
- [Turkish](https://github.com/electron/electron/tree/master/docs-translations/tr-TR)
- [Thai](https://github.com/electron/electron/tree/master/docs-translations/th-TH)
- [Ukrainian](https://github.com/electron/electron/tree/master/docs-translations/uk-UA)
- [Russian](https://github.com/electron/electron/tree/master/docs-translations/ru-RU)
- [French](https://github.com/electron/electron/tree/master/docs-translations/fr-FR)
- [Indonesian](https://github.com/electron/electron/tree/master/docs-translations/id)
## Community
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).
You can ask questions and interact with the community in the following
locations:
- [`electron`](http://discuss.atom.io/c/electron) category on the Atom
forums
- `#atom-shell` channel on Freenode
- [`Atom`](http://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`](http://www.meetup.com/electron-kr/) *(Korean)*
- [`electron-jp`](https://electron-jp.slack.com) *(Japanese)*
- [`electron-tr`](http://electron-tr.herokuapp.com) *(Turkish)*
- [`electron-id`](https://electron-id.slack.com) *(Indonesia)*
Check out [awesome-electron](https://github.com/sindresorhus/awesome-electron)
for a community maintained list of useful example apps, tools and resources.
## License

View File

@@ -2,11 +2,8 @@
The Electron team and community take security bugs in Electron seriously. We appreciate your efforts to responsibly disclose your findings, and will make every effort to acknowledge your contributions.
To report a security issue, email [security@electronjs.org](mailto:security@electronjs.org) and include the word "SECURITY" in the subject line.
To report a security issue, email [electron@github.com](mailto:electron@github.com) and include the word "SECURITY" in the subject line.
The Electron team will send a response indicating the next steps in handling your report. After the initial reply to your report, the security team will keep you informed of the progress towards a fix and full announcement, and may ask for additional information or guidance.
Report security bugs in third-party modules to the person or team maintaining the module. You can also report a vulnerability through the [Node Security Project](https://nodesecurity.io/report).
## Learning More About Security
To learn more about securing an Electron application, please see the [security tutorial](docs/tutorial/security.md).

View File

@@ -1,71 +0,0 @@
build_cloud: electron-16
image: electron-16-vs2017-15.4.5
build_script:
- ps: >-
echo "Build worker image $env:APPVEYOR_BUILD_WORKER_IMAGE"
&"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe"
if(($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
}
}

25
appveyor.yml Normal file
View File

@@ -0,0 +1,25 @@
# appveyor file
# http://www.appveyor.com/docs/appveyor-yml
version: "{build}"
os: Visual Studio 2015
init:
- git config --global core.autocrlf input
platform:
- x86
- x64
install:
- cmd: SET PATH=C:\Program Files (x86)\MSBuild\14.0\bin\;%PATH%
- cmd: SET PATH=C:\python27;%PATH%
- cmd: python script/cibuild
branches:
only:
- master
# disable build and test phases
build: off
test: off

1
atom/CPPLINT.cfg Normal file
View File

@@ -0,0 +1 @@
filter=+build/include_alpha

View File

@@ -7,6 +7,7 @@
#include <string>
#include <vector>
#include "atom/common/atom_constants.h"
#include "atom/common/atom_version.h"
#include "atom/common/chrome_version.h"
#include "atom/common/options_switches.h"
@@ -18,20 +19,16 @@
#include "content/public/common/content_constants.h"
#include "content/public/common/pepper_plugin_info.h"
#include "content/public/common/user_agent.h"
#include "media/media_features.h"
#include "pdf/pdf.h"
#include "ppapi/shared_impl/ppapi_permissions.h"
#include "third_party/widevine/cdm/stub/widevine_cdm_version.h"
#include "ui/base/l10n/l10n_util.h"
#include "url/url_constants.h"
#if defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_LIBRARY_CDMS)
#if defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_PEPPER_CDMS)
#include "chrome/common/widevine_cdm_constants.h"
#endif
#if defined(ENABLE_PDF_VIEWER)
#include "atom/common/atom_constants.h"
#include "pdf/pdf.h"
#endif // defined(ENABLE_PDF_VIEWER)
namespace atom {
namespace {
@@ -60,43 +57,59 @@ content::PepperPluginInfo CreatePepperFlashInfo(const base::FilePath& path,
flash_version_numbers.push_back("999");
// E.g., "Shockwave Flash 10.2 r154":
plugin.description = plugin.name + " " + flash_version_numbers[0] + "." +
flash_version_numbers[1] + " r" +
flash_version_numbers[2];
flash_version_numbers[1] + " r" + flash_version_numbers[2];
plugin.version = base::JoinString(flash_version_numbers, ".");
content::WebPluginMimeType swf_mime_type(content::kFlashPluginSwfMimeType,
content::kFlashPluginSwfExtension,
content::kFlashPluginSwfDescription);
content::WebPluginMimeType swf_mime_type(
content::kFlashPluginSwfMimeType,
content::kFlashPluginSwfExtension,
content::kFlashPluginSwfDescription);
plugin.mime_types.push_back(swf_mime_type);
content::WebPluginMimeType spl_mime_type(content::kFlashPluginSplMimeType,
content::kFlashPluginSplExtension,
content::kFlashPluginSplDescription);
content::WebPluginMimeType spl_mime_type(
content::kFlashPluginSplMimeType,
content::kFlashPluginSplExtension,
content::kFlashPluginSplDescription);
plugin.mime_types.push_back(spl_mime_type);
return plugin;
}
#if defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_LIBRARY_CDMS)
#if defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_PEPPER_CDMS)
content::PepperPluginInfo CreateWidevineCdmInfo(const base::FilePath& path,
const std::string& version) {
content::PepperPluginInfo widevine_cdm;
widevine_cdm.is_out_of_process = true;
widevine_cdm.path = path;
widevine_cdm.name = kWidevineCdmDisplayName;
widevine_cdm.description =
kWidevineCdmDescription + std::string(" (version: ") + version + ")";
widevine_cdm.description = kWidevineCdmDescription +
std::string(" (version: ") +
version + ")";
widevine_cdm.version = version;
content::WebPluginMimeType widevine_cdm_mime_type(
kWidevineCdmPluginMimeType, kWidevineCdmPluginExtension,
kWidevineCdmPluginMimeType,
kWidevineCdmPluginExtension,
kWidevineCdmPluginMimeTypeDescription);
// Add the supported codecs as if they came from the component manifest.
std::vector<std::string> codecs;
codecs.push_back(kCdmSupportedCodecVp8);
codecs.push_back(kCdmSupportedCodecVp9);
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
codecs.push_back(kCdmSupportedCodecAvc1);
#endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
std::string codec_string = base::JoinString(
codecs, std::string(1, kCdmSupportedCodecsValueDelimiter));
widevine_cdm_mime_type.additional_param_names.push_back(
base::ASCIIToUTF16(kCdmSupportedCodecsParamName));
widevine_cdm_mime_type.additional_param_values.push_back(
base::ASCIIToUTF16(codec_string));
widevine_cdm.mime_types.push_back(widevine_cdm_mime_type);
widevine_cdm.permissions = kWidevineCdmPluginPermissions;
return widevine_cdm;
}
#endif // defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_LIBRARY_CDMS)
#endif
#if defined(ENABLE_PDF_VIEWER)
void ComputeBuiltInPlugins(std::vector<content::PepperPluginInfo>* plugins) {
content::PepperPluginInfo pdf_info;
pdf_info.is_internal = true;
@@ -115,68 +128,70 @@ void ComputeBuiltInPlugins(std::vector<content::PepperPluginInfo>* plugins) {
pdf_info.permissions = ppapi::PERMISSION_PRIVATE | ppapi::PERMISSION_DEV;
plugins->push_back(pdf_info);
}
#endif // defined(ENABLE_PDF_VIEWER)
void ConvertStringWithSeparatorToVector(std::vector<std::string>* vec,
const char* separator,
const char* cmd_switch) {
auto* command_line = base::CommandLine::ForCurrentProcess();
auto command_line = base::CommandLine::ForCurrentProcess();
auto string_with_separator = command_line->GetSwitchValueASCII(cmd_switch);
if (!string_with_separator.empty())
*vec = base::SplitString(string_with_separator, separator,
base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
base::TRIM_WHITESPACE,
base::SPLIT_WANT_NONEMPTY);
}
} // namespace
void AddPepperFlashFromCommandLine(
std::vector<content::PepperPluginInfo>* plugins) {
auto* command_line = base::CommandLine::ForCurrentProcess();
base::FilePath flash_path =
command_line->GetSwitchValuePath(switches::kPpapiFlashPath);
auto command_line = base::CommandLine::ForCurrentProcess();
base::FilePath flash_path = command_line->GetSwitchValuePath(
switches::kPpapiFlashPath);
if (flash_path.empty())
return;
auto flash_version =
command_line->GetSwitchValueASCII(switches::kPpapiFlashVersion);
auto flash_version = command_line->GetSwitchValueASCII(
switches::kPpapiFlashVersion);
plugins->push_back(CreatePepperFlashInfo(flash_path, flash_version));
}
#if defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_LIBRARY_CDMS)
#if defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_PEPPER_CDMS)
void AddWidevineCdmFromCommandLine(
std::vector<content::PepperPluginInfo>* plugins) {
auto* command_line = base::CommandLine::ForCurrentProcess();
base::FilePath widevine_cdm_path =
command_line->GetSwitchValuePath(switches::kWidevineCdmPath);
auto command_line = base::CommandLine::ForCurrentProcess();
base::FilePath widevine_cdm_path = command_line->GetSwitchValuePath(
switches::kWidevineCdmPath);
if (widevine_cdm_path.empty())
return;
if (!base::PathExists(widevine_cdm_path))
return;
auto widevine_cdm_version =
command_line->GetSwitchValueASCII(switches::kWidevineCdmVersion);
auto widevine_cdm_version = command_line->GetSwitchValueASCII(
switches::kWidevineCdmVersion);
if (widevine_cdm_version.empty())
return;
plugins->push_back(
CreateWidevineCdmInfo(widevine_cdm_path, widevine_cdm_version));
plugins->push_back(CreateWidevineCdmInfo(widevine_cdm_path,
widevine_cdm_version));
}
#endif // defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_LIBRARY_CDMS)
#endif
AtomContentClient::AtomContentClient() {}
AtomContentClient::AtomContentClient() {
}
AtomContentClient::~AtomContentClient() {}
AtomContentClient::~AtomContentClient() {
}
std::string AtomContentClient::GetProduct() const {
return "Chrome/" CHROME_VERSION_STRING;
}
std::string AtomContentClient::GetUserAgent() const {
return content::BuildUserAgentFromProduct("Chrome/" CHROME_VERSION_STRING
" " ATOM_PRODUCT_NAME
"/" ATOM_VERSION_STRING);
return content::BuildUserAgentFromProduct(
"Chrome/" CHROME_VERSION_STRING " "
ATOM_PRODUCT_NAME "/" ATOM_VERSION_STRING);
}
base::string16 AtomContentClient::GetLocalizedString(int message_id) const {
@@ -201,44 +216,10 @@ void AtomContentClient::AddAdditionalSchemes(Schemes* schemes) {
void AtomContentClient::AddPepperPlugins(
std::vector<content::PepperPluginInfo>* plugins) {
AddPepperFlashFromCommandLine(plugins);
#if defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_LIBRARY_CDMS)
#if defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_PEPPER_CDMS)
AddWidevineCdmFromCommandLine(plugins);
#endif // defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_LIBRARY_CDMS)
#if defined(ENABLE_PDF_VIEWER)
#endif
ComputeBuiltInPlugins(plugins);
#endif // defined(ENABLE_PDF_VIEWER)
}
void AtomContentClient::AddContentDecryptionModules(
std::vector<content::CdmInfo>* cdms,
std::vector<media::CdmHostFilePath>* cdm_host_file_paths) {
#if defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_LIBRARY_CDMS)
auto command_line = base::CommandLine::ForCurrentProcess();
base::FilePath widevine_cdm_path =
command_line->GetSwitchValuePath(switches::kWidevineCdmPath);
if (widevine_cdm_path.empty())
return;
if (!base::PathExists(widevine_cdm_path))
return;
auto widevine_cdm_version =
command_line->GetSwitchValueASCII(switches::kWidevineCdmVersion);
if (widevine_cdm_version.empty())
return;
std::vector<media::VideoCodec> supported_video_codecs;
supported_video_codecs.push_back(media::VideoCodec::kCodecVP8);
supported_video_codecs.push_back(media::VideoCodec::kCodecVP9);
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
supported_video_codecs.push_back(media::VideoCodec::kCodecH264);
#endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
content::CdmRegistry::GetInstance()->RegisterCdm(
content::CdmInfo(kWidevineCdmDisplayName, kWidevineCdmGuid,
base::Version(widevine_cdm_version), widevine_cdm_path,
kWidevineCdmFileSystemId, supported_video_codecs, false,
kWidevineKeySystem, false));
#endif // defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_LIBRARY_CDMS)
}
} // namespace atom

View File

@@ -16,7 +16,7 @@ namespace atom {
class AtomContentClient : public brightray::ContentClient {
public:
AtomContentClient();
~AtomContentClient() override;
virtual ~AtomContentClient();
protected:
// content::ContentClient:
@@ -26,9 +26,6 @@ class AtomContentClient : public brightray::ContentClient {
void AddAdditionalSchemes(Schemes* schemes) override;
void AddPepperPlugins(
std::vector<content::PepperPluginInfo>* plugins) override;
void AddContentDecryptionModules(
std::vector<content::CdmInfo>* cdms,
std::vector<media::CdmHostFilePath>* cdm_host_file_paths) override;
private:
DISALLOW_COPY_AND_ASSIGN(AtomContentClient);

View File

@@ -9,13 +9,11 @@
#if defined(OS_MACOSX)
extern "C" {
__attribute__((visibility("default"))) int AtomMain(int argc, char* argv[]);
__attribute__((visibility("default")))
int AtomMain(int argc, char* argv[]);
#ifdef ENABLE_RUN_AS_NODE
__attribute__((visibility("default"))) int AtomInitializeICUandStartNode(
int argc,
char* argv[]);
#endif
__attribute__((visibility("default")))
int AtomInitializeICUandStartNode(int argc, char *argv[]);
}
#endif // OS_MACOSX

View File

@@ -14,6 +14,7 @@
#include "brightray/common/mac/main_application_bundle.h"
#include "content/public/app/content_main.h"
#if defined(OS_MACOSX)
int AtomMain(int argc, char* argv[]) {
atom::AtomMainDelegate delegate;
content::ContentMainParams params(&delegate);
@@ -23,8 +24,7 @@ int AtomMain(int argc, char* argv[]) {
return content::ContentMain(params);
}
#ifdef ENABLE_RUN_AS_NODE
int AtomInitializeICUandStartNode(int argc, char* argv[]) {
int AtomInitializeICUandStartNode(int argc, char *argv[]) {
base::AtExitManager atexit_manager;
base::mac::ScopedNSAutoreleasePool pool;
base::mac::SetOverrideFrameworkBundlePath(
@@ -35,4 +35,4 @@ int AtomInitializeICUandStartNode(int argc, char* argv[]) {
base::i18n::InitializeICU();
return atom::NodeMain(argc, argv);
}
#endif
#endif // OS_MACOSX

View File

@@ -1,12 +0,0 @@
#import <Cocoa/Cocoa.h>
int main(int argc, char* argv[]) {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSArray* pathComponents = [[[NSBundle mainBundle] bundlePath] pathComponents];
pathComponents = [pathComponents
subarrayWithRange:NSMakeRange(0, [pathComponents count] - 4)];
NSString* path = [NSString pathWithComponents:pathComponents];
[[NSWorkspace sharedWorkspace] launchApplication:path];
[pool drain];
return 0;
}

View File

@@ -10,7 +10,6 @@
#if defined(OS_WIN)
#include <windows.h> // windows.h must be included first
#include <atlbase.h> // ensures that ATL statics like `_AtlWinModule` are initialized (it's an issue in static debug build)
#include <shellapi.h>
#include <shellscalingapi.h>
#include <tchar.h>
@@ -24,7 +23,7 @@
#include "base/win/windows_version.h"
#include "content/public/app/sandbox_helper_win.h"
#include "sandbox/win/src/sandbox_types.h"
#elif defined(OS_LINUX) // defined(OS_WIN)
#elif defined(OS_LINUX) // defined(OS_WIN)
#include "atom/app/atom_main_delegate.h" // NOLINT
#include "content/public/app/content_main.h"
#else // defined(OS_LINUX)
@@ -38,11 +37,8 @@
namespace {
#ifdef ENABLE_RUN_AS_NODE
const char kRunAsNode[] = "ELECTRON_RUN_AS_NODE";
#endif
const char* kRunAsNode = "ELECTRON_RUN_AS_NODE";
#if defined(ENABLE_RUN_AS_NODE) || defined(OS_WIN)
bool IsEnvSet(const char* name) {
#if defined(OS_WIN)
size_t required_size;
@@ -53,7 +49,6 @@ bool IsEnvSet(const char* name) {
return indicator && indicator[0] != '\0';
#endif
}
#endif
} // namespace
@@ -93,11 +88,7 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
}
#endif
#ifdef ENABLE_RUN_AS_NODE
bool run_as_node = IsEnvSet(kRunAsNode);
#else
bool run_as_node = false;
#endif
// Make sure the output is printed to console.
if (run_as_node || !IsEnvSet("ELECTRON_NO_ATTACH_CONSOLE"))
@@ -117,10 +108,11 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
// from within the CRT's atexit facility, ensuring the heap functions are
// still active. The second invocation from the OS loader will be a no-op.
extern void NTAPI OnThreadExit(PVOID module, DWORD reason, PVOID reserved);
atexit([]() { OnThreadExit(nullptr, DLL_THREAD_DETACH, nullptr); });
atexit([]() {
OnThreadExit(nullptr, DLL_THREAD_DETACH, nullptr);
});
#endif
#ifdef ENABLE_RUN_AS_NODE
if (run_as_node) {
std::vector<char*> argv(arguments.argc);
std::transform(
@@ -132,10 +124,7 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
auto ret = atom::NodeMain(argv.size(), argv.data());
std::for_each(argv.begin(), argv.end(), free);
return ret;
}
#endif
if (IsEnvSet("ELECTRON_INTERNAL_CRASH_SERVICE")) {
} else if (IsEnvSet("ELECTRON_INTERNAL_CRASH_SERVICE")) {
return crash_service::Main(cmd);
}
@@ -156,13 +145,11 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
#elif defined(OS_LINUX) // defined(OS_WIN)
int main(int argc, char* argv[]) {
#ifdef ENABLE_RUN_AS_NODE
if (IsEnvSet(kRunAsNode)) {
base::i18n::InitializeICU();
base::AtExitManager atexit_manager;
return atom::NodeMain(argc, argv);
}
#endif
atom::AtomMainDelegate delegate;
content::ContentMainParams params(&delegate);
@@ -175,11 +162,9 @@ int main(int argc, char* argv[]) {
#else // defined(OS_LINUX)
int main(int argc, char* argv[]) {
#ifdef ENABLE_RUN_AS_NODE
if (IsEnvSet(kRunAsNode)) {
return AtomInitializeICUandStartNode(argc, argv);
}
#endif
return AtomMain(argc, argv);
}

View File

@@ -21,19 +21,9 @@
#include "base/logging.h"
#include "chrome/common/chrome_paths.h"
#include "content/public/common/content_switches.h"
#include "ipc/ipc_features.h"
#include "services/service_manager/sandbox/switches.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#if BUILDFLAG(IPC_MESSAGE_LOG_ENABLED)
#define IPC_MESSAGE_MACROS_LOG_ENABLED
#include "content/public/common/content_ipc_logging.h"
#define IPC_LOG_TABLE_ADD_ENTRY(msg_id, logger) \
content::RegisterIPCLogger(msg_id, logger)
#include "atom/common/common_message_generator.h"
#endif
namespace atom {
namespace {
@@ -46,23 +36,22 @@ bool IsBrowserProcess(base::CommandLine* cmd) {
}
#if defined(OS_WIN)
void InvalidParameterHandler(const wchar_t*,
const wchar_t*,
const wchar_t*,
unsigned int,
uintptr_t) {
void InvalidParameterHandler(const wchar_t*, const wchar_t*, const wchar_t*,
unsigned int, uintptr_t) {
// noop.
}
#endif
} // namespace
AtomMainDelegate::AtomMainDelegate() {}
AtomMainDelegate::AtomMainDelegate() {
}
AtomMainDelegate::~AtomMainDelegate() {}
AtomMainDelegate::~AtomMainDelegate() {
}
bool AtomMainDelegate::BasicStartupComplete(int* exit_code) {
auto* command_line = base::CommandLine::ForCurrentProcess();
auto command_line = base::CommandLine::ForCurrentProcess();
logging::LoggingSettings settings;
#if defined(OS_WIN)
@@ -79,12 +68,12 @@ bool AtomMainDelegate::BasicStartupComplete(int* exit_code) {
#else
settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
#endif // defined(DEBUG)
#else // defined(OS_WIN)
#else // defined(OS_WIN)
settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
#endif // !defined(OS_WIN)
// Only enable logging when --enable-logging is specified.
auto env = base::Environment::Create();
std::unique_ptr<base::Environment> env(base::Environment::Create());
if (!command_line->HasSwitch(::switches::kEnableLogging) &&
!env->HasVar("ELECTRON_ENABLE_LOGGING")) {
settings.logging_dest = logging::LOG_NONE;
@@ -97,15 +86,9 @@ bool AtomMainDelegate::BasicStartupComplete(int* exit_code) {
logging::SetLogItems(true, false, true, false);
// Enable convient stack printing.
#if defined(DEBUG) && defined(OS_LINUX)
bool enable_stack_dumping = true;
#else
bool enable_stack_dumping = env->HasVar("ELECTRON_ENABLE_STACK_DUMPING");
#endif
#if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
// For 32bit ARM enabling stack printing would end up crashing.
// https://github.com/electron/electron/pull/11230#issuecomment-363232482
enable_stack_dumping = false;
#if defined(DEBUG) && defined(OS_LINUX)
enable_stack_dumping = true;
#endif
if (enable_stack_dumping)
base::debug::EnableInProcessStackDumping();
@@ -130,9 +113,14 @@ bool AtomMainDelegate::BasicStartupComplete(int* exit_code) {
void AtomMainDelegate::PreSandboxStartup() {
brightray::MainDelegate::PreSandboxStartup();
auto* command_line = base::CommandLine::ForCurrentProcess();
std::string process_type =
command_line->GetSwitchValueASCII(::switches::kProcessType);
// Set google API key.
std::unique_ptr<base::Environment> env(base::Environment::Create());
if (!env->HasVar("GOOGLE_API_KEY"))
env->SetVar("GOOGLE_API_KEY", GOOGLEAPIS_API_KEY);
auto command_line = base::CommandLine::ForCurrentProcess();
std::string process_type = command_line->GetSwitchValueASCII(
::switches::kProcessType);
// Only append arguments for browser process.
if (!IsBrowserProcess(command_line))
@@ -142,8 +130,7 @@ void AtomMainDelegate::PreSandboxStartup() {
if (command_line->HasSwitch(switches::kEnableSandbox)) {
// Disable setuid sandbox since it is not longer required on
// linux(namespace sandbox is available on most distros).
command_line->AppendSwitch(
service_manager::switches::kDisableSetuidSandbox);
command_line->AppendSwitch(::switches::kDisableSetuidSandbox);
} else {
// Disable renderer sandbox for most of node's functions.
command_line->AppendSwitch(::switches::kNoSandbox);
@@ -165,11 +152,11 @@ content::ContentBrowserClient* AtomMainDelegate::CreateContentBrowserClient() {
}
content::ContentRendererClient*
AtomMainDelegate::CreateContentRendererClient() {
AtomMainDelegate::CreateContentRendererClient() {
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableSandbox) ||
switches::kEnableSandbox) ||
!base::CommandLine::ForCurrentProcess()->HasSwitch(
::switches::kNoSandbox)) {
::switches::kNoSandbox)) {
renderer_client_.reset(new AtomSandboxedRendererClient);
} else {
renderer_client_.reset(new AtomRendererClient);
@@ -205,7 +192,7 @@ bool AtomMainDelegate::DelaySandboxInitialization(
std::unique_ptr<brightray::ContentClient>
AtomMainDelegate::CreateContentClient() {
return std::make_unique<AtomContentClient>();
return std::unique_ptr<brightray::ContentClient>(new AtomContentClient);
}
} // namespace atom

View File

@@ -15,7 +15,7 @@ namespace atom {
class AtomMainDelegate : public brightray::MainDelegate {
public:
AtomMainDelegate();
~AtomMainDelegate() override;
~AtomMainDelegate();
protected:
// content::ContentMainDelegate:
@@ -44,6 +44,7 @@ class AtomMainDelegate : public brightray::MainDelegate {
void SetUpBundleOverrides();
#endif
brightray::ContentClient content_client_;
std::unique_ptr<content::ContentBrowserClient> browser_client_;
std::unique_ptr<content::ContentRendererClient> renderer_client_;
std::unique_ptr<content::ContentUtilityClient> utility_client_;

View File

@@ -4,9 +4,9 @@
#include "atom/app/atom_main_delegate.h"
#include "base/mac/bundle_locations.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/mac/bundle_locations.h"
#include "base/mac/foundation_util.h"
#include "base/mac/scoped_nsautorelease_pool.h"
#include "base/path_service.h"
@@ -20,17 +20,16 @@ namespace atom {
namespace {
base::FilePath GetFrameworksPath() {
return brightray::MainApplicationBundlePath()
.Append("Contents")
.Append("Frameworks");
return brightray::MainApplicationBundlePath().Append("Contents")
.Append("Frameworks");
}
base::FilePath GetHelperAppPath(const base::FilePath& frameworks_path,
const std::string& name) {
return frameworks_path.Append(name + " Helper.app")
.Append("Contents")
.Append("MacOS")
.Append(name + " Helper");
.Append("Contents")
.Append("MacOS")
.Append(name + " Helper");
}
} // namespace
@@ -42,11 +41,11 @@ void AtomMainDelegate::OverrideFrameworkBundlePath() {
void AtomMainDelegate::OverrideChildProcessPath() {
base::FilePath frameworks_path = GetFrameworksPath();
base::FilePath helper_path =
GetHelperAppPath(frameworks_path, ATOM_PRODUCT_NAME);
base::FilePath helper_path = GetHelperAppPath(frameworks_path,
ATOM_PRODUCT_NAME);
if (!base::PathExists(helper_path))
helper_path =
GetHelperAppPath(frameworks_path, brightray::GetApplicationName());
helper_path = GetHelperAppPath(frameworks_path,
brightray::GetApplicationName());
if (!base::PathExists(helper_path))
LOG(FATAL) << "Unable to find helper app";
PathService::Override(content::CHILD_PROCESS_EXE, helper_path);

File diff suppressed because it is too large Load Diff

View File

@@ -14,3 +14,4 @@ bool CheckCommandLineArguments(int argc, base::CommandLine::CharType** argv);
} // namespace atom
#endif // ATOM_APP_COMMAND_LINE_ARGS_H_

View File

@@ -2,8 +2,6 @@
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifdef ENABLE_RUN_AS_NODE
#include "atom/app/node_main.h"
#include "atom/app/uv_task_runner.h"
@@ -12,10 +10,8 @@
#include "atom/common/api/atom_bindings.h"
#include "atom/common/crash_reporter/crash_reporter.h"
#include "atom/common/native_mate_converters/string16_converter.h"
#include "atom/common/node_bindings.h"
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/task_scheduler/task_scheduler.h"
#include "base/threading/thread_task_runner_handle.h"
#include "gin/array_buffer.h"
#include "gin/public/isolate_holder.h"
@@ -26,7 +22,7 @@
namespace atom {
int NodeMain(int argc, char* argv[]) {
int NodeMain(int argc, char *argv[]) {
base::CommandLine::Init(argc, argv);
int exit_code = 1;
@@ -38,34 +34,26 @@ int NodeMain(int argc, char* argv[]) {
base::ThreadTaskRunnerHandle handle(uv_task_runner);
// Initialize feature list.
auto feature_list = std::make_unique<base::FeatureList>();
std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
feature_list->InitializeFromCommandLine("", "");
base::FeatureList::SetInstance(std::move(feature_list));
gin::V8Initializer::LoadV8Snapshot(
gin::V8Initializer::V8SnapshotFileType::kWithAdditionalContext);
gin::V8Initializer::LoadV8Snapshot();
gin::V8Initializer::LoadV8Natives();
// V8 requires a task scheduler apparently
base::TaskScheduler::CreateAndStartWithDefaultParams("Electron");
// Initialize gin::IsolateHolder.
JavascriptEnvironment gin_env;
// Explicitly register electron's builtin modules.
NodeBindings::RegisterBuiltinModules();
int exec_argc;
const char** exec_argv;
node::Init(&argc, const_cast<const char**>(argv), &exec_argc, &exec_argv);
node::IsolateData isolate_data(gin_env.isolate(), loop);
node::Environment* env = node::CreateEnvironment(
node::CreateIsolateData(gin_env.isolate(), loop, gin_env.platform()),
gin_env.context(), argc, argv, exec_argc, exec_argv);
&isolate_data, gin_env.context(), argc, argv,
exec_argc, exec_argv);
// Enable support for v8 inspector.
NodeDebugger node_debugger(env);
node_debugger.Start(gin_env.platform());
node_debugger.Start();
mate::Dictionary process(gin_env.isolate(), env->process_object());
#if defined(OS_WIN)
@@ -83,7 +71,6 @@ int NodeMain(int argc, char* argv[]) {
bool more;
do {
more = uv_run(env->event_loop(), UV_RUN_ONCE);
gin_env.platform()->DrainBackgroundTasks(env->isolate());
if (more == false) {
node::EmitBeforeExit(env);
@@ -97,24 +84,13 @@ int NodeMain(int argc, char* argv[]) {
exit_code = node::EmitExit(env);
node::RunAtExit(env);
gin_env.platform()->DrainBackgroundTasks(env->isolate());
gin_env.platform()->CancelPendingDelayedTasks(env->isolate());
node::FreeEnvironment(env);
}
// According to "src/gin/shell/gin_main.cc":
//
// gin::IsolateHolder waits for tasks running in TaskScheduler in its
// destructor and thus must be destroyed before TaskScheduler starts skipping
// CONTINUE_ON_SHUTDOWN tasks.
base::TaskScheduler::GetInstance()->Shutdown();
v8::V8::Dispose();
return exit_code;
}
} // namespace atom
#endif // ENABLE_RUN_AS_NODE

View File

@@ -5,14 +5,10 @@
#ifndef ATOM_APP_NODE_MAIN_H_
#define ATOM_APP_NODE_MAIN_H_
#ifdef ENABLE_RUN_AS_NODE
namespace atom {
int NodeMain(int argc, char* argv[]);
int NodeMain(int argc, char *argv[]);
} // namespace atom
#endif // ENABLE_RUN_AS_NODE
#endif // ATOM_APP_NODE_MAIN_H_

View File

@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>${ATOM_BUNDLE_ID}</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundleExecutable</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>LSBackgroundOnly</key>
<true/>
</dict>
</plist>

View File

@@ -2,15 +2,14 @@
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include <utility>
#include "atom/app/uv_task_runner.h"
#include "base/stl_util.h"
namespace atom {
UvTaskRunner::UvTaskRunner(uv_loop_t* loop) : loop_(loop) {}
UvTaskRunner::UvTaskRunner(uv_loop_t* loop) : loop_(loop) {
}
UvTaskRunner::~UvTaskRunner() {
for (auto& iter : tasks_) {
@@ -19,25 +18,26 @@ UvTaskRunner::~UvTaskRunner() {
}
}
bool UvTaskRunner::PostDelayedTask(const base::Location& from_here,
base::OnceClosure task,
bool UvTaskRunner::PostDelayedTask(const tracked_objects::Location& from_here,
const base::Closure& task,
base::TimeDelta delay) {
auto* timer = new uv_timer_t;
timer->data = this;
uv_timer_init(loop_, timer);
uv_timer_start(timer, UvTaskRunner::OnTimeout, delay.InMilliseconds(), 0);
tasks_[timer] = std::move(task);
tasks_[timer] = task;
return true;
}
bool UvTaskRunner::RunsTasksInCurrentSequence() const {
bool UvTaskRunner::RunsTasksOnCurrentThread() const {
return true;
}
bool UvTaskRunner::PostNonNestableDelayedTask(const base::Location& from_here,
base::OnceClosure task,
base::TimeDelta delay) {
return PostDelayedTask(from_here, std::move(task), delay);
bool UvTaskRunner::PostNonNestableDelayedTask(
const tracked_objects::Location& from_here,
const base::Closure& task,
base::TimeDelta delay) {
return PostDelayedTask(from_here, task, delay);
}
// static
@@ -46,7 +46,7 @@ void UvTaskRunner::OnTimeout(uv_timer_t* timer) {
if (!ContainsKey(self->tasks_, timer))
return;
std::move(self->tasks_[timer]).Run();
self->tasks_[timer].Run();
self->tasks_.erase(timer);
uv_timer_stop(timer);
uv_close(reinterpret_cast<uv_handle_t*>(timer), UvTaskRunner::OnClose);

View File

@@ -8,9 +8,8 @@
#include <map>
#include "base/callback.h"
#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "uv.h" // NOLINT(build/include)
#include "vendor/node/deps/uv/include/uv.h"
namespace atom {
@@ -18,24 +17,25 @@ namespace atom {
class UvTaskRunner : public base::SingleThreadTaskRunner {
public:
explicit UvTaskRunner(uv_loop_t* loop);
~UvTaskRunner() override;
// base::SingleThreadTaskRunner:
bool PostDelayedTask(const base::Location& from_here,
base::OnceClosure task,
bool PostDelayedTask(const tracked_objects::Location& from_here,
const base::Closure& task,
base::TimeDelta delay) override;
bool RunsTasksInCurrentSequence() const override;
bool PostNonNestableDelayedTask(const base::Location& from_here,
base::OnceClosure task,
base::TimeDelta delay) override;
bool RunsTasksOnCurrentThread() const override;
bool PostNonNestableDelayedTask(
const tracked_objects::Location& from_here,
const base::Closure& task,
base::TimeDelta delay) override;
private:
~UvTaskRunner() override;
static void OnTimeout(uv_timer_t* timer);
static void OnClose(uv_handle_t* handle);
uv_loop_t* loop_;
std::map<uv_timer_t*, base::OnceClosure> tasks_;
std::map<uv_timer_t*, base::Closure> tasks_;
DISALLOW_COPY_AND_ASSIGN(UvTaskRunner);
};

View File

@@ -20,7 +20,6 @@
#include "atom/common/native_mate_converters/gurl_converter.h"
#include "atom/common/native_mate_converters/image_converter.h"
#include "atom/common/native_mate_converters/net_converter.h"
#include "atom/common/native_mate_converters/network_converter.h"
#include "atom/common/native_mate_converters/value_converter.h"
#include "atom/common/node_includes.h"
#include "atom/common/options_switches.h"
@@ -46,9 +45,7 @@
#include "content/public/common/content_switches.h"
#include "media/audio/audio_manager.h"
#include "native_mate/object_template_builder.h"
#include "net/ssl/client_cert_identity.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "services/network/public/cpp/network_switches.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/image/image.h"
@@ -57,19 +54,14 @@
#include "base/strings/utf_string_conversions.h"
#endif
#if defined(OS_MACOSX)
#include "atom/browser/ui/cocoa/atom_bundle_mover.h"
#endif
using atom::Browser;
namespace mate {
#if defined(OS_WIN)
template <>
template<>
struct Converter<Browser::UserTask> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
Browser::UserTask* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
@@ -86,14 +78,13 @@ struct Converter<Browser::UserTask> {
}
};
using atom::JumpListCategory;
using atom::JumpListItem;
using atom::JumpListCategory;
using atom::JumpListResult;
template <>
template<>
struct Converter<JumpListItem::Type> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
JumpListItem::Type* out) {
std::string item_type;
if (!ConvertFromV8(isolate, val, &item_type))
@@ -131,10 +122,9 @@ struct Converter<JumpListItem::Type> {
}
};
template <>
template<>
struct Converter<JumpListItem> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
JumpListItem* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
@@ -194,10 +184,9 @@ struct Converter<JumpListItem> {
}
};
template <>
template<>
struct Converter<JumpListCategory::Type> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
JumpListCategory::Type* out) {
std::string category_type;
if (!ConvertFromV8(isolate, val, &category_type))
@@ -241,10 +230,9 @@ struct Converter<JumpListCategory::Type> {
}
};
template <>
template<>
struct Converter<JumpListCategory> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
JumpListCategory* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
@@ -271,7 +259,7 @@ struct Converter<JumpListCategory> {
};
// static
template <>
template<>
struct Converter<JumpListResult> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate, JumpListResult val) {
std::string result_code;
@@ -305,10 +293,9 @@ struct Converter<JumpListResult> {
};
#endif
template <>
template<>
struct Converter<Browser::LoginItemSettings> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
Browser::LoginItemSettings* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
@@ -333,16 +320,15 @@ struct Converter<Browser::LoginItemSettings> {
}
};
template <>
template<>
struct Converter<content::CertificateRequestResultType> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
content::CertificateRequestResultType* out) {
bool b;
if (!ConvertFromV8(isolate, val, &b))
return false;
*out = b ? content::CERTIFICATE_REQUEST_RESULT_TYPE_CONTINUE
: content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL;
*out = b ? content::CERTIFICATE_REQUEST_RESULT_TYPE_CONTINUE :
content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL;
return true;
}
};
@@ -351,16 +337,6 @@ struct Converter<content::CertificateRequestResultType> {
namespace atom {
ProcessMetric::ProcessMetric(int type,
base::ProcessId pid,
std::unique_ptr<base::ProcessMetrics> metrics) {
this->type = type;
this->pid = pid;
this->metrics = std::move(metrics);
}
ProcessMetric::~ProcessMetric() = default;
namespace api {
namespace {
@@ -395,8 +371,6 @@ int GetPathConstant(const std::string& name) {
return brightray::DIR_CACHE;
else if (name == "userCache")
return brightray::DIR_USER_CACHE;
else if (name == "logs")
return brightray::DIR_APP_LOGS;
else if (name == "home")
return base::DIR_HOME;
else if (name == "temp")
@@ -424,9 +398,7 @@ int GetPathConstant(const std::string& name) {
}
bool NotificationCallbackWrapper(
const base::Callback<
void(const base::CommandLine::StringVector& command_line,
const base::FilePath& current_directory)>& callback,
const ProcessSingleton::NotificationCallback& callback,
const base::CommandLine::StringVector& cmd,
const base::FilePath& cwd) {
// Make sure the callback is called after app gets ready.
@@ -436,32 +408,25 @@ bool NotificationCallbackWrapper(
scoped_refptr<base::SingleThreadTaskRunner> task_runner(
base::ThreadTaskRunnerHandle::Get());
task_runner->PostTask(
FROM_HERE, base::BindOnce(base::IgnoreResult(callback), cmd, cwd));
FROM_HERE, base::Bind(base::IgnoreResult(callback), cmd, cwd));
}
// ProcessSingleton needs to know whether current process is quiting.
return !Browser::Get()->is_shutting_down();
}
void GotPrivateKey(std::shared_ptr<content::ClientCertificateDelegate> delegate,
scoped_refptr<net::X509Certificate> cert,
scoped_refptr<net::SSLPrivateKey> private_key) {
delegate->ContinueWithCertificate(cert, private_key);
}
void OnClientCertificateSelected(
v8::Isolate* isolate,
std::shared_ptr<content::ClientCertificateDelegate> delegate,
std::shared_ptr<net::ClientCertIdentityList> identities,
mate::Arguments* args) {
if (args->Length() == 2) {
delegate->ContinueWithCertificate(nullptr, nullptr);
delegate->ContinueWithCertificate(nullptr);
return;
}
v8::Local<v8::Value> val;
args->GetNext(&val);
if (val->IsNull()) {
delegate->ContinueWithCertificate(nullptr, nullptr);
delegate->ContinueWithCertificate(nullptr);
return;
}
@@ -477,17 +442,8 @@ void OnClientCertificateSelected(
auto certs = net::X509Certificate::CreateCertificateListFromBytes(
data.c_str(), data.length(), net::X509Certificate::FORMAT_AUTO);
if (!certs.empty()) {
scoped_refptr<net::X509Certificate> cert(certs[0].get());
for (size_t i = 0; i < identities->size(); ++i) {
if (cert->Equals((*identities)[i]->certificate())) {
net::ClientCertIdentity::SelfOwningAcquirePrivateKey(
std::move((*identities)[i]),
base::Bind(&GotPrivateKey, delegate, std::move(cert)));
break;
}
}
}
if (!certs.empty())
delegate->ContinueWithCertificate(certs[0].get());
}
void PassLoginInformation(scoped_refptr<LoginHandler> login_handler,
@@ -500,11 +456,12 @@ void PassLoginInformation(scoped_refptr<LoginHandler> login_handler,
}
#if defined(USE_NSS_CERTS)
int ImportIntoCertStore(CertificateManagerModel* model,
const base::DictionaryValue& options) {
int ImportIntoCertStore(
CertificateManagerModel* model,
const base::DictionaryValue& options) {
std::string file_data, cert_path;
base::string16 password;
net::ScopedCERTCertificateList imported_certs;
net::CertificateList imported_certs;
int rv = -1;
options.GetString("certificate", &cert_path);
options.GetString("password", &password);
@@ -512,13 +469,17 @@ int ImportIntoCertStore(CertificateManagerModel* model,
if (!cert_path.empty()) {
if (base::ReadFileToString(base::FilePath(cert_path), &file_data)) {
auto module = model->cert_db()->GetPrivateSlot();
rv = model->ImportFromPKCS12(module.get(), file_data, password, true,
rv = model->ImportFromPKCS12(module.get(),
file_data,
password,
true,
&imported_certs);
if (imported_certs.size() > 1) {
auto it = imported_certs.begin();
++it; // skip first which would be the client certificate.
for (; it != imported_certs.end(); ++it)
rv &= model->SetCertTrust(it->get(), net::CA_CERT,
rv &= model->SetCertTrust(it->get(),
net::CA_CERT,
net::NSSCertDatabase::TRUSTED_SSL);
}
}
@@ -537,7 +498,7 @@ void OnIconDataAvailable(v8::Isolate* isolate,
callback.Run(v8::Null(isolate), *icon);
} else {
v8::Local<v8::String> error_message =
v8::String::NewFromUtf8(isolate, "Failed to get file icon.");
v8::String::NewFromUtf8(isolate, "Failed to get file icon.");
callback.Run(v8::Exception::Error(error_message), gfx::Image());
}
}
@@ -548,32 +509,31 @@ App::App(v8::Isolate* isolate) {
static_cast<AtomBrowserClient*>(AtomBrowserClient::Get())->set_delegate(this);
Browser::Get()->AddObserver(this);
content::GpuDataManager::GetInstance()->AddObserver(this);
content::BrowserChildProcessObserver::Add(this);
base::ProcessId pid = base::GetCurrentProcId();
auto process_metric = std::make_unique<atom::ProcessMetric>(
content::PROCESS_TYPE_BROWSER, pid,
base::ProcessMetrics::CreateCurrentProcessMetrics());
std::unique_ptr<atom::ProcessMetric> process_metric(
new atom::ProcessMetric(
content::PROCESS_TYPE_BROWSER,
pid,
base::ProcessMetrics::CreateCurrentProcessMetrics()));
app_metrics_[pid] = std::move(process_metric);
Init(isolate);
}
App::~App() {
static_cast<AtomBrowserClient*>(AtomBrowserClient::Get())
->set_delegate(nullptr);
static_cast<AtomBrowserClient*>(AtomBrowserClient::Get())->set_delegate(
nullptr);
Browser::Get()->RemoveObserver(this);
content::GpuDataManager::GetInstance()->RemoveObserver(this);
content::BrowserChildProcessObserver::Remove(this);
}
void App::OnBeforeQuit(bool* prevent_default) {
if (Emit("before-quit")) {
*prevent_default = true;
}
*prevent_default = Emit("before-quit");
}
void App::OnWillQuit(bool* prevent_default) {
if (Emit("will-quit")) {
*prevent_default = true;
}
*prevent_default = Emit("will-quit");
}
void App::OnWindowAllClosed() {
@@ -591,9 +551,7 @@ void App::OnQuit() {
}
void App::OnOpenFile(bool* prevent_default, const std::string& file_path) {
if (Emit("open-file", file_path)) {
*prevent_default = true;
}
*prevent_default = Emit("open-file", file_path);
}
void App::OnOpenURL(const std::string& url) {
@@ -618,7 +576,6 @@ void App::OnFinishLaunching(const base::DictionaryValue& launch_info) {
}
void App::OnPreMainMessageLoopRun() {
content::BrowserChildProcessObserver::Add(this);
if (process_singleton_) {
process_singleton_->OnBrowserReady();
}
@@ -629,89 +586,57 @@ void App::OnAccessibilitySupportChanged() {
}
#if defined(OS_MACOSX)
void App::OnWillContinueUserActivity(bool* prevent_default,
const std::string& type) {
if (Emit("will-continue-activity", type)) {
*prevent_default = true;
}
}
void App::OnDidFailToContinueUserActivity(const std::string& type,
const std::string& error) {
Emit("continue-activity-error", type, error);
}
void App::OnContinueUserActivity(bool* prevent_default,
const std::string& type,
const base::DictionaryValue& user_info) {
if (Emit("continue-activity", type, user_info)) {
*prevent_default = true;
}
}
void App::OnUserActivityWasContinued(const std::string& type,
const base::DictionaryValue& user_info) {
Emit("activity-was-continued", type, user_info);
}
void App::OnUpdateUserActivityState(bool* prevent_default,
const std::string& type,
const base::DictionaryValue& user_info) {
if (Emit("update-activity-state", type, user_info)) {
*prevent_default = true;
}
void App::OnContinueUserActivity(
bool* prevent_default,
const std::string& type,
const base::DictionaryValue& user_info) {
*prevent_default = Emit("continue-activity", type, user_info);
}
void App::OnNewWindowForTab() {
Emit("new-window-for-tab");
}
#endif
void App::OnLogin(scoped_refptr<LoginHandler> login_handler,
void App::OnLogin(LoginHandler* login_handler,
const base::DictionaryValue& request_details) {
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
bool prevent_default = false;
content::WebContents* web_contents = login_handler->GetWebContents();
if (web_contents) {
prevent_default = Emit(
"login", WebContents::CreateFrom(isolate(), web_contents),
request_details, login_handler->auth_info(),
base::Bind(&PassLoginInformation, base::RetainedRef(login_handler)));
}
bool prevent_default = Emit(
"login",
WebContents::CreateFrom(isolate(), login_handler->GetWebContents()),
request_details,
login_handler->auth_info(),
base::Bind(&PassLoginInformation, make_scoped_refptr(login_handler)));
// Default behavior is to always cancel the auth.
if (!prevent_default)
login_handler->CancelAuth();
}
bool App::CanCreateWindow(
content::RenderFrameHost* opener,
const GURL& opener_url,
const GURL& opener_top_level_frame_url,
const GURL& source_origin,
content::mojom::WindowContainerType container_type,
void App::OnCreateWindow(
const GURL& target_url,
const content::Referrer& referrer,
const std::string& frame_name,
WindowOpenDisposition disposition,
const blink::mojom::WindowFeatures& features,
const std::vector<std::string>& additional_features,
const scoped_refptr<network::ResourceRequestBody>& body,
bool user_gesture,
bool opener_suppressed,
bool* no_javascript_access) {
const std::vector<std::string>& features,
const scoped_refptr<content::ResourceRequestBodyImpl>& body,
int render_process_id,
int render_frame_id) {
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
content::RenderFrameHost* rfh =
content::RenderFrameHost::FromID(render_process_id, render_frame_id);
content::WebContents* web_contents =
content::WebContents::FromRenderFrameHost(opener);
content::WebContents::FromRenderFrameHost(rfh);
if (web_contents) {
auto api_web_contents = WebContents::CreateFrom(isolate(), web_contents);
api_web_contents->OnCreateWindow(target_url, referrer, frame_name,
disposition, additional_features, body);
api_web_contents->OnCreateWindow(target_url,
frame_name,
disposition,
features,
body);
}
return false;
}
void App::AllowCertificateError(
@@ -720,15 +645,19 @@ void App::AllowCertificateError(
const net::SSLInfo& ssl_info,
const GURL& request_url,
content::ResourceType resource_type,
bool overridable,
bool strict_enforcement,
bool expired_previous_decision,
const base::Callback<void(content::CertificateRequestResultType)>&
callback) {
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
bool prevent_default = Emit(
"certificate-error", WebContents::CreateFrom(isolate(), web_contents),
request_url, net::ErrorToString(cert_error), ssl_info.cert, callback);
bool prevent_default = Emit("certificate-error",
WebContents::CreateFrom(isolate(), web_contents),
request_url,
net::ErrorToString(cert_error),
ssl_info.cert,
callback);
// Deny the certificate by default.
if (!prevent_default)
@@ -738,40 +667,27 @@ void App::AllowCertificateError(
void App::SelectClientCertificate(
content::WebContents* web_contents,
net::SSLCertRequestInfo* cert_request_info,
net::ClientCertIdentityList identities,
std::unique_ptr<content::ClientCertificateDelegate> delegate) {
std::shared_ptr<content::ClientCertificateDelegate> shared_delegate(
delegate.release());
// Convert the ClientCertIdentityList to a CertificateList
// to avoid changes in the API.
auto client_certs = net::CertificateList();
for (const std::unique_ptr<net::ClientCertIdentity>& identity : identities)
client_certs.push_back(identity->certificate());
auto shared_identities =
std::make_shared<net::ClientCertIdentityList>(std::move(identities));
std::shared_ptr<content::ClientCertificateDelegate>
shared_delegate(delegate.release());
bool prevent_default =
Emit("select-client-certificate",
WebContents::CreateFrom(isolate(), web_contents),
cert_request_info->host_and_port.ToString(), std::move(client_certs),
base::Bind(&OnClientCertificateSelected, isolate(), shared_delegate,
shared_identities));
cert_request_info->host_and_port.ToString(),
cert_request_info->client_certs,
base::Bind(&OnClientCertificateSelected,
isolate(),
shared_delegate));
// Default to first certificate from the platform store.
if (!prevent_default) {
scoped_refptr<net::X509Certificate> cert =
(*shared_identities)[0]->certificate();
net::ClientCertIdentity::SelfOwningAcquirePrivateKey(
std::move((*shared_identities)[0]),
base::Bind(&GotPrivateKey, shared_delegate, std::move(cert)));
}
if (!prevent_default)
shared_delegate->ContinueWithCertificate(
cert_request_info->client_certs[0].get());
}
void App::OnGpuProcessCrashed(base::TerminationStatus status) {
Emit("gpu-process-crashed",
status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED);
status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED);
}
void App::BrowserChildProcessLaunchedAndConnected(
@@ -813,8 +729,9 @@ void App::ChildProcessLaunched(int process_type, base::ProcessHandle handle) {
std::unique_ptr<base::ProcessMetrics> metrics(
base::ProcessMetrics::CreateProcessMetrics(handle));
#endif
app_metrics_[pid] = std::make_unique<atom::ProcessMetric>(process_type, pid,
std::move(metrics));
std::unique_ptr<atom::ProcessMetric> process_metric(
new atom::ProcessMetric(process_type, pid, std::move(metrics)));
app_metrics_[pid] = std::move(process_metric);
}
void App::ChildProcessDisconnected(base::ProcessId pid) {
@@ -864,46 +781,32 @@ void App::SetDesktopName(const std::string& desktop_name) {
}
std::string App::GetLocale() {
return g_browser_process->GetApplicationLocale();
return l10n_util::GetApplicationLocale("");
}
void App::OnSecondInstance(const base::CommandLine::StringVector& cmd,
const base::FilePath& cwd) {
Emit("second-instance", cmd, cwd);
}
bool App::HasSingleInstanceLock() const {
bool App::MakeSingleInstance(
const ProcessSingleton::NotificationCallback& callback) {
if (process_singleton_)
return true;
return false;
}
bool App::RequestSingleInstanceLock() {
if (HasSingleInstanceLock())
return true;
return false;
base::FilePath user_dir;
PathService::Get(brightray::DIR_USER_DATA, &user_dir);
auto cb = base::Bind(&App::OnSecondInstance, base::Unretained(this));
process_singleton_.reset(new ProcessSingleton(
user_dir, base::Bind(NotificationCallbackWrapper, cb)));
user_dir, base::Bind(NotificationCallbackWrapper, callback)));
switch (process_singleton_->NotifyOtherProcessOrCreate()) {
case ProcessSingleton::NotifyResult::LOCK_ERROR:
case ProcessSingleton::NotifyResult::PROFILE_IN_USE:
case ProcessSingleton::NotifyResult::PROCESS_NOTIFIED: {
case ProcessSingleton::NotifyResult::PROCESS_NOTIFIED:
process_singleton_.reset();
return false;
}
return true;
case ProcessSingleton::NotifyResult::PROCESS_NONE:
default: // Shouldn't be needed, but VS warns if it is not there.
return true;
return false;
}
}
void App::ReleaseSingleInstanceLock() {
void App::ReleaseSingleInstance() {
if (process_singleton_) {
process_singleton_->Cleanup();
process_singleton_.reset();
@@ -945,9 +848,8 @@ bool App::Relaunch(mate::Arguments* js_args) {
void App::DisableHardwareAcceleration(mate::Arguments* args) {
if (Browser::Get()->is_ready()) {
args->ThrowError(
"app.disableHardwareAcceleration() can only be called "
"before app is ready");
args->ThrowError("app.disableHardwareAcceleration() can only be called "
"before app is ready");
return;
}
content::GpuDataManager::GetInstance()->DisableHardwareAcceleration();
@@ -965,20 +867,10 @@ void App::DisableDomainBlockingFor3DAPIs(mate::Arguments* args) {
}
bool App::IsAccessibilitySupportEnabled() {
auto* ax_state = content::BrowserAccessibilityState::GetInstance();
auto ax_state = content::BrowserAccessibilityState::GetInstance();
return ax_state->IsAccessibleBrowser();
}
void App::SetAccessibilitySupportEnabled(bool enabled) {
auto* ax_state = content::BrowserAccessibilityState::GetInstance();
if (enabled) {
ax_state->OnScreenReaderDetected();
} else {
ax_state->DisableAccessibility();
}
Browser::Get()->OnAccessibilitySupportChanged();
}
Browser::LoginItemSettings App::GetLoginItemSettings(mate::Arguments* args) {
Browser::LoginItemSettings options;
args->GetNext(&options);
@@ -986,15 +878,18 @@ Browser::LoginItemSettings App::GetLoginItemSettings(mate::Arguments* args) {
}
#if defined(USE_NSS_CERTS)
void App::ImportCertificate(const base::DictionaryValue& options,
const net::CompletionCallback& callback) {
void App::ImportCertificate(
const base::DictionaryValue& options,
const net::CompletionCallback& callback) {
auto browser_context = AtomBrowserContext::From("", false);
if (!certificate_manager_model_) {
std::unique_ptr<base::DictionaryValue> copy = options.CreateDeepCopy();
CertificateManagerModel::Create(
browser_context.get(),
base::Bind(&App::OnCertificateManagerModelCreated,
base::Unretained(this), base::Passed(&copy), callback));
base::Unretained(this),
base::Passed(&copy),
callback));
return;
}
@@ -1007,8 +902,8 @@ void App::OnCertificateManagerModelCreated(
const net::CompletionCallback& callback,
std::unique_ptr<CertificateManagerModel> model) {
certificate_manager_model_ = std::move(model);
int rv =
ImportIntoCertStore(certificate_manager_model_.get(), *(options.get()));
int rv = ImportIntoCertStore(certificate_manager_model_.get(),
*(options.get()));
callback.Run(rv);
}
#endif
@@ -1037,7 +932,7 @@ JumpListResult App::SetJumpList(v8::Local<v8::Value> val,
std::vector<JumpListCategory> categories;
bool delete_jump_list = val->IsNull();
if (!delete_jump_list &&
!mate::ConvertFromV8(args->isolate(), val, &categories)) {
!mate::ConvertFromV8(args->isolate(), val, &categories)) {
args->ThrowError("Argument must be null or an array of categories");
return JumpListResult::ARGUMENT_ERROR;
}
@@ -1045,8 +940,9 @@ JumpListResult App::SetJumpList(v8::Local<v8::Value> val,
JumpList jump_list(Browser::Get()->GetAppUserModelID());
if (delete_jump_list) {
return jump_list.Delete() ? JumpListResult::SUCCESS
: JumpListResult::GENERIC_ERROR;
return jump_list.Delete()
? JumpListResult::SUCCESS
: JumpListResult::GENERIC_ERROR;
}
// Start a transaction that updates the JumpList of this application.
@@ -1069,7 +965,8 @@ JumpListResult App::SetJumpList(v8::Local<v8::Value> val,
}
#endif // defined(OS_WIN)
void App::GetFileIcon(const base::FilePath& path, mate::Arguments* args) {
void App::GetFileIcon(const base::FilePath& path,
mate::Arguments* args) {
mate::Dictionary options;
IconLoader::IconSize icon_size;
FileIconCallback callback;
@@ -1092,7 +989,7 @@ void App::GetFileIcon(const base::FilePath& path, mate::Arguments* args) {
return;
}
auto* icon_manager = g_browser_process->GetIconManager();
auto icon_manager = g_browser_process->GetIconManager();
gfx::Image* icon =
icon_manager->LookupIconFromFilepath(normalized_path, icon_size);
if (icon) {
@@ -1114,12 +1011,10 @@ std::vector<mate::Dictionary> App::GetAppMetrics(v8::Isolate* isolate) {
mate::Dictionary memory_dict = mate::Dictionary::CreateEmpty(isolate);
mate::Dictionary cpu_dict = mate::Dictionary::CreateEmpty(isolate);
memory_dict.Set(
"workingSetSize",
memory_dict.Set("workingSetSize",
static_cast<double>(
process_metric.second->metrics->GetWorkingSetSize() >> 10));
memory_dict.Set(
"peakWorkingSetSize",
memory_dict.Set("peakWorkingSetSize",
static_cast<double>(
process_metric.second->metrics->GetPeakWorkingSetSize() >> 10));
@@ -1131,25 +1026,15 @@ std::vector<mate::Dictionary> App::GetAppMetrics(v8::Isolate* isolate) {
}
pid_dict.Set("memory", memory_dict);
cpu_dict.Set(
"percentCPUUsage",
process_metric.second->metrics->GetPlatformIndependentCPUUsage() /
processor_count);
#if !defined(OS_WIN)
cpu_dict.Set("percentCPUUsage",
process_metric.second->metrics->GetPlatformIndependentCPUUsage()
/ processor_count);
cpu_dict.Set("idleWakeupsPerSecond",
process_metric.second->metrics->GetIdleWakeupsPerSecond());
#else
// Chrome's underlying process_metrics.cc will throw a non-fatal warning
// that this method isn't implemented on Windows, so set it to 0 instead
// of calling it
cpu_dict.Set("idleWakeupsPerSecond", 0);
#endif
process_metric.second->metrics->GetIdleWakeupsPerSecond());
pid_dict.Set("cpu", cpu_dict);
pid_dict.Set("pid", process_metric.second->pid);
pid_dict.Set("type", content::GetProcessTypeNameInEnglish(
process_metric.second->type));
pid_dict.Set("type",
content::GetProcessTypeNameInEnglish(process_metric.second->type));
result.push_back(pid_dict);
}
@@ -1158,19 +1043,18 @@ std::vector<mate::Dictionary> App::GetAppMetrics(v8::Isolate* isolate) {
v8::Local<v8::Value> App::GetGPUFeatureStatus(v8::Isolate* isolate) {
auto status = content::GetFeatureStatus();
base::DictionaryValue temp;
return mate::ConvertToV8(isolate, status ? *status : temp);
return mate::ConvertToV8(isolate,
status ? *status : base::DictionaryValue());
}
void App::EnableMixedSandbox(mate::Arguments* args) {
if (Browser::Get()->is_ready()) {
args->ThrowError(
"app.enableMixedSandbox() can only be called "
"before app is ready");
args->ThrowError("app.enableMixedSandbox() can only be called "
"before app is ready");
return;
}
auto* command_line = base::CommandLine::ForCurrentProcess();
auto command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(::switches::kNoSandbox)) {
#if defined(OS_WIN)
const base::CommandLine::CharType* noSandboxArg = L"--no-sandbox";
@@ -1190,24 +1074,14 @@ void App::EnableMixedSandbox(mate::Arguments* args) {
command_line->AppendSwitch(switches::kEnableMixedSandbox);
}
#if defined(OS_MACOSX)
bool App::MoveToApplicationsFolder(mate::Arguments* args) {
return ui::cocoa::AtomBundleMover::Move(args);
}
bool App::IsInApplicationsFolder() {
return ui::cocoa::AtomBundleMover::IsCurrentAppInApplicationsFolder();
}
#endif
// static
mate::Handle<App> App::Create(v8::Isolate* isolate) {
return mate::CreateHandle(isolate, new App(isolate));
}
// static
void App::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) {
void App::BuildPrototype(
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(mate::StringToV8(isolate, "App"));
auto browser = base::Unretained(Browser::Get());
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
@@ -1243,10 +1117,6 @@ void App::BuildPrototype(v8::Isolate* isolate,
base::Bind(&Browser::SetUserActivity, browser))
.SetMethod("getCurrentActivityType",
base::Bind(&Browser::GetCurrentActivityType, browser))
.SetMethod("invalidateCurrentActivity",
base::Bind(&Browser::InvalidateCurrentActivity, browser))
.SetMethod("updateCurrentActivity",
base::Bind(&Browser::UpdateCurrentActivity, browser))
.SetMethod("setAboutPanelOptions",
base::Bind(&Browser::SetAboutPanelOptions, browser))
#endif
@@ -1268,14 +1138,11 @@ void App::BuildPrototype(v8::Isolate* isolate,
#if defined(USE_NSS_CERTS)
.SetMethod("importCertificate", &App::ImportCertificate)
#endif
.SetMethod("hasSingleInstanceLock", &App::HasSingleInstanceLock)
.SetMethod("requestSingleInstanceLock", &App::RequestSingleInstanceLock)
.SetMethod("releaseSingleInstanceLock", &App::ReleaseSingleInstanceLock)
.SetMethod("makeSingleInstance", &App::MakeSingleInstance)
.SetMethod("releaseSingleInstance", &App::ReleaseSingleInstance)
.SetMethod("relaunch", &App::Relaunch)
.SetMethod("isAccessibilitySupportEnabled",
&App::IsAccessibilitySupportEnabled)
.SetMethod("setAccessibilitySupportEnabled",
&App::SetAccessibilitySupportEnabled)
.SetMethod("disableHardwareAcceleration",
&App::DisableHardwareAcceleration)
.SetMethod("disableDomainBlockingFor3DAPIs",
@@ -1283,30 +1150,24 @@ void App::BuildPrototype(v8::Isolate* isolate,
.SetMethod("getFileIcon", &App::GetFileIcon)
.SetMethod("getAppMetrics", &App::GetAppMetrics)
.SetMethod("getGPUFeatureStatus", &App::GetGPUFeatureStatus)
// TODO(juturu): Remove in 2.0, deprecate before then with warnings
#if defined(OS_MACOSX)
.SetMethod("moveToApplicationsFolder", &App::MoveToApplicationsFolder)
.SetMethod("isInApplicationsFolder", &App::IsInApplicationsFolder)
#endif
#if defined(MAS_BUILD)
.SetMethod("startAccessingSecurityScopedResource",
&App::StartAccessingSecurityScopedResource)
#endif
.SetMethod("enableMixedSandbox", &App::EnableMixedSandbox);
.SetMethod("enableMixedSandbox", &App::EnableMixedSandbox)
// TODO(juturu): Remove in 2.0, deprecate before then with warnings
.SetMethod("getAppMemoryInfo", &App::GetAppMetrics);
}
} // namespace api
} // namespace atom
namespace {
void AppendSwitch(const std::string& switch_string, mate::Arguments* args) {
auto* command_line = base::CommandLine::ForCurrentProcess();
auto command_line = base::CommandLine::ForCurrentProcess();
if (base::EndsWith(switch_string, "-path",
base::CompareCase::INSENSITIVE_ASCII) ||
switch_string == network::switches::kLogNetLog) {
switch_string == switches::kLogNetLog) {
base::FilePath path;
args->GetNext(&path);
command_line->AppendSwitchPath(switch_string, path);
@@ -1335,19 +1196,18 @@ void DockSetMenu(atom::api::Menu* menu) {
}
#endif
void Initialize(v8::Local<v8::Object> exports,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv) {
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) {
v8::Isolate* isolate = context->GetIsolate();
auto* command_line = base::CommandLine::ForCurrentProcess();
auto command_line = base::CommandLine::ForCurrentProcess();
mate::Dictionary dict(isolate, exports);
dict.Set("App", atom::api::App::GetConstructor(isolate)->GetFunction());
dict.Set("app", atom::api::App::Create(isolate));
dict.SetMethod("appendSwitch", &AppendSwitch);
dict.SetMethod("appendArgument", base::Bind(&base::CommandLine::AppendArg,
base::Unretained(command_line)));
dict.SetMethod("appendArgument",
base::Bind(&base::CommandLine::AppendArg,
base::Unretained(command_line)));
#if defined(OS_MACOSX)
auto browser = base::Unretained(Browser::Get());
dict.SetMethod("dockBounce", &DockBounce);
@@ -1369,4 +1229,4 @@ void Initialize(v8::Local<v8::Object> exports,
} // namespace
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_app, Initialize)
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_app, Initialize)

View File

@@ -25,7 +25,6 @@
#include "native_mate/dictionary.h"
#include "native_mate/handle.h"
#include "net/base/completion_callback.h"
#include "net/ssl/client_cert_identity.h"
#if defined(USE_NSS_CERTS)
#include "chrome/browser/certificate_manager_model.h"
@@ -52,8 +51,11 @@ struct ProcessMetric {
ProcessMetric(int type,
base::ProcessId pid,
std::unique_ptr<base::ProcessMetrics> metrics);
~ProcessMetric();
std::unique_ptr<base::ProcessMetrics> metrics) {
this->type = type;
this->pid = pid;
this->metrics = std::move(metrics);
}
};
namespace api {
@@ -64,14 +66,24 @@ class App : public AtomBrowserClient::Delegate,
public content::GpuDataManagerObserver,
public content::BrowserChildProcessObserver {
public:
using FileIconCallback =
base::Callback<void(v8::Local<v8::Value>, const gfx::Image&)>;
using FileIconCallback = base::Callback<void(v8::Local<v8::Value>,
const gfx::Image&)>;
static mate::Handle<App> Create(v8::Isolate* isolate);
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype);
// Called when window with disposition needs to be created.
void OnCreateWindow(
const GURL& target_url,
const std::string& frame_name,
WindowOpenDisposition disposition,
const std::vector<std::string>& features,
const scoped_refptr<content::ResourceRequestBodyImpl>& body,
int render_process_id,
int render_frame_id);
#if defined(USE_NSS_CERTS)
void OnCertificateManagerModelCreated(
std::unique_ptr<base::DictionaryValue> options,
@@ -98,25 +110,16 @@ class App : public AtomBrowserClient::Delegate,
void OnActivate(bool has_visible_windows) override;
void OnWillFinishLaunching() override;
void OnFinishLaunching(const base::DictionaryValue& launch_info) override;
void OnLogin(scoped_refptr<LoginHandler> login_handler,
void OnLogin(LoginHandler* login_handler,
const base::DictionaryValue& request_details) override;
void OnAccessibilitySupportChanged() override;
void OnPreMainMessageLoopRun() override;
#if defined(OS_MACOSX)
void OnWillContinueUserActivity(bool* prevent_default,
const std::string& type) override;
void OnDidFailToContinueUserActivity(const std::string& type,
const std::string& error) override;
void OnContinueUserActivity(bool* prevent_default,
const std::string& type,
const base::DictionaryValue& user_info) override;
void OnUserActivityWasContinued(
const std::string& type,
const base::DictionaryValue& user_info) override;
void OnUpdateUserActivityState(
void OnContinueUserActivity(
bool* prevent_default,
const std::string& type,
const base::DictionaryValue& user_info) override;
void OnNewWindowForTab() override;
#endif
@@ -127,6 +130,7 @@ class App : public AtomBrowserClient::Delegate,
const net::SSLInfo& ssl_info,
const GURL& request_url,
content::ResourceType resource_type,
bool overridable,
bool strict_enforcement,
bool expired_previous_decision,
const base::Callback<void(content::CertificateRequestResultType)>&
@@ -134,23 +138,7 @@ class App : public AtomBrowserClient::Delegate,
void SelectClientCertificate(
content::WebContents* web_contents,
net::SSLCertRequestInfo* cert_request_info,
net::ClientCertIdentityList client_certs,
std::unique_ptr<content::ClientCertificateDelegate> delegate) override;
bool CanCreateWindow(content::RenderFrameHost* opener,
const GURL& opener_url,
const GURL& opener_top_level_frame_url,
const GURL& source_origin,
content::mojom::WindowContainerType container_type,
const GURL& target_url,
const content::Referrer& referrer,
const std::string& frame_name,
WindowOpenDisposition disposition,
const blink::mojom::WindowFeatures& features,
const std::vector<std::string>& additional_features,
const scoped_refptr<network::ResourceRequestBody>& body,
bool user_gesture,
bool opener_suppressed,
bool* no_javascript_access) override;
// content::GpuDataManagerObserver:
void OnGpuProcessCrashed(base::TerminationStatus status) override;
@@ -160,10 +148,10 @@ class App : public AtomBrowserClient::Delegate,
const content::ChildProcessData& data) override;
void BrowserChildProcessHostDisconnected(
const content::ChildProcessData& data) override;
void BrowserChildProcessCrashed(const content::ChildProcessData& data,
int exit_code) override;
void BrowserChildProcessKilled(const content::ChildProcessData& data,
int exit_code) override;
void BrowserChildProcessCrashed(
const content::ChildProcessData& data, int exit_code) override;
void BrowserChildProcessKilled(
const content::ChildProcessData& data, int exit_code) override;
private:
void SetAppPath(const base::FilePath& app_path);
@@ -178,36 +166,25 @@ class App : public AtomBrowserClient::Delegate,
void SetDesktopName(const std::string& desktop_name);
std::string GetLocale();
void OnSecondInstance(const base::CommandLine::StringVector& cmd,
const base::FilePath& cwd);
bool HasSingleInstanceLock() const;
bool RequestSingleInstanceLock();
void ReleaseSingleInstanceLock();
bool MakeSingleInstance(
const ProcessSingleton::NotificationCallback& callback);
void ReleaseSingleInstance();
bool Relaunch(mate::Arguments* args);
void DisableHardwareAcceleration(mate::Arguments* args);
void DisableDomainBlockingFor3DAPIs(mate::Arguments* args);
bool IsAccessibilitySupportEnabled();
void SetAccessibilitySupportEnabled(bool enabled);
Browser::LoginItemSettings GetLoginItemSettings(mate::Arguments* args);
#if defined(USE_NSS_CERTS)
void ImportCertificate(const base::DictionaryValue& options,
const net::CompletionCallback& callback);
#endif
void GetFileIcon(const base::FilePath& path, mate::Arguments* args);
void GetFileIcon(const base::FilePath& path,
mate::Arguments* args);
std::vector<mate::Dictionary> GetAppMetrics(v8::Isolate* isolate);
v8::Local<v8::Value> GetGPUFeatureStatus(v8::Isolate* isolate);
void EnableMixedSandbox(mate::Arguments* args);
#if defined(OS_MACOSX)
bool MoveToApplicationsFolder(mate::Arguments* args);
bool IsInApplicationsFolder();
#endif
#if defined(MAS_BUILD)
base::Callback<void()> StartAccessingSecurityScopedResource(
mate::Arguments* args);
#endif
#if defined(OS_WIN)
// Get the current Jump List settings.
v8::Local<v8::Value> GetJumpListSettings();
@@ -228,7 +205,8 @@ class App : public AtomBrowserClient::Delegate,
base::FilePath app_path_;
using ProcessMetricMap =
std::unordered_map<base::ProcessId, std::unique_ptr<atom::ProcessMetric>>;
std::unordered_map<base::ProcessId,
std::unique_ptr<atom::ProcessMetric>>;
ProcessMetricMap app_metrics_;
DISALLOW_COPY_AND_ASSIGN(App);

View File

@@ -1,63 +0,0 @@
// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/api/atom_api_app.h"
#import <Cocoa/Cocoa.h>
#include "base/strings/sys_string_conversions.h"
namespace atom {
namespace api {
// Callback passed to js which will stop accessing the given bookmark.
void OnStopAccessingSecurityScopedResource(NSURL* bookmarkUrl) {
[bookmarkUrl stopAccessingSecurityScopedResource];
[bookmarkUrl release];
}
// Get base64 encoded NSData, create a bookmark for it and start accessing it.
base::Callback<void()> App::StartAccessingSecurityScopedResource(
mate::Arguments* args) {
std::string data;
args->GetNext(&data);
NSString* base64str = base::SysUTF8ToNSString(data);
NSData* bookmarkData =
[[NSData alloc] initWithBase64EncodedString:base64str options:0];
// Create bookmarkUrl from NSData.
BOOL isStale = false;
NSError* error = nil;
NSURL* bookmarkUrl =
[NSURL URLByResolvingBookmarkData:bookmarkData
options:NSURLBookmarkResolutionWithSecurityScope
relativeToURL:nil
bookmarkDataIsStale:&isStale
error:&error];
if (error != nil) {
NSString* err =
[NSString stringWithFormat:@"NSError: %@ %@", error, [error userInfo]];
args->ThrowError(base::SysNSStringToUTF8(err));
}
if (isStale) {
args->ThrowError("bookmarkDataIsStale - try recreating the bookmark");
}
if (error == nil && isStale == false) {
[bookmarkUrl startAccessingSecurityScopedResource];
}
// Stop the NSURL from being GC'd.
[bookmarkUrl retain];
// Return a js callback which will close the bookmark.
return base::Bind(&OnStopAccessingSecurityScopedResource, bookmarkUrl);
}
} // namespace atom
} // namespace api

View File

@@ -16,12 +16,12 @@
namespace mate {
template <>
template<>
struct Converter<base::Time> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const base::Time& val) {
v8::MaybeLocal<v8::Value> date =
v8::Date::New(isolate->GetCurrentContext(), val.ToJsTime());
v8::MaybeLocal<v8::Value> date = v8::Date::New(
isolate->GetCurrentContext(), val.ToJsTime());
if (date.IsEmpty())
return v8::Null(isolate);
else
@@ -49,20 +49,21 @@ void AutoUpdater::OnError(const std::string& message) {
v8::HandleScope handle_scope(isolate());
auto error = v8::Exception::Error(mate::StringToV8(isolate(), message));
mate::EmitEvent(
isolate(), GetWrapper(), "error",
isolate(),
GetWrapper(),
"error",
error->ToObject(isolate()->GetCurrentContext()).ToLocalChecked(),
// Message is also emitted to keep compatibility with old code.
message);
}
void AutoUpdater::OnError(const std::string& message,
const int code,
const std::string& domain) {
const int code, const std::string& domain) {
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
auto error = v8::Exception::Error(mate::StringToV8(isolate(), message));
auto errorObject =
error->ToObject(isolate()->GetCurrentContext()).ToLocalChecked();
auto errorObject = error->ToObject(
isolate()->GetCurrentContext()).ToLocalChecked();
// add two new params for better error handling
errorObject->Set(mate::StringToV8(isolate(), "code"),
@@ -98,13 +99,13 @@ void AutoUpdater::OnWindowAllClosed() {
QuitAndInstall();
}
void AutoUpdater::SetFeedURL(mate::Arguments* args) {
auto_updater::AutoUpdater::SetFeedURL(args);
void AutoUpdater::SetFeedURL(const std::string& url, mate::Arguments* args) {
auto_updater::AutoUpdater::HeaderMap headers;
args->GetNext(&headers);
auto_updater::AutoUpdater::SetFeedURL(url, headers);
}
void AutoUpdater::QuitAndInstall() {
Emit("before-quit-for-update");
// If we don't have any window then quitAndInstall immediately.
if (WindowList::IsEmpty()) {
auto_updater::AutoUpdater::QuitAndInstall();
@@ -122,8 +123,8 @@ mate::Handle<AutoUpdater> AutoUpdater::Create(v8::Isolate* isolate) {
}
// static
void AutoUpdater::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) {
void AutoUpdater::BuildPrototype(
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(mate::StringToV8(isolate, "AutoUpdater"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("checkForUpdates", &auto_updater::AutoUpdater::CheckForUpdates)
@@ -136,14 +137,13 @@ void AutoUpdater::BuildPrototype(v8::Isolate* isolate,
} // namespace atom
namespace {
using atom::api::AutoUpdater;
void Initialize(v8::Local<v8::Object> exports,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv) {
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) {
v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary dict(isolate, exports);
dict.Set("autoUpdater", AutoUpdater::Create(isolate));
@@ -152,4 +152,4 @@ void Initialize(v8::Local<v8::Object> exports,
} // namespace
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_auto_updater, Initialize)
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_auto_updater, Initialize)

View File

@@ -32,9 +32,8 @@ class AutoUpdater : public mate::EventEmitter<AutoUpdater>,
// Delegate implementations.
void OnError(const std::string& error) override;
void OnError(const std::string& message,
const int code,
const std::string& domain) override;
void OnError(const std::string& message, const int code,
const std::string& domain);
void OnCheckingForUpdate() override;
void OnUpdateAvailable() override;
void OnUpdateNotAvailable() override;
@@ -48,7 +47,7 @@ class AutoUpdater : public mate::EventEmitter<AutoUpdater>,
private:
std::string GetFeedURL();
void SetFeedURL(mate::Arguments* args);
void SetFeedURL(const std::string& url, mate::Arguments* args);
void QuitAndInstall();
DISALLOW_COPY_AND_ASSIGN(AutoUpdater);

View File

@@ -1,87 +0,0 @@
// Copyright (c) 2018 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/api/atom_api_box_layout.h"
#include <string>
#include "atom/browser/api/atom_api_view.h"
#include "atom/common/api/constructor.h"
#include "native_mate/dictionary.h"
#include "atom/common/node_includes.h"
namespace mate {
template <>
struct Converter<views::BoxLayout::Orientation> {
static bool FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
views::BoxLayout::Orientation* out) {
std::string orientation;
if (!ConvertFromV8(isolate, val, &orientation))
return false;
if (orientation == "horizontal")
*out = views::BoxLayout::kHorizontal;
else if (orientation == "vertical")
*out = views::BoxLayout::kVertical;
else
return false;
return true;
}
};
} // namespace mate
namespace atom {
namespace api {
BoxLayout::BoxLayout(views::BoxLayout::Orientation orientation)
: LayoutManager(new views::BoxLayout(orientation)) {}
BoxLayout::~BoxLayout() {}
void BoxLayout::SetFlexForView(mate::Handle<View> view, int flex) {
auto* box_layout = static_cast<views::BoxLayout*>(layout_manager());
box_layout->SetFlexForView(view->view(), flex);
}
// static
mate::WrappableBase* BoxLayout::New(mate::Arguments* args,
views::BoxLayout::Orientation orientation) {
auto* layout = new BoxLayout(orientation);
layout->InitWith(args->isolate(), args->GetThis());
return layout;
}
// static
void BoxLayout::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(mate::StringToV8(isolate, "BoxLayout"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("setFlexForView", &BoxLayout::SetFlexForView);
}
} // namespace api
} // namespace atom
namespace {
using atom::api::BoxLayout;
void Initialize(v8::Local<v8::Object> exports,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv) {
v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary dict(isolate, exports);
dict.Set("BoxLayout", mate::CreateConstructor<BoxLayout>(
isolate, base::Bind(&BoxLayout::New)));
}
} // namespace
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_box_layout, Initialize)

View File

@@ -1,40 +0,0 @@
// 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_API_ATOM_API_BOX_LAYOUT_H_
#define ATOM_BROWSER_API_ATOM_API_BOX_LAYOUT_H_
#include "atom/browser/api/atom_api_layout_manager.h"
#include "native_mate/handle.h"
#include "ui/views/layout/box_layout.h"
namespace atom {
namespace api {
class View;
class BoxLayout : public LayoutManager {
public:
static mate::WrappableBase* New(mate::Arguments* args,
views::BoxLayout::Orientation orientation);
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype);
void SetFlexForView(mate::Handle<View> view, int flex);
protected:
explicit BoxLayout(views::BoxLayout::Orientation orientation);
~BoxLayout() override;
private:
DISALLOW_COPY_AND_ASSIGN(BoxLayout);
};
} // namespace api
} // namespace atom
#endif // ATOM_BROWSER_API_ATOM_API_BOX_LAYOUT_H_

View File

@@ -51,7 +51,8 @@ namespace api {
BrowserView::BrowserView(v8::Isolate* isolate,
v8::Local<v8::Object> wrapper,
const mate::Dictionary& options) {
const mate::Dictionary& options)
: api_web_contents_(nullptr) {
Init(isolate, wrapper, options);
}
@@ -67,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()));
view_.reset(NativeBrowserView::Create(
api_web_contents_->managed_web_contents()->GetView()));
InitWith(isolate, wrapper);
}
@@ -113,7 +114,7 @@ void BrowserView::SetBackgroundColor(const std::string& color_name) {
view_->SetBackgroundColor(ParseHexColor(color_name));
}
v8::Local<v8::Value> BrowserView::GetWebContents() {
v8::Local<v8::Value> BrowserView::WebContents() {
if (web_contents_.IsEmpty()) {
return v8::Null(isolate());
}
@@ -130,7 +131,7 @@ void BrowserView::BuildPrototype(v8::Isolate* isolate,
.SetMethod("setAutoResize", &BrowserView::SetAutoResize)
.SetMethod("setBounds", &BrowserView::SetBounds)
.SetMethod("setBackgroundColor", &BrowserView::SetBackgroundColor)
.SetProperty("webContents", &BrowserView::GetWebContents)
.SetProperty("webContents", &BrowserView::WebContents)
.SetProperty("id", &BrowserView::ID);
}
@@ -152,13 +153,11 @@ void Initialize(v8::Local<v8::Object> exports,
mate::Dictionary browser_view(
isolate, BrowserView::GetConstructor(isolate)->GetFunction());
browser_view.SetMethod("fromId",
&mate::TrackableObject<BrowserView>::FromWeakMapID);
browser_view.SetMethod("getAllViews",
&mate::TrackableObject<BrowserView>::GetAll);
&mate::TrackableObject<BrowserView>::FromWeakMapID);
mate::Dictionary dict(isolate, exports);
dict.Set("BrowserView", browser_view);
}
} // namespace
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_browser_view, Initialize)
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_browser_view, Initialize)

View File

@@ -56,10 +56,10 @@ class BrowserView : public mate::TrackableObject<BrowserView> {
void SetBounds(const gfx::Rect& bounds);
void SetBackgroundColor(const std::string& color_name);
v8::Local<v8::Value> GetWebContents();
v8::Local<v8::Value> WebContents();
v8::Global<v8::Value> web_contents_;
class WebContents* api_web_contents_ = nullptr;
class WebContents* api_web_contents_;
std::unique_ptr<NativeBrowserView> view_;

View File

@@ -1,452 +0,0 @@
// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/api/atom_api_browser_window.h"
#include "atom/browser/browser.h"
#include "atom/browser/unresponsive_suppressor.h"
#include "atom/browser/web_contents_preferences.h"
#include "atom/browser/window_list.h"
#include "atom/common/api/api_messages.h"
#include "atom/common/api/constructor.h"
#include "atom/common/color_util.h"
#include "atom/common/native_mate_converters/callback.h"
#include "atom/common/native_mate_converters/value_converter.h"
#include "atom/common/options_switches.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "native_mate/dictionary.h"
#include "ui/gl/gpu_switching_manager.h"
#include "atom/common/node_includes.h"
namespace atom {
namespace api {
BrowserWindow::BrowserWindow(v8::Isolate* isolate,
v8::Local<v8::Object> wrapper,
const mate::Dictionary& options)
: TopLevelWindow(isolate, options), weak_factory_(this) {
mate::Handle<class WebContents> web_contents;
// Use options.webPreferences in WebContents.
mate::Dictionary web_preferences = mate::Dictionary::CreateEmpty(isolate);
options.Get(options::kWebPreferences, &web_preferences);
// Copy the backgroundColor to webContents.
v8::Local<v8::Value> value;
if (options.Get(options::kBackgroundColor, &value))
web_preferences.Set(options::kBackgroundColor, value);
v8::Local<v8::Value> transparent;
if (options.Get("transparent", &transparent))
web_preferences.Set("transparent", transparent);
if (options.Get("webContents", &web_contents) && !web_contents.IsEmpty()) {
// Set webPreferences from options if using an existing webContents.
// These preferences will be used when the webContent launches new
// render processes.
auto* existing_preferences =
WebContentsPreferences::From(web_contents->web_contents());
base::DictionaryValue web_preferences_dict;
if (mate::ConvertFromV8(isolate, web_preferences.GetHandle(),
&web_preferences_dict)) {
existing_preferences->dict()->Clear();
existing_preferences->Merge(web_preferences_dict);
}
} else {
// Creates the WebContents used by BrowserWindow.
web_contents = WebContents::Create(isolate, web_preferences);
}
web_contents_.Reset(isolate, web_contents.ToV8());
api_web_contents_ = web_contents.get();
api_web_contents_->AddObserver(this);
Observe(api_web_contents_->web_contents());
// Keep a copy of the options for later use.
mate::Dictionary(isolate, web_contents->GetWrapper())
.Set("browserWindowOptions", options);
// Tell the content module to initialize renderer widget with transparent
// mode.
ui::GpuSwitchingManager::SetTransparent(window()->transparent());
// Associate with BrowserWindow.
web_contents->SetOwnerWindow(window());
auto* host = web_contents->web_contents()->GetRenderViewHost();
if (host)
host->GetWidget()->AddInputEventObserver(this);
InitWith(isolate, wrapper);
#if defined(OS_MACOSX)
if (!window()->has_frame())
OverrideNSWindowContentView(web_contents->managed_web_contents());
#endif
// Init window after everything has been setup.
window()->InitFromOptions(options);
}
BrowserWindow::~BrowserWindow() {
api_web_contents_->RemoveObserver(this);
// Note that the OnWindowClosed will not be called after the destructor runs,
// since the window object is managed by the TopLevelWindow class.
if (web_contents())
Cleanup();
}
void BrowserWindow::OnInputEvent(const blink::WebInputEvent& event) {
switch (event.GetType()) {
case blink::WebInputEvent::kGestureScrollBegin:
case blink::WebInputEvent::kGestureScrollUpdate:
case blink::WebInputEvent::kGestureScrollEnd:
Emit("scroll-touch-edge");
break;
default:
break;
}
}
void BrowserWindow::RenderViewHostChanged(content::RenderViewHost* old_host,
content::RenderViewHost* new_host) {
if (old_host)
old_host->GetWidget()->RemoveInputEventObserver(this);
if (new_host)
new_host->GetWidget()->AddInputEventObserver(this);
}
void BrowserWindow::RenderViewCreated(
content::RenderViewHost* render_view_host) {
if (!window()->transparent())
return;
content::RenderWidgetHostImpl* impl = content::RenderWidgetHostImpl::FromID(
render_view_host->GetProcess()->GetID(),
render_view_host->GetRoutingID());
if (impl)
impl->SetBackgroundOpaque(false);
}
void BrowserWindow::DidFirstVisuallyNonEmptyPaint() {
if (window()->IsVisible())
return;
// When there is a non-empty first paint, resize the RenderWidget to force
// Chromium to draw.
auto* const view = web_contents()->GetRenderWidgetHostView();
view->Show();
view->SetSize(window()->GetContentSize());
// Emit the ReadyToShow event in next tick in case of pending drawing work.
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(
[](base::WeakPtr<BrowserWindow> self) {
if (self)
self->Emit("ready-to-show");
},
GetWeakPtr()));
}
void BrowserWindow::BeforeUnloadDialogCancelled() {
WindowList::WindowCloseCancelled(window());
// Cancel unresponsive event when window close is cancelled.
window_unresponsive_closure_.Cancel();
}
void BrowserWindow::OnRendererUnresponsive(content::RenderProcessHost*) {
// Schedule the unresponsive shortly later, since we may receive the
// responsive event soon. This could happen after the whole application had
// blocked for a while.
// Also notice that when closing this event would be ignored because we have
// explicitly started a close timeout counter. This is on purpose because we
// don't want the unresponsive event to be sent too early when user is closing
// the window.
ScheduleUnresponsiveEvent(50);
}
bool BrowserWindow::OnMessageReceived(const IPC::Message& message,
content::RenderFrameHost* rfh) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(BrowserWindow, message, rfh)
IPC_MESSAGE_HANDLER(AtomFrameHostMsg_UpdateDraggableRegions,
UpdateDraggableRegions)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
void BrowserWindow::OnCloseContents() {
DCHECK(web_contents());
// Close all child windows before closing current window.
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
for (v8::Local<v8::Value> value : child_windows_.Values(isolate())) {
mate::Handle<BrowserWindow> child;
if (mate::ConvertFromV8(isolate(), value, &child) && !child.IsEmpty())
child->window()->CloseImmediately();
}
// When the web contents is gone, close the window immediately, but the
// memory will not be freed until you call delete.
// In this way, it would be safe to manage windows via smart pointers. If you
// want to free memory when the window is closed, you can do deleting by
// overriding the OnWindowClosed method in the observer.
window()->CloseImmediately();
// Do not sent "unresponsive" event after window is closed.
window_unresponsive_closure_.Cancel();
}
void BrowserWindow::OnRendererResponsive() {
window_unresponsive_closure_.Cancel();
Emit("responsive");
}
void BrowserWindow::RequestPreferredWidth(int* width) {
*width = web_contents()->GetPreferredSize().width();
}
void BrowserWindow::OnCloseButtonClicked(bool* prevent_default) {
// When user tries to close the window by clicking the close button, we do
// not close the window immediately, instead we try to close the web page
// first, and when the web page is closed the window will also be closed.
*prevent_default = true;
// Assume the window is not responding if it doesn't cancel the close and is
// not closed in 5s, in this way we can quickly show the unresponsive
// dialog when the window is busy executing some script withouth waiting for
// the unresponsive timeout.
if (window_unresponsive_closure_.IsCancelled())
ScheduleUnresponsiveEvent(5000);
if (!web_contents())
// Already closed by renderer
return;
if (web_contents()->NeedToFireBeforeUnload())
web_contents()->DispatchBeforeUnload();
else
web_contents()->Close();
}
void BrowserWindow::OnWindowClosed() {
Cleanup();
TopLevelWindow::OnWindowClosed();
}
void BrowserWindow::OnWindowBlur() {
web_contents()->StoreFocus();
#if defined(OS_MACOSX)
auto* rwhv = web_contents()->GetRenderWidgetHostView();
if (rwhv)
rwhv->SetActive(false);
#endif
TopLevelWindow::OnWindowBlur();
}
void BrowserWindow::OnWindowFocus() {
web_contents()->RestoreFocus();
#if defined(OS_MACOSX)
auto* rwhv = web_contents()->GetRenderWidgetHostView();
if (rwhv)
rwhv->SetActive(true);
#else
if (!api_web_contents_->IsDevToolsOpened())
web_contents()->Focus();
#endif
TopLevelWindow::OnWindowFocus();
}
void BrowserWindow::OnWindowResize() {
#if defined(OS_MACOSX)
if (!draggable_regions_.empty())
UpdateDraggableRegions(nullptr, draggable_regions_);
#endif
TopLevelWindow::OnWindowResize();
}
void BrowserWindow::OnWindowLeaveFullScreen() {
TopLevelWindow::OnWindowLeaveFullScreen();
#if defined(OS_MACOSX)
if (web_contents()->IsFullscreenForCurrentTab())
web_contents()->ExitFullscreen(true);
#endif
}
void BrowserWindow::Focus() {
if (api_web_contents_->IsOffScreen())
FocusOnWebView();
else
TopLevelWindow::Focus();
}
void BrowserWindow::Blur() {
if (api_web_contents_->IsOffScreen())
BlurWebView();
else
TopLevelWindow::Blur();
}
void BrowserWindow::SetBackgroundColor(const std::string& color_name) {
TopLevelWindow::SetBackgroundColor(color_name);
auto* view = web_contents()->GetRenderWidgetHostView();
if (view)
view->SetBackgroundColor(ParseHexColor(color_name));
}
void BrowserWindow::SetBrowserView(v8::Local<v8::Value> value) {
TopLevelWindow::SetBrowserView(value);
#if defined(OS_MACOSX)
UpdateDraggableRegions(nullptr, draggable_regions_);
#endif
}
void BrowserWindow::SetVibrancy(v8::Isolate* isolate,
v8::Local<v8::Value> value) {
std::string type = mate::V8ToString(value);
auto* render_view_host = web_contents()->GetRenderViewHost();
if (render_view_host) {
auto* impl = content::RenderWidgetHostImpl::FromID(
render_view_host->GetProcess()->GetID(),
render_view_host->GetRoutingID());
if (impl)
impl->SetBackgroundOpaque(type.empty() ? !window_->transparent() : false);
}
TopLevelWindow::SetVibrancy(isolate, value);
}
void BrowserWindow::FocusOnWebView() {
web_contents()->GetRenderViewHost()->GetWidget()->Focus();
}
void BrowserWindow::BlurWebView() {
web_contents()->GetRenderViewHost()->GetWidget()->Blur();
}
bool BrowserWindow::IsWebViewFocused() {
auto* host_view = web_contents()->GetRenderViewHost()->GetWidget()->GetView();
return host_view && host_view->HasFocus();
}
v8::Local<v8::Value> BrowserWindow::GetWebContents(v8::Isolate* isolate) {
if (web_contents_.IsEmpty())
return v8::Null(isolate);
return v8::Local<v8::Value>::New(isolate, web_contents_);
}
// Convert draggable regions in raw format to SkRegion format.
std::unique_ptr<SkRegion> BrowserWindow::DraggableRegionsToSkRegion(
const std::vector<DraggableRegion>& regions) {
auto sk_region = std::make_unique<SkRegion>();
for (const DraggableRegion& region : regions) {
sk_region->op(
region.bounds.x(), region.bounds.y(), region.bounds.right(),
region.bounds.bottom(),
region.draggable ? SkRegion::kUnion_Op : SkRegion::kDifference_Op);
}
return sk_region;
}
void BrowserWindow::ScheduleUnresponsiveEvent(int ms) {
if (!window_unresponsive_closure_.IsCancelled())
return;
window_unresponsive_closure_.Reset(
base::Bind(&BrowserWindow::NotifyWindowUnresponsive, GetWeakPtr()));
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, window_unresponsive_closure_.callback(),
base::TimeDelta::FromMilliseconds(ms));
}
void BrowserWindow::NotifyWindowUnresponsive() {
window_unresponsive_closure_.Cancel();
if (!window_->IsClosed() && window_->IsEnabled() &&
!IsUnresponsiveEventSuppressed()) {
Emit("unresponsive");
}
}
void BrowserWindow::Cleanup() {
auto* host = web_contents()->GetRenderViewHost();
if (host)
host->GetWidget()->RemoveInputEventObserver(this);
api_web_contents_->DestroyWebContents(true /* async */);
Observe(nullptr);
}
// static
mate::WrappableBase* BrowserWindow::New(mate::Arguments* args) {
if (!Browser::Get()->is_ready()) {
args->ThrowError("Cannot create BrowserWindow before app is ready");
return nullptr;
}
if (args->Length() > 1) {
args->ThrowError();
return nullptr;
}
mate::Dictionary options;
if (!(args->Length() == 1 && args->GetNext(&options))) {
options = mate::Dictionary::CreateEmpty(args->isolate());
}
return new BrowserWindow(args->isolate(), args->GetThis(), options);
}
// static
void BrowserWindow::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(mate::StringToV8(isolate, "BrowserWindow"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("focusOnWebView", &BrowserWindow::FocusOnWebView)
.SetMethod("blurWebView", &BrowserWindow::BlurWebView)
.SetMethod("isWebViewFocused", &BrowserWindow::IsWebViewFocused)
.SetProperty("webContents", &BrowserWindow::GetWebContents);
}
// static
v8::Local<v8::Value> BrowserWindow::From(v8::Isolate* isolate,
NativeWindow* native_window) {
auto* existing = TrackableObject::FromWrappedClass(isolate, native_window);
if (existing)
return existing->GetWrapper();
else
return v8::Null(isolate);
}
} // namespace api
} // namespace atom
namespace {
using atom::api::BrowserWindow;
using atom::api::TopLevelWindow;
void Initialize(v8::Local<v8::Object> exports,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv) {
v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary dict(isolate, exports);
dict.Set("BrowserWindow", mate::CreateConstructor<BrowserWindow>(
isolate, base::Bind(&BrowserWindow::New)));
}
} // namespace
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_window, Initialize)

View File

@@ -1,126 +0,0 @@
// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_BROWSER_API_ATOM_API_BROWSER_WINDOW_H_
#define ATOM_BROWSER_API_ATOM_API_BROWSER_WINDOW_H_
#include <string>
#include <vector>
#include "atom/browser/api/atom_api_top_level_window.h"
#include "atom/browser/api/atom_api_web_contents.h"
#include "base/cancelable_callback.h"
namespace atom {
namespace api {
class BrowserWindow : public TopLevelWindow,
public content::RenderWidgetHost::InputEventObserver,
public content::WebContentsObserver,
public ExtendedWebContentsObserver {
public:
static mate::WrappableBase* New(mate::Arguments* args);
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype);
// Returns the BrowserWindow object from |native_window|.
static v8::Local<v8::Value> From(v8::Isolate* isolate,
NativeWindow* native_window);
base::WeakPtr<BrowserWindow> GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
protected:
BrowserWindow(v8::Isolate* isolate,
v8::Local<v8::Object> wrapper,
const mate::Dictionary& options);
~BrowserWindow() override;
// content::RenderWidgetHost::InputEventObserver:
void OnInputEvent(const blink::WebInputEvent& event) override;
// content::WebContentsObserver:
void RenderViewHostChanged(content::RenderViewHost* old_host,
content::RenderViewHost* new_host) override;
void RenderViewCreated(content::RenderViewHost* render_view_host) override;
void DidFirstVisuallyNonEmptyPaint() override;
void BeforeUnloadDialogCancelled() override;
void OnRendererUnresponsive(content::RenderProcessHost*) override;
bool OnMessageReceived(const IPC::Message& message,
content::RenderFrameHost* rfh) override;
// ExtendedWebContentsObserver:
void OnCloseContents() override;
void OnRendererResponsive() override;
// NativeWindowObserver:
void RequestPreferredWidth(int* width) override;
void OnCloseButtonClicked(bool* prevent_default) override;
// TopLevelWindow:
void OnWindowClosed() override;
void OnWindowBlur() override;
void OnWindowFocus() override;
void OnWindowResize() override;
void OnWindowLeaveFullScreen() override;
void Focus() override;
void Blur() override;
void SetBackgroundColor(const std::string& color_name) override;
void SetBrowserView(v8::Local<v8::Value> value) override;
void SetVibrancy(v8::Isolate* isolate, v8::Local<v8::Value> value) override;
// BrowserWindow APIs.
void FocusOnWebView();
void BlurWebView();
bool IsWebViewFocused();
v8::Local<v8::Value> GetWebContents(v8::Isolate* isolate);
private:
#if defined(OS_MACOSX)
void OverrideNSWindowContentView(brightray::InspectableWebContents* iwc);
#endif
// Helpers.
// Called when the window needs to update its draggable region.
void UpdateDraggableRegions(content::RenderFrameHost* rfh,
const std::vector<DraggableRegion>& regions);
// Convert draggable regions in raw format to SkRegion format.
std::unique_ptr<SkRegion> DraggableRegionsToSkRegion(
const std::vector<DraggableRegion>& regions);
// Schedule a notification unresponsive event.
void ScheduleUnresponsiveEvent(int ms);
// Dispatch unresponsive event to observers.
void NotifyWindowUnresponsive();
// Cleanup our WebContents observers.
void Cleanup();
// Closure that would be called when window is unresponsive when closing,
// it should be cancelled when we can prove that the window is responsive.
base::CancelableClosure window_unresponsive_closure_;
#if defined(OS_MACOSX)
std::vector<DraggableRegion> draggable_regions_;
#endif
v8::Global<v8::Value> web_contents_;
api::WebContents* api_web_contents_;
base::WeakPtrFactory<BrowserWindow> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(BrowserWindow);
};
} // namespace api
} // namespace atom
#endif // ATOM_BROWSER_API_ATOM_API_BROWSER_WINDOW_H_

View File

@@ -1,130 +0,0 @@
// Copyright (c) 2018 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/api/atom_api_browser_window.h"
#import <Cocoa/Cocoa.h>
#include "atom/browser/native_browser_view.h"
#include "atom/browser/native_window_mac.h"
#include "atom/common/draggable_region.h"
#include "base/mac/scoped_nsobject.h"
#include "brightray/browser/inspectable_web_contents_view.h"
@interface NSView (WebContentsView)
- (void)setMouseDownCanMoveWindow:(BOOL)can_move;
@end
@interface ControlRegionView : NSView
@end
@implementation ControlRegionView
- (BOOL)mouseDownCanMoveWindow {
return NO;
}
- (NSView*)hitTest:(NSPoint)aPoint {
return nil;
}
@end
namespace atom {
namespace api {
namespace {
// Return a vector of non-draggable regions that fill a window of size
// |width| by |height|, but leave gaps where the window should be draggable.
std::vector<gfx::Rect> CalculateNonDraggableRegions(
std::unique_ptr<SkRegion> draggable,
int width,
int height) {
std::vector<gfx::Rect> result;
SkRegion non_draggable;
non_draggable.op(0, 0, width, height, SkRegion::kUnion_Op);
non_draggable.op(*draggable, SkRegion::kDifference_Op);
for (SkRegion::Iterator it(non_draggable); !it.done(); it.next()) {
result.push_back(gfx::SkIRectToRect(it.rect()));
}
return result;
}
} // namespace
void BrowserWindow::OverrideNSWindowContentView(
brightray::InspectableWebContents* iwc) {
// Make NativeWindow use a NSView as content view.
static_cast<NativeWindowMac*>(window())->OverrideNSWindowContentView();
// Add webview to contentView.
NSView* webView = iwc->GetView()->GetNativeView();
NSView* contentView = [window()->GetNativeWindow() contentView];
[webView setFrame:[contentView bounds]];
[contentView addSubview:webView];
[contentView viewDidMoveToWindow];
}
void BrowserWindow::UpdateDraggableRegions(
content::RenderFrameHost* rfh,
const std::vector<DraggableRegion>& regions) {
if (window_->has_frame())
return;
// All ControlRegionViews should be added as children of the WebContentsView,
// because WebContentsView will be removed and re-added when entering and
// leaving fullscreen mode.
NSView* webView = web_contents()->GetNativeView();
NSInteger webViewWidth = NSWidth([webView bounds]);
NSInteger webViewHeight = NSHeight([webView bounds]);
if ([webView respondsToSelector:@selector(setMouseDownCanMoveWindow:)]) {
[webView setMouseDownCanMoveWindow:YES];
}
// Remove all ControlRegionViews 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:[ControlRegionView class]])
[subview removeFromSuperview];
// Draggable regions is implemented by having the whole web view draggable
// (mouseDownCanMoveWindow) and overlaying regions that are not draggable.
draggable_regions_ = regions;
std::vector<gfx::Rect> drag_exclude_rects;
if (regions.empty()) {
drag_exclude_rects.push_back(gfx::Rect(0, 0, webViewWidth, webViewHeight));
} else {
drag_exclude_rects = CalculateNonDraggableRegions(
DraggableRegionsToSkRegion(regions), webViewWidth, webViewHeight);
}
if (window_->browser_view())
window_->browser_view()->UpdateDraggableRegions(drag_exclude_rects);
// Create and add a ControlRegionView for each region that needs to be
// excluded from the dragging.
for (const auto& rect : drag_exclude_rects) {
base::scoped_nsobject<NSView> controlRegion(
[[ControlRegionView alloc] initWithFrame:NSZeroRect]);
[controlRegion setFrame:NSMakeRect(rect.x(), webViewHeight - rect.bottom(),
rect.width(), rect.height())];
[webView addSubview:controlRegion];
}
// AppKit will not update its cache of mouseDownCanMoveWindow unless something
// changes. Previously we tried adding an NSView and removing it, but for some
// reason it required reposting the mouse-down event, and didn't always work.
// Calling the below seems to be an effective solution.
[[webView window] setMovableByWindowBackground:NO];
[[webView window] setMovableByWindowBackground:YES];
}
} // namespace api
} // namespace atom

View File

@@ -1,24 +0,0 @@
// Copyright (c) 2018 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/api/atom_api_browser_window.h"
#include "atom/browser/native_window_views.h"
namespace atom {
namespace api {
void BrowserWindow::UpdateDraggableRegions(
content::RenderFrameHost* rfh,
const std::vector<DraggableRegion>& regions) {
if (window_->has_frame())
return;
static_cast<NativeWindowViews*>(window_.get())
->UpdateDraggableRegions(DraggableRegionsToSkRegion(regions));
}
} // namespace api
} // namespace atom

View File

@@ -1,58 +0,0 @@
// Copyright (c) 2018 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/api/atom_api_button.h"
#include "atom/common/api/constructor.h"
#include "native_mate/dictionary.h"
#include "atom/common/node_includes.h"
namespace atom {
namespace api {
Button::Button(views::Button* button) : View(button) {
view()->set_owned_by_client();
}
Button::~Button() {}
void Button::ButtonPressed(views::Button* sender, const ui::Event& event) {
Emit("click");
}
// static
mate::WrappableBase* Button::New(mate::Arguments* args) {
args->ThrowError("Button can not be created directly");
return nullptr;
}
// static
void Button::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(mate::StringToV8(isolate, "Button"));
}
} // namespace api
} // namespace atom
namespace {
using atom::api::Button;
void Initialize(v8::Local<v8::Object> exports,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv) {
v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary dict(isolate, exports);
dict.Set("Button",
mate::CreateConstructor<Button>(isolate, base::Bind(&Button::New)));
}
} // namespace
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_button, Initialize)

View File

@@ -1,38 +0,0 @@
// 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_API_ATOM_API_BUTTON_H_
#define ATOM_BROWSER_API_ATOM_API_BUTTON_H_
#include "atom/browser/api/atom_api_view.h"
#include "native_mate/handle.h"
#include "ui/views/controls/button/button.h"
namespace atom {
namespace api {
class Button : public View, public views::ButtonListener {
public:
static mate::WrappableBase* New(mate::Arguments* args);
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype);
protected:
explicit Button(views::Button* view);
~Button() override;
// views::ButtonListener:
void ButtonPressed(views::Button* sender, const ui::Event& event) override;
private:
DISALLOW_COPY_AND_ASSIGN(Button);
};
} // namespace api
} // namespace atom
#endif // ATOM_BROWSER_API_ATOM_API_BUTTON_H_

View File

@@ -18,7 +18,7 @@ using content::TracingController;
namespace mate {
template <>
template<>
struct Converter<base::trace_event::TraceConfig> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
@@ -41,39 +41,36 @@ namespace {
using CompletionCallback = base::Callback<void(const base::FilePath&)>;
scoped_refptr<TracingController::TraceDataEndpoint> GetTraceDataEndpoint(
const base::FilePath& path,
const CompletionCallback& callback) {
scoped_refptr<TracingController::TraceDataSink> GetTraceDataSink(
const base::FilePath& path, const CompletionCallback& callback) {
base::FilePath result_file_path = path;
if (result_file_path.empty() && !base::CreateTemporaryFile(&result_file_path))
LOG(ERROR) << "Creating temporary file failed";
return TracingController::CreateFileEndpoint(
result_file_path, base::Bind(callback, result_file_path));
return TracingController::CreateFileSink(result_file_path,
base::Bind(callback,
result_file_path));
}
void StopRecording(const base::FilePath& path,
const CompletionCallback& callback) {
TracingController::GetInstance()->StopTracing(
GetTraceDataEndpoint(path, callback));
GetTraceDataSink(path, callback));
}
void Initialize(v8::Local<v8::Object> exports,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv) {
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) {
auto controller = base::Unretained(TracingController::GetInstance());
mate::Dictionary dict(context->GetIsolate(), exports);
dict.SetMethod("getCategories",
base::Bind(&TracingController::GetCategories, controller));
dict.SetMethod("startRecording",
base::Bind(&TracingController::StartTracing, controller));
dict.SetMethod("getCategories", base::Bind(
&TracingController::GetCategories, controller));
dict.SetMethod("startRecording", base::Bind(
&TracingController::StartTracing, controller));
dict.SetMethod("stopRecording", &StopRecording);
dict.SetMethod(
"getTraceBufferUsage",
base::Bind(&TracingController::GetTraceBufferUsage, controller));
dict.SetMethod("getTraceBufferUsage", base::Bind(
&TracingController::GetTraceBufferUsage, controller));
}
} // namespace
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_content_tracing, Initialize)
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_content_tracing, Initialize)

View File

@@ -5,7 +5,6 @@
#include "atom/browser/api/atom_api_cookies.h"
#include "atom/browser/atom_browser_context.h"
#include "atom/browser/request_context_delegate.h"
#include "atom/common/native_mate_converters/callback.h"
#include "atom/common/native_mate_converters/gurl_converter.h"
#include "atom/common/native_mate_converters/value_converter.h"
@@ -15,17 +14,18 @@
#include "content/public/browser/browser_thread.h"
#include "native_mate/dictionary.h"
#include "native_mate/object_template_builder.h"
#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_monster.h"
#include "net/cookies/cookie_store.h"
#include "net/cookies/cookie_util.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
using atom::AtomCookieDelegate;
using content::BrowserThread;
namespace mate {
template <>
template<>
struct Converter<atom::api::Cookies::Error> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
atom::api::Cookies::Error val) {
@@ -36,7 +36,7 @@ struct Converter<atom::api::Cookies::Error> {
}
};
template <>
template<>
struct Converter<net::CanonicalCookie> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const net::CanonicalCookie& val) {
@@ -55,21 +55,25 @@ struct Converter<net::CanonicalCookie> {
}
};
template <>
struct Converter<net::CookieChangeCause> {
template<>
struct Converter<net::CookieStore::ChangeCause> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const net::CookieChangeCause& val) {
const net::CookieStore::ChangeCause& val) {
switch (val) {
case net::CookieChangeCause::INSERTED:
case net::CookieChangeCause::EXPLICIT:
case net::CookieStore::ChangeCause::INSERTED:
case net::CookieStore::ChangeCause::EXPLICIT:
case net::CookieStore::ChangeCause::EXPLICIT_DELETE_BETWEEN:
case net::CookieStore::ChangeCause::EXPLICIT_DELETE_PREDICATE:
case net::CookieStore::ChangeCause::EXPLICIT_DELETE_SINGLE:
case net::CookieStore::ChangeCause::EXPLICIT_DELETE_CANONICAL:
return mate::StringToV8(isolate, "explicit");
case net::CookieChangeCause::OVERWRITE:
case net::CookieStore::ChangeCause::OVERWRITE:
return mate::StringToV8(isolate, "overwrite");
case net::CookieChangeCause::EXPIRED:
case net::CookieStore::ChangeCause::EXPIRED:
return mate::StringToV8(isolate, "expired");
case net::CookieChangeCause::EVICTED:
case net::CookieStore::ChangeCause::EVICTED:
return mate::StringToV8(isolate, "evicted");
case net::CookieChangeCause::EXPIRED_OVERWRITE:
case net::CookieStore::ChangeCause::EXPIRED_OVERWRITE:
return mate::StringToV8(isolate, "expired-overwrite");
default:
return mate::StringToV8(isolate, "unknown");
@@ -162,16 +166,15 @@ void GetCookiesOnIO(scoped_refptr<net::URLRequestContextGetter> getter,
GetCookieStore(getter)->GetAllCookiesAsync(filtered_callback);
else
GetCookieStore(getter)->GetAllCookiesForURLAsync(GURL(url),
filtered_callback);
filtered_callback);
}
// Removes cookie with |url| and |name| in IO thread.
void RemoveCookieOnIOThread(scoped_refptr<net::URLRequestContextGetter> getter,
const GURL& url,
const std::string& name,
const GURL& url, const std::string& name,
const base::Closure& callback) {
GetCookieStore(getter)->DeleteCookieAsync(
url, name, base::BindOnce(RunCallbackInUI, callback));
url, name, base::Bind(RunCallbackInUI, callback));
}
// Callback of SetCookie.
@@ -184,7 +187,7 @@ void OnSetCookie(const Cookies::SetCallback& callback, bool success) {
void FlushCookieStoreOnIOThread(
scoped_refptr<net::URLRequestContextGetter> getter,
const base::Closure& callback) {
GetCookieStore(getter)->FlushStore(base::BindOnce(RunCallbackInUI, callback));
GetCookieStore(getter)->FlushStore(base::Bind(RunCallbackInUI, callback));
}
// Sets cookie with |details| in IO thread.
@@ -207,106 +210,90 @@ void SetCookieOnIO(scoped_refptr<net::URLRequestContextGetter> getter,
base::Time creation_time;
if (details->GetDouble("creationDate", &creation_date)) {
creation_time = (creation_date == 0)
? base::Time::UnixEpoch()
: base::Time::FromDoubleT(creation_date);
creation_time = (creation_date == 0) ?
base::Time::UnixEpoch() :
base::Time::FromDoubleT(creation_date);
}
base::Time expiration_time;
if (details->GetDouble("expirationDate", &expiration_date)) {
expiration_time = (expiration_date == 0)
? base::Time::UnixEpoch()
: base::Time::FromDoubleT(expiration_date);
expiration_time = (expiration_date == 0) ?
base::Time::UnixEpoch() :
base::Time::FromDoubleT(expiration_date);
}
base::Time last_access_time;
if (details->GetDouble("lastAccessDate", &last_access_date)) {
last_access_time = (last_access_date == 0)
? base::Time::UnixEpoch()
: base::Time::FromDoubleT(last_access_date);
last_access_time = (last_access_date == 0) ?
base::Time::UnixEpoch() :
base::Time::FromDoubleT(last_access_date);
}
std::unique_ptr<net::CanonicalCookie> canonical_cookie(
net::CanonicalCookie::CreateSanitizedCookie(
GURL(url), name, value, domain, path, creation_time, expiration_time,
last_access_time, secure, http_only,
net::CookieSameSite::DEFAULT_MODE, net::COOKIE_PRIORITY_DEFAULT));
auto completion_callback = base::BindOnce(OnSetCookie, callback);
if (!canonical_cookie || !canonical_cookie->IsCanonical()) {
std::move(completion_callback).Run(false);
return;
}
if (url.empty()) {
std::move(completion_callback).Run(false);
return;
}
if (name.empty()) {
std::move(completion_callback).Run(false);
return;
}
GetCookieStore(getter)->SetCanonicalCookieAsync(
std::move(canonical_cookie), secure, http_only,
std::move(completion_callback));
GetCookieStore(getter)->SetCookieWithDetailsAsync(
GURL(url), name, value, domain, path, creation_time,
expiration_time, last_access_time, secure, http_only,
net::CookieSameSite::DEFAULT_MODE, net::COOKIE_PRIORITY_DEFAULT,
base::Bind(OnSetCookie, callback));
}
} // namespace
Cookies::Cookies(v8::Isolate* isolate, AtomBrowserContext* browser_context)
: browser_context_(browser_context) {
Cookies::Cookies(v8::Isolate* isolate,
AtomBrowserContext* browser_context)
: request_context_getter_(browser_context->url_request_context_getter()),
cookie_delegate_(browser_context->cookie_delegate()) {
Init(isolate);
cookie_change_subscription_ =
browser_context->GetRequestContextDelegate()
->RegisterCookieChangeCallback(
base::Bind(&Cookies::OnCookieChanged, base::Unretained(this)));
cookie_delegate_->AddObserver(this);
}
Cookies::~Cookies() {}
Cookies::~Cookies() {
cookie_delegate_->RemoveObserver(this);
}
void Cookies::Get(const base::DictionaryValue& filter,
const GetCallback& callback) {
std::unique_ptr<base::DictionaryValue> copied(filter.CreateDeepCopy());
auto* getter = browser_context_->GetRequestContext();
auto getter = make_scoped_refptr(request_context_getter_);
content::BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(GetCookiesOnIO, base::RetainedRef(getter),
std::move(copied), callback));
base::Bind(GetCookiesOnIO, getter, Passed(&copied), callback));
}
void Cookies::Remove(const GURL& url,
const std::string& name,
void Cookies::Remove(const GURL& url, const std::string& name,
const base::Closure& callback) {
auto* getter = browser_context_->GetRequestContext();
auto getter = make_scoped_refptr(request_context_getter_);
content::BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(RemoveCookieOnIOThread, base::RetainedRef(getter), url,
name, callback));
base::Bind(RemoveCookieOnIOThread, getter, url, name, callback));
}
void Cookies::Set(const base::DictionaryValue& details,
const SetCallback& callback) {
std::unique_ptr<base::DictionaryValue> copied(details.CreateDeepCopy());
auto* getter = browser_context_->GetRequestContext();
auto getter = make_scoped_refptr(request_context_getter_);
content::BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(SetCookieOnIO, base::RetainedRef(getter),
std::move(copied), callback));
base::Bind(SetCookieOnIO, getter, Passed(&copied), callback));
}
void Cookies::FlushStore(const base::Closure& callback) {
auto* getter = browser_context_->GetRequestContext();
auto getter = make_scoped_refptr(request_context_getter_);
content::BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(FlushCookieStoreOnIOThread, base::RetainedRef(getter),
callback));
base::Bind(FlushCookieStoreOnIOThread, getter, callback));
}
void Cookies::OnCookieChanged(const CookieDetails* details) {
Emit("changed", *(details->cookie), details->cause, details->removed);
void Cookies::OnCookieChanged(const net::CanonicalCookie& cookie,
bool removed,
net::CookieStore::ChangeCause cause) {
Emit("changed", cookie, cause, removed);
}
// static
mate::Handle<Cookies> Cookies::Create(v8::Isolate* isolate,
AtomBrowserContext* browser_context) {
mate::Handle<Cookies> Cookies::Create(
v8::Isolate* isolate,
AtomBrowserContext* browser_context) {
return mate::CreateHandle(isolate, new Cookies(isolate, browser_context));
}

View File

@@ -8,8 +8,8 @@
#include <string>
#include "atom/browser/api/trackable_object.h"
#include "atom/browser/net/cookie_details.h"
#include "base/callback_list.h"
#include "atom/browser/net/atom_cookie_delegate.h"
#include "base/callback.h"
#include "native_mate/handle.h"
#include "net/cookies/canonical_cookie.h"
@@ -27,7 +27,8 @@ class AtomBrowserContext;
namespace api {
class Cookies : public mate::TrackableObject<Cookies> {
class Cookies : public mate::TrackableObject<Cookies>,
public AtomCookieDelegate::Observer {
public:
enum Error {
SUCCESS,
@@ -49,19 +50,19 @@ class Cookies : public mate::TrackableObject<Cookies> {
~Cookies() override;
void Get(const base::DictionaryValue& filter, const GetCallback& callback);
void Remove(const GURL& url,
const std::string& name,
void Remove(const GURL& url, const std::string& name,
const base::Closure& callback);
void Set(const base::DictionaryValue& details, const SetCallback& callback);
void FlushStore(const base::Closure& callback);
// AtomBrowserContext::RegisterCookieChangeCallback subscription:
void OnCookieChanged(const CookieDetails*);
// AtomCookieDelegate::Observer:
void OnCookieChanged(const net::CanonicalCookie& cookie,
bool removed,
net::CookieStore::ChangeCause cause) override;
private:
std::unique_ptr<base::CallbackList<void(const CookieDetails*)>::Subscription>
cookie_change_subscription_;
scoped_refptr<AtomBrowserContext> browser_context_;
net::URLRequestContextGetter* request_context_getter_;
scoped_refptr<AtomCookieDelegate> cookie_delegate_;
DISALLOW_COPY_AND_ASSIGN(Cookies);
};

View File

@@ -6,13 +6,14 @@
#include <string>
#include "atom/browser/atom_browser_main_parts.h"
#include "atom/common/native_mate_converters/callback.h"
#include "atom/common/native_mate_converters/value_converter.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/web_contents.h"
#include "native_mate/dictionary.h"
#include "native_mate/object_template_builder.h"
#include "atom/common/node_includes.h"
@@ -23,31 +24,43 @@ namespace atom {
namespace api {
Debugger::Debugger(v8::Isolate* isolate, content::WebContents* web_contents)
: content::WebContentsObserver(web_contents), web_contents_(web_contents) {
: web_contents_(web_contents),
previous_request_id_(0) {
Init(isolate);
}
Debugger::~Debugger() {}
Debugger::~Debugger() {
}
void Debugger::AgentHostClosed(DevToolsAgentHost* agent_host) {
DCHECK(agent_host == agent_host_);
agent_host_ = nullptr;
ClearPendingRequests();
Emit("detach", "target closed");
void Debugger::AgentHostClosed(DevToolsAgentHost* agent_host,
bool replaced_with_another_client) {
std::string detach_reason = "target closed";
if (replaced_with_another_client)
detach_reason = "replaced with devtools";
Emit("detach", detach_reason);
}
void Debugger::DispatchProtocolMessage(DevToolsAgentHost* agent_host,
const std::string& message) {
DCHECK(agent_host == agent_host_);
DCHECK(agent_host == agent_host_.get());
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
std::unique_ptr<base::Value> parsed_message = base::JSONReader::Read(message);
if (!parsed_message || !parsed_message->is_dict())
v8::Local<v8::String> local_message =
v8::String::NewFromUtf8(isolate(), message.data());
v8::MaybeLocal<v8::Value> parsed_message = v8::JSON::Parse(
isolate()->GetCurrentContext(), local_message);
if (parsed_message.IsEmpty()) {
return;
base::DictionaryValue* dict =
static_cast<base::DictionaryValue*>(parsed_message.get());
}
std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
if (!mate::ConvertFromV8(isolate(), parsed_message.ToLocalChecked(),
dict.get())) {
return;
}
int id;
if (!dict->GetInteger("id", &id)) {
std::string method;
@@ -76,52 +89,42 @@ void Debugger::DispatchProtocolMessage(DevToolsAgentHost* agent_host,
}
}
void Debugger::RenderFrameHostChanged(content::RenderFrameHost* old_rfh,
content::RenderFrameHost* new_rfh) {
if (agent_host_) {
agent_host_->DisconnectWebContents();
auto* web_contents = content::WebContents::FromRenderFrameHost(new_rfh);
agent_host_->ConnectWebContents(web_contents);
}
}
void Debugger::Attach(mate::Arguments* args) {
std::string protocol_version;
args->GetNext(&protocol_version);
if (agent_host_) {
args->ThrowError("Debugger is already attached to the target");
return;
}
if (!protocol_version.empty() &&
!DevToolsAgentHost::IsSupportedProtocolVersion(protocol_version)) {
args->ThrowError("Requested protocol version is not supported");
return;
}
agent_host_ = DevToolsAgentHost::GetOrCreateFor(web_contents_);
if (!agent_host_) {
if (!agent_host_.get()) {
args->ThrowError("No target available");
return;
}
if (agent_host_->IsAttached()) {
args->ThrowError("Another debugger is already attached to this target");
return;
}
agent_host_->AttachClient(this);
}
bool Debugger::IsAttached() {
return agent_host_ && agent_host_->IsAttached();
return agent_host_.get() ? agent_host_->IsAttached() : false;
}
void Debugger::Detach() {
if (!agent_host_)
if (!agent_host_.get())
return;
agent_host_->DetachClient(this);
AgentHostClosed(agent_host_.get());
AgentHostClosed(agent_host_.get(), false);
agent_host_ = nullptr;
}
void Debugger::SendCommand(mate::Arguments* args) {
if (!agent_host_)
if (!agent_host_.get())
return;
std::string method;
@@ -140,26 +143,17 @@ void Debugger::SendCommand(mate::Arguments* args) {
request.SetInteger("id", request_id);
request.SetString("method", method);
if (!command_params.empty())
request.Set("params", base::WrapUnique(command_params.DeepCopy()));
request.Set("params", command_params.DeepCopy());
std::string json_args;
base::JSONWriter::Write(request, &json_args);
agent_host_->DispatchProtocolMessage(this, json_args);
}
void Debugger::ClearPendingRequests() {
if (pending_requests_.empty())
return;
base::Value error(base::Value::Type::DICTIONARY);
base::Value error_msg("target closed while handling command");
error.SetKey("message", std::move(error_msg));
for (const auto& it : pending_requests_)
it.second.Run(error, base::Value());
}
// static
mate::Handle<Debugger> Debugger::Create(v8::Isolate* isolate,
content::WebContents* web_contents) {
mate::Handle<Debugger> Debugger::Create(
v8::Isolate* isolate,
content::WebContents* web_contents) {
return mate::CreateHandle(isolate, new Debugger(isolate, web_contents));
}
@@ -182,10 +176,8 @@ namespace {
using atom::api::Debugger;
void Initialize(v8::Local<v8::Object> exports,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv) {
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) {
v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary(isolate, exports)
.Set("Debugger", Debugger::GetConstructor(isolate)->GetFunction());
@@ -193,4 +185,4 @@ void Initialize(v8::Local<v8::Object> exports,
} // namespace
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_debugger, Initialize);
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_debugger, Initialize);

View File

@@ -12,13 +12,12 @@
#include "base/callback.h"
#include "base/values.h"
#include "content/public/browser/devtools_agent_host_client.h"
#include "content/public/browser/web_contents_observer.h"
#include "native_mate/handle.h"
namespace content {
class DevToolsAgentHost;
class WebContents;
} // namespace content
}
namespace mate {
class Arguments;
@@ -28,15 +27,15 @@ namespace atom {
namespace api {
class Debugger : public mate::TrackableObject<Debugger>,
public content::DevToolsAgentHostClient,
public content::WebContentsObserver {
class Debugger: public mate::TrackableObject<Debugger>,
public content::DevToolsAgentHostClient {
public:
using SendCommandCallback =
base::Callback<void(const base::Value&, const base::Value&)>;
base::Callback<void(const base::DictionaryValue&,
const base::DictionaryValue&)>;
static mate::Handle<Debugger> Create(v8::Isolate* isolate,
content::WebContents* web_contents);
static mate::Handle<Debugger> Create(
v8::Isolate* isolate, content::WebContents* web_contents);
// mate::TrackableObject:
static void BuildPrototype(v8::Isolate* isolate,
@@ -47,14 +46,11 @@ class Debugger : public mate::TrackableObject<Debugger>,
~Debugger() override;
// content::DevToolsAgentHostClient:
void AgentHostClosed(content::DevToolsAgentHost* agent_host) override;
void AgentHostClosed(content::DevToolsAgentHost* agent_host,
bool replaced_with_another_client) override;
void DispatchProtocolMessage(content::DevToolsAgentHost* agent_host,
const std::string& message) override;
// content::WebContentsObserver:
void RenderFrameHostChanged(content::RenderFrameHost* old_rfh,
content::RenderFrameHost* new_rfh) override;
private:
using PendingRequestMap = std::map<int, SendCommandCallback>;
@@ -62,13 +58,12 @@ class Debugger : public mate::TrackableObject<Debugger>,
bool IsAttached();
void Detach();
void SendCommand(mate::Arguments* args);
void ClearPendingRequests();
content::WebContents* web_contents_; // Weak Reference.
scoped_refptr<content::DevToolsAgentHost> agent_host_;
PendingRequestMap pending_requests_;
int previous_request_id_ = 0;
int previous_request_id_;
DISALLOW_COPY_AND_ASSIGN(Debugger);
};

View File

@@ -4,172 +4,94 @@
#include "atom/browser/api/atom_api_desktop_capturer.h"
#include <vector>
using base::PlatformThreadRef;
#include "atom/common/api/atom_api_native_image.h"
#include "atom/common/native_mate_converters/gfx_converter.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task_scheduler/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chrome/browser/media/desktop_media_list.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/desktop_capture.h"
#include "native_mate/dictionary.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
#if defined(OS_WIN)
#include "third_party/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h"
#include "third_party/webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h"
#include "ui/display/win/display_info.h"
#endif // defined(OS_WIN)
#include "atom/common/node_includes.h"
namespace mate {
template <>
struct Converter<atom::api::DesktopCapturer::Source> {
static v8::Local<v8::Value> ToV8(
v8::Isolate* isolate,
const atom::api::DesktopCapturer::Source& source) {
template<>
struct Converter<DesktopMediaList::Source> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const DesktopMediaList::Source& source) {
mate::Dictionary dict(isolate, v8::Object::New(isolate));
content::DesktopMediaID id = source.media_list_source.id;
dict.Set("name", base::UTF16ToUTF8(source.media_list_source.name));
content::DesktopMediaID id = source.id;
dict.Set("name", base::UTF16ToUTF8(source.name));
dict.Set("id", id.ToString());
dict.Set("thumbnail",
atom::api::NativeImage::Create(
isolate, gfx::Image(source.media_list_source.thumbnail)));
dict.Set("display_id", source.display_id);
dict.Set(
"thumbnail",
atom::api::NativeImage::Create(isolate, gfx::Image(source.thumbnail)));
return ConvertToV8(isolate, dict);
}
};
} // namespace mate
namespace {
void EmitFinished(
const std::vector<atom::api::DesktopCapturer::Source>& sources,
atom::api::DesktopCapturer* cap) {
cap->Emit("finished", sources);
}
void StartHandlingTask(bool capture_window,
bool capture_screen,
const gfx::Size& thumbnail_size,
atom::api::DesktopCapturer* cap) {
#if defined(OS_WIN)
if (content::desktop_capture::CreateDesktopCaptureOptions()
.allow_directx_capturer()) {
// DxgiDuplicatorController should be alive in this scope according to
// screen_capturer_win.cc.
auto duplicator = webrtc::DxgiDuplicatorController::Instance();
cap->using_directx_capturer_ =
webrtc::ScreenCapturerWinDirectx::IsSupported();
}
#endif // defined(OS_WIN)
std::unique_ptr<webrtc::DesktopCapturer> screen_capturer(
capture_screen ? content::desktop_capture::CreateScreenCapturer()
: nullptr);
std::unique_ptr<webrtc::DesktopCapturer> window_capturer(
capture_window ? content::desktop_capture::CreateWindowCapturer()
: nullptr);
cap->media_list_.reset(new NativeDesktopMediaList(
std::move(screen_capturer), std::move(window_capturer)));
cap->media_list_->SetThumbnailSize(thumbnail_size);
cap->media_list_->StartUpdating(cap);
}
void OnRefreshFinishedTask(atom::api::DesktopCapturer* cap) {
const auto media_list_sources = cap->media_list_->GetSources();
std::vector<atom::api::DesktopCapturer::Source> sources;
for (const auto& media_list_source : media_list_sources) {
sources.emplace_back(
atom::api::DesktopCapturer::Source{media_list_source, std::string()});
}
#if defined(OS_WIN)
// Gather the same unique screen IDs used by the electron.screen API in order
// to provide an association between it and desktopCapturer/getUserMedia.
// This is only required when using the DirectX capturer, otherwise the IDs
// across the APIs already match.
if (cap->using_directx_capturer_) {
std::vector<std::string> device_names;
// Crucially, this list of device names will be in the same order as
// |media_list_sources|.
webrtc::DxgiDuplicatorController::Instance()->GetDeviceNames(&device_names);
int device_name_index = 0;
for (auto& source : sources) {
if (source.media_list_source.id.type ==
content::DesktopMediaID::TYPE_SCREEN) {
const auto& device_name = device_names[device_name_index++];
std::wstring wide_device_name;
base::UTF8ToWide(device_name.c_str(), device_name.size(),
&wide_device_name);
const int64_t device_id =
display::win::DisplayInfo::DeviceIdFromDeviceName(
wide_device_name.c_str());
source.display_id = base::Int64ToString(device_id);
}
}
}
#elif defined(OS_MACOSX)
// On Mac, the IDs across the APIs match.
for (auto& source : sources) {
if (source.media_list_source.id.type ==
content::DesktopMediaID::TYPE_SCREEN) {
source.display_id = base::Int64ToString(source.media_list_source.id.id);
}
}
#endif // defined(OS_WIN)
// TODO(ajmacd): Add Linux support. The IDs across APIs differ but Chrome only
// supports capturing the entire desktop on Linux. Revisit this if individual
// screen support is added.
content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
base::Bind(EmitFinished, sources, cap));
}
} // namespace
namespace atom {
namespace api {
DesktopCapturer::DesktopCapturer(v8::Isolate* isolate) {
Init(isolate);
capture_thread_ = base::CreateSequencedTaskRunnerWithTraits(
{base::WithBaseSyncPrimitives(), base::MayBlock(),
base::TaskPriority::USER_VISIBLE});
}
DesktopCapturer::~DesktopCapturer() {}
DesktopCapturer::~DesktopCapturer() {
}
void DesktopCapturer::StartHandling(bool capture_window,
bool capture_screen,
const gfx::Size& thumbnail_size) {
capture_thread_->PostTask(
FROM_HERE, base::BindOnce(StartHandlingTask, capture_window,
capture_screen, thumbnail_size, this));
webrtc::DesktopCaptureOptions options =
webrtc::DesktopCaptureOptions::CreateDefault();
#if defined(OS_WIN)
// On windows, desktop effects (e.g. Aero) will be disabled when the Desktop
// capture API is active by default.
// We keep the desktop effects in most times. Howerver, the screen still
// fickers when the API is capturing the window due to limitation of current
// implemetation. This is a known and wontFix issue in webrtc (see:
// http://code.google.com/p/webrtc/issues/detail?id=3373)
options.set_disable_effects(false);
#endif
std::unique_ptr<webrtc::DesktopCapturer> screen_capturer(
capture_screen ? webrtc::DesktopCapturer::CreateScreenCapturer(options)
: nullptr);
std::unique_ptr<webrtc::DesktopCapturer> window_capturer(
capture_window ? webrtc::DesktopCapturer::CreateWindowCapturer(options)
: nullptr);
media_list_.reset(new NativeDesktopMediaList(
std::move(screen_capturer), std::move(window_capturer)));
media_list_->SetThumbnailSize(thumbnail_size);
media_list_->StartUpdating(this);
}
void DesktopCapturer::OnSourceAdded(int index) {}
void DesktopCapturer::OnSourceAdded(int index) {
}
void DesktopCapturer::OnSourceRemoved(int index) {}
void DesktopCapturer::OnSourceRemoved(int index) {
}
void DesktopCapturer::OnSourceMoved(int old_index, int new_index) {}
void DesktopCapturer::OnSourceMoved(int old_index, int new_index) {
}
void DesktopCapturer::OnSourceNameChanged(int index) {}
void DesktopCapturer::OnSourceNameChanged(int index) {
}
void DesktopCapturer::OnSourceThumbnailChanged(int index) {}
void DesktopCapturer::OnSourceThumbnailChanged(int index) {
}
bool DesktopCapturer::OnRefreshFinished() {
capture_thread_->PostTask(FROM_HERE,
base::BindOnce(OnRefreshFinishedTask, this));
Emit("finished", media_list_->GetSources());
return false;
}
@@ -180,8 +102,7 @@ mate::Handle<DesktopCapturer> DesktopCapturer::Create(v8::Isolate* isolate) {
// static
void DesktopCapturer::BuildPrototype(
v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) {
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(mate::StringToV8(isolate, "DesktopCapturer"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("startHandling", &DesktopCapturer::StartHandling);
@@ -193,10 +114,8 @@ void DesktopCapturer::BuildPrototype(
namespace {
void Initialize(v8::Local<v8::Object> exports,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv) {
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) {
v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary dict(isolate, exports);
dict.Set("desktopCapturer", atom::api::DesktopCapturer::Create(isolate));
@@ -204,4 +123,4 @@ void Initialize(v8::Local<v8::Object> exports,
} // namespace
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_desktop_capturer, Initialize);
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_desktop_capturer, Initialize);

View File

@@ -5,8 +5,6 @@
#ifndef ATOM_BROWSER_API_ATOM_API_DESKTOP_CAPTURER_H_
#define ATOM_BROWSER_API_ATOM_API_DESKTOP_CAPTURER_H_
#include <string>
#include "atom/browser/api/event_emitter.h"
#include "chrome/browser/media/desktop_media_list_observer.h"
#include "chrome/browser/media/native_desktop_media_list.h"
@@ -16,15 +14,9 @@ namespace atom {
namespace api {
class DesktopCapturer : public mate::EventEmitter<DesktopCapturer>,
public DesktopMediaListObserver {
class DesktopCapturer: public mate::EventEmitter<DesktopCapturer>,
public DesktopMediaListObserver {
public:
struct Source {
DesktopMediaList::Source media_list_source;
// Will be an empty string if not available.
std::string display_id;
};
static mate::Handle<DesktopCapturer> Create(v8::Isolate* isolate);
static void BuildPrototype(v8::Isolate* isolate,
@@ -34,11 +26,6 @@ class DesktopCapturer : public mate::EventEmitter<DesktopCapturer>,
bool capture_screen,
const gfx::Size& thumbnail_size);
std::unique_ptr<DesktopMediaList> media_list_;
#if defined(OS_WIN)
bool using_directx_capturer_ = false;
#endif // defined(OS_WIN)
protected:
explicit DesktopCapturer(v8::Isolate* isolate);
~DesktopCapturer() override;
@@ -52,7 +39,7 @@ class DesktopCapturer : public mate::EventEmitter<DesktopCapturer>,
bool OnRefreshFinished() override;
private:
scoped_refptr<base::SequencedTaskRunner> capture_thread_;
std::unique_ptr<DesktopMediaList> media_list_;
DISALLOW_COPY_AND_ASSIGN(DesktopCapturer);
};

View File

@@ -6,7 +6,7 @@
#include <utility>
#include <vector>
#include "atom/browser/api/atom_api_browser_window.h"
#include "atom/browser/api/atom_api_window.h"
#include "atom/browser/native_window.h"
#include "atom/browser/ui/certificate_trust.h"
#include "atom/browser/ui/file_dialog.h"
@@ -21,7 +21,7 @@
namespace mate {
template <>
template<>
struct Converter<file_dialog::Filter> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
@@ -37,7 +37,7 @@ struct Converter<file_dialog::Filter> {
}
};
template <>
template<>
struct Converter<file_dialog::DialogSettings> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
@@ -54,9 +54,6 @@ struct Converter<file_dialog::DialogSettings> {
dict.Get("filters", &(out->filters));
dict.Get("properties", &(out->properties));
dict.Get("showsTagField", &(out->shows_tag_field));
#if defined(MAS_BUILD)
dict.Get("securityScopedBookmarks", &(out->security_scoped_bookmarks));
#endif
return true;
}
};
@@ -80,7 +77,8 @@ void ShowMessageBox(int type,
mate::Arguments* args) {
v8::Local<v8::Value> peek = args->PeekNext();
atom::MessageBoxCallback callback;
if (mate::Converter<atom::MessageBoxCallback>::FromV8(args->isolate(), peek,
if (mate::Converter<atom::MessageBoxCallback>::FromV8(args->isolate(),
peek,
&callback)) {
atom::ShowMessageBox(window, static_cast<atom::MessageBoxType>(type),
buttons, default_id, cancel_id, options, title,
@@ -98,8 +96,9 @@ void ShowOpenDialog(const file_dialog::DialogSettings& settings,
mate::Arguments* args) {
v8::Local<v8::Value> peek = args->PeekNext();
file_dialog::OpenDialogCallback callback;
if (mate::Converter<file_dialog::OpenDialogCallback>::FromV8(
args->isolate(), peek, &callback)) {
if (mate::Converter<file_dialog::OpenDialogCallback>::FromV8(args->isolate(),
peek,
&callback)) {
file_dialog::ShowOpenDialog(settings, callback);
} else {
std::vector<base::FilePath> paths;
@@ -112,8 +111,9 @@ void ShowSaveDialog(const file_dialog::DialogSettings& settings,
mate::Arguments* args) {
v8::Local<v8::Value> peek = args->PeekNext();
file_dialog::SaveDialogCallback callback;
if (mate::Converter<file_dialog::SaveDialogCallback>::FromV8(
args->isolate(), peek, &callback)) {
if (mate::Converter<file_dialog::SaveDialogCallback>::FromV8(args->isolate(),
peek,
&callback)) {
file_dialog::ShowSaveDialog(settings, callback);
} else {
base::FilePath path;
@@ -122,10 +122,8 @@ void ShowSaveDialog(const file_dialog::DialogSettings& settings,
}
}
void Initialize(v8::Local<v8::Object> exports,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv) {
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) {
mate::Dictionary dict(context->GetIsolate(), exports);
dict.SetMethod("showMessageBox", &ShowMessageBox);
dict.SetMethod("showErrorBox", &atom::ShowErrorBox);
@@ -139,4 +137,4 @@ void Initialize(v8::Local<v8::Object> exports,
} // namespace
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_dialog, Initialize)
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_dialog, Initialize)

View File

@@ -19,23 +19,22 @@
namespace mate {
template <>
struct Converter<download::DownloadItem::DownloadState> {
static v8::Local<v8::Value> ToV8(
v8::Isolate* isolate,
download::DownloadItem::DownloadState state) {
template<>
struct Converter<content::DownloadItem::DownloadState> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
content::DownloadItem::DownloadState state) {
std::string download_state;
switch (state) {
case download::DownloadItem::IN_PROGRESS:
case content::DownloadItem::IN_PROGRESS:
download_state = "progressing";
break;
case download::DownloadItem::COMPLETE:
case content::DownloadItem::COMPLETE:
download_state = "completed";
break;
case download::DownloadItem::CANCELLED:
case content::DownloadItem::CANCELLED:
download_state = "cancelled";
break;
case download::DownloadItem::INTERRUPTED:
case content::DownloadItem::INTERRUPTED:
download_state = "interrupted";
break;
default:
@@ -58,7 +57,7 @@ std::map<uint32_t, v8::Global<v8::Object>> g_download_item_objects;
} // namespace
DownloadItem::DownloadItem(v8::Isolate* isolate,
download::DownloadItem* download_item)
content::DownloadItem* download_item)
: download_item_(download_item) {
download_item_->AddObserver(this);
Init(isolate);
@@ -76,18 +75,18 @@ DownloadItem::~DownloadItem() {
g_download_item_objects.erase(weak_map_id());
}
void DownloadItem::OnDownloadUpdated(download::DownloadItem* item) {
void DownloadItem::OnDownloadUpdated(content::DownloadItem* item) {
if (download_item_->IsDone()) {
Emit("done", item->GetState());
// Destroy the item once item is downloaded.
base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
GetDestroyClosure());
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, GetDestroyClosure());
} else {
Emit("updated", item->GetState());
}
}
void DownloadItem::OnDownloadDestroyed(download::DownloadItem* download_item) {
void DownloadItem::OnDownloadDestroyed(content::DownloadItem* download_item) {
download_item_ = nullptr;
// Destroy the native class immediately when downloadItem is destroyed.
delete this;
@@ -130,11 +129,12 @@ bool DownloadItem::HasUserGesture() const {
}
std::string DownloadItem::GetFilename() const {
return base::UTF16ToUTF8(
net::GenerateFileName(GetURL(), GetContentDisposition(), std::string(),
download_item_->GetSuggestedFilename(),
GetMimeType(), "download")
.LossyDisplayName());
return base::UTF16ToUTF8(net::GenerateFileName(GetURL(),
GetContentDisposition(),
std::string(),
download_item_->GetSuggestedFilename(),
GetMimeType(),
"download").LossyDisplayName());
}
std::string DownloadItem::GetContentDisposition() const {
@@ -149,7 +149,7 @@ const std::vector<GURL>& DownloadItem::GetURLChain() const {
return download_item_->GetUrlChain();
}
download::DownloadItem::DownloadState DownloadItem::GetState() const {
content::DownloadItem::DownloadState DownloadItem::GetState() const {
return download_item_->GetState();
}
@@ -206,9 +206,9 @@ void DownloadItem::BuildPrototype(v8::Isolate* isolate,
}
// static
mate::Handle<DownloadItem> DownloadItem::Create(v8::Isolate* isolate,
download::DownloadItem* item) {
auto* existing = TrackableObject::FromWrappedClass(isolate, item);
mate::Handle<DownloadItem> DownloadItem::Create(
v8::Isolate* isolate, content::DownloadItem* item) {
auto existing = TrackableObject::FromWrappedClass(isolate, item);
if (existing)
return mate::CreateHandle(isolate, static_cast<DownloadItem*>(existing));
@@ -226,10 +226,8 @@ mate::Handle<DownloadItem> DownloadItem::Create(v8::Isolate* isolate,
namespace {
void Initialize(v8::Local<v8::Object> exports,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv) {
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) {
v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary(isolate, exports)
.Set("DownloadItem",
@@ -238,4 +236,4 @@ void Initialize(v8::Local<v8::Object> exports,
} // namespace
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_download_item, Initialize);
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_download_item, Initialize);

View File

@@ -10,7 +10,7 @@
#include "atom/browser/api/trackable_object.h"
#include "base/files/file_path.h"
#include "components/download/public/common/download_item.h"
#include "content/public/browser/download_item.h"
#include "native_mate/handle.h"
#include "url/gurl.h"
@@ -19,10 +19,10 @@ namespace atom {
namespace api {
class DownloadItem : public mate::TrackableObject<DownloadItem>,
public download::DownloadItem::Observer {
public content::DownloadItem::Observer {
public:
static mate::Handle<DownloadItem> Create(v8::Isolate* isolate,
download::DownloadItem* item);
content::DownloadItem* item);
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype);
@@ -40,7 +40,7 @@ class DownloadItem : public mate::TrackableObject<DownloadItem>,
std::string GetContentDisposition() const;
const GURL& GetURL() const;
const std::vector<GURL>& GetURLChain() const;
download::DownloadItem::DownloadState GetState() const;
content::DownloadItem::DownloadState GetState() const;
bool IsDone() const;
void SetSavePath(const base::FilePath& path);
base::FilePath GetSavePath() const;
@@ -49,16 +49,16 @@ class DownloadItem : public mate::TrackableObject<DownloadItem>,
double GetStartTime() const;
protected:
DownloadItem(v8::Isolate* isolate, download::DownloadItem* download_item);
~DownloadItem() override;
DownloadItem(v8::Isolate* isolate, content::DownloadItem* download_item);
~DownloadItem();
// Override download::DownloadItem::Observer methods
void OnDownloadUpdated(download::DownloadItem* download) override;
void OnDownloadDestroyed(download::DownloadItem* download) override;
// Override content::DownloadItem::Observer methods
void OnDownloadUpdated(content::DownloadItem* download) override;
void OnDownloadDestroyed(content::DownloadItem* download) override;
private:
base::FilePath save_path_;
download::DownloadItem* download_item_;
content::DownloadItem* download_item_;
DISALLOW_COPY_AND_ASSIGN(DownloadItem);
};

View File

@@ -40,8 +40,8 @@ void GlobalShortcut::OnKeyPressed(const ui::Accelerator& accelerator) {
bool GlobalShortcut::Register(const ui::Accelerator& accelerator,
const base::Closure& callback) {
if (!GlobalShortcutListener::GetInstance()->RegisterAccelerator(accelerator,
this)) {
if (!GlobalShortcutListener::GetInstance()->RegisterAccelerator(
accelerator, this)) {
return false;
}
@@ -54,8 +54,8 @@ void GlobalShortcut::Unregister(const ui::Accelerator& accelerator) {
return;
accelerator_callback_map_.erase(accelerator);
GlobalShortcutListener::GetInstance()->UnregisterAccelerator(accelerator,
this);
GlobalShortcutListener::GetInstance()->UnregisterAccelerator(
accelerator, this);
}
bool GlobalShortcut::IsRegistered(const ui::Accelerator& accelerator) {
@@ -73,8 +73,8 @@ mate::Handle<GlobalShortcut> GlobalShortcut::Create(v8::Isolate* isolate) {
}
// static
void GlobalShortcut::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) {
void GlobalShortcut::BuildPrototype(
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(mate::StringToV8(isolate, "GlobalShortcut"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("register", &GlobalShortcut::Register)
@@ -89,10 +89,8 @@ void GlobalShortcut::BuildPrototype(v8::Isolate* isolate,
namespace {
void Initialize(v8::Local<v8::Object> exports,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv) {
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) {
v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary dict(isolate, exports);
dict.Set("globalShortcut", atom::api::GlobalShortcut::Create(isolate));
@@ -100,4 +98,4 @@ void Initialize(v8::Local<v8::Object> exports,
} // namespace
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_global_shortcut, Initialize)
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_global_shortcut, Initialize)

View File

@@ -1,142 +0,0 @@
// Copyright (c) 2017 Amaplex Software, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/api/atom_api_in_app_purchase.h"
#include <string>
#include <utility>
#include <vector>
#include "atom/common/native_mate_converters/callback.h"
#include "native_mate/dictionary.h"
#include "atom/common/node_includes.h"
namespace mate {
template <>
struct Converter<in_app_purchase::Payment> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const in_app_purchase::Payment& payment) {
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
dict.SetHidden("simple", true);
dict.Set("productIdentifier", payment.productIdentifier);
dict.Set("quantity", payment.quantity);
return dict.GetHandle();
}
};
template <>
struct Converter<in_app_purchase::Transaction> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const in_app_purchase::Transaction& val) {
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
dict.SetHidden("simple", true);
dict.Set("transactionIdentifier", val.transactionIdentifier);
dict.Set("transactionDate", val.transactionDate);
dict.Set("originalTransactionIdentifier",
val.originalTransactionIdentifier);
dict.Set("transactionState", val.transactionState);
dict.Set("errorCode", val.errorCode);
dict.Set("errorMessage", val.errorMessage);
dict.Set("payment", val.payment);
return dict.GetHandle();
}
};
template <>
struct Converter<in_app_purchase::Product> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const in_app_purchase::Product& val) {
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
dict.SetHidden("simple", true);
dict.Set("productIdentifier", val.productIdentifier);
dict.Set("localizedDescription", val.localizedDescription);
dict.Set("localizedTitle", val.localizedTitle);
dict.Set("contentVersion", val.localizedTitle);
dict.Set("contentLengths", val.contentLengths);
// Pricing Information
dict.Set("price", val.price);
dict.Set("formattedPrice", val.formattedPrice);
// Downloadable Content Information
dict.Set("isDownloadable", val.downloadable);
return dict.GetHandle();
}
};
} // namespace mate
namespace atom {
namespace api {
#if defined(OS_MACOSX)
// static
mate::Handle<InAppPurchase> InAppPurchase::Create(v8::Isolate* isolate) {
return mate::CreateHandle(isolate, new InAppPurchase(isolate));
}
// static
void InAppPurchase::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(mate::StringToV8(isolate, "InAppPurchase"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("canMakePayments", &in_app_purchase::CanMakePayments)
.SetMethod("getReceiptURL", &in_app_purchase::GetReceiptURL)
.SetMethod("purchaseProduct", &InAppPurchase::PurchaseProduct)
.SetMethod("finishAllTransactions",
&in_app_purchase::FinishAllTransactions)
.SetMethod("finishTransactionByDate",
&in_app_purchase::FinishTransactionByDate)
.SetMethod("getProducts", &in_app_purchase::GetProducts);
}
InAppPurchase::InAppPurchase(v8::Isolate* isolate) {
Init(isolate);
}
InAppPurchase::~InAppPurchase() {}
void InAppPurchase::PurchaseProduct(const std::string& product_id,
mate::Arguments* args) {
int quantity = 1;
in_app_purchase::InAppPurchaseCallback callback;
args->GetNext(&quantity);
args->GetNext(&callback);
in_app_purchase::PurchaseProduct(product_id, quantity, callback);
}
void InAppPurchase::OnTransactionsUpdated(
const std::vector<in_app_purchase::Transaction>& transactions) {
Emit("transactions-updated", transactions);
}
#endif
} // namespace api
} // namespace atom
namespace {
using atom::api::InAppPurchase;
void Initialize(v8::Local<v8::Object> exports,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv) {
#if defined(OS_MACOSX)
v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary dict(isolate, exports);
dict.Set("inAppPurchase", InAppPurchase::Create(isolate));
dict.Set("InAppPurchase",
InAppPurchase::GetConstructor(isolate)->GetFunction());
#endif
}
} // namespace
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_in_app_purchase, Initialize)

View File

@@ -1,47 +0,0 @@
// Copyright (c) 2017 Amaplex Software, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_BROWSER_API_ATOM_API_IN_APP_PURCHASE_H_
#define ATOM_BROWSER_API_ATOM_API_IN_APP_PURCHASE_H_
#include <string>
#include <vector>
#include "atom/browser/api/event_emitter.h"
#include "atom/browser/mac/in_app_purchase.h"
#include "atom/browser/mac/in_app_purchase_observer.h"
#include "atom/browser/mac/in_app_purchase_product.h"
#include "native_mate/handle.h"
namespace atom {
namespace api {
class InAppPurchase : public mate::EventEmitter<InAppPurchase>,
public in_app_purchase::TransactionObserver {
public:
static mate::Handle<InAppPurchase> Create(v8::Isolate* isolate);
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype);
protected:
explicit InAppPurchase(v8::Isolate* isolate);
~InAppPurchase() override;
void PurchaseProduct(const std::string& product_id, mate::Arguments* args);
// TransactionObserver:
void OnTransactionsUpdated(
const std::vector<in_app_purchase::Transaction>& transactions) override;
private:
DISALLOW_COPY_AND_ASSIGN(InAppPurchase);
};
} // namespace api
} // namespace atom
#endif // ATOM_BROWSER_API_ATOM_API_IN_APP_PURCHASE_H_

View File

@@ -1,58 +0,0 @@
// Copyright (c) 2018 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/api/atom_api_label_button.h"
#include "atom/common/api/constructor.h"
#include "base/strings/utf_string_conversions.h"
#include "native_mate/dictionary.h"
#include "ui/views/controls/button/label_button.h"
#include "atom/common/node_includes.h"
namespace atom {
namespace api {
LabelButton::LabelButton(const std::string& text)
: Button(new views::LabelButton(this, base::UTF8ToUTF16(text))) {}
LabelButton::~LabelButton() {}
// static
mate::WrappableBase* LabelButton::New(mate::Arguments* args,
const std::string& text) {
// Constructor call.
auto* view = new LabelButton(text);
view->InitWith(args->isolate(), args->GetThis());
return view;
}
// static
void LabelButton::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(mate::StringToV8(isolate, "LabelButton"));
}
} // namespace api
} // namespace atom
namespace {
using atom::api::LabelButton;
void Initialize(v8::Local<v8::Object> exports,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv) {
v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary dict(isolate, exports);
dict.Set("LabelButton", mate::CreateConstructor<LabelButton>(
isolate, base::Bind(&LabelButton::New)));
}
} // namespace
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_label_button, Initialize)

View File

@@ -1,36 +0,0 @@
// 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_API_ATOM_API_LABEL_BUTTON_H_
#define ATOM_BROWSER_API_ATOM_API_LABEL_BUTTON_H_
#include <string>
#include "atom/browser/api/atom_api_button.h"
namespace atom {
namespace api {
class LabelButton : public Button {
public:
static mate::WrappableBase* New(mate::Arguments* args,
const std::string& text);
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype);
protected:
explicit LabelButton(const std::string& text);
~LabelButton() override;
private:
DISALLOW_COPY_AND_ASSIGN(LabelButton);
};
} // namespace api
} // namespace atom
#endif // ATOM_BROWSER_API_ATOM_API_LABEL_BUTTON_H_

View File

@@ -1,63 +0,0 @@
// Copyright (c) 2018 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/api/atom_api_layout_manager.h"
#include "atom/common/api/constructor.h"
#include "native_mate/dictionary.h"
#include "atom/common/node_includes.h"
namespace atom {
namespace api {
LayoutManager::LayoutManager(views::LayoutManager* layout_manager)
: layout_manager_(layout_manager) {
DCHECK(layout_manager_);
}
LayoutManager::~LayoutManager() {
if (managed_by_us_)
delete layout_manager_;
}
std::unique_ptr<views::LayoutManager> LayoutManager::TakeOver() {
if (!managed_by_us_) // already taken over.
return nullptr;
managed_by_us_ = false;
return std::unique_ptr<views::LayoutManager>(layout_manager_);
}
// static
mate::WrappableBase* LayoutManager::New(mate::Arguments* args) {
args->ThrowError("LayoutManager can not be created directly");
return nullptr;
}
// static
void LayoutManager::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) {}
} // namespace api
} // namespace atom
namespace {
using atom::api::LayoutManager;
void Initialize(v8::Local<v8::Object> exports,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv) {
v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary dict(isolate, exports);
dict.Set("LayoutManager", mate::CreateConstructor<LayoutManager>(
isolate, base::Bind(&LayoutManager::New)));
}
} // namespace
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_layout_manager, Initialize)

View File

@@ -1,44 +0,0 @@
// 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_API_ATOM_API_LAYOUT_MANAGER_H_
#define ATOM_BROWSER_API_ATOM_API_LAYOUT_MANAGER_H_
#include <memory>
#include "atom/browser/api/trackable_object.h"
#include "ui/views/layout/layout_manager.h"
namespace atom {
namespace api {
class LayoutManager : public mate::TrackableObject<LayoutManager> {
public:
static mate::WrappableBase* New(mate::Arguments* args);
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype);
// Take over the ownership of the LayoutManager, and leave weak ref here.
std::unique_ptr<views::LayoutManager> TakeOver();
views::LayoutManager* layout_manager() const { return layout_manager_; }
protected:
explicit LayoutManager(views::LayoutManager* layout_manager);
~LayoutManager() override;
private:
bool managed_by_us_ = true;
views::LayoutManager* layout_manager_;
DISALLOW_COPY_AND_ASSIGN(LayoutManager);
};
} // namespace api
} // namespace atom
#endif // ATOM_BROWSER_API_ATOM_API_LAYOUT_MANAGER_H_

View File

@@ -20,15 +20,12 @@ namespace atom {
namespace api {
Menu::Menu(v8::Isolate* isolate, v8::Local<v8::Object> wrapper)
: model_(new AtomMenuModel(this)) {
: model_(new AtomMenuModel(this)),
parent_(nullptr) {
InitWith(isolate, wrapper);
model_->AddObserver(this);
}
Menu::~Menu() {
if (model_) {
model_->RemoveObserver(this);
}
}
void Menu::AfterInit(v8::Isolate* isolate) {
@@ -46,21 +43,15 @@ void Menu::AfterInit(v8::Isolate* isolate) {
}
bool Menu::IsCommandIdChecked(int command_id) const {
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
return is_checked_.Run(GetWrapper(), command_id);
return is_checked_.Run(command_id);
}
bool Menu::IsCommandIdEnabled(int command_id) const {
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
return is_enabled_.Run(GetWrapper(), command_id);
return is_enabled_.Run(command_id);
}
bool Menu::IsCommandIdVisible(int command_id) const {
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
return is_visible_.Run(GetWrapper(), command_id);
return is_visible_.Run(command_id);
}
bool Menu::GetAcceleratorForCommandIdWithParams(
@@ -69,28 +60,23 @@ bool Menu::GetAcceleratorForCommandIdWithParams(
ui::Accelerator* accelerator) const {
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
v8::Local<v8::Value> val =
get_accelerator_.Run(GetWrapper(), command_id, use_default_accelerator);
v8::Local<v8::Value> val = get_accelerator_.Run(
command_id, use_default_accelerator);
return mate::ConvertFromV8(isolate(), val, accelerator);
}
void Menu::ExecuteCommand(int command_id, int flags) {
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
execute_command_.Run(GetWrapper(),
mate::internal::CreateEventFromFlags(isolate(), flags),
command_id);
execute_command_.Run(
mate::internal::CreateEventFromFlags(isolate(), flags),
command_id);
}
void Menu::MenuWillShow(ui::SimpleMenuModel* source) {
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
menu_will_show_.Run(GetWrapper());
menu_will_show_.Run();
}
void Menu::InsertItemAt(int index,
int command_id,
const base::string16& label) {
void Menu::InsertItemAt(
int index, int command_id, const base::string16& label) {
model_->InsertItemAt(index, command_id, label);
}
@@ -167,14 +153,6 @@ bool Menu::IsVisibleAt(int index) const {
return model_->IsVisibleAt(index);
}
void Menu::OnMenuWillClose() {
Emit("menu-will-close");
}
void Menu::OnMenuWillShow() {
Emit("menu-will-show");
}
// static
void Menu::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) {
@@ -206,14 +184,13 @@ void Menu::BuildPrototype(v8::Isolate* isolate,
} // namespace atom
namespace {
using atom::api::Menu;
void Initialize(v8::Local<v8::Object> exports,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv) {
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) {
v8::Isolate* isolate = context->GetIsolate();
Menu::SetConstructor(isolate, base::Bind(&Menu::New));
@@ -228,4 +205,4 @@ void Initialize(v8::Local<v8::Object> exports,
} // namespace
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_menu, Initialize)
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_menu, Initialize)

View File

@@ -8,7 +8,7 @@
#include <memory>
#include <string>
#include "atom/browser/api/atom_api_top_level_window.h"
#include "atom/browser/api/atom_api_window.h"
#include "atom/browser/api/trackable_object.h"
#include "atom/browser/ui/atom_menu_model.h"
#include "base/callback.h"
@@ -18,8 +18,7 @@ namespace atom {
namespace api {
class Menu : public mate::TrackableObject<Menu>,
public AtomMenuModel::Delegate,
public AtomMenuModel::Observer {
public AtomMenuModel::Delegate {
public:
static mate::WrappableBase* New(mate::Arguments* args);
@@ -54,19 +53,12 @@ class Menu : public mate::TrackableObject<Menu>,
void ExecuteCommand(int command_id, int event_flags) override;
void MenuWillShow(ui::SimpleMenuModel* source) override;
virtual void PopupAt(TopLevelWindow* window,
int x,
int y,
int positioning_item,
const base::Closure& callback) = 0;
virtual void PopupAt(
Window* window, int x, int y, int positioning_item, bool async) = 0;
virtual void ClosePopupAt(int32_t window_id) = 0;
std::unique_ptr<AtomMenuModel> model_;
Menu* parent_ = nullptr;
// Observable:
void OnMenuWillClose() override;
void OnMenuWillShow() override;
Menu* parent_;
private:
void InsertItemAt(int index, int command_id, const base::string16& label);
@@ -96,14 +88,12 @@ class Menu : public mate::TrackableObject<Menu>,
bool IsVisibleAt(int index) const;
// Stored delegate methods.
base::Callback<bool(v8::Local<v8::Value>, int)> is_checked_;
base::Callback<bool(v8::Local<v8::Value>, int)> is_enabled_;
base::Callback<bool(v8::Local<v8::Value>, int)> is_visible_;
base::Callback<v8::Local<v8::Value>(v8::Local<v8::Value>, int, bool)>
get_accelerator_;
base::Callback<void(v8::Local<v8::Value>, v8::Local<v8::Value>, int)>
execute_command_;
base::Callback<void(v8::Local<v8::Value>)> menu_will_show_;
base::Callback<bool(int)> is_checked_;
base::Callback<bool(int)> is_enabled_;
base::Callback<bool(int)> is_visible_;
base::Callback<v8::Local<v8::Value>(int, bool)> get_accelerator_;
base::Callback<void(v8::Local<v8::Value>, int)> execute_command_;
base::Callback<void()> menu_will_show_;
DISALLOW_COPY_AND_ASSIGN(Menu);
};
@@ -112,12 +102,12 @@ class Menu : public mate::TrackableObject<Menu>,
} // namespace atom
namespace mate {
template <>
template<>
struct Converter<atom::AtomMenuModel*> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
atom::AtomMenuModel** out) {
// null would be tranfered to NULL.
if (val->IsNull()) {

View File

@@ -21,25 +21,18 @@ namespace api {
class MenuMac : public Menu {
protected:
MenuMac(v8::Isolate* isolate, v8::Local<v8::Object> wrapper);
~MenuMac() override;
void PopupAt(TopLevelWindow* window,
int x,
int y,
int positioning_item,
const base::Closure& callback) override;
void PopupAt(
Window* window, int x, int y, int positioning_item, bool async) override;
void PopupOnUI(const base::WeakPtr<NativeWindow>& native_window,
int32_t window_id,
int x,
int y,
int positioning_item,
base::Closure callback);
int32_t window_id, int x, int y, int positioning_item,
bool async);
void ClosePopupAt(int32_t window_id) override;
private:
friend class Menu;
void OnClosed(int32_t window_id, base::Closure callback);
static void SendActionToFirstResponder(const std::string& action);
scoped_nsobject<AtomMenuController> menu_controller_;

View File

@@ -9,6 +9,8 @@
#include "base/mac/scoped_sending_event.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/sys_string_conversions.h"
#include "brightray/browser/inspectable_web_contents.h"
#include "brightray/browser/inspectable_web_contents_view.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
@@ -16,53 +18,47 @@
using content::BrowserThread;
namespace {
static scoped_nsobject<NSMenu> applicationMenu_;
} // namespace
namespace atom {
namespace api {
MenuMac::MenuMac(v8::Isolate* isolate, v8::Local<v8::Object> wrapper)
: Menu(isolate, wrapper), weak_factory_(this) {}
: Menu(isolate, wrapper),
weak_factory_(this) {
}
MenuMac::~MenuMac() = default;
void MenuMac::PopupAt(TopLevelWindow* window,
int x,
int y,
int positioning_item,
const base::Closure& callback) {
void MenuMac::PopupAt(
Window* window, int x, int y, int positioning_item, bool async) {
NativeWindow* native_window = window->window();
if (!native_window)
return;
auto popup = base::Bind(&MenuMac::PopupOnUI, weak_factory_.GetWeakPtr(),
native_window->GetWeakPtr(), window->weak_map_id(), x,
y, positioning_item, callback);
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, popup);
native_window->GetWeakPtr(), window->ID(), x, y,
positioning_item, async);
if (async)
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, popup);
else
popup.Run();
}
void MenuMac::PopupOnUI(const base::WeakPtr<NativeWindow>& native_window,
int32_t window_id,
int x,
int y,
int positioning_item,
base::Closure callback) {
int32_t window_id, int x, int y, int positioning_item,
bool async) {
if (!native_window)
return;
NSWindow* nswindow = native_window->GetNativeWindow();
brightray::InspectableWebContents* web_contents =
native_window->inspectable_web_contents();
if (!web_contents)
return;
auto close_callback = base::Bind(
&MenuMac::OnClosed, weak_factory_.GetWeakPtr(), window_id, callback);
popup_controllers_[window_id] = base::scoped_nsobject<AtomMenuController>([
[AtomMenuController alloc] initWithModel:model()
useDefaultAccelerator:NO]);
auto close_callback = base::Bind(&MenuMac::ClosePopupAt,
weak_factory_.GetWeakPtr(), window_id);
popup_controllers_[window_id] = base::scoped_nsobject<AtomMenuController>(
[[AtomMenuController alloc] initWithModel:model()
useDefaultAccelerator:NO]);
NSMenu* menu = [popup_controllers_[window_id] menu];
NSView* view = [nswindow contentView];
NSView* view = web_contents->GetView()->GetNativeView();
// Which menu item to show.
NSMenuItem* item = nil;
@@ -72,6 +68,7 @@ void MenuMac::PopupOnUI(const base::WeakPtr<NativeWindow>& native_window,
// (-1, -1) means showing on mouse location.
NSPoint position;
if (x == -1 || y == -1) {
NSWindow* nswindow = native_window->GetNativeWindow();
position = [view convertPoint:[nswindow mouseLocationOutsideOfEventStream]
fromView:nil];
} else {
@@ -95,61 +92,42 @@ void MenuMac::PopupOnUI(const base::WeakPtr<NativeWindow>& native_window,
if (rightmostMenuPoint > screenRight)
position.x = position.x - [menu size].width;
[popup_controllers_[window_id] setCloseCallback:close_callback];
// Make sure events can be pumped while the menu is up.
base::MessageLoop::ScopedNestableTaskAllower allow(
base::MessageLoop::current());
// One of the events that could be pumped is |window.close()|.
// User-initiated event-tracking loops protect against this by
// setting flags in -[CrApplication sendEvent:], but since
// web-content menus are initiated by IPC message the setup has to
// be done manually.
base::mac::ScopedSendingEvent sendingEventScoper;
if (async) {
[popup_controllers_[window_id] setCloseCallback:close_callback];
// Make sure events can be pumped while the menu is up.
base::MessageLoop::ScopedNestableTaskAllower allow(
base::MessageLoop::current());
// Don't emit unresponsive event when showing menu.
atom::UnresponsiveSuppressor suppressor;
[menu popUpMenuPositioningItem:item atLocation:position inView:view];
}
// One of the events that could be pumped is |window.close()|.
// User-initiated event-tracking loops protect against this by
// setting flags in -[CrApplication sendEvent:], but since
// web-content menus are initiated by IPC message the setup has to
// be done manually.
base::mac::ScopedSendingEvent sendingEventScoper;
void MenuMac::ClosePopupAt(int32_t window_id) {
auto controller = popup_controllers_.find(window_id);
if (controller != popup_controllers_.end()) {
// Close the controller for the window.
[controller->second cancel];
} else if (window_id == -1) {
// Or just close all opened controllers.
for (auto it = popup_controllers_.begin();
it != popup_controllers_.end();) {
// The iterator is invalidated after the call.
[(it++)->second cancel];
}
// Don't emit unresponsive event when showing menu.
atom::UnresponsiveSuppressor suppressor;
[menu popUpMenuPositioningItem:item atLocation:position inView:view];
} else {
// Don't emit unresponsive event when showing menu.
atom::UnresponsiveSuppressor suppressor;
[menu popUpMenuPositioningItem:item atLocation:position inView:view];
close_callback.Run();
}
}
void MenuMac::OnClosed(int32_t window_id, base::Closure callback) {
void MenuMac::ClosePopupAt(int32_t window_id) {
popup_controllers_.erase(window_id);
callback.Run();
}
// static
void Menu::SetApplicationMenu(Menu* base_menu) {
MenuMac* menu = static_cast<MenuMac*>(base_menu);
base::scoped_nsobject<AtomMenuController> menu_controller([
[AtomMenuController alloc] initWithModel:menu->model_.get()
useDefaultAccelerator:YES]);
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]];
base::scoped_nsobject<AtomMenuController> menu_controller(
[[AtomMenuController alloc] initWithModel:menu->model_.get()
useDefaultAccelerator:YES]);
[NSApp setMainMenu:[menu_controller menu]];
// Ensure the menu_controller_ is destroyed after main menu is set.
menu_controller.swap(menu->menu_controller_);

View File

@@ -6,6 +6,7 @@
#include "atom/browser/native_window_views.h"
#include "atom/browser/unresponsive_suppressor.h"
#include "content/public/browser/render_widget_host_view.h"
#include "ui/display/screen.h"
using views::MenuRunner;
@@ -15,61 +16,54 @@ namespace atom {
namespace api {
MenuViews::MenuViews(v8::Isolate* isolate, v8::Local<v8::Object> wrapper)
: Menu(isolate, wrapper), weak_factory_(this) {}
: Menu(isolate, wrapper),
weak_factory_(this) {
}
MenuViews::~MenuViews() = default;
void MenuViews::PopupAt(TopLevelWindow* window,
int x,
int y,
int positioning_item,
const base::Closure& callback) {
auto* native_window = static_cast<NativeWindowViews*>(window->window());
void MenuViews::PopupAt(
Window* window, int x, int y, int positioning_item, bool async) {
NativeWindow* native_window = static_cast<NativeWindow*>(window->window());
if (!native_window)
return;
content::WebContents* web_contents = native_window->web_contents();
if (!web_contents)
return;
content::RenderWidgetHostView* view = web_contents->GetRenderWidgetHostView();
if (!view)
return;
// (-1, -1) means showing on mouse location.
gfx::Point location;
if (x == -1 || y == -1) {
location = display::Screen::GetScreen()->GetCursorScreenPoint();
} else {
gfx::Point origin = native_window->GetContentBounds().origin();
gfx::Point origin = view->GetViewBounds().origin();
location = gfx::Point(origin.x() + x, origin.y() + y);
}
int flags = MenuRunner::CONTEXT_MENU | MenuRunner::HAS_MNEMONICS;
if (async)
flags |= MenuRunner::ASYNC;
// Don't emit unresponsive event when showing menu.
atom::UnresponsiveSuppressor suppressor;
// Show the menu.
int32_t window_id = window->weak_map_id();
int32_t window_id = window->ID();
auto close_callback = base::Bind(
&MenuViews::OnClosed, weak_factory_.GetWeakPtr(), window_id, callback);
menu_runners_[window_id] =
std::make_unique<MenuRunner>(model(), flags, close_callback);
menu_runners_[window_id]->RunMenuAt(
native_window->widget(), NULL, gfx::Rect(location, gfx::Size()),
views::MENU_ANCHOR_TOPLEFT, ui::MENU_SOURCE_MOUSE);
&MenuViews::ClosePopupAt, weak_factory_.GetWeakPtr(), window_id);
menu_runners_[window_id] = std::unique_ptr<MenuRunner>(new MenuRunner(
model(), flags, close_callback));
ignore_result(menu_runners_[window_id]->RunMenuAt(
static_cast<NativeWindowViews*>(window->window())->widget(),
NULL,
gfx::Rect(location, gfx::Size()),
views::MENU_ANCHOR_TOPLEFT,
ui::MENU_SOURCE_MOUSE));
}
void MenuViews::ClosePopupAt(int32_t window_id) {
auto runner = menu_runners_.find(window_id);
if (runner != menu_runners_.end()) {
// Close the runner for the window.
runner->second->Cancel();
} else if (window_id == -1) {
// Or just close all opened runners.
for (auto it = menu_runners_.begin(); it != menu_runners_.end();) {
// The iterator is invalidated after the call.
(it++)->second->Cancel();
}
}
}
void MenuViews::OnClosed(int32_t window_id, base::Closure callback) {
menu_runners_.erase(window_id);
callback.Run();
}
// static

View File

@@ -19,19 +19,13 @@ namespace api {
class MenuViews : public Menu {
public:
MenuViews(v8::Isolate* isolate, v8::Local<v8::Object> wrapper);
~MenuViews() override;
protected:
void PopupAt(TopLevelWindow* window,
int x,
int y,
int positioning_item,
const base::Closure& callback) override;
void PopupAt(
Window* window, int x, int y, int positioning_item, bool async) override;
void ClosePopupAt(int32_t window_id) override;
private:
void OnClosed(int32_t window_id, base::Closure callback);
// window ID -> open context menu
std::map<int32_t, std::unique_ptr<views::MenuRunner>> menu_runners_;

View File

@@ -58,4 +58,4 @@ void Initialize(v8::Local<v8::Object> exports,
} // namespace
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_net, Initialize)
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_net, Initialize)

View File

@@ -1,90 +0,0 @@
// Copyright (c) 2018 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/api/atom_api_net_log.h"
#include "atom/browser/atom_browser_client.h"
#include "atom/common/native_mate_converters/callback.h"
#include "atom/common/native_mate_converters/file_path_converter.h"
#include "base/callback.h"
#include "content/public/common/content_switches.h"
#include "native_mate/dictionary.h"
#include "native_mate/handle.h"
#include "atom/common/node_includes.h"
namespace atom {
namespace api {
NetLog::NetLog(v8::Isolate* isolate) {
Init(isolate);
net_log_ = atom::AtomBrowserClient::Get()->GetNetLog();
}
NetLog::~NetLog() {}
// static
v8::Local<v8::Value> NetLog::Create(v8::Isolate* isolate) {
return mate::CreateHandle(isolate, new NetLog(isolate)).ToV8();
}
void NetLog::StartLogging(mate::Arguments* args) {
base::FilePath log_path;
if (!args->GetNext(&log_path) || log_path.empty()) {
args->ThrowError("The first parameter must be a valid string");
return;
}
net_log_->StartDynamicLogging(log_path);
}
bool NetLog::IsCurrentlyLogging() {
return net_log_->IsDynamicLogging();
}
base::FilePath::StringType NetLog::GetCurrentlyLoggingPath() {
return net_log_->GetDynamicLoggingPath().value();
}
void NetLog::StopLogging(mate::Arguments* args) {
base::OnceClosure callback;
args->GetNext(&callback);
net_log_->StopDynamicLogging(std::move(callback));
}
// static
void NetLog::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(mate::StringToV8(isolate, "NetLog"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetProperty("currentlyLogging", &NetLog::IsCurrentlyLogging)
.SetProperty("currentlyLoggingPath", &NetLog::GetCurrentlyLoggingPath)
.SetMethod("startLogging", &NetLog::StartLogging)
.SetMethod("_stopLogging", &NetLog::StopLogging);
}
} // namespace api
} // namespace atom
namespace {
using atom::api::NetLog;
void Initialize(v8::Local<v8::Object> exports,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv) {
v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary dict(isolate, exports);
dict.Set("netLog", NetLog::Create(isolate));
dict.Set("NetLog", NetLog::GetConstructor(isolate)->GetFunction());
}
} // namespace
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_net_log, Initialize)

View File

@@ -1,42 +0,0 @@
// 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_API_ATOM_API_NET_LOG_H_
#define ATOM_BROWSER_API_ATOM_API_NET_LOG_H_
#include <string>
#include "brightray/browser/net_log.h"
#include "native_mate/wrappable.h"
namespace atom {
namespace api {
class NetLog : public mate::Wrappable<NetLog> {
public:
static v8::Local<v8::Value> Create(v8::Isolate* isolate);
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype);
void StartLogging(mate::Arguments* args);
bool IsCurrentlyLogging();
base::FilePath::StringType GetCurrentlyLoggingPath();
void StopLogging(mate::Arguments* args);
protected:
explicit NetLog(v8::Isolate* isolate);
~NetLog() override;
private:
brightray::NetLog* net_log_;
DISALLOW_COPY_AND_ASSIGN(NetLog);
};
} // namespace api
} // namespace atom
#endif // ATOM_BROWSER_API_ATOM_API_NET_LOG_H_

View File

@@ -9,23 +9,19 @@
#include "atom/common/native_mate_converters/gfx_converter.h"
#include "atom/common/native_mate_converters/image_converter.h"
#include "atom/common/native_mate_converters/string16_converter.h"
#include "base/guid.h"
#include "atom/common/node_includes.h"
#include "base/strings/utf_string_conversions.h"
#include "brightray/browser/browser_client.h"
#include "native_mate/constructor.h"
#include "native_mate/dictionary.h"
#include "native_mate/object_template_builder.h"
#include "url/gurl.h"
// Must be the last in the includes list.
// See https://github.com/electron/electron/issues/10363
#include "atom/common/node_includes.h"
namespace mate {
template <>
template<>
struct Converter<brightray::NotificationAction> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
brightray::NotificationAction* out) {
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
brightray::NotificationAction* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
@@ -38,7 +34,7 @@ struct Converter<brightray::NotificationAction> {
}
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
brightray::NotificationAction val) {
brightray::NotificationAction val) {
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
dict.Set("text", val.text);
dict.Set("type", val.type);
@@ -72,7 +68,6 @@ Notification::Notification(v8::Isolate* isolate,
opts.Get("hasReply", &has_reply_);
opts.Get("actions", &actions_);
opts.Get("sound", &sound_);
opts.Get("closeButtonText", &close_button_text_);
}
}
@@ -107,24 +102,20 @@ bool Notification::GetSilent() const {
return silent_;
}
bool Notification::GetHasReply() const {
return has_reply_;
}
base::string16 Notification::GetReplyPlaceholder() const {
return reply_placeholder_;
}
base::string16 Notification::GetSound() const {
return sound_;
bool Notification::GetHasReply() const {
return has_reply_;
}
std::vector<brightray::NotificationAction> Notification::GetActions() const {
return actions_;
}
base::string16 Notification::GetCloseButtonText() const {
return close_button_text_;
base::string16 Notification::GetSound() const {
return sound_;
}
// Setters
@@ -144,25 +135,21 @@ void Notification::SetSilent(bool new_silent) {
silent_ = new_silent;
}
void Notification::SetHasReply(bool new_has_reply) {
has_reply_ = new_has_reply;
}
void Notification::SetReplyPlaceholder(const base::string16& new_placeholder) {
reply_placeholder_ = new_placeholder;
}
void Notification::SetSound(const base::string16& new_sound) {
sound_ = new_sound;
void Notification::SetHasReply(bool new_has_reply) {
has_reply_ = new_has_reply;
}
void Notification::SetActions(
const std::vector<brightray::NotificationAction>& actions) {
const std::vector<brightray::NotificationAction>& actions) {
actions_ = actions;
}
void Notification::SetCloseButtonText(const base::string16& text) {
close_button_text_ = text;
void Notification::SetSound(const base::string16& new_sound) {
sound_ = new_sound;
}
void Notification::NotificationAction(int index) {
@@ -181,24 +168,17 @@ void Notification::NotificationDisplayed() {
Emit("show");
}
void Notification::NotificationDestroyed() {}
void Notification::NotificationClosed() {
void Notification::NotificationDestroyed() {
Emit("close");
}
void Notification::Close() {
if (notification_) {
notification_->Dismiss();
notification_.reset();
}
void Notification::NotificationClosed() {
}
// Showing notifications
void Notification::Show() {
Close();
if (presenter_) {
notification_ = presenter_->CreateNotification(this, base::GenerateGUID());
notification_ = presenter_->CreateNotification(this);
if (notification_) {
brightray::NotificationOptions options;
options.title = title_;
@@ -211,7 +191,6 @@ void Notification::Show() {
options.reply_placeholder = reply_placeholder_;
options.actions = actions_;
options.sound = sound_;
options.close_button_text = close_button_text_;
notification_->Show(options);
}
}
@@ -228,21 +207,19 @@ void Notification::BuildPrototype(v8::Isolate* isolate,
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.MakeDestroyable()
.SetMethod("show", &Notification::Show)
.SetMethod("close", &Notification::Close)
.SetProperty("title", &Notification::GetTitle, &Notification::SetTitle)
.SetProperty("subtitle", &Notification::GetSubtitle,
&Notification::SetSubtitle)
.SetProperty("body", &Notification::GetBody, &Notification::SetBody)
.SetProperty("silent", &Notification::GetSilent, &Notification::SetSilent)
.SetProperty("hasReply", &Notification::GetHasReply,
&Notification::SetHasReply)
.SetProperty("replyPlaceholder", &Notification::GetReplyPlaceholder,
&Notification::SetReplyPlaceholder)
.SetProperty("sound", &Notification::GetSound, &Notification::SetSound)
.SetProperty("hasReply", &Notification::GetHasReply,
&Notification::SetHasReply)
.SetProperty("actions", &Notification::GetActions,
&Notification::SetActions)
.SetProperty("closeButtonText", &Notification::GetCloseButtonText,
&Notification::SetCloseButtonText);
.SetProperty("sound", &Notification::GetSound,
&Notification::SetSound);
}
} // namespace api
@@ -269,4 +246,4 @@ void Initialize(v8::Local<v8::Object> exports,
} // namespace
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_common_notification, Initialize)
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_common_notification, Initialize)

View File

@@ -45,29 +45,26 @@ class Notification : public mate::TrackableObject<Notification>,
~Notification() override;
void Show();
void Close();
// Prop Getters
base::string16 GetTitle() const;
base::string16 GetSubtitle() const;
base::string16 GetBody() const;
bool GetSilent() const;
bool GetHasReply() const;
base::string16 GetReplyPlaceholder() const;
base::string16 GetSound() const;
bool GetHasReply() const;
std::vector<brightray::NotificationAction> GetActions() const;
base::string16 GetCloseButtonText() const;
base::string16 GetSound() const;
// Prop Setters
void SetTitle(const base::string16& new_title);
void SetSubtitle(const base::string16& new_subtitle);
void SetBody(const base::string16& new_body);
void SetSilent(bool new_silent);
void SetHasReply(bool new_has_reply);
void SetReplyPlaceholder(const base::string16& new_reply_placeholder);
void SetSound(const base::string16& sound);
void SetHasReply(bool new_has_reply);
void SetActions(const std::vector<brightray::NotificationAction>& actions);
void SetCloseButtonText(const base::string16& text);
void SetSound(const base::string16& sound);
private:
base::string16 title_;
@@ -77,11 +74,10 @@ class Notification : public mate::TrackableObject<Notification>,
base::string16 icon_path_;
bool has_icon_ = false;
bool silent_ = false;
bool has_reply_ = false;
base::string16 reply_placeholder_;
base::string16 sound_;
bool has_reply_ = false;
std::vector<brightray::NotificationAction> actions_;
base::string16 close_button_text_;
base::string16 sound_;
brightray::NotificationPresenter* presenter_;

View File

@@ -5,70 +5,25 @@
#include "atom/browser/api/atom_api_power_monitor.h"
#include "atom/browser/browser.h"
#include "atom/common/native_mate_converters/callback.h"
#include "base/power_monitor/power_monitor.h"
#include "base/power_monitor/power_monitor_device_source.h"
#include "native_mate/dictionary.h"
#include "atom/common/node_includes.h"
namespace mate {
template <>
struct Converter<ui::IdleState> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const ui::IdleState& in) {
switch (in) {
case ui::IDLE_STATE_ACTIVE:
return mate::StringToV8(isolate, "active");
case ui::IDLE_STATE_IDLE:
return mate::StringToV8(isolate, "idle");
case ui::IDLE_STATE_LOCKED:
return mate::StringToV8(isolate, "locked");
case ui::IDLE_STATE_UNKNOWN:
default:
return mate::StringToV8(isolate, "unknown");
}
}
};
} // namespace mate
namespace atom {
namespace api {
PowerMonitor::PowerMonitor(v8::Isolate* isolate) {
#if defined(OS_LINUX)
SetShutdownHandler(
base::Bind(&PowerMonitor::ShouldShutdown, base::Unretained(this)));
#elif defined(OS_MACOSX)
Browser::Get()->SetShutdownHandler(
base::Bind(&PowerMonitor::ShouldShutdown, base::Unretained(this)));
#endif
base::PowerMonitor::Get()->AddObserver(this);
Init(isolate);
#if defined(OS_MACOSX) || defined(OS_WIN)
InitPlatformSpecificMonitors();
#endif
}
PowerMonitor::~PowerMonitor() {
base::PowerMonitor::Get()->RemoveObserver(this);
}
bool PowerMonitor::ShouldShutdown() {
return !Emit("shutdown");
}
#if defined(OS_LINUX)
void PowerMonitor::BlockShutdown() {
PowerObserverLinux::BlockShutdown();
}
void PowerMonitor::UnblockShutdown() {
PowerObserverLinux::UnblockShutdown();
}
#endif
void PowerMonitor::OnPowerStateChange(bool on_battery_power) {
if (on_battery_power)
Emit("on-battery");
@@ -84,21 +39,6 @@ void PowerMonitor::OnResume() {
Emit("resume");
}
void PowerMonitor::QuerySystemIdleState(v8::Isolate* isolate,
int idle_threshold,
const ui::IdleCallback& callback) {
if (idle_threshold > 0) {
ui::CalculateIdleState(idle_threshold, callback);
} else {
isolate->ThrowException(v8::Exception::TypeError(mate::StringToV8(
isolate, "Invalid idle threshold, must be greater than 0")));
}
}
void PowerMonitor::QuerySystemIdleTime(const ui::IdleTimeCallback& callback) {
ui::CalculateIdleTime(callback);
}
// static
v8::Local<v8::Value> PowerMonitor::Create(v8::Isolate* isolate) {
if (!Browser::Get()->is_ready()) {
@@ -112,32 +52,26 @@ v8::Local<v8::Value> PowerMonitor::Create(v8::Isolate* isolate) {
}
// static
void PowerMonitor::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) {
void PowerMonitor::BuildPrototype(
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(mate::StringToV8(isolate, "PowerMonitor"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.MakeDestroyable()
#if defined(OS_LINUX)
.SetMethod("blockShutdown", &PowerMonitor::BlockShutdown)
.SetMethod("unblockShutdown", &PowerMonitor::UnblockShutdown)
#endif
.SetMethod("querySystemIdleState", &PowerMonitor::QuerySystemIdleState)
.SetMethod("querySystemIdleTime", &PowerMonitor::QuerySystemIdleTime);
}
} // namespace api
} // namespace atom
namespace {
using atom::api::PowerMonitor;
void Initialize(v8::Local<v8::Object> exports,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv) {
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) {
#if defined(OS_MACOSX)
base::PowerMonitorDeviceSource::AllocateSystemIOPorts();
#endif
v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary dict(isolate, exports);
dict.Set("powerMonitor", PowerMonitor::Create(isolate));
@@ -147,4 +81,4 @@ void Initialize(v8::Local<v8::Object> exports,
} // namespace
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_power_monitor, Initialize)
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_power_monitor, Initialize)

View File

@@ -6,17 +6,16 @@
#define ATOM_BROWSER_API_ATOM_API_POWER_MONITOR_H_
#include "atom/browser/api/trackable_object.h"
#include "atom/browser/lib/power_observer.h"
#include "base/compiler_specific.h"
#include "base/power_monitor/power_observer.h"
#include "native_mate/handle.h"
#include "ui/base/idle/idle.h"
namespace atom {
namespace api {
class PowerMonitor : public mate::TrackableObject<PowerMonitor>,
public PowerObserver {
public base::PowerObserver {
public:
static v8::Local<v8::Value> Create(v8::Isolate* isolate);
@@ -27,52 +26,12 @@ class PowerMonitor : public mate::TrackableObject<PowerMonitor>,
explicit PowerMonitor(v8::Isolate* isolate);
~PowerMonitor() override;
// Called by native calles.
bool ShouldShutdown();
#if defined(OS_LINUX)
// Private JS APIs.
void BlockShutdown();
void UnblockShutdown();
#endif
#if defined(OS_MACOSX) || defined(OS_WIN)
void InitPlatformSpecificMonitors();
#endif
// base::PowerObserver implementations:
void OnPowerStateChange(bool on_battery_power) override;
void OnSuspend() override;
void OnResume() override;
private:
void QuerySystemIdleState(v8::Isolate* isolate,
int idle_threshold,
const ui::IdleCallback& callback);
void QuerySystemIdleTime(const ui::IdleTimeCallback& callback);
#if defined(OS_WIN)
// Static callback invoked when a message comes in to our messaging window.
static LRESULT CALLBACK WndProcStatic(HWND hwnd,
UINT message,
WPARAM wparam,
LPARAM lparam);
LRESULT CALLBACK WndProc(HWND hwnd,
UINT message,
WPARAM wparam,
LPARAM lparam);
// The window class of |window_|.
ATOM atom_;
// The handle of the module that contains the window procedure of |window_|.
HMODULE instance_;
// The window used for processing events.
HWND window_;
#endif
DISALLOW_COPY_AND_ASSIGN(PowerMonitor);
};

View File

@@ -1,74 +0,0 @@
// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/api/atom_api_power_monitor.h"
#include <ApplicationServices/ApplicationServices.h>
#import <Cocoa/Cocoa.h>
@interface MacLockMonitor : NSObject {
@private
std::vector<atom::api::PowerMonitor*> emitters;
}
- (void)addEmitter:(atom::api::PowerMonitor*)monitor_;
@end
@implementation MacLockMonitor
- (id)init {
if ((self = [super init])) {
NSDistributedNotificationCenter* distCenter =
[NSDistributedNotificationCenter defaultCenter];
[distCenter addObserver:self
selector:@selector(onScreenLocked:)
name:@"com.apple.screenIsLocked"
object:nil];
[distCenter addObserver:self
selector:@selector(onScreenUnlocked:)
name:@"com.apple.screenIsUnlocked"
object:nil];
}
return self;
}
- (void)dealloc {
[[NSDistributedNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
- (void)addEmitter:(atom::api::PowerMonitor*)monitor_ {
self->emitters.push_back(monitor_);
}
- (void)onScreenLocked:(NSNotification*)notification {
for (auto*& emitter : self->emitters) {
emitter->Emit("lock-screen");
}
}
- (void)onScreenUnlocked:(NSNotification*)notification {
for (auto*& emitter : self->emitters) {
emitter->Emit("unlock-screen");
}
}
@end
namespace atom {
namespace api {
static MacLockMonitor* g_lock_monitor = nil;
void PowerMonitor::InitPlatformSpecificMonitors() {
if (!g_lock_monitor)
g_lock_monitor = [[MacLockMonitor alloc] init];
[g_lock_monitor addEmitter:this];
}
} // namespace api
} // namespace atom

View File

@@ -1,71 +0,0 @@
// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/api/atom_api_power_monitor.h"
#include "base/win/wrapped_window_proc.h"
#include "ui/base/win/shell.h"
#include "ui/gfx/win/hwnd_util.h"
#include "Wtsapi32.h"
namespace atom {
namespace {
const wchar_t kPowerMonitorWindowClass[] =
L"Electron_PowerMonitorHostWindow";
} // namespace
namespace api {
void PowerMonitor::InitPlatformSpecificMonitors() {
WNDCLASSEX window_class;
base::win::InitializeWindowClass(
kPowerMonitorWindowClass,
&base::win::WrappedWindowProc<PowerMonitor::WndProcStatic>, 0, 0, 0,
NULL, NULL, NULL, NULL, NULL, &window_class);
instance_ = window_class.hInstance;
atom_ = RegisterClassEx(&window_class);
// Create an offscreen window for receiving broadcast messages for the
// session lock and unlock events.
window_ = CreateWindow(MAKEINTATOM(atom_), 0, 0, 0, 0, 0, 0, HWND_MESSAGE, 0,
instance_, 0);
gfx::CheckWindowCreated(window_);
gfx::SetWindowUserData(window_, this);
// Tel windows we want to be notified with session events
WTSRegisterSessionNotification(window_, NOTIFY_FOR_THIS_SESSION);
}
LRESULT CALLBACK PowerMonitor::WndProcStatic(HWND hwnd,
UINT message,
WPARAM wparam,
LPARAM lparam) {
PowerMonitor* msg_wnd = reinterpret_cast<PowerMonitor*>(
GetWindowLongPtr(hwnd, GWLP_USERDATA));
if (msg_wnd)
return msg_wnd->WndProc(hwnd, message, wparam, lparam);
else
return ::DefWindowProc(hwnd, message, wparam, lparam);
}
LRESULT CALLBACK PowerMonitor::WndProc(HWND hwnd,
UINT message,
WPARAM wparam,
LPARAM lparam) {
if (message == WM_WTSSESSION_CHANGE) {
if (wparam == WTS_SESSION_LOCK) {
Emit("lock-screen");
} else if (wparam == WTS_SESSION_UNLOCK) {
Emit("unlock-screen");
}
}
return ::DefWindowProc(hwnd, message, wparam, lparam);
}
} // namespace api
} // namespace atom

View File

@@ -6,26 +6,28 @@
#include <string>
#include "base/task_scheduler/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/public/browser/browser_thread.h"
#include "native_mate/dictionary.h"
#include "atom/common/node_includes.h"
using content::BrowserThread;
namespace mate {
template <>
struct Converter<device::mojom::WakeLockType> {
template<>
struct Converter<device::PowerSaveBlocker::PowerSaveBlockerType> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
device::mojom::WakeLockType* out) {
device::PowerSaveBlocker::PowerSaveBlockerType* out) {
using device::PowerSaveBlocker;
std::string type;
if (!ConvertFromV8(isolate, val, &type))
return false;
if (type == "prevent-app-suspension")
*out = device::mojom::WakeLockType::kPreventAppSuspension;
*out = PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension;
else if (type == "prevent-display-sleep")
*out = device::mojom::WakeLockType::kPreventDisplaySleep;
*out = PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep;
else
return false;
return true;
@@ -40,11 +42,12 @@ namespace api {
PowerSaveBlocker::PowerSaveBlocker(v8::Isolate* isolate)
: current_blocker_type_(
device::mojom::WakeLockType::kPreventAppSuspension) {
device::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension) {
Init(isolate);
}
PowerSaveBlocker::~PowerSaveBlocker() {}
PowerSaveBlocker::~PowerSaveBlocker() {
}
void PowerSaveBlocker::UpdatePowerSaveBlocker() {
if (power_save_blocker_types_.empty()) {
@@ -52,39 +55,38 @@ void PowerSaveBlocker::UpdatePowerSaveBlocker() {
return;
}
// |WakeLockType::kPreventAppSuspension| keeps system active, but allows
// |kPowerSaveBlockPreventAppSuspension| keeps system active, but allows
// screen to be turned off.
// |WakeLockType::kPreventDisplaySleep| keeps system and screen active, has a
// higher precedence level than |WakeLockType::kPreventAppSuspension|.
// |kPowerSaveBlockPreventDisplaySleep| keeps system and screen active, has a
// higher precedence level than |kPowerSaveBlockPreventAppSuspension|.
//
// Only the highest-precedence blocker type takes effect.
device::mojom::WakeLockType new_blocker_type =
device::mojom::WakeLockType::kPreventAppSuspension;
device::PowerSaveBlocker::PowerSaveBlockerType new_blocker_type =
device::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension;
for (const auto& element : power_save_blocker_types_) {
if (element.second ==
device::mojom::WakeLockType::kPreventDisplaySleep) {
device::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep) {
new_blocker_type =
device::mojom::WakeLockType::kPreventDisplaySleep;
device::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep;
break;
}
}
if (!power_save_blocker_ || new_blocker_type != current_blocker_type_) {
auto new_blocker = std::make_unique<device::PowerSaveBlocker>(
new_blocker_type, device::mojom::WakeLockReason::kOther,
ATOM_PRODUCT_NAME, base::ThreadTaskRunnerHandle::Get(),
// This task runner may be used by some device service
// implementation bits to interface with dbus client code, which in
// turn imposes some subtle thread affinity on the clients. We
// therefore require a single-thread runner.
base::CreateSingleThreadTaskRunnerWithTraits(
{base::MayBlock(), base::TaskPriority::BACKGROUND}));
std::unique_ptr<device::PowerSaveBlocker> new_blocker(
new device::PowerSaveBlocker(
new_blocker_type,
device::PowerSaveBlocker::kReasonOther,
ATOM_PRODUCT_NAME,
BrowserThread::GetTaskRunnerForThread(BrowserThread::UI),
BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE)));
power_save_blocker_.swap(new_blocker);
current_blocker_type_ = new_blocker_type;
}
}
int PowerSaveBlocker::Start(device::mojom::WakeLockType type) {
int PowerSaveBlocker::Start(
device::PowerSaveBlocker::PowerSaveBlockerType type) {
static int count = 0;
power_save_blocker_types_[count] = type;
UpdatePowerSaveBlocker();
@@ -108,8 +110,7 @@ mate::Handle<PowerSaveBlocker> PowerSaveBlocker::Create(v8::Isolate* isolate) {
// static
void PowerSaveBlocker::BuildPrototype(
v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) {
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(mate::StringToV8(isolate, "PowerSaveBlocker"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("start", &PowerSaveBlocker::Start)
@@ -123,10 +124,8 @@ void PowerSaveBlocker::BuildPrototype(
namespace {
void Initialize(v8::Local<v8::Object> exports,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv) {
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) {
v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary dict(isolate, exports);
dict.Set("powerSaveBlocker", atom::api::PowerSaveBlocker::Create(isolate));
@@ -134,4 +133,4 @@ void Initialize(v8::Local<v8::Object> exports,
} // namespace
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_power_save_blocker, Initialize);
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_power_save_blocker, Initialize);

View File

@@ -9,8 +9,8 @@
#include <memory>
#include "atom/browser/api/trackable_object.h"
#include "device/power_save_blocker/power_save_blocker.h"
#include "native_mate/handle.h"
#include "services/device/wake_lock/power_save_blocker/power_save_blocker.h"
namespace mate {
class Dictionary;
@@ -33,18 +33,19 @@ class PowerSaveBlocker : public mate::TrackableObject<PowerSaveBlocker> {
private:
void UpdatePowerSaveBlocker();
int Start(device::mojom::WakeLockType type);
int Start(device::PowerSaveBlocker::PowerSaveBlockerType type);
bool Stop(int id);
bool IsStarted(int id);
std::unique_ptr<device::PowerSaveBlocker> power_save_blocker_;
// Current blocker type used by |power_save_blocker_|
device::mojom::WakeLockType current_blocker_type_;
// Currnet blocker type used by |power_save_blocker_|
device::PowerSaveBlocker::PowerSaveBlockerType current_blocker_type_;
// Map from id to the corresponding blocker type for each request.
using WakeLockTypeMap = std::map<int, device::mojom::WakeLockType>;
WakeLockTypeMap power_save_blocker_types_;
using PowerSaveBlockerTypeMap =
std::map<int, device::PowerSaveBlocker::PowerSaveBlockerType>;
PowerSaveBlockerTypeMap power_save_blocker_types_;
DISALLOW_COPY_AND_ASSIGN(PowerSaveBlocker);
};

View File

@@ -10,7 +10,6 @@
#include "atom/browser/net/url_request_async_asar_job.h"
#include "atom/browser/net/url_request_buffer_job.h"
#include "atom/browser/net/url_request_fetch_job.h"
#include "atom/browser/net/url_request_stream_job.h"
#include "atom/browser/net/url_request_string_job.h"
#include "atom/common/native_mate_converters/callback.h"
#include "atom/common/native_mate_converters/value_converter.h"
@@ -33,6 +32,14 @@ namespace {
// List of registered custom standard schemes.
std::vector<std::string> g_standard_schemes;
// Clear protocol handlers in IO thread.
void ClearJobFactoryInIO(
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter) {
auto job_factory = static_cast<AtomURLRequestJobFactory*>(
request_context_getter->job_factory());
job_factory->Clear();
}
} // namespace
std::vector<std::string> GetStandardSchemes() {
@@ -63,39 +70,44 @@ void RegisterStandardSchemes(const std::vector<std::string>& schemes,
atom::switches::kStandardSchemes, base::JoinString(schemes, ","));
if (secure) {
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
atom::switches::kSecureSchemes, base::JoinString(schemes, ","));
atom::switches::kSecureSchemes, base::JoinString(schemes, ","));
}
}
Protocol::Protocol(v8::Isolate* isolate, AtomBrowserContext* browser_context)
: browser_context_(browser_context), weak_factory_(this) {
: request_context_getter_(browser_context->GetRequestContext()),
weak_factory_(this) {
Init(isolate);
}
Protocol::~Protocol() {}
Protocol::~Protocol() {
content::BrowserThread::PostTask(
content::BrowserThread::IO, FROM_HERE,
base::Bind(ClearJobFactoryInIO, request_context_getter_));
}
void Protocol::RegisterServiceWorkerSchemes(
const std::vector<std::string>& schemes) {
atom::AtomBrowserClient::SetCustomServiceWorkerSchemes(schemes);
}
void Protocol::UnregisterProtocol(const std::string& scheme,
mate::Arguments* args) {
void Protocol::UnregisterProtocol(
const std::string& scheme, mate::Arguments* args) {
CompletionCallback callback;
args->GetNext(&callback);
auto* getter = browser_context_->GetRequestContext();
content::BrowserThread::PostTaskAndReplyWithResult(
content::BrowserThread::IO, FROM_HERE,
base::BindOnce(&Protocol::UnregisterProtocolInIO,
base::RetainedRef(getter), scheme),
base::BindOnce(&Protocol::OnIOCompleted, GetWeakPtr(), callback));
base::Bind(&Protocol::UnregisterProtocolInIO,
request_context_getter_, scheme),
base::Bind(&Protocol::OnIOCompleted,
GetWeakPtr(), callback));
}
// static
Protocol::ProtocolError Protocol::UnregisterProtocolInIO(
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter,
const std::string& scheme) {
auto* job_factory = static_cast<AtomURLRequestJobFactory*>(
auto job_factory = static_cast<AtomURLRequestJobFactory*>(
request_context_getter->job_factory());
if (!job_factory->HasProtocolHandler(scheme))
return PROTOCOL_NOT_REGISTERED;
@@ -105,11 +117,10 @@ Protocol::ProtocolError Protocol::UnregisterProtocolInIO(
void Protocol::IsProtocolHandled(const std::string& scheme,
const BooleanCallback& callback) {
auto* getter = browser_context_->GetRequestContext();
content::BrowserThread::PostTaskAndReplyWithResult(
content::BrowserThread::IO, FROM_HERE,
base::Bind(&Protocol::IsProtocolHandledInIO, base::RetainedRef(getter),
scheme),
base::Bind(&Protocol::IsProtocolHandledInIO,
request_context_getter_, scheme),
callback);
}
@@ -120,16 +131,16 @@ bool Protocol::IsProtocolHandledInIO(
return request_context_getter->job_factory()->IsHandledProtocol(scheme);
}
void Protocol::UninterceptProtocol(const std::string& scheme,
mate::Arguments* args) {
void Protocol::UninterceptProtocol(
const std::string& scheme, mate::Arguments* args) {
CompletionCallback callback;
args->GetNext(&callback);
auto* getter = browser_context_->GetRequestContext();
content::BrowserThread::PostTaskAndReplyWithResult(
content::BrowserThread::IO, FROM_HERE,
base::BindOnce(&Protocol::UninterceptProtocolInIO,
base::RetainedRef(getter), scheme),
base::BindOnce(&Protocol::OnIOCompleted, GetWeakPtr(), callback));
base::Bind(&Protocol::UninterceptProtocolInIO,
request_context_getter_, scheme),
base::Bind(&Protocol::OnIOCompleted,
GetWeakPtr(), callback));
}
// static
@@ -137,14 +148,12 @@ Protocol::ProtocolError Protocol::UninterceptProtocolInIO(
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter,
const std::string& scheme) {
return static_cast<AtomURLRequestJobFactory*>(
request_context_getter->job_factory())
->UninterceptProtocol(scheme)
? PROTOCOL_OK
: PROTOCOL_NOT_INTERCEPTED;
request_context_getter->job_factory())->UninterceptProtocol(scheme) ?
PROTOCOL_OK : PROTOCOL_NOT_INTERCEPTED;
}
void Protocol::OnIOCompleted(const CompletionCallback& callback,
ProtocolError error) {
void Protocol::OnIOCompleted(
const CompletionCallback& callback, ProtocolError error) {
// The completion callback is optional.
if (callback.is_null())
return;
@@ -162,30 +171,31 @@ void Protocol::OnIOCompleted(const CompletionCallback& callback,
std::string Protocol::ErrorCodeToString(ProtocolError error) {
switch (error) {
case PROTOCOL_FAIL:
return "Failed to manipulate protocol factory";
case PROTOCOL_REGISTERED:
return "The scheme has been registered";
case PROTOCOL_NOT_REGISTERED:
return "The scheme has not been registered";
case PROTOCOL_INTERCEPTED:
return "The scheme has been intercepted";
case PROTOCOL_NOT_INTERCEPTED:
return "The scheme has not been intercepted";
default:
return "Unexpected error";
case PROTOCOL_FAIL: return "Failed to manipulate protocol factory";
case PROTOCOL_REGISTERED: return "The scheme has been registered";
case PROTOCOL_NOT_REGISTERED: return "The scheme has not been registered";
case PROTOCOL_INTERCEPTED: return "The scheme has been intercepted";
case PROTOCOL_NOT_INTERCEPTED: return "The scheme has not been intercepted";
default: return "Unexpected error";
}
}
AtomURLRequestJobFactory* Protocol::GetJobFactoryInIO() const {
request_context_getter_->GetURLRequestContext(); // Force init.
return static_cast<AtomURLRequestJobFactory*>(
static_cast<brightray::URLRequestContextGetter*>(
request_context_getter_.get())->job_factory());
}
// static
mate::Handle<Protocol> Protocol::Create(v8::Isolate* isolate,
AtomBrowserContext* browser_context) {
mate::Handle<Protocol> Protocol::Create(
v8::Isolate* isolate, AtomBrowserContext* browser_context) {
return mate::CreateHandle(isolate, new Protocol(isolate, browser_context));
}
// static
void Protocol::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) {
void Protocol::BuildPrototype(
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(mate::StringToV8(isolate, "Protocol"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("registerServiceWorkerSchemes",
@@ -198,8 +208,6 @@ void Protocol::BuildPrototype(v8::Isolate* isolate,
&Protocol::RegisterProtocol<URLRequestAsyncAsarJob>)
.SetMethod("registerHttpProtocol",
&Protocol::RegisterProtocol<URLRequestFetchJob>)
.SetMethod("registerStreamProtocol",
&Protocol::RegisterProtocol<URLRequestStreamJob>)
.SetMethod("unregisterProtocol", &Protocol::UnregisterProtocol)
.SetMethod("isProtocolHandled", &Protocol::IsProtocolHandled)
.SetMethod("interceptStringProtocol",
@@ -210,8 +218,6 @@ void Protocol::BuildPrototype(v8::Isolate* isolate,
&Protocol::InterceptProtocol<URLRequestAsyncAsarJob>)
.SetMethod("interceptHttpProtocol",
&Protocol::InterceptProtocol<URLRequestFetchJob>)
.SetMethod("interceptStreamProtocol",
&Protocol::InterceptProtocol<URLRequestStreamJob>)
.SetMethod("uninterceptProtocol", &Protocol::UninterceptProtocol);
}
@@ -221,22 +227,19 @@ void Protocol::BuildPrototype(v8::Isolate* isolate,
namespace {
void RegisterStandardSchemes(const std::vector<std::string>& schemes,
mate::Arguments* args) {
void RegisterStandardSchemes(
const std::vector<std::string>& schemes, mate::Arguments* args) {
if (atom::Browser::Get()->is_ready()) {
args->ThrowError(
"protocol.registerStandardSchemes should be called before "
"app is ready");
args->ThrowError("protocol.registerStandardSchemes should be called before "
"app is ready");
return;
}
atom::api::RegisterStandardSchemes(schemes, args);
}
void Initialize(v8::Local<v8::Object> exports,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv) {
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) {
v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary dict(isolate, exports);
dict.SetMethod("registerStandardSchemes", &RegisterStandardSchemes);
@@ -245,4 +248,4 @@ void Initialize(v8::Local<v8::Object> exports,
} // namespace
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_protocol, Initialize)
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_protocol, Initialize)

View File

@@ -39,20 +39,20 @@ class Protocol : public mate::TrackableObject<Protocol> {
using CompletionCallback = base::Callback<void(v8::Local<v8::Value>)>;
using BooleanCallback = base::Callback<void(bool)>;
static mate::Handle<Protocol> Create(v8::Isolate* isolate,
AtomBrowserContext* browser_context);
static mate::Handle<Protocol> Create(
v8::Isolate* isolate, AtomBrowserContext* browser_context);
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype);
protected:
Protocol(v8::Isolate* isolate, AtomBrowserContext* browser_context);
~Protocol() override;
~Protocol();
private:
// Possible errors.
enum ProtocolError {
PROTOCOL_OK, // no error
PROTOCOL_OK, // no error
PROTOCOL_FAIL, // operation failed, should never occur
PROTOCOL_REGISTERED,
PROTOCOL_NOT_REGISTERED,
@@ -62,13 +62,14 @@ class Protocol : public mate::TrackableObject<Protocol> {
// The protocol handler that will create a protocol handler for certain
// request job.
template <typename RequestJob>
template<typename RequestJob>
class CustomProtocolHandler
: public net::URLRequestJobFactory::ProtocolHandler {
public:
CustomProtocolHandler(v8::Isolate* isolate,
net::URLRequestContextGetter* request_context,
const Handler& handler)
CustomProtocolHandler(
v8::Isolate* isolate,
net::URLRequestContextGetter* request_context,
const Handler& handler)
: isolate_(isolate),
request_context_(request_context),
handler_(handler) {}
@@ -78,13 +79,13 @@ class Protocol : public mate::TrackableObject<Protocol> {
net::URLRequest* request,
net::NetworkDelegate* network_delegate) const override {
RequestJob* request_job = new RequestJob(request, network_delegate);
request_job->SetHandlerInfo(isolate_, request_context_, handler_);
request_job->SetHandlerInfo(isolate_, request_context_.get(), handler_);
return request_job;
}
private:
v8::Isolate* isolate_;
net::URLRequestContextGetter* request_context_;
scoped_refptr<net::URLRequestContextGetter> request_context_;
Protocol::Handler handler_;
DISALLOW_COPY_AND_ASSIGN(CustomProtocolHandler);
@@ -94,31 +95,32 @@ class Protocol : public mate::TrackableObject<Protocol> {
void RegisterServiceWorkerSchemes(const std::vector<std::string>& schemes);
// Register the protocol with certain request job.
template <typename RequestJob>
template<typename RequestJob>
void RegisterProtocol(const std::string& scheme,
const Handler& handler,
mate::Arguments* args) {
CompletionCallback callback;
args->GetNext(&callback);
auto* getter = browser_context_->GetRequestContext();
content::BrowserThread::PostTaskAndReplyWithResult(
content::BrowserThread::IO, FROM_HERE,
base::BindOnce(&Protocol::RegisterProtocolInIO<RequestJob>,
base::RetainedRef(getter), isolate(), scheme, handler),
base::BindOnce(&Protocol::OnIOCompleted, GetWeakPtr(), callback));
base::Bind(&Protocol::RegisterProtocolInIO<RequestJob>,
request_context_getter_, isolate(), scheme, handler),
base::Bind(&Protocol::OnIOCompleted,
GetWeakPtr(), callback));
}
template <typename RequestJob>
template<typename RequestJob>
static ProtocolError RegisterProtocolInIO(
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter,
v8::Isolate* isolate,
const std::string& scheme,
const Handler& handler) {
auto* job_factory = static_cast<AtomURLRequestJobFactory*>(
auto job_factory = static_cast<AtomURLRequestJobFactory*>(
request_context_getter->job_factory());
if (job_factory->IsHandledProtocol(scheme))
return PROTOCOL_REGISTERED;
auto protocol_handler = std::make_unique<CustomProtocolHandler<RequestJob>>(
isolate, request_context_getter.get(), handler);
std::unique_ptr<CustomProtocolHandler<RequestJob>> protocol_handler(
new CustomProtocolHandler<RequestJob>(
isolate, request_context_getter.get(), handler));
if (job_factory->SetProtocolHandler(scheme, std::move(protocol_handler)))
return PROTOCOL_OK;
else
@@ -139,34 +141,35 @@ class Protocol : public mate::TrackableObject<Protocol> {
const std::string& scheme);
// Replace the protocol handler with a new one.
template <typename RequestJob>
template<typename RequestJob>
void InterceptProtocol(const std::string& scheme,
const Handler& handler,
mate::Arguments* args) {
CompletionCallback callback;
args->GetNext(&callback);
auto* getter = browser_context_->GetRequestContext();
content::BrowserThread::PostTaskAndReplyWithResult(
content::BrowserThread::IO, FROM_HERE,
base::BindOnce(&Protocol::InterceptProtocolInIO<RequestJob>,
base::RetainedRef(getter), isolate(), scheme, handler),
base::BindOnce(&Protocol::OnIOCompleted, GetWeakPtr(), callback));
base::Bind(&Protocol::InterceptProtocolInIO<RequestJob>,
request_context_getter_, isolate(), scheme, handler),
base::Bind(&Protocol::OnIOCompleted,
GetWeakPtr(), callback));
}
template <typename RequestJob>
template<typename RequestJob>
static ProtocolError InterceptProtocolInIO(
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter,
v8::Isolate* isolate,
const std::string& scheme,
const Handler& handler) {
auto* job_factory = static_cast<AtomURLRequestJobFactory*>(
auto job_factory = static_cast<AtomURLRequestJobFactory*>(
request_context_getter->job_factory());
if (!job_factory->IsHandledProtocol(scheme))
return PROTOCOL_NOT_REGISTERED;
// It is possible a protocol is handled but can not be intercepted.
if (!job_factory->HasProtocolHandler(scheme))
return PROTOCOL_FAIL;
auto protocol_handler = std::make_unique<CustomProtocolHandler<RequestJob>>(
isolate, request_context_getter.get(), handler);
std::unique_ptr<CustomProtocolHandler<RequestJob>> protocol_handler(
new CustomProtocolHandler<RequestJob>(
isolate, request_context_getter.get(), handler));
if (!job_factory->InterceptProtocol(scheme, std::move(protocol_handler)))
return PROTOCOL_INTERCEPTED;
return PROTOCOL_OK;
@@ -184,9 +187,13 @@ class Protocol : public mate::TrackableObject<Protocol> {
// Convert error code to string.
std::string ErrorCodeToString(ProtocolError error);
base::WeakPtr<Protocol> GetWeakPtr() { return weak_factory_.GetWeakPtr(); }
AtomURLRequestJobFactory* GetJobFactoryInIO() const;
scoped_refptr<AtomBrowserContext> browser_context_;
base::WeakPtr<Protocol> GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter_;
base::WeakPtrFactory<Protocol> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(Protocol);

View File

@@ -21,8 +21,8 @@ namespace {
bool IsWebContents(v8::Isolate* isolate, content::RenderProcessHost* process) {
content::WebContents* web_contents =
static_cast<AtomBrowserClient*>(AtomBrowserClient::Get())
->GetWebContentsFromProcessID(process->GetID());
static_cast<AtomBrowserClient*>(AtomBrowserClient::Get())->
GetWebContentsFromProcessID(process->GetID());
if (!web_contents)
return false;
@@ -41,7 +41,8 @@ RenderProcessPreferences::RenderProcessPreferences(
Init(isolate);
}
RenderProcessPreferences::~RenderProcessPreferences() {}
RenderProcessPreferences::~RenderProcessPreferences() {
}
int RenderProcessPreferences::AddEntry(const base::DictionaryValue& entry) {
return preferences_.AddEntry(entry);
@@ -53,8 +54,7 @@ void RenderProcessPreferences::RemoveEntry(int id) {
// static
void RenderProcessPreferences::BuildPrototype(
v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) {
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(
mate::StringToV8(isolate, "RenderProcessPreferences"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
@@ -65,9 +65,10 @@ void RenderProcessPreferences::BuildPrototype(
// static
mate::Handle<RenderProcessPreferences>
RenderProcessPreferences::ForAllWebContents(v8::Isolate* isolate) {
return mate::CreateHandle(isolate,
new RenderProcessPreferences(
isolate, base::Bind(&IsWebContents, isolate)));
return mate::CreateHandle(
isolate,
new RenderProcessPreferences(isolate,
base::Bind(&IsWebContents, isolate)));
}
} // namespace api
@@ -76,10 +77,8 @@ RenderProcessPreferences::ForAllWebContents(v8::Isolate* isolate) {
namespace {
void Initialize(v8::Local<v8::Object> exports,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv) {
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) {
mate::Dictionary dict(context->GetIsolate(), exports);
dict.SetMethod("forAllWebContents",
&atom::api::RenderProcessPreferences::ForAllWebContents);
@@ -87,5 +86,5 @@ void Initialize(v8::Local<v8::Object> exports,
} // namespace
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_render_process_preferences,
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_render_process_preferences,
Initialize)

View File

@@ -16,8 +16,8 @@ namespace api {
class RenderProcessPreferences
: public mate::Wrappable<RenderProcessPreferences> {
public:
static mate::Handle<RenderProcessPreferences> ForAllWebContents(
v8::Isolate* isolate);
static mate::Handle<RenderProcessPreferences>
ForAllWebContents(v8::Isolate* isolate);
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype);

Some files were not shown because too many files have changed in this diff Show More