Compare commits

..

87 Commits

Author SHA1 Message Date
John Kleinschmidt
9dcbbb08db v1.7.16 2018-08-22 16:36:54 -04:00
Samuel Attard
bab968ca77 fix: inheritance of webPreferences sub properties 2018-08-22 12:36:02 -05:00
Samuel Attard
7fa3eba951 chore: stop auto releasing from windows CI 2018-08-19 15:43:00 -07:00
John Kleinschmidt
c0efff45fa Merge pull request #14087 from electron/update-libcc-1-7-x
fix: Update to latest libcc for 1-7-x
2018-08-14 14:38:30 -07:00
John Kleinschmidt
5eac44126f Update to latest libcc
Fixes issue with bad libcc archive files in 1-7-x
2018-08-14 10:01:04 -07:00
John Kleinschmidt
b2cec7b602 Merge pull request #14083 from electron/appveyor-rename-1-7-x
ci: rename appveyor-override to appveyor
2018-08-14 09:54:26 -07:00
John Kleinschmidt
f6328a515d Rename appveyor-override to appveyor 2018-08-14 09:42:20 -07:00
Jeremy Apthorp
47fe11e281 chore: roll libcc (#13991) 2018-08-08 20:48:31 -05:00
trop[bot]
0be8732f03 Use Visual Studio 2015 for 2-0-x (#13609) 2018-07-10 10:30:38 -05:00
John Kleinschmidt
9c466846ed v1.7.15 2018-05-16 14:08:31 -04:00
John Kleinschmidt
67b75fe204 Merge pull request #12947 from electron/update-ci-1-7-x
Update CI for 1-7-x
2018-05-16 12:51:34 -04:00
John Kleinschmidt
ef6e045241 Update CI for 1-7-x
Remove custom appveyor config
Add mac builds to CircleCI
2018-05-16 11:39:52 -04:00
John Kleinschmidt
95f0eeeb37 Merge pull request #12928 from electron/disable-exec-stack_1-7-x
Disable executable stack in `electron` binary
2018-05-15 10:40:14 -04:00
Ales Pergl
dfa394ba29 Disable executable stack in electron binary 2018-05-14 20:48:35 -05:00
Charles Kerr
5f6997caee update command-line backlist switches (1.7.x) (#12808)
Do a better job of finding edge cases, e.g. network_switch_list.h

**NB: This can't be tropped** because the list is dependent on the libcc version
2018-05-14 17:16:03 -05:00
John Kleinschmidt
fed76dcfaa v1.7.14 2018-04-26 20:47:01 -04:00
trop[bot]
42d284607e net: change mime type deduction in Change URLRequestAsarJob (#12383) 2018-04-06 11:16:25 -05:00
Shelley Vohr
3e2fff287a Update CI to use Node 8 (#12357) 2018-04-06 08:52:57 -05:00
John Kleinschmidt
11ce66b79a v1.7.13 2018-03-15 10:28:46 -04:00
Samuel Attard
1a48ee2827 Backport (1-7-x) - Set appropriate defaults for webview options (#12294)
* Fix NIB.

* Fix up tests
2018-03-15 15:34:56 +09:00
Alexey Kuzmin
413519b081 Update to the latest libcc from electron-1-7-x (#12203)
* Update to the latest libcc from electron-1-7-x

* Use electron-typescript-definitions 1.2.x
2018-03-12 09:28:16 +09:00
Samuel Attard
d701526a55 Merge pull request #11730 from brenca/osr-gpu-update-1-7-x
Improve OSR API (1-7-x)
2018-02-13 05:36:31 +11:00
John Kleinschmidt
924e372def v1.7.12 2018-01-31 14:46:48 -07:00
John Kleinschmidt
a27b7d1f10 Merge pull request #11785 from electron/case-insensitive-comparison-1-7-x
Do case insensitive comparisons
2018-01-31 12:58:06 -05:00
John Kleinschmidt
d3d8c1626a Merge pull request #11775 from electron/parallel-releases-1-7-x
Parallel releases for 1-7-x
2018-01-31 12:39:14 -05:00
Samuel Attard
8b6aa225ae Do case insensitive comparisons 2018-01-31 10:38:21 -07:00
John Kleinschmidt
e02440e0d8 Allow multiple releases to run at once
Find draft release by draft flag and tag name
2018-01-30 17:52:58 -07:00
Heilig Benedek
cd5bdc88c3 Remove web_contents_impl() helper to clarify code and remove unnecessary guard 2018-01-26 10:32:20 +01:00
Heilig Benedek
9021989cfd Move OSR api to OsrWCV to allow api calls to take effect sooner 2018-01-25 15:31:57 +01:00
Heilig Benedek
4a61a8dd34 Call SetAuthoritativeVsyncInterval on the Compositor directly 2018-01-25 15:31:27 +01:00
Heilig Benedek
04efcac8cc Raise maximum OSR framerate to 240 2018-01-25 15:31:18 +01:00
Heilig Benedek
6f27d5dd51 Don't generate a frame with GPU OSR if IsPainting is false 2018-01-25 15:31:04 +01:00
Heilig Benedek
7fb00bfca7 Don't generate a paint when StartPainting is called inside paint cb 2018-01-25 15:29:17 +01:00
Heilig Benedek
b22734ccc1 Use null accelerated widget to avoid showing GPU accelerated OSR surface 2018-01-25 15:24:20 +01:00
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
1929 changed files with 107893 additions and 233180 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +0,0 @@
*
!tools/xvfb-init.sh
!tools/run-electron.sh
!build/install-build-deps.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=

View File

@@ -1,12 +0,0 @@
{
"extends": "standard",
"env": {
"browser": true
},
"rules": {
"no-var": "error",
"prefer-const": ["error", {
"destructuring": "all"
}]
}
}

3
.gitattributes vendored
View File

@@ -1,3 +0,0 @@
# `git apply` and friends don't understand CRLF, even on windows. Force those
# files to be checked out with LF endings even if core.autocrlf is true.
*.patch text eol=lf

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
---
* Output of `node_modules/.bin/electron --version`:
* Operating System (Platform and Version):
* Output of `node_modules/.bin/electron --version` on last known working Electron version (if applicable):
**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,13 +0,0 @@
---
name: Mac App Store Private API Rejection
about: Your app was rejected from the Mac App Store for using private API's
---
* Electron Version:
**Rejection Email**
Paste the contents of your rejection email here, censoring any private information such as app names.
**Additional Information**
Add any other context about the problem here.

View File

@@ -1,9 +0,0 @@
---
name: Security report
about: Do not create an issue for security reports, send an email to security@electronjs.org
---
Do not create an issue for security reports, send an email to:
security@electronjs.org

View File

@@ -1,22 +0,0 @@
##### Description of Change
<!--
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
- [ ] PR title follows semantic [commit guidelines](https://github.com/electron/electron/blob/master/docs/development/pull-requests.md#commit-message-guidelines)
##### Release Notes
<!-- Used to describe release notes for future release versions. See https://github.com/electron/clerk/blob/master/README.md for details. -->
Notes: <!-- One-line Change Summary Here-->

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.
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!

44
.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,43 +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
/vendor/pyyaml
node_modules/
SHASUMS256.txt
**/yarn.lock
compile_commands.json
.envrc
# npm package
/npm/dist
/npm/path.txt
.npmrc
# Generated API definitions
electron-api.json
electron.d.ts
# Spec hash calculation
spec/.hash
# Eslint Cache
.eslintcache

24
.gitmodules vendored
View File

@@ -1,6 +1,30 @@
[submodule "vendor/node"]
path = vendor/node
url = https://github.com/electron/node.git
[submodule "vendor/depot_tools"]
path = vendor/depot_tools
url = https://chromium.googlesource.com/chromium/tools/depot_tools.git
[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
[submodule "vendor/requests"]
path = vendor/requests
url = https://github.com/kennethreitz/requests
[submodule "vendor/boto"]
path = vendor/boto
url = https://github.com/boto/boto.git
[submodule "vendor/pdf_viewer"]
path = vendor/pdf_viewer
url = https://github.com/electron/pdf-viewer.git
[submodule "vendor/gyp"]
path = vendor/gyp
url = https://github.com/electron/gyp
[submodule "vendor/libchromiumcontent"]
path = vendor/libchromiumcontent
url = https://github.com/electron/libchromiumcontent

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"]
]
}

32
.travis.yml Normal file
View File

@@ -0,0 +1,32 @@
git:
depth: 10
notifications:
email: false
before_install:
- export BOTO_CONFIG=/dev/null
language: node_js
node_js:
- "4"
os:
- linux
- osx
env:
- TARGET_ARCH=x64
osx_image: xcode7.3
matrix:
include:
- os: linux
env: TARGET_ARCH=arm
- os: linux
env: TARGET_ARCH=ia32
allow_failures:
- os: osx
script: './script/cibuild'
branches:
only:
- master

View File

@@ -1,31 +0,0 @@
pool:
vmImage: 'Ubuntu 16.04'
steps:
- bash: |
# "depot_tools" has to be checkout into "//third_party/depot_tools" so pylint.py can a "pylintrc" file.
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "${AGENT_BUILDDIRECTORY}/third_party/depot_tools"
echo "##vso[task.setvariable variable=PATH]$PATH:${AGENT_BUILDDIRECTORY}/third_party/depot_tools"
displayName: Setup Depot Tools
- bash: |
chromium_revision="$(grep -A1 chromium_version DEPS | tr -d '\n' | cut -d\' -f4)"
buildtools_revision="$(curl -sL "https://chromium.googlesource.com/chromium/src/+/${chromium_revision}/DEPS?format=TEXT" | base64 -d | grep buildtools_revision -A1 | tr -d '\n' | cut -d\' -f4)"
git clone https://chromium.googlesource.com/chromium/buildtools "${AGENT_TEMPDIRECTORY}/buildtools"
(cd "${AGENT_TEMPDIRECTORY}/buildtools" && git checkout "$buildtools_revision")
echo "##vso[task.setvariable variable=CHROMIUM_BUILDTOOLS_PATH]$AGENT_TEMPDIRECTORY/buildtools"
download_from_google_storage --bucket chromium-gn -s "${AGENT_TEMPDIRECTORY}/buildtools/linux64/gn.sha1"
displayName: Download gn binary
- bash: |
# gn.py tries to find a gclient root folder starting from the current dir.
# When it fails and returns "None" path, the whole script fails. Let's "fix" it.
touch .gclient
# Another option would be to checkout "buildtools" inside the Electron checkout,
# but then we would lint its contents (at least gn format), and it doesn't pass it.
npm install
npm run lint
displayName: Run Lint

1020
BUILD.gn

File diff suppressed because it is too large Load Diff

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

137
DEPS
View File

@@ -1,137 +0,0 @@
gclient_gn_args_file = 'src/build/config/gclient_args.gni'
gclient_gn_args = [
'build_with_chromium',
'checkout_android',
'checkout_android_native_support',
'checkout_libaom',
'checkout_nacl',
'checkout_oculus_sdk'
]
vars = {
'chromium_version':
'69.0.3497.106',
'node_version':
'8bc5d171a0873c0ba49f9433798bc8b67399788c',
'boto_version': 'f7574aa6cc2c819430c1f05e9a1a1a666ef8169b',
'pyyaml_version': '3.12',
'requests_version': 'e4d59bedfd3c7f4f254f4f5d036587bcd8152458',
'boto_git': 'https://github.com/boto',
'chromium_git': 'https://chromium.googlesource.com',
'electron_git': 'https://github.com/electron',
'requests_git': 'https://github.com/kennethreitz',
'yaml_git': 'https://github.com/yaml',
# To be able to build clean Chromium from sources.
'apply_patches': True,
# Python interface to Amazon Web Services. Is used for releases only.
'checkout_boto': False,
# To allow in-house builds to checkout those manually.
'checkout_chromium': True,
'checkout_node': True,
# It's only needed to parse the native tests configurations.
'checkout_pyyaml': False,
# Python "requests" module is used for releases only.
'checkout_requests': False,
# It is always needed for normal Electron builds,
# but might be impossible for custom in-house builds.
'download_external_binaries': True,
'checkout_nacl':
False,
'checkout_libaom':
True,
'checkout_oculus_sdk':
False,
'build_with_chromium':
True,
'checkout_android':
False,
'checkout_android_native_support':
False,
}
deps = {
'src': {
'url': (Var("chromium_git")) + '/chromium/src.git@' + (Var("chromium_version")),
'condition': 'checkout_chromium',
},
'src/third_party/electron_node': {
'url': (Var("electron_git")) + '/node.git@' + (Var("node_version")),
'condition': 'checkout_node',
},
'src/electron/vendor/pyyaml': {
'url': (Var("yaml_git")) + '/pyyaml.git@' + (Var("pyyaml_version")),
'condition': 'checkout_pyyaml',
},
'src/electron/vendor/boto': {
'url': Var('boto_git') + '/boto.git' + '@' + Var('boto_version'),
'condition': 'checkout_boto',
},
'src/electron/vendor/requests': {
'url': Var('requests_git') + '/requests.git' + '@' + Var('requests_version'),
'condition': 'checkout_requests',
},
}
hooks = [
{
'name': 'patch_chromium',
'condition': 'checkout_chromium and apply_patches',
'pattern': 'src/electron',
'action': [
'python',
'src/electron/script/apply_all_patches.py',
'src/electron/patches/common/config.json',
],
},
{
'name': 'electron_external_binaries',
'pattern': 'src/electron/script/update-external-binaries.py',
'condition': 'download_external_binaries',
'action': [
'python',
'src/electron/script/update-external-binaries.py',
],
},
{
'name': 'electron_npm_deps',
'pattern': 'src/electron/package.json',
'action': [
'python',
'-c',
'import os, subprocess; os.chdir(os.path.join("src", "electron")); subprocess.check_call(["python", "script/lib/npm.py", "install"]);',
],
},
{
'name': 'setup_boto',
'pattern': 'src/electron',
'condition': 'checkout_boto',
'action': [
'python',
'-c',
'import os, subprocess; os.chdir(os.path.join("src", "electron", "vendor", "boto")); subprocess.check_call(["python", "setup.py", "build"]);',
],
},
{
'name': 'setup_requests',
'pattern': 'src/electron',
'condition': 'checkout_requests',
'action': [
'python',
'-c',
'import os, subprocess; os.chdir(os.path.join("src", "electron", "vendor", "requests")); subprocess.check_call(["python", "setup.py", "build"]);',
],
},
]
recursedeps = [
'src',
]

View File

@@ -1,44 +0,0 @@
FROM ubuntu:18.04
RUN groupadd --gid 1000 builduser \
&& useradd --uid 1000 --gid builduser --shell /bin/bash --create-home builduser
# Set up TEMP directory
ENV TEMP=/tmp
RUN chmod a+rwx /tmp
# Install Linux packages
ADD build/install-build-deps.sh /setup/install-build-deps.sh
RUN echo ttf-mscorefonts-installer msttcorefonts/accepted-mscorefonts-eula select true | debconf-set-selections
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \
curl \
libnotify-bin \
locales \
lsb-release \
nano \
python-dbusmock \
python-pip \
python-setuptools \
sudo \
vim-nox \
wget \
&& /setup/install-build-deps.sh --syms --no-prompt --no-chromeos-fonts --lib32 --arm \
&& rm -rf /var/lib/apt/lists/*
# Install Node.js
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y nodejs \
&& rm -rf /var/lib/apt/lists/*
# crcmod is required by gsutil, which is used for filling the gclient git cache
RUN pip install -U crcmod
RUN mkdir /tmp/workspace
RUN chown builduser:builduser /tmp/workspace
# 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

@@ -1,61 +0,0 @@
FROM arm32v7/ubuntu:18.04
RUN groupadd --gid 1000 builduser \
&& useradd --uid 1000 --gid builduser --shell /bin/bash --create-home builduser
# Set up TEMP directory
ENV TEMP=/tmp
RUN chmod a+rwx /tmp
RUN apt-get update && DEBIAN_FRONTEND=noninteractive 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-bin \
libnss3 \
libnss3-dev \
libxss1 \
libxtst-dev \
libxtst6 \
lsb-release \
locales \
nano \
python-setuptools \
python-pip \
python-dbusmock \
sudo \
unzip \
wget \
xvfb \
&& rm -rf /var/lib/apt/lists/*
# Install Node.js
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y nodejs \
&& rm -rf /var/lib/apt/lists/*
# crcmod is required by gsutil, which is used for filling the gclient git cache
RUN pip install -U crcmod
ADD tools/xvfb-init.sh /etc/init.d/xvfb
RUN chmod a+x /etc/init.d/xvfb
RUN usermod -aG sudo builduser
RUN echo 'builduser ALL=(ALL:ALL) NOPASSWD:ALL' >> /etc/sudoers
WORKDIR /home/builduser

View File

@@ -1,65 +0,0 @@
FROM arm64v8/ubuntu:16.04
RUN groupadd --gid 1000 builduser \
&& useradd --uid 1000 --gid builduser --shell /bin/bash --create-home builduser
# Set up TEMP directory
ENV TEMP=/tmp
RUN chmod a+rwx /tmp
RUN dpkg --add-architecture armhf
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \
bison \
build-essential \
clang \
curl \
gperf \
git \
libasound2 \
libasound2-dev \
libc6:armhf \
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-bin \
libnss3 \
libnss3-dev \
libstdc++6:armhf \
libxss1 \
libxtst-dev \
libxtst6 \
lsb-release \
locales \
nano \
python-setuptools \
python-pip \
python-dbusmock \
sudo \
unzip \
wget \
xvfb \
&& rm -rf /var/lib/apt/lists/*
# Install Node.js
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y nodejs \
&& rm -rf /var/lib/apt/lists/*
# crcmod is required by gsutil, which is used for filling the gclient git cache
RUN pip install -U crcmod
ADD tools/xvfb-init.sh /etc/init.d/xvfb
RUN chmod a+x /etc/init.d/xvfb
RUN usermod -aG sudo builduser
RUN echo 'builduser ALL=(ALL:ALL) NOPASSWD:ALL' >> /etc/sudoers
WORKDIR /home/builduser

View File

@@ -7,11 +7,8 @@ Thanks for opening an issue! A few things to keep in mind:
- If you need general advice, join our Slack: http://atom-slack.herokuapp.com
-->
* Output of `node_modules/.bin/electron --version`:
* Operating System (Platform and Version):
<!-- If this used to work -->
* Output of `node_modules/.bin/electron --version` on last known working Electron version (if applicable):
* Electron version:
* Operating system:
### Expected behavior

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,40 +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 & Electron Fiddle
## Quick Start
Use [`Electron Fiddle`](https://github.com/electron/fiddle)
to build, run, and package small Electron experiments, to see code examples for all of Electron's APIs, and
to try out different versions of Electron. It's designed to make the start of your journey with
Electron easier.
Alternatively, 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/fiddle](https://github.com/electron/fiddle) - A tool to build, run, and package small Electron experiments
- [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
@@ -90,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 +0,0 @@
4.0.5

View File

@@ -1,107 +1,58 @@
# The config expects the following environment variables to be set:
# - "GN_CONFIG" Build type. One of {'debug', 'testing', 'release'}.
# - "GN_EXTRA_ARGS" Additional gn arguments for a build config,
# e.g. 'target_cpu="x86"' to build for a 32bit platform.
# https://gn.googlesource.com/gn/+/master/docs/reference.md#target_cpu
# Don't forget to set up "NPM_CONFIG_ARCH" and "TARGET_ARCH" accordningly
# if you pass a custom value for 'target_cpu'.
# - "ELECTRON_RELEASE" Set it to '1' upload binaries on success.
# - "NPM_CONFIG_ARCH" E.g. 'x86'. Is used to build native Node.js modules.
# Must match 'target_cpu' passed to "GN_EXTRA_ARGS" and "TARGET_ARCH" value.
# - "TARGET_ARCH" Choose from {'ia32', 'x64', 'arm', 'arm64', 'mips64el'}.
# Is used in some publishing scripts, but does NOT affect the Electron binary.
# Must match 'target_cpu' passed to "GN_EXTRA_ARGS" and "NPM_CONFIG_ARCH" value.
# - "UPLOAD_TO_S3" Set it to '1' upload a release to the S3 bucket.
# Otherwise the release will be uploaded to the Github Releases.
# (The value is only checked if "ELECTRON_RELEASE" is defined.)
#
# The publishing scripts expect access tokens to be defined as env vars,
# but those are not covered here.
#
# AppVeyor docs on variables:
# https://www.appveyor.com/docs/environment-variables/
# https://www.appveyor.com/docs/build-configuration/#secure-variables
# https://www.appveyor.com/docs/build-configuration/#custom-environment-variables
version: 1.0.{build}
build_cloud: libcc-20
image: libcc-20-vs2017-15.7.4
environment:
GIT_CACHE_PATH: C:\Users\electron\libcc_cache
DISABLE_CRASH_REPORTER_TESTS: true
ELECTRON_OUT_DIR: Default
build_cloud: electron-16
image: electron-16-vs2015
build_script:
- ps: >-
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
- ps: >-
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"
}
- echo "Building $env:GN_CONFIG build"
- git config --global core.longpaths true
- cd ..
- md src
- ps: Move-Item $env:APPVEYOR_BUILD_FOLDER -Destination src\electron
- ps: $env:CHROMIUM_BUILDTOOLS_PATH="$pwd\src\buildtools"
- ps: $env:SCCACHE_PATH="$pwd\src\electron\external_binaries\sccache.exe"
- ps: >-
if ($env:GN_CONFIG -eq 'release') {
$env:GCLIENT_EXTRA_ARGS="--custom-var=checkout_boto=True --custom-var=checkout_requests=True"
$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"
}
- >-
gclient config
--name "src\electron"
--unmanaged
%GCLIENT_EXTRA_ARGS%
"https://github.com/electron/electron"
- gclient sync --with_branch_heads --with_tags
- cd src
- ps: $env:BUILD_CONFIG_PATH="//electron/build/args/%GN_CONFIG%.gn"
- gn gen out/Default "--args=import(\"%BUILD_CONFIG_PATH%\") %GN_EXTRA_ARGS%"
- ninja -C out/Default electron:electron_app
- gn gen out/ffmpeg "--args=import(\"//electron/build/args/ffmpeg.gn\") %GN_EXTRA_ARGS%"
- ninja -C out/ffmpeg electron:electron_ffmpeg_zip
- ninja -C out/Default electron:electron_dist_zip
- ninja -C out/Default electron:electron_mksnapshot_zip
- ninja -C out/Default electron:electron_chromedriver_zip
- ninja -C out/Default third_party/electron_node:headers
- appveyor PushArtifact out/Default/dist.zip
- appveyor PushArtifact out/Default/chromedriver.zip
- appveyor PushArtifact out/ffmpeg/ffmpeg.zip
- ps: >-
if ($env:GN_CONFIG -eq 'release') {
ninja -C out/Default third_party/breakpad:dump_syms
}
- if "%GN_CONFIG%"=="release" ( python electron\script\dump-symbols.py -d %cd%\out\Default\breakpad_symbols -v)
- ps: >-
if ($env:GN_CONFIG -eq 'release') {
python electron\script\zip-symbols.py
appveyor PushArtifact out/Default/symbols.zip
}
test_script:
- ps: >-
if ((-Not (Test-Path Env:\ELECTRON_RELEASE)) -And ($env:GN_CONFIG -in "testing", "release")) {
$env:RUN_TESTS="true"
}
- if "%RUN_TESTS%"=="true" ( echo Verifying non proprietary ffmpeg & python electron\script\verify-ffmpeg.py --build-dir out\Default --source-root %cd% --ffmpeg-path out\ffmpeg )
- if "%RUN_TESTS%"=="true" ( echo Verifying mksnapshot & python electron\script\verify-mksnapshot.py --build-dir out\Default --source-root %cd% )
- ps: >-
if ($env:RUN_TESTS -eq 'true') {
New-Item .\out\Default\gen\node_headers\Release -Type directory
Copy-Item -path .\out\Default\electron.lib -destination .\out\Default\gen\node_headers\Release\node.lib
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 {
echo "Skipping tests for $env:GN_CONFIG build"
Write-Output "Running debug build"
python script\bootstrap.py --target_arch=$env:TARGET_ARCH --dev
python script\build.py -c D
}
- cd electron
- if "%RUN_TESTS%"=="true" ( echo Running test suite & npm run test -- --ci )
- cd ..
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:
- cd electron
- ps: >-
if (Test-Path Env:\ELECTRON_RELEASE) {
if (Test-Path Env:\UPLOAD_TO_S3) {
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
}
}
- ps: "if (Test-Path Env:\\ELECTRON_RELEASE) {\n if (Test-Path Env:\\RUN_RELEASE_BUILD) {\n Write-Output \"Uploading Electron release distribution to s3\"\n & python script\\upload.py --upload_to_s3\n } else {\n Write-Output \"Uploading Electron release distribution to github releases\"\n & python script\\upload.py\n }\n} else {\n Write-Output \"Skipping upload distribution because build is not for release\"\n}"

1
atom/CPPLINT.cfg Normal file
View File

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

View File

@@ -1,5 +0,0 @@
{
"project_name": "electron",
"product_name": "Electron",
"mac_bundle_id": "com.github.Electron"
}

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,76 +19,20 @@
#include "content/public/common/content_constants.h"
#include "content/public/common/pepper_plugin_info.h"
#include "content/public/common/user_agent.h"
#include "electron/buildflags/buildflags.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"
// In SHARED_INTERMEDIATE_DIR.
#include "widevine_cdm_version.h" // NOLINT(build/include)
#if defined(WIDEVINE_CDM_AVAILABLE)
#include "base/native_library.h"
#include "content/public/common/cdm_info.h"
#include "media/base/video_codecs.h"
#endif // defined(WIDEVINE_CDM_AVAILABLE)
#if BUILDFLAG(ENABLE_PDF_VIEWER)
#include "atom/common/atom_constants.h"
#include "pdf/pdf.h"
#endif // BUILDFLAG(ENABLE_PDF_VIEWER)
#if defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_PEPPER_CDMS)
#include "chrome/common/widevine_cdm_constants.h"
#endif
namespace atom {
namespace {
#if defined(WIDEVINE_CDM_AVAILABLE)
bool IsWidevineAvailable(
base::FilePath* cdm_path,
std::vector<media::VideoCodec>* codecs_supported,
base::flat_set<media::CdmSessionType>* session_types_supported,
base::flat_set<media::EncryptionMode>* modes_supported) {
static enum {
NOT_CHECKED,
FOUND,
NOT_FOUND,
} widevine_cdm_file_check = NOT_CHECKED;
if (widevine_cdm_file_check == NOT_CHECKED) {
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
*cdm_path = command_line->GetSwitchValuePath(switches::kWidevineCdmPath);
if (!cdm_path->empty()) {
*cdm_path = cdm_path->AppendASCII(
base::GetNativeLibraryName(kWidevineCdmLibraryName));
widevine_cdm_file_check = base::PathExists(*cdm_path) ? FOUND : NOT_FOUND;
}
}
if (widevine_cdm_file_check == FOUND) {
// Add the supported codecs as if they came from the component manifest.
// This list must match the CDM that is being bundled with Chrome.
codecs_supported->push_back(media::VideoCodec::kCodecVP8);
codecs_supported->push_back(media::VideoCodec::kCodecVP9);
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
codecs_supported->push_back(media::VideoCodec::kCodecH264);
#endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
// TODO(crbug.com/767941): Push persistent-license support info here once
// we check in a new CDM that supports it on Linux.
session_types_supported->insert(media::CdmSessionType::kTemporary);
#if defined(OS_CHROMEOS)
session_types_supported->insert(media::CdmSessionType::kPersistentLicense);
#endif // defined(OS_CHROMEOS)
modes_supported->insert(media::EncryptionMode::kCenc);
return true;
}
return false;
}
#endif // defined(WIDEVINE_CDM_AVAILABLE)
#if BUILDFLAG(ENABLE_PEPPER_FLASH)
content::PepperPluginInfo CreatePepperFlashInfo(const base::FilePath& path,
const std::string& version) {
content::PepperPluginInfo plugin;
@@ -112,38 +57,60 @@ 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;
}
void AddPepperFlashFromCommandLine(
base::CommandLine* command_line,
std::vector<content::PepperPluginInfo>* plugins) {
base::FilePath flash_path =
command_line->GetSwitchValuePath(switches::kPpapiFlashPath);
if (flash_path.empty())
return;
#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.version = version;
content::WebPluginMimeType widevine_cdm_mime_type(
kWidevineCdmPluginMimeType,
kWidevineCdmPluginExtension,
kWidevineCdmPluginMimeTypeDescription);
auto flash_version =
command_line->GetSwitchValueASCII(switches::kPpapiFlashVersion);
// 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));
plugins->push_back(CreatePepperFlashInfo(flash_path, flash_version));
widevine_cdm.mime_types.push_back(widevine_cdm_mime_type);
widevine_cdm.permissions = kWidevineCdmPluginPermissions;
return widevine_cdm;
}
#endif // BUILDFLAG(ENABLE_PEPPER_FLASH)
#endif
void ComputeBuiltInPlugins(std::vector<content::PepperPluginInfo>* plugins) {
#if BUILDFLAG(ENABLE_PDF_VIEWER)
content::PepperPluginInfo pdf_info;
pdf_info.is_internal = true;
pdf_info.is_out_of_process = true;
@@ -160,33 +127,71 @@ void ComputeBuiltInPlugins(std::vector<content::PepperPluginInfo>* plugins) {
chrome_pdf::PPP_ShutdownModule;
pdf_info.permissions = ppapi::PERMISSION_PRIVATE | ppapi::PERMISSION_DEV;
plugins->push_back(pdf_info);
#endif // BUILDFLAG(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
AtomContentClient::AtomContentClient() {}
void AddPepperFlashFromCommandLine(
std::vector<content::PepperPluginInfo>* plugins) {
auto command_line = base::CommandLine::ForCurrentProcess();
base::FilePath flash_path = command_line->GetSwitchValuePath(
switches::kPpapiFlashPath);
if (flash_path.empty())
return;
AtomContentClient::~AtomContentClient() {}
auto flash_version = command_line->GetSwitchValueASCII(
switches::kPpapiFlashVersion);
plugins->push_back(CreatePepperFlashInfo(flash_path, flash_version));
}
#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);
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;
plugins->push_back(CreateWidevineCdmInfo(widevine_cdm_path,
widevine_cdm_version));
}
#endif
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 {
@@ -210,44 +215,11 @@ void AtomContentClient::AddAdditionalSchemes(Schemes* schemes) {
void AtomContentClient::AddPepperPlugins(
std::vector<content::PepperPluginInfo>* plugins) {
#if BUILDFLAG(ENABLE_PEPPER_FLASH)
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
AddPepperFlashFromCommandLine(command_line, plugins);
#endif // BUILDFLAG(ENABLE_PEPPER_FLASH)
AddPepperFlashFromCommandLine(plugins);
#if defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_PEPPER_CDMS)
AddWidevineCdmFromCommandLine(plugins);
#endif
ComputeBuiltInPlugins(plugins);
}
void AtomContentClient::AddContentDecryptionModules(
std::vector<content::CdmInfo>* cdms,
std::vector<media::CdmHostFilePath>* cdm_host_file_paths) {
if (cdms) {
#if defined(WIDEVINE_CDM_AVAILABLE)
base::FilePath cdm_path;
std::vector<media::VideoCodec> video_codecs_supported;
base::flat_set<media::CdmSessionType> session_types_supported;
base::flat_set<media::EncryptionMode> encryption_modes_supported;
if (IsWidevineAvailable(&cdm_path, &video_codecs_supported,
&session_types_supported,
&encryption_modes_supported)) {
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
auto cdm_version_string =
command_line->GetSwitchValueASCII(switches::kWidevineCdmVersion);
// CdmInfo needs |path| to be the actual Widevine library,
// not the adapter, so adjust as necessary. It will be in the
// same directory as the installed adapter.
const base::Version version(cdm_version_string);
DCHECK(version.IsValid());
content::CdmCapability capability(
video_codecs_supported, encryption_modes_supported,
session_types_supported, base::flat_set<media::CdmProxy::Protocol>());
cdms->push_back(content::CdmInfo(
kWidevineCdmDisplayName, kWidevineCdmGuid, version, cdm_path,
kWidevineCdmFileSystemId, capability, kWidevineKeySystem, false));
}
#endif // defined(WIDEVINE_CDM_AVAILABLE)
}
}
} // 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

@@ -6,17 +6,14 @@
#define ATOM_APP_ATOM_LIBRARY_MAIN_H_
#include "build/build_config.h"
#include "electron/buildflags/buildflags.h"
#if defined(OS_MACOSX)
extern "C" {
__attribute__((visibility("default"))) int AtomMain(int argc, char* argv[]);
__attribute__((visibility("default")))
int AtomMain(int argc, char* argv[]);
#if BUILDFLAG(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);
}
#if BUILDFLAG(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>
@@ -25,13 +24,9 @@
#include "content/public/app/sandbox_helper_win.h"
#include "sandbox/win/src/sandbox_types.h"
#elif defined(OS_LINUX) // defined(OS_WIN)
#include <unistd.h>
#include <cstdio>
#include "atom/app/atom_main_delegate.h" // NOLINT
#include "content/public/app/content_main.h"
#else // defined(OS_LINUX)
#include <unistd.h>
#include <cstdio>
#include "atom/app/atom_library_main.h"
#endif // defined(OS_MACOSX)
@@ -39,15 +34,12 @@
#include "atom/common/atom_command_line.h"
#include "base/at_exit.h"
#include "base/i18n/icu_util.h"
#include "electron/buildflags/buildflags.h"
namespace {
#if BUILDFLAG(ENABLE_RUN_AS_NODE)
const char kRunAsNode[] = "ELECTRON_RUN_AS_NODE";
#endif
const char* kRunAsNode = "ELECTRON_RUN_AS_NODE";
ALLOW_UNUSED_TYPE bool IsEnvSet(const char* name) {
bool IsEnvSet(const char* name) {
#if defined(OS_WIN)
size_t required_size;
getenv_s(&required_size, nullptr, 0, name);
@@ -58,25 +50,6 @@ ALLOW_UNUSED_TYPE bool IsEnvSet(const char* name) {
#endif
}
#if defined(OS_POSIX)
void FixStdioStreams() {
// libuv may mark stdin/stdout/stderr as close-on-exec, which interferes
// with chromium's subprocess spawning. As a workaround, we detect if these
// streams are closed on startup, and reopen them as /dev/null if necessary.
// Otherwise, an unrelated file descriptor will be assigned as stdout/stderr
// which may cause various errors when attempting to write to them.
//
// For details see https://github.com/libuv/libuv/issues/2062
struct stat st;
if (fstat(STDIN_FILENO, &st) < 0 && errno == EBADF)
ignore_result(freopen("/dev/null", "r", stdin));
if (fstat(STDOUT_FILENO, &st) < 0 && errno == EBADF)
ignore_result(freopen("/dev/null", "w", stdout));
if (fstat(STDERR_FILENO, &st) < 0 && errno == EBADF)
ignore_result(freopen("/dev/null", "w", stderr));
}
#endif
} // namespace
#if defined(OS_WIN)
@@ -93,7 +66,7 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
#ifdef _DEBUG
// Don't display assert dialog boxes in CI test runs
static const char* kCI = "ELECTRON_CI";
static const auto kCI = "ELECTRON_CI";
bool is_ci = IsEnvSet(kCI);
if (!is_ci) {
for (int i = 0; i < arguments.argc; ++i) {
@@ -115,11 +88,7 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
}
#endif
#if BUILDFLAG(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"))
@@ -139,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
#if BUILDFLAG(ENABLE_RUN_AS_NODE)
if (run_as_node) {
std::vector<char*> argv(arguments.argc);
std::transform(
@@ -154,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);
}
@@ -178,15 +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[]) {
FixStdioStreams();
#if BUILDFLAG(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);
@@ -199,13 +162,9 @@ int main(int argc, char* argv[]) {
#else // defined(OS_LINUX)
int main(int argc, char* argv[]) {
FixStdioStreams();
#if BUILDFLAG(ENABLE_RUN_AS_NODE)
if (IsEnvSet(kRunAsNode)) {
return AtomInitializeICUandStartNode(argc, argv);
}
#endif
return AtomMain(argc, argv);
}

View File

@@ -5,7 +5,6 @@
#include "atom/app/atom_main_delegate.h"
#include <iostream>
#include <memory>
#include <string>
#include "atom/app/atom_content_client.h"
@@ -22,23 +21,9 @@
#include "base/logging.h"
#include "chrome/common/chrome_paths.h"
#include "content/public/common/content_switches.h"
#include "ipc/ipc_buildflags.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
#if defined(OS_MACOSX)
#include "atom/app/atom_main_delegate_mac.h"
#endif
namespace atom {
namespace {
@@ -51,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)
@@ -84,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;
@@ -102,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();
@@ -135,7 +113,14 @@ bool AtomMainDelegate::BasicStartupComplete(int* exit_code) {
void AtomMainDelegate::PreSandboxStartup() {
brightray::MainDelegate::PreSandboxStartup();
auto* command_line = base::CommandLine::ForCurrentProcess();
// 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))
@@ -145,11 +130,10 @@ 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(service_manager::switches::kNoSandbox);
command_line->AppendSwitch(::switches::kNoSandbox);
}
}
@@ -162,23 +146,17 @@ void AtomMainDelegate::PreSandboxStartup() {
#endif
}
void AtomMainDelegate::PreContentInitialization() {
#if defined(OS_MACOSX)
RegisterAtomCrApp();
#endif
}
content::ContentBrowserClient* AtomMainDelegate::CreateContentBrowserClient() {
browser_client_.reset(new AtomBrowserClient);
return browser_client_.get();
}
content::ContentRendererClient*
AtomMainDelegate::CreateContentRendererClient() {
AtomMainDelegate::CreateContentRendererClient() {
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableSandbox) ||
switches::kEnableSandbox) ||
!base::CommandLine::ForCurrentProcess()->HasSwitch(
service_manager::switches::kNoSandbox)) {
::switches::kNoSandbox)) {
renderer_client_.reset(new AtomSandboxedRendererClient);
} else {
renderer_client_.reset(new AtomRendererClient);
@@ -214,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

@@ -5,7 +5,6 @@
#ifndef ATOM_APP_ATOM_MAIN_DELEGATE_H_
#define ATOM_APP_ATOM_MAIN_DELEGATE_H_
#include <memory>
#include <string>
#include "brightray/common/content_client.h"
@@ -16,13 +15,12 @@ namespace atom {
class AtomMainDelegate : public brightray::MainDelegate {
public:
AtomMainDelegate();
~AtomMainDelegate() override;
~AtomMainDelegate();
protected:
// content::ContentMainDelegate:
bool BasicStartupComplete(int* exit_code) override;
void PreSandboxStartup() override;
void PreContentInitialization() override;
content::ContentBrowserClient* CreateContentBrowserClient() override;
content::ContentRendererClient* CreateContentRendererClient() override;
content::ContentUtilityClient* CreateContentUtilityClient() override;
@@ -46,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

@@ -1,15 +0,0 @@
// Copyright 2013 Slack Technologies, Inc. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ATOM_APP_ATOM_MAIN_DELEGATE_MAC_H_
#define ATOM_APP_ATOM_MAIN_DELEGATE_MAC_H_
namespace atom {
// Initializes NSApplication.
void RegisterAtomCrApp();
} // namespace atom
#endif // ATOM_APP_ATOM_MAIN_DELEGATE_MAC_H_

View File

@@ -4,10 +4,9 @@
#include "atom/app/atom_main_delegate.h"
#include "atom/browser/mac/atom_application.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"
@@ -21,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
@@ -43,14 +41,14 @@ 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";
base::PathService::Override(content::CHILD_PROCESS_EXE, helper_path);
PathService::Override(content::CHILD_PROCESS_EXE, helper_path);
}
void AtomMainDelegate::SetUpBundleOverrides() {
@@ -64,9 +62,4 @@ void AtomMainDelegate::SetUpBundleOverrides() {
base::mac::SetBaseBundleID(base_bundle_id.c_str());
}
void RegisterAtomCrApp() {
// Force the NSApplication subclass to be used.
[AtomApplication sharedApplication];
}
} // namespace atom

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

@@ -4,19 +4,14 @@
#include "atom/app/node_main.h"
#include <memory>
#include <utility>
#include "atom/app/uv_task_runner.h"
#include "atom/browser/javascript_environment.h"
#include "atom/browser/node_debugger.h"
#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"
@@ -27,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;
@@ -39,30 +34,22 @@ 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(loop);
// Explicitly register electron's builtin modules.
NodeBindings::RegisterBuiltinModules();
JavascriptEnvironment gin_env;
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);
@@ -84,7 +71,6 @@ int NodeMain(int argc, char* argv[]) {
bool more;
do {
more = uv_run(env->event_loop(), UV_RUN_ONCE);
gin_env.platform()->DrainTasks(env->isolate());
if (more == false) {
node::EmitBeforeExit(env);
@@ -98,20 +84,10 @@ int NodeMain(int argc, char* argv[]) {
exit_code = node::EmitExit(env);
node::RunAtExit(env);
gin_env.platform()->DrainTasks(env->isolate());
gin_env.platform()->CancelPendingDelayedTasks(env->isolate());
gin_env.platform()->UnregisterIsolate(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;

View File

@@ -7,7 +7,7 @@
namespace atom {
int NodeMain(int argc, char* argv[]);
int NodeMain(int argc, char *argv[]);
} // namespace atom

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);
};

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,6 @@
#include <memory>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
@@ -16,7 +15,6 @@
#include "atom/browser/browser.h"
#include "atom/browser/browser_observer.h"
#include "atom/common/native_mate_converters/callback.h"
#include "atom/common/promise_util.h"
#include "base/process/process_iterator.h"
#include "base/task/cancelable_task_tracker.h"
#include "chrome/browser/icon_manager.h"
@@ -27,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"
@@ -54,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 {
@@ -66,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,
@@ -100,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
@@ -129,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)>&
@@ -136,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;
@@ -163,11 +149,9 @@ class App : public AtomBrowserClient::Delegate,
void BrowserChildProcessHostDisconnected(
const content::ChildProcessData& data) override;
void BrowserChildProcessCrashed(
const content::ChildProcessData& data,
const content::ChildProcessTerminationInfo& info) override;
const content::ChildProcessData& data, int exit_code) override;
void BrowserChildProcessKilled(
const content::ChildProcessData& data,
const content::ChildProcessTerminationInfo& info) override;
const content::ChildProcessData& data, int exit_code) override;
private:
void SetAppPath(const base::FilePath& app_path);
@@ -182,39 +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, mate::Arguments* args);
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);
v8::Local<v8::Promise> GetGPUInfo(v8::Isolate* isolate,
const std::string& info_type);
void EnableSandbox(mate::Arguments* args);
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();
@@ -235,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

@@ -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);
}
@@ -66,25 +67,15 @@ void BrowserView::Init(v8::Isolate* isolate,
web_contents_.Reset(isolate, web_contents.ToV8());
api_web_contents_ = web_contents.get();
Observe(web_contents->web_contents());
view_.reset(
NativeBrowserView::Create(api_web_contents_->managed_web_contents()));
view_.reset(NativeBrowserView::Create(
api_web_contents_->managed_web_contents()->GetView()));
InitWith(isolate, wrapper);
}
BrowserView::~BrowserView() {
if (api_web_contents_) { // destroy() is called
// Destroy WebContents asynchronously unless app is shutting down,
// because destroy() might be called inside WebContents's event handler.
api_web_contents_->DestroyWebContents(!Browser::Get()->is_shutting_down());
}
}
void BrowserView::WebContentsDestroyed() {
api_web_contents_ = nullptr;
web_contents_.Reset();
api_web_contents_->DestroyWebContents(true /* async */);
}
// static
@@ -123,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());
}
@@ -140,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);
}
@@ -162,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

@@ -10,7 +10,6 @@
#include "atom/browser/api/trackable_object.h"
#include "atom/browser/native_browser_view.h"
#include "content/public/browser/web_contents_observer.h"
#include "native_mate/handle.h"
namespace gfx {
@@ -30,8 +29,7 @@ namespace api {
class WebContents;
class BrowserView : public mate::TrackableObject<BrowserView>,
public content::WebContentsObserver {
class BrowserView : public mate::TrackableObject<BrowserView> {
public:
static mate::WrappableBase* New(mate::Arguments* args);
@@ -49,9 +47,6 @@ class BrowserView : public mate::TrackableObject<BrowserView>,
const mate::Dictionary& options);
~BrowserView() override;
// content::WebContentsObserver:
void WebContentsDestroyed() override;
private:
void Init(v8::Isolate* isolate,
v8::Local<v8::Object> wrapper,
@@ -61,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,463 +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 <memory>
#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->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() {
// On some machines it may happen that the window gets destroyed for twice,
// checking web_contents() can effectively guard against that.
// https://github.com/electron/electron/issues/16202.
//
// TODO(zcbenz): We should find out the root cause and improve the closing
// procedure of BrowserWindow.
if (!web_contents())
return;
// 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);
// Destroy WebContents asynchronously unless app is shutting down,
// because destroy() might be called inside WebContents's event handler.
api_web_contents_->DestroyWebContents(!Browser::Get()->is_shutting_down());
Observe(nullptr);
}
// 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,127 +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 <memory>
#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,135 +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]];
// ensure that buttons view is floated to top of view hierarchy
NSArray* subviews = [contentView subviews];
NSView* last = subviews.lastObject;
[contentView addSubview:webView positioned:NSWindowBelow relativeTo:last];
[contentView viewDidMoveToWindow];
}
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

@@ -7,7 +7,6 @@
#include "atom/common/native_mate_converters/callback.h"
#include "atom/common/native_mate_converters/file_path_converter.h"
#include "atom/common/native_mate_converters/value_converter.h"
#include "base/bind.h"
#include "base/files/file_util.h"
#include "content/public/browser/tracing_controller.h"
@@ -19,32 +18,20 @@ using content::TracingController;
namespace mate {
template <>
template<>
struct Converter<base::trace_event::TraceConfig> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
base::trace_event::TraceConfig* out) {
// (alexeykuzmin): A combination of "categoryFilter" and "traceOptions"
// has to be checked first because none of the fields
// in the `memory_dump_config` dict below are mandatory
// and we cannot check the config format.
Dictionary options;
if (ConvertFromV8(isolate, val, &options)) {
std::string category_filter, trace_options;
if (options.Get("categoryFilter", &category_filter) &&
options.Get("traceOptions", &trace_options)) {
*out = base::trace_event::TraceConfig(category_filter, trace_options);
return true;
}
}
base::DictionaryValue memory_dump_config;
if (ConvertFromV8(isolate, val, &memory_dump_config)) {
*out = base::trace_event::TraceConfig(memory_dump_config);
return true;
}
return false;
if (!ConvertFromV8(isolate, val, &options))
return false;
std::string category_filter, trace_options;
if (!options.Get("categoryFilter", &category_filter) ||
!options.Get("traceOptions", &trace_options))
return false;
*out = base::trace_event::TraceConfig(category_filter, trace_options);
return true;
}
};
@@ -54,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

@@ -4,11 +4,7 @@
#include "atom/browser/api/atom_api_cookies.h"
#include <memory>
#include <utility>
#include "atom/browser/atom_browser_context.h"
#include "atom/browser/cookie_change_notifier.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"
@@ -18,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) {
@@ -39,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) {
@@ -58,22 +55,25 @@ struct Converter<net::CanonicalCookie> {
}
};
template <>
struct Converter<network::mojom::CookieChangeCause> {
static v8::Local<v8::Value> ToV8(
v8::Isolate* isolate,
const network::mojom::CookieChangeCause& val) {
template<>
struct Converter<net::CookieStore::ChangeCause> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const net::CookieStore::ChangeCause& val) {
switch (val) {
case network::mojom::CookieChangeCause::INSERTED:
case network::mojom::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 network::mojom::CookieChangeCause::OVERWRITE:
case net::CookieStore::ChangeCause::OVERWRITE:
return mate::StringToV8(isolate, "overwrite");
case network::mojom::CookieChangeCause::EXPIRED:
case net::CookieStore::ChangeCause::EXPIRED:
return mate::StringToV8(isolate, "expired");
case network::mojom::CookieChangeCause::EVICTED:
case net::CookieStore::ChangeCause::EVICTED:
return mate::StringToV8(isolate, "evicted");
case network::mojom::CookieChangeCause::EXPIRED_OVERWRITE:
case net::CookieStore::ChangeCause::EXPIRED_OVERWRITE:
return mate::StringToV8(isolate, "expired-overwrite");
default:
return mate::StringToV8(isolate, "unknown");
@@ -166,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.
@@ -188,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.
@@ -211,107 +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_->cookie_change_notifier()->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) {
auto copy = base::DictionaryValue::From(
base::Value::ToUniquePtrValue(filter.Clone()));
auto* getter = browser_context_->GetRequestContext();
std::unique_ptr<base::DictionaryValue> copied(filter.CreateDeepCopy());
auto getter = make_scoped_refptr(request_context_getter_);
content::BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(GetCookiesOnIO, base::RetainedRef(getter), std::move(copy),
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) {
auto copy = base::DictionaryValue::From(
base::Value::ToUniquePtrValue(details.Clone()));
auto* getter = browser_context_->GetRequestContext();
std::unique_ptr<base::DictionaryValue> copied(details.CreateDeepCopy());
auto getter = make_scoped_refptr(request_context_getter_);
content::BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(SetCookieOnIO, base::RetainedRef(getter), std::move(copy),
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

@@ -5,12 +5,11 @@
#ifndef ATOM_BROWSER_API_ATOM_API_COOKIES_H_
#define ATOM_BROWSER_API_ATOM_API_COOKIES_H_
#include <memory>
#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"
@@ -28,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,
@@ -50,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);
// CookieChangeNotifier 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

@@ -4,17 +4,16 @@
#include "atom/browser/api/atom_api_debugger.h"
#include <memory>
#include <string>
#include <utility>
#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"
@@ -25,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;
@@ -67,26 +78,14 @@ void Debugger::DispatchProtocolMessage(DevToolsAgentHost* agent_host,
return;
base::DictionaryValue* error_body = nullptr;
base::DictionaryValue error;
bool has_error;
if ((has_error = dict->GetDictionary("error", &error_body))) {
if (dict->GetDictionary("error", &error_body))
error.Swap(error_body);
}
base::DictionaryValue* result_body = nullptr;
base::DictionaryValue result;
if (dict->GetDictionary("result", &result_body))
result.Swap(result_body);
send_command_callback.Run(has_error ? error.Clone() : base::Value(),
result);
}
}
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);
send_command_callback.Run(error, result);
}
}
@@ -94,39 +93,38 @@ 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;
@@ -145,27 +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::Value::ToUniquePtrValue(command_params.Clone()));
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));
}
@@ -188,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());
@@ -199,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,44 +4,31 @@
#include "atom/browser/api/atom_api_desktop_capturer.h"
#include <memory>
#include <utility>
#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/threading/thread_restrictions.h"
#include "chrome/browser/media/webrtc/desktop_media_list.h"
#include "content/public/browser/desktop_capture.h"
#include "chrome/browser/media/desktop_media_list.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);
}
};
@@ -56,140 +43,58 @@ DesktopCapturer::DesktopCapturer(v8::Isolate* isolate) {
Init(isolate);
}
DesktopCapturer::~DesktopCapturer() {}
DesktopCapturer::~DesktopCapturer() {
}
void DesktopCapturer::StartHandling(bool capture_window,
bool capture_screen,
const gfx::Size& thumbnail_size) {
webrtc::DesktopCaptureOptions options =
webrtc::DesktopCaptureOptions::CreateDefault();
#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();
using_directx_capturer_ = webrtc::ScreenCapturerWinDirectx::IsSupported();
}
#endif // 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
// clear any existing captured sources.
captured_sources_.clear();
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)));
// Start listening for captured sources.
capture_window_ = capture_window;
capture_screen_ = capture_screen;
{
// Remove this once
// https://bugs.chromium.org/p/chromium/issues/detail?id=795340 is fixed.
base::ScopedAllowBaseSyncPrimitivesForTesting
scoped_allow_base_sync_primitives;
// Initialize the source list.
// Apply the new thumbnail size and restart capture.
if (capture_window) {
window_capturer_.reset(new NativeDesktopMediaList(
content::DesktopMediaID::TYPE_WINDOW,
content::desktop_capture::CreateWindowCapturer()));
window_capturer_->SetThumbnailSize(thumbnail_size);
window_capturer_->AddObserver(this);
window_capturer_->StartUpdating();
}
if (capture_screen) {
screen_capturer_.reset(new NativeDesktopMediaList(
content::DesktopMediaID::TYPE_SCREEN,
content::desktop_capture::CreateScreenCapturer()));
screen_capturer_->SetThumbnailSize(thumbnail_size);
screen_capturer_->AddObserver(this);
screen_capturer_->StartUpdating();
}
}
media_list_->SetThumbnailSize(thumbnail_size);
media_list_->StartUpdating(this);
}
void DesktopCapturer::OnSourceAdded(DesktopMediaList* list, int index) {}
void DesktopCapturer::OnSourceRemoved(DesktopMediaList* list, int index) {}
void DesktopCapturer::OnSourceMoved(DesktopMediaList* list,
int old_index,
int new_index) {}
void DesktopCapturer::OnSourceNameChanged(DesktopMediaList* list, int index) {}
void DesktopCapturer::OnSourceThumbnailChanged(DesktopMediaList* list,
int index) {}
void DesktopCapturer::OnSourceUnchanged(DesktopMediaList* list) {
UpdateSourcesList(list);
void DesktopCapturer::OnSourceAdded(int index) {
}
bool DesktopCapturer::ShouldScheduleNextRefresh(DesktopMediaList* list) {
UpdateSourcesList(list);
void DesktopCapturer::OnSourceRemoved(int index) {
}
void DesktopCapturer::OnSourceMoved(int old_index, int new_index) {
}
void DesktopCapturer::OnSourceNameChanged(int index) {
}
void DesktopCapturer::OnSourceThumbnailChanged(int index) {
}
bool DesktopCapturer::OnRefreshFinished() {
Emit("finished", media_list_->GetSources());
return false;
}
void DesktopCapturer::UpdateSourcesList(DesktopMediaList* list) {
std::vector<DesktopCapturer::Source> window_sources;
if (capture_window_ &&
list->GetMediaListType() == content::DesktopMediaID::TYPE_WINDOW) {
capture_window_ = false;
const auto& media_list_sources = list->GetSources();
for (const auto& media_list_source : media_list_sources) {
window_sources.emplace_back(
DesktopCapturer::Source{media_list_source, std::string()});
}
std::move(window_sources.begin(), window_sources.end(),
std::back_inserter(captured_sources_));
}
std::vector<DesktopCapturer::Source> screen_sources;
if (capture_screen_ &&
list->GetMediaListType() == content::DesktopMediaID::TYPE_SCREEN) {
capture_screen_ = false;
const auto& media_list_sources = list->GetSources();
for (const auto& media_list_source : media_list_sources) {
screen_sources.emplace_back(
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 (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 : screen_sources) {
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 : screen_sources) {
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.
std::move(screen_sources.begin(), screen_sources.end(),
std::back_inserter(captured_sources_));
}
if (!capture_window_ && !capture_screen_)
Emit("finished", captured_sources_);
}
// static
mate::Handle<DesktopCapturer> DesktopCapturer::Create(v8::Isolate* isolate) {
return mate::CreateHandle(isolate, new DesktopCapturer(isolate));
@@ -197,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);
@@ -210,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));
@@ -221,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,28 +5,18 @@
#ifndef ATOM_BROWSER_API_ATOM_API_DESKTOP_CAPTURER_H_
#define ATOM_BROWSER_API_ATOM_API_DESKTOP_CAPTURER_H_
#include <memory>
#include <string>
#include <vector>
#include "atom/browser/api/event_emitter.h"
#include "chrome/browser/media/webrtc/desktop_media_list_observer.h"
#include "chrome/browser/media/webrtc/native_desktop_media_list.h"
#include "chrome/browser/media/desktop_media_list_observer.h"
#include "chrome/browser/media/native_desktop_media_list.h"
#include "native_mate/handle.h"
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,
@@ -41,27 +31,15 @@ class DesktopCapturer : public mate::EventEmitter<DesktopCapturer>,
~DesktopCapturer() override;
// DesktopMediaListObserver overrides.
void OnSourceAdded(DesktopMediaList* list, int index) override;
void OnSourceRemoved(DesktopMediaList* list, int index) override;
void OnSourceMoved(DesktopMediaList* list,
int old_index,
int new_index) override;
void OnSourceNameChanged(DesktopMediaList* list, int index) override;
void OnSourceThumbnailChanged(DesktopMediaList* list, int index) override;
void OnSourceUnchanged(DesktopMediaList* list) override;
bool ShouldScheduleNextRefresh(DesktopMediaList* list) override;
void OnSourceAdded(int index) override;
void OnSourceRemoved(int index) override;
void OnSourceMoved(int old_index, int new_index) override;
void OnSourceNameChanged(int index) override;
void OnSourceThumbnailChanged(int index) override;
bool OnRefreshFinished() override;
private:
void UpdateSourcesList(DesktopMediaList* list);
std::unique_ptr<DesktopMediaList> window_capturer_;
std::unique_ptr<DesktopMediaList> screen_capturer_;
std::vector<DesktopCapturer::Source> captured_sources_;
bool capture_window_ = false;
bool capture_screen_ = false;
#if defined(OS_WIN)
bool using_directx_capturer_ = false;
#endif // defined(OS_WIN)
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

@@ -1,26 +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/event_emitter.h"
#include "atom/common/node_includes.h"
#include "native_mate/dictionary.h"
namespace {
v8::Local<v8::Object> CreateWithSender(v8::Isolate* isolate,
v8::Local<v8::Object> sender) {
return mate::internal::CreateJSEvent(isolate, sender, nullptr, nullptr);
}
void Initialize(v8::Local<v8::Object> exports,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv) {
mate::Dictionary dict(context->GetIsolate(), exports);
dict.SetMethod("createWithSender", &CreateWithSender);
}
} // namespace
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_event, Initialize)

View File

@@ -6,44 +6,15 @@
#include <string>
#include "atom/browser/api/atom_api_system_preferences.h"
#include "atom/common/native_mate_converters/accelerator_converter.h"
#include "atom/common/native_mate_converters/callback.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "native_mate/dictionary.h"
#include "atom/common/node_includes.h"
#if defined(OS_MACOSX)
#include "base/mac/mac_util.h"
#endif
using extensions::GlobalShortcutListener;
namespace {
#if defined(OS_MACOSX)
bool RegisteringMediaKeyForUntrustedClient(const ui::Accelerator& accelerator) {
if (base::mac::IsAtLeastOS10_14()) {
constexpr ui::KeyboardCode mediaKeys[] = {
ui::VKEY_MEDIA_PLAY_PAUSE, ui::VKEY_MEDIA_NEXT_TRACK,
ui::VKEY_MEDIA_PREV_TRACK, ui::VKEY_MEDIA_STOP};
if (std::find(std::begin(mediaKeys), std::end(mediaKeys),
accelerator.key_code()) != std::end(mediaKeys)) {
bool trusted =
atom::api::SystemPreferences::IsTrustedAccessibilityClient(false);
if (!trusted)
return true;
}
}
return false;
}
#endif
} // namespace
namespace atom {
namespace api {
@@ -60,7 +31,7 @@ void GlobalShortcut::OnKeyPressed(const ui::Accelerator& accelerator) {
if (accelerator_callback_map_.find(accelerator) ==
accelerator_callback_map_.end()) {
// This should never occur, because if it does, GlobalGlobalShortcutListener
// notifies us with wrong accelerator.
// notifes us with wrong accelerator.
NOTREACHED();
return;
}
@@ -69,13 +40,8 @@ void GlobalShortcut::OnKeyPressed(const ui::Accelerator& accelerator) {
bool GlobalShortcut::Register(const ui::Accelerator& accelerator,
const base::Closure& callback) {
#if defined(OS_MACOSX)
if (RegisteringMediaKeyForUntrustedClient(accelerator))
return false;
#endif
if (!GlobalShortcutListener::GetInstance()->RegisterAccelerator(accelerator,
this)) {
if (!GlobalShortcutListener::GetInstance()->RegisterAccelerator(
accelerator, this)) {
return false;
}
@@ -88,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) {
@@ -107,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)
@@ -123,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));
@@ -134,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

@@ -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) {
@@ -41,28 +38,20 @@ void Menu::AfterInit(v8::Isolate* isolate) {
delegate.Get("isCommandIdEnabled", &is_enabled_);
delegate.Get("isCommandIdVisible", &is_visible_);
delegate.Get("getAcceleratorForCommandId", &get_accelerator_);
delegate.Get("shouldRegisterAcceleratorForCommandId",
&should_register_accelerator_);
delegate.Get("executeCommand", &execute_command_);
delegate.Get("menuWillShow", &menu_will_show_);
}
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(
@@ -71,34 +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);
}
bool Menu::ShouldRegisterAcceleratorForCommandId(int command_id) const {
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
return should_register_accelerator_.Run(GetWrapper(), command_id);
}
void Menu::ExecuteCommand(int command_id, int flags) {
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
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);
}
@@ -163,12 +141,6 @@ base::string16 Menu::GetSublabelAt(int index) const {
return model_->GetSublabelAt(index);
}
base::string16 Menu::GetAcceleratorTextAt(int index) const {
ui::Accelerator accelerator;
model_->GetAcceleratorAtWithParams(index, true, &accelerator);
return accelerator.GetShortcutText();
}
bool Menu::IsItemCheckedAt(int index) const {
return model_->IsItemCheckedAt(index);
}
@@ -181,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) {
@@ -209,7 +173,6 @@ void Menu::BuildPrototype(v8::Isolate* isolate,
.SetMethod("getCommandIdAt", &Menu::GetCommandIdAt)
.SetMethod("getLabelAt", &Menu::GetLabelAt)
.SetMethod("getSublabelAt", &Menu::GetSublabelAt)
.SetMethod("getAcceleratorTextAt", &Menu::GetAcceleratorTextAt)
.SetMethod("isItemCheckedAt", &Menu::IsItemCheckedAt)
.SetMethod("isEnabledAt", &Menu::IsEnabledAt)
.SetMethod("isVisibleAt", &Menu::IsVisibleAt)
@@ -221,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));
@@ -243,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);
@@ -51,23 +50,15 @@ class Menu : public mate::TrackableObject<Menu>,
int command_id,
bool use_default_accelerator,
ui::Accelerator* accelerator) const override;
bool ShouldRegisterAcceleratorForCommandId(int command_id) const override;
void ExecuteCommand(int command_id, int event_flags) override;
void MenuWillShow(ui::SimpleMenuModel* source) override;
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);
@@ -92,21 +83,17 @@ class Menu : public mate::TrackableObject<Menu>,
int GetCommandIdAt(int index) const;
base::string16 GetLabelAt(int index) const;
base::string16 GetSublabelAt(int index) const;
base::string16 GetAcceleratorTextAt(int index) const;
bool IsItemCheckedAt(int index) const;
bool IsEnabledAt(int index) const;
bool IsVisibleAt(int index) const;
// 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<bool(v8::Local<v8::Value>, int)> should_register_accelerator_;
base::Callback<void(v8::Local<v8::Value>, v8::Local<v8::Value>, int)>
execute_command_;
base::Callback<void(v8::Local<v8::Value>)> menu_will_show_;
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);
};
@@ -115,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,60 +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;
// 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

