mirror of
https://github.com/electron/electron.git
synced 2026-02-19 03:14:51 -05:00
Compare commits
2 Commits
v3.1.0-bet
...
v0.34.4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cb5273731f | ||
|
|
aa40c6c260 |
@@ -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!
|
||||
58
.gitignore
vendored
58
.gitignore
vendored
@@ -1,52 +1,20 @@
|
||||
.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_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
|
||||
debug.log
|
||||
npm-debug.log
|
||||
|
||||
21
.gitmodules
vendored
21
.gitmodules
vendored
@@ -1,27 +1,24 @@
|
||||
[submodule "vendor/brightray"]
|
||||
path = vendor/brightray
|
||||
url = https://github.com/atom/brightray.git
|
||||
[submodule "vendor/node"]
|
||||
path = vendor/node
|
||||
url = https://github.com/electron/node.git
|
||||
url = https://github.com/atom/node.git
|
||||
[submodule "vendor/depot_tools"]
|
||||
path = vendor/depot_tools
|
||||
url = https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
[submodule "vendor/breakpad"]
|
||||
path = vendor/breakpad
|
||||
url = https://github.com/electron/chromium-breakpad.git
|
||||
url = https://github.com/atom/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
|
||||
url = https://github.com/atom/crashpad.git
|
||||
[submodule "vendor/requests"]
|
||||
path = vendor/requests
|
||||
url = https://github.com/kennethreitz/requests
|
||||
[submodule "vendor/boto"]
|
||||
path = vendor/boto
|
||||
url = https://github.com/boto/boto.git
|
||||
[submodule "vendor/pdf_viewer"]
|
||||
path = vendor/pdf_viewer
|
||||
url = https://github.com/electron/pdf-viewer.git
|
||||
[submodule "vendor/gyp"]
|
||||
path = vendor/gyp
|
||||
url = https://github.com/electron/gyp
|
||||
[submodule "vendor/libchromiumcontent"]
|
||||
path = vendor/libchromiumcontent
|
||||
url = https://github.com/electron/libchromiumcontent
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"plugins": [
|
||||
["remark-lint-code-block-style", "fenced"],
|
||||
["remark-lint-fenced-code-flag"]
|
||||
]
|
||||
}
|
||||
15
.travis.yml
15
.travis.yml
@@ -3,18 +3,14 @@ git:
|
||||
notifications:
|
||||
email: false
|
||||
|
||||
before_install:
|
||||
- export BOTO_CONFIG=/dev/null
|
||||
|
||||
language: node_js
|
||||
node_js:
|
||||
- "4"
|
||||
language: cpp
|
||||
compiler: clang
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
env:
|
||||
- TARGET_ARCH=x64
|
||||
osx_image: xcode7.3
|
||||
osx_image: xcode7
|
||||
|
||||
matrix:
|
||||
include:
|
||||
@@ -22,10 +18,9 @@ matrix:
|
||||
env: TARGET_ARCH=arm
|
||||
- os: linux
|
||||
env: TARGET_ARCH=ia32
|
||||
- os: linux
|
||||
env: TARGET_ARCH=arm64
|
||||
allow_failures:
|
||||
- os: osx
|
||||
- env: TARGET_ARCH=arm
|
||||
- env: TARGET_ARCH=ia32
|
||||
|
||||
script: './script/cibuild'
|
||||
|
||||
|
||||
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,46 +0,0 @@
|
||||
# Contributor Covenant Code of Conduct:
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
||||
|
||||
## 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.
|
||||
|
||||
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]
|
||||
|
||||
[homepage]: https://contributor-covenant.org
|
||||
[version]: https://contributor-covenant.org/version/1/4/
|
||||
101
CONTRIBUTING.md
101
CONTRIBUTING.md
@@ -2,59 +2,74 @@
|
||||
|
||||
:+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.
|
||||
This project adheres to the [Contributor Covenant 1.2](http://contributor-covenant.org/version/1/2/0).
|
||||
By participating, you are expected to uphold this code. Please report unacceptable 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/atom/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/atom/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 CoffeeScript, 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
|
||||
* 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 Mac OS
|
||||
* :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':
|
||||
'29e02cd4c37777734f97d00b5a538d7c7acfa67a',
|
||||
'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
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
|
||||
|
||||
62
README-ko.md
Normal file
62
README-ko.md
Normal file
@@ -0,0 +1,62 @@
|
||||
[](http://electron.atom.io/)
|
||||
|
||||
[](https://travis-ci.org/atom/electron)
|
||||
[](https://david-dm.org/atom/electron#info=devDependencies)
|
||||
[](http://atom-slack.herokuapp.com/)
|
||||
|
||||
### [Electron](https://github.com/atom/electron/) 한국어 참조문서
|
||||
|
||||
:zap: *프레임워크 이름이 Atom Shell에서 Electron으로 변경되었습니다* :zap:
|
||||
|
||||
Electron 프레임워크는 JavaScript, HTML 그리고 CSS를 사용하여 Cross-Platform 데스크톱 어플리케이션을 개발할 수 있도록 해주는 프레임워크입니다. 이 프레임워크는 [Node.js](https://nodejs.org) 와
|
||||
[Chromium](http://www.chromium.org)을 기반으로 만들어 졌으며 [Atom Editor](https://github.com/atom/atom)에 사용되고 있습니다.
|
||||
|
||||
Electron에 대한 중요한 알림을 받고 싶다면 Twitter에서 [@ElectronJS](https://twitter.com/electronjs)를 팔로우 하세요.
|
||||
|
||||
이 프로젝트는 기여자 규약 1.2를 준수합니다. 이 프로젝트에 참여할 때 코드를 유지해야 합니다. 받아들일 수 없는 행동은 atom@github.com로 보고 하십시오.
|
||||
|
||||
## 다운로드
|
||||
|
||||
Linux, Windows, Mac용으로 미리 빌드된 Electron 바이너리와 디버그 심볼이 준비되어 있습니다. [releases](https://github.com/atom/electron/releases) 페이지에서 받아 볼 수 있습니다.
|
||||
|
||||
또한 [`npm`](https://docs.npmjs.com/)을 통해 미리 빌드된 Electron 바이너리를 받을 수도 있습니다:
|
||||
|
||||
```sh
|
||||
# $PATH에 `electron` 커맨드를 등록하고 전역에 설치합니다.
|
||||
npm install electron-prebuilt -g
|
||||
|
||||
# 개발 의존성 모듈 형태로 설치합니다.
|
||||
npm install electron-prebuilt --save-dev
|
||||
```
|
||||
|
||||
### 미러
|
||||
|
||||
- [China](https://npm.taobao.org/mirrors/electron)
|
||||
|
||||
## 참조 문서
|
||||
|
||||
[Docs](https://github.com/atom/electron/tree/master/docs/README.md)에 개발 가이드와 API 레퍼런스가 있습니다.
|
||||
Electron을 빌드 하는 방법과 프로젝트에 기여하는 방법도 문서에 포함되어 있으니 참고하시기 바랍니다.
|
||||
|
||||
## 참조 문서 (번역)
|
||||
|
||||
- [브라질 포르투칼어](https://github.com/atom/electron/tree/master/docs-translations/pt-BR)
|
||||
- [한국어](https://github.com/atom/electron/tree/master/docs-translations/ko-KR)
|
||||
- [일본어](https://github.com/atom/electron/tree/master/docs-translations/jp)
|
||||
- [스페인어](https://github.com/atom/electron/tree/master/docs-translations/es)
|
||||
- [중국어 간체](https://github.com/atom/electron/tree/master/docs-translations/zh-CN)
|
||||
- [중국어 번체](https://github.com/atom/electron/tree/master/docs-translations/zh-TW)
|
||||
|
||||
## 시작하기
|
||||
|
||||
[`atom/electron-quick-start`](https://github.com/atom/electron-quick-start) 저장소를 클론하여 Electron을 간단히 접해볼 수 있습니다.
|
||||
|
||||
## 커뮤니티
|
||||
|
||||
다음 링크를 통해 커뮤니티에 질문을 올리거나 토론을 나눌 수 있습니다:
|
||||
|
||||
- Atom 포럼의 [`electron`](http://discuss.atom.io/category/electron) 카테고리
|
||||
- Freenode 채팅의 `#atom-shell` 채널
|
||||
- Slack의 [`Atom`](http://atom-slack.herokuapp.com/) 채널
|
||||
|
||||
[awesome-electron](https://github.com/sindresorhus/awesome-electron) 프로젝트엔 커뮤니티가 운영중인 유용한 예제 어플리케이션과 도구, 리소스가 있으니 한번 참고해 보시기 바랍니다.
|
||||
117
README.md
117
README.md
@@ -1,98 +1,71 @@
|
||||
[](https://electronjs.org)
|
||||
[](http://electron.atom.io/)
|
||||
|
||||
[](https://travis-ci.org/atom/electron)
|
||||
[](https://david-dm.org/atom/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/).
|
||||
:zap: *Formerly known as Atom Shell* :zap:
|
||||
|
||||
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 in the [Atom
|
||||
editor](https://github.com/atom/atom).
|
||||
|
||||
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).
|
||||
By participating, you are expected to uphold this code. Please report unacceptable
|
||||
behavior to [coc@electronjs.org](mailto:coc@electronjs.org).
|
||||
This project adheres to the [Contributor Covenant 1.2](http://contributor-covenant.org/version/1/2/0/).
|
||||
By participating, you are expected to uphold this code. Please report
|
||||
unacceptable behavior to atom@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 OS X can
|
||||
be found on the [releases](https://github.com/atom/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-prebuilt -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-prebuilt --save-dev
|
||||
```
|
||||
|
||||
### Mirrors
|
||||
|
||||
- [China](https://npm.taobao.org/mirrors/electron)
|
||||
|
||||
## Documentation
|
||||
|
||||
Guides and the API reference are located in the
|
||||
[docs](https://github.com/atom/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/atom/electron/tree/master/docs-translations/pt-BR)
|
||||
- [Korean](https://github.com/atom/electron/tree/master/docs-translations/ko-KR)
|
||||
- [Japanese](https://github.com/atom/electron/tree/master/docs-translations/jp)
|
||||
- [Spanish](https://github.com/atom/electron/tree/master/docs-translations/es)
|
||||
- [Simplified Chinese](https://github.com/atom/electron/tree/master/docs-translations/zh-CN)
|
||||
- [Traditional Chinese](https://github.com/atom/electron/tree/master/docs-translations/zh-TW)
|
||||
|
||||
## Quick Start
|
||||
|
||||
Clone and run the [`atom/electron-quick-start`](https://github.com/atom/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
|
||||
|
||||
## 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).
|
||||
73
appveyor.yml
73
appveyor.yml
@@ -1,73 +0,0 @@
|
||||
build_cloud: electron-16
|
||||
image: electron-16-vs2017-15.4.5
|
||||
build_script:
|
||||
- ps: >-
|
||||
echo "Build worker image $env:APPVEYOR_BUILD_WORKER_IMAGE"
|
||||
|
||||
&"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe"
|
||||
|
||||
if($env: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
|
||||
}
|
||||
}
|
||||
@@ -4,13 +4,11 @@
|
||||
'product_name%': 'Electron',
|
||||
'company_name%': 'GitHub, Inc',
|
||||
'company_abbr%': 'github',
|
||||
'version%': '3.1.0-beta.5',
|
||||
'js2c_input_dir': '<(SHARED_INTERMEDIATE_DIR)/js2c',
|
||||
'version%': '0.34.4',
|
||||
},
|
||||
'includes': [
|
||||
'features.gypi',
|
||||
'filenames.gypi',
|
||||
'native_mate/native_mate_files.gypi',
|
||||
'vendor/native_mate/native_mate_files.gypi',
|
||||
],
|
||||
'target_defaults': {
|
||||
'defines': [
|
||||
@@ -23,31 +21,6 @@
|
||||
'<(source_root)/external_binaries',
|
||||
],
|
||||
}],
|
||||
['enable_desktop_capturer==1', {
|
||||
'defines': [
|
||||
'ENABLE_DESKTOP_CAPTURER',
|
||||
],
|
||||
}], # enable_desktop_capturer==1
|
||||
['enable_osr==1', {
|
||||
'defines': [
|
||||
'ENABLE_OSR',
|
||||
],
|
||||
}], # enable_osr==1
|
||||
['enable_pdf_viewer==1', {
|
||||
'defines': [
|
||||
'ENABLE_PDF_VIEWER',
|
||||
],
|
||||
}], # enable_pdf_viewer
|
||||
['enable_run_as_node==1', {
|
||||
'defines': [
|
||||
'ENABLE_RUN_AS_NODE',
|
||||
],
|
||||
}], # enable_run_as_node
|
||||
['enable_view_api==1', {
|
||||
'defines': [
|
||||
'ENABLE_VIEW_API',
|
||||
],
|
||||
}], # enable_view_api
|
||||
],
|
||||
},
|
||||
'targets': [
|
||||
@@ -55,8 +28,7 @@
|
||||
'target_name': '<(project_name)',
|
||||
'type': 'executable',
|
||||
'dependencies': [
|
||||
'js2asar',
|
||||
'app2asar',
|
||||
'compile_coffee',
|
||||
'<(project_name)_lib',
|
||||
],
|
||||
'sources': [
|
||||
@@ -94,6 +66,12 @@
|
||||
'<(PRODUCT_DIR)/<(product_name) Framework.framework',
|
||||
],
|
||||
},
|
||||
{
|
||||
'destination': '<(PRODUCT_DIR)/<(product_name).app/Contents/Resources',
|
||||
'files': [
|
||||
'atom/browser/default_app',
|
||||
],
|
||||
},
|
||||
],
|
||||
'postbuilds': [
|
||||
{
|
||||
@@ -107,14 +85,14 @@
|
||||
# is marked for no PIE (ASLR).
|
||||
'postbuild_name': 'Make More Helpers',
|
||||
'action': [
|
||||
'tools/mac/make_more_helpers.sh',
|
||||
'vendor/brightray/tools/mac/make_more_helpers.sh',
|
||||
'Frameworks',
|
||||
'<(product_name)',
|
||||
],
|
||||
},
|
||||
# The application doesn't have real localizations, it just has
|
||||
# empty .lproj directories, which is enough to convince Cocoa
|
||||
# that Electron supports those languages.
|
||||
# atom-shell supports those languages.
|
||||
{
|
||||
'postbuild_name': 'Make Empty Localizations',
|
||||
'variables': {
|
||||
@@ -142,19 +120,10 @@
|
||||
},
|
||||
],
|
||||
}],
|
||||
['mas_build==1', {
|
||||
'dependencies': [
|
||||
'<(project_name)_login_helper',
|
||||
],
|
||||
'copies': [
|
||||
{
|
||||
'destination': '<(PRODUCT_DIR)/<(product_name).app/Contents/Library/LoginItems',
|
||||
'files': [
|
||||
'<(PRODUCT_DIR)/<(product_name) Login Helper.app',
|
||||
],
|
||||
},
|
||||
],
|
||||
}],
|
||||
],
|
||||
}, { # OS=="mac"
|
||||
'dependencies': [
|
||||
'make_locale_paks',
|
||||
],
|
||||
}], # OS!="mac"
|
||||
['OS=="win"', {
|
||||
@@ -165,20 +134,7 @@
|
||||
'VCManifestTool': {
|
||||
'EmbedManifest': 'true',
|
||||
'AdditionalManifestFiles': 'atom/browser/resources/win/atom.manifest',
|
||||
},
|
||||
'VCLinkerTool': {
|
||||
# Chrome builds with this minimum environment which makes e.g.
|
||||
# GetSystemMetrics(SM_CXSIZEFRAME) return Windows XP/2003
|
||||
# compatible metrics. See: https://crbug.com/361720
|
||||
#
|
||||
# The following two settings translate to a linker flag
|
||||
# of /SUBSYSTEM:WINDOWS,5.02
|
||||
'MinimumRequiredVersion': '5.02',
|
||||
'SubSystem': '2',
|
||||
'AdditionalDependencies': [
|
||||
'wtsapi32.lib',
|
||||
],
|
||||
},
|
||||
}
|
||||
},
|
||||
'copies': [
|
||||
{
|
||||
@@ -191,7 +147,7 @@
|
||||
],
|
||||
}, {
|
||||
'copied_libraries': [
|
||||
'<(libchromiumcontent_dir)/ffmpeg.dll',
|
||||
'<(libchromiumcontent_dir)/pdf.dll',
|
||||
],
|
||||
}],
|
||||
],
|
||||
@@ -199,20 +155,27 @@
|
||||
'destination': '<(PRODUCT_DIR)',
|
||||
'files': [
|
||||
'<@(copied_libraries)',
|
||||
'<(libchromiumcontent_dir)/locales',
|
||||
'<(libchromiumcontent_dir)/libEGL.dll',
|
||||
'<(libchromiumcontent_dir)/libGLESv2.dll',
|
||||
'<(libchromiumcontent_dir)/icudtl.dat',
|
||||
'<(libchromiumcontent_dir)/blink_image_resources_200_percent.pak',
|
||||
'<(libchromiumcontent_dir)/content_resources_200_percent.pak',
|
||||
'<(libchromiumcontent_dir)/content_shell.pak',
|
||||
'<(libchromiumcontent_dir)/ui_resources_200_percent.pak',
|
||||
'<(libchromiumcontent_dir)/views_resources_200_percent.pak',
|
||||
'<(libchromiumcontent_dir)/natives_blob.bin',
|
||||
'<(libchromiumcontent_dir)/v8_context_snapshot.bin',
|
||||
'<(libchromiumcontent_dir)/snapshot_blob.bin',
|
||||
'external_binaries/d3dcompiler_47.dll',
|
||||
'external_binaries/xinput1_3.dll',
|
||||
'external_binaries/msvcp120.dll',
|
||||
'external_binaries/msvcr120.dll',
|
||||
'external_binaries/vccorlib120.dll',
|
||||
],
|
||||
},
|
||||
{
|
||||
'destination': '<(PRODUCT_DIR)/resources',
|
||||
'files': [
|
||||
'atom/browser/default_app',
|
||||
]
|
||||
},
|
||||
],
|
||||
}, {
|
||||
'dependencies': [
|
||||
@@ -233,7 +196,6 @@
|
||||
}, {
|
||||
'copied_libraries': [
|
||||
'<(PRODUCT_DIR)/lib/libnode.so',
|
||||
'<(libchromiumcontent_dir)/libffmpeg.so',
|
||||
],
|
||||
}],
|
||||
],
|
||||
@@ -241,17 +203,18 @@
|
||||
'destination': '<(PRODUCT_DIR)',
|
||||
'files': [
|
||||
'<@(copied_libraries)',
|
||||
'<(libchromiumcontent_dir)/locales',
|
||||
'<(libchromiumcontent_dir)/icudtl.dat',
|
||||
'<(libchromiumcontent_dir)/blink_image_resources_200_percent.pak',
|
||||
'<(libchromiumcontent_dir)/content_resources_200_percent.pak',
|
||||
'<(libchromiumcontent_dir)/content_shell.pak',
|
||||
'<(libchromiumcontent_dir)/ui_resources_200_percent.pak',
|
||||
'<(libchromiumcontent_dir)/views_resources_200_percent.pak',
|
||||
'<(libchromiumcontent_dir)/natives_blob.bin',
|
||||
'<(libchromiumcontent_dir)/v8_context_snapshot.bin',
|
||||
'<(libchromiumcontent_dir)/snapshot_blob.bin',
|
||||
],
|
||||
},
|
||||
{
|
||||
'destination': '<(PRODUCT_DIR)/resources',
|
||||
'files': [
|
||||
'atom/browser/default_app',
|
||||
]
|
||||
},
|
||||
],
|
||||
}], # OS=="linux"
|
||||
],
|
||||
@@ -260,40 +223,18 @@
|
||||
'target_name': '<(project_name)_lib',
|
||||
'type': 'static_library',
|
||||
'dependencies': [
|
||||
'atom_js2c',
|
||||
'brightray/brightray.gyp:brightray',
|
||||
'vendor/node/node.gyp:node_lib',
|
||||
'atom_coffee2c',
|
||||
'vendor/brightray/brightray.gyp:brightray',
|
||||
'vendor/node/node.gyp:node',
|
||||
],
|
||||
'defines': [
|
||||
# We need to access internal implementations of Node.
|
||||
'NODE_WANT_INTERNALS=1',
|
||||
'NODE_SHARED_MODE',
|
||||
'HAVE_OPENSSL=1',
|
||||
'HAVE_INSPECTOR=1',
|
||||
# This is defined in skia/skia_common.gypi.
|
||||
'SK_SUPPORT_LEGACY_GETTOPDEVICE',
|
||||
# Disable warnings for g_settings_list_schemas.
|
||||
'GLIB_DISABLE_DEPRECATION_WARNINGS',
|
||||
# Defined in Chromium but not exposed in its gyp file.
|
||||
'V8_USE_EXTERNAL_STARTUP_DATA',
|
||||
|
||||
# Import V8 symbols from shared library (node.dll / libnode.so)
|
||||
'USING_V8_SHARED',
|
||||
'USING_V8_PLATFORM_SHARED',
|
||||
'USING_V8_BASE_SHARED',
|
||||
|
||||
# See Chromium src/third_party/protobuf/BUILD.gn
|
||||
'GOOGLE_PROTOBUF_NO_RTTI',
|
||||
'GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER',
|
||||
|
||||
# Enables SkBitmap size 64 operations
|
||||
'SK_SUPPORT_LEGACY_SAFESIZE64',
|
||||
|
||||
# Enables flash support
|
||||
'ENABLE_PEPPER_FLASH',
|
||||
|
||||
# Enables widevine cdm support
|
||||
'WIDEVINE_CDM_AVAILABLE',
|
||||
'ENABLE_PLUGINS',
|
||||
],
|
||||
'sources': [
|
||||
'<@(lib_sources)',
|
||||
@@ -301,7 +242,8 @@
|
||||
'include_dirs': [
|
||||
'.',
|
||||
'chromium_src',
|
||||
'native_mate',
|
||||
'vendor/brightray',
|
||||
'vendor/native_mate',
|
||||
# Include atom_natives.h.
|
||||
'<(SHARED_INTERMEDIATE_DIR)',
|
||||
# Include directories for uv and node.
|
||||
@@ -314,19 +256,6 @@
|
||||
'vendor/node/deps/cares/include',
|
||||
# The `third_party/WebKit/Source/platform/weborigin/SchemeRegistry.h` is using `platform/PlatformExport.h`.
|
||||
'<(libchromiumcontent_src_dir)/third_party/WebKit/Source',
|
||||
# The 'third_party/libyuv/include/libyuv/scale_argb.h' is using 'libyuv/basic_types.h'.
|
||||
'<(libchromiumcontent_src_dir)/third_party/libyuv/include',
|
||||
# The 'third_party/webrtc/modules/desktop_capture/desktop_frame.h' is using 'webrtc/base/scoped_ptr.h'.
|
||||
'<(libchromiumcontent_src_dir)/third_party/',
|
||||
'<(libchromiumcontent_src_dir)/components/cdm',
|
||||
'<(libchromiumcontent_src_dir)/third_party/widevine',
|
||||
'<(libchromiumcontent_src_dir)/third_party/widevine/cdm/stub',
|
||||
'<(libchromiumcontent_src_dir)/third_party/protobuf/src',
|
||||
# The 'third_party/webrtc/modules/desktop_capture/desktop_capture_options.h' is using 'rtc_base/constructormagic.h'.
|
||||
'<(libchromiumcontent_src_dir)/third_party/webrtc',
|
||||
# leveldb includes are required
|
||||
'<(libchromiumcontent_src_dir)/third_party/leveldatabase/src',
|
||||
'<(libchromiumcontent_src_dir)/third_party/leveldatabase/src/include',
|
||||
],
|
||||
'direct_dependent_settings': {
|
||||
'include_dirs': [
|
||||
@@ -334,28 +263,13 @@
|
||||
],
|
||||
},
|
||||
'export_dependent_settings': [
|
||||
'brightray/brightray.gyp:brightray',
|
||||
'vendor/brightray/brightray.gyp:brightray',
|
||||
],
|
||||
'conditions': [
|
||||
['enable_pdf_viewer==1', {
|
||||
'dependencies': [
|
||||
'vendor/pdf_viewer/pdf_viewer.gyp:pdf_viewer',
|
||||
],
|
||||
}], # enable_pdf_viewer
|
||||
['libchromiumcontent_component', {
|
||||
'link_settings': {
|
||||
'libraries': [ '<@(libchromiumcontent_v8_libraries)' ],
|
||||
},
|
||||
'sources': [
|
||||
'<@(lib_sources_location_provider)',
|
||||
],
|
||||
'defines': [
|
||||
# Enable fake location provider to mock geolocation
|
||||
# responses in component build. Should not be enabled
|
||||
# for release build. If you need to test with chromium's
|
||||
# location provider, remove this definition.
|
||||
'OVERRIDE_LOCATION_PROVIDER',
|
||||
],
|
||||
}],
|
||||
['OS=="win"', {
|
||||
'sources': [
|
||||
@@ -368,10 +282,6 @@
|
||||
'-lcomctl32.lib',
|
||||
'-lcomdlg32.lib',
|
||||
'-lwininet.lib',
|
||||
'-lwinmm.lib',
|
||||
'-lcrypt32.lib',
|
||||
'-luiautomationcore.lib',
|
||||
'-lPropsys.lib'
|
||||
],
|
||||
},
|
||||
'dependencies': [
|
||||
@@ -397,14 +307,6 @@
|
||||
'$(SDKROOT)/System/Library/Frameworks/QTKit.framework',
|
||||
],
|
||||
},
|
||||
'xcode_settings': {
|
||||
# ReactiveCocoa which is used by Squirrel requires using __weak.
|
||||
'CLANG_ENABLE_OBJC_WEAK': 'YES',
|
||||
'OTHER_CFLAGS': [
|
||||
'-Wunguarded-availability',
|
||||
'-Wobjc-missing-property-synthesis',
|
||||
],
|
||||
},
|
||||
}], # OS=="mac" and mas_build==0
|
||||
['OS=="mac" and mas_build==1', {
|
||||
'defines': [
|
||||
@@ -415,25 +317,14 @@
|
||||
'atom/common/crash_reporter/crash_reporter_mac.h',
|
||||
'atom/common/crash_reporter/crash_reporter_mac.mm',
|
||||
],
|
||||
'dependencies': [
|
||||
# Somehow we have code from Chromium using crashpad, very likely
|
||||
# from components/crash.
|
||||
# Since we do not actually invoke code from components/crash, this
|
||||
# dependency should be eventually optimized out by linker.
|
||||
'vendor/crashpad/client/client.gyp:crashpad_client',
|
||||
],
|
||||
}], # OS=="mac" and mas_build==1
|
||||
['OS=="linux"', {
|
||||
'sources': [
|
||||
'<@(lib_sources_linux)',
|
||||
'<@(lib_sources_nss)',
|
||||
],
|
||||
'link_settings': {
|
||||
'ldflags': [
|
||||
# Make binary search for libraries under current directory, so we
|
||||
# don't have to manually set $LD_LIBRARY_PATH:
|
||||
# http://serverfault.com/questions/279068/cant-find-so-in-the-same-directory-as-the-executable
|
||||
'-Wl,-rpath=\$$ORIGIN',
|
||||
'-rpath \$$ORIGIN',
|
||||
# Make native module dynamic loading work.
|
||||
'-rdynamic',
|
||||
],
|
||||
@@ -441,6 +332,7 @@
|
||||
# Required settings of using breakpad.
|
||||
'cflags_cc': [
|
||||
'-Wno-empty-body',
|
||||
'-Wno-reserved-user-defined-literal',
|
||||
],
|
||||
'include_dirs': [
|
||||
'vendor/breakpad/src',
|
||||
@@ -449,20 +341,14 @@
|
||||
'vendor/breakpad/breakpad.gyp:breakpad_client',
|
||||
],
|
||||
}], # OS=="linux"
|
||||
['OS=="linux" and clang==1', {
|
||||
# Required settings of using breakpad.
|
||||
'cflags_cc': [
|
||||
'-Wno-reserved-user-defined-literal',
|
||||
],
|
||||
}], # OS=="linux" and clang==1
|
||||
],
|
||||
}, # target <(product_name)_lib
|
||||
{
|
||||
'target_name': 'js2asar',
|
||||
'target_name': 'compile_coffee',
|
||||
'type': 'none',
|
||||
'actions': [
|
||||
{
|
||||
'action_name': 'js2asar',
|
||||
'action_name': 'compile_coffee',
|
||||
'variables': {
|
||||
'conditions': [
|
||||
['OS=="mac"', {
|
||||
@@ -473,159 +359,41 @@
|
||||
],
|
||||
},
|
||||
'inputs': [
|
||||
'<@(js_sources)',
|
||||
'<@(coffee_sources)',
|
||||
],
|
||||
'outputs': [
|
||||
'<(resources_path)/electron.asar',
|
||||
'<(resources_path)/atom.asar',
|
||||
],
|
||||
'action': [
|
||||
'python',
|
||||
'tools/js2asar.py',
|
||||
'tools/coffee2asar.py',
|
||||
'<@(_outputs)',
|
||||
'lib',
|
||||
'<@(_inputs)',
|
||||
],
|
||||
}
|
||||
],
|
||||
}, # target js2asar
|
||||
}, # target compile_coffee
|
||||
{
|
||||
'target_name': 'app2asar',
|
||||
'target_name': 'atom_coffee2c',
|
||||
'type': 'none',
|
||||
'actions': [
|
||||
{
|
||||
'action_name': 'app2asar',
|
||||
'variables': {
|
||||
'conditions': [
|
||||
['OS=="mac"', {
|
||||
'resources_path': '<(PRODUCT_DIR)/<(product_name).app/Contents/Resources',
|
||||
},{
|
||||
'resources_path': '<(PRODUCT_DIR)/resources',
|
||||
}],
|
||||
],
|
||||
},
|
||||
'action_name': 'atom_coffee2c',
|
||||
'inputs': [
|
||||
'<@(default_app_sources)',
|
||||
],
|
||||
'outputs': [
|
||||
'<(resources_path)/default_app.asar',
|
||||
],
|
||||
'action': [
|
||||
'python',
|
||||
'tools/js2asar.py',
|
||||
'<@(_outputs)',
|
||||
'default_app',
|
||||
'<@(_inputs)',
|
||||
],
|
||||
}
|
||||
],
|
||||
}, # target app2asar
|
||||
{
|
||||
'target_name': 'atom_js2c_copy',
|
||||
'type': 'none',
|
||||
'copies': [
|
||||
{
|
||||
'destination': '<(js2c_input_dir)',
|
||||
'files': [
|
||||
'<@(js2c_sources)',
|
||||
],
|
||||
},
|
||||
],
|
||||
}, # target atom_js2c_copy
|
||||
{
|
||||
'target_name': 'atom_browserify',
|
||||
'type': 'none',
|
||||
'dependencies': [
|
||||
# depend on this target to ensure the '<(js2c_input_dir)' is created
|
||||
'atom_js2c_copy',
|
||||
],
|
||||
'variables': {
|
||||
'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'
|
||||
],
|
||||
'isolated_args': [
|
||||
'lib/isolated_renderer/init.js',
|
||||
]
|
||||
},
|
||||
'actions': [
|
||||
{
|
||||
'action_name': 'atom_browserify_sandbox',
|
||||
'inputs': [
|
||||
'<!@(python tools/list-browserify-deps.py <(sandbox_args))'
|
||||
],
|
||||
'outputs': [
|
||||
'<(js2c_input_dir)/preload_bundle.js',
|
||||
],
|
||||
'action': [
|
||||
'npm',
|
||||
'run',
|
||||
'--silent',
|
||||
'browserify',
|
||||
'--',
|
||||
'<@(sandbox_args)',
|
||||
'-o',
|
||||
'<@(_outputs)',
|
||||
],
|
||||
},
|
||||
{
|
||||
'action_name': 'atom_browserify_isolated_context',
|
||||
'inputs': [
|
||||
'<!@(python tools/list-browserify-deps.py <(isolated_args))'
|
||||
],
|
||||
'outputs': [
|
||||
'<(js2c_input_dir)/isolated_bundle.js',
|
||||
],
|
||||
'action': [
|
||||
'npm',
|
||||
'run',
|
||||
'--silent',
|
||||
'browserify',
|
||||
'--',
|
||||
'<@(isolated_args)',
|
||||
'-o',
|
||||
'<@(_outputs)',
|
||||
],
|
||||
},
|
||||
],
|
||||
}, # target atom_browserify
|
||||
{
|
||||
'target_name': 'atom_js2c',
|
||||
'type': 'none',
|
||||
'dependencies': [
|
||||
'atom_js2c_copy',
|
||||
'atom_browserify',
|
||||
],
|
||||
'actions': [
|
||||
{
|
||||
'action_name': 'atom_js2c',
|
||||
'inputs': [
|
||||
# List all input files that should trigger a rebuild with js2c
|
||||
'<@(js2c_sources)',
|
||||
'<(js2c_input_dir)/preload_bundle.js',
|
||||
'<(js2c_input_dir)/isolated_bundle.js',
|
||||
'<@(coffee2c_sources)',
|
||||
],
|
||||
'outputs': [
|
||||
'<(SHARED_INTERMEDIATE_DIR)/atom_natives.h',
|
||||
],
|
||||
'action': [
|
||||
'python',
|
||||
'tools/js2c.py',
|
||||
'vendor/node',
|
||||
'tools/coffee2c.py',
|
||||
'<@(_outputs)',
|
||||
'<(js2c_input_dir)',
|
||||
'<@(_inputs)',
|
||||
],
|
||||
}
|
||||
],
|
||||
}, # target atom_js2c
|
||||
}, # target atom_coffee2c
|
||||
],
|
||||
'conditions': [
|
||||
['OS=="mac"', {
|
||||
@@ -652,24 +420,15 @@
|
||||
'libraries': [
|
||||
'$(SDKROOT)/System/Library/Frameworks/Carbon.framework',
|
||||
'$(SDKROOT)/System/Library/Frameworks/QuartzCore.framework',
|
||||
'$(SDKROOT)/System/Library/Frameworks/Quartz.framework',
|
||||
'$(SDKROOT)/System/Library/Frameworks/Security.framework',
|
||||
'$(SDKROOT)/System/Library/Frameworks/SecurityInterface.framework',
|
||||
'$(SDKROOT)/System/Library/Frameworks/ServiceManagement.framework',
|
||||
'$(SDKROOT)/System/Library/Frameworks/StoreKit.framework',
|
||||
],
|
||||
},
|
||||
'mac_bundle': 1,
|
||||
'mac_bundle_resources': [
|
||||
'atom/common/resources/mac/MainMenu.xib',
|
||||
'<(libchromiumcontent_dir)/icudtl.dat',
|
||||
'<(libchromiumcontent_dir)/blink_image_resources_200_percent.pak',
|
||||
'<(libchromiumcontent_dir)/content_resources_200_percent.pak',
|
||||
'<(libchromiumcontent_dir)/content_shell.pak',
|
||||
'<(libchromiumcontent_dir)/ui_resources_200_percent.pak',
|
||||
'<(libchromiumcontent_dir)/views_resources_200_percent.pak',
|
||||
'<(libchromiumcontent_dir)/icudtl.dat',
|
||||
'<(libchromiumcontent_dir)/natives_blob.bin',
|
||||
'<(libchromiumcontent_dir)/v8_context_snapshot.bin',
|
||||
'<(libchromiumcontent_dir)/snapshot_blob.bin',
|
||||
],
|
||||
'xcode_settings': {
|
||||
'ATOM_BUNDLE_ID': 'com.<(company_abbr).<(project_name).framework',
|
||||
@@ -695,7 +454,6 @@
|
||||
}, {
|
||||
'copied_libraries': [
|
||||
'<(PRODUCT_DIR)/libnode.dylib',
|
||||
'<(libchromiumcontent_dir)/libffmpeg.dylib',
|
||||
],
|
||||
}],
|
||||
],
|
||||
@@ -717,6 +475,16 @@
|
||||
'${BUILT_PRODUCTS_DIR}/<(product_name) Framework.framework/Versions/A/<(product_name) Framework',
|
||||
],
|
||||
},
|
||||
{
|
||||
'postbuild_name': 'Fix path of ffmpeg',
|
||||
'action': [
|
||||
'install_name_tool',
|
||||
'-change',
|
||||
'@loader_path/libffmpeg.dylib',
|
||||
'@rpath/libffmpeg.dylib',
|
||||
'${BUILT_PRODUCTS_DIR}/<(product_name) Framework.framework/Versions/A/<(product_name) Framework',
|
||||
],
|
||||
},
|
||||
{
|
||||
'postbuild_name': 'Add symlinks for framework subdirectories',
|
||||
'action': [
|
||||
@@ -725,23 +493,8 @@
|
||||
'Libraries',
|
||||
],
|
||||
},
|
||||
{
|
||||
'postbuild_name': 'Copy locales',
|
||||
'action': [
|
||||
'tools/mac/copy-locales.py',
|
||||
'-d',
|
||||
'<(libchromiumcontent_dir)/locales',
|
||||
'${BUILT_PRODUCTS_DIR}/<(product_name) Framework.framework/Resources',
|
||||
'<@(locales)',
|
||||
],
|
||||
},
|
||||
],
|
||||
'conditions': [
|
||||
['enable_pdf_viewer==1', {
|
||||
'mac_bundle_resources': [
|
||||
'<(PRODUCT_DIR)/pdf_viewer_resources.pak',
|
||||
],
|
||||
}], # enable_pdf_viewer
|
||||
['mas_build==0', {
|
||||
'link_settings': {
|
||||
'libraries': [
|
||||
@@ -783,32 +536,31 @@
|
||||
],
|
||||
},
|
||||
}, # target helper
|
||||
],
|
||||
}, { # OS=="mac"
|
||||
'targets': [
|
||||
{
|
||||
'target_name': '<(project_name)_login_helper',
|
||||
'product_name': '<(product_name) Login Helper',
|
||||
'type': 'executable',
|
||||
'sources': [
|
||||
'<@(login_helper_sources)',
|
||||
'target_name': 'make_locale_paks',
|
||||
'type': 'none',
|
||||
'actions': [
|
||||
{
|
||||
'action_name': 'Make Empty Paks',
|
||||
'inputs': [
|
||||
'tools/make_locale_paks.py',
|
||||
],
|
||||
'outputs': [
|
||||
'<(PRODUCT_DIR)/locales'
|
||||
],
|
||||
'action': [
|
||||
'python',
|
||||
'tools/make_locale_paks.py',
|
||||
'<(PRODUCT_DIR)',
|
||||
'<@(locales)',
|
||||
],
|
||||
'msvs_cygwin_shell': 0,
|
||||
},
|
||||
],
|
||||
'include_dirs': [
|
||||
'.',
|
||||
'vendor',
|
||||
'<(libchromiumcontent_src_dir)',
|
||||
],
|
||||
'link_settings': {
|
||||
'libraries': [
|
||||
'$(SDKROOT)/System/Library/Frameworks/AppKit.framework',
|
||||
],
|
||||
},
|
||||
'mac_bundle': 1,
|
||||
'xcode_settings': {
|
||||
'ATOM_BUNDLE_ID': 'com.<(company_abbr).<(project_name).loginhelper',
|
||||
'INFOPLIST_FILE': 'atom/app/resources/mac/loginhelper-Info.plist',
|
||||
'OTHER_LDFLAGS': [
|
||||
'-ObjC',
|
||||
],
|
||||
},
|
||||
}, # target login_helper
|
||||
},
|
||||
],
|
||||
}], # OS!="mac"
|
||||
],
|
||||
@@ -11,97 +11,17 @@
|
||||
#include "atom/common/chrome_version.h"
|
||||
#include "atom/common/options_switches.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/files/file_util.h"
|
||||
#include "base/strings/string_split.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#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 "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"
|
||||
#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)
|
||||
|
||||
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;
|
||||
@@ -111,9 +31,9 @@ content::PepperPluginInfo CreatePepperFlashInfo(const base::FilePath& path,
|
||||
plugin.path = path;
|
||||
plugin.permissions = ppapi::PERMISSION_ALL_BITS;
|
||||
|
||||
std::vector<std::string> flash_version_numbers = base::SplitString(
|
||||
version, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
|
||||
if (flash_version_numbers.empty())
|
||||
std::vector<std::string> flash_version_numbers;
|
||||
base::SplitString(version, '.', &flash_version_numbers);
|
||||
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 +46,69 @@ 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];
|
||||
plugin.version = base::JoinString(flash_version_numbers, ".");
|
||||
content::WebPluginMimeType swf_mime_type(content::kFlashPluginSwfMimeType,
|
||||
content::kFlashPluginSwfExtension,
|
||||
content::kFlashPluginSwfDescription);
|
||||
flash_version_numbers[1] + " r" + flash_version_numbers[2];
|
||||
plugin.version = JoinString(flash_version_numbers, '.');
|
||||
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;
|
||||
|
||||
auto flash_version =
|
||||
command_line->GetSwitchValueASCII(switches::kPpapiFlashVersion);
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
void ConvertStringWithSeparatorToVector(std::vector<std::string>* vec,
|
||||
const char* separator,
|
||||
const char* cmd_switch) {
|
||||
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);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
AtomContentClient::AtomContentClient() {}
|
||||
AtomContentClient::AtomContentClient() {
|
||||
}
|
||||
|
||||
AtomContentClient::~AtomContentClient() {}
|
||||
AtomContentClient::~AtomContentClient() {
|
||||
}
|
||||
|
||||
std::string AtomContentClient::GetProduct() const {
|
||||
return "Chrome/" CHROME_VERSION_STRING;
|
||||
}
|
||||
|
||||
std::string AtomContentClient::GetUserAgent() const {
|
||||
return content::BuildUserAgentFromProduct("Chrome/" CHROME_VERSION_STRING
|
||||
" " ATOM_PRODUCT_NAME
|
||||
"/" ATOM_VERSION_STRING);
|
||||
return content::BuildUserAgentFromProduct(
|
||||
"Chrome/" CHROME_VERSION_STRING " "
|
||||
ATOM_PRODUCT_NAME "/" ATOM_VERSION_STRING);
|
||||
}
|
||||
|
||||
base::string16 AtomContentClient::GetLocalizedString(int message_id) const {
|
||||
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<std::string>* standard_schemes,
|
||||
std::vector<std::string>* savable_schemes) {
|
||||
auto command_line = base::CommandLine::ForCurrentProcess();
|
||||
auto custom_schemes = command_line->GetSwitchValueASCII(
|
||||
switches::kRegisterStandardSchemes);
|
||||
if (!custom_schemes.empty()) {
|
||||
std::vector<std::string> schemes;
|
||||
base::SplitString(custom_schemes, ',', &schemes);
|
||||
standard_schemes->insert(standard_schemes->end(),
|
||||
schemes.begin(),
|
||||
schemes.end());
|
||||
}
|
||||
standard_schemes->push_back("chrome-extension");
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
auto command_line = base::CommandLine::ForCurrentProcess();
|
||||
auto flash_path = command_line->GetSwitchValuePath(
|
||||
switches::kPpapiFlashPath);
|
||||
if (flash_path.empty())
|
||||
return;
|
||||
|
||||
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());
|
||||
auto flash_version = command_line->GetSwitchValueASCII(
|
||||
switches::kPpapiFlashVersion);
|
||||
|
||||
cdms->push_back(content::CdmInfo(
|
||||
kWidevineCdmDisplayName, kWidevineCdmGuid, version, cdm_path,
|
||||
kWidevineCdmFileSystemId, video_codecs_supported,
|
||||
supports_persistent_license, kWidevineKeySystem, false));
|
||||
}
|
||||
#endif // defined(WIDEVINE_CDM_AVAILABLE)
|
||||
}
|
||||
plugins->push_back(
|
||||
CreatePepperFlashInfo(flash_path, flash_version));
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#ifndef ATOM_APP_ATOM_CONTENT_CLIENT_H_
|
||||
#define ATOM_APP_ATOM_CONTENT_CLIENT_H_
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -16,19 +15,17 @@ 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<std::string>* standard_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;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomContentClient);
|
||||
|
||||
@@ -5,17 +5,15 @@
|
||||
#ifndef ATOM_APP_ATOM_LIBRARY_MAIN_H_
|
||||
#define ATOM_APP_ATOM_LIBRARY_MAIN_H_
|
||||
|
||||
#include "build/build_config.h"
|
||||
#include "base/basictypes.h"
|
||||
|
||||
#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,30 @@
|
||||
|
||||
#include "atom/app/atom_main.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <vector>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include <windows.h> // windows.h must be included first
|
||||
#include <stdio.h>
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <atlbase.h> // ensures that ATL statics like `_AtlWinModule` are initialized (it's an issue in static debug build)
|
||||
#include <shellapi.h>
|
||||
#include <windows.h>
|
||||
#include <shellscalingapi.h>
|
||||
#include <tchar.h>
|
||||
#include <shellapi.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 "content/public/app/startup_helper_win.h"
|
||||
#include "sandbox/win/src/sandbox_types.h"
|
||||
#include "ui/gfx/win/dpi.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)
|
||||
|
||||
@@ -40,173 +36,156 @@
|
||||
#include "base/at_exit.h"
|
||||
#include "base/i18n/icu_util.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
|
||||
namespace {
|
||||
|
||||
#ifdef ENABLE_RUN_AS_NODE
|
||||
const char kRunAsNode[] = "ELECTRON_RUN_AS_NODE";
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_RUN_AS_NODE) || defined(OS_WIN)
|
||||
bool IsEnvSet(const char* name) {
|
||||
#if defined(OS_WIN)
|
||||
size_t required_size;
|
||||
getenv_s(&required_size, nullptr, 0, name);
|
||||
return required_size != 0;
|
||||
#else
|
||||
char* indicator = getenv(name);
|
||||
return indicator && indicator[0] != '\0';
|
||||
#endif
|
||||
// Win8.1 supports monitor-specific DPI scaling.
|
||||
bool SetProcessDpiAwarenessWrapper(PROCESS_DPI_AWARENESS value) {
|
||||
typedef HRESULT(WINAPI *SetProcessDpiAwarenessPtr)(PROCESS_DPI_AWARENESS);
|
||||
SetProcessDpiAwarenessPtr set_process_dpi_awareness_func =
|
||||
reinterpret_cast<SetProcessDpiAwarenessPtr>(
|
||||
GetProcAddress(GetModuleHandleA("user32.dll"),
|
||||
"SetProcessDpiAwarenessInternal"));
|
||||
if (set_process_dpi_awareness_func) {
|
||||
HRESULT hr = set_process_dpi_awareness_func(value);
|
||||
if (SUCCEEDED(hr)) {
|
||||
VLOG(1) << "SetProcessDpiAwareness succeeded.";
|
||||
return true;
|
||||
} else if (hr == E_ACCESSDENIED) {
|
||||
LOG(ERROR) << "Access denied error from SetProcessDpiAwareness. "
|
||||
"Function called twice, or manifest was used.";
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#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);
|
||||
// This function works for Windows Vista through Win8. Win8.1 must use
|
||||
// SetProcessDpiAwareness[Wrapper].
|
||||
BOOL SetProcessDPIAwareWrapper() {
|
||||
typedef BOOL(WINAPI *SetProcessDPIAwarePtr)(VOID);
|
||||
SetProcessDPIAwarePtr set_process_dpi_aware_func =
|
||||
reinterpret_cast<SetProcessDPIAwarePtr>(
|
||||
GetProcAddress(GetModuleHandleA("user32.dll"),
|
||||
"SetProcessDPIAware"));
|
||||
return set_process_dpi_aware_func &&
|
||||
set_process_dpi_aware_func();
|
||||
}
|
||||
|
||||
void EnableHighDPISupport() {
|
||||
if (!SetProcessDpiAwarenessWrapper(PROCESS_SYSTEM_DPI_AWARE)) {
|
||||
SetProcessDPIAwareWrapper();
|
||||
}
|
||||
}
|
||||
#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;
|
||||
scoped_ptr<base::Environment> env(base::Environment::Create());
|
||||
|
||||
if (!arguments.argv)
|
||||
return -1;
|
||||
// Make output work in console if we are not in cygiwn.
|
||||
std::string os;
|
||||
if (env->GetVar("OS", &os) && os != "cygwin") {
|
||||
AttachConsole(ATTACH_PARENT_PROCESS);
|
||||
|
||||
#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;
|
||||
}
|
||||
FILE* dontcare;
|
||||
freopen_s(&dontcare, "CON", "w", stdout);
|
||||
freopen_s(&dontcare, "CON", "w", stderr);
|
||||
freopen_s(&dontcare, "CON", "r", stdin);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
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
|
||||
|
||||
#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()); });
|
||||
|
||||
std::string node_indicator, crash_service_indicator;
|
||||
if (env->GetVar("ATOM_SHELL_INTERNAL_RUN_AS_NODE", &node_indicator) &&
|
||||
node_indicator == "1") {
|
||||
// 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 (env->GetVar("ATOM_SHELL_INTERNAL_CRASH_SERVICE",
|
||||
&crash_service_indicator) &&
|
||||
crash_service_indicator == "1") {
|
||||
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;
|
||||
|
||||
// We don't want to set DPI awareness on pre-Win7 because we don't support
|
||||
// DirectWrite there. GDI fonts are kerned very badly, so better to leave
|
||||
// DPI-unaware and at effective 1.0. See also ShouldUseDirectWrite().
|
||||
if (base::win::GetVersion() >= base::win::VERSION_WIN7)
|
||||
EnableHighDPISupport();
|
||||
|
||||
content::ContentMainParams params(&delegate);
|
||||
params.instance = instance;
|
||||
params.sandbox_info = &sandbox_info;
|
||||
atom::AtomCommandLine::Init(arguments.argc, arguments.argv);
|
||||
atom::AtomCommandLine::Init(argc, argv);
|
||||
return content::ContentMain(params);
|
||||
}
|
||||
|
||||
#elif defined(OS_LINUX) // defined(OS_WIN)
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
#ifdef ENABLE_RUN_AS_NODE
|
||||
FixStdioStreams();
|
||||
|
||||
if (IsEnvSet(kRunAsNode)) {
|
||||
int main(int argc, const char* argv[]) {
|
||||
char* node_indicator = getenv("ATOM_SHELL_INTERNAL_RUN_AS_NODE");
|
||||
if (node_indicator != NULL && strcmp(node_indicator, "1") == 0) {
|
||||
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();
|
||||
|
||||
if (IsEnvSet(kRunAsNode)) {
|
||||
return AtomInitializeICUandStartNode(argc, argv);
|
||||
int main(int argc, const char* argv[]) {
|
||||
char* node_indicator = getenv("ATOM_SHELL_INTERNAL_RUN_AS_NODE");
|
||||
if (node_indicator != NULL && strcmp(node_indicator, "1") == 0) {
|
||||
return AtomInitializeICUandStartNode(argc, const_cast<char**>(argv));
|
||||
}
|
||||
#endif
|
||||
|
||||
return AtomMain(argc, argv);
|
||||
}
|
||||
|
||||
@@ -4,65 +4,40 @@
|
||||
|
||||
#include "atom/app/atom_main_delegate.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
#include "atom/app/atom_content_client.h"
|
||||
#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"
|
||||
#include "base/environment.h"
|
||||
#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 {
|
||||
|
||||
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) {
|
||||
// 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 +54,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) &&
|
||||
scoped_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,61 +72,41 @@ 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();
|
||||
|
||||
chrome::RegisterPathProvider();
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
SetUpBundleOverrides();
|
||||
#endif
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
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.
|
||||
scoped_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);
|
||||
|
||||
if (process_type == switches::kUtilityProcess) {
|
||||
AtomContentUtilityClient::PreSandboxStartup();
|
||||
}
|
||||
|
||||
// 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 +120,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();
|
||||
}
|
||||
|
||||
@@ -183,29 +130,20 @@ content::ContentUtilityClient* AtomMainDelegate::CreateContentUtilityClient() {
|
||||
return utility_client_.get();
|
||||
}
|
||||
|
||||
int AtomMainDelegate::RunProcess(
|
||||
const std::string& process_type,
|
||||
const content::MainFunctionParams& main_function_params) {
|
||||
if (process_type == kRelauncherProcess)
|
||||
return relauncher::RelauncherMain(main_function_params);
|
||||
else
|
||||
return -1;
|
||||
scoped_ptr<brightray::ContentClient> AtomMainDelegate::CreateContentClient() {
|
||||
return scoped_ptr<brightray::ContentClient>(new AtomContentClient).Pass();
|
||||
}
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
bool AtomMainDelegate::ShouldSendMachPort(const std::string& process_type) {
|
||||
return process_type != kRelauncherProcess;
|
||||
}
|
||||
|
||||
bool AtomMainDelegate::DelaySandboxInitialization(
|
||||
const std::string& process_type) {
|
||||
return process_type == kRelauncherProcess;
|
||||
}
|
||||
void AtomMainDelegate::AddDataPackFromPath(
|
||||
ui::ResourceBundle* bundle, const base::FilePath& pak_dir) {
|
||||
#if defined(OS_WIN)
|
||||
bundle->AddDataPackFromPath(
|
||||
pak_dir.Append(FILE_PATH_LITERAL("ui_resources_200_percent.pak")),
|
||||
ui::SCALE_FACTOR_200P);
|
||||
bundle->AddDataPackFromPath(
|
||||
pak_dir.Append(FILE_PATH_LITERAL("content_resources_200_percent.pak")),
|
||||
ui::SCALE_FACTOR_200P);
|
||||
#endif
|
||||
|
||||
std::unique_ptr<brightray::ContentClient>
|
||||
AtomMainDelegate::CreateContentClient() {
|
||||
return std::make_unique<AtomContentClient>();
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -5,17 +5,15 @@
|
||||
#ifndef ATOM_APP_ATOM_MAIN_DELEGATE_H_
|
||||
#define ATOM_APP_ATOM_MAIN_DELEGATE_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "brightray/common/content_client.h"
|
||||
#include "brightray/common/main_delegate.h"
|
||||
#include "brightray/common/content_client.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomMainDelegate : public brightray::MainDelegate {
|
||||
public:
|
||||
AtomMainDelegate();
|
||||
~AtomMainDelegate() override;
|
||||
~AtomMainDelegate();
|
||||
|
||||
protected:
|
||||
// content::ContentMainDelegate:
|
||||
@@ -24,29 +22,21 @@ class AtomMainDelegate : public brightray::MainDelegate {
|
||||
content::ContentBrowserClient* CreateContentBrowserClient() override;
|
||||
content::ContentRendererClient* CreateContentRendererClient() override;
|
||||
content::ContentUtilityClient* CreateContentUtilityClient() override;
|
||||
int RunProcess(
|
||||
const std::string& process_type,
|
||||
const content::MainFunctionParams& main_function_params) override;
|
||||
#if defined(OS_MACOSX)
|
||||
bool ShouldSendMachPort(const std::string& process_type) override;
|
||||
bool DelaySandboxInitialization(const std::string& process_type) override;
|
||||
#endif
|
||||
|
||||
// brightray::MainDelegate:
|
||||
std::unique_ptr<brightray::ContentClient> CreateContentClient() override;
|
||||
scoped_ptr<brightray::ContentClient> CreateContentClient() override;
|
||||
void AddDataPackFromPath(
|
||||
ui::ResourceBundle* bundle, const base::FilePath& pak_dir) override;
|
||||
#if defined(OS_MACOSX)
|
||||
void OverrideChildProcessPath() override;
|
||||
void OverrideFrameworkBundlePath() override;
|
||||
#endif
|
||||
|
||||
private:
|
||||
#if defined(OS_MACOSX)
|
||||
void SetUpBundleOverrides();
|
||||
#endif
|
||||
|
||||
std::unique_ptr<content::ContentBrowserClient> browser_client_;
|
||||
std::unique_ptr<content::ContentRendererClient> renderer_client_;
|
||||
std::unique_ptr<content::ContentUtilityClient> utility_client_;
|
||||
brightray::ContentClient content_client_;
|
||||
scoped_ptr<content::ContentBrowserClient> browser_client_;
|
||||
scoped_ptr<content::ContentRendererClient> renderer_client_;
|
||||
scoped_ptr<content::ContentUtilityClient> utility_client_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomMainDelegate);
|
||||
};
|
||||
|
||||
@@ -4,13 +4,10 @@
|
||||
|
||||
#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"
|
||||
#include "base/strings/sys_string_conversions.h"
|
||||
#include "brightray/common/application_info.h"
|
||||
#include "brightray/common/mac/main_application_bundle.h"
|
||||
#include "content/public/common/content_paths.h"
|
||||
@@ -20,17 +17,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,25 +38,14 @@ void AtomMainDelegate::OverrideFrameworkBundlePath() {
|
||||
|
||||
void AtomMainDelegate::OverrideChildProcessPath() {
|
||||
base::FilePath frameworks_path = GetFrameworksPath();
|
||||
base::FilePath helper_path =
|
||||
GetHelperAppPath(frameworks_path, ATOM_PRODUCT_NAME);
|
||||
base::FilePath helper_path = GetHelperAppPath(frameworks_path,
|
||||
ATOM_PRODUCT_NAME);
|
||||
if (!base::PathExists(helper_path))
|
||||
helper_path =
|
||||
GetHelperAppPath(frameworks_path, brightray::GetApplicationName());
|
||||
helper_path = GetHelperAppPath(frameworks_path,
|
||||
brightray::GetApplicationName());
|
||||
if (!base::PathExists(helper_path))
|
||||
LOG(FATAL) << "Unable to find helper app";
|
||||
PathService::Override(content::CHILD_PROCESS_EXE, helper_path);
|
||||
}
|
||||
|
||||
void AtomMainDelegate::SetUpBundleOverrides() {
|
||||
base::mac::ScopedNSAutoreleasePool pool;
|
||||
NSBundle* bundle = brightray::MainApplicationBundle();
|
||||
std::string base_bundle_id =
|
||||
base::SysNSStringToUTF8([bundle bundleIdentifier]);
|
||||
NSString* team_id = [bundle objectForInfoDictionaryKey:@"ElectronTeamID"];
|
||||
if (team_id)
|
||||
base_bundle_id = base::SysNSStringToUTF8(team_id) + "." + base_bundle_id;
|
||||
base::mac::SetBaseBundleID(base_bundle_id.c_str());
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -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,21 @@
|
||||
// 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 "atom/common/node_includes.h"
|
||||
#include "base/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;
|
||||
@@ -37,53 +27,28 @@ int NodeMain(int argc, char* argv[]) {
|
||||
scoped_refptr<UvTaskRunner> uv_task_runner(new UvTaskRunner(loop));
|
||||
base::ThreadTaskRunnerHandle handle(uv_task_runner);
|
||||
|
||||
// Initialize feature list.
|
||||
auto feature_list = std::make_unique<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 +62,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);
|
||||
env->Dispose();
|
||||
}
|
||||
|
||||
// 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;
|
||||
uv_timer_t* 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,31 +5,14 @@
|
||||
#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"
|
||||
#endif
|
||||
|
||||
namespace base {
|
||||
class FilePath;
|
||||
@@ -37,56 +20,21 @@ class FilePath;
|
||||
|
||||
namespace mate {
|
||||
class Arguments;
|
||||
} // namespace mate
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
#if defined(OS_WIN)
|
||||
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>,
|
||||
class App : public mate::EventEmitter,
|
||||
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);
|
||||
|
||||
#if defined(USE_NSS_CERTS)
|
||||
void OnCertificateManagerModelCreated(
|
||||
std::unique_ptr<base::DictionaryValue> options,
|
||||
const net::CompletionCallback& callback,
|
||||
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;
|
||||
App();
|
||||
virtual ~App();
|
||||
|
||||
// BrowserObserver:
|
||||
void OnBeforeQuit(bool* prevent_default) override;
|
||||
@@ -97,79 +45,21 @@ class App : public AtomBrowserClient::Delegate,
|
||||
void OnOpenURL(const std::string& url) override;
|
||||
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,
|
||||
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(
|
||||
bool* prevent_default,
|
||||
const std::string& type,
|
||||
const base::DictionaryValue& user_info) override;
|
||||
void OnNewWindowForTab() override;
|
||||
#endif
|
||||
|
||||
// content::ContentBrowserClient:
|
||||
void AllowCertificateError(
|
||||
content::WebContents* web_contents,
|
||||
int cert_error,
|
||||
const net::SSLInfo& ssl_info,
|
||||
const GURL& request_url,
|
||||
content::ResourceType resource_type,
|
||||
bool strict_enforcement,
|
||||
bool expired_previous_decision,
|
||||
const base::Callback<void(content::CertificateRequestResultType)>&
|
||||
callback) override;
|
||||
void SelectClientCertificate(
|
||||
void OnFinishLaunching() override;
|
||||
void OnSelectCertificate(
|
||||
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;
|
||||
scoped_ptr<content::ClientCertificateDelegate> delegate) override;
|
||||
void OnLogin(LoginHandler* login_handler) override;
|
||||
|
||||
// content::GpuDataManagerObserver:
|
||||
void OnGpuProcessCrashed(base::TerminationStatus status) override;
|
||||
void OnGpuProcessCrashed(base::TerminationStatus exit_code) 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;
|
||||
// mate::Wrappable:
|
||||
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) 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,
|
||||
@@ -177,59 +67,15 @@ class App : public AtomBrowserClient::Delegate,
|
||||
const base::FilePath& path);
|
||||
|
||||
void SetDesktopName(const std::string& desktop_name);
|
||||
void AllowNTLMCredentialsForAllDomains(bool should_allow);
|
||||
bool MakeSingleInstance(
|
||||
const ProcessSingleton::NotificationCallback& callback);
|
||||
std::string GetLocale();
|
||||
void OnSecondInstance(const base::CommandLine::StringVector& cmd,
|
||||
const base::FilePath& cwd);
|
||||
bool HasSingleInstanceLock() const;
|
||||
bool RequestSingleInstanceLock();
|
||||
void ReleaseSingleInstanceLock();
|
||||
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);
|
||||
v8::Local<v8::Value> DefaultSession(v8::Isolate* isolate);
|
||||
|
||||
std::vector<mate::Dictionary> GetAppMetrics(v8::Isolate* isolate);
|
||||
v8::Local<v8::Value> GetGPUFeatureStatus(v8::Isolate* isolate);
|
||||
void EnableMixedSandbox(mate::Arguments* args);
|
||||
v8::Global<v8::Value> default_session_;
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
bool MoveToApplicationsFolder(mate::Arguments* args);
|
||||
bool IsInApplicationsFolder();
|
||||
#endif
|
||||
#if defined(MAS_BUILD)
|
||||
base::Callback<void()> StartAccessingSecurityScopedResource(
|
||||
mate::Arguments* args);
|
||||
#endif
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// Get the current Jump List settings.
|
||||
v8::Local<v8::Value> GetJumpListSettings();
|
||||
|
||||
// Set or remove a custom Jump List for the application.
|
||||
JumpListResult SetJumpList(v8::Local<v8::Value> val, mate::Arguments* args);
|
||||
#endif // defined(OS_WIN)
|
||||
|
||||
std::unique_ptr<ProcessSingleton> process_singleton_;
|
||||
|
||||
#if defined(USE_NSS_CERTS)
|
||||
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_;
|
||||
scoped_ptr<ProcessSingleton> process_singleton_;
|
||||
|
||||
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
|
||||
@@ -4,24 +4,23 @@
|
||||
|
||||
#include "atom/browser/api/atom_api_auto_updater.h"
|
||||
|
||||
#include "base/time/time.h"
|
||||
#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"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/object_template_builder.h"
|
||||
|
||||
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
|
||||
@@ -35,9 +34,8 @@ namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
AutoUpdater::AutoUpdater(v8::Isolate* isolate) {
|
||||
AutoUpdater::AutoUpdater() {
|
||||
auto_updater::AutoUpdater::SetDelegate(this);
|
||||
Init(isolate);
|
||||
}
|
||||
|
||||
AutoUpdater::~AutoUpdater() {
|
||||
@@ -48,31 +46,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,58 +78,47 @@ void AutoUpdater::OnWindowAllClosed() {
|
||||
QuitAndInstall();
|
||||
}
|
||||
|
||||
void AutoUpdater::SetFeedURL(mate::Arguments* args) {
|
||||
auto_updater::AutoUpdater::SetFeedURL(args);
|
||||
mate::ObjectTemplateBuilder AutoUpdater::GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) {
|
||||
return mate::ObjectTemplateBuilder(isolate)
|
||||
.SetMethod("setFeedUrl", &auto_updater::AutoUpdater::SetFeedURL)
|
||||
.SetMethod("checkForUpdates", &auto_updater::AutoUpdater::CheckForUpdates)
|
||||
.SetMethod("quitAndInstall", &AutoUpdater::QuitAndInstall);
|
||||
}
|
||||
|
||||
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
|
||||
mate::Handle<AutoUpdater> AutoUpdater::Create(v8::Isolate* isolate) {
|
||||
return mate::CreateHandle(isolate, new AutoUpdater(isolate));
|
||||
}
|
||||
|
||||
// static
|
||||
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)
|
||||
.SetMethod("getFeedURL", &auto_updater::AutoUpdater::GetFeedURL)
|
||||
.SetMethod("setFeedURL", &AutoUpdater::SetFeedURL)
|
||||
.SetMethod("quitAndInstall", &AutoUpdater::QuitAndInstall);
|
||||
return CreateHandle(isolate, new AutoUpdater);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // 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));
|
||||
dict.Set("AutoUpdater", AutoUpdater::GetConstructor(isolate)->GetFunction());
|
||||
dict.Set("autoUpdater", atom::api::AutoUpdater::Create(isolate));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_auto_updater, Initialize)
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_auto_updater, Initialize)
|
||||
|
||||
@@ -10,31 +10,24 @@
|
||||
#include "atom/browser/api/event_emitter.h"
|
||||
#include "atom/browser/auto_updater.h"
|
||||
#include "atom/browser/window_list_observer.h"
|
||||
#include "native_mate/arguments.h"
|
||||
#include "native_mate/handle.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class AutoUpdater : public mate::EventEmitter<AutoUpdater>,
|
||||
class AutoUpdater : public mate::EventEmitter,
|
||||
public auto_updater::Delegate,
|
||||
public WindowListObserver {
|
||||
public:
|
||||
static mate::Handle<AutoUpdater> Create(v8::Isolate* isolate);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
protected:
|
||||
explicit AutoUpdater(v8::Isolate* isolate);
|
||||
~AutoUpdater() override;
|
||||
AutoUpdater();
|
||||
virtual ~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;
|
||||
@@ -46,9 +39,11 @@ class AutoUpdater : public mate::EventEmitter<AutoUpdater>,
|
||||
// WindowListObserver:
|
||||
void OnWindowAllClosed() override;
|
||||
|
||||
// mate::Wrappable implementations:
|
||||
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) override;
|
||||
|
||||
private:
|
||||
std::string GetFeedURL();
|
||||
void SetFeedURL(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,44 +7,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/value_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,
|
||||
base::trace_event::TraceConfig* out) {
|
||||
// (alexeykuzmin): A combination of "categoryFilter" and "traceOptions"
|
||||
// has to be checked first because none of the fields
|
||||
// in the `memory_dump_config` dict below are mandatory
|
||||
// and we cannot check the config format.
|
||||
Dictionary options;
|
||||
if (ConvertFromV8(isolate, val, &options)) {
|
||||
std::string category_filter, trace_options;
|
||||
if (options.Get("categoryFilter", &category_filter) &&
|
||||
options.Get("traceOptions", &trace_options)) {
|
||||
*out = base::trace_event::TraceConfig(category_filter, trace_options);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
base::DictionaryValue memory_dump_config;
|
||||
if (ConvertFromV8(isolate, val, &memory_dump_config)) {
|
||||
*out = base::trace_event::TraceConfig(memory_dump_config);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
if (!ConvertFromV8(isolate, val, &options))
|
||||
return false;
|
||||
std::string category_filter, trace_options;
|
||||
if (!options.Get("categoryFilter", &category_filter) ||
|
||||
!options.Get("traceOptions", &trace_options))
|
||||
return false;
|
||||
*out = base::trace_event::TraceConfig(category_filter, trace_options);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -54,39 +40,51 @@ 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));
|
||||
TracingController::GetInstance()->DisableRecording(
|
||||
GetTraceDataSink(path, callback));
|
||||
}
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
void CaptureMonitoringSnapshot(const base::FilePath& path,
|
||||
const CompletionCallback& callback) {
|
||||
TracingController::GetInstance()->CaptureMonitoringSnapshot(
|
||||
GetTraceDataSink(path, callback));
|
||||
}
|
||||
|
||||
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::EnableRecording, controller));
|
||||
dict.SetMethod("stopRecording", &StopRecording);
|
||||
dict.SetMethod(
|
||||
"getTraceBufferUsage",
|
||||
base::Bind(&TracingController::GetTraceBufferUsage, controller));
|
||||
dict.SetMethod("startMonitoring", base::Bind(
|
||||
&TracingController::EnableMonitoring, controller));
|
||||
dict.SetMethod("stopMonitoring", base::Bind(
|
||||
&TracingController::DisableMonitoring, controller));
|
||||
dict.SetMethod("captureMonitoringSnapshot", &CaptureMonitoringSnapshot);
|
||||
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)
|
||||
|
||||
@@ -4,39 +4,156 @@
|
||||
|
||||
#include "atom/browser/api/atom_api_cookies.h"
|
||||
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/cookie_change_notifier.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "base/bind.h"
|
||||
#include "base/time/time.h"
|
||||
#include "base/values.h"
|
||||
#include "content/public/browser/browser_context.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/object_template_builder.h"
|
||||
#include "net/cookies/canonical_cookie.h"
|
||||
#include "net/cookies/cookie_monster.h"
|
||||
#include "net/cookies/cookie_store.h"
|
||||
#include "net/cookies/cookie_util.h"
|
||||
#include "net/url_request/url_request_context.h"
|
||||
#include "net/url_request/url_request_context_getter.h"
|
||||
|
||||
using atom::api::Cookies;
|
||||
using content::BrowserThread;
|
||||
|
||||
namespace {
|
||||
|
||||
bool GetCookieListFromStore(
|
||||
net::CookieStore* cookie_store,
|
||||
const std::string& url,
|
||||
const net::CookieMonster::GetCookieListCallback& callback) {
|
||||
DCHECK(cookie_store);
|
||||
GURL gurl(url);
|
||||
net::CookieMonster* monster = cookie_store->GetCookieMonster();
|
||||
// Empty url will match all url cookies.
|
||||
if (url.empty()) {
|
||||
monster->GetAllCookiesAsync(callback);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!gurl.is_valid())
|
||||
return false;
|
||||
|
||||
monster->GetAllCookiesForURLAsync(gurl, callback);
|
||||
return true;
|
||||
}
|
||||
|
||||
void RunGetCookiesCallbackOnUIThread(v8::Isolate* isolate,
|
||||
const std::string& error_message,
|
||||
const net::CookieList& cookie_list,
|
||||
const Cookies::CookiesCallback& callback) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
|
||||
v8::Locker locker(isolate);
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
|
||||
if (!error_message.empty()) {
|
||||
v8::Local<v8::Value> error = mate::ConvertToV8(isolate, error_message);
|
||||
callback.Run(error, v8::Null(isolate));
|
||||
return;
|
||||
}
|
||||
callback.Run(v8::Null(isolate), mate::ConvertToV8(isolate, cookie_list));
|
||||
}
|
||||
|
||||
void RunRemoveCookiesCallbackOnUIThread(
|
||||
v8::Isolate* isolate,
|
||||
const std::string& error_message,
|
||||
const Cookies::CookiesCallback& callback) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
|
||||
v8::Locker locker(isolate);
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
|
||||
if (!error_message.empty()) {
|
||||
v8::Local<v8::Value> error = mate::ConvertToV8(isolate, error_message);
|
||||
callback.Run(error, v8::Null(isolate));
|
||||
return;
|
||||
}
|
||||
|
||||
callback.Run(v8::Null(isolate), v8::Null(isolate));
|
||||
}
|
||||
|
||||
void RunSetCookiesCallbackOnUIThread(v8::Isolate* isolate,
|
||||
const std::string& error_message,
|
||||
bool set_success,
|
||||
const Cookies::CookiesCallback& callback) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
|
||||
v8::Locker locker(isolate);
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
|
||||
if (!error_message.empty()) {
|
||||
v8::Local<v8::Value> error = mate::ConvertToV8(isolate, error_message);
|
||||
callback.Run(error, v8::Null(isolate));
|
||||
return;
|
||||
}
|
||||
if (!set_success) {
|
||||
v8::Local<v8::Value> error = mate::ConvertToV8(
|
||||
isolate, "Failed to set cookies");
|
||||
callback.Run(error, v8::Null(isolate));
|
||||
}
|
||||
|
||||
callback.Run(v8::Null(isolate), v8::Null(isolate));
|
||||
}
|
||||
|
||||
bool MatchesDomain(const base::DictionaryValue* filter,
|
||||
const std::string& cookie_domain) {
|
||||
std::string filter_domain;
|
||||
if (!filter->GetString("domain", &filter_domain))
|
||||
return true;
|
||||
|
||||
// Add a leading '.' character to the filter domain if it doesn't exist.
|
||||
if (net::cookie_util::DomainIsHostOnly(filter_domain))
|
||||
filter_domain.insert(0, ".");
|
||||
|
||||
std::string sub_domain(cookie_domain);
|
||||
// Strip any leading '.' character from the input cookie domain.
|
||||
if (!net::cookie_util::DomainIsHostOnly(sub_domain))
|
||||
sub_domain = sub_domain.substr(1);
|
||||
|
||||
// Now check whether the domain argument is a subdomain of the filter domain.
|
||||
for (sub_domain.insert(0, ".");
|
||||
sub_domain.length() >= filter_domain.length();) {
|
||||
if (sub_domain == filter_domain) {
|
||||
return true;
|
||||
}
|
||||
const size_t next_dot = sub_domain.find('.', 1); // Skip over leading dot.
|
||||
sub_domain.erase(0, next_dot);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MatchesCookie(const base::DictionaryValue* filter,
|
||||
const net::CanonicalCookie& cookie) {
|
||||
std::string name, domain, path;
|
||||
bool is_secure, session;
|
||||
if (filter->GetString("name", &name) && name != cookie.Name())
|
||||
return false;
|
||||
if (filter->GetString("path", &path) && path != cookie.Path())
|
||||
return false;
|
||||
if (!MatchesDomain(filter, cookie.Domain()))
|
||||
return false;
|
||||
if (filter->GetBoolean("secure", &is_secure) &&
|
||||
is_secure != cookie.IsSecure())
|
||||
return false;
|
||||
if (filter->GetBoolean("session", &session) &&
|
||||
session != cookie.IsPersistent())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace mate {
|
||||
|
||||
template <>
|
||||
struct Converter<atom::api::Cookies::Error> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
atom::api::Cookies::Error val) {
|
||||
if (val == atom::api::Cookies::SUCCESS)
|
||||
return v8::Null(isolate);
|
||||
else
|
||||
return v8::Exception::Error(StringToV8(isolate, "Setting cookie failed"));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
template<>
|
||||
struct Converter<net::CanonicalCookie> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
const net::CanonicalCookie& val) {
|
||||
@@ -44,281 +161,184 @@ struct Converter<net::CanonicalCookie> {
|
||||
dict.Set("name", val.Name());
|
||||
dict.Set("value", val.Value());
|
||||
dict.Set("domain", val.Domain());
|
||||
dict.Set("hostOnly", net::cookie_util::DomainIsHostOnly(val.Domain()));
|
||||
dict.Set("host_only", net::cookie_util::DomainIsHostOnly(val.Domain()));
|
||||
dict.Set("path", val.Path());
|
||||
dict.Set("secure", val.IsSecure());
|
||||
dict.Set("httpOnly", val.IsHttpOnly());
|
||||
dict.Set("session", !val.IsPersistent());
|
||||
if (val.IsPersistent())
|
||||
dict.Set("http_only", val.IsHttpOnly());
|
||||
dict.Set("session", val.IsPersistent());
|
||||
if (!val.IsPersistent())
|
||||
dict.Set("expirationDate", val.ExpiryDate().ToDoubleT());
|
||||
return dict.GetHandle();
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<network::mojom::CookieChangeCause> {
|
||||
static v8::Local<v8::Value> ToV8(
|
||||
v8::Isolate* isolate,
|
||||
const network::mojom::CookieChangeCause& val) {
|
||||
switch (val) {
|
||||
case network::mojom::CookieChangeCause::INSERTED:
|
||||
case network::mojom::CookieChangeCause::EXPLICIT:
|
||||
return mate::StringToV8(isolate, "explicit");
|
||||
case network::mojom::CookieChangeCause::OVERWRITE:
|
||||
return mate::StringToV8(isolate, "overwrite");
|
||||
case network::mojom::CookieChangeCause::EXPIRED:
|
||||
return mate::StringToV8(isolate, "expired");
|
||||
case network::mojom::CookieChangeCause::EVICTED:
|
||||
return mate::StringToV8(isolate, "evicted");
|
||||
case network::mojom::CookieChangeCause::EXPIRED_OVERWRITE:
|
||||
return mate::StringToV8(isolate, "expired-overwrite");
|
||||
default:
|
||||
return mate::StringToV8(isolate, "unknown");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
namespace {
|
||||
Cookies::Cookies(content::BrowserContext* browser_context)
|
||||
: request_context_getter_(browser_context->GetRequestContext()) {
|
||||
}
|
||||
|
||||
// Returns whether |domain| matches |filter|.
|
||||
bool MatchesDomain(std::string filter, const std::string& domain) {
|
||||
// Add a leading '.' character to the filter domain if it doesn't exist.
|
||||
if (net::cookie_util::DomainIsHostOnly(filter))
|
||||
filter.insert(0, ".");
|
||||
Cookies::~Cookies() {
|
||||
}
|
||||
|
||||
std::string sub_domain(domain);
|
||||
// Strip any leading '.' character from the input cookie domain.
|
||||
if (!net::cookie_util::DomainIsHostOnly(sub_domain))
|
||||
sub_domain = sub_domain.substr(1);
|
||||
void Cookies::Get(const base::DictionaryValue& options,
|
||||
const CookiesCallback& callback) {
|
||||
scoped_ptr<base::DictionaryValue> filter(
|
||||
options.DeepCopyWithoutEmptyChildren());
|
||||
|
||||
// Now check whether the domain argument is a subdomain of the filter domain.
|
||||
for (sub_domain.insert(0, "."); sub_domain.length() >= filter.length();) {
|
||||
if (sub_domain == filter)
|
||||
return true;
|
||||
const size_t next_dot = sub_domain.find('.', 1); // Skip over leading dot.
|
||||
sub_domain.erase(0, next_dot);
|
||||
content::BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&Cookies::GetCookiesOnIOThread, base::Unretained(this),
|
||||
Passed(&filter), callback));
|
||||
}
|
||||
|
||||
void Cookies::GetCookiesOnIOThread(scoped_ptr<base::DictionaryValue> filter,
|
||||
const CookiesCallback& callback) {
|
||||
std::string url;
|
||||
filter->GetString("url", &url);
|
||||
if (!GetCookieListFromStore(GetCookieStore(), url,
|
||||
base::Bind(&Cookies::OnGetCookies, base::Unretained(this),
|
||||
Passed(&filter), callback))) {
|
||||
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
|
||||
base::Bind(&RunGetCookiesCallbackOnUIThread, isolate(),
|
||||
"Url is not valid", net::CookieList(), callback));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns whether |cookie| matches |filter|.
|
||||
bool MatchesCookie(const base::DictionaryValue* filter,
|
||||
const net::CanonicalCookie& cookie) {
|
||||
std::string str;
|
||||
bool b;
|
||||
if (filter->GetString("name", &str) && str != cookie.Name())
|
||||
return false;
|
||||
if (filter->GetString("path", &str) && str != cookie.Path())
|
||||
return false;
|
||||
if (filter->GetString("domain", &str) && !MatchesDomain(str, cookie.Domain()))
|
||||
return false;
|
||||
if (filter->GetBoolean("secure", &b) && b != cookie.IsSecure())
|
||||
return false;
|
||||
if (filter->GetBoolean("session", &b) && b != !cookie.IsPersistent())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Helper to returns the CookieStore.
|
||||
inline net::CookieStore* GetCookieStore(
|
||||
scoped_refptr<net::URLRequestContextGetter> getter) {
|
||||
return getter->GetURLRequestContext()->cookie_store();
|
||||
}
|
||||
|
||||
// Run |callback| on UI thread.
|
||||
void RunCallbackInUI(const base::Closure& callback) {
|
||||
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
|
||||
}
|
||||
|
||||
// Remove cookies from |list| not matching |filter|, and pass it to |callback|.
|
||||
void FilterCookies(std::unique_ptr<base::DictionaryValue> filter,
|
||||
const Cookies::GetCallback& callback,
|
||||
const net::CookieList& list) {
|
||||
void Cookies::OnGetCookies(scoped_ptr<base::DictionaryValue> filter,
|
||||
const CookiesCallback& callback,
|
||||
const net::CookieList& cookie_list) {
|
||||
net::CookieList result;
|
||||
for (const auto& cookie : list) {
|
||||
for (const auto& cookie : cookie_list) {
|
||||
if (MatchesCookie(filter.get(), cookie))
|
||||
result.push_back(cookie);
|
||||
}
|
||||
RunCallbackInUI(base::Bind(callback, Cookies::SUCCESS, result));
|
||||
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
|
||||
&RunGetCookiesCallbackOnUIThread, isolate(), "", result, callback));
|
||||
}
|
||||
|
||||
// Receives cookies matching |filter| in IO thread.
|
||||
void GetCookiesOnIO(scoped_refptr<net::URLRequestContextGetter> getter,
|
||||
std::unique_ptr<base::DictionaryValue> filter,
|
||||
const Cookies::GetCallback& callback) {
|
||||
void Cookies::Remove(const mate::Dictionary& details,
|
||||
const CookiesCallback& callback) {
|
||||
GURL url;
|
||||
std::string name;
|
||||
std::string error_message;
|
||||
if (!details.Get("url", &url) || !details.Get("name", &name)) {
|
||||
error_message = "Details(url, name) of removing cookie are required.";
|
||||
}
|
||||
if (error_message.empty() && !url.is_valid()) {
|
||||
error_message = "Url is not valid.";
|
||||
}
|
||||
if (!error_message.empty()) {
|
||||
RunRemoveCookiesCallbackOnUIThread(isolate(), error_message, callback);
|
||||
return;
|
||||
}
|
||||
content::BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&Cookies::RemoveCookiesOnIOThread, base::Unretained(this),
|
||||
url, name, callback));
|
||||
}
|
||||
|
||||
void Cookies::RemoveCookiesOnIOThread(const GURL& url, const std::string& name,
|
||||
const CookiesCallback& callback) {
|
||||
GetCookieStore()->DeleteCookieAsync(url, name,
|
||||
base::Bind(&Cookies::OnRemoveCookies, base::Unretained(this), callback));
|
||||
}
|
||||
|
||||
void Cookies::OnRemoveCookies(const CookiesCallback& callback) {
|
||||
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
|
||||
base::Bind(&RunRemoveCookiesCallbackOnUIThread, isolate(), "", callback));
|
||||
}
|
||||
|
||||
void Cookies::Set(const base::DictionaryValue& options,
|
||||
const CookiesCallback& callback) {
|
||||
std::string url;
|
||||
filter->GetString("url", &url);
|
||||
std::string error_message;
|
||||
if (!options.GetString("url", &url)) {
|
||||
error_message = "The url field is required.";
|
||||
}
|
||||
|
||||
auto filtered_callback =
|
||||
base::Bind(FilterCookies, base::Passed(&filter), callback);
|
||||
GURL gurl(url);
|
||||
if (error_message.empty() && !gurl.is_valid()) {
|
||||
error_message = "Url is not valid.";
|
||||
}
|
||||
|
||||
// Empty url will match all url cookies.
|
||||
if (url.empty())
|
||||
GetCookieStore(getter)->GetAllCookiesAsync(filtered_callback);
|
||||
else
|
||||
GetCookieStore(getter)->GetAllCookiesForURLAsync(GURL(url),
|
||||
filtered_callback);
|
||||
if (!error_message.empty()) {
|
||||
RunSetCookiesCallbackOnUIThread(isolate(), error_message, false, callback);
|
||||
return;
|
||||
}
|
||||
|
||||
scoped_ptr<base::DictionaryValue> details(
|
||||
options.DeepCopyWithoutEmptyChildren());
|
||||
|
||||
content::BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&Cookies::SetCookiesOnIOThread, base::Unretained(this),
|
||||
Passed(&details), gurl, 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 base::Closure& callback) {
|
||||
GetCookieStore(getter)->DeleteCookieAsync(
|
||||
url, name, base::BindOnce(RunCallbackInUI, callback));
|
||||
}
|
||||
void Cookies::SetCookiesOnIOThread(scoped_ptr<base::DictionaryValue> details,
|
||||
const GURL& url,
|
||||
const CookiesCallback& callback) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
||||
|
||||
// Callback of SetCookie.
|
||||
void OnSetCookie(const Cookies::SetCallback& callback, bool success) {
|
||||
RunCallbackInUI(
|
||||
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,
|
||||
const Cookies::SetCallback& callback) {
|
||||
std::string url, name, value, domain, path;
|
||||
std::string name, value, domain, path;
|
||||
bool secure = false;
|
||||
bool http_only = false;
|
||||
double creation_date;
|
||||
double expiration_date;
|
||||
double last_access_date;
|
||||
details->GetString("url", &url);
|
||||
|
||||
details->GetString("name", &name);
|
||||
details->GetString("value", &value);
|
||||
details->GetString("domain", &domain);
|
||||
details->GetString("path", &path);
|
||||
details->GetBoolean("secure", &secure);
|
||||
details->GetBoolean("httpOnly", &http_only);
|
||||
|
||||
base::Time creation_time;
|
||||
if (details->GetDouble("creationDate", &creation_date)) {
|
||||
creation_time = (creation_date == 0)
|
||||
? base::Time::UnixEpoch()
|
||||
: base::Time::FromDoubleT(creation_date);
|
||||
}
|
||||
details->GetBoolean("http_only", &http_only);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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()->GetCookieMonster()->SetCookieWithDetailsAsync(
|
||||
url,
|
||||
name,
|
||||
value,
|
||||
domain,
|
||||
path,
|
||||
expiration_time,
|
||||
secure,
|
||||
http_only,
|
||||
false,
|
||||
net::COOKIE_PRIORITY_DEFAULT,
|
||||
base::Bind(&Cookies::OnSetCookies, base::Unretained(this), callback));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Cookies::Cookies(v8::Isolate* isolate, AtomBrowserContext* browser_context)
|
||||
: browser_context_(browser_context) {
|
||||
Init(isolate);
|
||||
cookie_change_subscription_ =
|
||||
browser_context_->cookie_change_notifier()->RegisterCookieChangeCallback(
|
||||
base::Bind(&Cookies::OnCookieChanged, base::Unretained(this)));
|
||||
void Cookies::OnSetCookies(const CookiesCallback& callback,
|
||||
bool set_success) {
|
||||
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
|
||||
base::Bind(&RunSetCookiesCallbackOnUIThread, isolate(), "", set_success,
|
||||
callback));
|
||||
}
|
||||
|
||||
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();
|
||||
content::BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::BindOnce(GetCookiesOnIO, base::RetainedRef(getter),
|
||||
std::move(copied), callback));
|
||||
}
|
||||
|
||||
void Cookies::Remove(const GURL& url,
|
||||
const std::string& name,
|
||||
const base::Closure& callback) {
|
||||
auto* getter = browser_context_->GetRequestContext();
|
||||
content::BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::BindOnce(RemoveCookieOnIOThread, base::RetainedRef(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();
|
||||
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);
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<Cookies> Cookies::Create(v8::Isolate* isolate,
|
||||
AtomBrowserContext* browser_context) {
|
||||
return mate::CreateHandle(isolate, new Cookies(isolate, browser_context));
|
||||
}
|
||||
|
||||
// static
|
||||
void Cookies::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "Cookies"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
mate::ObjectTemplateBuilder Cookies::GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) {
|
||||
return mate::ObjectTemplateBuilder(isolate)
|
||||
.SetMethod("get", &Cookies::Get)
|
||||
.SetMethod("remove", &Cookies::Remove)
|
||||
.SetMethod("set", &Cookies::Set)
|
||||
.SetMethod("flushStore", &Cookies::FlushStore);
|
||||
.SetMethod("set", &Cookies::Set);
|
||||
}
|
||||
|
||||
net::CookieStore* Cookies::GetCookieStore() {
|
||||
return request_context_getter_->GetURLRequestContext()->cookie_store();
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<Cookies> Cookies::Create(
|
||||
v8::Isolate* isolate,
|
||||
content::BrowserContext* browser_context) {
|
||||
return mate::CreateHandle(isolate, new Cookies(browser_context));
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
@@ -7,9 +7,8 @@
|
||||
|
||||
#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/wrappable.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "net/cookies/canonical_cookie.h"
|
||||
|
||||
@@ -17,51 +16,69 @@ namespace base {
|
||||
class DictionaryValue;
|
||||
}
|
||||
|
||||
namespace content {
|
||||
class BrowserContext;
|
||||
}
|
||||
|
||||
namespace mate {
|
||||
class Dictionary;
|
||||
}
|
||||
|
||||
namespace net {
|
||||
class CookieStore;
|
||||
class URLRequestContextGetter;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomBrowserContext;
|
||||
|
||||
namespace api {
|
||||
|
||||
class Cookies : public mate::TrackableObject<Cookies> {
|
||||
class Cookies : public mate::Wrappable {
|
||||
public:
|
||||
enum Error {
|
||||
SUCCESS,
|
||||
FAILED,
|
||||
};
|
||||
|
||||
using GetCallback = base::Callback<void(Error, const net::CookieList&)>;
|
||||
using SetCallback = base::Callback<void(Error)>;
|
||||
// node.js style callback function(error, result)
|
||||
typedef base::Callback<void(v8::Local<v8::Value>, v8::Local<v8::Value>)>
|
||||
CookiesCallback;
|
||||
|
||||
static mate::Handle<Cookies> Create(v8::Isolate* isolate,
|
||||
AtomBrowserContext* browser_context);
|
||||
|
||||
// mate::TrackableObject:
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
content::BrowserContext* browser_context);
|
||||
|
||||
protected:
|
||||
Cookies(v8::Isolate* isolate, AtomBrowserContext* browser_context);
|
||||
~Cookies() override;
|
||||
explicit Cookies(content::BrowserContext* browser_context);
|
||||
~Cookies();
|
||||
|
||||
void Get(const base::DictionaryValue& filter, const GetCallback& callback);
|
||||
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);
|
||||
void Get(const base::DictionaryValue& options,
|
||||
const CookiesCallback& callback);
|
||||
void Remove(const mate::Dictionary& details,
|
||||
const CookiesCallback& callback);
|
||||
void Set(const base::DictionaryValue& details,
|
||||
const CookiesCallback& callback);
|
||||
|
||||
// CookieChangeNotifier subscription:
|
||||
void OnCookieChanged(const CookieDetails*);
|
||||
void GetCookiesOnIOThread(scoped_ptr<base::DictionaryValue> filter,
|
||||
const CookiesCallback& callback);
|
||||
void OnGetCookies(scoped_ptr<base::DictionaryValue> filter,
|
||||
const CookiesCallback& callback,
|
||||
const net::CookieList& cookie_list);
|
||||
|
||||
void RemoveCookiesOnIOThread(const GURL& url,
|
||||
const std::string& name,
|
||||
const CookiesCallback& callback);
|
||||
void OnRemoveCookies(const CookiesCallback& callback);
|
||||
|
||||
void SetCookiesOnIOThread(scoped_ptr<base::DictionaryValue> details,
|
||||
const GURL& url,
|
||||
const CookiesCallback& callback);
|
||||
void OnSetCookies(const CookiesCallback& callback,
|
||||
bool set_success);
|
||||
|
||||
// mate::Wrappable:
|
||||
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<base::CallbackList<void(const CookieDetails*)>::Subscription>
|
||||
cookie_change_subscription_;
|
||||
scoped_refptr<AtomBrowserContext> browser_context_;
|
||||
// Must be called on IO thread.
|
||||
net::CookieStore* GetCookieStore();
|
||||
|
||||
net::URLRequestContextGetter* request_context_getter_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Cookies);
|
||||
};
|
||||
|
||||
@@ -1,196 +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_debugger.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "base/json/json_reader.h"
|
||||
#include "base/json/json_writer.h"
|
||||
#include "content/public/browser/devtools_agent_host.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
using content::DevToolsAgentHost;
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
Debugger::Debugger(v8::Isolate* isolate, content::WebContents* web_contents)
|
||||
: content::WebContentsObserver(web_contents), web_contents_(web_contents) {
|
||||
Init(isolate);
|
||||
}
|
||||
|
||||
Debugger::~Debugger() {}
|
||||
|
||||
void Debugger::AgentHostClosed(DevToolsAgentHost* agent_host) {
|
||||
DCHECK(agent_host == agent_host_);
|
||||
agent_host_ = nullptr;
|
||||
ClearPendingRequests();
|
||||
Emit("detach", "target closed");
|
||||
}
|
||||
|
||||
void Debugger::DispatchProtocolMessage(DevToolsAgentHost* agent_host,
|
||||
const std::string& message) {
|
||||
DCHECK(agent_host == agent_host_);
|
||||
|
||||
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())
|
||||
return;
|
||||
base::DictionaryValue* dict =
|
||||
static_cast<base::DictionaryValue*>(parsed_message.get());
|
||||
int id;
|
||||
if (!dict->GetInteger("id", &id)) {
|
||||
std::string method;
|
||||
if (!dict->GetString("method", &method))
|
||||
return;
|
||||
base::DictionaryValue* params_value = nullptr;
|
||||
base::DictionaryValue params;
|
||||
if (dict->GetDictionary("params", ¶ms_value))
|
||||
params.Swap(params_value);
|
||||
Emit("message", method, params);
|
||||
} else {
|
||||
auto send_command_callback = pending_requests_[id];
|
||||
pending_requests_.erase(id);
|
||||
if (send_command_callback.is_null())
|
||||
return;
|
||||
base::DictionaryValue* error_body = nullptr;
|
||||
base::DictionaryValue error;
|
||||
if (dict->GetDictionary("error", &error_body))
|
||||
error.Swap(error_body);
|
||||
|
||||
base::DictionaryValue* result_body = nullptr;
|
||||
base::DictionaryValue result;
|
||||
if (dict->GetDictionary("result", &result_body))
|
||||
result.Swap(result_body);
|
||||
send_command_callback.Run(error, result);
|
||||
}
|
||||
}
|
||||
|
||||
void Debugger::RenderFrameHostChanged(content::RenderFrameHost* old_rfh,
|
||||
content::RenderFrameHost* new_rfh) {
|
||||
if (agent_host_) {
|
||||
agent_host_->DisconnectWebContents();
|
||||
auto* web_contents = content::WebContents::FromRenderFrameHost(new_rfh);
|
||||
agent_host_->ConnectWebContents(web_contents);
|
||||
}
|
||||
}
|
||||
|
||||
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_) {
|
||||
args->ThrowError("No target available");
|
||||
return;
|
||||
}
|
||||
|
||||
agent_host_->AttachClient(this);
|
||||
}
|
||||
|
||||
bool Debugger::IsAttached() {
|
||||
return agent_host_ && agent_host_->IsAttached();
|
||||
}
|
||||
|
||||
void Debugger::Detach() {
|
||||
if (!agent_host_)
|
||||
return;
|
||||
agent_host_->DetachClient(this);
|
||||
AgentHostClosed(agent_host_.get());
|
||||
}
|
||||
|
||||
void Debugger::SendCommand(mate::Arguments* args) {
|
||||
if (!agent_host_)
|
||||
return;
|
||||
|
||||
std::string method;
|
||||
if (!args->GetNext(&method)) {
|
||||
args->ThrowError();
|
||||
return;
|
||||
}
|
||||
base::DictionaryValue command_params;
|
||||
args->GetNext(&command_params);
|
||||
SendCommandCallback callback;
|
||||
args->GetNext(&callback);
|
||||
|
||||
base::DictionaryValue request;
|
||||
int request_id = ++previous_request_id_;
|
||||
pending_requests_[request_id] = callback;
|
||||
request.SetInteger("id", request_id);
|
||||
request.SetString("method", method);
|
||||
if (!command_params.empty())
|
||||
request.Set("params", base::WrapUnique(command_params.DeepCopy()));
|
||||
|
||||
std::string json_args;
|
||||
base::JSONWriter::Write(request, &json_args);
|
||||
agent_host_->DispatchProtocolMessage(this, json_args);
|
||||
}
|
||||
|
||||
void Debugger::ClearPendingRequests() {
|
||||
if (pending_requests_.empty())
|
||||
return;
|
||||
base::Value error(base::Value::Type::DICTIONARY);
|
||||
base::Value error_msg("target closed while handling command");
|
||||
error.SetKey("message", std::move(error_msg));
|
||||
for (const auto& it : pending_requests_)
|
||||
it.second.Run(error, base::Value());
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<Debugger> Debugger::Create(v8::Isolate* isolate,
|
||||
content::WebContents* web_contents) {
|
||||
return mate::CreateHandle(isolate, new Debugger(isolate, web_contents));
|
||||
}
|
||||
|
||||
// static
|
||||
void Debugger::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "Debugger"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetMethod("attach", &Debugger::Attach)
|
||||
.SetMethod("isAttached", &Debugger::IsAttached)
|
||||
.SetMethod("detach", &Debugger::Detach)
|
||||
.SetMethod("sendCommand", &Debugger::SendCommand);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
namespace {
|
||||
|
||||
using atom::api::Debugger;
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_debugger, Initialize);
|
||||
@@ -1,80 +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_DEBUGGER_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_DEBUGGER_H_
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#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;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class Debugger : public mate::TrackableObject<Debugger>,
|
||||
public content::DevToolsAgentHostClient,
|
||||
public content::WebContentsObserver {
|
||||
public:
|
||||
using SendCommandCallback =
|
||||
base::Callback<void(const base::Value&, const base::Value&)>;
|
||||
|
||||
static mate::Handle<Debugger> Create(v8::Isolate* isolate,
|
||||
content::WebContents* web_contents);
|
||||
|
||||
// mate::TrackableObject:
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
protected:
|
||||
Debugger(v8::Isolate* isolate, content::WebContents* web_contents);
|
||||
~Debugger() override;
|
||||
|
||||
// content::DevToolsAgentHostClient:
|
||||
void AgentHostClosed(content::DevToolsAgentHost* agent_host) 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>;
|
||||
|
||||
void Attach(mate::Arguments* args);
|
||||
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;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Debugger);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_DEBUGGER_H_
|
||||
@@ -1,207 +0,0 @@
|
||||
// Copyright (c) 2015 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_desktop_capturer.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
using base::PlatformThreadRef;
|
||||
|
||||
#include "atom/common/api/atom_api_native_image.h"
|
||||
#include "atom/common/native_mate_converters/gfx_converter.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "base/task_scheduler/post_task.h"
|
||||
#include "base/threading/thread_task_runner_handle.h"
|
||||
#include "chrome/browser/media/desktop_media_list.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/desktop_capture.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
|
||||
#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
|
||||
#if defined(OS_WIN)
|
||||
#include "third_party/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h"
|
||||
#include "third_party/webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h"
|
||||
#include "ui/display/win/display_info.h"
|
||||
#endif // defined(OS_WIN)
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace mate {
|
||||
|
||||
template <>
|
||||
struct Converter<atom::api::DesktopCapturer::Source> {
|
||||
static v8::Local<v8::Value> ToV8(
|
||||
v8::Isolate* isolate,
|
||||
const atom::api::DesktopCapturer::Source& source) {
|
||||
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));
|
||||
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);
|
||||
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() {}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
void DesktopCapturer::OnSourceAdded(int index) {}
|
||||
|
||||
void DesktopCapturer::OnSourceRemoved(int index) {}
|
||||
|
||||
void DesktopCapturer::OnSourceMoved(int old_index, int new_index) {}
|
||||
|
||||
void DesktopCapturer::OnSourceNameChanged(int index) {}
|
||||
|
||||
void DesktopCapturer::OnSourceThumbnailChanged(int index) {}
|
||||
|
||||
bool DesktopCapturer::OnRefreshFinished() {
|
||||
capture_thread_->PostTask(FROM_HERE,
|
||||
base::BindOnce(OnRefreshFinishedTask, this));
|
||||
return false;
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<DesktopCapturer> DesktopCapturer::Create(v8::Isolate* isolate) {
|
||||
return mate::CreateHandle(isolate, new DesktopCapturer(isolate));
|
||||
}
|
||||
|
||||
// static
|
||||
void DesktopCapturer::BuildPrototype(
|
||||
v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "DesktopCapturer"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetMethod("startHandling", &DesktopCapturer::StartHandling);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
namespace {
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_desktop_capturer, Initialize);
|
||||
@@ -1,64 +0,0 @@
|
||||
// Copyright (c) 2015 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_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"
|
||||
#include "native_mate/handle.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
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,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
void StartHandling(bool capture_window,
|
||||
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;
|
||||
|
||||
// DesktopMediaListObserver overrides.
|
||||
void OnSourceAdded(int index) override;
|
||||
void OnSourceRemoved(int index) override;
|
||||
void OnSourceMoved(int old_index, int new_index) override;
|
||||
void OnSourceNameChanged(int index) override;
|
||||
void OnSourceThumbnailChanged(int index) override;
|
||||
bool OnRefreshFinished() override;
|
||||
|
||||
private:
|
||||
scoped_refptr<base::SequencedTaskRunner> capture_thread_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(DesktopCapturer);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_DESKTOP_CAPTURER_H_
|
||||
@@ -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,106 +35,84 @@ 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 {
|
||||
|
||||
void ShowMessageBox(int type,
|
||||
const std::vector<std::string>& buttons,
|
||||
int default_id,
|
||||
int cancel_id,
|
||||
int options,
|
||||
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, 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, cancel_id, options, title,
|
||||
message, detail, icon);
|
||||
args->Return(chosen);
|
||||
}
|
||||
}
|
||||
|
||||
void ShowOpenDialog(const file_dialog::DialogSettings& settings,
|
||||
void ShowOpenDialog(const std::string& title,
|
||||
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, default_path, filters,
|
||||
properties, callback);
|
||||
} else {
|
||||
std::vector<base::FilePath> paths;
|
||||
if (file_dialog::ShowOpenDialog(settings, &paths))
|
||||
if (file_dialog::ShowOpenDialog(window, title, default_path, filters,
|
||||
properties, &paths))
|
||||
args->Return(paths);
|
||||
}
|
||||
}
|
||||
|
||||
void ShowSaveDialog(const file_dialog::DialogSettings& settings,
|
||||
void ShowSaveDialog(const std::string& title,
|
||||
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, default_path, filters, callback);
|
||||
} else {
|
||||
base::FilePath path;
|
||||
if (file_dialog::ShowSaveDialog(settings, &path))
|
||||
if (file_dialog::ShowSaveDialog(window, title, 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,27 @@
|
||||
#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/memory/linked_ptr.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:
|
||||
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:
|
||||
@@ -52,190 +47,159 @@ namespace atom {
|
||||
namespace api {
|
||||
|
||||
namespace {
|
||||
// The wrapDownloadItem funtion which is implemented in JavaScript
|
||||
using WrapDownloadItemCallback = base::Callback<void(v8::Local<v8::Value>)>;
|
||||
WrapDownloadItemCallback g_wrap_download_item;
|
||||
|
||||
std::map<uint32_t, v8::Global<v8::Object>> g_download_item_objects;
|
||||
char kDownloadItemSavePathKey[] = "DownloadItemSavePathKey";
|
||||
|
||||
std::map<uint32, linked_ptr<v8::Global<v8::Value>>> g_download_item_objects;
|
||||
} // namespace
|
||||
|
||||
DownloadItem::DownloadItem(v8::Isolate* isolate,
|
||||
download::DownloadItem* download_item)
|
||||
: download_item_(download_item) {
|
||||
DownloadItem::SavePathData::SavePathData(const base::FilePath& path) :
|
||||
path_(path) {
|
||||
}
|
||||
|
||||
const base::FilePath& DownloadItem::SavePathData::path() {
|
||||
return path_;
|
||||
}
|
||||
|
||||
DownloadItem::DownloadItem(content::DownloadItem* download_item) :
|
||||
download_item_(download_item) {
|
||||
download_item_->AddObserver(this);
|
||||
Init(isolate);
|
||||
AttachAsUserData(download_item);
|
||||
}
|
||||
|
||||
DownloadItem::~DownloadItem() {
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void DownloadItem::Destroy() {
|
||||
if (download_item_) {
|
||||
// Destroyed by either garbage collection or destroy().
|
||||
download_item_->RemoveObserver(this);
|
||||
download_item_->Remove();
|
||||
}
|
||||
|
||||
// Remove from the global map.
|
||||
g_download_item_objects.erase(weak_map_id());
|
||||
}
|
||||
|
||||
void DownloadItem::OnDownloadUpdated(download::DownloadItem* item) {
|
||||
if (download_item_->IsDone()) {
|
||||
Emit("done", item->GetState());
|
||||
// Destroy the item once item is downloaded.
|
||||
base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
|
||||
GetDestroyClosure());
|
||||
} else {
|
||||
Emit("updated", item->GetState());
|
||||
auto iter = g_download_item_objects.find(download_item_->GetId());
|
||||
if (iter != g_download_item_objects.end())
|
||||
g_download_item_objects.erase(iter);
|
||||
download_item_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadItem::OnDownloadDestroyed(download::DownloadItem* download_item) {
|
||||
download_item_ = nullptr;
|
||||
// Destroy the native class immediately when downloadItem is destroyed.
|
||||
delete this;
|
||||
bool DownloadItem::IsDestroyed() const {
|
||||
return download_item_ == nullptr;
|
||||
}
|
||||
|
||||
void DownloadItem::OnDownloadUpdated(content::DownloadItem* item) {
|
||||
download_item_->IsDone() ? Emit("done", item->GetState()) : Emit("updated");
|
||||
}
|
||||
|
||||
void DownloadItem::OnDownloadDestroyed(content::DownloadItem* download) {
|
||||
Destroy();
|
||||
}
|
||||
|
||||
int64 DownloadItem::GetReceivedBytes() {
|
||||
return download_item_->GetReceivedBytes();
|
||||
}
|
||||
|
||||
int64 DownloadItem::GetTotalBytes() {
|
||||
return download_item_->GetTotalBytes();
|
||||
}
|
||||
|
||||
const GURL& DownloadItem::GetUrl() {
|
||||
return download_item_->GetURL();
|
||||
}
|
||||
|
||||
std::string DownloadItem::GetMimeType() {
|
||||
return download_item_->GetMimeType();
|
||||
}
|
||||
|
||||
bool DownloadItem::HasUserGesture() {
|
||||
return download_item_->HasUserGesture();
|
||||
}
|
||||
|
||||
std::string DownloadItem::GetFilename() {
|
||||
return base::UTF16ToUTF8(net::GenerateFileName(GetUrl(),
|
||||
GetContentDisposition(),
|
||||
std::string(),
|
||||
download_item_->GetSuggestedFilename(),
|
||||
GetMimeType(),
|
||||
std::string()).LossyDisplayName());
|
||||
}
|
||||
|
||||
std::string DownloadItem::GetContentDisposition() {
|
||||
return download_item_->GetContentDisposition();
|
||||
}
|
||||
|
||||
void DownloadItem::SetSavePath(const base::FilePath& path) {
|
||||
download_item_->SetUserData(UserDataKey(), new SavePathData(path));
|
||||
}
|
||||
|
||||
void DownloadItem::Pause() {
|
||||
download_item_->Pause();
|
||||
}
|
||||
|
||||
bool DownloadItem::IsPaused() const {
|
||||
return download_item_->IsPaused();
|
||||
}
|
||||
|
||||
void DownloadItem::Resume() {
|
||||
download_item_->Resume();
|
||||
}
|
||||
|
||||
bool DownloadItem::CanResume() const {
|
||||
return download_item_->CanResume();
|
||||
}
|
||||
|
||||
void DownloadItem::Cancel() {
|
||||
download_item_->Cancel(true);
|
||||
}
|
||||
|
||||
int64_t DownloadItem::GetReceivedBytes() const {
|
||||
return download_item_->GetReceivedBytes();
|
||||
}
|
||||
|
||||
int64_t DownloadItem::GetTotalBytes() const {
|
||||
return download_item_->GetTotalBytes();
|
||||
}
|
||||
|
||||
std::string DownloadItem::GetMimeType() const {
|
||||
return download_item_->GetMimeType();
|
||||
}
|
||||
|
||||
bool DownloadItem::HasUserGesture() const {
|
||||
return download_item_->HasUserGesture();
|
||||
}
|
||||
|
||||
std::string DownloadItem::GetFilename() const {
|
||||
return base::UTF16ToUTF8(
|
||||
net::GenerateFileName(GetURL(), GetContentDisposition(), std::string(),
|
||||
download_item_->GetSuggestedFilename(),
|
||||
GetMimeType(), "download")
|
||||
.LossyDisplayName());
|
||||
}
|
||||
|
||||
std::string DownloadItem::GetContentDisposition() const {
|
||||
return download_item_->GetContentDisposition();
|
||||
}
|
||||
|
||||
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 {
|
||||
return download_item_->GetState();
|
||||
}
|
||||
|
||||
bool DownloadItem::IsDone() const {
|
||||
return download_item_->IsDone();
|
||||
}
|
||||
|
||||
void DownloadItem::SetSavePath(const base::FilePath& path) {
|
||||
save_path_ = path;
|
||||
}
|
||||
|
||||
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) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "DownloadItem"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.MakeDestroyable()
|
||||
mate::ObjectTemplateBuilder DownloadItem::GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) {
|
||||
return mate::ObjectTemplateBuilder(isolate)
|
||||
.SetMethod("pause", &DownloadItem::Pause)
|
||||
.SetMethod("isPaused", &DownloadItem::IsPaused)
|
||||
.SetMethod("resume", &DownloadItem::Resume)
|
||||
.SetMethod("canResume", &DownloadItem::CanResume)
|
||||
.SetMethod("cancel", &DownloadItem::Cancel)
|
||||
.SetMethod("getReceivedBytes", &DownloadItem::GetReceivedBytes)
|
||||
.SetMethod("getTotalBytes", &DownloadItem::GetTotalBytes)
|
||||
.SetMethod("getUrl", &DownloadItem::GetUrl)
|
||||
.SetMethod("getMimeType", &DownloadItem::GetMimeType)
|
||||
.SetMethod("hasUserGesture", &DownloadItem::HasUserGesture)
|
||||
.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("setSavePath", &DownloadItem::SetSavePath);
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<DownloadItem> DownloadItem::Create(v8::Isolate* isolate,
|
||||
download::DownloadItem* item) {
|
||||
auto* existing = TrackableObject::FromWrappedClass(isolate, item);
|
||||
if (existing)
|
||||
return mate::CreateHandle(isolate, static_cast<DownloadItem*>(existing));
|
||||
|
||||
auto handle = mate::CreateHandle(isolate, new DownloadItem(isolate, item));
|
||||
|
||||
// Reference this object in case it got garbage collected.
|
||||
g_download_item_objects[handle->weak_map_id()] =
|
||||
v8::Global<v8::Object>(isolate, handle.ToV8());
|
||||
mate::Handle<DownloadItem> DownloadItem::Create(
|
||||
v8::Isolate* isolate, content::DownloadItem* item) {
|
||||
auto handle = mate::CreateHandle(isolate, new DownloadItem(item));
|
||||
g_wrap_download_item.Run(handle.ToV8());
|
||||
g_download_item_objects[item->GetId()] = make_linked_ptr(
|
||||
new v8::Global<v8::Value>(isolate, handle.ToV8()));
|
||||
return handle;
|
||||
}
|
||||
|
||||
// static
|
||||
void* DownloadItem::UserDataKey() {
|
||||
return &kDownloadItemSavePathKey;
|
||||
}
|
||||
|
||||
void ClearWrapDownloadItem() {
|
||||
g_wrap_download_item.Reset();
|
||||
}
|
||||
|
||||
void SetWrapDownloadItem(const WrapDownloadItemCallback& callback) {
|
||||
g_wrap_download_item = callback;
|
||||
|
||||
// Cleanup the wrapper on exit.
|
||||
atom::AtomBrowserMainParts::Get()->RegisterDestructionCallback(
|
||||
base::Bind(ClearWrapDownloadItem));
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
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",
|
||||
atom::api::DownloadItem::GetConstructor(isolate)->GetFunction());
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.SetMethod("_setWrapDownloadItem", &atom::api::SetWrapDownloadItem);
|
||||
}
|
||||
|
||||
} // 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"
|
||||
|
||||
@@ -18,47 +17,50 @@ namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class DownloadItem : public mate::TrackableObject<DownloadItem>,
|
||||
public download::DownloadItem::Observer {
|
||||
class DownloadItem : public mate::EventEmitter,
|
||||
public content::DownloadItem::Observer {
|
||||
public:
|
||||
class SavePathData : public base::SupportsUserData::Data {
|
||||
public:
|
||||
explicit SavePathData(const base::FilePath& path);
|
||||
const base::FilePath& path();
|
||||
private:
|
||||
base::FilePath path_;
|
||||
};
|
||||
|
||||
static mate::Handle<DownloadItem> Create(v8::Isolate* isolate,
|
||||
download::DownloadItem* item);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
void Pause();
|
||||
bool IsPaused() const;
|
||||
void Resume();
|
||||
bool CanResume() const;
|
||||
void Cancel();
|
||||
int64_t GetReceivedBytes() const;
|
||||
int64_t GetTotalBytes() const;
|
||||
std::string GetMimeType() const;
|
||||
bool HasUserGesture() const;
|
||||
std::string GetFilename() const;
|
||||
std::string GetContentDisposition() const;
|
||||
const GURL& GetURL() const;
|
||||
const std::vector<GURL>& GetURLChain() const;
|
||||
download::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;
|
||||
content::DownloadItem* item);
|
||||
static void* UserDataKey();
|
||||
|
||||
protected:
|
||||
DownloadItem(v8::Isolate* isolate, download::DownloadItem* download_item);
|
||||
~DownloadItem() override;
|
||||
explicit DownloadItem(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;
|
||||
|
||||
void Pause();
|
||||
void Resume();
|
||||
void Cancel();
|
||||
int64 GetReceivedBytes();
|
||||
int64 GetTotalBytes();
|
||||
std::string GetMimeType();
|
||||
bool HasUserGesture();
|
||||
std::string GetFilename();
|
||||
std::string GetContentDisposition();
|
||||
const GURL& GetUrl();
|
||||
void SetSavePath(const base::FilePath& path);
|
||||
|
||||
private:
|
||||
base::FilePath save_path_;
|
||||
download::DownloadItem* download_item_;
|
||||
// mate::Wrappable:
|
||||
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) override;
|
||||
bool IsDestroyed() const override;
|
||||
|
||||
void Destroy();
|
||||
|
||||
content::DownloadItem* download_item_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(DownloadItem);
|
||||
};
|
||||
|
||||
@@ -19,11 +19,13 @@ namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
GlobalShortcut::GlobalShortcut(v8::Isolate* isolate) {
|
||||
Init(isolate);
|
||||
GlobalShortcut::GlobalShortcut() {
|
||||
}
|
||||
|
||||
GlobalShortcut::~GlobalShortcut() {
|
||||
}
|
||||
|
||||
void GlobalShortcut::Destroy() {
|
||||
UnregisterAll();
|
||||
}
|
||||
|
||||
@@ -40,8 +42,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 +56,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) {
|
||||
@@ -67,32 +69,28 @@ void GlobalShortcut::UnregisterAll() {
|
||||
GlobalShortcutListener::GetInstance()->UnregisterAccelerators(this);
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<GlobalShortcut> GlobalShortcut::Create(v8::Isolate* isolate) {
|
||||
return mate::CreateHandle(isolate, new GlobalShortcut(isolate));
|
||||
}
|
||||
|
||||
// static
|
||||
void GlobalShortcut::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "GlobalShortcut"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
mate::ObjectTemplateBuilder GlobalShortcut::GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) {
|
||||
return mate::ObjectTemplateBuilder(isolate)
|
||||
.SetMethod("register", &GlobalShortcut::Register)
|
||||
.SetMethod("isRegistered", &GlobalShortcut::IsRegistered)
|
||||
.SetMethod("unregister", &GlobalShortcut::Unregister)
|
||||
.SetMethod("unregisterAll", &GlobalShortcut::UnregisterAll);
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<GlobalShortcut> GlobalShortcut::Create(v8::Isolate* isolate) {
|
||||
return CreateHandle(isolate, new GlobalShortcut);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
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)
|
||||
|
||||
@@ -23,13 +23,17 @@ class GlobalShortcut : public extensions::GlobalShortcutListener::Observer,
|
||||
public:
|
||||
static mate::Handle<GlobalShortcut> Create(v8::Isolate* isolate);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
protected:
|
||||
explicit GlobalShortcut(v8::Isolate* isolate);
|
||||
GlobalShortcut();
|
||||
~GlobalShortcut() override;
|
||||
|
||||
// mate::TrackableObject:
|
||||
void Destroy() override;
|
||||
|
||||
// mate::Wrappable implementations:
|
||||
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) override;
|
||||
|
||||
private:
|
||||
typedef std::map<ui::Accelerator, base::Closure> AcceleratorCallbackMap;
|
||||
|
||||
|
||||
@@ -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_
|
||||
@@ -19,20 +19,24 @@ namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
Menu::Menu(v8::Isolate* isolate, v8::Local<v8::Object> wrapper)
|
||||
: model_(new AtomMenuModel(this)) {
|
||||
InitWith(isolate, wrapper);
|
||||
model_->AddObserver(this);
|
||||
Menu::Menu()
|
||||
: model_(new AtomMenuModel(this)),
|
||||
parent_(NULL) {
|
||||
}
|
||||
|
||||
Menu::~Menu() {
|
||||
if (model_) {
|
||||
model_->RemoveObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
void Menu::Destroy() {
|
||||
model_.reset();
|
||||
}
|
||||
|
||||
bool Menu::IsDestroyed() const {
|
||||
return !model_;
|
||||
}
|
||||
|
||||
void Menu::AfterInit(v8::Isolate* isolate) {
|
||||
mate::Dictionary wrappable(isolate, GetWrapper());
|
||||
mate::Dictionary wrappable(isolate, GetWrapper(isolate));
|
||||
mate::Dictionary delegate;
|
||||
if (!wrappable.Get("delegate", &delegate))
|
||||
return;
|
||||
@@ -46,51 +50,35 @@ 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(
|
||||
int command_id,
|
||||
bool use_default_accelerator,
|
||||
ui::Accelerator* accelerator) const {
|
||||
bool Menu::GetAcceleratorForCommandId(int command_id,
|
||||
ui::Accelerator* accelerator) {
|
||||
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);
|
||||
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);
|
||||
void Menu::ExecuteCommand(int command_id, int event_flags) {
|
||||
execute_command_.Run(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,20 +155,10 @@ 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) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "Menu"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.MakeDestroyable()
|
||||
v8::Local<v8::ObjectTemplate> prototype) {
|
||||
mate::ObjectTemplateBuilder(isolate, prototype)
|
||||
.SetMethod("insertItem", &Menu::InsertItemAt)
|
||||
.SetMethod("insertCheckItem", &Menu::InsertCheckItemAt)
|
||||
.SetMethod("insertRadioItem", &Menu::InsertRadioItemAt)
|
||||
@@ -198,27 +176,25 @@ 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("_popup", &Menu::Popup)
|
||||
.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) {
|
||||
using atom::api::Menu;
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
Menu::SetConstructor(isolate, base::Bind(&Menu::New));
|
||||
|
||||
v8::Local<v8::Function> constructor = mate::CreateConstructor<Menu>(
|
||||
isolate, "Menu", base::Bind(&Menu::Create));
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("Menu", Menu::GetConstructor(isolate)->GetFunction());
|
||||
dict.Set("Menu", static_cast<v8::Local<v8::Value>>(constructor));
|
||||
#if defined(OS_MACOSX)
|
||||
dict.SetMethod("setApplicationMenu", &Menu::SetApplicationMenu);
|
||||
dict.SetMethod("sendActionToFirstResponder",
|
||||
@@ -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)
|
||||
|
||||
@@ -5,26 +5,25 @@
|
||||
#ifndef ATOM_BROWSER_API_ATOM_API_MENU_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_MENU_H_
|
||||
|
||||
#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"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
|
||||
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);
|
||||
static mate::Wrappable* Create();
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
v8::Local<v8::ObjectTemplate> prototype);
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
// Set the global menubar.
|
||||
@@ -37,36 +36,30 @@ class Menu : public mate::TrackableObject<Menu>,
|
||||
AtomMenuModel* model() const { return model_.get(); }
|
||||
|
||||
protected:
|
||||
Menu(v8::Isolate* isolate, v8::Local<v8::Object> wrapper);
|
||||
Menu();
|
||||
~Menu() override;
|
||||
|
||||
// mate::TrackableObject:
|
||||
void Destroy() override;
|
||||
|
||||
// mate::Wrappable:
|
||||
bool IsDestroyed() const override;
|
||||
void AfterInit(v8::Isolate* isolate) override;
|
||||
|
||||
// ui::SimpleMenuModel::Delegate:
|
||||
bool IsCommandIdChecked(int command_id) const override;
|
||||
bool IsCommandIdEnabled(int command_id) const override;
|
||||
bool IsCommandIdVisible(int command_id) const override;
|
||||
bool GetAcceleratorForCommandIdWithParams(
|
||||
int command_id,
|
||||
bool use_default_accelerator,
|
||||
ui::Accelerator* accelerator) const override;
|
||||
bool GetAcceleratorForCommandId(int command_id,
|
||||
ui::Accelerator* accelerator) override;
|
||||
void ExecuteCommand(int command_id, int event_flags) override;
|
||||
void MenuWillShow(ui::SimpleMenuModel* source) override;
|
||||
|
||||
virtual void PopupAt(TopLevelWindow* window,
|
||||
int x,
|
||||
int y,
|
||||
int positioning_item,
|
||||
const base::Closure& callback) = 0;
|
||||
virtual void ClosePopupAt(int32_t window_id) = 0;
|
||||
virtual void Popup(Window* window) = 0;
|
||||
virtual void PopupAt(Window* window, int x, int y) = 0;
|
||||
|
||||
std::unique_ptr<AtomMenuModel> model_;
|
||||
Menu* parent_ = nullptr;
|
||||
|
||||
// Observable:
|
||||
void OnMenuWillClose() override;
|
||||
void OnMenuWillShow() override;
|
||||
scoped_ptr<AtomMenuModel> model_;
|
||||
Menu* parent_;
|
||||
|
||||
private:
|
||||
void InsertItemAt(int index, int command_id, const base::string16& label);
|
||||
@@ -96,14 +89,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)> get_accelerator_;
|
||||
base::Callback<void(int)> execute_command_;
|
||||
base::Callback<void()> menu_will_show_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Menu);
|
||||
};
|
||||
@@ -112,12 +103,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,46 +7,28 @@
|
||||
|
||||
#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 {
|
||||
|
||||
class MenuMac : public Menu {
|
||||
protected:
|
||||
MenuMac(v8::Isolate* isolate, v8::Local<v8::Object> wrapper);
|
||||
~MenuMac() override;
|
||||
MenuMac();
|
||||
|
||||
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 Destroy() override;
|
||||
void Popup(Window* window) override;
|
||||
void PopupAt(Window* window, int x, int y) 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);
|
||||
};
|
||||
|
||||
@@ -5,151 +5,81 @@
|
||||
#import "atom/browser/api/atom_api_menu_mac.h"
|
||||
|
||||
#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 "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) {}
|
||||
MenuMac::MenuMac() {
|
||||
}
|
||||
|
||||
MenuMac::~MenuMac() = default;
|
||||
void MenuMac::Destroy() {
|
||||
menu_controller_.reset();
|
||||
Menu::Destroy();
|
||||
}
|
||||
|
||||
void MenuMac::PopupAt(TopLevelWindow* window,
|
||||
int x,
|
||||
int y,
|
||||
int positioning_item,
|
||||
const base::Closure& callback) {
|
||||
void MenuMac::Popup(Window* window) {
|
||||
NativeWindow* native_window = window->window();
|
||||
if (!native_window)
|
||||
return;
|
||||
content::WebContents* web_contents = native_window->web_contents();
|
||||
if (!web_contents)
|
||||
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);
|
||||
NSWindow* nswindow = native_window->GetNativeWindow();
|
||||
base::scoped_nsobject<AtomMenuController> menu_controller(
|
||||
[[AtomMenuController alloc] initWithModel:model_.get()]);
|
||||
|
||||
// Fake out a context menu event.
|
||||
NSEvent* currentEvent = [NSApp currentEvent];
|
||||
NSPoint position = [nswindow mouseLocationOutsideOfEventStream];
|
||||
NSTimeInterval eventTime = [currentEvent timestamp];
|
||||
NSEvent* clickEvent = [NSEvent mouseEventWithType:NSRightMouseDown
|
||||
location:position
|
||||
modifierFlags:NSRightMouseDownMask
|
||||
timestamp:eventTime
|
||||
windowNumber:[nswindow windowNumber]
|
||||
context:nil
|
||||
eventNumber:0
|
||||
clickCount:1
|
||||
pressure:1.0];
|
||||
|
||||
// Show the menu.
|
||||
[NSMenu popUpContextMenu:[menu_controller menu]
|
||||
withEvent:clickEvent
|
||||
forView:web_contents->GetContentNativeView()];
|
||||
}
|
||||
|
||||
void MenuMac::PopupOnUI(const base::WeakPtr<NativeWindow>& native_window,
|
||||
int32_t window_id,
|
||||
int x,
|
||||
int y,
|
||||
int positioning_item,
|
||||
base::Closure callback) {
|
||||
void MenuMac::PopupAt(Window* window, int x, int y) {
|
||||
NativeWindow* native_window = window->window();
|
||||
if (!native_window)
|
||||
return;
|
||||
NSWindow* nswindow = native_window->GetNativeWindow();
|
||||
content::WebContents* web_contents = native_window->web_contents();
|
||||
if (!web_contents)
|
||||
return;
|
||||
|
||||
auto close_callback = base::Bind(
|
||||
&MenuMac::OnClosed, weak_factory_.GetWeakPtr(), window_id, callback);
|
||||
popup_controllers_[window_id] = base::scoped_nsobject<AtomMenuController>([
|
||||
[AtomMenuController alloc] initWithModel:model()
|
||||
useDefaultAccelerator:NO]);
|
||||
NSMenu* menu = [popup_controllers_[window_id] menu];
|
||||
NSView* view = [nswindow contentView];
|
||||
base::scoped_nsobject<AtomMenuController> menu_controller(
|
||||
[[AtomMenuController alloc] initWithModel:model_.get()]);
|
||||
NSMenu* menu = [menu_controller menu];
|
||||
NSView* view = web_contents->GetContentNativeView();
|
||||
|
||||
// Which menu item to show.
|
||||
NSMenuItem* item = nil;
|
||||
if (positioning_item < [menu numberOfItems] && positioning_item >= 0)
|
||||
item = [menu itemAtIndex:positioning_item];
|
||||
|
||||
// (-1, -1) means showing on mouse location.
|
||||
NSPoint position;
|
||||
if (x == -1 || y == -1) {
|
||||
position = [view convertPoint:[nswindow mouseLocationOutsideOfEventStream]
|
||||
fromView:nil];
|
||||
} else {
|
||||
position = NSMakePoint(x, [view frame].size.height - y);
|
||||
}
|
||||
|
||||
// If no preferred item is specified, try to show all of the menu items.
|
||||
if (!positioning_item) {
|
||||
CGFloat windowBottom = CGRectGetMinY([view window].frame);
|
||||
CGFloat lowestMenuPoint = windowBottom + position.y - [menu size].height;
|
||||
CGFloat screenBottom = CGRectGetMinY([view window].screen.frame);
|
||||
CGFloat distanceFromBottom = lowestMenuPoint - screenBottom;
|
||||
if (distanceFromBottom < 0)
|
||||
position.y = position.y - distanceFromBottom + 4;
|
||||
}
|
||||
|
||||
// Place the menu left of cursor if it is overflowing off right of screen.
|
||||
CGFloat windowLeft = CGRectGetMinX([view window].frame);
|
||||
CGFloat rightmostMenuPoint = windowLeft + position.x + [menu size].width;
|
||||
CGFloat screenRight = CGRectGetMaxX([view window].screen.frame);
|
||||
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;
|
||||
[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();
|
||||
// Show the menu.
|
||||
[menu popUpMenuPositioningItem:[menu itemAtIndex:0]
|
||||
atLocation:NSMakePoint(x, [view frame].size.height - y)
|
||||
inView:view];
|
||||
}
|
||||
|
||||
// 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()]);
|
||||
[NSApp setMainMenu:[menu_controller menu]];
|
||||
|
||||
// Ensure the menu_controller_ is destroyed after main menu is set.
|
||||
menu_controller.swap(menu->menu_controller_);
|
||||
@@ -162,8 +92,8 @@ void Menu::SendActionToFirstResponder(const std::string& action) {
|
||||
}
|
||||
|
||||
// static
|
||||
mate::WrappableBase* Menu::New(mate::Arguments* args) {
|
||||
return new MenuMac(args->isolate(), args->GetThis());
|
||||
mate::Wrappable* Menu::Create() {
|
||||
return new MenuMac();
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
@@ -5,76 +5,51 @@
|
||||
#include "atom/browser/api/atom_api_menu_views.h"
|
||||
|
||||
#include "atom/browser/native_window_views.h"
|
||||
#include "atom/browser/unresponsive_suppressor.h"
|
||||
#include "ui/display/screen.h"
|
||||
|
||||
using views::MenuRunner;
|
||||
#include "content/public/browser/render_widget_host_view.h"
|
||||
#include "ui/gfx/screen.h"
|
||||
#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) {}
|
||||
MenuViews::MenuViews() {
|
||||
}
|
||||
|
||||
MenuViews::~MenuViews() = default;
|
||||
void MenuViews::Popup(Window* window) {
|
||||
PopupAtPoint(window, gfx::Screen::GetNativeScreen()->GetCursorScreenPoint());
|
||||
}
|
||||
|
||||
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) {
|
||||
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();
|
||||
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);
|
||||
gfx::Point origin = view->GetViewBounds().origin();
|
||||
PopupAtPoint(window, gfx::Point(origin.x() + x, origin.y() + y));
|
||||
}
|
||||
|
||||
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();
|
||||
void MenuViews::PopupAtPoint(Window* window, const gfx::Point& point) {
|
||||
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(point, gfx::Size()),
|
||||
views::MENU_ANCHOR_TOPLEFT,
|
||||
ui::MENU_SOURCE_MOUSE));
|
||||
}
|
||||
|
||||
// static
|
||||
mate::WrappableBase* Menu::New(mate::Arguments* args) {
|
||||
return new MenuViews(args->isolate(), args->GetThis());
|
||||
mate::Wrappable* Menu::Create() {
|
||||
return new MenuViews();
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
@@ -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"
|
||||
#include "ui/gfx/screen.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
@@ -18,24 +14,14 @@ namespace api {
|
||||
|
||||
class MenuViews : public Menu {
|
||||
public:
|
||||
MenuViews(v8::Isolate* isolate, v8::Local<v8::Object> wrapper);
|
||||
~MenuViews() override;
|
||||
MenuViews();
|
||||
|
||||
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 Popup(Window* window) override;
|
||||
void PopupAt(Window* window, int x, int y) 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_;
|
||||
void PopupAtPoint(Window* window, const gfx::Point& point);
|
||||
|
||||
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,137 +0,0 @@
|
||||
// Copyright (c) 2018 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_net_log.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/atom_browser_main_parts.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/file_path_converter.h"
|
||||
#include "base/command_line.h"
|
||||
#include "components/net_log/chrome_net_log.h"
|
||||
#include "content/public/browser/storage_partition.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "net/url_request/url_request_context_getter.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
NetLog::NetLog(v8::Isolate* isolate, AtomBrowserContext* browser_context)
|
||||
: browser_context_(browser_context) {
|
||||
Init(isolate);
|
||||
|
||||
net_log_writer_ =
|
||||
atom::AtomBrowserMainParts::Get()->net_log()->net_export_file_writer();
|
||||
net_log_writer_->AddObserver(this);
|
||||
}
|
||||
|
||||
NetLog::~NetLog() {
|
||||
net_log_writer_->RemoveObserver(this);
|
||||
}
|
||||
|
||||
void NetLog::StartLogging(mate::Arguments* args) {
|
||||
base::FilePath log_path;
|
||||
if (!args->GetNext(&log_path) || log_path.empty()) {
|
||||
args->ThrowError("The first parameter must be a valid string");
|
||||
return;
|
||||
}
|
||||
|
||||
net_log::NetExportFileWriter::URLRequestContextGetterList context_getters = {
|
||||
browser_context_->GetRequestContext()};
|
||||
|
||||
// TODO(deepak1556): Provide more flexibility to this module
|
||||
// by allowing customizations on the capturing options.
|
||||
net_log_writer_->StartNetLog(
|
||||
log_path, net::NetLogCaptureMode::Default(),
|
||||
net_log::NetExportFileWriter::kNoLimit /* file size limit */,
|
||||
base::CommandLine::ForCurrentProcess()->GetCommandLineString(),
|
||||
std::string(), context_getters);
|
||||
}
|
||||
|
||||
std::string NetLog::GetLoggingState() const {
|
||||
if (!net_log_state_)
|
||||
return std::string();
|
||||
const base::Value* current_log_state =
|
||||
net_log_state_->FindKeyOfType("state", base::Value::Type::STRING);
|
||||
if (!current_log_state)
|
||||
return std::string();
|
||||
return current_log_state->GetString();
|
||||
}
|
||||
|
||||
bool NetLog::IsCurrentlyLogging() const {
|
||||
const std::string log_state = GetLoggingState();
|
||||
return (log_state == "STARTING_LOG") || (log_state == "LOGGING");
|
||||
}
|
||||
|
||||
std::string NetLog::GetCurrentlyLoggingPath() const {
|
||||
// Net log exporter has a default path which will be used
|
||||
// when no log path is provided, but since we don't allow
|
||||
// net log capture without user provided file path, this
|
||||
// check is completely safe.
|
||||
if (IsCurrentlyLogging()) {
|
||||
const base::Value* current_log_path =
|
||||
net_log_state_->FindKeyOfType("file", base::Value::Type::STRING);
|
||||
if (current_log_path)
|
||||
return current_log_path->GetString();
|
||||
}
|
||||
|
||||
return std::string();
|
||||
}
|
||||
|
||||
void NetLog::StopLogging(mate::Arguments* args) {
|
||||
net_log::NetExportFileWriter::FilePathCallback callback;
|
||||
if (!args->GetNext(&callback)) {
|
||||
args->ThrowError("Invalid callback function");
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsCurrentlyLogging()) {
|
||||
stop_callback_queue_.emplace_back(callback);
|
||||
net_log_writer_->StopNetLog(nullptr, nullptr);
|
||||
} else {
|
||||
callback.Run(base::FilePath());
|
||||
}
|
||||
}
|
||||
|
||||
void NetLog::OnNewState(const base::DictionaryValue& state) {
|
||||
net_log_state_ = state.CreateDeepCopy();
|
||||
|
||||
if (stop_callback_queue_.empty())
|
||||
return;
|
||||
|
||||
if (GetLoggingState() == "NOT_LOGGING") {
|
||||
for (auto& callback : stop_callback_queue_) {
|
||||
if (!callback.is_null())
|
||||
net_log_writer_->GetFilePathToCompletedLog(callback);
|
||||
}
|
||||
stop_callback_queue_.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<NetLog> NetLog::Create(v8::Isolate* isolate,
|
||||
AtomBrowserContext* browser_context) {
|
||||
return mate::CreateHandle(isolate, new NetLog(isolate, browser_context));
|
||||
}
|
||||
|
||||
// static
|
||||
void NetLog::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "NetLog"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetProperty("currentlyLogging", &NetLog::IsCurrentlyLogging)
|
||||
.SetProperty("currentlyLoggingPath", &NetLog::GetCurrentlyLoggingPath)
|
||||
.SetMethod("startLogging", &NetLog::StartLogging)
|
||||
.SetMethod("stopLogging", &NetLog::StopLogging);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
@@ -1,60 +0,0 @@
|
||||
// Copyright (c) 2018 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_API_ATOM_API_NET_LOG_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_NET_LOG_H_
|
||||
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "base/callback.h"
|
||||
#include "base/values.h"
|
||||
#include "components/net_log/net_export_file_writer.h"
|
||||
#include "native_mate/handle.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomBrowserContext;
|
||||
|
||||
namespace api {
|
||||
|
||||
class NetLog : public mate::TrackableObject<NetLog>,
|
||||
public net_log::NetExportFileWriter::StateObserver {
|
||||
public:
|
||||
static mate::Handle<NetLog> Create(v8::Isolate* isolate,
|
||||
AtomBrowserContext* browser_context);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
void StartLogging(mate::Arguments* args);
|
||||
std::string GetLoggingState() const;
|
||||
bool IsCurrentlyLogging() const;
|
||||
std::string GetCurrentlyLoggingPath() const;
|
||||
void StopLogging(mate::Arguments* args);
|
||||
|
||||
protected:
|
||||
explicit NetLog(v8::Isolate* isolate, AtomBrowserContext* browser_context);
|
||||
~NetLog() override;
|
||||
|
||||
// net_log::NetExportFileWriter::StateObserver implementation
|
||||
void OnNewState(const base::DictionaryValue& state) override;
|
||||
|
||||
private:
|
||||
AtomBrowserContext* browser_context_;
|
||||
net_log::NetExportFileWriter* net_log_writer_;
|
||||
std::list<net_log::NetExportFileWriter::FilePathCallback>
|
||||
stop_callback_queue_;
|
||||
std::unique_ptr<base::DictionaryValue> net_log_state_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(NetLog);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_NET_LOG_H_
|
||||
@@ -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,26 @@
|
||||
#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
|
||||
PowerMonitor::PowerMonitor() {
|
||||
base::PowerMonitor::Get()->AddObserver(this);
|
||||
Init(isolate);
|
||||
#if defined(OS_MACOSX) || defined(OS_WIN)
|
||||
InitPlatformSpecificMonitors();
|
||||
#endif
|
||||
}
|
||||
|
||||
PowerMonitor::~PowerMonitor() {
|
||||
}
|
||||
|
||||
void PowerMonitor::Destroy() {
|
||||
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,67 +40,37 @@ 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);
|
||||
}
|
||||
|
||||
return mate::CreateHandle(isolate, new PowerMonitor(isolate)).ToV8();
|
||||
}
|
||||
|
||||
// static
|
||||
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);
|
||||
return CreateHandle(isolate, new PowerMonitor).ToV8();
|
||||
}
|
||||
|
||||
} // 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) {
|
||||
#if defined(OS_MACOSX)
|
||||
base::PowerMonitorDeviceSource::AllocateSystemIOPorts();
|
||||
#endif
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
using atom::api::PowerMonitor;
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("powerMonitor", PowerMonitor::Create(isolate));
|
||||
dict.Set("PowerMonitor",
|
||||
PowerMonitor::GetConstructor(isolate)->GetFunction());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_power_monitor, Initialize)
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_power_monitor, Initialize)
|
||||
|
||||
@@ -6,39 +6,25 @@
|
||||
#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);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
protected:
|
||||
explicit PowerMonitor(v8::Isolate* isolate);
|
||||
PowerMonitor();
|
||||
~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
|
||||
// mate::TrackableObject:
|
||||
void Destroy() override;
|
||||
|
||||
// base::PowerObserver implementations:
|
||||
void OnPowerStateChange(bool on_battery_power) override;
|
||||
@@ -46,33 +32,6 @@ class PowerMonitor : public mate::TrackableObject<PowerMonitor>,
|
||||
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;
|
||||
@@ -38,13 +37,18 @@ namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
PowerSaveBlocker::PowerSaveBlocker(v8::Isolate* isolate)
|
||||
PowerSaveBlocker::PowerSaveBlocker()
|
||||
: current_blocker_type_(
|
||||
device::mojom::WakeLockType::kPreventAppSuspension) {
|
||||
Init(isolate);
|
||||
content::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension) {
|
||||
}
|
||||
|
||||
PowerSaveBlocker::~PowerSaveBlocker() {}
|
||||
PowerSaveBlocker::~PowerSaveBlocker() {
|
||||
}
|
||||
|
||||
void PowerSaveBlocker::Destroy() {
|
||||
power_save_blocker_types_.clear();
|
||||
power_save_blocker_.reset();
|
||||
}
|
||||
|
||||
void PowerSaveBlocker::UpdatePowerSaveBlocker() {
|
||||
if (power_save_blocker_types_.empty()) {
|
||||
@@ -52,39 +56,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}));
|
||||
scoped_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();
|
||||
@@ -101,32 +102,27 @@ bool PowerSaveBlocker::IsStarted(int id) {
|
||||
return power_save_blocker_types_.find(id) != power_save_blocker_types_.end();
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<PowerSaveBlocker> PowerSaveBlocker::Create(v8::Isolate* isolate) {
|
||||
return mate::CreateHandle(isolate, new PowerSaveBlocker(isolate));
|
||||
}
|
||||
|
||||
// static
|
||||
void PowerSaveBlocker::BuildPrototype(
|
||||
v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "PowerSaveBlocker"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
mate::ObjectTemplateBuilder PowerSaveBlocker::GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) {
|
||||
return mate::ObjectTemplateBuilder(isolate)
|
||||
.SetMethod("start", &PowerSaveBlocker::Start)
|
||||
.SetMethod("stop", &PowerSaveBlocker::Stop)
|
||||
.SetMethod("isStarted", &PowerSaveBlocker::IsStarted);
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<PowerSaveBlocker> PowerSaveBlocker::Create(v8::Isolate* isolate) {
|
||||
return CreateHandle(isolate, new PowerSaveBlocker);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
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 +130,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);
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
#define ATOM_BROWSER_API_ATOM_API_POWER_SAVE_BLOCKER_H_
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "base/memory/scoped_ptr.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;
|
||||
@@ -24,27 +24,32 @@ class PowerSaveBlocker : public mate::TrackableObject<PowerSaveBlocker> {
|
||||
public:
|
||||
static mate::Handle<PowerSaveBlocker> Create(v8::Isolate* isolate);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
protected:
|
||||
explicit PowerSaveBlocker(v8::Isolate* isolate);
|
||||
PowerSaveBlocker();
|
||||
~PowerSaveBlocker() override;
|
||||
|
||||
// mate::TrackableObject:
|
||||
void Destroy() override;
|
||||
|
||||
// mate::Wrappable implementations:
|
||||
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) override;
|
||||
|
||||
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_;
|
||||
scoped_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);
|
||||
};
|
||||
|
||||
@@ -5,22 +5,16 @@
|
||||
#include "atom/browser/api/atom_api_protocol.h"
|
||||
|
||||
#include "atom/browser/atom_browser_client.h"
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/atom_browser_main_parts.h"
|
||||
#include "atom/browser/browser.h"
|
||||
#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"
|
||||
#include "atom/common/native_mate_converters/net_converter.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "atom/common/options_switches.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "content/public/browser/child_process_security_policy.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "url/url_util.h"
|
||||
|
||||
using content::BrowserThread;
|
||||
|
||||
@@ -28,123 +22,98 @@ namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
namespace {
|
||||
|
||||
// List of registered custom standard schemes.
|
||||
std::vector<std::string> g_standard_schemes;
|
||||
|
||||
} // namespace
|
||||
|
||||
std::vector<std::string> GetStandardSchemes() {
|
||||
return g_standard_schemes;
|
||||
Protocol::Protocol(AtomBrowserContext* browser_context)
|
||||
: request_context_getter_(browser_context->GetRequestContext()),
|
||||
job_factory_(browser_context->job_factory()) {
|
||||
CHECK(job_factory_);
|
||||
}
|
||||
|
||||
void RegisterStandardSchemes(const std::vector<std::string>& schemes,
|
||||
mate::Arguments* args) {
|
||||
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, ","));
|
||||
}
|
||||
mate::ObjectTemplateBuilder Protocol::GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) {
|
||||
return mate::ObjectTemplateBuilder(isolate)
|
||||
.SetMethod("registerStandardSchemes", &Protocol::RegisterStandardSchemes)
|
||||
.SetMethod("registerStringProtocol",
|
||||
&Protocol::RegisterProtocol<URLRequestStringJob>)
|
||||
.SetMethod("registerBufferProtocol",
|
||||
&Protocol::RegisterProtocol<URLRequestBufferJob>)
|
||||
.SetMethod("registerFileProtocol",
|
||||
&Protocol::RegisterProtocol<UrlRequestAsyncAsarJob>)
|
||||
.SetMethod("registerHttpProtocol",
|
||||
&Protocol::RegisterProtocol<URLRequestFetchJob>)
|
||||
.SetMethod("unregisterProtocol", &Protocol::UnregisterProtocol)
|
||||
.SetMethod("isProtocolHandled", &Protocol::IsProtocolHandled)
|
||||
.SetMethod("interceptStringProtocol",
|
||||
&Protocol::InterceptProtocol<URLRequestStringJob>)
|
||||
.SetMethod("interceptBufferProtocol",
|
||||
&Protocol::InterceptProtocol<URLRequestBufferJob>)
|
||||
.SetMethod("interceptFileProtocol",
|
||||
&Protocol::InterceptProtocol<UrlRequestAsyncAsarJob>)
|
||||
.SetMethod("interceptHttpProtocol",
|
||||
&Protocol::InterceptProtocol<URLRequestFetchJob>)
|
||||
.SetMethod("uninterceptProtocol", &Protocol::UninterceptProtocol);
|
||||
}
|
||||
|
||||
Protocol::Protocol(v8::Isolate* isolate, AtomBrowserContext* browser_context)
|
||||
: browser_context_(browser_context), weak_factory_(this) {
|
||||
Init(isolate);
|
||||
}
|
||||
|
||||
Protocol::~Protocol() {}
|
||||
|
||||
void Protocol::RegisterServiceWorkerSchemes(
|
||||
void Protocol::RegisterStandardSchemes(
|
||||
const std::vector<std::string>& schemes) {
|
||||
atom::AtomBrowserClient::SetCustomServiceWorkerSchemes(schemes);
|
||||
atom::AtomBrowserClient::SetCustomSchemes(schemes);
|
||||
}
|
||||
|
||||
void Protocol::UnregisterProtocol(const std::string& scheme,
|
||||
mate::Arguments* args) {
|
||||
void Protocol::UnregisterProtocol(
|
||||
const std::string& scheme, mate::Arguments* args) {
|
||||
CompletionCallback callback;
|
||||
args->GetNext(&callback);
|
||||
auto* getter = static_cast<URLRequestContextGetter*>(
|
||||
browser_context_->GetRequestContext());
|
||||
content::BrowserThread::PostTaskAndReplyWithResult(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::BindOnce(&Protocol::UnregisterProtocolInIO,
|
||||
base::RetainedRef(getter), scheme),
|
||||
base::BindOnce(&Protocol::OnIOCompleted, GetWeakPtr(), callback));
|
||||
base::Bind(&Protocol::UnregisterProtocolInIO,
|
||||
base::Unretained(this), scheme),
|
||||
base::Bind(&Protocol::OnIOCompleted,
|
||||
base::Unretained(this), callback));
|
||||
}
|
||||
|
||||
// static
|
||||
Protocol::ProtocolError Protocol::UnregisterProtocolInIO(
|
||||
scoped_refptr<URLRequestContextGetter> request_context_getter,
|
||||
const std::string& scheme) {
|
||||
auto* job_factory = request_context_getter->job_factory();
|
||||
if (!job_factory->HasProtocolHandler(scheme))
|
||||
if (!job_factory_->HasProtocolHandler(scheme))
|
||||
return PROTOCOL_NOT_REGISTERED;
|
||||
job_factory->SetProtocolHandler(scheme, nullptr);
|
||||
job_factory_->SetProtocolHandler(scheme, nullptr);
|
||||
return PROTOCOL_OK;
|
||||
}
|
||||
|
||||
void Protocol::IsProtocolHandled(const std::string& scheme,
|
||||
const BooleanCallback& callback) {
|
||||
auto* getter = static_cast<URLRequestContextGetter*>(
|
||||
browser_context_->GetRequestContext());
|
||||
const BooleanCallback& callback) {
|
||||
content::BrowserThread::PostTaskAndReplyWithResult(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&Protocol::IsProtocolHandledInIO, base::RetainedRef(getter),
|
||||
scheme),
|
||||
base::Bind(&Protocol::IsProtocolHandledInIO,
|
||||
base::Unretained(this), scheme),
|
||||
callback);
|
||||
}
|
||||
|
||||
// static
|
||||
bool Protocol::IsProtocolHandledInIO(
|
||||
scoped_refptr<URLRequestContextGetter> request_context_getter,
|
||||
const std::string& scheme) {
|
||||
return request_context_getter->job_factory()->IsHandledProtocol(scheme);
|
||||
bool Protocol::IsProtocolHandledInIO(const std::string& scheme) {
|
||||
return job_factory_->IsHandledProtocol(scheme);
|
||||
}
|
||||
|
||||
void Protocol::UninterceptProtocol(const std::string& scheme,
|
||||
mate::Arguments* args) {
|
||||
void Protocol::UninterceptProtocol(
|
||||
const std::string& scheme, mate::Arguments* args) {
|
||||
CompletionCallback callback;
|
||||
args->GetNext(&callback);
|
||||
auto* getter = static_cast<URLRequestContextGetter*>(
|
||||
browser_context_->GetRequestContext());
|
||||
content::BrowserThread::PostTaskAndReplyWithResult(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::BindOnce(&Protocol::UninterceptProtocolInIO,
|
||||
base::RetainedRef(getter), scheme),
|
||||
base::BindOnce(&Protocol::OnIOCompleted, GetWeakPtr(), callback));
|
||||
base::Bind(&Protocol::UninterceptProtocolInIO,
|
||||
base::Unretained(this), scheme),
|
||||
base::Bind(&Protocol::OnIOCompleted,
|
||||
base::Unretained(this), callback));
|
||||
}
|
||||
|
||||
// static
|
||||
Protocol::ProtocolError Protocol::UninterceptProtocolInIO(
|
||||
scoped_refptr<URLRequestContextGetter> request_context_getter,
|
||||
const std::string& scheme) {
|
||||
return request_context_getter->job_factory()->UninterceptProtocol(scheme)
|
||||
? PROTOCOL_OK
|
||||
: PROTOCOL_NOT_INTERCEPTED;
|
||||
if (!original_protocols_.contains(scheme))
|
||||
return PROTOCOL_NOT_INTERCEPTED;
|
||||
job_factory_->ReplaceProtocol(scheme,
|
||||
original_protocols_.take_and_erase(scheme));
|
||||
return PROTOCOL_OK;
|
||||
}
|
||||
|
||||
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,57 +131,19 @@ 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 registred";
|
||||
case PROTOCOL_NOT_REGISTERED: return "The scheme has not been registred";
|
||||
case PROTOCOL_INTERCEPTED: return "The scheme has been intercepted";
|
||||
case PROTOCOL_NOT_INTERCEPTED: return "The scheme has not been intercepted";
|
||||
default: return "Unexpected error";
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
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) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "Protocol"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetMethod("registerServiceWorkerSchemes",
|
||||
&Protocol::RegisterServiceWorkerSchemes)
|
||||
.SetMethod("registerStringProtocol",
|
||||
&Protocol::RegisterProtocol<URLRequestStringJob>)
|
||||
.SetMethod("registerBufferProtocol",
|
||||
&Protocol::RegisterProtocol<URLRequestBufferJob>)
|
||||
.SetMethod("registerFileProtocol",
|
||||
&Protocol::RegisterProtocol<URLRequestAsyncAsarJob>)
|
||||
.SetMethod("registerHttpProtocol",
|
||||
&Protocol::RegisterProtocol<URLRequestFetchJob>)
|
||||
.SetMethod("registerStreamProtocol",
|
||||
&Protocol::RegisterProtocol<URLRequestStreamJob>)
|
||||
.SetMethod("unregisterProtocol", &Protocol::UnregisterProtocol)
|
||||
.SetMethod("isProtocolHandled", &Protocol::IsProtocolHandled)
|
||||
.SetMethod("interceptStringProtocol",
|
||||
&Protocol::InterceptProtocol<URLRequestStringJob>)
|
||||
.SetMethod("interceptBufferProtocol",
|
||||
&Protocol::InterceptProtocol<URLRequestBufferJob>)
|
||||
.SetMethod("interceptFileProtocol",
|
||||
&Protocol::InterceptProtocol<URLRequestAsyncAsarJob>)
|
||||
.SetMethod("interceptHttpProtocol",
|
||||
&Protocol::InterceptProtocol<URLRequestFetchJob>)
|
||||
.SetMethod("interceptStreamProtocol",
|
||||
&Protocol::InterceptProtocol<URLRequestStreamJob>)
|
||||
.SetMethod("uninterceptProtocol", &Protocol::UninterceptProtocol);
|
||||
mate::Handle<Protocol> Protocol::Create(
|
||||
v8::Isolate* isolate, AtomBrowserContext* browser_context) {
|
||||
return mate::CreateHandle(isolate, new Protocol(browser_context));
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
@@ -221,28 +152,15 @@ void Protocol::BuildPrototype(v8::Isolate* isolate,
|
||||
|
||||
namespace {
|
||||
|
||||
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");
|
||||
return;
|
||||
}
|
||||
|
||||
atom::api::RegisterStandardSchemes(schemes, args);
|
||||
}
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.SetMethod("registerStandardSchemes", &RegisterStandardSchemes);
|
||||
dict.SetMethod("getStandardSchemes", &atom::api::GetStandardSchemes);
|
||||
auto browser_context = static_cast<atom::AtomBrowserContext*>(
|
||||
atom::AtomBrowserMainParts::Get()->browser_context());
|
||||
dict.Set("protocol", atom::api::Protocol::Create(isolate, browser_context));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_protocol, Initialize)
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_protocol, Initialize)
|
||||
|
||||
@@ -5,54 +5,52 @@
|
||||
#ifndef ATOM_BROWSER_API_ATOM_API_PROTOCOL_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_PROTOCOL_H_
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/net/atom_url_request_job_factory.h"
|
||||
#include "base/callback.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/containers/scoped_ptr_hash_map.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "native_mate/arguments.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "net/url_request/url_request_context.h"
|
||||
#include "native_mate/wrappable.h"
|
||||
|
||||
namespace base {
|
||||
class DictionaryValue;
|
||||
namespace net {
|
||||
class URLRequest;
|
||||
class URLRequestContextGetter;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomBrowserContext;
|
||||
class AtomURLRequestJobFactory;
|
||||
|
||||
namespace api {
|
||||
|
||||
std::vector<std::string> GetStandardSchemes();
|
||||
void RegisterStandardSchemes(const std::vector<std::string>& schemes,
|
||||
mate::Arguments* args);
|
||||
|
||||
class Protocol : public mate::TrackableObject<Protocol> {
|
||||
class Protocol : public mate::Wrappable {
|
||||
public:
|
||||
using Handler =
|
||||
base::Callback<void(const base::DictionaryValue&, v8::Local<v8::Value>)>;
|
||||
base::Callback<void(const net::URLRequest*, v8::Local<v8::Value>)>;
|
||||
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 void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
static mate::Handle<Protocol> Create(
|
||||
v8::Isolate* isolate, AtomBrowserContext* browser_context);
|
||||
|
||||
protected:
|
||||
Protocol(v8::Isolate* isolate, AtomBrowserContext* browser_context);
|
||||
~Protocol() override;
|
||||
explicit Protocol(AtomBrowserContext* browser_context);
|
||||
|
||||
// mate::Wrappable implementations:
|
||||
virtual mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate);
|
||||
|
||||
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 +60,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) {}
|
||||
@@ -90,36 +89,32 @@ class Protocol : public mate::TrackableObject<Protocol> {
|
||||
DISALLOW_COPY_AND_ASSIGN(CustomProtocolHandler);
|
||||
};
|
||||
|
||||
// Register schemes that can handle service worker.
|
||||
void RegisterServiceWorkerSchemes(const std::vector<std::string>& schemes);
|
||||
// Register schemes to standard scheme list.
|
||||
void RegisterStandardSchemes(const std::vector<std::string>& schemes);
|
||||
|
||||
// Register the protocol with certain request job.
|
||||
template <typename RequestJob>
|
||||
template<typename RequestJob>
|
||||
void RegisterProtocol(const std::string& scheme,
|
||||
const Handler& handler,
|
||||
mate::Arguments* args) {
|
||||
CompletionCallback callback;
|
||||
args->GetNext(&callback);
|
||||
auto* getter = static_cast<URLRequestContextGetter*>(
|
||||
browser_context_->GetRequestContext());
|
||||
content::BrowserThread::PostTaskAndReplyWithResult(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::BindOnce(&Protocol::RegisterProtocolInIO<RequestJob>,
|
||||
base::RetainedRef(getter), isolate(), scheme, handler),
|
||||
base::BindOnce(&Protocol::OnIOCompleted, GetWeakPtr(), callback));
|
||||
base::Bind(&Protocol::RegisterProtocolInIO<RequestJob>,
|
||||
base::Unretained(this), scheme, handler),
|
||||
base::Bind(&Protocol::OnIOCompleted,
|
||||
base::Unretained(this), callback));
|
||||
}
|
||||
template <typename RequestJob>
|
||||
static ProtocolError RegisterProtocolInIO(
|
||||
scoped_refptr<URLRequestContextGetter> request_context_getter,
|
||||
v8::Isolate* isolate,
|
||||
const std::string& scheme,
|
||||
const Handler& handler) {
|
||||
auto* job_factory = request_context_getter->job_factory();
|
||||
if (job_factory->IsHandledProtocol(scheme))
|
||||
template<typename RequestJob>
|
||||
ProtocolError RegisterProtocolInIO(const std::string& scheme,
|
||||
const Handler& handler) {
|
||||
if (job_factory_->IsHandledProtocol(scheme))
|
||||
return PROTOCOL_REGISTERED;
|
||||
auto protocol_handler = std::make_unique<CustomProtocolHandler<RequestJob>>(
|
||||
isolate, request_context_getter.get(), handler);
|
||||
if (job_factory->SetProtocolHandler(scheme, std::move(protocol_handler)))
|
||||
scoped_ptr<CustomProtocolHandler<RequestJob>> protocol_handler(
|
||||
new CustomProtocolHandler<RequestJob>(
|
||||
isolate(), request_context_getter_, handler));
|
||||
if (job_factory_->SetProtocolHandler(scheme, protocol_handler.Pass()))
|
||||
return PROTOCOL_OK;
|
||||
else
|
||||
return PROTOCOL_FAIL;
|
||||
@@ -127,56 +122,49 @@ class Protocol : public mate::TrackableObject<Protocol> {
|
||||
|
||||
// Unregister the protocol handler that handles |scheme|.
|
||||
void UnregisterProtocol(const std::string& scheme, mate::Arguments* args);
|
||||
static ProtocolError UnregisterProtocolInIO(
|
||||
scoped_refptr<URLRequestContextGetter> request_context_getter,
|
||||
const std::string& scheme);
|
||||
ProtocolError UnregisterProtocolInIO(const std::string& scheme);
|
||||
|
||||
// Whether the protocol has handler registered.
|
||||
void IsProtocolHandled(const std::string& scheme,
|
||||
const BooleanCallback& callback);
|
||||
static bool IsProtocolHandledInIO(
|
||||
scoped_refptr<URLRequestContextGetter> request_context_getter,
|
||||
const std::string& scheme);
|
||||
bool IsProtocolHandledInIO(const std::string& scheme);
|
||||
|
||||
// Replace the protocol handler with a new one.
|
||||
template <typename RequestJob>
|
||||
template<typename RequestJob>
|
||||
void InterceptProtocol(const std::string& scheme,
|
||||
const Handler& handler,
|
||||
mate::Arguments* args) {
|
||||
CompletionCallback callback;
|
||||
args->GetNext(&callback);
|
||||
auto* getter = static_cast<URLRequestContextGetter*>(
|
||||
browser_context_->GetRequestContext());
|
||||
content::BrowserThread::PostTaskAndReplyWithResult(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::BindOnce(&Protocol::InterceptProtocolInIO<RequestJob>,
|
||||
base::RetainedRef(getter), isolate(), scheme, handler),
|
||||
base::BindOnce(&Protocol::OnIOCompleted, GetWeakPtr(), callback));
|
||||
base::Bind(&Protocol::InterceptProtocolInIO<RequestJob>,
|
||||
base::Unretained(this), scheme, handler),
|
||||
base::Bind(&Protocol::OnIOCompleted,
|
||||
base::Unretained(this), callback));
|
||||
}
|
||||
template <typename RequestJob>
|
||||
static ProtocolError InterceptProtocolInIO(
|
||||
scoped_refptr<URLRequestContextGetter> request_context_getter,
|
||||
v8::Isolate* isolate,
|
||||
const std::string& scheme,
|
||||
const Handler& handler) {
|
||||
auto* job_factory = request_context_getter->job_factory();
|
||||
if (!job_factory->IsHandledProtocol(scheme))
|
||||
template<typename RequestJob>
|
||||
ProtocolError InterceptProtocolInIO(const std::string& scheme,
|
||||
const Handler& handler) {
|
||||
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))
|
||||
if (!job_factory_->HasProtocolHandler(scheme))
|
||||
return PROTOCOL_FAIL;
|
||||
auto protocol_handler = std::make_unique<CustomProtocolHandler<RequestJob>>(
|
||||
isolate, request_context_getter.get(), handler);
|
||||
if (!job_factory->InterceptProtocol(scheme, std::move(protocol_handler)))
|
||||
if (ContainsKey(original_protocols_, scheme))
|
||||
return PROTOCOL_INTERCEPTED;
|
||||
scoped_ptr<CustomProtocolHandler<RequestJob>> protocol_handler(
|
||||
new CustomProtocolHandler<RequestJob>(
|
||||
isolate(), request_context_getter_, handler));
|
||||
original_protocols_.set(
|
||||
scheme,
|
||||
job_factory_->ReplaceProtocol(scheme, protocol_handler.Pass()));
|
||||
return PROTOCOL_OK;
|
||||
}
|
||||
|
||||
// Restore the |scheme| to its original protocol handler.
|
||||
void UninterceptProtocol(const std::string& scheme, mate::Arguments* args);
|
||||
static ProtocolError UninterceptProtocolInIO(
|
||||
scoped_refptr<URLRequestContextGetter> request_context_getter,
|
||||
const std::string& scheme);
|
||||
ProtocolError UninterceptProtocolInIO(const std::string& scheme);
|
||||
|
||||
// Convert error code to JS exception and call the callback.
|
||||
void OnIOCompleted(const CompletionCallback& callback, ProtocolError error);
|
||||
@@ -184,10 +172,15 @@ class Protocol : public mate::TrackableObject<Protocol> {
|
||||
// Convert error code to string.
|
||||
std::string ErrorCodeToString(ProtocolError error);
|
||||
|
||||
base::WeakPtr<Protocol> GetWeakPtr() { return weak_factory_.GetWeakPtr(); }
|
||||
net::URLRequestContextGetter* request_context_getter_;
|
||||
|
||||
scoped_refptr<AtomBrowserContext> browser_context_;
|
||||
base::WeakPtrFactory<Protocol> weak_factory_;
|
||||
// Map that stores the original protocols of schemes.
|
||||
using OriginalProtocolsMap = base::ScopedPtrHashMap<
|
||||
std::string,
|
||||
scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>>;
|
||||
OriginalProtocolsMap original_protocols_;
|
||||
|
||||
AtomURLRequestJobFactory* job_factory_; // weak ref
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Protocol);
|
||||
};
|
||||
|
||||
@@ -1,91 +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_render_process_preferences.h"
|
||||
|
||||
#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 "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 {
|
||||
|
||||
namespace {
|
||||
|
||||
bool IsWebContents(v8::Isolate* isolate, content::RenderProcessHost* process) {
|
||||
content::WebContents* web_contents =
|
||||
static_cast<AtomBrowserClient*>(AtomBrowserClient::Get())
|
||||
->GetWebContentsFromProcessID(process->GetID());
|
||||
if (!web_contents)
|
||||
return false;
|
||||
|
||||
auto api_web_contents = WebContents::CreateFrom(isolate, web_contents);
|
||||
auto type = api_web_contents->GetType();
|
||||
return type == WebContents::Type::BROWSER_WINDOW ||
|
||||
type == WebContents::Type::WEB_VIEW;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
RenderProcessPreferences::RenderProcessPreferences(
|
||||
v8::Isolate* isolate,
|
||||
const atom::RenderProcessPreferences::Predicate& predicate)
|
||||
: preferences_(predicate) {
|
||||
Init(isolate);
|
||||
}
|
||||
|
||||
RenderProcessPreferences::~RenderProcessPreferences() {}
|
||||
|
||||
int RenderProcessPreferences::AddEntry(const base::DictionaryValue& entry) {
|
||||
return preferences_.AddEntry(entry);
|
||||
}
|
||||
|
||||
void RenderProcessPreferences::RemoveEntry(int id) {
|
||||
preferences_.RemoveEntry(id);
|
||||
}
|
||||
|
||||
// static
|
||||
void RenderProcessPreferences::BuildPrototype(
|
||||
v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(
|
||||
mate::StringToV8(isolate, "RenderProcessPreferences"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetMethod("addEntry", &RenderProcessPreferences::AddEntry)
|
||||
.SetMethod("removeEntry", &RenderProcessPreferences::RemoveEntry);
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<RenderProcessPreferences>
|
||||
RenderProcessPreferences::ForAllWebContents(v8::Isolate* isolate) {
|
||||
return mate::CreateHandle(isolate,
|
||||
new RenderProcessPreferences(
|
||||
isolate, base::Bind(&IsWebContents, isolate)));
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
namespace {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(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