mirror of
https://github.com/electron/electron.git
synced 2026-02-26 03:01:17 -05:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
86ffbe16fb | ||
|
|
25aaafde45 | ||
|
|
61e990e8cd | ||
|
|
fb143a5dab |
@@ -1,35 +0,0 @@
|
||||
# Defines the Chromium style for automatic reformatting.
|
||||
# http://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
||||
BasedOnStyle: Chromium
|
||||
# This defaults to 'Auto'. Explicitly set it for a while, so that
|
||||
# 'vector<vector<int> >' in existing files gets formatted to
|
||||
# 'vector<vector<int>>'. ('Auto' means that clang-format will only use
|
||||
# 'int>>' if the file already contains at least one such instance.)
|
||||
Standard: Cpp11
|
||||
# Make sure code like:
|
||||
# IPC_BEGIN_MESSAGE_MAP()
|
||||
# IPC_MESSAGE_HANDLER(WidgetHostViewHost_Update, OnUpdate)
|
||||
# IPC_END_MESSAGE_MAP()
|
||||
# gets correctly indented.
|
||||
MacroBlockBegin: "^\
|
||||
BEGIN_MSG_MAP|\
|
||||
BEGIN_MSG_MAP_EX|\
|
||||
BEGIN_SAFE_MSG_MAP_EX|\
|
||||
CR_BEGIN_MSG_MAP_EX|\
|
||||
IPC_BEGIN_MESSAGE_MAP|\
|
||||
IPC_BEGIN_MESSAGE_MAP_WITH_PARAM|\
|
||||
IPC_PROTOBUF_MESSAGE_TRAITS_BEGIN|\
|
||||
IPC_STRUCT_BEGIN|\
|
||||
IPC_STRUCT_BEGIN_WITH_PARENT|\
|
||||
IPC_STRUCT_TRAITS_BEGIN|\
|
||||
POLPARAMS_BEGIN|\
|
||||
PPAPI_BEGIN_MESSAGE_MAP$"
|
||||
MacroBlockEnd: "^\
|
||||
CR_END_MSG_MAP|\
|
||||
END_MSG_MAP|\
|
||||
IPC_END_MESSAGE_MAP|\
|
||||
IPC_PROTOBUF_MESSAGE_TRAITS_END|\
|
||||
IPC_STRUCT_END|\
|
||||
IPC_STRUCT_TRAITS_END|\
|
||||
POLPARAMS_END|\
|
||||
PPAPI_END_MESSAGE_MAP$"
|
||||
12
.gitignore
vendored
12
.gitignore
vendored
@@ -6,7 +6,6 @@
|
||||
/external_binaries/
|
||||
/out/
|
||||
/vendor/brightray/vendor/download/
|
||||
/vendor/debian_wheezy_amd64-sysroot/
|
||||
/vendor/debian_wheezy_arm-sysroot/
|
||||
/vendor/debian_wheezy_i386-sysroot/
|
||||
/vendor/python_26/
|
||||
@@ -18,12 +17,5 @@ node_modules/
|
||||
*.xcodeproj
|
||||
*.swp
|
||||
*.pyc
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
.vs/
|
||||
.vscode/
|
||||
*.vcxproj
|
||||
*.vcxproj.user
|
||||
*.vcxproj.filters
|
||||
*.sln
|
||||
*.log
|
||||
debug.log
|
||||
npm-debug.log
|
||||
|
||||
13
.gitmodules
vendored
13
.gitmodules
vendored
@@ -1,27 +1,24 @@
|
||||
[submodule "vendor/brightray"]
|
||||
path = vendor/brightray
|
||||
url = https://github.com/electron/brightray.git
|
||||
url = https://github.com/atom/brightray.git
|
||||
[submodule "vendor/node"]
|
||||
path = vendor/node
|
||||
url = https://github.com/electron/node.git
|
||||
url = https://github.com/atom/node.git
|
||||
[submodule "vendor/depot_tools"]
|
||||
path = vendor/depot_tools
|
||||
url = https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
[submodule "vendor/breakpad"]
|
||||
path = vendor/breakpad
|
||||
url = https://github.com/electron/chromium-breakpad.git
|
||||
url = https://github.com/atom/chromium-breakpad.git
|
||||
[submodule "vendor/native_mate"]
|
||||
path = vendor/native_mate
|
||||
url = https://github.com/electron/native-mate.git
|
||||
url = https://github.com/zcbenz/native-mate.git
|
||||
[submodule "vendor/crashpad"]
|
||||
path = vendor/crashpad
|
||||
url = https://github.com/electron/crashpad.git
|
||||
url = https://github.com/atom/crashpad.git
|
||||
[submodule "vendor/requests"]
|
||||
path = vendor/requests
|
||||
url = https://github.com/kennethreitz/requests
|
||||
[submodule "vendor/boto"]
|
||||
path = vendor/boto
|
||||
url = https://github.com/boto/boto.git
|
||||
[submodule "vendor/pdf_viewer"]
|
||||
path = vendor/pdf_viewer
|
||||
url = https://github.com/electron/pdf-viewer.git
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
v7.4.0
|
||||
10
.travis.yml
10
.travis.yml
@@ -3,15 +3,14 @@ git:
|
||||
notifications:
|
||||
email: false
|
||||
|
||||
language: node_js
|
||||
node_js:
|
||||
- "4"
|
||||
language: cpp
|
||||
compiler: clang
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
env:
|
||||
- TARGET_ARCH=x64
|
||||
osx_image: xcode7.3
|
||||
osx_image: xcode7
|
||||
|
||||
matrix:
|
||||
include:
|
||||
@@ -20,7 +19,8 @@ matrix:
|
||||
- os: linux
|
||||
env: TARGET_ARCH=ia32
|
||||
allow_failures:
|
||||
- os: osx
|
||||
- env: TARGET_ARCH=arm
|
||||
- env: TARGET_ARCH=ia32
|
||||
|
||||
script: './script/cibuild'
|
||||
|
||||
|
||||
@@ -1,46 +1,24 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
# Contributor Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality.
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||
- The use of sexualized language or imagery
|
||||
- Personal attacks
|
||||
- Trolling or insulting/derogatory comments
|
||||
- Public or private harassment
|
||||
- Publishing other's private information, such as physical or electronic addresses, without explicit permission
|
||||
- Other unethical or unprofessional conduct
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team.
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community.
|
||||
|
||||
## Enforcement
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting a project maintainer at [atom@github.com](mailto:atom@github.com). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. Maintainers are obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
|
||||
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 [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
||||
This Code of Conduct is adapted from the Contributor Covenant, version 1.3.0, available from http://contributor-covenant.org/version/1/3/0/
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# Electron에 기여하기
|
||||
|
||||
:+1::tada: 먼저, 기여에 관심을 가져주셔서 감사합니다! :tada::+1:
|
||||
:+1::tada: 먼저, 이 프로젝트에 기여해주셔서 감사합니다! :tada::+1:
|
||||
|
||||
이 프로젝트는 기여자 규약인 [행동강령](CODE_OF_CONDUCT.md)을 준수합니다. 따라서 이
|
||||
이 프로젝트는 기여자 규약 [행동강령](CODE_OF_CONDUCT.md)을 준수합니다. 따라서 이
|
||||
프로젝트의 개발에 참여하려면 이 규약을 지켜야 합니다. 받아들일 수 없는 행위를 발견했을
|
||||
경우 atom@github.com로 보고하세요.
|
||||
경우 atom@github.com로 보고 하십시오.
|
||||
|
||||
다음 항목들은 Electron에 기여하는 가이드라인을 제시합니다.
|
||||
참고로 이 항목들은 그저 가이드라인에 불과하며 규칙이 아닙니다. 따라서 스스로의 적절한
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
## 이슈 제출
|
||||
|
||||
* [여기](https://github.com/electron/electron/issues/new)에서 새로운 이슈를 만들 수
|
||||
* [여기](https://github.com/atom/electron/issues/new)에서 새로운 이슈를 만들 수
|
||||
있습니다. 하지만 이슈를 작성하기 전에 아래의 항목들을 숙지하고 가능한한 이슈 보고에
|
||||
대해 최대한 많은 정보와 자세한 설명을 포함해야 합니다. 가능하다면 다음 항목을 포함해야
|
||||
합니다:
|
||||
@@ -23,18 +23,18 @@
|
||||
* 추가로 다음 사항을 준수하면 이슈를 해결하는데 큰 도움이 됩니다:
|
||||
* 스크린샷 또는 GIF 애니메이션 이미지들
|
||||
* 터미널에 출력된 에러의 내용 또는 개발자 도구, 알림창에 뜬 내용
|
||||
* [Cursory search](https://github.com/electron/electron/issues?utf8=✓&q=is%3Aissue+)를
|
||||
* [Cursory search](https://github.com/atom/electron/issues?utf8=✓&q=is%3Aissue+)를
|
||||
통해 이미 비슷한 내용의 이슈가 등록되어있는지 확인
|
||||
|
||||
## Pull Request 하기
|
||||
|
||||
* 가능한한 스크린샷과 GIF 애니메이션 이미지를 pull request에 추가
|
||||
* JavaScript, C++과 Python등
|
||||
[참조 문서에 정의된 코딩스타일](/docs-translations/ko-KR/development/coding-style.md)을
|
||||
* CoffeeScript, JavaScript, C++과 Python등
|
||||
[참조문서에 정의된 코딩스타일](/docs-translations/ko-KR/development/coding-style.md)을
|
||||
준수
|
||||
* [문서 스타일 가이드](/docs-translations/ko-KR/styleguide.md)에 따라 문서를
|
||||
[Markdown](https://daringfireball.net/projects/markdown) 형식으로 작성.
|
||||
* 짧은, 현재 시제 커밋 메시지 사용. [커밋 메시지 스타일 가이드](#git-커밋-메시지)를
|
||||
* 짧은, 현재 시제 커밋 메시지 사용. [커밋 메시지 스타일 가이드](#Git-커밋-메시지)를
|
||||
참고하세요
|
||||
|
||||
## 스타일 가이드
|
||||
@@ -58,7 +58,7 @@
|
||||
### Git 커밋 메시지
|
||||
|
||||
* 현재 시제 사용 ("Added feature" 대신 "Add feature" 사용)
|
||||
* 명령법(imperative mood) 사용 ("Moves cursor to..." 대신 "Move cursor to..." 사용)
|
||||
* 필수적 분위기(imperative mood) 사용 ("Moves cursor to..." 대신 "Move cursor to..." 사용)
|
||||
* 첫 줄은 72자에 맞추거나 그 보다 적게 제한
|
||||
* 자유롭게 필요에 따라 이슈나 PR링크를 참조
|
||||
* 단순한 문서 변경일 경우 `[ci skip]`을 커밋 메시지에 추가
|
||||
@@ -68,13 +68,13 @@
|
||||
* :non-potable_water: `:non-potable_water:` 메모리 누수를 연결했을 때
|
||||
* :memo: `:memo:` 문서를 작성했을 때
|
||||
* :penguin: `:penguin:` Linux에 대한 패치를 했을 때
|
||||
* :apple: `:apple:` macOS에 대한 패치를 했을 때
|
||||
* :apple: `:apple:` Mac OS에 대한 패치를 했을 때
|
||||
* :checkered_flag: `:checkered_flag:` Windows에 대한 패치를 했을 때
|
||||
* :bug: `:bug:` 버그를 고쳤을 때
|
||||
* :fire: `:fire:` 코드 또는 파일을 삭제했을 때
|
||||
* :green_heart: `:green_heart:` CI 빌드를 고쳤을 때
|
||||
* :white_check_mark: `:white_check_mark:` 테스트를 추가했을 때
|
||||
* :lock: `:lock:` 보안 문제를 해결했을 때
|
||||
* :arrow_up: `:arrow_up:` 의존성 라이브러리를 업데이트 했을 때
|
||||
* :arrow_down: `:arrow_down:` 의존성 라이브러리를 다운그레이드 했을 때
|
||||
* :arrow_up: `:arrow_up:` 종속성 라이브러리를 업데이트 했을 때
|
||||
* :arrow_down: `:arrow_down:` 종속성 라이브러리를 다운그레이드 했을 때
|
||||
* :shirt: `:shirt:` linter(코드 검사기)의 경고를 제거했을 때
|
||||
@@ -1,7 +1,5 @@
|
||||
# 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).
|
||||
@@ -14,7 +12,7 @@ propose changes to this document in a pull request.
|
||||
|
||||
## Submitting Issues
|
||||
|
||||
* You can create an issue [here](https://github.com/electron/electron/issues/new),
|
||||
* You can create an issue [here](https://github.com/atom/electron/issues/new),
|
||||
but before doing that please read the notes below and include as many details as
|
||||
possible with your report. If you can, please include:
|
||||
* The version of Electron you are using
|
||||
@@ -24,13 +22,13 @@ possible with your report. If you can, please include:
|
||||
* 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+)
|
||||
* Perform a [cursory search](https://github.com/atom/electron/issues?utf8=✓&q=is%3Aissue+)
|
||||
to see if a similar issue has already been submitted
|
||||
|
||||
## Submitting Pull Requests
|
||||
|
||||
* 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).
|
||||
* Follow the CoffeeScript, JavaScript, C++ and Python [coding style defined in docs](/docs/development/coding-style.md).
|
||||
* Write documentation in [Markdown](https://daringfireball.net/projects/markdown).
|
||||
See the [Documentation Styleguide](/docs/styleguide.md).
|
||||
* Use short, present tense commit messages. See [Commit Message Styleguide](#git-commit-messages).
|
||||
@@ -67,7 +65,7 @@ possible with your report. If you can, please include:
|
||||
* :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
|
||||
* :apple: `:apple:` when fixing something on Mac OS
|
||||
* :checkered_flag: `:checkered_flag:` when fixing something on Windows
|
||||
* :bug: `:bug:` when fixing a bug
|
||||
* :fire: `:fire:` when removing code or files
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
<!--
|
||||
Thanks for opening an issue! A few things to keep in mind:
|
||||
|
||||
- The issue tracker is only for bugs and feature requests.
|
||||
- Before reporting a bug, please try reproducing your issue against
|
||||
the latest version of Electron.
|
||||
- If you need general advice, join our Slack: http://atom-slack.herokuapp.com
|
||||
-->
|
||||
|
||||
* Electron version:
|
||||
* Operating system:
|
||||
|
||||
### Expected behavior
|
||||
|
||||
<!-- What do you think should happen? -->
|
||||
|
||||
### Actual behavior
|
||||
|
||||
<!-- What actually happens? -->
|
||||
|
||||
### How to reproduce
|
||||
|
||||
<!--
|
||||
|
||||
Your best chance of getting this bug looked at quickly is to provide a REPOSITORY that can be cloned and run.
|
||||
|
||||
You can fork https://github.com/electron/electron-quick-start and include a link to the branch with your changes.
|
||||
|
||||
If you provide a URL, please list the commands required to clone/setup/run your repo e.g.
|
||||
|
||||
$ git clone $YOUR_URL -b $BRANCH
|
||||
$ npm install
|
||||
$ npm start || electron .
|
||||
|
||||
-->
|
||||
2
LICENSE
2
LICENSE
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2013-2017 GitHub Inc.
|
||||
Copyright (c) 2014 GitHub Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
||||
74
README-ko.md
Normal file
74
README-ko.md
Normal file
@@ -0,0 +1,74 @@
|
||||
[](http://electron.atom.io/)
|
||||
|
||||
[](https://travis-ci.org/atom/electron)
|
||||
[](https://david-dm.org/atom/electron#info=devDependencies)
|
||||
[](http://atom-slack.herokuapp.com/)
|
||||
|
||||
### [Electron](https://github.com/atom/electron/) 한국어 참조문서
|
||||
|
||||
:zap: *프레임워크 이름이 Atom Shell에서 Electron으로 변경되었습니다* :zap:
|
||||
|
||||
Electron 프레임워크는 JavaScript, HTML 그리고 CSS를 사용하여
|
||||
Cross-Platform 데스크톱 어플리케이션을 개발할 수 있도록 해주는 프레임워크입니다.
|
||||
[Node.js](https://nodejs.org/)와 [Chromium](http://www.chromium.org)을 기반으로
|
||||
만들어졌으며 [Atom Editor](https://github.com/atom/atom)에 사용되고 있습니다.
|
||||
|
||||
Electron에 대한 중요한 알림을 받고 싶다면 Twitter에서
|
||||
[@ElectronJS](https://twitter.com/electronjs)를 팔로우 하세요.
|
||||
|
||||
이 프로젝트는 기여자 규약 [행동강령](CODE_OF_CONDUCT.md)을 준수합니다. 따라서 이
|
||||
프로젝트의 개발에 참여하려면 이 규약을 지켜야 합니다. 받아들일 수 없는 행위를 발견했을
|
||||
경우 atom@github.com로 보고 하십시오.
|
||||
|
||||
## 다운로드
|
||||
|
||||
Linux, Windows, OS X 용으로 미리 빌드된 Electron 바이너리와 디버그 심볼이 준비되어
|
||||
있습니다. [releases](https://github.com/atom/electron/releases) 페이지에서 받아 볼
|
||||
수 있습니다.
|
||||
|
||||
또한 [`npm`](https://docs.npmjs.com/)을 통해 미리 빌드된 Electron 바이너리를 설치할
|
||||
수도 있습니다:
|
||||
|
||||
```sh
|
||||
# $PATH에 `electron` 커맨드를 등록하고 전역에 설치합니다.
|
||||
npm install electron-prebuilt -g
|
||||
|
||||
# 개발 의존성 모듈 형태로 설치합니다.
|
||||
npm install electron-prebuilt --save-dev
|
||||
```
|
||||
|
||||
### 미러
|
||||
|
||||
- [China](https://npm.taobao.org/mirrors/electron)
|
||||
|
||||
## 참조 문서
|
||||
|
||||
[Docs](https://github.com/atom/electron/tree/master/docs/README.md)에 개발 지침과
|
||||
API 레퍼런스가 있습니다. Electron을 빌드 하는 방법과 프로젝트에 기여하는법 또한 문서에
|
||||
포함되어 있으니 참고하시기 바랍니다.
|
||||
|
||||
## 참조 문서 (번역)
|
||||
|
||||
- [브라질 포르투칼어](https://github.com/atom/electron/tree/master/docs-translations/pt-BR)
|
||||
- [한국어](https://github.com/atom/electron/tree/master/docs-translations/ko-KR)
|
||||
- [일본어](https://github.com/atom/electron/tree/master/docs-translations/jp)
|
||||
- [스페인어](https://github.com/atom/electron/tree/master/docs-translations/es)
|
||||
- [중국어 간체](https://github.com/atom/electron/tree/master/docs-translations/zh-CN)
|
||||
- [중국어 번체](https://github.com/atom/electron/tree/master/docs-translations/zh-TW)
|
||||
|
||||
## 시작하기
|
||||
|
||||
[`atom/electron-quick-start`](https://github.com/atom/electron-quick-start)
|
||||
저장소를 클론하여 Electron을 간단히 접해볼 수 있습니다.
|
||||
|
||||
## 커뮤니티
|
||||
|
||||
다음 링크를 통해 커뮤니티에 질문을 올리거나 토론을 나눌 수 있습니다:
|
||||
|
||||
- Atom 포럼의 [`electron`](http://discuss.atom.io/c/electron) 카테고리
|
||||
- Freenode 채팅의 `#atom-shell` 채널
|
||||
- Slack의 [`Atom`](http://atom-slack.herokuapp.com/) 채널
|
||||
|
||||
[awesome-electron](https://github.com/sindresorhus/awesome-electron) 프로젝트에
|
||||
커뮤니티가 운영중인 유용한 예제 어플리케이션과 도구, 리소스가 있으니 한번 참고해 보시기
|
||||
바랍니다.
|
||||
66
README.md
66
README.md
@@ -1,39 +1,38 @@
|
||||
[](https://electron.atom.io/)
|
||||
[](http://electron.atom.io/)
|
||||
|
||||
[](https://travis-ci.org/electron/electron)
|
||||
[](https://ci.appveyor.com/project/electron-bot/electron/branch/master)
|
||||
[](https://david-dm.org/electron/electron?type=dev)
|
||||
[](https://travis-ci.org/atom/electron)
|
||||
[](https://david-dm.org/atom/electron#info=devDependencies)
|
||||
[](http://atom-slack.herokuapp.com/)
|
||||
|
||||
:memo: Available Translations: [Korean](https://github.com/electron/electron/tree/master/docs-translations/ko-KR/project/README.md) | [Simplified Chinese](https://github.com/electron/electron/tree/master/docs-translations/zh-CN/project/README.md) | [Brazilian Portuguese](https://github.com/electron/electron/tree/master/docs-translations/pt-BR/project/README.md) | [Traditional Chinese](https://github.com/electron/electron/tree/master/docs-translations/zh-TW/project/README.md) | [Spanish](https://github.com/electron/electron/tree/master/docs-translations/es/project/README.md) | [Turkish](https://github.com/electron/electron/tree/master/docs-translations/tr-TR/project/README.md)
|
||||
:zap: *Formerly known as Atom Shell* :zap:
|
||||
|
||||
The Electron framework lets you write cross-platform desktop applications
|
||||
using JavaScript, HTML and CSS. It is based on [Node.js](https://nodejs.org/) and
|
||||
[Chromium](http://www.chromium.org) and is used by the [Atom
|
||||
editor](https://github.com/atom/atom) and many other [apps](https://electron.atom.io/apps).
|
||||
[Chromium](http://www.chromium.org) and is used in the [Atom
|
||||
editor](https://github.com/atom/atom).
|
||||
|
||||
Follow [@ElectronJS](https://twitter.com/electronjs) on Twitter for important
|
||||
announcements.
|
||||
|
||||
This project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDUCT.md).
|
||||
By participating, you are expected to uphold this code. Please report unacceptable
|
||||
behavior to electron@github.com.
|
||||
behavior to atom@github.com.
|
||||
|
||||
## Downloads
|
||||
|
||||
To install prebuilt Electron binaries, use
|
||||
[`npm`](https://docs.npmjs.com/):
|
||||
Prebuilt binaries and debug symbols of Electron for Linux, Windows and OS X can
|
||||
be found on the [releases](https://github.com/atom/electron/releases) page.
|
||||
|
||||
You can also use [`npm`](https://docs.npmjs.com/) to install prebuilt electron
|
||||
binaries:
|
||||
|
||||
```sh
|
||||
# Install as a development dependency
|
||||
npm install electron --save-dev
|
||||
|
||||
# Install the `electron` command globally in your $PATH
|
||||
npm install electron -g
|
||||
```
|
||||
npm install electron-prebuilt -g
|
||||
|
||||
See the [releases page](https://github.com/electron/electron/releases) for
|
||||
prebuilt binaries, debug symbols, and more.
|
||||
# Install as a development dependency
|
||||
npm install electron-prebuilt --save-dev
|
||||
```
|
||||
|
||||
### Mirrors
|
||||
|
||||
@@ -42,26 +41,22 @@ prebuilt binaries, debug symbols, and more.
|
||||
## Documentation
|
||||
|
||||
Guides and the API reference are located in the
|
||||
[docs](https://github.com/electron/electron/tree/master/docs) directory. It also
|
||||
[docs](https://github.com/atom/electron/tree/master/docs) directory. It also
|
||||
contains documents describing how to build and contribute to Electron.
|
||||
|
||||
## Documentation Translations
|
||||
|
||||
- [Brazilian Portuguese](https://github.com/electron/electron/tree/master/docs-translations/pt-BR)
|
||||
- [Korean](https://github.com/electron/electron/tree/master/docs-translations/ko-KR)
|
||||
- [Japanese](https://github.com/electron/electron/tree/master/docs-translations/jp)
|
||||
- [Spanish](https://github.com/electron/electron/tree/master/docs-translations/es)
|
||||
- [Simplified Chinese](https://github.com/electron/electron/tree/master/docs-translations/zh-CN)
|
||||
- [Traditional Chinese](https://github.com/electron/electron/tree/master/docs-translations/zh-TW)
|
||||
- [Turkish](https://github.com/electron/electron/tree/master/docs-translations/tr-TR)
|
||||
- [Thai](https://github.com/electron/electron/tree/master/docs-Translations/th-TH)
|
||||
- [Ukrainian](https://github.com/electron/electron/tree/master/docs-translations/uk-UA)
|
||||
- [Russian](https://github.com/electron/electron/tree/master/docs-translations/ru-RU)
|
||||
- [French](https://github.com/electron/electron/tree/master/docs-translations/fr-FR)
|
||||
- [Brazilian Portuguese](https://github.com/atom/electron/tree/master/docs-translations/pt-BR)
|
||||
- [Korean](https://github.com/atom/electron/tree/master/docs-translations/ko-KR)
|
||||
- [Japanese](https://github.com/atom/electron/tree/master/docs-translations/jp)
|
||||
- [Spanish](https://github.com/atom/electron/tree/master/docs-translations/es)
|
||||
- [Simplified Chinese](https://github.com/atom/electron/tree/master/docs-translations/zh-CN)
|
||||
- [Traditional Chinese](https://github.com/atom/electron/tree/master/docs-translations/zh-TW)
|
||||
- [Russian](https://github.com/atom/electron/tree/master/docs-translations/ru-RU)
|
||||
|
||||
## Quick Start
|
||||
|
||||
Clone and run the [`electron/electron-quick-start`](https://github.com/electron/electron-quick-start)
|
||||
Clone and run the [`atom/electron-quick-start`](https://github.com/atom/electron-quick-start)
|
||||
repository to see a minimal Electron app in action.
|
||||
|
||||
## Community
|
||||
@@ -72,18 +67,7 @@ locations:
|
||||
forums
|
||||
- `#atom-shell` channel on Freenode
|
||||
- [`Atom`](http://atom-slack.herokuapp.com/) channel on Slack
|
||||
- [`electron-ru`](https://telegram.me/electron_ru) *(Russian)*
|
||||
- [`electron-br`](https://electron-br.slack.com) *(Brazilian Portuguese)*
|
||||
- [`electron-kr`](http://www.meetup.com/electron-kr/) *(Korean)*
|
||||
- [`electron-jp`](https://electron-jp.slack.com) *(Japanese)*
|
||||
- [`electron-tr`](http://electron-tr.herokuapp.com) *(Turkish)*
|
||||
- [`electron-id`](https://electron-id.slack.com) *(Indonesia)*
|
||||
|
||||
Check out [awesome-electron](https://github.com/sindresorhus/awesome-electron)
|
||||
for a community maintained list of useful example apps, tools and resources.
|
||||
|
||||
## License
|
||||
|
||||
[MIT](https://github.com/electron/electron/blob/master/LICENSE)
|
||||
|
||||
When using the Electron or other GitHub logos, be sure to follow the [GitHub logo guidelines](https://github.com/logos).
|
||||
|
||||
@@ -1,9 +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 [electron@github.com](mailto:electron@github.com) and include the word "SECURITY" in the subject line.
|
||||
|
||||
The Electron team will send a response indicating the next steps in handling your report. After the initial reply to your report, the security team will keep you informed of the progress towards a fix and full announcement, and may ask for additional information or guidance.
|
||||
|
||||
Report security bugs in third-party modules to the person or team maintaining the module. You can also report a vulnerability through the [Node Security Project](https://nodesecurity.io/report).
|
||||
25
appveyor.yml
25
appveyor.yml
@@ -1,25 +0,0 @@
|
||||
# appveyor file
|
||||
# http://www.appveyor.com/docs/appveyor-yml
|
||||
version: "{build}"
|
||||
|
||||
os: Visual Studio 2015
|
||||
|
||||
init:
|
||||
- git config --global core.autocrlf input
|
||||
|
||||
platform:
|
||||
- x86
|
||||
- x64
|
||||
|
||||
install:
|
||||
- cmd: SET PATH=C:\Program Files (x86)\MSBuild\14.0\bin\;%PATH%
|
||||
- cmd: SET PATH=C:\python27;%PATH%
|
||||
- cmd: python script/cibuild
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
# disable build and test pahses
|
||||
build: off
|
||||
test: off
|
||||
@@ -4,8 +4,7 @@
|
||||
'product_name%': 'Electron',
|
||||
'company_name%': 'GitHub, Inc',
|
||||
'company_abbr%': 'github',
|
||||
'version%': '1.6.11',
|
||||
'js2c_input_dir': '<(SHARED_INTERMEDIATE_DIR)/js2c',
|
||||
'version%': '0.35.6',
|
||||
},
|
||||
'includes': [
|
||||
'filenames.gypi',
|
||||
@@ -29,8 +28,7 @@
|
||||
'target_name': '<(project_name)',
|
||||
'type': 'executable',
|
||||
'dependencies': [
|
||||
'js2asar',
|
||||
'app2asar',
|
||||
'compile_coffee',
|
||||
'<(project_name)_lib',
|
||||
],
|
||||
'sources': [
|
||||
@@ -68,6 +66,12 @@
|
||||
'<(PRODUCT_DIR)/<(product_name) Framework.framework',
|
||||
],
|
||||
},
|
||||
{
|
||||
'destination': '<(PRODUCT_DIR)/<(product_name).app/Contents/Resources',
|
||||
'files': [
|
||||
'atom/browser/default_app',
|
||||
],
|
||||
},
|
||||
],
|
||||
'postbuilds': [
|
||||
{
|
||||
@@ -88,7 +92,7 @@
|
||||
},
|
||||
# The application doesn't have real localizations, it just has
|
||||
# empty .lproj directories, which is enough to convince Cocoa
|
||||
# that Electron supports those languages.
|
||||
# atom-shell supports those languages.
|
||||
{
|
||||
'postbuild_name': 'Make Empty Localizations',
|
||||
'variables': {
|
||||
@@ -117,6 +121,10 @@
|
||||
],
|
||||
}],
|
||||
],
|
||||
}, { # OS=="mac"
|
||||
'dependencies': [
|
||||
'make_locale_paks',
|
||||
],
|
||||
}], # OS!="mac"
|
||||
['OS=="win"', {
|
||||
'include_dirs': [
|
||||
@@ -126,17 +134,7 @@
|
||||
'VCManifestTool': {
|
||||
'EmbedManifest': 'true',
|
||||
'AdditionalManifestFiles': 'atom/browser/resources/win/atom.manifest',
|
||||
},
|
||||
'VCLinkerTool': {
|
||||
# Chrome builds with this minimum environment which makes e.g.
|
||||
# GetSystemMetrics(SM_CXSIZEFRAME) return Windows XP/2003
|
||||
# compatible metrics. See: https://crbug.com/361720
|
||||
#
|
||||
# The following two settings translate to a linker flag
|
||||
# of /SUBSYSTEM:WINDOWS,5.02
|
||||
'MinimumRequiredVersion': '5.02',
|
||||
'SubSystem': '2',
|
||||
},
|
||||
}
|
||||
},
|
||||
'copies': [
|
||||
{
|
||||
@@ -149,7 +147,7 @@
|
||||
],
|
||||
}, {
|
||||
'copied_libraries': [
|
||||
'<(libchromiumcontent_dir)/ffmpeg.dll',
|
||||
'<(libchromiumcontent_dir)/pdf.dll',
|
||||
],
|
||||
}],
|
||||
],
|
||||
@@ -157,20 +155,27 @@
|
||||
'destination': '<(PRODUCT_DIR)',
|
||||
'files': [
|
||||
'<@(copied_libraries)',
|
||||
'<(libchromiumcontent_dir)/locales',
|
||||
'<(libchromiumcontent_dir)/libEGL.dll',
|
||||
'<(libchromiumcontent_dir)/libGLESv2.dll',
|
||||
'<(libchromiumcontent_dir)/icudtl.dat',
|
||||
'<(libchromiumcontent_dir)/blink_image_resources_200_percent.pak',
|
||||
'<(libchromiumcontent_dir)/content_resources_200_percent.pak',
|
||||
'<(libchromiumcontent_dir)/content_shell.pak',
|
||||
'<(libchromiumcontent_dir)/ui_resources_200_percent.pak',
|
||||
'<(libchromiumcontent_dir)/views_resources_200_percent.pak',
|
||||
'<(libchromiumcontent_dir)/natives_blob.bin',
|
||||
'<(libchromiumcontent_dir)/snapshot_blob.bin',
|
||||
'external_binaries/d3dcompiler_47.dll',
|
||||
'external_binaries/xinput1_3.dll',
|
||||
'external_binaries/msvcp120.dll',
|
||||
'external_binaries/msvcr120.dll',
|
||||
'external_binaries/vccorlib120.dll',
|
||||
],
|
||||
},
|
||||
{
|
||||
'destination': '<(PRODUCT_DIR)/resources',
|
||||
'files': [
|
||||
'atom/browser/default_app',
|
||||
]
|
||||
},
|
||||
],
|
||||
}, {
|
||||
'dependencies': [
|
||||
@@ -191,7 +196,6 @@
|
||||
}, {
|
||||
'copied_libraries': [
|
||||
'<(PRODUCT_DIR)/lib/libnode.so',
|
||||
'<(libchromiumcontent_dir)/libffmpeg.so',
|
||||
],
|
||||
}],
|
||||
],
|
||||
@@ -199,17 +203,18 @@
|
||||
'destination': '<(PRODUCT_DIR)',
|
||||
'files': [
|
||||
'<@(copied_libraries)',
|
||||
'<(libchromiumcontent_dir)/locales',
|
||||
'<(libchromiumcontent_dir)/icudtl.dat',
|
||||
'<(libchromiumcontent_dir)/blink_image_resources_200_percent.pak',
|
||||
'<(libchromiumcontent_dir)/content_resources_200_percent.pak',
|
||||
'<(libchromiumcontent_dir)/content_shell.pak',
|
||||
'<(libchromiumcontent_dir)/ui_resources_200_percent.pak',
|
||||
'<(libchromiumcontent_dir)/views_resources_200_percent.pak',
|
||||
'<(libchromiumcontent_dir)/natives_blob.bin',
|
||||
'<(libchromiumcontent_dir)/snapshot_blob.bin',
|
||||
],
|
||||
},
|
||||
{
|
||||
'destination': '<(PRODUCT_DIR)/resources',
|
||||
'files': [
|
||||
'atom/browser/default_app',
|
||||
]
|
||||
},
|
||||
],
|
||||
}], # OS=="linux"
|
||||
],
|
||||
@@ -218,28 +223,18 @@
|
||||
'target_name': '<(project_name)_lib',
|
||||
'type': 'static_library',
|
||||
'dependencies': [
|
||||
'atom_js2c',
|
||||
'vendor/pdf_viewer/pdf_viewer.gyp:pdf_viewer',
|
||||
'atom_coffee2c',
|
||||
'vendor/brightray/brightray.gyp:brightray',
|
||||
'vendor/node/node.gyp:node',
|
||||
],
|
||||
'defines': [
|
||||
# We need to access internal implementations of Node.
|
||||
'NODE_WANT_INTERNALS=1',
|
||||
'NODE_SHARED_MODE',
|
||||
# This is defined in skia/skia_common.gypi.
|
||||
'SK_SUPPORT_LEGACY_GETTOPDEVICE',
|
||||
# Disable warnings for g_settings_list_schemas.
|
||||
'GLIB_DISABLE_DEPRECATION_WARNINGS',
|
||||
# Defined in Chromium but not exposed in its gyp file.
|
||||
'V8_USE_EXTERNAL_STARTUP_DATA',
|
||||
'V8_SHARED',
|
||||
'USING_V8_SHARED',
|
||||
'USING_V8_PLATFORM_SHARED',
|
||||
'USING_V8_BASE_SHARED',
|
||||
# Remove this after enable_plugins becomes a feature flag.
|
||||
'ENABLE_PLUGINS',
|
||||
'USE_PROPRIETARY_CODECS',
|
||||
],
|
||||
'sources': [
|
||||
'<@(lib_sources)',
|
||||
@@ -261,12 +256,6 @@
|
||||
'vendor/node/deps/cares/include',
|
||||
# The `third_party/WebKit/Source/platform/weborigin/SchemeRegistry.h` is using `platform/PlatformExport.h`.
|
||||
'<(libchromiumcontent_src_dir)/third_party/WebKit/Source',
|
||||
# The 'third_party/libyuv/include/libyuv/scale_argb.h' is using 'libyuv/basic_types.h'.
|
||||
'<(libchromiumcontent_src_dir)/third_party/libyuv/include',
|
||||
# The 'third_party/webrtc/modules/desktop_capture/desktop_frame.h' is using 'webrtc/base/scoped_ptr.h'.
|
||||
'<(libchromiumcontent_src_dir)/third_party/',
|
||||
'<(libchromiumcontent_src_dir)/components/cdm',
|
||||
'<(libchromiumcontent_src_dir)/third_party/widevine',
|
||||
],
|
||||
'direct_dependent_settings': {
|
||||
'include_dirs': [
|
||||
@@ -293,9 +282,6 @@
|
||||
'-lcomctl32.lib',
|
||||
'-lcomdlg32.lib',
|
||||
'-lwininet.lib',
|
||||
'-lwinmm.lib',
|
||||
'-lcrypt32.lib',
|
||||
'-luiautomationcore.lib',
|
||||
],
|
||||
},
|
||||
'dependencies': [
|
||||
@@ -321,10 +307,6 @@
|
||||
'$(SDKROOT)/System/Library/Frameworks/QTKit.framework',
|
||||
],
|
||||
},
|
||||
'xcode_settings': {
|
||||
# ReactiveCocoa which is used by Squirrel requires using __weak.
|
||||
'CLANG_ENABLE_OBJC_WEAK': 'YES',
|
||||
},
|
||||
}], # OS=="mac" and mas_build==0
|
||||
['OS=="mac" and mas_build==1', {
|
||||
'defines': [
|
||||
@@ -337,10 +319,6 @@
|
||||
],
|
||||
}], # OS=="mac" and mas_build==1
|
||||
['OS=="linux"', {
|
||||
'sources': [
|
||||
'<@(lib_sources_linux)',
|
||||
'<@(lib_sources_nss)',
|
||||
],
|
||||
'link_settings': {
|
||||
'ldflags': [
|
||||
# Make binary search for libraries under current directory, so we
|
||||
@@ -366,11 +344,11 @@
|
||||
],
|
||||
}, # target <(product_name)_lib
|
||||
{
|
||||
'target_name': 'js2asar',
|
||||
'target_name': 'compile_coffee',
|
||||
'type': 'none',
|
||||
'actions': [
|
||||
{
|
||||
'action_name': 'js2asar',
|
||||
'action_name': 'compile_coffee',
|
||||
'variables': {
|
||||
'conditions': [
|
||||
['OS=="mac"', {
|
||||
@@ -381,158 +359,41 @@
|
||||
],
|
||||
},
|
||||
'inputs': [
|
||||
'<@(js_sources)',
|
||||
'<@(coffee_sources)',
|
||||
],
|
||||
'outputs': [
|
||||
'<(resources_path)/electron.asar',
|
||||
'<(resources_path)/atom.asar',
|
||||
],
|
||||
'action': [
|
||||
'python',
|
||||
'tools/js2asar.py',
|
||||
'tools/coffee2asar.py',
|
||||
'<@(_outputs)',
|
||||
'lib',
|
||||
'<@(_inputs)',
|
||||
],
|
||||
}
|
||||
],
|
||||
}, # target js2asar
|
||||
}, # target compile_coffee
|
||||
{
|
||||
'target_name': 'app2asar',
|
||||
'target_name': 'atom_coffee2c',
|
||||
'type': 'none',
|
||||
'actions': [
|
||||
{
|
||||
'action_name': 'app2asar',
|
||||
'variables': {
|
||||
'conditions': [
|
||||
['OS=="mac"', {
|
||||
'resources_path': '<(PRODUCT_DIR)/<(product_name).app/Contents/Resources',
|
||||
},{
|
||||
'resources_path': '<(PRODUCT_DIR)/resources',
|
||||
}],
|
||||
],
|
||||
},
|
||||
'action_name': 'atom_coffee2c',
|
||||
'inputs': [
|
||||
'<@(default_app_sources)',
|
||||
],
|
||||
'outputs': [
|
||||
'<(resources_path)/default_app.asar',
|
||||
],
|
||||
'action': [
|
||||
'python',
|
||||
'tools/js2asar.py',
|
||||
'<@(_outputs)',
|
||||
'default_app',
|
||||
'<@(_inputs)',
|
||||
],
|
||||
}
|
||||
],
|
||||
}, # target app2asar
|
||||
{
|
||||
'target_name': 'atom_js2c_copy',
|
||||
'type': 'none',
|
||||
'copies': [
|
||||
{
|
||||
'destination': '<(js2c_input_dir)',
|
||||
'files': [
|
||||
'<@(js2c_sources)',
|
||||
],
|
||||
},
|
||||
],
|
||||
}, # target atom_js2c_copy
|
||||
{
|
||||
'target_name': 'atom_browserify',
|
||||
'type': 'none',
|
||||
'dependencies': [
|
||||
# depend on this target to ensure the '<(js2c_input_dir)' is created
|
||||
'atom_js2c_copy',
|
||||
],
|
||||
'variables': {
|
||||
'sandbox_args': [
|
||||
'./lib/sandboxed_renderer/init.js',
|
||||
'-r',
|
||||
'./lib/sandboxed_renderer/api/exports/electron.js:electron',
|
||||
'-r',
|
||||
'./lib/sandboxed_renderer/api/exports/fs.js:fs',
|
||||
'-r',
|
||||
'./lib/sandboxed_renderer/api/exports/os.js:os',
|
||||
'-r',
|
||||
'./lib/sandboxed_renderer/api/exports/path.js:path',
|
||||
'-r',
|
||||
'./lib/sandboxed_renderer/api/exports/child_process.js:child_process'
|
||||
],
|
||||
'isolated_args': [
|
||||
'lib/isolated_renderer/init.js',
|
||||
]
|
||||
},
|
||||
'actions': [
|
||||
{
|
||||
'action_name': 'atom_browserify_sandbox',
|
||||
'inputs': [
|
||||
'<!@(python tools/list-browserify-deps.py <(sandbox_args))'
|
||||
],
|
||||
'outputs': [
|
||||
'<(js2c_input_dir)/preload_bundle.js',
|
||||
],
|
||||
'action': [
|
||||
'npm',
|
||||
'run',
|
||||
'--silent',
|
||||
'browserify',
|
||||
'--',
|
||||
'<@(sandbox_args)',
|
||||
'-o',
|
||||
'<@(_outputs)',
|
||||
],
|
||||
},
|
||||
{
|
||||
'action_name': 'atom_browserify_isolated_context',
|
||||
'inputs': [
|
||||
'<!@(python tools/list-browserify-deps.py <(isolated_args))'
|
||||
],
|
||||
'outputs': [
|
||||
'<(js2c_input_dir)/isolated_bundle.js',
|
||||
],
|
||||
'action': [
|
||||
'npm',
|
||||
'run',
|
||||
'--silent',
|
||||
'browserify',
|
||||
'--',
|
||||
'<@(isolated_args)',
|
||||
'-o',
|
||||
'<@(_outputs)',
|
||||
],
|
||||
},
|
||||
],
|
||||
}, # target atom_browserify
|
||||
{
|
||||
'target_name': 'atom_js2c',
|
||||
'type': 'none',
|
||||
'dependencies': [
|
||||
'atom_js2c_copy',
|
||||
'atom_browserify',
|
||||
],
|
||||
'actions': [
|
||||
{
|
||||
'action_name': 'atom_js2c',
|
||||
'inputs': [
|
||||
# List all input files that should trigger a rebuild with js2c
|
||||
'<@(js2c_sources)',
|
||||
'<(js2c_input_dir)/preload_bundle.js',
|
||||
'<(js2c_input_dir)/isolated_bundle.js',
|
||||
'<@(coffee2c_sources)',
|
||||
],
|
||||
'outputs': [
|
||||
'<(SHARED_INTERMEDIATE_DIR)/atom_natives.h',
|
||||
],
|
||||
'action': [
|
||||
'python',
|
||||
'tools/js2c.py',
|
||||
'tools/coffee2c.py',
|
||||
'<@(_outputs)',
|
||||
'<(js2c_input_dir)',
|
||||
'<@(_inputs)',
|
||||
],
|
||||
}
|
||||
],
|
||||
}, # target atom_js2c
|
||||
}, # target atom_coffee2c
|
||||
],
|
||||
'conditions': [
|
||||
['OS=="mac"', {
|
||||
@@ -559,9 +420,6 @@
|
||||
'libraries': [
|
||||
'$(SDKROOT)/System/Library/Frameworks/Carbon.framework',
|
||||
'$(SDKROOT)/System/Library/Frameworks/QuartzCore.framework',
|
||||
'$(SDKROOT)/System/Library/Frameworks/Quartz.framework',
|
||||
'$(SDKROOT)/System/Library/Frameworks/Security.framework',
|
||||
'$(SDKROOT)/System/Library/Frameworks/SecurityInterface.framework',
|
||||
],
|
||||
},
|
||||
'mac_bundle': 1,
|
||||
@@ -571,7 +429,6 @@
|
||||
'<(libchromiumcontent_dir)/icudtl.dat',
|
||||
'<(libchromiumcontent_dir)/natives_blob.bin',
|
||||
'<(libchromiumcontent_dir)/snapshot_blob.bin',
|
||||
'<(PRODUCT_DIR)/pdf_viewer_resources.pak',
|
||||
],
|
||||
'xcode_settings': {
|
||||
'ATOM_BUNDLE_ID': 'com.<(company_abbr).<(project_name).framework',
|
||||
@@ -597,7 +454,6 @@
|
||||
}, {
|
||||
'copied_libraries': [
|
||||
'<(PRODUCT_DIR)/libnode.dylib',
|
||||
'<(libchromiumcontent_dir)/libffmpeg.dylib',
|
||||
],
|
||||
}],
|
||||
],
|
||||
@@ -619,6 +475,16 @@
|
||||
'${BUILT_PRODUCTS_DIR}/<(product_name) Framework.framework/Versions/A/<(product_name) Framework',
|
||||
],
|
||||
},
|
||||
{
|
||||
'postbuild_name': 'Fix path of ffmpeg',
|
||||
'action': [
|
||||
'install_name_tool',
|
||||
'-change',
|
||||
'@loader_path/libffmpeg.dylib',
|
||||
'@rpath/libffmpeg.dylib',
|
||||
'${BUILT_PRODUCTS_DIR}/<(product_name) Framework.framework/Versions/A/<(product_name) Framework',
|
||||
],
|
||||
},
|
||||
{
|
||||
'postbuild_name': 'Add symlinks for framework subdirectories',
|
||||
'action': [
|
||||
@@ -627,16 +493,6 @@
|
||||
'Libraries',
|
||||
],
|
||||
},
|
||||
{
|
||||
'postbuild_name': 'Copy locales',
|
||||
'action': [
|
||||
'tools/mac/copy-locales.py',
|
||||
'-d',
|
||||
'<(libchromiumcontent_dir)/locales',
|
||||
'${BUILT_PRODUCTS_DIR}/<(product_name) Framework.framework/Resources',
|
||||
'<@(locales)',
|
||||
],
|
||||
},
|
||||
],
|
||||
'conditions': [
|
||||
['mas_build==0', {
|
||||
@@ -681,6 +537,31 @@
|
||||
},
|
||||
}, # target helper
|
||||
],
|
||||
}, { # OS=="mac"
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'make_locale_paks',
|
||||
'type': 'none',
|
||||
'actions': [
|
||||
{
|
||||
'action_name': 'Make Empty Paks',
|
||||
'inputs': [
|
||||
'tools/make_locale_paks.py',
|
||||
],
|
||||
'outputs': [
|
||||
'<(PRODUCT_DIR)/locales'
|
||||
],
|
||||
'action': [
|
||||
'python',
|
||||
'tools/make_locale_paks.py',
|
||||
'<(PRODUCT_DIR)',
|
||||
'<@(locales)',
|
||||
],
|
||||
'msvs_cygwin_shell': 0,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}], # OS!="mac"
|
||||
],
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
filter=+build/include_alpha
|
||||
@@ -7,27 +7,16 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/common/atom_constants.h"
|
||||
#include "atom/common/atom_version.h"
|
||||
#include "atom/common/chrome_version.h"
|
||||
#include "atom/common/options_switches.h"
|
||||
#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 "pdf/pdf.h"
|
||||
#include "ppapi/shared_impl/ppapi_permissions.h"
|
||||
#include "third_party/widevine/cdm/stub/widevine_cdm_version.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
#include "url/url_constants.h"
|
||||
|
||||
#if defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_PEPPER_CDMS)
|
||||
#include "chrome/common/widevine_cdm_constants.h"
|
||||
#endif
|
||||
|
||||
namespace atom {
|
||||
|
||||
@@ -42,9 +31,9 @@ content::PepperPluginInfo CreatePepperFlashInfo(const base::FilePath& path,
|
||||
plugin.path = path;
|
||||
plugin.permissions = ppapi::PERMISSION_ALL_BITS;
|
||||
|
||||
std::vector<std::string> flash_version_numbers = base::SplitString(
|
||||
version, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
|
||||
if (flash_version_numbers.empty())
|
||||
std::vector<std::string> flash_version_numbers;
|
||||
base::SplitString(version, '.', &flash_version_numbers);
|
||||
if (flash_version_numbers.size() < 1)
|
||||
flash_version_numbers.push_back("11");
|
||||
// |SplitString()| puts in an empty string given an empty string. :(
|
||||
else if (flash_version_numbers[0].empty())
|
||||
@@ -58,7 +47,7 @@ content::PepperPluginInfo CreatePepperFlashInfo(const base::FilePath& path,
|
||||
// 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, ".");
|
||||
plugin.version = JoinString(flash_version_numbers, '.');
|
||||
content::WebPluginMimeType swf_mime_type(
|
||||
content::kFlashPluginSwfMimeType,
|
||||
content::kFlashPluginSwfExtension,
|
||||
@@ -73,111 +62,8 @@ content::PepperPluginInfo CreatePepperFlashInfo(const base::FilePath& path,
|
||||
return plugin;
|
||||
}
|
||||
|
||||
#if defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_PEPPER_CDMS)
|
||||
content::PepperPluginInfo CreateWidevineCdmInfo(const base::FilePath& path,
|
||||
const std::string& version) {
|
||||
content::PepperPluginInfo widevine_cdm;
|
||||
widevine_cdm.is_out_of_process = true;
|
||||
widevine_cdm.path = path;
|
||||
widevine_cdm.name = kWidevineCdmDisplayName;
|
||||
widevine_cdm.description = kWidevineCdmDescription +
|
||||
std::string(" (version: ") +
|
||||
version + ")";
|
||||
widevine_cdm.version = version;
|
||||
content::WebPluginMimeType widevine_cdm_mime_type(
|
||||
kWidevineCdmPluginMimeType,
|
||||
kWidevineCdmPluginExtension,
|
||||
kWidevineCdmPluginMimeTypeDescription);
|
||||
|
||||
// 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 ComputeBuiltInPlugins(std::vector<content::PepperPluginInfo>* plugins) {
|
||||
content::PepperPluginInfo pdf_info;
|
||||
pdf_info.is_internal = true;
|
||||
pdf_info.is_out_of_process = true;
|
||||
pdf_info.name = "Chromium PDF Viewer";
|
||||
pdf_info.description = "Portable Document Format";
|
||||
pdf_info.path = base::FilePath::FromUTF8Unsafe(kPdfPluginPath);
|
||||
content::WebPluginMimeType pdf_mime_type(kPdfPluginMimeType, "pdf",
|
||||
"Portable Document Format");
|
||||
pdf_info.mime_types.push_back(pdf_mime_type);
|
||||
pdf_info.internal_entry_points.get_interface = chrome_pdf::PPP_GetInterface;
|
||||
pdf_info.internal_entry_points.initialize_module =
|
||||
chrome_pdf::PPP_InitializeModule;
|
||||
pdf_info.internal_entry_points.shutdown_module =
|
||||
chrome_pdf::PPP_ShutdownModule;
|
||||
pdf_info.permissions = ppapi::PERMISSION_PRIVATE | ppapi::PERMISSION_DEV;
|
||||
plugins->push_back(pdf_info);
|
||||
}
|
||||
|
||||
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) && BUILDFLAG(ENABLE_PEPPER_CDMS)
|
||||
void AddWidevineCdmFromCommandLine(
|
||||
std::vector<content::PepperPluginInfo>* plugins) {
|
||||
auto command_line = base::CommandLine::ForCurrentProcess();
|
||||
base::FilePath widevine_cdm_path = command_line->GetSwitchValuePath(
|
||||
switches::kWidevineCdmPath);
|
||||
if (widevine_cdm_path.empty())
|
||||
return;
|
||||
|
||||
if (!base::PathExists(widevine_cdm_path))
|
||||
return;
|
||||
|
||||
auto widevine_cdm_version = command_line->GetSwitchValueASCII(
|
||||
switches::kWidevineCdmVersion);
|
||||
if (widevine_cdm_version.empty())
|
||||
return;
|
||||
|
||||
plugins->push_back(CreateWidevineCdmInfo(widevine_cdm_path,
|
||||
widevine_cdm_version));
|
||||
}
|
||||
#endif
|
||||
|
||||
AtomContentClient::AtomContentClient() {
|
||||
}
|
||||
|
||||
@@ -194,45 +80,35 @@ std::string AtomContentClient::GetUserAgent() const {
|
||||
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>* standard_schemes,
|
||||
std::vector<std::string>* savable_schemes) {
|
||||
standard_schemes->push_back({"chrome-extension", url::SCHEME_WITHOUT_PORT});
|
||||
auto command_line = base::CommandLine::ForCurrentProcess();
|
||||
auto custom_schemes = command_line->GetSwitchValueASCII(
|
||||
switches::kRegisterStandardSchemes);
|
||||
if (!custom_schemes.empty()) {
|
||||
std::vector<std::string> schemes;
|
||||
base::SplitString(custom_schemes, ',', &schemes);
|
||||
standard_schemes->insert(standard_schemes->end(),
|
||||
schemes.begin(),
|
||||
schemes.end());
|
||||
}
|
||||
standard_schemes->push_back("chrome-extension");
|
||||
}
|
||||
|
||||
void AtomContentClient::AddPepperPlugins(
|
||||
std::vector<content::PepperPluginInfo>* plugins) {
|
||||
AddPepperFlashFromCommandLine(plugins);
|
||||
#if defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_PEPPER_CDMS)
|
||||
AddWidevineCdmFromCommandLine(plugins);
|
||||
#endif
|
||||
ComputeBuiltInPlugins(plugins);
|
||||
auto command_line = base::CommandLine::ForCurrentProcess();
|
||||
auto 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));
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#ifndef ATOM_APP_ATOM_CONTENT_CLIENT_H_
|
||||
#define ATOM_APP_ATOM_CONTENT_CLIENT_H_
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -22,18 +21,11 @@ class AtomContentClient : public brightray::ContentClient {
|
||||
// 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>* standard_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);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#ifndef ATOM_APP_ATOM_LIBRARY_MAIN_H_
|
||||
#define ATOM_APP_ATOM_LIBRARY_MAIN_H_
|
||||
|
||||
#include "build/build_config.h"
|
||||
#include "base/basictypes.h"
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
extern "C" {
|
||||
|
||||
@@ -7,19 +7,22 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include <windows.h> // windows.h must be included first
|
||||
#include <stdio.h>
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <shellapi.h>
|
||||
#include <windows.h>
|
||||
#include <shellscalingapi.h>
|
||||
#include <tchar.h>
|
||||
#include <shellapi.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 "content/public/app/startup_helper_win.h"
|
||||
#include "sandbox/win/src/sandbox_types.h"
|
||||
#include "ui/gfx/win/dpi.h"
|
||||
#elif defined(OS_LINUX) // defined(OS_WIN)
|
||||
#include "atom/app/atom_main_delegate.h" // NOLINT
|
||||
#include "content/public/app/content_main.h"
|
||||
@@ -35,6 +38,7 @@
|
||||
namespace {
|
||||
|
||||
const char* kRunAsNode = "ELECTRON_RUN_AS_NODE";
|
||||
const char* kOldRunAsNode = "ATOM_SHELL_INTERNAL_RUN_AS_NODE";
|
||||
|
||||
bool IsEnvSet(const char* name) {
|
||||
#if defined(OS_WIN)
|
||||
@@ -47,6 +51,56 @@ bool IsEnvSet(const char* name) {
|
||||
#endif
|
||||
}
|
||||
|
||||
bool IsRunAsNode() {
|
||||
return IsEnvSet(kRunAsNode) || IsEnvSet(kOldRunAsNode);
|
||||
}
|
||||
|
||||
#if defined(OS_WIN)
|
||||
bool IsCygwin() {
|
||||
std::string os;
|
||||
scoped_ptr<base::Environment> env(base::Environment::Create());
|
||||
return env->GetVar("OS", &os) && os == "cygwin";
|
||||
}
|
||||
|
||||
// Win8.1 supports monitor-specific DPI scaling.
|
||||
bool SetProcessDpiAwarenessWrapper(PROCESS_DPI_AWARENESS value) {
|
||||
typedef HRESULT(WINAPI *SetProcessDpiAwarenessPtr)(PROCESS_DPI_AWARENESS);
|
||||
SetProcessDpiAwarenessPtr set_process_dpi_awareness_func =
|
||||
reinterpret_cast<SetProcessDpiAwarenessPtr>(
|
||||
GetProcAddress(GetModuleHandleA("user32.dll"),
|
||||
"SetProcessDpiAwarenessInternal"));
|
||||
if (set_process_dpi_awareness_func) {
|
||||
HRESULT hr = set_process_dpi_awareness_func(value);
|
||||
if (SUCCEEDED(hr)) {
|
||||
VLOG(1) << "SetProcessDpiAwareness succeeded.";
|
||||
return true;
|
||||
} else if (hr == E_ACCESSDENIED) {
|
||||
LOG(ERROR) << "Access denied error from SetProcessDpiAwareness. "
|
||||
"Function called twice, or manifest was used.";
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// This function works for Windows Vista through Win8. Win8.1 must use
|
||||
// SetProcessDpiAwareness[Wrapper].
|
||||
BOOL SetProcessDPIAwareWrapper() {
|
||||
typedef BOOL(WINAPI *SetProcessDPIAwarePtr)(VOID);
|
||||
SetProcessDPIAwarePtr set_process_dpi_aware_func =
|
||||
reinterpret_cast<SetProcessDPIAwarePtr>(
|
||||
GetProcAddress(GetModuleHandleA("user32.dll"),
|
||||
"SetProcessDPIAware"));
|
||||
return set_process_dpi_aware_func &&
|
||||
set_process_dpi_aware_func();
|
||||
}
|
||||
|
||||
void EnableHighDPISupport() {
|
||||
if (!SetProcessDpiAwarenessWrapper(PROCESS_SYSTEM_DPI_AWARE)) {
|
||||
SetProcessDPIAwareWrapper();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
#if defined(OS_WIN)
|
||||
@@ -54,11 +108,14 @@ 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 output work in console if we are not in cygiwn.
|
||||
if (!IsCygwin() && !IsEnvSet("ELECTRON_NO_ATTACH_CONSOLE")) {
|
||||
AttachConsole(ATTACH_PARENT_PROCESS);
|
||||
|
||||
// Make sure the output is printed to console.
|
||||
if (run_as_node || !IsEnvSet("ELECTRON_NO_ATTACH_CONSOLE"))
|
||||
base::RouteStdioToConsole(false);
|
||||
FILE* dontcare;
|
||||
freopen_s(&dontcare, "CON", "w", stdout);
|
||||
freopen_s(&dontcare, "CON", "w", stderr);
|
||||
}
|
||||
|
||||
// Convert argv to to UTF8
|
||||
char** argv = new char*[argc];
|
||||
@@ -94,12 +151,12 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
|
||||
}
|
||||
}
|
||||
|
||||
if (run_as_node) {
|
||||
if (IsRunAsNode()) {
|
||||
// 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")) {
|
||||
} else if (IsEnvSet("ATOM_SHELL_INTERNAL_CRASH_SERVICE")) {
|
||||
return crash_service::Main(cmd);
|
||||
}
|
||||
|
||||
@@ -107,18 +164,23 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
|
||||
content::InitializeSandboxInfo(&sandbox_info);
|
||||
atom::AtomMainDelegate delegate;
|
||||
|
||||
// We don't want to set DPI awareness on pre-Win7 because we don't support
|
||||
// DirectWrite there. GDI fonts are kerned very badly, so better to leave
|
||||
// DPI-unaware and at effective 1.0. See also ShouldUseDirectWrite().
|
||||
if (base::win::GetVersion() >= base::win::VERSION_WIN7)
|
||||
EnableHighDPISupport();
|
||||
|
||||
content::ContentMainParams params(&delegate);
|
||||
params.instance = instance;
|
||||
params.sandbox_info = &sandbox_info;
|
||||
atom::AtomCommandLine::Init(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)) {
|
||||
if (IsRunAsNode()) {
|
||||
base::i18n::InitializeICU();
|
||||
base::AtExitManager atexit_manager;
|
||||
return atom::NodeMain(argc, const_cast<char**>(argv));
|
||||
@@ -135,7 +197,7 @@ int main(int argc, const char* argv[]) {
|
||||
#else // defined(OS_LINUX)
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
if (IsEnvSet(kRunAsNode)) {
|
||||
if (IsRunAsNode()) {
|
||||
return AtomInitializeICUandStartNode(argc, const_cast<char**>(argv));
|
||||
}
|
||||
|
||||
|
||||
@@ -4,16 +4,13 @@
|
||||
|
||||
#include "atom/app/atom_main_delegate.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
#include "atom/app/atom_content_client.h"
|
||||
#include "atom/browser/atom_browser_client.h"
|
||||
#include "atom/browser/relauncher.h"
|
||||
#include "atom/common/google_api_key.h"
|
||||
#include "atom/common/options_switches.h"
|
||||
#include "atom/renderer/atom_renderer_client.h"
|
||||
#include "atom/renderer/atom_sandboxed_renderer_client.h"
|
||||
#include "atom/utility/atom_content_utility_client.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/debug/stack_trace.h"
|
||||
@@ -21,27 +18,17 @@
|
||||
#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);
|
||||
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() {
|
||||
@@ -73,8 +60,8 @@ bool AtomMainDelegate::BasicStartupComplete(int* exit_code) {
|
||||
#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) &&
|
||||
scoped_ptr<base::Environment> env(base::Environment::Create());
|
||||
if (!command_line->HasSwitch(switches::kEnableLogging) &&
|
||||
!env->HasVar("ELECTRON_ENABLE_LOGGING")) {
|
||||
settings.logging_dest = logging::LOG_NONE;
|
||||
logging::SetMinLogLevel(logging::LOG_NUM_SEVERITIES);
|
||||
@@ -95,18 +82,6 @@ bool AtomMainDelegate::BasicStartupComplete(int* exit_code) {
|
||||
|
||||
chrome::RegisterPathProvider();
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
SetUpBundleOverrides();
|
||||
#endif
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// Ignore invalid parameter errors.
|
||||
_set_invalid_parameter_handler(InvalidParameterHandler);
|
||||
// Disable the ActiveVerifier, which is used by Chrome to track possible
|
||||
// bugs, but no use in Electron.
|
||||
base::win::DisableHandleVerifier();
|
||||
#endif
|
||||
|
||||
return brightray::MainDelegate::BasicStartupComplete(exit_code);
|
||||
}
|
||||
|
||||
@@ -114,29 +89,27 @@ void AtomMainDelegate::PreSandboxStartup() {
|
||||
brightray::MainDelegate::PreSandboxStartup();
|
||||
|
||||
// Set google API key.
|
||||
std::unique_ptr<base::Environment> env(base::Environment::Create());
|
||||
scoped_ptr<base::Environment> env(base::Environment::Create());
|
||||
if (!env->HasVar("GOOGLE_API_KEY"))
|
||||
env->SetVar("GOOGLE_API_KEY", GOOGLEAPIS_API_KEY);
|
||||
|
||||
auto command_line = base::CommandLine::ForCurrentProcess();
|
||||
std::string process_type = command_line->GetSwitchValueASCII(
|
||||
::switches::kProcessType);
|
||||
switches::kProcessType);
|
||||
|
||||
if (process_type == switches::kUtilityProcess) {
|
||||
AtomContentUtilityClient::PreSandboxStartup();
|
||||
}
|
||||
|
||||
// Only append arguments for browser process.
|
||||
if (!IsBrowserProcess(command_line))
|
||||
return;
|
||||
|
||||
if (command_line->HasSwitch(switches::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);
|
||||
}
|
||||
// Disable renderer sandbox for most of node's functions.
|
||||
command_line->AppendSwitch(switches::kNoSandbox);
|
||||
|
||||
// Allow file:// URIs to read other file:// URIs by default.
|
||||
command_line->AppendSwitch(::switches::kAllowFileAccessFromFiles);
|
||||
command_line->AppendSwitch(switches::kAllowFileAccessFromFiles);
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
// Enable AVFoundation.
|
||||
@@ -151,13 +124,7 @@ content::ContentBrowserClient* AtomMainDelegate::CreateContentBrowserClient() {
|
||||
|
||||
content::ContentRendererClient*
|
||||
AtomMainDelegate::CreateContentRendererClient() {
|
||||
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
|
||||
switches::kEnableSandbox)) {
|
||||
renderer_client_.reset(new AtomSandboxedRendererClient);
|
||||
} else {
|
||||
renderer_client_.reset(new AtomRendererClient);
|
||||
}
|
||||
|
||||
renderer_client_.reset(new AtomRendererClient);
|
||||
return renderer_client_.get();
|
||||
}
|
||||
|
||||
@@ -166,29 +133,20 @@ content::ContentUtilityClient* AtomMainDelegate::CreateContentUtilityClient() {
|
||||
return utility_client_.get();
|
||||
}
|
||||
|
||||
int AtomMainDelegate::RunProcess(
|
||||
const std::string& process_type,
|
||||
const content::MainFunctionParams& main_function_params) {
|
||||
if (process_type == kRelauncherProcess)
|
||||
return relauncher::RelauncherMain(main_function_params);
|
||||
else
|
||||
return -1;
|
||||
scoped_ptr<brightray::ContentClient> AtomMainDelegate::CreateContentClient() {
|
||||
return scoped_ptr<brightray::ContentClient>(new AtomContentClient).Pass();
|
||||
}
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
bool AtomMainDelegate::ShouldSendMachPort(const std::string& process_type) {
|
||||
return process_type != kRelauncherProcess;
|
||||
}
|
||||
|
||||
bool AtomMainDelegate::DelaySandboxInitialization(
|
||||
const std::string& process_type) {
|
||||
return process_type == kRelauncherProcess;
|
||||
}
|
||||
void AtomMainDelegate::AddDataPackFromPath(
|
||||
ui::ResourceBundle* bundle, const base::FilePath& pak_dir) {
|
||||
#if defined(OS_WIN)
|
||||
bundle->AddDataPackFromPath(
|
||||
pak_dir.Append(FILE_PATH_LITERAL("ui_resources_200_percent.pak")),
|
||||
ui::SCALE_FACTOR_200P);
|
||||
bundle->AddDataPackFromPath(
|
||||
pak_dir.Append(FILE_PATH_LITERAL("content_resources_200_percent.pak")),
|
||||
ui::SCALE_FACTOR_200P);
|
||||
#endif
|
||||
|
||||
std::unique_ptr<brightray::ContentClient>
|
||||
AtomMainDelegate::CreateContentClient() {
|
||||
return std::unique_ptr<brightray::ContentClient>(new AtomContentClient);
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -5,10 +5,8 @@
|
||||
#ifndef ATOM_APP_ATOM_MAIN_DELEGATE_H_
|
||||
#define ATOM_APP_ATOM_MAIN_DELEGATE_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "brightray/common/content_client.h"
|
||||
#include "brightray/common/main_delegate.h"
|
||||
#include "brightray/common/content_client.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
@@ -24,30 +22,21 @@ class AtomMainDelegate : public brightray::MainDelegate {
|
||||
content::ContentBrowserClient* CreateContentBrowserClient() override;
|
||||
content::ContentRendererClient* CreateContentRendererClient() override;
|
||||
content::ContentUtilityClient* CreateContentUtilityClient() override;
|
||||
int RunProcess(
|
||||
const std::string& process_type,
|
||||
const content::MainFunctionParams& main_function_params) override;
|
||||
#if defined(OS_MACOSX)
|
||||
bool ShouldSendMachPort(const std::string& process_type) override;
|
||||
bool DelaySandboxInitialization(const std::string& process_type) override;
|
||||
#endif
|
||||
|
||||
// brightray::MainDelegate:
|
||||
std::unique_ptr<brightray::ContentClient> CreateContentClient() override;
|
||||
scoped_ptr<brightray::ContentClient> CreateContentClient() override;
|
||||
void AddDataPackFromPath(
|
||||
ui::ResourceBundle* bundle, const base::FilePath& pak_dir) override;
|
||||
#if defined(OS_MACOSX)
|
||||
void OverrideChildProcessPath() override;
|
||||
void OverrideFrameworkBundlePath() override;
|
||||
#endif
|
||||
|
||||
private:
|
||||
#if defined(OS_MACOSX)
|
||||
void SetUpBundleOverrides();
|
||||
#endif
|
||||
|
||||
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_;
|
||||
scoped_ptr<content::ContentBrowserClient> browser_client_;
|
||||
scoped_ptr<content::ContentRendererClient> renderer_client_;
|
||||
scoped_ptr<content::ContentUtilityClient> utility_client_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomMainDelegate);
|
||||
};
|
||||
|
||||
@@ -7,10 +7,7 @@
|
||||
#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"
|
||||
@@ -51,15 +48,4 @@ void AtomMainDelegate::OverrideChildProcessPath() {
|
||||
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
|
||||
|
||||
@@ -7,18 +7,12 @@
|
||||
#include "atom/app/uv_task_runner.h"
|
||||
#include "atom/browser/javascript_environment.h"
|
||||
#include "atom/browser/node_debugger.h"
|
||||
#include "atom/common/api/atom_bindings.h"
|
||||
#include "atom/common/crash_reporter/crash_reporter.h"
|
||||
#include "atom/common/native_mate_converters/string16_converter.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/feature_list.h"
|
||||
#include "base/threading/thread_task_runner_handle.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "base/thread_task_runner_handle.h"
|
||||
#include "gin/array_buffer.h"
|
||||
#include "gin/public/isolate_holder.h"
|
||||
#include "gin/v8_initializer.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
@@ -33,11 +27,6 @@ int NodeMain(int argc, char *argv[]) {
|
||||
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;
|
||||
@@ -46,26 +35,14 @@ int NodeMain(int argc, char *argv[]) {
|
||||
const char** exec_argv;
|
||||
node::Init(&argc, const_cast<const char**>(argv), &exec_argc, &exec_argv);
|
||||
|
||||
node::IsolateData isolate_data(gin_env.isolate(), loop);
|
||||
node::Environment* env = node::CreateEnvironment(
|
||||
&isolate_data, gin_env.context(), argc, argv,
|
||||
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(gin_env.isolate()));
|
||||
|
||||
mate::Dictionary process(gin_env.isolate(), env->process_object());
|
||||
#if defined(OS_WIN)
|
||||
process.SetMethod("log", &AtomBindings::Log);
|
||||
#endif
|
||||
process.SetMethod("crash", &AtomBindings::Crash);
|
||||
|
||||
// Setup process.crashReporter.start in child node processes
|
||||
auto reporter = mate::Dictionary::CreateEmpty(gin_env.isolate());
|
||||
reporter.SetMethod("start", &crash_reporter::CrashReporter::StartInstance);
|
||||
process.Set("crashReporter", reporter);
|
||||
env->AssignToContext(v8::Debug::GetDebugContext());
|
||||
|
||||
node::LoadEnvironment(env);
|
||||
|
||||
@@ -86,7 +63,7 @@ int NodeMain(int argc, char *argv[]) {
|
||||
exit_code = node::EmitExit(env);
|
||||
node::RunAtExit(env);
|
||||
|
||||
node::FreeEnvironment(env);
|
||||
env->Dispose();
|
||||
}
|
||||
|
||||
v8::V8::Dispose();
|
||||
|
||||
@@ -21,7 +21,7 @@ UvTaskRunner::~UvTaskRunner() {
|
||||
bool UvTaskRunner::PostDelayedTask(const tracked_objects::Location& from_here,
|
||||
const base::Closure& task,
|
||||
base::TimeDelta delay) {
|
||||
auto* timer = new uv_timer_t;
|
||||
uv_timer_t* timer = new uv_timer_t;
|
||||
timer->data = this;
|
||||
uv_timer_init(loop_, timer);
|
||||
uv_timer_start(timer, UvTaskRunner::OnTimeout, delay.InMilliseconds(), 0);
|
||||
@@ -37,7 +37,7 @@ bool UvTaskRunner::PostNonNestableDelayedTask(
|
||||
const tracked_objects::Location& from_here,
|
||||
const base::Closure& task,
|
||||
base::TimeDelta delay) {
|
||||
return PostDelayedTask(from_here, task, delay);
|
||||
return PostDelayedTask(from_here, task, delay);;
|
||||
}
|
||||
|
||||
// static
|
||||
|
||||
@@ -12,41 +12,30 @@
|
||||
#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/net_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/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/browser/browser_process.h"
|
||||
#include "chrome/browser/icon_manager.h"
|
||||
#include "chrome/common/chrome_paths.h"
|
||||
#include "content/public/browser/browser_accessibility_state.h"
|
||||
#include "content/public/browser/browser_child_process_host.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
|
||||
|
||||
@@ -73,290 +62,17 @@ struct Converter<Browser::UserTask> {
|
||||
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));
|
||||
dict.Get("path", &(out->path));
|
||||
dict.Get("args", &(out->args));
|
||||
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();
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Converter<content::CertificateRequestResultType> {
|
||||
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
|
||||
content::CertificateRequestResultType* out) {
|
||||
bool b;
|
||||
if (!ConvertFromV8(isolate, val, &b))
|
||||
return false;
|
||||
*out = b ? content::CERTIFICATE_REQUEST_RESULT_TYPE_CONTINUE :
|
||||
content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
namespace {
|
||||
|
||||
class AppIdProcessIterator : public base::ProcessIterator {
|
||||
public:
|
||||
AppIdProcessIterator() : base::ProcessIterator(nullptr) {}
|
||||
|
||||
protected:
|
||||
bool IncludeEntry() override {
|
||||
return (entry().parent_pid() == base::GetCurrentProcId() ||
|
||||
entry().pid() == base::GetCurrentProcId());
|
||||
}
|
||||
};
|
||||
|
||||
IconLoader::IconSize GetIconSizeByString(const std::string& size) {
|
||||
if (size == "small") {
|
||||
return IconLoader::IconSize::SMALL;
|
||||
} else if (size == "large") {
|
||||
return IconLoader::IconSize::LARGE;
|
||||
}
|
||||
return IconLoader::IconSize::NORMAL;
|
||||
}
|
||||
|
||||
// Return the path constant from string.
|
||||
int GetPathConstant(const std::string& name) {
|
||||
if (name == "appData")
|
||||
@@ -387,8 +103,6 @@ int GetPathConstant(const std::string& name) {
|
||||
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;
|
||||
}
|
||||
@@ -414,32 +128,20 @@ 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.");
|
||||
if (!(args->Length() == 1 && args->GetNext(&cert_data))) {
|
||||
args->ThrowError();
|
||||
return;
|
||||
}
|
||||
|
||||
std::string data;
|
||||
if (!cert_data.Get("data", &data))
|
||||
return;
|
||||
std::string encoded_data;
|
||||
cert_data.Get("data", &encoded_data);
|
||||
|
||||
auto certs = net::X509Certificate::CreateCertificateListFromBytes(
|
||||
data.c_str(), data.length(), net::X509Certificate::FORMAT_AUTO);
|
||||
if (!certs.empty())
|
||||
delegate->ContinueWithCertificate(certs[0].get());
|
||||
auto certs =
|
||||
net::X509Certificate::CreateCertificateListFromBytes(
|
||||
encoded_data.data(), encoded_data.size(),
|
||||
net::X509Certificate::FORMAT_AUTO);
|
||||
delegate->ContinueWithCertificate(certs[0].get());
|
||||
}
|
||||
|
||||
void PassLoginInformation(scoped_refptr<LoginHandler> login_handler,
|
||||
@@ -451,61 +153,12 @@ void PassLoginInformation(scoped_refptr<LoginHandler> login_handler,
|
||||
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
|
||||
|
||||
void OnIconDataAvailable(v8::Isolate* isolate,
|
||||
const App::FileIconCallback& callback,
|
||||
gfx::Image* icon) {
|
||||
v8::Locker locker(isolate);
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
|
||||
if (icon && !icon->IsEmpty()) {
|
||||
callback.Run(v8::Null(isolate), *icon);
|
||||
} else {
|
||||
v8::Local<v8::String> error_message =
|
||||
v8::String::NewFromUtf8(isolate, "Failed to get file icon.");
|
||||
callback.Run(v8::Exception::Error(error_message), gfx::Image());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
App::App(v8::Isolate* isolate) {
|
||||
App::App() {
|
||||
static_cast<AtomBrowserClient*>(AtomBrowserClient::Get())->set_delegate(this);
|
||||
Browser::Get()->AddObserver(this);
|
||||
content::GpuDataManager::GetInstance()->AddObserver(this);
|
||||
Init(isolate);
|
||||
}
|
||||
|
||||
App::~App() {
|
||||
@@ -528,10 +181,9 @@ void App::OnWindowAllClosed() {
|
||||
}
|
||||
|
||||
void App::OnQuit() {
|
||||
int exitCode = AtomBrowserMainParts::Get()->GetExitCode();
|
||||
Emit("quit", exitCode);
|
||||
Emit("quit");
|
||||
|
||||
if (process_singleton_) {
|
||||
if (process_singleton_.get()) {
|
||||
process_singleton_->Cleanup();
|
||||
process_singleton_.reset();
|
||||
}
|
||||
@@ -553,36 +205,17 @@ 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::OnFinishLaunching() {
|
||||
Emit("ready");
|
||||
}
|
||||
|
||||
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) {
|
||||
void App::OnLogin(LoginHandler* login_handler) {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
bool prevent_default = Emit(
|
||||
"login",
|
||||
WebContents::CreateFrom(isolate(), login_handler->GetWebContents()),
|
||||
request_details,
|
||||
login_handler->request(),
|
||||
login_handler->auth_info(),
|
||||
base::Bind(&PassLoginInformation, make_scoped_refptr(login_handler)));
|
||||
|
||||
@@ -591,32 +224,9 @@ void App::OnLogin(LoginHandler* login_handler,
|
||||
login_handler->CancelAuth();
|
||||
}
|
||||
|
||||
void App::OnCreateWindow(
|
||||
const GURL& target_url,
|
||||
const std::string& frame_name,
|
||||
WindowOpenDisposition disposition,
|
||||
const std::vector<std::string>& features,
|
||||
const scoped_refptr<content::ResourceRequestBodyImpl>& body,
|
||||
int render_process_id,
|
||||
int render_frame_id) {
|
||||
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 pid,
|
||||
int fid,
|
||||
int cert_error,
|
||||
const net::SSLInfo& ssl_info,
|
||||
const GURL& request_url,
|
||||
@@ -624,8 +234,11 @@ void App::AllowCertificateError(
|
||||
bool overridable,
|
||||
bool strict_enforcement,
|
||||
bool expired_previous_decision,
|
||||
const base::Callback<void(content::CertificateRequestResultType)>&
|
||||
callback) {
|
||||
const base::Callback<void(bool)>& callback,
|
||||
content::CertificateRequestResultType* request) {
|
||||
auto rfh = content::RenderFrameHost::FromID(pid, fid);
|
||||
auto web_contents = content::WebContents::FromRenderFrameHost(rfh);
|
||||
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
bool prevent_default = Emit("certificate-error",
|
||||
@@ -637,13 +250,13 @@ void App::AllowCertificateError(
|
||||
|
||||
// Deny the certificate by default.
|
||||
if (!prevent_default)
|
||||
callback.Run(content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY);
|
||||
*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) {
|
||||
scoped_ptr<content::ClientCertificateDelegate> delegate) {
|
||||
std::shared_ptr<content::ClientCertificateDelegate>
|
||||
shared_delegate(delegate.release());
|
||||
bool prevent_default =
|
||||
@@ -661,17 +274,8 @@ void App::SelectClientCertificate(
|
||||
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::GetAppPath() const {
|
||||
return app_path_;
|
||||
}
|
||||
|
||||
void App::SetAppPath(const base::FilePath& app_path) {
|
||||
app_path_ = app_path;
|
||||
void App::OnGpuProcessCrashed(base::TerminationStatus exit_code) {
|
||||
Emit("gpu-process-crashed");
|
||||
}
|
||||
|
||||
base::FilePath App::GetPath(mate::Arguments* args, const std::string& name) {
|
||||
@@ -681,40 +285,41 @@ base::FilePath App::GetPath(mate::Arguments* args, const std::string& name) {
|
||||
if (key >= 0)
|
||||
succeed = PathService::Get(key, &path);
|
||||
if (!succeed)
|
||||
args->ThrowError("Failed to get '" + name + "' path");
|
||||
args->ThrowError("Failed to get 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);
|
||||
succeed = PathService::Override(key, path);
|
||||
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());
|
||||
scoped_ptr<base::Environment> env(base::Environment::Create());
|
||||
env->SetVar("CHROME_DESKTOP", desktop_name);
|
||||
#endif
|
||||
}
|
||||
|
||||
void App::AllowNTLMCredentialsForAllDomains(bool should_allow) {
|
||||
auto browser_context = static_cast<AtomBrowserContext*>(
|
||||
AtomBrowserMainParts::Get()->browser_context());
|
||||
browser_context->AllowNTLMCredentialsForAllDomains(should_allow);
|
||||
}
|
||||
|
||||
std::string App::GetLocale() {
|
||||
return l10n_util::GetApplicationLocale("");
|
||||
}
|
||||
|
||||
bool App::MakeSingleInstance(
|
||||
const ProcessSingleton::NotificationCallback& callback) {
|
||||
if (process_singleton_)
|
||||
if (process_singleton_.get())
|
||||
return false;
|
||||
|
||||
base::FilePath user_dir;
|
||||
@@ -734,247 +339,10 @@ bool App::MakeSingleInstance(
|
||||
}
|
||||
}
|
||||
|
||||
void App::ReleaseSingleInstance() {
|
||||
if (process_singleton_) {
|
||||
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();
|
||||
}
|
||||
|
||||
Browser::LoginItemSettings App::GetLoginItemSettings(mate::Arguments* args) {
|
||||
Browser::LoginItemSettings options;
|
||||
args->GetNext(&options);
|
||||
return Browser::Get()->GetLoginItemSettings(options);
|
||||
}
|
||||
|
||||
#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)
|
||||
|
||||
void App::GetFileIcon(const base::FilePath& path,
|
||||
mate::Arguments* args) {
|
||||
mate::Dictionary options;
|
||||
IconLoader::IconSize icon_size;
|
||||
FileIconCallback callback;
|
||||
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
|
||||
base::FilePath normalized_path = path.NormalizePathSeparators();
|
||||
|
||||
if (!args->GetNext(&options)) {
|
||||
icon_size = IconLoader::IconSize::NORMAL;
|
||||
} else {
|
||||
std::string icon_size_string;
|
||||
options.Get("size", &icon_size_string);
|
||||
icon_size = GetIconSizeByString(icon_size_string);
|
||||
}
|
||||
|
||||
if (!args->GetNext(&callback)) {
|
||||
args->ThrowError("Missing required callback function");
|
||||
return;
|
||||
}
|
||||
|
||||
auto icon_manager = g_browser_process->GetIconManager();
|
||||
gfx::Image* icon =
|
||||
icon_manager->LookupIconFromFilepath(normalized_path, icon_size);
|
||||
if (icon) {
|
||||
callback.Run(v8::Null(isolate()), *icon);
|
||||
} else {
|
||||
icon_manager->LoadIcon(
|
||||
normalized_path, icon_size,
|
||||
base::Bind(&OnIconDataAvailable, isolate(), callback),
|
||||
&cancelable_task_tracker_);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<mate::Dictionary> App::GetAppMemoryInfo(v8::Isolate* isolate) {
|
||||
AppIdProcessIterator process_iterator;
|
||||
auto process_entry = process_iterator.NextProcessEntry();
|
||||
std::vector<mate::Dictionary> result;
|
||||
|
||||
while (process_entry != nullptr) {
|
||||
int64_t pid = process_entry->pid();
|
||||
auto process = base::Process::OpenWithExtraPrivileges(pid);
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
std::unique_ptr<base::ProcessMetrics> metrics(
|
||||
base::ProcessMetrics::CreateProcessMetrics(
|
||||
process.Handle(), content::BrowserChildProcessHost::GetPortProvider()));
|
||||
#else
|
||||
std::unique_ptr<base::ProcessMetrics> metrics(
|
||||
base::ProcessMetrics::CreateProcessMetrics(process.Handle()));
|
||||
#endif
|
||||
|
||||
mate::Dictionary pid_dict = mate::Dictionary::CreateEmpty(isolate);
|
||||
mate::Dictionary memory_dict = mate::Dictionary::CreateEmpty(isolate);
|
||||
|
||||
memory_dict.Set("workingSetSize",
|
||||
static_cast<double>(metrics->GetWorkingSetSize() >> 10));
|
||||
memory_dict.Set("peakWorkingSetSize",
|
||||
static_cast<double>(metrics->GetPeakWorkingSetSize() >> 10));
|
||||
|
||||
size_t private_bytes, shared_bytes;
|
||||
if (metrics->GetMemoryBytes(&private_bytes, &shared_bytes)) {
|
||||
memory_dict.Set("privateBytes", static_cast<double>(private_bytes >> 10));
|
||||
memory_dict.Set("sharedBytes", static_cast<double>(shared_bytes >> 10));
|
||||
}
|
||||
|
||||
pid_dict.Set("memory", memory_dict);
|
||||
pid_dict.Set("pid", pid);
|
||||
result.push_back(pid_dict);
|
||||
process_entry = process_iterator.NextProcessEntry();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// 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"));
|
||||
mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) {
|
||||
auto browser = base::Unretained(Browser::Get());
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
return mate::ObjectTemplateBuilder(isolate)
|
||||
.SetMethod("quit", base::Bind(&Browser::Quit, browser))
|
||||
.SetMethod("exit", base::Bind(&Browser::Exit, browser))
|
||||
.SetMethod("focus", base::Bind(&Browser::Focus, browser))
|
||||
@@ -989,54 +357,22 @@ void App::BuildPrototype(
|
||||
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", &App::GetLoginItemSettings)
|
||||
.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)
|
||||
.SetMethod("setUserTasks",
|
||||
base::Bind(&Browser::SetUserTasks, browser))
|
||||
#endif
|
||||
#if defined(OS_LINUX)
|
||||
.SetMethod("isUnityRunning",
|
||||
base::Bind(&Browser::IsUnityRunning, browser))
|
||||
#endif
|
||||
.SetMethod("setAppPath", &App::SetAppPath)
|
||||
.SetMethod("getAppPath", &App::GetAppPath)
|
||||
.SetMethod("setPath", &App::SetPath)
|
||||
.SetMethod("getPath", &App::GetPath)
|
||||
.SetMethod("setDesktopName", &App::SetDesktopName)
|
||||
.SetMethod("allowNTLMCredentialsForAllDomains",
|
||||
&App::AllowNTLMCredentialsForAllDomains)
|
||||
.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)
|
||||
.SetMethod("getFileIcon", &App::GetFileIcon)
|
||||
.SetMethod("getAppMemoryInfo", &App::GetAppMemoryInfo);
|
||||
.SetMethod("makeSingleInstance", &App::MakeSingleInstance);
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<App> App::Create(v8::Isolate* isolate) {
|
||||
return CreateHandle(isolate, new App);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
@@ -1049,8 +385,8 @@ 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) ||
|
||||
if (switch_string == atom::switches::kPpapiFlashPath ||
|
||||
switch_string == atom::switches::kClientCertificate ||
|
||||
switch_string == switches::kLogNetLog) {
|
||||
base::FilePath path;
|
||||
args->GetNext(&path);
|
||||
@@ -1086,7 +422,6 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
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",
|
||||
@@ -1097,17 +432,13 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
@@ -6,25 +6,14 @@
|
||||
#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.h"
|
||||
#include "atom/browser/browser_observer.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "base/process/process_iterator.h"
|
||||
#include "base/task/cancelable_task_tracker.h"
|
||||
#include "chrome/browser/icon_manager.h"
|
||||
#include "chrome/browser/process_singleton.h"
|
||||
#include "content/public/browser/gpu_data_manager_observer.h"
|
||||
#include "native_mate/dictionary.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;
|
||||
@@ -32,51 +21,22 @@ 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 mate::EventEmitter,
|
||||
public BrowserObserver,
|
||||
public content::GpuDataManagerObserver {
|
||||
public:
|
||||
using FileIconCallback = base::Callback<void(v8::Local<v8::Value>,
|
||||
const gfx::Image&)>;
|
||||
|
||||
static mate::Handle<App> Create(v8::Isolate* isolate);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
// Called when window with disposition needs to be created.
|
||||
void OnCreateWindow(
|
||||
const GURL& target_url,
|
||||
const std::string& frame_name,
|
||||
WindowOpenDisposition disposition,
|
||||
const std::vector<std::string>& features,
|
||||
const scoped_refptr<content::ResourceRequestBodyImpl>& body,
|
||||
int render_process_id,
|
||||
int render_frame_id);
|
||||
|
||||
#if defined(USE_NSS_CERTS)
|
||||
void OnCertificateManagerModelCreated(
|
||||
std::unique_ptr<base::DictionaryValue> options,
|
||||
const net::CompletionCallback& callback,
|
||||
std::unique_ptr<CertificateManagerModel> model);
|
||||
#endif
|
||||
|
||||
base::FilePath GetAppPath() const;
|
||||
|
||||
protected:
|
||||
explicit App(v8::Isolate* isolate);
|
||||
~App() override;
|
||||
App();
|
||||
virtual ~App();
|
||||
|
||||
// BrowserObserver:
|
||||
void OnBeforeQuit(bool* prevent_default) override;
|
||||
@@ -87,20 +47,13 @@ class App : public AtomBrowserClient::Delegate,
|
||||
void OnOpenURL(const std::string& url) override;
|
||||
void OnActivate(bool has_visible_windows) override;
|
||||
void OnWillFinishLaunching() override;
|
||||
void OnFinishLaunching(const base::DictionaryValue& launch_info) override;
|
||||
void OnLogin(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
|
||||
void OnFinishLaunching() override;
|
||||
void OnLogin(LoginHandler* login_handler) override;
|
||||
|
||||
// content::ContentBrowserClient:
|
||||
void AllowCertificateError(
|
||||
content::WebContents* web_contents,
|
||||
int render_process_id,
|
||||
int render_frame_id,
|
||||
int cert_error,
|
||||
const net::SSLInfo& ssl_info,
|
||||
const GURL& request_url,
|
||||
@@ -108,19 +61,21 @@ class App : public AtomBrowserClient::Delegate,
|
||||
bool overridable,
|
||||
bool strict_enforcement,
|
||||
bool expired_previous_decision,
|
||||
const base::Callback<void(content::CertificateRequestResultType)>&
|
||||
callback) override;
|
||||
const base::Callback<void(bool)>& callback,
|
||||
content::CertificateRequestResultType* request) override;
|
||||
void SelectClientCertificate(
|
||||
content::WebContents* web_contents,
|
||||
net::SSLCertRequestInfo* cert_request_info,
|
||||
std::unique_ptr<content::ClientCertificateDelegate> delegate) override;
|
||||
scoped_ptr<content::ClientCertificateDelegate> delegate) override;
|
||||
|
||||
// content::GpuDataManagerObserver:
|
||||
void OnGpuProcessCrashed(base::TerminationStatus status) override;
|
||||
void OnGpuProcessCrashed(base::TerminationStatus exit_code) override;
|
||||
|
||||
// mate::Wrappable:
|
||||
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) override;
|
||||
|
||||
private:
|
||||
void SetAppPath(const base::FilePath& app_path);
|
||||
|
||||
// Get/Set the pre-defined path in PathService.
|
||||
base::FilePath GetPath(mate::Arguments* args, const std::string& name);
|
||||
void SetPath(mate::Arguments* args,
|
||||
@@ -128,41 +83,12 @@ class App : public AtomBrowserClient::Delegate,
|
||||
const base::FilePath& path);
|
||||
|
||||
void SetDesktopName(const std::string& desktop_name);
|
||||
std::string GetLocale();
|
||||
void AllowNTLMCredentialsForAllDomains(bool should_allow);
|
||||
bool MakeSingleInstance(
|
||||
const ProcessSingleton::NotificationCallback& callback);
|
||||
void ReleaseSingleInstance();
|
||||
bool Relaunch(mate::Arguments* args);
|
||||
void DisableHardwareAcceleration(mate::Arguments* args);
|
||||
bool IsAccessibilitySupportEnabled();
|
||||
Browser::LoginItemSettings GetLoginItemSettings(mate::Arguments* args);
|
||||
#if defined(USE_NSS_CERTS)
|
||||
void ImportCertificate(const base::DictionaryValue& options,
|
||||
const net::CompletionCallback& callback);
|
||||
#endif
|
||||
void GetFileIcon(const base::FilePath& path,
|
||||
mate::Arguments* args);
|
||||
std::string GetLocale();
|
||||
|
||||
std::vector<mate::Dictionary> GetAppMemoryInfo(v8::Isolate* isolate);
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// Get the current Jump List settings.
|
||||
v8::Local<v8::Value> GetJumpListSettings();
|
||||
|
||||
// Set or remove a custom Jump List for the application.
|
||||
JumpListResult SetJumpList(v8::Local<v8::Value> val, mate::Arguments* args);
|
||||
#endif // defined(OS_WIN)
|
||||
|
||||
std::unique_ptr<ProcessSingleton> process_singleton_;
|
||||
|
||||
#if defined(USE_NSS_CERTS)
|
||||
std::unique_ptr<CertificateManagerModel> certificate_manager_model_;
|
||||
#endif
|
||||
|
||||
// Tracks tasks requesting file icons.
|
||||
base::CancelableTaskTracker cancelable_task_tracker_;
|
||||
|
||||
base::FilePath app_path_;
|
||||
scoped_ptr<ProcessSingleton> process_singleton_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(App);
|
||||
};
|
||||
|
||||
@@ -4,13 +4,12 @@
|
||||
|
||||
#include "atom/browser/api/atom_api_auto_updater.h"
|
||||
|
||||
#include "base/time/time.h"
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "atom/browser/window_list.h"
|
||||
#include "atom/common/api/event_emitter_caller.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "base/time/time.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/object_template_builder.h"
|
||||
|
||||
@@ -35,9 +34,8 @@ namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
AutoUpdater::AutoUpdater(v8::Isolate* isolate) {
|
||||
AutoUpdater::AutoUpdater() {
|
||||
auto_updater::AutoUpdater::SetDelegate(this);
|
||||
Init(isolate);
|
||||
}
|
||||
|
||||
AutoUpdater::~AutoUpdater() {
|
||||
@@ -48,9 +46,7 @@ void AutoUpdater::OnError(const std::string& message) {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
auto error = v8::Exception::Error(mate::StringToV8(isolate(), message));
|
||||
mate::EmitEvent(
|
||||
isolate(),
|
||||
GetWrapper(),
|
||||
EmitCustomEvent(
|
||||
"error",
|
||||
error->ToObject(isolate()->GetCurrentContext()).ToLocalChecked(),
|
||||
// Message is also emitted to keep compatibility with old code.
|
||||
@@ -82,38 +78,31 @@ 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);
|
||||
mate::ObjectTemplateBuilder AutoUpdater::GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) {
|
||||
return mate::ObjectTemplateBuilder(isolate)
|
||||
.SetMethod("setFeedURL", &auto_updater::AutoUpdater::SetFeedURL)
|
||||
.SetMethod("checkForUpdates", &auto_updater::AutoUpdater::CheckForUpdates)
|
||||
.SetMethod("quitAndInstall", &AutoUpdater::QuitAndInstall);
|
||||
}
|
||||
|
||||
void AutoUpdater::QuitAndInstall() {
|
||||
// If we don't have any window then quitAndInstall immediately.
|
||||
if (WindowList::IsEmpty()) {
|
||||
WindowList* window_list = WindowList::GetInstance();
|
||||
if (window_list->size() == 0) {
|
||||
auto_updater::AutoUpdater::QuitAndInstall();
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise do the restart after all windows have been closed.
|
||||
WindowList::AddObserver(this);
|
||||
WindowList::CloseAllWindows();
|
||||
window_list->AddObserver(this);
|
||||
for (NativeWindow* window : *window_list)
|
||||
window->Close();
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<AutoUpdater> AutoUpdater::Create(v8::Isolate* isolate) {
|
||||
return mate::CreateHandle(isolate, new AutoUpdater(isolate));
|
||||
}
|
||||
|
||||
// static
|
||||
void AutoUpdater::BuildPrototype(
|
||||
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "AutoUpdater"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetMethod("checkForUpdates", &auto_updater::AutoUpdater::CheckForUpdates)
|
||||
.SetMethod("getFeedURL", &auto_updater::AutoUpdater::GetFeedURL)
|
||||
.SetMethod("setFeedURL", &AutoUpdater::SetFeedURL)
|
||||
.SetMethod("quitAndInstall", &AutoUpdater::QuitAndInstall);
|
||||
return CreateHandle(isolate, new AutoUpdater);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
@@ -123,14 +112,11 @@ void AutoUpdater::BuildPrototype(
|
||||
|
||||
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());
|
||||
dict.Set("autoUpdater", atom::api::AutoUpdater::Create(isolate));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -10,25 +10,21 @@
|
||||
#include "atom/browser/api/event_emitter.h"
|
||||
#include "atom/browser/auto_updater.h"
|
||||
#include "atom/browser/window_list_observer.h"
|
||||
#include "native_mate/arguments.h"
|
||||
#include "native_mate/handle.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class AutoUpdater : public mate::EventEmitter<AutoUpdater>,
|
||||
class AutoUpdater : public mate::EventEmitter,
|
||||
public auto_updater::Delegate,
|
||||
public WindowListObserver {
|
||||
public:
|
||||
static mate::Handle<AutoUpdater> Create(v8::Isolate* isolate);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
protected:
|
||||
explicit AutoUpdater(v8::Isolate* isolate);
|
||||
~AutoUpdater() override;
|
||||
AutoUpdater();
|
||||
virtual ~AutoUpdater();
|
||||
|
||||
// Delegate implementations.
|
||||
void OnError(const std::string& error) override;
|
||||
@@ -43,9 +39,11 @@ class AutoUpdater : public mate::EventEmitter<AutoUpdater>,
|
||||
// WindowListObserver:
|
||||
void OnWindowAllClosed() override;
|
||||
|
||||
// mate::Wrappable implementations:
|
||||
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) override;
|
||||
|
||||
private:
|
||||
std::string GetFeedURL();
|
||||
void SetFeedURL(const std::string& url, mate::Arguments* args);
|
||||
void QuitAndInstall();
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AutoUpdater);
|
||||
|
||||
@@ -1,162 +0,0 @@
|
||||
// Copyright (c) 2017 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_browser_view.h"
|
||||
|
||||
#include "atom/browser/api/atom_api_web_contents.h"
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/browser/native_browser_view.h"
|
||||
#include "atom/common/color_util.h"
|
||||
#include "atom/common/native_mate_converters/gfx_converter.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "atom/common/options_switches.h"
|
||||
#include "native_mate/constructor.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "ui/gfx/geometry/rect.h"
|
||||
|
||||
namespace mate {
|
||||
|
||||
template <>
|
||||
struct Converter<atom::AutoResizeFlags> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
atom::AutoResizeFlags* auto_resize_flags) {
|
||||
mate::Dictionary params;
|
||||
if (!ConvertFromV8(isolate, val, ¶ms)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t flags = 0;
|
||||
bool width = false;
|
||||
if (params.Get("width", &width) && width) {
|
||||
flags |= atom::kAutoResizeWidth;
|
||||
}
|
||||
bool height = false;
|
||||
if (params.Get("height", &height) && height) {
|
||||
flags |= atom::kAutoResizeHeight;
|
||||
}
|
||||
|
||||
*auto_resize_flags = static_cast<atom::AutoResizeFlags>(flags);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
BrowserView::BrowserView(v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> wrapper,
|
||||
const mate::Dictionary& options)
|
||||
: api_web_contents_(nullptr) {
|
||||
Init(isolate, wrapper, options);
|
||||
}
|
||||
|
||||
void BrowserView::Init(v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> wrapper,
|
||||
const mate::Dictionary& options) {
|
||||
mate::Dictionary web_preferences = mate::Dictionary::CreateEmpty(isolate);
|
||||
options.Get(options::kWebPreferences, &web_preferences);
|
||||
web_preferences.Set("isBrowserView", true);
|
||||
mate::Handle<class WebContents> web_contents =
|
||||
WebContents::Create(isolate, web_preferences);
|
||||
|
||||
web_contents_.Reset(isolate, web_contents.ToV8());
|
||||
api_web_contents_ = web_contents.get();
|
||||
|
||||
view_.reset(NativeBrowserView::Create(
|
||||
api_web_contents_->managed_web_contents()->GetView()));
|
||||
|
||||
InitWith(isolate, wrapper);
|
||||
}
|
||||
|
||||
BrowserView::~BrowserView() {
|
||||
api_web_contents_->DestroyWebContents(true /* async */);
|
||||
}
|
||||
|
||||
// static
|
||||
mate::WrappableBase* BrowserView::New(mate::Arguments* args) {
|
||||
if (!Browser::Get()->is_ready()) {
|
||||
args->ThrowError("Cannot create BrowserView before app is ready");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (args->Length() > 1) {
|
||||
args->ThrowError("Too many arguments");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mate::Dictionary options;
|
||||
if (!(args->Length() == 1 && args->GetNext(&options))) {
|
||||
options = mate::Dictionary::CreateEmpty(args->isolate());
|
||||
}
|
||||
|
||||
return new BrowserView(args->isolate(), args->GetThis(), options);
|
||||
}
|
||||
|
||||
int32_t BrowserView::ID() const {
|
||||
return weak_map_id();
|
||||
}
|
||||
|
||||
void BrowserView::SetAutoResize(AutoResizeFlags flags) {
|
||||
view_->SetAutoResizeFlags(flags);
|
||||
}
|
||||
|
||||
void BrowserView::SetBounds(const gfx::Rect& bounds) {
|
||||
view_->SetBounds(bounds);
|
||||
}
|
||||
|
||||
void BrowserView::SetBackgroundColor(const std::string& color_name) {
|
||||
view_->SetBackgroundColor(ParseHexColor(color_name));
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> BrowserView::WebContents() {
|
||||
if (web_contents_.IsEmpty()) {
|
||||
return v8::Null(isolate());
|
||||
}
|
||||
|
||||
return v8::Local<v8::Value>::New(isolate(), web_contents_);
|
||||
}
|
||||
|
||||
// static
|
||||
void BrowserView::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "BrowserView"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.MakeDestroyable()
|
||||
.SetMethod("setAutoResize", &BrowserView::SetAutoResize)
|
||||
.SetMethod("setBounds", &BrowserView::SetBounds)
|
||||
.SetMethod("setBackgroundColor", &BrowserView::SetBackgroundColor)
|
||||
.SetProperty("webContents", &BrowserView::WebContents)
|
||||
.SetProperty("id", &BrowserView::ID);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
namespace {
|
||||
|
||||
using atom::api::BrowserView;
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
BrowserView::SetConstructor(isolate, base::Bind(&BrowserView::New));
|
||||
|
||||
mate::Dictionary browser_view(
|
||||
isolate, BrowserView::GetConstructor(isolate)->GetFunction());
|
||||
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("BrowserView", browser_view);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_browser_view, Initialize)
|
||||
@@ -1,72 +0,0 @@
|
||||
// Copyright (c) 2017 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_API_ATOM_API_BROWSER_VIEW_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_BROWSER_VIEW_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "atom/browser/native_browser_view.h"
|
||||
#include "native_mate/handle.h"
|
||||
|
||||
namespace gfx {
|
||||
class Rect;
|
||||
}
|
||||
|
||||
namespace mate {
|
||||
class Arguments;
|
||||
class Dictionary;
|
||||
} // namespace mate
|
||||
|
||||
namespace atom {
|
||||
|
||||
class NativeBrowserView;
|
||||
|
||||
namespace api {
|
||||
|
||||
class WebContents;
|
||||
|
||||
class BrowserView : public mate::TrackableObject<BrowserView> {
|
||||
public:
|
||||
static mate::WrappableBase* New(mate::Arguments* args);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
NativeBrowserView* view() const { return view_.get(); }
|
||||
|
||||
int32_t ID() const;
|
||||
|
||||
protected:
|
||||
BrowserView(v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> wrapper,
|
||||
const mate::Dictionary& options);
|
||||
~BrowserView() override;
|
||||
|
||||
private:
|
||||
void Init(v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> wrapper,
|
||||
const mate::Dictionary& options);
|
||||
|
||||
void SetAutoResize(AutoResizeFlags flags);
|
||||
void SetBounds(const gfx::Rect& bounds);
|
||||
void SetBackgroundColor(const std::string& color_name);
|
||||
|
||||
v8::Local<v8::Value> WebContents();
|
||||
|
||||
v8::Global<v8::Value> web_contents_;
|
||||
class WebContents* api_web_contents_;
|
||||
|
||||
std::unique_ptr<NativeBrowserView> view_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(BrowserView);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_BROWSER_VIEW_H_
|
||||
@@ -7,13 +7,12 @@
|
||||
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/file_path_converter.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "base/bind.h"
|
||||
#include "base/files/file_util.h"
|
||||
#include "content/public/browser/tracing_controller.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
using content::TracingController;
|
||||
|
||||
namespace mate {
|
||||
@@ -54,7 +53,13 @@ scoped_refptr<TracingController::TraceDataSink> GetTraceDataSink(
|
||||
|
||||
void StopRecording(const base::FilePath& path,
|
||||
const CompletionCallback& callback) {
|
||||
TracingController::GetInstance()->StopTracing(
|
||||
TracingController::GetInstance()->DisableRecording(
|
||||
GetTraceDataSink(path, callback));
|
||||
}
|
||||
|
||||
void CaptureMonitoringSnapshot(const base::FilePath& path,
|
||||
const CompletionCallback& callback) {
|
||||
TracingController::GetInstance()->CaptureMonitoringSnapshot(
|
||||
GetTraceDataSink(path, callback));
|
||||
}
|
||||
|
||||
@@ -65,10 +70,19 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
dict.SetMethod("getCategories", base::Bind(
|
||||
&TracingController::GetCategories, controller));
|
||||
dict.SetMethod("startRecording", base::Bind(
|
||||
&TracingController::StartTracing, controller));
|
||||
&TracingController::EnableRecording, controller));
|
||||
dict.SetMethod("stopRecording", &StopRecording);
|
||||
dict.SetMethod("startMonitoring", base::Bind(
|
||||
&TracingController::EnableMonitoring, controller));
|
||||
dict.SetMethod("stopMonitoring", base::Bind(
|
||||
&TracingController::DisableMonitoring, controller));
|
||||
dict.SetMethod("captureMonitoringSnapshot", &CaptureMonitoringSnapshot);
|
||||
dict.SetMethod("getTraceBufferUsage", base::Bind(
|
||||
&TracingController::GetTraceBufferUsage, controller));
|
||||
dict.SetMethod("setWatchEvent", base::Bind(
|
||||
&TracingController::SetWatchEvent, controller));
|
||||
dict.SetMethod("cancelWatchEvent", base::Bind(
|
||||
&TracingController::CancelWatchEvent, controller));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
|
||||
#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/bind.h"
|
||||
#include "base/time/time.h"
|
||||
#include "base/values.h"
|
||||
#include "content/public/browser/browser_context.h"
|
||||
@@ -20,21 +20,138 @@
|
||||
#include "net/url_request/url_request_context.h"
|
||||
#include "net/url_request/url_request_context_getter.h"
|
||||
|
||||
using atom::AtomCookieDelegate;
|
||||
using atom::api::Cookies;
|
||||
using content::BrowserThread;
|
||||
|
||||
namespace mate {
|
||||
namespace {
|
||||
|
||||
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"));
|
||||
bool GetCookieListFromStore(
|
||||
net::CookieStore* cookie_store,
|
||||
const std::string& url,
|
||||
const net::CookieMonster::GetCookieListCallback& callback) {
|
||||
DCHECK(cookie_store);
|
||||
GURL gurl(url);
|
||||
net::CookieMonster* monster = cookie_store->GetCookieMonster();
|
||||
// Empty url will match all url cookies.
|
||||
if (url.empty()) {
|
||||
monster->GetAllCookiesAsync(callback);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
if (!gurl.is_valid())
|
||||
return false;
|
||||
|
||||
monster->GetAllCookiesForURLAsync(gurl, callback);
|
||||
return true;
|
||||
}
|
||||
|
||||
void RunGetCookiesCallbackOnUIThread(v8::Isolate* isolate,
|
||||
const std::string& error_message,
|
||||
const net::CookieList& cookie_list,
|
||||
const Cookies::CookiesCallback& callback) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
|
||||
v8::Locker locker(isolate);
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
|
||||
if (!error_message.empty()) {
|
||||
v8::Local<v8::Value> error = mate::ConvertToV8(isolate, error_message);
|
||||
callback.Run(error, v8::Null(isolate));
|
||||
return;
|
||||
}
|
||||
callback.Run(v8::Null(isolate), mate::ConvertToV8(isolate, cookie_list));
|
||||
}
|
||||
|
||||
void RunRemoveCookiesCallbackOnUIThread(
|
||||
v8::Isolate* isolate,
|
||||
const std::string& error_message,
|
||||
const Cookies::CookiesCallback& callback) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
|
||||
v8::Locker locker(isolate);
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
|
||||
if (!error_message.empty()) {
|
||||
v8::Local<v8::Value> error = mate::ConvertToV8(isolate, error_message);
|
||||
callback.Run(error, v8::Null(isolate));
|
||||
return;
|
||||
}
|
||||
|
||||
callback.Run(v8::Null(isolate), v8::Null(isolate));
|
||||
}
|
||||
|
||||
void RunSetCookiesCallbackOnUIThread(v8::Isolate* isolate,
|
||||
const std::string& error_message,
|
||||
bool set_success,
|
||||
const Cookies::CookiesCallback& callback) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
|
||||
v8::Locker locker(isolate);
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
|
||||
if (!error_message.empty()) {
|
||||
v8::Local<v8::Value> error = mate::ConvertToV8(isolate, error_message);
|
||||
callback.Run(error, v8::Null(isolate));
|
||||
return;
|
||||
}
|
||||
if (!set_success) {
|
||||
v8::Local<v8::Value> error = mate::ConvertToV8(
|
||||
isolate, "Failed to set cookies");
|
||||
callback.Run(error, v8::Null(isolate));
|
||||
}
|
||||
|
||||
callback.Run(v8::Null(isolate), v8::Null(isolate));
|
||||
}
|
||||
|
||||
bool MatchesDomain(const base::DictionaryValue* filter,
|
||||
const std::string& cookie_domain) {
|
||||
std::string filter_domain;
|
||||
if (!filter->GetString("domain", &filter_domain))
|
||||
return true;
|
||||
|
||||
// Add a leading '.' character to the filter domain if it doesn't exist.
|
||||
if (net::cookie_util::DomainIsHostOnly(filter_domain))
|
||||
filter_domain.insert(0, ".");
|
||||
|
||||
std::string sub_domain(cookie_domain);
|
||||
// Strip any leading '.' character from the input cookie domain.
|
||||
if (!net::cookie_util::DomainIsHostOnly(sub_domain))
|
||||
sub_domain = sub_domain.substr(1);
|
||||
|
||||
// Now check whether the domain argument is a subdomain of the filter domain.
|
||||
for (sub_domain.insert(0, ".");
|
||||
sub_domain.length() >= filter_domain.length();) {
|
||||
if (sub_domain == filter_domain) {
|
||||
return true;
|
||||
}
|
||||
const size_t next_dot = sub_domain.find('.', 1); // Skip over leading dot.
|
||||
sub_domain.erase(0, next_dot);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MatchesCookie(const base::DictionaryValue* filter,
|
||||
const net::CanonicalCookie& cookie) {
|
||||
std::string name, domain, path;
|
||||
bool is_secure, session;
|
||||
if (filter->GetString("name", &name) && name != cookie.Name())
|
||||
return false;
|
||||
if (filter->GetString("path", &path) && path != cookie.Path())
|
||||
return false;
|
||||
if (!MatchesDomain(filter, cookie.Domain()))
|
||||
return false;
|
||||
if (filter->GetBoolean("secure", &is_secure) &&
|
||||
is_secure != cookie.IsSecure())
|
||||
return false;
|
||||
if (filter->GetBoolean("session", &session) &&
|
||||
session != cookie.IsPersistent())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace mate {
|
||||
|
||||
template<>
|
||||
struct Converter<net::CanonicalCookie> {
|
||||
@@ -44,172 +161,138 @@ struct Converter<net::CanonicalCookie> {
|
||||
dict.Set("name", val.Name());
|
||||
dict.Set("value", val.Value());
|
||||
dict.Set("domain", val.Domain());
|
||||
dict.Set("hostOnly", net::cookie_util::DomainIsHostOnly(val.Domain()));
|
||||
dict.Set("host_only", net::cookie_util::DomainIsHostOnly(val.Domain()));
|
||||
dict.Set("path", val.Path());
|
||||
dict.Set("secure", val.IsSecure());
|
||||
dict.Set("httpOnly", val.IsHttpOnly());
|
||||
dict.Set("session", !val.IsPersistent());
|
||||
if (val.IsPersistent())
|
||||
dict.Set("http_only", val.IsHttpOnly());
|
||||
dict.Set("session", val.IsPersistent());
|
||||
if (!val.IsPersistent())
|
||||
dict.Set("expirationDate", val.ExpiryDate().ToDoubleT());
|
||||
return dict.GetHandle();
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Converter<net::CookieStore::ChangeCause> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
const net::CookieStore::ChangeCause& val) {
|
||||
switch (val) {
|
||||
case net::CookieStore::ChangeCause::INSERTED:
|
||||
case net::CookieStore::ChangeCause::EXPLICIT:
|
||||
return mate::StringToV8(isolate, "explicit");
|
||||
case net::CookieStore::ChangeCause::OVERWRITE:
|
||||
return mate::StringToV8(isolate, "overwrite");
|
||||
case net::CookieStore::ChangeCause::EXPIRED:
|
||||
return mate::StringToV8(isolate, "expired");
|
||||
case net::CookieStore::ChangeCause::EVICTED:
|
||||
return mate::StringToV8(isolate, "evicted");
|
||||
case net::CookieStore::ChangeCause::EXPIRED_OVERWRITE:
|
||||
return mate::StringToV8(isolate, "expired-overwrite");
|
||||
default:
|
||||
return mate::StringToV8(isolate, "unknown");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
namespace {
|
||||
Cookies::Cookies(content::BrowserContext* browser_context)
|
||||
: request_context_getter_(browser_context->GetRequestContext()) {
|
||||
}
|
||||
|
||||
// Returns whether |domain| matches |filter|.
|
||||
bool MatchesDomain(std::string filter, const std::string& domain) {
|
||||
// Add a leading '.' character to the filter domain if it doesn't exist.
|
||||
if (net::cookie_util::DomainIsHostOnly(filter))
|
||||
filter.insert(0, ".");
|
||||
Cookies::~Cookies() {
|
||||
}
|
||||
|
||||
std::string sub_domain(domain);
|
||||
// Strip any leading '.' character from the input cookie domain.
|
||||
if (!net::cookie_util::DomainIsHostOnly(sub_domain))
|
||||
sub_domain = sub_domain.substr(1);
|
||||
void Cookies::Get(const base::DictionaryValue& options,
|
||||
const CookiesCallback& callback) {
|
||||
scoped_ptr<base::DictionaryValue> filter(
|
||||
options.DeepCopyWithoutEmptyChildren());
|
||||
|
||||
// Now check whether the domain argument is a subdomain of the filter domain.
|
||||
for (sub_domain.insert(0, "."); sub_domain.length() >= filter.length();) {
|
||||
if (sub_domain == filter)
|
||||
return true;
|
||||
const size_t next_dot = sub_domain.find('.', 1); // Skip over leading dot.
|
||||
sub_domain.erase(0, next_dot);
|
||||
content::BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&Cookies::GetCookiesOnIOThread, base::Unretained(this),
|
||||
Passed(&filter), callback));
|
||||
}
|
||||
|
||||
void Cookies::GetCookiesOnIOThread(scoped_ptr<base::DictionaryValue> filter,
|
||||
const CookiesCallback& callback) {
|
||||
std::string url;
|
||||
filter->GetString("url", &url);
|
||||
if (!GetCookieListFromStore(GetCookieStore(), url,
|
||||
base::Bind(&Cookies::OnGetCookies, base::Unretained(this),
|
||||
Passed(&filter), callback))) {
|
||||
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
|
||||
base::Bind(&RunGetCookiesCallbackOnUIThread, isolate(),
|
||||
"URL is not valid", net::CookieList(), callback));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns whether |cookie| matches |filter|.
|
||||
bool MatchesCookie(const base::DictionaryValue* filter,
|
||||
const net::CanonicalCookie& cookie) {
|
||||
std::string str;
|
||||
bool b;
|
||||
if (filter->GetString("name", &str) && str != cookie.Name())
|
||||
return false;
|
||||
if (filter->GetString("path", &str) && str != cookie.Path())
|
||||
return false;
|
||||
if (filter->GetString("domain", &str) && !MatchesDomain(str, cookie.Domain()))
|
||||
return false;
|
||||
if (filter->GetBoolean("secure", &b) && b != cookie.IsSecure())
|
||||
return false;
|
||||
if (filter->GetBoolean("session", &b) && b != !cookie.IsPersistent())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Helper to returns the CookieStore.
|
||||
inline net::CookieStore* GetCookieStore(
|
||||
scoped_refptr<net::URLRequestContextGetter> getter) {
|
||||
return getter->GetURLRequestContext()->cookie_store();
|
||||
}
|
||||
|
||||
// Run |callback| on UI thread.
|
||||
void RunCallbackInUI(const base::Closure& callback) {
|
||||
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
|
||||
}
|
||||
|
||||
// Remove cookies from |list| not matching |filter|, and pass it to |callback|.
|
||||
void FilterCookies(std::unique_ptr<base::DictionaryValue> filter,
|
||||
const Cookies::GetCallback& callback,
|
||||
const net::CookieList& list) {
|
||||
void Cookies::OnGetCookies(scoped_ptr<base::DictionaryValue> filter,
|
||||
const CookiesCallback& callback,
|
||||
const net::CookieList& cookie_list) {
|
||||
net::CookieList result;
|
||||
for (const auto& cookie : list) {
|
||||
for (const auto& cookie : cookie_list) {
|
||||
if (MatchesCookie(filter.get(), cookie))
|
||||
result.push_back(cookie);
|
||||
}
|
||||
RunCallbackInUI(base::Bind(callback, Cookies::SUCCESS, result));
|
||||
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
|
||||
&RunGetCookiesCallbackOnUIThread, isolate(), "", result, callback));
|
||||
}
|
||||
|
||||
// Receives cookies matching |filter| in IO thread.
|
||||
void GetCookiesOnIO(scoped_refptr<net::URLRequestContextGetter> getter,
|
||||
std::unique_ptr<base::DictionaryValue> filter,
|
||||
const Cookies::GetCallback& callback) {
|
||||
void Cookies::Remove(const mate::Dictionary& details,
|
||||
const CookiesCallback& callback) {
|
||||
GURL url;
|
||||
std::string name;
|
||||
std::string error_message;
|
||||
if (!details.Get("url", &url) || !details.Get("name", &name)) {
|
||||
error_message = "Details(url, name) of removing cookie are required.";
|
||||
}
|
||||
if (error_message.empty() && !url.is_valid()) {
|
||||
error_message = "URL is not valid.";
|
||||
}
|
||||
if (!error_message.empty()) {
|
||||
RunRemoveCookiesCallbackOnUIThread(isolate(), error_message, callback);
|
||||
return;
|
||||
}
|
||||
content::BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&Cookies::RemoveCookiesOnIOThread, base::Unretained(this),
|
||||
url, name, callback));
|
||||
}
|
||||
|
||||
void Cookies::RemoveCookiesOnIOThread(const GURL& url, const std::string& name,
|
||||
const CookiesCallback& callback) {
|
||||
GetCookieStore()->DeleteCookieAsync(url, name,
|
||||
base::Bind(&Cookies::OnRemoveCookies, base::Unretained(this), callback));
|
||||
}
|
||||
|
||||
void Cookies::OnRemoveCookies(const CookiesCallback& callback) {
|
||||
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
|
||||
base::Bind(&RunRemoveCookiesCallbackOnUIThread, isolate(), "", callback));
|
||||
}
|
||||
|
||||
void Cookies::Set(const base::DictionaryValue& options,
|
||||
const CookiesCallback& callback) {
|
||||
std::string url;
|
||||
filter->GetString("url", &url);
|
||||
std::string error_message;
|
||||
if (!options.GetString("url", &url)) {
|
||||
error_message = "The url field is required.";
|
||||
}
|
||||
|
||||
auto filtered_callback =
|
||||
base::Bind(FilterCookies, base::Passed(&filter), callback);
|
||||
GURL gurl(url);
|
||||
if (error_message.empty() && !gurl.is_valid()) {
|
||||
error_message = "URL is not valid.";
|
||||
}
|
||||
|
||||
// Empty url will match all url cookies.
|
||||
if (url.empty())
|
||||
GetCookieStore(getter)->GetAllCookiesAsync(filtered_callback);
|
||||
else
|
||||
GetCookieStore(getter)->GetAllCookiesForURLAsync(GURL(url),
|
||||
filtered_callback);
|
||||
if (!error_message.empty()) {
|
||||
RunSetCookiesCallbackOnUIThread(isolate(), error_message, false, callback);
|
||||
return;
|
||||
}
|
||||
|
||||
scoped_ptr<base::DictionaryValue> details(
|
||||
options.DeepCopyWithoutEmptyChildren());
|
||||
|
||||
content::BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&Cookies::SetCookiesOnIOThread, base::Unretained(this),
|
||||
Passed(&details), gurl, callback));
|
||||
}
|
||||
|
||||
// Removes cookie with |url| and |name| in IO thread.
|
||||
void RemoveCookieOnIOThread(scoped_refptr<net::URLRequestContextGetter> getter,
|
||||
const GURL& url, const std::string& name,
|
||||
const base::Closure& callback) {
|
||||
GetCookieStore(getter)->DeleteCookieAsync(
|
||||
url, name, base::Bind(RunCallbackInUI, callback));
|
||||
}
|
||||
void Cookies::SetCookiesOnIOThread(scoped_ptr<base::DictionaryValue> details,
|
||||
const GURL& url,
|
||||
const CookiesCallback& callback) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
||||
|
||||
// Callback of SetCookie.
|
||||
void OnSetCookie(const Cookies::SetCallback& callback, bool success) {
|
||||
RunCallbackInUI(
|
||||
base::Bind(callback, success ? Cookies::SUCCESS : Cookies::FAILED));
|
||||
}
|
||||
|
||||
// Flushes cookie store in IO thread.
|
||||
void FlushCookieStoreOnIOThread(
|
||||
scoped_refptr<net::URLRequestContextGetter> getter,
|
||||
const base::Closure& callback) {
|
||||
GetCookieStore(getter)->FlushStore(base::Bind(RunCallbackInUI, callback));
|
||||
}
|
||||
|
||||
// Sets cookie with |details| in IO thread.
|
||||
void SetCookieOnIO(scoped_refptr<net::URLRequestContextGetter> getter,
|
||||
std::unique_ptr<base::DictionaryValue> details,
|
||||
const Cookies::SetCallback& callback) {
|
||||
std::string url, name, value, domain, path;
|
||||
std::string name, value, domain, path;
|
||||
bool secure = false;
|
||||
bool http_only = false;
|
||||
double creation_date;
|
||||
double expiration_date;
|
||||
double last_access_date;
|
||||
details->GetString("url", &url);
|
||||
|
||||
details->GetString("name", &name);
|
||||
details->GetString("value", &value);
|
||||
details->GetString("domain", &domain);
|
||||
details->GetString("path", &path);
|
||||
details->GetBoolean("secure", &secure);
|
||||
details->GetBoolean("httpOnly", &http_only);
|
||||
|
||||
base::Time creation_time;
|
||||
if (details->GetDouble("creationDate", &creation_date)) {
|
||||
creation_time = (creation_date == 0) ?
|
||||
base::Time::UnixEpoch() :
|
||||
base::Time::FromDoubleT(creation_date);
|
||||
}
|
||||
details->GetBoolean("http_only", &http_only);
|
||||
|
||||
base::Time expiration_time;
|
||||
if (details->GetDouble("expirationDate", &expiration_date)) {
|
||||
@@ -218,90 +301,45 @@ void SetCookieOnIO(scoped_refptr<net::URLRequestContextGetter> getter,
|
||||
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));
|
||||
GetCookieStore()->GetCookieMonster()->SetCookieWithDetailsAsync(
|
||||
url,
|
||||
name,
|
||||
value,
|
||||
domain,
|
||||
path,
|
||||
expiration_time,
|
||||
secure,
|
||||
http_only,
|
||||
false,
|
||||
net::COOKIE_PRIORITY_DEFAULT,
|
||||
base::Bind(&Cookies::OnSetCookies, base::Unretained(this), callback));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Cookies::Cookies(v8::Isolate* isolate,
|
||||
AtomBrowserContext* browser_context)
|
||||
: request_context_getter_(browser_context->url_request_context_getter()),
|
||||
cookie_delegate_(browser_context->cookie_delegate()) {
|
||||
Init(isolate);
|
||||
cookie_delegate_->AddObserver(this);
|
||||
void Cookies::OnSetCookies(const CookiesCallback& callback,
|
||||
bool set_success) {
|
||||
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
|
||||
base::Bind(&RunSetCookiesCallbackOnUIThread, isolate(), "", set_success,
|
||||
callback));
|
||||
}
|
||||
|
||||
Cookies::~Cookies() {
|
||||
cookie_delegate_->RemoveObserver(this);
|
||||
net::CookieStore* Cookies::GetCookieStore() {
|
||||
return request_context_getter_->GetURLRequestContext()->cookie_store();
|
||||
}
|
||||
|
||||
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::FlushStore(const base::Closure& callback) {
|
||||
auto getter = make_scoped_refptr(request_context_getter_);
|
||||
content::BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(FlushCookieStoreOnIOThread, getter, callback));
|
||||
}
|
||||
|
||||
void Cookies::OnCookieChanged(const net::CanonicalCookie& cookie,
|
||||
bool removed,
|
||||
net::CookieStore::ChangeCause cause) {
|
||||
Emit("changed", cookie, cause, removed);
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
mate::Handle<Cookies> Cookies::Create(
|
||||
v8::Isolate* isolate,
|
||||
AtomBrowserContext* browser_context) {
|
||||
return mate::CreateHandle(isolate, new Cookies(isolate, browser_context));
|
||||
content::BrowserContext* browser_context) {
|
||||
return mate::CreateHandle(isolate, new Cookies(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())
|
||||
v8::Local<v8::ObjectTemplate> prototype) {
|
||||
mate::ObjectTemplateBuilder(isolate, prototype)
|
||||
.SetMethod("get", &Cookies::Get)
|
||||
.SetMethod("remove", &Cookies::Remove)
|
||||
.SetMethod("set", &Cookies::Set)
|
||||
.SetMethod("flushStore", &Cookies::FlushStore);
|
||||
.SetMethod("set", &Cookies::Set);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#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"
|
||||
@@ -17,52 +16,69 @@ namespace base {
|
||||
class DictionaryValue;
|
||||
}
|
||||
|
||||
namespace content {
|
||||
class BrowserContext;
|
||||
}
|
||||
|
||||
namespace mate {
|
||||
class Dictionary;
|
||||
}
|
||||
|
||||
namespace net {
|
||||
class CookieStore;
|
||||
class URLRequestContextGetter;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomBrowserContext;
|
||||
|
||||
namespace api {
|
||||
|
||||
class Cookies : public mate::TrackableObject<Cookies>,
|
||||
public AtomCookieDelegate::Observer {
|
||||
class Cookies : public mate::TrackableObject<Cookies> {
|
||||
public:
|
||||
enum Error {
|
||||
SUCCESS,
|
||||
FAILED,
|
||||
};
|
||||
|
||||
using GetCallback = base::Callback<void(Error, const net::CookieList&)>;
|
||||
using SetCallback = base::Callback<void(Error)>;
|
||||
// node.js style callback function(error, result)
|
||||
typedef base::Callback<void(v8::Local<v8::Value>, v8::Local<v8::Value>)>
|
||||
CookiesCallback;
|
||||
|
||||
static mate::Handle<Cookies> Create(v8::Isolate* isolate,
|
||||
AtomBrowserContext* browser_context);
|
||||
content::BrowserContext* browser_context);
|
||||
|
||||
// mate::TrackableObject:
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
v8::Local<v8::ObjectTemplate> prototype);
|
||||
|
||||
protected:
|
||||
Cookies(v8::Isolate* isolate, AtomBrowserContext* browser_context);
|
||||
~Cookies() override;
|
||||
explicit Cookies(content::BrowserContext* browser_context);
|
||||
~Cookies();
|
||||
|
||||
void Get(const base::DictionaryValue& filter, const GetCallback& callback);
|
||||
void Remove(const GURL& url, const std::string& name,
|
||||
const base::Closure& callback);
|
||||
void Set(const base::DictionaryValue& details, const SetCallback& callback);
|
||||
void FlushStore(const base::Closure& callback);
|
||||
void Get(const base::DictionaryValue& options,
|
||||
const CookiesCallback& callback);
|
||||
void Remove(const mate::Dictionary& details,
|
||||
const CookiesCallback& callback);
|
||||
void Set(const base::DictionaryValue& details,
|
||||
const CookiesCallback& callback);
|
||||
|
||||
// AtomCookieDelegate::Observer:
|
||||
void OnCookieChanged(const net::CanonicalCookie& cookie,
|
||||
bool removed,
|
||||
net::CookieStore::ChangeCause cause) override;
|
||||
void GetCookiesOnIOThread(scoped_ptr<base::DictionaryValue> filter,
|
||||
const CookiesCallback& callback);
|
||||
void OnGetCookies(scoped_ptr<base::DictionaryValue> filter,
|
||||
const CookiesCallback& callback,
|
||||
const net::CookieList& cookie_list);
|
||||
|
||||
void RemoveCookiesOnIOThread(const GURL& url,
|
||||
const std::string& name,
|
||||
const CookiesCallback& callback);
|
||||
void OnRemoveCookies(const CookiesCallback& callback);
|
||||
|
||||
void SetCookiesOnIOThread(scoped_ptr<base::DictionaryValue> details,
|
||||
const GURL& url,
|
||||
const CookiesCallback& callback);
|
||||
void OnSetCookies(const CookiesCallback& callback,
|
||||
bool set_success);
|
||||
|
||||
private:
|
||||
// Must be called on IO thread.
|
||||
net::CookieStore* GetCookieStore();
|
||||
|
||||
net::URLRequestContextGetter* request_context_getter_;
|
||||
scoped_refptr<AtomCookieDelegate> cookie_delegate_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Cookies);
|
||||
};
|
||||
|
||||
@@ -1,188 +0,0 @@
|
||||
// Copyright (c) 2016 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_debugger.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "atom/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_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());
|
||||
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
|
||||
v8::Local<v8::String> local_message =
|
||||
v8::String::NewFromUtf8(isolate(), message.data());
|
||||
v8::MaybeLocal<v8::Value> parsed_message = v8::JSON::Parse(
|
||||
isolate()->GetCurrentContext(), local_message);
|
||||
if (parsed_message.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
|
||||
if (!mate::ConvertFromV8(isolate(), parsed_message.ToLocalChecked(),
|
||||
dict.get())) {
|
||||
return;
|
||||
}
|
||||
|
||||
int id;
|
||||
if (!dict->GetInteger("id", &id)) {
|
||||
std::string method;
|
||||
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);
|
||||
@@ -1,75 +0,0 @@
|
||||
// Copyright (c) 2016 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_API_ATOM_API_DEBUGGER_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_DEBUGGER_H_
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "base/callback.h"
|
||||
#include "base/values.h"
|
||||
#include "content/public/browser/devtools_agent_host_client.h"
|
||||
#include "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_
|
||||
@@ -1,124 +0,0 @@
|
||||
// Copyright (c) 2015 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_desktop_capturer.h"
|
||||
|
||||
#include "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/desktop_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::DesktopCapturer> screen_capturer(
|
||||
capture_screen ? webrtc::DesktopCapturer::CreateScreenCapturer(options)
|
||||
: nullptr);
|
||||
std::unique_ptr<webrtc::DesktopCapturer> window_capturer(
|
||||
capture_window ? webrtc::DesktopCapturer::CreateWindowCapturer(options)
|
||||
: nullptr);
|
||||
media_list_.reset(new NativeDesktopMediaList(
|
||||
std::move(screen_capturer), std::move(window_capturer)));
|
||||
|
||||
media_list_->SetThumbnailSize(thumbnail_size);
|
||||
media_list_->StartUpdating(this);
|
||||
}
|
||||
|
||||
void DesktopCapturer::OnSourceAdded(int index) {
|
||||
}
|
||||
|
||||
void DesktopCapturer::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);
|
||||
@@ -1,51 +0,0 @@
|
||||
// Copyright (c) 2015 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_API_ATOM_API_DESKTOP_CAPTURER_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_DESKTOP_CAPTURER_H_
|
||||
|
||||
#include "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_
|
||||
@@ -8,13 +8,11 @@
|
||||
|
||||
#include "atom/browser/api/atom_api_window.h"
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "atom/browser/ui/certificate_trust.h"
|
||||
#include "atom/browser/ui/file_dialog.h"
|
||||
#include "atom/browser/ui/message_box.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/file_path_converter.h"
|
||||
#include "atom/common/native_mate_converters/image_converter.h"
|
||||
#include "atom/common/native_mate_converters/net_converter.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
@@ -37,41 +35,17 @@ struct Converter<file_dialog::Filter> {
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Converter<file_dialog::DialogSettings> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
file_dialog::DialogSettings* out) {
|
||||
mate::Dictionary dict;
|
||||
if (!ConvertFromV8(isolate, val, &dict))
|
||||
return false;
|
||||
dict.Get("window", &(out->parent_window));
|
||||
dict.Get("title", &(out->title));
|
||||
dict.Get("message", &(out->message));
|
||||
dict.Get("buttonLabel", &(out->button_label));
|
||||
dict.Get("nameFieldLabel", &(out->name_field_label));
|
||||
dict.Get("defaultPath", &(out->default_path));
|
||||
dict.Get("filters", &(out->filters));
|
||||
dict.Get("properties", &(out->properties));
|
||||
dict.Get("showsTagField", &(out->shows_tag_field));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
namespace {
|
||||
|
||||
void ShowMessageBox(int type,
|
||||
const std::vector<std::string>& buttons,
|
||||
int default_id,
|
||||
int cancel_id,
|
||||
int options,
|
||||
const std::string& title,
|
||||
const std::string& message,
|
||||
const std::string& detail,
|
||||
const std::string& checkbox_label,
|
||||
bool checkbox_checked,
|
||||
const gfx::ImageSkia& icon,
|
||||
atom::NativeWindow* window,
|
||||
mate::Arguments* args) {
|
||||
@@ -80,44 +54,52 @@ void ShowMessageBox(int type,
|
||||
if (mate::Converter<atom::MessageBoxCallback>::FromV8(args->isolate(),
|
||||
peek,
|
||||
&callback)) {
|
||||
atom::ShowMessageBox(window, static_cast<atom::MessageBoxType>(type),
|
||||
buttons, default_id, cancel_id, options, title,
|
||||
message, detail, checkbox_label, checkbox_checked,
|
||||
icon, callback);
|
||||
atom::ShowMessageBox(window, (atom::MessageBoxType)type, buttons, cancel_id,
|
||||
options, title, message, detail, icon, callback);
|
||||
} else {
|
||||
int chosen = atom::ShowMessageBox(
|
||||
window, static_cast<atom::MessageBoxType>(type), buttons, default_id,
|
||||
cancel_id, options, title, message, detail, icon);
|
||||
int chosen = atom::ShowMessageBox(window, (atom::MessageBoxType)type,
|
||||
buttons, cancel_id, options, title,
|
||||
message, detail, icon);
|
||||
args->Return(chosen);
|
||||
}
|
||||
}
|
||||
|
||||
void ShowOpenDialog(const file_dialog::DialogSettings& settings,
|
||||
void ShowOpenDialog(const std::string& title,
|
||||
const base::FilePath& default_path,
|
||||
const file_dialog::Filters& filters,
|
||||
int properties,
|
||||
atom::NativeWindow* window,
|
||||
mate::Arguments* args) {
|
||||
v8::Local<v8::Value> peek = args->PeekNext();
|
||||
file_dialog::OpenDialogCallback callback;
|
||||
if (mate::Converter<file_dialog::OpenDialogCallback>::FromV8(args->isolate(),
|
||||
peek,
|
||||
&callback)) {
|
||||
file_dialog::ShowOpenDialog(settings, callback);
|
||||
file_dialog::ShowOpenDialog(window, title, default_path, filters,
|
||||
properties, callback);
|
||||
} else {
|
||||
std::vector<base::FilePath> paths;
|
||||
if (file_dialog::ShowOpenDialog(settings, &paths))
|
||||
if (file_dialog::ShowOpenDialog(window, title, default_path, filters,
|
||||
properties, &paths))
|
||||
args->Return(paths);
|
||||
}
|
||||
}
|
||||
|
||||
void ShowSaveDialog(const file_dialog::DialogSettings& settings,
|
||||
void ShowSaveDialog(const std::string& title,
|
||||
const base::FilePath& default_path,
|
||||
const file_dialog::Filters& filters,
|
||||
atom::NativeWindow* window,
|
||||
mate::Arguments* args) {
|
||||
v8::Local<v8::Value> peek = args->PeekNext();
|
||||
file_dialog::SaveDialogCallback callback;
|
||||
if (mate::Converter<file_dialog::SaveDialogCallback>::FromV8(args->isolate(),
|
||||
peek,
|
||||
&callback)) {
|
||||
file_dialog::ShowSaveDialog(settings, callback);
|
||||
file_dialog::ShowSaveDialog(window, title, default_path, filters, callback);
|
||||
} else {
|
||||
base::FilePath path;
|
||||
if (file_dialog::ShowSaveDialog(settings, &path))
|
||||
if (file_dialog::ShowSaveDialog(window, title, default_path, filters,
|
||||
&path))
|
||||
args->Return(path);
|
||||
}
|
||||
}
|
||||
@@ -129,10 +111,6 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
dict.SetMethod("showErrorBox", &atom::ShowErrorBox);
|
||||
dict.SetMethod("showOpenDialog", &ShowOpenDialog);
|
||||
dict.SetMethod("showSaveDialog", &ShowSaveDialog);
|
||||
#if defined(OS_MACOSX) || defined(OS_WIN)
|
||||
dict.SetMethod("showCertificateTrustDialog",
|
||||
&certificate_trust::ShowCertificateTrust);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -10,13 +10,12 @@
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/file_path_converter.h"
|
||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "base/memory/linked_ptr.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "base/threading/thread_task_runner_handle.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "net/base/filename_util.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace mate {
|
||||
|
||||
template<>
|
||||
@@ -25,9 +24,6 @@ struct Converter<content::DownloadItem::DownloadState> {
|
||||
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;
|
||||
@@ -51,175 +47,139 @@ namespace atom {
|
||||
namespace api {
|
||||
|
||||
namespace {
|
||||
// The wrapDownloadItem funtion which is implemented in JavaScript
|
||||
using WrapDownloadItemCallback = base::Callback<void(v8::Local<v8::Value>)>;
|
||||
WrapDownloadItemCallback g_wrap_download_item;
|
||||
|
||||
std::map<uint32_t, v8::Global<v8::Object>> g_download_item_objects;
|
||||
char kDownloadItemSavePathKey[] = "DownloadItemSavePathKey";
|
||||
|
||||
std::map<uint32, linked_ptr<v8::Global<v8::Value>>> g_download_item_objects;
|
||||
} // namespace
|
||||
|
||||
DownloadItem::DownloadItem(v8::Isolate* isolate,
|
||||
content::DownloadItem* download_item)
|
||||
: download_item_(download_item) {
|
||||
DownloadItem::SavePathData::SavePathData(const base::FilePath& path) :
|
||||
path_(path) {
|
||||
}
|
||||
|
||||
const base::FilePath& DownloadItem::SavePathData::path() {
|
||||
return path_;
|
||||
}
|
||||
|
||||
DownloadItem::DownloadItem(content::DownloadItem* download_item) :
|
||||
download_item_(download_item) {
|
||||
download_item_->AddObserver(this);
|
||||
Init(isolate);
|
||||
AttachAsUserData(download_item);
|
||||
}
|
||||
|
||||
DownloadItem::~DownloadItem() {
|
||||
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());
|
||||
if (download_item_)
|
||||
OnDownloadDestroyed(download_item_);
|
||||
}
|
||||
|
||||
void DownloadItem::OnDownloadUpdated(content::DownloadItem* item) {
|
||||
if (download_item_->IsDone()) {
|
||||
Emit("done", item->GetState());
|
||||
// Destroy the item once item is downloaded.
|
||||
base::ThreadTaskRunnerHandle::Get()->PostTask(
|
||||
FROM_HERE, GetDestroyClosure());
|
||||
} else {
|
||||
Emit("updated", item->GetState());
|
||||
}
|
||||
download_item_->IsDone() ? Emit("done", item->GetState()) : Emit("updated");
|
||||
}
|
||||
|
||||
void DownloadItem::OnDownloadDestroyed(content::DownloadItem* download_item) {
|
||||
download_item_->RemoveObserver(this);
|
||||
auto iter = g_download_item_objects.find(download_item_->GetId());
|
||||
if (iter != g_download_item_objects.end())
|
||||
g_download_item_objects.erase(iter);
|
||||
download_item_ = nullptr;
|
||||
// Destroy the native class immediately when downloadItem is destroyed.
|
||||
delete this;
|
||||
}
|
||||
|
||||
int64 DownloadItem::GetReceivedBytes() {
|
||||
return download_item_->GetReceivedBytes();
|
||||
}
|
||||
|
||||
int64 DownloadItem::GetTotalBytes() {
|
||||
return download_item_->GetTotalBytes();
|
||||
}
|
||||
|
||||
const GURL& DownloadItem::GetURL() {
|
||||
return download_item_->GetURL();
|
||||
}
|
||||
|
||||
std::string DownloadItem::GetMimeType() {
|
||||
return download_item_->GetMimeType();
|
||||
}
|
||||
|
||||
bool DownloadItem::HasUserGesture() {
|
||||
return download_item_->HasUserGesture();
|
||||
}
|
||||
|
||||
std::string DownloadItem::GetFilename() {
|
||||
return base::UTF16ToUTF8(net::GenerateFileName(GetURL(),
|
||||
GetContentDisposition(),
|
||||
std::string(),
|
||||
download_item_->GetSuggestedFilename(),
|
||||
GetMimeType(),
|
||||
std::string()).LossyDisplayName());
|
||||
}
|
||||
|
||||
std::string DownloadItem::GetContentDisposition() {
|
||||
return download_item_->GetContentDisposition();
|
||||
}
|
||||
|
||||
void DownloadItem::SetSavePath(const base::FilePath& path) {
|
||||
download_item_->SetUserData(UserDataKey(), new SavePathData(path));
|
||||
}
|
||||
|
||||
void DownloadItem::Pause() {
|
||||
download_item_->Pause();
|
||||
}
|
||||
|
||||
bool DownloadItem::IsPaused() const {
|
||||
return download_item_->IsPaused();
|
||||
}
|
||||
|
||||
void DownloadItem::Resume() {
|
||||
download_item_->Resume();
|
||||
}
|
||||
|
||||
bool DownloadItem::CanResume() const {
|
||||
return download_item_->CanResume();
|
||||
}
|
||||
|
||||
void DownloadItem::Cancel() {
|
||||
download_item_->Cancel(true);
|
||||
}
|
||||
|
||||
int64_t DownloadItem::GetReceivedBytes() const {
|
||||
return download_item_->GetReceivedBytes();
|
||||
}
|
||||
|
||||
int64_t DownloadItem::GetTotalBytes() const {
|
||||
return download_item_->GetTotalBytes();
|
||||
}
|
||||
|
||||
std::string DownloadItem::GetMimeType() const {
|
||||
return download_item_->GetMimeType();
|
||||
}
|
||||
|
||||
bool DownloadItem::HasUserGesture() const {
|
||||
return download_item_->HasUserGesture();
|
||||
}
|
||||
|
||||
std::string DownloadItem::GetFilename() const {
|
||||
return base::UTF16ToUTF8(net::GenerateFileName(GetURL(),
|
||||
GetContentDisposition(),
|
||||
std::string(),
|
||||
download_item_->GetSuggestedFilename(),
|
||||
GetMimeType(),
|
||||
"download").LossyDisplayName());
|
||||
}
|
||||
|
||||
std::string DownloadItem::GetContentDisposition() const {
|
||||
return download_item_->GetContentDisposition();
|
||||
}
|
||||
|
||||
const GURL& DownloadItem::GetURL() const {
|
||||
return download_item_->GetURL();
|
||||
}
|
||||
|
||||
const std::vector<GURL>& DownloadItem::GetURLChain() const {
|
||||
return download_item_->GetUrlChain();
|
||||
}
|
||||
|
||||
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())
|
||||
v8::Local<v8::ObjectTemplate> prototype) {
|
||||
mate::ObjectTemplateBuilder(isolate, prototype)
|
||||
.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("getURL", &DownloadItem::GetURL)
|
||||
.SetMethod("getMimeType", &DownloadItem::GetMimeType)
|
||||
.SetMethod("hasUserGesture", &DownloadItem::HasUserGesture)
|
||||
.SetMethod("getFilename", &DownloadItem::GetFilename)
|
||||
.SetMethod("getContentDisposition", &DownloadItem::GetContentDisposition)
|
||||
.SetMethod("getURL", &DownloadItem::GetURL)
|
||||
.SetMethod("getURLChain", &DownloadItem::GetURLChain)
|
||||
.SetMethod("getState", &DownloadItem::GetState)
|
||||
.SetMethod("isDone", &DownloadItem::IsDone)
|
||||
.SetMethod("setSavePath", &DownloadItem::SetSavePath)
|
||||
.SetMethod("getSavePath", &DownloadItem::GetSavePath)
|
||||
.SetMethod("getLastModifiedTime", &DownloadItem::GetLastModifiedTime)
|
||||
.SetMethod("getETag", &DownloadItem::GetETag)
|
||||
.SetMethod("getStartTime", &DownloadItem::GetStartTime);
|
||||
.SetMethod("setSavePath", &DownloadItem::SetSavePath);
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<DownloadItem> DownloadItem::Create(
|
||||
v8::Isolate* isolate, 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());
|
||||
auto handle = mate::CreateHandle(isolate, new DownloadItem(item));
|
||||
g_wrap_download_item.Run(handle.ToV8());
|
||||
g_download_item_objects[item->GetId()] = make_linked_ptr(
|
||||
new v8::Global<v8::Value>(isolate, handle.ToV8()));
|
||||
return handle;
|
||||
}
|
||||
|
||||
// static
|
||||
void* DownloadItem::UserDataKey() {
|
||||
return &kDownloadItemSavePathKey;
|
||||
}
|
||||
|
||||
void ClearWrapDownloadItem() {
|
||||
g_wrap_download_item.Reset();
|
||||
}
|
||||
|
||||
void SetWrapDownloadItem(const WrapDownloadItemCallback& callback) {
|
||||
g_wrap_download_item = callback;
|
||||
|
||||
// Cleanup the wrapper on exit.
|
||||
atom::AtomBrowserMainParts::Get()->RegisterDestructionCallback(
|
||||
base::Bind(ClearWrapDownloadItem));
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
@@ -229,9 +189,8 @@ 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());
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.SetMethod("_setWrapDownloadItem", &atom::api::SetWrapDownloadItem);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#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"
|
||||
@@ -21,43 +20,43 @@ namespace api {
|
||||
class DownloadItem : public mate::TrackableObject<DownloadItem>,
|
||||
public content::DownloadItem::Observer {
|
||||
public:
|
||||
class SavePathData : public base::SupportsUserData::Data {
|
||||
public:
|
||||
explicit SavePathData(const base::FilePath& path);
|
||||
const base::FilePath& path();
|
||||
private:
|
||||
base::FilePath path_;
|
||||
};
|
||||
|
||||
static mate::Handle<DownloadItem> Create(v8::Isolate* isolate,
|
||||
content::DownloadItem* item);
|
||||
static void* UserDataKey();
|
||||
|
||||
// mate::TrackableObject:
|
||||
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;
|
||||
v8::Local<v8::ObjectTemplate> prototype);
|
||||
|
||||
protected:
|
||||
DownloadItem(v8::Isolate* isolate, content::DownloadItem* download_item);
|
||||
explicit DownloadItem(content::DownloadItem* download_item);
|
||||
~DownloadItem();
|
||||
|
||||
// Override content::DownloadItem::Observer methods
|
||||
void OnDownloadUpdated(content::DownloadItem* download) override;
|
||||
void OnDownloadDestroyed(content::DownloadItem* download) override;
|
||||
|
||||
void Pause();
|
||||
void Resume();
|
||||
void Cancel();
|
||||
int64 GetReceivedBytes();
|
||||
int64 GetTotalBytes();
|
||||
std::string GetMimeType();
|
||||
bool HasUserGesture();
|
||||
std::string GetFilename();
|
||||
std::string GetContentDisposition();
|
||||
const GURL& GetURL();
|
||||
void SetSavePath(const base::FilePath& path);
|
||||
|
||||
private:
|
||||
base::FilePath save_path_;
|
||||
content::DownloadItem* download_item_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(DownloadItem);
|
||||
|
||||
@@ -19,8 +19,7 @@ namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
GlobalShortcut::GlobalShortcut(v8::Isolate* isolate) {
|
||||
Init(isolate);
|
||||
GlobalShortcut::GlobalShortcut() {
|
||||
}
|
||||
|
||||
GlobalShortcut::~GlobalShortcut() {
|
||||
@@ -67,22 +66,20 @@ void GlobalShortcut::UnregisterAll() {
|
||||
GlobalShortcutListener::GetInstance()->UnregisterAccelerators(this);
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<GlobalShortcut> GlobalShortcut::Create(v8::Isolate* isolate) {
|
||||
return mate::CreateHandle(isolate, new GlobalShortcut(isolate));
|
||||
}
|
||||
|
||||
// static
|
||||
void GlobalShortcut::BuildPrototype(
|
||||
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "GlobalShortcut"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
mate::ObjectTemplateBuilder GlobalShortcut::GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) {
|
||||
return mate::ObjectTemplateBuilder(isolate)
|
||||
.SetMethod("register", &GlobalShortcut::Register)
|
||||
.SetMethod("isRegistered", &GlobalShortcut::IsRegistered)
|
||||
.SetMethod("unregister", &GlobalShortcut::Unregister)
|
||||
.SetMethod("unregisterAll", &GlobalShortcut::UnregisterAll);
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<GlobalShortcut> GlobalShortcut::Create(v8::Isolate* isolate) {
|
||||
return CreateHandle(isolate, new GlobalShortcut);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -23,13 +23,14 @@ class GlobalShortcut : public extensions::GlobalShortcutListener::Observer,
|
||||
public:
|
||||
static mate::Handle<GlobalShortcut> Create(v8::Isolate* isolate);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
protected:
|
||||
explicit GlobalShortcut(v8::Isolate* isolate);
|
||||
GlobalShortcut();
|
||||
~GlobalShortcut() override;
|
||||
|
||||
// mate::Wrappable implementations:
|
||||
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) override;
|
||||
|
||||
private:
|
||||
typedef std::map<ui::Accelerator, base::Closure> AcceleratorCallbackMap;
|
||||
|
||||
|
||||
@@ -19,17 +19,16 @@ namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
Menu::Menu(v8::Isolate* isolate, v8::Local<v8::Object> wrapper)
|
||||
Menu::Menu()
|
||||
: model_(new AtomMenuModel(this)),
|
||||
parent_(nullptr) {
|
||||
InitWith(isolate, wrapper);
|
||||
parent_(NULL) {
|
||||
}
|
||||
|
||||
Menu::~Menu() {
|
||||
}
|
||||
|
||||
void Menu::AfterInit(v8::Isolate* isolate) {
|
||||
mate::Dictionary wrappable(isolate, GetWrapper());
|
||||
mate::Dictionary wrappable(isolate, GetWrapper(isolate));
|
||||
mate::Dictionary delegate;
|
||||
if (!wrappable.Get("delegate", &delegate))
|
||||
return;
|
||||
@@ -54,21 +53,16 @@ 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 {
|
||||
bool Menu::GetAcceleratorForCommandId(int command_id,
|
||||
ui::Accelerator* accelerator) {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
v8::Local<v8::Value> val = get_accelerator_.Run(
|
||||
command_id, use_default_accelerator);
|
||||
v8::Local<v8::Value> val = get_accelerator_.Run(command_id);
|
||||
return mate::ConvertFromV8(isolate(), val, accelerator);
|
||||
}
|
||||
|
||||
void Menu::ExecuteCommand(int command_id, int flags) {
|
||||
execute_command_.Run(
|
||||
mate::internal::CreateEventFromFlags(isolate(), flags),
|
||||
command_id);
|
||||
void Menu::ExecuteCommand(int command_id, int event_flags) {
|
||||
execute_command_.Run(command_id);
|
||||
}
|
||||
|
||||
void Menu::MenuWillShow(ui::SimpleMenuModel* source) {
|
||||
@@ -155,9 +149,8 @@ bool Menu::IsVisibleAt(int index) const {
|
||||
|
||||
// static
|
||||
void Menu::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "Menu"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
v8::Local<v8::ObjectTemplate> prototype) {
|
||||
mate::ObjectTemplateBuilder(isolate, prototype)
|
||||
.MakeDestroyable()
|
||||
.SetMethod("insertItem", &Menu::InsertItemAt)
|
||||
.SetMethod("insertCheckItem", &Menu::InsertCheckItemAt)
|
||||
@@ -176,8 +169,8 @@ void Menu::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("isItemCheckedAt", &Menu::IsItemCheckedAt)
|
||||
.SetMethod("isEnabledAt", &Menu::IsEnabledAt)
|
||||
.SetMethod("isVisibleAt", &Menu::IsVisibleAt)
|
||||
.SetMethod("popupAt", &Menu::PopupAt)
|
||||
.SetMethod("closePopupAt", &Menu::ClosePopupAt);
|
||||
.SetMethod("_popup", &Menu::Popup)
|
||||
.SetMethod("_popupAt", &Menu::PopupAt);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
@@ -187,15 +180,14 @@ void Menu::BuildPrototype(v8::Isolate* isolate,
|
||||
|
||||
namespace {
|
||||
|
||||
using atom::api::Menu;
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
using atom::api::Menu;
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
Menu::SetConstructor(isolate, base::Bind(&Menu::New));
|
||||
|
||||
v8::Local<v8::Function> constructor = mate::CreateConstructor<Menu>(
|
||||
isolate, "Menu", base::Bind(&Menu::Create));
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("Menu", Menu::GetConstructor(isolate)->GetFunction());
|
||||
dict.Set("Menu", static_cast<v8::Local<v8::Value>>(constructor));
|
||||
#if defined(OS_MACOSX)
|
||||
dict.SetMethod("setApplicationMenu", &Menu::SetApplicationMenu);
|
||||
dict.SetMethod("sendActionToFirstResponder",
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
#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"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
@@ -20,10 +20,10 @@ namespace api {
|
||||
class Menu : public mate::TrackableObject<Menu>,
|
||||
public AtomMenuModel::Delegate {
|
||||
public:
|
||||
static mate::WrappableBase* New(mate::Arguments* args);
|
||||
static mate::Wrappable* Create();
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
v8::Local<v8::ObjectTemplate> prototype);
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
// Set the global menubar.
|
||||
@@ -36,7 +36,7 @@ class Menu : public mate::TrackableObject<Menu>,
|
||||
AtomMenuModel* model() const { return model_.get(); }
|
||||
|
||||
protected:
|
||||
Menu(v8::Isolate* isolate, v8::Local<v8::Object> wrapper);
|
||||
Menu();
|
||||
~Menu() override;
|
||||
|
||||
// mate::Wrappable:
|
||||
@@ -46,18 +46,15 @@ class Menu : public mate::TrackableObject<Menu>,
|
||||
bool IsCommandIdChecked(int command_id) const override;
|
||||
bool IsCommandIdEnabled(int command_id) const override;
|
||||
bool IsCommandIdVisible(int command_id) const override;
|
||||
bool GetAcceleratorForCommandIdWithParams(
|
||||
int command_id,
|
||||
bool use_default_accelerator,
|
||||
ui::Accelerator* accelerator) const override;
|
||||
bool GetAcceleratorForCommandId(int command_id,
|
||||
ui::Accelerator* accelerator) override;
|
||||
void ExecuteCommand(int command_id, int event_flags) override;
|
||||
void MenuWillShow(ui::SimpleMenuModel* source) override;
|
||||
|
||||
virtual void PopupAt(
|
||||
Window* window, int x, int y, int positioning_item, bool async) = 0;
|
||||
virtual void ClosePopupAt(int32_t window_id) = 0;
|
||||
virtual void Popup(Window* window) = 0;
|
||||
virtual void PopupAt(Window* window, int x, int y) = 0;
|
||||
|
||||
std::unique_ptr<AtomMenuModel> model_;
|
||||
scoped_ptr<AtomMenuModel> model_;
|
||||
Menu* parent_;
|
||||
|
||||
private:
|
||||
@@ -91,8 +88,8 @@ class Menu : public mate::TrackableObject<Menu>,
|
||||
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<v8::Local<v8::Value>(int)> get_accelerator_;
|
||||
base::Callback<void(int)> execute_command_;
|
||||
base::Callback<void()> menu_will_show_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Menu);
|
||||
|
||||
@@ -7,40 +7,28 @@
|
||||
|
||||
#include "atom/browser/api/atom_api_menu.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#import "atom/browser/ui/cocoa/atom_menu_controller.h"
|
||||
|
||||
using base::scoped_nsobject;
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class MenuMac : public Menu {
|
||||
protected:
|
||||
MenuMac(v8::Isolate* isolate, v8::Local<v8::Object> wrapper);
|
||||
MenuMac();
|
||||
|
||||
void PopupAt(
|
||||
Window* window, int x, int y, int positioning_item, bool async) override;
|
||||
void PopupOnUI(const base::WeakPtr<NativeWindow>& native_window,
|
||||
int32_t window_id, int x, int y, int positioning_item,
|
||||
bool async);
|
||||
void ClosePopupAt(int32_t window_id) override;
|
||||
void Popup(Window* window) override;
|
||||
void PopupAt(Window* window, int x, int y) override;
|
||||
|
||||
base::scoped_nsobject<AtomMenuController> menu_controller_;
|
||||
|
||||
private:
|
||||
friend class Menu;
|
||||
|
||||
static void SendActionToFirstResponder(const std::string& action);
|
||||
|
||||
scoped_nsobject<AtomMenuController> menu_controller_;
|
||||
|
||||
// window ID -> open context menu
|
||||
std::map<int32_t, scoped_nsobject<AtomMenuController>> popup_controllers_;
|
||||
|
||||
base::WeakPtrFactory<MenuMac> weak_factory_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(MenuMac);
|
||||
};
|
||||
|
||||
|
||||
@@ -5,128 +5,75 @@
|
||||
#import "atom/browser/api/atom_api_menu_mac.h"
|
||||
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "atom/browser/unresponsive_suppressor.h"
|
||||
#include "base/mac/scoped_sending_event.h"
|
||||
#include "base/message_loop/message_loop.h"
|
||||
#include "base/strings/sys_string_conversions.h"
|
||||
#include "brightray/browser/inspectable_web_contents.h"
|
||||
#include "brightray/browser/inspectable_web_contents_view.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
using content::BrowserThread;
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
MenuMac::MenuMac(v8::Isolate* isolate, v8::Local<v8::Object> wrapper)
|
||||
: Menu(isolate, wrapper),
|
||||
weak_factory_(this) {
|
||||
MenuMac::MenuMac() {
|
||||
}
|
||||
|
||||
void MenuMac::PopupAt(
|
||||
Window* window, int x, int y, int positioning_item, bool async) {
|
||||
void MenuMac::Popup(Window* window) {
|
||||
NativeWindow* native_window = window->window();
|
||||
if (!native_window)
|
||||
return;
|
||||
|
||||
auto popup = base::Bind(&MenuMac::PopupOnUI, weak_factory_.GetWeakPtr(),
|
||||
native_window->GetWeakPtr(), window->ID(), x, y,
|
||||
positioning_item, async);
|
||||
if (async)
|
||||
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, popup);
|
||||
else
|
||||
popup.Run();
|
||||
}
|
||||
|
||||
void MenuMac::PopupOnUI(const base::WeakPtr<NativeWindow>& native_window,
|
||||
int32_t window_id, int x, int y, int positioning_item,
|
||||
bool async) {
|
||||
if (!native_window)
|
||||
return;
|
||||
brightray::InspectableWebContents* web_contents =
|
||||
native_window->inspectable_web_contents();
|
||||
content::WebContents* web_contents = native_window->web_contents();
|
||||
if (!web_contents)
|
||||
return;
|
||||
|
||||
auto close_callback = base::Bind(&MenuMac::ClosePopupAt,
|
||||
weak_factory_.GetWeakPtr(), window_id);
|
||||
popup_controllers_[window_id] = base::scoped_nsobject<AtomMenuController>(
|
||||
[[AtomMenuController alloc] initWithModel:model()
|
||||
useDefaultAccelerator:NO]);
|
||||
NSMenu* menu = [popup_controllers_[window_id] menu];
|
||||
NSView* view = web_contents->GetView()->GetNativeView();
|
||||
NSWindow* nswindow = native_window->GetNativeWindow();
|
||||
base::scoped_nsobject<AtomMenuController> menu_controller(
|
||||
[[AtomMenuController alloc] initWithModel:model_.get()]);
|
||||
|
||||
// Which menu item to show.
|
||||
NSMenuItem* item = nil;
|
||||
if (positioning_item < [menu numberOfItems] && positioning_item >= 0)
|
||||
item = [menu itemAtIndex:positioning_item];
|
||||
// Fake out a context menu event.
|
||||
NSEvent* currentEvent = [NSApp currentEvent];
|
||||
NSPoint position = [nswindow mouseLocationOutsideOfEventStream];
|
||||
NSTimeInterval eventTime = [currentEvent timestamp];
|
||||
NSEvent* clickEvent = [NSEvent mouseEventWithType:NSRightMouseDown
|
||||
location:position
|
||||
modifierFlags:NSRightMouseDownMask
|
||||
timestamp:eventTime
|
||||
windowNumber:[nswindow windowNumber]
|
||||
context:nil
|
||||
eventNumber:0
|
||||
clickCount:1
|
||||
pressure:1.0];
|
||||
|
||||
// (-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;
|
||||
|
||||
|
||||
if (async) {
|
||||
[popup_controllers_[window_id] setCloseCallback:close_callback];
|
||||
// Make sure events can be pumped while the menu is up.
|
||||
base::MessageLoop::ScopedNestableTaskAllower allow(
|
||||
base::MessageLoop::current());
|
||||
|
||||
// One of the events that could be pumped is |window.close()|.
|
||||
// User-initiated event-tracking loops protect against this by
|
||||
// setting flags in -[CrApplication sendEvent:], but since
|
||||
// web-content menus are initiated by IPC message the setup has to
|
||||
// be done manually.
|
||||
base::mac::ScopedSendingEvent sendingEventScoper;
|
||||
|
||||
// Don't emit unresponsive event when showing menu.
|
||||
atom::UnresponsiveSuppressor suppressor;
|
||||
[menu popUpMenuPositioningItem:item atLocation:position inView:view];
|
||||
} else {
|
||||
// Don't emit unresponsive event when showing menu.
|
||||
atom::UnresponsiveSuppressor suppressor;
|
||||
[menu popUpMenuPositioningItem:item atLocation:position inView:view];
|
||||
close_callback.Run();
|
||||
}
|
||||
// Show the menu.
|
||||
[NSMenu popUpContextMenu:[menu_controller menu]
|
||||
withEvent:clickEvent
|
||||
forView:web_contents->GetContentNativeView()];
|
||||
}
|
||||
|
||||
void MenuMac::ClosePopupAt(int32_t window_id) {
|
||||
popup_controllers_.erase(window_id);
|
||||
void MenuMac::PopupAt(Window* window, int x, int y) {
|
||||
NativeWindow* native_window = window->window();
|
||||
if (!native_window)
|
||||
return;
|
||||
content::WebContents* web_contents = native_window->web_contents();
|
||||
if (!web_contents)
|
||||
return;
|
||||
|
||||
base::scoped_nsobject<AtomMenuController> menu_controller(
|
||||
[[AtomMenuController alloc] initWithModel:model_.get()]);
|
||||
NSMenu* menu = [menu_controller menu];
|
||||
NSView* view = web_contents->GetContentNativeView();
|
||||
|
||||
// Show the menu.
|
||||
[menu popUpMenuPositioningItem:[menu itemAtIndex:0]
|
||||
atLocation:NSMakePoint(x, [view frame].size.height - y)
|
||||
inView:view];
|
||||
}
|
||||
|
||||
// static
|
||||
void Menu::SetApplicationMenu(Menu* base_menu) {
|
||||
MenuMac* menu = static_cast<MenuMac*>(base_menu);
|
||||
base::scoped_nsobject<AtomMenuController> menu_controller(
|
||||
[[AtomMenuController alloc] initWithModel:menu->model_.get()
|
||||
useDefaultAccelerator:YES]);
|
||||
[[AtomMenuController alloc] initWithModel:menu->model_.get()]);
|
||||
[NSApp setMainMenu:[menu_controller menu]];
|
||||
|
||||
// Ensure the menu_controller_ is destroyed after main menu is set.
|
||||
@@ -140,8 +87,8 @@ void Menu::SendActionToFirstResponder(const std::string& action) {
|
||||
}
|
||||
|
||||
// static
|
||||
mate::WrappableBase* Menu::New(mate::Arguments* args) {
|
||||
return new MenuMac(args->isolate(), args->GetThis());
|
||||
mate::Wrappable* Menu::Create() {
|
||||
return new MenuMac();
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
@@ -5,23 +5,22 @@
|
||||
#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"
|
||||
|
||||
using views::MenuRunner;
|
||||
#include "ui/gfx/screen.h"
|
||||
#include "ui/views/controls/menu/menu_runner.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
MenuViews::MenuViews(v8::Isolate* isolate, v8::Local<v8::Object> wrapper)
|
||||
: Menu(isolate, wrapper),
|
||||
weak_factory_(this) {
|
||||
MenuViews::MenuViews() {
|
||||
}
|
||||
|
||||
void MenuViews::PopupAt(
|
||||
Window* window, int x, int y, int positioning_item, bool async) {
|
||||
void MenuViews::Popup(Window* window) {
|
||||
PopupAtPoint(window, gfx::Screen::GetNativeScreen()->GetCursorScreenPoint());
|
||||
}
|
||||
|
||||
void MenuViews::PopupAt(Window* window, int x, int y) {
|
||||
NativeWindow* native_window = static_cast<NativeWindow*>(window->window());
|
||||
if (!native_window)
|
||||
return;
|
||||
@@ -32,43 +31,25 @@ void MenuViews::PopupAt(
|
||||
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);
|
||||
}
|
||||
gfx::Point origin = view->GetViewBounds().origin();
|
||||
PopupAtPoint(window, gfx::Point(origin.x() + x, origin.y() + y));
|
||||
}
|
||||
|
||||
int flags = MenuRunner::CONTEXT_MENU | MenuRunner::HAS_MNEMONICS;
|
||||
if (async)
|
||||
flags |= MenuRunner::ASYNC;
|
||||
|
||||
// Don't emit unresponsive event when showing menu.
|
||||
atom::UnresponsiveSuppressor suppressor;
|
||||
|
||||
// Show the menu.
|
||||
int32_t window_id = window->ID();
|
||||
auto close_callback = base::Bind(
|
||||
&MenuViews::ClosePopupAt, weak_factory_.GetWeakPtr(), window_id);
|
||||
menu_runners_[window_id] = std::unique_ptr<MenuRunner>(new MenuRunner(
|
||||
model(), flags, close_callback));
|
||||
ignore_result(menu_runners_[window_id]->RunMenuAt(
|
||||
void MenuViews::PopupAtPoint(Window* window, const gfx::Point& point) {
|
||||
views::MenuRunner menu_runner(
|
||||
model(),
|
||||
views::MenuRunner::CONTEXT_MENU | views::MenuRunner::HAS_MNEMONICS);
|
||||
ignore_result(menu_runner.RunMenuAt(
|
||||
static_cast<NativeWindowViews*>(window->window())->widget(),
|
||||
NULL,
|
||||
gfx::Rect(location, gfx::Size()),
|
||||
gfx::Rect(point, gfx::Size()),
|
||||
views::MENU_ANCHOR_TOPLEFT,
|
||||
ui::MENU_SOURCE_MOUSE));
|
||||
}
|
||||
|
||||
void MenuViews::ClosePopupAt(int32_t window_id) {
|
||||
menu_runners_.erase(window_id);
|
||||
}
|
||||
|
||||
// static
|
||||
mate::WrappableBase* Menu::New(mate::Arguments* args) {
|
||||
return new MenuViews(args->isolate(), args->GetThis());
|
||||
mate::Wrappable* Menu::Create() {
|
||||
return new MenuViews();
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
@@ -5,12 +5,8 @@
|
||||
#ifndef ATOM_BROWSER_API_ATOM_API_MENU_VIEWS_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_MENU_VIEWS_H_
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "atom/browser/api/atom_api_menu.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "ui/display/screen.h"
|
||||
#include "ui/views/controls/menu/menu_runner.h"
|
||||
#include "ui/gfx/screen.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
@@ -18,18 +14,14 @@ namespace api {
|
||||
|
||||
class MenuViews : public Menu {
|
||||
public:
|
||||
MenuViews(v8::Isolate* isolate, v8::Local<v8::Object> wrapper);
|
||||
MenuViews();
|
||||
|
||||
protected:
|
||||
void PopupAt(
|
||||
Window* window, int x, int y, int positioning_item, bool async) override;
|
||||
void ClosePopupAt(int32_t window_id) override;
|
||||
void Popup(Window* window) override;
|
||||
void PopupAt(Window* window, int x, int y) override;
|
||||
|
||||
private:
|
||||
// window ID -> open context menu
|
||||
std::map<int32_t, std::unique_ptr<views::MenuRunner>> menu_runners_;
|
||||
|
||||
base::WeakPtrFactory<MenuViews> weak_factory_;
|
||||
void PopupAtPoint(Window* window, const gfx::Point& point);
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(MenuViews);
|
||||
};
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
// Copyright (c) 2016 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_net.h"
|
||||
#include "atom/browser/api/atom_api_url_request.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
Net::Net(v8::Isolate* isolate) {
|
||||
Init(isolate);
|
||||
}
|
||||
|
||||
Net::~Net() {}
|
||||
|
||||
// static
|
||||
v8::Local<v8::Value> Net::Create(v8::Isolate* isolate) {
|
||||
return mate::CreateHandle(isolate, new Net(isolate)).ToV8();
|
||||
}
|
||||
|
||||
// static
|
||||
void Net::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "Net"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetProperty("URLRequest", &Net::URLRequest);
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> Net::URLRequest(v8::Isolate* isolate) {
|
||||
return URLRequest::GetConstructor(isolate)->GetFunction();
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
namespace {
|
||||
|
||||
using atom::api::Net;
|
||||
using atom::api::URLRequest;
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
|
||||
URLRequest::SetConstructor(isolate, base::Bind(URLRequest::New));
|
||||
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("net", Net::Create(isolate));
|
||||
dict.Set("Net", Net::GetConstructor(isolate)->GetFunction());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_net, Initialize)
|
||||
@@ -1,35 +0,0 @@
|
||||
// Copyright (c) 2016 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_API_ATOM_API_NET_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_NET_H_
|
||||
|
||||
#include "atom/browser/api/event_emitter.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class Net : public mate::EventEmitter<Net> {
|
||||
public:
|
||||
static v8::Local<v8::Value> Create(v8::Isolate* isolate);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
v8::Local<v8::Value> URLRequest(v8::Isolate* isolate);
|
||||
|
||||
protected:
|
||||
explicit Net(v8::Isolate* isolate);
|
||||
~Net() override;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(Net);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_NET_H_
|
||||
@@ -5,19 +5,17 @@
|
||||
#include "atom/browser/api/atom_api_power_monitor.h"
|
||||
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "base/power_monitor/power_monitor.h"
|
||||
#include "base/power_monitor/power_monitor_device_source.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
PowerMonitor::PowerMonitor(v8::Isolate* isolate) {
|
||||
PowerMonitor::PowerMonitor() {
|
||||
base::PowerMonitor::Get()->AddObserver(this);
|
||||
Init(isolate);
|
||||
}
|
||||
|
||||
PowerMonitor::~PowerMonitor() {
|
||||
@@ -44,17 +42,11 @@ v8::Local<v8::Value> PowerMonitor::Create(v8::Isolate* isolate) {
|
||||
if (!Browser::Get()->is_ready()) {
|
||||
isolate->ThrowException(v8::Exception::Error(mate::StringToV8(
|
||||
isolate,
|
||||
"Cannot require \"powerMonitor\" module before app is ready")));
|
||||
"Cannot initialize \"power-monitor\" module before app is ready")));
|
||||
return v8::Null(isolate);
|
||||
}
|
||||
|
||||
return mate::CreateHandle(isolate, new PowerMonitor(isolate)).ToV8();
|
||||
}
|
||||
|
||||
// static
|
||||
void PowerMonitor::BuildPrototype(
|
||||
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "PowerMonitor"));
|
||||
return CreateHandle(isolate, new PowerMonitor).ToV8();
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
@@ -64,19 +56,16 @@ void PowerMonitor::BuildPrototype(
|
||||
|
||||
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
|
||||
|
||||
using atom::api::PowerMonitor;
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("powerMonitor", PowerMonitor::Create(isolate));
|
||||
dict.Set("PowerMonitor",
|
||||
PowerMonitor::GetConstructor(isolate)->GetFunction());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -19,11 +19,8 @@ class PowerMonitor : public mate::TrackableObject<PowerMonitor>,
|
||||
public:
|
||||
static v8::Local<v8::Value> Create(v8::Isolate* isolate);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
protected:
|
||||
explicit PowerMonitor(v8::Isolate* isolate);
|
||||
PowerMonitor();
|
||||
~PowerMonitor() override;
|
||||
|
||||
// base::PowerObserver implementations:
|
||||
|
||||
@@ -6,21 +6,18 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
using content::BrowserThread;
|
||||
#include "content/public/browser/power_save_blocker.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
namespace mate {
|
||||
|
||||
template<>
|
||||
struct Converter<device::PowerSaveBlocker::PowerSaveBlockerType> {
|
||||
struct Converter<content::PowerSaveBlocker::PowerSaveBlockerType> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
device::PowerSaveBlocker::PowerSaveBlockerType* out) {
|
||||
using device::PowerSaveBlocker;
|
||||
content::PowerSaveBlocker::PowerSaveBlockerType* out) {
|
||||
using content::PowerSaveBlocker;
|
||||
std::string type;
|
||||
if (!ConvertFromV8(isolate, val, &type))
|
||||
return false;
|
||||
@@ -40,10 +37,9 @@ namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
PowerSaveBlocker::PowerSaveBlocker(v8::Isolate* isolate)
|
||||
PowerSaveBlocker::PowerSaveBlocker()
|
||||
: current_blocker_type_(
|
||||
device::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension) {
|
||||
Init(isolate);
|
||||
content::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension) {
|
||||
}
|
||||
|
||||
PowerSaveBlocker::~PowerSaveBlocker() {
|
||||
@@ -61,32 +57,30 @@ void PowerSaveBlocker::UpdatePowerSaveBlocker() {
|
||||
// higher precedence level than |kPowerSaveBlockPreventAppSuspension|.
|
||||
//
|
||||
// Only the highest-precedence blocker type takes effect.
|
||||
device::PowerSaveBlocker::PowerSaveBlockerType new_blocker_type =
|
||||
device::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension;
|
||||
content::PowerSaveBlocker::PowerSaveBlockerType new_blocker_type =
|
||||
content::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension;
|
||||
for (const auto& element : power_save_blocker_types_) {
|
||||
if (element.second ==
|
||||
device::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep) {
|
||||
content::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep) {
|
||||
new_blocker_type =
|
||||
device::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep;
|
||||
content::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!power_save_blocker_ || new_blocker_type != current_blocker_type_) {
|
||||
std::unique_ptr<device::PowerSaveBlocker> new_blocker(
|
||||
new device::PowerSaveBlocker(
|
||||
scoped_ptr<content::PowerSaveBlocker> new_blocker =
|
||||
content::PowerSaveBlocker::Create(
|
||||
new_blocker_type,
|
||||
device::PowerSaveBlocker::kReasonOther,
|
||||
ATOM_PRODUCT_NAME,
|
||||
BrowserThread::GetTaskRunnerForThread(BrowserThread::UI),
|
||||
BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE)));
|
||||
content::PowerSaveBlocker::kReasonOther,
|
||||
ATOM_PRODUCT_NAME);
|
||||
power_save_blocker_.swap(new_blocker);
|
||||
current_blocker_type_ = new_blocker_type;
|
||||
}
|
||||
}
|
||||
|
||||
int PowerSaveBlocker::Start(
|
||||
device::PowerSaveBlocker::PowerSaveBlockerType type) {
|
||||
content::PowerSaveBlocker::PowerSaveBlockerType type) {
|
||||
static int count = 0;
|
||||
power_save_blocker_types_[count] = type;
|
||||
UpdatePowerSaveBlocker();
|
||||
@@ -103,21 +97,19 @@ bool PowerSaveBlocker::IsStarted(int id) {
|
||||
return power_save_blocker_types_.find(id) != power_save_blocker_types_.end();
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<PowerSaveBlocker> PowerSaveBlocker::Create(v8::Isolate* isolate) {
|
||||
return mate::CreateHandle(isolate, new PowerSaveBlocker(isolate));
|
||||
}
|
||||
|
||||
// static
|
||||
void PowerSaveBlocker::BuildPrototype(
|
||||
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "PowerSaveBlocker"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
mate::ObjectTemplateBuilder PowerSaveBlocker::GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) {
|
||||
return mate::ObjectTemplateBuilder(isolate)
|
||||
.SetMethod("start", &PowerSaveBlocker::Start)
|
||||
.SetMethod("stop", &PowerSaveBlocker::Stop)
|
||||
.SetMethod("isStarted", &PowerSaveBlocker::IsStarted);
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<PowerSaveBlocker> PowerSaveBlocker::Create(v8::Isolate* isolate) {
|
||||
return CreateHandle(isolate, new PowerSaveBlocker);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
#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 "base/memory/scoped_ptr.h"
|
||||
#include "content/public/browser/power_save_blocker.h"
|
||||
#include "native_mate/handle.h"
|
||||
|
||||
namespace mate {
|
||||
@@ -24,27 +24,28 @@ class PowerSaveBlocker : public mate::TrackableObject<PowerSaveBlocker> {
|
||||
public:
|
||||
static mate::Handle<PowerSaveBlocker> Create(v8::Isolate* isolate);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
protected:
|
||||
explicit PowerSaveBlocker(v8::Isolate* isolate);
|
||||
PowerSaveBlocker();
|
||||
~PowerSaveBlocker() override;
|
||||
|
||||
// mate::Wrappable implementations:
|
||||
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) override;
|
||||
|
||||
private:
|
||||
void UpdatePowerSaveBlocker();
|
||||
int Start(device::PowerSaveBlocker::PowerSaveBlockerType type);
|
||||
int Start(content::PowerSaveBlocker::PowerSaveBlockerType type);
|
||||
bool Stop(int id);
|
||||
bool IsStarted(int id);
|
||||
|
||||
std::unique_ptr<device::PowerSaveBlocker> power_save_blocker_;
|
||||
scoped_ptr<content::PowerSaveBlocker> power_save_blocker_;
|
||||
|
||||
// Currnet blocker type used by |power_save_blocker_|
|
||||
device::PowerSaveBlocker::PowerSaveBlockerType current_blocker_type_;
|
||||
content::PowerSaveBlocker::PowerSaveBlockerType current_blocker_type_;
|
||||
|
||||
// Map from id to the corresponding blocker type for each request.
|
||||
using PowerSaveBlockerTypeMap =
|
||||
std::map<int, device::PowerSaveBlocker::PowerSaveBlockerType>;
|
||||
std::map<int, content::PowerSaveBlocker::PowerSaveBlockerType>;
|
||||
PowerSaveBlockerTypeMap power_save_blocker_types_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PowerSaveBlocker);
|
||||
|
||||
@@ -5,21 +5,16 @@
|
||||
#include "atom/browser/api/atom_api_protocol.h"
|
||||
|
||||
#include "atom/browser/atom_browser_client.h"
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/atom_browser_main_parts.h"
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/browser/net/url_request_async_asar_job.h"
|
||||
#include "atom/browser/net/url_request_buffer_job.h"
|
||||
#include "atom/browser/net/url_request_fetch_job.h"
|
||||
#include "atom/browser/net/url_request_string_job.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "atom/common/native_mate_converters/net_converter.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "atom/common/options_switches.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "content/public/browser/child_process_security_policy.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "url/url_util.h"
|
||||
|
||||
using content::BrowserThread;
|
||||
|
||||
@@ -27,63 +22,40 @@ 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)
|
||||
Protocol::Protocol(AtomBrowserContext* browser_context)
|
||||
: request_context_getter_(browser_context->GetRequestContext()),
|
||||
weak_factory_(this) {
|
||||
Init(isolate);
|
||||
job_factory_(browser_context->job_factory()) {
|
||||
CHECK(job_factory_);
|
||||
}
|
||||
|
||||
Protocol::~Protocol() {
|
||||
content::BrowserThread::PostTask(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(ClearJobFactoryInIO, request_context_getter_));
|
||||
mate::ObjectTemplateBuilder Protocol::GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) {
|
||||
return mate::ObjectTemplateBuilder(isolate)
|
||||
.SetMethod("registerStandardSchemes", &Protocol::RegisterStandardSchemes)
|
||||
.SetMethod("registerStringProtocol",
|
||||
&Protocol::RegisterProtocol<URLRequestStringJob>)
|
||||
.SetMethod("registerBufferProtocol",
|
||||
&Protocol::RegisterProtocol<URLRequestBufferJob>)
|
||||
.SetMethod("registerFileProtocol",
|
||||
&Protocol::RegisterProtocol<URLRequestAsyncAsarJob>)
|
||||
.SetMethod("registerHttpProtocol",
|
||||
&Protocol::RegisterProtocol<URLRequestFetchJob>)
|
||||
.SetMethod("unregisterProtocol", &Protocol::UnregisterProtocol)
|
||||
.SetMethod("isProtocolHandled", &Protocol::IsProtocolHandled)
|
||||
.SetMethod("interceptStringProtocol",
|
||||
&Protocol::InterceptProtocol<URLRequestStringJob>)
|
||||
.SetMethod("interceptBufferProtocol",
|
||||
&Protocol::InterceptProtocol<URLRequestBufferJob>)
|
||||
.SetMethod("interceptFileProtocol",
|
||||
&Protocol::InterceptProtocol<URLRequestAsyncAsarJob>)
|
||||
.SetMethod("interceptHttpProtocol",
|
||||
&Protocol::InterceptProtocol<URLRequestFetchJob>)
|
||||
.SetMethod("uninterceptProtocol", &Protocol::UninterceptProtocol);
|
||||
}
|
||||
|
||||
void Protocol::RegisterServiceWorkerSchemes(
|
||||
void Protocol::RegisterStandardSchemes(
|
||||
const std::vector<std::string>& schemes) {
|
||||
atom::AtomBrowserClient::SetCustomServiceWorkerSchemes(schemes);
|
||||
atom::AtomBrowserClient::SetCustomSchemes(schemes);
|
||||
}
|
||||
|
||||
void Protocol::UnregisterProtocol(
|
||||
@@ -93,37 +65,30 @@ void Protocol::UnregisterProtocol(
|
||||
content::BrowserThread::PostTaskAndReplyWithResult(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&Protocol::UnregisterProtocolInIO,
|
||||
request_context_getter_, scheme),
|
||||
base::Unretained(this), scheme),
|
||||
base::Bind(&Protocol::OnIOCompleted,
|
||||
GetWeakPtr(), callback));
|
||||
base::Unretained(this), 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))
|
||||
if (!job_factory_->HasProtocolHandler(scheme))
|
||||
return PROTOCOL_NOT_REGISTERED;
|
||||
job_factory->SetProtocolHandler(scheme, nullptr);
|
||||
job_factory_->SetProtocolHandler(scheme, nullptr);
|
||||
return PROTOCOL_OK;
|
||||
}
|
||||
|
||||
void Protocol::IsProtocolHandled(const std::string& scheme,
|
||||
const BooleanCallback& callback) {
|
||||
const BooleanCallback& callback) {
|
||||
content::BrowserThread::PostTaskAndReplyWithResult(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&Protocol::IsProtocolHandledInIO,
|
||||
request_context_getter_, scheme),
|
||||
base::Unretained(this), 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);
|
||||
bool Protocol::IsProtocolHandledInIO(const std::string& scheme) {
|
||||
return job_factory_->IsHandledProtocol(scheme);
|
||||
}
|
||||
|
||||
void Protocol::UninterceptProtocol(
|
||||
@@ -133,18 +98,18 @@ void Protocol::UninterceptProtocol(
|
||||
content::BrowserThread::PostTaskAndReplyWithResult(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&Protocol::UninterceptProtocolInIO,
|
||||
request_context_getter_, scheme),
|
||||
base::Unretained(this), scheme),
|
||||
base::Bind(&Protocol::OnIOCompleted,
|
||||
GetWeakPtr(), callback));
|
||||
base::Unretained(this), 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;
|
||||
if (!original_protocols_.contains(scheme))
|
||||
return PROTOCOL_NOT_INTERCEPTED;
|
||||
job_factory_->ReplaceProtocol(scheme,
|
||||
original_protocols_.take_and_erase(scheme));
|
||||
return PROTOCOL_OK;
|
||||
}
|
||||
|
||||
void Protocol::OnIOCompleted(
|
||||
@@ -167,53 +132,18 @@ void Protocol::OnIOCompleted(
|
||||
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_REGISTERED: return "The scheme has been registred";
|
||||
case PROTOCOL_NOT_REGISTERED: return "The scheme has not been registred";
|
||||
case PROTOCOL_INTERCEPTED: return "The scheme has been intercepted";
|
||||
case PROTOCOL_NOT_INTERCEPTED: return "The scheme has not been intercepted";
|
||||
default: return "Unexpected error";
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
return mate::CreateHandle(isolate, new Protocol(browser_context));
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
@@ -222,23 +152,13 @@ void Protocol::BuildPrototype(
|
||||
|
||||
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);
|
||||
auto browser_context = static_cast<atom::AtomBrowserContext*>(
|
||||
atom::AtomBrowserMainParts::Get()->browser_context());
|
||||
dict.Set("protocol", atom::api::Protocol::Create(isolate, browser_context));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -5,49 +5,47 @@
|
||||
#ifndef ATOM_BROWSER_API_ATOM_API_PROTOCOL_H_
|
||||
#define ATOM_BROWSER_API_ATOM_API_PROTOCOL_H_
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/net/atom_url_request_job_factory.h"
|
||||
#include "base/callback.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/containers/scoped_ptr_hash_map.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "native_mate/arguments.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "net/url_request/url_request_context.h"
|
||||
#include "native_mate/wrappable.h"
|
||||
|
||||
namespace base {
|
||||
class DictionaryValue;
|
||||
namespace net {
|
||||
class URLRequest;
|
||||
class URLRequestContextGetter;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomBrowserContext;
|
||||
class AtomURLRequestJobFactory;
|
||||
|
||||
namespace api {
|
||||
|
||||
std::vector<std::string> GetStandardSchemes();
|
||||
void RegisterStandardSchemes(const std::vector<std::string>& schemes,
|
||||
mate::Arguments* args);
|
||||
|
||||
class Protocol : public mate::TrackableObject<Protocol> {
|
||||
class Protocol : public mate::Wrappable {
|
||||
public:
|
||||
using Handler =
|
||||
base::Callback<void(const base::DictionaryValue&, v8::Local<v8::Value>)>;
|
||||
base::Callback<void(const net::URLRequest*, v8::Local<v8::Value>)>;
|
||||
using CompletionCallback = base::Callback<void(v8::Local<v8::Value>)>;
|
||||
using BooleanCallback = base::Callback<void(bool)>;
|
||||
|
||||
static mate::Handle<Protocol> Create(
|
||||
v8::Isolate* isolate, AtomBrowserContext* browser_context);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
protected:
|
||||
Protocol(v8::Isolate* isolate, AtomBrowserContext* browser_context);
|
||||
~Protocol();
|
||||
explicit Protocol(AtomBrowserContext* browser_context);
|
||||
|
||||
// mate::Wrappable implementations:
|
||||
virtual mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate);
|
||||
|
||||
private:
|
||||
// Possible errors.
|
||||
@@ -79,20 +77,20 @@ class Protocol : public mate::TrackableObject<Protocol> {
|
||||
net::URLRequest* request,
|
||||
net::NetworkDelegate* network_delegate) const override {
|
||||
RequestJob* request_job = new RequestJob(request, network_delegate);
|
||||
request_job->SetHandlerInfo(isolate_, request_context_.get(), handler_);
|
||||
request_job->SetHandlerInfo(isolate_, request_context_, handler_);
|
||||
return request_job;
|
||||
}
|
||||
|
||||
private:
|
||||
v8::Isolate* isolate_;
|
||||
scoped_refptr<net::URLRequestContextGetter> request_context_;
|
||||
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 schemes to standard scheme list.
|
||||
void RegisterStandardSchemes(const std::vector<std::string>& schemes);
|
||||
|
||||
// Register the protocol with certain request job.
|
||||
template<typename RequestJob>
|
||||
@@ -104,24 +102,19 @@ class Protocol : public mate::TrackableObject<Protocol> {
|
||||
content::BrowserThread::PostTaskAndReplyWithResult(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&Protocol::RegisterProtocolInIO<RequestJob>,
|
||||
request_context_getter_, isolate(), scheme, handler),
|
||||
base::Unretained(this), scheme, handler),
|
||||
base::Bind(&Protocol::OnIOCompleted,
|
||||
GetWeakPtr(), callback));
|
||||
base::Unretained(this), 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))
|
||||
ProtocolError RegisterProtocolInIO(const std::string& scheme,
|
||||
const Handler& handler) {
|
||||
if (job_factory_->IsHandledProtocol(scheme))
|
||||
return PROTOCOL_REGISTERED;
|
||||
std::unique_ptr<CustomProtocolHandler<RequestJob>> protocol_handler(
|
||||
scoped_ptr<CustomProtocolHandler<RequestJob>> protocol_handler(
|
||||
new CustomProtocolHandler<RequestJob>(
|
||||
isolate, request_context_getter.get(), handler));
|
||||
if (job_factory->SetProtocolHandler(scheme, std::move(protocol_handler)))
|
||||
isolate(), request_context_getter_, handler));
|
||||
if (job_factory_->SetProtocolHandler(scheme, protocol_handler.Pass()))
|
||||
return PROTOCOL_OK;
|
||||
else
|
||||
return PROTOCOL_FAIL;
|
||||
@@ -129,16 +122,12 @@ class Protocol : public mate::TrackableObject<Protocol> {
|
||||
|
||||
// Unregister the protocol handler that handles |scheme|.
|
||||
void UnregisterProtocol(const std::string& scheme, mate::Arguments* args);
|
||||
static ProtocolError UnregisterProtocolInIO(
|
||||
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter,
|
||||
const std::string& scheme);
|
||||
ProtocolError UnregisterProtocolInIO(const std::string& scheme);
|
||||
|
||||
// Whether the protocol has handler registered.
|
||||
void IsProtocolHandled(const std::string& scheme,
|
||||
const BooleanCallback& callback);
|
||||
static bool IsProtocolHandledInIO(
|
||||
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter,
|
||||
const std::string& scheme);
|
||||
bool IsProtocolHandledInIO(const std::string& scheme);
|
||||
|
||||
// Replace the protocol handler with a new one.
|
||||
template<typename RequestJob>
|
||||
@@ -150,36 +139,32 @@ class Protocol : public mate::TrackableObject<Protocol> {
|
||||
content::BrowserThread::PostTaskAndReplyWithResult(
|
||||
content::BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&Protocol::InterceptProtocolInIO<RequestJob>,
|
||||
request_context_getter_, isolate(), scheme, handler),
|
||||
base::Unretained(this), scheme, handler),
|
||||
base::Bind(&Protocol::OnIOCompleted,
|
||||
GetWeakPtr(), callback));
|
||||
base::Unretained(this), 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))
|
||||
ProtocolError InterceptProtocolInIO(const std::string& scheme,
|
||||
const Handler& handler) {
|
||||
if (!job_factory_->IsHandledProtocol(scheme))
|
||||
return PROTOCOL_NOT_REGISTERED;
|
||||
// It is possible a protocol is handled but can not be intercepted.
|
||||
if (!job_factory->HasProtocolHandler(scheme))
|
||||
if (!job_factory_->HasProtocolHandler(scheme))
|
||||
return PROTOCOL_FAIL;
|
||||
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)))
|
||||
if (ContainsKey(original_protocols_, scheme))
|
||||
return PROTOCOL_INTERCEPTED;
|
||||
scoped_ptr<CustomProtocolHandler<RequestJob>> protocol_handler(
|
||||
new CustomProtocolHandler<RequestJob>(
|
||||
isolate(), request_context_getter_, handler));
|
||||
original_protocols_.set(
|
||||
scheme,
|
||||
job_factory_->ReplaceProtocol(scheme, protocol_handler.Pass()));
|
||||
return PROTOCOL_OK;
|
||||
}
|
||||
|
||||
// Restore the |scheme| to its original protocol handler.
|
||||
void UninterceptProtocol(const std::string& scheme, mate::Arguments* args);
|
||||
static ProtocolError UninterceptProtocolInIO(
|
||||
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter,
|
||||
const std::string& scheme);
|
||||
ProtocolError UninterceptProtocolInIO(const std::string& scheme);
|
||||
|
||||
// Convert error code to JS exception and call the callback.
|
||||
void OnIOCompleted(const CompletionCallback& callback, ProtocolError error);
|
||||
@@ -187,14 +172,15 @@ class Protocol : public mate::TrackableObject<Protocol> {
|
||||
// Convert error code to string.
|
||||
std::string ErrorCodeToString(ProtocolError error);
|
||||
|
||||
AtomURLRequestJobFactory* GetJobFactoryInIO() const;
|
||||
net::URLRequestContextGetter* request_context_getter_;
|
||||
|
||||
base::WeakPtr<Protocol> GetWeakPtr() {
|
||||
return weak_factory_.GetWeakPtr();
|
||||
}
|
||||
// Map that stores the original protocols of schemes.
|
||||
using OriginalProtocolsMap = base::ScopedPtrHashMap<
|
||||
std::string,
|
||||
scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>>;
|
||||
OriginalProtocolsMap original_protocols_;
|
||||
|
||||
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter_;
|
||||
base::WeakPtrFactory<Protocol> weak_factory_;
|
||||
AtomURLRequestJobFactory* job_factory_; // weak ref
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Protocol);
|
||||
};
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
// Copyright (c) 2016 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_render_process_preferences.h"
|
||||
|
||||
#include "atom/browser/api/atom_api_web_contents.h"
|
||||
#include "atom/browser/atom_browser_client.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/object_template_builder.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
namespace {
|
||||
|
||||
bool IsWebContents(v8::Isolate* isolate, content::RenderProcessHost* process) {
|
||||
content::WebContents* web_contents =
|
||||
static_cast<AtomBrowserClient*>(AtomBrowserClient::Get())->
|
||||
GetWebContentsFromProcessID(process->GetID());
|
||||
if (!web_contents)
|
||||
return false;
|
||||
|
||||
auto api_web_contents = WebContents::CreateFrom(isolate, web_contents);
|
||||
auto type = api_web_contents->GetType();
|
||||
return type == WebContents::Type::BROWSER_WINDOW ||
|
||||
type == WebContents::Type::WEB_VIEW;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
RenderProcessPreferences::RenderProcessPreferences(
|
||||
v8::Isolate* isolate,
|
||||
const atom::RenderProcessPreferences::Predicate& predicate)
|
||||
: preferences_(predicate) {
|
||||
Init(isolate);
|
||||
}
|
||||
|
||||
RenderProcessPreferences::~RenderProcessPreferences() {
|
||||
}
|
||||
|
||||
int RenderProcessPreferences::AddEntry(const base::DictionaryValue& entry) {
|
||||
return preferences_.AddEntry(entry);
|
||||
}
|
||||
|
||||
void RenderProcessPreferences::RemoveEntry(int id) {
|
||||
preferences_.RemoveEntry(id);
|
||||
}
|
||||
|
||||
// static
|
||||
void RenderProcessPreferences::BuildPrototype(
|
||||
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(
|
||||
mate::StringToV8(isolate, "RenderProcessPreferences"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetMethod("addEntry", &RenderProcessPreferences::AddEntry)
|
||||
.SetMethod("removeEntry", &RenderProcessPreferences::RemoveEntry);
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<RenderProcessPreferences>
|
||||
RenderProcessPreferences::ForAllWebContents(v8::Isolate* isolate) {
|
||||
return mate::CreateHandle(
|
||||
isolate,
|
||||
new RenderProcessPreferences(isolate,
|
||||
base::Bind(&IsWebContents, isolate)));
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
namespace {
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
mate::Dictionary dict(context->GetIsolate(), exports);
|
||||
dict.SetMethod("forAllWebContents",
|
||||
&atom::api::RenderProcessPreferences::ForAllWebContents);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_render_process_preferences,
|
||||
Initialize)
|
||||
@@ -1,44 +0,0 @@
|
||||
// Copyright (c) 2016 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_API_ATOM_API_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_
|
||||
@@ -12,9 +12,7 @@
|
||||
#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 "ui/gfx/screen.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
@@ -36,23 +34,22 @@ typename T::iterator FindById(T* container, int id) {
|
||||
// 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)
|
||||
if (metrics & gfx::DisplayObserver::DISPLAY_METRIC_BOUNDS)
|
||||
array.push_back("bounds");
|
||||
if (metrics & display::DisplayObserver::DISPLAY_METRIC_WORK_AREA)
|
||||
if (metrics & gfx::DisplayObserver::DISPLAY_METRIC_WORK_AREA)
|
||||
array.push_back("workArea");
|
||||
if (metrics & display::DisplayObserver::DISPLAY_METRIC_DEVICE_SCALE_FACTOR)
|
||||
if (metrics & gfx::DisplayObserver::DISPLAY_METRIC_DEVICE_SCALE_FACTOR)
|
||||
array.push_back("scaleFactor");
|
||||
if (metrics & display::DisplayObserver::DISPLAY_METRIC_ROTATION)
|
||||
if (metrics & gfx::DisplayObserver::DISPLAY_METRIC_ROTATION)
|
||||
array.push_back("rotation");
|
||||
return array;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Screen::Screen(v8::Isolate* isolate, display::Screen* screen)
|
||||
: screen_(screen) {
|
||||
Screen::Screen(gfx::Screen* screen) : screen_(screen) {
|
||||
displays_ = screen_->GetAllDisplays();
|
||||
screen_->AddObserver(this);
|
||||
Init(isolate);
|
||||
}
|
||||
|
||||
Screen::~Screen() {
|
||||
@@ -63,64 +60,73 @@ gfx::Point Screen::GetCursorScreenPoint() {
|
||||
return screen_->GetCursorScreenPoint();
|
||||
}
|
||||
|
||||
display::Display Screen::GetPrimaryDisplay() {
|
||||
gfx::Display Screen::GetPrimaryDisplay() {
|
||||
return screen_->GetPrimaryDisplay();
|
||||
}
|
||||
|
||||
std::vector<display::Display> Screen::GetAllDisplays() {
|
||||
return screen_->GetAllDisplays();
|
||||
std::vector<gfx::Display> Screen::GetAllDisplays() {
|
||||
return displays_;
|
||||
}
|
||||
|
||||
display::Display Screen::GetDisplayNearestPoint(const gfx::Point& point) {
|
||||
gfx::Display Screen::GetDisplayNearestPoint(const gfx::Point& point) {
|
||||
return screen_->GetDisplayNearestPoint(point);
|
||||
}
|
||||
|
||||
display::Display Screen::GetDisplayMatching(const gfx::Rect& match_rect) {
|
||||
gfx::Display Screen::GetDisplayMatching(const gfx::Rect& match_rect) {
|
||||
return screen_->GetDisplayMatching(match_rect);
|
||||
}
|
||||
|
||||
void Screen::OnDisplayAdded(const display::Display& new_display) {
|
||||
void Screen::OnDisplayAdded(const gfx::Display& new_display) {
|
||||
displays_.push_back(new_display);
|
||||
Emit("display-added", new_display);
|
||||
}
|
||||
|
||||
void Screen::OnDisplayRemoved(const display::Display& old_display) {
|
||||
void Screen::OnDisplayRemoved(const gfx::Display& old_display) {
|
||||
auto iter = FindById(&displays_, old_display.id());
|
||||
if (iter == displays_.end())
|
||||
return;
|
||||
|
||||
displays_.erase(iter);
|
||||
Emit("display-removed", old_display);
|
||||
}
|
||||
|
||||
void Screen::OnDisplayMetricsChanged(const display::Display& display,
|
||||
void Screen::OnDisplayMetricsChanged(const gfx::Display& display,
|
||||
uint32_t changed_metrics) {
|
||||
auto iter = FindById(&displays_, display.id());
|
||||
if (iter == displays_.end())
|
||||
return;
|
||||
|
||||
*iter = display;
|
||||
Emit("display-metrics-changed", display, MetricsToArray(changed_metrics));
|
||||
}
|
||||
|
||||
mate::ObjectTemplateBuilder Screen::GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) {
|
||||
return mate::ObjectTemplateBuilder(isolate)
|
||||
.SetMethod("getCursorScreenPoint", &Screen::GetCursorScreenPoint)
|
||||
.SetMethod("getPrimaryDisplay", &Screen::GetPrimaryDisplay)
|
||||
.SetMethod("getAllDisplays", &Screen::GetAllDisplays)
|
||||
.SetMethod("getDisplayNearestPoint", &Screen::GetDisplayNearestPoint)
|
||||
.SetMethod("getDisplayMatching", &Screen::GetDisplayMatching);
|
||||
}
|
||||
|
||||
// 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")));
|
||||
"Cannot initialize \"screen\" module before app is ready")));
|
||||
return v8::Null(isolate);
|
||||
}
|
||||
|
||||
display::Screen* screen = display::Screen::GetScreen();
|
||||
gfx::Screen* screen = gfx::Screen::GetNativeScreen();
|
||||
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);
|
||||
return mate::CreateHandle(isolate, new Screen(screen)).ToV8();
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
@@ -129,14 +135,10 @@ void Screen::BuildPrototype(
|
||||
|
||||
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());
|
||||
mate::Dictionary dict(context->GetIsolate(), exports);
|
||||
dict.Set("screen", atom::api::Screen::Create(context->GetIsolate()));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -9,8 +9,7 @@
|
||||
|
||||
#include "atom/browser/api/event_emitter.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "ui/display/display_observer.h"
|
||||
#include "ui/display/screen.h"
|
||||
#include "ui/gfx/display_observer.h"
|
||||
|
||||
namespace gfx {
|
||||
class Point;
|
||||
@@ -22,32 +21,34 @@ namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class Screen : public mate::EventEmitter<Screen>,
|
||||
public display::DisplayObserver {
|
||||
class Screen : public mate::EventEmitter,
|
||||
public gfx::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;
|
||||
explicit Screen(gfx::Screen* screen);
|
||||
virtual ~Screen();
|
||||
|
||||
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);
|
||||
gfx::Display GetPrimaryDisplay();
|
||||
std::vector<gfx::Display> GetAllDisplays();
|
||||
gfx::Display GetDisplayNearestPoint(const gfx::Point& point);
|
||||
gfx::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,
|
||||
// gfx::DisplayObserver:
|
||||
void OnDisplayAdded(const gfx::Display& new_display) override;
|
||||
void OnDisplayRemoved(const gfx::Display& old_display) override;
|
||||
void OnDisplayMetricsChanged(const gfx::Display& display,
|
||||
uint32_t changed_metrics) override;
|
||||
|
||||
// mate::Wrappable:
|
||||
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) override;
|
||||
|
||||
private:
|
||||
display::Screen* screen_;
|
||||
gfx::Screen* screen_;
|
||||
std::vector<gfx::Display> displays_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Screen);
|
||||
};
|
||||
|
||||
@@ -4,54 +4,39 @@
|
||||
|
||||
#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/api/atom_api_web_contents.h"
|
||||
#include "atom/browser/api/save_page_handler.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/file_path_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/prefs/pref_service.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 "base/thread_task_runner_handle.h"
|
||||
#include "brightray/browser/net/devtools_network_conditions.h"
|
||||
#include "brightray/browser/net/devtools_network_controller_handle.h"
|
||||
#include "brightray/browser/net/devtools_network_controller.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/proxy/proxy_config_service_fixed.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;
|
||||
|
||||
@@ -59,23 +44,14 @@ namespace {
|
||||
|
||||
struct ClearStorageDataOptions {
|
||||
GURL origin;
|
||||
uint32_t storage_types = StoragePartition::REMOVE_DATA_MASK_ALL;
|
||||
uint32_t quota_types = StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL;
|
||||
uint32 storage_types = StoragePartition::REMOVE_DATA_MASK_ALL;
|
||||
uint32 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;
|
||||
uint32 GetStorageMask(const std::vector<std::string>& storage_types) {
|
||||
uint32 storage_mask = 0;
|
||||
for (const auto& it : storage_types) {
|
||||
auto type = base::ToLowerASCII(it);
|
||||
auto type = base::StringToLowerASCII(it);
|
||||
if (type == "appcache")
|
||||
storage_mask |= StoragePartition::REMOVE_DATA_MASK_APPCACHE;
|
||||
else if (type == "cookies")
|
||||
@@ -96,10 +72,10 @@ uint32_t GetStorageMask(const std::vector<std::string>& storage_types) {
|
||||
return storage_mask;
|
||||
}
|
||||
|
||||
uint32_t GetQuotaMask(const std::vector<std::string>& quota_types) {
|
||||
uint32_t quota_mask = 0;
|
||||
uint32 GetQuotaMask(const std::vector<std::string>& quota_types) {
|
||||
uint32 quota_mask = 0;
|
||||
for (const auto& it : quota_types) {
|
||||
auto type = base::ToLowerASCII(it);
|
||||
auto type = base::StringToLowerASCII(it);
|
||||
if (type == "temporary")
|
||||
quota_mask |= StoragePartition::QUOTA_MANAGED_STORAGE_MASK_TEMPORARY;
|
||||
else if (type == "persistent")
|
||||
@@ -110,27 +86,6 @@ uint32_t GetQuotaMask(const std::vector<std::string>& quota_types) {
|
||||
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 {
|
||||
@@ -153,69 +108,24 @@ struct Converter<ClearStorageDataOptions> {
|
||||
}
|
||||
};
|
||||
|
||||
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 <>
|
||||
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 {
|
||||
std::string proxy;
|
||||
if (!ConvertFromV8(isolate, val, &proxy))
|
||||
return false;
|
||||
}
|
||||
|
||||
// pacScript takes precedence over proxyRules.
|
||||
if (!pac_url.is_empty() && pac_url.is_valid()) {
|
||||
auto pac_url = GURL(proxy);
|
||||
if (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);
|
||||
out->proxy_rules().ParseFromString(proxy);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Converter<atom::VerifyRequestParams> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
atom::VerifyRequestParams val) {
|
||||
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
|
||||
dict.Set("hostname", val.hostname);
|
||||
dict.Set("certificate", val.certificate);
|
||||
dict.Set("verificationResult", val.default_result);
|
||||
return dict.GetHandle();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
namespace atom {
|
||||
@@ -224,20 +134,19 @@ namespace api {
|
||||
|
||||
namespace {
|
||||
|
||||
const char kPersistPrefix[] = "persist:";
|
||||
|
||||
// Referenced session objects.
|
||||
std::map<uint32_t, v8::Global<v8::Object>> g_sessions;
|
||||
// The wrapSession funtion which is implemented in JavaScript
|
||||
using WrapSessionCallback = base::Callback<void(v8::Local<v8::Value>)>;
|
||||
WrapSessionCallback g_wrap_session;
|
||||
|
||||
class ResolveProxyHelper {
|
||||
public:
|
||||
ResolveProxyHelper(AtomBrowserContext* browser_context,
|
||||
const GURL& url,
|
||||
const Session::ResolveProxyCallback& callback)
|
||||
Session::ResolveProxyCallback callback)
|
||||
: callback_(callback),
|
||||
original_thread_(base::ThreadTaskRunnerHandle::Get()) {
|
||||
scoped_refptr<net::URLRequestContextGetter> context_getter =
|
||||
browser_context->url_request_context_getter();
|
||||
browser_context->GetRequestContext();
|
||||
context_getter->GetNetworkTaskRunner()->PostTask(
|
||||
FROM_HERE,
|
||||
base::Bind(&ResolveProxyHelper::ResolveProxy,
|
||||
@@ -266,8 +175,8 @@ class ResolveProxyHelper {
|
||||
|
||||
// Start the request.
|
||||
int result = proxy_service->ResolveProxy(
|
||||
url, "GET", &proxy_info_, completion_callback, &pac_req_, nullptr,
|
||||
net::NetLogWithSource());
|
||||
url, net::LOAD_NORMAL, &proxy_info_, completion_callback,
|
||||
&pac_req_, nullptr, net::BoundNetLog());
|
||||
|
||||
// Completed synchronously.
|
||||
if (result != net::ERR_IO_PENDING)
|
||||
@@ -283,10 +192,7 @@ class ResolveProxyHelper {
|
||||
};
|
||||
|
||||
// Runs the callback in UI thread.
|
||||
void RunCallbackInUI(const base::Callback<void()>& callback) {
|
||||
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
|
||||
}
|
||||
template<typename ...T>
|
||||
template <typename ...T>
|
||||
void RunCallbackInUI(const base::Callback<void(T...)>& callback, T... result) {
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::UI, FROM_HERE, base::Bind(callback, result...));
|
||||
@@ -294,35 +200,19 @@ void RunCallbackInUI(const base::Callback<void(T...)>& callback, T... 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
(*backend_ptr)->DoomAllEntries(base::Bind(&RunCallbackInUI<int>, callback));
|
||||
} else {
|
||||
RunCallbackInUI<int>(callback, net::ERR_FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
void DoCacheActionInIO(
|
||||
void ClearHttpCacheInIO(
|
||||
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();
|
||||
@@ -331,9 +221,9 @@ void DoCacheActionInIO(
|
||||
|
||||
// Call GetBackend and make the backend's ptr accessable in OnGetBackend.
|
||||
using BackendPtr = disk_cache::Backend*;
|
||||
auto* backend_ptr = new BackendPtr(nullptr);
|
||||
BackendPtr* backend_ptr = new BackendPtr(nullptr);
|
||||
net::CompletionCallback on_get_backend =
|
||||
base::Bind(&OnGetBackend, base::Owned(backend_ptr), action, callback);
|
||||
base::Bind(&OnGetBackend, base::Owned(backend_ptr), callback);
|
||||
int rv = http_cache->GetBackend(backend_ptr, on_get_backend);
|
||||
if (rv != net::ERR_IO_PENDING)
|
||||
on_get_backend.Run(net::OK);
|
||||
@@ -343,128 +233,37 @@ 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)));
|
||||
proxy_service->ResetConfigService(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->ClearEntriesAddedWithin(base::TimeDelta::Max());
|
||||
}
|
||||
} 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.
|
||||
Session::Session(AtomBrowserContext* browser_context)
|
||||
: browser_context_(browser_context) {
|
||||
AttachAsUserData(browser_context);
|
||||
|
||||
// Observe DownloadManger 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())
|
||||
auto web_contents = item->GetWebContents();
|
||||
if (SavePageHandler::IsSavePageTypes(item->GetMimeType()))
|
||||
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());
|
||||
bool prevent_default = Emit(
|
||||
"will-download",
|
||||
DownloadItem::Create(isolate(), item),
|
||||
api::WebContents::CreateFrom(isolate(), web_contents));
|
||||
if (prevent_default) {
|
||||
item->Cancel(true);
|
||||
item->Remove();
|
||||
@@ -475,40 +274,29 @@ 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) {
|
||||
void Session::ClearCache(const net::CompletionCallback& callback) {
|
||||
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&DoCacheActionInIO,
|
||||
base::Bind(&ClearHttpCacheInIO,
|
||||
make_scoped_refptr(browser_context_->GetRequestContext()),
|
||||
action,
|
||||
callback));
|
||||
}
|
||||
|
||||
void Session::ClearStorageData(mate::Arguments* args) {
|
||||
// clearStorageData([options, callback])
|
||||
// clearStorageData([options, ]callback)
|
||||
ClearStorageDataOptions options;
|
||||
base::Closure callback;
|
||||
args->GetNext(&options);
|
||||
args->GetNext(&callback);
|
||||
base::Closure callback;
|
||||
if (!args->GetNext(&callback)) {
|
||||
args->ThrowError();
|
||||
return;
|
||||
}
|
||||
|
||||
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();
|
||||
base::Time(), base::Time::Max(), callback);
|
||||
}
|
||||
|
||||
void Session::SetProxy(const net::ProxyConfig& config,
|
||||
@@ -524,9 +312,9 @@ void Session::SetDownloadPath(const base::FilePath& path) {
|
||||
}
|
||||
|
||||
void Session::EnableNetworkEmulation(const mate::Dictionary& options) {
|
||||
std::unique_ptr<brightray::DevToolsNetworkConditions> conditions;
|
||||
scoped_ptr<brightray::DevToolsNetworkConditions> conditions;
|
||||
bool offline = false;
|
||||
double latency = 0.0, download_throughput = 0.0, upload_throughput = 0.0;
|
||||
double latency, download_throughput, upload_throughput;
|
||||
if (options.Get("offline", &offline) && offline) {
|
||||
conditions.reset(new brightray::DevToolsNetworkConditions(offline));
|
||||
} else {
|
||||
@@ -539,19 +327,25 @@ void Session::EnableNetworkEmulation(const mate::Dictionary& options) {
|
||||
download_throughput,
|
||||
upload_throughput));
|
||||
}
|
||||
auto controller = browser_context_->GetDevToolsNetworkController();
|
||||
|
||||
browser_context_->network_controller_handle()->SetNetworkState(
|
||||
devtools_network_emulation_client_id_, std::move(conditions));
|
||||
browser_context_->network_delegate()->SetDevToolsNetworkEmulationClientId(
|
||||
devtools_network_emulation_client_id_);
|
||||
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&brightray::DevToolsNetworkController::SetNetworkState,
|
||||
base::Unretained(controller),
|
||||
std::string(),
|
||||
base::Passed(&conditions)));
|
||||
}
|
||||
|
||||
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());
|
||||
scoped_ptr<brightray::DevToolsNetworkConditions> conditions(
|
||||
new brightray::DevToolsNetworkConditions(false));
|
||||
auto controller = browser_context_->GetDevToolsNetworkController();
|
||||
|
||||
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&brightray::DevToolsNetworkController::SetNetworkState,
|
||||
base::Unretained(controller),
|
||||
std::string(),
|
||||
base::Passed(&conditions)));
|
||||
}
|
||||
|
||||
void Session::SetCertVerifyProc(v8::Local<v8::Value> val,
|
||||
@@ -562,144 +356,17 @@ void Session::SetCertVerifyProc(v8::Local<v8::Value> val,
|
||||
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)));
|
||||
browser_context_->cert_verifier()->SetVerifyProc(proc);
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> Session::Cookies(v8::Isolate* isolate) {
|
||||
if (cookies_.IsEmpty()) {
|
||||
auto handle = Cookies::Create(isolate, browser_context());
|
||||
auto handle = atom::api::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) {
|
||||
@@ -707,64 +374,45 @@ mate::Handle<Session> Session::CreateFrom(
|
||||
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());
|
||||
|
||||
auto handle = mate::CreateHandle(isolate, new Session(browser_context));
|
||||
g_wrap_session.Run(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());
|
||||
v8::Isolate* isolate, const std::string& partition, bool in_memory) {
|
||||
auto browser_context = brightray::BrowserContext::From(partition, in_memory);
|
||||
return CreateFrom(isolate,
|
||||
static_cast<AtomBrowserContext*>(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())
|
||||
v8::Local<v8::ObjectTemplate> prototype) {
|
||||
mate::ObjectTemplateBuilder(isolate, prototype)
|
||||
.MakeDestroyable()
|
||||
.SetMethod("resolveProxy", &Session::ResolveProxy)
|
||||
.SetMethod("getCacheSize", &Session::DoCacheAction<CacheAction::STATS>)
|
||||
.SetMethod("clearCache", &Session::DoCacheAction<CacheAction::CLEAR>)
|
||||
.SetMethod("clearCache", &Session::ClearCache)
|
||||
.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);
|
||||
.SetMethod("setCertificateVerifyProc", &Session::SetCertVerifyProc)
|
||||
.SetProperty("cookies", &Session::Cookies);
|
||||
}
|
||||
|
||||
void ClearWrapSession() {
|
||||
g_wrap_session.Reset();
|
||||
}
|
||||
|
||||
void SetWrapSession(const WrapSessionCallback& callback) {
|
||||
g_wrap_session = callback;
|
||||
|
||||
// Cleanup the wrapper on exit.
|
||||
atom::AtomBrowserMainParts::Get()->RegisterDestructionCallback(
|
||||
base::Bind(ClearWrapSession));
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
@@ -773,26 +421,12 @@ void Session::BuildPrototype(v8::Isolate* isolate,
|
||||
|
||||
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);
|
||||
dict.SetMethod("fromPartition", &atom::api::Session::FromPartition);
|
||||
dict.SetMethod("_setWrapSession", &atom::api::SetWrapSession);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
#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"
|
||||
@@ -40,53 +38,22 @@ class Session: public mate::TrackableObject<Session>,
|
||||
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|.
|
||||
// Gets the Session of |partition| and |in_memory|.
|
||||
static mate::Handle<Session> FromPartition(
|
||||
v8::Isolate* isolate, const std::string& partition,
|
||||
const base::DictionaryValue& options = base::DictionaryValue());
|
||||
v8::Isolate* isolate, const std::string& partition, bool in_memory);
|
||||
|
||||
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);
|
||||
v8::Local<v8::ObjectTemplate> prototype);
|
||||
|
||||
protected:
|
||||
Session(v8::Isolate* isolate, AtomBrowserContext* browser_context);
|
||||
explicit Session(AtomBrowserContext* browser_context);
|
||||
~Session();
|
||||
|
||||
// content::DownloadManager::Observer:
|
||||
@@ -94,13 +61,18 @@ class Session: public mate::TrackableObject<Session>,
|
||||
content::DownloadItem* item) override;
|
||||
|
||||
private:
|
||||
// Cached object.
|
||||
v8::Global<v8::Value> cookies_;
|
||||
v8::Global<v8::Value> protocol_;
|
||||
v8::Global<v8::Value> web_request_;
|
||||
void ResolveProxy(const GURL& url, ResolveProxyCallback callback);
|
||||
void ClearCache(const net::CompletionCallback& callback);
|
||||
void ClearStorageData(mate::Arguments* args);
|
||||
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);
|
||||
v8::Local<v8::Value> Cookies(v8::Isolate* isolate);
|
||||
|
||||
// The X-DevTools-Emulate-Network-Conditions-Client-Id.
|
||||
std::string devtools_network_emulation_client_id_;
|
||||
// Cached object for cookies API.
|
||||
v8::Global<v8::Value> cookies_;
|
||||
|
||||
scoped_refptr<AtomBrowserContext> browser_context_;
|
||||
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
// Copyright (c) 2016 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_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) {
|
||||
Init(isolate);
|
||||
#if defined(OS_WIN)
|
||||
InitializeWindow();
|
||||
#endif
|
||||
}
|
||||
|
||||
SystemPreferences::~SystemPreferences() {
|
||||
#if defined(OS_WIN)
|
||||
Browser::Get()->RemoveObserver(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
#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);
|
||||
@@ -1,129 +0,0 @@
|
||||
// Copyright (c) 2016 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_API_ATOM_API_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 "atom/browser/browser.h"
|
||||
#include "atom/browser/browser_observer.h"
|
||||
#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 BrowserObserver
|
||||
, 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;
|
||||
|
||||
// BrowserObserver:
|
||||
void OnFinishLaunching(const base::DictionaryValue& launch_info) 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_;
|
||||
|
||||
std::unique_ptr<gfx::ScopedSysColorChangeListener> color_change_listener_;
|
||||
#endif
|
||||
DISALLOW_COPY_AND_ASSIGN(SystemPreferences);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_SYSTEM_PREFERENCES_H_
|
||||
@@ -1,244 +0,0 @@
|
||||
// Copyright (c) 2016 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_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
|
||||
@@ -1,190 +0,0 @@
|
||||
// Copyright (c) 2014 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_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();
|
||||
|
||||
// Wait until app is ready before creating sys color listener
|
||||
// Creating this listener before the app is ready causes global shortcuts
|
||||
// to not fire
|
||||
if (Browser::Get()->is_ready())
|
||||
color_change_listener_.reset(new gfx::ScopedSysColorChangeListener(this));
|
||||
else
|
||||
Browser::Get()->AddObserver(this);
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
void SystemPreferences::OnFinishLaunching(
|
||||
const base::DictionaryValue& launch_info) {
|
||||
color_change_listener_.reset(new gfx::ScopedSysColorChangeListener(this));
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
@@ -8,94 +8,58 @@
|
||||
|
||||
#include "atom/browser/api/atom_api_menu.h"
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/common/api/atom_api_native_image.h"
|
||||
#include "atom/browser/ui/tray_icon.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 "base/threading/thread_task_runner_handle.h"
|
||||
#include "native_mate/constructor.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "ui/events/event_constants.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::Tray(const gfx::Image& image)
|
||||
: tray_icon_(TrayIcon::Create()) {
|
||||
SetImage(isolate, image);
|
||||
tray_icon_->SetImage(image);
|
||||
tray_icon_->AddObserver(this);
|
||||
|
||||
InitWith(isolate, wrapper);
|
||||
}
|
||||
|
||||
Tray::~Tray() {
|
||||
// Destroy the native tray in next tick.
|
||||
base::ThreadTaskRunnerHandle::Get()->DeleteSoon(
|
||||
FROM_HERE, tray_icon_.release());
|
||||
}
|
||||
|
||||
// static
|
||||
mate::WrappableBase* Tray::New(mate::Handle<NativeImage> image,
|
||||
mate::Arguments* args) {
|
||||
mate::Wrappable* Tray::New(v8::Isolate* isolate, const gfx::Image& image) {
|
||||
if (!Browser::Get()->is_ready()) {
|
||||
args->ThrowError("Cannot create Tray before app is ready");
|
||||
isolate->ThrowException(v8::Exception::Error(mate::StringToV8(
|
||||
isolate, "Cannot create Tray before app is ready")));
|
||||
return nullptr;
|
||||
}
|
||||
return new Tray(args->isolate(), args->GetThis(), image);
|
||||
return new Tray(image);
|
||||
}
|
||||
|
||||
void Tray::OnClicked(const gfx::Rect& bounds, int modifiers) {
|
||||
EmitWithFlags("click", modifiers, bounds);
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
EmitCustomEvent("click",
|
||||
ModifiersToObject(isolate(), modifiers), bounds);
|
||||
}
|
||||
|
||||
void Tray::OnDoubleClicked(const gfx::Rect& bounds, int modifiers) {
|
||||
EmitWithFlags("double-click", modifiers, bounds);
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
EmitCustomEvent("double-click",
|
||||
ModifiersToObject(isolate(), modifiers), bounds);
|
||||
}
|
||||
|
||||
void Tray::OnRightClicked(const gfx::Rect& bounds, int modifiers) {
|
||||
EmitWithFlags("right-click", modifiers, bounds);
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
EmitCustomEvent("right-click",
|
||||
ModifiersToObject(isolate(), modifiers), bounds);
|
||||
}
|
||||
|
||||
void Tray::OnBalloonShow() {
|
||||
@@ -118,10 +82,6 @@ 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");
|
||||
}
|
||||
@@ -134,38 +94,29 @@ 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::SetImage(mate::Arguments* args, const gfx::Image& image) {
|
||||
tray_icon_->SetImage(image);
|
||||
}
|
||||
|
||||
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::SetPressedImage(mate::Arguments* args, const gfx::Image& image) {
|
||||
tray_icon_->SetPressedImage(image);
|
||||
}
|
||||
|
||||
void Tray::SetToolTip(const std::string& tool_tip) {
|
||||
void Tray::SetToolTip(mate::Arguments* args, const std::string& tool_tip) {
|
||||
tray_icon_->SetToolTip(tool_tip);
|
||||
}
|
||||
|
||||
void Tray::SetTitle(const std::string& title) {
|
||||
void Tray::SetTitle(mate::Arguments* args, const std::string& title) {
|
||||
tray_icon_->SetTitle(title);
|
||||
}
|
||||
|
||||
void Tray::SetHighlightMode(TrayIcon::HighlightMode mode) {
|
||||
tray_icon_->SetHighlightMode(mode);
|
||||
void Tray::SetHighlightMode(mate::Arguments* args, bool highlight) {
|
||||
tray_icon_->SetHighlightMode(highlight);
|
||||
}
|
||||
|
||||
void Tray::DisplayBalloon(mate::Arguments* args,
|
||||
const mate::Dictionary& options) {
|
||||
mate::Handle<NativeImage> icon;
|
||||
gfx::Image icon;
|
||||
options.Get("icon", &icon);
|
||||
base::string16 title, content;
|
||||
if (!options.Get("title", &title) ||
|
||||
@@ -174,14 +125,7 @@ void Tray::DisplayBalloon(mate::Arguments* args,
|
||||
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
|
||||
tray_icon_->DisplayBalloon(icon, title, content);
|
||||
}
|
||||
|
||||
void Tray::PopUpContextMenu(mate::Arguments* args) {
|
||||
@@ -192,20 +136,24 @@ void Tray::PopUpContextMenu(mate::Arguments* args) {
|
||||
tray_icon_->PopUpContextMenu(pos, menu.IsEmpty() ? nullptr : menu->model());
|
||||
}
|
||||
|
||||
void Tray::SetContextMenu(v8::Isolate* isolate, mate::Handle<Menu> menu) {
|
||||
menu_.Reset(isolate, menu.ToV8());
|
||||
void Tray::SetContextMenu(mate::Arguments* args, Menu* menu) {
|
||||
tray_icon_->SetContextMenu(menu->model());
|
||||
}
|
||||
|
||||
gfx::Rect Tray::GetBounds() {
|
||||
return tray_icon_->GetBounds();
|
||||
v8::Local<v8::Object> Tray::ModifiersToObject(v8::Isolate* isolate,
|
||||
int modifiers) {
|
||||
mate::Dictionary obj(isolate, v8::Object::New(isolate));
|
||||
obj.Set("shiftKey", static_cast<bool>(modifiers & ui::EF_SHIFT_DOWN));
|
||||
obj.Set("ctrlKey", static_cast<bool>(modifiers & ui::EF_CONTROL_DOWN));
|
||||
obj.Set("altKey", static_cast<bool>(modifiers & ui::EF_ALT_DOWN));
|
||||
obj.Set("metaKey", static_cast<bool>(modifiers & ui::EF_COMMAND_DOWN));
|
||||
return obj.GetHandle();
|
||||
}
|
||||
|
||||
// static
|
||||
void Tray::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "Tray"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
v8::Local<v8::ObjectTemplate> prototype) {
|
||||
mate::ObjectTemplateBuilder(isolate, prototype)
|
||||
.MakeDestroyable()
|
||||
.SetMethod("setImage", &Tray::SetImage)
|
||||
.SetMethod("setPressedImage", &Tray::SetPressedImage)
|
||||
@@ -214,8 +162,7 @@ void Tray::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("setHighlightMode", &Tray::SetHighlightMode)
|
||||
.SetMethod("displayBalloon", &Tray::DisplayBalloon)
|
||||
.SetMethod("popUpContextMenu", &Tray::PopUpContextMenu)
|
||||
.SetMethod("setContextMenu", &Tray::SetContextMenu)
|
||||
.SetMethod("getBounds", &Tray::GetBounds);
|
||||
.SetMethod("_setContextMenu", &Tray::SetContextMenu);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
@@ -225,15 +172,14 @@ void Tray::BuildPrototype(v8::Isolate* isolate,
|
||||
|
||||
namespace {
|
||||
|
||||
using atom::api::Tray;
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
using atom::api::Tray;
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
Tray::SetConstructor(isolate, base::Bind(&Tray::New));
|
||||
|
||||
v8::Local<v8::Function> constructor = mate::CreateConstructor<Tray>(
|
||||
isolate, "Tray", base::Bind(&Tray::New));
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("Tray", Tray::GetConstructor(isolate)->GetFunction());
|
||||
dict.Set("Tray", static_cast<v8::Local<v8::Value>>(constructor));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -5,14 +5,12 @@
|
||||
#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"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
|
||||
namespace gfx {
|
||||
class Image;
|
||||
@@ -30,20 +28,17 @@ 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 mate::Wrappable* New(v8::Isolate* isolate, const gfx::Image& image);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
v8::Local<v8::ObjectTemplate> prototype);
|
||||
|
||||
protected:
|
||||
Tray(v8::Isolate* isolate, v8::Local<v8::Object> wrapper,
|
||||
mate::Handle<NativeImage> image);
|
||||
explicit Tray(const gfx::Image& image);
|
||||
~Tray() override;
|
||||
|
||||
// TrayIconObserver:
|
||||
@@ -55,24 +50,23 @@ class Tray : public mate::TrackableObject<Tray>,
|
||||
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 SetImage(mate::Arguments* args, const gfx::Image& image);
|
||||
void SetPressedImage(mate::Arguments* args, const gfx::Image& image);
|
||||
void SetToolTip(mate::Arguments* args, const std::string& tool_tip);
|
||||
void SetTitle(mate::Arguments* args, const std::string& title);
|
||||
void SetHighlightMode(mate::Arguments* args, bool highlight);
|
||||
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();
|
||||
void SetContextMenu(mate::Arguments* args, Menu* menu);
|
||||
|
||||
private:
|
||||
v8::Global<v8::Object> menu_;
|
||||
std::unique_ptr<TrayIcon> tray_icon_;
|
||||
v8::Local<v8::Object> ModifiersToObject(v8::Isolate* isolate, int modifiers);
|
||||
|
||||
scoped_ptr<TrayIcon> tray_icon_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Tray);
|
||||
};
|
||||
|
||||
@@ -1,481 +0,0 @@
|
||||
// Copyright (c) 2016 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_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/gurl_converter.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 redirect_policy;
|
||||
dict.Get("redirect", &redirect_policy);
|
||||
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, redirect_policy, 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("followRedirect", &URLRequest::FollowRedirect)
|
||||
.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();
|
||||
}
|
||||
|
||||
void URLRequest::FollowRedirect() {
|
||||
if (request_state_.Canceled() || request_state_.Closed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
DCHECK(atom_request_);
|
||||
if (atom_request_) {
|
||||
atom_request_->FollowRedirect();
|
||||
}
|
||||
}
|
||||
|
||||
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::OnReceivedRedirect(
|
||||
int status_code,
|
||||
const std::string& method,
|
||||
const GURL& url,
|
||||
scoped_refptr<net::HttpResponseHeaders> response_headers) {
|
||||
if (request_state_.Canceled() || request_state_.Closed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
DCHECK(atom_request_);
|
||||
if (!atom_request_) {
|
||||
return;
|
||||
}
|
||||
|
||||
EmitRequestEvent(false, "redirect", status_code, method, url,
|
||||
response_headers.get());
|
||||
}
|
||||
|
||||
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
|
||||
@@ -1,213 +0,0 @@
|
||||
// Copyright (c) 2016 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_API_ATOM_API_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 OnReceivedRedirect(
|
||||
int status_code,
|
||||
const std::string& method,
|
||||
const GURL& url,
|
||||
scoped_refptr<net::HttpResponseHeaders> response_headers);
|
||||
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();
|
||||
void FollowRedirect();
|
||||
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_
|
||||
File diff suppressed because it is too large
Load Diff
@@ -12,9 +12,6 @@
|
||||
#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/notification_observer.h"
|
||||
#include "content/public/browser/notification_registrar.h"
|
||||
#include "content/public/browser/web_contents_observer.h"
|
||||
#include "content/public/common/favicon_url.h"
|
||||
#include "native_mate/handle.h"
|
||||
@@ -28,10 +25,6 @@ namespace brightray {
|
||||
class InspectableWebContents;
|
||||
}
|
||||
|
||||
namespace content {
|
||||
class ResourceRequestBodyImpl;
|
||||
}
|
||||
|
||||
namespace mate {
|
||||
class Arguments;
|
||||
class Dictionary;
|
||||
@@ -41,25 +34,14 @@ namespace atom {
|
||||
|
||||
struct SetSizeParams;
|
||||
class AtomBrowserContext;
|
||||
class WebContentsZoomController;
|
||||
class WebViewGuestDelegate;
|
||||
|
||||
namespace api {
|
||||
|
||||
class WebContents : public mate::TrackableObject<WebContents>,
|
||||
public CommonWebContentsDelegate,
|
||||
public content::WebContentsObserver,
|
||||
public content::NotificationObserver {
|
||||
public content::WebContentsObserver {
|
||||
public:
|
||||
enum Type {
|
||||
BACKGROUND_PAGE, // A DevTools extension background page.
|
||||
BROWSER_WINDOW, // Used by BrowserWindow.
|
||||
BROWSER_VIEW, // Used by BrowserView.
|
||||
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>)>;
|
||||
@@ -67,48 +49,36 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
// 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);
|
||||
|
||||
// Notifies to destroy any guest web contents before destroying self.
|
||||
void DestroyWebContents(bool async);
|
||||
|
||||
int64_t GetID() const;
|
||||
int GetProcessID() const;
|
||||
Type GetType() const;
|
||||
int GetID() 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);
|
||||
const std::string GetWebRTCIPHandlingPolicy() const;
|
||||
void SetWebRTCIPHandlingPolicy(const std::string& webrtc_ip_handling_policy);
|
||||
bool IsCrashed() const;
|
||||
void SetUserAgent(const std::string& user_agent, mate::Arguments* args);
|
||||
void SetUserAgent(const std::string& user_agent);
|
||||
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 ExecuteJavaScript(const base::string16& code,
|
||||
bool has_user_gesture);
|
||||
void OpenDevTools(mate::Arguments* args);
|
||||
void CloseDevTools();
|
||||
bool IsDevToolsOpened();
|
||||
bool IsDevToolsFocused();
|
||||
void ToggleDevTools();
|
||||
void EnableDeviceEmulation(const blink::WebDeviceEmulationParams& params);
|
||||
void DisableDeviceEmulation();
|
||||
@@ -119,7 +89,6 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
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,
|
||||
@@ -141,68 +110,28 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
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,
|
||||
bool SendIPCMessage(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 BeginFrameSubscription(
|
||||
const FrameSubscriber::FrameCaptureCallback& callback);
|
||||
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);
|
||||
void SetAllowTransparency(bool allow);
|
||||
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();
|
||||
|
||||
// Methods for zoom handling.
|
||||
void SetZoomLevel(double level);
|
||||
double GetZoomLevel();
|
||||
void SetZoomFactor(double factor);
|
||||
double GetZoomFactor();
|
||||
|
||||
// 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<std::string>& features,
|
||||
const scoped_refptr<content::ResourceRequestBodyImpl>& body);
|
||||
|
||||
// Returns the web preferences of current WebContents.
|
||||
v8::Local<v8::Value> GetWebPreferences(v8::Isolate* isolate);
|
||||
|
||||
@@ -210,44 +139,33 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
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);
|
||||
|
||||
WebContentsZoomController* GetZoomController() { return zoom_controller_; }
|
||||
// mate::TrackableObject:
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::ObjectTemplate> prototype);
|
||||
|
||||
protected:
|
||||
WebContents(v8::Isolate* isolate,
|
||||
content::WebContents* web_contents,
|
||||
Type type);
|
||||
explicit WebContents(content::WebContents* web_contents);
|
||||
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 DidAddMessageToConsole(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_process_id,
|
||||
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;
|
||||
bool AddMessageToConsole(content::WebContents* source,
|
||||
int32 level,
|
||||
const base::string16& message,
|
||||
int32 line_no,
|
||||
const base::string16& source_id) override;
|
||||
bool ShouldCreateWebContents(
|
||||
content::WebContents* web_contents,
|
||||
int route_id,
|
||||
int main_frame_route_id,
|
||||
WindowContainerType window_container_type,
|
||||
const std::string& frame_name,
|
||||
const GURL& target_url,
|
||||
const std::string& partition_id,
|
||||
content::SessionStorageNamespace* session_storage_namespace) override;
|
||||
content::WebContents* OpenURLFromTab(
|
||||
content::WebContents* source,
|
||||
const content::OpenURLParams& params) override;
|
||||
@@ -258,48 +176,19 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
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,
|
||||
const content::WebContentsUnresponsiveState& unresponsive_state) 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(
|
||||
@@ -311,16 +200,21 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
int error_code,
|
||||
const base::string16& error_description,
|
||||
bool was_ignored_by_handler) override;
|
||||
void DidFailProvisionalLoad(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 DidStartNavigation(
|
||||
content::NavigationHandle* navigation_handle) override;
|
||||
void DidFinishNavigation(
|
||||
content::NavigationHandle* navigation_handle) override;
|
||||
void DidNavigateMainFrame(
|
||||
const content::LoadCommittedDetails& details,
|
||||
const content::FrameNavigateParams& params) override;
|
||||
bool OnMessageReceived(const IPC::Message& message) override;
|
||||
void WebContentsDestroyed() override;
|
||||
void NavigationEntryCommitted(
|
||||
@@ -330,20 +224,6 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
const std::vector<content::FaviconURL>& urls) override;
|
||||
void PluginCrashed(const base::FilePath& plugin_path,
|
||||
base::ProcessId plugin_pid) override;
|
||||
void MediaStartedPlaying(const MediaPlayerInfo& video_type,
|
||||
const MediaPlayerId& id) override;
|
||||
void MediaStoppedPlaying(const MediaPlayerInfo& video_type,
|
||||
const MediaPlayerId& id) override;
|
||||
void DidChangeThemeColor(SkColor theme_color) override;
|
||||
|
||||
// content::NotificationObserver:
|
||||
void Observe(int type,
|
||||
const content::NotificationSource& source,
|
||||
const content::NotificationDetails& details) override;
|
||||
void BeforeUnloadDialogCancelled() override;
|
||||
|
||||
// brightray::InspectableWebContentsDelegate:
|
||||
void DevToolsReloadPage() override;
|
||||
|
||||
// brightray::InspectableWebContentsViewDelegate:
|
||||
void DevToolsFocused() override;
|
||||
@@ -351,22 +231,14 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
void DevToolsClosed() override;
|
||||
|
||||
private:
|
||||
struct LoadURLParams {
|
||||
LoadURLParams() : params(GURL()), id(0) {}
|
||||
|
||||
content::NavigationController::LoadURLParams params;
|
||||
int id;
|
||||
enum Type {
|
||||
BROWSER_WINDOW, // Used by BrowserWindow.
|
||||
WEB_VIEW, // Used by <webview>.
|
||||
REMOTE, // Thin wrap around an existing WebContents.
|
||||
};
|
||||
|
||||
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);
|
||||
@@ -376,43 +248,18 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
const base::ListValue& args,
|
||||
IPC::Message* message);
|
||||
|
||||
// Called when received a synchronous message from renderer to
|
||||
// set temporary zoom level.
|
||||
void OnSetTemporaryZoomLevel(double level, IPC::Message* reply_msg);
|
||||
|
||||
// Called when received a synchronous message from renderer to
|
||||
// get the zoom level.
|
||||
void OnGetZoomLevel(IPC::Message* reply_msg);
|
||||
// Called when guests need to be notified of
|
||||
// embedders' zoom level change.
|
||||
void OnZoomLevelChanged(double level);
|
||||
|
||||
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 zoom controller for this webContents.
|
||||
WebContentsZoomController* zoom_controller_;
|
||||
scoped_ptr<WebViewGuestDelegate> guest_delegate_;
|
||||
|
||||
// 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_;
|
||||
|
||||
// Container to hold url parms for deferred load when
|
||||
// there is a pending navigation entry.
|
||||
LoadURLParams deferred_load_url_;
|
||||
content::NotificationRegistrar registrar_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(WebContents);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
// Copyright (c) 2016 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_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
|
||||
@@ -1,123 +0,0 @@
|
||||
// Copyright (c) 2015 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_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<URLPattern> {
|
||||
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
|
||||
URLPattern* out) {
|
||||
std::string pattern;
|
||||
if (!ConvertFromV8(isolate, val, &pattern))
|
||||
return false;
|
||||
*out = URLPattern(URLPattern::SCHEME_ALL);
|
||||
return out->Parse(pattern) == 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
|
||||
@@ -1,49 +0,0 @@
|
||||
// Copyright (c) 2015 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_API_ATOM_API_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_
|
||||
@@ -2,41 +2,59 @@
|
||||
// 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"
|
||||
#include "atom/browser/web_contents_preferences.h"
|
||||
#include "atom/browser/web_contents_zoom_controller.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 "atom/common/options_switches.h"
|
||||
#include "content/public/browser/browser_context.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
using atom::WebContentsPreferences;
|
||||
|
||||
namespace mate {
|
||||
|
||||
template<>
|
||||
struct Converter<content::WebContents*> {
|
||||
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
|
||||
content::WebContents** out) {
|
||||
atom::api::WebContents* contents;
|
||||
if (!Converter<atom::api::WebContents*>::FromV8(isolate, val, &contents))
|
||||
return false;
|
||||
*out = contents->web_contents();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
namespace {
|
||||
|
||||
atom::WebViewManager* GetWebViewManager(content::WebContents* web_contents) {
|
||||
auto context = web_contents->GetBrowserContext();
|
||||
if (context) {
|
||||
auto manager = context->GetGuestManager();
|
||||
return static_cast<atom::WebViewManager*>(manager);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
auto manager = GetWebViewManager(embedder);
|
||||
if (manager)
|
||||
manager->AddGuest(guest_instance_id, element_instance_id, embedder,
|
||||
guest_web_contents);
|
||||
|
||||
double zoom_factor;
|
||||
if (options.GetDouble(atom::options::kZoomFactor, &zoom_factor)) {
|
||||
atom::WebContentsZoomController::FromWebContents(guest_web_contents)
|
||||
->SetDefaultZoomFactor(zoom_factor);
|
||||
}
|
||||
|
||||
WebContentsPreferences::FromWebContents(guest_web_contents)->Merge(options);
|
||||
}
|
||||
|
||||
void RemoveGuest(content::WebContents* embedder, int guest_instance_id) {
|
||||
auto manager = atom::WebViewManager::GetWebViewManager(embedder);
|
||||
auto manager = GetWebViewManager(embedder);
|
||||
if (manager)
|
||||
manager->RemoveGuest(guest_instance_id);
|
||||
}
|
||||
|
||||
@@ -5,37 +5,27 @@
|
||||
#include "atom/browser/api/atom_api_window.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
|
||||
#include "atom/browser/api/atom_api_browser_view.h"
|
||||
#include "atom/browser/api/atom_api_menu.h"
|
||||
#include "atom/browser/api/atom_api_web_contents.h"
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/browser/native_window.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/gfx_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/string16_converter.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "atom/common/options_switches.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/threading/thread_task_runner_handle.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
#include "content/public/common/content_switches.h"
|
||||
#include "native_mate/constructor.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "ui/gfx/geometry/rect.h"
|
||||
|
||||
#if defined(TOOLKIT_VIEWS)
|
||||
#include "atom/browser/native_window_views.h"
|
||||
#endif
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include "atom/browser/native_window_views.h"
|
||||
#include "atom/browser/ui/win/taskbar_host.h"
|
||||
#include "ui/base/win/shell.h"
|
||||
#endif
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
namespace mate {
|
||||
|
||||
@@ -62,90 +52,108 @@ namespace api {
|
||||
|
||||
namespace {
|
||||
|
||||
void OnCapturePageDone(
|
||||
v8::Isolate* isolate,
|
||||
const base::Callback<void(const gfx::Image&)>& callback,
|
||||
const SkBitmap& bitmap) {
|
||||
v8::Locker locker(isolate);
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
callback.Run(gfx::Image::CreateFrom1xBitmap(bitmap));
|
||||
}
|
||||
|
||||
// Converts min-width to minWidth, returns false if no conversion is needed.
|
||||
bool TranslateOldKey(const std::string& key, std::string* new_key) {
|
||||
if (key.find('-') == std::string::npos)
|
||||
return false;
|
||||
new_key->reserve(key.size());
|
||||
bool next_upper_case = false;
|
||||
for (char c : key) {
|
||||
if (c == '-') {
|
||||
next_upper_case = true;
|
||||
} else if (next_upper_case) {
|
||||
new_key->push_back(base::ToUpperASCII(c));
|
||||
next_upper_case = false;
|
||||
} else {
|
||||
new_key->push_back(c);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Converts min-width to minWidth recursively in the dictionary.
|
||||
void TranslateOldOptions(v8::Isolate* isolate, v8::Local<v8::Object> options) {
|
||||
auto context = isolate->GetCurrentContext();
|
||||
auto maybe_keys = options->GetOwnPropertyNames(context);
|
||||
if (maybe_keys.IsEmpty())
|
||||
return;
|
||||
std::vector<std::string> keys;
|
||||
if (!mate::ConvertFromV8(isolate, maybe_keys.ToLocalChecked(), &keys))
|
||||
return;
|
||||
mate::Dictionary dict(isolate, options);
|
||||
for (const auto& key : keys) {
|
||||
v8::Local<v8::Value> value;
|
||||
if (!dict.Get(key, &value)) // Shouldn't happen, but guard it anyway.
|
||||
continue;
|
||||
// Go recursively.
|
||||
v8::Local<v8::Object> sub_options;
|
||||
if (mate::ConvertFromV8(isolate, value, &sub_options))
|
||||
TranslateOldOptions(isolate, sub_options);
|
||||
// Translate key.
|
||||
std::string new_key;
|
||||
if (TranslateOldKey(key, &new_key)) {
|
||||
dict.Set(new_key, value);
|
||||
dict.Delete(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// Converts binary data to Buffer.
|
||||
v8::Local<v8::Value> ToBuffer(v8::Isolate* isolate, void* val, int size) {
|
||||
auto buffer = node::Buffer::Copy(isolate, static_cast<char*>(val), size);
|
||||
auto buffer = node::Buffer::New(isolate, static_cast<char*>(val), size);
|
||||
if (buffer.IsEmpty())
|
||||
return v8::Null(isolate);
|
||||
else
|
||||
return buffer.ToLocalChecked();
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
Window::Window(v8::Isolate* isolate, v8::Local<v8::Object> wrapper,
|
||||
const mate::Dictionary& options) {
|
||||
mate::Handle<class WebContents> web_contents;
|
||||
// If no WebContents was passed to the constructor, create it from options.
|
||||
if (!options.Get("webContents", &web_contents)) {
|
||||
// Use options.webPreferences to create WebContents.
|
||||
mate::Dictionary web_preferences = mate::Dictionary::CreateEmpty(isolate);
|
||||
options.Get(options::kWebPreferences, &web_preferences);
|
||||
Window::Window(v8::Isolate* isolate, const mate::Dictionary& options) {
|
||||
// Be compatible with old style field names like min-width.
|
||||
TranslateOldOptions(isolate, options.GetHandle());
|
||||
|
||||
// Copy the backgroundColor to webContents.
|
||||
v8::Local<v8::Value> value;
|
||||
if (options.Get(options::kBackgroundColor, &value))
|
||||
web_preferences.Set(options::kBackgroundColor, value);
|
||||
// Use options.webPreferences to create WebContents.
|
||||
mate::Dictionary web_preferences = mate::Dictionary::CreateEmpty(isolate);
|
||||
options.Get(options::kWebPreferences, &web_preferences);
|
||||
|
||||
v8::Local<v8::Value> transparent;
|
||||
if (options.Get("transparent", &transparent))
|
||||
web_preferences.Set("transparent", transparent);
|
||||
// Be compatible with old options which are now in web_preferences.
|
||||
v8::Local<v8::Value> value;
|
||||
if (options.Get(options::kNodeIntegration, &value))
|
||||
web_preferences.Set(options::kNodeIntegration, value);
|
||||
if (options.Get(options::kPreloadScript, &value))
|
||||
web_preferences.Set(options::kPreloadScript, value);
|
||||
if (options.Get(options::kZoomFactor, &value))
|
||||
web_preferences.Set(options::kZoomFactor, value);
|
||||
|
||||
// Offscreen windows are always created frameless.
|
||||
bool offscreen;
|
||||
if (web_preferences.Get("offscreen", &offscreen) && offscreen) {
|
||||
auto window_options = const_cast<mate::Dictionary&>(options);
|
||||
window_options.Set(options::kFrame, false);
|
||||
}
|
||||
|
||||
// Creates the WebContents used by BrowserWindow.
|
||||
web_contents = WebContents::Create(isolate, web_preferences);
|
||||
}
|
||||
|
||||
Init(isolate, wrapper, options, web_contents);
|
||||
}
|
||||
|
||||
void Window::Init(v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> wrapper,
|
||||
const mate::Dictionary& options,
|
||||
mate::Handle<class WebContents> web_contents) {
|
||||
// Creates the WebContents used by BrowserWindow.
|
||||
auto web_contents = WebContents::Create(isolate, web_preferences);
|
||||
web_contents_.Reset(isolate, web_contents.ToV8());
|
||||
api_web_contents_ = web_contents.get();
|
||||
|
||||
// Keep a copy of the options for later use.
|
||||
mate::Dictionary(isolate, web_contents->GetWrapper()).Set(
|
||||
mate::Dictionary(isolate, web_contents->GetWrapper(isolate)).Set(
|
||||
"browserWindowOptions", options);
|
||||
|
||||
// The parent window.
|
||||
mate::Handle<Window> parent;
|
||||
if (options.Get("parent", &parent))
|
||||
parent_window_.Reset(isolate, parent.ToV8());
|
||||
|
||||
// Creates BrowserWindow.
|
||||
window_.reset(NativeWindow::Create(
|
||||
web_contents->managed_web_contents(),
|
||||
options,
|
||||
parent.IsEmpty() ? nullptr : parent->window_.get()));
|
||||
window_.reset(NativeWindow::Create(web_contents->managed_web_contents(),
|
||||
options));
|
||||
web_contents->SetOwnerWindow(window_.get());
|
||||
|
||||
#if defined(TOOLKIT_VIEWS)
|
||||
// Sets the window icon.
|
||||
mate::Handle<NativeImage> icon;
|
||||
if (options.Get(options::kIcon, &icon))
|
||||
SetIcon(icon);
|
||||
#endif
|
||||
|
||||
window_->InitFromOptions(options);
|
||||
window_->AddObserver(this);
|
||||
|
||||
InitWith(isolate, wrapper);
|
||||
AttachAsUserData(window_.get());
|
||||
|
||||
// We can only append this window to parent window's child windows after this
|
||||
// window's JS wrapper gets initialized.
|
||||
if (!parent.IsEmpty())
|
||||
parent->child_windows_.Set(isolate, ID(), wrapper);
|
||||
}
|
||||
|
||||
Window::~Window() {
|
||||
@@ -154,26 +162,15 @@ Window::~Window() {
|
||||
|
||||
// Destroy the native window in next tick because the native code might be
|
||||
// iterating all windows.
|
||||
base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, window_.release());
|
||||
base::MessageLoop::current()->DeleteSoon(FROM_HERE, window_.release());
|
||||
}
|
||||
|
||||
void Window::WillCloseWindow(bool* prevent_default) {
|
||||
*prevent_default = Emit("close");
|
||||
}
|
||||
|
||||
void Window::WillDestroyNativeObject() {
|
||||
// Close all child windows before closing current window.
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
for (v8::Local<v8::Value> value : child_windows_.Values(isolate())) {
|
||||
mate::Handle<Window> child;
|
||||
if (mate::ConvertFromV8(isolate(), value, &child))
|
||||
child->window_->CloseImmediately();
|
||||
}
|
||||
}
|
||||
|
||||
void Window::OnWindowClosed() {
|
||||
api_web_contents_->DestroyWebContents(true /* async */);
|
||||
api_web_contents_->DestroyWebContents();
|
||||
|
||||
RemoveFromWeakMap();
|
||||
window_->RemoveObserver(this);
|
||||
@@ -184,15 +181,8 @@ void Window::OnWindowClosed() {
|
||||
|
||||
Emit("closed");
|
||||
|
||||
RemoveFromParentChildWindows();
|
||||
|
||||
// Destroy the native class when window is closed.
|
||||
base::ThreadTaskRunnerHandle::Get()->PostTask(
|
||||
FROM_HERE, GetDestroyClosure());
|
||||
}
|
||||
|
||||
void Window::OnWindowEndSession() {
|
||||
Emit("session-end");
|
||||
base::MessageLoop::current()->PostTask(FROM_HERE, GetDestroyClosure());
|
||||
}
|
||||
|
||||
void Window::OnWindowBlur() {
|
||||
@@ -203,18 +193,6 @@ void Window::OnWindowFocus() {
|
||||
Emit("focus");
|
||||
}
|
||||
|
||||
void Window::OnWindowShow() {
|
||||
Emit("show");
|
||||
}
|
||||
|
||||
void Window::OnWindowHide() {
|
||||
Emit("hide");
|
||||
}
|
||||
|
||||
void Window::OnReadyToShow() {
|
||||
Emit("ready-to-show");
|
||||
}
|
||||
|
||||
void Window::OnWindowMaximize() {
|
||||
Emit("maximize");
|
||||
}
|
||||
@@ -251,30 +229,6 @@ void Window::OnWindowLeaveFullScreen() {
|
||||
Emit("leave-full-screen");
|
||||
}
|
||||
|
||||
void Window::OnWindowScrollTouchBegin() {
|
||||
Emit("scroll-touch-begin");
|
||||
}
|
||||
|
||||
void Window::OnWindowScrollTouchEnd() {
|
||||
Emit("scroll-touch-end");
|
||||
}
|
||||
|
||||
void Window::OnWindowScrollTouchEdge() {
|
||||
Emit("scroll-touch-edge");
|
||||
}
|
||||
|
||||
void Window::OnWindowSwipe(const std::string& direction) {
|
||||
Emit("swipe", direction);
|
||||
}
|
||||
|
||||
void Window::OnWindowSheetBegin() {
|
||||
Emit("sheet-begin");
|
||||
}
|
||||
|
||||
void Window::OnWindowSheetEnd() {
|
||||
Emit("sheet-end");
|
||||
}
|
||||
|
||||
void Window::OnWindowEnterHtmlFullScreen() {
|
||||
Emit("enter-html-full-screen");
|
||||
}
|
||||
@@ -295,11 +249,6 @@ void Window::OnExecuteWindowsCommand(const std::string& command_name) {
|
||||
Emit("app-command", command_name);
|
||||
}
|
||||
|
||||
void Window::OnTouchBarItemResult(const std::string& item_id,
|
||||
const base::DictionaryValue& details) {
|
||||
Emit("-touch-bar-interaction", item_id, details);
|
||||
}
|
||||
|
||||
#if defined(OS_WIN)
|
||||
void Window::OnWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) {
|
||||
if (IsWindowMessageHooked(message)) {
|
||||
@@ -311,9 +260,10 @@ void Window::OnWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) {
|
||||
#endif
|
||||
|
||||
// static
|
||||
mate::WrappableBase* Window::New(mate::Arguments* args) {
|
||||
mate::Wrappable* Window::New(v8::Isolate* isolate, mate::Arguments* args) {
|
||||
if (!Browser::Get()->is_ready()) {
|
||||
args->ThrowError("Cannot create BrowserWindow before app is ready");
|
||||
isolate->ThrowException(v8::Exception::Error(mate::StringToV8(
|
||||
isolate, "Cannot create BrowserWindow before app is ready")));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -324,10 +274,10 @@ mate::WrappableBase* Window::New(mate::Arguments* args) {
|
||||
|
||||
mate::Dictionary options;
|
||||
if (!(args->Length() == 1 && args->GetNext(&options))) {
|
||||
options = mate::Dictionary::CreateEmpty(args->isolate());
|
||||
options = mate::Dictionary::CreateEmpty(isolate);
|
||||
}
|
||||
|
||||
return new Window(args->isolate(), args->GetThis(), options);
|
||||
return new Window(isolate, options);
|
||||
}
|
||||
|
||||
void Window::Close() {
|
||||
@@ -338,10 +288,6 @@ void Window::Focus() {
|
||||
window_->Focus(true);
|
||||
}
|
||||
|
||||
void Window::Blur() {
|
||||
window_->Focus(false);
|
||||
}
|
||||
|
||||
bool Window::IsFocused() {
|
||||
return window_->IsFocused();
|
||||
}
|
||||
@@ -351,10 +297,6 @@ void Window::Show() {
|
||||
}
|
||||
|
||||
void Window::ShowInactive() {
|
||||
// This method doesn't make sense for modal window..
|
||||
if (IsModal())
|
||||
return;
|
||||
|
||||
window_->ShowInactive();
|
||||
}
|
||||
|
||||
@@ -366,10 +308,6 @@ bool Window::IsVisible() {
|
||||
return window_->IsVisible();
|
||||
}
|
||||
|
||||
bool Window::IsEnabled() {
|
||||
return window_->IsEnabled();
|
||||
}
|
||||
|
||||
void Window::Maximize() {
|
||||
window_->Maximize();
|
||||
}
|
||||
@@ -402,30 +340,16 @@ bool Window::IsFullscreen() {
|
||||
return window_->IsFullscreen();
|
||||
}
|
||||
|
||||
void Window::SetBounds(const gfx::Rect& bounds, mate::Arguments* args) {
|
||||
bool animate = false;
|
||||
args->GetNext(&animate);
|
||||
window_->SetBounds(bounds, animate);
|
||||
void Window::SetBounds(const gfx::Rect& bounds) {
|
||||
window_->SetBounds(bounds);
|
||||
}
|
||||
|
||||
gfx::Rect Window::GetBounds() {
|
||||
return window_->GetBounds();
|
||||
}
|
||||
|
||||
void Window::SetContentBounds(const gfx::Rect& bounds, mate::Arguments* args) {
|
||||
bool animate = false;
|
||||
args->GetNext(&animate);
|
||||
window_->SetContentBounds(bounds, animate);
|
||||
}
|
||||
|
||||
gfx::Rect Window::GetContentBounds() {
|
||||
return window_->GetContentBounds();
|
||||
}
|
||||
|
||||
void Window::SetSize(int width, int height, mate::Arguments* args) {
|
||||
bool animate = false;
|
||||
args->GetNext(&animate);
|
||||
window_->SetSize(gfx::Size(width, height), animate);
|
||||
void Window::SetSize(int width, int height) {
|
||||
window_->SetSize(gfx::Size(width, height));
|
||||
}
|
||||
|
||||
std::vector<int> Window::GetSize() {
|
||||
@@ -436,10 +360,8 @@ std::vector<int> Window::GetSize() {
|
||||
return result;
|
||||
}
|
||||
|
||||
void Window::SetContentSize(int width, int height, mate::Arguments* args) {
|
||||
bool animate = false;
|
||||
args->GetNext(&animate);
|
||||
window_->SetContentSize(gfx::Size(width, height), animate);
|
||||
void Window::SetContentSize(int width, int height) {
|
||||
window_->SetContentSize(gfx::Size(width, height));
|
||||
}
|
||||
|
||||
std::vector<int> Window::GetContentSize() {
|
||||
@@ -474,12 +396,6 @@ std::vector<int> Window::GetMaximumSize() {
|
||||
return result;
|
||||
}
|
||||
|
||||
void Window::SetSheetOffset(double offsetY, mate::Arguments* args) {
|
||||
double offsetX = 0.0;
|
||||
args->GetNext(&offsetX);
|
||||
window_->SetSheetOffset(offsetX, offsetY);
|
||||
}
|
||||
|
||||
void Window::SetResizable(bool resizable) {
|
||||
window_->SetResizable(resizable);
|
||||
}
|
||||
@@ -488,59 +404,8 @@ bool Window::IsResizable() {
|
||||
return window_->IsResizable();
|
||||
}
|
||||
|
||||
void Window::SetMovable(bool movable) {
|
||||
window_->SetMovable(movable);
|
||||
}
|
||||
|
||||
bool Window::IsMovable() {
|
||||
return window_->IsMovable();
|
||||
}
|
||||
|
||||
void Window::SetMinimizable(bool minimizable) {
|
||||
window_->SetMinimizable(minimizable);
|
||||
}
|
||||
|
||||
bool Window::IsMinimizable() {
|
||||
return window_->IsMinimizable();
|
||||
}
|
||||
|
||||
void Window::SetMaximizable(bool maximizable) {
|
||||
window_->SetMaximizable(maximizable);
|
||||
}
|
||||
|
||||
bool Window::IsMaximizable() {
|
||||
return window_->IsMaximizable();
|
||||
}
|
||||
|
||||
void Window::SetFullScreenable(bool fullscreenable) {
|
||||
window_->SetFullScreenable(fullscreenable);
|
||||
}
|
||||
|
||||
bool Window::IsFullScreenable() {
|
||||
return window_->IsFullScreenable();
|
||||
}
|
||||
|
||||
void Window::SetClosable(bool closable) {
|
||||
window_->SetClosable(closable);
|
||||
}
|
||||
|
||||
bool Window::IsClosable() {
|
||||
return window_->IsClosable();
|
||||
}
|
||||
|
||||
void Window::SetAlwaysOnTop(bool top, mate::Arguments* args) {
|
||||
std::string level = "floating";
|
||||
int relativeLevel = 0;
|
||||
std::string error;
|
||||
|
||||
args->GetNext(&level);
|
||||
args->GetNext(&relativeLevel);
|
||||
|
||||
window_->SetAlwaysOnTop(top, level, relativeLevel, &error);
|
||||
|
||||
if (!error.empty()) {
|
||||
args->ThrowError(error);
|
||||
}
|
||||
void Window::SetAlwaysOnTop(bool top) {
|
||||
window_->SetAlwaysOnTop(top);
|
||||
}
|
||||
|
||||
bool Window::IsAlwaysOnTop() {
|
||||
@@ -551,10 +416,8 @@ void Window::Center() {
|
||||
window_->Center();
|
||||
}
|
||||
|
||||
void Window::SetPosition(int x, int y, mate::Arguments* args) {
|
||||
bool animate = false;
|
||||
args->GetNext(&animate);
|
||||
window_->SetPosition(gfx::Point(x, y), animate);
|
||||
void Window::SetPosition(int x, int y) {
|
||||
window_->SetPosition(gfx::Point(x, y));
|
||||
}
|
||||
|
||||
std::vector<int> Window::GetPosition() {
|
||||
@@ -593,14 +456,6 @@ void Window::SetBackgroundColor(const std::string& color_name) {
|
||||
window_->SetBackgroundColor(color_name);
|
||||
}
|
||||
|
||||
void Window::SetHasShadow(bool has_shadow) {
|
||||
window_->SetHasShadow(has_shadow);
|
||||
}
|
||||
|
||||
bool Window::HasShadow() {
|
||||
return window_->HasShadow();
|
||||
}
|
||||
|
||||
void Window::FocusOnWebView() {
|
||||
window_->FocusOnWebView();
|
||||
}
|
||||
@@ -613,6 +468,10 @@ bool Window::IsWebViewFocused() {
|
||||
return window_->IsWebViewFocused();
|
||||
}
|
||||
|
||||
bool Window::IsDevToolsFocused() {
|
||||
return window_->IsDevToolsFocused();
|
||||
}
|
||||
|
||||
void Window::SetRepresentedFilename(const std::string& filename) {
|
||||
window_->SetRepresentedFilename(filename);
|
||||
}
|
||||
@@ -629,36 +488,23 @@ bool Window::IsDocumentEdited() {
|
||||
return window_->IsDocumentEdited();
|
||||
}
|
||||
|
||||
void Window::SetIgnoreMouseEvents(bool ignore) {
|
||||
return window_->SetIgnoreMouseEvents(ignore);
|
||||
}
|
||||
void Window::CapturePage(mate::Arguments* args) {
|
||||
gfx::Rect rect;
|
||||
base::Callback<void(const gfx::Image&)> callback;
|
||||
|
||||
void Window::SetContentProtection(bool enable) {
|
||||
return window_->SetContentProtection(enable);
|
||||
}
|
||||
|
||||
void Window::SetFocusable(bool focusable) {
|
||||
return window_->SetFocusable(focusable);
|
||||
}
|
||||
|
||||
void Window::SetProgressBar(double progress, mate::Arguments* args) {
|
||||
mate::Dictionary options;
|
||||
std::string mode;
|
||||
NativeWindow::ProgressState state = NativeWindow::PROGRESS_NORMAL;
|
||||
|
||||
args->GetNext(&options) && options.Get("mode", &mode);
|
||||
|
||||
if (mode == "error") {
|
||||
state = NativeWindow::PROGRESS_ERROR;
|
||||
} else if (mode == "paused") {
|
||||
state = NativeWindow::PROGRESS_PAUSED;
|
||||
} else if (mode == "indeterminate") {
|
||||
state = NativeWindow::PROGRESS_INDETERMINATE;
|
||||
} else if (mode == "none") {
|
||||
state = NativeWindow::PROGRESS_NONE;
|
||||
if (!(args->Length() == 1 && args->GetNext(&callback)) &&
|
||||
!(args->Length() == 2 && args->GetNext(&rect)
|
||||
&& args->GetNext(&callback))) {
|
||||
args->ThrowError();
|
||||
return;
|
||||
}
|
||||
|
||||
window_->SetProgressBar(progress, state);
|
||||
window_->CapturePage(
|
||||
rect, base::Bind(&OnCapturePageDone, args->isolate(), callback));
|
||||
}
|
||||
|
||||
void Window::SetProgressBar(double progress) {
|
||||
window_->SetProgressBar(progress);
|
||||
}
|
||||
|
||||
void Window::SetOverlayIcon(const gfx::Image& overlay,
|
||||
@@ -675,7 +521,7 @@ bool Window::SetThumbarButtons(mate::Arguments* args) {
|
||||
}
|
||||
auto window = static_cast<NativeWindowViews*>(window_.get());
|
||||
return window->taskbar_host().SetThumbarButtons(
|
||||
window_->GetAcceleratedWidget(), buttons);
|
||||
window->GetAcceleratedWidget(), buttons);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
@@ -734,49 +580,11 @@ bool Window::IsWindowMessageHooked(UINT message) {
|
||||
void Window::UnhookAllWindowMessages() {
|
||||
messages_callback_map_.clear();
|
||||
}
|
||||
|
||||
bool Window::SetThumbnailClip(const gfx::Rect& region) {
|
||||
auto window = static_cast<NativeWindowViews*>(window_.get());
|
||||
return window->taskbar_host().SetThumbnailClip(
|
||||
window_->GetAcceleratedWidget(), region);
|
||||
}
|
||||
|
||||
bool Window::SetThumbnailToolTip(const std::string& tooltip) {
|
||||
auto window = static_cast<NativeWindowViews*>(window_.get());
|
||||
return window->taskbar_host().SetThumbnailToolTip(
|
||||
window_->GetAcceleratedWidget(), tooltip);
|
||||
}
|
||||
|
||||
void Window::SetAppDetails(const mate::Dictionary& options) {
|
||||
base::string16 app_id;
|
||||
base::FilePath app_icon_path;
|
||||
int app_icon_index = 0;
|
||||
base::string16 relaunch_command;
|
||||
base::string16 relaunch_display_name;
|
||||
|
||||
options.Get("appId", &app_id);
|
||||
options.Get("appIconPath", &app_icon_path);
|
||||
options.Get("appIconIndex", &app_icon_index);
|
||||
options.Get("relaunchCommand", &relaunch_command);
|
||||
options.Get("relaunchDisplayName", &relaunch_display_name);
|
||||
|
||||
ui::win::SetAppDetailsForWindow(
|
||||
app_id, app_icon_path, app_icon_index,
|
||||
relaunch_command, relaunch_display_name,
|
||||
window_->GetAcceleratedWidget());
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(TOOLKIT_VIEWS)
|
||||
void Window::SetIcon(mate::Handle<NativeImage> icon) {
|
||||
#if defined(OS_WIN)
|
||||
static_cast<NativeWindowViews*>(window_.get())->SetIcon(
|
||||
icon->GetHICON(GetSystemMetrics(SM_CXSMICON)),
|
||||
icon->GetHICON(GetSystemMetrics(SM_CXICON)));
|
||||
#elif defined(USE_X11)
|
||||
static_cast<NativeWindowViews*>(window_.get())->SetIcon(
|
||||
icon->image().AsImageSkia());
|
||||
#endif
|
||||
#if defined(OS_MACOSX)
|
||||
void Window::ShowDefinitionForSelection() {
|
||||
window_->ShowDefinitionForSelection();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -786,78 +594,6 @@ void Window::SetAspectRatio(double aspect_ratio, mate::Arguments* args) {
|
||||
window_->SetAspectRatio(aspect_ratio, extra_size);
|
||||
}
|
||||
|
||||
void Window::PreviewFile(const std::string& path, mate::Arguments* args) {
|
||||
std::string display_name;
|
||||
if (!args->GetNext(&display_name))
|
||||
display_name = path;
|
||||
window_->PreviewFile(path, display_name);
|
||||
}
|
||||
|
||||
void Window::CloseFilePreview() {
|
||||
window_->CloseFilePreview();
|
||||
}
|
||||
|
||||
void Window::SetParentWindow(v8::Local<v8::Value> value,
|
||||
mate::Arguments* args) {
|
||||
if (IsModal()) {
|
||||
args->ThrowError("Can not be called for modal window");
|
||||
return;
|
||||
}
|
||||
|
||||
mate::Handle<Window> parent;
|
||||
if (value->IsNull()) {
|
||||
RemoveFromParentChildWindows();
|
||||
parent_window_.Reset();
|
||||
window_->SetParentWindow(nullptr);
|
||||
} else if (mate::ConvertFromV8(isolate(), value, &parent)) {
|
||||
parent_window_.Reset(isolate(), value);
|
||||
window_->SetParentWindow(parent->window_.get());
|
||||
parent->child_windows_.Set(isolate(), ID(), GetWrapper());
|
||||
} else {
|
||||
args->ThrowError("Must pass BrowserWindow instance or null");
|
||||
}
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> Window::GetParentWindow() const {
|
||||
if (parent_window_.IsEmpty())
|
||||
return v8::Null(isolate());
|
||||
else
|
||||
return v8::Local<v8::Value>::New(isolate(), parent_window_);
|
||||
}
|
||||
|
||||
std::vector<v8::Local<v8::Object>> Window::GetChildWindows() const {
|
||||
return child_windows_.Values(isolate());
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> Window::GetBrowserView() const {
|
||||
if (browser_view_.IsEmpty()) {
|
||||
return v8::Null(isolate());
|
||||
}
|
||||
|
||||
return v8::Local<v8::Value>::New(isolate(), browser_view_);
|
||||
}
|
||||
|
||||
void Window::SetBrowserView(v8::Local<v8::Value> value) {
|
||||
mate::Handle<BrowserView> browser_view;
|
||||
if (value->IsNull()) {
|
||||
window_->SetBrowserView(nullptr);
|
||||
browser_view_.Reset();
|
||||
} else if (mate::ConvertFromV8(isolate(), value, &browser_view)) {
|
||||
window_->SetBrowserView(browser_view->view());
|
||||
browser_view_.Reset(isolate(), value);
|
||||
}
|
||||
}
|
||||
|
||||
bool Window::IsModal() const {
|
||||
return window_->is_modal();
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> Window::GetNativeWindowHandle() {
|
||||
gfx::AcceleratedWidget handle = window_->GetAcceleratedWidget();
|
||||
return ToBuffer(
|
||||
isolate(), static_cast<void*>(&handle), sizeof(gfx::AcceleratedWidget));
|
||||
}
|
||||
|
||||
void Window::SetVisibleOnAllWorkspaces(bool visible) {
|
||||
return window_->SetVisibleOnAllWorkspaces(visible);
|
||||
}
|
||||
@@ -866,67 +602,29 @@ bool Window::IsVisibleOnAllWorkspaces() {
|
||||
return window_->IsVisibleOnAllWorkspaces();
|
||||
}
|
||||
|
||||
void Window::SetAutoHideCursor(bool auto_hide) {
|
||||
window_->SetAutoHideCursor(auto_hide);
|
||||
}
|
||||
|
||||
void Window::SetVibrancy(mate::Arguments* args) {
|
||||
std::string type;
|
||||
|
||||
args->GetNext(&type);
|
||||
window_->SetVibrancy(type);
|
||||
}
|
||||
|
||||
void Window::SetTouchBar(const std::vector<mate::PersistentDictionary>& items) {
|
||||
window_->SetTouchBar(items);
|
||||
}
|
||||
|
||||
void Window::RefreshTouchBarItem(const std::string& item_id) {
|
||||
window_->RefreshTouchBarItem(item_id);
|
||||
}
|
||||
|
||||
void Window::SetEscapeTouchBarItem(const mate::PersistentDictionary& item) {
|
||||
window_->SetEscapeTouchBarItem(item);
|
||||
}
|
||||
|
||||
int32_t Window::ID() const {
|
||||
return weak_map_id();
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> Window::WebContents(v8::Isolate* isolate) {
|
||||
if (web_contents_.IsEmpty()) {
|
||||
if (web_contents_.IsEmpty())
|
||||
return v8::Null(isolate);
|
||||
}
|
||||
|
||||
return v8::Local<v8::Value>::New(isolate, web_contents_);
|
||||
}
|
||||
|
||||
void Window::RemoveFromParentChildWindows() {
|
||||
if (parent_window_.IsEmpty())
|
||||
return;
|
||||
|
||||
mate::Handle<Window> parent;
|
||||
if (!mate::ConvertFromV8(isolate(), GetParentWindow(), &parent))
|
||||
return;
|
||||
|
||||
parent->child_windows_.Remove(ID());
|
||||
else
|
||||
return v8::Local<v8::Value>::New(isolate, web_contents_);
|
||||
}
|
||||
|
||||
// static
|
||||
void Window::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "BrowserWindow"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
v8::Local<v8::ObjectTemplate> prototype) {
|
||||
mate::ObjectTemplateBuilder(isolate, prototype)
|
||||
.MakeDestroyable()
|
||||
.SetMethod("close", &Window::Close)
|
||||
.SetMethod("focus", &Window::Focus)
|
||||
.SetMethod("blur", &Window::Blur)
|
||||
.SetMethod("isFocused", &Window::IsFocused)
|
||||
.SetMethod("show", &Window::Show)
|
||||
.SetMethod("showInactive", &Window::ShowInactive)
|
||||
.SetMethod("hide", &Window::Hide)
|
||||
.SetMethod("isVisible", &Window::IsVisible)
|
||||
.SetMethod("isEnabled", &Window::IsEnabled)
|
||||
.SetMethod("maximize", &Window::Maximize)
|
||||
.SetMethod("unmaximize", &Window::Unmaximize)
|
||||
.SetMethod("isMaximized", &Window::IsMaximized)
|
||||
@@ -936,42 +634,18 @@ void Window::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("setFullScreen", &Window::SetFullScreen)
|
||||
.SetMethod("isFullScreen", &Window::IsFullscreen)
|
||||
.SetMethod("setAspectRatio", &Window::SetAspectRatio)
|
||||
.SetMethod("previewFile", &Window::PreviewFile)
|
||||
.SetMethod("closeFilePreview", &Window::CloseFilePreview)
|
||||
#if !defined(OS_WIN)
|
||||
.SetMethod("setParentWindow", &Window::SetParentWindow)
|
||||
#endif
|
||||
.SetMethod("getParentWindow", &Window::GetParentWindow)
|
||||
.SetMethod("getChildWindows", &Window::GetChildWindows)
|
||||
.SetMethod("getBrowserView", &Window::GetBrowserView)
|
||||
.SetMethod("setBrowserView", &Window::SetBrowserView)
|
||||
.SetMethod("isModal", &Window::IsModal)
|
||||
.SetMethod("getNativeWindowHandle", &Window::GetNativeWindowHandle)
|
||||
.SetMethod("getBounds", &Window::GetBounds)
|
||||
.SetMethod("setBounds", &Window::SetBounds)
|
||||
.SetMethod("getSize", &Window::GetSize)
|
||||
.SetMethod("setSize", &Window::SetSize)
|
||||
.SetMethod("getContentBounds", &Window::GetContentBounds)
|
||||
.SetMethod("setContentBounds", &Window::SetContentBounds)
|
||||
.SetMethod("getContentSize", &Window::GetContentSize)
|
||||
.SetMethod("setContentSize", &Window::SetContentSize)
|
||||
.SetMethod("setMinimumSize", &Window::SetMinimumSize)
|
||||
.SetMethod("getMinimumSize", &Window::GetMinimumSize)
|
||||
.SetMethod("setMaximumSize", &Window::SetMaximumSize)
|
||||
.SetMethod("getMaximumSize", &Window::GetMaximumSize)
|
||||
.SetMethod("setSheetOffset", &Window::SetSheetOffset)
|
||||
.SetMethod("setResizable", &Window::SetResizable)
|
||||
.SetMethod("isResizable", &Window::IsResizable)
|
||||
.SetMethod("setMovable", &Window::SetMovable)
|
||||
.SetMethod("isMovable", &Window::IsMovable)
|
||||
.SetMethod("setMinimizable", &Window::SetMinimizable)
|
||||
.SetMethod("isMinimizable", &Window::IsMinimizable)
|
||||
.SetMethod("setMaximizable", &Window::SetMaximizable)
|
||||
.SetMethod("isMaximizable", &Window::IsMaximizable)
|
||||
.SetMethod("setFullScreenable", &Window::SetFullScreenable)
|
||||
.SetMethod("isFullScreenable", &Window::IsFullScreenable)
|
||||
.SetMethod("setClosable", &Window::SetClosable)
|
||||
.SetMethod("isClosable", &Window::IsClosable)
|
||||
.SetMethod("setAlwaysOnTop", &Window::SetAlwaysOnTop)
|
||||
.SetMethod("isAlwaysOnTop", &Window::IsAlwaysOnTop)
|
||||
.SetMethod("center", &Window::Center)
|
||||
@@ -984,18 +658,15 @@ void Window::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("setKiosk", &Window::SetKiosk)
|
||||
.SetMethod("isKiosk", &Window::IsKiosk)
|
||||
.SetMethod("setBackgroundColor", &Window::SetBackgroundColor)
|
||||
.SetMethod("setHasShadow", &Window::SetHasShadow)
|
||||
.SetMethod("hasShadow", &Window::HasShadow)
|
||||
.SetMethod("setRepresentedFilename", &Window::SetRepresentedFilename)
|
||||
.SetMethod("getRepresentedFilename", &Window::GetRepresentedFilename)
|
||||
.SetMethod("setDocumentEdited", &Window::SetDocumentEdited)
|
||||
.SetMethod("isDocumentEdited", &Window::IsDocumentEdited)
|
||||
.SetMethod("setIgnoreMouseEvents", &Window::SetIgnoreMouseEvents)
|
||||
.SetMethod("setContentProtection", &Window::SetContentProtection)
|
||||
.SetMethod("setFocusable", &Window::SetFocusable)
|
||||
.SetMethod("focusOnWebView", &Window::FocusOnWebView)
|
||||
.SetMethod("blurWebView", &Window::BlurWebView)
|
||||
.SetMethod("isWebViewFocused", &Window::IsWebViewFocused)
|
||||
.SetMethod("isDevToolsFocused", &Window::IsDevToolsFocused)
|
||||
.SetMethod("capturePage", &Window::CapturePage)
|
||||
.SetMethod("setProgressBar", &Window::SetProgressBar)
|
||||
.SetMethod("setOverlayIcon", &Window::SetOverlayIcon)
|
||||
.SetMethod("setThumbarButtons", &Window::SetThumbarButtons)
|
||||
@@ -1008,24 +679,15 @@ void Window::BuildPrototype(v8::Isolate* isolate,
|
||||
&Window::SetVisibleOnAllWorkspaces)
|
||||
.SetMethod("isVisibleOnAllWorkspaces",
|
||||
&Window::IsVisibleOnAllWorkspaces)
|
||||
#if defined(OS_MACOSX)
|
||||
.SetMethod("setAutoHideCursor", &Window::SetAutoHideCursor)
|
||||
#endif
|
||||
.SetMethod("setVibrancy", &Window::SetVibrancy)
|
||||
.SetMethod("_setTouchBarItems", &Window::SetTouchBar)
|
||||
.SetMethod("_refreshTouchBarItem", &Window::RefreshTouchBarItem)
|
||||
.SetMethod("_setEscapeTouchBarItem", &Window::SetEscapeTouchBarItem)
|
||||
#if defined(OS_WIN)
|
||||
.SetMethod("hookWindowMessage", &Window::HookWindowMessage)
|
||||
.SetMethod("isWindowMessageHooked", &Window::IsWindowMessageHooked)
|
||||
.SetMethod("unhookWindowMessage", &Window::UnhookWindowMessage)
|
||||
.SetMethod("unhookAllWindowMessages", &Window::UnhookAllWindowMessages)
|
||||
.SetMethod("setThumbnailClip", &Window::SetThumbnailClip)
|
||||
.SetMethod("setThumbnailToolTip", &Window::SetThumbnailToolTip)
|
||||
.SetMethod("setAppDetails", &Window::SetAppDetails)
|
||||
#endif
|
||||
#if defined(TOOLKIT_VIEWS)
|
||||
.SetMethod("setIcon", &Window::SetIcon)
|
||||
#if defined(OS_MACOSX)
|
||||
.SetMethod("showDefinitionForSelection",
|
||||
&Window::ShowDefinitionForSelection)
|
||||
#endif
|
||||
.SetProperty("id", &Window::ID)
|
||||
.SetProperty("webContents", &Window::WebContents);
|
||||
@@ -1036,7 +698,7 @@ v8::Local<v8::Value> Window::From(v8::Isolate* isolate,
|
||||
NativeWindow* native_window) {
|
||||
auto existing = TrackableObject::FromWrappedClass(isolate, native_window);
|
||||
if (existing)
|
||||
return existing->GetWrapper();
|
||||
return existing->GetWrapper(isolate);
|
||||
else
|
||||
return v8::Null(isolate);
|
||||
}
|
||||
@@ -1053,10 +715,9 @@ using atom::api::Window;
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
Window::SetConstructor(isolate, base::Bind(&Window::New));
|
||||
|
||||
mate::Dictionary browser_window(
|
||||
isolate, Window::GetConstructor(isolate)->GetFunction());
|
||||
v8::Local<v8::Function> constructor = mate::CreateConstructor<Window>(
|
||||
isolate, "BrowserWindow", base::Bind(&Window::New));
|
||||
mate::Dictionary browser_window(isolate, constructor);
|
||||
browser_window.SetMethod("fromId",
|
||||
&mate::TrackableObject<Window>::FromWeakMapID);
|
||||
browser_window.SetMethod("getAllWindows",
|
||||
|
||||
@@ -6,18 +6,15 @@
|
||||
#define ATOM_BROWSER_API_ATOM_API_WINDOW_H_
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "ui/gfx/image/image.h"
|
||||
#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 "native_mate/persistent_dictionary.h"
|
||||
#include "ui/gfx/image/image.h"
|
||||
|
||||
class GURL;
|
||||
|
||||
@@ -41,10 +38,10 @@ class WebContents;
|
||||
class Window : public mate::TrackableObject<Window>,
|
||||
public NativeWindowObserver {
|
||||
public:
|
||||
static mate::WrappableBase* New(mate::Arguments* args);
|
||||
static mate::Wrappable* New(v8::Isolate* isolate, mate::Arguments* args);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
v8::Local<v8::ObjectTemplate> prototype);
|
||||
|
||||
// Returns the BrowserWindow object from |native_window|.
|
||||
static v8::Local<v8::Value> From(v8::Isolate* isolate,
|
||||
@@ -52,23 +49,15 @@ class Window : public mate::TrackableObject<Window>,
|
||||
|
||||
NativeWindow* window() const { return window_.get(); }
|
||||
|
||||
int32_t ID() const;
|
||||
|
||||
protected:
|
||||
Window(v8::Isolate* isolate, v8::Local<v8::Object> wrapper,
|
||||
const mate::Dictionary& options);
|
||||
~Window() override;
|
||||
Window(v8::Isolate* isolate, const mate::Dictionary& options);
|
||||
virtual ~Window();
|
||||
|
||||
// NativeWindowObserver:
|
||||
void WillCloseWindow(bool* prevent_default) override;
|
||||
void WillDestroyNativeObject() override;
|
||||
void OnWindowClosed() override;
|
||||
void OnWindowEndSession() 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;
|
||||
@@ -76,12 +65,6 @@ class Window : public mate::TrackableObject<Window>,
|
||||
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 OnWindowSheetBegin() override;
|
||||
void OnWindowSheetEnd() override;
|
||||
void OnWindowEnterFullScreen() override;
|
||||
void OnWindowLeaveFullScreen() override;
|
||||
void OnWindowEnterHtmlFullScreen() override;
|
||||
@@ -89,28 +72,20 @@ class Window : public mate::TrackableObject<Window>,
|
||||
void OnRendererUnresponsive() override;
|
||||
void OnRendererResponsive() override;
|
||||
void OnExecuteWindowsCommand(const std::string& command_name) override;
|
||||
void OnTouchBarItemResult(const std::string& item_id,
|
||||
const base::DictionaryValue& details) 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();
|
||||
@@ -119,35 +94,22 @@ class Window : public mate::TrackableObject<Window>,
|
||||
bool IsMinimized();
|
||||
void SetFullScreen(bool fullscreen);
|
||||
bool IsFullscreen();
|
||||
void SetBounds(const gfx::Rect& bounds, mate::Arguments* args);
|
||||
void SetBounds(const gfx::Rect& bounds);
|
||||
gfx::Rect GetBounds();
|
||||
void SetSize(int width, int height, mate::Arguments* args);
|
||||
void SetSize(int width, int height);
|
||||
std::vector<int> GetSize();
|
||||
void SetContentSize(int width, int height, mate::Arguments* args);
|
||||
void SetContentSize(int width, int height);
|
||||
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);
|
||||
void SetAlwaysOnTop(bool top);
|
||||
bool IsAlwaysOnTop();
|
||||
void Center();
|
||||
void SetPosition(int x, int y, mate::Arguments* args);
|
||||
void SetPosition(int x, int y);
|
||||
std::vector<int> GetPosition();
|
||||
void SetTitle(const std::string& title);
|
||||
std::string GetTitle();
|
||||
@@ -156,19 +118,16 @@ class Window : public mate::TrackableObject<Window>,
|
||||
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();
|
||||
bool IsDevToolsFocused();
|
||||
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 CapturePage(mate::Arguments* args);
|
||||
void SetProgressBar(double progress);
|
||||
void SetOverlayIcon(const gfx::Image& overlay,
|
||||
const std::string& description);
|
||||
bool SetThumbarButtons(mate::Arguments* args);
|
||||
@@ -178,15 +137,6 @@ class Window : public mate::TrackableObject<Window>,
|
||||
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;
|
||||
v8::Local<v8::Value> GetBrowserView() const;
|
||||
void SetBrowserView(v8::Local<v8::Value> value);
|
||||
bool IsModal() const;
|
||||
v8::Local<v8::Value> GetNativeWindowHandle();
|
||||
|
||||
#if defined(OS_WIN)
|
||||
typedef base::Callback<void(v8::Local<v8::Value>,
|
||||
@@ -196,44 +146,29 @@ class Window : public mate::TrackableObject<Window>,
|
||||
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);
|
||||
#if defined(OS_MACOSX)
|
||||
void ShowDefinitionForSelection();
|
||||
#endif
|
||||
|
||||
void SetVisibleOnAllWorkspaces(bool visible);
|
||||
bool IsVisibleOnAllWorkspaces();
|
||||
|
||||
void SetAutoHideCursor(bool auto_hide);
|
||||
|
||||
void SetVibrancy(mate::Arguments* args);
|
||||
void SetTouchBar(const std::vector<mate::PersistentDictionary>& items);
|
||||
void RefreshTouchBarItem(const std::string& item_id);
|
||||
void SetEscapeTouchBarItem(const mate::PersistentDictionary& item);
|
||||
|
||||
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> browser_view_;
|
||||
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_;
|
||||
scoped_ptr<NativeWindow> window_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Window);
|
||||
};
|
||||
|
||||
@@ -11,15 +11,31 @@
|
||||
|
||||
namespace mate {
|
||||
|
||||
Event::Event(v8::Isolate* isolate)
|
||||
: sender_(nullptr),
|
||||
message_(nullptr) {
|
||||
Init(isolate);
|
||||
namespace {
|
||||
|
||||
v8::Persistent<v8::ObjectTemplate> template_;
|
||||
|
||||
} // namespace
|
||||
|
||||
Event::Event()
|
||||
: sender_(NULL),
|
||||
message_(NULL) {
|
||||
}
|
||||
|
||||
Event::~Event() {
|
||||
}
|
||||
|
||||
ObjectTemplateBuilder Event::GetObjectTemplateBuilder(v8::Isolate* isolate) {
|
||||
if (template_.IsEmpty())
|
||||
template_.Reset(isolate, ObjectTemplateBuilder(isolate)
|
||||
.SetMethod("preventDefault", &Event::PreventDefault)
|
||||
.SetMethod("sendReply", &Event::SendReply)
|
||||
.Build());
|
||||
|
||||
return ObjectTemplateBuilder(
|
||||
isolate, v8::Local<v8::ObjectTemplate>::New(isolate, template_));
|
||||
}
|
||||
|
||||
void Event::SetSenderAndMessage(content::WebContents* sender,
|
||||
IPC::Message* message) {
|
||||
DCHECK(!sender_);
|
||||
@@ -31,38 +47,26 @@ void Event::SetSenderAndMessage(content::WebContents* sender,
|
||||
}
|
||||
|
||||
void Event::WebContentsDestroyed() {
|
||||
sender_ = nullptr;
|
||||
message_ = nullptr;
|
||||
sender_ = NULL;
|
||||
message_ = NULL;
|
||||
}
|
||||
|
||||
void Event::PreventDefault(v8::Isolate* isolate) {
|
||||
GetWrapper()->Set(StringToV8(isolate, "defaultPrevented"),
|
||||
GetWrapper(isolate)->Set(StringToV8(isolate, "defaultPrevented"),
|
||||
v8::True(isolate));
|
||||
}
|
||||
|
||||
bool Event::SendReply(const base::string16& json) {
|
||||
if (message_ == nullptr || sender_ == nullptr)
|
||||
if (message_ == NULL || sender_ == NULL)
|
||||
return false;
|
||||
|
||||
AtomViewHostMsg_Message_Sync::WriteReplyParams(message_, json);
|
||||
bool success = sender_->Send(message_);
|
||||
message_ = nullptr;
|
||||
sender_ = nullptr;
|
||||
return success;
|
||||
return sender_->Send(message_);
|
||||
}
|
||||
|
||||
// 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);
|
||||
return CreateHandle(isolate, new Event);
|
||||
}
|
||||
|
||||
} // namespace mate
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
#define ATOM_BROWSER_API_EVENT_H_
|
||||
|
||||
#include "content/public/browser/web_contents_observer.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "native_mate/wrappable.h"
|
||||
#include "native_mate/handle.h"
|
||||
|
||||
namespace IPC {
|
||||
class Message;
|
||||
@@ -15,14 +15,11 @@ class Message;
|
||||
|
||||
namespace mate {
|
||||
|
||||
class Event : public Wrappable<Event>,
|
||||
class Event : public Wrappable,
|
||||
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);
|
||||
|
||||
@@ -33,8 +30,11 @@ class Event : public Wrappable<Event>,
|
||||
bool SendReply(const base::string16& json);
|
||||
|
||||
protected:
|
||||
explicit Event(v8::Isolate* isolate);
|
||||
~Event() override;
|
||||
Event();
|
||||
virtual ~Event();
|
||||
|
||||
// Wrappable implementations:
|
||||
ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate* isolate) override;
|
||||
|
||||
// content::WebContentsObserver implementations:
|
||||
void WebContentsDestroyed() override;
|
||||
|
||||
@@ -8,9 +8,6 @@
|
||||
#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 {
|
||||
|
||||
@@ -37,13 +34,11 @@ v8::Local<v8::Object> CreateEventObject(v8::Isolate* isolate) {
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace internal {
|
||||
EventEmitter::EventEmitter() {
|
||||
}
|
||||
|
||||
v8::Local<v8::Object> CreateJSEvent(
|
||||
v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> object,
|
||||
content::WebContents* sender,
|
||||
IPC::Message* message) {
|
||||
v8::Local<v8::Object> EventEmitter::CreateJSEvent(
|
||||
v8::Isolate* isolate, content::WebContents* sender, IPC::Message* message) {
|
||||
v8::Local<v8::Object> event;
|
||||
bool use_native_event = sender && message;
|
||||
|
||||
@@ -54,29 +49,16 @@ v8::Local<v8::Object> CreateJSEvent(
|
||||
} else {
|
||||
event = CreateEventObject(isolate);
|
||||
}
|
||||
mate::Dictionary(isolate, event).Set("sender", object);
|
||||
mate::Dictionary(isolate, event).Set("sender", GetWrapper(isolate));
|
||||
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> EventEmitter::CreateCustomEvent(
|
||||
v8::Isolate* isolate, 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);
|
||||
mate::Dictionary(isolate, event).Set("sender", GetWrapper(isolate));
|
||||
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
|
||||
|
||||
@@ -20,49 +20,17 @@ 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> {
|
||||
class EventEmitter : public Wrappable {
|
||||
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...);
|
||||
return EmitWithEvent(name, CreateCustomEvent(isolate(), event), args...);
|
||||
}
|
||||
|
||||
// this.emit(name, new Event(), args...);
|
||||
@@ -79,13 +47,12 @@ class EventEmitter : public Wrappable<T> {
|
||||
const Args&... args) {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
v8::Local<v8::Object> event = internal::CreateJSEvent(
|
||||
isolate(), GetWrapper(), sender, message);
|
||||
v8::Local<v8::Object> event = CreateJSEvent(isolate(), sender, message);
|
||||
return EmitWithEvent(name, event, args...);
|
||||
}
|
||||
|
||||
protected:
|
||||
EventEmitter() {}
|
||||
EventEmitter();
|
||||
|
||||
private:
|
||||
// this.emit(name, event, args...);
|
||||
@@ -95,11 +62,17 @@ class EventEmitter : public Wrappable<T> {
|
||||
const Args&... args) {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
EmitEvent(isolate(), GetWrapper(), name, event, args...);
|
||||
EmitEvent(isolate(), GetWrapper(isolate()), name, event, args...);
|
||||
return event->Get(
|
||||
StringToV8(isolate(), "defaultPrevented"))->BooleanValue();
|
||||
}
|
||||
|
||||
v8::Local<v8::Object> CreateJSEvent(v8::Isolate* isolate,
|
||||
content::WebContents* sender,
|
||||
IPC::Message* message);
|
||||
v8::Local<v8::Object> CreateCustomEvent(
|
||||
v8::Isolate* isolate, v8::Local<v8::Object> event);
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(EventEmitter);
|
||||
};
|
||||
|
||||
|
||||
@@ -4,90 +4,62 @@
|
||||
|
||||
#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"
|
||||
#include "base/bind.h"
|
||||
#include "media/base/video_frame.h"
|
||||
#include "media/base/yuv_convert.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) {
|
||||
const gfx::Size& size,
|
||||
const FrameCaptureCallback& callback)
|
||||
: isolate_(isolate), size_(size), callback_(callback) {
|
||||
}
|
||||
|
||||
bool FrameSubscriber::ShouldCaptureFrame(
|
||||
const gfx::Rect& dirty_rect,
|
||||
const gfx::Rect& damage_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;
|
||||
*storage = media::VideoFrame::CreateFrame(media::VideoFrame::YV12, size_,
|
||||
gfx::Rect(size_), size_,
|
||||
base::TimeDelta());
|
||||
*callback = base::Bind(&FrameSubscriber::OnFrameDelivered,
|
||||
base::Unretained(this),
|
||||
*storage);
|
||||
return true;
|
||||
}
|
||||
|
||||
void FrameSubscriber::OnFrameDelivered(const FrameCaptureCallback& callback,
|
||||
const gfx::Rect& damage_rect,
|
||||
const SkBitmap& bitmap,
|
||||
content::ReadbackResponse response) {
|
||||
if (response != content::ReadbackResponse::READBACK_SUCCESS)
|
||||
void FrameSubscriber::OnFrameDelivered(
|
||||
scoped_refptr<media::VideoFrame> frame, base::TimeTicks, bool result) {
|
||||
if (!result)
|
||||
return;
|
||||
|
||||
v8::Locker locker(isolate_);
|
||||
v8::HandleScope handle_scope(isolate_);
|
||||
|
||||
size_t rgb_arr_size = bitmap.width() * bitmap.height() *
|
||||
bitmap.bytesPerPixel();
|
||||
gfx::Rect rect = frame->visible_rect();
|
||||
size_t rgb_arr_size = rect.width() * rect.height() * 4;
|
||||
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);
|
||||
// Convert a frame of YUV to 32 bit ARGB.
|
||||
media::ConvertYUVToRGB32(frame->data(media::VideoFrame::kYPlane),
|
||||
frame->data(media::VideoFrame::kUPlane),
|
||||
frame->data(media::VideoFrame::kVPlane),
|
||||
reinterpret_cast<uint8*>(
|
||||
node::Buffer::Data(buffer.ToLocalChecked())),
|
||||
rect.width(), rect.height(),
|
||||
frame->stride(media::VideoFrame::kYPlane),
|
||||
frame->stride(media::VideoFrame::kUVPlane),
|
||||
rect.width() * 4,
|
||||
media::YV12);
|
||||
|
||||
v8::Local<v8::Value> damage =
|
||||
mate::Converter<gfx::Rect>::ToV8(isolate_, damage_rect);
|
||||
|
||||
callback_.Run(buffer.ToLocalChecked(), damage);
|
||||
callback_.Run(buffer.ToLocalChecked());
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
@@ -6,11 +6,7 @@
|
||||
#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"
|
||||
|
||||
@@ -20,13 +16,11 @@ namespace api {
|
||||
|
||||
class FrameSubscriber : public content::RenderWidgetHostViewFrameSubscriber {
|
||||
public:
|
||||
using FrameCaptureCallback =
|
||||
base::Callback<void(v8::Local<v8::Value>, v8::Local<v8::Value>)>;
|
||||
using FrameCaptureCallback = base::Callback<void(v8::Local<v8::Value>)>;
|
||||
|
||||
FrameSubscriber(v8::Isolate* isolate,
|
||||
content::RenderWidgetHostView* view,
|
||||
const FrameCaptureCallback& callback,
|
||||
bool only_dirty);
|
||||
const gfx::Size& size,
|
||||
const FrameCaptureCallback& callback);
|
||||
|
||||
bool ShouldCaptureFrame(const gfx::Rect& damage_rect,
|
||||
base::TimeTicks present_time,
|
||||
@@ -34,17 +28,12 @@ class FrameSubscriber : public content::RenderWidgetHostViewFrameSubscriber {
|
||||
DeliverFrameCallback* callback) override;
|
||||
|
||||
private:
|
||||
void OnFrameDelivered(const FrameCaptureCallback& callback,
|
||||
const gfx::Rect& damage_rect,
|
||||
const SkBitmap& bitmap,
|
||||
content::ReadbackResponse response);
|
||||
void OnFrameDelivered(
|
||||
scoped_refptr<media::VideoFrame> frame, base::TimeTicks, bool);
|
||||
|
||||
v8::Isolate* isolate_;
|
||||
content::RenderWidgetHostView* view_;
|
||||
gfx::Size size_;
|
||||
FrameCaptureCallback callback_;
|
||||
bool only_dirty_;
|
||||
|
||||
base::WeakPtrFactory<FrameSubscriber> weak_factory_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(FrameSubscriber);
|
||||
};
|
||||
|
||||
72
atom/browser/api/lib/app.coffee
Normal file
72
atom/browser/api/lib/app.coffee
Normal file
@@ -0,0 +1,72 @@
|
||||
{deprecate, session, Menu} = require 'electron'
|
||||
{EventEmitter} = require 'events'
|
||||
|
||||
bindings = process.atomBinding 'app'
|
||||
downloadItemBindings = process.atomBinding 'download_item'
|
||||
|
||||
app = bindings.app
|
||||
app.__proto__ = EventEmitter.prototype
|
||||
|
||||
app.setApplicationMenu = (menu) ->
|
||||
Menu.setApplicationMenu menu
|
||||
|
||||
app.getApplicationMenu = ->
|
||||
Menu.getApplicationMenu()
|
||||
|
||||
app.commandLine =
|
||||
appendSwitch: bindings.appendSwitch,
|
||||
appendArgument: bindings.appendArgument
|
||||
|
||||
if process.platform is 'darwin'
|
||||
app.dock =
|
||||
bounce: (type='informational') -> bindings.dockBounce type
|
||||
cancelBounce: bindings.dockCancelBounce
|
||||
setBadge: bindings.dockSetBadgeText
|
||||
getBadge: bindings.dockGetBadgeText
|
||||
hide: bindings.dockHide
|
||||
show: bindings.dockShow
|
||||
setMenu: bindings.dockSetMenu
|
||||
|
||||
appPath = null
|
||||
app.setAppPath = (path) ->
|
||||
appPath = path
|
||||
|
||||
app.getAppPath = ->
|
||||
appPath
|
||||
|
||||
# Routes the events to webContents.
|
||||
for name in ['login', 'certificate-error', 'select-client-certificate']
|
||||
do (name) ->
|
||||
app.on name, (event, webContents, args...) ->
|
||||
webContents.emit name, event, args...
|
||||
|
||||
# Deprecated.
|
||||
app.getHomeDir = deprecate 'app.getHomeDir', 'app.getPath', ->
|
||||
@getPath 'home'
|
||||
app.getDataPath = deprecate 'app.getDataPath', 'app.getPath', ->
|
||||
@getPath 'userData'
|
||||
app.setDataPath = deprecate 'app.setDataPath', 'app.setPath', (path) ->
|
||||
@setPath 'userData', path
|
||||
app.resolveProxy = deprecate 'app.resolveProxy', 'session.defaultSession.resolveProxy', (url, callback) ->
|
||||
session.defaultSession.resolveProxy url, callback
|
||||
deprecate.rename app, 'terminate', 'quit'
|
||||
deprecate.event app, 'finish-launching', 'ready', ->
|
||||
setImmediate => # give default app a chance to setup default menu.
|
||||
@emit 'finish-launching'
|
||||
deprecate.event app, 'activate-with-no-open-windows', 'activate', (event, hasVisibleWindows) ->
|
||||
@emit 'activate-with-no-open-windows', event if not hasVisibleWindows
|
||||
deprecate.event app, 'select-certificate', 'select-client-certificate'
|
||||
|
||||
# Wrappers for native classes.
|
||||
wrapDownloadItem = (downloadItem) ->
|
||||
# downloadItem is an EventEmitter.
|
||||
downloadItem.__proto__ = EventEmitter.prototype
|
||||
# Deprecated.
|
||||
deprecate.property downloadItem, 'url', 'getURL'
|
||||
deprecate.property downloadItem, 'filename', 'getFilename'
|
||||
deprecate.property downloadItem, 'mimeType', 'getMimeType'
|
||||
deprecate.rename downloadItem, 'getUrl', 'getURL'
|
||||
downloadItemBindings._setWrapDownloadItem wrapDownloadItem
|
||||
|
||||
# Only one App object pemitted.
|
||||
module.exports = app
|
||||
12
atom/browser/api/lib/auto-updater.coffee
Normal file
12
atom/browser/api/lib/auto-updater.coffee
Normal file
@@ -0,0 +1,12 @@
|
||||
{deprecate} = require 'electron'
|
||||
|
||||
autoUpdater =
|
||||
if process.platform is 'win32'
|
||||
require './auto-updater/auto-updater-win'
|
||||
else
|
||||
require './auto-updater/auto-updater-native'
|
||||
|
||||
# Deprecated.
|
||||
deprecate.rename autoUpdater, 'setFeedUrl', 'setFeedURL'
|
||||
|
||||
module.exports = autoUpdater
|
||||
@@ -0,0 +1,6 @@
|
||||
{EventEmitter} = require 'events'
|
||||
{autoUpdater} = process.atomBinding 'auto_updater'
|
||||
|
||||
autoUpdater.__proto__ = EventEmitter.prototype
|
||||
|
||||
module.exports = autoUpdater
|
||||
42
atom/browser/api/lib/auto-updater/auto-updater-win.coffee
Normal file
42
atom/browser/api/lib/auto-updater/auto-updater-win.coffee
Normal file
@@ -0,0 +1,42 @@
|
||||
{app} = require 'electron'
|
||||
{EventEmitter} = require 'events'
|
||||
url = require 'url'
|
||||
|
||||
squirrelUpdate = require './squirrel-update-win'
|
||||
|
||||
class AutoUpdater extends EventEmitter
|
||||
quitAndInstall: ->
|
||||
squirrelUpdate.processStart()
|
||||
app.quit()
|
||||
|
||||
setFeedURL: (updateURL) ->
|
||||
@updateURL = updateURL
|
||||
|
||||
checkForUpdates: ->
|
||||
return @emitError 'Update URL is not set' unless @updateURL
|
||||
return @emitError 'Can not find Squirrel' unless squirrelUpdate.supported()
|
||||
|
||||
@emit 'checking-for-update'
|
||||
|
||||
squirrelUpdate.download @updateURL, (error, update) =>
|
||||
return @emitError error if error?
|
||||
return @emit 'update-not-available' unless update?
|
||||
|
||||
@emit 'update-available'
|
||||
|
||||
squirrelUpdate.update @updateURL, (error) =>
|
||||
return @emitError error if error?
|
||||
|
||||
{releaseNotes, version} = update
|
||||
# Following information is not available on Windows, so fake them.
|
||||
date = new Date
|
||||
url = @updateURL
|
||||
|
||||
@emit 'update-downloaded', {}, releaseNotes, version, date, url, => @quitAndInstall()
|
||||
|
||||
# Private: Emit both error object and message, this is to keep compatibility
|
||||
# with Old APIs.
|
||||
emitError: (message) ->
|
||||
@emit 'error', new Error(message), message
|
||||
|
||||
module.exports = new AutoUpdater
|
||||
67
atom/browser/api/lib/auto-updater/squirrel-update-win.coffee
Normal file
67
atom/browser/api/lib/auto-updater/squirrel-update-win.coffee
Normal file
@@ -0,0 +1,67 @@
|
||||
fs = require 'fs'
|
||||
path = require 'path'
|
||||
{spawn} = require 'child_process'
|
||||
|
||||
appFolder = path.dirname process.execPath # i.e. my-app/app-0.1.13/
|
||||
updateExe = path.resolve appFolder, '..', 'Update.exe' # i.e. my-app/Update.exe
|
||||
exeName = path.basename process.execPath
|
||||
|
||||
# Spawn a command and invoke the callback when it completes with an error
|
||||
# and the output from standard out.
|
||||
spawnUpdate = (args, detached, callback) ->
|
||||
try
|
||||
spawnedProcess = spawn updateExe, args, {detached}
|
||||
catch error
|
||||
# Shouldn't happen, but still guard it.
|
||||
process.nextTick -> callback error
|
||||
return
|
||||
|
||||
stdout = ''
|
||||
stderr = ''
|
||||
spawnedProcess.stdout.on 'data', (data) -> stdout += data
|
||||
spawnedProcess.stderr.on 'data', (data) -> stderr += data
|
||||
|
||||
errorEmitted = false
|
||||
spawnedProcess.on 'error', (error) ->
|
||||
errorEmitted = true
|
||||
callback error
|
||||
spawnedProcess.on 'exit', (code, signal) ->
|
||||
# We may have already emitted an error.
|
||||
return if errorEmitted
|
||||
|
||||
# Process terminated with error.
|
||||
if code isnt 0
|
||||
return callback "Command failed: #{signal ? code}\n#{stderr}"
|
||||
|
||||
# Success.
|
||||
callback null, stdout
|
||||
|
||||
# Start an instance of the installed app.
|
||||
exports.processStart = (callback) ->
|
||||
spawnUpdate ['--processStart', exeName], true, ->
|
||||
|
||||
# Download the releases specified by the URL and write new results to stdout.
|
||||
exports.download = (updateURL, callback) ->
|
||||
spawnUpdate ['--download', updateURL], false, (error, stdout) ->
|
||||
return callback(error) if error?
|
||||
|
||||
try
|
||||
# Last line of output is the JSON details about the releases
|
||||
json = stdout.trim().split('\n').pop()
|
||||
update = JSON.parse(json)?.releasesToApply?.pop?()
|
||||
catch
|
||||
return callback "Invalid result:\n#{stdout}"
|
||||
|
||||
callback null, update
|
||||
|
||||
# Update the application to the latest remote version specified by URL.
|
||||
exports.update = (updateURL, callback) ->
|
||||
spawnUpdate ['--update', updateURL], false, callback
|
||||
|
||||
# Is the Update.exe installed with the current application?
|
||||
exports.supported = ->
|
||||
try
|
||||
fs.accessSync updateExe, fs.R_OK
|
||||
return true
|
||||
catch
|
||||
return false
|
||||
112
atom/browser/api/lib/browser-window.coffee
Normal file
112
atom/browser/api/lib/browser-window.coffee
Normal file
@@ -0,0 +1,112 @@
|
||||
{ipcMain, deprecate} = require 'electron'
|
||||
{EventEmitter} = require 'events'
|
||||
|
||||
{BrowserWindow} = process.atomBinding 'window'
|
||||
BrowserWindow::__proto__ = EventEmitter.prototype
|
||||
|
||||
BrowserWindow::_init = ->
|
||||
{app} = require 'electron' # avoid recursive require.
|
||||
|
||||
# Simulate the application menu on platforms other than OS X.
|
||||
if process.platform isnt 'darwin'
|
||||
menu = app.getApplicationMenu()
|
||||
@setMenu menu if menu?
|
||||
|
||||
# Make new windows requested by links behave like "window.open"
|
||||
@webContents.on '-new-window', (event, url, frameName) ->
|
||||
options = show: true, width: 800, height: 600
|
||||
ipcMain.emit 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPEN', event, url, frameName, options
|
||||
|
||||
# window.resizeTo(...)
|
||||
# window.moveTo(...)
|
||||
@webContents.on 'move', (event, size) =>
|
||||
@setBounds size
|
||||
|
||||
# Hide the auto-hide menu when webContents is focused.
|
||||
@webContents.on 'activate', =>
|
||||
if process.platform isnt 'darwin' and @isMenuBarAutoHide() and @isMenuBarVisible()
|
||||
@setMenuBarVisibility false
|
||||
|
||||
# Forward the crashed event.
|
||||
@webContents.on 'crashed', =>
|
||||
@emit 'crashed'
|
||||
|
||||
# Change window title to page title.
|
||||
@webContents.on 'page-title-updated', (event, title, explicitSet) =>
|
||||
@emit 'page-title-updated', event, title
|
||||
@setTitle title unless event.defaultPrevented
|
||||
|
||||
# Sometimes the webContents doesn't get focus when window is shown, so we have
|
||||
# to force focusing on webContents in this case. The safest way is to focus it
|
||||
# when we first start to load URL, if we do it earlier it won't have effect,
|
||||
# if we do it later we might move focus in the page.
|
||||
# Though this hack is only needed on OS X when the app is launched from
|
||||
# Finder, we still do it on all platforms in case of other bugs we don't know.
|
||||
@webContents.once 'load-url', ->
|
||||
@focus()
|
||||
|
||||
# Redirect focus/blur event to app instance too.
|
||||
@on 'blur', (event) =>
|
||||
app.emit 'browser-window-blur', event, this
|
||||
@on 'focus', (event) =>
|
||||
app.emit 'browser-window-focus', event, this
|
||||
|
||||
# Notify the creation of the window.
|
||||
app.emit 'browser-window-created', {}, this
|
||||
|
||||
# Be compatible with old APIs.
|
||||
@webContents.on 'devtools-focused', => @emit 'devtools-focused'
|
||||
@webContents.on 'devtools-opened', => @emit 'devtools-opened'
|
||||
@webContents.on 'devtools-closed', => @emit 'devtools-closed'
|
||||
Object.defineProperty this, 'devToolsWebContents',
|
||||
enumerable: true,
|
||||
configurable: false,
|
||||
get: -> @webContents.devToolsWebContents
|
||||
|
||||
BrowserWindow.getFocusedWindow = ->
|
||||
windows = BrowserWindow.getAllWindows()
|
||||
return window for window in windows when window.isFocused()
|
||||
|
||||
BrowserWindow.fromWebContents = (webContents) ->
|
||||
windows = BrowserWindow.getAllWindows()
|
||||
return window for window in windows when window.webContents?.equal webContents
|
||||
|
||||
BrowserWindow.fromDevToolsWebContents = (webContents) ->
|
||||
windows = BrowserWindow.getAllWindows()
|
||||
return window for window in windows when window.devToolsWebContents?.equal webContents
|
||||
|
||||
# Helpers.
|
||||
BrowserWindow::loadURL = -> @webContents.loadURL.apply @webContents, arguments
|
||||
BrowserWindow::getURL = -> @webContents.getURL()
|
||||
BrowserWindow::reload = -> @webContents.reload.apply @webContents, arguments
|
||||
BrowserWindow::send = -> @webContents.send.apply @webContents, arguments
|
||||
BrowserWindow::openDevTools = -> @webContents.openDevTools.apply @webContents, arguments
|
||||
BrowserWindow::closeDevTools = -> @webContents.closeDevTools()
|
||||
BrowserWindow::isDevToolsOpened = -> @webContents.isDevToolsOpened()
|
||||
BrowserWindow::toggleDevTools = -> @webContents.toggleDevTools()
|
||||
BrowserWindow::inspectElement = -> @webContents.inspectElement.apply @webContents, arguments
|
||||
BrowserWindow::inspectServiceWorker = -> @webContents.inspectServiceWorker()
|
||||
|
||||
# Deprecated.
|
||||
deprecate.member BrowserWindow, 'undo', 'webContents'
|
||||
deprecate.member BrowserWindow, 'redo', 'webContents'
|
||||
deprecate.member BrowserWindow, 'cut', 'webContents'
|
||||
deprecate.member BrowserWindow, 'copy', 'webContents'
|
||||
deprecate.member BrowserWindow, 'paste', 'webContents'
|
||||
deprecate.member BrowserWindow, 'selectAll', 'webContents'
|
||||
deprecate.member BrowserWindow, 'reloadIgnoringCache', 'webContents'
|
||||
deprecate.member BrowserWindow, 'isLoading', 'webContents'
|
||||
deprecate.member BrowserWindow, 'isWaitingForResponse', 'webContents'
|
||||
deprecate.member BrowserWindow, 'stop', 'webContents'
|
||||
deprecate.member BrowserWindow, 'isCrashed', 'webContents'
|
||||
deprecate.member BrowserWindow, 'print', 'webContents'
|
||||
deprecate.member BrowserWindow, 'printToPDF', 'webContents'
|
||||
deprecate.rename BrowserWindow, 'restart', 'reload'
|
||||
deprecate.rename BrowserWindow, 'loadUrl', 'loadURL'
|
||||
deprecate.rename BrowserWindow, 'getUrl', 'getURL'
|
||||
BrowserWindow::executeJavaScriptInDevTools = deprecate 'executeJavaScriptInDevTools', 'devToolsWebContents.executeJavaScript', (code) ->
|
||||
@devToolsWebContents?.executeJavaScript code
|
||||
BrowserWindow::getPageTitle = deprecate 'getPageTitle', 'webContents.getTitle', ->
|
||||
@webContents?.getTitle()
|
||||
|
||||
module.exports = BrowserWindow
|
||||
1
atom/browser/api/lib/content-tracing.coffee
Normal file
1
atom/browser/api/lib/content-tracing.coffee
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = process.atomBinding 'content_tracing'
|
||||
125
atom/browser/api/lib/dialog.coffee
Normal file
125
atom/browser/api/lib/dialog.coffee
Normal file
@@ -0,0 +1,125 @@
|
||||
{app, BrowserWindow} = require 'electron'
|
||||
|
||||
binding = process.atomBinding 'dialog'
|
||||
v8Util = process.atomBinding 'v8_util'
|
||||
|
||||
fileDialogProperties =
|
||||
openFile: 1 << 0
|
||||
openDirectory: 1 << 1
|
||||
multiSelections: 1 << 2
|
||||
createDirectory: 1 << 3
|
||||
|
||||
messageBoxTypes = ['none', 'info', 'warning', 'error', 'question']
|
||||
|
||||
messageBoxOptions =
|
||||
noLink: 1 << 0
|
||||
|
||||
parseArgs = (window, options, callback) ->
|
||||
unless window is null or window?.constructor is BrowserWindow
|
||||
# Shift.
|
||||
callback = options
|
||||
options = window
|
||||
window = null
|
||||
if not callback? and typeof options is 'function'
|
||||
# Shift.
|
||||
callback = options
|
||||
options = null
|
||||
[window, options, callback]
|
||||
|
||||
checkAppInitialized = ->
|
||||
throw new Error('dialog module can only be used after app is ready') unless app.isReady()
|
||||
|
||||
module.exports =
|
||||
showOpenDialog: (args...) ->
|
||||
checkAppInitialized()
|
||||
[window, options, callback] = parseArgs args...
|
||||
|
||||
options ?= title: 'Open', properties: ['openFile']
|
||||
options.properties ?= ['openFile']
|
||||
throw new TypeError('Properties need to be array') unless Array.isArray options.properties
|
||||
|
||||
properties = 0
|
||||
for prop, value of fileDialogProperties
|
||||
properties |= value if prop in options.properties
|
||||
|
||||
options.title ?= ''
|
||||
options.defaultPath ?= ''
|
||||
options.filters ?= []
|
||||
|
||||
wrappedCallback =
|
||||
if typeof callback is 'function'
|
||||
(success, result) -> callback(if success then result)
|
||||
else
|
||||
null
|
||||
|
||||
binding.showOpenDialog String(options.title),
|
||||
String(options.defaultPath),
|
||||
options.filters
|
||||
properties,
|
||||
window,
|
||||
wrappedCallback
|
||||
|
||||
showSaveDialog: (args...) ->
|
||||
checkAppInitialized()
|
||||
[window, options, callback] = parseArgs args...
|
||||
|
||||
options ?= title: 'Save'
|
||||
options.title ?= ''
|
||||
options.defaultPath ?= ''
|
||||
options.filters ?= []
|
||||
|
||||
wrappedCallback =
|
||||
if typeof callback is 'function'
|
||||
(success, result) -> callback(if success then result)
|
||||
else
|
||||
null
|
||||
|
||||
binding.showSaveDialog String(options.title),
|
||||
String(options.defaultPath),
|
||||
options.filters
|
||||
window,
|
||||
wrappedCallback
|
||||
|
||||
showMessageBox: (args...) ->
|
||||
checkAppInitialized()
|
||||
[window, options, callback] = parseArgs args...
|
||||
|
||||
options ?= type: 'none'
|
||||
options.type ?= 'none'
|
||||
messageBoxType = messageBoxTypes.indexOf options.type
|
||||
throw new TypeError('Invalid message box type') unless messageBoxType > -1
|
||||
|
||||
throw new TypeError('Buttons need to be array') unless Array.isArray options.buttons
|
||||
|
||||
options.title ?= ''
|
||||
options.message ?= ''
|
||||
options.detail ?= ''
|
||||
options.icon ?= null
|
||||
|
||||
# Choose a default button to get selected when dialog is cancelled.
|
||||
unless options.cancelId?
|
||||
options.cancelId = 0
|
||||
for text, i in options.buttons
|
||||
if text.toLowerCase() in ['cancel', 'no']
|
||||
options.cancelId = i
|
||||
break
|
||||
|
||||
flags = if options.noLink then messageBoxOptions.noLink else 0
|
||||
|
||||
binding.showMessageBox messageBoxType,
|
||||
options.buttons,
|
||||
options.cancelId,
|
||||
flags,
|
||||
options.title,
|
||||
options.message,
|
||||
options.detail,
|
||||
options.icon,
|
||||
window,
|
||||
callback
|
||||
|
||||
showErrorBox: (args...) ->
|
||||
binding.showErrorBox args...
|
||||
|
||||
# Mark standard asynchronous functions.
|
||||
for api in ['showMessageBox', 'showOpenDialog', 'showSaveDialog']
|
||||
v8Util.setHiddenValue module.exports[api], 'asynchronous', true
|
||||
55
atom/browser/api/lib/exports/electron.coffee
Normal file
55
atom/browser/api/lib/exports/electron.coffee
Normal file
@@ -0,0 +1,55 @@
|
||||
# Import common modules.
|
||||
module.exports = require '../../../../common/api/lib/exports/electron'
|
||||
|
||||
Object.defineProperties module.exports,
|
||||
# Browser side modules, please sort with alphabet order.
|
||||
app:
|
||||
enumerable: true
|
||||
get: -> require '../app'
|
||||
autoUpdater:
|
||||
enumerable: true
|
||||
get: -> require '../auto-updater'
|
||||
BrowserWindow:
|
||||
enumerable: true
|
||||
get: -> require '../browser-window'
|
||||
contentTracing:
|
||||
enumerable: true
|
||||
get: -> require '../content-tracing'
|
||||
dialog:
|
||||
enumerable: true
|
||||
get: -> require '../dialog'
|
||||
ipcMain:
|
||||
enumerable: true
|
||||
get: -> require '../ipc-main'
|
||||
globalShortcut:
|
||||
enumerable: true
|
||||
get: -> require '../global-shortcut'
|
||||
Menu:
|
||||
enumerable: true
|
||||
get: -> require '../menu'
|
||||
MenuItem:
|
||||
enumerable: true
|
||||
get: -> require '../menu-item'
|
||||
powerMonitor:
|
||||
enumerable: true
|
||||
get: -> require '../power-monitor'
|
||||
powerSaveBlocker:
|
||||
enumerable: true
|
||||
get: -> require '../power-save-blocker'
|
||||
protocol:
|
||||
enumerable: true
|
||||
get: -> require '../protocol'
|
||||
screen:
|
||||
enumerable: true
|
||||
get: -> require '../screen'
|
||||
session:
|
||||
enumerable: true
|
||||
get: -> require '../session'
|
||||
Tray:
|
||||
enumerable: true
|
||||
get: -> require '../tray'
|
||||
# The internal modules, invisible unless you know their names.
|
||||
NavigationController:
|
||||
get: -> require '../navigation-controller'
|
||||
webContents:
|
||||
get: -> require '../web-contents'
|
||||
3
atom/browser/api/lib/global-shortcut.coffee
Normal file
3
atom/browser/api/lib/global-shortcut.coffee
Normal file
@@ -0,0 +1,3 @@
|
||||
{globalShortcut} = process.atomBinding 'global_shortcut'
|
||||
|
||||
module.exports = globalShortcut
|
||||
3
atom/browser/api/lib/ipc-main.coffee
Normal file
3
atom/browser/api/lib/ipc-main.coffee
Normal file
@@ -0,0 +1,3 @@
|
||||
{EventEmitter} = require 'events'
|
||||
|
||||
module.exports = new EventEmitter
|
||||
6
atom/browser/api/lib/ipc.coffee
Normal file
6
atom/browser/api/lib/ipc.coffee
Normal file
@@ -0,0 +1,6 @@
|
||||
{deprecate, ipcMain} = require 'electron'
|
||||
|
||||
# This module is deprecated, we mirror everything from ipcMain.
|
||||
deprecate.warn 'ipc module', 'require("electron").ipcMain'
|
||||
|
||||
module.exports = ipcMain
|
||||
71
atom/browser/api/lib/menu-item.coffee
Normal file
71
atom/browser/api/lib/menu-item.coffee
Normal file
@@ -0,0 +1,71 @@
|
||||
v8Util = process.atomBinding 'v8_util'
|
||||
|
||||
nextCommandId = 0
|
||||
|
||||
# Maps role to methods of webContents
|
||||
rolesMap =
|
||||
undo: 'undo'
|
||||
redo: 'redo'
|
||||
cut: 'cut'
|
||||
copy: 'copy'
|
||||
paste: 'paste'
|
||||
selectall: 'selectAll'
|
||||
minimize: 'minimize'
|
||||
close: 'close'
|
||||
|
||||
# Maps methods that should be called directly on the BrowserWindow instance
|
||||
methodInBrowserWindow =
|
||||
minimize: true
|
||||
close: true
|
||||
|
||||
class MenuItem
|
||||
@types = ['normal', 'separator', 'submenu', 'checkbox', 'radio']
|
||||
|
||||
constructor: (options) ->
|
||||
{Menu} = require 'electron'
|
||||
|
||||
{click, @selector, @type, @role, @label, @sublabel, @accelerator, @icon, @enabled, @visible, @checked, @submenu} = options
|
||||
|
||||
@type = 'submenu' if not @type? and @submenu?
|
||||
throw new Error('Invalid submenu') if @type is 'submenu' and @submenu?.constructor isnt Menu
|
||||
|
||||
@overrideReadOnlyProperty 'type', 'normal'
|
||||
@overrideReadOnlyProperty 'role'
|
||||
@overrideReadOnlyProperty 'accelerator'
|
||||
@overrideReadOnlyProperty 'icon'
|
||||
@overrideReadOnlyProperty 'submenu'
|
||||
@overrideProperty 'label', ''
|
||||
@overrideProperty 'sublabel', ''
|
||||
@overrideProperty 'enabled', true
|
||||
@overrideProperty 'visible', true
|
||||
@overrideProperty 'checked', false
|
||||
|
||||
throw new Error("Unknown menu type #{@type}") if MenuItem.types.indexOf(@type) is -1
|
||||
|
||||
@commandId = ++nextCommandId
|
||||
@click = (focusedWindow) =>
|
||||
# Manually flip the checked flags when clicked.
|
||||
@checked = !@checked if @type in ['checkbox', 'radio']
|
||||
|
||||
if @role and rolesMap[@role] and process.platform isnt 'darwin' and focusedWindow?
|
||||
methodName = rolesMap[@role]
|
||||
if methodInBrowserWindow[methodName]
|
||||
focusedWindow[methodName]()
|
||||
else
|
||||
focusedWindow.webContents?[methodName]()
|
||||
else if typeof click is 'function'
|
||||
click this, focusedWindow
|
||||
else if typeof @selector is 'string'
|
||||
Menu.sendActionToFirstResponder @selector
|
||||
|
||||
overrideProperty: (name, defaultValue=null) ->
|
||||
this[name] ?= defaultValue
|
||||
|
||||
overrideReadOnlyProperty: (name, defaultValue=null) ->
|
||||
this[name] ?= defaultValue
|
||||
Object.defineProperty this, name,
|
||||
enumerable: true
|
||||
writable: false
|
||||
value: this[name]
|
||||
|
||||
module.exports = MenuItem
|
||||
179
atom/browser/api/lib/menu.coffee
Normal file
179
atom/browser/api/lib/menu.coffee
Normal file
@@ -0,0 +1,179 @@
|
||||
{BrowserWindow, MenuItem} = require 'electron'
|
||||
{EventEmitter} = require 'events'
|
||||
|
||||
v8Util = process.atomBinding 'v8_util'
|
||||
bindings = process.atomBinding 'menu'
|
||||
|
||||
# Automatically generated radio menu item's group id.
|
||||
nextGroupId = 0
|
||||
|
||||
# Search between seperators to find a radio menu item and return its group id,
|
||||
# otherwise generate a group id.
|
||||
generateGroupId = (items, pos) ->
|
||||
if pos > 0
|
||||
for i in [pos - 1..0]
|
||||
item = items[i]
|
||||
return item.groupId if item.type is 'radio'
|
||||
break if item.type is 'separator'
|
||||
else if pos < items.length
|
||||
for i in [pos..items.length - 1]
|
||||
item = items[i]
|
||||
return item.groupId if item.type is 'radio'
|
||||
break if item.type is 'separator'
|
||||
++nextGroupId
|
||||
|
||||
# Returns the index of item according to |id|.
|
||||
indexOfItemById = (items, id) ->
|
||||
return i for item, i in items when item.id is id
|
||||
-1
|
||||
|
||||
# Returns the index of where to insert the item according to |position|.
|
||||
indexToInsertByPosition = (items, position) ->
|
||||
return items.length unless position
|
||||
|
||||
[query, id] = position.split '='
|
||||
insertIndex = indexOfItemById items, id
|
||||
if insertIndex is -1 and query isnt 'endof'
|
||||
console.warn "Item with id '#{id}' is not found"
|
||||
return items.length
|
||||
|
||||
switch query
|
||||
when 'after'
|
||||
insertIndex++
|
||||
when 'endof'
|
||||
# If the |id| doesn't exist, then create a new group with the |id|.
|
||||
if insertIndex is -1
|
||||
items.push id: id, type: 'separator'
|
||||
insertIndex = items.length - 1
|
||||
|
||||
# Find the end of the group.
|
||||
insertIndex++
|
||||
while insertIndex < items.length and items[insertIndex].type isnt 'separator'
|
||||
insertIndex++
|
||||
|
||||
insertIndex
|
||||
|
||||
Menu = bindings.Menu
|
||||
Menu::__proto__ = EventEmitter.prototype
|
||||
|
||||
Menu::_init = ->
|
||||
@commandsMap = {}
|
||||
@groupsMap = {}
|
||||
@items = []
|
||||
@delegate =
|
||||
isCommandIdChecked: (commandId) => @commandsMap[commandId]?.checked
|
||||
isCommandIdEnabled: (commandId) => @commandsMap[commandId]?.enabled
|
||||
isCommandIdVisible: (commandId) => @commandsMap[commandId]?.visible
|
||||
getAcceleratorForCommandId: (commandId) => @commandsMap[commandId]?.accelerator
|
||||
getIconForCommandId: (commandId) => @commandsMap[commandId]?.icon
|
||||
executeCommand: (commandId) =>
|
||||
@commandsMap[commandId]?.click BrowserWindow.getFocusedWindow()
|
||||
menuWillShow: =>
|
||||
# Make sure radio groups have at least one menu item seleted.
|
||||
for id, group of @groupsMap
|
||||
checked = false
|
||||
for radioItem in group when radioItem.checked
|
||||
checked = true
|
||||
break
|
||||
v8Util.setHiddenValue group[0], 'checked', true unless checked
|
||||
|
||||
Menu::popup = (window, x, y) ->
|
||||
unless window?.constructor is BrowserWindow
|
||||
# Shift.
|
||||
y = x
|
||||
x = window
|
||||
window = BrowserWindow.getFocusedWindow()
|
||||
if x? and y?
|
||||
@_popupAt(window, x, y)
|
||||
else
|
||||
@_popup window
|
||||
|
||||
Menu::append = (item) ->
|
||||
@insert @getItemCount(), item
|
||||
|
||||
Menu::insert = (pos, item) ->
|
||||
throw new TypeError('Invalid item') unless item?.constructor is MenuItem
|
||||
|
||||
switch item.type
|
||||
when 'normal' then @insertItem pos, item.commandId, item.label
|
||||
when 'checkbox' then @insertCheckItem pos, item.commandId, item.label
|
||||
when 'separator' then @insertSeparator pos
|
||||
when 'submenu' then @insertSubMenu pos, item.commandId, item.label, item.submenu
|
||||
when 'radio'
|
||||
# Grouping radio menu items.
|
||||
item.overrideReadOnlyProperty 'groupId', generateGroupId(@items, pos)
|
||||
@groupsMap[item.groupId] ?= []
|
||||
@groupsMap[item.groupId].push item
|
||||
|
||||
# Setting a radio menu item should flip other items in the group.
|
||||
v8Util.setHiddenValue item, 'checked', item.checked
|
||||
Object.defineProperty item, 'checked',
|
||||
enumerable: true
|
||||
get: -> v8Util.getHiddenValue item, 'checked'
|
||||
set: (val) =>
|
||||
for otherItem in @groupsMap[item.groupId] when otherItem isnt item
|
||||
v8Util.setHiddenValue otherItem, 'checked', false
|
||||
v8Util.setHiddenValue item, 'checked', true
|
||||
|
||||
@insertRadioItem pos, item.commandId, item.label, item.groupId
|
||||
|
||||
@setSublabel pos, item.sublabel if item.sublabel?
|
||||
@setIcon pos, item.icon if item.icon?
|
||||
@setRole pos, item.role if item.role?
|
||||
|
||||
# Make menu accessable to items.
|
||||
item.overrideReadOnlyProperty 'menu', this
|
||||
|
||||
# Remember the items.
|
||||
@items.splice pos, 0, item
|
||||
@commandsMap[item.commandId] = item
|
||||
|
||||
# Force menuWillShow to be called
|
||||
Menu::_callMenuWillShow = ->
|
||||
@delegate?.menuWillShow()
|
||||
item.submenu._callMenuWillShow() for item in @items when item.submenu?
|
||||
|
||||
applicationMenu = null
|
||||
Menu.setApplicationMenu = (menu) ->
|
||||
throw new TypeError('Invalid menu') unless menu is null or menu.constructor is Menu
|
||||
applicationMenu = menu # Keep a reference.
|
||||
|
||||
if process.platform is 'darwin'
|
||||
return if menu is null
|
||||
menu._callMenuWillShow()
|
||||
bindings.setApplicationMenu menu
|
||||
else
|
||||
windows = BrowserWindow.getAllWindows()
|
||||
w.setMenu menu for w in windows
|
||||
|
||||
Menu.getApplicationMenu = -> applicationMenu
|
||||
|
||||
Menu.sendActionToFirstResponder = bindings.sendActionToFirstResponder
|
||||
|
||||
Menu.buildFromTemplate = (template) ->
|
||||
throw new TypeError('Invalid template for Menu') unless Array.isArray template
|
||||
|
||||
positionedTemplate = []
|
||||
insertIndex = 0
|
||||
|
||||
for item in template
|
||||
if item.position
|
||||
insertIndex = indexToInsertByPosition positionedTemplate, item.position
|
||||
else
|
||||
# If no |position| is specified, insert after last item.
|
||||
insertIndex++
|
||||
positionedTemplate.splice insertIndex, 0, item
|
||||
|
||||
menu = new Menu
|
||||
|
||||
for item in positionedTemplate
|
||||
throw new TypeError('Invalid template for MenuItem') unless typeof item is 'object'
|
||||
|
||||
item.submenu = Menu.buildFromTemplate item.submenu if item.submenu?
|
||||
menuItem = new MenuItem(item)
|
||||
menuItem[key] = value for key, value of item when not menuItem[key]?
|
||||
menu.append menuItem
|
||||
|
||||
menu
|
||||
|
||||
module.exports = Menu
|
||||
122
atom/browser/api/lib/navigation-controller.coffee
Normal file
122
atom/browser/api/lib/navigation-controller.coffee
Normal file
@@ -0,0 +1,122 @@
|
||||
{ipcMain} = require 'electron'
|
||||
|
||||
# The history operation in renderer is redirected to browser.
|
||||
ipcMain.on 'ATOM_SHELL_NAVIGATION_CONTROLLER', (event, method, args...) ->
|
||||
event.sender[method] args...
|
||||
|
||||
ipcMain.on 'ATOM_SHELL_SYNC_NAVIGATION_CONTROLLER', (event, method, args...) ->
|
||||
event.returnValue = event.sender[method] args...
|
||||
|
||||
# JavaScript implementation of Chromium's NavigationController.
|
||||
# Instead of relying on Chromium for history control, we compeletely do history
|
||||
# control on user land, and only rely on WebContents.loadURL for navigation.
|
||||
# This helps us avoid Chromium's various optimizations so we can ensure renderer
|
||||
# process is restarted everytime.
|
||||
class NavigationController
|
||||
constructor: (@webContents) ->
|
||||
@clearHistory()
|
||||
|
||||
# webContents may have already navigated to a page.
|
||||
if @webContents._getURL()
|
||||
@currentIndex++
|
||||
@history.push @webContents._getURL()
|
||||
|
||||
@webContents.on 'navigation-entry-commited', (event, url, inPage, replaceEntry) =>
|
||||
if @inPageIndex > -1 and not inPage
|
||||
# Navigated to a new page, clear in-page mark.
|
||||
@inPageIndex = -1
|
||||
else if @inPageIndex is -1 and inPage
|
||||
# Started in-page navigations.
|
||||
@inPageIndex = @currentIndex
|
||||
|
||||
if @pendingIndex >= 0 # Go to index.
|
||||
@currentIndex = @pendingIndex
|
||||
@pendingIndex = -1
|
||||
@history[@currentIndex] = url
|
||||
else if replaceEntry # Non-user initialized navigation.
|
||||
@history[@currentIndex] = url
|
||||
else # Normal navigation.
|
||||
@history = @history.slice 0, @currentIndex + 1 # Clear history.
|
||||
currentEntry = @history[@currentIndex]
|
||||
if currentEntry?.url isnt url
|
||||
@currentIndex++
|
||||
@history.push url
|
||||
|
||||
loadURL: (url, options={}) ->
|
||||
@pendingIndex = -1
|
||||
@webContents._loadURL url, options
|
||||
@webContents.emit 'load-url', url, options
|
||||
|
||||
getURL: ->
|
||||
if @currentIndex is -1
|
||||
''
|
||||
else
|
||||
@history[@currentIndex]
|
||||
|
||||
stop: ->
|
||||
@pendingIndex = -1
|
||||
@webContents._stop()
|
||||
|
||||
reload: ->
|
||||
@pendingIndex = @currentIndex
|
||||
@webContents._loadURL @getURL(), {}
|
||||
|
||||
reloadIgnoringCache: ->
|
||||
@pendingIndex = @currentIndex
|
||||
@webContents._loadURL @getURL(), {extraHeaders: "pragma: no-cache\n"}
|
||||
|
||||
canGoBack: ->
|
||||
@getActiveIndex() > 0
|
||||
|
||||
canGoForward: ->
|
||||
@getActiveIndex() < @history.length - 1
|
||||
|
||||
canGoToIndex: (index) ->
|
||||
index >=0 and index < @history.length
|
||||
|
||||
canGoToOffset: (offset) ->
|
||||
@canGoToIndex @currentIndex + offset
|
||||
|
||||
clearHistory: ->
|
||||
@history = []
|
||||
@currentIndex = -1
|
||||
@pendingIndex = -1
|
||||
@inPageIndex = -1
|
||||
|
||||
goBack: ->
|
||||
return unless @canGoBack()
|
||||
@pendingIndex = @getActiveIndex() - 1
|
||||
if @inPageIndex > -1 and @pendingIndex >= @inPageIndex
|
||||
@webContents._goBack()
|
||||
else
|
||||
@webContents._loadURL @history[@pendingIndex], {}
|
||||
|
||||
goForward: ->
|
||||
return unless @canGoForward()
|
||||
@pendingIndex = @getActiveIndex() + 1
|
||||
if @inPageIndex > -1 and @pendingIndex >= @inPageIndex
|
||||
@webContents._goForward()
|
||||
else
|
||||
@webContents._loadURL @history[@pendingIndex], {}
|
||||
|
||||
goToIndex: (index) ->
|
||||
return unless @canGoToIndex index
|
||||
@pendingIndex = index
|
||||
@webContents._loadURL @history[@pendingIndex], {}
|
||||
|
||||
goToOffset: (offset) ->
|
||||
return unless @canGoToOffset offset
|
||||
pendingIndex = @currentIndex + offset
|
||||
if @inPageIndex > -1 and pendingIndex >= @inPageIndex
|
||||
@pendingIndex = pendingIndex
|
||||
@webContents._goToOffset offset
|
||||
else
|
||||
@goToIndex pendingIndex
|
||||
|
||||
getActiveIndex: ->
|
||||
if @pendingIndex is -1 then @currentIndex else @pendingIndex
|
||||
|
||||
length: ->
|
||||
@history.length
|
||||
|
||||
module.exports = NavigationController
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user