@@ -4,10 +4,9 @@
#include "atom/browser/api/atom_api_menu_views.h"
#include <memory>
#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;
@@ -17,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

@@ -6,7 +6,6 @@
#define ATOM_BROWSER_API_ATOM_API_MENU_VIEWS_H_
#include <map>
#include <memory>
#include "atom/browser/api/atom_api_menu.h"
#include "base/memory/weak_ptr.h"
@@ -20,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,138 +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 <utility>
#include "atom/browser/atom_browser_context.h"
#include "atom/browser/atom_browser_main_parts.h"
#include "atom/common/native_mate_converters/callback.h"
#include "atom/common/native_mate_converters/file_path_converter.h"
#include "base/command_line.h"
#include "components/net_log/chrome_net_log.h"
#include "content/public/browser/storage_partition.h"
#include "native_mate/dictionary.h"
#include "native_mate/handle.h"
#include "net/url_request/url_request_context_getter.h"
#include "atom/common/node_includes.h"
namespace atom {
namespace api {
NetLog::NetLog(v8::Isolate* isolate, AtomBrowserContext* browser_context)
: browser_context_(browser_context) {
Init(isolate);
net_log_writer_ =
atom::AtomBrowserMainParts::Get()->net_log()->net_export_file_writer();
net_log_writer_->AddObserver(this);
}
NetLog::~NetLog() {
net_log_writer_->RemoveObserver(this);
}
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;
}
auto* network_context =
content::BrowserContext::GetDefaultStoragePartition(browser_context_)
->GetNetworkContext();
// TODO(deepak1556): Provide more flexibility to this module
// by allowing customizations on the capturing options.
net_log_writer_->StartNetLog(
log_path, net::NetLogCaptureMode::Default(),
net_log::NetExportFileWriter::kNoLimit /* file size limit */,
base::CommandLine::ForCurrentProcess()->GetCommandLineString(),
std::string(), network_context);
}
std::string NetLog::GetLoggingState() const {
if (!net_log_state_)
return std::string();
const base::Value* current_log_state =
net_log_state_->FindKeyOfType("state", base::Value::Type::STRING);
if (!current_log_state)
return std::string();
return current_log_state->GetString();
}
bool NetLog::IsCurrentlyLogging() const {
const std::string log_state = GetLoggingState();
return (log_state == "STARTING_LOG") || (log_state == "LOGGING");
}
std::string NetLog::GetCurrentlyLoggingPath() const {
// Net log exporter has a default path which will be used
// when no log path is provided, but since we don't allow
// net log capture without user provided file path, this
// check is completely safe.
if (IsCurrentlyLogging()) {
const base::Value* current_log_path =
net_log_state_->FindKeyOfType("file", base::Value::Type::STRING);
if (current_log_path)
return current_log_path->GetString();
}
return std::string();
}
void NetLog::StopLogging(mate::Arguments* args) {
net_log::NetExportFileWriter::FilePathCallback callback;
if (!args->GetNext(&callback)) {
args->ThrowError("Invalid callback function");
return;
}
if (IsCurrentlyLogging()) {
stop_callback_queue_.emplace_back(callback);
net_log_writer_->StopNetLog(nullptr);
} else {
callback.Run(base::FilePath());
}
}
void NetLog::OnNewState(const base::DictionaryValue& state) {
net_log_state_ = state.CreateDeepCopy();
if (stop_callback_queue_.empty())
return;
if (GetLoggingState() == "NOT_LOGGING") {
for (auto& callback : stop_callback_queue_) {
if (!callback.is_null())
net_log_writer_->GetFilePathToCompletedLog(callback);
}
stop_callback_queue_.clear();
}
}
// static
mate::Handle<NetLog> NetLog::Create(v8::Isolate* isolate,
AtomBrowserContext* browser_context) {
return mate::CreateHandle(isolate, new NetLog(isolate, browser_context));
}
// 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

