mirror of
https://github.com/electron/electron.git
synced 2026-02-19 03:14:51 -05:00
Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cb84d26d20 | ||
|
|
78cf807cf0 | ||
|
|
f3de3334cf | ||
|
|
a9d5a1d771 | ||
|
|
2356577614 | ||
|
|
94a5132b07 | ||
|
|
dca200d918 | ||
|
|
e86e7d699f | ||
|
|
922fcfb3da | ||
|
|
1d35151353 | ||
|
|
cb9fdc45e6 | ||
|
|
2dafd845b9 | ||
|
|
9017f90b57 | ||
|
|
b94638894e | ||
|
|
8a3288d791 | ||
|
|
6f5336c63f | ||
|
|
73c1fab423 | ||
|
|
1e36ee918e | ||
|
|
1f49da7a06 | ||
|
|
037a458e1d | ||
|
|
03a274ee27 | ||
|
|
c4bd516b77 | ||
|
|
4c914c1277 | ||
|
|
e3688a8e9d | ||
|
|
375534cf4a | ||
|
|
397e5ad0ac |
@@ -1,351 +0,0 @@
|
||||
build-steps: &build-steps
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Install Node.js 10 on MacOS
|
||||
command: |
|
||||
if [ "$INSTALL_MACOS_NODE" == "true" ]; then
|
||||
echo 'Installing Node.js 10 for MacOS'
|
||||
brew update
|
||||
brew install node@10
|
||||
echo 'export PATH="/usr/local/opt/node@10/bin:$PATH"' >> $BASH_ENV
|
||||
fi
|
||||
- run:
|
||||
name: Check for release
|
||||
command: |
|
||||
if [ -n "${RUN_RELEASE_BUILD}" ]; then
|
||||
echo 'release build triggered from api'
|
||||
echo 'export ELECTRON_RELEASE=1 UPLOAD_TO_S3=1' >> $BASH_ENV
|
||||
fi
|
||||
- run:
|
||||
name: Bootstrap
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ]; then
|
||||
echo "Bootstrapping Electron for release build for $TARGET_ARCH"
|
||||
script/bootstrap.py --target_arch=$TARGET_ARCH
|
||||
else
|
||||
echo "Bootstrapping Electron for debug build for $TARGET_ARCH"
|
||||
script/bootstrap.py --target_arch=$TARGET_ARCH --dev
|
||||
fi
|
||||
- run:
|
||||
name: Lint
|
||||
command: npm run lint
|
||||
- run:
|
||||
name: Build
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ]; then
|
||||
echo 'Building Electron for release'
|
||||
script/build.py -c R
|
||||
else
|
||||
echo 'Building Electron for debug'
|
||||
script/build.py -c D
|
||||
fi
|
||||
- run:
|
||||
name: Create distribution
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ]; then
|
||||
echo 'Creating Electron release distribution'
|
||||
script/create-dist.py
|
||||
else
|
||||
echo 'Skipping create distribution because build is not for release'
|
||||
fi
|
||||
- run:
|
||||
name: Upload distribution
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" == "1" ] && [ "$UPLOAD_TO_S3" != "1" ]; then
|
||||
echo 'Uploading Electron release distribution to github releases'
|
||||
script/upload.py
|
||||
elif [ "$ELECTRON_RELEASE" == "1" ] && [ "$UPLOAD_TO_S3" == "1" ]; then
|
||||
echo 'Uploading Electron release distribution to s3'
|
||||
script/upload.py --upload_to_s3
|
||||
else
|
||||
echo 'Skipping upload distribution because build is not for release'
|
||||
fi
|
||||
- run:
|
||||
name: Setup for headless testing
|
||||
command: |
|
||||
if [ "$RUN_HEADLESS_TESTS" == "true" ]; then
|
||||
echo 'Setup for headless testing'
|
||||
sh -e /etc/init.d/xvfb start
|
||||
else
|
||||
echo 'Headless testing not needed'
|
||||
fi
|
||||
|
||||
- run:
|
||||
name: Verify mksnapshot
|
||||
command: |
|
||||
if [ "$RUN_TESTS" == "true" ] && [ "$ELECTRON_RELEASE" == "1" ]; then
|
||||
echo 'Verifying mksnapshot on release build'
|
||||
script/verify-mksnapshot.py
|
||||
else
|
||||
echo 'Skipping mksnapshot tests due to configuration'
|
||||
fi
|
||||
|
||||
- run:
|
||||
name: Test
|
||||
environment:
|
||||
MOCHA_FILE: junit/test-results.xml
|
||||
MOCHA_REPORTER: mocha-junit-reporter
|
||||
command: |
|
||||
if [ "$RUN_TESTS" == "true" ]; then
|
||||
if [ "$ELECTRON_RELEASE" != "1" ]; then
|
||||
echo 'Testing Electron debug build'
|
||||
mkdir junit
|
||||
script/test.py --ci --rebuild_native_modules
|
||||
else
|
||||
if [ "$UPLOAD_TO_S3" == "1" ]; then
|
||||
echo 'Testing Electron release build'
|
||||
mkdir junit
|
||||
script/test.py --ci --rebuild_native_modules -c R
|
||||
else
|
||||
echo 'Skipping tests on GitHub release'
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo 'Skipping tests due to configuration'
|
||||
fi
|
||||
- run:
|
||||
name: Verify FFmpeg
|
||||
command: |
|
||||
if [ "$RUN_TESTS" == "true" ]; then
|
||||
if [ "$ELECTRON_RELEASE" != "1" ]; then
|
||||
echo 'Verifying ffmpeg on debug build'
|
||||
script/verify-ffmpeg.py
|
||||
else
|
||||
echo 'Verifying ffmpeg on release build'
|
||||
script/verify-ffmpeg.py -R
|
||||
fi
|
||||
else
|
||||
echo 'Skipping tests due to configuration'
|
||||
fi
|
||||
|
||||
- run:
|
||||
name: Generate Typescript Definitions
|
||||
command: |
|
||||
if [ "$CREATE_TYPESCRIPT_DEFS" == "true" ]; then
|
||||
npm run create-typescript-definitions
|
||||
fi
|
||||
- persist_to_workspace:
|
||||
root: out
|
||||
paths:
|
||||
- "*"
|
||||
- store_test_results:
|
||||
path: junit
|
||||
- store_artifacts:
|
||||
path: junit
|
||||
- store_artifacts:
|
||||
path: out
|
||||
|
||||
build-defaults: &build-defaults
|
||||
docker:
|
||||
- image: electronbuilds/electron:0.0.8
|
||||
<<: *build-steps
|
||||
|
||||
version: 2
|
||||
jobs:
|
||||
electron-linux-arm:
|
||||
environment:
|
||||
TARGET_ARCH: arm
|
||||
<<: *build-defaults
|
||||
resource_class: 2xlarge
|
||||
|
||||
electron-linux-arm-test:
|
||||
machine: true
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: /tmp/workspace/project/out
|
||||
- checkout
|
||||
- run:
|
||||
name: Test in ARM docker container
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" != "1" ]; then
|
||||
docker run --rm --privileged multiarch/qemu-user-static:register --reset
|
||||
docker run -it \
|
||||
--mount type=bind,source=/tmp/workspace,target=/tmp/workspace \
|
||||
--rm electronbuilds/electronarm7:0.0.5 > version.txt
|
||||
cat version.txt
|
||||
if grep -q `script/get-version.py` version.txt; then
|
||||
echo "Versions match"
|
||||
else
|
||||
echo "Versions do not match"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "Skipping test for release build"
|
||||
fi
|
||||
|
||||
electron-linux-arm-release-nightly:
|
||||
environment:
|
||||
TARGET_ARCH: arm
|
||||
RUN_RELEASE_BUILD: true
|
||||
<<: *build-defaults
|
||||
resource_class: 2xlarge
|
||||
|
||||
electron-linux-arm64:
|
||||
environment:
|
||||
TARGET_ARCH: arm64
|
||||
<<: *build-defaults
|
||||
resource_class: 2xlarge
|
||||
|
||||
electron-linux-arm64-test:
|
||||
machine: true
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: /tmp/workspace/project/out
|
||||
- checkout
|
||||
- run:
|
||||
name: Test in ARM64 docker container
|
||||
command: |
|
||||
if [ "$ELECTRON_RELEASE" != "1" ]; then
|
||||
docker run --rm --privileged multiarch/qemu-user-static:register --reset
|
||||
docker run -it \
|
||||
--mount type=bind,source=/tmp/workspace,target=/tmp/workspace \
|
||||
--rm electronbuilds/electronarm64:0.0.6 > version.txt
|
||||
cat version.txt
|
||||
if grep -q `script/get-version.py` version.txt; then
|
||||
echo "Versions match"
|
||||
else
|
||||
echo "Versions do not match"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "Skipping test for release build"
|
||||
fi
|
||||
|
||||
electron-linux-arm64-release-nightly:
|
||||
environment:
|
||||
TARGET_ARCH: arm64
|
||||
RUN_RELEASE_BUILD: true
|
||||
<<: *build-defaults
|
||||
resource_class: 2xlarge
|
||||
|
||||
electron-linux-ia32:
|
||||
environment:
|
||||
TARGET_ARCH: ia32
|
||||
DISPLAY: ':99.0'
|
||||
RUN_TESTS: true
|
||||
RUN_HEADLESS_TESTS: true
|
||||
<<: *build-defaults
|
||||
resource_class: xlarge
|
||||
|
||||
electron-linux-ia32-release-nightly:
|
||||
environment:
|
||||
TARGET_ARCH: ia32
|
||||
RUN_RELEASE_BUILD: true
|
||||
<<: *build-defaults
|
||||
resource_class: xlarge
|
||||
|
||||
electron-linux-mips64el:
|
||||
environment:
|
||||
TARGET_ARCH: mips64el
|
||||
<<: *build-defaults
|
||||
resource_class: xlarge
|
||||
|
||||
electron-linux-x64:
|
||||
environment:
|
||||
TARGET_ARCH: x64
|
||||
DISPLAY: ':99.0'
|
||||
RUN_TESTS: true
|
||||
RUN_HEADLESS_TESTS: true
|
||||
CREATE_TYPESCRIPT_DEFS: true
|
||||
<<: *build-defaults
|
||||
resource_class: xlarge
|
||||
|
||||
electron-linux-x64-release-nightly:
|
||||
environment:
|
||||
TARGET_ARCH: x64
|
||||
RUN_RELEASE_BUILD: true
|
||||
<<: *build-defaults
|
||||
resource_class: xlarge
|
||||
|
||||
electron-osx-x64:
|
||||
environment:
|
||||
TARGET_ARCH: x64
|
||||
RUN_TESTS: true
|
||||
INSTALL_MACOS_NODE: true
|
||||
macos:
|
||||
xcode: "8.3.3"
|
||||
<<: *build-steps
|
||||
|
||||
electron-osx-x64-release-nightly:
|
||||
environment:
|
||||
TARGET_ARCH: x64
|
||||
RUN_RELEASE_BUILD: true
|
||||
INSTALL_MACOS_NODE: true
|
||||
macos:
|
||||
xcode: "8.3.3"
|
||||
<<: *build-steps
|
||||
|
||||
electron-mas-x64:
|
||||
environment:
|
||||
TARGET_ARCH: x64
|
||||
MAS_BUILD: 1
|
||||
RUN_TESTS: true
|
||||
INSTALL_MACOS_NODE: true
|
||||
macos:
|
||||
xcode: "8.3.3"
|
||||
<<: *build-steps
|
||||
|
||||
electron-mas-x64-release-nightly:
|
||||
environment:
|
||||
TARGET_ARCH: x64
|
||||
MAS_BUILD: 1
|
||||
RUN_RELEASE_BUILD: true
|
||||
INSTALL_MACOS_NODE: true
|
||||
macos:
|
||||
xcode: "8.3.3"
|
||||
<<: *build-steps
|
||||
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
build-arm:
|
||||
jobs:
|
||||
- electron-linux-arm
|
||||
- electron-linux-arm-test:
|
||||
requires:
|
||||
- electron-linux-arm
|
||||
build-arm64:
|
||||
jobs:
|
||||
- electron-linux-arm64
|
||||
- electron-linux-arm64-test:
|
||||
requires:
|
||||
- electron-linux-arm64
|
||||
build-ia32:
|
||||
jobs:
|
||||
- electron-linux-ia32
|
||||
build-x64:
|
||||
jobs:
|
||||
- electron-linux-x64
|
||||
build-osx-x64:
|
||||
jobs:
|
||||
- electron-osx-x64
|
||||
build-mas-x64:
|
||||
jobs:
|
||||
- electron-mas-x64
|
||||
|
||||
nightly-release-test:
|
||||
triggers:
|
||||
- schedule:
|
||||
cron: "0 0 * * *"
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- 2-0-x
|
||||
- 1-8-x
|
||||
- 1-7-x
|
||||
jobs:
|
||||
- electron-linux-arm-release-nightly
|
||||
- electron-linux-arm64-release-nightly
|
||||
- electron-linux-ia32-release-nightly
|
||||
- electron-linux-x64-release-nightly
|
||||
|
||||
experimental:
|
||||
notify:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- 2-0-x
|
||||
- 1-8-x
|
||||
- 1-7-x
|
||||
@@ -1,35 +0,0 @@
|
||||
# Defines the Chromium style for automatic reformatting.
|
||||
# http://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
||||
BasedOnStyle: Chromium
|
||||
# This defaults to 'Auto'. Explicitly set it for a while, so that
|
||||
# 'vector<vector<int> >' in existing files gets formatted to
|
||||
# 'vector<vector<int>>'. ('Auto' means that clang-format will only use
|
||||
# 'int>>' if the file already contains at least one such instance.)
|
||||
Standard: Cpp11
|
||||
# Make sure code like:
|
||||
# IPC_BEGIN_MESSAGE_MAP()
|
||||
# IPC_MESSAGE_HANDLER(WidgetHostViewHost_Update, OnUpdate)
|
||||
# IPC_END_MESSAGE_MAP()
|
||||
# gets correctly indented.
|
||||
MacroBlockBegin: "^\
|
||||
BEGIN_MSG_MAP|\
|
||||
BEGIN_MSG_MAP_EX|\
|
||||
BEGIN_SAFE_MSG_MAP_EX|\
|
||||
CR_BEGIN_MSG_MAP_EX|\
|
||||
IPC_BEGIN_MESSAGE_MAP|\
|
||||
IPC_BEGIN_MESSAGE_MAP_WITH_PARAM|\
|
||||
IPC_PROTOBUF_MESSAGE_TRAITS_BEGIN|\
|
||||
IPC_STRUCT_BEGIN|\
|
||||
IPC_STRUCT_BEGIN_WITH_PARENT|\
|
||||
IPC_STRUCT_TRAITS_BEGIN|\
|
||||
POLPARAMS_BEGIN|\
|
||||
PPAPI_BEGIN_MESSAGE_MAP$"
|
||||
MacroBlockEnd: "^\
|
||||
CR_END_MSG_MAP|\
|
||||
END_MSG_MAP|\
|
||||
IPC_END_MESSAGE_MAP|\
|
||||
IPC_PROTOBUF_MESSAGE_TRAITS_END|\
|
||||
IPC_STRUCT_END|\
|
||||
IPC_STRUCT_TRAITS_END|\
|
||||
POLPARAMS_END|\
|
||||
PPAPI_END_MESSAGE_MAP$"
|
||||
@@ -1,3 +0,0 @@
|
||||
*
|
||||
!tools/xvfb-init.sh
|
||||
!tools/run-electron.sh
|
||||
@@ -1,7 +0,0 @@
|
||||
# These env vars are only necessary for creating Electron releases.
|
||||
# See docs/development/releasing.md
|
||||
|
||||
APPVEYOR_TOKEN=
|
||||
CIRCLE_TOKEN=
|
||||
ELECTRON_GITHUB_TOKEN=
|
||||
VSTS_TOKEN=
|
||||
21
.github/CODEOWNERS
vendored
21
.github/CODEOWNERS
vendored
@@ -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
|
||||
38
.github/ISSUE_TEMPLATE.md
vendored
38
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,38 +0,0 @@
|
||||
<!--
|
||||
Thanks for opening an issue! A few things to keep in mind:
|
||||
|
||||
- The issue tracker is only for bugs and feature requests.
|
||||
- Before reporting a bug, please try reproducing your issue against
|
||||
the latest version of Electron.
|
||||
- If you need general advice, join our Slack: http://atom-slack.herokuapp.com
|
||||
-->
|
||||
|
||||
* Electron version:
|
||||
* Operating system:
|
||||
|
||||
<!-- If this used to work -->
|
||||
* Last known working Electron version:
|
||||
|
||||
### Expected behavior
|
||||
|
||||
<!-- What do you think should happen? -->
|
||||
|
||||
### Actual behavior
|
||||
|
||||
<!-- What actually happens? -->
|
||||
|
||||
### How 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 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.
|
||||
|
||||
$ git clone $YOUR_URL -b $BRANCH
|
||||
$ npm install
|
||||
$ npm start || electron .
|
||||
|
||||
-->
|
||||
32
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
32
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
@@ -1,32 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve Electron
|
||||
|
||||
---
|
||||
|
||||
* Electron Version:
|
||||
* Operating System (Platform and Version):
|
||||
* Last known working Electron version:
|
||||
|
||||
**Expected Behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Actual behavior**
|
||||
A clear and concise description of what actually happened.
|
||||
|
||||
**To Reproduce**
|
||||
Your best chance of getting this bug looked at quickly is to provide a REPOSITORY that can be cloned and run.
|
||||
|
||||
You can fork [electron-quick-start](https://github.com/electron/electron-quick-start) and include a link to the branch with your changes.
|
||||
|
||||
If you provide a URL, please list the commands required to clone/setup/run your repo e.g.
|
||||
```sh
|
||||
$ git clone $YOUR_URL -b $BRANCH
|
||||
$ npm install
|
||||
$ npm start || electron .
|
||||
```
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Additional Information**
|
||||
Add any other context about the problem here.
|
||||
17
.github/ISSUE_TEMPLATE/Feature_request.md
vendored
17
.github/ISSUE_TEMPLATE/Feature_request.md
vendored
@@ -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.
|
||||
15
.github/PULL_REQUEST_TEMPLATE.md
vendored
15
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,15 +0,0 @@
|
||||
<!--
|
||||
Thank you for your Pull Request. Please provide a description above and review
|
||||
the requirements below.
|
||||
|
||||
Contributors guide: https://github.com/electron/electron/blob/master/CONTRIBUTING.md
|
||||
-->
|
||||
|
||||
##### Checklist
|
||||
<!-- Remove items that do not apply. For completed items, change [ ] to [x]. -->
|
||||
|
||||
- [ ] PR description included and stakeholders cc'd
|
||||
- [ ] `npm test` passes
|
||||
- [ ] tests are [changed or added](https://github.com/electron/electron/blob/master/docs/development/testing.md)
|
||||
- [ ] relevant documentation is changed or added
|
||||
- [ ] commit messages or PR title follow semantic [commit guidelines](https://github.com/electron/electron/blob/master/docs/development/pull-requests.md#commit-message-guidelines)
|
||||
53
.github/config.yml
vendored
53
.github/config.yml
vendored
@@ -1,53 +0,0 @@
|
||||
# Configuration for new-issue-welcome - https://github.com/behaviorbot/new-issue-welcome
|
||||
|
||||
# Comment to be posted to on first time issues
|
||||
newIssueWelcomeComment: |
|
||||
👋 Thanks for opening your first issue here! If you're reporting a 🐞 bug, please make sure you include steps to reproduce it. We get a lot of issues on this repo, so please be patient and we will get back to you as soon as we can.
|
||||
|
||||
To help make it easier for us to investigate your issue, please follow the [contributing guidelines](https://github.com/electron/electron/blob/master/CONTRIBUTING.md).
|
||||
|
||||
# Configuration for new-pr-welcome - https://github.com/behaviorbot/new-pr-welcome
|
||||
|
||||
# Comment to be posted to on PRs from first time contributors in your repository
|
||||
newPRWelcomeComment: |
|
||||
💖 Thanks for opening this pull request! 💖
|
||||
|
||||
We use [semantic commit messages](https://github.com/electron/electron/blob/master/docs/development/pull-requests.md#commit-message-guidelines) to streamline the release process. Before your pull request can be merged, you should **update your pull request title** to start with a semantic prefix, OR prefix at least one of your commit messages.
|
||||
|
||||
Examples of commit messages with semantic prefixes:
|
||||
|
||||
- `fix: don't overwrite prevent_default if default wasn't prevented`
|
||||
- `feat: add app.isPackaged() method`
|
||||
- `docs: app.isDefaultProtocolClient is now available on Linux`
|
||||
|
||||
Things that will help get your PR across the finish line:
|
||||
|
||||
- Follow the JavaScript, C++, and Python [coding style](https://github.com/electron/electron/blob/master/docs/development/coding-style.md).
|
||||
- Run `npm run lint` locally to catch formatting errors earlier.
|
||||
- Document any user-facing changes you've made following the [documentation styleguide](https://github.com/electron/electron/blob/master/docs/styleguide.md).
|
||||
- Include tests when adding/changing behavior.
|
||||
- Include screenshots and animated GIFs whenever possible.
|
||||
|
||||
We get a lot of pull requests on this repo, so please be patient and we will get back to you as soon as we can.
|
||||
|
||||
# Configuration for first-pr-merge - https://github.com/behaviorbot/first-pr-merge
|
||||
|
||||
# Comment to be posted to on pull requests merged by a first time user
|
||||
firstPRMergeComment: >
|
||||
Congrats on merging your first pull request! 🎉🎉🎉
|
||||
|
||||
# Configuration for trop - https://github.com/codebytere/trop
|
||||
|
||||
watchedProject:
|
||||
name: Backports
|
||||
|
||||
authorizedUsers:
|
||||
- alexeykuzmin
|
||||
- ckerr
|
||||
- codebytere
|
||||
- deepak1556
|
||||
- jkleinsc
|
||||
- MarshallOfSound
|
||||
- nitsakh
|
||||
- nornagon
|
||||
- zcbenz
|
||||
25
.github/stale.yml
vendored
25
.github/stale.yml
vendored
@@ -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!
|
||||
66
.gitignore
vendored
66
.gitignore
vendored
@@ -1,52 +1,30 @@
|
||||
.DS_Store
|
||||
.env
|
||||
.gclient_done
|
||||
**/.npmrc
|
||||
.tags*
|
||||
.vs/
|
||||
.vscode/
|
||||
*.log
|
||||
*.pyc
|
||||
*.sln
|
||||
*.swp
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
*.vcxproj
|
||||
*.vcxproj.filters
|
||||
*.vcxproj.user
|
||||
*.xcodeproj
|
||||
/.idea/
|
||||
/brightray/brightray.opensdf
|
||||
/brightray/brightray.sdf
|
||||
/brightray/brightray.sln
|
||||
/brightray/brightray.suo
|
||||
/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/download/
|
||||
/vendor/llvm-build/
|
||||
/vendor/llvm/
|
||||
/vendor/npm/
|
||||
/vendor/brightray/vendor/download/
|
||||
/vendor/debian_wheezy_amd64-sysroot/
|
||||
/vendor/debian_wheezy_arm-sysroot/
|
||||
/vendor/debian_wheezy_i386-sysroot/
|
||||
/vendor/python_26/
|
||||
/vendor/native_mksnapshot
|
||||
/vendor/LICENSES.chromium.html
|
||||
/vendor/npm/
|
||||
/vendor/llvm/
|
||||
/vendor/llvm-build/
|
||||
/vendor/.gclient
|
||||
node_modules/
|
||||
SHASUMS256.txt
|
||||
**/yarn.lock
|
||||
compile_commands.json
|
||||
.envrc
|
||||
|
||||
# npm package
|
||||
/npm/dist
|
||||
/npm/path.txt
|
||||
*.xcodeproj
|
||||
*.swp
|
||||
*.pyc
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
.vs/
|
||||
.vscode/
|
||||
*.vcxproj
|
||||
*.vcxproj.user
|
||||
*.vcxproj.filters
|
||||
*.sln
|
||||
debug.log
|
||||
npm-debug.log
|
||||
15
.gitmodules
vendored
15
.gitmodules
vendored
@@ -1,3 +1,6 @@
|
||||
[submodule "vendor/brightray"]
|
||||
path = vendor/brightray
|
||||
url = https://github.com/electron/brightray.git
|
||||
[submodule "vendor/node"]
|
||||
path = vendor/node
|
||||
url = https://github.com/electron/node.git
|
||||
@@ -7,6 +10,9 @@
|
||||
[submodule "vendor/breakpad"]
|
||||
path = vendor/breakpad
|
||||
url = https://github.com/electron/chromium-breakpad.git
|
||||
[submodule "vendor/native_mate"]
|
||||
path = vendor/native_mate
|
||||
url = https://github.com/zcbenz/native-mate.git
|
||||
[submodule "vendor/crashpad"]
|
||||
path = vendor/crashpad
|
||||
url = https://github.com/electron/crashpad.git
|
||||
@@ -16,12 +22,3 @@
|
||||
[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
1
.node-version
Normal file
@@ -0,0 +1 @@
|
||||
v6.3.0
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"plugins": [
|
||||
["remark-lint-code-block-style", "fenced"],
|
||||
["remark-lint-fenced-code-flag"]
|
||||
]
|
||||
}
|
||||
@@ -3,9 +3,6 @@ git:
|
||||
notifications:
|
||||
email: false
|
||||
|
||||
before_install:
|
||||
- export BOTO_CONFIG=/dev/null
|
||||
|
||||
language: node_js
|
||||
node_js:
|
||||
- "4"
|
||||
@@ -22,8 +19,6 @@ matrix:
|
||||
env: TARGET_ARCH=arm
|
||||
- os: linux
|
||||
env: TARGET_ARCH=ia32
|
||||
- os: linux
|
||||
env: TARGET_ARCH=arm64
|
||||
allow_failures:
|
||||
- os: osx
|
||||
|
||||
|
||||
592
BUILD.gn
592
BUILD.gn
@@ -1,592 +0,0 @@
|
||||
import("//build/config/locales.gni")
|
||||
import("//tools/grit/repack.gni")
|
||||
import("build/asar.gni")
|
||||
import("build/npm.gni")
|
||||
|
||||
if (is_mac) {
|
||||
import("//build/config/mac/rules.gni")
|
||||
import("//third_party/icu/config.gni")
|
||||
import("//v8/gni/v8.gni")
|
||||
}
|
||||
|
||||
if (is_linux) {
|
||||
import("//build/config/linux/pkg_config.gni")
|
||||
|
||||
pkg_config("gio_unix") {
|
||||
packages = [ "gio-unix-2.0" ]
|
||||
}
|
||||
}
|
||||
|
||||
declare_args() {
|
||||
electron_project_name = "electron"
|
||||
electron_product_name = "Electron"
|
||||
electron_company_name = "GitHub, Inc"
|
||||
electron_company_abbr = "github"
|
||||
electron_version = "0.0.0-dev"
|
||||
|
||||
enable_desktop_capturer = true
|
||||
enable_run_as_node = true
|
||||
enable_osr = true
|
||||
|
||||
# Provide a fake location provider for mocking
|
||||
# the geolocation responses. Disable it if you
|
||||
# need to test with chromium's location provider.
|
||||
# Should not be enabled for release build.
|
||||
enable_fake_location_provider = !is_official_build
|
||||
}
|
||||
|
||||
filenames_gypi = exec_script(
|
||||
"//build/gypi_to_gn.py",
|
||||
[
|
||||
rebase_path("filenames.gypi"),
|
||||
"--replace=<(SHARED_INTERMEDIATE_DIR)=$target_gen_dir",
|
||||
],
|
||||
"scope",
|
||||
[ "filenames.gypi" ]
|
||||
)
|
||||
|
||||
config("branding") {
|
||||
defines = [
|
||||
"ATOM_PRODUCT_NAME=\"$electron_product_name\"",
|
||||
"ATOM_PROJECT_NAME=\"$electron_project_name\"",
|
||||
]
|
||||
}
|
||||
|
||||
config("features") {
|
||||
defines = []
|
||||
if (enable_desktop_capturer) {
|
||||
defines += [ "ENABLE_DESKTOP_CAPTURER=1" ]
|
||||
}
|
||||
if (enable_run_as_node) {
|
||||
defines += [ "ENABLE_RUN_AS_NODE=1" ]
|
||||
}
|
||||
if (enable_osr) {
|
||||
defines += [ "ENABLE_OSR=1" ]
|
||||
}
|
||||
}
|
||||
|
||||
config("native_mate_config") {
|
||||
include_dirs = [
|
||||
"//third_party/native_mate",
|
||||
]
|
||||
cflags_cc = [
|
||||
"-Wno-deprecated-declarations",
|
||||
]
|
||||
cflags_objcc = cflags_cc
|
||||
}
|
||||
|
||||
source_set("native_mate") {
|
||||
deps = [
|
||||
"//base",
|
||||
"//net",
|
||||
"//v8:v8_headers",
|
||||
"build/node",
|
||||
]
|
||||
public_configs = [ ":native_mate_config" ]
|
||||
sources = [
|
||||
"//third_party/native_mate/native_mate/arguments.cc",
|
||||
"//third_party/native_mate/native_mate/arguments.h",
|
||||
"//third_party/native_mate/native_mate/compat.h",
|
||||
"//third_party/native_mate/native_mate/constructor.h",
|
||||
"//third_party/native_mate/native_mate/converter.cc",
|
||||
"//third_party/native_mate/native_mate/converter.h",
|
||||
"//third_party/native_mate/native_mate/dictionary.cc",
|
||||
"//third_party/native_mate/native_mate/dictionary.h",
|
||||
"//third_party/native_mate/native_mate/function_template.cc",
|
||||
"//third_party/native_mate/native_mate/function_template.h",
|
||||
"//third_party/native_mate/native_mate/handle.h",
|
||||
"//third_party/native_mate/native_mate/object_template_builder.cc",
|
||||
"//third_party/native_mate/native_mate/object_template_builder.h",
|
||||
"//third_party/native_mate/native_mate/persistent_dictionary.cc",
|
||||
"//third_party/native_mate/native_mate/persistent_dictionary.h",
|
||||
"//third_party/native_mate/native_mate/scoped_persistent.h",
|
||||
"//third_party/native_mate/native_mate/wrappable.cc",
|
||||
"//third_party/native_mate/native_mate/wrappable.h",
|
||||
"//third_party/native_mate/native_mate/wrappable_base.h",
|
||||
]
|
||||
}
|
||||
|
||||
npm_action("atom_browserify_sandbox") {
|
||||
deps = [ ":atom_js2c_copy" ]
|
||||
|
||||
sandbox_args = [
|
||||
"lib/sandboxed_renderer/init.js",
|
||||
"-r", "./lib/sandboxed_renderer/api/exports/electron.js:electron",
|
||||
"-r", "./lib/sandboxed_renderer/api/exports/fs.js:fs",
|
||||
"-r", "./lib/sandboxed_renderer/api/exports/os.js:os",
|
||||
"-r", "./lib/sandboxed_renderer/api/exports/path.js:path",
|
||||
"-r", "./lib/sandboxed_renderer/api/exports/child_process.js:child_process",
|
||||
]
|
||||
|
||||
inputs = [
|
||||
"lib/sandboxed_renderer/init.js",
|
||||
"lib/sandboxed_renderer/api/exports/electron.js",
|
||||
"lib/sandboxed_renderer/api/exports/fs.js",
|
||||
"lib/sandboxed_renderer/api/exports/os.js",
|
||||
"lib/sandboxed_renderer/api/exports/path.js",
|
||||
"lib/sandboxed_renderer/api/exports/child_process.js",
|
||||
]
|
||||
outputs = [ "$target_gen_dir/js2c/preload_bundle.js" ]
|
||||
|
||||
script = "browserify"
|
||||
args = sandbox_args + [
|
||||
"-o", rebase_path(outputs[0])
|
||||
]
|
||||
}
|
||||
|
||||
npm_action("atom_browserify_isolated") {
|
||||
deps = [ ":atom_js2c_copy" ]
|
||||
|
||||
inputs = [ "lib/isolated_renderer/init.js" ]
|
||||
outputs = [ "$target_gen_dir/js2c/isolated_bundle.js" ]
|
||||
|
||||
script = "browserify"
|
||||
args = inputs + [
|
||||
"-o", rebase_path(outputs[0])
|
||||
]
|
||||
}
|
||||
|
||||
copy("atom_js2c_copy") {
|
||||
sources = [
|
||||
"lib/common/asar.js",
|
||||
"lib/common/asar_init.js",
|
||||
]
|
||||
outputs = [ "$target_gen_dir/js2c/{{source_file_part}}" ]
|
||||
}
|
||||
|
||||
action("atom_js2c") {
|
||||
deps = [
|
||||
":atom_js2c_copy",
|
||||
":atom_browserify_sandbox",
|
||||
":atom_browserify_isolated",
|
||||
]
|
||||
|
||||
js2c_sources = filenames_gypi.js2c_sources
|
||||
|
||||
browserify_sources = [
|
||||
"$target_gen_dir/js2c/isolated_bundle.js",
|
||||
"$target_gen_dir/js2c/preload_bundle.js",
|
||||
]
|
||||
|
||||
inputs = js2c_sources + browserify_sources
|
||||
|
||||
outputs = [ "$target_gen_dir/atom_natives.h" ]
|
||||
|
||||
script = "tools/js2c.py"
|
||||
args = [
|
||||
rebase_path("//third_party/electron_node")
|
||||
] + rebase_path(outputs, root_build_dir) + [
|
||||
rebase_path("$target_gen_dir/js2c", root_build_dir)
|
||||
]
|
||||
}
|
||||
|
||||
asar("js2asar") {
|
||||
sources = filenames_gypi.js_sources
|
||||
outputs = [ "$root_out_dir/resources/electron.asar" ]
|
||||
root = "lib"
|
||||
}
|
||||
|
||||
asar("app2asar") {
|
||||
sources = filenames_gypi.default_app_sources
|
||||
outputs = [ "$root_out_dir/resources/default_app.asar" ]
|
||||
root = "default_app"
|
||||
}
|
||||
|
||||
group("electron") {
|
||||
deps = [ ":electron_lib" ]
|
||||
}
|
||||
|
||||
static_library("electron_lib") {
|
||||
configs += [
|
||||
"//v8:external_startup_data",
|
||||
]
|
||||
public_configs = [
|
||||
":branding",
|
||||
":features",
|
||||
]
|
||||
deps = [
|
||||
"//chrome/common:constants",
|
||||
"//components/cdm/renderer",
|
||||
"//components/network_session_configurator/common",
|
||||
"//components/prefs",
|
||||
"//components/printing/common",
|
||||
"//components/security_state/content",
|
||||
"//content/public/browser",
|
||||
"//device/geolocation",
|
||||
"//gin",
|
||||
"//net:net_resources",
|
||||
"//ppapi/host",
|
||||
"//ppapi/proxy",
|
||||
"//ppapi/shared_impl",
|
||||
"//printing",
|
||||
"//services/device/wake_lock/power_save_blocker", # TODO: this requires a visibility patch to chromium src
|
||||
"//skia",
|
||||
"//third_party/WebKit/public:blink",
|
||||
"//third_party/boringssl",
|
||||
"//third_party/crashpad/crashpad/client",
|
||||
"//third_party/leveldatabase",
|
||||
"//third_party/libyuv",
|
||||
"//third_party/webrtc/modules/desktop_capture",
|
||||
"//third_party/webrtc/modules/desktop_capture:primitives",
|
||||
"//ui/events:dom_keycode_converter",
|
||||
"//ui/views",
|
||||
"//v8",
|
||||
":atom_js2c",
|
||||
":native_mate",
|
||||
"brightray",
|
||||
"build/node",
|
||||
]
|
||||
if (is_mac) {
|
||||
deps += [
|
||||
"//ui/accelerated_widget_mac",
|
||||
"//base/allocator:features",
|
||||
]
|
||||
}
|
||||
if (is_linux) {
|
||||
deps += [
|
||||
"//build/config/linux/gtk3",
|
||||
"//chrome/browser/ui/libgtkui",
|
||||
"//device/bluetooth",
|
||||
"//third_party/breakpad:client",
|
||||
"//ui/events/devices/x11",
|
||||
"//ui/events/platform/x11",
|
||||
"//ui/native_theme",
|
||||
"//ui/views/controls/webview",
|
||||
"//ui/wm",
|
||||
]
|
||||
configs += [ ":gio_unix" ]
|
||||
}
|
||||
defines = [
|
||||
# This is defined in skia/skia_common.gypi.
|
||||
"SK_SUPPORT_LEGACY_GETTOPDEVICE",
|
||||
# Disable warnings for g_settings_list_schemas.
|
||||
"GLIB_DISABLE_DEPRECATION_WARNINGS",
|
||||
|
||||
# Import V8 symbols from shared library (node.dll / libnode.so)
|
||||
"USING_V8_SHARED",
|
||||
"USING_V8_PLATFORM_SHARED",
|
||||
"USING_V8_BASE_SHARED",
|
||||
|
||||
# Enables SkBitmap size 64 operations
|
||||
#"SK_SUPPORT_LEGACY_SAFESIZE64", # doesn't seem to be needed to build?
|
||||
]
|
||||
include_dirs = [
|
||||
"chromium_src",
|
||||
".",
|
||||
"$target_gen_dir",
|
||||
# TODO(nornagon): replace usage of SchemeRegistry by an actually exported
|
||||
# API of blink, then delete this include dir.
|
||||
"//third_party/WebKit/Source",
|
||||
# NOTE(nornagon): other chromium files use the full path to include
|
||||
# crashpad; this is just here for compatibility between GN and GYP, so that
|
||||
# the #includes can be agnostic about where crashpad is vendored.
|
||||
"//third_party/crashpad",
|
||||
]
|
||||
if (is_linux) {
|
||||
include_dirs += [
|
||||
"//third_party/breakpad",
|
||||
]
|
||||
}
|
||||
|
||||
extra_source_filters = []
|
||||
if (!is_linux) {
|
||||
extra_source_filters += [
|
||||
"*\bx/*",
|
||||
"*_x11.h",
|
||||
"*_x11.cc",
|
||||
"*_gtk.h",
|
||||
"*_gtk.cc",
|
||||
]
|
||||
}
|
||||
if (!is_win) {
|
||||
extra_source_filters += [
|
||||
"*\bwin_*.h",
|
||||
"*\bwin_*.cc",
|
||||
]
|
||||
}
|
||||
if (is_mac) {
|
||||
extra_source_filters += [
|
||||
"*_views.cc",
|
||||
"*_views.h",
|
||||
"*\bviews/*",
|
||||
"*/autofill_popup.cc",
|
||||
"*/autofill_popup.h",
|
||||
]
|
||||
}
|
||||
|
||||
set_sources_assignment_filter(sources_assignment_filter + extra_source_filters)
|
||||
sources = filenames_gypi.lib_sources
|
||||
set_sources_assignment_filter(sources_assignment_filter)
|
||||
|
||||
if (enable_fake_location_provider) {
|
||||
defines += [
|
||||
"OVERRIDE_LOCATION_PROVIDER"
|
||||
]
|
||||
sources += filenames_gypi.lib_sources_location_provider
|
||||
}
|
||||
|
||||
if (enable_run_as_node) {
|
||||
sources += [
|
||||
"atom/app/node_main.cc",
|
||||
"atom/app/node_main.h",
|
||||
]
|
||||
}
|
||||
|
||||
if (enable_osr) {
|
||||
sources += [
|
||||
"atom/browser/api/atom_api_web_contents_osr.cc",
|
||||
"atom/browser/osr/osr_output_device.cc",
|
||||
"atom/browser/osr/osr_output_device.h",
|
||||
"atom/browser/osr/osr_render_widget_host_view.cc",
|
||||
"atom/browser/osr/osr_render_widget_host_view.h",
|
||||
"atom/browser/osr/osr_render_widget_host_view_mac.mm",
|
||||
"atom/browser/osr/osr_view_proxy.cc",
|
||||
"atom/browser/osr/osr_view_proxy.h",
|
||||
"atom/browser/osr/osr_web_contents_view.cc",
|
||||
"atom/browser/osr/osr_web_contents_view.h",
|
||||
"atom/browser/osr/osr_web_contents_view_mac.mm",
|
||||
]
|
||||
deps += [
|
||||
"//ui/compositor",
|
||||
"//components/viz/service",
|
||||
]
|
||||
}
|
||||
|
||||
if (enable_desktop_capturer) {
|
||||
sources += [
|
||||
"atom/browser/api/atom_api_desktop_capturer.cc",
|
||||
"atom/browser/api/atom_api_desktop_capturer.h",
|
||||
]
|
||||
}
|
||||
|
||||
if (is_mac) {
|
||||
libs = [
|
||||
"Squirrel.framework",
|
||||
"ReactiveCocoa.framework",
|
||||
"Mantle.framework",
|
||||
]
|
||||
cflags_objcc = [
|
||||
"-F", rebase_path("external_binaries", root_build_dir)
|
||||
]
|
||||
if (true) { # !is_mas_build
|
||||
# ReactiveCocoa which is used by Squirrel requires using __weak.
|
||||
cflags_objcc += [ "-fobjc-weak" ]
|
||||
}
|
||||
}
|
||||
if (is_linux) {
|
||||
sources += filenames_gypi.lib_sources_linux
|
||||
sources += filenames_gypi.lib_sources_nss
|
||||
}
|
||||
}
|
||||
|
||||
if (is_mac) {
|
||||
electron_framework_name = electron_product_name + " Framework"
|
||||
electron_helper_name = electron_product_name + " Helper"
|
||||
electron_framework_version = "A"
|
||||
electron_mac_bundle_id = "com.$electron_company_abbr.$electron_project_name"
|
||||
|
||||
mac_xib_bundle_data("electron_xibs") {
|
||||
sources = [ "atom/common/resources/mac/MainMenu.xib" ]
|
||||
}
|
||||
|
||||
bundle_data("electron_framework_resources") {
|
||||
public_deps = [
|
||||
"//content/shell:pak",
|
||||
":electron_locales",
|
||||
]
|
||||
sources = [
|
||||
"$root_out_dir/content_shell.pak",
|
||||
]
|
||||
if (icu_use_data_file) {
|
||||
sources += [ "$root_out_dir/icudtl.dat" ]
|
||||
public_deps += [ "//third_party/icu:icudata" ]
|
||||
}
|
||||
if (v8_use_external_startup_data) {
|
||||
sources += [
|
||||
"$root_out_dir/natives_blob.bin",
|
||||
"$root_out_dir/snapshot_blob.bin",
|
||||
]
|
||||
public_deps += [ "//v8" ]
|
||||
}
|
||||
outputs = [
|
||||
"{{bundle_resources_dir}}/{{source_file_part}}",
|
||||
]
|
||||
}
|
||||
|
||||
bundle_data("electron_framework_libraries") {
|
||||
public_deps = [ "build/node" ]
|
||||
sources = [
|
||||
"$root_out_dir/libnode.dylib"
|
||||
]
|
||||
outputs = [
|
||||
"{{bundle_contents_dir}}/Libraries/{{source_file_part}}"
|
||||
]
|
||||
}
|
||||
|
||||
bundle_data("electron_framework_helpers") {
|
||||
sources = [
|
||||
"$root_out_dir/crashpad_handler",
|
||||
]
|
||||
|
||||
outputs = [
|
||||
"{{bundle_resources_dir}}/{{source_file_part}}",
|
||||
]
|
||||
|
||||
public_deps = [
|
||||
"//third_party/crashpad/crashpad/handler:crashpad_handler",
|
||||
]
|
||||
}
|
||||
|
||||
mac_framework_bundle("electron_framework") {
|
||||
output_name = electron_framework_name
|
||||
framework_version = electron_framework_version
|
||||
framework_contents = [ "Resources" ]
|
||||
public_deps = [ ":electron_lib" ]
|
||||
deps = [
|
||||
"//base",
|
||||
"//base:i18n",
|
||||
":electron_framework_helpers",
|
||||
":electron_framework_libraries",
|
||||
":electron_framework_resources",
|
||||
":electron_xibs",
|
||||
]
|
||||
info_plist = "atom/common/resources/mac/Info.plist"
|
||||
extra_substitutions = [
|
||||
"ATOM_BUNDLE_ID=$electron_mac_bundle_id.framework",
|
||||
]
|
||||
|
||||
include_dirs = [
|
||||
".",
|
||||
]
|
||||
sources = filenames_gypi.framework_sources
|
||||
|
||||
libs = [
|
||||
"Carbon.framework",
|
||||
"QuartzCore.framework",
|
||||
"Quartz.framework",
|
||||
"Security.framework",
|
||||
"SecurityInterface.framework",
|
||||
"ServiceManagement.framework",
|
||||
"StoreKit.framework",
|
||||
]
|
||||
ldflags = [
|
||||
"-F", rebase_path("external_binaries", root_build_dir),
|
||||
"-Wl,-install_name,@rpath/$output_name.framework/$output_name",
|
||||
"-rpath",
|
||||
"@loader_path/Libraries",
|
||||
]
|
||||
if (is_component_build) {
|
||||
ldflags += [
|
||||
"-rpath",
|
||||
"@executable_path/../../../../../.."
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
mac_app_bundle("electron_helper_app") {
|
||||
output_name = electron_helper_name
|
||||
deps = [ ":electron_framework+link" ]
|
||||
sources = filenames_gypi.app_sources
|
||||
include_dirs = [ "." ]
|
||||
info_plist = "atom/renderer/resources/mac/Info.plist"
|
||||
extra_substitutions = [
|
||||
"ATOM_BUNDLE_ID=$electron_mac_bundle_id.helper",
|
||||
]
|
||||
ldflags = [
|
||||
"-rpath",
|
||||
"@executable_path/../../..",
|
||||
]
|
||||
}
|
||||
|
||||
bundle_data("electron_app_framework_bundle_data") {
|
||||
sources = [
|
||||
"$root_out_dir/$electron_framework_name.framework",
|
||||
"$root_out_dir/$electron_helper_name.app",
|
||||
"external_binaries/Squirrel.framework",
|
||||
"external_binaries/ReactiveCocoa.framework",
|
||||
"external_binaries/Mantle.framework",
|
||||
]
|
||||
outputs = [
|
||||
"{{bundle_contents_dir}}/Frameworks/{{source_file_part}}",
|
||||
]
|
||||
public_deps = [
|
||||
":electron_framework+link",
|
||||
":electron_helper_app",
|
||||
]
|
||||
}
|
||||
|
||||
bundle_data("electron_app_resources") {
|
||||
public_deps = [
|
||||
":js2asar",
|
||||
":app2asar",
|
||||
]
|
||||
sources = [
|
||||
"$root_out_dir/resources/electron.asar",
|
||||
"$root_out_dir/resources/default_app.asar",
|
||||
]
|
||||
outputs = [
|
||||
"{{bundle_resources_dir}}/{{source_file_part}}"
|
||||
]
|
||||
}
|
||||
|
||||
repack_locales("electron_locales") {
|
||||
source_patterns = [
|
||||
"${root_gen_dir}/content/app/strings/content_strings_",
|
||||
]
|
||||
deps = [
|
||||
"//content/app/strings",
|
||||
]
|
||||
|
||||
input_locales = locales
|
||||
|
||||
if (is_mac) {
|
||||
output_locales = locales_as_mac_outputs
|
||||
} else {
|
||||
output_locales = locales
|
||||
}
|
||||
|
||||
if (is_mac) {
|
||||
output_dir = "$root_gen_dir/repack"
|
||||
copy_data_to_bundle = true
|
||||
} else {
|
||||
output_dir = root_out_dir
|
||||
}
|
||||
}
|
||||
|
||||
mac_app_bundle("electron_app") {
|
||||
output_name = electron_product_name
|
||||
sources = filenames_gypi.app_sources
|
||||
include_dirs = [ "." ]
|
||||
deps = [
|
||||
":electron_app_framework_bundle_data",
|
||||
":electron_app_resources",
|
||||
]
|
||||
info_plist = "atom/browser/resources/mac/Info.plist"
|
||||
extra_substitutions = [
|
||||
"ATOM_BUNDLE_ID=$electron_mac_bundle_id",
|
||||
]
|
||||
ldflags = [
|
||||
"-rpath",
|
||||
"@executable_path/../Frameworks",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
if (is_linux) {
|
||||
executable("electron_app") {
|
||||
output_name = electron_project_name
|
||||
sources = filenames_gypi.app_sources
|
||||
include_dirs = [ "." ]
|
||||
deps = [
|
||||
":app2asar",
|
||||
":electron_lib",
|
||||
":js2asar",
|
||||
"//build/config:exe_and_shlib_deps",
|
||||
"//chrome:packed_resources",
|
||||
"//content/shell:copy_shell_resources",
|
||||
"//content/shell:pak",
|
||||
"//third_party/WebKit/public:image_resources",
|
||||
"//ui/strings",
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -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/
|
||||
|
||||
101
CONTRIBUTING.md
101
CONTRIBUTING.md
@@ -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)
|
||||
|
||||
:+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 atom@github.com.
|
||||
|
||||
The following is a set of guidelines for contributing to Electron.
|
||||
These are just guidelines, not rules, use your best judgment and feel free to
|
||||
propose changes to this document in a pull request.
|
||||
|
||||
## [Issues](https://electronjs.org/docs/development/issues)
|
||||
## Submitting Issues
|
||||
|
||||
Issues are created [here](https://github.com/electron/electron/issues/new).
|
||||
* You can create an issue [here](https://github.com/electron/electron/issues/new),
|
||||
but before doing that please read the notes below and include as many details as
|
||||
possible with your report. If you can, please include:
|
||||
* The version of Electron you are using
|
||||
* The operating system you are using
|
||||
* If applicable, what you were doing when the issue arose and what you
|
||||
expected to happen
|
||||
* Other things that will help resolve your issue:
|
||||
* Screenshots and animated GIFs
|
||||
* Error output that appears in your terminal, dev tools or as an alert
|
||||
* Perform a [cursory search](https://github.com/electron/electron/issues?utf8=✓&q=is%3Aissue+)
|
||||
to see if a similar issue has already been submitted
|
||||
|
||||
* [How to Contribute in Issues](https://electronjs.org/docs/development/issues#how-to-contribute-in-issues)
|
||||
* [Asking for General Help](https://electronjs.org/docs/development/issues#asking-for-general-help)
|
||||
* [Submitting a Bug Report](https://electronjs.org/docs/development/issues#submitting-a-bug-report)
|
||||
* [Triaging a Bug Report](https://electronjs.org/docs/development/issues#triaging-a-bug-report)
|
||||
* [Resolving a Bug Report](https://electronjs.org/docs/development/issues#resolving-a-bug-report)
|
||||
## Submitting Pull Requests
|
||||
|
||||
### Issue Maintenance and Closure
|
||||
* If an issue is inactive for 45 days (no activity of any kind), it will be
|
||||
marked for closure with `stale`.
|
||||
* If after this label is applied, no further activity occurs in the next 7 days,
|
||||
the issue will be closed.
|
||||
* If an issue has been closed and you still feel it's relevant, feel free to
|
||||
ping a maintainer or add a comment!
|
||||
* Include screenshots and animated GIFs in your pull request whenever possible.
|
||||
* Follow the JavaScript, C++, and Python [coding style defined in docs](/docs/development/coding-style.md).
|
||||
* Write documentation in [Markdown](https://daringfireball.net/projects/markdown).
|
||||
See the [Documentation Styleguide](/docs/styleguide.md).
|
||||
* Use short, present tense commit messages. See [Commit Message Styleguide](#git-commit-messages).
|
||||
|
||||
## [Pull Requests](https://electronjs.org/docs/development/pull-requests)
|
||||
## Styleguides
|
||||
|
||||
Pull Requests are the way concrete changes are made to the code, documentation,
|
||||
dependencies, and tools contained in the `electron/electron` repository.
|
||||
### General Code
|
||||
|
||||
* [Setting up your local environment](https://electronjs.org/docs/development/pull-requests#setting-up-your-local-environment)
|
||||
* [Step 1: Fork](https://electronjs.org/docs/development/pull-requests#step-1-fork)
|
||||
* [Step 2: Build](https://electronjs.org/docs/development/pull-requests#step-2-build)
|
||||
* [Step 3: Branch](https://electronjs.org/docs/development/pull-requests#step-3-branch)
|
||||
* [The Process of Making Changes](https://electronjs.org/docs/development/pull-requests#the-process-of-making-changes)
|
||||
* [Step 4: Code](https://electronjs.org/docs/development/pull-requests#step-4-code)
|
||||
* [Step 5: Commit](https://electronjs.org/docs/development/pull-requests#step-5-commit)
|
||||
* [Commit message guidelines](https://electronjs.org/docs/development/pull-requests#commit-message-guidelines)
|
||||
* [Step 6: Rebase](https://electronjs.org/docs/development/pull-requests#step-6-rebase)
|
||||
* [Step 7: Test](https://electronjs.org/docs/development/pull-requests#step-7-test)
|
||||
* [Step 8: Push](https://electronjs.org/docs/development/pull-requests#step-8-push)
|
||||
* [Step 8: Opening the Pull Request](https://electronjs.org/docs/development/pull-requests#step-8-opening-the-pull-request)
|
||||
* [Step 9: Discuss and Update](#step-9-discuss-and-update)
|
||||
* [Approval and Request Changes Workflow](https://electronjs.org/docs/development/pull-requests#approval-and-request-changes-workflow)
|
||||
* [Step 10: Landing](https://electronjs.org/docs/development/pull-requests#step-10-landing)
|
||||
* [Continuous Integration Testing](https://electronjs.org/docs/development/pull-requests#continuous-integration-testing)
|
||||
* End files with a newline.
|
||||
* Place requires in the following order:
|
||||
* Built in Node Modules (such as `path`)
|
||||
* Built in Electron Modules (such as `ipc`, `app`)
|
||||
* Local Modules (using relative paths)
|
||||
* Place class properties in the following order:
|
||||
* Class methods and properties (methods starting with a `@`)
|
||||
* Instance methods and properties
|
||||
* Avoid platform-dependent code:
|
||||
* Use `path.join()` to concatenate filenames.
|
||||
* Use `os.tmpdir()` rather than `/tmp` when you need to reference the
|
||||
temporary directory.
|
||||
* Using a plain `return` when returning explicitly at the end of a function.
|
||||
* Not `return null`, `return undefined`, `null`, or `undefined`
|
||||
|
||||
## Style Guides
|
||||
### Git Commit Messages
|
||||
|
||||
See [Coding Style](https://electronjs.org/docs/development/coding-style) for information about which standards Electron adheres to in different parts of its codebase.
|
||||
|
||||
## Further Reading
|
||||
|
||||
For more in-depth guides on developing Electron, see
|
||||
[/docs/development](/docs/development/README.md)
|
||||
* Use the present tense ("Add feature" not "Added feature")
|
||||
* Use the imperative mood ("Move cursor to..." not "Moves cursor to...")
|
||||
* Limit the first line to 72 characters or less
|
||||
* Reference issues and pull requests liberally
|
||||
* When only changing documentation, include `[ci skip]` in the commit description
|
||||
* Consider starting the commit message with an applicable emoji:
|
||||
* :art: `:art:` when improving the format/structure of the code
|
||||
* :racehorse: `:racehorse:` when improving performance
|
||||
* :non-potable_water: `:non-potable_water:` when plugging memory leaks
|
||||
* :memo: `:memo:` when writing docs
|
||||
* :penguin: `:penguin:` when fixing something on Linux
|
||||
* :apple: `:apple:` when fixing something on macOS
|
||||
* :checkered_flag: `:checkered_flag:` when fixing something on Windows
|
||||
* :bug: `:bug:` when fixing a bug
|
||||
* :fire: `:fire:` when removing code or files
|
||||
* :green_heart: `:green_heart:` when fixing the CI build
|
||||
* :white_check_mark: `:white_check_mark:` when adding tests
|
||||
* :lock: `:lock:` when dealing with security
|
||||
* :arrow_up: `:arrow_up:` when upgrading dependencies
|
||||
* :arrow_down: `:arrow_down:` when downgrading dependencies
|
||||
* :shirt: `:shirt:` when removing linter warnings
|
||||
|
||||
73
DEPS
73
DEPS
@@ -1,73 +0,0 @@
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'63.0.3239.150',
|
||||
'libchromiumcontent_revision':
|
||||
'39cd2efa4af73897f89c51e43e0c0746f1601c80',
|
||||
'node_version':
|
||||
'v9.7.0-33-g538a5023af',
|
||||
'native_mate_revision':
|
||||
'4cd7d113915de0cc08e9a218be35bff9c7361906',
|
||||
|
||||
'chromium_git':
|
||||
'https://chromium.googlesource.com',
|
||||
|
||||
'electron_git':
|
||||
'https://github.com/electron',
|
||||
}
|
||||
|
||||
deps = {
|
||||
'src':
|
||||
(Var("chromium_git")) + '/chromium/src.git@' + (Var("chromium_version")),
|
||||
'src/libchromiumcontent':
|
||||
(Var("electron_git")) + '/libchromiumcontent.git@' + (Var("libchromiumcontent_revision")),
|
||||
'src/third_party/electron_node':
|
||||
(Var("electron_git")) + '/node.git@' + (Var("node_version")),
|
||||
'src/third_party/native_mate':
|
||||
(Var("electron_git")) + '/native-mate.git@' + (Var("native_mate_revision")),
|
||||
}
|
||||
|
||||
hooks = [
|
||||
{
|
||||
'action': [
|
||||
'src/libchromiumcontent/script/apply-patches'
|
||||
],
|
||||
'pattern':
|
||||
'src/libchromiumcontent',
|
||||
'name':
|
||||
'patch_chromium'
|
||||
},
|
||||
{
|
||||
'action': [
|
||||
'src/electron/script/update-external-binaries.py'
|
||||
],
|
||||
'pattern':
|
||||
'src/electron/script/update-external-binaries.py',
|
||||
'name':
|
||||
'electron_external_binaries'
|
||||
},
|
||||
{
|
||||
'action': [
|
||||
'bash',
|
||||
'-c',
|
||||
# NOTE(nornagon): this ridiculous {{}} stuff is because these strings get
|
||||
# variable-substituted twice by gclient.
|
||||
'echo -e "#\\n{{{{\'variables\':{{{{}}}}}}}}" > src/third_party/electron_node/config.gypi',
|
||||
],
|
||||
'pattern': 'src/third_party/electron_node',
|
||||
'name': 'touch_node_config_gypi'
|
||||
},
|
||||
{
|
||||
'action': [
|
||||
'bash',
|
||||
'-c',
|
||||
'cd src/electron; npm install',
|
||||
],
|
||||
'pattern': 'src/electron/package.json',
|
||||
'name': 'electron_npm_deps'
|
||||
},
|
||||
]
|
||||
|
||||
recursedeps = [
|
||||
'src',
|
||||
'src/libchromiumcontent',
|
||||
]
|
||||
24
Dockerfile
24
Dockerfile
@@ -1,24 +0,0 @@
|
||||
FROM electronbuilds/libchromiumcontent:0.0.4
|
||||
|
||||
USER root
|
||||
|
||||
# Set up HOME directory
|
||||
ENV HOME=/home
|
||||
RUN chmod a+rwx /home
|
||||
|
||||
# Install node.js
|
||||
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash -
|
||||
RUN apt-get install -y nodejs
|
||||
|
||||
# Install wget used by crash reporter
|
||||
RUN apt-get install -y wget
|
||||
|
||||
# Install python-dbusmock
|
||||
RUN apt-get install -y python-dbusmock
|
||||
|
||||
# Install libnotify
|
||||
RUN apt-get install -y libnotify-bin
|
||||
|
||||
# Add xvfb init script
|
||||
ADD tools/xvfb-init.sh /etc/init.d/xvfb
|
||||
RUN chmod a+x /etc/init.d/xvfb
|
||||
@@ -1,35 +0,0 @@
|
||||
FROM multiarch/debian-debootstrap:arm64-jessie
|
||||
|
||||
RUN apt-get update && apt-get install -y\
|
||||
bison \
|
||||
build-essential \
|
||||
clang \
|
||||
curl \
|
||||
gperf \
|
||||
libasound2 \
|
||||
libasound2-dev \
|
||||
libcap-dev \
|
||||
libcups2-dev \
|
||||
libdbus-1-dev \
|
||||
libgconf-2-4 \
|
||||
libgconf2-dev \
|
||||
libgnome-keyring-dev \
|
||||
libgtk-3-0 \
|
||||
libgtk-3-dev \
|
||||
libnotify-bin \
|
||||
libnotify-dev \
|
||||
libnss3 \
|
||||
libnss3-dev \
|
||||
libx11-xcb-dev \
|
||||
libxss1 \
|
||||
libxtst-dev \
|
||||
libxtst6 \
|
||||
python-dbusmock \
|
||||
wget \
|
||||
xvfb
|
||||
|
||||
ADD tools/xvfb-init.sh /etc/init.d/xvfb
|
||||
RUN chmod a+x /etc/init.d/xvfb
|
||||
ADD tools/run-electron.sh /run-electron.sh
|
||||
RUN chmod a+x /run-electron.sh
|
||||
CMD sh /run-electron.sh
|
||||
@@ -1,63 +0,0 @@
|
||||
FROM arm64v8/ubuntu:16.04
|
||||
|
||||
RUN groupadd --gid 1000 builduser \
|
||||
&& useradd --uid 1000 --gid builduser --shell /bin/bash --create-home builduser
|
||||
|
||||
RUN groupadd --gid 114 jenkins \
|
||||
&& useradd --uid 110 --gid jenkins --shell /bin/bash --create-home jenkins
|
||||
|
||||
# Set up TEMP directory
|
||||
ENV TEMP=/tmp
|
||||
RUN chmod a+rwx /tmp
|
||||
|
||||
RUN apt-get update && apt-get install -y\
|
||||
bison \
|
||||
build-essential \
|
||||
clang \
|
||||
curl \
|
||||
gperf \
|
||||
git \
|
||||
libasound2 \
|
||||
libasound2-dev \
|
||||
libcap-dev \
|
||||
libcups2-dev \
|
||||
libdbus-1-dev \
|
||||
libgconf-2-4 \
|
||||
libgconf2-dev \
|
||||
libgnome-keyring-dev \
|
||||
libgtk2.0-0 \
|
||||
libgtk2.0-dev \
|
||||
libgtk-3-0 \
|
||||
libgtk-3-dev \
|
||||
libnotify-dev \
|
||||
libnss3 \
|
||||
libnss3-dev \
|
||||
libx11-xcb-dev \
|
||||
libxss1 \
|
||||
libxtst-dev \
|
||||
libxtst6 \
|
||||
lsb-release \
|
||||
locales \
|
||||
ninja \
|
||||
python-setuptools \
|
||||
python-pip \
|
||||
python-dbusmock \
|
||||
wget \
|
||||
xvfb
|
||||
|
||||
# Install node.js
|
||||
RUN curl -sL https://deb.nodesource.com/setup_8.x | bash -
|
||||
RUN apt-get update && apt-get install -y nodejs
|
||||
|
||||
# Install crcmod
|
||||
RUN pip install -U crcmod
|
||||
|
||||
ADD tools/xvfb-init.sh /etc/init.d/xvfb
|
||||
RUN chmod a+x /etc/init.d/xvfb
|
||||
|
||||
# Install ninja in /usr/local
|
||||
RUN cd /usr/local && git clone https://github.com/martine/ninja.git -b v1.5.3
|
||||
RUN cd /usr/local/ninja && ./configure.py --bootstrap
|
||||
|
||||
USER builduser
|
||||
WORKDIR /home/builduser
|
||||
@@ -1,36 +0,0 @@
|
||||
FROM multiarch/debian-debootstrap:armhf-jessie
|
||||
|
||||
RUN apt-get update && apt-get install -y\
|
||||
bison \
|
||||
build-essential \
|
||||
clang \
|
||||
curl \
|
||||
gperf \
|
||||
libasound2 \
|
||||
libasound2-dev \
|
||||
libcap-dev \
|
||||
libcups2-dev \
|
||||
libdbus-1-dev \
|
||||
libgconf-2-4 \
|
||||
libgconf2-dev \
|
||||
libgnome-keyring-dev \
|
||||
libgtk-3-0 \
|
||||
libgtk-3-dev \
|
||||
libnotify-bin \
|
||||
libnotify-dev \
|
||||
libnss3 \
|
||||
libnss3-dev \
|
||||
libx11-xcb-dev \
|
||||
libxss1 \
|
||||
libxtst-dev \
|
||||
libxtst6 \
|
||||
python-dbusmock \
|
||||
git \
|
||||
wget \
|
||||
xvfb
|
||||
|
||||
ADD tools/xvfb-init.sh /etc/init.d/xvfb
|
||||
RUN chmod a+x /etc/init.d/xvfb
|
||||
ADD tools/run-electron.sh /run-electron.sh
|
||||
RUN chmod a+x /run-electron.sh
|
||||
CMD sh /run-electron.sh
|
||||
@@ -1,23 +0,0 @@
|
||||
FROM electronbuilds/libchromiumcontent:0.0.4
|
||||
|
||||
USER root
|
||||
|
||||
# Install node.js
|
||||
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash -
|
||||
RUN apt-get install -y nodejs
|
||||
|
||||
# Install wget used by crash reporter
|
||||
RUN apt-get install -y wget
|
||||
|
||||
# Install python-dbusmock
|
||||
RUN apt-get install -y python-dbusmock
|
||||
|
||||
# Install libnotify
|
||||
RUN apt-get install -y libnotify-bin
|
||||
|
||||
# Add xvfb init script
|
||||
ADD tools/xvfb-init.sh /etc/init.d/xvfb
|
||||
RUN chmod a+x /etc/init.d/xvfb
|
||||
|
||||
USER builduser
|
||||
WORKDIR /home/builduser
|
||||
2
ISSUE_TEMPLATE.md
Normal file
2
ISSUE_TEMPLATE.md
Normal file
@@ -0,0 +1,2 @@
|
||||
* Electron version:
|
||||
* Operating system:
|
||||
2
LICENSE
2
LICENSE
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2013-2018 GitHub Inc.
|
||||
Copyright (c) 2014 GitHub Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
||||
125
README.md
125
README.md
@@ -1,98 +1,81 @@
|
||||
[](https://electronjs.org)
|
||||
[](http://electron.atom.io/)
|
||||
|
||||
[](https://travis-ci.org/electron/electron)
|
||||
[](https://ci.appveyor.com/project/Atom/electron)
|
||||
[](https://david-dm.org/electron/electron#info=devDependencies)
|
||||
[](http://atom-slack.herokuapp.com/)
|
||||
|
||||
[](https://circleci.com/gh/electron/electron/tree/master)
|
||||
[](https://windows-ci.electronjs.org/project/AppVeyor/electron/branch/master)
|
||||
[](https://david-dm.org/electron/electron?type=dev)
|
||||
[](https://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)
|
||||
|
||||
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](http://electron.atom.io/apps).
|
||||
|
||||
Follow [@ElectronJS](https://twitter.com/electronjs) on Twitter for important
|
||||
announcements.
|
||||
|
||||
This project adheres to the Contributor Covenant
|
||||
[code of conduct](https://github.com/electron/electron/tree/master/CODE_OF_CONDUCT.md).
|
||||
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](mailto:coc@electronjs.org).
|
||||
behavior to electron@github.com.
|
||||
|
||||
## Installation
|
||||
## Downloads
|
||||
|
||||
To install prebuilt Electron binaries, use [`npm`](https://docs.npmjs.com/).
|
||||
The preferred method is to install Electron as a development dependency in your
|
||||
app:
|
||||
Prebuilt binaries and debug symbols of Electron for Linux, Windows and macOS can
|
||||
be found on the [releases](https://github.com/electron/electron/releases) page.
|
||||
|
||||
You can also use [`npm`](https://docs.npmjs.com/) to install prebuilt electron
|
||||
binaries:
|
||||
|
||||
```sh
|
||||
npm install electron --save-dev [--save-exact]
|
||||
```
|
||||
# Install the `electron` command globally in your $PATH
|
||||
npm install electron -g
|
||||
|
||||
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).
|
||||
|
||||
For more installation options and troubleshooting tips, see
|
||||
[installation](docs/tutorial/installation.md).
|
||||
|
||||
## Quick start
|
||||
|
||||
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
|
||||
|
||||
- [electronjs.org/docs](https://electronjs.org/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/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
|
||||
|
||||
## Programmatic usage
|
||||
|
||||
Most people use Electron from the command line, but if you require `electron` inside
|
||||
your **Node app** (not your Electron app) it will return the file path to the
|
||||
binary. Use this to spawn Electron from Node scripts:
|
||||
|
||||
```javascript
|
||||
const electron = require('electron')
|
||||
const proc = require('child_process')
|
||||
|
||||
// will print something similar to /Users/maf/.../Electron
|
||||
console.log(electron)
|
||||
|
||||
// spawn Electron
|
||||
const child = proc.spawn(electron)
|
||||
# Install as a development dependency
|
||||
npm install electron --save-dev
|
||||
```
|
||||
|
||||
### Mirrors
|
||||
|
||||
- [China](https://npm.taobao.org/mirrors/electron)
|
||||
|
||||
## Documentation
|
||||
|
||||
Guides and the API reference are located in the
|
||||
[docs](https://github.com/electron/electron/tree/master/docs) directory. It also
|
||||
contains documents describing how to build and contribute to 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)
|
||||
- [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)
|
||||
|
||||
## Quick Start
|
||||
|
||||
Clone and run the [`electron/electron-quick-start`](https://github.com/electron/electron-quick-start)
|
||||
repository to see a minimal Electron app in action.
|
||||
|
||||
## 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-br`](https://electron-br.slack.com) *(Brazilian Portuguese)*
|
||||
- [`electron-kr`](http://www.meetup.com/electron-kr/) *(Korean)*
|
||||
- [`electron-jp`](https://electron-jp-slackin.herokuapp.com/) *(Japanese)*
|
||||
- [`electron-tr`](http://www.meetup.com/Electron-JS-Istanbul/) *(Turkish)*
|
||||
- [`electron-id`](https://electron-id.slack.com) *(Indonesia)*
|
||||
|
||||
## License
|
||||
|
||||
[MIT](https://github.com/electron/electron/blob/master/LICENSE)
|
||||
|
||||
When using the Electron or other GitHub logos, be sure to follow the [GitHub logo guidelines](https://github.com/logos).
|
||||
Check out [awesome-electron](https://github.com/sindresorhus/awesome-electron)
|
||||
for a community maintained list of useful example apps, tools and resources.
|
||||
|
||||
12
SECURITY.md
12
SECURITY.md
@@ -1,12 +0,0 @@
|
||||
# Reporting Security Issues
|
||||
|
||||
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.
|
||||
|
||||
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).
|
||||
96
appveyor.yml
96
appveyor.yml
@@ -1,73 +1,25 @@
|
||||
build_cloud: electron-16
|
||||
image: electron-16-vs2017-15.4.5
|
||||
build_script:
|
||||
- ps: >-
|
||||
echo "Build worker image $env:APPVEYOR_BUILD_WORKER_IMAGE"
|
||||
# appveyor file
|
||||
# http://www.appveyor.com/docs/appveyor-yml
|
||||
version: "{build}"
|
||||
|
||||
&"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe"
|
||||
|
||||
if($env:SKIP_GYP_BUILD -eq "true") {
|
||||
Write-warning "Skipping debug build for older branch"; Exit-AppveyorBuild
|
||||
} elseif(($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME -split "/")[0] -eq ($env:APPVEYOR_REPO_NAME -split "/")[0]) {
|
||||
Write-warning "Skipping PR build for branch"; Exit-AppveyorBuild
|
||||
} else {
|
||||
Add-Path "$env:ProgramFiles (x86)\Windows Kits\10\Debuggers\x64"
|
||||
$env:path = "$env:ProgramFiles (x86)\Windows Kits\10\Debuggers\x64;$env:path"
|
||||
if($env:APPVEYOR_SCHEDULED_BUILD -eq 'True') {
|
||||
$env:RUN_RELEASE_BUILD = "1"
|
||||
}
|
||||
$Message = (git log --format=%B -n 1 HEAD) | Out-String
|
||||
if ((Test-Path Env:\RUN_RELEASE_BUILD)) {
|
||||
$env:ELECTRON_RELEASE = '1'
|
||||
Write-Output "release build triggered from api"
|
||||
}
|
||||
if ((Test-Path Env:\ELECTRON_RELEASE)) {
|
||||
Write-Output "Running release build"
|
||||
python script\bootstrap.py --target_arch=$env:TARGET_ARCH
|
||||
python script\build.py -c R
|
||||
python script\create-dist.py
|
||||
} else {
|
||||
Write-Output "Running debug build"
|
||||
python script\bootstrap.py --target_arch=$env:TARGET_ARCH --dev
|
||||
python script\build.py -c D
|
||||
}
|
||||
if ($? -ne 'True') {
|
||||
throw "Build failed with exit code $?"
|
||||
} else {
|
||||
"Build succeeded."
|
||||
}
|
||||
Push-AppveyorArtifact out
|
||||
}
|
||||
test_script:
|
||||
- ps: >-
|
||||
if (Test-Path Env:\ELECTRON_RELEASE) {
|
||||
Write-Output "Skipping tests for release build"
|
||||
} else {
|
||||
Write-Output "Running tests for debug build"
|
||||
python script\test.py --ci --rebuild_native_modules
|
||||
if ($LASTEXITCODE -ne '0') {
|
||||
throw "Tests failed with exit code $LASTEXITCODE"
|
||||
} else {
|
||||
Write-Output "Tests succeeded."
|
||||
}
|
||||
python script\verify-ffmpeg.py
|
||||
if ($LASTEXITCODE -ne '0') {
|
||||
throw "Verify ffmpeg failed with exit code $LASTEXITCODE"
|
||||
} else {
|
||||
"Verify ffmpeg succeeded."
|
||||
}
|
||||
}
|
||||
artifacts:
|
||||
- path: test-results.xml
|
||||
name: test-results.xml
|
||||
deploy_script:
|
||||
- ps: >-
|
||||
if (Test-Path Env:\ELECTRON_RELEASE) {
|
||||
if (Test-Path Env:\RUN_RELEASE_BUILD) {
|
||||
Write-Output "Uploading Electron release distribution to s3"
|
||||
& python script\upload.py --upload_to_s3
|
||||
} else {
|
||||
Write-Output "Uploading Electron release distribution to github releases"
|
||||
& python script\upload.py
|
||||
}
|
||||
}
|
||||
os: Visual Studio 2015
|
||||
|
||||
init:
|
||||
- git config --global core.autocrlf input
|
||||
|
||||
platform:
|
||||
- x86
|
||||
- x64
|
||||
|
||||
install:
|
||||
- cmd: SET PATH=C:\Program Files (x86)\MSBuild\14.0\bin\;%PATH%
|
||||
- cmd: SET PATH=C:\python27;%PATH%
|
||||
- cmd: python script/cibuild
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
# disable build and test pahses
|
||||
build: off
|
||||
test: off
|
||||
|
||||
1
atom/CPPLINT.cfg
Normal file
1
atom/CPPLINT.cfg
Normal file
@@ -0,0 +1 @@
|
||||
filter=+build/include_alpha
|
||||
@@ -18,90 +18,19 @@
|
||||
#include "content/public/common/content_constants.h"
|
||||
#include "content/public/common/pepper_plugin_info.h"
|
||||
#include "content/public/common/user_agent.h"
|
||||
#include "media/media_features.h"
|
||||
#include "ppapi/shared_impl/ppapi_permissions.h"
|
||||
#include "third_party/widevine/cdm/widevine_cdm_common.h"
|
||||
#include "third_party/widevine/cdm/stub/widevine_cdm_version.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
#include "url/url_constants.h"
|
||||
|
||||
#if defined(WIDEVINE_CDM_AVAILABLE)
|
||||
#include "base/native_library.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
#if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
|
||||
#include "chrome/common/widevine_cdm_constants.h"
|
||||
#include "content/public/common/cdm_info.h"
|
||||
#include "media/base/video_codecs.h"
|
||||
#endif // defined(WIDEVINE_CDM_AVAILABLE)
|
||||
|
||||
#if defined(ENABLE_PDF_VIEWER)
|
||||
#include "atom/common/atom_constants.h"
|
||||
#include "pdf/pdf.h"
|
||||
#endif // defined(ENABLE_PDF_VIEWER)
|
||||
#endif
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
#if defined(WIDEVINE_CDM_AVAILABLE)
|
||||
bool IsWidevineAvailable(base::FilePath* adapter_path,
|
||||
base::FilePath* cdm_path,
|
||||
std::vector<media::VideoCodec>* codecs_supported) {
|
||||
static enum {
|
||||
NOT_CHECKED,
|
||||
FOUND,
|
||||
NOT_FOUND,
|
||||
} widevine_cdm_file_check = NOT_CHECKED;
|
||||
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
|
||||
*adapter_path = command_line->GetSwitchValuePath(switches::kWidevineCdmPath);
|
||||
if (!adapter_path->empty()) {
|
||||
*cdm_path = adapter_path->DirName().AppendASCII(
|
||||
base::GetNativeLibraryName(kWidevineCdmLibraryName));
|
||||
if (widevine_cdm_file_check == NOT_CHECKED) {
|
||||
widevine_cdm_file_check =
|
||||
(base::PathExists(*adapter_path) && 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)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void AddWidevineAdapterFromCommandLine(
|
||||
base::CommandLine* command_line,
|
||||
std::vector<content::PepperPluginInfo>* plugins) {
|
||||
base::FilePath adapter_path;
|
||||
base::FilePath cdm_path;
|
||||
std::vector<media::VideoCodec> video_codecs_supported;
|
||||
if (IsWidevineAvailable(&adapter_path, &cdm_path, &video_codecs_supported)) {
|
||||
auto cdm_version_string =
|
||||
command_line->GetSwitchValueASCII(switches::kWidevineCdmVersion);
|
||||
content::PepperPluginInfo info;
|
||||
info.is_out_of_process = true;
|
||||
info.path = adapter_path;
|
||||
info.name = kWidevineCdmDisplayName;
|
||||
info.description =
|
||||
base::StringPrintf("%s (version: %s)", kWidevineCdmDescription,
|
||||
cdm_version_string.c_str());
|
||||
info.version = cdm_version_string;
|
||||
info.permissions = kWidevineCdmPluginPermissions;
|
||||
content::WebPluginMimeType mime_type(kWidevineCdmPluginMimeType,
|
||||
kWidevineCdmPluginExtension,
|
||||
kWidevineCdmPluginMimeTypeDescription);
|
||||
info.mime_types.push_back(mime_type);
|
||||
plugins->push_back(info);
|
||||
}
|
||||
}
|
||||
#endif // defined(WIDEVINE_CDM_AVAILABLE)
|
||||
|
||||
#if defined(ENABLE_PEPPER_FLASH)
|
||||
content::PepperPluginInfo CreatePepperFlashInfo(const base::FilePath& path,
|
||||
const std::string& version) {
|
||||
content::PepperPluginInfo plugin;
|
||||
@@ -113,7 +42,7 @@ content::PepperPluginInfo CreatePepperFlashInfo(const base::FilePath& path,
|
||||
|
||||
std::vector<std::string> flash_version_numbers = base::SplitString(
|
||||
version, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
|
||||
if (flash_version_numbers.empty())
|
||||
if (flash_version_numbers.size() < 1)
|
||||
flash_version_numbers.push_back("11");
|
||||
// |SplitString()| puts in an empty string given an empty string. :(
|
||||
else if (flash_version_numbers[0].empty())
|
||||
@@ -126,141 +55,153 @@ 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) && defined(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 defined(USE_PROPRIETARY_CODECS)
|
||||
codecs.push_back(kCdmSupportedCodecAvc1);
|
||||
#endif // defined(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));
|
||||
}
|
||||
#endif // defined(ENABLE_PEPPER_FLASH)
|
||||
|
||||
void ComputeBuiltInPlugins(std::vector<content::PepperPluginInfo>* plugins) {
|
||||
#if defined(ENABLE_PDF_VIEWER)
|
||||
content::PepperPluginInfo pdf_info;
|
||||
pdf_info.is_internal = true;
|
||||
pdf_info.is_out_of_process = true;
|
||||
pdf_info.name = "Chromium PDF Viewer";
|
||||
pdf_info.description = "Portable Document Format";
|
||||
pdf_info.path = base::FilePath::FromUTF8Unsafe(kPdfPluginPath);
|
||||
content::WebPluginMimeType pdf_mime_type(kPdfPluginMimeType, "pdf",
|
||||
"Portable Document Format");
|
||||
pdf_info.mime_types.push_back(pdf_mime_type);
|
||||
pdf_info.internal_entry_points.get_interface = chrome_pdf::PPP_GetInterface;
|
||||
pdf_info.internal_entry_points.initialize_module =
|
||||
chrome_pdf::PPP_InitializeModule;
|
||||
pdf_info.internal_entry_points.shutdown_module =
|
||||
chrome_pdf::PPP_ShutdownModule;
|
||||
pdf_info.permissions = ppapi::PERMISSION_PRIVATE | ppapi::PERMISSION_DEV;
|
||||
plugins->push_back(pdf_info);
|
||||
#endif // defined(ENABLE_PDF_VIEWER)
|
||||
widevine_cdm.mime_types.push_back(widevine_cdm_mime_type);
|
||||
widevine_cdm.permissions = kWidevineCdmPluginPermissions;
|
||||
|
||||
return widevine_cdm;
|
||||
}
|
||||
#endif
|
||||
|
||||
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) && defined(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 {
|
||||
return l10n_util::GetStringUTF16(message_id);
|
||||
}
|
||||
|
||||
void AtomContentClient::AddAdditionalSchemes(Schemes* schemes) {
|
||||
schemes->standard_schemes.push_back("chrome-extension");
|
||||
|
||||
std::vector<std::string> splited;
|
||||
ConvertStringWithSeparatorToVector(&splited, ",",
|
||||
switches::kRegisterServiceWorkerSchemes);
|
||||
for (const std::string& scheme : splited)
|
||||
schemes->service_worker_schemes.push_back(scheme);
|
||||
schemes->service_worker_schemes.push_back(url::kFileScheme);
|
||||
|
||||
ConvertStringWithSeparatorToVector(&splited, ",", switches::kSecureSchemes);
|
||||
for (const std::string& scheme : splited)
|
||||
schemes->secure_schemes.push_back(scheme);
|
||||
void AtomContentClient::AddAdditionalSchemes(
|
||||
std::vector<url::SchemeWithType>* standard_schemes,
|
||||
std::vector<url::SchemeWithType>* referrer_schemes,
|
||||
std::vector<std::string>* savable_schemes) {
|
||||
standard_schemes->push_back({"chrome-extension", url::SCHEME_WITHOUT_PORT});
|
||||
}
|
||||
|
||||
void AtomContentClient::AddPepperPlugins(
|
||||
std::vector<content::PepperPluginInfo>* plugins) {
|
||||
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
|
||||
#if defined(ENABLE_PEPPER_FLASH)
|
||||
AddPepperFlashFromCommandLine(command_line, plugins);
|
||||
#endif // defined(ENABLE_PEPPER_FLASH)
|
||||
#if defined(WIDEVINE_CDM_AVAILABLE)
|
||||
AddWidevineAdapterFromCommandLine(command_line, plugins);
|
||||
#endif // defined(WIDEVINE_CDM_AVAILABLE)
|
||||
ComputeBuiltInPlugins(plugins);
|
||||
AddPepperFlashFromCommandLine(plugins);
|
||||
#if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
|
||||
AddWidevineCdmFromCommandLine(plugins);
|
||||
#endif
|
||||
}
|
||||
|
||||
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 adapter_path;
|
||||
base::FilePath cdm_path;
|
||||
std::vector<media::VideoCodec> video_codecs_supported;
|
||||
bool supports_persistent_license = false;
|
||||
if (IsWidevineAvailable(&adapter_path, &cdm_path,
|
||||
&video_codecs_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());
|
||||
|
||||
cdms->push_back(content::CdmInfo(
|
||||
kWidevineCdmDisplayName, kWidevineCdmGuid, version, cdm_path,
|
||||
kWidevineCdmFileSystemId, video_codecs_supported,
|
||||
supports_persistent_license, kWidevineKeySystem, false));
|
||||
}
|
||||
#endif // defined(WIDEVINE_CDM_AVAILABLE)
|
||||
void AtomContentClient::AddServiceWorkerSchemes(
|
||||
std::set<std::string>* service_worker_schemes) {
|
||||
std::vector<std::string> schemes;
|
||||
ConvertStringWithSeparatorToVector(&schemes, ",",
|
||||
switches::kRegisterServiceWorkerSchemes);
|
||||
if (!schemes.empty()) {
|
||||
for (const std::string& scheme : schemes)
|
||||
service_worker_schemes->insert(scheme);
|
||||
}
|
||||
service_worker_schemes->insert(url::kFileScheme);
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -16,19 +16,21 @@ namespace atom {
|
||||
class AtomContentClient : public brightray::ContentClient {
|
||||
public:
|
||||
AtomContentClient();
|
||||
~AtomContentClient() override;
|
||||
virtual ~AtomContentClient();
|
||||
|
||||
protected:
|
||||
// content::ContentClient:
|
||||
std::string GetProduct() const override;
|
||||
std::string GetUserAgent() const override;
|
||||
base::string16 GetLocalizedString(int message_id) const override;
|
||||
void AddAdditionalSchemes(Schemes* schemes) override;
|
||||
void AddAdditionalSchemes(
|
||||
std::vector<url::SchemeWithType>* standard_schemes,
|
||||
std::vector<url::SchemeWithType>* referrer_schemes,
|
||||
std::vector<std::string>* savable_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;
|
||||
void AddServiceWorkerSchemes(
|
||||
std::set<std::string>* service_worker_schemes) override;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomContentClient);
|
||||
|
||||
@@ -9,13 +9,11 @@
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
extern "C" {
|
||||
__attribute__((visibility("default"))) int AtomMain(int argc, char* argv[]);
|
||||
__attribute__((visibility("default")))
|
||||
int AtomMain(int argc, const char* argv[]);
|
||||
|
||||
#ifdef ENABLE_RUN_AS_NODE
|
||||
__attribute__((visibility("default"))) int AtomInitializeICUandStartNode(
|
||||
int argc,
|
||||
char* argv[]);
|
||||
#endif
|
||||
__attribute__((visibility("default")))
|
||||
int AtomInitializeICUandStartNode(int argc, char *argv[]);
|
||||
}
|
||||
#endif // OS_MACOSX
|
||||
|
||||
|
||||
@@ -14,17 +14,17 @@
|
||||
#include "brightray/common/mac/main_application_bundle.h"
|
||||
#include "content/public/app/content_main.h"
|
||||
|
||||
int AtomMain(int argc, char* argv[]) {
|
||||
#if defined(OS_MACOSX)
|
||||
int AtomMain(int argc, const char* argv[]) {
|
||||
atom::AtomMainDelegate delegate;
|
||||
content::ContentMainParams params(&delegate);
|
||||
params.argc = argc;
|
||||
params.argv = const_cast<const char**>(argv);
|
||||
params.argv = argv;
|
||||
atom::AtomCommandLine::Init(argc, argv);
|
||||
return content::ContentMain(params);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_RUN_AS_NODE
|
||||
int AtomInitializeICUandStartNode(int argc, char* argv[]) {
|
||||
int AtomInitializeICUandStartNode(int argc, char *argv[]) {
|
||||
base::AtExitManager atexit_manager;
|
||||
base::mac::ScopedNSAutoreleasePool pool;
|
||||
base::mac::SetOverrideFrameworkBundlePath(
|
||||
@@ -35,4 +35,4 @@ int AtomInitializeICUandStartNode(int argc, char* argv[]) {
|
||||
base::i18n::InitializeICU();
|
||||
return atom::NodeMain(argc, argv);
|
||||
}
|
||||
#endif
|
||||
#endif // OS_MACOSX
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -4,34 +4,26 @@
|
||||
|
||||
#include "atom/app/atom_main.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <vector>
|
||||
#include <stdlib.h>
|
||||
|
||||
#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>
|
||||
|
||||
#include "atom/app/atom_main_delegate.h"
|
||||
#include "atom/app/command_line_args.h"
|
||||
#include "atom/common/crash_reporter/win/crash_service_main.h"
|
||||
#include "base/environment.h"
|
||||
#include "base/process/launch.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "base/win/windows_version.h"
|
||||
#include "content/public/app/sandbox_helper_win.h"
|
||||
#include "sandbox/win/src/sandbox_types.h"
|
||||
#elif defined(OS_LINUX) // defined(OS_WIN)
|
||||
#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)
|
||||
|
||||
@@ -42,11 +34,8 @@
|
||||
|
||||
namespace {
|
||||
|
||||
#ifdef ENABLE_RUN_AS_NODE
|
||||
const char kRunAsNode[] = "ELECTRON_RUN_AS_NODE";
|
||||
#endif
|
||||
const char* kRunAsNode = "ELECTRON_RUN_AS_NODE";
|
||||
|
||||
#if defined(ENABLE_RUN_AS_NODE) || defined(OS_WIN)
|
||||
bool IsEnvSet(const char* name) {
|
||||
#if defined(OS_WIN)
|
||||
size_t required_size;
|
||||
@@ -57,114 +46,63 @@ bool IsEnvSet(const char* name) {
|
||||
return indicator && indicator[0] != '\0';
|
||||
#endif
|
||||
}
|
||||
#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)
|
||||
freopen("/dev/null", "r", stdin);
|
||||
if (fstat(STDOUT_FILENO, &st) < 0 && errno == EBADF)
|
||||
freopen("/dev/null", "w", stdout);
|
||||
if (fstat(STDERR_FILENO, &st) < 0 && errno == EBADF)
|
||||
freopen("/dev/null", "w", stderr);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
#if defined(OS_WIN)
|
||||
int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
|
||||
struct Arguments {
|
||||
int argc = 0;
|
||||
wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
|
||||
int argc = 0;
|
||||
wchar_t** wargv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
|
||||
|
||||
~Arguments() { LocalFree(argv); }
|
||||
} arguments;
|
||||
|
||||
if (!arguments.argv)
|
||||
return -1;
|
||||
|
||||
#ifdef _DEBUG
|
||||
// Don't display assert dialog boxes in CI test runs
|
||||
static const auto kCI = "ELECTRON_CI";
|
||||
bool is_ci = IsEnvSet(kCI);
|
||||
if (!is_ci) {
|
||||
for (int i = 0; i < arguments.argc; ++i) {
|
||||
if (!_wcsicmp(arguments.argv[i], L"--ci")) {
|
||||
is_ci = true;
|
||||
_putenv_s(kCI, "1"); // set flag for child processes
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (is_ci) {
|
||||
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG | _CRTDBG_MODE_FILE);
|
||||
_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
|
||||
|
||||
_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG | _CRTDBG_MODE_FILE);
|
||||
_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
|
||||
|
||||
_set_error_mode(_OUT_TO_STDERR);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_RUN_AS_NODE
|
||||
bool run_as_node = IsEnvSet(kRunAsNode);
|
||||
#else
|
||||
bool run_as_node = false;
|
||||
#endif
|
||||
|
||||
// Make sure the output is printed to console.
|
||||
if (run_as_node || !IsEnvSet("ELECTRON_NO_ATTACH_CONSOLE"))
|
||||
base::RouteStdioToConsole(false);
|
||||
|
||||
#ifndef DEBUG
|
||||
// Chromium has its own TLS subsystem which supports automatic destruction
|
||||
// of thread-local data, and also depends on memory allocation routines
|
||||
// provided by the CRT. The problem is that the auto-destruction mechanism
|
||||
// uses a hidden feature of the OS loader which calls a callback on thread
|
||||
// exit, but only after all loaded DLLs have been detached. Since the CRT is
|
||||
// also a DLL, it happens that by the time Chromium's `OnThreadExit` function
|
||||
// is called, the heap functions, though still in memory, no longer perform
|
||||
// their duties, and when Chromium calls `free` on its buffer, it triggers
|
||||
// an access violation error.
|
||||
// We work around this problem by invoking Chromium's `OnThreadExit` in time
|
||||
// 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); });
|
||||
#endif
|
||||
// Convert argv to to UTF8
|
||||
char** argv = new char*[argc];
|
||||
for (int i = 0; i < argc; i++) {
|
||||
// Compute the size of the required buffer
|
||||
DWORD size = WideCharToMultiByte(CP_UTF8,
|
||||
0,
|
||||
wargv[i],
|
||||
-1,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
if (size == 0) {
|
||||
// This should never happen.
|
||||
fprintf(stderr, "Could not convert arguments to utf8.");
|
||||
exit(1);
|
||||
}
|
||||
// Do the actual conversion
|
||||
argv[i] = new char[size];
|
||||
DWORD result = WideCharToMultiByte(CP_UTF8,
|
||||
0,
|
||||
wargv[i],
|
||||
-1,
|
||||
argv[i],
|
||||
size,
|
||||
NULL,
|
||||
NULL);
|
||||
if (result == 0) {
|
||||
// This should never happen.
|
||||
fprintf(stderr, "Could not convert arguments to utf8.");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_RUN_AS_NODE
|
||||
if (run_as_node) {
|
||||
std::vector<char*> argv(arguments.argc);
|
||||
std::transform(
|
||||
arguments.argv, arguments.argv + arguments.argc, argv.begin(),
|
||||
[](auto& a) { return _strdup(base::WideToUTF8(a).c_str()); });
|
||||
|
||||
// Now that argv conversion is done, we can finally start.
|
||||
base::AtExitManager atexit_manager;
|
||||
base::i18n::InitializeICU();
|
||||
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")) {
|
||||
return atom::NodeMain(argc, argv);
|
||||
} else if (IsEnvSet("ELECTRON_INTERNAL_CRASH_SERVICE")) {
|
||||
return crash_service::Main(cmd);
|
||||
}
|
||||
|
||||
if (!atom::CheckCommandLineArguments(arguments.argc, arguments.argv))
|
||||
return -1;
|
||||
|
||||
sandbox::SandboxInterfaceInfo sandbox_info = {0};
|
||||
content::InitializeSandboxInfo(&sandbox_info);
|
||||
atom::AtomMainDelegate delegate;
|
||||
@@ -172,41 +110,34 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
|
||||
content::ContentMainParams params(&delegate);
|
||||
params.instance = instance;
|
||||
params.sandbox_info = &sandbox_info;
|
||||
atom::AtomCommandLine::Init(arguments.argc, arguments.argv);
|
||||
atom::AtomCommandLine::Init(argc, argv);
|
||||
atom::AtomCommandLine::InitW(argc, wargv);
|
||||
return content::ContentMain(params);
|
||||
}
|
||||
|
||||
#elif defined(OS_LINUX) // defined(OS_WIN)
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
#ifdef ENABLE_RUN_AS_NODE
|
||||
FixStdioStreams();
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
if (IsEnvSet(kRunAsNode)) {
|
||||
base::i18n::InitializeICU();
|
||||
base::AtExitManager atexit_manager;
|
||||
return atom::NodeMain(argc, argv);
|
||||
return atom::NodeMain(argc, const_cast<char**>(argv));
|
||||
}
|
||||
#endif
|
||||
|
||||
atom::AtomMainDelegate delegate;
|
||||
content::ContentMainParams params(&delegate);
|
||||
params.argc = argc;
|
||||
params.argv = const_cast<const char**>(argv);
|
||||
params.argv = argv;
|
||||
atom::AtomCommandLine::Init(argc, argv);
|
||||
return content::ContentMain(params);
|
||||
}
|
||||
|
||||
#else // defined(OS_LINUX)
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
#ifdef ENABLE_RUN_AS_NODE
|
||||
FixStdioStreams();
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
if (IsEnvSet(kRunAsNode)) {
|
||||
return AtomInitializeICUandStartNode(argc, argv);
|
||||
return AtomInitializeICUandStartNode(argc, const_cast<char**>(argv));
|
||||
}
|
||||
#endif
|
||||
|
||||
return AtomMain(argc, argv);
|
||||
}
|
||||
|
||||
@@ -11,9 +11,7 @@
|
||||
#include "atom/browser/atom_browser_client.h"
|
||||
#include "atom/browser/relauncher.h"
|
||||
#include "atom/common/google_api_key.h"
|
||||
#include "atom/common/options_switches.h"
|
||||
#include "atom/renderer/atom_renderer_client.h"
|
||||
#include "atom/renderer/atom_sandboxed_renderer_client.h"
|
||||
#include "atom/utility/atom_content_utility_client.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/debug/stack_trace.h"
|
||||
@@ -21,19 +19,9 @@
|
||||
#include "base/logging.h"
|
||||
#include "chrome/common/chrome_paths.h"
|
||||
#include "content/public/common/content_switches.h"
|
||||
#include "ipc/ipc_features.h"
|
||||
#include "services/service_manager/sandbox/switches.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
#include "ui/base/resource/resource_bundle.h"
|
||||
|
||||
#if BUILDFLAG(IPC_MESSAGE_LOG_ENABLED)
|
||||
#define IPC_MESSAGE_MACROS_LOG_ENABLED
|
||||
#include "content/public/common/content_ipc_logging.h"
|
||||
#define IPC_LOG_TABLE_ADD_ENTRY(msg_id, logger) \
|
||||
content::RegisterIPCLogger(msg_id, logger)
|
||||
#include "atom/common/common_message_generator.h"
|
||||
#endif
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
@@ -41,28 +29,27 @@ namespace {
|
||||
const char* kRelauncherProcess = "relauncher";
|
||||
|
||||
bool IsBrowserProcess(base::CommandLine* cmd) {
|
||||
std::string process_type = cmd->GetSwitchValueASCII(::switches::kProcessType);
|
||||
std::string process_type = cmd->GetSwitchValueASCII(switches::kProcessType);
|
||||
return process_type.empty();
|
||||
}
|
||||
|
||||
#if defined(OS_WIN)
|
||||
void InvalidParameterHandler(const wchar_t*,
|
||||
const wchar_t*,
|
||||
const wchar_t*,
|
||||
unsigned int,
|
||||
uintptr_t) {
|
||||
void InvalidParameterHandler(const wchar_t*, const wchar_t*, const wchar_t*,
|
||||
unsigned int, uintptr_t) {
|
||||
// noop.
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
AtomMainDelegate::AtomMainDelegate() {}
|
||||
AtomMainDelegate::AtomMainDelegate() {
|
||||
}
|
||||
|
||||
AtomMainDelegate::~AtomMainDelegate() {}
|
||||
AtomMainDelegate::~AtomMainDelegate() {
|
||||
}
|
||||
|
||||
bool AtomMainDelegate::BasicStartupComplete(int* exit_code) {
|
||||
auto* command_line = base::CommandLine::ForCurrentProcess();
|
||||
auto command_line = base::CommandLine::ForCurrentProcess();
|
||||
|
||||
logging::LoggingSettings settings;
|
||||
#if defined(OS_WIN)
|
||||
@@ -79,13 +66,13 @@ 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();
|
||||
if (!command_line->HasSwitch(::switches::kEnableLogging) &&
|
||||
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;
|
||||
logging::SetMinLogLevel(logging::LOG_NUM_SEVERITIES);
|
||||
@@ -97,15 +84,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();
|
||||
@@ -119,9 +100,6 @@ bool AtomMainDelegate::BasicStartupComplete(int* exit_code) {
|
||||
#if defined(OS_WIN)
|
||||
// Ignore invalid parameter errors.
|
||||
_set_invalid_parameter_handler(InvalidParameterHandler);
|
||||
// Disable the ActiveVerifier, which is used by Chrome to track possible
|
||||
// bugs, but no use in Electron.
|
||||
base::win::DisableHandleVerifier();
|
||||
#endif
|
||||
|
||||
return brightray::MainDelegate::BasicStartupComplete(exit_code);
|
||||
@@ -130,28 +108,24 @@ bool AtomMainDelegate::BasicStartupComplete(int* exit_code) {
|
||||
void AtomMainDelegate::PreSandboxStartup() {
|
||||
brightray::MainDelegate::PreSandboxStartup();
|
||||
|
||||
auto* command_line = base::CommandLine::ForCurrentProcess();
|
||||
std::string process_type =
|
||||
command_line->GetSwitchValueASCII(::switches::kProcessType);
|
||||
// Set google API key.
|
||||
std::unique_ptr<base::Environment> env(base::Environment::Create());
|
||||
if (!env->HasVar("GOOGLE_API_KEY"))
|
||||
env->SetVar("GOOGLE_API_KEY", GOOGLEAPIS_API_KEY);
|
||||
|
||||
auto command_line = base::CommandLine::ForCurrentProcess();
|
||||
std::string process_type = command_line->GetSwitchValueASCII(
|
||||
switches::kProcessType);
|
||||
|
||||
// Only append arguments for browser process.
|
||||
if (!IsBrowserProcess(command_line))
|
||||
return;
|
||||
|
||||
if (!command_line->HasSwitch(switches::kEnableMixedSandbox)) {
|
||||
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);
|
||||
} else {
|
||||
// Disable renderer sandbox for most of node's functions.
|
||||
command_line->AppendSwitch(::switches::kNoSandbox);
|
||||
}
|
||||
}
|
||||
// Disable renderer sandbox for most of node's functions.
|
||||
command_line->AppendSwitch(switches::kNoSandbox);
|
||||
|
||||
// Allow file:// URIs to read other file:// URIs by default.
|
||||
command_line->AppendSwitch(::switches::kAllowFileAccessFromFiles);
|
||||
command_line->AppendSwitch(switches::kAllowFileAccessFromFiles);
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
// Enable AVFoundation.
|
||||
@@ -165,16 +139,8 @@ content::ContentBrowserClient* AtomMainDelegate::CreateContentBrowserClient() {
|
||||
}
|
||||
|
||||
content::ContentRendererClient*
|
||||
AtomMainDelegate::CreateContentRendererClient() {
|
||||
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
|
||||
switches::kEnableSandbox) ||
|
||||
!base::CommandLine::ForCurrentProcess()->HasSwitch(
|
||||
::switches::kNoSandbox)) {
|
||||
renderer_client_.reset(new AtomSandboxedRendererClient);
|
||||
} else {
|
||||
renderer_client_.reset(new AtomRendererClient);
|
||||
}
|
||||
|
||||
AtomMainDelegate::CreateContentRendererClient() {
|
||||
renderer_client_.reset(new AtomRendererClient);
|
||||
return renderer_client_.get();
|
||||
}
|
||||
|
||||
@@ -205,7 +171,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
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace atom {
|
||||
class AtomMainDelegate : public brightray::MainDelegate {
|
||||
public:
|
||||
AtomMainDelegate();
|
||||
~AtomMainDelegate() override;
|
||||
~AtomMainDelegate();
|
||||
|
||||
protected:
|
||||
// content::ContentMainDelegate:
|
||||
@@ -44,6 +44,7 @@ class AtomMainDelegate : public brightray::MainDelegate {
|
||||
void SetUpBundleOverrides();
|
||||
#endif
|
||||
|
||||
brightray::ContentClient content_client_;
|
||||
std::unique_ptr<content::ContentBrowserClient> browser_client_;
|
||||
std::unique_ptr<content::ContentRendererClient> renderer_client_;
|
||||
std::unique_ptr<content::ContentUtilityClient> utility_client_;
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
#include "atom/app/atom_main_delegate.h"
|
||||
|
||||
#include "base/mac/bundle_locations.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/files/file_util.h"
|
||||
#include "base/mac/bundle_locations.h"
|
||||
#include "base/mac/foundation_util.h"
|
||||
#include "base/mac/scoped_nsautorelease_pool.h"
|
||||
#include "base/path_service.h"
|
||||
@@ -20,17 +20,16 @@ namespace atom {
|
||||
namespace {
|
||||
|
||||
base::FilePath GetFrameworksPath() {
|
||||
return brightray::MainApplicationBundlePath()
|
||||
.Append("Contents")
|
||||
.Append("Frameworks");
|
||||
return brightray::MainApplicationBundlePath().Append("Contents")
|
||||
.Append("Frameworks");
|
||||
}
|
||||
|
||||
base::FilePath GetHelperAppPath(const base::FilePath& frameworks_path,
|
||||
const std::string& name) {
|
||||
return frameworks_path.Append(name + " Helper.app")
|
||||
.Append("Contents")
|
||||
.Append("MacOS")
|
||||
.Append(name + " Helper");
|
||||
.Append("Contents")
|
||||
.Append("MacOS")
|
||||
.Append(name + " Helper");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -42,11 +41,11 @@ void AtomMainDelegate::OverrideFrameworkBundlePath() {
|
||||
|
||||
void AtomMainDelegate::OverrideChildProcessPath() {
|
||||
base::FilePath frameworks_path = GetFrameworksPath();
|
||||
base::FilePath helper_path =
|
||||
GetHelperAppPath(frameworks_path, ATOM_PRODUCT_NAME);
|
||||
base::FilePath helper_path = GetHelperAppPath(frameworks_path,
|
||||
ATOM_PRODUCT_NAME);
|
||||
if (!base::PathExists(helper_path))
|
||||
helper_path =
|
||||
GetHelperAppPath(frameworks_path, brightray::GetApplicationName());
|
||||
helper_path = GetHelperAppPath(frameworks_path,
|
||||
brightray::GetApplicationName());
|
||||
if (!base::PathExists(helper_path))
|
||||
LOG(FATAL) << "Unable to find helper app";
|
||||
PathService::Override(content::CHILD_PROCESS_EXE, helper_path);
|
||||
|
||||
@@ -1,53 +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/app/command_line_args.h"
|
||||
|
||||
namespace {
|
||||
|
||||
bool IsUrlArg(const base::CommandLine::CharType* arg) {
|
||||
// the first character must be a letter for this to be a URL
|
||||
auto c = *arg;
|
||||
if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) {
|
||||
for (auto* p = arg + 1; *p; ++p) {
|
||||
c = *p;
|
||||
|
||||
// colon indicates that the argument starts with a URI scheme
|
||||
if (c == ':') {
|
||||
// it could also be a Windows filesystem path
|
||||
if (p == arg + 1)
|
||||
break;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// white-space before a colon means it's not a URL
|
||||
if (c == ' ' || (0x9 <= c && c <= 0xD))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace atom {
|
||||
|
||||
bool CheckCommandLineArguments(int argc, base::CommandLine::CharType** argv) {
|
||||
const base::CommandLine::StringType dashdash(2, '-');
|
||||
bool block_args = false;
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
if (argv[i] == dashdash)
|
||||
break;
|
||||
if (block_args) {
|
||||
return false;
|
||||
} else if (IsUrlArg(argv[i])) {
|
||||
block_args = true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
@@ -1,16 +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_APP_COMMAND_LINE_ARGS_H_
|
||||
#define ATOM_APP_COMMAND_LINE_ARGS_H_
|
||||
|
||||
#include "base/command_line.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
bool CheckCommandLineArguments(int argc, base::CommandLine::CharType** argv);
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_APP_COMMAND_LINE_ARGS_H_
|
||||
@@ -2,31 +2,23 @@
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifdef ENABLE_RUN_AS_NODE
|
||||
|
||||
#include "atom/app/node_main.h"
|
||||
|
||||
#include "atom/app/uv_task_runner.h"
|
||||
#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"
|
||||
#include "gin/v8_initializer.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
int NodeMain(int argc, char* argv[]) {
|
||||
int NodeMain(int argc, char *argv[]) {
|
||||
base::CommandLine::Init(argc, argv);
|
||||
|
||||
int exit_code = 1;
|
||||
@@ -38,52 +30,32 @@ int NodeMain(int argc, char* argv[]) {
|
||||
base::ThreadTaskRunnerHandle handle(uv_task_runner);
|
||||
|
||||
// Initialize feature list.
|
||||
auto feature_list = std::make_unique<base::FeatureList>();
|
||||
std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
|
||||
feature_list->InitializeFromCommandLine("", "");
|
||||
base::FeatureList::SetInstance(std::move(feature_list));
|
||||
|
||||
gin::V8Initializer::LoadV8Snapshot(
|
||||
gin::V8Initializer::V8SnapshotFileType::kWithAdditionalContext);
|
||||
gin::V8Initializer::LoadV8Snapshot();
|
||||
gin::V8Initializer::LoadV8Natives();
|
||||
|
||||
// V8 requires a task scheduler apparently
|
||||
base::TaskScheduler::CreateAndStartWithDefaultParams("Electron");
|
||||
|
||||
// Initialize gin::IsolateHolder.
|
||||
JavascriptEnvironment gin_env;
|
||||
|
||||
// Explicitly register electron's builtin modules.
|
||||
NodeBindings::RegisterBuiltinModules();
|
||||
|
||||
int exec_argc;
|
||||
const char** exec_argv;
|
||||
node::Init(&argc, const_cast<const char**>(argv), &exec_argc, &exec_argv);
|
||||
|
||||
node::Environment* env = node::CreateEnvironment(
|
||||
node::CreateIsolateData(gin_env.isolate(), loop, gin_env.platform()),
|
||||
gin_env.context(), argc, argv, exec_argc, exec_argv);
|
||||
gin_env.isolate(), loop, gin_env.context(), argc, argv,
|
||||
exec_argc, exec_argv);
|
||||
|
||||
// Enable support for v8 inspector.
|
||||
NodeDebugger node_debugger(env);
|
||||
node_debugger.Start(gin_env.platform());
|
||||
|
||||
mate::Dictionary process(gin_env.isolate(), env->process_object());
|
||||
#if defined(OS_WIN)
|
||||
process.SetMethod("log", &AtomBindings::Log);
|
||||
#endif
|
||||
process.SetMethod("crash", &AtomBindings::Crash);
|
||||
|
||||
// Setup process.crashReporter.start in child node processes
|
||||
auto reporter = mate::Dictionary::CreateEmpty(gin_env.isolate());
|
||||
reporter.SetMethod("start", &crash_reporter::CrashReporter::StartInstance);
|
||||
process.Set("crashReporter", reporter);
|
||||
// Start our custom debugger implementation.
|
||||
NodeDebugger node_debugger(gin_env.isolate());
|
||||
if (node_debugger.IsRunning())
|
||||
env->AssignToContext(v8::Debug::GetDebugContext());
|
||||
|
||||
node::LoadEnvironment(env);
|
||||
|
||||
bool more;
|
||||
do {
|
||||
more = uv_run(env->event_loop(), UV_RUN_ONCE);
|
||||
gin_env.platform()->DrainBackgroundTasks(env->isolate());
|
||||
if (more == false) {
|
||||
node::EmitBeforeExit(env);
|
||||
|
||||
@@ -97,24 +69,13 @@ int NodeMain(int argc, char* argv[]) {
|
||||
|
||||
exit_code = node::EmitExit(env);
|
||||
node::RunAtExit(env);
|
||||
gin_env.platform()->DrainBackgroundTasks(env->isolate());
|
||||
gin_env.platform()->CancelPendingDelayedTasks(env->isolate());
|
||||
|
||||
node::FreeEnvironment(env);
|
||||
}
|
||||
|
||||
// According to "src/gin/shell/gin_main.cc":
|
||||
//
|
||||
// gin::IsolateHolder waits for tasks running in TaskScheduler in its
|
||||
// destructor and thus must be destroyed before TaskScheduler starts skipping
|
||||
// CONTINUE_ON_SHUTDOWN tasks.
|
||||
base::TaskScheduler::GetInstance()->Shutdown();
|
||||
|
||||
v8::V8::Dispose();
|
||||
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ENABLE_RUN_AS_NODE
|
||||
|
||||
@@ -5,14 +5,10 @@
|
||||
#ifndef ATOM_APP_NODE_MAIN_H_
|
||||
#define ATOM_APP_NODE_MAIN_H_
|
||||
|
||||
#ifdef ENABLE_RUN_AS_NODE
|
||||
|
||||
namespace atom {
|
||||
|
||||
int NodeMain(int argc, char* argv[]);
|
||||
int NodeMain(int argc, char *argv[]);
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ENABLE_RUN_AS_NODE
|
||||
|
||||
#endif // ATOM_APP_NODE_MAIN_H_
|
||||
|
||||
@@ -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>
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -5,27 +5,16 @@
|
||||
#ifndef ATOM_BROWSER_API_ATOM_API_APP_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_APP_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/browser/api/event_emitter.h"
|
||||
#include "atom/browser/atom_browser_client.h"
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/browser/browser_observer.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "base/process/process_iterator.h"
|
||||
#include "base/task/cancelable_task_tracker.h"
|
||||
#include "chrome/browser/icon_manager.h"
|
||||
#include "chrome/browser/process_singleton.h"
|
||||
#include "content/public/browser/browser_child_process_observer.h"
|
||||
#include "content/public/browser/gpu_data_manager_observer.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
#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"
|
||||
@@ -45,33 +34,25 @@ namespace atom {
|
||||
enum class JumpListResult : int;
|
||||
#endif
|
||||
|
||||
struct ProcessMetric {
|
||||
int type;
|
||||
base::ProcessId pid;
|
||||
std::unique_ptr<base::ProcessMetrics> metrics;
|
||||
|
||||
ProcessMetric(int type,
|
||||
base::ProcessId pid,
|
||||
std::unique_ptr<base::ProcessMetrics> metrics);
|
||||
~ProcessMetric();
|
||||
};
|
||||
|
||||
namespace api {
|
||||
|
||||
class App : public AtomBrowserClient::Delegate,
|
||||
public mate::EventEmitter<App>,
|
||||
public BrowserObserver,
|
||||
public content::GpuDataManagerObserver,
|
||||
public content::BrowserChildProcessObserver {
|
||||
public content::GpuDataManagerObserver {
|
||||
public:
|
||||
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,
|
||||
int render_process_id,
|
||||
int render_frame_id);
|
||||
|
||||
#if defined(USE_NSS_CERTS)
|
||||
void OnCertificateManagerModelCreated(
|
||||
std::unique_ptr<base::DictionaryValue> options,
|
||||
@@ -79,11 +60,6 @@ class App : public AtomBrowserClient::Delegate,
|
||||
std::unique_ptr<CertificateManagerModel> model);
|
||||
#endif
|
||||
|
||||
base::FilePath GetAppPath() const;
|
||||
void RenderProcessReady(content::RenderProcessHost* host);
|
||||
void RenderProcessDisconnected(base::ProcessId host_pid);
|
||||
void PreMainMessageLoopRun();
|
||||
|
||||
protected:
|
||||
explicit App(v8::Isolate* isolate);
|
||||
~App() override;
|
||||
@@ -98,26 +74,14 @@ 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
|
||||
|
||||
// content::ContentBrowserClient:
|
||||
@@ -127,49 +91,20 @@ 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)>&
|
||||
callback) override;
|
||||
const base::Callback<void(bool)>& callback,
|
||||
content::CertificateRequestResultType* request) override;
|
||||
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;
|
||||
|
||||
// content::BrowserChildProcessObserver:
|
||||
void BrowserChildProcessLaunchedAndConnected(
|
||||
const content::ChildProcessData& data) override;
|
||||
void BrowserChildProcessHostDisconnected(
|
||||
const content::ChildProcessData& data) override;
|
||||
void BrowserChildProcessCrashed(const content::ChildProcessData& data,
|
||||
int exit_code) override;
|
||||
void BrowserChildProcessKilled(const content::ChildProcessData& data,
|
||||
int exit_code) override;
|
||||
void OnGpuProcessCrashed(base::TerminationStatus exit_code) override;
|
||||
|
||||
private:
|
||||
void SetAppPath(const base::FilePath& app_path);
|
||||
void ChildProcessLaunched(int process_type, base::ProcessHandle handle);
|
||||
void ChildProcessDisconnected(base::ProcessId pid);
|
||||
|
||||
// Get/Set the pre-defined path in PathService.
|
||||
base::FilePath GetPath(mate::Arguments* args, const std::string& name);
|
||||
void SetPath(mate::Arguments* args,
|
||||
@@ -178,35 +113,16 @@ class App : public AtomBrowserClient::Delegate,
|
||||
|
||||
void SetDesktopName(const std::string& desktop_name);
|
||||
std::string GetLocale();
|
||||
void OnSecondInstance(const base::CommandLine::StringVector& cmd,
|
||||
const base::FilePath& cwd);
|
||||
bool HasSingleInstanceLock() const;
|
||||
bool RequestSingleInstanceLock();
|
||||
void ReleaseSingleInstanceLock();
|
||||
bool MakeSingleInstance(
|
||||
const ProcessSingleton::NotificationCallback& callback);
|
||||
void ReleaseSingleInstance();
|
||||
bool Relaunch(mate::Arguments* args);
|
||||
void DisableHardwareAcceleration(mate::Arguments* args);
|
||||
void DisableDomainBlockingFor3DAPIs(mate::Arguments* args);
|
||||
bool IsAccessibilitySupportEnabled();
|
||||
void SetAccessibilitySupportEnabled(bool enabled);
|
||||
Browser::LoginItemSettings GetLoginItemSettings(mate::Arguments* args);
|
||||
#if defined(USE_NSS_CERTS)
|
||||
void ImportCertificate(const base::DictionaryValue& options,
|
||||
const net::CompletionCallback& callback);
|
||||
#endif
|
||||
void GetFileIcon(const base::FilePath& path, mate::Arguments* args);
|
||||
|
||||
std::vector<mate::Dictionary> GetAppMetrics(v8::Isolate* isolate);
|
||||
v8::Local<v8::Value> GetGPUFeatureStatus(v8::Isolate* isolate);
|
||||
void EnableMixedSandbox(mate::Arguments* args);
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
bool MoveToApplicationsFolder(mate::Arguments* args);
|
||||
bool IsInApplicationsFolder();
|
||||
#endif
|
||||
#if defined(MAS_BUILD)
|
||||
base::Callback<void()> StartAccessingSecurityScopedResource(
|
||||
mate::Arguments* args);
|
||||
#endif
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// Get the current Jump List settings.
|
||||
@@ -222,15 +138,6 @@ class App : public AtomBrowserClient::Delegate,
|
||||
std::unique_ptr<CertificateManagerModel> certificate_manager_model_;
|
||||
#endif
|
||||
|
||||
// Tracks tasks requesting file icons.
|
||||
base::CancelableTaskTracker cancelable_task_tracker_;
|
||||
|
||||
base::FilePath app_path_;
|
||||
|
||||
using ProcessMetricMap =
|
||||
std::unordered_map<base::ProcessId, std::unique_ptr<atom::ProcessMetric>>;
|
||||
ProcessMetricMap app_metrics_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(App);
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -7,7 +7,6 @@
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "atom/browser/window_list.h"
|
||||
#include "atom/common/api/event_emitter_caller.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "base/time/time.h"
|
||||
@@ -16,12 +15,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
|
||||
@@ -48,31 +47,13 @@ void AutoUpdater::OnError(const std::string& message) {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
auto error = v8::Exception::Error(mate::StringToV8(isolate(), message));
|
||||
mate::EmitEvent(
|
||||
isolate(), GetWrapper(), "error",
|
||||
EmitCustomEvent(
|
||||
"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) {
|
||||
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();
|
||||
|
||||
// add two new params for better error handling
|
||||
errorObject->Set(mate::StringToV8(isolate(), "code"),
|
||||
v8::Integer::New(isolate(), code));
|
||||
errorObject->Set(mate::StringToV8(isolate(), "domain"),
|
||||
mate::StringToV8(isolate(), domain));
|
||||
|
||||
mate::EmitEvent(isolate(), GetWrapper(), "error", errorObject, message);
|
||||
}
|
||||
|
||||
void AutoUpdater::OnCheckingForUpdate() {
|
||||
Emit("checking-for-update");
|
||||
}
|
||||
@@ -98,22 +79,24 @@ 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()) {
|
||||
WindowList* window_list = WindowList::GetInstance();
|
||||
if (window_list->size() == 0) {
|
||||
auto_updater::AutoUpdater::QuitAndInstall();
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise do the restart after all windows have been closed.
|
||||
WindowList::AddObserver(this);
|
||||
WindowList::CloseAllWindows();
|
||||
window_list->AddObserver(this);
|
||||
for (NativeWindow* window : *window_list)
|
||||
window->Close();
|
||||
}
|
||||
|
||||
// static
|
||||
@@ -122,8 +105,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 +119,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 +134,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)
|
||||
|
||||
@@ -32,9 +32,6 @@ 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 OnCheckingForUpdate() override;
|
||||
void OnUpdateAvailable() override;
|
||||
void OnUpdateNotAvailable() override;
|
||||
@@ -48,7 +45,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);
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
// Copyright (c) 2018 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_box_layout.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/api/atom_api_view.h"
|
||||
#include "atom/common/api/constructor.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace mate {
|
||||
|
||||
template <>
|
||||
struct Converter<views::BoxLayout::Orientation> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Handle<v8::Value> val,
|
||||
views::BoxLayout::Orientation* out) {
|
||||
std::string orientation;
|
||||
if (!ConvertFromV8(isolate, val, &orientation))
|
||||
return false;
|
||||
if (orientation == "horizontal")
|
||||
*out = views::BoxLayout::kHorizontal;
|
||||
else if (orientation == "vertical")
|
||||
*out = views::BoxLayout::kVertical;
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
BoxLayout::BoxLayout(views::BoxLayout::Orientation orientation)
|
||||
: LayoutManager(new views::BoxLayout(orientation)) {}
|
||||
|
||||
BoxLayout::~BoxLayout() {}
|
||||
|
||||
void BoxLayout::SetFlexForView(mate::Handle<View> view, int flex) {
|
||||
auto* box_layout = static_cast<views::BoxLayout*>(layout_manager());
|
||||
box_layout->SetFlexForView(view->view(), flex);
|
||||
}
|
||||
|
||||
// static
|
||||
mate::WrappableBase* BoxLayout::New(mate::Arguments* args,
|
||||
views::BoxLayout::Orientation orientation) {
|
||||
auto* layout = new BoxLayout(orientation);
|
||||
layout->InitWith(args->isolate(), args->GetThis());
|
||||
return layout;
|
||||
}
|
||||
|
||||
// static
|
||||
void BoxLayout::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "BoxLayout"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetMethod("setFlexForView", &BoxLayout::SetFlexForView);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
namespace {
|
||||
|
||||
using atom::api::BoxLayout;
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("BoxLayout", mate::CreateConstructor<BoxLayout>(
|
||||
isolate, base::Bind(&BoxLayout::New)));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_box_layout, Initialize)
|
||||
@@ -1,40 +0,0 @@
|
||||
// Copyright (c) 2018 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_API_ATOM_API_BOX_LAYOUT_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_BOX_LAYOUT_H_
|
||||
|
||||
#include "atom/browser/api/atom_api_layout_manager.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "ui/views/layout/box_layout.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class View;
|
||||
|
||||
class BoxLayout : public LayoutManager {
|
||||
public:
|
||||
static mate::WrappableBase* New(mate::Arguments* args,
|
||||
views::BoxLayout::Orientation orientation);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
void SetFlexForView(mate::Handle<View> view, int flex);
|
||||
|
||||
protected:
|
||||
explicit BoxLayout(views::BoxLayout::Orientation orientation);
|
||||
~BoxLayout() override;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(BoxLayout);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_BOX_LAYOUT_H_
|
||||
@@ -1,164 +0,0 @@
|
||||
// Copyright (c) 2017 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_view.h"
|
||||
|
||||
#include "atom/browser/api/atom_api_web_contents.h"
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/browser/native_browser_view.h"
|
||||
#include "atom/common/color_util.h"
|
||||
#include "atom/common/native_mate_converters/gfx_converter.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "atom/common/options_switches.h"
|
||||
#include "native_mate/constructor.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "ui/gfx/geometry/rect.h"
|
||||
|
||||
namespace mate {
|
||||
|
||||
template <>
|
||||
struct Converter<atom::AutoResizeFlags> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
atom::AutoResizeFlags* auto_resize_flags) {
|
||||
mate::Dictionary params;
|
||||
if (!ConvertFromV8(isolate, val, ¶ms)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t flags = 0;
|
||||
bool width = false;
|
||||
if (params.Get("width", &width) && width) {
|
||||
flags |= atom::kAutoResizeWidth;
|
||||
}
|
||||
bool height = false;
|
||||
if (params.Get("height", &height) && height) {
|
||||
flags |= atom::kAutoResizeHeight;
|
||||
}
|
||||
|
||||
*auto_resize_flags = static_cast<atom::AutoResizeFlags>(flags);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
BrowserView::BrowserView(v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> wrapper,
|
||||
const mate::Dictionary& options) {
|
||||
Init(isolate, wrapper, options);
|
||||
}
|
||||
|
||||
void BrowserView::Init(v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> wrapper,
|
||||
const mate::Dictionary& options) {
|
||||
mate::Dictionary web_preferences = mate::Dictionary::CreateEmpty(isolate);
|
||||
options.Get(options::kWebPreferences, &web_preferences);
|
||||
web_preferences.Set("isBrowserView", true);
|
||||
mate::Handle<class WebContents> web_contents =
|
||||
WebContents::Create(isolate, web_preferences);
|
||||
|
||||
web_contents_.Reset(isolate, web_contents.ToV8());
|
||||
api_web_contents_ = web_contents.get();
|
||||
|
||||
view_.reset(
|
||||
NativeBrowserView::Create(api_web_contents_->managed_web_contents()));
|
||||
|
||||
InitWith(isolate, wrapper);
|
||||
}
|
||||
|
||||
BrowserView::~BrowserView() {
|
||||
api_web_contents_->DestroyWebContents(true /* async */);
|
||||
}
|
||||
|
||||
// static
|
||||
mate::WrappableBase* BrowserView::New(mate::Arguments* args) {
|
||||
if (!Browser::Get()->is_ready()) {
|
||||
args->ThrowError("Cannot create BrowserView before app is ready");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (args->Length() > 1) {
|
||||
args->ThrowError("Too many arguments");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mate::Dictionary options;
|
||||
if (!(args->Length() == 1 && args->GetNext(&options))) {
|
||||
options = mate::Dictionary::CreateEmpty(args->isolate());
|
||||
}
|
||||
|
||||
return new BrowserView(args->isolate(), args->GetThis(), options);
|
||||
}
|
||||
|
||||
int32_t BrowserView::ID() const {
|
||||
return weak_map_id();
|
||||
}
|
||||
|
||||
void BrowserView::SetAutoResize(AutoResizeFlags flags) {
|
||||
view_->SetAutoResizeFlags(flags);
|
||||
}
|
||||
|
||||
void BrowserView::SetBounds(const gfx::Rect& bounds) {
|
||||
view_->SetBounds(bounds);
|
||||
}
|
||||
|
||||
void BrowserView::SetBackgroundColor(const std::string& color_name) {
|
||||
view_->SetBackgroundColor(ParseHexColor(color_name));
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> BrowserView::GetWebContents() {
|
||||
if (web_contents_.IsEmpty()) {
|
||||
return v8::Null(isolate());
|
||||
}
|
||||
|
||||
return v8::Local<v8::Value>::New(isolate(), web_contents_);
|
||||
}
|
||||
|
||||
// static
|
||||
void BrowserView::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "BrowserView"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.MakeDestroyable()
|
||||
.SetMethod("setAutoResize", &BrowserView::SetAutoResize)
|
||||
.SetMethod("setBounds", &BrowserView::SetBounds)
|
||||
.SetMethod("setBackgroundColor", &BrowserView::SetBackgroundColor)
|
||||
.SetProperty("webContents", &BrowserView::GetWebContents)
|
||||
.SetProperty("id", &BrowserView::ID);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
namespace {
|
||||
|
||||
using atom::api::BrowserView;
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
BrowserView::SetConstructor(isolate, base::Bind(&BrowserView::New));
|
||||
|
||||
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::Dictionary dict(isolate, exports);
|
||||
dict.Set("BrowserView", browser_view);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_browser_view, Initialize)
|
||||
@@ -1,73 +0,0 @@
|
||||
// Copyright (c) 2017 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_VIEW_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_BROWSER_VIEW_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "atom/browser/native_browser_view.h"
|
||||
#include "native_mate/handle.h"
|
||||
|
||||
namespace gfx {
|
||||
class Rect;
|
||||
}
|
||||
|
||||
namespace mate {
|
||||
class Arguments;
|
||||
class Dictionary;
|
||||
} // namespace mate
|
||||
|
||||
namespace atom {
|
||||
|
||||
class NativeBrowserView;
|
||||
|
||||
namespace api {
|
||||
|
||||
class WebContents;
|
||||
|
||||
class BrowserView : public mate::TrackableObject<BrowserView> {
|
||||
public:
|
||||
static mate::WrappableBase* New(mate::Arguments* args);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
WebContents* web_contents() const { return api_web_contents_; }
|
||||
NativeBrowserView* view() const { return view_.get(); }
|
||||
|
||||
int32_t ID() const;
|
||||
|
||||
protected:
|
||||
BrowserView(v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> wrapper,
|
||||
const mate::Dictionary& options);
|
||||
~BrowserView() override;
|
||||
|
||||
private:
|
||||
void Init(v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> wrapper,
|
||||
const mate::Dictionary& options);
|
||||
|
||||
void SetAutoResize(AutoResizeFlags flags);
|
||||
void SetBounds(const gfx::Rect& bounds);
|
||||
void SetBackgroundColor(const std::string& color_name);
|
||||
|
||||
v8::Local<v8::Value> GetWebContents();
|
||||
|
||||
v8::Global<v8::Value> web_contents_;
|
||||
class WebContents* api_web_contents_ = nullptr;
|
||||
|
||||
std::unique_ptr<NativeBrowserView> view_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(BrowserView);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_BROWSER_VIEW_H_
|
||||
@@ -1,452 +0,0 @@
|
||||
// Copyright (c) 2013 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_browser_window.h"
|
||||
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/browser/unresponsive_suppressor.h"
|
||||
#include "atom/browser/web_contents_preferences.h"
|
||||
#include "atom/browser/window_list.h"
|
||||
#include "atom/common/api/api_messages.h"
|
||||
#include "atom/common/api/constructor.h"
|
||||
#include "atom/common/color_util.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "atom/common/options_switches.h"
|
||||
#include "base/threading/thread_task_runner_handle.h"
|
||||
#include "content/browser/renderer_host/render_widget_host_impl.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
#include "content/public/browser/render_view_host.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "ui/gl/gpu_switching_manager.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
BrowserWindow::BrowserWindow(v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> wrapper,
|
||||
const mate::Dictionary& options)
|
||||
: TopLevelWindow(isolate, options), weak_factory_(this) {
|
||||
mate::Handle<class WebContents> web_contents;
|
||||
|
||||
// Use options.webPreferences in WebContents.
|
||||
mate::Dictionary web_preferences = mate::Dictionary::CreateEmpty(isolate);
|
||||
options.Get(options::kWebPreferences, &web_preferences);
|
||||
|
||||
// Copy the backgroundColor to webContents.
|
||||
v8::Local<v8::Value> value;
|
||||
if (options.Get(options::kBackgroundColor, &value))
|
||||
web_preferences.Set(options::kBackgroundColor, value);
|
||||
|
||||
v8::Local<v8::Value> transparent;
|
||||
if (options.Get("transparent", &transparent))
|
||||
web_preferences.Set("transparent", transparent);
|
||||
|
||||
if (options.Get("webContents", &web_contents) && !web_contents.IsEmpty()) {
|
||||
// Set webPreferences from options if using an existing webContents.
|
||||
// These preferences will be used when the webContent launches new
|
||||
// render processes.
|
||||
auto* existing_preferences =
|
||||
WebContentsPreferences::From(web_contents->web_contents());
|
||||
base::DictionaryValue web_preferences_dict;
|
||||
if (mate::ConvertFromV8(isolate, web_preferences.GetHandle(),
|
||||
&web_preferences_dict)) {
|
||||
existing_preferences->dict()->Clear();
|
||||
existing_preferences->Merge(web_preferences_dict);
|
||||
}
|
||||
} else {
|
||||
// Creates the WebContents used by BrowserWindow.
|
||||
web_contents = WebContents::Create(isolate, web_preferences);
|
||||
}
|
||||
|
||||
web_contents_.Reset(isolate, web_contents.ToV8());
|
||||
api_web_contents_ = web_contents.get();
|
||||
api_web_contents_->AddObserver(this);
|
||||
Observe(api_web_contents_->web_contents());
|
||||
|
||||
// Keep a copy of the options for later use.
|
||||
mate::Dictionary(isolate, web_contents->GetWrapper())
|
||||
.Set("browserWindowOptions", options);
|
||||
|
||||
// Tell the content module to initialize renderer widget with transparent
|
||||
// mode.
|
||||
ui::GpuSwitchingManager::SetTransparent(window()->transparent());
|
||||
|
||||
// Associate with BrowserWindow.
|
||||
web_contents->SetOwnerWindow(window());
|
||||
|
||||
auto* host = web_contents->web_contents()->GetRenderViewHost();
|
||||
if (host)
|
||||
host->GetWidget()->AddInputEventObserver(this);
|
||||
|
||||
InitWith(isolate, wrapper);
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
if (!window()->has_frame())
|
||||
OverrideNSWindowContentView(web_contents->managed_web_contents());
|
||||
#endif
|
||||
|
||||
// Init window after everything has been setup.
|
||||
window()->InitFromOptions(options);
|
||||
}
|
||||
|
||||
BrowserWindow::~BrowserWindow() {
|
||||
api_web_contents_->RemoveObserver(this);
|
||||
// Note that the OnWindowClosed will not be called after the destructor runs,
|
||||
// since the window object is managed by the TopLevelWindow class.
|
||||
if (web_contents())
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
void BrowserWindow::OnInputEvent(const blink::WebInputEvent& event) {
|
||||
switch (event.GetType()) {
|
||||
case blink::WebInputEvent::kGestureScrollBegin:
|
||||
case blink::WebInputEvent::kGestureScrollUpdate:
|
||||
case blink::WebInputEvent::kGestureScrollEnd:
|
||||
Emit("scroll-touch-edge");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void BrowserWindow::RenderViewHostChanged(content::RenderViewHost* old_host,
|
||||
content::RenderViewHost* new_host) {
|
||||
if (old_host)
|
||||
old_host->GetWidget()->RemoveInputEventObserver(this);
|
||||
if (new_host)
|
||||
new_host->GetWidget()->AddInputEventObserver(this);
|
||||
}
|
||||
|
||||
void BrowserWindow::RenderViewCreated(
|
||||
content::RenderViewHost* render_view_host) {
|
||||
if (!window()->transparent())
|
||||
return;
|
||||
|
||||
content::RenderWidgetHostImpl* impl = content::RenderWidgetHostImpl::FromID(
|
||||
render_view_host->GetProcess()->GetID(),
|
||||
render_view_host->GetRoutingID());
|
||||
if (impl)
|
||||
impl->SetBackgroundOpaque(false);
|
||||
}
|
||||
|
||||
void BrowserWindow::DidFirstVisuallyNonEmptyPaint() {
|
||||
if (window()->IsVisible())
|
||||
return;
|
||||
|
||||
// When there is a non-empty first paint, resize the RenderWidget to force
|
||||
// Chromium to draw.
|
||||
auto* const view = web_contents()->GetRenderWidgetHostView();
|
||||
view->Show();
|
||||
view->SetSize(window()->GetContentSize());
|
||||
|
||||
// Emit the ReadyToShow event in next tick in case of pending drawing work.
|
||||
base::ThreadTaskRunnerHandle::Get()->PostTask(
|
||||
FROM_HERE, base::BindOnce(
|
||||
[](base::WeakPtr<BrowserWindow> self) {
|
||||
if (self)
|
||||
self->Emit("ready-to-show");
|
||||
},
|
||||
GetWeakPtr()));
|
||||
}
|
||||
|
||||
void BrowserWindow::BeforeUnloadDialogCancelled() {
|
||||
WindowList::WindowCloseCancelled(window());
|
||||
// Cancel unresponsive event when window close is cancelled.
|
||||
window_unresponsive_closure_.Cancel();
|
||||
}
|
||||
|
||||
void BrowserWindow::OnRendererUnresponsive(content::RenderProcessHost*) {
|
||||
// Schedule the unresponsive shortly later, since we may receive the
|
||||
// responsive event soon. This could happen after the whole application had
|
||||
// blocked for a while.
|
||||
// Also notice that when closing this event would be ignored because we have
|
||||
// explicitly started a close timeout counter. This is on purpose because we
|
||||
// don't want the unresponsive event to be sent too early when user is closing
|
||||
// the window.
|
||||
ScheduleUnresponsiveEvent(50);
|
||||
}
|
||||
|
||||
bool BrowserWindow::OnMessageReceived(const IPC::Message& message,
|
||||
content::RenderFrameHost* rfh) {
|
||||
bool handled = true;
|
||||
IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(BrowserWindow, message, rfh)
|
||||
IPC_MESSAGE_HANDLER(AtomFrameHostMsg_UpdateDraggableRegions,
|
||||
UpdateDraggableRegions)
|
||||
IPC_MESSAGE_UNHANDLED(handled = false)
|
||||
IPC_END_MESSAGE_MAP()
|
||||
return handled;
|
||||
}
|
||||
|
||||
void BrowserWindow::OnCloseContents() {
|
||||
DCHECK(web_contents());
|
||||
|
||||
// Close all child windows before closing current window.
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
for (v8::Local<v8::Value> value : child_windows_.Values(isolate())) {
|
||||
mate::Handle<BrowserWindow> child;
|
||||
if (mate::ConvertFromV8(isolate(), value, &child) && !child.IsEmpty())
|
||||
child->window()->CloseImmediately();
|
||||
}
|
||||
|
||||
// When the web contents is gone, close the window immediately, but the
|
||||
// memory will not be freed until you call delete.
|
||||
// In this way, it would be safe to manage windows via smart pointers. If you
|
||||
// want to free memory when the window is closed, you can do deleting by
|
||||
// overriding the OnWindowClosed method in the observer.
|
||||
window()->CloseImmediately();
|
||||
|
||||
// Do not sent "unresponsive" event after window is closed.
|
||||
window_unresponsive_closure_.Cancel();
|
||||
}
|
||||
|
||||
void BrowserWindow::OnRendererResponsive() {
|
||||
window_unresponsive_closure_.Cancel();
|
||||
Emit("responsive");
|
||||
}
|
||||
|
||||
void BrowserWindow::RequestPreferredWidth(int* width) {
|
||||
*width = web_contents()->GetPreferredSize().width();
|
||||
}
|
||||
|
||||
void BrowserWindow::OnCloseButtonClicked(bool* prevent_default) {
|
||||
// When user tries to close the window by clicking the close button, we do
|
||||
// not close the window immediately, instead we try to close the web page
|
||||
// first, and when the web page is closed the window will also be closed.
|
||||
*prevent_default = true;
|
||||
|
||||
// Assume the window is not responding if it doesn't cancel the close and is
|
||||
// not closed in 5s, in this way we can quickly show the unresponsive
|
||||
// dialog when the window is busy executing some script withouth waiting for
|
||||
// the unresponsive timeout.
|
||||
if (window_unresponsive_closure_.IsCancelled())
|
||||
ScheduleUnresponsiveEvent(5000);
|
||||
|
||||
if (!web_contents())
|
||||
// Already closed by renderer
|
||||
return;
|
||||
|
||||
if (web_contents()->NeedToFireBeforeUnload())
|
||||
web_contents()->DispatchBeforeUnload();
|
||||
else
|
||||
web_contents()->Close();
|
||||
}
|
||||
|
||||
void BrowserWindow::OnWindowClosed() {
|
||||
Cleanup();
|
||||
TopLevelWindow::OnWindowClosed();
|
||||
}
|
||||
|
||||
void BrowserWindow::OnWindowBlur() {
|
||||
web_contents()->StoreFocus();
|
||||
#if defined(OS_MACOSX)
|
||||
auto* rwhv = web_contents()->GetRenderWidgetHostView();
|
||||
if (rwhv)
|
||||
rwhv->SetActive(false);
|
||||
#endif
|
||||
|
||||
TopLevelWindow::OnWindowBlur();
|
||||
}
|
||||
|
||||
void BrowserWindow::OnWindowFocus() {
|
||||
web_contents()->RestoreFocus();
|
||||
#if defined(OS_MACOSX)
|
||||
auto* rwhv = web_contents()->GetRenderWidgetHostView();
|
||||
if (rwhv)
|
||||
rwhv->SetActive(true);
|
||||
#else
|
||||
if (!api_web_contents_->IsDevToolsOpened())
|
||||
web_contents()->Focus();
|
||||
#endif
|
||||
|
||||
TopLevelWindow::OnWindowFocus();
|
||||
}
|
||||
|
||||
void BrowserWindow::OnWindowResize() {
|
||||
#if defined(OS_MACOSX)
|
||||
if (!draggable_regions_.empty())
|
||||
UpdateDraggableRegions(nullptr, draggable_regions_);
|
||||
#endif
|
||||
TopLevelWindow::OnWindowResize();
|
||||
}
|
||||
|
||||
void BrowserWindow::OnWindowLeaveFullScreen() {
|
||||
TopLevelWindow::OnWindowLeaveFullScreen();
|
||||
#if defined(OS_MACOSX)
|
||||
if (web_contents()->IsFullscreenForCurrentTab())
|
||||
web_contents()->ExitFullscreen(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
void BrowserWindow::Focus() {
|
||||
if (api_web_contents_->IsOffScreen())
|
||||
FocusOnWebView();
|
||||
else
|
||||
TopLevelWindow::Focus();
|
||||
}
|
||||
|
||||
void BrowserWindow::Blur() {
|
||||
if (api_web_contents_->IsOffScreen())
|
||||
BlurWebView();
|
||||
else
|
||||
TopLevelWindow::Blur();
|
||||
}
|
||||
|
||||
void BrowserWindow::SetBackgroundColor(const std::string& color_name) {
|
||||
TopLevelWindow::SetBackgroundColor(color_name);
|
||||
auto* view = web_contents()->GetRenderWidgetHostView();
|
||||
if (view)
|
||||
view->SetBackgroundColor(ParseHexColor(color_name));
|
||||
}
|
||||
|
||||
void BrowserWindow::SetBrowserView(v8::Local<v8::Value> value) {
|
||||
TopLevelWindow::SetBrowserView(value);
|
||||
#if defined(OS_MACOSX)
|
||||
UpdateDraggableRegions(nullptr, draggable_regions_);
|
||||
#endif
|
||||
}
|
||||
|
||||
void BrowserWindow::SetVibrancy(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> value) {
|
||||
std::string type = mate::V8ToString(value);
|
||||
|
||||
auto* render_view_host = web_contents()->GetRenderViewHost();
|
||||
if (render_view_host) {
|
||||
auto* impl = content::RenderWidgetHostImpl::FromID(
|
||||
render_view_host->GetProcess()->GetID(),
|
||||
render_view_host->GetRoutingID());
|
||||
if (impl)
|
||||
impl->SetBackgroundOpaque(type.empty() ? !window_->transparent() : false);
|
||||
}
|
||||
|
||||
TopLevelWindow::SetVibrancy(isolate, value);
|
||||
}
|
||||
|
||||
void BrowserWindow::FocusOnWebView() {
|
||||
web_contents()->GetRenderViewHost()->GetWidget()->Focus();
|
||||
}
|
||||
|
||||
void BrowserWindow::BlurWebView() {
|
||||
web_contents()->GetRenderViewHost()->GetWidget()->Blur();
|
||||
}
|
||||
|
||||
bool BrowserWindow::IsWebViewFocused() {
|
||||
auto* host_view = web_contents()->GetRenderViewHost()->GetWidget()->GetView();
|
||||
return host_view && host_view->HasFocus();
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> BrowserWindow::GetWebContents(v8::Isolate* isolate) {
|
||||
if (web_contents_.IsEmpty())
|
||||
return v8::Null(isolate);
|
||||
return v8::Local<v8::Value>::New(isolate, web_contents_);
|
||||
}
|
||||
|
||||
// Convert draggable regions in raw format to SkRegion format.
|
||||
std::unique_ptr<SkRegion> BrowserWindow::DraggableRegionsToSkRegion(
|
||||
const std::vector<DraggableRegion>& regions) {
|
||||
auto sk_region = std::make_unique<SkRegion>();
|
||||
for (const DraggableRegion& region : regions) {
|
||||
sk_region->op(
|
||||
region.bounds.x(), region.bounds.y(), region.bounds.right(),
|
||||
region.bounds.bottom(),
|
||||
region.draggable ? SkRegion::kUnion_Op : SkRegion::kDifference_Op);
|
||||
}
|
||||
return sk_region;
|
||||
}
|
||||
|
||||
void BrowserWindow::ScheduleUnresponsiveEvent(int ms) {
|
||||
if (!window_unresponsive_closure_.IsCancelled())
|
||||
return;
|
||||
|
||||
window_unresponsive_closure_.Reset(
|
||||
base::Bind(&BrowserWindow::NotifyWindowUnresponsive, GetWeakPtr()));
|
||||
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
|
||||
FROM_HERE, window_unresponsive_closure_.callback(),
|
||||
base::TimeDelta::FromMilliseconds(ms));
|
||||
}
|
||||
|
||||
void BrowserWindow::NotifyWindowUnresponsive() {
|
||||
window_unresponsive_closure_.Cancel();
|
||||
if (!window_->IsClosed() && window_->IsEnabled() &&
|
||||
!IsUnresponsiveEventSuppressed()) {
|
||||
Emit("unresponsive");
|
||||
}
|
||||
}
|
||||
|
||||
void BrowserWindow::Cleanup() {
|
||||
auto* host = web_contents()->GetRenderViewHost();
|
||||
if (host)
|
||||
host->GetWidget()->RemoveInputEventObserver(this);
|
||||
|
||||
api_web_contents_->DestroyWebContents(true /* async */);
|
||||
Observe(nullptr);
|
||||
}
|
||||
|
||||
// static
|
||||
mate::WrappableBase* BrowserWindow::New(mate::Arguments* args) {
|
||||
if (!Browser::Get()->is_ready()) {
|
||||
args->ThrowError("Cannot create BrowserWindow before app is ready");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (args->Length() > 1) {
|
||||
args->ThrowError();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mate::Dictionary options;
|
||||
if (!(args->Length() == 1 && args->GetNext(&options))) {
|
||||
options = mate::Dictionary::CreateEmpty(args->isolate());
|
||||
}
|
||||
|
||||
return new BrowserWindow(args->isolate(), args->GetThis(), options);
|
||||
}
|
||||
|
||||
// static
|
||||
void BrowserWindow::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "BrowserWindow"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetMethod("focusOnWebView", &BrowserWindow::FocusOnWebView)
|
||||
.SetMethod("blurWebView", &BrowserWindow::BlurWebView)
|
||||
.SetMethod("isWebViewFocused", &BrowserWindow::IsWebViewFocused)
|
||||
.SetProperty("webContents", &BrowserWindow::GetWebContents);
|
||||
}
|
||||
|
||||
// static
|
||||
v8::Local<v8::Value> BrowserWindow::From(v8::Isolate* isolate,
|
||||
NativeWindow* native_window) {
|
||||
auto* existing = TrackableObject::FromWrappedClass(isolate, native_window);
|
||||
if (existing)
|
||||
return existing->GetWrapper();
|
||||
else
|
||||
return v8::Null(isolate);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
namespace {
|
||||
|
||||
using atom::api::BrowserWindow;
|
||||
using atom::api::TopLevelWindow;
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("BrowserWindow", mate::CreateConstructor<BrowserWindow>(
|
||||
isolate, base::Bind(&BrowserWindow::New)));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_window, Initialize)
|
||||
@@ -1,126 +0,0 @@
|
||||
// Copyright (c) 2013 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_API_ATOM_API_BROWSER_WINDOW_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_BROWSER_WINDOW_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/browser/api/atom_api_top_level_window.h"
|
||||
#include "atom/browser/api/atom_api_web_contents.h"
|
||||
#include "base/cancelable_callback.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class BrowserWindow : public TopLevelWindow,
|
||||
public content::RenderWidgetHost::InputEventObserver,
|
||||
public content::WebContentsObserver,
|
||||
public ExtendedWebContentsObserver {
|
||||
public:
|
||||
static mate::WrappableBase* New(mate::Arguments* args);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
// Returns the BrowserWindow object from |native_window|.
|
||||
static v8::Local<v8::Value> From(v8::Isolate* isolate,
|
||||
NativeWindow* native_window);
|
||||
|
||||
base::WeakPtr<BrowserWindow> GetWeakPtr() {
|
||||
return weak_factory_.GetWeakPtr();
|
||||
}
|
||||
|
||||
protected:
|
||||
BrowserWindow(v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> wrapper,
|
||||
const mate::Dictionary& options);
|
||||
~BrowserWindow() override;
|
||||
|
||||
// content::RenderWidgetHost::InputEventObserver:
|
||||
void OnInputEvent(const blink::WebInputEvent& event) override;
|
||||
|
||||
// content::WebContentsObserver:
|
||||
void RenderViewHostChanged(content::RenderViewHost* old_host,
|
||||
content::RenderViewHost* new_host) override;
|
||||
void RenderViewCreated(content::RenderViewHost* render_view_host) override;
|
||||
void DidFirstVisuallyNonEmptyPaint() override;
|
||||
void BeforeUnloadDialogCancelled() override;
|
||||
void OnRendererUnresponsive(content::RenderProcessHost*) override;
|
||||
bool OnMessageReceived(const IPC::Message& message,
|
||||
content::RenderFrameHost* rfh) override;
|
||||
|
||||
// ExtendedWebContentsObserver:
|
||||
void OnCloseContents() override;
|
||||
void OnRendererResponsive() override;
|
||||
|
||||
// NativeWindowObserver:
|
||||
void RequestPreferredWidth(int* width) override;
|
||||
void OnCloseButtonClicked(bool* prevent_default) override;
|
||||
|
||||
// TopLevelWindow:
|
||||
void OnWindowClosed() override;
|
||||
void OnWindowBlur() override;
|
||||
void OnWindowFocus() override;
|
||||
void OnWindowResize() override;
|
||||
void OnWindowLeaveFullScreen() override;
|
||||
void Focus() override;
|
||||
void Blur() override;
|
||||
void SetBackgroundColor(const std::string& color_name) override;
|
||||
void SetBrowserView(v8::Local<v8::Value> value) override;
|
||||
void SetVibrancy(v8::Isolate* isolate, v8::Local<v8::Value> value) override;
|
||||
|
||||
// BrowserWindow APIs.
|
||||
void FocusOnWebView();
|
||||
void BlurWebView();
|
||||
bool IsWebViewFocused();
|
||||
v8::Local<v8::Value> GetWebContents(v8::Isolate* isolate);
|
||||
|
||||
private:
|
||||
#if defined(OS_MACOSX)
|
||||
void OverrideNSWindowContentView(brightray::InspectableWebContents* iwc);
|
||||
#endif
|
||||
|
||||
// Helpers.
|
||||
|
||||
// Called when the window needs to update its draggable region.
|
||||
void UpdateDraggableRegions(content::RenderFrameHost* rfh,
|
||||
const std::vector<DraggableRegion>& regions);
|
||||
|
||||
// Convert draggable regions in raw format to SkRegion format.
|
||||
std::unique_ptr<SkRegion> DraggableRegionsToSkRegion(
|
||||
const std::vector<DraggableRegion>& regions);
|
||||
|
||||
// Schedule a notification unresponsive event.
|
||||
void ScheduleUnresponsiveEvent(int ms);
|
||||
|
||||
// Dispatch unresponsive event to observers.
|
||||
void NotifyWindowUnresponsive();
|
||||
|
||||
// Cleanup our WebContents observers.
|
||||
void Cleanup();
|
||||
|
||||
// Closure that would be called when window is unresponsive when closing,
|
||||
// it should be cancelled when we can prove that the window is responsive.
|
||||
base::CancelableClosure window_unresponsive_closure_;
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
std::vector<DraggableRegion> draggable_regions_;
|
||||
#endif
|
||||
|
||||
v8::Global<v8::Value> web_contents_;
|
||||
api::WebContents* api_web_contents_;
|
||||
|
||||
base::WeakPtrFactory<BrowserWindow> weak_factory_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(BrowserWindow);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_BROWSER_WINDOW_H_
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -1,58 +0,0 @@
|
||||
// Copyright (c) 2018 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_button.h"
|
||||
|
||||
#include "atom/common/api/constructor.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
Button::Button(views::Button* button) : View(button) {
|
||||
view()->set_owned_by_client();
|
||||
}
|
||||
|
||||
Button::~Button() {}
|
||||
|
||||
void Button::ButtonPressed(views::Button* sender, const ui::Event& event) {
|
||||
Emit("click");
|
||||
}
|
||||
|
||||
// static
|
||||
mate::WrappableBase* Button::New(mate::Arguments* args) {
|
||||
args->ThrowError("Button can not be created directly");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// static
|
||||
void Button::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "Button"));
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
namespace {
|
||||
|
||||
using atom::api::Button;
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("Button",
|
||||
mate::CreateConstructor<Button>(isolate, base::Bind(&Button::New)));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_button, Initialize)
|
||||
@@ -1,38 +0,0 @@
|
||||
// Copyright (c) 2018 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_API_ATOM_API_BUTTON_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_BUTTON_H_
|
||||
|
||||
#include "atom/browser/api/atom_api_view.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "ui/views/controls/button/button.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class Button : public View, public views::ButtonListener {
|
||||
public:
|
||||
static mate::WrappableBase* New(mate::Arguments* args);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
protected:
|
||||
explicit Button(views::Button* view);
|
||||
~Button() override;
|
||||
|
||||
// views::ButtonListener:
|
||||
void ButtonPressed(views::Button* sender, const ui::Event& event) override;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(Button);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_BUTTON_H_
|
||||
@@ -7,18 +7,17 @@
|
||||
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/file_path_converter.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "base/bind.h"
|
||||
#include "base/files/file_util.h"
|
||||
#include "content/public/browser/tracing_controller.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
using content::TracingController;
|
||||
|
||||
namespace mate {
|
||||
|
||||
template <>
|
||||
template<>
|
||||
struct Converter<base::trace_event::TraceConfig> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
@@ -41,39 +40,40 @@ 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));
|
||||
dict.SetMethod("setWatchEvent", base::Bind(
|
||||
&TracingController::SetWatchEvent, controller));
|
||||
dict.SetMethod("cancelWatchEvent", base::Bind(
|
||||
&TracingController::CancelWatchEvent, controller));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_content_tracing, Initialize)
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_content_tracing, Initialize)
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include "atom/browser/api/atom_api_cookies.h"
|
||||
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/request_context_delegate.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
@@ -15,7 +14,7 @@
|
||||
#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"
|
||||
@@ -25,7 +24,7 @@ using content::BrowserThread;
|
||||
|
||||
namespace mate {
|
||||
|
||||
template <>
|
||||
template<>
|
||||
struct Converter<atom::api::Cookies::Error> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
atom::api::Cookies::Error val) {
|
||||
@@ -36,7 +35,7 @@ struct Converter<atom::api::Cookies::Error> {
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
template<>
|
||||
struct Converter<net::CanonicalCookie> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
const net::CanonicalCookie& val) {
|
||||
@@ -55,28 +54,6 @@ struct Converter<net::CanonicalCookie> {
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<net::CookieChangeCause> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
const net::CookieChangeCause& val) {
|
||||
switch (val) {
|
||||
case net::CookieChangeCause::INSERTED:
|
||||
case net::CookieChangeCause::EXPLICIT:
|
||||
return mate::StringToV8(isolate, "explicit");
|
||||
case net::CookieChangeCause::OVERWRITE:
|
||||
return mate::StringToV8(isolate, "overwrite");
|
||||
case net::CookieChangeCause::EXPIRED:
|
||||
return mate::StringToV8(isolate, "expired");
|
||||
case net::CookieChangeCause::EVICTED:
|
||||
return mate::StringToV8(isolate, "evicted");
|
||||
case net::CookieChangeCause::EXPIRED_OVERWRITE:
|
||||
return mate::StringToV8(isolate, "expired-overwrite");
|
||||
default:
|
||||
return mate::StringToV8(isolate, "unknown");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
namespace atom {
|
||||
@@ -162,16 +139,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.
|
||||
@@ -180,13 +156,6 @@ void OnSetCookie(const Cookies::SetCallback& callback, bool success) {
|
||||
base::Bind(callback, success ? Cookies::SUCCESS : Cookies::FAILED));
|
||||
}
|
||||
|
||||
// Flushes cookie store in IO thread.
|
||||
void FlushCookieStoreOnIOThread(
|
||||
scoped_refptr<net::URLRequestContextGetter> getter,
|
||||
const base::Closure& callback) {
|
||||
GetCookieStore(getter)->FlushStore(base::BindOnce(RunCallbackInUI, callback));
|
||||
}
|
||||
|
||||
// Sets cookie with |details| in IO thread.
|
||||
void SetCookieOnIO(scoped_refptr<net::URLRequestContextGetter> getter,
|
||||
std::unique_ptr<base::DictionaryValue> details,
|
||||
@@ -207,106 +176,73 @@ 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, false,
|
||||
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()) {
|
||||
Init(isolate);
|
||||
cookie_change_subscription_ =
|
||||
browser_context->GetRequestContextDelegate()
|
||||
->RegisterCookieChangeCallback(
|
||||
base::Bind(&Cookies::OnCookieChanged, base::Unretained(this)));
|
||||
}
|
||||
|
||||
Cookies::~Cookies() {}
|
||||
Cookies::~Cookies() {
|
||||
}
|
||||
|
||||
void Cookies::Get(const base::DictionaryValue& filter,
|
||||
const GetCallback& callback) {
|
||||
std::unique_ptr<base::DictionaryValue> copied(filter.CreateDeepCopy());
|
||||
auto* getter = browser_context_->GetRequestContext();
|
||||
auto getter = make_scoped_refptr(request_context_getter_);
|
||||
content::BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::BindOnce(GetCookiesOnIO, base::RetainedRef(getter),
|
||||
std::move(copied), callback));
|
||||
base::Bind(GetCookiesOnIO, getter, Passed(&copied), callback));
|
||||
}
|
||||
|
||||
void Cookies::Remove(const GURL& url,
|
||||
const std::string& name,
|
||||
void Cookies::Remove(const GURL& url, const std::string& name,
|
||||
const base::Closure& callback) {
|
||||
auto* getter = browser_context_->GetRequestContext();
|
||||
auto getter = make_scoped_refptr(request_context_getter_);
|
||||
content::BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::BindOnce(RemoveCookieOnIOThread, base::RetainedRef(getter), url,
|
||||
name, callback));
|
||||
base::Bind(RemoveCookieOnIOThread, getter, url, name, callback));
|
||||
}
|
||||
|
||||
void Cookies::Set(const base::DictionaryValue& details,
|
||||
const SetCallback& callback) {
|
||||
std::unique_ptr<base::DictionaryValue> copied(details.CreateDeepCopy());
|
||||
auto* getter = browser_context_->GetRequestContext();
|
||||
auto getter = make_scoped_refptr(request_context_getter_);
|
||||
content::BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::BindOnce(SetCookieOnIO, base::RetainedRef(getter),
|
||||
std::move(copied), callback));
|
||||
}
|
||||
|
||||
void Cookies::FlushStore(const base::Closure& callback) {
|
||||
auto* getter = browser_context_->GetRequestContext();
|
||||
content::BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::BindOnce(FlushCookieStoreOnIOThread, base::RetainedRef(getter),
|
||||
callback));
|
||||
}
|
||||
|
||||
void Cookies::OnCookieChanged(const CookieDetails* details) {
|
||||
Emit("changed", *(details->cookie), details->cause, details->removed);
|
||||
base::Bind(SetCookieOnIO, getter, Passed(&copied), callback));
|
||||
}
|
||||
|
||||
// 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));
|
||||
}
|
||||
|
||||
@@ -317,8 +253,7 @@ void Cookies::BuildPrototype(v8::Isolate* isolate,
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetMethod("get", &Cookies::Get)
|
||||
.SetMethod("remove", &Cookies::Remove)
|
||||
.SetMethod("set", &Cookies::Set)
|
||||
.SetMethod("flushStore", &Cookies::FlushStore);
|
||||
.SetMethod("set", &Cookies::Set);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
@@ -8,8 +8,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "atom/browser/net/cookie_details.h"
|
||||
#include "base/callback_list.h"
|
||||
#include "base/callback.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "net/cookies/canonical_cookie.h"
|
||||
|
||||
@@ -49,19 +48,12 @@ class Cookies : public mate::TrackableObject<Cookies> {
|
||||
~Cookies() override;
|
||||
|
||||
void Get(const base::DictionaryValue& filter, const GetCallback& callback);
|
||||
void Remove(const GURL& url,
|
||||
const std::string& name,
|
||||
void Remove(const GURL& url, const std::string& name,
|
||||
const base::Closure& callback);
|
||||
void Set(const base::DictionaryValue& details, const SetCallback& callback);
|
||||
void FlushStore(const base::Closure& callback);
|
||||
|
||||
// AtomBrowserContext::RegisterCookieChangeCallback subscription:
|
||||
void OnCookieChanged(const CookieDetails*);
|
||||
|
||||
private:
|
||||
std::unique_ptr<base::CallbackList<void(const CookieDetails*)>::Subscription>
|
||||
cookie_change_subscription_;
|
||||
scoped_refptr<AtomBrowserContext> browser_context_;
|
||||
net::URLRequestContextGetter* request_context_getter_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Cookies);
|
||||
};
|
||||
|
||||
@@ -6,15 +6,16 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/atom_browser_main_parts.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "atom/common/node_includes.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 "atom/common/node_includes.h"
|
||||
#include "native_mate/object_template_builder.h"
|
||||
|
||||
using content::DevToolsAgentHost;
|
||||
|
||||
@@ -23,29 +24,30 @@ 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())
|
||||
std::unique_ptr<base::Value> parsed_message(base::JSONReader::Read(message));
|
||||
if (!parsed_message->IsType(base::Value::TYPE_DICTIONARY))
|
||||
return;
|
||||
|
||||
base::DictionaryValue* dict =
|
||||
static_cast<base::DictionaryValue*>(parsed_message.get());
|
||||
int id;
|
||||
@@ -76,52 +78,42 @@ void Debugger::DispatchProtocolMessage(DevToolsAgentHost* agent_host,
|
||||
}
|
||||
}
|
||||
|
||||
void Debugger::RenderFrameHostChanged(content::RenderFrameHost* old_rfh,
|
||||
content::RenderFrameHost* new_rfh) {
|
||||
if (agent_host_) {
|
||||
agent_host_->DisconnectWebContents();
|
||||
auto* web_contents = content::WebContents::FromRenderFrameHost(new_rfh);
|
||||
agent_host_->ConnectWebContents(web_contents);
|
||||
}
|
||||
}
|
||||
|
||||
void Debugger::Attach(mate::Arguments* args) {
|
||||
std::string protocol_version;
|
||||
args->GetNext(&protocol_version);
|
||||
|
||||
if (agent_host_) {
|
||||
args->ThrowError("Debugger is already attached to the target");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!protocol_version.empty() &&
|
||||
!DevToolsAgentHost::IsSupportedProtocolVersion(protocol_version)) {
|
||||
args->ThrowError("Requested protocol version is not supported");
|
||||
return;
|
||||
}
|
||||
|
||||
agent_host_ = DevToolsAgentHost::GetOrCreateFor(web_contents_);
|
||||
if (!agent_host_) {
|
||||
if (!agent_host_.get()) {
|
||||
args->ThrowError("No target available");
|
||||
return;
|
||||
}
|
||||
if (agent_host_->IsAttached()) {
|
||||
args->ThrowError("Another debugger is already attached to this target");
|
||||
return;
|
||||
}
|
||||
|
||||
agent_host_->AttachClient(this);
|
||||
}
|
||||
|
||||
bool Debugger::IsAttached() {
|
||||
return agent_host_ && agent_host_->IsAttached();
|
||||
return agent_host_.get() ? agent_host_->IsAttached() : false;
|
||||
}
|
||||
|
||||
void Debugger::Detach() {
|
||||
if (!agent_host_)
|
||||
if (!agent_host_.get())
|
||||
return;
|
||||
agent_host_->DetachClient(this);
|
||||
AgentHostClosed(agent_host_.get());
|
||||
agent_host_->DetachClient();
|
||||
AgentHostClosed(agent_host_.get(), false);
|
||||
agent_host_ = nullptr;
|
||||
}
|
||||
|
||||
void Debugger::SendCommand(mate::Arguments* args) {
|
||||
if (!agent_host_)
|
||||
if (!agent_host_.get())
|
||||
return;
|
||||
|
||||
std::string method;
|
||||
@@ -140,26 +132,17 @@ void Debugger::SendCommand(mate::Arguments* args) {
|
||||
request.SetInteger("id", request_id);
|
||||
request.SetString("method", method);
|
||||
if (!command_params.empty())
|
||||
request.Set("params", base::WrapUnique(command_params.DeepCopy()));
|
||||
request.Set("params", command_params.DeepCopy());
|
||||
|
||||
std::string json_args;
|
||||
base::JSONWriter::Write(request, &json_args);
|
||||
agent_host_->DispatchProtocolMessage(this, json_args);
|
||||
}
|
||||
|
||||
void Debugger::ClearPendingRequests() {
|
||||
if (pending_requests_.empty())
|
||||
return;
|
||||
base::Value error(base::Value::Type::DICTIONARY);
|
||||
base::Value error_msg("target closed while handling command");
|
||||
error.SetKey("message", std::move(error_msg));
|
||||
for (const auto& it : pending_requests_)
|
||||
it.second.Run(error, base::Value());
|
||||
agent_host_->DispatchProtocolMessage(json_args);
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<Debugger> Debugger::Create(v8::Isolate* isolate,
|
||||
content::WebContents* web_contents) {
|
||||
mate::Handle<Debugger> Debugger::Create(
|
||||
v8::Isolate* isolate,
|
||||
content::WebContents* web_contents) {
|
||||
return mate::CreateHandle(isolate, new Debugger(isolate, web_contents));
|
||||
}
|
||||
|
||||
@@ -182,10 +165,8 @@ namespace {
|
||||
|
||||
using atom::api::Debugger;
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary(isolate, exports)
|
||||
.Set("Debugger", Debugger::GetConstructor(isolate)->GetFunction());
|
||||
@@ -193,4 +174,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);
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -4,172 +4,91 @@
|
||||
|
||||
#include "atom/browser/api/atom_api_desktop_capturer.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
using base::PlatformThreadRef;
|
||||
|
||||
#include "atom/common/api/atom_api_native_image.h"
|
||||
#include "atom/common/native_mate_converters/gfx_converter.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "base/task_scheduler/post_task.h"
|
||||
#include "base/threading/thread_task_runner_handle.h"
|
||||
#include "chrome/browser/media/desktop_media_list.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/desktop_capture.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
|
||||
#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
|
||||
#if defined(OS_WIN)
|
||||
#include "third_party/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h"
|
||||
#include "third_party/webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h"
|
||||
#include "ui/display/win/display_info.h"
|
||||
#endif // defined(OS_WIN)
|
||||
#include "third_party/webrtc/modules/desktop_capture/screen_capturer.h"
|
||||
#include "third_party/webrtc/modules/desktop_capture/window_capturer.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace mate {
|
||||
|
||||
template <>
|
||||
struct Converter<atom::api::DesktopCapturer::Source> {
|
||||
static v8::Local<v8::Value> ToV8(
|
||||
v8::Isolate* isolate,
|
||||
const atom::api::DesktopCapturer::Source& source) {
|
||||
template<>
|
||||
struct Converter<DesktopMediaList::Source> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
const DesktopMediaList::Source& source) {
|
||||
mate::Dictionary dict(isolate, v8::Object::New(isolate));
|
||||
content::DesktopMediaID id = source.media_list_source.id;
|
||||
dict.Set("name", base::UTF16ToUTF8(source.media_list_source.name));
|
||||
content::DesktopMediaID id = source.id;
|
||||
dict.Set("name", base::UTF16ToUTF8(source.name));
|
||||
dict.Set("id", id.ToString());
|
||||
dict.Set("thumbnail",
|
||||
atom::api::NativeImage::Create(
|
||||
isolate, gfx::Image(source.media_list_source.thumbnail)));
|
||||
dict.Set("display_id", source.display_id);
|
||||
dict.Set(
|
||||
"thumbnail",
|
||||
atom::api::NativeImage::Create(isolate, gfx::Image(source.thumbnail)));
|
||||
return ConvertToV8(isolate, dict);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
namespace {
|
||||
|
||||
void EmitFinished(
|
||||
const std::vector<atom::api::DesktopCapturer::Source>& sources,
|
||||
atom::api::DesktopCapturer* cap) {
|
||||
cap->Emit("finished", sources);
|
||||
}
|
||||
|
||||
void StartHandlingTask(bool capture_window,
|
||||
bool capture_screen,
|
||||
const gfx::Size& thumbnail_size,
|
||||
atom::api::DesktopCapturer* cap) {
|
||||
#if defined(OS_WIN)
|
||||
if (content::desktop_capture::CreateDesktopCaptureOptions()
|
||||
.allow_directx_capturer()) {
|
||||
// DxgiDuplicatorController should be alive in this scope according to
|
||||
// screen_capturer_win.cc.
|
||||
auto duplicator = webrtc::DxgiDuplicatorController::Instance();
|
||||
cap->using_directx_capturer_ =
|
||||
webrtc::ScreenCapturerWinDirectx::IsSupported();
|
||||
}
|
||||
#endif // defined(OS_WIN)
|
||||
std::unique_ptr<webrtc::DesktopCapturer> screen_capturer(
|
||||
capture_screen ? content::desktop_capture::CreateScreenCapturer()
|
||||
: nullptr);
|
||||
std::unique_ptr<webrtc::DesktopCapturer> window_capturer(
|
||||
capture_window ? content::desktop_capture::CreateWindowCapturer()
|
||||
: nullptr);
|
||||
cap->media_list_.reset(new NativeDesktopMediaList(
|
||||
std::move(screen_capturer), std::move(window_capturer)));
|
||||
|
||||
cap->media_list_->SetThumbnailSize(thumbnail_size);
|
||||
cap->media_list_->StartUpdating(cap);
|
||||
}
|
||||
|
||||
void OnRefreshFinishedTask(atom::api::DesktopCapturer* cap) {
|
||||
const auto media_list_sources = cap->media_list_->GetSources();
|
||||
std::vector<atom::api::DesktopCapturer::Source> sources;
|
||||
for (const auto& media_list_source : media_list_sources) {
|
||||
sources.emplace_back(
|
||||
atom::api::DesktopCapturer::Source{media_list_source, std::string()});
|
||||
}
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// Gather the same unique screen IDs used by the electron.screen API in order
|
||||
// to provide an association between it and desktopCapturer/getUserMedia.
|
||||
// This is only required when using the DirectX capturer, otherwise the IDs
|
||||
// across the APIs already match.
|
||||
if (cap->using_directx_capturer_) {
|
||||
std::vector<std::string> device_names;
|
||||
// Crucially, this list of device names will be in the same order as
|
||||
// |media_list_sources|.
|
||||
webrtc::DxgiDuplicatorController::Instance()->GetDeviceNames(&device_names);
|
||||
int device_name_index = 0;
|
||||
for (auto& source : sources) {
|
||||
if (source.media_list_source.id.type ==
|
||||
content::DesktopMediaID::TYPE_SCREEN) {
|
||||
const auto& device_name = device_names[device_name_index++];
|
||||
std::wstring wide_device_name;
|
||||
base::UTF8ToWide(device_name.c_str(), device_name.size(),
|
||||
&wide_device_name);
|
||||
const int64_t device_id =
|
||||
display::win::DisplayInfo::DeviceIdFromDeviceName(
|
||||
wide_device_name.c_str());
|
||||
source.display_id = base::Int64ToString(device_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
#elif defined(OS_MACOSX)
|
||||
// On Mac, the IDs across the APIs match.
|
||||
for (auto& source : sources) {
|
||||
if (source.media_list_source.id.type ==
|
||||
content::DesktopMediaID::TYPE_SCREEN) {
|
||||
source.display_id = base::Int64ToString(source.media_list_source.id.id);
|
||||
}
|
||||
}
|
||||
#endif // defined(OS_WIN)
|
||||
// TODO(ajmacd): Add Linux support. The IDs across APIs differ but Chrome only
|
||||
// supports capturing the entire desktop on Linux. Revisit this if individual
|
||||
// screen support is added.
|
||||
|
||||
content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
|
||||
base::Bind(EmitFinished, sources, cap));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
DesktopCapturer::DesktopCapturer(v8::Isolate* isolate) {
|
||||
Init(isolate);
|
||||
capture_thread_ = base::CreateSequencedTaskRunnerWithTraits(
|
||||
{base::WithBaseSyncPrimitives(), base::MayBlock(),
|
||||
base::TaskPriority::USER_VISIBLE});
|
||||
}
|
||||
|
||||
DesktopCapturer::~DesktopCapturer() {}
|
||||
DesktopCapturer::~DesktopCapturer() {
|
||||
}
|
||||
|
||||
void DesktopCapturer::StartHandling(bool capture_window,
|
||||
bool capture_screen,
|
||||
const gfx::Size& thumbnail_size) {
|
||||
capture_thread_->PostTask(
|
||||
FROM_HERE, base::BindOnce(StartHandlingTask, capture_window,
|
||||
capture_screen, thumbnail_size, this));
|
||||
webrtc::DesktopCaptureOptions options =
|
||||
webrtc::DesktopCaptureOptions::CreateDefault();
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// On windows, desktop effects (e.g. Aero) will be disabled when the Desktop
|
||||
// capture API is active by default.
|
||||
// We keep the desktop effects in most times. Howerver, the screen still
|
||||
// fickers when the API is capturing the window due to limitation of current
|
||||
// implemetation. This is a known and wontFix issue in webrtc (see:
|
||||
// http://code.google.com/p/webrtc/issues/detail?id=3373)
|
||||
options.set_disable_effects(false);
|
||||
#endif
|
||||
|
||||
std::unique_ptr<webrtc::ScreenCapturer> screen_capturer(
|
||||
capture_screen ? webrtc::ScreenCapturer::Create(options) : nullptr);
|
||||
std::unique_ptr<webrtc::WindowCapturer> window_capturer(
|
||||
capture_window ? webrtc::WindowCapturer::Create(options) : nullptr);
|
||||
media_list_.reset(new NativeDesktopMediaList(
|
||||
std::move(screen_capturer), std::move(window_capturer)));
|
||||
|
||||
media_list_->SetThumbnailSize(thumbnail_size);
|
||||
media_list_->StartUpdating(this);
|
||||
}
|
||||
|
||||
void DesktopCapturer::OnSourceAdded(int index) {}
|
||||
void DesktopCapturer::OnSourceAdded(int index) {
|
||||
}
|
||||
|
||||
void DesktopCapturer::OnSourceRemoved(int index) {}
|
||||
void DesktopCapturer::OnSourceRemoved(int index) {
|
||||
}
|
||||
|
||||
void DesktopCapturer::OnSourceMoved(int old_index, int new_index) {}
|
||||
void DesktopCapturer::OnSourceMoved(int old_index, int new_index) {
|
||||
}
|
||||
|
||||
void DesktopCapturer::OnSourceNameChanged(int index) {}
|
||||
void DesktopCapturer::OnSourceNameChanged(int index) {
|
||||
}
|
||||
|
||||
void DesktopCapturer::OnSourceThumbnailChanged(int index) {}
|
||||
void DesktopCapturer::OnSourceThumbnailChanged(int index) {
|
||||
}
|
||||
|
||||
bool DesktopCapturer::OnRefreshFinished() {
|
||||
capture_thread_->PostTask(FROM_HERE,
|
||||
base::BindOnce(OnRefreshFinishedTask, this));
|
||||
Emit("finished", media_list_->GetSources());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -180,8 +99,7 @@ mate::Handle<DesktopCapturer> DesktopCapturer::Create(v8::Isolate* isolate) {
|
||||
|
||||
// static
|
||||
void DesktopCapturer::BuildPrototype(
|
||||
v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "DesktopCapturer"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetMethod("startHandling", &DesktopCapturer::StartHandling);
|
||||
@@ -193,10 +111,8 @@ void DesktopCapturer::BuildPrototype(
|
||||
|
||||
namespace {
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("desktopCapturer", atom::api::DesktopCapturer::Create(isolate));
|
||||
@@ -204,4 +120,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);
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
#ifndef ATOM_BROWSER_API_ATOM_API_DESKTOP_CAPTURER_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_DESKTOP_CAPTURER_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/api/event_emitter.h"
|
||||
#include "chrome/browser/media/desktop_media_list_observer.h"
|
||||
#include "chrome/browser/media/native_desktop_media_list.h"
|
||||
@@ -16,15 +14,9 @@ namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class DesktopCapturer : public mate::EventEmitter<DesktopCapturer>,
|
||||
public DesktopMediaListObserver {
|
||||
class DesktopCapturer: public mate::EventEmitter<DesktopCapturer>,
|
||||
public DesktopMediaListObserver {
|
||||
public:
|
||||
struct Source {
|
||||
DesktopMediaList::Source media_list_source;
|
||||
// Will be an empty string if not available.
|
||||
std::string display_id;
|
||||
};
|
||||
|
||||
static mate::Handle<DesktopCapturer> Create(v8::Isolate* isolate);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
@@ -34,11 +26,6 @@ class DesktopCapturer : public mate::EventEmitter<DesktopCapturer>,
|
||||
bool capture_screen,
|
||||
const gfx::Size& thumbnail_size);
|
||||
|
||||
std::unique_ptr<DesktopMediaList> media_list_;
|
||||
#if defined(OS_WIN)
|
||||
bool using_directx_capturer_ = false;
|
||||
#endif // defined(OS_WIN)
|
||||
|
||||
protected:
|
||||
explicit DesktopCapturer(v8::Isolate* isolate);
|
||||
~DesktopCapturer() override;
|
||||
@@ -52,7 +39,7 @@ class DesktopCapturer : public mate::EventEmitter<DesktopCapturer>,
|
||||
bool OnRefreshFinished() override;
|
||||
|
||||
private:
|
||||
scoped_refptr<base::SequencedTaskRunner> capture_thread_;
|
||||
std::unique_ptr<DesktopMediaList> media_list_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(DesktopCapturer);
|
||||
};
|
||||
|
||||
@@ -6,22 +6,20 @@
|
||||
#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"
|
||||
#include "atom/browser/ui/message_box.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/file_path_converter.h"
|
||||
#include "atom/common/native_mate_converters/image_converter.h"
|
||||
#include "atom/common/native_mate_converters/net_converter.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace mate {
|
||||
|
||||
template <>
|
||||
template<>
|
||||
struct Converter<file_dialog::Filter> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
@@ -37,30 +35,6 @@ struct Converter<file_dialog::Filter> {
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<file_dialog::DialogSettings> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
file_dialog::DialogSettings* out) {
|
||||
mate::Dictionary dict;
|
||||
if (!ConvertFromV8(isolate, val, &dict))
|
||||
return false;
|
||||
dict.Get("window", &(out->parent_window));
|
||||
dict.Get("title", &(out->title));
|
||||
dict.Get("message", &(out->message));
|
||||
dict.Get("buttonLabel", &(out->button_label));
|
||||
dict.Get("nameFieldLabel", &(out->name_field_label));
|
||||
dict.Get("defaultPath", &(out->default_path));
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
namespace {
|
||||
@@ -73,70 +47,77 @@ void ShowMessageBox(int type,
|
||||
const std::string& title,
|
||||
const std::string& message,
|
||||
const std::string& detail,
|
||||
const std::string& checkbox_label,
|
||||
bool checkbox_checked,
|
||||
const gfx::ImageSkia& icon,
|
||||
atom::NativeWindow* window,
|
||||
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,
|
||||
message, detail, checkbox_label, checkbox_checked,
|
||||
icon, callback);
|
||||
atom::ShowMessageBox(window, (atom::MessageBoxType)type, buttons,
|
||||
default_id, cancel_id, options, title,
|
||||
message, detail, icon, callback);
|
||||
} else {
|
||||
int chosen = atom::ShowMessageBox(
|
||||
window, static_cast<atom::MessageBoxType>(type), buttons, default_id,
|
||||
cancel_id, options, title, message, detail, icon);
|
||||
int chosen = atom::ShowMessageBox(window, (atom::MessageBoxType)type,
|
||||
buttons, default_id, cancel_id,
|
||||
options, title, message, detail, icon);
|
||||
args->Return(chosen);
|
||||
}
|
||||
}
|
||||
|
||||
void ShowOpenDialog(const file_dialog::DialogSettings& settings,
|
||||
void ShowOpenDialog(const std::string& title,
|
||||
const std::string& button_label,
|
||||
const base::FilePath& default_path,
|
||||
const file_dialog::Filters& filters,
|
||||
int properties,
|
||||
atom::NativeWindow* window,
|
||||
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)) {
|
||||
file_dialog::ShowOpenDialog(settings, callback);
|
||||
if (mate::Converter<file_dialog::OpenDialogCallback>::FromV8(args->isolate(),
|
||||
peek,
|
||||
&callback)) {
|
||||
file_dialog::ShowOpenDialog(window, title, button_label, default_path,
|
||||
filters, properties, callback);
|
||||
} else {
|
||||
std::vector<base::FilePath> paths;
|
||||
if (file_dialog::ShowOpenDialog(settings, &paths))
|
||||
if (file_dialog::ShowOpenDialog(window, title, button_label, default_path,
|
||||
filters, properties, &paths))
|
||||
args->Return(paths);
|
||||
}
|
||||
}
|
||||
|
||||
void ShowSaveDialog(const file_dialog::DialogSettings& settings,
|
||||
void ShowSaveDialog(const std::string& title,
|
||||
const std::string& button_label,
|
||||
const base::FilePath& default_path,
|
||||
const file_dialog::Filters& filters,
|
||||
atom::NativeWindow* window,
|
||||
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)) {
|
||||
file_dialog::ShowSaveDialog(settings, callback);
|
||||
if (mate::Converter<file_dialog::SaveDialogCallback>::FromV8(args->isolate(),
|
||||
peek,
|
||||
&callback)) {
|
||||
file_dialog::ShowSaveDialog(window, title, button_label, default_path,
|
||||
filters, callback);
|
||||
} else {
|
||||
base::FilePath path;
|
||||
if (file_dialog::ShowSaveDialog(settings, &path))
|
||||
if (file_dialog::ShowSaveDialog(window, title, button_label, default_path,
|
||||
filters, &path))
|
||||
args->Return(path);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
dict.SetMethod("showOpenDialog", &ShowOpenDialog);
|
||||
dict.SetMethod("showSaveDialog", &ShowSaveDialog);
|
||||
#if defined(OS_MACOSX) || defined(OS_WIN)
|
||||
dict.SetMethod("showCertificateTrustDialog",
|
||||
&certificate_trust::ShowCertificateTrust);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_dialog, Initialize)
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_dialog, Initialize)
|
||||
|
||||
@@ -10,32 +10,30 @@
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/file_path_converter.h"
|
||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "base/message_loop/message_loop.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "base/threading/thread_task_runner_handle.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "net/base/filename_util.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
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 +56,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 +74,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::MessageLoop::current()->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;
|
||||
@@ -111,6 +109,7 @@ bool DownloadItem::CanResume() const {
|
||||
|
||||
void DownloadItem::Cancel() {
|
||||
download_item_->Cancel(true);
|
||||
download_item_->Remove();
|
||||
}
|
||||
|
||||
int64_t DownloadItem::GetReceivedBytes() const {
|
||||
@@ -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(),
|
||||
std::string()).LossyDisplayName());
|
||||
}
|
||||
|
||||
std::string DownloadItem::GetContentDisposition() const {
|
||||
@@ -145,11 +145,7 @@ const GURL& DownloadItem::GetURL() const {
|
||||
return download_item_->GetURL();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -165,18 +161,6 @@ base::FilePath DownloadItem::GetSavePath() const {
|
||||
return save_path_;
|
||||
}
|
||||
|
||||
std::string DownloadItem::GetLastModifiedTime() const {
|
||||
return download_item_->GetLastModifiedTime();
|
||||
}
|
||||
|
||||
std::string DownloadItem::GetETag() const {
|
||||
return download_item_->GetETag();
|
||||
}
|
||||
|
||||
double DownloadItem::GetStartTime() const {
|
||||
return download_item_->GetStartTime().ToDoubleT();
|
||||
}
|
||||
|
||||
// static
|
||||
void DownloadItem::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
@@ -195,20 +179,16 @@ void DownloadItem::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("getFilename", &DownloadItem::GetFilename)
|
||||
.SetMethod("getContentDisposition", &DownloadItem::GetContentDisposition)
|
||||
.SetMethod("getURL", &DownloadItem::GetURL)
|
||||
.SetMethod("getURLChain", &DownloadItem::GetURLChain)
|
||||
.SetMethod("getState", &DownloadItem::GetState)
|
||||
.SetMethod("isDone", &DownloadItem::IsDone)
|
||||
.SetMethod("setSavePath", &DownloadItem::SetSavePath)
|
||||
.SetMethod("getSavePath", &DownloadItem::GetSavePath)
|
||||
.SetMethod("getLastModifiedTime", &DownloadItem::GetLastModifiedTime)
|
||||
.SetMethod("getETag", &DownloadItem::GetETag)
|
||||
.SetMethod("getStartTime", &DownloadItem::GetStartTime);
|
||||
.SetMethod("getSavePath", &DownloadItem::GetSavePath);
|
||||
}
|
||||
|
||||
// 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 +206,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 +216,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);
|
||||
|
||||
@@ -6,11 +6,10 @@
|
||||
#define ATOM_BROWSER_API_ATOM_API_DOWNLOAD_ITEM_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#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 +18,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);
|
||||
@@ -39,26 +38,22 @@ class DownloadItem : public mate::TrackableObject<DownloadItem>,
|
||||
std::string GetFilename() const;
|
||||
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;
|
||||
std::string GetLastModifiedTime() const;
|
||||
std::string GetETag() const;
|
||||
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);
|
||||
};
|
||||
|
||||
@@ -40,8 +40,8 @@ void GlobalShortcut::OnKeyPressed(const ui::Accelerator& accelerator) {
|
||||
|
||||
bool GlobalShortcut::Register(const ui::Accelerator& accelerator,
|
||||
const base::Closure& callback) {
|
||||
if (!GlobalShortcutListener::GetInstance()->RegisterAccelerator(accelerator,
|
||||
this)) {
|
||||
if (!GlobalShortcutListener::GetInstance()->RegisterAccelerator(
|
||||
accelerator, this)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -54,8 +54,8 @@ void GlobalShortcut::Unregister(const ui::Accelerator& accelerator) {
|
||||
return;
|
||||
|
||||
accelerator_callback_map_.erase(accelerator);
|
||||
GlobalShortcutListener::GetInstance()->UnregisterAccelerator(accelerator,
|
||||
this);
|
||||
GlobalShortcutListener::GetInstance()->UnregisterAccelerator(
|
||||
accelerator, this);
|
||||
}
|
||||
|
||||
bool GlobalShortcut::IsRegistered(const ui::Accelerator& accelerator) {
|
||||
@@ -73,8 +73,8 @@ mate::Handle<GlobalShortcut> GlobalShortcut::Create(v8::Isolate* isolate) {
|
||||
}
|
||||
|
||||
// static
|
||||
void GlobalShortcut::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
void GlobalShortcut::BuildPrototype(
|
||||
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "GlobalShortcut"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetMethod("register", &GlobalShortcut::Register)
|
||||
@@ -89,10 +89,8 @@ void GlobalShortcut::BuildPrototype(v8::Isolate* isolate,
|
||||
|
||||
namespace {
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("globalShortcut", atom::api::GlobalShortcut::Create(isolate));
|
||||
@@ -100,4 +98,4 @@ void Initialize(v8::Local<v8::Object> exports,
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_global_shortcut, Initialize)
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_global_shortcut, Initialize)
|
||||
|
||||
@@ -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)
|
||||
@@ -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_
|
||||
@@ -1,58 +0,0 @@
|
||||
// Copyright (c) 2018 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_label_button.h"
|
||||
|
||||
#include "atom/common/api/constructor.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "ui/views/controls/button/label_button.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
LabelButton::LabelButton(const std::string& text)
|
||||
: Button(new views::LabelButton(this, base::UTF8ToUTF16(text))) {}
|
||||
|
||||
LabelButton::~LabelButton() {}
|
||||
|
||||
// static
|
||||
mate::WrappableBase* LabelButton::New(mate::Arguments* args,
|
||||
const std::string& text) {
|
||||
// Constructor call.
|
||||
auto* view = new LabelButton(text);
|
||||
view->InitWith(args->isolate(), args->GetThis());
|
||||
return view;
|
||||
}
|
||||
|
||||
// static
|
||||
void LabelButton::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "LabelButton"));
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
namespace {
|
||||
|
||||
using atom::api::LabelButton;
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("LabelButton", mate::CreateConstructor<LabelButton>(
|
||||
isolate, base::Bind(&LabelButton::New)));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_label_button, Initialize)
|
||||
@@ -1,36 +0,0 @@
|
||||
// Copyright (c) 2018 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_API_ATOM_API_LABEL_BUTTON_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_LABEL_BUTTON_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/api/atom_api_button.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class LabelButton : public Button {
|
||||
public:
|
||||
static mate::WrappableBase* New(mate::Arguments* args,
|
||||
const std::string& text);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
protected:
|
||||
explicit LabelButton(const std::string& text);
|
||||
~LabelButton() override;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(LabelButton);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_LABEL_BUTTON_H_
|
||||
@@ -1,63 +0,0 @@
|
||||
// Copyright (c) 2018 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_layout_manager.h"
|
||||
|
||||
#include "atom/common/api/constructor.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
LayoutManager::LayoutManager(views::LayoutManager* layout_manager)
|
||||
: layout_manager_(layout_manager) {
|
||||
DCHECK(layout_manager_);
|
||||
}
|
||||
|
||||
LayoutManager::~LayoutManager() {
|
||||
if (managed_by_us_)
|
||||
delete layout_manager_;
|
||||
}
|
||||
|
||||
std::unique_ptr<views::LayoutManager> LayoutManager::TakeOver() {
|
||||
if (!managed_by_us_) // already taken over.
|
||||
return nullptr;
|
||||
managed_by_us_ = false;
|
||||
return std::unique_ptr<views::LayoutManager>(layout_manager_);
|
||||
}
|
||||
|
||||
// static
|
||||
mate::WrappableBase* LayoutManager::New(mate::Arguments* args) {
|
||||
args->ThrowError("LayoutManager can not be created directly");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// static
|
||||
void LayoutManager::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
namespace {
|
||||
|
||||
using atom::api::LayoutManager;
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("LayoutManager", mate::CreateConstructor<LayoutManager>(
|
||||
isolate, base::Bind(&LayoutManager::New)));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_layout_manager, Initialize)
|
||||
@@ -1,44 +0,0 @@
|
||||
// Copyright (c) 2018 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_API_ATOM_API_LAYOUT_MANAGER_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_LAYOUT_MANAGER_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "ui/views/layout/layout_manager.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class LayoutManager : public mate::TrackableObject<LayoutManager> {
|
||||
public:
|
||||
static mate::WrappableBase* New(mate::Arguments* args);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
// Take over the ownership of the LayoutManager, and leave weak ref here.
|
||||
std::unique_ptr<views::LayoutManager> TakeOver();
|
||||
|
||||
views::LayoutManager* layout_manager() const { return layout_manager_; }
|
||||
|
||||
protected:
|
||||
explicit LayoutManager(views::LayoutManager* layout_manager);
|
||||
~LayoutManager() override;
|
||||
|
||||
private:
|
||||
bool managed_by_us_ = true;
|
||||
views::LayoutManager* layout_manager_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(LayoutManager);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_LAYOUT_MANAGER_H_
|
||||
@@ -20,15 +20,12 @@ namespace atom {
|
||||
namespace api {
|
||||
|
||||
Menu::Menu(v8::Isolate* isolate, v8::Local<v8::Object> wrapper)
|
||||
: model_(new AtomMenuModel(this)) {
|
||||
: model_(new AtomMenuModel(this)),
|
||||
parent_(nullptr) {
|
||||
InitWith(isolate, wrapper);
|
||||
model_->AddObserver(this);
|
||||
}
|
||||
|
||||
Menu::~Menu() {
|
||||
if (model_) {
|
||||
model_->RemoveObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
void Menu::AfterInit(v8::Isolate* isolate) {
|
||||
@@ -46,21 +43,15 @@ void Menu::AfterInit(v8::Isolate* isolate) {
|
||||
}
|
||||
|
||||
bool Menu::IsCommandIdChecked(int command_id) const {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
return is_checked_.Run(GetWrapper(), command_id);
|
||||
return is_checked_.Run(command_id);
|
||||
}
|
||||
|
||||
bool Menu::IsCommandIdEnabled(int command_id) const {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
return is_enabled_.Run(GetWrapper(), command_id);
|
||||
return is_enabled_.Run(command_id);
|
||||
}
|
||||
|
||||
bool Menu::IsCommandIdVisible(int command_id) const {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
return is_visible_.Run(GetWrapper(), command_id);
|
||||
return is_visible_.Run(command_id);
|
||||
}
|
||||
|
||||
bool Menu::GetAcceleratorForCommandIdWithParams(
|
||||
@@ -69,28 +60,23 @@ bool Menu::GetAcceleratorForCommandIdWithParams(
|
||||
ui::Accelerator* accelerator) const {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
v8::Local<v8::Value> val =
|
||||
get_accelerator_.Run(GetWrapper(), command_id, use_default_accelerator);
|
||||
v8::Local<v8::Value> val = get_accelerator_.Run(
|
||||
command_id, use_default_accelerator);
|
||||
return mate::ConvertFromV8(isolate(), val, accelerator);
|
||||
}
|
||||
|
||||
void Menu::ExecuteCommand(int command_id, int flags) {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
execute_command_.Run(GetWrapper(),
|
||||
mate::internal::CreateEventFromFlags(isolate(), flags),
|
||||
command_id);
|
||||
execute_command_.Run(
|
||||
mate::internal::CreateEventFromFlags(isolate(), flags),
|
||||
command_id);
|
||||
}
|
||||
|
||||
void Menu::MenuWillShow(ui::SimpleMenuModel* source) {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
menu_will_show_.Run(GetWrapper());
|
||||
menu_will_show_.Run();
|
||||
}
|
||||
|
||||
void Menu::InsertItemAt(int index,
|
||||
int command_id,
|
||||
const base::string16& label) {
|
||||
void Menu::InsertItemAt(
|
||||
int index, int command_id, const base::string16& label) {
|
||||
model_->InsertItemAt(index, command_id, label);
|
||||
}
|
||||
|
||||
@@ -167,14 +153,6 @@ bool Menu::IsVisibleAt(int index) const {
|
||||
return model_->IsVisibleAt(index);
|
||||
}
|
||||
|
||||
void Menu::OnMenuWillClose() {
|
||||
Emit("menu-will-close");
|
||||
}
|
||||
|
||||
void Menu::OnMenuWillShow() {
|
||||
Emit("menu-will-show");
|
||||
}
|
||||
|
||||
// static
|
||||
void Menu::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
@@ -198,22 +176,20 @@ void Menu::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("isItemCheckedAt", &Menu::IsItemCheckedAt)
|
||||
.SetMethod("isEnabledAt", &Menu::IsEnabledAt)
|
||||
.SetMethod("isVisibleAt", &Menu::IsVisibleAt)
|
||||
.SetMethod("popupAt", &Menu::PopupAt)
|
||||
.SetMethod("closePopupAt", &Menu::ClosePopupAt);
|
||||
.SetMethod("popupAt", &Menu::PopupAt);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
using atom::api::Menu;
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
Menu::SetConstructor(isolate, base::Bind(&Menu::New));
|
||||
|
||||
@@ -228,4 +204,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)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/api/atom_api_top_level_window.h"
|
||||
#include "atom/browser/api/atom_api_window.h"
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "atom/browser/ui/atom_menu_model.h"
|
||||
#include "base/callback.h"
|
||||
@@ -18,8 +18,7 @@ namespace atom {
|
||||
namespace api {
|
||||
|
||||
class Menu : public mate::TrackableObject<Menu>,
|
||||
public AtomMenuModel::Delegate,
|
||||
public AtomMenuModel::Observer {
|
||||
public AtomMenuModel::Delegate {
|
||||
public:
|
||||
static mate::WrappableBase* New(mate::Arguments* args);
|
||||
|
||||
@@ -54,19 +53,12 @@ class Menu : public mate::TrackableObject<Menu>,
|
||||
void ExecuteCommand(int command_id, int event_flags) override;
|
||||
void MenuWillShow(ui::SimpleMenuModel* source) override;
|
||||
|
||||
virtual void PopupAt(TopLevelWindow* window,
|
||||
int x,
|
||||
int y,
|
||||
int positioning_item,
|
||||
const base::Closure& callback) = 0;
|
||||
virtual void ClosePopupAt(int32_t window_id) = 0;
|
||||
virtual void PopupAt(Window* window,
|
||||
int x = -1, int y = -1,
|
||||
int positioning_item = 0) = 0;
|
||||
|
||||
std::unique_ptr<AtomMenuModel> model_;
|
||||
Menu* parent_ = nullptr;
|
||||
|
||||
// Observable:
|
||||
void OnMenuWillClose() override;
|
||||
void OnMenuWillShow() override;
|
||||
Menu* parent_;
|
||||
|
||||
private:
|
||||
void InsertItemAt(int index, int command_id, const base::string16& label);
|
||||
@@ -96,14 +88,12 @@ class Menu : public mate::TrackableObject<Menu>,
|
||||
bool IsVisibleAt(int index) const;
|
||||
|
||||
// Stored delegate methods.
|
||||
base::Callback<bool(v8::Local<v8::Value>, int)> is_checked_;
|
||||
base::Callback<bool(v8::Local<v8::Value>, int)> is_enabled_;
|
||||
base::Callback<bool(v8::Local<v8::Value>, int)> is_visible_;
|
||||
base::Callback<v8::Local<v8::Value>(v8::Local<v8::Value>, int, bool)>
|
||||
get_accelerator_;
|
||||
base::Callback<void(v8::Local<v8::Value>, v8::Local<v8::Value>, int)>
|
||||
execute_command_;
|
||||
base::Callback<void(v8::Local<v8::Value>)> menu_will_show_;
|
||||
base::Callback<bool(int)> is_checked_;
|
||||
base::Callback<bool(int)> is_enabled_;
|
||||
base::Callback<bool(int)> is_visible_;
|
||||
base::Callback<v8::Local<v8::Value>(int, bool)> get_accelerator_;
|
||||
base::Callback<void(v8::Local<v8::Value>, int)> execute_command_;
|
||||
base::Callback<void()> menu_will_show_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Menu);
|
||||
};
|
||||
@@ -112,12 +102,12 @@ class Menu : public mate::TrackableObject<Menu>,
|
||||
|
||||
} // namespace atom
|
||||
|
||||
|
||||
namespace mate {
|
||||
|
||||
template <>
|
||||
template<>
|
||||
struct Converter<atom::AtomMenuModel*> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
|
||||
atom::AtomMenuModel** out) {
|
||||
// null would be tranfered to NULL.
|
||||
if (val->IsNull()) {
|
||||
|
||||
@@ -7,13 +7,10 @@
|
||||
|
||||
#include "atom/browser/api/atom_api_menu.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#import "atom/browser/ui/cocoa/atom_menu_controller.h"
|
||||
|
||||
using base::scoped_nsobject;
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
@@ -21,32 +18,15 @@ 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 PopupOnUI(const base::WeakPtr<NativeWindow>& native_window,
|
||||
int32_t window_id,
|
||||
int x,
|
||||
int y,
|
||||
int positioning_item,
|
||||
base::Closure callback);
|
||||
void ClosePopupAt(int32_t window_id) override;
|
||||
void PopupAt(Window* window, int x, int y, int positioning_item) override;
|
||||
|
||||
base::scoped_nsobject<AtomMenuController> menu_controller_;
|
||||
|
||||
private:
|
||||
friend class Menu;
|
||||
|
||||
void OnClosed(int32_t window_id, base::Closure callback);
|
||||
|
||||
scoped_nsobject<AtomMenuController> menu_controller_;
|
||||
|
||||
// window ID -> open context menu
|
||||
std::map<int32_t, scoped_nsobject<AtomMenuController>> popup_controllers_;
|
||||
|
||||
base::WeakPtrFactory<MenuMac> weak_factory_;
|
||||
static void SendActionToFirstResponder(const std::string& action);
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(MenuMac);
|
||||
};
|
||||
|
||||
@@ -6,63 +6,36 @@
|
||||
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "atom/browser/unresponsive_suppressor.h"
|
||||
#include "base/mac/scoped_sending_event.h"
|
||||
#include "base/message_loop/message_loop.h"
|
||||
#include "base/strings/sys_string_conversions.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "brightray/browser/inspectable_web_contents.h"
|
||||
#include "brightray/browser/inspectable_web_contents_view.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
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) {
|
||||
}
|
||||
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
|
||||
void MenuMac::PopupOnUI(const base::WeakPtr<NativeWindow>& native_window,
|
||||
int32_t window_id,
|
||||
int x,
|
||||
int y,
|
||||
int positioning_item,
|
||||
base::Closure callback) {
|
||||
if (!native_window)
|
||||
brightray::InspectableWebContents* web_contents =
|
||||
native_window->inspectable_web_contents();
|
||||
if (!web_contents)
|
||||
return;
|
||||
NSWindow* nswindow = native_window->GetNativeWindow();
|
||||
|
||||
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]);
|
||||
NSMenu* menu = [popup_controllers_[window_id] menu];
|
||||
NSView* view = [nswindow contentView];
|
||||
base::scoped_nsobject<AtomMenuController> menu_controller(
|
||||
[[AtomMenuController alloc] initWithModel:model_.get()
|
||||
useDefaultAccelerator:NO]);
|
||||
NSMenu* menu = [menu_controller menu];
|
||||
NSView* view = web_contents->GetView()->GetNativeView();
|
||||
|
||||
// Which menu item to show.
|
||||
NSMenuItem* item = nil;
|
||||
@@ -72,6 +45,7 @@ void MenuMac::PopupOnUI(const base::WeakPtr<NativeWindow>& native_window,
|
||||
// (-1, -1) means showing on mouse location.
|
||||
NSPoint position;
|
||||
if (x == -1 || y == -1) {
|
||||
NSWindow* nswindow = native_window->GetNativeWindow();
|
||||
position = [view convertPoint:[nswindow mouseLocationOutsideOfEventStream]
|
||||
fromView:nil];
|
||||
} else {
|
||||
@@ -95,61 +69,20 @@ void MenuMac::PopupOnUI(const base::WeakPtr<NativeWindow>& native_window,
|
||||
if (rightmostMenuPoint > screenRight)
|
||||
position.x = position.x - [menu size].width;
|
||||
|
||||
[popup_controllers_[window_id] setCloseCallback:close_callback];
|
||||
// Make sure events can be pumped while the menu is up.
|
||||
base::MessageLoop::ScopedNestableTaskAllower allow(
|
||||
base::MessageLoop::current());
|
||||
|
||||
// One of the events that could be pumped is |window.close()|.
|
||||
// User-initiated event-tracking loops protect against this by
|
||||
// setting flags in -[CrApplication sendEvent:], but since
|
||||
// web-content menus are initiated by IPC message the setup has to
|
||||
// be done manually.
|
||||
base::mac::ScopedSendingEvent sendingEventScoper;
|
||||
|
||||
// Don't emit unresponsive event when showing menu.
|
||||
atom::UnresponsiveSuppressor suppressor;
|
||||
|
||||
// Show the menu.
|
||||
[menu popUpMenuPositioningItem:item atLocation:position inView:view];
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MenuMac::OnClosed(int32_t window_id, base::Closure callback) {
|
||||
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_);
|
||||
|
||||
@@ -6,70 +6,51 @@
|
||||
|
||||
#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;
|
||||
#include "ui/views/controls/menu/menu_runner.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
MenuViews::MenuViews(v8::Isolate* isolate, v8::Local<v8::Object> wrapper)
|
||||
: Menu(isolate, wrapper), weak_factory_(this) {}
|
||||
: Menu(isolate, wrapper) {
|
||||
}
|
||||
|
||||
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) {
|
||||
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;
|
||||
|
||||
// Don't emit unresponsive event when showing menu.
|
||||
atom::UnresponsiveSuppressor suppressor;
|
||||
|
||||
// Show the menu.
|
||||
int32_t window_id = window->weak_map_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);
|
||||
}
|
||||
|
||||
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();
|
||||
views::MenuRunner menu_runner(
|
||||
model(),
|
||||
views::MenuRunner::CONTEXT_MENU | views::MenuRunner::HAS_MNEMONICS);
|
||||
ignore_result(menu_runner.RunMenuAt(
|
||||
static_cast<NativeWindowViews*>(window->window())->widget(),
|
||||
NULL,
|
||||
gfx::Rect(location, gfx::Size()),
|
||||
views::MENU_ANCHOR_TOPLEFT,
|
||||
ui::MENU_SOURCE_MOUSE));
|
||||
}
|
||||
|
||||
// static
|
||||
|
||||
@@ -5,12 +5,8 @@
|
||||
#ifndef ATOM_BROWSER_API_ATOM_API_MENU_VIEWS_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_MENU_VIEWS_H_
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "atom/browser/api/atom_api_menu.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "ui/display/screen.h"
|
||||
#include "ui/views/controls/menu/menu_runner.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
@@ -19,24 +15,11 @@ 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 ClosePopupAt(int32_t window_id) override;
|
||||
void PopupAt(Window* window, int x, int y, int positioning_item) 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_;
|
||||
|
||||
base::WeakPtrFactory<MenuViews> weak_factory_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(MenuViews);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
// Copyright (c) 2016 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.h"
|
||||
#include "atom/browser/api/atom_api_url_request.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
Net::Net(v8::Isolate* isolate) {
|
||||
Init(isolate);
|
||||
}
|
||||
|
||||
Net::~Net() {}
|
||||
|
||||
// static
|
||||
v8::Local<v8::Value> Net::Create(v8::Isolate* isolate) {
|
||||
return mate::CreateHandle(isolate, new Net(isolate)).ToV8();
|
||||
}
|
||||
|
||||
// static
|
||||
void Net::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "Net"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetProperty("URLRequest", &Net::URLRequest);
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> Net::URLRequest(v8::Isolate* isolate) {
|
||||
return URLRequest::GetConstructor(isolate)->GetFunction();
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
namespace {
|
||||
|
||||
using atom::api::Net;
|
||||
using atom::api::URLRequest;
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
|
||||
URLRequest::SetConstructor(isolate, base::Bind(URLRequest::New));
|
||||
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("net", Net::Create(isolate));
|
||||
dict.Set("Net", Net::GetConstructor(isolate)->GetFunction());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_net, Initialize)
|
||||
@@ -1,35 +0,0 @@
|
||||
// Copyright (c) 2016 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_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_NET_H_
|
||||
|
||||
#include "atom/browser/api/event_emitter.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class Net : public mate::EventEmitter<Net> {
|
||||
public:
|
||||
static v8::Local<v8::Value> Create(v8::Isolate* isolate);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
v8::Local<v8::Value> URLRequest(v8::Isolate* isolate);
|
||||
|
||||
protected:
|
||||
explicit Net(v8::Isolate* isolate);
|
||||
~Net() override;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(Net);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_NET_H_
|
||||
@@ -1,90 +0,0 @@
|
||||
// Copyright (c) 2018 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_net_log.h"
|
||||
#include "atom/browser/atom_browser_client.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/file_path_converter.h"
|
||||
#include "base/callback.h"
|
||||
#include "content/public/common/content_switches.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/handle.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
NetLog::NetLog(v8::Isolate* isolate) {
|
||||
Init(isolate);
|
||||
|
||||
net_log_ = atom::AtomBrowserClient::Get()->GetNetLog();
|
||||
}
|
||||
|
||||
NetLog::~NetLog() {}
|
||||
|
||||
// static
|
||||
v8::Local<v8::Value> NetLog::Create(v8::Isolate* isolate) {
|
||||
return mate::CreateHandle(isolate, new NetLog(isolate)).ToV8();
|
||||
}
|
||||
|
||||
void NetLog::StartLogging(mate::Arguments* args) {
|
||||
base::FilePath log_path;
|
||||
if (!args->GetNext(&log_path) || log_path.empty()) {
|
||||
args->ThrowError("The first parameter must be a valid string");
|
||||
return;
|
||||
}
|
||||
|
||||
net_log_->StartDynamicLogging(log_path);
|
||||
}
|
||||
|
||||
bool NetLog::IsCurrentlyLogging() {
|
||||
return net_log_->IsDynamicLogging();
|
||||
}
|
||||
|
||||
base::FilePath::StringType NetLog::GetCurrentlyLoggingPath() {
|
||||
return net_log_->GetDynamicLoggingPath().value();
|
||||
}
|
||||
|
||||
void NetLog::StopLogging(mate::Arguments* args) {
|
||||
base::OnceClosure callback;
|
||||
args->GetNext(&callback);
|
||||
|
||||
net_log_->StopDynamicLogging(std::move(callback));
|
||||
}
|
||||
|
||||
// static
|
||||
void NetLog::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "NetLog"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetProperty("currentlyLogging", &NetLog::IsCurrentlyLogging)
|
||||
.SetProperty("currentlyLoggingPath", &NetLog::GetCurrentlyLoggingPath)
|
||||
.SetMethod("startLogging", &NetLog::StartLogging)
|
||||
.SetMethod("_stopLogging", &NetLog::StopLogging);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
namespace {
|
||||
|
||||
using atom::api::NetLog;
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("netLog", NetLog::Create(isolate));
|
||||
dict.Set("NetLog", NetLog::GetConstructor(isolate)->GetFunction());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_net_log, Initialize)
|
||||
@@ -1,42 +0,0 @@
|
||||
// Copyright (c) 2018 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_API_ATOM_API_NET_LOG_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_NET_LOG_H_
|
||||
|
||||
#include <string>
|
||||
#include "brightray/browser/net_log.h"
|
||||
#include "native_mate/wrappable.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class NetLog : public mate::Wrappable<NetLog> {
|
||||
public:
|
||||
static v8::Local<v8::Value> Create(v8::Isolate* isolate);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
void StartLogging(mate::Arguments* args);
|
||||
bool IsCurrentlyLogging();
|
||||
base::FilePath::StringType GetCurrentlyLoggingPath();
|
||||
void StopLogging(mate::Arguments* args);
|
||||
|
||||
protected:
|
||||
explicit NetLog(v8::Isolate* isolate);
|
||||
~NetLog() override;
|
||||
|
||||
private:
|
||||
brightray::NetLog* net_log_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(NetLog);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_NET_LOG_H_
|
||||
@@ -1,272 +0,0 @@
|
||||
// Copyright (c) 2014 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_notification.h"
|
||||
|
||||
#include "atom/browser/api/atom_api_menu.h"
|
||||
#include "atom/browser/browser.h"
|
||||
#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 "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 <>
|
||||
struct Converter<brightray::NotificationAction> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
brightray::NotificationAction* out) {
|
||||
mate::Dictionary dict;
|
||||
if (!ConvertFromV8(isolate, val, &dict))
|
||||
return false;
|
||||
|
||||
if (!dict.Get("type", &(out->type))) {
|
||||
return false;
|
||||
}
|
||||
dict.Get("text", &(out->text));
|
||||
return true;
|
||||
}
|
||||
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
brightray::NotificationAction val) {
|
||||
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
|
||||
dict.Set("text", val.text);
|
||||
dict.Set("type", val.type);
|
||||
return dict.GetHandle();
|
||||
}
|
||||
};
|
||||
} // namespace mate
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
Notification::Notification(v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> wrapper,
|
||||
mate::Arguments* args) {
|
||||
InitWith(isolate, wrapper);
|
||||
|
||||
presenter_ = brightray::BrowserClient::Get()->GetNotificationPresenter();
|
||||
|
||||
mate::Dictionary opts;
|
||||
if (args->GetNext(&opts)) {
|
||||
opts.Get("title", &title_);
|
||||
opts.Get("subtitle", &subtitle_);
|
||||
opts.Get("body", &body_);
|
||||
has_icon_ = opts.Get("icon", &icon_);
|
||||
if (has_icon_) {
|
||||
opts.Get("icon", &icon_path_);
|
||||
}
|
||||
opts.Get("silent", &silent_);
|
||||
opts.Get("replyPlaceholder", &reply_placeholder_);
|
||||
opts.Get("hasReply", &has_reply_);
|
||||
opts.Get("actions", &actions_);
|
||||
opts.Get("sound", &sound_);
|
||||
opts.Get("closeButtonText", &close_button_text_);
|
||||
}
|
||||
}
|
||||
|
||||
Notification::~Notification() {
|
||||
if (notification_)
|
||||
notification_->set_delegate(nullptr);
|
||||
}
|
||||
|
||||
// static
|
||||
mate::WrappableBase* Notification::New(mate::Arguments* args) {
|
||||
if (!Browser::Get()->is_ready()) {
|
||||
args->ThrowError("Cannot create Notification before app is ready");
|
||||
return nullptr;
|
||||
}
|
||||
return new Notification(args->isolate(), args->GetThis(), args);
|
||||
}
|
||||
|
||||
// Getters
|
||||
base::string16 Notification::GetTitle() const {
|
||||
return title_;
|
||||
}
|
||||
|
||||
base::string16 Notification::GetSubtitle() const {
|
||||
return subtitle_;
|
||||
}
|
||||
|
||||
base::string16 Notification::GetBody() const {
|
||||
return body_;
|
||||
}
|
||||
|
||||
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_;
|
||||
}
|
||||
|
||||
std::vector<brightray::NotificationAction> Notification::GetActions() const {
|
||||
return actions_;
|
||||
}
|
||||
|
||||
base::string16 Notification::GetCloseButtonText() const {
|
||||
return close_button_text_;
|
||||
}
|
||||
|
||||
// Setters
|
||||
void Notification::SetTitle(const base::string16& new_title) {
|
||||
title_ = new_title;
|
||||
}
|
||||
|
||||
void Notification::SetSubtitle(const base::string16& new_subtitle) {
|
||||
subtitle_ = new_subtitle;
|
||||
}
|
||||
|
||||
void Notification::SetBody(const base::string16& new_body) {
|
||||
body_ = new_body;
|
||||
}
|
||||
|
||||
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::SetActions(
|
||||
const std::vector<brightray::NotificationAction>& actions) {
|
||||
actions_ = actions;
|
||||
}
|
||||
|
||||
void Notification::SetCloseButtonText(const base::string16& text) {
|
||||
close_button_text_ = text;
|
||||
}
|
||||
|
||||
void Notification::NotificationAction(int index) {
|
||||
Emit("action", index);
|
||||
}
|
||||
|
||||
void Notification::NotificationClick() {
|
||||
Emit("click");
|
||||
}
|
||||
|
||||
void Notification::NotificationReplied(const std::string& reply) {
|
||||
Emit("reply", reply);
|
||||
}
|
||||
|
||||
void Notification::NotificationDisplayed() {
|
||||
Emit("show");
|
||||
}
|
||||
|
||||
void Notification::NotificationDestroyed() {}
|
||||
|
||||
void Notification::NotificationClosed() {
|
||||
Emit("close");
|
||||
}
|
||||
|
||||
void Notification::Close() {
|
||||
if (notification_) {
|
||||
notification_->Dismiss();
|
||||
notification_.reset();
|
||||
}
|
||||
}
|
||||
|
||||
// Showing notifications
|
||||
void Notification::Show() {
|
||||
Close();
|
||||
if (presenter_) {
|
||||
notification_ = presenter_->CreateNotification(this, base::GenerateGUID());
|
||||
if (notification_) {
|
||||
brightray::NotificationOptions options;
|
||||
options.title = title_;
|
||||
options.subtitle = subtitle_;
|
||||
options.msg = body_;
|
||||
options.icon_url = GURL();
|
||||
options.icon = icon_.AsBitmap();
|
||||
options.silent = silent_;
|
||||
options.has_reply = has_reply_;
|
||||
options.reply_placeholder = reply_placeholder_;
|
||||
options.actions = actions_;
|
||||
options.sound = sound_;
|
||||
options.close_button_text = close_button_text_;
|
||||
notification_->Show(options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Notification::IsSupported() {
|
||||
return !!brightray::BrowserClient::Get()->GetNotificationPresenter();
|
||||
}
|
||||
|
||||
// static
|
||||
void Notification::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "Notification"));
|
||||
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("actions", &Notification::GetActions,
|
||||
&Notification::SetActions)
|
||||
.SetProperty("closeButtonText", &Notification::GetCloseButtonText,
|
||||
&Notification::SetCloseButtonText);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
namespace {
|
||||
|
||||
using atom::api::Notification;
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
Notification::SetConstructor(isolate, base::Bind(&Notification::New));
|
||||
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("Notification",
|
||||
Notification::GetConstructor(isolate)->GetFunction());
|
||||
|
||||
dict.SetMethod("isSupported", &Notification::IsSupported);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_common_notification, Initialize)
|
||||
@@ -1,97 +0,0 @@
|
||||
// Copyright (c) 2014 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_NOTIFICATION_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_NOTIFICATION_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "brightray/browser/notification.h"
|
||||
#include "brightray/browser/notification_delegate.h"
|
||||
#include "brightray/browser/notification_presenter.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "ui/gfx/image/image.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class Notification : public mate::TrackableObject<Notification>,
|
||||
public brightray::NotificationDelegate {
|
||||
public:
|
||||
static mate::WrappableBase* New(mate::Arguments* args);
|
||||
static bool IsSupported();
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
// NotificationDelegate:
|
||||
void NotificationAction(int index) override;
|
||||
void NotificationClick() override;
|
||||
void NotificationReplied(const std::string& reply) override;
|
||||
void NotificationDisplayed() override;
|
||||
void NotificationDestroyed() override;
|
||||
void NotificationClosed() override;
|
||||
|
||||
protected:
|
||||
Notification(v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> wrapper,
|
||||
mate::Arguments* args);
|
||||
~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;
|
||||
std::vector<brightray::NotificationAction> GetActions() const;
|
||||
base::string16 GetCloseButtonText() 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 SetActions(const std::vector<brightray::NotificationAction>& actions);
|
||||
void SetCloseButtonText(const base::string16& text);
|
||||
|
||||
private:
|
||||
base::string16 title_;
|
||||
base::string16 subtitle_;
|
||||
base::string16 body_;
|
||||
gfx::Image icon_;
|
||||
base::string16 icon_path_;
|
||||
bool has_icon_ = false;
|
||||
bool silent_ = false;
|
||||
bool has_reply_ = false;
|
||||
base::string16 reply_placeholder_;
|
||||
base::string16 sound_;
|
||||
std::vector<brightray::NotificationAction> actions_;
|
||||
base::string16 close_button_text_;
|
||||
|
||||
brightray::NotificationPresenter* presenter_;
|
||||
|
||||
base::WeakPtr<brightray::Notification> notification_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Notification);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_NOTIFICATION_H_
|
||||
@@ -5,70 +5,24 @@
|
||||
#include "atom/browser/api/atom_api_power_monitor.h"
|
||||
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/node_includes.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,27 +38,12 @@ 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()) {
|
||||
isolate->ThrowException(v8::Exception::Error(mate::StringToV8(
|
||||
isolate,
|
||||
"Cannot require \"powerMonitor\" module before app is ready")));
|
||||
"Cannot initialize \"power-monitor\" module before app is ready")));
|
||||
return v8::Null(isolate);
|
||||
}
|
||||
|
||||
@@ -112,32 +51,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 +80,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)
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -1,71 +0,0 @@
|
||||
// Copyright (c) 2013 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_power_monitor.h"
|
||||
|
||||
#include "base/win/wrapped_window_proc.h"
|
||||
#include "ui/base/win/shell.h"
|
||||
#include "ui/gfx/win/hwnd_util.h"
|
||||
#include "Wtsapi32.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
const wchar_t kPowerMonitorWindowClass[] =
|
||||
L"Electron_PowerMonitorHostWindow";
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace api {
|
||||
|
||||
void PowerMonitor::InitPlatformSpecificMonitors() {
|
||||
WNDCLASSEX window_class;
|
||||
base::win::InitializeWindowClass(
|
||||
kPowerMonitorWindowClass,
|
||||
&base::win::WrappedWindowProc<PowerMonitor::WndProcStatic>, 0, 0, 0,
|
||||
NULL, NULL, NULL, NULL, NULL, &window_class);
|
||||
instance_ = window_class.hInstance;
|
||||
atom_ = RegisterClassEx(&window_class);
|
||||
|
||||
// Create an offscreen window for receiving broadcast messages for the
|
||||
// session lock and unlock events.
|
||||
window_ = CreateWindow(MAKEINTATOM(atom_), 0, 0, 0, 0, 0, 0, HWND_MESSAGE, 0,
|
||||
instance_, 0);
|
||||
gfx::CheckWindowCreated(window_);
|
||||
gfx::SetWindowUserData(window_, this);
|
||||
|
||||
// Tel windows we want to be notified with session events
|
||||
WTSRegisterSessionNotification(window_, NOTIFY_FOR_THIS_SESSION);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK PowerMonitor::WndProcStatic(HWND hwnd,
|
||||
UINT message,
|
||||
WPARAM wparam,
|
||||
LPARAM lparam) {
|
||||
PowerMonitor* msg_wnd = reinterpret_cast<PowerMonitor*>(
|
||||
GetWindowLongPtr(hwnd, GWLP_USERDATA));
|
||||
if (msg_wnd)
|
||||
return msg_wnd->WndProc(hwnd, message, wparam, lparam);
|
||||
else
|
||||
return ::DefWindowProc(hwnd, message, wparam, lparam);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK PowerMonitor::WndProc(HWND hwnd,
|
||||
UINT message,
|
||||
WPARAM wparam,
|
||||
LPARAM lparam) {
|
||||
if (message == WM_WTSSESSION_CHANGE) {
|
||||
if (wparam == WTS_SESSION_LOCK) {
|
||||
Emit("lock-screen");
|
||||
} else if (wparam == WTS_SESSION_UNLOCK) {
|
||||
Emit("unlock-screen");
|
||||
}
|
||||
}
|
||||
return ::DefWindowProc(hwnd, message, wparam, lparam);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
@@ -6,26 +6,25 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/task_scheduler/post_task.h"
|
||||
#include "base/threading/thread_task_runner_handle.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "content/public/browser/power_save_blocker.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
namespace mate {
|
||||
|
||||
template <>
|
||||
struct Converter<device::mojom::WakeLockType> {
|
||||
template<>
|
||||
struct Converter<content::PowerSaveBlocker::PowerSaveBlockerType> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
device::mojom::WakeLockType* out) {
|
||||
content::PowerSaveBlocker::PowerSaveBlockerType* out) {
|
||||
using content::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 +39,12 @@ namespace api {
|
||||
|
||||
PowerSaveBlocker::PowerSaveBlocker(v8::Isolate* isolate)
|
||||
: current_blocker_type_(
|
||||
device::mojom::WakeLockType::kPreventAppSuspension) {
|
||||
content::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension) {
|
||||
Init(isolate);
|
||||
}
|
||||
|
||||
PowerSaveBlocker::~PowerSaveBlocker() {}
|
||||
PowerSaveBlocker::~PowerSaveBlocker() {
|
||||
}
|
||||
|
||||
void PowerSaveBlocker::UpdatePowerSaveBlocker() {
|
||||
if (power_save_blocker_types_.empty()) {
|
||||
@@ -52,39 +52,36 @@ 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;
|
||||
content::PowerSaveBlocker::PowerSaveBlockerType new_blocker_type =
|
||||
content::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension;
|
||||
for (const auto& element : power_save_blocker_types_) {
|
||||
if (element.second ==
|
||||
device::mojom::WakeLockType::kPreventDisplaySleep) {
|
||||
content::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep) {
|
||||
new_blocker_type =
|
||||
device::mojom::WakeLockType::kPreventDisplaySleep;
|
||||
content::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<content::PowerSaveBlocker> new_blocker =
|
||||
content::PowerSaveBlocker::Create(
|
||||
new_blocker_type,
|
||||
content::PowerSaveBlocker::kReasonOther,
|
||||
ATOM_PRODUCT_NAME);
|
||||
power_save_blocker_.swap(new_blocker);
|
||||
current_blocker_type_ = new_blocker_type;
|
||||
}
|
||||
}
|
||||
|
||||
int PowerSaveBlocker::Start(device::mojom::WakeLockType type) {
|
||||
int PowerSaveBlocker::Start(
|
||||
content::PowerSaveBlocker::PowerSaveBlockerType type) {
|
||||
static int count = 0;
|
||||
power_save_blocker_types_[count] = type;
|
||||
UpdatePowerSaveBlocker();
|
||||
@@ -108,8 +105,7 @@ mate::Handle<PowerSaveBlocker> PowerSaveBlocker::Create(v8::Isolate* isolate) {
|
||||
|
||||
// static
|
||||
void PowerSaveBlocker::BuildPrototype(
|
||||
v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "PowerSaveBlocker"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetMethod("start", &PowerSaveBlocker::Start)
|
||||
@@ -123,10 +119,8 @@ void PowerSaveBlocker::BuildPrototype(
|
||||
|
||||
namespace {
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("powerSaveBlocker", atom::api::PowerSaveBlocker::Create(isolate));
|
||||
@@ -134,4 +128,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);
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
#include <memory>
|
||||
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "content/public/browser/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(content::PowerSaveBlocker::PowerSaveBlockerType type);
|
||||
bool Stop(int id);
|
||||
bool IsStarted(int id);
|
||||
|
||||
std::unique_ptr<device::PowerSaveBlocker> power_save_blocker_;
|
||||
std::unique_ptr<content::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_|
|
||||
content::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, content::PowerSaveBlocker::PowerSaveBlockerType>;
|
||||
PowerSaveBlockerTypeMap power_save_blocker_types_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PowerSaveBlocker);
|
||||
};
|
||||
|
||||
@@ -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,69 +32,67 @@ 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() {
|
||||
return g_standard_schemes;
|
||||
}
|
||||
|
||||
void RegisterStandardSchemes(const std::vector<std::string>& schemes,
|
||||
mate::Arguments* args) {
|
||||
void RegisterStandardSchemes(const std::vector<std::string>& schemes) {
|
||||
g_standard_schemes = schemes;
|
||||
|
||||
mate::Dictionary opts;
|
||||
bool secure = false;
|
||||
args->GetNext(&opts) && opts.Get("secure", &secure);
|
||||
|
||||
// Dynamically register the schemes.
|
||||
auto* policy = content::ChildProcessSecurityPolicy::GetInstance();
|
||||
for (const std::string& scheme : schemes) {
|
||||
url::AddStandardScheme(scheme.c_str(), url::SCHEME_WITHOUT_PORT);
|
||||
if (secure) {
|
||||
url::AddSecureScheme(scheme.c_str());
|
||||
}
|
||||
policy->RegisterWebSafeScheme(scheme);
|
||||
}
|
||||
|
||||
// Add the schemes to command line switches, so child processes can also
|
||||
// register them.
|
||||
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
|
||||
atom::switches::kStandardSchemes, base::JoinString(schemes, ","));
|
||||
if (secure) {
|
||||
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
|
||||
atom::switches::kSecureSchemes, base::JoinString(schemes, ","));
|
||||
}
|
||||
}
|
||||
|
||||
Protocol::Protocol(v8::Isolate* isolate, AtomBrowserContext* browser_context)
|
||||
: browser_context_(browser_context), weak_factory_(this) {
|
||||
: request_context_getter_(browser_context->GetRequestContext()),
|
||||
weak_factory_(this) {
|
||||
Init(isolate);
|
||||
}
|
||||
|
||||
Protocol::~Protocol() {}
|
||||
Protocol::~Protocol() {
|
||||
content::BrowserThread::PostTask(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(ClearJobFactoryInIO, request_context_getter_));
|
||||
}
|
||||
|
||||
void Protocol::RegisterServiceWorkerSchemes(
|
||||
const std::vector<std::string>& schemes) {
|
||||
atom::AtomBrowserClient::SetCustomServiceWorkerSchemes(schemes);
|
||||
}
|
||||
|
||||
void Protocol::UnregisterProtocol(const std::string& scheme,
|
||||
mate::Arguments* args) {
|
||||
void Protocol::UnregisterProtocol(
|
||||
const std::string& scheme, mate::Arguments* args) {
|
||||
CompletionCallback callback;
|
||||
args->GetNext(&callback);
|
||||
auto* getter = browser_context_->GetRequestContext();
|
||||
content::BrowserThread::PostTaskAndReplyWithResult(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::BindOnce(&Protocol::UnregisterProtocolInIO,
|
||||
base::RetainedRef(getter), scheme),
|
||||
base::BindOnce(&Protocol::OnIOCompleted, GetWeakPtr(), callback));
|
||||
base::Bind(&Protocol::UnregisterProtocolInIO,
|
||||
request_context_getter_, scheme),
|
||||
base::Bind(&Protocol::OnIOCompleted,
|
||||
GetWeakPtr(), callback));
|
||||
}
|
||||
|
||||
// static
|
||||
Protocol::ProtocolError Protocol::UnregisterProtocolInIO(
|
||||
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter,
|
||||
const std::string& scheme) {
|
||||
auto* job_factory = static_cast<AtomURLRequestJobFactory*>(
|
||||
auto job_factory = static_cast<AtomURLRequestJobFactory*>(
|
||||
request_context_getter->job_factory());
|
||||
if (!job_factory->HasProtocolHandler(scheme))
|
||||
return PROTOCOL_NOT_REGISTERED;
|
||||
@@ -105,11 +102,10 @@ Protocol::ProtocolError Protocol::UnregisterProtocolInIO(
|
||||
|
||||
void Protocol::IsProtocolHandled(const std::string& scheme,
|
||||
const BooleanCallback& callback) {
|
||||
auto* getter = browser_context_->GetRequestContext();
|
||||
content::BrowserThread::PostTaskAndReplyWithResult(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&Protocol::IsProtocolHandledInIO, base::RetainedRef(getter),
|
||||
scheme),
|
||||
base::Bind(&Protocol::IsProtocolHandledInIO,
|
||||
request_context_getter_, scheme),
|
||||
callback);
|
||||
}
|
||||
|
||||
@@ -120,16 +116,16 @@ bool Protocol::IsProtocolHandledInIO(
|
||||
return request_context_getter->job_factory()->IsHandledProtocol(scheme);
|
||||
}
|
||||
|
||||
void Protocol::UninterceptProtocol(const std::string& scheme,
|
||||
mate::Arguments* args) {
|
||||
void Protocol::UninterceptProtocol(
|
||||
const std::string& scheme, mate::Arguments* args) {
|
||||
CompletionCallback callback;
|
||||
args->GetNext(&callback);
|
||||
auto* getter = browser_context_->GetRequestContext();
|
||||
content::BrowserThread::PostTaskAndReplyWithResult(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::BindOnce(&Protocol::UninterceptProtocolInIO,
|
||||
base::RetainedRef(getter), scheme),
|
||||
base::BindOnce(&Protocol::OnIOCompleted, GetWeakPtr(), callback));
|
||||
base::Bind(&Protocol::UninterceptProtocolInIO,
|
||||
request_context_getter_, scheme),
|
||||
base::Bind(&Protocol::OnIOCompleted,
|
||||
GetWeakPtr(), callback));
|
||||
}
|
||||
|
||||
// static
|
||||
@@ -137,14 +133,12 @@ Protocol::ProtocolError Protocol::UninterceptProtocolInIO(
|
||||
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter,
|
||||
const std::string& scheme) {
|
||||
return static_cast<AtomURLRequestJobFactory*>(
|
||||
request_context_getter->job_factory())
|
||||
->UninterceptProtocol(scheme)
|
||||
? PROTOCOL_OK
|
||||
: PROTOCOL_NOT_INTERCEPTED;
|
||||
request_context_getter->job_factory())->UninterceptProtocol(scheme) ?
|
||||
PROTOCOL_OK : PROTOCOL_NOT_INTERCEPTED;
|
||||
}
|
||||
|
||||
void Protocol::OnIOCompleted(const CompletionCallback& callback,
|
||||
ProtocolError error) {
|
||||
void Protocol::OnIOCompleted(
|
||||
const CompletionCallback& callback, ProtocolError error) {
|
||||
// The completion callback is optional.
|
||||
if (callback.is_null())
|
||||
return;
|
||||
@@ -162,30 +156,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 +193,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 +203,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 +212,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);
|
||||
atom::api::RegisterStandardSchemes(schemes);
|
||||
}
|
||||
|
||||
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 +233,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)
|
||||
|
||||
@@ -29,8 +29,7 @@ namespace atom {
|
||||
namespace api {
|
||||
|
||||
std::vector<std::string> GetStandardSchemes();
|
||||
void RegisterStandardSchemes(const std::vector<std::string>& schemes,
|
||||
mate::Arguments* args);
|
||||
void RegisterStandardSchemes(const std::vector<std::string>& schemes);
|
||||
|
||||
class Protocol : public mate::TrackableObject<Protocol> {
|
||||
public:
|
||||
@@ -39,20 +38,20 @@ class Protocol : public mate::TrackableObject<Protocol> {
|
||||
using CompletionCallback = base::Callback<void(v8::Local<v8::Value>)>;
|
||||
using BooleanCallback = base::Callback<void(bool)>;
|
||||
|
||||
static mate::Handle<Protocol> Create(v8::Isolate* isolate,
|
||||
AtomBrowserContext* browser_context);
|
||||
static mate::Handle<Protocol> Create(
|
||||
v8::Isolate* isolate, AtomBrowserContext* browser_context);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
protected:
|
||||
Protocol(v8::Isolate* isolate, AtomBrowserContext* browser_context);
|
||||
~Protocol() override;
|
||||
~Protocol();
|
||||
|
||||
private:
|
||||
// Possible errors.
|
||||
enum ProtocolError {
|
||||
PROTOCOL_OK, // no error
|
||||
PROTOCOL_OK, // no error
|
||||
PROTOCOL_FAIL, // operation failed, should never occur
|
||||
PROTOCOL_REGISTERED,
|
||||
PROTOCOL_NOT_REGISTERED,
|
||||
@@ -62,13 +61,14 @@ class Protocol : public mate::TrackableObject<Protocol> {
|
||||
|
||||
// The protocol handler that will create a protocol handler for certain
|
||||
// request job.
|
||||
template <typename RequestJob>
|
||||
template<typename RequestJob>
|
||||
class CustomProtocolHandler
|
||||
: public net::URLRequestJobFactory::ProtocolHandler {
|
||||
public:
|
||||
CustomProtocolHandler(v8::Isolate* isolate,
|
||||
net::URLRequestContextGetter* request_context,
|
||||
const Handler& handler)
|
||||
CustomProtocolHandler(
|
||||
v8::Isolate* isolate,
|
||||
net::URLRequestContextGetter* request_context,
|
||||
const Handler& handler)
|
||||
: isolate_(isolate),
|
||||
request_context_(request_context),
|
||||
handler_(handler) {}
|
||||
@@ -78,13 +78,13 @@ class Protocol : public mate::TrackableObject<Protocol> {
|
||||
net::URLRequest* request,
|
||||
net::NetworkDelegate* network_delegate) const override {
|
||||
RequestJob* request_job = new RequestJob(request, network_delegate);
|
||||
request_job->SetHandlerInfo(isolate_, request_context_, handler_);
|
||||
request_job->SetHandlerInfo(isolate_, request_context_.get(), handler_);
|
||||
return request_job;
|
||||
}
|
||||
|
||||
private:
|
||||
v8::Isolate* isolate_;
|
||||
net::URLRequestContextGetter* request_context_;
|
||||
scoped_refptr<net::URLRequestContextGetter> request_context_;
|
||||
Protocol::Handler handler_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CustomProtocolHandler);
|
||||
@@ -94,31 +94,32 @@ class Protocol : public mate::TrackableObject<Protocol> {
|
||||
void RegisterServiceWorkerSchemes(const std::vector<std::string>& schemes);
|
||||
|
||||
// Register the protocol with certain request job.
|
||||
template <typename RequestJob>
|
||||
template<typename RequestJob>
|
||||
void RegisterProtocol(const std::string& scheme,
|
||||
const Handler& handler,
|
||||
mate::Arguments* args) {
|
||||
CompletionCallback callback;
|
||||
args->GetNext(&callback);
|
||||
auto* getter = browser_context_->GetRequestContext();
|
||||
content::BrowserThread::PostTaskAndReplyWithResult(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::BindOnce(&Protocol::RegisterProtocolInIO<RequestJob>,
|
||||
base::RetainedRef(getter), isolate(), scheme, handler),
|
||||
base::BindOnce(&Protocol::OnIOCompleted, GetWeakPtr(), callback));
|
||||
base::Bind(&Protocol::RegisterProtocolInIO<RequestJob>,
|
||||
request_context_getter_, isolate(), scheme, handler),
|
||||
base::Bind(&Protocol::OnIOCompleted,
|
||||
GetWeakPtr(), callback));
|
||||
}
|
||||
template <typename RequestJob>
|
||||
template<typename RequestJob>
|
||||
static ProtocolError RegisterProtocolInIO(
|
||||
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter,
|
||||
v8::Isolate* isolate,
|
||||
const std::string& scheme,
|
||||
const Handler& handler) {
|
||||
auto* job_factory = static_cast<AtomURLRequestJobFactory*>(
|
||||
auto job_factory = static_cast<AtomURLRequestJobFactory*>(
|
||||
request_context_getter->job_factory());
|
||||
if (job_factory->IsHandledProtocol(scheme))
|
||||
return PROTOCOL_REGISTERED;
|
||||
auto protocol_handler = std::make_unique<CustomProtocolHandler<RequestJob>>(
|
||||
isolate, request_context_getter.get(), handler);
|
||||
std::unique_ptr<CustomProtocolHandler<RequestJob>> protocol_handler(
|
||||
new CustomProtocolHandler<RequestJob>(
|
||||
isolate, request_context_getter.get(), handler));
|
||||
if (job_factory->SetProtocolHandler(scheme, std::move(protocol_handler)))
|
||||
return PROTOCOL_OK;
|
||||
else
|
||||
@@ -139,34 +140,35 @@ class Protocol : public mate::TrackableObject<Protocol> {
|
||||
const std::string& scheme);
|
||||
|
||||
// Replace the protocol handler with a new one.
|
||||
template <typename RequestJob>
|
||||
template<typename RequestJob>
|
||||
void InterceptProtocol(const std::string& scheme,
|
||||
const Handler& handler,
|
||||
mate::Arguments* args) {
|
||||
CompletionCallback callback;
|
||||
args->GetNext(&callback);
|
||||
auto* getter = browser_context_->GetRequestContext();
|
||||
content::BrowserThread::PostTaskAndReplyWithResult(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::BindOnce(&Protocol::InterceptProtocolInIO<RequestJob>,
|
||||
base::RetainedRef(getter), isolate(), scheme, handler),
|
||||
base::BindOnce(&Protocol::OnIOCompleted, GetWeakPtr(), callback));
|
||||
base::Bind(&Protocol::InterceptProtocolInIO<RequestJob>,
|
||||
request_context_getter_, isolate(), scheme, handler),
|
||||
base::Bind(&Protocol::OnIOCompleted,
|
||||
GetWeakPtr(), callback));
|
||||
}
|
||||
template <typename RequestJob>
|
||||
template<typename RequestJob>
|
||||
static ProtocolError InterceptProtocolInIO(
|
||||
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter,
|
||||
v8::Isolate* isolate,
|
||||
const std::string& scheme,
|
||||
const Handler& handler) {
|
||||
auto* job_factory = static_cast<AtomURLRequestJobFactory*>(
|
||||
auto job_factory = static_cast<AtomURLRequestJobFactory*>(
|
||||
request_context_getter->job_factory());
|
||||
if (!job_factory->IsHandledProtocol(scheme))
|
||||
return PROTOCOL_NOT_REGISTERED;
|
||||
// It is possible a protocol is handled but can not be intercepted.
|
||||
if (!job_factory->HasProtocolHandler(scheme))
|
||||
return PROTOCOL_FAIL;
|
||||
auto protocol_handler = std::make_unique<CustomProtocolHandler<RequestJob>>(
|
||||
isolate, request_context_getter.get(), handler);
|
||||
std::unique_ptr<CustomProtocolHandler<RequestJob>> protocol_handler(
|
||||
new CustomProtocolHandler<RequestJob>(
|
||||
isolate, request_context_getter.get(), handler));
|
||||
if (!job_factory->InterceptProtocol(scheme, std::move(protocol_handler)))
|
||||
return PROTOCOL_INTERCEPTED;
|
||||
return PROTOCOL_OK;
|
||||
@@ -184,9 +186,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);
|
||||
|
||||
@@ -7,12 +7,11 @@
|
||||
#include "atom/browser/api/atom_api_web_contents.h"
|
||||
#include "atom/browser/atom_browser_client.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/object_template_builder.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
@@ -21,8 +20,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 +40,8 @@ RenderProcessPreferences::RenderProcessPreferences(
|
||||
Init(isolate);
|
||||
}
|
||||
|
||||
RenderProcessPreferences::~RenderProcessPreferences() {}
|
||||
RenderProcessPreferences::~RenderProcessPreferences() {
|
||||
}
|
||||
|
||||
int RenderProcessPreferences::AddEntry(const base::DictionaryValue& entry) {
|
||||
return preferences_.AddEntry(entry);
|
||||
@@ -53,8 +53,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 +64,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 +76,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 +85,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)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user