mirror of
https://github.com/electron/electron.git
synced 2026-02-19 03:14:51 -05:00
Compare commits
3 Commits
circle-win
...
v1.4.16
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8f487aa2cf | ||
|
|
634eb677c6 | ||
|
|
3d54b23b7a |
2489
.circleci/config.yml
2489
.circleci/config.yml
File diff suppressed because it is too large
Load Diff
@@ -1,7 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
mkdir -p ~/.ssh
|
||||
echo "|1|B3r+7aO0/x90IdefihIjxIoJrrk=|OJddGDfhbuLFc1bUyy84hhIw57M= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
|
||||
|1|rGlEvW55DtzNZp+pzw9gvyOyKi4=|LLWr+7qlkAlw3YGGVfLHHxB/kR0= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==" >> ~/.ssh/known_hosts
|
||||
@@ -1,3 +0,0 @@
|
||||
*
|
||||
!tools/xvfb-init.sh
|
||||
!build/install-build-deps.sh
|
||||
@@ -1,7 +0,0 @@
|
||||
# These env vars are only necessary for creating Electron releases.
|
||||
# See docs/development/releasing.md
|
||||
|
||||
APPVEYOR_CLOUD_TOKEN=
|
||||
CIRCLE_TOKEN=
|
||||
ELECTRON_GITHUB_TOKEN=
|
||||
VSTS_TOKEN=
|
||||
@@ -1,45 +0,0 @@
|
||||
{
|
||||
"extends": "standard",
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"plugins": ["@typescript-eslint"],
|
||||
"env": {
|
||||
"browser": true
|
||||
},
|
||||
"rules": {
|
||||
"no-var": "error",
|
||||
"no-unused-vars": 0,
|
||||
"no-global-assign": 0,
|
||||
"@typescript-eslint/no-unused-vars": ["error", {
|
||||
"vars": "all",
|
||||
"args": "after-used",
|
||||
"ignoreRestSiblings": false
|
||||
}],
|
||||
"prefer-const": ["error", {
|
||||
"destructuring": "all"
|
||||
}],
|
||||
"standard/no-callback-literal": "off",
|
||||
"node/no-deprecated-api": 0
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 6,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"globals": {
|
||||
"standardScheme": "readonly"
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": "*.js",
|
||||
"rules": {
|
||||
"@typescript-eslint/no-unused-vars": "off"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": "*.d.ts",
|
||||
"rules": {
|
||||
"no-useless-constructor": "off",
|
||||
"@typescript-eslint/no-unused-vars": "off"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
3
.gitattributes
vendored
3
.gitattributes
vendored
@@ -1,3 +0,0 @@
|
||||
# `git apply` and friends don't understand CRLF, even on windows. Force those
|
||||
# files to be checked out with LF endings even if core.autocrlf is true.
|
||||
*.patch text eol=lf
|
||||
22
.github/CODEOWNERS
vendored
22
.github/CODEOWNERS
vendored
@@ -1,22 +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
|
||||
|
||||
# Most stuff in here is owned by the Community & Safety WG...
|
||||
/.github/* @electron/wg-community
|
||||
|
||||
# ...except the Admin WG maintains this file.
|
||||
/.github/CODEOWNERS @electron/wg-admin
|
||||
|
||||
# Upgrades WG
|
||||
/patches/ @electron/wg-upgrades
|
||||
DEPS @electron/wg-upgrades
|
||||
|
||||
# Docs & Tooling WG
|
||||
/default_app/ @electron/wg-docs-tools
|
||||
/docs/ @electron/wg-docs-tools
|
||||
|
||||
# Releases WG
|
||||
/npm/ @electron/wg-releases
|
||||
/script/release @electron/wg-releases
|
||||
58
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
58
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
@@ -1,58 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve Electron
|
||||
|
||||
---
|
||||
|
||||
<!-- As an open source project with a dedicated but small maintainer team, it can sometimes take a long time for issues to be addressed so please be patient and we will get back to you as soon as we can.
|
||||
-->
|
||||
|
||||
### Preflight Checklist
|
||||
<!-- Please ensure you've completed the following steps by replacing [ ] with [x]-->
|
||||
|
||||
* [ ] I have read the [Contributing Guidelines](https://github.com/electron/electron/blob/master/CONTRIBUTING.md) for this project.
|
||||
* [ ] I agree to follow the [Code of Conduct](https://github.com/electron/electron/blob/master/CODE_OF_CONDUCT.md) that this project adheres to.
|
||||
* [ ] I have searched the issue tracker for an issue that matches the one I want to file, without success.
|
||||
|
||||
### Issue Details
|
||||
|
||||
* **Electron Version:**
|
||||
* <!-- (output of `node_modules/.bin/electron --version`) e.g. 4.0.3 -->
|
||||
* **Operating System:**
|
||||
* <!-- (Platform and Version) e.g. macOS 10.13.6 / Windows 10 (1803) / Ubuntu 18.04 x64 -->
|
||||
* **Last Known Working Electron version:**
|
||||
* <!-- (if applicable) e.g. 3.1.0 -->
|
||||
|
||||
### 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 an example.
|
||||
-->
|
||||
|
||||
<!--
|
||||
For bugs that can be encapsulated in a small experiment, you can use Electron Fiddle (https://github.com/electron/fiddle) to publish your example to a GitHub Gist and link it your bug report.
|
||||
-->
|
||||
|
||||
<!--
|
||||
If Fiddle is insufficient to produce an example, please provide an example 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. -->
|
||||
27
.github/ISSUE_TEMPLATE/Feature_request.md
vendored
27
.github/ISSUE_TEMPLATE/Feature_request.md
vendored
@@ -1,27 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for Electron
|
||||
|
||||
---
|
||||
|
||||
<!-- As an open source project with a dedicated but small maintainer team, it can sometimes take a long time for issues to be addressed so please be patient and we will get back to you as soon as we can.
|
||||
-->
|
||||
|
||||
### Preflight Checklist
|
||||
<!-- Please ensure you've completed the following steps by replacing [ ] with [x]-->
|
||||
|
||||
* [ ] I have read the [Contributing Guidelines](https://github.com/electron/electron/blob/master/CONTRIBUTING.md) for this project.
|
||||
* [ ] I agree to follow the [Code of Conduct](https://github.com/electron/electron/blob/master/CODE_OF_CONDUCT.md) that this project adheres to.
|
||||
* [ ] I have searched the issue tracker for a feature request that matches the one I want to file, without success.
|
||||
|
||||
### Problem Description
|
||||
<!-- Is your feature request related to a problem? Please add a clear and concise description of what the problem is. -->
|
||||
|
||||
### Proposed Solution
|
||||
<!-- Describe the solution you'd like in a clear and concise manner -->
|
||||
|
||||
### Alternatives Considered
|
||||
<!-- A clear and concise description of any alternative solutions or features you've considered. -->
|
||||
|
||||
### Additional Information
|
||||
<!-- Add any other context about the problem here. -->
|
||||
@@ -1,25 +0,0 @@
|
||||
---
|
||||
name: Mac App Store Private API Rejection
|
||||
about: Your app was rejected from the Mac App Store for using private API's
|
||||
|
||||
---
|
||||
|
||||
<!-- As an open source project with a dedicated but small maintainer team, it can sometimes take a long time for issues to be addressed so please be patient and we will get back to you as soon as we can.
|
||||
-->
|
||||
|
||||
### Preflight Checklist
|
||||
<!-- Please ensure you've completed the following steps by replacing [ ] with [x]-->
|
||||
|
||||
* [ ] I have read the [Contributing Guidelines](https://github.com/electron/electron/blob/master/CONTRIBUTING.md) for this project.
|
||||
* [ ] I agree to follow the [Code of Conduct](https://github.com/electron/electron/blob/master/CODE_OF_CONDUCT.md) that this project adheres to.
|
||||
|
||||
### Issue Details
|
||||
|
||||
* **Electron Version:**
|
||||
* <!-- (output of `node_modules/.bin/electron --version`) e.g. 4.0.3 -->
|
||||
|
||||
### Rejection Email
|
||||
<!-- Paste the contents of your rejection email here, censoring any private information such as app names.-->
|
||||
|
||||
### Additional Information
|
||||
<!-- Add any other context about the problem here. -->
|
||||
10
.github/ISSUE_TEMPLATE/security_report.md
vendored
10
.github/ISSUE_TEMPLATE/security_report.md
vendored
@@ -1,10 +0,0 @@
|
||||
---
|
||||
name: Security report
|
||||
about: Do not create an issue for security reports, send an email to security@electronjs.org
|
||||
|
||||
---
|
||||
|
||||
### Notice
|
||||
|
||||
**DO NOT** create an issue for security reports.
|
||||
Send an email to: **security@electronjs.org**.
|
||||
21
.github/PULL_REQUEST_TEMPLATE.md
vendored
21
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,21 +0,0 @@
|
||||
#### Description of Change
|
||||
<!--
|
||||
Thank you for your Pull Request. Please provide a description above and review
|
||||
the requirements below.
|
||||
|
||||
Contributors guide: https://github.com/electron/electron/blob/master/CONTRIBUTING.md
|
||||
-->
|
||||
|
||||
#### Checklist
|
||||
<!-- Remove items that do not apply. For completed items, change [ ] to [x]. -->
|
||||
|
||||
- [ ] PR description included and stakeholders cc'd
|
||||
- [ ] `npm test` passes
|
||||
- [ ] tests are [changed or added](https://github.com/electron/electron/blob/master/docs/development/testing.md)
|
||||
- [ ] relevant documentation is changed or added
|
||||
- [ ] PR title follows semantic [commit guidelines](https://github.com/electron/electron/blob/master/docs/development/pull-requests.md#commit-message-guidelines)
|
||||
- [ ] [PR release notes](https://github.com/electron/clerk/blob/master/README.md) describe the change in a way relevant to app developers, and are [capitalized, punctuated, and past tense](https://github.com/electron/clerk/blob/master/README.md#examples).
|
||||
|
||||
#### Release Notes
|
||||
|
||||
Notes: <!-- Please add a one-line description for app developers to read in the release notes, or `no-notes` if no notes relevant to app developers. Examples and help on special cases: https://github.com/electron/clerk/blob/master/README.md#examples -->
|
||||
39
.github/config.yml
vendored
39
.github/config.yml
vendored
@@ -1,39 +0,0 @@
|
||||
# Comment to be posted to on PRs from first time contributors in your repository
|
||||
newPRWelcomeComment: |
|
||||
💖 Thanks for opening this pull request! 💖
|
||||
|
||||
We use [semantic commit messages](https://github.com/electron/electron/blob/master/docs/development/pull-requests.md#commit-message-guidelines) to streamline the release process. Before your pull request can be merged, you should **update your pull request title** to start with a semantic prefix.
|
||||
|
||||
Examples of commit messages with semantic prefixes:
|
||||
|
||||
- `fix: don't overwrite prevent_default if default wasn't prevented`
|
||||
- `feat: add app.isPackaged() method`
|
||||
- `docs: app.isDefaultProtocolClient is now available on Linux`
|
||||
|
||||
Things that will help get your PR across the finish line:
|
||||
|
||||
- Follow the JavaScript, C++, and Python [coding style](https://github.com/electron/electron/blob/master/docs/development/coding-style.md).
|
||||
- Run `npm run lint` locally to catch formatting errors earlier.
|
||||
- Document any user-facing changes you've made following the [documentation styleguide](https://github.com/electron/electron/blob/master/docs/styleguide.md).
|
||||
- Include tests when adding/changing behavior.
|
||||
- Include screenshots and animated GIFs whenever possible.
|
||||
|
||||
We get a lot of pull requests on this repo, so please be patient and we will get back to you as soon as we can.
|
||||
|
||||
# Configuration for first-pr-merge - https://github.com/behaviorbot/first-pr-merge
|
||||
|
||||
# Comment to be posted to on pull requests merged by a first time user
|
||||
firstPRMergeComment: >
|
||||
Congrats on merging your first pull request! 🎉🎉🎉
|
||||
|
||||
# Users authorized to run manual trop backports
|
||||
authorizedUsers:
|
||||
- alexeykuzmin
|
||||
- ckerr
|
||||
- codebytere
|
||||
- deepak1556
|
||||
- jkleinsc
|
||||
- MarshallOfSound
|
||||
- miniak
|
||||
- nornagon
|
||||
- zcbenz
|
||||
81
.gitignore
vendored
81
.gitignore
vendored
@@ -1,68 +1,29 @@
|
||||
.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/
|
||||
/build/
|
||||
/dist/
|
||||
/external_binaries/
|
||||
/out/
|
||||
/vendor/.gclient
|
||||
/vendor/debian_jessie_mips64-sysroot/
|
||||
/vendor/debian_stretch_amd64-sysroot/
|
||||
/vendor/debian_stretch_arm-sysroot/
|
||||
/vendor/debian_stretch_arm64-sysroot/
|
||||
/vendor/debian_stretch_i386-sysroot/
|
||||
/vendor/gcc-4.8.3-d197-n64-loongson/
|
||||
/vendor/readme-gcc483-loongson.txt
|
||||
/vendor/download/
|
||||
/vendor/llvm-build/
|
||||
/vendor/llvm/
|
||||
/vendor/npm/
|
||||
/vendor/brightray/vendor/download/
|
||||
/vendor/debian_wheezy_amd64-sysroot/
|
||||
/vendor/debian_wheezy_arm-sysroot/
|
||||
/vendor/debian_wheezy_i386-sysroot/
|
||||
/vendor/python_26/
|
||||
/vendor/native_mksnapshot
|
||||
/vendor/LICENSES.chromium.html
|
||||
/vendor/pyyaml
|
||||
/vendor/npm/
|
||||
/vendor/llvm/
|
||||
/vendor/llvm-build/
|
||||
/vendor/.gclient
|
||||
node_modules/
|
||||
SHASUMS256.txt
|
||||
**/package-lock.json
|
||||
compile_commands.json
|
||||
.envrc
|
||||
|
||||
# npm package
|
||||
/npm/dist
|
||||
/npm/path.txt
|
||||
|
||||
.npmrc
|
||||
|
||||
# Generated API definitions
|
||||
electron-api.json
|
||||
electron.d.ts
|
||||
|
||||
# Spec hash calculation
|
||||
spec/.hash
|
||||
|
||||
# Eslint Cache
|
||||
.eslintcache
|
||||
|
||||
# Generated native addon files
|
||||
/spec-main/fixtures/native-addon/echo/build/
|
||||
|
||||
# If someone runs tsc this is where stuff will end up
|
||||
ts-gen
|
||||
|
||||
# Used to accelerate CI builds
|
||||
.depshash
|
||||
.depshash-target
|
||||
*.xcodeproj
|
||||
*.swp
|
||||
*.pyc
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
.vs/
|
||||
.vscode/
|
||||
*.vcxproj
|
||||
*.vcxproj.user
|
||||
*.vcxproj.filters
|
||||
*.sln
|
||||
*.log
|
||||
|
||||
18
.gitmodules
vendored
18
.gitmodules
vendored
@@ -1,3 +1,21 @@
|
||||
[submodule "vendor/brightray"]
|
||||
path = vendor/brightray
|
||||
url = https://github.com/electron/brightray.git
|
||||
[submodule "vendor/node"]
|
||||
path = vendor/node
|
||||
url = https://github.com/electron/node.git
|
||||
[submodule "vendor/depot_tools"]
|
||||
path = vendor/depot_tools
|
||||
url = https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
[submodule "vendor/breakpad"]
|
||||
path = vendor/breakpad
|
||||
url = https://github.com/electron/chromium-breakpad.git
|
||||
[submodule "vendor/native_mate"]
|
||||
path = vendor/native_mate
|
||||
url = https://github.com/electron/native-mate.git
|
||||
[submodule "vendor/crashpad"]
|
||||
path = vendor/crashpad
|
||||
url = https://github.com/electron/crashpad.git
|
||||
[submodule "vendor/requests"]
|
||||
path = vendor/requests
|
||||
url = https://github.com/kennethreitz/requests
|
||||
|
||||
1
.node-version
Normal file
1
.node-version
Normal file
@@ -0,0 +1 @@
|
||||
v6.3.0
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"plugins": [
|
||||
["remark-lint-code-block-style", "fenced"],
|
||||
["remark-lint-fenced-code-flag"]
|
||||
]
|
||||
}
|
||||
29
.travis.yml
Normal file
29
.travis.yml
Normal file
@@ -0,0 +1,29 @@
|
||||
git:
|
||||
depth: 10
|
||||
notifications:
|
||||
email: false
|
||||
|
||||
language: node_js
|
||||
node_js:
|
||||
- "4"
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
env:
|
||||
- TARGET_ARCH=x64
|
||||
osx_image: xcode7.3
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
env: TARGET_ARCH=arm
|
||||
- os: linux
|
||||
env: TARGET_ARCH=ia32
|
||||
allow_failures:
|
||||
- os: osx
|
||||
|
||||
script: './script/cibuild'
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
@@ -1,4 +1,4 @@
|
||||
# Contributor Covenant Code of Conduct:
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
@@ -34,13 +34,13 @@ This Code of Conduct applies both within project spaces and in public spaces whe
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [coc@electronjs.org](mailto:coc@electronjs.org). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [electron@github.com](mailto:electron@github.com). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor-Covenant][homepage], version 1.4, available at [https://contributor-covenant.org/version/1/4][version]
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: https://contributor-covenant.org
|
||||
[version]: https://contributor-covenant.org/version/1/4/
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
||||
|
||||
111
CONTRIBUTING.md
111
CONTRIBUTING.md
@@ -1,70 +1,79 @@
|
||||
# Contributing to Electron
|
||||
|
||||
:memo: Available Translations: [Korean](https://github.com/electron/electron/tree/master/docs-translations/ko-KR/project/CONTRIBUTING.md) | [Simplified Chinese](https://github.com/electron/electron/tree/master/docs-translations/zh-CN/project/CONTRIBUTING.md) | [Brazilian Portuguese](https://github.com/electron/electron/tree/master/docs-translations/pt-BR/project/CONTRIBUTING.md) | [Dutch](https://github.com/electron/electron/tree/master/docs-translations/nl/project/CONTRIBUTING.md)
|
||||
|
||||
:+1::tada: First off, thanks for taking the time to contribute! :tada::+1:
|
||||
|
||||
This project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDUCT.md).
|
||||
By participating, you are expected to uphold this code. Please report unacceptable
|
||||
behavior to coc@electronjs.org.
|
||||
behavior to atom@github.com.
|
||||
|
||||
The following is a set of guidelines for contributing to Electron.
|
||||
These are just guidelines, not rules, use your best judgment and feel free to
|
||||
propose changes to this document in a pull request.
|
||||
|
||||
## [Issues](https://electronjs.org/docs/development/issues)
|
||||
## Submitting Issues
|
||||
|
||||
Issues are created [here](https://github.com/electron/electron/issues/new).
|
||||
* You can create an issue [here](https://github.com/electron/electron/issues/new),
|
||||
but before doing that please read the notes below and include as many details as
|
||||
possible with your report. If you can, please include:
|
||||
* The version of Electron you are using
|
||||
* The operating system you are using
|
||||
* If applicable, what you were doing when the issue arose and what you
|
||||
expected to happen
|
||||
* Other things that will help resolve your issue:
|
||||
* Screenshots and animated GIFs
|
||||
* Error output that appears in your terminal, dev tools or as an alert
|
||||
* Perform a [cursory search](https://github.com/electron/electron/issues?utf8=✓&q=is%3Aissue+)
|
||||
to see if a similar issue has already been submitted
|
||||
|
||||
* [How to Contribute in Issues](https://electronjs.org/docs/development/issues#how-to-contribute-in-issues)
|
||||
* [Asking for General Help](https://electronjs.org/docs/development/issues#asking-for-general-help)
|
||||
* [Submitting a Bug Report](https://electronjs.org/docs/development/issues#submitting-a-bug-report)
|
||||
* [Triaging a Bug Report](https://electronjs.org/docs/development/issues#triaging-a-bug-report)
|
||||
* [Resolving a Bug Report](https://electronjs.org/docs/development/issues#resolving-a-bug-report)
|
||||
## Submitting Pull Requests
|
||||
|
||||
### Issue Closure
|
||||
* Include screenshots and animated GIFs in your pull request whenever possible.
|
||||
* Follow the JavaScript, C++, and Python [coding style defined in docs](/docs/development/coding-style.md).
|
||||
* Write documentation in [Markdown](https://daringfireball.net/projects/markdown).
|
||||
See the [Documentation Styleguide](/docs/styleguide.md).
|
||||
* Use short, present tense commit messages. See [Commit Message Styleguide](#git-commit-messages).
|
||||
|
||||
Bug reports will be closed if the issue has been inactive and the latest affected version no longer receives support. At the moment, Electron maintains its three latest major versions, with a new major version being released every 12 weeks. (For more information on Electron's release cadence, see [this blog post](https://electronjs.org/blog/12-week-cadence).)
|
||||
## Styleguides
|
||||
|
||||
_If an issue has been closed and you still feel it's relevant, feel free to ping a maintainer or add a comment!_
|
||||
### General Code
|
||||
|
||||
### Languages
|
||||
* 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`
|
||||
|
||||
We accept issues in *any* language.
|
||||
When an issue is posted in a language besides English, it is acceptable and encouraged to post an English-translated copy as a reply.
|
||||
Anyone may post the translated reply.
|
||||
In most cases, a quick pass through translation software is sufficient.
|
||||
Having the original text _as well as_ the translation can help mitigate translation errors.
|
||||
### Git Commit Messages
|
||||
|
||||
Responses to posted issues may or may not be in the original language.
|
||||
|
||||
**Please note** that using non-English as an attempt to circumvent our [Code of Conduct](https://github.com/electron/electron/blob/master/CODE_OF_CONDUCT.md) will be an immediate, and possibly indefinite, ban from the project.
|
||||
|
||||
## [Pull Requests](https://electronjs.org/docs/development/pull-requests)
|
||||
|
||||
Pull Requests are the way concrete changes are made to the code, documentation,
|
||||
dependencies, and tools contained in the `electron/electron` repository.
|
||||
|
||||
* [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)
|
||||
|
||||
## Style Guides
|
||||
|
||||
See [Coding Style](https://electronjs.org/docs/development/coding-style) for information about which standards Electron adheres to in different parts of its codebase.
|
||||
|
||||
## Further Reading
|
||||
|
||||
For more in-depth guides on developing Electron, see
|
||||
[/docs/development](/docs/development/README.md)
|
||||
* Use the present tense ("Add feature" not "Added feature")
|
||||
* Use the imperative mood ("Move cursor to..." not "Moves cursor to...")
|
||||
* Limit the first line to 72 characters or less
|
||||
* Reference issues and pull requests liberally
|
||||
* When only changing documentation, include `[ci skip]` in the commit description
|
||||
* Consider starting the commit message with an applicable emoji:
|
||||
* :art: `:art:` when improving the format/structure of the code
|
||||
* :racehorse: `:racehorse:` when improving performance
|
||||
* :non-potable_water: `:non-potable_water:` when plugging memory leaks
|
||||
* :memo: `:memo:` when writing docs
|
||||
* :penguin: `:penguin:` when fixing something on Linux
|
||||
* :apple: `:apple:` when fixing something on macOS
|
||||
* :checkered_flag: `:checkered_flag:` when fixing something on Windows
|
||||
* :bug: `:bug:` when fixing a bug
|
||||
* :fire: `:fire:` when removing code or files
|
||||
* :green_heart: `:green_heart:` when fixing the CI build
|
||||
* :white_check_mark: `:white_check_mark:` when adding tests
|
||||
* :lock: `:lock:` when dealing with security
|
||||
* :arrow_up: `:arrow_up:` when upgrading dependencies
|
||||
* :arrow_down: `:arrow_down:` when downgrading dependencies
|
||||
* :shirt: `:shirt:` when removing linter warnings
|
||||
|
||||
154
DEPS
154
DEPS
@@ -1,154 +0,0 @@
|
||||
gclient_gn_args_file = 'src/build/config/gclient_args.gni'
|
||||
gclient_gn_args = [
|
||||
'build_with_chromium',
|
||||
'checkout_android',
|
||||
'checkout_android_native_support',
|
||||
'checkout_libaom',
|
||||
'checkout_nacl',
|
||||
'checkout_oculus_sdk',
|
||||
'checkout_openxr'
|
||||
]
|
||||
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'dc9525d251bf30828899e4cd7161f6dc6507023f',
|
||||
'node_version':
|
||||
'v12.13.0',
|
||||
'nan_version':
|
||||
'2ee313aaca52e2b478965ac50eb5082520380d1b',
|
||||
|
||||
'boto_version': 'f7574aa6cc2c819430c1f05e9a1a1a666ef8169b',
|
||||
'pyyaml_version': '3.12',
|
||||
'requests_version': 'e4d59bedfd3c7f4f254f4f5d036587bcd8152458',
|
||||
|
||||
'boto_git': 'https://github.com/boto',
|
||||
'chromium_git': 'https://chromium.googlesource.com',
|
||||
'electron_git': 'https://github.com/electron',
|
||||
'nodejs_git': 'https://github.com/nodejs',
|
||||
'requests_git': 'https://github.com/kennethreitz',
|
||||
'yaml_git': 'https://github.com/yaml',
|
||||
|
||||
# KEEP IN SYNC WITH utils.js FILE
|
||||
'yarn_version': '1.15.2',
|
||||
|
||||
# To be able to build clean Chromium from sources.
|
||||
'apply_patches': True,
|
||||
|
||||
# Python interface to Amazon Web Services. Is used for releases only.
|
||||
'checkout_boto': False,
|
||||
|
||||
# To allow in-house builds to checkout those manually.
|
||||
'checkout_chromium': True,
|
||||
'checkout_node': True,
|
||||
'checkout_nan': True,
|
||||
|
||||
# It's only needed to parse the native tests configurations.
|
||||
'checkout_pyyaml': False,
|
||||
|
||||
# Python "requests" module is used for releases only.
|
||||
'checkout_requests': False,
|
||||
|
||||
# To allow running hooks without parsing the DEPS tree
|
||||
'process_deps': True,
|
||||
|
||||
# It is always needed for normal Electron builds,
|
||||
# but might be impossible for custom in-house builds.
|
||||
'download_external_binaries': True,
|
||||
|
||||
'checkout_nacl':
|
||||
False,
|
||||
'checkout_libaom':
|
||||
True,
|
||||
'checkout_oculus_sdk':
|
||||
False,
|
||||
'checkout_openxr':
|
||||
False,
|
||||
'build_with_chromium':
|
||||
True,
|
||||
'checkout_android':
|
||||
False,
|
||||
'checkout_android_native_support':
|
||||
False,
|
||||
}
|
||||
|
||||
deps = {
|
||||
'src': {
|
||||
'url': (Var("chromium_git")) + '/chromium/src.git@' + (Var("chromium_version")),
|
||||
'condition': 'checkout_chromium and process_deps',
|
||||
},
|
||||
'src/third_party/nan': {
|
||||
'url': (Var("nodejs_git")) + '/nan.git@' + (Var("nan_version")),
|
||||
'condition': 'checkout_nan and process_deps',
|
||||
},
|
||||
'src/third_party/electron_node': {
|
||||
'url': (Var("nodejs_git")) + '/node.git@' + (Var("node_version")),
|
||||
'condition': 'checkout_node and process_deps',
|
||||
},
|
||||
'src/electron/vendor/pyyaml': {
|
||||
'url': (Var("yaml_git")) + '/pyyaml.git@' + (Var("pyyaml_version")),
|
||||
'condition': 'checkout_pyyaml and process_deps',
|
||||
},
|
||||
'src/electron/vendor/boto': {
|
||||
'url': Var('boto_git') + '/boto.git' + '@' + Var('boto_version'),
|
||||
'condition': 'checkout_boto and process_deps',
|
||||
},
|
||||
'src/electron/vendor/requests': {
|
||||
'url': Var('requests_git') + '/requests.git' + '@' + Var('requests_version'),
|
||||
'condition': 'checkout_requests and process_deps',
|
||||
},
|
||||
}
|
||||
|
||||
hooks = [
|
||||
{
|
||||
'name': 'patch_chromium',
|
||||
'condition': '(checkout_chromium and apply_patches) and process_deps',
|
||||
'pattern': 'src/electron',
|
||||
'action': [
|
||||
'python',
|
||||
'src/electron/script/apply_all_patches.py',
|
||||
'src/electron/patches/config.json',
|
||||
],
|
||||
},
|
||||
{
|
||||
'name': 'electron_external_binaries',
|
||||
'pattern': 'src/electron/script/update-external-binaries.py',
|
||||
'condition': 'download_external_binaries',
|
||||
'action': [
|
||||
'python3',
|
||||
'src/electron/script/update-external-binaries.py',
|
||||
],
|
||||
},
|
||||
{
|
||||
'name': 'electron_npm_deps',
|
||||
'pattern': 'src/electron/package.json',
|
||||
'action': [
|
||||
'python',
|
||||
'-c',
|
||||
'import os, subprocess; os.chdir(os.path.join("src", "electron")); subprocess.check_call(["python", "script/lib/npx.py", "yarn@' + (Var("yarn_version")) + '", "install", "--frozen-lockfile"]);',
|
||||
],
|
||||
},
|
||||
{
|
||||
'name': 'setup_boto',
|
||||
'pattern': 'src/electron',
|
||||
'condition': 'checkout_boto and process_deps',
|
||||
'action': [
|
||||
'python',
|
||||
'-c',
|
||||
'import os, subprocess; os.chdir(os.path.join("src", "electron", "vendor", "boto")); subprocess.check_call(["python", "setup.py", "build"]);',
|
||||
],
|
||||
},
|
||||
{
|
||||
'name': 'setup_requests',
|
||||
'pattern': 'src/electron',
|
||||
'condition': 'checkout_requests and process_deps',
|
||||
'action': [
|
||||
'python',
|
||||
'-c',
|
||||
'import os, subprocess; os.chdir(os.path.join("src", "electron", "vendor", "requests")); subprocess.check_call(["python", "setup.py", "build"]);',
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
recursedeps = [
|
||||
'src',
|
||||
]
|
||||
@@ -1 +0,0 @@
|
||||
9.0.0-nightly.20191127
|
||||
23
ISSUE_TEMPLATE.md
Normal file
23
ISSUE_TEMPLATE.md
Normal file
@@ -0,0 +1,23 @@
|
||||
<!--
|
||||
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:
|
||||
|
||||
### Expected behavior
|
||||
|
||||
<!-- What do you think should happen? -->
|
||||
|
||||
### Actual behavior
|
||||
|
||||
<!-- What actually happens? -->
|
||||
|
||||
### How to reproduce
|
||||
|
||||
<!-- For bugs, provide sample code or a repo URL that demos the problem -->
|
||||
2
LICENSE
2
LICENSE
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2013-2019 GitHub Inc.
|
||||
Copyright (c) 2013-2017 GitHub Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
||||
124
README.md
124
README.md
@@ -1,104 +1,84 @@
|
||||
[](https://electronjs.org)
|
||||
[](http://electron.atom.io/)
|
||||
|
||||
|
||||
[](https://circleci.com/gh/electron/electron/tree/master)
|
||||
[](https://ci.appveyor.com/project/electron-bot/electron-ljo26/branch/master)
|
||||
[](https://travis-ci.org/electron/electron)
|
||||
[](https://ci.appveyor.com/project/Atom/electron)
|
||||
[](https://david-dm.org/electron/electron?type=dev)
|
||||
[](http://atom-slack.herokuapp.com/)
|
||||
|
||||
:memo: Available Translations: 🇨🇳 🇹🇼 🇧🇷 🇪🇸 🇰🇷 🇯🇵 🇷🇺 🇫🇷 🇹🇭 🇳🇱 🇹🇷 🇮🇩 🇺🇦 🇨🇿 🇮🇹 🇵🇱.
|
||||
View these docs in other languages at [electron/i18n](https://github.com/electron/i18n/tree/master/content/).
|
||||
:memo: Available Translations: [Korean](https://github.com/electron/electron/tree/master/docs-translations/ko-KR/project/README.md) | [Simplified Chinese](https://github.com/electron/electron/tree/master/docs-translations/zh-CN/project/README.md) | [Brazilian Portuguese](https://github.com/electron/electron/tree/master/docs-translations/pt-BR/project/README.md) | [Traditional Chinese](https://github.com/electron/electron/tree/master/docs-translations/zh-TW/project/README.md)
|
||||
|
||||
The Electron framework lets you write cross-platform desktop applications
|
||||
using JavaScript, HTML and CSS. It is based on [Node.js](https://nodejs.org/) and
|
||||
[Chromium](https://www.chromium.org) and is used by the [Atom
|
||||
editor](https://github.com/atom/atom) and many other [apps](https://electronjs.org/apps).
|
||||
[Chromium](http://www.chromium.org) and is used by the [Atom
|
||||
editor](https://github.com/atom/atom) and many other [apps](http://electron.atom.io/apps).
|
||||
|
||||
Follow [@ElectronJS](https://twitter.com/electronjs) on Twitter for important
|
||||
announcements.
|
||||
|
||||
This project adheres to the Contributor Covenant
|
||||
[code of conduct](https://github.com/electron/electron/tree/master/CODE_OF_CONDUCT.md).
|
||||
This project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDUCT.md).
|
||||
By participating, you are expected to uphold this code. Please report unacceptable
|
||||
behavior to [coc@electronjs.org](mailto:coc@electronjs.org).
|
||||
behavior to electron@github.com.
|
||||
|
||||
## Installation
|
||||
## Downloads
|
||||
|
||||
To install prebuilt Electron binaries, use [`npm`](https://docs.npmjs.com/).
|
||||
The preferred method is to install Electron as a development dependency in your
|
||||
app:
|
||||
To install prebuilt Electron binaries, use
|
||||
[`npm`](https://docs.npmjs.com/):
|
||||
|
||||
```sh
|
||||
npm install electron --save-dev [--save-exact]
|
||||
# Install as a development dependency
|
||||
npm install electron --save-dev
|
||||
|
||||
# Install the `electron` command globally in your $PATH
|
||||
npm install electron -g
|
||||
```
|
||||
|
||||
The `--save-exact` flag is recommended for Electron prior to version 2, as it does not follow semantic
|
||||
versioning. As of version 2.0.0, Electron follows semver, so you don't need `--save-exact` flag. For info on how to manage Electron versions in your apps, see
|
||||
[Electron versioning](docs/tutorial/electron-versioning.md).
|
||||
|
||||
For more installation options and troubleshooting tips, see
|
||||
[installation](docs/tutorial/installation.md).
|
||||
|
||||
## Quick start & Electron Fiddle
|
||||
|
||||
Use [`Electron Fiddle`](https://github.com/electron/fiddle)
|
||||
to build, run, and package small Electron experiments, to see code examples for all of Electron's APIs, and
|
||||
to try out different versions of Electron. It's designed to make the start of your journey with
|
||||
Electron easier.
|
||||
|
||||
Alternatively, clone and run the
|
||||
[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/fiddle](https://github.com/electron/fiddle) - A tool to build, run, and package small Electron experiments
|
||||
- [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)
|
||||
```
|
||||
See the [releases page](https://github.com/electron/electron/releases) for
|
||||
prebuilt binaries, debug symbols, and more.
|
||||
|
||||
### Mirrors
|
||||
|
||||
- [China](https://npm.taobao.org/mirrors/electron)
|
||||
|
||||
## Documentation
|
||||
|
||||
Guides and the API reference are located in the
|
||||
[docs](https://github.com/electron/electron/tree/master/docs) directory. It also
|
||||
contains documents describing how to build and contribute to Electron.
|
||||
|
||||
## Documentation Translations
|
||||
|
||||
Find documentation translations in [electron/i18n](https://github.com/electron/i18n).
|
||||
- [Brazilian Portuguese](https://github.com/electron/electron/tree/master/docs-translations/pt-BR)
|
||||
- [Korean](https://github.com/electron/electron/tree/master/docs-translations/ko-KR)
|
||||
- [Japanese](https://github.com/electron/electron/tree/master/docs-translations/jp)
|
||||
- [Spanish](https://github.com/electron/electron/tree/master/docs-translations/es)
|
||||
- [Simplified Chinese](https://github.com/electron/electron/tree/master/docs-translations/zh-CN)
|
||||
- [Traditional Chinese](https://github.com/electron/electron/tree/master/docs-translations/zh-TW)
|
||||
- [Turkish](https://github.com/electron/electron/tree/master/docs-translations/tr-TR)
|
||||
- [Ukrainian](https://github.com/electron/electron/tree/master/docs-translations/uk-UA)
|
||||
- [Russian](https://github.com/electron/electron/tree/master/docs-translations/ru-RU)
|
||||
- [French](https://github.com/electron/electron/tree/master/docs-translations/fr-FR)
|
||||
|
||||
## Contributing
|
||||
## Quick Start
|
||||
|
||||
If you are interested in reporting/fixing issues and contributing directly to the code base, please see [CONTRIBUTING.md](CONTRIBUTING.md) for more information on what we're looking for and how to get started.
|
||||
Clone and run the [`electron/electron-quick-start`](https://github.com/electron/electron-quick-start)
|
||||
repository to see a minimal Electron app in action.
|
||||
|
||||
## Community
|
||||
|
||||
Info on reporting bugs, getting help, finding third-party tools and sample apps,
|
||||
and more can be found in the [support document](docs/tutorial/support.md#finding-support).
|
||||
You can ask questions and interact with the community in the following
|
||||
locations:
|
||||
- [`electron`](http://discuss.atom.io/c/electron) category on the Atom
|
||||
forums
|
||||
- `#atom-shell` channel on Freenode
|
||||
- [`Atom`](http://atom-slack.herokuapp.com/) channel on Slack
|
||||
- [`electron-br`](https://electron-br.slack.com) *(Brazilian Portuguese)*
|
||||
- [`electron-kr`](http://www.meetup.com/electron-kr/) *(Korean)*
|
||||
- [`electron-jp`](https://electron-jp.slack.com) *(Japanese)*
|
||||
- [`electron-tr`](http://www.meetup.com/Electron-JS-Istanbul/) *(Turkish)*
|
||||
- [`electron-id`](https://electron-id.slack.com) *(Indonesia)*
|
||||
|
||||
Check out [awesome-electron](https://github.com/sindresorhus/awesome-electron)
|
||||
for a community maintained list of useful example apps, tools and resources.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
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).
|
||||
204
appveyor.yml
204
appveyor.yml
@@ -1,185 +1,25 @@
|
||||
# The config expects the following environment variables to be set:
|
||||
# - "GN_CONFIG" Build type. One of {'testing', 'release'}.
|
||||
# - "GN_EXTRA_ARGS" Additional gn arguments for a build config,
|
||||
# e.g. 'target_cpu="x86"' to build for a 32bit platform.
|
||||
# https://gn.googlesource.com/gn/+/master/docs/reference.md#target_cpu
|
||||
# Don't forget to set up "NPM_CONFIG_ARCH" and "TARGET_ARCH" accordningly
|
||||
# if you pass a custom value for 'target_cpu'.
|
||||
# - "ELECTRON_RELEASE" Set it to '1' upload binaries on success.
|
||||
# - "NPM_CONFIG_ARCH" E.g. 'x86'. Is used to build native Node.js modules.
|
||||
# Must match 'target_cpu' passed to "GN_EXTRA_ARGS" and "TARGET_ARCH" value.
|
||||
# - "TARGET_ARCH" Choose from {'ia32', 'x64', 'arm', 'arm64', 'mips64el'}.
|
||||
# Is used in some publishing scripts, but does NOT affect the Electron binary.
|
||||
# Must match 'target_cpu' passed to "GN_EXTRA_ARGS" and "NPM_CONFIG_ARCH" value.
|
||||
# - "UPLOAD_TO_S3" Set it to '1' upload a release to the S3 bucket.
|
||||
# Otherwise the release will be uploaded to the Github Releases.
|
||||
# (The value is only checked if "ELECTRON_RELEASE" is defined.)
|
||||
#
|
||||
# The publishing scripts expect access tokens to be defined as env vars,
|
||||
# but those are not covered here.
|
||||
#
|
||||
# AppVeyor docs on variables:
|
||||
# https://www.appveyor.com/docs/environment-variables/
|
||||
# https://www.appveyor.com/docs/build-configuration/#secure-variables
|
||||
# https://www.appveyor.com/docs/build-configuration/#custom-environment-variables
|
||||
# appveyor file
|
||||
# http://www.appveyor.com/docs/appveyor-yml
|
||||
version: "{build}"
|
||||
|
||||
# Uncomment these lines to enable RDP
|
||||
#on_finish:
|
||||
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
os: Visual Studio 2015
|
||||
|
||||
version: 1.0.{build}
|
||||
build_cloud: libcc-20
|
||||
image: vs2019-16.3-10.0.18362
|
||||
environment:
|
||||
GIT_CACHE_PATH: C:\Users\electron\libcc_cache
|
||||
ELECTRON_OUT_DIR: Default
|
||||
ELECTRON_ENABLE_STACK_DUMPING: 1
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
MOCHA_MULTI_REPORTERS: mocha-appveyor-reporter, tap
|
||||
notifications:
|
||||
- provider: Webhook
|
||||
url: https://electron-mission-control.herokuapp.com/rest/appveyor-hook
|
||||
method: POST
|
||||
headers:
|
||||
x-mission-control-secret:
|
||||
secure: 90BLVPcqhJPG7d24v0q/RRray6W3wDQ8uVQlQjOHaBWkw1i8FoA1lsjr2C/v1dVok+tS2Pi6KxDctPUkwIb4T27u4RhvmcPzQhVpfwVJAG9oNtq+yKN7vzHfg7k/pojEzVdJpQLzeJGcSrZu7VY39Q==
|
||||
on_build_success: false
|
||||
on_build_failure: true
|
||||
on_build_status_changed: false
|
||||
build_script:
|
||||
- ps: >-
|
||||
if(($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME -split "/")[0] -eq ($env:APPVEYOR_REPO_NAME -split "/")[0]) {
|
||||
Write-warning "Skipping PR build for branch"; Exit-AppveyorBuild
|
||||
} else {
|
||||
node script/yarn.js install --frozen-lockfile
|
||||
init:
|
||||
- git config --global core.autocrlf input
|
||||
|
||||
if ($(node script/doc-only-change.js --prNumber=$env:APPVEYOR_PULL_REQUEST_NUMBER --prBranch=$env:APPVEYOR_REPO_BRANCH;$LASTEXITCODE -eq 0)) {
|
||||
Write-warning "Skipping build for doc only change"; Exit-AppveyorBuild
|
||||
}
|
||||
}
|
||||
- echo "Building $env:GN_CONFIG build"
|
||||
- git config --global core.longpaths true
|
||||
- cd ..
|
||||
- mkdir src
|
||||
- ps: Move-Item $env:APPVEYOR_BUILD_FOLDER -Destination src\electron
|
||||
- ps: $env:CHROMIUM_BUILDTOOLS_PATH="$pwd\src\buildtools"
|
||||
- ps: $env:SCCACHE_PATH="$pwd\src\electron\external_binaries\sccache.exe"
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -eq 'release') {
|
||||
$env:GCLIENT_EXTRA_ARGS="$env:GCLIENT_EXTRA_ARGS --custom-var=checkout_boto=True --custom-var=checkout_requests=True"
|
||||
} else {
|
||||
$env:NINJA_STATUS="[%r processes, %f/%t @ %o/s : %es] "
|
||||
}
|
||||
- >-
|
||||
gclient config
|
||||
--name "src\electron"
|
||||
--unmanaged
|
||||
%GCLIENT_EXTRA_ARGS%
|
||||
"https://github.com/electron/electron"
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -eq 'release') {
|
||||
gclient sync --with_branch_heads --with_tags --reset
|
||||
} else {
|
||||
cd src\electron
|
||||
node script\generate-deps-hash.js
|
||||
$depshash = Get-Content .\.depshash -Raw
|
||||
$zipfile = "Z:\$depshash.7z"
|
||||
cd ..\..
|
||||
if (Test-Path -Path $zipfile) {
|
||||
# file exists, unzip and then gclient sync
|
||||
7z x -y $zipfile -mmt=30 -aoa
|
||||
# update external binaries
|
||||
python src/electron/script/update-external-binaries.py
|
||||
} else {
|
||||
# file does not exist, gclient sync, then zip
|
||||
gclient sync --with_branch_heads --with_tags --reset
|
||||
if ($env:TARGET_ARCH -ne 'ia32') {
|
||||
# archive current source for future use
|
||||
# only run on x64/woa to avoid contention saving
|
||||
if ($(7z a $zipfile src -xr!android_webview -xr!electron -xr'!*\.git' -xr!third_party\WebKit\LayoutTests! -xr!third_party\blink\web_tests -xr!third_party\blink\perf_tests -slp -t7z -mmt=30;$LASTEXITCODE -ne 0)) {
|
||||
Write-warning "Could not save source to shared drive; continuing anyway"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
- cd src
|
||||
- ps: $env:BUILD_CONFIG_PATH="//electron/build/args/%GN_CONFIG%.gn"
|
||||
- gn gen out/Default "--args=import(\"%BUILD_CONFIG_PATH%\") %GN_EXTRA_ARGS% cc_wrapper=\"%SCCACHE_PATH%\""
|
||||
- gn check out/Default //electron:electron_lib
|
||||
- gn check out/Default //electron:electron_app
|
||||
- gn check out/Default //electron:manifests
|
||||
- gn check out/Default //electron/shell/common/api:mojo
|
||||
- ninja -C out/Default electron:electron_app
|
||||
- if "%GN_CONFIG%"=="testing" ( python C:\Users\electron\depot_tools\post_build_ninja_summary.py -C out\Default )
|
||||
- gn gen out/ffmpeg "--args=import(\"//electron/build/args/ffmpeg.gn\") %GN_EXTRA_ARGS%"
|
||||
- ninja -C out/ffmpeg electron:electron_ffmpeg_zip
|
||||
- ninja -C out/Default electron:electron_dist_zip
|
||||
- ninja -C out/Default shell_browser_ui_unittests
|
||||
- ninja -C out/Default electron:electron_mksnapshot_zip
|
||||
- ninja -C out/Default electron:hunspell_dictionaries_zip
|
||||
- ninja -C out/Default electron:electron_chromedriver_zip
|
||||
- ninja -C out/Default third_party/electron_node:headers
|
||||
- cmd /C %SCCACHE_PATH% --show-stats
|
||||
- python electron/build/profile_toolchain.py --output-json=out/Default/windows_toolchain_profile.json
|
||||
- appveyor PushArtifact out/Default/windows_toolchain_profile.json
|
||||
- appveyor PushArtifact out/Default/dist.zip
|
||||
- appveyor PushArtifact out/Default/shell_browser_ui_unittests.exe
|
||||
- appveyor PushArtifact out/Default/chromedriver.zip
|
||||
- appveyor PushArtifact out/ffmpeg/ffmpeg.zip
|
||||
- 7z a node_headers.zip out\Default\gen\node_headers
|
||||
- appveyor PushArtifact node_headers.zip
|
||||
- appveyor PushArtifact out/Default/mksnapshot.zip
|
||||
- appveyor PushArtifact out/Default/hunspell_dictionaries.zip
|
||||
- appveyor PushArtifact out/Default/electron.lib
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -eq 'release') {
|
||||
# Needed for msdia140.dll on 64-bit windows
|
||||
$env:Path += ";$pwd\third_party\llvm-build\Release+Asserts\bin"
|
||||
ninja -C out/Default electron:electron_symbols
|
||||
}
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -eq 'release') {
|
||||
python electron\script\zip-symbols.py
|
||||
appveyor PushArtifact out/Default/symbols.zip
|
||||
} else {
|
||||
# It's useful to have pdb files when debugging testing builds that are
|
||||
# built on CI.
|
||||
7z a pdb.zip out\Default\*.pdb
|
||||
appveyor PushArtifact pdb.zip
|
||||
}
|
||||
- python electron/script/zip_manifests/check-zip-manifest.py out/Default/dist.zip electron/script/zip_manifests/dist_zip.win.%TARGET_ARCH%.manifest
|
||||
test_script:
|
||||
# Workaround for https://github.com/appveyor/ci/issues/2420
|
||||
- set "PATH=%PATH%;C:\Program Files\Git\mingw64\libexec\git-core"
|
||||
- ps: >-
|
||||
if ((-Not (Test-Path Env:\TEST_WOA)) -And (-Not (Test-Path Env:\ELECTRON_RELEASE)) -And ($env:GN_CONFIG -in "testing", "release")) {
|
||||
$env:RUN_TESTS="true"
|
||||
}
|
||||
- ps: >-
|
||||
if ($env:RUN_TESTS -eq 'true') {
|
||||
New-Item .\out\Default\gen\node_headers\Release -Type directory
|
||||
Copy-Item -path .\out\Default\electron.lib -destination .\out\Default\gen\node_headers\Release\node.lib
|
||||
} else {
|
||||
echo "Skipping tests for $env:GN_CONFIG build"
|
||||
}
|
||||
- cd electron
|
||||
- if "%RUN_TESTS%"=="true" ( echo Running test suite & node script/yarn test -- --enable-logging)
|
||||
- cd ..
|
||||
- if "%RUN_TESTS%"=="true" ( echo Verifying non proprietary ffmpeg & python electron\script\verify-ffmpeg.py --build-dir out\Default --source-root %cd% --ffmpeg-path out\ffmpeg )
|
||||
- echo "About to verify mksnapshot"
|
||||
- if "%RUN_TESTS%"=="true" ( echo Verifying mksnapshot & python electron\script\verify-mksnapshot.py --build-dir out\Default --source-root %cd% )
|
||||
- echo "Done verifying mksnapshot"
|
||||
deploy_script:
|
||||
- cd electron
|
||||
- ps: >-
|
||||
if (Test-Path Env:\ELECTRON_RELEASE) {
|
||||
if (Test-Path Env:\UPLOAD_TO_S3) {
|
||||
Write-Output "Uploading Electron release distribution to s3"
|
||||
& python script\release\uploaders\upload.py --upload_to_s3
|
||||
} else {
|
||||
Write-Output "Uploading Electron release distribution to github releases"
|
||||
& python script\release\uploaders\upload.py
|
||||
}
|
||||
} elseif (Test-Path Env:\TEST_WOA) {
|
||||
node script/release/ci-release-build.js --job=electron-woa-testing --ci=VSTS --armTest --appveyorJobId=$env:APPVEYOR_JOB_ID $env:APPVEYOR_REPO_BRANCH
|
||||
}
|
||||
platform:
|
||||
- x86
|
||||
- x64
|
||||
|
||||
install:
|
||||
- cmd: SET PATH=C:\Program Files (x86)\MSBuild\14.0\bin\;%PATH%
|
||||
- cmd: SET PATH=C:\python27;%PATH%
|
||||
- cmd: python script/cibuild
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
# disable build and test pahses
|
||||
build: off
|
||||
test: off
|
||||
|
||||
1
atom/CPPLINT.cfg
Normal file
1
atom/CPPLINT.cfg
Normal file
@@ -0,0 +1 @@
|
||||
filter=+build/include_alpha
|
||||
216
atom/app/atom_content_client.cc
Normal file
216
atom/app/atom_content_client.cc
Normal file
@@ -0,0 +1,216 @@
|
||||
// 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/app/atom_content_client.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/common/atom_version.h"
|
||||
#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 "ppapi/shared_impl/ppapi_permissions.h"
|
||||
#include "third_party/widevine/cdm/stub/widevine_cdm_version.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
#include "url/url_constants.h"
|
||||
|
||||
#if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
|
||||
#include "chrome/common/widevine_cdm_constants.h"
|
||||
#endif
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
content::PepperPluginInfo CreatePepperFlashInfo(const base::FilePath& path,
|
||||
const std::string& version) {
|
||||
content::PepperPluginInfo plugin;
|
||||
|
||||
plugin.is_out_of_process = true;
|
||||
plugin.name = content::kFlashPluginName;
|
||||
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.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())
|
||||
flash_version_numbers[0] = "11";
|
||||
if (flash_version_numbers.size() < 2)
|
||||
flash_version_numbers.push_back("2");
|
||||
if (flash_version_numbers.size() < 3)
|
||||
flash_version_numbers.push_back("999");
|
||||
if (flash_version_numbers.size() < 4)
|
||||
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);
|
||||
plugin.mime_types.push_back(swf_mime_type);
|
||||
content::WebPluginMimeType spl_mime_type(
|
||||
content::kFlashPluginSplMimeType,
|
||||
content::kFlashPluginSplExtension,
|
||||
content::kFlashPluginSplDescription);
|
||||
plugin.mime_types.push_back(spl_mime_type);
|
||||
|
||||
return plugin;
|
||||
}
|
||||
|
||||
#if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
|
||||
content::PepperPluginInfo CreateWidevineCdmInfo(const base::FilePath& path,
|
||||
const std::string& version) {
|
||||
content::PepperPluginInfo widevine_cdm;
|
||||
widevine_cdm.is_out_of_process = true;
|
||||
widevine_cdm.path = path;
|
||||
widevine_cdm.name = kWidevineCdmDisplayName;
|
||||
widevine_cdm.description = kWidevineCdmDescription +
|
||||
std::string(" (version: ") +
|
||||
version + ")";
|
||||
widevine_cdm.version = version;
|
||||
content::WebPluginMimeType widevine_cdm_mime_type(
|
||||
kWidevineCdmPluginMimeType,
|
||||
kWidevineCdmPluginExtension,
|
||||
kWidevineCdmPluginMimeTypeDescription);
|
||||
|
||||
// Add the supported codecs as if they came from the component manifest.
|
||||
std::vector<std::string> codecs;
|
||||
codecs.push_back(kCdmSupportedCodecVp8);
|
||||
codecs.push_back(kCdmSupportedCodecVp9);
|
||||
#if defined(USE_PROPRIETARY_CODECS)
|
||||
codecs.push_back(kCdmSupportedCodecAvc1);
|
||||
#endif // defined(USE_PROPRIETARY_CODECS)
|
||||
std::string codec_string = base::JoinString(
|
||||
codecs, std::string(1, kCdmSupportedCodecsValueDelimiter));
|
||||
widevine_cdm_mime_type.additional_param_names.push_back(
|
||||
base::ASCIIToUTF16(kCdmSupportedCodecsParamName));
|
||||
widevine_cdm_mime_type.additional_param_values.push_back(
|
||||
base::ASCIIToUTF16(codec_string));
|
||||
|
||||
widevine_cdm.mime_types.push_back(widevine_cdm_mime_type);
|
||||
widevine_cdm.permissions = kWidevineCdmPluginPermissions;
|
||||
|
||||
return widevine_cdm;
|
||||
}
|
||||
#endif
|
||||
|
||||
void ConvertStringWithSeparatorToVector(std::vector<std::string>* vec,
|
||||
const char* separator,
|
||||
const char* cmd_switch) {
|
||||
auto command_line = base::CommandLine::ForCurrentProcess();
|
||||
auto 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
|
||||
|
||||
void AddPepperFlashFromCommandLine(
|
||||
std::vector<content::PepperPluginInfo>* plugins) {
|
||||
auto command_line = base::CommandLine::ForCurrentProcess();
|
||||
base::FilePath flash_path = command_line->GetSwitchValuePath(
|
||||
switches::kPpapiFlashPath);
|
||||
if (flash_path.empty())
|
||||
return;
|
||||
|
||||
auto flash_version = command_line->GetSwitchValueASCII(
|
||||
switches::kPpapiFlashVersion);
|
||||
|
||||
plugins->push_back(CreatePepperFlashInfo(flash_path, flash_version));
|
||||
}
|
||||
|
||||
#if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
|
||||
void AddWidevineCdmFromCommandLine(
|
||||
std::vector<content::PepperPluginInfo>* plugins) {
|
||||
auto command_line = base::CommandLine::ForCurrentProcess();
|
||||
base::FilePath widevine_cdm_path = command_line->GetSwitchValuePath(
|
||||
switches::kWidevineCdmPath);
|
||||
if (widevine_cdm_path.empty())
|
||||
return;
|
||||
|
||||
if (!base::PathExists(widevine_cdm_path))
|
||||
return;
|
||||
|
||||
auto widevine_cdm_version = command_line->GetSwitchValueASCII(
|
||||
switches::kWidevineCdmVersion);
|
||||
if (widevine_cdm_version.empty())
|
||||
return;
|
||||
|
||||
plugins->push_back(CreateWidevineCdmInfo(widevine_cdm_path,
|
||||
widevine_cdm_version));
|
||||
}
|
||||
#endif
|
||||
|
||||
AtomContentClient::AtomContentClient() {
|
||||
}
|
||||
|
||||
AtomContentClient::~AtomContentClient() {
|
||||
}
|
||||
|
||||
std::string AtomContentClient::GetProduct() const {
|
||||
return "Chrome/" CHROME_VERSION_STRING;
|
||||
}
|
||||
|
||||
std::string AtomContentClient::GetUserAgent() const {
|
||||
return content::BuildUserAgentFromProduct(
|
||||
"Chrome/" CHROME_VERSION_STRING " "
|
||||
ATOM_PRODUCT_NAME "/" ATOM_VERSION_STRING);
|
||||
}
|
||||
|
||||
base::string16 AtomContentClient::GetLocalizedString(int message_id) const {
|
||||
return l10n_util::GetStringUTF16(message_id);
|
||||
}
|
||||
|
||||
void AtomContentClient::AddAdditionalSchemes(
|
||||
std::vector<url::SchemeWithType>* standard_schemes,
|
||||
std::vector<url::SchemeWithType>* referrer_schemes,
|
||||
std::vector<std::string>* savable_schemes) {
|
||||
standard_schemes->push_back({"chrome-extension", url::SCHEME_WITHOUT_PORT});
|
||||
}
|
||||
|
||||
void AtomContentClient::AddPepperPlugins(
|
||||
std::vector<content::PepperPluginInfo>* plugins) {
|
||||
AddPepperFlashFromCommandLine(plugins);
|
||||
#if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
|
||||
AddWidevineCdmFromCommandLine(plugins);
|
||||
#endif
|
||||
}
|
||||
|
||||
void AtomContentClient::AddServiceWorkerSchemes(
|
||||
std::set<std::string>* service_worker_schemes) {
|
||||
std::vector<std::string> schemes;
|
||||
ConvertStringWithSeparatorToVector(&schemes, ",",
|
||||
switches::kRegisterServiceWorkerSchemes);
|
||||
for (const std::string& scheme : schemes)
|
||||
service_worker_schemes->insert(scheme);
|
||||
|
||||
service_worker_schemes->insert(url::kFileScheme);
|
||||
}
|
||||
|
||||
void AtomContentClient::AddSecureSchemesAndOrigins(
|
||||
std::set<std::string>* secure_schemes,
|
||||
std::set<GURL>* secure_origins) {
|
||||
std::vector<std::string> schemes;
|
||||
ConvertStringWithSeparatorToVector(&schemes, ",", switches::kSecureSchemes);
|
||||
for (const std::string& scheme : schemes)
|
||||
secure_schemes->insert(scheme);
|
||||
}
|
||||
|
||||
|
||||
} // namespace atom
|
||||
44
atom/app/atom_content_client.h
Normal file
44
atom/app/atom_content_client.h
Normal file
@@ -0,0 +1,44 @@
|
||||
// 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_APP_ATOM_CONTENT_CLIENT_H_
|
||||
#define ATOM_APP_ATOM_CONTENT_CLIENT_H_
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "brightray/common/content_client.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomContentClient : public brightray::ContentClient {
|
||||
public:
|
||||
AtomContentClient();
|
||||
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(
|
||||
std::vector<url::SchemeWithType>* standard_schemes,
|
||||
std::vector<url::SchemeWithType>* referrer_schemes,
|
||||
std::vector<std::string>* savable_schemes) override;
|
||||
void AddPepperPlugins(
|
||||
std::vector<content::PepperPluginInfo>* plugins) override;
|
||||
void AddServiceWorkerSchemes(
|
||||
std::set<std::string>* service_worker_schemes) override;
|
||||
void AddSecureSchemesAndOrigins(
|
||||
std::set<std::string>* secure_schemes,
|
||||
std::set<GURL>* secure_origins) override;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomContentClient);
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_APP_ATOM_CONTENT_CLIENT_H_
|
||||
20
atom/app/atom_library_main.h
Normal file
20
atom/app/atom_library_main.h
Normal file
@@ -0,0 +1,20 @@
|
||||
// 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_APP_ATOM_LIBRARY_MAIN_H_
|
||||
#define ATOM_APP_ATOM_LIBRARY_MAIN_H_
|
||||
|
||||
#include "build/build_config.h"
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
extern "C" {
|
||||
__attribute__((visibility("default")))
|
||||
int AtomMain(int argc, const char* argv[]);
|
||||
|
||||
__attribute__((visibility("default")))
|
||||
int AtomInitializeICUandStartNode(int argc, char *argv[]);
|
||||
}
|
||||
#endif // OS_MACOSX
|
||||
|
||||
#endif // ATOM_APP_ATOM_LIBRARY_MAIN_H_
|
||||
38
atom/app/atom_library_main.mm
Normal file
38
atom/app/atom_library_main.mm
Normal file
@@ -0,0 +1,38 @@
|
||||
// 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/app/atom_library_main.h"
|
||||
|
||||
#include "atom/app/atom_main_delegate.h"
|
||||
#include "atom/app/node_main.h"
|
||||
#include "atom/common/atom_command_line.h"
|
||||
#include "base/at_exit.h"
|
||||
#include "base/i18n/icu_util.h"
|
||||
#include "base/mac/bundle_locations.h"
|
||||
#include "base/mac/scoped_nsautorelease_pool.h"
|
||||
#include "brightray/common/mac/main_application_bundle.h"
|
||||
#include "content/public/app/content_main.h"
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
int AtomMain(int argc, const char* argv[]) {
|
||||
atom::AtomMainDelegate delegate;
|
||||
content::ContentMainParams params(&delegate);
|
||||
params.argc = argc;
|
||||
params.argv = argv;
|
||||
atom::AtomCommandLine::Init(argc, argv);
|
||||
return content::ContentMain(params);
|
||||
}
|
||||
|
||||
int AtomInitializeICUandStartNode(int argc, char *argv[]) {
|
||||
base::AtExitManager atexit_manager;
|
||||
base::mac::ScopedNSAutoreleasePool pool;
|
||||
base::mac::SetOverrideFrameworkBundlePath(
|
||||
brightray::MainApplicationBundlePath()
|
||||
.Append("Contents")
|
||||
.Append("Frameworks")
|
||||
.Append(ATOM_PRODUCT_NAME " Framework.framework"));
|
||||
base::i18n::InitializeICU();
|
||||
return atom::NodeMain(argc, argv);
|
||||
}
|
||||
#endif // OS_MACOSX
|
||||
145
atom/app/atom_main.cc
Normal file
145
atom/app/atom_main.cc
Normal file
@@ -0,0 +1,145 @@
|
||||
// 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/app/atom_main.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include <windows.h> // windows.h must be included first
|
||||
|
||||
#include <shellapi.h>
|
||||
#include <shellscalingapi.h>
|
||||
#include <tchar.h>
|
||||
|
||||
#include "atom/app/atom_main_delegate.h"
|
||||
#include "atom/common/crash_reporter/win/crash_service_main.h"
|
||||
#include "base/environment.h"
|
||||
#include "base/process/launch.h"
|
||||
#include "base/win/windows_version.h"
|
||||
#include "content/public/app/sandbox_helper_win.h"
|
||||
#include "sandbox/win/src/sandbox_types.h"
|
||||
#elif defined(OS_LINUX) // defined(OS_WIN)
|
||||
#include "atom/app/atom_main_delegate.h" // NOLINT
|
||||
#include "content/public/app/content_main.h"
|
||||
#else // defined(OS_LINUX)
|
||||
#include "atom/app/atom_library_main.h"
|
||||
#endif // defined(OS_MACOSX)
|
||||
|
||||
#include "atom/app/node_main.h"
|
||||
#include "atom/common/atom_command_line.h"
|
||||
#include "base/at_exit.h"
|
||||
#include "base/i18n/icu_util.h"
|
||||
|
||||
namespace {
|
||||
|
||||
const char* kRunAsNode = "ELECTRON_RUN_AS_NODE";
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#if defined(OS_WIN)
|
||||
int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
|
||||
int argc = 0;
|
||||
wchar_t** wargv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
|
||||
|
||||
bool run_as_node = IsEnvSet(kRunAsNode);
|
||||
|
||||
// Make sure the output is printed to console.
|
||||
if (run_as_node || !IsEnvSet("ELECTRON_NO_ATTACH_CONSOLE"))
|
||||
base::RouteStdioToConsole(false);
|
||||
|
||||
// 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 (run_as_node) {
|
||||
// Now that argv conversion is done, we can finally start.
|
||||
base::AtExitManager atexit_manager;
|
||||
base::i18n::InitializeICU();
|
||||
return atom::NodeMain(argc, argv);
|
||||
} else if (IsEnvSet("ELECTRON_INTERNAL_CRASH_SERVICE")) {
|
||||
return crash_service::Main(cmd);
|
||||
}
|
||||
|
||||
sandbox::SandboxInterfaceInfo sandbox_info = {0};
|
||||
content::InitializeSandboxInfo(&sandbox_info);
|
||||
atom::AtomMainDelegate delegate;
|
||||
|
||||
content::ContentMainParams params(&delegate);
|
||||
params.instance = instance;
|
||||
params.sandbox_info = &sandbox_info;
|
||||
atom::AtomCommandLine::Init(argc, argv);
|
||||
atom::AtomCommandLine::InitW(argc, wargv);
|
||||
return content::ContentMain(params);
|
||||
}
|
||||
|
||||
#elif defined(OS_LINUX) // defined(OS_WIN)
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
if (IsEnvSet(kRunAsNode)) {
|
||||
base::i18n::InitializeICU();
|
||||
base::AtExitManager atexit_manager;
|
||||
return atom::NodeMain(argc, const_cast<char**>(argv));
|
||||
}
|
||||
|
||||
atom::AtomMainDelegate delegate;
|
||||
content::ContentMainParams params(&delegate);
|
||||
params.argc = argc;
|
||||
params.argv = argv;
|
||||
atom::AtomCommandLine::Init(argc, argv);
|
||||
return content::ContentMain(params);
|
||||
}
|
||||
|
||||
#else // defined(OS_LINUX)
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
if (IsEnvSet(kRunAsNode)) {
|
||||
return AtomInitializeICUandStartNode(argc, const_cast<char**>(argv));
|
||||
}
|
||||
|
||||
return AtomMain(argc, argv);
|
||||
}
|
||||
|
||||
#endif // defined(OS_MACOSX)
|
||||
10
atom/app/atom_main.h
Normal file
10
atom/app/atom_main.h
Normal file
@@ -0,0 +1,10 @@
|
||||
// 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_APP_ATOM_MAIN_H_
|
||||
#define ATOM_APP_ATOM_MAIN_H_
|
||||
|
||||
#include "content/public/app/content_main.h"
|
||||
|
||||
#endif // ATOM_APP_ATOM_MAIN_H_
|
||||
191
atom/app/atom_main_delegate.cc
Normal file
191
atom/app/atom_main_delegate.cc
Normal file
@@ -0,0 +1,191 @@
|
||||
// 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/app/atom_main_delegate.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#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 "ui/base/l10n/l10n_util.h"
|
||||
#include "ui/base/resource/resource_bundle.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
const char* kRelauncherProcess = "relauncher";
|
||||
|
||||
bool IsBrowserProcess(base::CommandLine* cmd) {
|
||||
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() {
|
||||
}
|
||||
|
||||
bool AtomMainDelegate::BasicStartupComplete(int* exit_code) {
|
||||
auto command_line = base::CommandLine::ForCurrentProcess();
|
||||
|
||||
logging::LoggingSettings settings;
|
||||
#if defined(OS_WIN)
|
||||
// On Windows the terminal returns immediately, so we add a new line to
|
||||
// prevent output in the same line as the prompt.
|
||||
if (IsBrowserProcess(command_line))
|
||||
std::wcout << std::endl;
|
||||
#if defined(DEBUG)
|
||||
// Print logging to debug.log on Windows
|
||||
settings.logging_dest = logging::LOG_TO_ALL;
|
||||
settings.log_file = L"debug.log";
|
||||
settings.lock_log = logging::LOCK_LOG_FILE;
|
||||
settings.delete_old = logging::DELETE_OLD_LOG_FILE;
|
||||
#else
|
||||
settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
|
||||
#endif // defined(DEBUG)
|
||||
#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.
|
||||
std::unique_ptr<base::Environment> env(base::Environment::Create());
|
||||
if (!command_line->HasSwitch(::switches::kEnableLogging) &&
|
||||
!env->HasVar("ELECTRON_ENABLE_LOGGING")) {
|
||||
settings.logging_dest = logging::LOG_NONE;
|
||||
logging::SetMinLogLevel(logging::LOG_NUM_SEVERITIES);
|
||||
}
|
||||
|
||||
logging::InitLogging(settings);
|
||||
|
||||
// Logging with pid and timestamp.
|
||||
logging::SetLogItems(true, false, true, false);
|
||||
|
||||
// Enable convient stack printing.
|
||||
bool enable_stack_dumping = env->HasVar("ELECTRON_ENABLE_STACK_DUMPING");
|
||||
#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);
|
||||
#endif
|
||||
|
||||
return brightray::MainDelegate::BasicStartupComplete(exit_code);
|
||||
}
|
||||
|
||||
void AtomMainDelegate::PreSandboxStartup() {
|
||||
brightray::MainDelegate::PreSandboxStartup();
|
||||
|
||||
// Set google API key.
|
||||
std::unique_ptr<base::Environment> env(base::Environment::Create());
|
||||
if (!env->HasVar("GOOGLE_API_KEY"))
|
||||
env->SetVar("GOOGLE_API_KEY", GOOGLEAPIS_API_KEY);
|
||||
|
||||
auto command_line = base::CommandLine::ForCurrentProcess();
|
||||
std::string process_type = command_line->GetSwitchValueASCII(
|
||||
::switches::kProcessType);
|
||||
|
||||
// Only append arguments for browser process.
|
||||
if (!IsBrowserProcess(command_line))
|
||||
return;
|
||||
|
||||
if (command_line->HasSwitch(switches::kEnableSandbox)) {
|
||||
// Disable setuid sandbox since it is not longer required on linux(namespace
|
||||
// sandbox is available on most distros).
|
||||
command_line->AppendSwitch(::switches::kDisableSetuidSandbox);
|
||||
} else {
|
||||
// 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);
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
// Enable AVFoundation.
|
||||
command_line->AppendSwitch("enable-avfoundation");
|
||||
#endif
|
||||
}
|
||||
|
||||
content::ContentBrowserClient* AtomMainDelegate::CreateContentBrowserClient() {
|
||||
browser_client_.reset(new AtomBrowserClient);
|
||||
return browser_client_.get();
|
||||
}
|
||||
|
||||
content::ContentRendererClient*
|
||||
AtomMainDelegate::CreateContentRendererClient() {
|
||||
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
|
||||
switches::kEnableSandbox)) {
|
||||
renderer_client_.reset(new AtomSandboxedRendererClient);
|
||||
} else {
|
||||
renderer_client_.reset(new AtomRendererClient);
|
||||
}
|
||||
|
||||
return renderer_client_.get();
|
||||
}
|
||||
|
||||
content::ContentUtilityClient* AtomMainDelegate::CreateContentUtilityClient() {
|
||||
utility_client_.reset(new AtomContentUtilityClient);
|
||||
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;
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
#endif
|
||||
|
||||
std::unique_ptr<brightray::ContentClient>
|
||||
AtomMainDelegate::CreateContentClient() {
|
||||
return std::unique_ptr<brightray::ContentClient>(new AtomContentClient);
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
57
atom/app/atom_main_delegate.h
Normal file
57
atom/app/atom_main_delegate.h
Normal file
@@ -0,0 +1,57 @@
|
||||
// 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_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"
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomMainDelegate : public brightray::MainDelegate {
|
||||
public:
|
||||
AtomMainDelegate();
|
||||
~AtomMainDelegate();
|
||||
|
||||
protected:
|
||||
// content::ContentMainDelegate:
|
||||
bool BasicStartupComplete(int* exit_code) override;
|
||||
void PreSandboxStartup() override;
|
||||
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;
|
||||
#if defined(OS_MACOSX)
|
||||
void OverrideChildProcessPath() override;
|
||||
void OverrideFrameworkBundlePath() override;
|
||||
#endif
|
||||
|
||||
private:
|
||||
#if defined(OS_MACOSX)
|
||||
void SetUpBundleOverrides();
|
||||
#endif
|
||||
|
||||
brightray::ContentClient content_client_;
|
||||
std::unique_ptr<content::ContentBrowserClient> browser_client_;
|
||||
std::unique_ptr<content::ContentRendererClient> renderer_client_;
|
||||
std::unique_ptr<content::ContentUtilityClient> utility_client_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomMainDelegate);
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_APP_ATOM_MAIN_DELEGATE_H_
|
||||
65
atom/app/atom_main_delegate_mac.mm
Normal file
65
atom/app/atom_main_delegate_mac.mm
Normal file
@@ -0,0 +1,65 @@
|
||||
// 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/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/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"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
base::FilePath GetFrameworksPath() {
|
||||
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");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void AtomMainDelegate::OverrideFrameworkBundlePath() {
|
||||
base::mac::SetOverrideFrameworkBundlePath(
|
||||
GetFrameworksPath().Append(ATOM_PRODUCT_NAME " Framework.framework"));
|
||||
}
|
||||
|
||||
void AtomMainDelegate::OverrideChildProcessPath() {
|
||||
base::FilePath frameworks_path = GetFrameworksPath();
|
||||
base::FilePath helper_path = GetHelperAppPath(frameworks_path,
|
||||
ATOM_PRODUCT_NAME);
|
||||
if (!base::PathExists(helper_path))
|
||||
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
|
||||
92
atom/app/node_main.cc
Normal file
92
atom/app/node_main.cc
Normal file
@@ -0,0 +1,92 @@
|
||||
// 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/app/node_main.h"
|
||||
|
||||
#include "atom/app/uv_task_runner.h"
|
||||
#include "atom/browser/javascript_environment.h"
|
||||
#include "atom/browser/node_debugger.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/feature_list.h"
|
||||
#include "base/threading/thread_task_runner_handle.h"
|
||||
#include "gin/array_buffer.h"
|
||||
#include "gin/public/isolate_holder.h"
|
||||
#include "gin/v8_initializer.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include "atom/common/api/atom_bindings.h"
|
||||
#include "atom/common/native_mate_converters/string16_converter.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#endif
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
int NodeMain(int argc, char *argv[]) {
|
||||
base::CommandLine::Init(argc, argv);
|
||||
|
||||
int exit_code = 1;
|
||||
{
|
||||
// Feed gin::PerIsolateData with a task runner.
|
||||
argv = uv_setup_args(argc, argv);
|
||||
uv_loop_t* loop = uv_default_loop();
|
||||
scoped_refptr<UvTaskRunner> uv_task_runner(new UvTaskRunner(loop));
|
||||
base::ThreadTaskRunnerHandle handle(uv_task_runner);
|
||||
|
||||
// Initialize feature list.
|
||||
std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
|
||||
feature_list->InitializeFromCommandLine("", "");
|
||||
base::FeatureList::SetInstance(std::move(feature_list));
|
||||
|
||||
gin::V8Initializer::LoadV8Snapshot();
|
||||
gin::V8Initializer::LoadV8Natives();
|
||||
JavascriptEnvironment gin_env;
|
||||
|
||||
int exec_argc;
|
||||
const char** exec_argv;
|
||||
node::Init(&argc, const_cast<const char**>(argv), &exec_argc, &exec_argv);
|
||||
|
||||
node::Environment* env = node::CreateEnvironment(
|
||||
gin_env.isolate(), loop, gin_env.context(), argc, argv,
|
||||
exec_argc, exec_argv);
|
||||
|
||||
// Start our custom debugger implementation.
|
||||
NodeDebugger node_debugger(gin_env.isolate());
|
||||
if (node_debugger.IsRunning())
|
||||
env->AssignToContext(v8::Debug::GetDebugContext());
|
||||
|
||||
#if defined(OS_WIN)
|
||||
mate::Dictionary process(gin_env.isolate(), env->process_object());
|
||||
process.SetMethod("log", &AtomBindings::Log);
|
||||
#endif
|
||||
|
||||
node::LoadEnvironment(env);
|
||||
|
||||
bool more;
|
||||
do {
|
||||
more = uv_run(env->event_loop(), UV_RUN_ONCE);
|
||||
if (more == false) {
|
||||
node::EmitBeforeExit(env);
|
||||
|
||||
// Emit `beforeExit` if the loop became alive either after emitting
|
||||
// event, or after running some callbacks.
|
||||
more = uv_loop_alive(env->event_loop());
|
||||
if (uv_run(env->event_loop(), UV_RUN_NOWAIT) != 0)
|
||||
more = true;
|
||||
}
|
||||
} while (more == true);
|
||||
|
||||
exit_code = node::EmitExit(env);
|
||||
node::RunAtExit(env);
|
||||
|
||||
node::FreeEnvironment(env);
|
||||
}
|
||||
|
||||
v8::V8::Dispose();
|
||||
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
14
atom/app/node_main.h
Normal file
14
atom/app/node_main.h
Normal file
@@ -0,0 +1,14 @@
|
||||
// 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_APP_NODE_MAIN_H_
|
||||
#define ATOM_APP_NODE_MAIN_H_
|
||||
|
||||
namespace atom {
|
||||
|
||||
int NodeMain(int argc, char *argv[]);
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_APP_NODE_MAIN_H_
|
||||
60
atom/app/uv_task_runner.cc
Normal file
60
atom/app/uv_task_runner.cc
Normal file
@@ -0,0 +1,60 @@
|
||||
// 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/app/uv_task_runner.h"
|
||||
|
||||
#include "base/stl_util.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
UvTaskRunner::UvTaskRunner(uv_loop_t* loop) : loop_(loop) {
|
||||
}
|
||||
|
||||
UvTaskRunner::~UvTaskRunner() {
|
||||
for (auto& iter : tasks_) {
|
||||
uv_unref(reinterpret_cast<uv_handle_t*>(iter.first));
|
||||
delete iter.first;
|
||||
}
|
||||
}
|
||||
|
||||
bool UvTaskRunner::PostDelayedTask(const tracked_objects::Location& from_here,
|
||||
const base::Closure& task,
|
||||
base::TimeDelta delay) {
|
||||
auto* timer = new uv_timer_t;
|
||||
timer->data = this;
|
||||
uv_timer_init(loop_, timer);
|
||||
uv_timer_start(timer, UvTaskRunner::OnTimeout, delay.InMilliseconds(), 0);
|
||||
tasks_[timer] = task;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UvTaskRunner::RunsTasksOnCurrentThread() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UvTaskRunner::PostNonNestableDelayedTask(
|
||||
const tracked_objects::Location& from_here,
|
||||
const base::Closure& task,
|
||||
base::TimeDelta delay) {
|
||||
return PostDelayedTask(from_here, task, delay);
|
||||
}
|
||||
|
||||
// static
|
||||
void UvTaskRunner::OnTimeout(uv_timer_t* timer) {
|
||||
UvTaskRunner* self = static_cast<UvTaskRunner*>(timer->data);
|
||||
if (!ContainsKey(self->tasks_, timer))
|
||||
return;
|
||||
|
||||
self->tasks_[timer].Run();
|
||||
self->tasks_.erase(timer);
|
||||
uv_timer_stop(timer);
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(timer), UvTaskRunner::OnClose);
|
||||
}
|
||||
|
||||
// static
|
||||
void UvTaskRunner::OnClose(uv_handle_t* handle) {
|
||||
delete reinterpret_cast<uv_timer_t*>(handle);
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
45
atom/app/uv_task_runner.h
Normal file
45
atom/app/uv_task_runner.h
Normal file
@@ -0,0 +1,45 @@
|
||||
// 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_APP_UV_TASK_RUNNER_H_
|
||||
#define ATOM_APP_UV_TASK_RUNNER_H_
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "base/single_thread_task_runner.h"
|
||||
#include "vendor/node/deps/uv/include/uv.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
// TaskRunner implementation that posts tasks into libuv's default loop.
|
||||
class UvTaskRunner : public base::SingleThreadTaskRunner {
|
||||
public:
|
||||
explicit UvTaskRunner(uv_loop_t* loop);
|
||||
~UvTaskRunner() override;
|
||||
|
||||
// base::SingleThreadTaskRunner:
|
||||
bool PostDelayedTask(const tracked_objects::Location& from_here,
|
||||
const base::Closure& 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:
|
||||
static void OnTimeout(uv_timer_t* timer);
|
||||
static void OnClose(uv_handle_t* handle);
|
||||
|
||||
uv_loop_t* loop_;
|
||||
|
||||
std::map<uv_timer_t*, base::Closure> tasks_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(UvTaskRunner);
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_APP_UV_TASK_RUNNER_H_
|
||||
970
atom/browser/api/atom_api_app.cc
Normal file
970
atom/browser/api/atom_api_app.cc
Normal file
@@ -0,0 +1,970 @@
|
||||
// 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"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/browser/api/atom_api_menu.h"
|
||||
#include "atom/browser/api/atom_api_session.h"
|
||||
#include "atom/browser/api/atom_api_web_contents.h"
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/atom_browser_main_parts.h"
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/browser/login_handler.h"
|
||||
#include "atom/browser/relauncher.h"
|
||||
#include "atom/common/atom_command_line.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/gurl_converter.h"
|
||||
#include "atom/common/native_mate_converters/image_converter.h"
|
||||
#include "atom/common/native_mate_converters/net_converter.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "atom/common/options_switches.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/environment.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/files/file_util.h"
|
||||
#include "base/path_service.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "brightray/browser/brightray_paths.h"
|
||||
#include "chrome/common/chrome_paths.h"
|
||||
#include "content/public/browser/browser_accessibility_state.h"
|
||||
#include "content/public/browser/client_certificate_delegate.h"
|
||||
#include "content/public/browser/gpu_data_manager.h"
|
||||
#include "content/public/browser/render_frame_host.h"
|
||||
#include "content/public/common/content_switches.h"
|
||||
#include "media/audio/audio_manager.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/object_template_builder.h"
|
||||
#include "net/ssl/ssl_cert_request_info.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
#include "ui/gfx/image/image.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include "atom/browser/ui/win/jump_list.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#endif
|
||||
|
||||
using atom::Browser;
|
||||
|
||||
namespace mate {
|
||||
|
||||
#if defined(OS_WIN)
|
||||
template<>
|
||||
struct Converter<Browser::UserTask> {
|
||||
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
|
||||
Browser::UserTask* out) {
|
||||
mate::Dictionary dict;
|
||||
if (!ConvertFromV8(isolate, val, &dict))
|
||||
return false;
|
||||
if (!dict.Get("program", &(out->program)) ||
|
||||
!dict.Get("title", &(out->title)))
|
||||
return false;
|
||||
if (dict.Get("iconPath", &(out->icon_path)) &&
|
||||
!dict.Get("iconIndex", &(out->icon_index)))
|
||||
return false;
|
||||
dict.Get("arguments", &(out->arguments));
|
||||
dict.Get("description", &(out->description));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
using atom::JumpListItem;
|
||||
using atom::JumpListCategory;
|
||||
using atom::JumpListResult;
|
||||
|
||||
template<>
|
||||
struct Converter<JumpListItem::Type> {
|
||||
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
|
||||
JumpListItem::Type* out) {
|
||||
std::string item_type;
|
||||
if (!ConvertFromV8(isolate, val, &item_type))
|
||||
return false;
|
||||
|
||||
if (item_type == "task")
|
||||
*out = JumpListItem::Type::TASK;
|
||||
else if (item_type == "separator")
|
||||
*out = JumpListItem::Type::SEPARATOR;
|
||||
else if (item_type == "file")
|
||||
*out = JumpListItem::Type::FILE;
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
JumpListItem::Type val) {
|
||||
std::string item_type;
|
||||
switch (val) {
|
||||
case JumpListItem::Type::TASK:
|
||||
item_type = "task";
|
||||
break;
|
||||
|
||||
case JumpListItem::Type::SEPARATOR:
|
||||
item_type = "separator";
|
||||
break;
|
||||
|
||||
case JumpListItem::Type::FILE:
|
||||
item_type = "file";
|
||||
break;
|
||||
}
|
||||
return mate::ConvertToV8(isolate, item_type);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Converter<JumpListItem> {
|
||||
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
|
||||
JumpListItem* out) {
|
||||
mate::Dictionary dict;
|
||||
if (!ConvertFromV8(isolate, val, &dict))
|
||||
return false;
|
||||
|
||||
if (!dict.Get("type", &(out->type)))
|
||||
return false;
|
||||
|
||||
switch (out->type) {
|
||||
case JumpListItem::Type::TASK:
|
||||
if (!dict.Get("program", &(out->path)) ||
|
||||
!dict.Get("title", &(out->title)))
|
||||
return false;
|
||||
|
||||
if (dict.Get("iconPath", &(out->icon_path)) &&
|
||||
!dict.Get("iconIndex", &(out->icon_index)))
|
||||
return false;
|
||||
|
||||
dict.Get("args", &(out->arguments));
|
||||
dict.Get("description", &(out->description));
|
||||
return true;
|
||||
|
||||
case JumpListItem::Type::SEPARATOR:
|
||||
return true;
|
||||
|
||||
case JumpListItem::Type::FILE:
|
||||
return dict.Get("path", &(out->path));
|
||||
}
|
||||
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
const JumpListItem& val) {
|
||||
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
|
||||
dict.Set("type", val.type);
|
||||
|
||||
switch (val.type) {
|
||||
case JumpListItem::Type::TASK:
|
||||
dict.Set("program", val.path);
|
||||
dict.Set("args", val.arguments);
|
||||
dict.Set("title", val.title);
|
||||
dict.Set("iconPath", val.icon_path);
|
||||
dict.Set("iconIndex", val.icon_index);
|
||||
dict.Set("description", val.description);
|
||||
break;
|
||||
|
||||
case JumpListItem::Type::SEPARATOR:
|
||||
break;
|
||||
|
||||
case JumpListItem::Type::FILE:
|
||||
dict.Set("path", val.path);
|
||||
break;
|
||||
}
|
||||
return dict.GetHandle();
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Converter<JumpListCategory::Type> {
|
||||
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
|
||||
JumpListCategory::Type* out) {
|
||||
std::string category_type;
|
||||
if (!ConvertFromV8(isolate, val, &category_type))
|
||||
return false;
|
||||
|
||||
if (category_type == "tasks")
|
||||
*out = JumpListCategory::Type::TASKS;
|
||||
else if (category_type == "frequent")
|
||||
*out = JumpListCategory::Type::FREQUENT;
|
||||
else if (category_type == "recent")
|
||||
*out = JumpListCategory::Type::RECENT;
|
||||
else if (category_type == "custom")
|
||||
*out = JumpListCategory::Type::CUSTOM;
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
JumpListCategory::Type val) {
|
||||
std::string category_type;
|
||||
switch (val) {
|
||||
case JumpListCategory::Type::TASKS:
|
||||
category_type = "tasks";
|
||||
break;
|
||||
|
||||
case JumpListCategory::Type::FREQUENT:
|
||||
category_type = "frequent";
|
||||
break;
|
||||
|
||||
case JumpListCategory::Type::RECENT:
|
||||
category_type = "recent";
|
||||
break;
|
||||
|
||||
case JumpListCategory::Type::CUSTOM:
|
||||
category_type = "custom";
|
||||
break;
|
||||
}
|
||||
return mate::ConvertToV8(isolate, category_type);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Converter<JumpListCategory> {
|
||||
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
|
||||
JumpListCategory* out) {
|
||||
mate::Dictionary dict;
|
||||
if (!ConvertFromV8(isolate, val, &dict))
|
||||
return false;
|
||||
|
||||
if (dict.Get("name", &(out->name)) && out->name.empty())
|
||||
return false;
|
||||
|
||||
if (!dict.Get("type", &(out->type))) {
|
||||
if (out->name.empty())
|
||||
out->type = JumpListCategory::Type::TASKS;
|
||||
else
|
||||
out->type = JumpListCategory::Type::CUSTOM;
|
||||
}
|
||||
|
||||
if ((out->type == JumpListCategory::Type::TASKS) ||
|
||||
(out->type == JumpListCategory::Type::CUSTOM)) {
|
||||
if (!dict.Get("items", &(out->items)))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// static
|
||||
template<>
|
||||
struct Converter<JumpListResult> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate, JumpListResult val) {
|
||||
std::string result_code;
|
||||
switch (val) {
|
||||
case JumpListResult::SUCCESS:
|
||||
result_code = "ok";
|
||||
break;
|
||||
|
||||
case JumpListResult::ARGUMENT_ERROR:
|
||||
result_code = "argumentError";
|
||||
break;
|
||||
|
||||
case JumpListResult::GENERIC_ERROR:
|
||||
result_code = "error";
|
||||
break;
|
||||
|
||||
case JumpListResult::CUSTOM_CATEGORY_SEPARATOR_ERROR:
|
||||
result_code = "invalidSeparatorError";
|
||||
break;
|
||||
|
||||
case JumpListResult::MISSING_FILE_TYPE_REGISTRATION_ERROR:
|
||||
result_code = "fileTypeRegistrationError";
|
||||
break;
|
||||
|
||||
case JumpListResult::CUSTOM_CATEGORY_ACCESS_DENIED_ERROR:
|
||||
result_code = "customCategoryAccessDeniedError";
|
||||
break;
|
||||
}
|
||||
return ConvertToV8(isolate, result_code);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
template<>
|
||||
struct Converter<Browser::LoginItemSettings> {
|
||||
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
|
||||
Browser::LoginItemSettings* out) {
|
||||
mate::Dictionary dict;
|
||||
if (!ConvertFromV8(isolate, val, &dict))
|
||||
return false;
|
||||
|
||||
dict.Get("openAtLogin", &(out->open_at_login));
|
||||
dict.Get("openAsHidden", &(out->open_as_hidden));
|
||||
return true;
|
||||
}
|
||||
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
Browser::LoginItemSettings val) {
|
||||
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
|
||||
dict.Set("openAtLogin", val.open_at_login);
|
||||
dict.Set("openAsHidden", val.open_as_hidden);
|
||||
dict.Set("restoreState", val.restore_state);
|
||||
dict.Set("wasOpenedAtLogin", val.opened_at_login);
|
||||
dict.Set("wasOpenedAsHidden", val.opened_as_hidden);
|
||||
return dict.GetHandle();
|
||||
}
|
||||
};
|
||||
} // namespace mate
|
||||
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
namespace {
|
||||
|
||||
// Return the path constant from string.
|
||||
int GetPathConstant(const std::string& name) {
|
||||
if (name == "appData")
|
||||
return brightray::DIR_APP_DATA;
|
||||
else if (name == "userData")
|
||||
return brightray::DIR_USER_DATA;
|
||||
else if (name == "cache")
|
||||
return brightray::DIR_CACHE;
|
||||
else if (name == "userCache")
|
||||
return brightray::DIR_USER_CACHE;
|
||||
else if (name == "home")
|
||||
return base::DIR_HOME;
|
||||
else if (name == "temp")
|
||||
return base::DIR_TEMP;
|
||||
else if (name == "userDesktop" || name == "desktop")
|
||||
return base::DIR_USER_DESKTOP;
|
||||
else if (name == "exe")
|
||||
return base::FILE_EXE;
|
||||
else if (name == "module")
|
||||
return base::FILE_MODULE;
|
||||
else if (name == "documents")
|
||||
return chrome::DIR_USER_DOCUMENTS;
|
||||
else if (name == "downloads")
|
||||
return chrome::DIR_DEFAULT_DOWNLOADS;
|
||||
else if (name == "music")
|
||||
return chrome::DIR_USER_MUSIC;
|
||||
else if (name == "pictures")
|
||||
return chrome::DIR_USER_PICTURES;
|
||||
else if (name == "videos")
|
||||
return chrome::DIR_USER_VIDEOS;
|
||||
else if (name == "pepperFlashSystemPlugin")
|
||||
return chrome::FILE_PEPPER_FLASH_SYSTEM_PLUGIN;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool NotificationCallbackWrapper(
|
||||
const ProcessSingleton::NotificationCallback& callback,
|
||||
const base::CommandLine::StringVector& cmd,
|
||||
const base::FilePath& cwd) {
|
||||
// Make sure the callback is called after app gets ready.
|
||||
if (Browser::Get()->is_ready()) {
|
||||
callback.Run(cmd, cwd);
|
||||
} else {
|
||||
scoped_refptr<base::SingleThreadTaskRunner> task_runner(
|
||||
base::ThreadTaskRunnerHandle::Get());
|
||||
task_runner->PostTask(
|
||||
FROM_HERE, base::Bind(base::IgnoreResult(callback), cmd, cwd));
|
||||
}
|
||||
// ProcessSingleton needs to know whether current process is quiting.
|
||||
return !Browser::Get()->is_shutting_down();
|
||||
}
|
||||
|
||||
void OnClientCertificateSelected(
|
||||
v8::Isolate* isolate,
|
||||
std::shared_ptr<content::ClientCertificateDelegate> delegate,
|
||||
mate::Arguments* args) {
|
||||
if (args->Length() == 2) {
|
||||
delegate->ContinueWithCertificate(nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> val;
|
||||
args->GetNext(&val);
|
||||
if (val->IsNull()) {
|
||||
delegate->ContinueWithCertificate(nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
mate::Dictionary cert_data;
|
||||
if (!mate::ConvertFromV8(isolate, val, &cert_data)) {
|
||||
args->ThrowError("Must pass valid certificate object.");
|
||||
return;
|
||||
}
|
||||
|
||||
std::string data;
|
||||
if (!cert_data.Get("data", &data))
|
||||
return;
|
||||
|
||||
auto certs = net::X509Certificate::CreateCertificateListFromBytes(
|
||||
data.c_str(), data.length(), net::X509Certificate::FORMAT_AUTO);
|
||||
if (certs.size() > 0)
|
||||
delegate->ContinueWithCertificate(certs[0].get());
|
||||
}
|
||||
|
||||
void PassLoginInformation(scoped_refptr<LoginHandler> login_handler,
|
||||
mate::Arguments* args) {
|
||||
base::string16 username, password;
|
||||
if (args->GetNext(&username) && args->GetNext(&password))
|
||||
login_handler->Login(username, password);
|
||||
else
|
||||
login_handler->CancelAuth();
|
||||
}
|
||||
|
||||
#if defined(USE_NSS_CERTS)
|
||||
int ImportIntoCertStore(
|
||||
CertificateManagerModel* model,
|
||||
const base::DictionaryValue& options) {
|
||||
std::string file_data, cert_path;
|
||||
base::string16 password;
|
||||
net::CertificateList imported_certs;
|
||||
int rv = -1;
|
||||
options.GetString("certificate", &cert_path);
|
||||
options.GetString("password", &password);
|
||||
|
||||
if (!cert_path.empty()) {
|
||||
if (base::ReadFileToString(base::FilePath(cert_path), &file_data)) {
|
||||
auto module = model->cert_db()->GetPublicModule();
|
||||
rv = model->ImportFromPKCS12(module,
|
||||
file_data,
|
||||
password,
|
||||
true,
|
||||
&imported_certs);
|
||||
if (imported_certs.size() > 1) {
|
||||
auto it = imported_certs.begin();
|
||||
++it; // skip first which would be the client certificate.
|
||||
for (; it != imported_certs.end(); ++it)
|
||||
rv &= model->SetCertTrust(it->get(),
|
||||
net::CA_CERT,
|
||||
net::NSSCertDatabase::TRUSTED_SSL);
|
||||
}
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
App::App(v8::Isolate* isolate) {
|
||||
static_cast<AtomBrowserClient*>(AtomBrowserClient::Get())->set_delegate(this);
|
||||
Browser::Get()->AddObserver(this);
|
||||
content::GpuDataManager::GetInstance()->AddObserver(this);
|
||||
Init(isolate);
|
||||
}
|
||||
|
||||
App::~App() {
|
||||
static_cast<AtomBrowserClient*>(AtomBrowserClient::Get())->set_delegate(
|
||||
nullptr);
|
||||
Browser::Get()->RemoveObserver(this);
|
||||
content::GpuDataManager::GetInstance()->RemoveObserver(this);
|
||||
}
|
||||
|
||||
void App::OnBeforeQuit(bool* prevent_default) {
|
||||
*prevent_default = Emit("before-quit");
|
||||
}
|
||||
|
||||
void App::OnWillQuit(bool* prevent_default) {
|
||||
*prevent_default = Emit("will-quit");
|
||||
}
|
||||
|
||||
void App::OnWindowAllClosed() {
|
||||
Emit("window-all-closed");
|
||||
}
|
||||
|
||||
void App::OnQuit() {
|
||||
int exitCode = AtomBrowserMainParts::Get()->GetExitCode();
|
||||
Emit("quit", exitCode);
|
||||
|
||||
if (process_singleton_.get()) {
|
||||
process_singleton_->Cleanup();
|
||||
process_singleton_.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void App::OnOpenFile(bool* prevent_default, const std::string& file_path) {
|
||||
*prevent_default = Emit("open-file", file_path);
|
||||
}
|
||||
|
||||
void App::OnOpenURL(const std::string& url) {
|
||||
Emit("open-url", url);
|
||||
}
|
||||
|
||||
void App::OnActivate(bool has_visible_windows) {
|
||||
Emit("activate", has_visible_windows);
|
||||
}
|
||||
|
||||
void App::OnWillFinishLaunching() {
|
||||
Emit("will-finish-launching");
|
||||
}
|
||||
|
||||
void App::OnFinishLaunching(const base::DictionaryValue& launch_info) {
|
||||
#if defined(OS_LINUX)
|
||||
// Set the application name for audio streams shown in external
|
||||
// applications. Only affects pulseaudio currently.
|
||||
media::AudioManager::SetGlobalAppName(Browser::Get()->GetName());
|
||||
#endif
|
||||
Emit("ready", launch_info);
|
||||
}
|
||||
|
||||
void App::OnAccessibilitySupportChanged() {
|
||||
Emit("accessibility-support-changed", IsAccessibilitySupportEnabled());
|
||||
}
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
void App::OnContinueUserActivity(
|
||||
bool* prevent_default,
|
||||
const std::string& type,
|
||||
const base::DictionaryValue& user_info) {
|
||||
*prevent_default = Emit("continue-activity", type, user_info);
|
||||
}
|
||||
#endif
|
||||
|
||||
void App::OnLogin(LoginHandler* login_handler,
|
||||
const base::DictionaryValue& request_details) {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
bool prevent_default = Emit(
|
||||
"login",
|
||||
WebContents::CreateFrom(isolate(), login_handler->GetWebContents()),
|
||||
request_details,
|
||||
login_handler->auth_info(),
|
||||
base::Bind(&PassLoginInformation, make_scoped_refptr(login_handler)));
|
||||
|
||||
// Default behavior is to always cancel the auth.
|
||||
if (!prevent_default)
|
||||
login_handler->CancelAuth();
|
||||
}
|
||||
|
||||
void App::OnCreateWindow(
|
||||
const GURL& target_url,
|
||||
const std::string& frame_name,
|
||||
WindowOpenDisposition disposition,
|
||||
const std::vector<base::string16>& features,
|
||||
const scoped_refptr<content::ResourceRequestBodyImpl>& body,
|
||||
int render_process_id,
|
||||
int render_frame_id) {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
content::RenderFrameHost* rfh =
|
||||
content::RenderFrameHost::FromID(render_process_id, render_frame_id);
|
||||
content::WebContents* web_contents =
|
||||
content::WebContents::FromRenderFrameHost(rfh);
|
||||
if (web_contents) {
|
||||
auto api_web_contents = WebContents::CreateFrom(isolate(), web_contents);
|
||||
api_web_contents->OnCreateWindow(target_url,
|
||||
frame_name,
|
||||
disposition,
|
||||
features,
|
||||
body);
|
||||
}
|
||||
}
|
||||
|
||||
void App::AllowCertificateError(
|
||||
content::WebContents* web_contents,
|
||||
int cert_error,
|
||||
const net::SSLInfo& ssl_info,
|
||||
const GURL& request_url,
|
||||
content::ResourceType resource_type,
|
||||
bool overridable,
|
||||
bool strict_enforcement,
|
||||
bool expired_previous_decision,
|
||||
const base::Callback<void(bool)>& callback,
|
||||
content::CertificateRequestResultType* request) {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
bool prevent_default = Emit("certificate-error",
|
||||
WebContents::CreateFrom(isolate(), web_contents),
|
||||
request_url,
|
||||
net::ErrorToString(cert_error),
|
||||
ssl_info.cert,
|
||||
callback);
|
||||
|
||||
// Deny the certificate by default.
|
||||
if (!prevent_default)
|
||||
*request = content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY;
|
||||
}
|
||||
|
||||
void App::SelectClientCertificate(
|
||||
content::WebContents* web_contents,
|
||||
net::SSLCertRequestInfo* cert_request_info,
|
||||
std::unique_ptr<content::ClientCertificateDelegate> delegate) {
|
||||
std::shared_ptr<content::ClientCertificateDelegate>
|
||||
shared_delegate(delegate.release());
|
||||
bool prevent_default =
|
||||
Emit("select-client-certificate",
|
||||
WebContents::CreateFrom(isolate(), web_contents),
|
||||
cert_request_info->host_and_port.ToString(),
|
||||
cert_request_info->client_certs,
|
||||
base::Bind(&OnClientCertificateSelected,
|
||||
isolate(),
|
||||
shared_delegate));
|
||||
|
||||
// Default to first certificate from the platform store.
|
||||
if (!prevent_default)
|
||||
shared_delegate->ContinueWithCertificate(
|
||||
cert_request_info->client_certs[0].get());
|
||||
}
|
||||
|
||||
void App::OnGpuProcessCrashed(base::TerminationStatus status) {
|
||||
Emit("gpu-process-crashed",
|
||||
status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED);
|
||||
}
|
||||
|
||||
base::FilePath App::GetPath(mate::Arguments* args, const std::string& name) {
|
||||
bool succeed = false;
|
||||
base::FilePath path;
|
||||
int key = GetPathConstant(name);
|
||||
if (key >= 0)
|
||||
succeed = PathService::Get(key, &path);
|
||||
if (!succeed)
|
||||
args->ThrowError("Failed to get '" + name + "' path");
|
||||
return path;
|
||||
}
|
||||
|
||||
void App::SetPath(mate::Arguments* args,
|
||||
const std::string& name,
|
||||
const base::FilePath& path) {
|
||||
if (!path.IsAbsolute()) {
|
||||
args->ThrowError("Path must be absolute");
|
||||
return;
|
||||
}
|
||||
|
||||
bool succeed = false;
|
||||
int key = GetPathConstant(name);
|
||||
if (key >= 0)
|
||||
succeed = PathService::OverrideAndCreateIfNeeded(key, path, true, false);
|
||||
if (!succeed)
|
||||
args->ThrowError("Failed to set path");
|
||||
}
|
||||
|
||||
void App::SetDesktopName(const std::string& desktop_name) {
|
||||
#if defined(OS_LINUX)
|
||||
std::unique_ptr<base::Environment> env(base::Environment::Create());
|
||||
env->SetVar("CHROME_DESKTOP", desktop_name);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string App::GetLocale() {
|
||||
return l10n_util::GetApplicationLocale("");
|
||||
}
|
||||
|
||||
bool App::MakeSingleInstance(
|
||||
const ProcessSingleton::NotificationCallback& callback) {
|
||||
if (process_singleton_.get())
|
||||
return false;
|
||||
|
||||
base::FilePath user_dir;
|
||||
PathService::Get(brightray::DIR_USER_DATA, &user_dir);
|
||||
process_singleton_.reset(new ProcessSingleton(
|
||||
user_dir, base::Bind(NotificationCallbackWrapper, callback)));
|
||||
|
||||
switch (process_singleton_->NotifyOtherProcessOrCreate()) {
|
||||
case ProcessSingleton::NotifyResult::LOCK_ERROR:
|
||||
case ProcessSingleton::NotifyResult::PROFILE_IN_USE:
|
||||
case ProcessSingleton::NotifyResult::PROCESS_NOTIFIED:
|
||||
process_singleton_.reset();
|
||||
return true;
|
||||
case ProcessSingleton::NotifyResult::PROCESS_NONE:
|
||||
default: // Shouldn't be needed, but VS warns if it is not there.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void App::ReleaseSingleInstance() {
|
||||
if (process_singleton_.get()) {
|
||||
process_singleton_->Cleanup();
|
||||
process_singleton_.reset();
|
||||
}
|
||||
}
|
||||
|
||||
bool App::Relaunch(mate::Arguments* js_args) {
|
||||
// Parse parameters.
|
||||
bool override_argv = false;
|
||||
base::FilePath exec_path;
|
||||
relauncher::StringVector args;
|
||||
|
||||
mate::Dictionary options;
|
||||
if (js_args->GetNext(&options)) {
|
||||
if (options.Get("execPath", &exec_path) | options.Get("args", &args))
|
||||
override_argv = true;
|
||||
}
|
||||
|
||||
if (!override_argv) {
|
||||
#if defined(OS_WIN)
|
||||
const relauncher::StringVector& argv = atom::AtomCommandLine::wargv();
|
||||
#else
|
||||
const relauncher::StringVector& argv = atom::AtomCommandLine::argv();
|
||||
#endif
|
||||
return relauncher::RelaunchApp(argv);
|
||||
}
|
||||
|
||||
relauncher::StringVector argv;
|
||||
argv.reserve(1 + args.size());
|
||||
|
||||
if (exec_path.empty()) {
|
||||
base::FilePath current_exe_path;
|
||||
PathService::Get(base::FILE_EXE, ¤t_exe_path);
|
||||
argv.push_back(current_exe_path.value());
|
||||
} else {
|
||||
argv.push_back(exec_path.value());
|
||||
}
|
||||
|
||||
argv.insert(argv.end(), args.begin(), args.end());
|
||||
|
||||
return relauncher::RelaunchApp(argv);
|
||||
}
|
||||
|
||||
void App::DisableHardwareAcceleration(mate::Arguments* args) {
|
||||
if (Browser::Get()->is_ready()) {
|
||||
args->ThrowError("app.disableHardwareAcceleration() can only be called "
|
||||
"before app is ready");
|
||||
return;
|
||||
}
|
||||
content::GpuDataManager::GetInstance()->DisableHardwareAcceleration();
|
||||
}
|
||||
|
||||
bool App::IsAccessibilitySupportEnabled() {
|
||||
auto ax_state = content::BrowserAccessibilityState::GetInstance();
|
||||
return ax_state->IsAccessibleBrowser();
|
||||
}
|
||||
|
||||
#if defined(USE_NSS_CERTS)
|
||||
void App::ImportCertificate(
|
||||
const base::DictionaryValue& options,
|
||||
const net::CompletionCallback& callback) {
|
||||
auto browser_context = AtomBrowserContext::From("", false);
|
||||
if (!certificate_manager_model_) {
|
||||
std::unique_ptr<base::DictionaryValue> copy = options.CreateDeepCopy();
|
||||
CertificateManagerModel::Create(
|
||||
browser_context.get(),
|
||||
base::Bind(&App::OnCertificateManagerModelCreated,
|
||||
base::Unretained(this),
|
||||
base::Passed(©),
|
||||
callback));
|
||||
return;
|
||||
}
|
||||
|
||||
int rv = ImportIntoCertStore(certificate_manager_model_.get(), options);
|
||||
callback.Run(rv);
|
||||
}
|
||||
|
||||
void App::OnCertificateManagerModelCreated(
|
||||
std::unique_ptr<base::DictionaryValue> options,
|
||||
const net::CompletionCallback& callback,
|
||||
std::unique_ptr<CertificateManagerModel> model) {
|
||||
certificate_manager_model_ = std::move(model);
|
||||
int rv = ImportIntoCertStore(certificate_manager_model_.get(),
|
||||
*(options.get()));
|
||||
callback.Run(rv);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(OS_WIN)
|
||||
v8::Local<v8::Value> App::GetJumpListSettings() {
|
||||
JumpList jump_list(Browser::Get()->GetAppUserModelID());
|
||||
|
||||
int min_items = 10;
|
||||
std::vector<JumpListItem> removed_items;
|
||||
if (jump_list.Begin(&min_items, &removed_items)) {
|
||||
// We don't actually want to change anything, so abort the transaction.
|
||||
jump_list.Abort();
|
||||
} else {
|
||||
LOG(ERROR) << "Failed to begin Jump List transaction.";
|
||||
}
|
||||
|
||||
auto dict = mate::Dictionary::CreateEmpty(isolate());
|
||||
dict.Set("minItems", min_items);
|
||||
dict.Set("removedItems", mate::ConvertToV8(isolate(), removed_items));
|
||||
return dict.GetHandle();
|
||||
}
|
||||
|
||||
JumpListResult App::SetJumpList(v8::Local<v8::Value> val,
|
||||
mate::Arguments* args) {
|
||||
std::vector<JumpListCategory> categories;
|
||||
bool delete_jump_list = val->IsNull();
|
||||
if (!delete_jump_list &&
|
||||
!mate::ConvertFromV8(args->isolate(), val, &categories)) {
|
||||
args->ThrowError("Argument must be null or an array of categories");
|
||||
return JumpListResult::ARGUMENT_ERROR;
|
||||
}
|
||||
|
||||
JumpList jump_list(Browser::Get()->GetAppUserModelID());
|
||||
|
||||
if (delete_jump_list) {
|
||||
return jump_list.Delete()
|
||||
? JumpListResult::SUCCESS
|
||||
: JumpListResult::GENERIC_ERROR;
|
||||
}
|
||||
|
||||
// Start a transaction that updates the JumpList of this application.
|
||||
if (!jump_list.Begin())
|
||||
return JumpListResult::GENERIC_ERROR;
|
||||
|
||||
JumpListResult result = jump_list.AppendCategories(categories);
|
||||
// AppendCategories may have failed to add some categories, but it's better
|
||||
// to have something than nothing so try to commit the changes anyway.
|
||||
if (!jump_list.Commit()) {
|
||||
LOG(ERROR) << "Failed to commit changes to custom Jump List.";
|
||||
// It's more useful to return the earlier error code that might give
|
||||
// some indication as to why the transaction actually failed, so don't
|
||||
// overwrite it with a "generic error" code here.
|
||||
if (result == JumpListResult::SUCCESS)
|
||||
result = JumpListResult::GENERIC_ERROR;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif // defined(OS_WIN)
|
||||
|
||||
// static
|
||||
mate::Handle<App> App::Create(v8::Isolate* isolate) {
|
||||
return mate::CreateHandle(isolate, new App(isolate));
|
||||
}
|
||||
|
||||
// static
|
||||
void App::BuildPrototype(
|
||||
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "App"));
|
||||
auto browser = base::Unretained(Browser::Get());
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetMethod("quit", base::Bind(&Browser::Quit, browser))
|
||||
.SetMethod("exit", base::Bind(&Browser::Exit, browser))
|
||||
.SetMethod("focus", base::Bind(&Browser::Focus, browser))
|
||||
.SetMethod("getVersion", base::Bind(&Browser::GetVersion, browser))
|
||||
.SetMethod("setVersion", base::Bind(&Browser::SetVersion, browser))
|
||||
.SetMethod("getName", base::Bind(&Browser::GetName, browser))
|
||||
.SetMethod("setName", base::Bind(&Browser::SetName, browser))
|
||||
.SetMethod("isReady", base::Bind(&Browser::is_ready, browser))
|
||||
.SetMethod("addRecentDocument",
|
||||
base::Bind(&Browser::AddRecentDocument, browser))
|
||||
.SetMethod("clearRecentDocuments",
|
||||
base::Bind(&Browser::ClearRecentDocuments, browser))
|
||||
.SetMethod("setAppUserModelId",
|
||||
base::Bind(&Browser::SetAppUserModelID, browser))
|
||||
.SetMethod("isDefaultProtocolClient",
|
||||
base::Bind(&Browser::IsDefaultProtocolClient, browser))
|
||||
.SetMethod("setAsDefaultProtocolClient",
|
||||
base::Bind(&Browser::SetAsDefaultProtocolClient, browser))
|
||||
.SetMethod("removeAsDefaultProtocolClient",
|
||||
base::Bind(&Browser::RemoveAsDefaultProtocolClient, browser))
|
||||
.SetMethod("setBadgeCount", base::Bind(&Browser::SetBadgeCount, browser))
|
||||
.SetMethod("getBadgeCount", base::Bind(&Browser::GetBadgeCount, browser))
|
||||
.SetMethod("getLoginItemSettings",
|
||||
base::Bind(&Browser::GetLoginItemSettings, browser))
|
||||
.SetMethod("setLoginItemSettings",
|
||||
base::Bind(&Browser::SetLoginItemSettings, browser))
|
||||
#if defined(OS_MACOSX)
|
||||
.SetMethod("hide", base::Bind(&Browser::Hide, browser))
|
||||
.SetMethod("show", base::Bind(&Browser::Show, browser))
|
||||
.SetMethod("setUserActivity",
|
||||
base::Bind(&Browser::SetUserActivity, browser))
|
||||
.SetMethod("getCurrentActivityType",
|
||||
base::Bind(&Browser::GetCurrentActivityType, browser))
|
||||
.SetMethod("setAboutPanelOptions",
|
||||
base::Bind(&Browser::SetAboutPanelOptions, browser))
|
||||
#endif
|
||||
#if defined(OS_WIN)
|
||||
.SetMethod("setUserTasks", base::Bind(&Browser::SetUserTasks, browser))
|
||||
.SetMethod("getJumpListSettings", &App::GetJumpListSettings)
|
||||
.SetMethod("setJumpList", &App::SetJumpList)
|
||||
#endif
|
||||
#if defined(OS_LINUX)
|
||||
.SetMethod("isUnityRunning",
|
||||
base::Bind(&Browser::IsUnityRunning, browser))
|
||||
#endif
|
||||
.SetMethod("setPath", &App::SetPath)
|
||||
.SetMethod("getPath", &App::GetPath)
|
||||
.SetMethod("setDesktopName", &App::SetDesktopName)
|
||||
.SetMethod("getLocale", &App::GetLocale)
|
||||
#if defined(USE_NSS_CERTS)
|
||||
.SetMethod("importCertificate", &App::ImportCertificate)
|
||||
#endif
|
||||
.SetMethod("makeSingleInstance", &App::MakeSingleInstance)
|
||||
.SetMethod("releaseSingleInstance", &App::ReleaseSingleInstance)
|
||||
.SetMethod("relaunch", &App::Relaunch)
|
||||
.SetMethod("isAccessibilitySupportEnabled",
|
||||
&App::IsAccessibilitySupportEnabled)
|
||||
.SetMethod("disableHardwareAcceleration",
|
||||
&App::DisableHardwareAcceleration);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
void AppendSwitch(const std::string& switch_string, mate::Arguments* args) {
|
||||
auto command_line = base::CommandLine::ForCurrentProcess();
|
||||
|
||||
if (base::EndsWith(switch_string, "-path",
|
||||
base::CompareCase::INSENSITIVE_ASCII) ||
|
||||
switch_string == switches::kLogNetLog) {
|
||||
base::FilePath path;
|
||||
args->GetNext(&path);
|
||||
command_line->AppendSwitchPath(switch_string, path);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string value;
|
||||
if (args->GetNext(&value))
|
||||
command_line->AppendSwitchASCII(switch_string, value);
|
||||
else
|
||||
command_line->AppendSwitch(switch_string);
|
||||
}
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
int DockBounce(const std::string& type) {
|
||||
int request_id = -1;
|
||||
if (type == "critical")
|
||||
request_id = Browser::Get()->DockBounce(Browser::BOUNCE_CRITICAL);
|
||||
else if (type == "informational")
|
||||
request_id = Browser::Get()->DockBounce(Browser::BOUNCE_INFORMATIONAL);
|
||||
return request_id;
|
||||
}
|
||||
|
||||
void DockSetMenu(atom::api::Menu* menu) {
|
||||
Browser::Get()->DockSetMenu(menu->model());
|
||||
}
|
||||
#endif
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
auto command_line = base::CommandLine::ForCurrentProcess();
|
||||
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("App", atom::api::App::GetConstructor(isolate)->GetFunction());
|
||||
dict.Set("app", atom::api::App::Create(isolate));
|
||||
dict.SetMethod("appendSwitch", &AppendSwitch);
|
||||
dict.SetMethod("appendArgument",
|
||||
base::Bind(&base::CommandLine::AppendArg,
|
||||
base::Unretained(command_line)));
|
||||
#if defined(OS_MACOSX)
|
||||
auto browser = base::Unretained(Browser::Get());
|
||||
dict.SetMethod("dockBounce", &DockBounce);
|
||||
dict.SetMethod("dockCancelBounce",
|
||||
base::Bind(&Browser::DockCancelBounce, browser));
|
||||
dict.SetMethod("dockDownloadFinished",
|
||||
base::Bind(&Browser::DockDownloadFinished, browser));
|
||||
dict.SetMethod("dockSetBadgeText",
|
||||
base::Bind(&Browser::DockSetBadgeText, browser));
|
||||
dict.SetMethod("dockGetBadgeText",
|
||||
base::Bind(&Browser::DockGetBadgeText, browser));
|
||||
dict.SetMethod("dockHide", base::Bind(&Browser::DockHide, browser));
|
||||
dict.SetMethod("dockShow", base::Bind(&Browser::DockShow, browser));
|
||||
dict.SetMethod("dockIsVisible", base::Bind(&Browser::DockIsVisible, browser));
|
||||
dict.SetMethod("dockSetMenu", &DockSetMenu);
|
||||
dict.SetMethod("dockSetIcon", base::Bind(&Browser::DockSetIcon, browser));
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_app, Initialize)
|
||||
152
atom/browser/api/atom_api_app.h
Normal file
152
atom/browser/api/atom_api_app.h
Normal file
@@ -0,0 +1,152 @@
|
||||
// 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_APP_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_APP_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/browser/api/event_emitter.h"
|
||||
#include "atom/browser/atom_browser_client.h"
|
||||
#include "atom/browser/browser_observer.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "chrome/browser/process_singleton.h"
|
||||
#include "content/public/browser/gpu_data_manager_observer.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "net/base/completion_callback.h"
|
||||
|
||||
#if defined(USE_NSS_CERTS)
|
||||
#include "chrome/browser/certificate_manager_model.h"
|
||||
#endif
|
||||
|
||||
namespace base {
|
||||
class FilePath;
|
||||
}
|
||||
|
||||
namespace mate {
|
||||
class Arguments;
|
||||
} // namespace mate
|
||||
|
||||
namespace atom {
|
||||
|
||||
#if defined(OS_WIN)
|
||||
enum class JumpListResult : int;
|
||||
#endif
|
||||
|
||||
namespace api {
|
||||
|
||||
class App : public AtomBrowserClient::Delegate,
|
||||
public mate::EventEmitter<App>,
|
||||
public BrowserObserver,
|
||||
public content::GpuDataManagerObserver {
|
||||
public:
|
||||
static mate::Handle<App> Create(v8::Isolate* isolate);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
// Called when window with disposition needs to be created.
|
||||
void OnCreateWindow(
|
||||
const GURL& target_url,
|
||||
const std::string& frame_name,
|
||||
WindowOpenDisposition disposition,
|
||||
const std::vector<base::string16>& features,
|
||||
const scoped_refptr<content::ResourceRequestBodyImpl>& body,
|
||||
int render_process_id,
|
||||
int render_frame_id);
|
||||
|
||||
#if defined(USE_NSS_CERTS)
|
||||
void OnCertificateManagerModelCreated(
|
||||
std::unique_ptr<base::DictionaryValue> options,
|
||||
const net::CompletionCallback& callback,
|
||||
std::unique_ptr<CertificateManagerModel> model);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
explicit App(v8::Isolate* isolate);
|
||||
~App() override;
|
||||
|
||||
// BrowserObserver:
|
||||
void OnBeforeQuit(bool* prevent_default) override;
|
||||
void OnWillQuit(bool* prevent_default) override;
|
||||
void OnWindowAllClosed() override;
|
||||
void OnQuit() override;
|
||||
void OnOpenFile(bool* prevent_default, const std::string& file_path) override;
|
||||
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(LoginHandler* login_handler,
|
||||
const base::DictionaryValue& request_details) override;
|
||||
void OnAccessibilitySupportChanged() override;
|
||||
#if defined(OS_MACOSX)
|
||||
void OnContinueUserActivity(
|
||||
bool* prevent_default,
|
||||
const std::string& type,
|
||||
const base::DictionaryValue& user_info) 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 overridable,
|
||||
bool strict_enforcement,
|
||||
bool expired_previous_decision,
|
||||
const base::Callback<void(bool)>& callback,
|
||||
content::CertificateRequestResultType* request) override;
|
||||
void SelectClientCertificate(
|
||||
content::WebContents* web_contents,
|
||||
net::SSLCertRequestInfo* cert_request_info,
|
||||
std::unique_ptr<content::ClientCertificateDelegate> delegate) override;
|
||||
|
||||
// content::GpuDataManagerObserver:
|
||||
void OnGpuProcessCrashed(base::TerminationStatus status) override;
|
||||
|
||||
private:
|
||||
// Get/Set the pre-defined path in PathService.
|
||||
base::FilePath GetPath(mate::Arguments* args, const std::string& name);
|
||||
void SetPath(mate::Arguments* args,
|
||||
const std::string& name,
|
||||
const base::FilePath& path);
|
||||
|
||||
void SetDesktopName(const std::string& desktop_name);
|
||||
std::string GetLocale();
|
||||
bool MakeSingleInstance(
|
||||
const ProcessSingleton::NotificationCallback& callback);
|
||||
void ReleaseSingleInstance();
|
||||
bool Relaunch(mate::Arguments* args);
|
||||
void DisableHardwareAcceleration(mate::Arguments* args);
|
||||
bool IsAccessibilitySupportEnabled();
|
||||
#if defined(USE_NSS_CERTS)
|
||||
void ImportCertificate(const base::DictionaryValue& options,
|
||||
const net::CompletionCallback& callback);
|
||||
#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
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(App);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_APP_H_
|
||||
137
atom/browser/api/atom_api_auto_updater.cc
Normal file
137
atom/browser/api/atom_api_auto_updater.cc
Normal file
@@ -0,0 +1,137 @@
|
||||
// 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_auto_updater.h"
|
||||
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "atom/browser/window_list.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<>
|
||||
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());
|
||||
if (date.IsEmpty())
|
||||
return v8::Null(isolate);
|
||||
else
|
||||
return date.ToLocalChecked();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
AutoUpdater::AutoUpdater(v8::Isolate* isolate) {
|
||||
auto_updater::AutoUpdater::SetDelegate(this);
|
||||
Init(isolate);
|
||||
}
|
||||
|
||||
AutoUpdater::~AutoUpdater() {
|
||||
auto_updater::AutoUpdater::SetDelegate(nullptr);
|
||||
}
|
||||
|
||||
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));
|
||||
EmitCustomEvent(
|
||||
"error",
|
||||
error->ToObject(isolate()->GetCurrentContext()).ToLocalChecked(),
|
||||
// Message is also emitted to keep compatibility with old code.
|
||||
message);
|
||||
}
|
||||
|
||||
void AutoUpdater::OnCheckingForUpdate() {
|
||||
Emit("checking-for-update");
|
||||
}
|
||||
|
||||
void AutoUpdater::OnUpdateAvailable() {
|
||||
Emit("update-available");
|
||||
}
|
||||
|
||||
void AutoUpdater::OnUpdateNotAvailable() {
|
||||
Emit("update-not-available");
|
||||
}
|
||||
|
||||
void AutoUpdater::OnUpdateDownloaded(const std::string& release_notes,
|
||||
const std::string& release_name,
|
||||
const base::Time& release_date,
|
||||
const std::string& url) {
|
||||
Emit("update-downloaded", release_notes, release_name, release_date, url,
|
||||
// Keep compatibility with old APIs.
|
||||
base::Bind(&AutoUpdater::QuitAndInstall, base::Unretained(this)));
|
||||
}
|
||||
|
||||
void AutoUpdater::OnWindowAllClosed() {
|
||||
QuitAndInstall();
|
||||
}
|
||||
|
||||
void AutoUpdater::SetFeedURL(const std::string& url, mate::Arguments* args) {
|
||||
auto_updater::AutoUpdater::HeaderMap headers;
|
||||
args->GetNext(&headers);
|
||||
auto_updater::AutoUpdater::SetFeedURL(url, headers);
|
||||
}
|
||||
|
||||
void AutoUpdater::QuitAndInstall() {
|
||||
// If we don't have any window then quitAndInstall immediately.
|
||||
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.
|
||||
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);
|
||||
}
|
||||
|
||||
} // 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) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("autoUpdater", AutoUpdater::Create(isolate));
|
||||
dict.Set("AutoUpdater", AutoUpdater::GetConstructor(isolate)->GetFunction());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_auto_updater, Initialize)
|
||||
58
atom/browser/api/atom_api_auto_updater.h
Normal file
58
atom/browser/api/atom_api_auto_updater.h
Normal file
@@ -0,0 +1,58 @@
|
||||
// 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_AUTO_UPDATER_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_AUTO_UPDATER_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#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>,
|
||||
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;
|
||||
|
||||
// Delegate implementations.
|
||||
void OnError(const std::string& error) override;
|
||||
void OnCheckingForUpdate() override;
|
||||
void OnUpdateAvailable() override;
|
||||
void OnUpdateNotAvailable() override;
|
||||
void OnUpdateDownloaded(const std::string& release_notes,
|
||||
const std::string& release_name,
|
||||
const base::Time& release_date,
|
||||
const std::string& update_url) override;
|
||||
|
||||
// WindowListObserver:
|
||||
void OnWindowAllClosed() override;
|
||||
|
||||
private:
|
||||
std::string GetFeedURL();
|
||||
void SetFeedURL(const std::string& url, mate::Arguments* args);
|
||||
void QuitAndInstall();
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AutoUpdater);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_AUTO_UPDATER_H_
|
||||
80
atom/browser/api/atom_api_content_tracing.cc
Normal file
80
atom/browser/api/atom_api_content_tracing.cc
Normal file
@@ -0,0 +1,80 @@
|
||||
// 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 <set>
|
||||
#include <string>
|
||||
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/file_path_converter.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<>
|
||||
struct Converter<base::trace_event::TraceConfig> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
base::trace_event::TraceConfig* out) {
|
||||
Dictionary options;
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
namespace {
|
||||
|
||||
using CompletionCallback = base::Callback<void(const base::FilePath&)>;
|
||||
|
||||
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::CreateFileSink(result_file_path,
|
||||
base::Bind(callback,
|
||||
result_file_path));
|
||||
}
|
||||
|
||||
void StopRecording(const base::FilePath& path,
|
||||
const CompletionCallback& callback) {
|
||||
TracingController::GetInstance()->StopTracing(
|
||||
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("stopRecording", &StopRecording);
|
||||
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_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_content_tracing, Initialize)
|
||||
293
atom/browser/api/atom_api_cookies.cc
Normal file
293
atom/browser/api/atom_api_cookies.cc
Normal file
@@ -0,0 +1,293 @@
|
||||
// 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_cookies.h"
|
||||
|
||||
#include "atom/browser/atom_browser_context.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/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/cookie_monster.h"
|
||||
#include "net/cookies/cookie_store.h"
|
||||
#include "net/cookies/cookie_util.h"
|
||||
#include "net/url_request/url_request_context.h"
|
||||
#include "net/url_request/url_request_context_getter.h"
|
||||
|
||||
using atom::AtomCookieDelegate;
|
||||
using content::BrowserThread;
|
||||
|
||||
namespace mate {
|
||||
|
||||
template<>
|
||||
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<>
|
||||
struct Converter<net::CanonicalCookie> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
const net::CanonicalCookie& val) {
|
||||
mate::Dictionary dict(isolate, v8::Object::New(isolate));
|
||||
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("path", val.Path());
|
||||
dict.Set("secure", val.IsSecure());
|
||||
dict.Set("httpOnly", val.IsHttpOnly());
|
||||
dict.Set("session", !val.IsPersistent());
|
||||
if (val.IsPersistent())
|
||||
dict.Set("expirationDate", val.ExpiryDate().ToDoubleT());
|
||||
return dict.GetHandle();
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Converter<AtomCookieDelegate::ChangeCause> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
const AtomCookieDelegate::ChangeCause& val) {
|
||||
switch (val) {
|
||||
case AtomCookieDelegate::ChangeCause::CHANGE_COOKIE_EXPLICIT:
|
||||
return mate::StringToV8(isolate, "explicit");
|
||||
case AtomCookieDelegate::ChangeCause::CHANGE_COOKIE_OVERWRITE:
|
||||
return mate::StringToV8(isolate, "overwrite");
|
||||
case AtomCookieDelegate::ChangeCause::CHANGE_COOKIE_EXPIRED:
|
||||
return mate::StringToV8(isolate, "expired");
|
||||
case AtomCookieDelegate::ChangeCause::CHANGE_COOKIE_EVICTED:
|
||||
return mate::StringToV8(isolate, "evicted");
|
||||
case AtomCookieDelegate::ChangeCause::CHANGE_COOKIE_EXPIRED_OVERWRITE:
|
||||
return mate::StringToV8(isolate, "expired-overwrite");
|
||||
default:
|
||||
return mate::StringToV8(isolate, "unknown");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
namespace {
|
||||
|
||||
// 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, ".");
|
||||
|
||||
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);
|
||||
|
||||
// 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);
|
||||
}
|
||||
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) {
|
||||
net::CookieList result;
|
||||
for (const auto& cookie : list) {
|
||||
if (MatchesCookie(filter.get(), cookie))
|
||||
result.push_back(cookie);
|
||||
}
|
||||
RunCallbackInUI(base::Bind(callback, Cookies::SUCCESS, result));
|
||||
}
|
||||
|
||||
// Receives cookies matching |filter| in IO thread.
|
||||
void GetCookiesOnIO(scoped_refptr<net::URLRequestContextGetter> getter,
|
||||
std::unique_ptr<base::DictionaryValue> filter,
|
||||
const Cookies::GetCallback& callback) {
|
||||
std::string url;
|
||||
filter->GetString("url", &url);
|
||||
|
||||
auto filtered_callback =
|
||||
base::Bind(FilterCookies, base::Passed(&filter), callback);
|
||||
|
||||
// Empty url will match all url cookies.
|
||||
if (url.empty())
|
||||
GetCookieStore(getter)->GetAllCookiesAsync(filtered_callback);
|
||||
else
|
||||
GetCookieStore(getter)->GetAllCookiesForURLAsync(GURL(url),
|
||||
filtered_callback);
|
||||
}
|
||||
|
||||
// Removes cookie with |url| and |name| in IO thread.
|
||||
void RemoveCookieOnIOThread(scoped_refptr<net::URLRequestContextGetter> getter,
|
||||
const GURL& url, const std::string& name,
|
||||
const base::Closure& callback) {
|
||||
GetCookieStore(getter)->DeleteCookieAsync(
|
||||
url, name, base::Bind(RunCallbackInUI, callback));
|
||||
}
|
||||
|
||||
// Callback of SetCookie.
|
||||
void OnSetCookie(const Cookies::SetCallback& callback, bool success) {
|
||||
RunCallbackInUI(
|
||||
base::Bind(callback, success ? Cookies::SUCCESS : Cookies::FAILED));
|
||||
}
|
||||
|
||||
// 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;
|
||||
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);
|
||||
}
|
||||
|
||||
base::Time expiration_time;
|
||||
if (details->GetDouble("expirationDate", &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);
|
||||
}
|
||||
|
||||
GetCookieStore(getter)->SetCookieWithDetailsAsync(
|
||||
GURL(url), name, value, domain, path, creation_time,
|
||||
expiration_time, last_access_time, secure, http_only,
|
||||
net::CookieSameSite::DEFAULT_MODE, false,
|
||||
net::COOKIE_PRIORITY_DEFAULT, base::Bind(OnSetCookie, callback));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Cookies::Cookies(v8::Isolate* isolate,
|
||||
AtomBrowserContext* browser_context)
|
||||
: request_context_getter_(browser_context->url_request_context_getter()),
|
||||
cookie_delegate_(browser_context->cookie_delegate()) {
|
||||
Init(isolate);
|
||||
cookie_delegate_->AddObserver(this);
|
||||
}
|
||||
|
||||
Cookies::~Cookies() {
|
||||
cookie_delegate_->RemoveObserver(this);
|
||||
}
|
||||
|
||||
void Cookies::Get(const base::DictionaryValue& filter,
|
||||
const GetCallback& callback) {
|
||||
std::unique_ptr<base::DictionaryValue> copied(filter.CreateDeepCopy());
|
||||
auto getter = make_scoped_refptr(request_context_getter_);
|
||||
content::BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(GetCookiesOnIO, getter, Passed(&copied), callback));
|
||||
}
|
||||
|
||||
void Cookies::Remove(const GURL& url, const std::string& name,
|
||||
const base::Closure& callback) {
|
||||
auto getter = make_scoped_refptr(request_context_getter_);
|
||||
content::BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(RemoveCookieOnIOThread, getter, url, name, callback));
|
||||
}
|
||||
|
||||
void Cookies::Set(const base::DictionaryValue& details,
|
||||
const SetCallback& callback) {
|
||||
std::unique_ptr<base::DictionaryValue> copied(details.CreateDeepCopy());
|
||||
auto getter = make_scoped_refptr(request_context_getter_);
|
||||
content::BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(SetCookieOnIO, getter, Passed(&copied), callback));
|
||||
}
|
||||
|
||||
void Cookies::OnCookieChanged(const net::CanonicalCookie& cookie,
|
||||
bool removed,
|
||||
AtomCookieDelegate::ChangeCause cause) {
|
||||
Emit("changed", cookie, cause, 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())
|
||||
.SetMethod("get", &Cookies::Get)
|
||||
.SetMethod("remove", &Cookies::Remove)
|
||||
.SetMethod("set", &Cookies::Set);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
73
atom/browser/api/atom_api_cookies.h
Normal file
73
atom/browser/api/atom_api_cookies.h
Normal file
@@ -0,0 +1,73 @@
|
||||
// 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_COOKIES_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_COOKIES_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "atom/browser/net/atom_cookie_delegate.h"
|
||||
#include "base/callback.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "net/cookies/canonical_cookie.h"
|
||||
|
||||
namespace base {
|
||||
class DictionaryValue;
|
||||
}
|
||||
|
||||
namespace net {
|
||||
class URLRequestContextGetter;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomBrowserContext;
|
||||
|
||||
namespace api {
|
||||
|
||||
class Cookies : public mate::TrackableObject<Cookies>,
|
||||
public AtomCookieDelegate::Observer {
|
||||
public:
|
||||
enum Error {
|
||||
SUCCESS,
|
||||
FAILED,
|
||||
};
|
||||
|
||||
using GetCallback = base::Callback<void(Error, const net::CookieList&)>;
|
||||
using SetCallback = base::Callback<void(Error)>;
|
||||
|
||||
static mate::Handle<Cookies> Create(v8::Isolate* isolate,
|
||||
AtomBrowserContext* browser_context);
|
||||
|
||||
// mate::TrackableObject:
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
protected:
|
||||
Cookies(v8::Isolate* isolate, AtomBrowserContext* browser_context);
|
||||
~Cookies() override;
|
||||
|
||||
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);
|
||||
|
||||
// AtomCookieDelegate::Observer:
|
||||
void OnCookieChanged(const net::CanonicalCookie& cookie,
|
||||
bool removed,
|
||||
AtomCookieDelegate::ChangeCause cause) override;
|
||||
|
||||
private:
|
||||
net::URLRequestContextGetter* request_context_getter_;
|
||||
scoped_refptr<AtomCookieDelegate> cookie_delegate_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Cookies);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_COOKIES_H_
|
||||
178
atom/browser/api/atom_api_debugger.cc
Normal file
178
atom/browser/api/atom_api_debugger.cc
Normal file
@@ -0,0 +1,178 @@
|
||||
// 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/browser/atom_browser_main_parts.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "base/json/json_reader.h"
|
||||
#include "base/json/json_writer.h"
|
||||
#include "content/public/browser/devtools_agent_host.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/object_template_builder.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
using content::DevToolsAgentHost;
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
Debugger::Debugger(v8::Isolate* isolate, content::WebContents* web_contents)
|
||||
: web_contents_(web_contents),
|
||||
previous_request_id_(0) {
|
||||
Init(isolate);
|
||||
}
|
||||
|
||||
Debugger::~Debugger() {
|
||||
}
|
||||
|
||||
void Debugger::AgentHostClosed(DevToolsAgentHost* agent_host,
|
||||
bool replaced_with_another_client) {
|
||||
std::string detach_reason = "target closed";
|
||||
if (replaced_with_another_client)
|
||||
detach_reason = "replaced with devtools";
|
||||
Emit("detach", detach_reason);
|
||||
}
|
||||
|
||||
void Debugger::DispatchProtocolMessage(DevToolsAgentHost* agent_host,
|
||||
const std::string& message) {
|
||||
DCHECK(agent_host == agent_host_.get());
|
||||
|
||||
std::unique_ptr<base::Value> parsed_message(base::JSONReader::Read(message));
|
||||
if (!parsed_message->IsType(base::Value::TYPE_DICTIONARY))
|
||||
return;
|
||||
|
||||
base::DictionaryValue* dict =
|
||||
static_cast<base::DictionaryValue*>(parsed_message.get());
|
||||
int id;
|
||||
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::Attach(mate::Arguments* args) {
|
||||
std::string protocol_version;
|
||||
args->GetNext(&protocol_version);
|
||||
|
||||
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_.get()) {
|
||||
args->ThrowError("No target available");
|
||||
return;
|
||||
}
|
||||
if (agent_host_->IsAttached()) {
|
||||
args->ThrowError("Another debugger is already attached to this target");
|
||||
return;
|
||||
}
|
||||
|
||||
agent_host_->AttachClient(this);
|
||||
}
|
||||
|
||||
bool Debugger::IsAttached() {
|
||||
return agent_host_.get() ? agent_host_->IsAttached() : false;
|
||||
}
|
||||
|
||||
void Debugger::Detach() {
|
||||
if (!agent_host_.get())
|
||||
return;
|
||||
agent_host_->DetachClient(this);
|
||||
AgentHostClosed(agent_host_.get(), false);
|
||||
agent_host_ = nullptr;
|
||||
}
|
||||
|
||||
void Debugger::SendCommand(mate::Arguments* args) {
|
||||
if (!agent_host_.get())
|
||||
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", command_params.DeepCopy());
|
||||
|
||||
std::string json_args;
|
||||
base::JSONWriter::Write(request, &json_args);
|
||||
agent_host_->DispatchProtocolMessage(this, json_args);
|
||||
}
|
||||
|
||||
// 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_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_debugger, Initialize);
|
||||
75
atom/browser/api/atom_api_debugger.h
Normal file
75
atom/browser/api/atom_api_debugger.h
Normal file
@@ -0,0 +1,75 @@
|
||||
// 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 "native_mate/handle.h"
|
||||
|
||||
namespace content {
|
||||
class DevToolsAgentHost;
|
||||
class WebContents;
|
||||
}
|
||||
|
||||
namespace mate {
|
||||
class Arguments;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class Debugger: public mate::TrackableObject<Debugger>,
|
||||
public content::DevToolsAgentHostClient {
|
||||
public:
|
||||
using SendCommandCallback =
|
||||
base::Callback<void(const base::DictionaryValue&,
|
||||
const base::DictionaryValue&)>;
|
||||
|
||||
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,
|
||||
bool replaced_with_another_client) override;
|
||||
void DispatchProtocolMessage(content::DevToolsAgentHost* agent_host,
|
||||
const std::string& message) override;
|
||||
|
||||
private:
|
||||
using PendingRequestMap = std::map<int, SendCommandCallback>;
|
||||
|
||||
void Attach(mate::Arguments* args);
|
||||
bool IsAttached();
|
||||
void Detach();
|
||||
void SendCommand(mate::Arguments* args);
|
||||
|
||||
content::WebContents* web_contents_; // Weak Reference.
|
||||
scoped_refptr<content::DevToolsAgentHost> agent_host_;
|
||||
|
||||
PendingRequestMap pending_requests_;
|
||||
int previous_request_id_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Debugger);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_DEBUGGER_H_
|
||||
123
atom/browser/api/atom_api_desktop_capturer.cc
Normal file
123
atom/browser/api/atom_api_desktop_capturer.cc
Normal file
@@ -0,0 +1,123 @@
|
||||
// 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 "atom/common/api/atom_api_native_image.h"
|
||||
#include "atom/common/native_mate_converters/gfx_converter.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "chrome/browser/media/desktop_media_list.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
|
||||
#include "third_party/webrtc/modules/desktop_capture/screen_capturer.h"
|
||||
#include "third_party/webrtc/modules/desktop_capture/window_capturer.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace mate {
|
||||
|
||||
template<>
|
||||
struct Converter<DesktopMediaList::Source> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
const DesktopMediaList::Source& source) {
|
||||
mate::Dictionary dict(isolate, v8::Object::New(isolate));
|
||||
content::DesktopMediaID id = source.id;
|
||||
dict.Set("name", base::UTF16ToUTF8(source.name));
|
||||
dict.Set("id", id.ToString());
|
||||
dict.Set(
|
||||
"thumbnail",
|
||||
atom::api::NativeImage::Create(isolate, gfx::Image(source.thumbnail)));
|
||||
return ConvertToV8(isolate, dict);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
DesktopCapturer::DesktopCapturer(v8::Isolate* isolate) {
|
||||
Init(isolate);
|
||||
}
|
||||
|
||||
DesktopCapturer::~DesktopCapturer() {
|
||||
}
|
||||
|
||||
void DesktopCapturer::StartHandling(bool capture_window,
|
||||
bool capture_screen,
|
||||
const gfx::Size& thumbnail_size) {
|
||||
webrtc::DesktopCaptureOptions options =
|
||||
webrtc::DesktopCaptureOptions::CreateDefault();
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// On windows, desktop effects (e.g. Aero) will be disabled when the Desktop
|
||||
// capture API is active by default.
|
||||
// We keep the desktop effects in most times. Howerver, the screen still
|
||||
// fickers when the API is capturing the window due to limitation of current
|
||||
// implemetation. This is a known and wontFix issue in webrtc (see:
|
||||
// http://code.google.com/p/webrtc/issues/detail?id=3373)
|
||||
options.set_disable_effects(false);
|
||||
#endif
|
||||
|
||||
std::unique_ptr<webrtc::ScreenCapturer> screen_capturer(
|
||||
capture_screen ? webrtc::ScreenCapturer::Create(options) : nullptr);
|
||||
std::unique_ptr<webrtc::WindowCapturer> window_capturer(
|
||||
capture_window ? webrtc::WindowCapturer::Create(options) : nullptr);
|
||||
media_list_.reset(new NativeDesktopMediaList(
|
||||
std::move(screen_capturer), std::move(window_capturer)));
|
||||
|
||||
media_list_->SetThumbnailSize(thumbnail_size);
|
||||
media_list_->StartUpdating(this);
|
||||
}
|
||||
|
||||
void DesktopCapturer::OnSourceAdded(int index) {
|
||||
}
|
||||
|
||||
void DesktopCapturer::OnSourceRemoved(int index) {
|
||||
}
|
||||
|
||||
void DesktopCapturer::OnSourceMoved(int old_index, int new_index) {
|
||||
}
|
||||
|
||||
void DesktopCapturer::OnSourceNameChanged(int index) {
|
||||
}
|
||||
|
||||
void DesktopCapturer::OnSourceThumbnailChanged(int index) {
|
||||
}
|
||||
|
||||
bool DesktopCapturer::OnRefreshFinished() {
|
||||
Emit("finished", media_list_->GetSources());
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_desktop_capturer, Initialize);
|
||||
51
atom/browser/api/atom_api_desktop_capturer.h
Normal file
51
atom/browser/api/atom_api_desktop_capturer.h
Normal file
@@ -0,0 +1,51 @@
|
||||
// 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 "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:
|
||||
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);
|
||||
|
||||
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:
|
||||
std::unique_ptr<DesktopMediaList> media_list_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(DesktopCapturer);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_DESKTOP_CAPTURER_H_
|
||||
123
atom/browser/api/atom_api_dialog.cc
Normal file
123
atom/browser/api/atom_api_dialog.cc
Normal file
@@ -0,0 +1,123 @@
|
||||
// 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 <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/browser/api/atom_api_window.h"
|
||||
#include "atom/browser/native_window.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 "native_mate/dictionary.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace mate {
|
||||
|
||||
template<>
|
||||
struct Converter<file_dialog::Filter> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
file_dialog::Filter* out) {
|
||||
mate::Dictionary dict;
|
||||
if (!ConvertFromV8(isolate, val, &dict))
|
||||
return false;
|
||||
if (!dict.Get("name", &(out->first)))
|
||||
return false;
|
||||
if (!dict.Get("extensions", &(out->second)))
|
||||
return false;
|
||||
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 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,
|
||||
&callback)) {
|
||||
atom::ShowMessageBox(window, (atom::MessageBoxType)type, buttons,
|
||||
default_id, cancel_id, options, title,
|
||||
message, detail, icon, callback);
|
||||
} else {
|
||||
int chosen = atom::ShowMessageBox(window, (atom::MessageBoxType)type,
|
||||
buttons, default_id, cancel_id,
|
||||
options, title, message, detail, icon);
|
||||
args->Return(chosen);
|
||||
}
|
||||
}
|
||||
|
||||
void ShowOpenDialog(const std::string& title,
|
||||
const std::string& button_label,
|
||||
const base::FilePath& default_path,
|
||||
const file_dialog::Filters& filters,
|
||||
int properties,
|
||||
atom::NativeWindow* window,
|
||||
mate::Arguments* args) {
|
||||
v8::Local<v8::Value> peek = args->PeekNext();
|
||||
file_dialog::OpenDialogCallback callback;
|
||||
if (mate::Converter<file_dialog::OpenDialogCallback>::FromV8(args->isolate(),
|
||||
peek,
|
||||
&callback)) {
|
||||
file_dialog::ShowOpenDialog(window, title, button_label, default_path,
|
||||
filters, properties, callback);
|
||||
} else {
|
||||
std::vector<base::FilePath> paths;
|
||||
if (file_dialog::ShowOpenDialog(window, title, button_label, default_path,
|
||||
filters, properties, &paths))
|
||||
args->Return(paths);
|
||||
}
|
||||
}
|
||||
|
||||
void ShowSaveDialog(const std::string& title,
|
||||
const std::string& button_label,
|
||||
const base::FilePath& default_path,
|
||||
const file_dialog::Filters& filters,
|
||||
atom::NativeWindow* window,
|
||||
mate::Arguments* args) {
|
||||
v8::Local<v8::Value> peek = args->PeekNext();
|
||||
file_dialog::SaveDialogCallback callback;
|
||||
if (mate::Converter<file_dialog::SaveDialogCallback>::FromV8(args->isolate(),
|
||||
peek,
|
||||
&callback)) {
|
||||
file_dialog::ShowSaveDialog(window, title, button_label, default_path,
|
||||
filters, callback);
|
||||
} else {
|
||||
base::FilePath path;
|
||||
if (file_dialog::ShowSaveDialog(window, title, button_label, default_path,
|
||||
filters, &path))
|
||||
args->Return(path);
|
||||
}
|
||||
}
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
mate::Dictionary dict(context->GetIsolate(), exports);
|
||||
dict.SetMethod("showMessageBox", &ShowMessageBox);
|
||||
dict.SetMethod("showErrorBox", &atom::ShowErrorBox);
|
||||
dict.SetMethod("showOpenDialog", &ShowOpenDialog);
|
||||
dict.SetMethod("showSaveDialog", &ShowSaveDialog);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_dialog, Initialize)
|
||||
240
atom/browser/api/atom_api_download_item.cc
Normal file
240
atom/browser/api/atom_api_download_item.cc
Normal file
@@ -0,0 +1,240 @@
|
||||
// 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_download_item.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
#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 "atom/common/native_mate_converters/gurl_converter.h"
|
||||
#include "base/message_loop/message_loop.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "net/base/filename_util.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace mate {
|
||||
|
||||
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 content::DownloadItem::IN_PROGRESS:
|
||||
download_state = "progressing";
|
||||
break;
|
||||
case content::DownloadItem::COMPLETE:
|
||||
download_state = "completed";
|
||||
break;
|
||||
case content::DownloadItem::CANCELLED:
|
||||
download_state = "cancelled";
|
||||
break;
|
||||
case content::DownloadItem::INTERRUPTED:
|
||||
download_state = "interrupted";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ConvertToV8(isolate, download_state);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
namespace {
|
||||
|
||||
std::map<uint32_t, v8::Global<v8::Object>> g_download_item_objects;
|
||||
|
||||
} // namespace
|
||||
|
||||
DownloadItem::DownloadItem(v8::Isolate* isolate,
|
||||
content::DownloadItem* download_item)
|
||||
: download_item_(download_item) {
|
||||
download_item_->AddObserver(this);
|
||||
Init(isolate);
|
||||
AttachAsUserData(download_item);
|
||||
}
|
||||
|
||||
DownloadItem::~DownloadItem() {
|
||||
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(content::DownloadItem* item) {
|
||||
if (download_item_->IsDone()) {
|
||||
Emit("done", item->GetState());
|
||||
|
||||
// Destroy the item once item is downloaded.
|
||||
base::MessageLoop::current()->PostTask(FROM_HERE, GetDestroyClosure());
|
||||
} else {
|
||||
Emit("updated", item->GetState());
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadItem::OnDownloadDestroyed(content::DownloadItem* download_item) {
|
||||
download_item_ = nullptr;
|
||||
// Destroy the native class immediately when downloadItem is destroyed.
|
||||
delete this;
|
||||
}
|
||||
|
||||
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);
|
||||
download_item_->Remove();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
content::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()
|
||||
.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("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);
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<DownloadItem> DownloadItem::Create(
|
||||
v8::Isolate* isolate, content::DownloadItem* item) {
|
||||
auto existing = TrackableObject::FromWrappedClass(isolate, item);
|
||||
if (existing)
|
||||
return mate::CreateHandle(isolate, static_cast<DownloadItem*>(existing));
|
||||
|
||||
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());
|
||||
return handle;
|
||||
}
|
||||
|
||||
} // 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(isolate, exports)
|
||||
.Set("DownloadItem",
|
||||
atom::api::DownloadItem::GetConstructor(isolate)->GetFunction());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_download_item, Initialize);
|
||||
70
atom/browser/api/atom_api_download_item.h
Normal file
70
atom/browser/api/atom_api_download_item.h
Normal file
@@ -0,0 +1,70 @@
|
||||
// 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_DOWNLOAD_ITEM_H_
|
||||
#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 "content/public/browser/download_item.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class DownloadItem : public mate::TrackableObject<DownloadItem>,
|
||||
public content::DownloadItem::Observer {
|
||||
public:
|
||||
static mate::Handle<DownloadItem> Create(v8::Isolate* isolate,
|
||||
content::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;
|
||||
content::DownloadItem::DownloadState GetState() const;
|
||||
bool IsDone() const;
|
||||
void SetSavePath(const base::FilePath& path);
|
||||
base::FilePath GetSavePath() const;
|
||||
std::string GetLastModifiedTime() const;
|
||||
std::string GetETag() const;
|
||||
double GetStartTime() const;
|
||||
|
||||
protected:
|
||||
DownloadItem(v8::Isolate* isolate, content::DownloadItem* download_item);
|
||||
~DownloadItem();
|
||||
|
||||
// Override content::DownloadItem::Observer methods
|
||||
void OnDownloadUpdated(content::DownloadItem* download) override;
|
||||
void OnDownloadDestroyed(content::DownloadItem* download) override;
|
||||
|
||||
private:
|
||||
base::FilePath save_path_;
|
||||
content::DownloadItem* download_item_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(DownloadItem);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_DOWNLOAD_ITEM_H_
|
||||
101
atom/browser/api/atom_api_global_shortcut.cc
Normal file
101
atom/browser/api/atom_api_global_shortcut.cc
Normal file
@@ -0,0 +1,101 @@
|
||||
// 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_global_shortcut.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "atom/common/native_mate_converters/accelerator_converter.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "base/stl_util.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
using extensions::GlobalShortcutListener;
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
GlobalShortcut::GlobalShortcut(v8::Isolate* isolate) {
|
||||
Init(isolate);
|
||||
}
|
||||
|
||||
GlobalShortcut::~GlobalShortcut() {
|
||||
UnregisterAll();
|
||||
}
|
||||
|
||||
void GlobalShortcut::OnKeyPressed(const ui::Accelerator& accelerator) {
|
||||
if (accelerator_callback_map_.find(accelerator) ==
|
||||
accelerator_callback_map_.end()) {
|
||||
// This should never occur, because if it does, GlobalGlobalShortcutListener
|
||||
// notifes us with wrong accelerator.
|
||||
NOTREACHED();
|
||||
return;
|
||||
}
|
||||
accelerator_callback_map_[accelerator].Run();
|
||||
}
|
||||
|
||||
bool GlobalShortcut::Register(const ui::Accelerator& accelerator,
|
||||
const base::Closure& callback) {
|
||||
if (!GlobalShortcutListener::GetInstance()->RegisterAccelerator(
|
||||
accelerator, this)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
accelerator_callback_map_[accelerator] = callback;
|
||||
return true;
|
||||
}
|
||||
|
||||
void GlobalShortcut::Unregister(const ui::Accelerator& accelerator) {
|
||||
if (!ContainsKey(accelerator_callback_map_, accelerator))
|
||||
return;
|
||||
|
||||
accelerator_callback_map_.erase(accelerator);
|
||||
GlobalShortcutListener::GetInstance()->UnregisterAccelerator(
|
||||
accelerator, this);
|
||||
}
|
||||
|
||||
bool GlobalShortcut::IsRegistered(const ui::Accelerator& accelerator) {
|
||||
return ContainsKey(accelerator_callback_map_, accelerator);
|
||||
}
|
||||
|
||||
void GlobalShortcut::UnregisterAll() {
|
||||
accelerator_callback_map_.clear();
|
||||
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())
|
||||
.SetMethod("register", &GlobalShortcut::Register)
|
||||
.SetMethod("isRegistered", &GlobalShortcut::IsRegistered)
|
||||
.SetMethod("unregister", &GlobalShortcut::Unregister)
|
||||
.SetMethod("unregisterAll", &GlobalShortcut::UnregisterAll);
|
||||
}
|
||||
|
||||
} // 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("globalShortcut", atom::api::GlobalShortcut::Create(isolate));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_global_shortcut, Initialize)
|
||||
54
atom/browser/api/atom_api_global_shortcut.h
Normal file
54
atom/browser/api/atom_api_global_shortcut.h
Normal file
@@ -0,0 +1,54 @@
|
||||
// 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_GLOBAL_SHORTCUT_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_GLOBAL_SHORTCUT_H_
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "base/callback.h"
|
||||
#include "chrome/browser/extensions/global_shortcut_listener.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "ui/base/accelerators/accelerator.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class GlobalShortcut : public extensions::GlobalShortcutListener::Observer,
|
||||
public mate::TrackableObject<GlobalShortcut> {
|
||||
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() override;
|
||||
|
||||
private:
|
||||
typedef std::map<ui::Accelerator, base::Closure> AcceleratorCallbackMap;
|
||||
|
||||
bool Register(const ui::Accelerator& accelerator,
|
||||
const base::Closure& callback);
|
||||
bool IsRegistered(const ui::Accelerator& accelerator);
|
||||
void Unregister(const ui::Accelerator& accelerator);
|
||||
void UnregisterAll();
|
||||
|
||||
// GlobalShortcutListener::Observer implementation.
|
||||
void OnKeyPressed(const ui::Accelerator& accelerator) override;
|
||||
|
||||
AcceleratorCallbackMap accelerator_callback_map_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(GlobalShortcut);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_GLOBAL_SHORTCUT_H_
|
||||
207
atom/browser/api/atom_api_menu.cc
Normal file
207
atom/browser/api/atom_api_menu.cc
Normal file
@@ -0,0 +1,207 @@
|
||||
// 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_menu.h"
|
||||
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "atom/common/native_mate_converters/accelerator_converter.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/image_converter.h"
|
||||
#include "atom/common/native_mate_converters/string16_converter.h"
|
||||
#include "native_mate/constructor.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/object_template_builder.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
Menu::Menu(v8::Isolate* isolate, v8::Local<v8::Object> wrapper)
|
||||
: model_(new AtomMenuModel(this)),
|
||||
parent_(nullptr) {
|
||||
InitWith(isolate, wrapper);
|
||||
}
|
||||
|
||||
Menu::~Menu() {
|
||||
}
|
||||
|
||||
void Menu::AfterInit(v8::Isolate* isolate) {
|
||||
mate::Dictionary wrappable(isolate, GetWrapper());
|
||||
mate::Dictionary delegate;
|
||||
if (!wrappable.Get("delegate", &delegate))
|
||||
return;
|
||||
|
||||
delegate.Get("isCommandIdChecked", &is_checked_);
|
||||
delegate.Get("isCommandIdEnabled", &is_enabled_);
|
||||
delegate.Get("isCommandIdVisible", &is_visible_);
|
||||
delegate.Get("getAcceleratorForCommandId", &get_accelerator_);
|
||||
delegate.Get("executeCommand", &execute_command_);
|
||||
delegate.Get("menuWillShow", &menu_will_show_);
|
||||
}
|
||||
|
||||
bool Menu::IsCommandIdChecked(int command_id) const {
|
||||
return is_checked_.Run(command_id);
|
||||
}
|
||||
|
||||
bool Menu::IsCommandIdEnabled(int command_id) const {
|
||||
return is_enabled_.Run(command_id);
|
||||
}
|
||||
|
||||
bool Menu::IsCommandIdVisible(int command_id) const {
|
||||
return is_visible_.Run(command_id);
|
||||
}
|
||||
|
||||
bool Menu::GetAcceleratorForCommandIdWithParams(
|
||||
int command_id,
|
||||
bool use_default_accelerator,
|
||||
ui::Accelerator* accelerator) const {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
v8::Local<v8::Value> val = get_accelerator_.Run(
|
||||
command_id, use_default_accelerator);
|
||||
return mate::ConvertFromV8(isolate(), val, accelerator);
|
||||
}
|
||||
|
||||
void Menu::ExecuteCommand(int command_id, int flags) {
|
||||
execute_command_.Run(
|
||||
mate::internal::CreateEventFromFlags(isolate(), flags),
|
||||
command_id);
|
||||
}
|
||||
|
||||
void Menu::MenuWillShow(ui::SimpleMenuModel* source) {
|
||||
menu_will_show_.Run();
|
||||
}
|
||||
|
||||
void Menu::InsertItemAt(
|
||||
int index, int command_id, const base::string16& label) {
|
||||
model_->InsertItemAt(index, command_id, label);
|
||||
}
|
||||
|
||||
void Menu::InsertSeparatorAt(int index) {
|
||||
model_->InsertSeparatorAt(index, ui::NORMAL_SEPARATOR);
|
||||
}
|
||||
|
||||
void Menu::InsertCheckItemAt(int index,
|
||||
int command_id,
|
||||
const base::string16& label) {
|
||||
model_->InsertCheckItemAt(index, command_id, label);
|
||||
}
|
||||
|
||||
void Menu::InsertRadioItemAt(int index,
|
||||
int command_id,
|
||||
const base::string16& label,
|
||||
int group_id) {
|
||||
model_->InsertRadioItemAt(index, command_id, label, group_id);
|
||||
}
|
||||
|
||||
void Menu::InsertSubMenuAt(int index,
|
||||
int command_id,
|
||||
const base::string16& label,
|
||||
Menu* menu) {
|
||||
menu->parent_ = this;
|
||||
model_->InsertSubMenuAt(index, command_id, label, menu->model_.get());
|
||||
}
|
||||
|
||||
void Menu::SetIcon(int index, const gfx::Image& image) {
|
||||
model_->SetIcon(index, image);
|
||||
}
|
||||
|
||||
void Menu::SetSublabel(int index, const base::string16& sublabel) {
|
||||
model_->SetSublabel(index, sublabel);
|
||||
}
|
||||
|
||||
void Menu::SetRole(int index, const base::string16& role) {
|
||||
model_->SetRole(index, role);
|
||||
}
|
||||
|
||||
void Menu::Clear() {
|
||||
model_->Clear();
|
||||
}
|
||||
|
||||
int Menu::GetIndexOfCommandId(int command_id) {
|
||||
return model_->GetIndexOfCommandId(command_id);
|
||||
}
|
||||
|
||||
int Menu::GetItemCount() const {
|
||||
return model_->GetItemCount();
|
||||
}
|
||||
|
||||
int Menu::GetCommandIdAt(int index) const {
|
||||
return model_->GetCommandIdAt(index);
|
||||
}
|
||||
|
||||
base::string16 Menu::GetLabelAt(int index) const {
|
||||
return model_->GetLabelAt(index);
|
||||
}
|
||||
|
||||
base::string16 Menu::GetSublabelAt(int index) const {
|
||||
return model_->GetSublabelAt(index);
|
||||
}
|
||||
|
||||
bool Menu::IsItemCheckedAt(int index) const {
|
||||
return model_->IsItemCheckedAt(index);
|
||||
}
|
||||
|
||||
bool Menu::IsEnabledAt(int index) const {
|
||||
return model_->IsEnabledAt(index);
|
||||
}
|
||||
|
||||
bool Menu::IsVisibleAt(int index) const {
|
||||
return model_->IsVisibleAt(index);
|
||||
}
|
||||
|
||||
// static
|
||||
void Menu::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "Menu"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.MakeDestroyable()
|
||||
.SetMethod("insertItem", &Menu::InsertItemAt)
|
||||
.SetMethod("insertCheckItem", &Menu::InsertCheckItemAt)
|
||||
.SetMethod("insertRadioItem", &Menu::InsertRadioItemAt)
|
||||
.SetMethod("insertSeparator", &Menu::InsertSeparatorAt)
|
||||
.SetMethod("insertSubMenu", &Menu::InsertSubMenuAt)
|
||||
.SetMethod("setIcon", &Menu::SetIcon)
|
||||
.SetMethod("setSublabel", &Menu::SetSublabel)
|
||||
.SetMethod("setRole", &Menu::SetRole)
|
||||
.SetMethod("clear", &Menu::Clear)
|
||||
.SetMethod("getIndexOfCommandId", &Menu::GetIndexOfCommandId)
|
||||
.SetMethod("getItemCount", &Menu::GetItemCount)
|
||||
.SetMethod("getCommandIdAt", &Menu::GetCommandIdAt)
|
||||
.SetMethod("getLabelAt", &Menu::GetLabelAt)
|
||||
.SetMethod("getSublabelAt", &Menu::GetSublabelAt)
|
||||
.SetMethod("isItemCheckedAt", &Menu::IsItemCheckedAt)
|
||||
.SetMethod("isEnabledAt", &Menu::IsEnabledAt)
|
||||
.SetMethod("isVisibleAt", &Menu::IsVisibleAt)
|
||||
.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) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
Menu::SetConstructor(isolate, base::Bind(&Menu::New));
|
||||
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("Menu", Menu::GetConstructor(isolate)->GetFunction());
|
||||
#if defined(OS_MACOSX)
|
||||
dict.SetMethod("setApplicationMenu", &Menu::SetApplicationMenu);
|
||||
dict.SetMethod("sendActionToFirstResponder",
|
||||
&Menu::SendActionToFirstResponder);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_menu, Initialize)
|
||||
128
atom/browser/api/atom_api_menu.h
Normal file
128
atom/browser/api/atom_api_menu.h
Normal file
@@ -0,0 +1,128 @@
|
||||
// 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_MENU_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_MENU_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#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"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class Menu : public mate::TrackableObject<Menu>,
|
||||
public AtomMenuModel::Delegate {
|
||||
public:
|
||||
static mate::WrappableBase* New(mate::Arguments* args);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
// Set the global menubar.
|
||||
static void SetApplicationMenu(Menu* menu);
|
||||
|
||||
// Fake sending an action from the application menu.
|
||||
static void SendActionToFirstResponder(const std::string& action);
|
||||
#endif
|
||||
|
||||
AtomMenuModel* model() const { return model_.get(); }
|
||||
|
||||
protected:
|
||||
Menu(v8::Isolate* isolate, v8::Local<v8::Object> wrapper);
|
||||
~Menu() override;
|
||||
|
||||
// mate::Wrappable:
|
||||
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;
|
||||
void ExecuteCommand(int command_id, int event_flags) override;
|
||||
void MenuWillShow(ui::SimpleMenuModel* source) override;
|
||||
|
||||
virtual void PopupAt(Window* window,
|
||||
int x = -1, int y = -1,
|
||||
int positioning_item = 0) = 0;
|
||||
|
||||
std::unique_ptr<AtomMenuModel> model_;
|
||||
Menu* parent_;
|
||||
|
||||
private:
|
||||
void InsertItemAt(int index, int command_id, const base::string16& label);
|
||||
void InsertSeparatorAt(int index);
|
||||
void InsertCheckItemAt(int index,
|
||||
int command_id,
|
||||
const base::string16& label);
|
||||
void InsertRadioItemAt(int index,
|
||||
int command_id,
|
||||
const base::string16& label,
|
||||
int group_id);
|
||||
void InsertSubMenuAt(int index,
|
||||
int command_id,
|
||||
const base::string16& label,
|
||||
Menu* menu);
|
||||
void SetIcon(int index, const gfx::Image& image);
|
||||
void SetSublabel(int index, const base::string16& sublabel);
|
||||
void SetRole(int index, const base::string16& role);
|
||||
void Clear();
|
||||
int GetIndexOfCommandId(int command_id);
|
||||
int GetItemCount() const;
|
||||
int GetCommandIdAt(int index) const;
|
||||
base::string16 GetLabelAt(int index) const;
|
||||
base::string16 GetSublabelAt(int index) const;
|
||||
bool IsItemCheckedAt(int index) const;
|
||||
bool IsEnabledAt(int index) const;
|
||||
bool IsVisibleAt(int index) const;
|
||||
|
||||
// Stored delegate methods.
|
||||
base::Callback<bool(int)> is_checked_;
|
||||
base::Callback<bool(int)> is_enabled_;
|
||||
base::Callback<bool(int)> is_visible_;
|
||||
base::Callback<v8::Local<v8::Value>(int, bool)> get_accelerator_;
|
||||
base::Callback<void(v8::Local<v8::Value>, int)> execute_command_;
|
||||
base::Callback<void()> menu_will_show_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Menu);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
|
||||
namespace mate {
|
||||
|
||||
template<>
|
||||
struct Converter<atom::AtomMenuModel*> {
|
||||
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
|
||||
atom::AtomMenuModel** out) {
|
||||
// null would be tranfered to NULL.
|
||||
if (val->IsNull()) {
|
||||
*out = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
atom::api::Menu* menu;
|
||||
if (!Converter<atom::api::Menu*>::FromV8(isolate, val, &menu))
|
||||
return false;
|
||||
*out = menu->model();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_MENU_H_
|
||||
38
atom/browser/api/atom_api_menu_mac.h
Normal file
38
atom/browser/api/atom_api_menu_mac.h
Normal file
@@ -0,0 +1,38 @@
|
||||
// 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_MENU_MAC_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_MENU_MAC_H_
|
||||
|
||||
#include "atom/browser/api/atom_api_menu.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#import "atom/browser/ui/cocoa/atom_menu_controller.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class MenuMac : public Menu {
|
||||
protected:
|
||||
MenuMac(v8::Isolate* isolate, v8::Local<v8::Object> wrapper);
|
||||
|
||||
void PopupAt(Window* window, int x, int y, int positioning_item) override;
|
||||
|
||||
base::scoped_nsobject<AtomMenuController> menu_controller_;
|
||||
|
||||
private:
|
||||
friend class Menu;
|
||||
|
||||
static void SendActionToFirstResponder(const std::string& action);
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(MenuMac);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_MENU_MAC_H_
|
||||
104
atom/browser/api/atom_api_menu_mac.mm
Normal file
104
atom/browser/api/atom_api_menu_mac.mm
Normal file
@@ -0,0 +1,104 @@
|
||||
// Copyright (c) 2013 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#import "atom/browser/api/atom_api_menu_mac.h"
|
||||
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "atom/browser/unresponsive_suppressor.h"
|
||||
#include "base/message_loop/message_loop.h"
|
||||
#include "base/strings/sys_string_conversions.h"
|
||||
#include "brightray/browser/inspectable_web_contents.h"
|
||||
#include "brightray/browser/inspectable_web_contents_view.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
MenuMac::MenuMac(v8::Isolate* isolate, v8::Local<v8::Object> wrapper)
|
||||
: Menu(isolate, wrapper) {
|
||||
}
|
||||
|
||||
void MenuMac::PopupAt(Window* window, int x, int y, int positioning_item) {
|
||||
NativeWindow* native_window = window->window();
|
||||
if (!native_window)
|
||||
return;
|
||||
brightray::InspectableWebContents* web_contents =
|
||||
native_window->inspectable_web_contents();
|
||||
if (!web_contents)
|
||||
return;
|
||||
|
||||
base::scoped_nsobject<AtomMenuController> menu_controller(
|
||||
[[AtomMenuController alloc] initWithModel:model_.get()
|
||||
useDefaultAccelerator:NO]);
|
||||
NSMenu* menu = [menu_controller menu];
|
||||
NSView* view = web_contents->GetView()->GetNativeView();
|
||||
|
||||
// Which menu item to show.
|
||||
NSMenuItem* item = nil;
|
||||
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) {
|
||||
NSWindow* nswindow = native_window->GetNativeWindow();
|
||||
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;
|
||||
|
||||
// Don't emit unresponsive event when showing menu.
|
||||
atom::UnresponsiveSuppressor suppressor;
|
||||
|
||||
// Show the menu.
|
||||
[menu popUpMenuPositioningItem:item atLocation:position 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]);
|
||||
[NSApp setMainMenu:[menu_controller menu]];
|
||||
|
||||
// Ensure the menu_controller_ is destroyed after main menu is set.
|
||||
menu_controller.swap(menu->menu_controller_);
|
||||
}
|
||||
|
||||
// static
|
||||
void Menu::SendActionToFirstResponder(const std::string& action) {
|
||||
SEL selector = NSSelectorFromString(base::SysUTF8ToNSString(action));
|
||||
[NSApp sendAction:selector to:nil from:[NSApp mainMenu]];
|
||||
}
|
||||
|
||||
// static
|
||||
mate::WrappableBase* Menu::New(mate::Arguments* args) {
|
||||
return new MenuMac(args->isolate(), args->GetThis());
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
63
atom/browser/api/atom_api_menu_views.cc
Normal file
63
atom/browser/api/atom_api_menu_views.cc
Normal file
@@ -0,0 +1,63 @@
|
||||
// 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_menu_views.h"
|
||||
|
||||
#include "atom/browser/native_window_views.h"
|
||||
#include "atom/browser/unresponsive_suppressor.h"
|
||||
#include "content/public/browser/render_widget_host_view.h"
|
||||
#include "ui/display/screen.h"
|
||||
#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) {
|
||||
}
|
||||
|
||||
void MenuViews::PopupAt(Window* window, int x, int y, int positioning_item) {
|
||||
NativeWindow* native_window = static_cast<NativeWindow*>(window->window());
|
||||
if (!native_window)
|
||||
return;
|
||||
content::WebContents* web_contents = native_window->web_contents();
|
||||
if (!web_contents)
|
||||
return;
|
||||
content::RenderWidgetHostView* view = web_contents->GetRenderWidgetHostView();
|
||||
if (!view)
|
||||
return;
|
||||
|
||||
// (-1, -1) means showing on mouse location.
|
||||
gfx::Point location;
|
||||
if (x == -1 || y == -1) {
|
||||
location = display::Screen::GetScreen()->GetCursorScreenPoint();
|
||||
} else {
|
||||
gfx::Point origin = view->GetViewBounds().origin();
|
||||
location = gfx::Point(origin.x() + x, origin.y() + y);
|
||||
}
|
||||
|
||||
// Don't emit unresponsive event when showing menu.
|
||||
atom::UnresponsiveSuppressor suppressor;
|
||||
|
||||
// Show the menu.
|
||||
views::MenuRunner menu_runner(
|
||||
model(),
|
||||
views::MenuRunner::CONTEXT_MENU | views::MenuRunner::HAS_MNEMONICS);
|
||||
ignore_result(menu_runner.RunMenuAt(
|
||||
static_cast<NativeWindowViews*>(window->window())->widget(),
|
||||
NULL,
|
||||
gfx::Rect(location, gfx::Size()),
|
||||
views::MENU_ANCHOR_TOPLEFT,
|
||||
ui::MENU_SOURCE_MOUSE));
|
||||
}
|
||||
|
||||
// static
|
||||
mate::WrappableBase* Menu::New(mate::Arguments* args) {
|
||||
return new MenuViews(args->isolate(), args->GetThis());
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
30
atom/browser/api/atom_api_menu_views.h
Normal file
30
atom/browser/api/atom_api_menu_views.h
Normal file
@@ -0,0 +1,30 @@
|
||||
// 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_MENU_VIEWS_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_MENU_VIEWS_H_
|
||||
|
||||
#include "atom/browser/api/atom_api_menu.h"
|
||||
#include "ui/display/screen.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class MenuViews : public Menu {
|
||||
public:
|
||||
MenuViews(v8::Isolate* isolate, v8::Local<v8::Object> wrapper);
|
||||
|
||||
protected:
|
||||
void PopupAt(Window* window, int x, int y, int positioning_item) override;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(MenuViews);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_MENU_VIEWS_H_
|
||||
61
atom/browser/api/atom_api_net.cc
Normal file
61
atom/browser/api/atom_api_net.cc
Normal file
@@ -0,0 +1,61 @@
|
||||
// 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_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_net, Initialize)
|
||||
35
atom/browser/api/atom_api_net.h
Normal file
35
atom/browser/api/atom_api_net.h
Normal file
@@ -0,0 +1,35 @@
|
||||
// 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_
|
||||
84
atom/browser/api/atom_api_power_monitor.cc
Normal file
84
atom/browser/api/atom_api_power_monitor.cc
Normal file
@@ -0,0 +1,84 @@
|
||||
// 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 "atom/browser/browser.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 atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
PowerMonitor::PowerMonitor(v8::Isolate* isolate) {
|
||||
base::PowerMonitor::Get()->AddObserver(this);
|
||||
Init(isolate);
|
||||
}
|
||||
|
||||
PowerMonitor::~PowerMonitor() {
|
||||
base::PowerMonitor::Get()->RemoveObserver(this);
|
||||
}
|
||||
|
||||
void PowerMonitor::OnPowerStateChange(bool on_battery_power) {
|
||||
if (on_battery_power)
|
||||
Emit("on-battery");
|
||||
else
|
||||
Emit("on-ac");
|
||||
}
|
||||
|
||||
void PowerMonitor::OnSuspend() {
|
||||
Emit("suspend");
|
||||
}
|
||||
|
||||
void PowerMonitor::OnResume() {
|
||||
Emit("resume");
|
||||
}
|
||||
|
||||
// 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")));
|
||||
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"));
|
||||
}
|
||||
|
||||
} // 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
|
||||
|
||||
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_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_power_monitor, Initialize)
|
||||
42
atom/browser/api/atom_api_power_monitor.h
Normal file
42
atom/browser/api/atom_api_power_monitor.h
Normal file
@@ -0,0 +1,42 @@
|
||||
// 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_POWER_MONITOR_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_POWER_MONITOR_H_
|
||||
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "base/compiler_specific.h"
|
||||
#include "base/power_monitor/power_observer.h"
|
||||
#include "native_mate/handle.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class PowerMonitor : public mate::TrackableObject<PowerMonitor>,
|
||||
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() override;
|
||||
|
||||
// base::PowerObserver implementations:
|
||||
void OnPowerStateChange(bool on_battery_power) override;
|
||||
void OnSuspend() override;
|
||||
void OnResume() override;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(PowerMonitor);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_POWER_MONITOR_H_
|
||||
136
atom/browser/api/atom_api_power_save_blocker.cc
Normal file
136
atom/browser/api/atom_api_power_save_blocker.cc
Normal file
@@ -0,0 +1,136 @@
|
||||
// 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_power_save_blocker.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace mate {
|
||||
|
||||
template<>
|
||||
struct Converter<device::PowerSaveBlocker::PowerSaveBlockerType> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
device::PowerSaveBlocker::PowerSaveBlockerType* out) {
|
||||
using device::PowerSaveBlocker;
|
||||
std::string type;
|
||||
if (!ConvertFromV8(isolate, val, &type))
|
||||
return false;
|
||||
if (type == "prevent-app-suspension")
|
||||
*out = PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension;
|
||||
else if (type == "prevent-display-sleep")
|
||||
*out = PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep;
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
PowerSaveBlocker::PowerSaveBlocker(v8::Isolate* isolate)
|
||||
: current_blocker_type_(
|
||||
device::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension) {
|
||||
Init(isolate);
|
||||
}
|
||||
|
||||
PowerSaveBlocker::~PowerSaveBlocker() {
|
||||
}
|
||||
|
||||
void PowerSaveBlocker::UpdatePowerSaveBlocker() {
|
||||
if (power_save_blocker_types_.empty()) {
|
||||
power_save_blocker_.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
// |kPowerSaveBlockPreventAppSuspension| keeps system active, but allows
|
||||
// screen to be turned off.
|
||||
// |kPowerSaveBlockPreventDisplaySleep| keeps system and screen active, has a
|
||||
// higher precedence level than |kPowerSaveBlockPreventAppSuspension|.
|
||||
//
|
||||
// Only the highest-precedence blocker type takes effect.
|
||||
device::PowerSaveBlocker::PowerSaveBlockerType new_blocker_type =
|
||||
device::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension;
|
||||
for (const auto& element : power_save_blocker_types_) {
|
||||
if (element.second ==
|
||||
device::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep) {
|
||||
new_blocker_type =
|
||||
device::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!power_save_blocker_ || new_blocker_type != current_blocker_type_) {
|
||||
std::unique_ptr<device::PowerSaveBlocker> new_blocker(
|
||||
new device::PowerSaveBlocker(
|
||||
new_blocker_type,
|
||||
device::PowerSaveBlocker::kReasonOther,
|
||||
ATOM_PRODUCT_NAME,
|
||||
content::BrowserThread::GetMessageLoopProxyForThread(
|
||||
content::BrowserThread::UI),
|
||||
content::BrowserThread::GetMessageLoopProxyForThread(
|
||||
content::BrowserThread::FILE)));
|
||||
power_save_blocker_.swap(new_blocker);
|
||||
current_blocker_type_ = new_blocker_type;
|
||||
}
|
||||
}
|
||||
|
||||
int PowerSaveBlocker::Start(
|
||||
device::PowerSaveBlocker::PowerSaveBlockerType type) {
|
||||
static int count = 0;
|
||||
power_save_blocker_types_[count] = type;
|
||||
UpdatePowerSaveBlocker();
|
||||
return count++;
|
||||
}
|
||||
|
||||
bool PowerSaveBlocker::Stop(int id) {
|
||||
bool success = power_save_blocker_types_.erase(id) > 0;
|
||||
UpdatePowerSaveBlocker();
|
||||
return success;
|
||||
}
|
||||
|
||||
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())
|
||||
.SetMethod("start", &PowerSaveBlocker::Start)
|
||||
.SetMethod("stop", &PowerSaveBlocker::Stop)
|
||||
.SetMethod("isStarted", &PowerSaveBlocker::IsStarted);
|
||||
}
|
||||
|
||||
} // 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("powerSaveBlocker", atom::api::PowerSaveBlocker::Create(isolate));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_power_save_blocker, Initialize);
|
||||
57
atom/browser/api/atom_api_power_save_blocker.h
Normal file
57
atom/browser/api/atom_api_power_save_blocker.h
Normal file
@@ -0,0 +1,57 @@
|
||||
// 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_POWER_SAVE_BLOCKER_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_POWER_SAVE_BLOCKER_H_
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "device/power_save_blocker/power_save_blocker.h"
|
||||
#include "native_mate/handle.h"
|
||||
|
||||
namespace mate {
|
||||
class Dictionary;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
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() override;
|
||||
|
||||
private:
|
||||
void UpdatePowerSaveBlocker();
|
||||
int Start(device::PowerSaveBlocker::PowerSaveBlockerType type);
|
||||
bool Stop(int id);
|
||||
bool IsStarted(int id);
|
||||
|
||||
std::unique_ptr<device::PowerSaveBlocker> power_save_blocker_;
|
||||
|
||||
// Currnet blocker type used by |power_save_blocker_|
|
||||
device::PowerSaveBlocker::PowerSaveBlockerType current_blocker_type_;
|
||||
|
||||
// Map from id to the corresponding blocker type for each request.
|
||||
using PowerSaveBlockerTypeMap =
|
||||
std::map<int, device::PowerSaveBlocker::PowerSaveBlockerType>;
|
||||
PowerSaveBlockerTypeMap power_save_blocker_types_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PowerSaveBlocker);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_POWER_SAVE_BLOCKER_H_
|
||||
246
atom/browser/api/atom_api_protocol.cc
Normal file
246
atom/browser/api/atom_api_protocol.cc
Normal file
@@ -0,0 +1,246 @@
|
||||
// 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_protocol.h"
|
||||
|
||||
#include "atom/browser/atom_browser_client.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_string_job.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "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;
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
namespace {
|
||||
|
||||
// List of registered custom standard schemes.
|
||||
std::vector<std::string> g_standard_schemes;
|
||||
|
||||
// Clear protocol handlers in IO thread.
|
||||
void ClearJobFactoryInIO(
|
||||
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter) {
|
||||
auto job_factory = static_cast<AtomURLRequestJobFactory*>(
|
||||
request_context_getter->job_factory());
|
||||
job_factory->Clear();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::vector<std::string> GetStandardSchemes() {
|
||||
return g_standard_schemes;
|
||||
}
|
||||
|
||||
void RegisterStandardSchemes(const std::vector<std::string>& schemes,
|
||||
mate::Arguments* args) {
|
||||
g_standard_schemes = schemes;
|
||||
|
||||
auto* policy = content::ChildProcessSecurityPolicy::GetInstance();
|
||||
for (const std::string& scheme : schemes) {
|
||||
url::AddStandardScheme(scheme.c_str(), url::SCHEME_WITHOUT_PORT);
|
||||
policy->RegisterWebSafeScheme(scheme);
|
||||
}
|
||||
|
||||
// add switches to register as standard
|
||||
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
|
||||
atom::switches::kStandardSchemes, base::JoinString(schemes, ","));
|
||||
|
||||
mate::Dictionary opts;
|
||||
bool secure = false;
|
||||
if (args->GetNext(&opts) && opts.Get("secure", &secure) && secure) {
|
||||
// add switches to register as secure
|
||||
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
|
||||
atom::switches::kSecureSchemes, base::JoinString(schemes, ","));
|
||||
}
|
||||
}
|
||||
|
||||
Protocol::Protocol(v8::Isolate* isolate, AtomBrowserContext* browser_context)
|
||||
: request_context_getter_(browser_context->GetRequestContext()),
|
||||
weak_factory_(this) {
|
||||
Init(isolate);
|
||||
}
|
||||
|
||||
Protocol::~Protocol() {
|
||||
content::BrowserThread::PostTask(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(ClearJobFactoryInIO, request_context_getter_));
|
||||
}
|
||||
|
||||
void Protocol::RegisterServiceWorkerSchemes(
|
||||
const std::vector<std::string>& schemes) {
|
||||
atom::AtomBrowserClient::SetCustomServiceWorkerSchemes(schemes);
|
||||
}
|
||||
|
||||
void Protocol::UnregisterProtocol(
|
||||
const std::string& scheme, mate::Arguments* args) {
|
||||
CompletionCallback callback;
|
||||
args->GetNext(&callback);
|
||||
content::BrowserThread::PostTaskAndReplyWithResult(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&Protocol::UnregisterProtocolInIO,
|
||||
request_context_getter_, scheme),
|
||||
base::Bind(&Protocol::OnIOCompleted,
|
||||
GetWeakPtr(), callback));
|
||||
}
|
||||
|
||||
// static
|
||||
Protocol::ProtocolError Protocol::UnregisterProtocolInIO(
|
||||
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter,
|
||||
const std::string& scheme) {
|
||||
auto job_factory = static_cast<AtomURLRequestJobFactory*>(
|
||||
request_context_getter->job_factory());
|
||||
if (!job_factory->HasProtocolHandler(scheme))
|
||||
return PROTOCOL_NOT_REGISTERED;
|
||||
job_factory->SetProtocolHandler(scheme, nullptr);
|
||||
return PROTOCOL_OK;
|
||||
}
|
||||
|
||||
void Protocol::IsProtocolHandled(const std::string& scheme,
|
||||
const BooleanCallback& callback) {
|
||||
content::BrowserThread::PostTaskAndReplyWithResult(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&Protocol::IsProtocolHandledInIO,
|
||||
request_context_getter_, scheme),
|
||||
callback);
|
||||
}
|
||||
|
||||
// static
|
||||
bool Protocol::IsProtocolHandledInIO(
|
||||
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter,
|
||||
const std::string& scheme) {
|
||||
return request_context_getter->job_factory()->IsHandledProtocol(scheme);
|
||||
}
|
||||
|
||||
void Protocol::UninterceptProtocol(
|
||||
const std::string& scheme, mate::Arguments* args) {
|
||||
CompletionCallback callback;
|
||||
args->GetNext(&callback);
|
||||
content::BrowserThread::PostTaskAndReplyWithResult(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&Protocol::UninterceptProtocolInIO,
|
||||
request_context_getter_, scheme),
|
||||
base::Bind(&Protocol::OnIOCompleted,
|
||||
GetWeakPtr(), callback));
|
||||
}
|
||||
|
||||
// static
|
||||
Protocol::ProtocolError Protocol::UninterceptProtocolInIO(
|
||||
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter,
|
||||
const std::string& scheme) {
|
||||
return static_cast<AtomURLRequestJobFactory*>(
|
||||
request_context_getter->job_factory())->UninterceptProtocol(scheme) ?
|
||||
PROTOCOL_OK : PROTOCOL_NOT_INTERCEPTED;
|
||||
}
|
||||
|
||||
void Protocol::OnIOCompleted(
|
||||
const CompletionCallback& callback, ProtocolError error) {
|
||||
// The completion callback is optional.
|
||||
if (callback.is_null())
|
||||
return;
|
||||
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
|
||||
if (error == PROTOCOL_OK) {
|
||||
callback.Run(v8::Null(isolate()));
|
||||
} else {
|
||||
std::string str = ErrorCodeToString(error);
|
||||
callback.Run(v8::Exception::Error(mate::StringToV8(isolate(), str)));
|
||||
}
|
||||
}
|
||||
|
||||
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";
|
||||
}
|
||||
}
|
||||
|
||||
AtomURLRequestJobFactory* Protocol::GetJobFactoryInIO() const {
|
||||
request_context_getter_->GetURLRequestContext(); // Force init.
|
||||
return static_cast<AtomURLRequestJobFactory*>(
|
||||
static_cast<brightray::URLRequestContextGetter*>(
|
||||
request_context_getter_.get())->job_factory());
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<Protocol> Protocol::Create(
|
||||
v8::Isolate* isolate, AtomBrowserContext* browser_context) {
|
||||
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("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);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
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) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.SetMethod("registerStandardSchemes", &RegisterStandardSchemes);
|
||||
dict.SetMethod("getStandardSchemes", &atom::api::GetStandardSchemes);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_protocol, Initialize)
|
||||
206
atom/browser/api/atom_api_protocol.h
Normal file
206
atom/browser/api/atom_api_protocol.h
Normal file
@@ -0,0 +1,206 @@
|
||||
// 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_PROTOCOL_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_PROTOCOL_H_
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#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 "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"
|
||||
|
||||
namespace base {
|
||||
class DictionaryValue;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
std::vector<std::string> GetStandardSchemes();
|
||||
void RegisterStandardSchemes(const std::vector<std::string>& schemes,
|
||||
mate::Arguments* args);
|
||||
|
||||
class Protocol : public mate::TrackableObject<Protocol> {
|
||||
public:
|
||||
using Handler =
|
||||
base::Callback<void(const base::DictionaryValue&, 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);
|
||||
|
||||
protected:
|
||||
Protocol(v8::Isolate* isolate, AtomBrowserContext* browser_context);
|
||||
~Protocol();
|
||||
|
||||
private:
|
||||
// Possible errors.
|
||||
enum ProtocolError {
|
||||
PROTOCOL_OK, // no error
|
||||
PROTOCOL_FAIL, // operation failed, should never occur
|
||||
PROTOCOL_REGISTERED,
|
||||
PROTOCOL_NOT_REGISTERED,
|
||||
PROTOCOL_INTERCEPTED,
|
||||
PROTOCOL_NOT_INTERCEPTED,
|
||||
};
|
||||
|
||||
// The protocol handler that will create a protocol handler for certain
|
||||
// request job.
|
||||
template<typename RequestJob>
|
||||
class CustomProtocolHandler
|
||||
: public net::URLRequestJobFactory::ProtocolHandler {
|
||||
public:
|
||||
CustomProtocolHandler(
|
||||
v8::Isolate* isolate,
|
||||
net::URLRequestContextGetter* request_context,
|
||||
const Handler& handler)
|
||||
: isolate_(isolate),
|
||||
request_context_(request_context),
|
||||
handler_(handler) {}
|
||||
~CustomProtocolHandler() override {}
|
||||
|
||||
net::URLRequestJob* MaybeCreateJob(
|
||||
net::URLRequest* request,
|
||||
net::NetworkDelegate* network_delegate) const override {
|
||||
RequestJob* request_job = new RequestJob(request, network_delegate);
|
||||
request_job->SetHandlerInfo(isolate_, request_context_.get(), handler_);
|
||||
return request_job;
|
||||
}
|
||||
|
||||
private:
|
||||
v8::Isolate* isolate_;
|
||||
scoped_refptr<net::URLRequestContextGetter> request_context_;
|
||||
Protocol::Handler handler_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CustomProtocolHandler);
|
||||
};
|
||||
|
||||
// Register schemes that can handle service worker.
|
||||
void RegisterServiceWorkerSchemes(const std::vector<std::string>& schemes);
|
||||
|
||||
// Register the protocol with certain request job.
|
||||
template<typename RequestJob>
|
||||
void RegisterProtocol(const std::string& scheme,
|
||||
const Handler& handler,
|
||||
mate::Arguments* args) {
|
||||
CompletionCallback callback;
|
||||
args->GetNext(&callback);
|
||||
content::BrowserThread::PostTaskAndReplyWithResult(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&Protocol::RegisterProtocolInIO<RequestJob>,
|
||||
request_context_getter_, isolate(), scheme, handler),
|
||||
base::Bind(&Protocol::OnIOCompleted,
|
||||
GetWeakPtr(), callback));
|
||||
}
|
||||
template<typename RequestJob>
|
||||
static ProtocolError RegisterProtocolInIO(
|
||||
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter,
|
||||
v8::Isolate* isolate,
|
||||
const std::string& scheme,
|
||||
const Handler& handler) {
|
||||
auto job_factory = static_cast<AtomURLRequestJobFactory*>(
|
||||
request_context_getter->job_factory());
|
||||
if (job_factory->IsHandledProtocol(scheme))
|
||||
return PROTOCOL_REGISTERED;
|
||||
std::unique_ptr<CustomProtocolHandler<RequestJob>> protocol_handler(
|
||||
new CustomProtocolHandler<RequestJob>(
|
||||
isolate, request_context_getter.get(), handler));
|
||||
if (job_factory->SetProtocolHandler(scheme, std::move(protocol_handler)))
|
||||
return PROTOCOL_OK;
|
||||
else
|
||||
return PROTOCOL_FAIL;
|
||||
}
|
||||
|
||||
// Unregister the protocol handler that handles |scheme|.
|
||||
void UnregisterProtocol(const std::string& scheme, mate::Arguments* args);
|
||||
static ProtocolError UnregisterProtocolInIO(
|
||||
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter,
|
||||
const std::string& scheme);
|
||||
|
||||
// Whether the protocol has handler registered.
|
||||
void IsProtocolHandled(const std::string& scheme,
|
||||
const BooleanCallback& callback);
|
||||
static bool IsProtocolHandledInIO(
|
||||
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter,
|
||||
const std::string& scheme);
|
||||
|
||||
// Replace the protocol handler with a new one.
|
||||
template<typename RequestJob>
|
||||
void InterceptProtocol(const std::string& scheme,
|
||||
const Handler& handler,
|
||||
mate::Arguments* args) {
|
||||
CompletionCallback callback;
|
||||
args->GetNext(&callback);
|
||||
content::BrowserThread::PostTaskAndReplyWithResult(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&Protocol::InterceptProtocolInIO<RequestJob>,
|
||||
request_context_getter_, isolate(), scheme, handler),
|
||||
base::Bind(&Protocol::OnIOCompleted,
|
||||
GetWeakPtr(), callback));
|
||||
}
|
||||
template<typename RequestJob>
|
||||
static ProtocolError InterceptProtocolInIO(
|
||||
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter,
|
||||
v8::Isolate* isolate,
|
||||
const std::string& scheme,
|
||||
const Handler& handler) {
|
||||
auto job_factory = static_cast<AtomURLRequestJobFactory*>(
|
||||
request_context_getter->job_factory());
|
||||
if (!job_factory->IsHandledProtocol(scheme))
|
||||
return PROTOCOL_NOT_REGISTERED;
|
||||
// It is possible a protocol is handled but can not be intercepted.
|
||||
if (!job_factory->HasProtocolHandler(scheme))
|
||||
return PROTOCOL_FAIL;
|
||||
std::unique_ptr<CustomProtocolHandler<RequestJob>> protocol_handler(
|
||||
new CustomProtocolHandler<RequestJob>(
|
||||
isolate, request_context_getter.get(), handler));
|
||||
if (!job_factory->InterceptProtocol(scheme, std::move(protocol_handler)))
|
||||
return PROTOCOL_INTERCEPTED;
|
||||
return PROTOCOL_OK;
|
||||
}
|
||||
|
||||
// Restore the |scheme| to its original protocol handler.
|
||||
void UninterceptProtocol(const std::string& scheme, mate::Arguments* args);
|
||||
static ProtocolError UninterceptProtocolInIO(
|
||||
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter,
|
||||
const std::string& scheme);
|
||||
|
||||
// Convert error code to JS exception and call the callback.
|
||||
void OnIOCompleted(const CompletionCallback& callback, ProtocolError error);
|
||||
|
||||
// Convert error code to string.
|
||||
std::string ErrorCodeToString(ProtocolError error);
|
||||
|
||||
AtomURLRequestJobFactory* GetJobFactoryInIO() const;
|
||||
|
||||
base::WeakPtr<Protocol> GetWeakPtr() {
|
||||
return weak_factory_.GetWeakPtr();
|
||||
}
|
||||
|
||||
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter_;
|
||||
base::WeakPtrFactory<Protocol> weak_factory_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Protocol);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_PROTOCOL_H_
|
||||
90
atom/browser/api/atom_api_render_process_preferences.cc
Normal file
90
atom/browser/api/atom_api_render_process_preferences.cc
Normal file
@@ -0,0 +1,90 @@
|
||||
// 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_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_render_process_preferences,
|
||||
Initialize)
|
||||
44
atom/browser/api/atom_api_render_process_preferences.h
Normal file
44
atom/browser/api/atom_api_render_process_preferences.h
Normal file
@@ -0,0 +1,44 @@
|
||||
// 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_RENDER_PROCESS_PREFERENCES_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_RENDER_PROCESS_PREFERENCES_H_
|
||||
|
||||
#include "atom/browser/render_process_preferences.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "native_mate/wrappable.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class RenderProcessPreferences
|
||||
: public mate::Wrappable<RenderProcessPreferences> {
|
||||
public:
|
||||
static mate::Handle<RenderProcessPreferences>
|
||||
ForAllWebContents(v8::Isolate* isolate);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
int AddEntry(const base::DictionaryValue& entry);
|
||||
void RemoveEntry(int id);
|
||||
|
||||
protected:
|
||||
RenderProcessPreferences(
|
||||
v8::Isolate* isolate,
|
||||
const atom::RenderProcessPreferences::Predicate& predicate);
|
||||
~RenderProcessPreferences() override;
|
||||
|
||||
private:
|
||||
atom::RenderProcessPreferences preferences_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(RenderProcessPreferences);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_RENDER_PROCESS_PREFERENCES_H_
|
||||
144
atom/browser/api/atom_api_screen.cc
Normal file
144
atom/browser/api/atom_api_screen.cc
Normal file
@@ -0,0 +1,144 @@
|
||||
// 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_screen.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/common/native_mate_converters/gfx_converter.h"
|
||||
#include "base/bind.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/object_template_builder.h"
|
||||
#include "ui/display/display.h"
|
||||
#include "ui/display/screen.h"
|
||||
#include "ui/gfx/geometry/point.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
namespace {
|
||||
|
||||
// Find an item in container according to its ID.
|
||||
template<class T>
|
||||
typename T::iterator FindById(T* container, int id) {
|
||||
auto predicate = [id] (const typename T::value_type& item) -> bool {
|
||||
return item.id() == id;
|
||||
};
|
||||
return std::find_if(container->begin(), container->end(), predicate);
|
||||
}
|
||||
|
||||
// Convert the changed_metrics bitmask to string array.
|
||||
std::vector<std::string> MetricsToArray(uint32_t metrics) {
|
||||
std::vector<std::string> array;
|
||||
if (metrics & display::DisplayObserver::DISPLAY_METRIC_BOUNDS)
|
||||
array.push_back("bounds");
|
||||
if (metrics & display::DisplayObserver::DISPLAY_METRIC_WORK_AREA)
|
||||
array.push_back("workArea");
|
||||
if (metrics & display::DisplayObserver::DISPLAY_METRIC_DEVICE_SCALE_FACTOR)
|
||||
array.push_back("scaleFactor");
|
||||
if (metrics & display::DisplayObserver::DISPLAY_METRIC_ROTATION)
|
||||
array.push_back("rotation");
|
||||
return array;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Screen::Screen(v8::Isolate* isolate, display::Screen* screen)
|
||||
: screen_(screen) {
|
||||
screen_->AddObserver(this);
|
||||
Init(isolate);
|
||||
}
|
||||
|
||||
Screen::~Screen() {
|
||||
screen_->RemoveObserver(this);
|
||||
}
|
||||
|
||||
gfx::Point Screen::GetCursorScreenPoint() {
|
||||
return screen_->GetCursorScreenPoint();
|
||||
}
|
||||
|
||||
display::Display Screen::GetPrimaryDisplay() {
|
||||
return screen_->GetPrimaryDisplay();
|
||||
}
|
||||
|
||||
std::vector<display::Display> Screen::GetAllDisplays() {
|
||||
return screen_->GetAllDisplays();
|
||||
}
|
||||
|
||||
display::Display Screen::GetDisplayNearestPoint(const gfx::Point& point) {
|
||||
return screen_->GetDisplayNearestPoint(point);
|
||||
}
|
||||
|
||||
display::Display Screen::GetDisplayMatching(const gfx::Rect& match_rect) {
|
||||
return screen_->GetDisplayMatching(match_rect);
|
||||
}
|
||||
|
||||
void Screen::OnDisplayAdded(const display::Display& new_display) {
|
||||
Emit("display-added", new_display);
|
||||
}
|
||||
|
||||
void Screen::OnDisplayRemoved(const display::Display& old_display) {
|
||||
Emit("display-removed", old_display);
|
||||
}
|
||||
|
||||
void Screen::OnDisplayMetricsChanged(const display::Display& display,
|
||||
uint32_t changed_metrics) {
|
||||
Emit("display-metrics-changed", display, MetricsToArray(changed_metrics));
|
||||
}
|
||||
|
||||
// static
|
||||
v8::Local<v8::Value> Screen::Create(v8::Isolate* isolate) {
|
||||
if (!Browser::Get()->is_ready()) {
|
||||
isolate->ThrowException(v8::Exception::Error(mate::StringToV8(
|
||||
isolate,
|
||||
"Cannot require \"screen\" module before app is ready")));
|
||||
return v8::Null(isolate);
|
||||
}
|
||||
|
||||
display::Screen* screen = display::Screen::GetScreen();
|
||||
if (!screen) {
|
||||
isolate->ThrowException(v8::Exception::Error(mate::StringToV8(
|
||||
isolate, "Failed to get screen information")));
|
||||
return v8::Null(isolate);
|
||||
}
|
||||
|
||||
return mate::CreateHandle(isolate, new Screen(isolate, screen)).ToV8();
|
||||
}
|
||||
|
||||
// static
|
||||
void Screen::BuildPrototype(
|
||||
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "Screen"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetMethod("getCursorScreenPoint", &Screen::GetCursorScreenPoint)
|
||||
.SetMethod("getPrimaryDisplay", &Screen::GetPrimaryDisplay)
|
||||
.SetMethod("getAllDisplays", &Screen::GetAllDisplays)
|
||||
.SetMethod("getDisplayNearestPoint", &Screen::GetDisplayNearestPoint)
|
||||
.SetMethod("getDisplayMatching", &Screen::GetDisplayMatching);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
namespace {
|
||||
|
||||
using atom::api::Screen;
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("screen", Screen::Create(isolate));
|
||||
dict.Set("Screen", Screen::GetConstructor(isolate)->GetFunction());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_common_screen, Initialize)
|
||||
59
atom/browser/api/atom_api_screen.h
Normal file
59
atom/browser/api/atom_api_screen.h
Normal file
@@ -0,0 +1,59 @@
|
||||
// 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_SCREEN_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_SCREEN_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "atom/browser/api/event_emitter.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "ui/display/display_observer.h"
|
||||
#include "ui/display/screen.h"
|
||||
|
||||
namespace gfx {
|
||||
class Point;
|
||||
class Rect;
|
||||
class Screen;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class Screen : public mate::EventEmitter<Screen>,
|
||||
public display::DisplayObserver {
|
||||
public:
|
||||
static v8::Local<v8::Value> Create(v8::Isolate* isolate);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
protected:
|
||||
Screen(v8::Isolate* isolate, display::Screen* screen);
|
||||
~Screen() override;
|
||||
|
||||
gfx::Point GetCursorScreenPoint();
|
||||
display::Display GetPrimaryDisplay();
|
||||
std::vector<display::Display> GetAllDisplays();
|
||||
display::Display GetDisplayNearestPoint(const gfx::Point& point);
|
||||
display::Display GetDisplayMatching(const gfx::Rect& match_rect);
|
||||
|
||||
// display::DisplayObserver:
|
||||
void OnDisplayAdded(const display::Display& new_display) override;
|
||||
void OnDisplayRemoved(const display::Display& old_display) override;
|
||||
void OnDisplayMetricsChanged(const display::Display& display,
|
||||
uint32_t changed_metrics) override;
|
||||
|
||||
private:
|
||||
display::Screen* screen_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Screen);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_SCREEN_H_
|
||||
785
atom/browser/api/atom_api_session.cc
Normal file
785
atom/browser/api/atom_api_session.cc
Normal file
@@ -0,0 +1,785 @@
|
||||
// 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_session.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/browser/api/atom_api_cookies.h"
|
||||
#include "atom/browser/api/atom_api_download_item.h"
|
||||
#include "atom/browser/api/atom_api_protocol.h"
|
||||
#include "atom/browser/api/atom_api_web_request.h"
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/atom_browser_main_parts.h"
|
||||
#include "atom/browser/atom_permission_manager.h"
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/browser/net/atom_cert_verifier.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/content_converter.h"
|
||||
#include "atom/common/native_mate_converters/file_path_converter.h"
|
||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||
#include "atom/common/native_mate_converters/net_converter.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/guid.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "base/threading/thread_task_runner_handle.h"
|
||||
#include "brightray/browser/media/media_device_id_salt.h"
|
||||
#include "brightray/browser/net/devtools_network_conditions.h"
|
||||
#include "brightray/browser/net/devtools_network_controller_handle.h"
|
||||
#include "chrome/common/pref_names.h"
|
||||
#include "components/prefs/pref_service.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/download_manager_delegate.h"
|
||||
#include "content/public/browser/storage_partition.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/object_template_builder.h"
|
||||
#include "net/base/load_flags.h"
|
||||
#include "net/disk_cache/disk_cache.h"
|
||||
#include "net/dns/host_cache.h"
|
||||
#include "net/http/http_auth_handler_factory.h"
|
||||
#include "net/http/http_auth_preferences.h"
|
||||
#include "net/proxy/proxy_config_service_fixed.h"
|
||||
#include "net/proxy/proxy_service.h"
|
||||
#include "net/url_request/static_http_user_agent_settings.h"
|
||||
#include "net/url_request/url_request_context.h"
|
||||
#include "net/url_request/url_request_context_getter.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
|
||||
using atom::api::Cookies;
|
||||
using content::BrowserThread;
|
||||
using content::StoragePartition;
|
||||
|
||||
namespace {
|
||||
|
||||
struct ClearStorageDataOptions {
|
||||
GURL origin;
|
||||
uint32_t storage_types = StoragePartition::REMOVE_DATA_MASK_ALL;
|
||||
uint32_t quota_types = StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL;
|
||||
};
|
||||
|
||||
struct ClearAuthCacheOptions {
|
||||
std::string type;
|
||||
GURL origin;
|
||||
std::string realm;
|
||||
base::string16 username;
|
||||
base::string16 password;
|
||||
net::HttpAuth::Scheme auth_scheme;
|
||||
};
|
||||
|
||||
uint32_t GetStorageMask(const std::vector<std::string>& storage_types) {
|
||||
uint32_t storage_mask = 0;
|
||||
for (const auto& it : storage_types) {
|
||||
auto type = base::ToLowerASCII(it);
|
||||
if (type == "appcache")
|
||||
storage_mask |= StoragePartition::REMOVE_DATA_MASK_APPCACHE;
|
||||
else if (type == "cookies")
|
||||
storage_mask |= StoragePartition::REMOVE_DATA_MASK_COOKIES;
|
||||
else if (type == "filesystem")
|
||||
storage_mask |= StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS;
|
||||
else if (type == "indexdb")
|
||||
storage_mask |= StoragePartition::REMOVE_DATA_MASK_INDEXEDDB;
|
||||
else if (type == "localstorage")
|
||||
storage_mask |= StoragePartition::REMOVE_DATA_MASK_LOCAL_STORAGE;
|
||||
else if (type == "shadercache")
|
||||
storage_mask |= StoragePartition::REMOVE_DATA_MASK_SHADER_CACHE;
|
||||
else if (type == "websql")
|
||||
storage_mask |= StoragePartition::REMOVE_DATA_MASK_WEBSQL;
|
||||
else if (type == "serviceworkers")
|
||||
storage_mask |= StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS;
|
||||
}
|
||||
return storage_mask;
|
||||
}
|
||||
|
||||
uint32_t GetQuotaMask(const std::vector<std::string>& quota_types) {
|
||||
uint32_t quota_mask = 0;
|
||||
for (const auto& it : quota_types) {
|
||||
auto type = base::ToLowerASCII(it);
|
||||
if (type == "temporary")
|
||||
quota_mask |= StoragePartition::QUOTA_MANAGED_STORAGE_MASK_TEMPORARY;
|
||||
else if (type == "persistent")
|
||||
quota_mask |= StoragePartition::QUOTA_MANAGED_STORAGE_MASK_PERSISTENT;
|
||||
else if (type == "syncable")
|
||||
quota_mask |= StoragePartition::QUOTA_MANAGED_STORAGE_MASK_SYNCABLE;
|
||||
}
|
||||
return quota_mask;
|
||||
}
|
||||
|
||||
net::HttpAuth::Scheme GetAuthSchemeFromString(const std::string& scheme) {
|
||||
if (scheme == "basic")
|
||||
return net::HttpAuth::AUTH_SCHEME_BASIC;
|
||||
if (scheme == "digest")
|
||||
return net::HttpAuth::AUTH_SCHEME_DIGEST;
|
||||
if (scheme == "ntlm")
|
||||
return net::HttpAuth::AUTH_SCHEME_NTLM;
|
||||
if (scheme == "negotiate")
|
||||
return net::HttpAuth::AUTH_SCHEME_NEGOTIATE;
|
||||
return net::HttpAuth::AUTH_SCHEME_MAX;
|
||||
}
|
||||
|
||||
void SetUserAgentInIO(scoped_refptr<net::URLRequestContextGetter> getter,
|
||||
const std::string& accept_lang,
|
||||
const std::string& user_agent) {
|
||||
getter->GetURLRequestContext()->set_http_user_agent_settings(
|
||||
new net::StaticHttpUserAgentSettings(
|
||||
net::HttpUtil::GenerateAcceptLanguageHeader(accept_lang),
|
||||
user_agent));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace mate {
|
||||
|
||||
template<>
|
||||
struct Converter<ClearStorageDataOptions> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
ClearStorageDataOptions* out) {
|
||||
mate::Dictionary options;
|
||||
if (!ConvertFromV8(isolate, val, &options))
|
||||
return false;
|
||||
options.Get("origin", &out->origin);
|
||||
std::vector<std::string> types;
|
||||
if (options.Get("storages", &types))
|
||||
out->storage_types = GetStorageMask(types);
|
||||
if (options.Get("quotas", &types))
|
||||
out->quota_types = GetQuotaMask(types);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<ClearAuthCacheOptions> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
ClearAuthCacheOptions* out) {
|
||||
mate::Dictionary options;
|
||||
if (!ConvertFromV8(isolate, val, &options))
|
||||
return false;
|
||||
options.Get("type", &out->type);
|
||||
options.Get("origin", &out->origin);
|
||||
options.Get("realm", &out->realm);
|
||||
options.Get("username", &out->username);
|
||||
options.Get("password", &out->password);
|
||||
std::string scheme;
|
||||
if (options.Get("scheme", &scheme))
|
||||
out->auth_scheme = GetAuthSchemeFromString(scheme);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<net::ProxyConfig> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
net::ProxyConfig* out) {
|
||||
std::string proxy_rules, proxy_bypass_rules;
|
||||
GURL pac_url;
|
||||
mate::Dictionary options;
|
||||
// Fallback to previous API when passed String.
|
||||
// https://git.io/vuhjj
|
||||
if (ConvertFromV8(isolate, val, &proxy_rules)) {
|
||||
pac_url = GURL(proxy_rules); // Assume it is PAC script if it is URL.
|
||||
} else if (ConvertFromV8(isolate, val, &options)) {
|
||||
options.Get("pacScript", &pac_url);
|
||||
options.Get("proxyRules", &proxy_rules);
|
||||
options.Get("proxyBypassRules", &proxy_bypass_rules);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
// pacScript takes precedence over proxyRules.
|
||||
if (!pac_url.is_empty() && pac_url.is_valid()) {
|
||||
out->set_pac_url(pac_url);
|
||||
} else {
|
||||
out->proxy_rules().ParseFromString(proxy_rules);
|
||||
out->proxy_rules().bypass_rules.ParseFromString(proxy_bypass_rules);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
namespace {
|
||||
|
||||
const char kPersistPrefix[] = "persist:";
|
||||
|
||||
// Referenced session objects.
|
||||
std::map<uint32_t, v8::Global<v8::Object>> g_sessions;
|
||||
|
||||
class ResolveProxyHelper {
|
||||
public:
|
||||
ResolveProxyHelper(AtomBrowserContext* browser_context,
|
||||
const GURL& url,
|
||||
Session::ResolveProxyCallback callback)
|
||||
: callback_(callback),
|
||||
original_thread_(base::ThreadTaskRunnerHandle::Get()) {
|
||||
scoped_refptr<net::URLRequestContextGetter> context_getter =
|
||||
browser_context->url_request_context_getter();
|
||||
context_getter->GetNetworkTaskRunner()->PostTask(
|
||||
FROM_HERE,
|
||||
base::Bind(&ResolveProxyHelper::ResolveProxy,
|
||||
base::Unretained(this), context_getter, url));
|
||||
}
|
||||
|
||||
void OnResolveProxyCompleted(int result) {
|
||||
std::string proxy;
|
||||
if (result == net::OK)
|
||||
proxy = proxy_info_.ToPacString();
|
||||
original_thread_->PostTask(FROM_HERE,
|
||||
base::Bind(callback_, proxy));
|
||||
delete this;
|
||||
}
|
||||
|
||||
private:
|
||||
void ResolveProxy(scoped_refptr<net::URLRequestContextGetter> context_getter,
|
||||
const GURL& url) {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
||||
|
||||
net::ProxyService* proxy_service =
|
||||
context_getter->GetURLRequestContext()->proxy_service();
|
||||
net::CompletionCallback completion_callback =
|
||||
base::Bind(&ResolveProxyHelper::OnResolveProxyCompleted,
|
||||
base::Unretained(this));
|
||||
|
||||
// Start the request.
|
||||
int result = proxy_service->ResolveProxy(
|
||||
url, "GET", net::LOAD_NORMAL, &proxy_info_, completion_callback,
|
||||
&pac_req_, nullptr, net::BoundNetLog());
|
||||
|
||||
// Completed synchronously.
|
||||
if (result != net::ERR_IO_PENDING)
|
||||
completion_callback.Run(result);
|
||||
}
|
||||
|
||||
Session::ResolveProxyCallback callback_;
|
||||
net::ProxyInfo proxy_info_;
|
||||
net::ProxyService::PacRequest* pac_req_;
|
||||
scoped_refptr<base::SingleThreadTaskRunner> original_thread_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ResolveProxyHelper);
|
||||
};
|
||||
|
||||
// Runs the callback in UI thread.
|
||||
template<typename ...T>
|
||||
void RunCallbackInUI(const base::Callback<void(T...)>& callback, T... result) {
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::UI, FROM_HERE, base::Bind(callback, result...));
|
||||
}
|
||||
|
||||
// Callback of HttpCache::GetBackend.
|
||||
void OnGetBackend(disk_cache::Backend** backend_ptr,
|
||||
Session::CacheAction action,
|
||||
const net::CompletionCallback& callback,
|
||||
int result) {
|
||||
if (result != net::OK) {
|
||||
RunCallbackInUI(callback, result);
|
||||
} else if (backend_ptr && *backend_ptr) {
|
||||
if (action == Session::CacheAction::CLEAR) {
|
||||
(*backend_ptr)->DoomAllEntries(base::Bind(&RunCallbackInUI<int>,
|
||||
callback));
|
||||
} else if (action == Session::CacheAction::STATS) {
|
||||
base::StringPairs stats;
|
||||
(*backend_ptr)->GetStats(&stats);
|
||||
for (const auto& stat : stats) {
|
||||
if (stat.first == "Current size") {
|
||||
int current_size;
|
||||
base::StringToInt(stat.second, ¤t_size);
|
||||
RunCallbackInUI(callback, current_size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
RunCallbackInUI<int>(callback, net::ERR_FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
void DoCacheActionInIO(
|
||||
const scoped_refptr<net::URLRequestContextGetter>& context_getter,
|
||||
Session::CacheAction action,
|
||||
const net::CompletionCallback& callback) {
|
||||
auto request_context = context_getter->GetURLRequestContext();
|
||||
auto http_cache = request_context->http_transaction_factory()->GetCache();
|
||||
if (!http_cache)
|
||||
RunCallbackInUI<int>(callback, net::ERR_FAILED);
|
||||
|
||||
// Call GetBackend and make the backend's ptr accessable in OnGetBackend.
|
||||
using BackendPtr = disk_cache::Backend*;
|
||||
auto* backend_ptr = new BackendPtr(nullptr);
|
||||
net::CompletionCallback on_get_backend =
|
||||
base::Bind(&OnGetBackend, base::Owned(backend_ptr), action, callback);
|
||||
int rv = http_cache->GetBackend(backend_ptr, on_get_backend);
|
||||
if (rv != net::ERR_IO_PENDING)
|
||||
on_get_backend.Run(net::OK);
|
||||
}
|
||||
|
||||
void SetProxyInIO(net::URLRequestContextGetter* getter,
|
||||
const net::ProxyConfig& config,
|
||||
const base::Closure& callback) {
|
||||
auto proxy_service = getter->GetURLRequestContext()->proxy_service();
|
||||
proxy_service->ResetConfigService(base::WrapUnique(
|
||||
new net::ProxyConfigServiceFixed(config)));
|
||||
// Refetches and applies the new pac script if provided.
|
||||
proxy_service->ForceReloadProxyConfig();
|
||||
RunCallbackInUI(callback);
|
||||
}
|
||||
|
||||
void SetCertVerifyProcInIO(
|
||||
const scoped_refptr<net::URLRequestContextGetter>& context_getter,
|
||||
const AtomCertVerifier::VerifyProc& proc) {
|
||||
auto request_context = context_getter->GetURLRequestContext();
|
||||
static_cast<AtomCertVerifier*>(request_context->cert_verifier())->
|
||||
SetVerifyProc(proc);
|
||||
}
|
||||
|
||||
void ClearHostResolverCacheInIO(
|
||||
const scoped_refptr<net::URLRequestContextGetter>& context_getter,
|
||||
const base::Closure& callback) {
|
||||
auto request_context = context_getter->GetURLRequestContext();
|
||||
auto cache = request_context->host_resolver()->GetHostCache();
|
||||
if (cache) {
|
||||
cache->clear();
|
||||
DCHECK_EQ(0u, cache->size());
|
||||
if (!callback.is_null())
|
||||
RunCallbackInUI(callback);
|
||||
}
|
||||
}
|
||||
|
||||
void ClearAuthCacheInIO(
|
||||
const scoped_refptr<net::URLRequestContextGetter>& context_getter,
|
||||
const ClearAuthCacheOptions& options,
|
||||
const base::Closure& callback) {
|
||||
auto request_context = context_getter->GetURLRequestContext();
|
||||
auto network_session =
|
||||
request_context->http_transaction_factory()->GetSession();
|
||||
if (network_session) {
|
||||
if (options.type == "password") {
|
||||
auto auth_cache = network_session->http_auth_cache();
|
||||
if (!options.origin.is_empty()) {
|
||||
auth_cache->Remove(
|
||||
options.origin, options.realm, options.auth_scheme,
|
||||
net::AuthCredentials(options.username, options.password));
|
||||
} else {
|
||||
auth_cache->Clear();
|
||||
}
|
||||
} else if (options.type == "clientCertificate") {
|
||||
auto client_auth_cache = network_session->ssl_client_auth_cache();
|
||||
client_auth_cache->Remove(net::HostPortPair::FromURL(options.origin));
|
||||
}
|
||||
network_session->CloseAllConnections();
|
||||
}
|
||||
if (!callback.is_null())
|
||||
RunCallbackInUI(callback);
|
||||
}
|
||||
|
||||
void AllowNTLMCredentialsForDomainsInIO(
|
||||
const scoped_refptr<net::URLRequestContextGetter>& context_getter,
|
||||
const std::string& domains) {
|
||||
auto request_context = context_getter->GetURLRequestContext();
|
||||
auto auth_handler = request_context->http_auth_handler_factory();
|
||||
if (auth_handler) {
|
||||
auto auth_preferences = const_cast<net::HttpAuthPreferences*>(
|
||||
auth_handler->http_auth_preferences());
|
||||
if (auth_preferences)
|
||||
auth_preferences->set_server_whitelist(domains);
|
||||
}
|
||||
}
|
||||
|
||||
void OnClearStorageDataDone(const base::Closure& callback) {
|
||||
if (!callback.is_null())
|
||||
callback.Run();
|
||||
}
|
||||
|
||||
void DownloadIdCallback(content::DownloadManager* download_manager,
|
||||
const base::FilePath& path,
|
||||
const std::vector<GURL>& url_chain,
|
||||
const std::string& mime_type,
|
||||
int64_t offset,
|
||||
int64_t length,
|
||||
const std::string& last_modified,
|
||||
const std::string& etag,
|
||||
const base::Time& start_time,
|
||||
uint32_t id) {
|
||||
download_manager->CreateDownloadItem(
|
||||
base::GenerateGUID(), id, path, path, url_chain, GURL(), GURL(), GURL(),
|
||||
GURL(), mime_type, mime_type, start_time, base::Time(), etag,
|
||||
last_modified, offset, length, std::string(),
|
||||
content::DownloadItem::INTERRUPTED,
|
||||
content::DownloadDangerType::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
|
||||
content::DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT, false);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Session::Session(v8::Isolate* isolate, AtomBrowserContext* browser_context)
|
||||
: devtools_network_emulation_client_id_(base::GenerateGUID()),
|
||||
browser_context_(browser_context) {
|
||||
// Observe DownloadManager to get download notifications.
|
||||
content::BrowserContext::GetDownloadManager(browser_context)->
|
||||
AddObserver(this);
|
||||
|
||||
Init(isolate);
|
||||
AttachAsUserData(browser_context);
|
||||
}
|
||||
|
||||
Session::~Session() {
|
||||
content::BrowserContext::GetDownloadManager(browser_context())->
|
||||
RemoveObserver(this);
|
||||
g_sessions.erase(weak_map_id());
|
||||
}
|
||||
|
||||
void Session::OnDownloadCreated(content::DownloadManager* manager,
|
||||
content::DownloadItem* item) {
|
||||
if (item->IsSavePackageDownload())
|
||||
return;
|
||||
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
auto handle = DownloadItem::Create(isolate(), item);
|
||||
if (item->GetState() == content::DownloadItem::INTERRUPTED)
|
||||
handle->SetSavePath(item->GetTargetFilePath());
|
||||
bool prevent_default = Emit("will-download", handle, item->GetWebContents());
|
||||
if (prevent_default) {
|
||||
item->Cancel(true);
|
||||
item->Remove();
|
||||
}
|
||||
}
|
||||
|
||||
void Session::ResolveProxy(const GURL& url, ResolveProxyCallback callback) {
|
||||
new ResolveProxyHelper(browser_context(), url, callback);
|
||||
}
|
||||
|
||||
template<Session::CacheAction action>
|
||||
void Session::DoCacheAction(const net::CompletionCallback& callback) {
|
||||
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&DoCacheActionInIO,
|
||||
make_scoped_refptr(browser_context_->GetRequestContext()),
|
||||
action,
|
||||
callback));
|
||||
}
|
||||
|
||||
void Session::ClearStorageData(mate::Arguments* args) {
|
||||
// clearStorageData([options, callback])
|
||||
ClearStorageDataOptions options;
|
||||
base::Closure callback;
|
||||
args->GetNext(&options);
|
||||
args->GetNext(&callback);
|
||||
|
||||
auto storage_partition =
|
||||
content::BrowserContext::GetStoragePartition(browser_context(), nullptr);
|
||||
if (options.storage_types & StoragePartition::REMOVE_DATA_MASK_COOKIES) {
|
||||
// Reset media device id salt when cookies are cleared.
|
||||
// https://w3c.github.io/mediacapture-main/#dom-mediadeviceinfo-deviceid
|
||||
brightray::MediaDeviceIDSalt::Reset(browser_context()->prefs());
|
||||
}
|
||||
storage_partition->ClearData(
|
||||
options.storage_types, options.quota_types, options.origin,
|
||||
content::StoragePartition::OriginMatcherFunction(),
|
||||
base::Time(), base::Time::Max(),
|
||||
base::Bind(&OnClearStorageDataDone, callback));
|
||||
}
|
||||
|
||||
void Session::FlushStorageData() {
|
||||
auto storage_partition =
|
||||
content::BrowserContext::GetStoragePartition(browser_context(), nullptr);
|
||||
storage_partition->Flush();
|
||||
}
|
||||
|
||||
void Session::SetProxy(const net::ProxyConfig& config,
|
||||
const base::Closure& callback) {
|
||||
auto getter = browser_context_->GetRequestContext();
|
||||
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&SetProxyInIO, base::Unretained(getter), config, callback));
|
||||
}
|
||||
|
||||
void Session::SetDownloadPath(const base::FilePath& path) {
|
||||
browser_context_->prefs()->SetFilePath(
|
||||
prefs::kDownloadDefaultDirectory, path);
|
||||
}
|
||||
|
||||
void Session::EnableNetworkEmulation(const mate::Dictionary& options) {
|
||||
std::unique_ptr<brightray::DevToolsNetworkConditions> conditions;
|
||||
bool offline = false;
|
||||
double latency = 0.0, download_throughput = 0.0, upload_throughput = 0.0;
|
||||
if (options.Get("offline", &offline) && offline) {
|
||||
conditions.reset(new brightray::DevToolsNetworkConditions(offline));
|
||||
} else {
|
||||
options.Get("latency", &latency);
|
||||
options.Get("downloadThroughput", &download_throughput);
|
||||
options.Get("uploadThroughput", &upload_throughput);
|
||||
conditions.reset(
|
||||
new brightray::DevToolsNetworkConditions(false,
|
||||
latency,
|
||||
download_throughput,
|
||||
upload_throughput));
|
||||
}
|
||||
|
||||
browser_context_->network_controller_handle()->SetNetworkState(
|
||||
devtools_network_emulation_client_id_, std::move(conditions));
|
||||
browser_context_->network_delegate()->SetDevToolsNetworkEmulationClientId(
|
||||
devtools_network_emulation_client_id_);
|
||||
}
|
||||
|
||||
void Session::DisableNetworkEmulation() {
|
||||
std::unique_ptr<brightray::DevToolsNetworkConditions> conditions;
|
||||
browser_context_->network_controller_handle()->SetNetworkState(
|
||||
devtools_network_emulation_client_id_, std::move(conditions));
|
||||
browser_context_->network_delegate()->SetDevToolsNetworkEmulationClientId(
|
||||
std::string());
|
||||
}
|
||||
|
||||
void Session::SetCertVerifyProc(v8::Local<v8::Value> val,
|
||||
mate::Arguments* args) {
|
||||
AtomCertVerifier::VerifyProc proc;
|
||||
if (!(val->IsNull() || mate::ConvertFromV8(args->isolate(), val, &proc))) {
|
||||
args->ThrowError("Must pass null or function");
|
||||
return;
|
||||
}
|
||||
|
||||
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&SetCertVerifyProcInIO,
|
||||
make_scoped_refptr(browser_context_->GetRequestContext()),
|
||||
proc));
|
||||
}
|
||||
|
||||
void Session::SetPermissionRequestHandler(v8::Local<v8::Value> val,
|
||||
mate::Arguments* args) {
|
||||
AtomPermissionManager::RequestHandler handler;
|
||||
if (!(val->IsNull() || mate::ConvertFromV8(args->isolate(), val, &handler))) {
|
||||
args->ThrowError("Must pass null or function");
|
||||
return;
|
||||
}
|
||||
auto permission_manager = static_cast<AtomPermissionManager*>(
|
||||
browser_context()->GetPermissionManager());
|
||||
permission_manager->SetPermissionRequestHandler(handler);
|
||||
}
|
||||
|
||||
void Session::ClearHostResolverCache(mate::Arguments* args) {
|
||||
base::Closure callback;
|
||||
args->GetNext(&callback);
|
||||
|
||||
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&ClearHostResolverCacheInIO,
|
||||
make_scoped_refptr(browser_context_->GetRequestContext()),
|
||||
callback));
|
||||
}
|
||||
|
||||
void Session::ClearAuthCache(mate::Arguments* args) {
|
||||
ClearAuthCacheOptions options;
|
||||
if (!args->GetNext(&options)) {
|
||||
args->ThrowError("Must specify options object");
|
||||
return;
|
||||
}
|
||||
base::Closure callback;
|
||||
args->GetNext(&callback);
|
||||
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&ClearAuthCacheInIO,
|
||||
make_scoped_refptr(browser_context_->GetRequestContext()),
|
||||
options, callback));
|
||||
}
|
||||
|
||||
void Session::AllowNTLMCredentialsForDomains(const std::string& domains) {
|
||||
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&AllowNTLMCredentialsForDomainsInIO,
|
||||
make_scoped_refptr(browser_context_->GetRequestContext()),
|
||||
domains));
|
||||
}
|
||||
|
||||
void Session::SetUserAgent(const std::string& user_agent,
|
||||
mate::Arguments* args) {
|
||||
browser_context_->SetUserAgent(user_agent);
|
||||
|
||||
std::string accept_lang = l10n_util::GetApplicationLocale("");
|
||||
args->GetNext(&accept_lang);
|
||||
|
||||
auto getter = browser_context_->GetRequestContext();
|
||||
getter->GetNetworkTaskRunner()->PostTask(
|
||||
FROM_HERE,
|
||||
base::Bind(&SetUserAgentInIO, getter, accept_lang, user_agent));
|
||||
}
|
||||
|
||||
std::string Session::GetUserAgent() {
|
||||
return browser_context_->GetUserAgent();
|
||||
}
|
||||
|
||||
void Session::GetBlobData(
|
||||
const std::string& uuid,
|
||||
const AtomBlobReader::CompletionCallback& callback) {
|
||||
if (callback.is_null())
|
||||
return;
|
||||
|
||||
AtomBlobReader* blob_reader =
|
||||
browser_context()->GetBlobReader();
|
||||
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&AtomBlobReader::StartReading,
|
||||
base::Unretained(blob_reader),
|
||||
uuid,
|
||||
callback));
|
||||
}
|
||||
|
||||
void Session::CreateInterruptedDownload(const mate::Dictionary& options) {
|
||||
int64_t offset = 0, length = 0;
|
||||
double start_time = 0.0;
|
||||
std::string mime_type, last_modified, etag;
|
||||
base::FilePath path;
|
||||
std::vector<GURL> url_chain;
|
||||
options.Get("path", &path);
|
||||
options.Get("urlChain", &url_chain);
|
||||
options.Get("mimeType", &mime_type);
|
||||
options.Get("offset", &offset);
|
||||
options.Get("length", &length);
|
||||
options.Get("lastModified", &last_modified);
|
||||
options.Get("eTag", &etag);
|
||||
options.Get("startTime", &start_time);
|
||||
if (path.empty() || url_chain.empty() || length == 0) {
|
||||
isolate()->ThrowException(v8::Exception::Error(mate::StringToV8(
|
||||
isolate(), "Must pass non-empty path, urlChain and length.")));
|
||||
return;
|
||||
}
|
||||
if (offset >= length) {
|
||||
isolate()->ThrowException(v8::Exception::Error(mate::StringToV8(
|
||||
isolate(), "Must pass an offset value less than length.")));
|
||||
return;
|
||||
}
|
||||
auto download_manager =
|
||||
content::BrowserContext::GetDownloadManager(browser_context());
|
||||
download_manager->GetDelegate()->GetNextId(base::Bind(
|
||||
&DownloadIdCallback, download_manager, path, url_chain, mime_type, offset,
|
||||
length, last_modified, etag, base::Time::FromDoubleT(start_time)));
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> Session::Cookies(v8::Isolate* isolate) {
|
||||
if (cookies_.IsEmpty()) {
|
||||
auto handle = Cookies::Create(isolate, browser_context());
|
||||
cookies_.Reset(isolate, handle.ToV8());
|
||||
}
|
||||
return v8::Local<v8::Value>::New(isolate, cookies_);
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> Session::Protocol(v8::Isolate* isolate) {
|
||||
if (protocol_.IsEmpty()) {
|
||||
auto handle = atom::api::Protocol::Create(isolate, browser_context());
|
||||
protocol_.Reset(isolate, handle.ToV8());
|
||||
}
|
||||
return v8::Local<v8::Value>::New(isolate, protocol_);
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> Session::WebRequest(v8::Isolate* isolate) {
|
||||
if (web_request_.IsEmpty()) {
|
||||
auto handle = atom::api::WebRequest::Create(isolate, browser_context());
|
||||
web_request_.Reset(isolate, handle.ToV8());
|
||||
}
|
||||
return v8::Local<v8::Value>::New(isolate, web_request_);
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<Session> Session::CreateFrom(
|
||||
v8::Isolate* isolate, AtomBrowserContext* browser_context) {
|
||||
auto existing = TrackableObject::FromWrappedClass(isolate, browser_context);
|
||||
if (existing)
|
||||
return mate::CreateHandle(isolate, static_cast<Session*>(existing));
|
||||
|
||||
auto handle = mate::CreateHandle(
|
||||
isolate, new Session(isolate, browser_context));
|
||||
|
||||
// The Sessions should never be garbage collected, since the common pattern is
|
||||
// to use partition strings, instead of using the Session object directly.
|
||||
g_sessions[handle->weak_map_id()] =
|
||||
v8::Global<v8::Object>(isolate, handle.ToV8());
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<Session> Session::FromPartition(
|
||||
v8::Isolate* isolate, const std::string& partition,
|
||||
const base::DictionaryValue& options) {
|
||||
scoped_refptr<AtomBrowserContext> browser_context;
|
||||
if (partition.empty()) {
|
||||
browser_context = AtomBrowserContext::From("", false, options);
|
||||
} else if (base::StartsWith(partition, kPersistPrefix,
|
||||
base::CompareCase::SENSITIVE)) {
|
||||
std::string name = partition.substr(8);
|
||||
browser_context = AtomBrowserContext::From(name, false, options);
|
||||
} else {
|
||||
browser_context = AtomBrowserContext::From(partition, true, options);
|
||||
}
|
||||
return CreateFrom(isolate, browser_context.get());
|
||||
}
|
||||
|
||||
// static
|
||||
void Session::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "Session"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.MakeDestroyable()
|
||||
.SetMethod("resolveProxy", &Session::ResolveProxy)
|
||||
.SetMethod("getCacheSize", &Session::DoCacheAction<CacheAction::STATS>)
|
||||
.SetMethod("clearCache", &Session::DoCacheAction<CacheAction::CLEAR>)
|
||||
.SetMethod("clearStorageData", &Session::ClearStorageData)
|
||||
.SetMethod("flushStorageData", &Session::FlushStorageData)
|
||||
.SetMethod("setProxy", &Session::SetProxy)
|
||||
.SetMethod("setDownloadPath", &Session::SetDownloadPath)
|
||||
.SetMethod("enableNetworkEmulation", &Session::EnableNetworkEmulation)
|
||||
.SetMethod("disableNetworkEmulation", &Session::DisableNetworkEmulation)
|
||||
.SetMethod("setCertificateVerifyProc", &Session::SetCertVerifyProc)
|
||||
.SetMethod("setPermissionRequestHandler",
|
||||
&Session::SetPermissionRequestHandler)
|
||||
.SetMethod("clearHostResolverCache", &Session::ClearHostResolverCache)
|
||||
.SetMethod("clearAuthCache", &Session::ClearAuthCache)
|
||||
.SetMethod("allowNTLMCredentialsForDomains",
|
||||
&Session::AllowNTLMCredentialsForDomains)
|
||||
.SetMethod("setUserAgent", &Session::SetUserAgent)
|
||||
.SetMethod("getUserAgent", &Session::GetUserAgent)
|
||||
.SetMethod("getBlobData", &Session::GetBlobData)
|
||||
.SetMethod("createInterruptedDownload",
|
||||
&Session::CreateInterruptedDownload)
|
||||
.SetProperty("cookies", &Session::Cookies)
|
||||
.SetProperty("protocol", &Session::Protocol)
|
||||
.SetProperty("webRequest", &Session::WebRequest);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
namespace {
|
||||
|
||||
using atom::api::Session;
|
||||
|
||||
v8::Local<v8::Value> FromPartition(
|
||||
const std::string& partition, mate::Arguments* args) {
|
||||
if (!atom::Browser::Get()->is_ready()) {
|
||||
args->ThrowError("Session can only be received when app is ready");
|
||||
return v8::Null(args->isolate());
|
||||
}
|
||||
base::DictionaryValue options;
|
||||
args->GetNext(&options);
|
||||
return Session::FromPartition(args->isolate(), partition, options).ToV8();
|
||||
}
|
||||
|
||||
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("Session", Session::GetConstructor(isolate)->GetFunction());
|
||||
dict.Set("Cookies", Cookies::GetConstructor(isolate)->GetFunction());
|
||||
dict.SetMethod("fromPartition", &FromPartition);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_session, Initialize)
|
||||
114
atom/browser/api/atom_api_session.h
Normal file
114
atom/browser/api/atom_api_session.h
Normal file
@@ -0,0 +1,114 @@
|
||||
// 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_SESSION_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_SESSION_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "atom/browser/atom_blob_reader.h"
|
||||
#include "base/values.h"
|
||||
#include "content/public/browser/download_manager.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "net/base/completion_callback.h"
|
||||
|
||||
class GURL;
|
||||
|
||||
namespace base {
|
||||
class FilePath;
|
||||
}
|
||||
|
||||
namespace mate {
|
||||
class Arguments;
|
||||
class Dictionary;
|
||||
}
|
||||
|
||||
namespace net {
|
||||
class ProxyConfig;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomBrowserContext;
|
||||
|
||||
namespace api {
|
||||
|
||||
class Session: public mate::TrackableObject<Session>,
|
||||
public content::DownloadManager::Observer {
|
||||
public:
|
||||
using ResolveProxyCallback = base::Callback<void(std::string)>;
|
||||
|
||||
enum class CacheAction {
|
||||
CLEAR,
|
||||
STATS,
|
||||
};
|
||||
|
||||
// Gets or creates Session from the |browser_context|.
|
||||
static mate::Handle<Session> CreateFrom(
|
||||
v8::Isolate* isolate, AtomBrowserContext* browser_context);
|
||||
|
||||
// Gets the Session of |partition|.
|
||||
static mate::Handle<Session> FromPartition(
|
||||
v8::Isolate* isolate, const std::string& partition,
|
||||
const base::DictionaryValue& options = base::DictionaryValue());
|
||||
|
||||
AtomBrowserContext* browser_context() const { return browser_context_.get(); }
|
||||
|
||||
// mate::TrackableObject:
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
// Methods.
|
||||
void ResolveProxy(const GURL& url, ResolveProxyCallback callback);
|
||||
template<CacheAction action>
|
||||
void DoCacheAction(const net::CompletionCallback& callback);
|
||||
void ClearStorageData(mate::Arguments* args);
|
||||
void FlushStorageData();
|
||||
void SetProxy(const net::ProxyConfig& config, const base::Closure& callback);
|
||||
void SetDownloadPath(const base::FilePath& path);
|
||||
void EnableNetworkEmulation(const mate::Dictionary& options);
|
||||
void DisableNetworkEmulation();
|
||||
void SetCertVerifyProc(v8::Local<v8::Value> proc, mate::Arguments* args);
|
||||
void SetPermissionRequestHandler(v8::Local<v8::Value> val,
|
||||
mate::Arguments* args);
|
||||
void ClearHostResolverCache(mate::Arguments* args);
|
||||
void ClearAuthCache(mate::Arguments* args);
|
||||
void AllowNTLMCredentialsForDomains(const std::string& domains);
|
||||
void SetUserAgent(const std::string& user_agent, mate::Arguments* args);
|
||||
std::string GetUserAgent();
|
||||
void GetBlobData(const std::string& uuid,
|
||||
const AtomBlobReader::CompletionCallback& callback);
|
||||
void CreateInterruptedDownload(const mate::Dictionary& options);
|
||||
v8::Local<v8::Value> Cookies(v8::Isolate* isolate);
|
||||
v8::Local<v8::Value> Protocol(v8::Isolate* isolate);
|
||||
v8::Local<v8::Value> WebRequest(v8::Isolate* isolate);
|
||||
|
||||
protected:
|
||||
Session(v8::Isolate* isolate, AtomBrowserContext* browser_context);
|
||||
~Session();
|
||||
|
||||
// content::DownloadManager::Observer:
|
||||
void OnDownloadCreated(content::DownloadManager* manager,
|
||||
content::DownloadItem* item) override;
|
||||
|
||||
private:
|
||||
// Cached object.
|
||||
v8::Global<v8::Value> cookies_;
|
||||
v8::Global<v8::Value> protocol_;
|
||||
v8::Global<v8::Value> web_request_;
|
||||
|
||||
// The X-DevTools-Emulate-Network-Conditions-Client-Id.
|
||||
std::string devtools_network_emulation_client_id_;
|
||||
|
||||
scoped_refptr<AtomBrowserContext> browser_context_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Session);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_SESSION_H_
|
||||
98
atom/browser/api/atom_api_system_preferences.cc
Normal file
98
atom/browser/api/atom_api_system_preferences.cc
Normal file
@@ -0,0 +1,98 @@
|
||||
// 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_system_preferences.h"
|
||||
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "ui/gfx/color_utils.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
SystemPreferences::SystemPreferences(v8::Isolate* isolate)
|
||||
#if defined(OS_WIN)
|
||||
: color_change_listener_(this)
|
||||
#endif
|
||||
{
|
||||
Init(isolate);
|
||||
#if defined(OS_WIN)
|
||||
InitializeWindow();
|
||||
#endif
|
||||
}
|
||||
|
||||
SystemPreferences::~SystemPreferences() {
|
||||
}
|
||||
|
||||
#if !defined(OS_MACOSX)
|
||||
bool SystemPreferences::IsDarkMode() {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool SystemPreferences::IsInvertedColorScheme() {
|
||||
return color_utils::IsInvertedColorScheme();
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<SystemPreferences> SystemPreferences::Create(
|
||||
v8::Isolate* isolate) {
|
||||
return mate::CreateHandle(isolate, new SystemPreferences(isolate));
|
||||
}
|
||||
|
||||
// static
|
||||
void SystemPreferences::BuildPrototype(
|
||||
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "SystemPreferences"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
#if defined(OS_WIN)
|
||||
.SetMethod("getAccentColor", &SystemPreferences::GetAccentColor)
|
||||
.SetMethod("isAeroGlassEnabled", &SystemPreferences::IsAeroGlassEnabled)
|
||||
.SetMethod("getColor", &SystemPreferences::GetColor)
|
||||
#elif defined(OS_MACOSX)
|
||||
.SetMethod("postNotification",
|
||||
&SystemPreferences::PostNotification)
|
||||
.SetMethod("postLocalNotification",
|
||||
&SystemPreferences::PostLocalNotification)
|
||||
.SetMethod("subscribeNotification",
|
||||
&SystemPreferences::SubscribeNotification)
|
||||
.SetMethod("unsubscribeNotification",
|
||||
&SystemPreferences::UnsubscribeNotification)
|
||||
.SetMethod("subscribeLocalNotification",
|
||||
&SystemPreferences::SubscribeLocalNotification)
|
||||
.SetMethod("unsubscribeLocalNotification",
|
||||
&SystemPreferences::UnsubscribeLocalNotification)
|
||||
.SetMethod("getUserDefault", &SystemPreferences::GetUserDefault)
|
||||
.SetMethod("setUserDefault", &SystemPreferences::SetUserDefault)
|
||||
.SetMethod("isSwipeTrackingFromScrollEventsEnabled",
|
||||
&SystemPreferences::IsSwipeTrackingFromScrollEventsEnabled)
|
||||
#endif
|
||||
.SetMethod("isInvertedColorScheme",
|
||||
&SystemPreferences::IsInvertedColorScheme)
|
||||
.SetMethod("isDarkMode", &SystemPreferences::IsDarkMode);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
namespace {
|
||||
|
||||
using atom::api::SystemPreferences;
|
||||
|
||||
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("systemPreferences", SystemPreferences::Create(isolate));
|
||||
dict.Set("SystemPreferences",
|
||||
SystemPreferences::GetConstructor(isolate)->GetFunction());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_system_preferences, Initialize);
|
||||
123
atom/browser/api/atom_api_system_preferences.h
Normal file
123
atom/browser/api/atom_api_system_preferences.h
Normal file
@@ -0,0 +1,123 @@
|
||||
// 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_SYSTEM_PREFERENCES_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_SYSTEM_PREFERENCES_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/api/event_emitter.h"
|
||||
#include "base/callback.h"
|
||||
#include "base/values.h"
|
||||
#include "native_mate/handle.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include "ui/gfx/sys_color_change_listener.h"
|
||||
#endif
|
||||
|
||||
namespace base {
|
||||
class DictionaryValue;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class SystemPreferences : public mate::EventEmitter<SystemPreferences>
|
||||
#if defined(OS_WIN)
|
||||
, public gfx::SysColorChangeListener
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
static mate::Handle<SystemPreferences> Create(v8::Isolate* isolate);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
#if defined(OS_WIN)
|
||||
bool IsAeroGlassEnabled();
|
||||
|
||||
typedef HRESULT (STDAPICALLTYPE *DwmGetColorizationColor)(DWORD *, BOOL *);
|
||||
DwmGetColorizationColor dwmGetColorizationColor =
|
||||
(DwmGetColorizationColor) GetProcAddress(LoadLibraryW(L"dwmapi.dll"),
|
||||
"DwmGetColorizationColor");
|
||||
|
||||
std::string GetAccentColor();
|
||||
std::string GetColor(const std::string& color, mate::Arguments* args);
|
||||
|
||||
void InitializeWindow();
|
||||
|
||||
// gfx::SysColorChangeListener:
|
||||
void OnSysColorChange() override;
|
||||
|
||||
#elif defined(OS_MACOSX)
|
||||
using NotificationCallback = base::Callback<
|
||||
void(const std::string&, const base::DictionaryValue&)>;
|
||||
|
||||
void PostNotification(const std::string& name,
|
||||
const base::DictionaryValue& user_info);
|
||||
void PostLocalNotification(const std::string& name,
|
||||
const base::DictionaryValue& user_info);
|
||||
int SubscribeNotification(const std::string& name,
|
||||
const NotificationCallback& callback);
|
||||
void UnsubscribeNotification(int id);
|
||||
int SubscribeLocalNotification(const std::string& name,
|
||||
const NotificationCallback& callback);
|
||||
void UnsubscribeLocalNotification(int request_id);
|
||||
v8::Local<v8::Value> GetUserDefault(const std::string& name,
|
||||
const std::string& type);
|
||||
void SetUserDefault(const std::string& name,
|
||||
const std::string& type,
|
||||
mate::Arguments* args);
|
||||
bool IsSwipeTrackingFromScrollEventsEnabled();
|
||||
#endif
|
||||
bool IsDarkMode();
|
||||
bool IsInvertedColorScheme();
|
||||
|
||||
protected:
|
||||
explicit SystemPreferences(v8::Isolate* isolate);
|
||||
~SystemPreferences() override;
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
void DoPostNotification(const std::string& name,
|
||||
const base::DictionaryValue& user_info,
|
||||
bool is_local);
|
||||
int DoSubscribeNotification(const std::string& name,
|
||||
const NotificationCallback& callback,
|
||||
bool is_local);
|
||||
void DoUnsubscribeNotification(int request_id, bool is_local);
|
||||
#endif
|
||||
|
||||
private:
|
||||
#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_;
|
||||
|
||||
std::string current_color_;
|
||||
|
||||
bool invertered_color_scheme_;
|
||||
|
||||
gfx::ScopedSysColorChangeListener color_change_listener_;
|
||||
#endif
|
||||
DISALLOW_COPY_AND_ASSIGN(SystemPreferences);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_SYSTEM_PREFERENCES_H_
|
||||
244
atom/browser/api/atom_api_system_preferences_mac.mm
Normal file
244
atom/browser/api/atom_api_system_preferences_mac.mm
Normal file
@@ -0,0 +1,244 @@
|
||||
// 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_system_preferences.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#include "atom/browser/mac/dict_util.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||
#include "base/strings/sys_string_conversions.h"
|
||||
#include "base/values.h"
|
||||
#include "net/base/mac/url_conversions.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
namespace {
|
||||
|
||||
int g_next_id = 0;
|
||||
|
||||
// The map to convert |id| to |int|.
|
||||
std::map<int, id> g_id_map;
|
||||
|
||||
} // namespace
|
||||
|
||||
void SystemPreferences::PostNotification(const std::string& name,
|
||||
const base::DictionaryValue& user_info) {
|
||||
DoPostNotification(name, user_info, false);
|
||||
}
|
||||
|
||||
void SystemPreferences::PostLocalNotification(const std::string& name,
|
||||
const base::DictionaryValue& user_info) {
|
||||
DoPostNotification(name, user_info, true);
|
||||
}
|
||||
|
||||
void SystemPreferences::DoPostNotification(const std::string& name,
|
||||
const base::DictionaryValue& user_info, bool is_local) {
|
||||
NSNotificationCenter* center = is_local ?
|
||||
[NSNotificationCenter defaultCenter] :
|
||||
[NSDistributedNotificationCenter defaultCenter];
|
||||
[center
|
||||
postNotificationName:base::SysUTF8ToNSString(name)
|
||||
object:nil
|
||||
userInfo:DictionaryValueToNSDictionary(user_info)
|
||||
];
|
||||
}
|
||||
|
||||
int SystemPreferences::SubscribeNotification(
|
||||
const std::string& name, const NotificationCallback& callback) {
|
||||
return DoSubscribeNotification(name, callback, false);
|
||||
}
|
||||
|
||||
void SystemPreferences::UnsubscribeNotification(int request_id) {
|
||||
DoUnsubscribeNotification(request_id, false);
|
||||
}
|
||||
|
||||
int SystemPreferences::SubscribeLocalNotification(
|
||||
const std::string& name, const NotificationCallback& callback) {
|
||||
return DoSubscribeNotification(name, callback, true);
|
||||
}
|
||||
|
||||
void SystemPreferences::UnsubscribeLocalNotification(int request_id) {
|
||||
DoUnsubscribeNotification(request_id, true);
|
||||
}
|
||||
|
||||
int SystemPreferences::DoSubscribeNotification(const std::string& name,
|
||||
const NotificationCallback& callback, bool is_local) {
|
||||
int request_id = g_next_id++;
|
||||
__block NotificationCallback copied_callback = callback;
|
||||
NSNotificationCenter* center = is_local ?
|
||||
[NSNotificationCenter defaultCenter] :
|
||||
[NSDistributedNotificationCenter defaultCenter];
|
||||
|
||||
g_id_map[request_id] = [center
|
||||
addObserverForName:base::SysUTF8ToNSString(name)
|
||||
object:nil
|
||||
queue:nil
|
||||
usingBlock:^(NSNotification* notification) {
|
||||
std::unique_ptr<base::DictionaryValue> user_info =
|
||||
NSDictionaryToDictionaryValue(notification.userInfo);
|
||||
if (user_info) {
|
||||
copied_callback.Run(
|
||||
base::SysNSStringToUTF8(notification.name),
|
||||
*user_info);
|
||||
} else {
|
||||
copied_callback.Run(
|
||||
base::SysNSStringToUTF8(notification.name),
|
||||
base::DictionaryValue());
|
||||
}
|
||||
}
|
||||
];
|
||||
return request_id;
|
||||
}
|
||||
|
||||
void SystemPreferences::DoUnsubscribeNotification(int request_id, bool is_local) {
|
||||
auto iter = g_id_map.find(request_id);
|
||||
if (iter != g_id_map.end()) {
|
||||
id observer = iter->second;
|
||||
NSNotificationCenter* center = is_local ?
|
||||
[NSNotificationCenter defaultCenter] :
|
||||
[NSDistributedNotificationCenter defaultCenter];
|
||||
[center removeObserver:observer];
|
||||
g_id_map.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> SystemPreferences::GetUserDefault(
|
||||
const std::string& name, const std::string& type) {
|
||||
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
|
||||
NSString* key = base::SysUTF8ToNSString(name);
|
||||
if (type == "string") {
|
||||
return mate::StringToV8(isolate(),
|
||||
base::SysNSStringToUTF8([defaults stringForKey:key]));
|
||||
} else if (type == "boolean") {
|
||||
return v8::Boolean::New(isolate(), [defaults boolForKey:key]);
|
||||
} else if (type == "float") {
|
||||
return v8::Number::New(isolate(), [defaults floatForKey:key]);
|
||||
} else if (type == "integer") {
|
||||
return v8::Integer::New(isolate(), [defaults integerForKey:key]);
|
||||
} else if (type == "double") {
|
||||
return v8::Number::New(isolate(), [defaults doubleForKey:key]);
|
||||
} else if (type == "url") {
|
||||
return mate::ConvertToV8(isolate(),
|
||||
net::GURLWithNSURL([defaults URLForKey:key]));
|
||||
} else if (type == "array") {
|
||||
std::unique_ptr<base::ListValue> list =
|
||||
NSArrayToListValue([defaults arrayForKey:key]);
|
||||
if (list == nullptr)
|
||||
list.reset(new base::ListValue());
|
||||
return mate::ConvertToV8(isolate(), *list);
|
||||
} else if (type == "dictionary") {
|
||||
std::unique_ptr<base::DictionaryValue> dictionary =
|
||||
NSDictionaryToDictionaryValue([defaults dictionaryForKey:key]);
|
||||
if (dictionary == nullptr)
|
||||
dictionary.reset(new base::DictionaryValue());
|
||||
return mate::ConvertToV8(isolate(), *dictionary);
|
||||
} else {
|
||||
return v8::Undefined(isolate());
|
||||
}
|
||||
}
|
||||
|
||||
void SystemPreferences::SetUserDefault(const std::string& name,
|
||||
const std::string& type,
|
||||
mate::Arguments* args) {
|
||||
const auto throwConversionError = [&] {
|
||||
args->ThrowError("Unable to convert value to: " + type);
|
||||
};
|
||||
|
||||
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
|
||||
NSString* key = base::SysUTF8ToNSString(name);
|
||||
if (type == "string") {
|
||||
std::string value;
|
||||
if (!args->GetNext(&value)) {
|
||||
throwConversionError();
|
||||
return;
|
||||
}
|
||||
|
||||
[defaults setObject:base::SysUTF8ToNSString(value) forKey:key];
|
||||
} else if (type == "boolean") {
|
||||
bool value;
|
||||
if (!args->GetNext(&value)) {
|
||||
throwConversionError();
|
||||
return;
|
||||
}
|
||||
|
||||
[defaults setBool:value forKey:key];
|
||||
} else if (type == "float") {
|
||||
float value;
|
||||
if (!args->GetNext(&value)) {
|
||||
throwConversionError();
|
||||
return;
|
||||
}
|
||||
|
||||
[defaults setFloat:value forKey:key];
|
||||
} else if (type == "integer") {
|
||||
int value;
|
||||
if (!args->GetNext(&value)) {
|
||||
throwConversionError();
|
||||
return;
|
||||
}
|
||||
|
||||
[defaults setInteger:value forKey:key];
|
||||
} else if (type == "double") {
|
||||
double value;
|
||||
if (!args->GetNext(&value)) {
|
||||
throwConversionError();
|
||||
return;
|
||||
}
|
||||
|
||||
[defaults setDouble:value forKey:key];
|
||||
} else if (type == "url") {
|
||||
GURL value;
|
||||
if (!args->GetNext(&value)) {
|
||||
throwConversionError();
|
||||
return;
|
||||
}
|
||||
|
||||
if (NSURL* url = net::NSURLWithGURL(value)) {
|
||||
[defaults setURL:url forKey:key];
|
||||
}
|
||||
} else if (type == "array") {
|
||||
base::ListValue value;
|
||||
if (!args->GetNext(&value)) {
|
||||
throwConversionError();
|
||||
return;
|
||||
}
|
||||
|
||||
if (NSArray* array = ListValueToNSArray(value)) {
|
||||
[defaults setObject:array forKey:key];
|
||||
}
|
||||
} else if (type == "dictionary") {
|
||||
base::DictionaryValue value;
|
||||
if (!args->GetNext(&value)) {
|
||||
throwConversionError();
|
||||
return;
|
||||
}
|
||||
|
||||
if (NSDictionary* dict = DictionaryValueToNSDictionary(value)) {
|
||||
[defaults setObject:dict forKey:key];
|
||||
}
|
||||
} else {
|
||||
args->ThrowError("Invalid type: " + type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool SystemPreferences::IsDarkMode() {
|
||||
NSString* mode = [[NSUserDefaults standardUserDefaults]
|
||||
stringForKey:@"AppleInterfaceStyle"];
|
||||
return [mode isEqualToString:@"Dark"];
|
||||
}
|
||||
|
||||
bool SystemPreferences::IsSwipeTrackingFromScrollEventsEnabled() {
|
||||
return [NSEvent isSwipeTrackingFromScrollEventsEnabled];
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
177
atom/browser/api/atom_api_system_preferences_win.cc
Normal file
177
atom/browser/api/atom_api_system_preferences_win.cc
Normal file
@@ -0,0 +1,177 @@
|
||||
// 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_system_preferences.h"
|
||||
|
||||
#include "atom/common/color_util.h"
|
||||
#include "base/win/wrapped_window_proc.h"
|
||||
#include "ui/base/win/shell.h"
|
||||
#include "ui/gfx/color_utils.h"
|
||||
#include "ui/gfx/win/hwnd_util.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
const wchar_t kSystemPreferencesWindowClass[] =
|
||||
L"Electron_SystemPreferencesHostWindow";
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace api {
|
||||
|
||||
bool SystemPreferences::IsAeroGlassEnabled() {
|
||||
return ui::win::IsAeroGlassEnabled();
|
||||
}
|
||||
|
||||
std::string hexColorDWORDToRGBA(DWORD color) {
|
||||
std::ostringstream stream;
|
||||
stream << std::hex << color;
|
||||
std::string hexColor = stream.str();
|
||||
return hexColor.substr(2) + hexColor.substr(0, 2);
|
||||
}
|
||||
|
||||
std::string SystemPreferences::GetAccentColor() {
|
||||
DWORD color = 0;
|
||||
BOOL opaque = FALSE;
|
||||
|
||||
if (FAILED(dwmGetColorizationColor(&color, &opaque))) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return hexColorDWORDToRGBA(color);
|
||||
}
|
||||
|
||||
std::string SystemPreferences::GetColor(const std::string& color,
|
||||
mate::Arguments* args) {
|
||||
int id;
|
||||
if (color == "3d-dark-shadow") {
|
||||
id = COLOR_3DDKSHADOW;
|
||||
} else if (color == "3d-face") {
|
||||
id = COLOR_3DFACE;
|
||||
} else if (color == "3d-highlight") {
|
||||
id = COLOR_3DHIGHLIGHT;
|
||||
} else if (color == "3d-light") {
|
||||
id = COLOR_3DLIGHT;
|
||||
} else if (color == "3d-shadow") {
|
||||
id = COLOR_3DSHADOW;
|
||||
} else if (color == "active-border") {
|
||||
id = COLOR_ACTIVEBORDER;
|
||||
} else if (color == "active-caption") {
|
||||
id = COLOR_ACTIVECAPTION;
|
||||
} else if (color == "active-caption-gradient") {
|
||||
id = COLOR_GRADIENTACTIVECAPTION;
|
||||
} else if (color == "app-workspace") {
|
||||
id = COLOR_APPWORKSPACE;
|
||||
} else if (color == "button-text") {
|
||||
id = COLOR_BTNTEXT;
|
||||
} else if (color == "caption-text") {
|
||||
id = COLOR_CAPTIONTEXT;
|
||||
} else if (color == "desktop") {
|
||||
id = COLOR_DESKTOP;
|
||||
} else if (color == "disabled-text") {
|
||||
id = COLOR_GRAYTEXT;
|
||||
} else if (color == "highlight") {
|
||||
id = COLOR_HIGHLIGHT;
|
||||
} else if (color == "highlight-text") {
|
||||
id = COLOR_HIGHLIGHTTEXT;
|
||||
} else if (color == "hotlight") {
|
||||
id = COLOR_HOTLIGHT;
|
||||
} else if (color == "inactive-border") {
|
||||
id = COLOR_INACTIVEBORDER;
|
||||
} else if (color == "inactive-caption") {
|
||||
id = COLOR_INACTIVECAPTION;
|
||||
} else if (color == "inactive-caption-gradient") {
|
||||
id = COLOR_GRADIENTINACTIVECAPTION;
|
||||
} else if (color == "inactive-caption-text") {
|
||||
id = COLOR_INACTIVECAPTIONTEXT;
|
||||
} else if (color == "info-background") {
|
||||
id = COLOR_INFOBK;
|
||||
} else if (color == "info-text") {
|
||||
id = COLOR_INFOTEXT;
|
||||
} else if (color == "menu") {
|
||||
id = COLOR_MENU;
|
||||
} else if (color == "menu-highlight") {
|
||||
id = COLOR_MENUHILIGHT;
|
||||
} else if (color == "menubar") {
|
||||
id = COLOR_MENUBAR;
|
||||
} else if (color == "menu-text") {
|
||||
id = COLOR_MENUTEXT;
|
||||
} else if (color == "scrollbar") {
|
||||
id = COLOR_SCROLLBAR;
|
||||
} else if (color == "window") {
|
||||
id = COLOR_WINDOW;
|
||||
} else if (color == "window-frame") {
|
||||
id = COLOR_WINDOWFRAME;
|
||||
} else if (color == "window-text") {
|
||||
id = COLOR_WINDOWTEXT;
|
||||
} else {
|
||||
args->ThrowError("Unknown color: " + color);
|
||||
return "";
|
||||
}
|
||||
|
||||
return ToRGBHex(color_utils::GetSysSkColor(id));
|
||||
}
|
||||
|
||||
void SystemPreferences::InitializeWindow() {
|
||||
invertered_color_scheme_ = IsInvertedColorScheme();
|
||||
|
||||
WNDCLASSEX window_class;
|
||||
base::win::InitializeWindowClass(
|
||||
kSystemPreferencesWindowClass,
|
||||
&base::win::WrappedWindowProc<SystemPreferences::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 system
|
||||
// colorization color. Create a hidden WS_POPUP window instead of an
|
||||
// HWND_MESSAGE window, because only top-level windows such as popups can
|
||||
// receive broadcast messages like "WM_DWMCOLORIZATIONCOLORCHANGED".
|
||||
window_ = CreateWindow(MAKEINTATOM(atom_),
|
||||
0, WS_POPUP, 0, 0, 0, 0, 0, 0, instance_, 0);
|
||||
gfx::CheckWindowCreated(window_);
|
||||
gfx::SetWindowUserData(window_, this);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK SystemPreferences::WndProcStatic(HWND hwnd,
|
||||
UINT message,
|
||||
WPARAM wparam,
|
||||
LPARAM lparam) {
|
||||
SystemPreferences* msg_wnd = reinterpret_cast<SystemPreferences*>(
|
||||
GetWindowLongPtr(hwnd, GWLP_USERDATA));
|
||||
if (msg_wnd)
|
||||
return msg_wnd->WndProc(hwnd, message, wparam, lparam);
|
||||
else
|
||||
return ::DefWindowProc(hwnd, message, wparam, lparam);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK SystemPreferences::WndProc(HWND hwnd,
|
||||
UINT message,
|
||||
WPARAM wparam,
|
||||
LPARAM lparam) {
|
||||
if (message == WM_DWMCOLORIZATIONCOLORCHANGED) {
|
||||
DWORD new_color = (DWORD) wparam;
|
||||
std::string new_color_string = hexColorDWORDToRGBA(new_color);
|
||||
if (new_color_string != current_color_) {
|
||||
Emit("accent-color-changed", hexColorDWORDToRGBA(new_color));
|
||||
current_color_ = new_color_string;
|
||||
}
|
||||
}
|
||||
return ::DefWindowProc(hwnd, message, wparam, lparam);
|
||||
}
|
||||
|
||||
void SystemPreferences::OnSysColorChange() {
|
||||
bool new_invertered_color_scheme = IsInvertedColorScheme();
|
||||
if (new_invertered_color_scheme != invertered_color_scheme_) {
|
||||
invertered_color_scheme_ = new_invertered_color_scheme;
|
||||
Emit("inverted-color-scheme-changed", new_invertered_color_scheme);
|
||||
}
|
||||
Emit("color-changed");
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
239
atom/browser/api/atom_api_tray.cc
Normal file
239
atom/browser/api/atom_api_tray.cc
Normal file
@@ -0,0 +1,239 @@
|
||||
// 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_tray.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/api/atom_api_menu.h"
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/common/api/atom_api_native_image.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 "atom/common/node_includes.h"
|
||||
#include "native_mate/constructor.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "ui/gfx/image/image.h"
|
||||
|
||||
namespace mate {
|
||||
|
||||
template<>
|
||||
struct Converter<atom::TrayIcon::HighlightMode> {
|
||||
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
|
||||
atom::TrayIcon::HighlightMode* out) {
|
||||
std::string mode;
|
||||
if (ConvertFromV8(isolate, val, &mode)) {
|
||||
if (mode == "always") {
|
||||
*out = atom::TrayIcon::HighlightMode::ALWAYS;
|
||||
return true;
|
||||
}
|
||||
if (mode == "selection") {
|
||||
*out = atom::TrayIcon::HighlightMode::SELECTION;
|
||||
return true;
|
||||
}
|
||||
if (mode == "never") {
|
||||
*out = atom::TrayIcon::HighlightMode::NEVER;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Support old boolean parameter
|
||||
// TODO(kevinsawicki): Remove in 2.0, deprecate before then with warnings
|
||||
bool highlight;
|
||||
if (ConvertFromV8(isolate, val, &highlight)) {
|
||||
if (highlight)
|
||||
*out = atom::TrayIcon::HighlightMode::SELECTION;
|
||||
else
|
||||
*out = atom::TrayIcon::HighlightMode::NEVER;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
} // namespace mate
|
||||
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
Tray::Tray(v8::Isolate* isolate, v8::Local<v8::Object> wrapper,
|
||||
mate::Handle<NativeImage> image)
|
||||
: tray_icon_(TrayIcon::Create()) {
|
||||
SetImage(isolate, image);
|
||||
tray_icon_->AddObserver(this);
|
||||
|
||||
InitWith(isolate, wrapper);
|
||||
}
|
||||
|
||||
Tray::~Tray() {
|
||||
// Destroy the native tray in next tick.
|
||||
base::MessageLoop::current()->DeleteSoon(FROM_HERE, tray_icon_.release());
|
||||
}
|
||||
|
||||
// static
|
||||
mate::WrappableBase* Tray::New(mate::Handle<NativeImage> image,
|
||||
mate::Arguments* args) {
|
||||
if (!Browser::Get()->is_ready()) {
|
||||
args->ThrowError("Cannot create Tray before app is ready");
|
||||
return nullptr;
|
||||
}
|
||||
return new Tray(args->isolate(), args->GetThis(), image);
|
||||
}
|
||||
|
||||
void Tray::OnClicked(const gfx::Rect& bounds, int modifiers) {
|
||||
EmitWithFlags("click", modifiers, bounds);
|
||||
}
|
||||
|
||||
void Tray::OnDoubleClicked(const gfx::Rect& bounds, int modifiers) {
|
||||
EmitWithFlags("double-click", modifiers, bounds);
|
||||
}
|
||||
|
||||
void Tray::OnRightClicked(const gfx::Rect& bounds, int modifiers) {
|
||||
EmitWithFlags("right-click", modifiers, bounds);
|
||||
}
|
||||
|
||||
void Tray::OnBalloonShow() {
|
||||
Emit("balloon-show");
|
||||
}
|
||||
|
||||
void Tray::OnBalloonClicked() {
|
||||
Emit("balloon-click");
|
||||
}
|
||||
|
||||
void Tray::OnBalloonClosed() {
|
||||
Emit("balloon-closed");
|
||||
}
|
||||
|
||||
void Tray::OnDrop() {
|
||||
Emit("drop");
|
||||
}
|
||||
|
||||
void Tray::OnDropFiles(const std::vector<std::string>& files) {
|
||||
Emit("drop-files", files);
|
||||
}
|
||||
|
||||
void Tray::OnDropText(const std::string& text) {
|
||||
Emit("drop-text", text);
|
||||
}
|
||||
|
||||
void Tray::OnDragEntered() {
|
||||
Emit("drag-enter");
|
||||
}
|
||||
|
||||
void Tray::OnDragExited() {
|
||||
Emit("drag-leave");
|
||||
}
|
||||
|
||||
void Tray::OnDragEnded() {
|
||||
Emit("drag-end");
|
||||
}
|
||||
|
||||
void Tray::SetImage(v8::Isolate* isolate, mate::Handle<NativeImage> image) {
|
||||
#if defined(OS_WIN)
|
||||
tray_icon_->SetImage(image->GetHICON(GetSystemMetrics(SM_CXSMICON)));
|
||||
#else
|
||||
tray_icon_->SetImage(image->image());
|
||||
#endif
|
||||
}
|
||||
|
||||
void Tray::SetPressedImage(v8::Isolate* isolate,
|
||||
mate::Handle<NativeImage> image) {
|
||||
#if defined(OS_WIN)
|
||||
tray_icon_->SetPressedImage(image->GetHICON(GetSystemMetrics(SM_CXSMICON)));
|
||||
#else
|
||||
tray_icon_->SetPressedImage(image->image());
|
||||
#endif
|
||||
}
|
||||
|
||||
void Tray::SetToolTip(const std::string& tool_tip) {
|
||||
tray_icon_->SetToolTip(tool_tip);
|
||||
}
|
||||
|
||||
void Tray::SetTitle(const std::string& title) {
|
||||
tray_icon_->SetTitle(title);
|
||||
}
|
||||
|
||||
void Tray::SetHighlightMode(TrayIcon::HighlightMode mode) {
|
||||
tray_icon_->SetHighlightMode(mode);
|
||||
}
|
||||
|
||||
void Tray::DisplayBalloon(mate::Arguments* args,
|
||||
const mate::Dictionary& options) {
|
||||
mate::Handle<NativeImage> icon;
|
||||
options.Get("icon", &icon);
|
||||
base::string16 title, content;
|
||||
if (!options.Get("title", &title) ||
|
||||
!options.Get("content", &content)) {
|
||||
args->ThrowError("'title' and 'content' must be defined");
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(OS_WIN)
|
||||
tray_icon_->DisplayBalloon(
|
||||
icon.IsEmpty() ? NULL : icon->GetHICON(GetSystemMetrics(SM_CXSMICON)),
|
||||
title, content);
|
||||
#else
|
||||
tray_icon_->DisplayBalloon(
|
||||
icon.IsEmpty() ? gfx::Image() : icon->image(), title, content);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Tray::PopUpContextMenu(mate::Arguments* args) {
|
||||
mate::Handle<Menu> menu;
|
||||
args->GetNext(&menu);
|
||||
gfx::Point pos;
|
||||
args->GetNext(&pos);
|
||||
tray_icon_->PopUpContextMenu(pos, menu.IsEmpty() ? nullptr : menu->model());
|
||||
}
|
||||
|
||||
void Tray::SetContextMenu(v8::Isolate* isolate, mate::Handle<Menu> menu) {
|
||||
menu_.Reset(isolate, menu.ToV8());
|
||||
tray_icon_->SetContextMenu(menu->model());
|
||||
}
|
||||
|
||||
gfx::Rect Tray::GetBounds() {
|
||||
return tray_icon_->GetBounds();
|
||||
}
|
||||
|
||||
// static
|
||||
void Tray::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "Tray"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.MakeDestroyable()
|
||||
.SetMethod("setImage", &Tray::SetImage)
|
||||
.SetMethod("setPressedImage", &Tray::SetPressedImage)
|
||||
.SetMethod("setToolTip", &Tray::SetToolTip)
|
||||
.SetMethod("setTitle", &Tray::SetTitle)
|
||||
.SetMethod("setHighlightMode", &Tray::SetHighlightMode)
|
||||
.SetMethod("displayBalloon", &Tray::DisplayBalloon)
|
||||
.SetMethod("popUpContextMenu", &Tray::PopUpContextMenu)
|
||||
.SetMethod("setContextMenu", &Tray::SetContextMenu)
|
||||
.SetMethod("getBounds", &Tray::GetBounds);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
using atom::api::Tray;
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
Tray::SetConstructor(isolate, base::Bind(&Tray::New));
|
||||
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("Tray", Tray::GetConstructor(isolate)->GetFunction());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_tray, Initialize)
|
||||
84
atom/browser/api/atom_api_tray.h
Normal file
84
atom/browser/api/atom_api_tray.h
Normal file
@@ -0,0 +1,84 @@
|
||||
// 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_TRAY_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_TRAY_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "atom/browser/ui/tray_icon.h"
|
||||
#include "atom/browser/ui/tray_icon_observer.h"
|
||||
#include "native_mate/handle.h"
|
||||
|
||||
namespace gfx {
|
||||
class Image;
|
||||
}
|
||||
|
||||
namespace mate {
|
||||
class Arguments;
|
||||
class Dictionary;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
class TrayIcon;
|
||||
|
||||
namespace api {
|
||||
|
||||
class Menu;
|
||||
class NativeImage;
|
||||
|
||||
class Tray : public mate::TrackableObject<Tray>,
|
||||
public TrayIconObserver {
|
||||
public:
|
||||
static mate::WrappableBase* New(mate::Handle<NativeImage> image,
|
||||
mate::Arguments* args);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
protected:
|
||||
Tray(v8::Isolate* isolate, v8::Local<v8::Object> wrapper,
|
||||
mate::Handle<NativeImage> image);
|
||||
~Tray() override;
|
||||
|
||||
// TrayIconObserver:
|
||||
void OnClicked(const gfx::Rect& bounds, int modifiers) override;
|
||||
void OnDoubleClicked(const gfx::Rect& bounds, int modifiers) override;
|
||||
void OnRightClicked(const gfx::Rect& bounds, int modifiers) override;
|
||||
void OnBalloonShow() override;
|
||||
void OnBalloonClicked() override;
|
||||
void OnBalloonClosed() override;
|
||||
void OnDrop() override;
|
||||
void OnDropFiles(const std::vector<std::string>& files) override;
|
||||
void OnDropText(const std::string& text) override;
|
||||
void OnDragEntered() override;
|
||||
void OnDragExited() override;
|
||||
void OnDragEnded() override;
|
||||
|
||||
void SetImage(v8::Isolate* isolate, mate::Handle<NativeImage> image);
|
||||
void SetPressedImage(v8::Isolate* isolate, mate::Handle<NativeImage> image);
|
||||
void SetToolTip(const std::string& tool_tip);
|
||||
void SetTitle(const std::string& title);
|
||||
void SetHighlightMode(TrayIcon::HighlightMode mode);
|
||||
void DisplayBalloon(mate::Arguments* args, const mate::Dictionary& options);
|
||||
void PopUpContextMenu(mate::Arguments* args);
|
||||
void SetContextMenu(v8::Isolate* isolate, mate::Handle<Menu> menu);
|
||||
gfx::Rect GetBounds();
|
||||
|
||||
private:
|
||||
v8::Global<v8::Object> menu_;
|
||||
std::unique_ptr<TrayIcon> tray_icon_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Tray);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_TRAY_H_
|
||||
448
atom/browser/api/atom_api_url_request.cc
Normal file
448
atom/browser/api/atom_api_url_request.cc
Normal file
@@ -0,0 +1,448 @@
|
||||
// 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_url_request.h"
|
||||
#include <string>
|
||||
#include "atom/browser/api/atom_api_session.h"
|
||||
#include "atom/browser/net/atom_url_request.h"
|
||||
#include "atom/common/api/event_emitter_caller.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/net_converter.h"
|
||||
#include "atom/common/native_mate_converters/string16_converter.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
namespace mate {
|
||||
|
||||
template <>
|
||||
struct Converter<scoped_refptr<const net::IOBufferWithSize>> {
|
||||
static v8::Local<v8::Value> ToV8(
|
||||
v8::Isolate* isolate,
|
||||
scoped_refptr<const net::IOBufferWithSize> buffer) {
|
||||
return node::Buffer::Copy(isolate, buffer->data(), buffer->size())
|
||||
.ToLocalChecked();
|
||||
}
|
||||
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
scoped_refptr<const net::IOBufferWithSize>* out) {
|
||||
auto size = node::Buffer::Length(val);
|
||||
|
||||
if (size == 0) {
|
||||
// Support conversion from empty buffer. A use case is
|
||||
// a GET request without body.
|
||||
// Since zero-sized IOBuffer(s) are not supported, we set the
|
||||
// out pointer to null.
|
||||
*out = nullptr;
|
||||
return true;
|
||||
}
|
||||
auto data = node::Buffer::Data(val);
|
||||
if (!data) {
|
||||
// This is an error as size is positive but data is null.
|
||||
return false;
|
||||
}
|
||||
|
||||
*out = new net::IOBufferWithSize(size);
|
||||
// We do a deep copy. We could have used Buffer's internal memory
|
||||
// but that is much more complicated to be properly handled.
|
||||
memcpy((*out)->data(), data, size);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
namespace atom {
|
||||
namespace api {
|
||||
|
||||
template <typename Flags>
|
||||
URLRequest::StateBase<Flags>::StateBase(Flags initialState)
|
||||
: state_(initialState) {}
|
||||
|
||||
template <typename Flags>
|
||||
void URLRequest::StateBase<Flags>::SetFlag(Flags flag) {
|
||||
state_ =
|
||||
static_cast<Flags>(static_cast<int>(state_) | static_cast<int>(flag));
|
||||
}
|
||||
|
||||
template <typename Flags>
|
||||
bool URLRequest::StateBase<Flags>::operator==(Flags flag) const {
|
||||
return state_ == flag;
|
||||
}
|
||||
|
||||
template <typename Flags>
|
||||
bool URLRequest::StateBase<Flags>::IsFlagSet(Flags flag) const {
|
||||
return static_cast<int>(state_) & static_cast<int>(flag);
|
||||
}
|
||||
|
||||
URLRequest::RequestState::RequestState()
|
||||
: StateBase(RequestStateFlags::kNotStarted) {}
|
||||
|
||||
bool URLRequest::RequestState::NotStarted() const {
|
||||
return *this == RequestStateFlags::kNotStarted;
|
||||
}
|
||||
|
||||
bool URLRequest::RequestState::Started() const {
|
||||
return IsFlagSet(RequestStateFlags::kStarted);
|
||||
}
|
||||
|
||||
bool URLRequest::RequestState::Finished() const {
|
||||
return IsFlagSet(RequestStateFlags::kFinished);
|
||||
}
|
||||
|
||||
bool URLRequest::RequestState::Canceled() const {
|
||||
return IsFlagSet(RequestStateFlags::kCanceled);
|
||||
}
|
||||
|
||||
bool URLRequest::RequestState::Failed() const {
|
||||
return IsFlagSet(RequestStateFlags::kFailed);
|
||||
}
|
||||
|
||||
bool URLRequest::RequestState::Closed() const {
|
||||
return IsFlagSet(RequestStateFlags::kClosed);
|
||||
}
|
||||
|
||||
URLRequest::ResponseState::ResponseState()
|
||||
: StateBase(ResponseStateFlags::kNotStarted) {}
|
||||
|
||||
bool URLRequest::ResponseState::NotStarted() const {
|
||||
return *this == ResponseStateFlags::kNotStarted;
|
||||
}
|
||||
|
||||
bool URLRequest::ResponseState::Started() const {
|
||||
return IsFlagSet(ResponseStateFlags::kStarted);
|
||||
}
|
||||
|
||||
bool URLRequest::ResponseState::Ended() const {
|
||||
return IsFlagSet(ResponseStateFlags::kEnded);
|
||||
}
|
||||
|
||||
bool URLRequest::ResponseState::Failed() const {
|
||||
return IsFlagSet(ResponseStateFlags::kFailed);
|
||||
}
|
||||
|
||||
URLRequest::URLRequest(v8::Isolate* isolate, v8::Local<v8::Object> wrapper) {
|
||||
InitWith(isolate, wrapper);
|
||||
}
|
||||
|
||||
URLRequest::~URLRequest() {
|
||||
// A request has been created in JS, it was not used and then
|
||||
// it got collected, no close event to cleanup, only destructor
|
||||
// is called.
|
||||
if (atom_request_) {
|
||||
atom_request_->Terminate();
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
mate::WrappableBase* URLRequest::New(mate::Arguments* args) {
|
||||
auto isolate = args->isolate();
|
||||
v8::Local<v8::Object> options;
|
||||
args->GetNext(&options);
|
||||
mate::Dictionary dict(isolate, options);
|
||||
std::string method;
|
||||
dict.Get("method", &method);
|
||||
std::string url;
|
||||
dict.Get("url", &url);
|
||||
std::string partition;
|
||||
mate::Handle<api::Session> session;
|
||||
if (dict.Get("session", &session)) {
|
||||
} else if (dict.Get("partition", &partition)) {
|
||||
session = Session::FromPartition(isolate, partition);
|
||||
} else {
|
||||
// Use the default session if not specified.
|
||||
session = Session::FromPartition(isolate, "");
|
||||
}
|
||||
auto browser_context = session->browser_context();
|
||||
auto api_url_request = new URLRequest(args->isolate(), args->GetThis());
|
||||
auto atom_url_request =
|
||||
AtomURLRequest::Create(browser_context, method, url, api_url_request);
|
||||
|
||||
api_url_request->atom_request_ = atom_url_request;
|
||||
|
||||
return api_url_request;
|
||||
}
|
||||
|
||||
// static
|
||||
void URLRequest::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "URLRequest"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
// Request API
|
||||
.MakeDestroyable()
|
||||
.SetMethod("write", &URLRequest::Write)
|
||||
.SetMethod("cancel", &URLRequest::Cancel)
|
||||
.SetMethod("setExtraHeader", &URLRequest::SetExtraHeader)
|
||||
.SetMethod("removeExtraHeader", &URLRequest::RemoveExtraHeader)
|
||||
.SetMethod("setChunkedUpload", &URLRequest::SetChunkedUpload)
|
||||
.SetMethod("_setLoadFlags", &URLRequest::SetLoadFlags)
|
||||
.SetProperty("notStarted", &URLRequest::NotStarted)
|
||||
.SetProperty("finished", &URLRequest::Finished)
|
||||
// Response APi
|
||||
.SetProperty("statusCode", &URLRequest::StatusCode)
|
||||
.SetProperty("statusMessage", &URLRequest::StatusMessage)
|
||||
.SetProperty("rawResponseHeaders", &URLRequest::RawResponseHeaders)
|
||||
.SetProperty("httpVersionMajor", &URLRequest::ResponseHttpVersionMajor)
|
||||
.SetProperty("httpVersionMinor", &URLRequest::ResponseHttpVersionMinor);
|
||||
}
|
||||
|
||||
bool URLRequest::NotStarted() const {
|
||||
return request_state_.NotStarted();
|
||||
}
|
||||
|
||||
bool URLRequest::Finished() const {
|
||||
return request_state_.Finished();
|
||||
}
|
||||
|
||||
bool URLRequest::Canceled() const {
|
||||
return request_state_.Canceled();
|
||||
}
|
||||
|
||||
bool URLRequest::Write(scoped_refptr<const net::IOBufferWithSize> buffer,
|
||||
bool is_last) {
|
||||
if (request_state_.Canceled() || request_state_.Failed() ||
|
||||
request_state_.Finished() || request_state_.Closed()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (request_state_.NotStarted()) {
|
||||
request_state_.SetFlag(RequestStateFlags::kStarted);
|
||||
// Pin on first write.
|
||||
Pin();
|
||||
}
|
||||
|
||||
if (is_last) {
|
||||
request_state_.SetFlag(RequestStateFlags::kFinished);
|
||||
EmitRequestEvent(true, "finish");
|
||||
}
|
||||
|
||||
DCHECK(atom_request_);
|
||||
if (atom_request_) {
|
||||
return atom_request_->Write(buffer, is_last);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void URLRequest::Cancel() {
|
||||
if (request_state_.Canceled() || request_state_.Closed()) {
|
||||
// Cancel only once.
|
||||
return;
|
||||
}
|
||||
|
||||
// Mark as canceled.
|
||||
request_state_.SetFlag(RequestStateFlags::kCanceled);
|
||||
|
||||
DCHECK(atom_request_);
|
||||
if (atom_request_ && request_state_.Started()) {
|
||||
// Really cancel if it was started.
|
||||
atom_request_->Cancel();
|
||||
}
|
||||
EmitRequestEvent(true, "abort");
|
||||
|
||||
if (response_state_.Started() && !response_state_.Ended()) {
|
||||
EmitResponseEvent(true, "aborted");
|
||||
}
|
||||
Close();
|
||||
}
|
||||
|
||||
bool URLRequest::SetExtraHeader(const std::string& name,
|
||||
const std::string& value) {
|
||||
// Request state must be in the initial non started state.
|
||||
if (!request_state_.NotStarted()) {
|
||||
// Cannot change headers after send.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!net::HttpUtil::IsValidHeaderName(name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!net::HttpUtil::IsValidHeaderValue(value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DCHECK(atom_request_);
|
||||
if (atom_request_) {
|
||||
atom_request_->SetExtraHeader(name, value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void URLRequest::RemoveExtraHeader(const std::string& name) {
|
||||
// State must be equal to not started.
|
||||
if (!request_state_.NotStarted()) {
|
||||
// Cannot change headers after send.
|
||||
return;
|
||||
}
|
||||
DCHECK(atom_request_);
|
||||
if (atom_request_) {
|
||||
atom_request_->RemoveExtraHeader(name);
|
||||
}
|
||||
}
|
||||
|
||||
void URLRequest::SetChunkedUpload(bool is_chunked_upload) {
|
||||
// State must be equal to not started.
|
||||
if (!request_state_.NotStarted()) {
|
||||
// Cannot change headers after send.
|
||||
return;
|
||||
}
|
||||
DCHECK(atom_request_);
|
||||
if (atom_request_) {
|
||||
atom_request_->SetChunkedUpload(is_chunked_upload);
|
||||
}
|
||||
}
|
||||
|
||||
void URLRequest::SetLoadFlags(int flags) {
|
||||
// State must be equal to not started.
|
||||
if (!request_state_.NotStarted()) {
|
||||
// Cannot change load flags after start.
|
||||
return;
|
||||
}
|
||||
DCHECK(atom_request_);
|
||||
if (atom_request_) {
|
||||
atom_request_->SetLoadFlags(flags);
|
||||
}
|
||||
}
|
||||
|
||||
void URLRequest::OnAuthenticationRequired(
|
||||
scoped_refptr<const net::AuthChallengeInfo> auth_info) {
|
||||
if (request_state_.Canceled() || request_state_.Closed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
DCHECK(atom_request_);
|
||||
if (!atom_request_) {
|
||||
return;
|
||||
}
|
||||
|
||||
Emit("login", auth_info.get(),
|
||||
base::Bind(&AtomURLRequest::PassLoginInformation, atom_request_));
|
||||
}
|
||||
|
||||
void URLRequest::OnResponseStarted(
|
||||
scoped_refptr<net::HttpResponseHeaders> response_headers) {
|
||||
if (request_state_.Canceled() || request_state_.Failed() ||
|
||||
request_state_.Closed()) {
|
||||
// Don't emit any event after request cancel.
|
||||
return;
|
||||
}
|
||||
response_headers_ = response_headers;
|
||||
response_state_.SetFlag(ResponseStateFlags::kStarted);
|
||||
Emit("response");
|
||||
}
|
||||
|
||||
void URLRequest::OnResponseData(
|
||||
scoped_refptr<const net::IOBufferWithSize> buffer) {
|
||||
if (request_state_.Canceled() || request_state_.Closed() ||
|
||||
request_state_.Failed() || response_state_.Failed()) {
|
||||
// In case we received an unexpected event from Chromium net,
|
||||
// don't emit any data event after request cancel/error/close.
|
||||
return;
|
||||
}
|
||||
if (!buffer || !buffer->data() || !buffer->size()) {
|
||||
return;
|
||||
}
|
||||
Emit("data", buffer);
|
||||
}
|
||||
|
||||
void URLRequest::OnResponseCompleted() {
|
||||
if (request_state_.Canceled() || request_state_.Closed() ||
|
||||
request_state_.Failed() || response_state_.Failed()) {
|
||||
// In case we received an unexpected event from Chromium net,
|
||||
// don't emit any data event after request cancel/error/close.
|
||||
return;
|
||||
}
|
||||
response_state_.SetFlag(ResponseStateFlags::kEnded);
|
||||
Emit("end");
|
||||
Close();
|
||||
}
|
||||
|
||||
void URLRequest::OnError(const std::string& error, bool isRequestError) {
|
||||
auto error_object = v8::Exception::Error(mate::StringToV8(isolate(), error));
|
||||
if (isRequestError) {
|
||||
request_state_.SetFlag(RequestStateFlags::kFailed);
|
||||
EmitRequestEvent(false, "error", error_object);
|
||||
} else {
|
||||
response_state_.SetFlag(ResponseStateFlags::kFailed);
|
||||
EmitResponseEvent(false, "error", error_object);
|
||||
}
|
||||
Close();
|
||||
}
|
||||
|
||||
int URLRequest::StatusCode() const {
|
||||
if (response_headers_) {
|
||||
return response_headers_->response_code();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::string URLRequest::StatusMessage() const {
|
||||
std::string result;
|
||||
if (response_headers_) {
|
||||
result = response_headers_->GetStatusText();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
net::HttpResponseHeaders* URLRequest::RawResponseHeaders() const {
|
||||
return response_headers_.get();
|
||||
}
|
||||
|
||||
uint32_t URLRequest::ResponseHttpVersionMajor() const {
|
||||
if (response_headers_) {
|
||||
return response_headers_->GetHttpVersion().major_value();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t URLRequest::ResponseHttpVersionMinor() const {
|
||||
if (response_headers_) {
|
||||
return response_headers_->GetHttpVersion().minor_value();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void URLRequest::Close() {
|
||||
if (!request_state_.Closed()) {
|
||||
request_state_.SetFlag(RequestStateFlags::kClosed);
|
||||
if (response_state_.Started()) {
|
||||
// Emit a close event if we really have a response object.
|
||||
EmitResponseEvent(true, "close");
|
||||
}
|
||||
EmitRequestEvent(true, "close");
|
||||
}
|
||||
Unpin();
|
||||
if (atom_request_) {
|
||||
// A request has been created in JS, used and then it ended.
|
||||
// We release unneeded net resources.
|
||||
atom_request_->Terminate();
|
||||
}
|
||||
atom_request_ = nullptr;
|
||||
}
|
||||
|
||||
void URLRequest::Pin() {
|
||||
if (wrapper_.IsEmpty()) {
|
||||
wrapper_.Reset(isolate(), GetWrapper());
|
||||
}
|
||||
}
|
||||
|
||||
void URLRequest::Unpin() {
|
||||
wrapper_.Reset();
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void URLRequest::EmitRequestEvent(Args... args) {
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
mate::CustomEmit(isolate(), GetWrapper(), "_emitRequestEvent", args...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void URLRequest::EmitResponseEvent(Args... args) {
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
mate::CustomEmit(isolate(), GetWrapper(), "_emitResponseEvent", args...);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
207
atom/browser/api/atom_api_url_request.h
Normal file
207
atom/browser/api/atom_api_url_request.h
Normal file
@@ -0,0 +1,207 @@
|
||||
// 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_URL_REQUEST_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_URL_REQUEST_H_
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include "atom/browser/api/event_emitter.h"
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "native_mate/wrappable_base.h"
|
||||
#include "net/base/auth.h"
|
||||
#include "net/base/io_buffer.h"
|
||||
#include "net/http/http_response_headers.h"
|
||||
#include "net/url_request/url_request_context.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomURLRequest;
|
||||
|
||||
namespace api {
|
||||
|
||||
//
|
||||
// The URLRequest class implements the V8 binding between the JavaScript API
|
||||
// and Chromium native net library. It is responsible for handling HTTP/HTTPS
|
||||
// requests.
|
||||
//
|
||||
// The current class provides only the binding layer. Two other JavaScript
|
||||
// classes (ClientRequest and IncomingMessage) in the net module provide the
|
||||
// final API, including some state management and arguments validation.
|
||||
//
|
||||
// URLRequest's methods fall into two main categories: command and event
|
||||
// methods. They are always executed on the Browser's UI thread.
|
||||
// Command methods are called directly from JavaScript code via the API defined
|
||||
// in BuildPrototype. A command method is generally implemented by forwarding
|
||||
// the call to a corresponding method on AtomURLRequest which does the
|
||||
// synchronization on the Browser IO thread. The latter then calls into Chromium
|
||||
// net library. On the other hand, net library events originate on the IO
|
||||
// thread in AtomURLRequest and are synchronized back on the UI thread, then
|
||||
// forwarded to a corresponding event method in URLRequest and then to
|
||||
// JavaScript via the EmitRequestEvent/EmitResponseEvent helpers.
|
||||
//
|
||||
// URLRequest lifetime management: we followed the Wrapper/Wrappable pattern
|
||||
// defined in native_mate. However, we augment that pattern with a pin/unpin
|
||||
// mechanism. The main reason is that we want the JS API to provide a similar
|
||||
// lifetime guarantees as the XMLHttpRequest.
|
||||
// https://xhr.spec.whatwg.org/#garbage-collection
|
||||
//
|
||||
// The primary motivation is to not garbage collect a URLInstance as long as the
|
||||
// object is emitting network events. For instance, in the following JS code
|
||||
//
|
||||
// (function() {
|
||||
// let request = new URLRequest(...);
|
||||
// request.on('response', (response)=>{
|
||||
// response.on('data', (data) = > {
|
||||
// console.log(data.toString());
|
||||
// });
|
||||
// });
|
||||
// })();
|
||||
//
|
||||
// we still want data to be logged even if the response/request objects are n
|
||||
// more referenced in JavaScript.
|
||||
//
|
||||
// Binding by simply following the native_mate Wrapper/Wrappable pattern will
|
||||
// delete the URLRequest object when the corresponding JS object is collected.
|
||||
// The v8 handle is a private member in WrappableBase and it is always weak,
|
||||
// there is no way to make it strong without changing native_mate.
|
||||
// The solution we implement consists of maintaining some kind of state that
|
||||
// prevents collection of JS wrappers as long as the request is emitting network
|
||||
// events. At initialization, the object is unpinned. When the request starts,
|
||||
// it is pinned. When no more events would be emitted, the object is unpinned
|
||||
// and lifetime is again managed by the standard native mate Wrapper/Wrappable
|
||||
// pattern.
|
||||
//
|
||||
// pin/unpin: are implemented by constructing/reseting a V8 strong persistent
|
||||
// handle.
|
||||
//
|
||||
// The URLRequest/AtmURLRequest interaction could have been implemented in a
|
||||
// single class. However, it implies that the resulting class lifetime will be
|
||||
// managed by two conflicting mechanisms: JavaScript garbage collection and
|
||||
// Chromium reference counting. Reasoning about lifetime issues become much
|
||||
// more complex.
|
||||
//
|
||||
// We chose to split the implementation into two classes linked via a
|
||||
// reference counted/raw pointers. A URLRequest instance is deleted if it is
|
||||
// unpinned and the corresponding JS wrapper object is garbage collected. On the
|
||||
// other hand, an AtmURLRequest instance lifetime is totally governed by
|
||||
// reference counting.
|
||||
//
|
||||
class URLRequest : public mate::EventEmitter<URLRequest> {
|
||||
public:
|
||||
static mate::WrappableBase* New(mate::Arguments* args);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
// Methods for reporting events into JavaScript.
|
||||
void OnAuthenticationRequired(
|
||||
scoped_refptr<const net::AuthChallengeInfo> auth_info);
|
||||
void OnResponseStarted(
|
||||
scoped_refptr<net::HttpResponseHeaders> response_headers);
|
||||
void OnResponseData(scoped_refptr<const net::IOBufferWithSize> data);
|
||||
void OnResponseCompleted();
|
||||
void OnError(const std::string& error, bool isRequestError);
|
||||
|
||||
protected:
|
||||
explicit URLRequest(v8::Isolate* isolate, v8::Local<v8::Object> wrapper);
|
||||
~URLRequest() override;
|
||||
|
||||
private:
|
||||
template <typename Flags>
|
||||
class StateBase {
|
||||
public:
|
||||
void SetFlag(Flags flag);
|
||||
|
||||
protected:
|
||||
explicit StateBase(Flags initialState);
|
||||
bool operator==(Flags flag) const;
|
||||
bool IsFlagSet(Flags flag) const;
|
||||
|
||||
private:
|
||||
Flags state_;
|
||||
};
|
||||
|
||||
enum class RequestStateFlags {
|
||||
kNotStarted = 0x0,
|
||||
kStarted = 0x1,
|
||||
kFinished = 0x2,
|
||||
kCanceled = 0x4,
|
||||
kFailed = 0x8,
|
||||
kClosed = 0x10
|
||||
};
|
||||
|
||||
class RequestState : public StateBase<RequestStateFlags> {
|
||||
public:
|
||||
RequestState();
|
||||
bool NotStarted() const;
|
||||
bool Started() const;
|
||||
bool Finished() const;
|
||||
bool Canceled() const;
|
||||
bool Failed() const;
|
||||
bool Closed() const;
|
||||
};
|
||||
|
||||
enum class ResponseStateFlags {
|
||||
kNotStarted = 0x0,
|
||||
kStarted = 0x1,
|
||||
kEnded = 0x2,
|
||||
kFailed = 0x4
|
||||
};
|
||||
|
||||
class ResponseState : public StateBase<ResponseStateFlags> {
|
||||
public:
|
||||
ResponseState();
|
||||
bool NotStarted() const;
|
||||
bool Started() const;
|
||||
bool Ended() const;
|
||||
bool Canceled() const;
|
||||
bool Failed() const;
|
||||
bool Closed() const;
|
||||
};
|
||||
|
||||
bool NotStarted() const;
|
||||
bool Finished() const;
|
||||
bool Canceled() const;
|
||||
bool Failed() const;
|
||||
bool Write(scoped_refptr<const net::IOBufferWithSize> buffer, bool is_last);
|
||||
void Cancel();
|
||||
bool SetExtraHeader(const std::string& name, const std::string& value);
|
||||
void RemoveExtraHeader(const std::string& name);
|
||||
void SetChunkedUpload(bool is_chunked_upload);
|
||||
void SetLoadFlags(int flags);
|
||||
|
||||
int StatusCode() const;
|
||||
std::string StatusMessage() const;
|
||||
net::HttpResponseHeaders* RawResponseHeaders() const;
|
||||
uint32_t ResponseHttpVersionMajor() const;
|
||||
uint32_t ResponseHttpVersionMinor() const;
|
||||
|
||||
void Close();
|
||||
void Pin();
|
||||
void Unpin();
|
||||
template <typename... Args>
|
||||
void EmitRequestEvent(Args... args);
|
||||
template <typename... Args>
|
||||
void EmitResponseEvent(Args... args);
|
||||
|
||||
scoped_refptr<AtomURLRequest> atom_request_;
|
||||
RequestState request_state_;
|
||||
ResponseState response_state_;
|
||||
|
||||
// Used to implement pin/unpin.
|
||||
v8::Global<v8::Object> wrapper_;
|
||||
scoped_refptr<net::HttpResponseHeaders> response_headers_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(URLRequest);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_URL_REQUEST_H_
|
||||
1693
atom/browser/api/atom_api_web_contents.cc
Normal file
1693
atom/browser/api/atom_api_web_contents.cc
Normal file
File diff suppressed because it is too large
Load Diff
370
atom/browser/api/atom_api_web_contents.h
Normal file
370
atom/browser/api/atom_api_web_contents.h
Normal file
@@ -0,0 +1,370 @@
|
||||
// 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_WEB_CONTENTS_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_WEB_CONTENTS_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/browser/api/frame_subscriber.h"
|
||||
#include "atom/browser/api/save_page_handler.h"
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "atom/browser/common_web_contents_delegate.h"
|
||||
#include "content/common/cursors/webcursor.h"
|
||||
#include "content/public/browser/web_contents_observer.h"
|
||||
#include "content/public/common/favicon_url.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "ui/gfx/image/image.h"
|
||||
|
||||
namespace blink {
|
||||
struct WebDeviceEmulationParams;
|
||||
}
|
||||
|
||||
namespace brightray {
|
||||
class InspectableWebContents;
|
||||
}
|
||||
|
||||
namespace content {
|
||||
class ResourceRequestBodyImpl;
|
||||
}
|
||||
|
||||
namespace mate {
|
||||
class Arguments;
|
||||
class Dictionary;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
struct SetSizeParams;
|
||||
class AtomBrowserContext;
|
||||
class WebViewGuestDelegate;
|
||||
|
||||
namespace api {
|
||||
|
||||
class WebContents : public mate::TrackableObject<WebContents>,
|
||||
public CommonWebContentsDelegate,
|
||||
public content::WebContentsObserver {
|
||||
public:
|
||||
enum Type {
|
||||
BACKGROUND_PAGE, // A DevTools extension background page.
|
||||
BROWSER_WINDOW, // Used by BrowserWindow.
|
||||
REMOTE, // Thin wrap around an existing WebContents.
|
||||
WEB_VIEW, // Used by <webview>.
|
||||
OFF_SCREEN, // Used for offscreen rendering
|
||||
};
|
||||
|
||||
// For node.js callback function type: function(error, buffer)
|
||||
using PrintToPDFCallback =
|
||||
base::Callback<void(v8::Local<v8::Value>, v8::Local<v8::Value>)>;
|
||||
|
||||
// Create from an existing WebContents.
|
||||
static mate::Handle<WebContents> CreateFrom(
|
||||
v8::Isolate* isolate, content::WebContents* web_contents);
|
||||
static mate::Handle<WebContents> CreateFrom(
|
||||
v8::Isolate* isolate, content::WebContents* web_contents, Type type);
|
||||
|
||||
// Create a new WebContents.
|
||||
static mate::Handle<WebContents> Create(
|
||||
v8::Isolate* isolate, const mate::Dictionary& options);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
int64_t GetID() const;
|
||||
int GetProcessID() const;
|
||||
Type GetType() const;
|
||||
bool Equal(const WebContents* web_contents) const;
|
||||
void LoadURL(const GURL& url, const mate::Dictionary& options);
|
||||
void DownloadURL(const GURL& url);
|
||||
GURL GetURL() const;
|
||||
base::string16 GetTitle() const;
|
||||
bool IsLoading() const;
|
||||
bool IsLoadingMainFrame() const;
|
||||
bool IsWaitingForResponse() const;
|
||||
void Stop();
|
||||
void ReloadIgnoringCache();
|
||||
void GoBack();
|
||||
void GoForward();
|
||||
void GoToOffset(int offset);
|
||||
bool IsCrashed() const;
|
||||
void SetUserAgent(const std::string& user_agent, mate::Arguments* args);
|
||||
std::string GetUserAgent();
|
||||
void InsertCSS(const std::string& css);
|
||||
bool SavePage(const base::FilePath& full_file_path,
|
||||
const content::SavePageType& save_type,
|
||||
const SavePageHandler::SavePageCallback& callback);
|
||||
void OpenDevTools(mate::Arguments* args);
|
||||
void CloseDevTools();
|
||||
bool IsDevToolsOpened();
|
||||
bool IsDevToolsFocused();
|
||||
void ToggleDevTools();
|
||||
void EnableDeviceEmulation(const blink::WebDeviceEmulationParams& params);
|
||||
void DisableDeviceEmulation();
|
||||
void InspectElement(int x, int y);
|
||||
void InspectServiceWorker();
|
||||
void HasServiceWorker(const base::Callback<void(bool)>&);
|
||||
void UnregisterServiceWorker(const base::Callback<void(bool)>&);
|
||||
void SetAudioMuted(bool muted);
|
||||
bool IsAudioMuted();
|
||||
void Print(mate::Arguments* args);
|
||||
void SetEmbedder(const WebContents* embedder);
|
||||
|
||||
// Print current page as PDF.
|
||||
void PrintToPDF(const base::DictionaryValue& setting,
|
||||
const PrintToPDFCallback& callback);
|
||||
|
||||
// DevTools workspace api.
|
||||
void AddWorkSpace(mate::Arguments* args, const base::FilePath& path);
|
||||
void RemoveWorkSpace(mate::Arguments* args, const base::FilePath& path);
|
||||
|
||||
// Editing commands.
|
||||
void Undo();
|
||||
void Redo();
|
||||
void Cut();
|
||||
void Copy();
|
||||
void Paste();
|
||||
void PasteAndMatchStyle();
|
||||
void Delete();
|
||||
void SelectAll();
|
||||
void Unselect();
|
||||
void Replace(const base::string16& word);
|
||||
void ReplaceMisspelling(const base::string16& word);
|
||||
uint32_t FindInPage(mate::Arguments* args);
|
||||
void StopFindInPage(content::StopFindAction action);
|
||||
void ShowDefinitionForSelection();
|
||||
void CopyImageAt(int x, int y);
|
||||
|
||||
// Focus.
|
||||
void Focus();
|
||||
bool IsFocused() const;
|
||||
void TabTraverse(bool reverse);
|
||||
|
||||
// Send messages to browser.
|
||||
bool SendIPCMessage(bool all_frames,
|
||||
const base::string16& channel,
|
||||
const base::ListValue& args);
|
||||
|
||||
// Send WebInputEvent to the page.
|
||||
void SendInputEvent(v8::Isolate* isolate, v8::Local<v8::Value> input_event);
|
||||
|
||||
// Subscribe to the frame updates.
|
||||
void BeginFrameSubscription(mate::Arguments* args);
|
||||
void EndFrameSubscription();
|
||||
|
||||
// Dragging native items.
|
||||
void StartDrag(const mate::Dictionary& item, mate::Arguments* args);
|
||||
|
||||
// Captures the page with |rect|, |callback| would be called when capturing is
|
||||
// done.
|
||||
void CapturePage(mate::Arguments* args);
|
||||
|
||||
// Methods for creating <webview>.
|
||||
void SetSize(const SetSizeParams& params);
|
||||
bool IsGuest() const;
|
||||
|
||||
// Methods for offscreen rendering
|
||||
bool IsOffScreen() const;
|
||||
void OnPaint(const gfx::Rect& dirty_rect, const SkBitmap& bitmap);
|
||||
void StartPainting();
|
||||
void StopPainting();
|
||||
bool IsPainting() const;
|
||||
void SetFrameRate(int frame_rate);
|
||||
int GetFrameRate() const;
|
||||
void Invalidate();
|
||||
|
||||
// Callback triggered on permission response.
|
||||
void OnEnterFullscreenModeForTab(content::WebContents* source,
|
||||
const GURL& origin,
|
||||
bool allowed);
|
||||
|
||||
// Create window with the given disposition.
|
||||
void OnCreateWindow(
|
||||
const GURL& target_url,
|
||||
const std::string& frame_name,
|
||||
WindowOpenDisposition disposition,
|
||||
const std::vector<base::string16>& features,
|
||||
const scoped_refptr<content::ResourceRequestBodyImpl>& body);
|
||||
|
||||
// Returns the web preferences of current WebContents.
|
||||
v8::Local<v8::Value> GetWebPreferences(v8::Isolate* isolate);
|
||||
|
||||
// Returns the owner window.
|
||||
v8::Local<v8::Value> GetOwnerBrowserWindow();
|
||||
|
||||
// Properties.
|
||||
int32_t ID() const;
|
||||
v8::Local<v8::Value> Session(v8::Isolate* isolate);
|
||||
content::WebContents* HostWebContents();
|
||||
v8::Local<v8::Value> DevToolsWebContents(v8::Isolate* isolate);
|
||||
v8::Local<v8::Value> Debugger(v8::Isolate* isolate);
|
||||
|
||||
protected:
|
||||
WebContents(v8::Isolate* isolate,
|
||||
content::WebContents* web_contents,
|
||||
Type type);
|
||||
WebContents(v8::Isolate* isolate, const mate::Dictionary& options);
|
||||
~WebContents();
|
||||
|
||||
void InitWithSessionAndOptions(v8::Isolate* isolate,
|
||||
content::WebContents *web_contents,
|
||||
mate::Handle<class Session> session,
|
||||
const mate::Dictionary& options);
|
||||
|
||||
// content::WebContentsDelegate:
|
||||
bool AddMessageToConsole(content::WebContents* source,
|
||||
int32_t level,
|
||||
const base::string16& message,
|
||||
int32_t line_no,
|
||||
const base::string16& source_id) override;
|
||||
void WebContentsCreated(content::WebContents* source_contents,
|
||||
int opener_render_frame_id,
|
||||
const std::string& frame_name,
|
||||
const GURL& target_url,
|
||||
content::WebContents* new_contents) override;
|
||||
void AddNewContents(content::WebContents* source,
|
||||
content::WebContents* new_contents,
|
||||
WindowOpenDisposition disposition,
|
||||
const gfx::Rect& initial_rect,
|
||||
bool user_gesture,
|
||||
bool* was_blocked) override;
|
||||
content::WebContents* OpenURLFromTab(
|
||||
content::WebContents* source,
|
||||
const content::OpenURLParams& params) override;
|
||||
void BeforeUnloadFired(content::WebContents* tab,
|
||||
bool proceed,
|
||||
bool* proceed_to_fire_unload) override;
|
||||
void MoveContents(content::WebContents* source,
|
||||
const gfx::Rect& pos) override;
|
||||
void CloseContents(content::WebContents* source) override;
|
||||
void ActivateContents(content::WebContents* contents) override;
|
||||
void UpdateTargetURL(content::WebContents* source, const GURL& url) override;
|
||||
bool IsPopupOrPanel(const content::WebContents* source) const override;
|
||||
void HandleKeyboardEvent(
|
||||
content::WebContents* source,
|
||||
const content::NativeWebKeyboardEvent& event) override;
|
||||
bool PreHandleKeyboardEvent(content::WebContents* source,
|
||||
const content::NativeWebKeyboardEvent& event,
|
||||
bool* is_keyboard_shortcut) override;
|
||||
void EnterFullscreenModeForTab(content::WebContents* source,
|
||||
const GURL& origin) override;
|
||||
void ExitFullscreenModeForTab(content::WebContents* source) override;
|
||||
void RendererUnresponsive(content::WebContents* source) override;
|
||||
void RendererResponsive(content::WebContents* source) override;
|
||||
bool HandleContextMenu(const content::ContextMenuParams& params) override;
|
||||
bool OnGoToEntryOffset(int offset) override;
|
||||
void FindReply(content::WebContents* web_contents,
|
||||
int request_id,
|
||||
int number_of_matches,
|
||||
const gfx::Rect& selection_rect,
|
||||
int active_match_ordinal,
|
||||
bool final_update) override;
|
||||
bool CheckMediaAccessPermission(
|
||||
content::WebContents* web_contents,
|
||||
const GURL& security_origin,
|
||||
content::MediaStreamType type) override;
|
||||
void RequestMediaAccessPermission(
|
||||
content::WebContents* web_contents,
|
||||
const content::MediaStreamRequest& request,
|
||||
const content::MediaResponseCallback& callback) override;
|
||||
void RequestToLockMouse(
|
||||
content::WebContents* web_contents,
|
||||
bool user_gesture,
|
||||
bool last_unlocked_by_target) override;
|
||||
std::unique_ptr<content::BluetoothChooser> RunBluetoothChooser(
|
||||
content::RenderFrameHost* frame,
|
||||
const content::BluetoothChooser::EventHandler& handler) override;
|
||||
|
||||
// content::WebContentsObserver:
|
||||
void BeforeUnloadFired(const base::TimeTicks& proceed_time) override;
|
||||
void RenderViewCreated(content::RenderViewHost*) override;
|
||||
void RenderViewDeleted(content::RenderViewHost*) override;
|
||||
void RenderProcessGone(base::TerminationStatus status) override;
|
||||
void DocumentLoadedInFrame(
|
||||
content::RenderFrameHost* render_frame_host) override;
|
||||
void DidFinishLoad(content::RenderFrameHost* render_frame_host,
|
||||
const GURL& validated_url) override;
|
||||
void DidFailLoad(content::RenderFrameHost* render_frame_host,
|
||||
const GURL& validated_url,
|
||||
int error_code,
|
||||
const base::string16& error_description,
|
||||
bool was_ignored_by_handler) override;
|
||||
void DidStartLoading() override;
|
||||
void DidStopLoading() override;
|
||||
void DidGetResourceResponseStart(
|
||||
const content::ResourceRequestDetails& details) override;
|
||||
void DidGetRedirectForResourceRequest(
|
||||
content::RenderFrameHost* render_frame_host,
|
||||
const content::ResourceRedirectDetails& details) override;
|
||||
void DidFinishNavigation(
|
||||
content::NavigationHandle* navigation_handle) override;
|
||||
bool OnMessageReceived(const IPC::Message& message) override;
|
||||
void WebContentsDestroyed() override;
|
||||
void NavigationEntryCommitted(
|
||||
const content::LoadCommittedDetails& load_details) override;
|
||||
void TitleWasSet(content::NavigationEntry* entry, bool explicit_set) override;
|
||||
void DidUpdateFaviconURL(
|
||||
const std::vector<content::FaviconURL>& urls) override;
|
||||
void PluginCrashed(const base::FilePath& plugin_path,
|
||||
base::ProcessId plugin_pid) override;
|
||||
void MediaStartedPlaying(const MediaPlayerId& id) override;
|
||||
void MediaStoppedPlaying(const MediaPlayerId& id) override;
|
||||
void DidChangeThemeColor(SkColor theme_color) override;
|
||||
|
||||
// brightray::InspectableWebContentsDelegate:
|
||||
void DevToolsReloadPage() override;
|
||||
|
||||
// brightray::InspectableWebContentsViewDelegate:
|
||||
void DevToolsFocused() override;
|
||||
void DevToolsOpened() override;
|
||||
void DevToolsClosed() override;
|
||||
|
||||
private:
|
||||
AtomBrowserContext* GetBrowserContext() const;
|
||||
|
||||
uint32_t GetNextRequestId() {
|
||||
return ++request_id_;
|
||||
}
|
||||
|
||||
// Called when we receive a CursorChange message from chromium.
|
||||
void OnCursorChange(const content::WebCursor& cursor);
|
||||
|
||||
// Called when received a message from renderer.
|
||||
void OnRendererMessage(const base::string16& channel,
|
||||
const base::ListValue& args);
|
||||
|
||||
// Called when received a synchronous message from renderer.
|
||||
void OnRendererMessageSync(const base::string16& channel,
|
||||
const base::ListValue& args,
|
||||
IPC::Message* message);
|
||||
|
||||
v8::Global<v8::Value> session_;
|
||||
v8::Global<v8::Value> devtools_web_contents_;
|
||||
v8::Global<v8::Value> debugger_;
|
||||
|
||||
std::unique_ptr<WebViewGuestDelegate> guest_delegate_;
|
||||
|
||||
// The host webcontents that may contain this webcontents.
|
||||
WebContents* embedder_;
|
||||
|
||||
// The type of current WebContents.
|
||||
Type type_;
|
||||
|
||||
// Request id used for findInPage request.
|
||||
uint32_t request_id_;
|
||||
|
||||
// Whether background throttling is disabled.
|
||||
bool background_throttling_;
|
||||
|
||||
// Whether to enable devtools.
|
||||
bool enable_devtools_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(WebContents);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_WEB_CONTENTS_H_
|
||||
30
atom/browser/api/atom_api_web_contents_mac.mm
Normal file
30
atom/browser/api/atom_api_web_contents_mac.mm
Normal file
@@ -0,0 +1,30 @@
|
||||
// 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_web_contents.h"
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
bool WebContents::IsFocused() const {
|
||||
auto view = web_contents()->GetRenderWidgetHostView();
|
||||
if (!view) return false;
|
||||
|
||||
if (GetType() != BACKGROUND_PAGE) {
|
||||
auto window = [web_contents()->GetNativeView() window];
|
||||
// On Mac the render widget host view does not lose focus when the window
|
||||
// loses focus so check if the top level window is the key window.
|
||||
if (window && ![window isKeyWindow])
|
||||
return false;
|
||||
}
|
||||
|
||||
return view->HasFocus();
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
122
atom/browser/api/atom_api_web_request.cc
Normal file
122
atom/browser/api/atom_api_web_request.cc
Normal file
@@ -0,0 +1,122 @@
|
||||
// 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_web_request.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/net/atom_network_delegate.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/net_converter.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/object_template_builder.h"
|
||||
|
||||
using content::BrowserThread;
|
||||
|
||||
namespace mate {
|
||||
|
||||
template<>
|
||||
struct Converter<extensions::URLPattern> {
|
||||
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
|
||||
extensions::URLPattern* out) {
|
||||
std::string pattern;
|
||||
if (!ConvertFromV8(isolate, val, &pattern))
|
||||
return false;
|
||||
return out->Parse(pattern) == extensions::URLPattern::PARSE_SUCCESS;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
WebRequest::WebRequest(v8::Isolate* isolate,
|
||||
AtomBrowserContext* browser_context)
|
||||
: browser_context_(browser_context) {
|
||||
Init(isolate);
|
||||
}
|
||||
|
||||
WebRequest::~WebRequest() {
|
||||
}
|
||||
|
||||
template<AtomNetworkDelegate::SimpleEvent type>
|
||||
void WebRequest::SetSimpleListener(mate::Arguments* args) {
|
||||
SetListener<AtomNetworkDelegate::SimpleListener>(
|
||||
&AtomNetworkDelegate::SetSimpleListenerInIO, type, args);
|
||||
}
|
||||
|
||||
template<AtomNetworkDelegate::ResponseEvent type>
|
||||
void WebRequest::SetResponseListener(mate::Arguments* args) {
|
||||
SetListener<AtomNetworkDelegate::ResponseListener>(
|
||||
&AtomNetworkDelegate::SetResponseListenerInIO, type, args);
|
||||
}
|
||||
|
||||
template<typename Listener, typename Method, typename Event>
|
||||
void WebRequest::SetListener(Method method, Event type, mate::Arguments* args) {
|
||||
// { urls }.
|
||||
URLPatterns patterns;
|
||||
mate::Dictionary dict;
|
||||
args->GetNext(&dict) && dict.Get("urls", &patterns);
|
||||
|
||||
// Function or null.
|
||||
v8::Local<v8::Value> value;
|
||||
Listener listener;
|
||||
if (!args->GetNext(&listener) &&
|
||||
!(args->GetNext(&value) && value->IsNull())) {
|
||||
args->ThrowError("Must pass null or a Function");
|
||||
return;
|
||||
}
|
||||
|
||||
auto delegate = browser_context_->network_delegate();
|
||||
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(method, base::Unretained(delegate), type,
|
||||
patterns, listener));
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<WebRequest> WebRequest::Create(
|
||||
v8::Isolate* isolate,
|
||||
AtomBrowserContext* browser_context) {
|
||||
return mate::CreateHandle(isolate, new WebRequest(isolate, browser_context));
|
||||
}
|
||||
|
||||
// static
|
||||
void WebRequest::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "WebRequest"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetMethod("onBeforeRequest",
|
||||
&WebRequest::SetResponseListener<
|
||||
AtomNetworkDelegate::kOnBeforeRequest>)
|
||||
.SetMethod("onBeforeSendHeaders",
|
||||
&WebRequest::SetResponseListener<
|
||||
AtomNetworkDelegate::kOnBeforeSendHeaders>)
|
||||
.SetMethod("onHeadersReceived",
|
||||
&WebRequest::SetResponseListener<
|
||||
AtomNetworkDelegate::kOnHeadersReceived>)
|
||||
.SetMethod("onSendHeaders",
|
||||
&WebRequest::SetSimpleListener<
|
||||
AtomNetworkDelegate::kOnSendHeaders>)
|
||||
.SetMethod("onBeforeRedirect",
|
||||
&WebRequest::SetSimpleListener<
|
||||
AtomNetworkDelegate::kOnBeforeRedirect>)
|
||||
.SetMethod("onResponseStarted",
|
||||
&WebRequest::SetSimpleListener<
|
||||
AtomNetworkDelegate::kOnResponseStarted>)
|
||||
.SetMethod("onCompleted",
|
||||
&WebRequest::SetSimpleListener<
|
||||
AtomNetworkDelegate::kOnCompleted>)
|
||||
.SetMethod("onErrorOccurred",
|
||||
&WebRequest::SetSimpleListener<
|
||||
AtomNetworkDelegate::kOnErrorOccurred>);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
49
atom/browser/api/atom_api_web_request.h
Normal file
49
atom/browser/api/atom_api_web_request.h
Normal file
@@ -0,0 +1,49 @@
|
||||
// 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_WEB_REQUEST_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_WEB_REQUEST_H_
|
||||
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "atom/browser/net/atom_network_delegate.h"
|
||||
#include "native_mate/arguments.h"
|
||||
#include "native_mate/handle.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomBrowserContext;
|
||||
|
||||
namespace api {
|
||||
|
||||
class WebRequest : public mate::TrackableObject<WebRequest> {
|
||||
public:
|
||||
static mate::Handle<WebRequest> Create(v8::Isolate* isolate,
|
||||
AtomBrowserContext* browser_context);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
protected:
|
||||
WebRequest(v8::Isolate* isolate, AtomBrowserContext* browser_context);
|
||||
~WebRequest() override;
|
||||
|
||||
// C++ can not distinguish overloaded member function.
|
||||
template<AtomNetworkDelegate::SimpleEvent type>
|
||||
void SetSimpleListener(mate::Arguments* args);
|
||||
template<AtomNetworkDelegate::ResponseEvent type>
|
||||
void SetResponseListener(mate::Arguments* args);
|
||||
template<typename Listener, typename Method, typename Event>
|
||||
void SetListener(Method method, Event type, mate::Arguments* args);
|
||||
|
||||
private:
|
||||
scoped_refptr<AtomBrowserContext> browser_context_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(WebRequest);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_WEB_REQUEST_H_
|
||||
45
atom/browser/api/atom_api_web_view_manager.cc
Normal file
45
atom/browser/api/atom_api_web_view_manager.cc
Normal file
@@ -0,0 +1,45 @@
|
||||
// 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/web_contents_preferences.h"
|
||||
#include "atom/browser/web_view_manager.h"
|
||||
#include "atom/common/native_mate_converters/content_converter.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "content/public/browser/browser_context.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
using atom::WebContentsPreferences;
|
||||
|
||||
namespace {
|
||||
|
||||
void AddGuest(int guest_instance_id,
|
||||
int element_instance_id,
|
||||
content::WebContents* embedder,
|
||||
content::WebContents* guest_web_contents,
|
||||
const base::DictionaryValue& options) {
|
||||
auto manager = atom::WebViewManager::GetWebViewManager(embedder);
|
||||
if (manager)
|
||||
manager->AddGuest(guest_instance_id, element_instance_id, embedder,
|
||||
guest_web_contents);
|
||||
|
||||
WebContentsPreferences::FromWebContents(guest_web_contents)->Merge(options);
|
||||
}
|
||||
|
||||
void RemoveGuest(content::WebContents* embedder, int guest_instance_id) {
|
||||
auto manager = atom::WebViewManager::GetWebViewManager(embedder);
|
||||
if (manager)
|
||||
manager->RemoveGuest(guest_instance_id);
|
||||
}
|
||||
|
||||
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("addGuest", &AddGuest);
|
||||
dict.SetMethod("removeGuest", &RemoveGuest);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_web_view_manager, Initialize)
|
||||
1005
atom/browser/api/atom_api_window.cc
Normal file
1005
atom/browser/api/atom_api_window.cc
Normal file
File diff suppressed because it is too large
Load Diff
255
atom/browser/api/atom_api_window.h
Normal file
255
atom/browser/api/atom_api_window.h
Normal file
@@ -0,0 +1,255 @@
|
||||
// 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_WINDOW_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_WINDOW_H_
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "atom/browser/native_window_observer.h"
|
||||
#include "atom/common/api/atom_api_native_image.h"
|
||||
#include "atom/common/key_weak_map.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "ui/gfx/image/image.h"
|
||||
|
||||
class GURL;
|
||||
|
||||
namespace gfx {
|
||||
class Rect;
|
||||
}
|
||||
|
||||
namespace mate {
|
||||
class Arguments;
|
||||
class Dictionary;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
class NativeWindow;
|
||||
|
||||
namespace api {
|
||||
|
||||
class WebContents;
|
||||
|
||||
class Window : public mate::TrackableObject<Window>,
|
||||
public NativeWindowObserver {
|
||||
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);
|
||||
|
||||
NativeWindow* window() const { return window_.get(); }
|
||||
|
||||
protected:
|
||||
Window(v8::Isolate* isolate, v8::Local<v8::Object> wrapper,
|
||||
const mate::Dictionary& options);
|
||||
~Window() override;
|
||||
|
||||
// NativeWindowObserver:
|
||||
void WillCloseWindow(bool* prevent_default) override;
|
||||
void WillDestroyNativeObject() override;
|
||||
void OnWindowClosed() override;
|
||||
void OnWindowBlur() override;
|
||||
void OnWindowFocus() override;
|
||||
void OnWindowShow() override;
|
||||
void OnWindowHide() override;
|
||||
void OnReadyToShow() override;
|
||||
void OnWindowMaximize() override;
|
||||
void OnWindowUnmaximize() override;
|
||||
void OnWindowMinimize() override;
|
||||
void OnWindowRestore() override;
|
||||
void OnWindowResize() override;
|
||||
void OnWindowMove() override;
|
||||
void OnWindowMoved() override;
|
||||
void OnWindowScrollTouchBegin() override;
|
||||
void OnWindowScrollTouchEnd() override;
|
||||
void OnWindowScrollTouchEdge() override;
|
||||
void OnWindowSwipe(const std::string& direction) override;
|
||||
void OnWindowEnterFullScreen() override;
|
||||
void OnWindowLeaveFullScreen() override;
|
||||
void OnWindowEnterHtmlFullScreen() override;
|
||||
void OnWindowLeaveHtmlFullScreen() override;
|
||||
void OnRendererUnresponsive() override;
|
||||
void OnRendererResponsive() override;
|
||||
void OnExecuteWindowsCommand(const std::string& command_name) override;
|
||||
|
||||
#if defined(OS_WIN)
|
||||
void OnWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) override;
|
||||
#endif
|
||||
|
||||
private:
|
||||
void Init(v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> wrapper,
|
||||
const mate::Dictionary& options,
|
||||
mate::Handle<class WebContents> web_contents);
|
||||
// APIs for NativeWindow.
|
||||
void Close();
|
||||
void Focus();
|
||||
void Blur();
|
||||
bool IsFocused();
|
||||
void Show();
|
||||
void ShowInactive();
|
||||
void Hide();
|
||||
bool IsVisible();
|
||||
bool IsEnabled();
|
||||
void Maximize();
|
||||
void Unmaximize();
|
||||
bool IsMaximized();
|
||||
void Minimize();
|
||||
void Restore();
|
||||
bool IsMinimized();
|
||||
void SetFullScreen(bool fullscreen);
|
||||
bool IsFullscreen();
|
||||
void SetBounds(const gfx::Rect& bounds, mate::Arguments* args);
|
||||
gfx::Rect GetBounds();
|
||||
void SetSize(int width, int height, mate::Arguments* args);
|
||||
std::vector<int> GetSize();
|
||||
void SetContentSize(int width, int height, mate::Arguments* args);
|
||||
std::vector<int> GetContentSize();
|
||||
void SetContentBounds(const gfx::Rect& bounds, mate::Arguments* args);
|
||||
gfx::Rect GetContentBounds();
|
||||
void SetMinimumSize(int width, int height);
|
||||
std::vector<int> GetMinimumSize();
|
||||
void SetMaximumSize(int width, int height);
|
||||
std::vector<int> GetMaximumSize();
|
||||
void SetSheetOffset(double offsetY, mate::Arguments* args);
|
||||
void SetResizable(bool resizable);
|
||||
bool IsResizable();
|
||||
void SetMovable(bool movable);
|
||||
bool IsMovable();
|
||||
void SetMinimizable(bool minimizable);
|
||||
bool IsMinimizable();
|
||||
void SetMaximizable(bool maximizable);
|
||||
bool IsMaximizable();
|
||||
void SetFullScreenable(bool fullscreenable);
|
||||
bool IsFullScreenable();
|
||||
void SetClosable(bool closable);
|
||||
bool IsClosable();
|
||||
void SetAlwaysOnTop(bool top, mate::Arguments* args);
|
||||
bool IsAlwaysOnTop();
|
||||
void Center();
|
||||
void SetPosition(int x, int y, mate::Arguments* args);
|
||||
std::vector<int> GetPosition();
|
||||
void SetTitle(const std::string& title);
|
||||
std::string GetTitle();
|
||||
void FlashFrame(bool flash);
|
||||
void SetSkipTaskbar(bool skip);
|
||||
void SetKiosk(bool kiosk);
|
||||
bool IsKiosk();
|
||||
void SetBackgroundColor(const std::string& color_name);
|
||||
void SetHasShadow(bool has_shadow);
|
||||
bool HasShadow();
|
||||
void FocusOnWebView();
|
||||
void BlurWebView();
|
||||
bool IsWebViewFocused();
|
||||
void SetRepresentedFilename(const std::string& filename);
|
||||
std::string GetRepresentedFilename();
|
||||
void SetDocumentEdited(bool edited);
|
||||
bool IsDocumentEdited();
|
||||
void SetIgnoreMouseEvents(bool ignore);
|
||||
void SetContentProtection(bool enable);
|
||||
void SetFocusable(bool focusable);
|
||||
void SetProgressBar(double progress, mate::Arguments* args);
|
||||
void SetOverlayIcon(const gfx::Image& overlay,
|
||||
const std::string& description);
|
||||
bool SetThumbarButtons(mate::Arguments* args);
|
||||
void SetMenu(v8::Isolate* isolate, v8::Local<v8::Value> menu);
|
||||
void SetAutoHideMenuBar(bool auto_hide);
|
||||
bool IsMenuBarAutoHide();
|
||||
void SetMenuBarVisibility(bool visible);
|
||||
bool IsMenuBarVisible();
|
||||
void SetAspectRatio(double aspect_ratio, mate::Arguments* args);
|
||||
void PreviewFile(const std::string& path, mate::Arguments* args);
|
||||
void CloseFilePreview();
|
||||
void SetParentWindow(v8::Local<v8::Value> value, mate::Arguments* args);
|
||||
v8::Local<v8::Value> GetParentWindow() const;
|
||||
std::vector<v8::Local<v8::Object>> GetChildWindows() const;
|
||||
bool IsModal() const;
|
||||
v8::Local<v8::Value> GetNativeWindowHandle();
|
||||
|
||||
#if defined(OS_WIN)
|
||||
typedef base::Callback<void(v8::Local<v8::Value>,
|
||||
v8::Local<v8::Value>)> MessageCallback;
|
||||
|
||||
bool HookWindowMessage(UINT message, const MessageCallback& callback);
|
||||
bool IsWindowMessageHooked(UINT message);
|
||||
void UnhookWindowMessage(UINT message);
|
||||
void UnhookAllWindowMessages();
|
||||
bool SetThumbnailClip(const gfx::Rect& region);
|
||||
bool SetThumbnailToolTip(const std::string& tooltip);
|
||||
void SetAppDetails(const mate::Dictionary& options);
|
||||
#endif
|
||||
|
||||
#if defined(TOOLKIT_VIEWS)
|
||||
void SetIcon(mate::Handle<NativeImage> icon);
|
||||
#endif
|
||||
|
||||
void SetVisibleOnAllWorkspaces(bool visible);
|
||||
bool IsVisibleOnAllWorkspaces();
|
||||
|
||||
void SetAutoHideCursor(bool auto_hide);
|
||||
|
||||
void SetVibrancy(mate::Arguments* args);
|
||||
|
||||
int32_t ID() const;
|
||||
v8::Local<v8::Value> WebContents(v8::Isolate* isolate);
|
||||
|
||||
// Remove this window from parent window's |child_windows_|.
|
||||
void RemoveFromParentChildWindows();
|
||||
|
||||
#if defined(OS_WIN)
|
||||
typedef std::map<UINT, MessageCallback> MessageCallbackMap;
|
||||
MessageCallbackMap messages_callback_map_;
|
||||
#endif
|
||||
|
||||
v8::Global<v8::Value> web_contents_;
|
||||
v8::Global<v8::Value> menu_;
|
||||
v8::Global<v8::Value> parent_window_;
|
||||
KeyWeakMap<int> child_windows_;
|
||||
|
||||
api::WebContents* api_web_contents_;
|
||||
|
||||
std::unique_ptr<NativeWindow> window_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Window);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
|
||||
namespace mate {
|
||||
|
||||
template<>
|
||||
struct Converter<atom::NativeWindow*> {
|
||||
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
|
||||
atom::NativeWindow** out) {
|
||||
// null would be tranfered to NULL.
|
||||
if (val->IsNull()) {
|
||||
*out = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
atom::api::Window* window;
|
||||
if (!Converter<atom::api::Window*>::FromV8(isolate, val, &window))
|
||||
return false;
|
||||
*out = window->window();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_WINDOW_H_
|
||||
68
atom/browser/api/event.cc
Normal file
68
atom/browser/api/event.cc
Normal file
@@ -0,0 +1,68 @@
|
||||
// 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/event.h"
|
||||
|
||||
#include "atom/common/api/api_messages.h"
|
||||
#include "atom/common/native_mate_converters/string16_converter.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
#include "native_mate/object_template_builder.h"
|
||||
|
||||
namespace mate {
|
||||
|
||||
Event::Event(v8::Isolate* isolate)
|
||||
: sender_(nullptr),
|
||||
message_(nullptr) {
|
||||
Init(isolate);
|
||||
}
|
||||
|
||||
Event::~Event() {
|
||||
}
|
||||
|
||||
void Event::SetSenderAndMessage(content::WebContents* sender,
|
||||
IPC::Message* message) {
|
||||
DCHECK(!sender_);
|
||||
DCHECK(!message_);
|
||||
sender_ = sender;
|
||||
message_ = message;
|
||||
|
||||
Observe(sender);
|
||||
}
|
||||
|
||||
void Event::WebContentsDestroyed() {
|
||||
sender_ = nullptr;
|
||||
message_ = nullptr;
|
||||
}
|
||||
|
||||
void Event::PreventDefault(v8::Isolate* isolate) {
|
||||
GetWrapper()->Set(StringToV8(isolate, "defaultPrevented"),
|
||||
v8::True(isolate));
|
||||
}
|
||||
|
||||
bool Event::SendReply(const base::string16& json) {
|
||||
if (message_ == nullptr || sender_ == nullptr)
|
||||
return false;
|
||||
|
||||
AtomViewHostMsg_Message_Sync::WriteReplyParams(message_, json);
|
||||
bool success = sender_->Send(message_);
|
||||
message_ = nullptr;
|
||||
sender_ = nullptr;
|
||||
return success;
|
||||
}
|
||||
|
||||
// static
|
||||
Handle<Event> Event::Create(v8::Isolate* isolate) {
|
||||
return mate::CreateHandle(isolate, new Event(isolate));
|
||||
}
|
||||
|
||||
// static
|
||||
void Event::BuildPrototype(
|
||||
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "Event"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetMethod("preventDefault", &Event::PreventDefault)
|
||||
.SetMethod("sendReply", &Event::SendReply);
|
||||
}
|
||||
|
||||
} // namespace mate
|
||||
52
atom/browser/api/event.h
Normal file
52
atom/browser/api/event.h
Normal file
@@ -0,0 +1,52 @@
|
||||
// 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_EVENT_H_
|
||||
#define ATOM_BROWSER_API_EVENT_H_
|
||||
|
||||
#include "content/public/browser/web_contents_observer.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "native_mate/wrappable.h"
|
||||
|
||||
namespace IPC {
|
||||
class Message;
|
||||
}
|
||||
|
||||
namespace mate {
|
||||
|
||||
class Event : public Wrappable<Event>,
|
||||
public content::WebContentsObserver {
|
||||
public:
|
||||
static Handle<Event> Create(v8::Isolate* isolate);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
// Pass the sender and message to be replied.
|
||||
void SetSenderAndMessage(content::WebContents* sender, IPC::Message* message);
|
||||
|
||||
// event.PreventDefault().
|
||||
void PreventDefault(v8::Isolate* isolate);
|
||||
|
||||
// event.sendReply(json), used for replying synchronous message.
|
||||
bool SendReply(const base::string16& json);
|
||||
|
||||
protected:
|
||||
explicit Event(v8::Isolate* isolate);
|
||||
~Event() override;
|
||||
|
||||
// content::WebContentsObserver implementations:
|
||||
void WebContentsDestroyed() override;
|
||||
|
||||
private:
|
||||
// Replyer for the synchronous messages.
|
||||
content::WebContents* sender_;
|
||||
IPC::Message* message_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Event);
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
#endif // ATOM_BROWSER_API_EVENT_H_
|
||||
82
atom/browser/api/event_emitter.cc
Normal file
82
atom/browser/api/event_emitter.cc
Normal file
@@ -0,0 +1,82 @@
|
||||
// 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/event_emitter.h"
|
||||
|
||||
#include "atom/browser/api/event.h"
|
||||
#include "native_mate/arguments.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/object_template_builder.h"
|
||||
#include "ui/events/event_constants.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace mate {
|
||||
|
||||
namespace {
|
||||
|
||||
v8::Persistent<v8::ObjectTemplate> event_template;
|
||||
|
||||
void PreventDefault(mate::Arguments* args) {
|
||||
mate::Dictionary self(args->isolate(), args->GetThis());
|
||||
self.Set("defaultPrevented", true);
|
||||
}
|
||||
|
||||
// Create a pure JavaScript Event object.
|
||||
v8::Local<v8::Object> CreateEventObject(v8::Isolate* isolate) {
|
||||
if (event_template.IsEmpty()) {
|
||||
event_template.Reset(isolate, ObjectTemplateBuilder(isolate)
|
||||
.SetMethod("preventDefault", &PreventDefault)
|
||||
.Build());
|
||||
}
|
||||
|
||||
return v8::Local<v8::ObjectTemplate>::New(
|
||||
isolate, event_template)->NewInstance();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace internal {
|
||||
|
||||
v8::Local<v8::Object> CreateJSEvent(
|
||||
v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> object,
|
||||
content::WebContents* sender,
|
||||
IPC::Message* message) {
|
||||
v8::Local<v8::Object> event;
|
||||
bool use_native_event = sender && message;
|
||||
|
||||
if (use_native_event) {
|
||||
mate::Handle<mate::Event> native_event = mate::Event::Create(isolate);
|
||||
native_event->SetSenderAndMessage(sender, message);
|
||||
event = v8::Local<v8::Object>::Cast(native_event.ToV8());
|
||||
} else {
|
||||
event = CreateEventObject(isolate);
|
||||
}
|
||||
mate::Dictionary(isolate, event).Set("sender", object);
|
||||
return event;
|
||||
}
|
||||
|
||||
v8::Local<v8::Object> CreateCustomEvent(
|
||||
v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> object,
|
||||
v8::Local<v8::Object> custom_event) {
|
||||
v8::Local<v8::Object> event = CreateEventObject(isolate);
|
||||
(void)event->SetPrototype(custom_event->CreationContext(), custom_event);
|
||||
mate::Dictionary(isolate, event).Set("sender", object);
|
||||
return event;
|
||||
}
|
||||
|
||||
v8::Local<v8::Object> CreateEventFromFlags(v8::Isolate* isolate, int flags) {
|
||||
mate::Dictionary obj = mate::Dictionary::CreateEmpty(isolate);
|
||||
obj.Set("shiftKey", static_cast<bool>(flags & ui::EF_SHIFT_DOWN));
|
||||
obj.Set("ctrlKey", static_cast<bool>(flags & ui::EF_CONTROL_DOWN));
|
||||
obj.Set("altKey", static_cast<bool>(flags & ui::EF_ALT_DOWN));
|
||||
obj.Set("metaKey", static_cast<bool>(flags & ui::EF_COMMAND_DOWN));
|
||||
return obj.GetHandle();
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace mate
|
||||
108
atom/browser/api/event_emitter.h
Normal file
108
atom/browser/api/event_emitter.h
Normal file
@@ -0,0 +1,108 @@
|
||||
// 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_EVENT_EMITTER_H_
|
||||
#define ATOM_BROWSER_API_EVENT_EMITTER_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "atom/common/api/event_emitter_caller.h"
|
||||
#include "native_mate/wrappable.h"
|
||||
|
||||
namespace content {
|
||||
class WebContents;
|
||||
}
|
||||
|
||||
namespace IPC {
|
||||
class Message;
|
||||
}
|
||||
|
||||
namespace mate {
|
||||
|
||||
namespace internal {
|
||||
|
||||
v8::Local<v8::Object> CreateJSEvent(v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> object,
|
||||
content::WebContents* sender,
|
||||
IPC::Message* message);
|
||||
v8::Local<v8::Object> CreateCustomEvent(
|
||||
v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> object,
|
||||
v8::Local<v8::Object> event);
|
||||
v8::Local<v8::Object> CreateEventFromFlags(v8::Isolate* isolate, int flags);
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// Provide helperers to emit event in JavaScript.
|
||||
template<typename T>
|
||||
class EventEmitter : public Wrappable<T> {
|
||||
public:
|
||||
typedef std::vector<v8::Local<v8::Value>> ValueArray;
|
||||
|
||||
// Make the convinient methods visible:
|
||||
// https://isocpp.org/wiki/faq/templates#nondependent-name-lookup-members
|
||||
v8::Local<v8::Object> GetWrapper() { return Wrappable<T>::GetWrapper(); }
|
||||
v8::Isolate* isolate() const { return Wrappable<T>::isolate(); }
|
||||
|
||||
// this.emit(name, event, args...);
|
||||
template<typename... Args>
|
||||
bool EmitCustomEvent(const base::StringPiece& name,
|
||||
v8::Local<v8::Object> event,
|
||||
const Args&... args) {
|
||||
return EmitWithEvent(
|
||||
name,
|
||||
internal::CreateCustomEvent(isolate(), GetWrapper(), event), args...);
|
||||
}
|
||||
|
||||
// this.emit(name, new Event(flags), args...);
|
||||
template<typename... Args>
|
||||
bool EmitWithFlags(const base::StringPiece& name,
|
||||
int flags,
|
||||
const Args&... args) {
|
||||
return EmitCustomEvent(
|
||||
name,
|
||||
internal::CreateEventFromFlags(isolate(), flags), args...);
|
||||
}
|
||||
|
||||
// this.emit(name, new Event(), args...);
|
||||
template<typename... Args>
|
||||
bool Emit(const base::StringPiece& name, const Args&... args) {
|
||||
return EmitWithSender(name, nullptr, nullptr, args...);
|
||||
}
|
||||
|
||||
// this.emit(name, new Event(sender, message), args...);
|
||||
template<typename... Args>
|
||||
bool EmitWithSender(const base::StringPiece& name,
|
||||
content::WebContents* sender,
|
||||
IPC::Message* message,
|
||||
const Args&... args) {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
v8::Local<v8::Object> event = internal::CreateJSEvent(
|
||||
isolate(), GetWrapper(), sender, message);
|
||||
return EmitWithEvent(name, event, args...);
|
||||
}
|
||||
|
||||
protected:
|
||||
EventEmitter() {}
|
||||
|
||||
private:
|
||||
// this.emit(name, event, args...);
|
||||
template<typename... Args>
|
||||
bool EmitWithEvent(const base::StringPiece& name,
|
||||
v8::Local<v8::Object> event,
|
||||
const Args&... args) {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
EmitEvent(isolate(), GetWrapper(), name, event, args...);
|
||||
return event->Get(
|
||||
StringToV8(isolate(), "defaultPrevented"))->BooleanValue();
|
||||
}
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(EventEmitter);
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
#endif // ATOM_BROWSER_API_EVENT_EMITTER_H_
|
||||
95
atom/browser/api/frame_subscriber.cc
Normal file
95
atom/browser/api/frame_subscriber.cc
Normal file
@@ -0,0 +1,95 @@
|
||||
// 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/frame_subscriber.h"
|
||||
|
||||
#include "atom/common/native_mate_converters/gfx_converter.h"
|
||||
#include "base/bind.h"
|
||||
#include "content/public/browser/render_widget_host.h"
|
||||
#include "ui/display/display.h"
|
||||
#include "ui/display/screen.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
FrameSubscriber::FrameSubscriber(v8::Isolate* isolate,
|
||||
content::RenderWidgetHostView* view,
|
||||
const FrameCaptureCallback& callback,
|
||||
bool only_dirty)
|
||||
: isolate_(isolate),
|
||||
view_(view),
|
||||
callback_(callback),
|
||||
only_dirty_(only_dirty),
|
||||
weak_factory_(this) {
|
||||
}
|
||||
|
||||
bool FrameSubscriber::ShouldCaptureFrame(
|
||||
const gfx::Rect& dirty_rect,
|
||||
base::TimeTicks present_time,
|
||||
scoped_refptr<media::VideoFrame>* storage,
|
||||
DeliverFrameCallback* callback) {
|
||||
const auto host = view_ ? view_->GetRenderWidgetHost() : nullptr;
|
||||
if (!view_ || !host)
|
||||
return false;
|
||||
|
||||
if (dirty_rect.IsEmpty())
|
||||
return false;
|
||||
|
||||
gfx::Rect rect = gfx::Rect(view_->GetVisibleViewportSize());
|
||||
if (only_dirty_)
|
||||
rect = dirty_rect;
|
||||
|
||||
gfx::Size view_size = rect.size();
|
||||
gfx::Size bitmap_size = view_size;
|
||||
const gfx::NativeView native_view = view_->GetNativeView();
|
||||
const float scale =
|
||||
display::Screen::GetScreen()->GetDisplayNearestWindow(native_view)
|
||||
.device_scale_factor();
|
||||
if (scale > 1.0f)
|
||||
bitmap_size = gfx::ScaleToCeiledSize(view_size, scale);
|
||||
|
||||
rect = gfx::Rect(rect.origin(), bitmap_size);
|
||||
|
||||
host->CopyFromBackingStore(
|
||||
rect,
|
||||
rect.size(),
|
||||
base::Bind(&FrameSubscriber::OnFrameDelivered,
|
||||
weak_factory_.GetWeakPtr(), callback_, rect),
|
||||
kBGRA_8888_SkColorType);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void FrameSubscriber::OnFrameDelivered(const FrameCaptureCallback& callback,
|
||||
const gfx::Rect& damage_rect,
|
||||
const SkBitmap& bitmap,
|
||||
content::ReadbackResponse response) {
|
||||
if (response != content::ReadbackResponse::READBACK_SUCCESS)
|
||||
return;
|
||||
|
||||
v8::Locker locker(isolate_);
|
||||
v8::HandleScope handle_scope(isolate_);
|
||||
|
||||
size_t rgb_arr_size = bitmap.width() * bitmap.height() *
|
||||
bitmap.bytesPerPixel();
|
||||
v8::MaybeLocal<v8::Object> buffer = node::Buffer::New(isolate_, rgb_arr_size);
|
||||
if (buffer.IsEmpty())
|
||||
return;
|
||||
|
||||
bitmap.copyPixelsTo(
|
||||
reinterpret_cast<uint8_t*>(node::Buffer::Data(buffer.ToLocalChecked())),
|
||||
rgb_arr_size);
|
||||
|
||||
v8::Local<v8::Value> damage =
|
||||
mate::Converter<gfx::Rect>::ToV8(isolate_, damage_rect);
|
||||
|
||||
callback_.Run(buffer.ToLocalChecked(), damage);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
56
atom/browser/api/frame_subscriber.h
Normal file
56
atom/browser/api/frame_subscriber.h
Normal file
@@ -0,0 +1,56 @@
|
||||
// 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_FRAME_SUBSCRIBER_H_
|
||||
#define ATOM_BROWSER_API_FRAME_SUBSCRIBER_H_
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "content/public/browser/readback_types.h"
|
||||
#include "content/public/browser/render_widget_host_view.h"
|
||||
#include "content/public/browser/render_widget_host_view_frame_subscriber.h"
|
||||
#include "third_party/skia/include/core/SkBitmap.h"
|
||||
#include "ui/gfx/geometry/size.h"
|
||||
#include "v8/include/v8.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class FrameSubscriber : public content::RenderWidgetHostViewFrameSubscriber {
|
||||
public:
|
||||
using FrameCaptureCallback =
|
||||
base::Callback<void(v8::Local<v8::Value>, v8::Local<v8::Value>)>;
|
||||
|
||||
FrameSubscriber(v8::Isolate* isolate,
|
||||
content::RenderWidgetHostView* view,
|
||||
const FrameCaptureCallback& callback,
|
||||
bool only_dirty);
|
||||
|
||||
bool ShouldCaptureFrame(const gfx::Rect& damage_rect,
|
||||
base::TimeTicks present_time,
|
||||
scoped_refptr<media::VideoFrame>* storage,
|
||||
DeliverFrameCallback* callback) override;
|
||||
|
||||
private:
|
||||
void OnFrameDelivered(const FrameCaptureCallback& callback,
|
||||
const gfx::Rect& damage_rect,
|
||||
const SkBitmap& bitmap,
|
||||
content::ReadbackResponse response);
|
||||
|
||||
v8::Isolate* isolate_;
|
||||
content::RenderWidgetHostView* view_;
|
||||
FrameCaptureCallback callback_;
|
||||
bool only_dirty_;
|
||||
|
||||
base::WeakPtrFactory<FrameSubscriber> weak_factory_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(FrameSubscriber);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_FRAME_SUBSCRIBER_H_
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user