View File

@@ -1,60 +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 <list>
#include <memory>
#include <string>
#include "atom/browser/api/trackable_object.h"
#include "base/callback.h"
#include "base/values.h"
#include "components/net_log/net_export_file_writer.h"
#include "native_mate/handle.h"
namespace atom {
class AtomBrowserContext;
namespace api {
class NetLog : public mate::TrackableObject<NetLog>,
public net_log::NetExportFileWriter::StateObserver {
public:
static mate::Handle<NetLog> Create(v8::Isolate* isolate,
AtomBrowserContext* browser_context);
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype);
void StartLogging(mate::Arguments* args);
std::string GetLoggingState() const;
bool IsCurrentlyLogging() const;
std::string GetCurrentlyLoggingPath() const;
void StopLogging(mate::Arguments* args);
protected:
explicit NetLog(v8::Isolate* isolate, AtomBrowserContext* browser_context);
~NetLog() override;
// net_log::NetExportFileWriter::StateObserver implementation
void OnNewState(const base::DictionaryValue& state) override;
private:
AtomBrowserContext* browser_context_;
net_log::NetExportFileWriter* net_log_writer_;
std::list<net_log::NetExportFileWriter::FilePathCallback>
stop_callback_queue_;
std::unique_ptr<base::DictionaryValue> net_log_state_;
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,72 +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 <windows.h>
#include <wtsapi32.h>
#include "base/win/wrapped_window_proc.h"
#include "ui/base/win/shell.h"
#include "ui/gfx/win/hwnd_util.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,37 +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) {
new_blocker_type = device::mojom::WakeLockType::kPreventDisplaySleep;
if (element.second ==
device::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep) {
new_blocker_type =
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();
@@ -106,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)
@@ -121,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));
@@ -132,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() {
@@ -50,7 +57,7 @@ void RegisterStandardSchemes(const std::vector<std::string>& schemes,
// Dynamically register the schemes.
auto* policy = content::ChildProcessSecurityPolicy::GetInstance();
for (const std::string& scheme : schemes) {
url::AddStandardScheme(scheme.c_str(), url::SCHEME_WITH_HOST);
url::AddStandardScheme(scheme.c_str(), url::SCHEME_WITHOUT_PORT);
if (secure) {
url::AddSecureScheme(scheme.c_str());
}
@@ -63,40 +70,45 @@ 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 = static_cast<URLRequestContextGetter*>(
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<URLRequestContextGetter> request_context_getter,
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter,
const std::string& scheme) {
auto* job_factory = request_context_getter->job_factory();
auto job_factory = static_cast<AtomURLRequestJobFactory*>(
request_context_getter->job_factory());
if (!job_factory->HasProtocolHandler(scheme))
return PROTOCOL_NOT_REGISTERED;
job_factory->SetProtocolHandler(scheme, nullptr);
@@ -105,46 +117,43 @@ Protocol::ProtocolError Protocol::UnregisterProtocolInIO(
void Protocol::IsProtocolHandled(const std::string& scheme,
const BooleanCallback& callback) {
auto* getter = static_cast<URLRequestContextGetter*>(
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);
}
// static
bool Protocol::IsProtocolHandledInIO(
scoped_refptr<URLRequestContextGetter> request_context_getter,
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter,
const std::string& scheme) {
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 = static_cast<URLRequestContextGetter*>(
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
Protocol::ProtocolError Protocol::UninterceptProtocolInIO(
scoped_refptr<URLRequestContextGetter> request_context_getter,
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter,
const std::string& scheme) {
return request_context_getter->job_factory()->UninterceptProtocol(scheme)
? PROTOCOL_OK
: PROTOCOL_NOT_INTERCEPTED;
return static_cast<AtomURLRequestJobFactory*>(
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

@@ -6,9 +6,7 @@
#define ATOM_BROWSER_API_ATOM_API_PROTOCOL_H_
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "atom/browser/api/trackable_object.h"
@@ -41,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,
@@ -64,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) {}
@@ -80,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);
@@ -96,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 = static_cast<URLRequestContextGetter*>(
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<URLRequestContextGetter> request_context_getter,
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter,
v8::Isolate* isolate,
const std::string& scheme,
const Handler& handler) {
auto* job_factory = request_context_getter->job_factory();
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
@@ -130,45 +130,46 @@ class Protocol : public mate::TrackableObject<Protocol> {
// Unregister the protocol handler that handles |scheme|.
void UnregisterProtocol(const std::string& scheme, mate::Arguments* args);
static ProtocolError UnregisterProtocolInIO(
scoped_refptr<URLRequestContextGetter> request_context_getter,
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter,
const std::string& scheme);
// Whether the protocol has handler registered.
void IsProtocolHandled(const std::string& scheme,
const BooleanCallback& callback);
static bool IsProtocolHandledInIO(
scoped_refptr<URLRequestContextGetter> request_context_getter,
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter,
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 = static_cast<URLRequestContextGetter*>(
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<URLRequestContextGetter> request_context_getter,
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter,
v8::Isolate* isolate,
const std::string& scheme,
const Handler& handler) {
auto* job_factory = request_context_getter->job_factory();
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;
@@ -177,7 +178,7 @@ class Protocol : public mate::TrackableObject<Protocol> {
// Restore the |scheme| to its original protocol handler.
void UninterceptProtocol(const std::string& scheme, mate::Arguments* args);
static ProtocolError UninterceptProtocolInIO(
scoped_refptr<URLRequestContextGetter> request_context_getter,
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter,
const std::string& scheme);
// Convert error code to JS exception and call the callback.
@@ -186,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);

View File

@@ -7,7 +7,6 @@
#include <algorithm>
#include <string>
#include "atom/browser/api/atom_api_browser_window.h"
#include "atom/browser/browser.h"
#include "atom/common/native_mate_converters/gfx_converter.h"
#include "base/bind.h"
@@ -17,10 +16,6 @@
#include "ui/display/screen.h"
#include "ui/gfx/geometry/point.h"
#if defined(OS_WIN)
#include "ui/display/win/screen_win.h"
#endif
#include "atom/common/node_includes.h"
namespace atom {
@@ -30,9 +25,9 @@ namespace api {
namespace {
// Find an item in container according to its ID.
template <class T>
template<class T>
typename T::iterator FindById(T* container, int id) {
auto predicate = [id](const typename T::value_type& item) -> bool {
auto predicate = [id] (const typename T::value_type& item) -> bool {
return item.id() == id;
};
return std::find_if(container->begin(), container->end(), predicate);
@@ -84,22 +79,6 @@ display::Display Screen::GetDisplayMatching(const gfx::Rect& match_rect) {
return screen_->GetDisplayMatching(match_rect);
}
#if defined(OS_WIN)
static gfx::Rect ScreenToDIPRect(atom::NativeWindow* window,
const gfx::Rect& rect) {
HWND hwnd = window ? window->GetAcceleratedWidget() : nullptr;
return display::win::ScreenWin::ScreenToDIPRect(hwnd, rect);
}
static gfx::Rect DIPToScreenRect(atom::NativeWindow* window,
const gfx::Rect& rect) {
HWND hwnd = window ? window->GetAcceleratedWidget() : nullptr;
return display::win::ScreenWin::DIPToScreenRect(hwnd, rect);
}
#endif
void Screen::OnDisplayAdded(const display::Display& new_display) {
Emit("display-added", new_display);
}
@@ -117,14 +96,15 @@ void Screen::OnDisplayMetricsChanged(const display::Display& display,
v8::Local<v8::Value> Screen::Create(v8::Isolate* isolate) {
if (!Browser::Get()->is_ready()) {
isolate->ThrowException(v8::Exception::Error(mate::StringToV8(
isolate, "Cannot require \"screen\" module before app is ready")));
isolate,
"Cannot require \"screen\" module before app is ready")));
return v8::Null(isolate);
}
display::Screen* screen = display::Screen::GetScreen();
if (!screen) {
isolate->ThrowException(v8::Exception::Error(
mate::StringToV8(isolate, "Failed to get screen information")));
isolate->ThrowException(v8::Exception::Error(mate::StringToV8(
isolate, "Failed to get screen information")));
return v8::Null(isolate);
}
@@ -132,19 +112,16 @@ v8::Local<v8::Value> Screen::Create(v8::Isolate* isolate) {
}
// static
void Screen::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) {
void Screen::BuildPrototype(
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(mate::StringToV8(isolate, "Screen"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("getCursorScreenPoint", &Screen::GetCursorScreenPoint)
.SetMethod("getPrimaryDisplay", &Screen::GetPrimaryDisplay)
.SetMethod("getAllDisplays", &Screen::GetAllDisplays)
.SetMethod("getDisplayNearestPoint", &Screen::GetDisplayNearestPoint)
#if defined(OS_WIN)
.SetMethod("screenToDipPoint", &display::win::ScreenWin::ScreenToDIPPoint)
.SetMethod("dipToScreenPoint", &display::win::ScreenWin::DIPToScreenPoint)
.SetMethod("screenToDipRect", &ScreenToDIPRect)
.SetMethod("dipToScreenRect", &DIPToScreenRect)
#if defined(OS_MACOSX)
.SetMethod("getMenuBarHeight", &Screen::getMenuBarHeight)
#endif
.SetMethod("getDisplayMatching", &Screen::GetDisplayMatching);
}
@@ -157,10 +134,8 @@ namespace {
using atom::api::Screen;
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("screen", Screen::Create(isolate));
@@ -169,4 +144,4 @@ void Initialize(v8::Local<v8::Object> exports,
} // namespace
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_common_screen, Initialize)
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_common_screen, Initialize)

View File

@@ -16,7 +16,7 @@ namespace gfx {
class Point;
class Rect;
class Screen;
} // namespace gfx
}
namespace atom {
@@ -40,6 +40,10 @@ class Screen : public mate::EventEmitter<Screen>,
display::Display GetDisplayNearestPoint(const gfx::Point& point);
display::Display GetDisplayMatching(const gfx::Rect& match_rect);
#if defined(OS_MACOSX)
int getMenuBarHeight();
#endif
// display::DisplayObserver:
void OnDisplayAdded(const display::Display& new_display) override;
void OnDisplayRemoved(const display::Display& old_display) override;

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