commit
c5dee6a3d8
341 changed files with 10067 additions and 2156 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,4 +1,5 @@
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
.tags*
|
||||||
/.idea/
|
/.idea/
|
||||||
/build/
|
/build/
|
||||||
/dist/
|
/dist/
|
||||||
|
|
24
CODE_OF_CONDUCT.md
Normal file
24
CODE_OF_CONDUCT.md
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
# Contributor Code of Conduct
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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
|
||||||
|
- 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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
This Code of Conduct is adapted from the Contributor Covenant, version 1.3.0, available from http://contributor-covenant.org/version/1/3/0/
|
80
CONTRIBUTING-ko.md
Normal file
80
CONTRIBUTING-ko.md
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
# Electron에 기여하기
|
||||||
|
|
||||||
|
:+1::tada: 먼저, 이 프로젝트에 기여해주셔서 감사합니다! :tada::+1:
|
||||||
|
|
||||||
|
이 프로젝트는 기여자 규약 [행동강령](CODE_OF_CONDUCT.md)을 준수합니다. 따라서 이
|
||||||
|
프로젝트의 개발에 참여하려면 이 규약을 지켜야 합니다. 받아들일 수 없는 행위를 발견했을
|
||||||
|
경우 atom@github.com로 보고 하십시오.
|
||||||
|
|
||||||
|
다음 항목들은 Electron에 기여하는 가이드라인을 제시합니다.
|
||||||
|
참고로 이 항목들은 그저 가이드라인에 불과하며 규칙이 아닙니다. 따라서 스스로의 적절한
|
||||||
|
판단에 따라 이 문서의 변경을 제안할 수 있으며 변경시 pull request를 넣으면 됩니다.
|
||||||
|
|
||||||
|
## 이슈 제출
|
||||||
|
|
||||||
|
* [여기](https://github.com/atom/electron/issues/new)에서 새로운 이슈를 만들 수
|
||||||
|
있습니다. 하지만 이슈를 작성하기 전에 아래의 항목들을 숙지하고 가능한한 이슈 보고에
|
||||||
|
대해 최대한 많은 정보와 자세한 설명을 포함해야 합니다. 가능하다면 다음 항목을 포함해야
|
||||||
|
합니다:
|
||||||
|
* 사용하고 있는 Electron의 버전
|
||||||
|
* 현재 사용중인 운영체제
|
||||||
|
* 가능하다면 무엇을 하려고 했고, 어떤 결과를 예측했으며, 어떤 것이 예측된대로
|
||||||
|
작동하지 않았는지에 대해 서술해야 합니다.
|
||||||
|
* 추가로 다음 사항을 준수하면 이슈를 해결하는데 큰 도움이 됩니다:
|
||||||
|
* 스크린샷 또는 GIF 애니메이션 이미지들
|
||||||
|
* 터미널에 출력된 에러의 내용 또는 개발자 도구, 알림창에 뜬 내용
|
||||||
|
* [Cursory search](https://github.com/atom/electron/issues?utf8=✓&q=is%3Aissue+)를
|
||||||
|
통해 이미 비슷한 내용의 이슈가 등록되어있는지 확인
|
||||||
|
|
||||||
|
## Pull Request 하기
|
||||||
|
|
||||||
|
* 가능한한 스크린샷과 GIF 애니메이션 이미지를 pull request에 추가
|
||||||
|
* 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-커밋-메시지)를
|
||||||
|
참고하세요
|
||||||
|
|
||||||
|
## 스타일 가이드
|
||||||
|
|
||||||
|
### 공통 코드
|
||||||
|
|
||||||
|
* 파일 마지막에 공백 라인(newline) 추가
|
||||||
|
* 다음 순서에 맞춰서 require 코드 작성:
|
||||||
|
* Node 빌트인 모듈 (`path` 같은)
|
||||||
|
* Electron 모듈 (`ipc`, `app` 같은)
|
||||||
|
* 로컬 모듈 (상대 경로상에 있는)
|
||||||
|
* 다음 순서에 맞춰서 클래스 속성 지정:
|
||||||
|
* 클래스 메서드와 속성 (메서드는 `@`로 시작)
|
||||||
|
* 인스턴스 메서드와 속성
|
||||||
|
* 플랫폼 종속적인 코드 자제:
|
||||||
|
* 파일 이름 결합시 `path.join()`을 사용.
|
||||||
|
* 임시 디렉터리가 필요할 땐 `/tmp` 대신 `os.tmpdir()`을 통해 접근.
|
||||||
|
* 명시적인 함수 종료가 필요할 땐 `return` 만 사용.
|
||||||
|
* `return null`, `return undefined`, `null`, 또는 `undefined` 사용 X
|
||||||
|
|
||||||
|
### Git 커밋 메시지
|
||||||
|
|
||||||
|
* 현재 시제 사용 ("Added feature" 대신 "Add feature" 사용)
|
||||||
|
* 필수적 분위기(imperative mood) 사용 ("Moves cursor to..." 대신 "Move cursor to..." 사용)
|
||||||
|
* 첫 줄은 72자에 맞추거나 그 보다 적게 제한
|
||||||
|
* 자유롭게 필요에 따라 이슈나 PR링크를 참조
|
||||||
|
* 단순한 문서 변경일 경우 `[ci skip]`을 커밋 메시지에 추가
|
||||||
|
* 커밋 메시지의 도입부에 의미있는 이모티콘 사용:
|
||||||
|
* :art: `:art:` 코드의 포맷이나 구조를 개선(추가)했을 때
|
||||||
|
* :racehorse: `:racehorse:` 성능을 개선했을 때
|
||||||
|
* :non-potable_water: `:non-potable_water:` 메모리 누수를 연결했을 때
|
||||||
|
* :memo: `:memo:` 문서를 작성했을 때
|
||||||
|
* :penguin: `:penguin:` Linux에 대한 패치를 했을 때
|
||||||
|
* :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:` 종속성 라이브러리를 다운그레이드 했을 때
|
||||||
|
* :shirt: `:shirt:` linter(코드 검사기)의 경고를 제거했을 때
|
|
@ -2,8 +2,9 @@
|
||||||
|
|
||||||
:+1::tada: First off, thanks for taking the time to contribute! :tada::+1:
|
:+1::tada: First off, thanks for taking the time to contribute! :tada::+1:
|
||||||
|
|
||||||
This project adheres to the [Contributor Covenant 1.2](http://contributor-covenant.org/version/1/2/0).
|
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 atom@github.com.
|
By participating, you are expected to uphold this code. Please report unacceptable
|
||||||
|
behavior to atom@github.com.
|
||||||
|
|
||||||
The following is a set of guidelines for contributing to Electron.
|
The following is a set of guidelines for contributing to Electron.
|
||||||
These are just guidelines, not rules, use your best judgment and feel free to
|
These are just guidelines, not rules, use your best judgment and feel free to
|
||||||
|
@ -57,6 +58,7 @@ possible with your report. If you can, please include:
|
||||||
* Use the imperative mood ("Move cursor to..." not "Moves cursor to...")
|
* Use the imperative mood ("Move cursor to..." not "Moves cursor to...")
|
||||||
* Limit the first line to 72 characters or less
|
* Limit the first line to 72 characters or less
|
||||||
* Reference issues and pull requests liberally
|
* Reference issues and pull requests liberally
|
||||||
|
* When only changing documentation, include `[ci skip]` in the commit description
|
||||||
* Consider starting the commit message with an applicable emoji:
|
* Consider starting the commit message with an applicable emoji:
|
||||||
* :art: `:art:` when improving the format/structure of the code
|
* :art: `:art:` when improving the format/structure of the code
|
||||||
* :racehorse: `:racehorse:` when improving performance
|
* :racehorse: `:racehorse:` when improving performance
|
||||||
|
|
11
README-ko.md
11
README-ko.md
|
@ -16,9 +16,9 @@ Cross-Platform 데스크톱 어플리케이션을 개발할 수 있도록 해주
|
||||||
Electron에 대한 중요한 알림을 받고 싶다면 Twitter에서
|
Electron에 대한 중요한 알림을 받고 싶다면 Twitter에서
|
||||||
[@ElectronJS](https://twitter.com/electronjs)를 팔로우 하세요.
|
[@ElectronJS](https://twitter.com/electronjs)를 팔로우 하세요.
|
||||||
|
|
||||||
이 프로젝트는 [기여자 규약 1.2](http://contributor-covenant.org/version/1/2/0/)을
|
이 프로젝트는 기여자 규약 [행동강령](CODE_OF_CONDUCT.md)을 준수합니다. 따라서 이
|
||||||
준수합니다. 따라서 이 프로젝트의 개발에 참여하려면 이 계약을 지켜야 합니다. 받아들일 수
|
프로젝트의 개발에 참여하려면 이 규약을 지켜야 합니다. 받아들일 수 없는 행위를 발견했을
|
||||||
없는 행위를 발견했을 경우 atom@github.com로 보고 하십시오.
|
경우 atom@github.com로 보고 하십시오.
|
||||||
|
|
||||||
## 다운로드
|
## 다운로드
|
||||||
|
|
||||||
|
@ -49,12 +49,14 @@ API 레퍼런스가 있습니다. Electron을 빌드 하는 방법과 프로젝
|
||||||
|
|
||||||
## 참조 문서 (번역)
|
## 참조 문서 (번역)
|
||||||
|
|
||||||
- [브라질 포르투칼어](https://github.com/atom/electron/tree/master/docs-translations/pt-BR)
|
- [브라질 포르투갈어](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/ko-KR)
|
||||||
- [일본어](https://github.com/atom/electron/tree/master/docs-translations/jp)
|
- [일본어](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/es)
|
||||||
- [중국어 간체](https://github.com/atom/electron/tree/master/docs-translations/zh-CN)
|
- [중국어 간체](https://github.com/atom/electron/tree/master/docs-translations/zh-CN)
|
||||||
- [중국어 번체](https://github.com/atom/electron/tree/master/docs-translations/zh-TW)
|
- [중국어 번체](https://github.com/atom/electron/tree/master/docs-translations/zh-TW)
|
||||||
|
- [우크라이나어](https://github.com/atom/electron/tree/master/docs-translations/uk-UA)
|
||||||
|
- [러시아어](https://github.com/atom/electron/tree/master/docs-translations/ru-RU)
|
||||||
|
|
||||||
## 시작하기
|
## 시작하기
|
||||||
|
|
||||||
|
@ -68,6 +70,7 @@ API 레퍼런스가 있습니다. Electron을 빌드 하는 방법과 프로젝
|
||||||
- Atom 포럼의 [`electron`](http://discuss.atom.io/c/electron) 카테고리
|
- Atom 포럼의 [`electron`](http://discuss.atom.io/c/electron) 카테고리
|
||||||
- Freenode 채팅의 `#atom-shell` 채널
|
- Freenode 채팅의 `#atom-shell` 채널
|
||||||
- Slack의 [`Atom`](http://atom-slack.herokuapp.com/) 채널
|
- Slack의 [`Atom`](http://atom-slack.herokuapp.com/) 채널
|
||||||
|
- [`electron-br`](https://electron-br.slack.com) *(브라질 포르투갈어)*
|
||||||
|
|
||||||
[awesome-electron](https://github.com/sindresorhus/awesome-electron) 프로젝트에
|
[awesome-electron](https://github.com/sindresorhus/awesome-electron) 프로젝트에
|
||||||
커뮤니티가 운영중인 유용한 예제 어플리케이션과 도구, 리소스가 있으니 한번 참고해 보시기
|
커뮤니티가 운영중인 유용한 예제 어플리케이션과 도구, 리소스가 있으니 한번 참고해 보시기
|
||||||
|
|
|
@ -14,9 +14,9 @@ editor](https://github.com/atom/atom).
|
||||||
Follow [@ElectronJS](https://twitter.com/electronjs) on Twitter for important
|
Follow [@ElectronJS](https://twitter.com/electronjs) on Twitter for important
|
||||||
announcements.
|
announcements.
|
||||||
|
|
||||||
This project adheres to the [Contributor Covenant 1.2](http://contributor-covenant.org/version/1/2/0/).
|
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
|
By participating, you are expected to uphold this code. Please report unacceptable
|
||||||
unacceptable behavior to atom@github.com.
|
behavior to atom@github.com.
|
||||||
|
|
||||||
## Downloads
|
## Downloads
|
||||||
|
|
||||||
|
@ -52,6 +52,8 @@ contains documents describing how to build and contribute to Electron.
|
||||||
- [Spanish](https://github.com/atom/electron/tree/master/docs-translations/es)
|
- [Spanish](https://github.com/atom/electron/tree/master/docs-translations/es)
|
||||||
- [Simplified Chinese](https://github.com/atom/electron/tree/master/docs-translations/zh-CN)
|
- [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)
|
- [Traditional Chinese](https://github.com/atom/electron/tree/master/docs-translations/zh-TW)
|
||||||
|
- [Ukrainian](https://github.com/atom/electron/tree/master/docs-translations/uk-UA)
|
||||||
|
- [Russian](https://github.com/atom/electron/tree/master/docs-translations/ru-RU)
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
|
@ -66,6 +68,7 @@ locations:
|
||||||
forums
|
forums
|
||||||
- `#atom-shell` channel on Freenode
|
- `#atom-shell` channel on Freenode
|
||||||
- [`Atom`](http://atom-slack.herokuapp.com/) channel on Slack
|
- [`Atom`](http://atom-slack.herokuapp.com/) channel on Slack
|
||||||
|
- [`electron-br`](https://electron-br.slack.com) *(Brazilian Portuguese)*
|
||||||
|
|
||||||
Check out [awesome-electron](https://github.com/sindresorhus/awesome-electron)
|
Check out [awesome-electron](https://github.com/sindresorhus/awesome-electron)
|
||||||
for a community maintained list of useful example apps, tools and resources.
|
for a community maintained list of useful example apps, tools and resources.
|
||||||
|
|
23
appveyor.yml
Normal file
23
appveyor.yml
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
# appveyor file
|
||||||
|
# http://www.appveyor.com/docs/appveyor-yml
|
||||||
|
version: "{build}"
|
||||||
|
|
||||||
|
init:
|
||||||
|
- git config --global core.autocrlf input
|
||||||
|
|
||||||
|
platform:
|
||||||
|
- x86
|
||||||
|
- x64
|
||||||
|
|
||||||
|
install:
|
||||||
|
- cmd: SET PATH=C:\Program Files (x86)\MSBuild\12.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
|
52
atom.gyp
52
atom.gyp
|
@ -4,7 +4,7 @@
|
||||||
'product_name%': 'Electron',
|
'product_name%': 'Electron',
|
||||||
'company_name%': 'GitHub, Inc',
|
'company_name%': 'GitHub, Inc',
|
||||||
'company_abbr%': 'github',
|
'company_abbr%': 'github',
|
||||||
'version%': '0.35.1',
|
'version%': '0.36.2',
|
||||||
},
|
},
|
||||||
'includes': [
|
'includes': [
|
||||||
'filenames.gypi',
|
'filenames.gypi',
|
||||||
|
@ -121,10 +121,6 @@
|
||||||
],
|
],
|
||||||
}],
|
}],
|
||||||
],
|
],
|
||||||
}, { # OS=="mac"
|
|
||||||
'dependencies': [
|
|
||||||
'make_locale_paks',
|
|
||||||
],
|
|
||||||
}], # OS!="mac"
|
}], # OS!="mac"
|
||||||
['OS=="win"', {
|
['OS=="win"', {
|
||||||
'include_dirs': [
|
'include_dirs': [
|
||||||
|
@ -155,6 +151,7 @@
|
||||||
'destination': '<(PRODUCT_DIR)',
|
'destination': '<(PRODUCT_DIR)',
|
||||||
'files': [
|
'files': [
|
||||||
'<@(copied_libraries)',
|
'<@(copied_libraries)',
|
||||||
|
'<(libchromiumcontent_dir)/locales',
|
||||||
'<(libchromiumcontent_dir)/libEGL.dll',
|
'<(libchromiumcontent_dir)/libEGL.dll',
|
||||||
'<(libchromiumcontent_dir)/libGLESv2.dll',
|
'<(libchromiumcontent_dir)/libGLESv2.dll',
|
||||||
'<(libchromiumcontent_dir)/icudtl.dat',
|
'<(libchromiumcontent_dir)/icudtl.dat',
|
||||||
|
@ -203,6 +200,7 @@
|
||||||
'destination': '<(PRODUCT_DIR)',
|
'destination': '<(PRODUCT_DIR)',
|
||||||
'files': [
|
'files': [
|
||||||
'<@(copied_libraries)',
|
'<@(copied_libraries)',
|
||||||
|
'<(libchromiumcontent_dir)/locales',
|
||||||
'<(libchromiumcontent_dir)/icudtl.dat',
|
'<(libchromiumcontent_dir)/icudtl.dat',
|
||||||
'<(libchromiumcontent_dir)/content_shell.pak',
|
'<(libchromiumcontent_dir)/content_shell.pak',
|
||||||
'<(libchromiumcontent_dir)/natives_blob.bin',
|
'<(libchromiumcontent_dir)/natives_blob.bin',
|
||||||
|
@ -235,6 +233,8 @@
|
||||||
# Defined in Chromium but not exposed in its gyp file.
|
# Defined in Chromium but not exposed in its gyp file.
|
||||||
'V8_USE_EXTERNAL_STARTUP_DATA',
|
'V8_USE_EXTERNAL_STARTUP_DATA',
|
||||||
'ENABLE_PLUGINS',
|
'ENABLE_PLUGINS',
|
||||||
|
'ENABLE_PEPPER_CDMS',
|
||||||
|
'USE_PROPRIETARY_CODECS',
|
||||||
],
|
],
|
||||||
'sources': [
|
'sources': [
|
||||||
'<@(lib_sources)',
|
'<@(lib_sources)',
|
||||||
|
@ -256,6 +256,12 @@
|
||||||
'vendor/node/deps/cares/include',
|
'vendor/node/deps/cares/include',
|
||||||
# The `third_party/WebKit/Source/platform/weborigin/SchemeRegistry.h` is using `platform/PlatformExport.h`.
|
# The `third_party/WebKit/Source/platform/weborigin/SchemeRegistry.h` is using `platform/PlatformExport.h`.
|
||||||
'<(libchromiumcontent_src_dir)/third_party/WebKit/Source',
|
'<(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': {
|
'direct_dependent_settings': {
|
||||||
'include_dirs': [
|
'include_dirs': [
|
||||||
|
@ -282,6 +288,7 @@
|
||||||
'-lcomctl32.lib',
|
'-lcomctl32.lib',
|
||||||
'-lcomdlg32.lib',
|
'-lcomdlg32.lib',
|
||||||
'-lwininet.lib',
|
'-lwininet.lib',
|
||||||
|
'-lwinmm.lib',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
'dependencies': [
|
'dependencies': [
|
||||||
|
@ -493,6 +500,16 @@
|
||||||
'Libraries',
|
'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': [
|
'conditions': [
|
||||||
['mas_build==0', {
|
['mas_build==0', {
|
||||||
|
@ -537,31 +554,6 @@
|
||||||
},
|
},
|
||||||
}, # target helper
|
}, # 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"
|
}], # OS!="mac"
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,12 +11,21 @@
|
||||||
#include "atom/common/chrome_version.h"
|
#include "atom/common/chrome_version.h"
|
||||||
#include "atom/common/options_switches.h"
|
#include "atom/common/options_switches.h"
|
||||||
#include "base/command_line.h"
|
#include "base/command_line.h"
|
||||||
|
#include "base/files/file_util.h"
|
||||||
#include "base/strings/string_split.h"
|
#include "base/strings/string_split.h"
|
||||||
#include "base/strings/string_util.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/content_constants.h"
|
||||||
#include "content/public/common/pepper_plugin_info.h"
|
#include "content/public/common/pepper_plugin_info.h"
|
||||||
#include "content/public/common/user_agent.h"
|
#include "content/public/common/user_agent.h"
|
||||||
#include "ppapi/shared_impl/ppapi_permissions.h"
|
#include "ppapi/shared_impl/ppapi_permissions.h"
|
||||||
|
#include "third_party/widevine/cdm/stub/widevine_cdm_version.h"
|
||||||
|
#include "ui/base/l10n/l10n_util.h"
|
||||||
|
#include "url/url_constants.h"
|
||||||
|
|
||||||
|
#if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
|
||||||
|
#include "chrome/common/widevine_cdm_constants.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace atom {
|
namespace atom {
|
||||||
|
|
||||||
|
@ -31,8 +40,8 @@ content::PepperPluginInfo CreatePepperFlashInfo(const base::FilePath& path,
|
||||||
plugin.path = path;
|
plugin.path = path;
|
||||||
plugin.permissions = ppapi::PERMISSION_ALL_BITS;
|
plugin.permissions = ppapi::PERMISSION_ALL_BITS;
|
||||||
|
|
||||||
std::vector<std::string> flash_version_numbers;
|
std::vector<std::string> flash_version_numbers = base::SplitString(
|
||||||
base::SplitString(version, '.', &flash_version_numbers);
|
version, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
|
||||||
if (flash_version_numbers.size() < 1)
|
if (flash_version_numbers.size() < 1)
|
||||||
flash_version_numbers.push_back("11");
|
flash_version_numbers.push_back("11");
|
||||||
// |SplitString()| puts in an empty string given an empty string. :(
|
// |SplitString()| puts in an empty string given an empty string. :(
|
||||||
|
@ -47,7 +56,7 @@ content::PepperPluginInfo CreatePepperFlashInfo(const base::FilePath& path,
|
||||||
// E.g., "Shockwave Flash 10.2 r154":
|
// E.g., "Shockwave Flash 10.2 r154":
|
||||||
plugin.description = plugin.name + " " + flash_version_numbers[0] + "." +
|
plugin.description = plugin.name + " " + flash_version_numbers[0] + "." +
|
||||||
flash_version_numbers[1] + " r" + flash_version_numbers[2];
|
flash_version_numbers[1] + " r" + flash_version_numbers[2];
|
||||||
plugin.version = JoinString(flash_version_numbers, '.');
|
plugin.version = base::JoinString(flash_version_numbers, ".");
|
||||||
content::WebPluginMimeType swf_mime_type(
|
content::WebPluginMimeType swf_mime_type(
|
||||||
content::kFlashPluginSwfMimeType,
|
content::kFlashPluginSwfMimeType,
|
||||||
content::kFlashPluginSwfExtension,
|
content::kFlashPluginSwfExtension,
|
||||||
|
@ -62,8 +71,95 @@ content::PepperPluginInfo CreatePepperFlashInfo(const base::FilePath& path,
|
||||||
return plugin;
|
return plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
|
||||||
|
content::PepperPluginInfo CreateWidevineCdmInfo(const base::FilePath& path,
|
||||||
|
const std::string& version) {
|
||||||
|
content::PepperPluginInfo widevine_cdm;
|
||||||
|
widevine_cdm.is_out_of_process = true;
|
||||||
|
widevine_cdm.path = path;
|
||||||
|
widevine_cdm.name = kWidevineCdmDisplayName;
|
||||||
|
widevine_cdm.description = kWidevineCdmDescription +
|
||||||
|
std::string(" (version: ") +
|
||||||
|
version + ")";
|
||||||
|
widevine_cdm.version = version;
|
||||||
|
content::WebPluginMimeType widevine_cdm_mime_type(
|
||||||
|
kWidevineCdmPluginMimeType,
|
||||||
|
kWidevineCdmPluginExtension,
|
||||||
|
kWidevineCdmPluginMimeTypeDescription);
|
||||||
|
|
||||||
|
// Add the supported codecs as if they came from the component manifest.
|
||||||
|
std::vector<std::string> codecs;
|
||||||
|
codecs.push_back(kCdmSupportedCodecVorbis);
|
||||||
|
codecs.push_back(kCdmSupportedCodecVp8);
|
||||||
|
codecs.push_back(kCdmSupportedCodecVp9);
|
||||||
|
#if defined(USE_PROPRIETARY_CODECS)
|
||||||
|
codecs.push_back(kCdmSupportedCodecAac);
|
||||||
|
codecs.push_back(kCdmSupportedCodecAvc1);
|
||||||
|
#endif // defined(USE_PROPRIETARY_CODECS)
|
||||||
|
std::string codec_string = base::JoinString(
|
||||||
|
codecs, std::string(1, kCdmSupportedCodecsValueDelimiter));
|
||||||
|
widevine_cdm_mime_type.additional_param_names.push_back(
|
||||||
|
base::ASCIIToUTF16(kCdmSupportedCodecsParamName));
|
||||||
|
widevine_cdm_mime_type.additional_param_values.push_back(
|
||||||
|
base::ASCIIToUTF16(codec_string));
|
||||||
|
|
||||||
|
widevine_cdm.mime_types.push_back(widevine_cdm_mime_type);
|
||||||
|
widevine_cdm.permissions = kWidevineCdmPluginPermissions;
|
||||||
|
|
||||||
|
return widevine_cdm;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void ConvertStringWithSeparatorToVector(std::vector<std::string>* vec,
|
||||||
|
const char* separator,
|
||||||
|
const char* cmd_switch) {
|
||||||
|
auto command_line = base::CommandLine::ForCurrentProcess();
|
||||||
|
auto string_with_separator = command_line->GetSwitchValueASCII(cmd_switch);
|
||||||
|
if (!string_with_separator.empty())
|
||||||
|
*vec = base::SplitString(string_with_separator, separator,
|
||||||
|
base::TRIM_WHITESPACE,
|
||||||
|
base::SPLIT_WANT_NONEMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
void AddPepperFlashFromCommandLine(
|
||||||
|
std::vector<content::PepperPluginInfo>* plugins) {
|
||||||
|
auto command_line = base::CommandLine::ForCurrentProcess();
|
||||||
|
auto flash_path = command_line->GetSwitchValueNative(
|
||||||
|
switches::kPpapiFlashPath);
|
||||||
|
if (flash_path.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto flash_version = command_line->GetSwitchValueASCII(
|
||||||
|
switches::kPpapiFlashVersion);
|
||||||
|
|
||||||
|
plugins->push_back(
|
||||||
|
CreatePepperFlashInfo(base::FilePath(flash_path), flash_version));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
|
||||||
|
void AddWidevineCdmFromCommandLine(
|
||||||
|
std::vector<content::PepperPluginInfo>* plugins) {
|
||||||
|
auto command_line = base::CommandLine::ForCurrentProcess();
|
||||||
|
auto widevine_cdm_path = command_line->GetSwitchValueNative(
|
||||||
|
switches::kWidevineCdmPath);
|
||||||
|
if (widevine_cdm_path.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!base::PathExists(base::FilePath(widevine_cdm_path)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto widevine_cdm_version = command_line->GetSwitchValueASCII(
|
||||||
|
switches::kWidevineCdmVersion);
|
||||||
|
if (widevine_cdm_version.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
plugins->push_back(CreateWidevineCdmInfo(base::FilePath(widevine_cdm_path),
|
||||||
|
widevine_cdm_version));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
AtomContentClient::AtomContentClient() {
|
AtomContentClient::AtomContentClient() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,35 +176,41 @@ std::string AtomContentClient::GetUserAgent() const {
|
||||||
ATOM_PRODUCT_NAME "/" ATOM_VERSION_STRING);
|
ATOM_PRODUCT_NAME "/" ATOM_VERSION_STRING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
base::string16 AtomContentClient::GetLocalizedString(int message_id) const {
|
||||||
|
return l10n_util::GetStringUTF16(message_id);
|
||||||
|
}
|
||||||
|
|
||||||
void AtomContentClient::AddAdditionalSchemes(
|
void AtomContentClient::AddAdditionalSchemes(
|
||||||
std::vector<std::string>* standard_schemes,
|
std::vector<url::SchemeWithType>* standard_schemes,
|
||||||
std::vector<std::string>* savable_schemes) {
|
std::vector<std::string>* savable_schemes) {
|
||||||
auto command_line = base::CommandLine::ForCurrentProcess();
|
std::vector<std::string> schemes;
|
||||||
auto custom_schemes = command_line->GetSwitchValueASCII(
|
ConvertStringWithSeparatorToVector(&schemes, ",",
|
||||||
switches::kRegisterStandardSchemes);
|
switches::kRegisterStandardSchemes);
|
||||||
if (!custom_schemes.empty()) {
|
if (!schemes.empty()) {
|
||||||
std::vector<std::string> schemes;
|
for (const std::string& scheme : schemes)
|
||||||
base::SplitString(custom_schemes, ',', &schemes);
|
standard_schemes->push_back({scheme.c_str(), url::SCHEME_WITHOUT_PORT});
|
||||||
standard_schemes->insert(standard_schemes->end(),
|
|
||||||
schemes.begin(),
|
|
||||||
schemes.end());
|
|
||||||
}
|
}
|
||||||
standard_schemes->push_back("chrome-extension");
|
standard_schemes->push_back({"chrome-extension", url::SCHEME_WITHOUT_PORT});
|
||||||
}
|
}
|
||||||
|
|
||||||
void AtomContentClient::AddPepperPlugins(
|
void AtomContentClient::AddPepperPlugins(
|
||||||
std::vector<content::PepperPluginInfo>* plugins) {
|
std::vector<content::PepperPluginInfo>* plugins) {
|
||||||
auto command_line = base::CommandLine::ForCurrentProcess();
|
AddPepperFlashFromCommandLine(plugins);
|
||||||
auto flash_path = command_line->GetSwitchValuePath(
|
#if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
|
||||||
switches::kPpapiFlashPath);
|
AddWidevineCdmFromCommandLine(plugins);
|
||||||
if (flash_path.empty())
|
#endif
|
||||||
return;
|
}
|
||||||
|
|
||||||
auto flash_version = command_line->GetSwitchValueASCII(
|
void AtomContentClient::AddServiceWorkerSchemes(
|
||||||
switches::kPpapiFlashVersion);
|
std::set<std::string>* service_worker_schemes) {
|
||||||
|
std::vector<std::string> schemes;
|
||||||
plugins->push_back(
|
ConvertStringWithSeparatorToVector(&schemes, ",",
|
||||||
CreatePepperFlashInfo(flash_path, flash_version));
|
switches::kRegisterServiceWorkerSchemes);
|
||||||
|
if (!schemes.empty()) {
|
||||||
|
for (const std::string& scheme : schemes)
|
||||||
|
service_worker_schemes->insert(scheme);
|
||||||
|
}
|
||||||
|
service_worker_schemes->insert(url::kFileScheme);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace atom
|
} // namespace atom
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#ifndef ATOM_APP_ATOM_CONTENT_CLIENT_H_
|
#ifndef ATOM_APP_ATOM_CONTENT_CLIENT_H_
|
||||||
#define ATOM_APP_ATOM_CONTENT_CLIENT_H_
|
#define ATOM_APP_ATOM_CONTENT_CLIENT_H_
|
||||||
|
|
||||||
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -21,11 +22,14 @@ class AtomContentClient : public brightray::ContentClient {
|
||||||
// content::ContentClient:
|
// content::ContentClient:
|
||||||
std::string GetProduct() const override;
|
std::string GetProduct() const override;
|
||||||
std::string GetUserAgent() const override;
|
std::string GetUserAgent() const override;
|
||||||
|
base::string16 GetLocalizedString(int message_id) const override;
|
||||||
void AddAdditionalSchemes(
|
void AddAdditionalSchemes(
|
||||||
std::vector<std::string>* standard_schemes,
|
std::vector<url::SchemeWithType>* standard_schemes,
|
||||||
std::vector<std::string>* savable_schemes) override;
|
std::vector<std::string>* savable_schemes) override;
|
||||||
void AddPepperPlugins(
|
void AddPepperPlugins(
|
||||||
std::vector<content::PepperPluginInfo>* plugins) override;
|
std::vector<content::PepperPluginInfo>* plugins) override;
|
||||||
|
void AddServiceWorkerSchemes(
|
||||||
|
std::set<std::string>* service_worker_schemes) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DISALLOW_COPY_AND_ASSIGN(AtomContentClient);
|
DISALLOW_COPY_AND_ASSIGN(AtomContentClient);
|
||||||
|
|
|
@ -5,13 +5,8 @@
|
||||||
#include "atom/app/atom_main.h"
|
#include "atom/app/atom_main.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
#if defined(OS_WIN)
|
||||||
#include <stdio.h>
|
|
||||||
#include <io.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <shellscalingapi.h>
|
#include <shellscalingapi.h>
|
||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
|
@ -36,10 +31,27 @@
|
||||||
#include "base/at_exit.h"
|
#include "base/at_exit.h"
|
||||||
#include "base/i18n/icu_util.h"
|
#include "base/i18n/icu_util.h"
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
|
||||||
|
|
||||||
namespace {
|
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)
|
||||||
|
size_t required_size;
|
||||||
|
getenv_s(&required_size, nullptr, 0, name);
|
||||||
|
return required_size != 0;
|
||||||
|
#else
|
||||||
|
char* indicator = getenv(name);
|
||||||
|
return indicator && indicator[0] != '\0';
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsRunAsNode() {
|
||||||
|
return IsEnvSet(kRunAsNode) || IsEnvSet(kOldRunAsNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(OS_WIN)
|
||||||
// Win8.1 supports monitor-specific DPI scaling.
|
// Win8.1 supports monitor-specific DPI scaling.
|
||||||
bool SetProcessDpiAwarenessWrapper(PROCESS_DPI_AWARENESS value) {
|
bool SetProcessDpiAwarenessWrapper(PROCESS_DPI_AWARENESS value) {
|
||||||
typedef HRESULT(WINAPI *SetProcessDpiAwarenessPtr)(PROCESS_DPI_AWARENESS);
|
typedef HRESULT(WINAPI *SetProcessDpiAwarenessPtr)(PROCESS_DPI_AWARENESS);
|
||||||
|
@ -77,24 +89,22 @@ void EnableHighDPISupport() {
|
||||||
SetProcessDPIAwareWrapper();
|
SetProcessDPIAwareWrapper();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
#if defined(OS_WIN)
|
||||||
int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
|
int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
|
||||||
int argc = 0;
|
int argc = 0;
|
||||||
wchar_t** wargv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
|
wchar_t** wargv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
|
||||||
|
|
||||||
scoped_ptr<base::Environment> env(base::Environment::Create());
|
|
||||||
|
|
||||||
// Make output work in console if we are not in cygiwn.
|
// Make output work in console if we are not in cygiwn.
|
||||||
std::string os;
|
if (!IsEnvSet("TERM") && !IsEnvSet("ELECTRON_NO_ATTACH_CONSOLE")) {
|
||||||
if (env->GetVar("OS", &os) && os != "cygwin") {
|
|
||||||
AttachConsole(ATTACH_PARENT_PROCESS);
|
AttachConsole(ATTACH_PARENT_PROCESS);
|
||||||
|
|
||||||
FILE* dontcare;
|
FILE* dontcare;
|
||||||
freopen_s(&dontcare, "CON", "w", stdout);
|
freopen_s(&dontcare, "CON", "w", stdout);
|
||||||
freopen_s(&dontcare, "CON", "w", stderr);
|
freopen_s(&dontcare, "CON", "w", stderr);
|
||||||
freopen_s(&dontcare, "CON", "r", stdin);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert argv to to UTF8
|
// Convert argv to to UTF8
|
||||||
|
@ -131,16 +141,12 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string node_indicator, crash_service_indicator;
|
if (IsRunAsNode()) {
|
||||||
if (env->GetVar("ATOM_SHELL_INTERNAL_RUN_AS_NODE", &node_indicator) &&
|
|
||||||
node_indicator == "1") {
|
|
||||||
// Now that argv conversion is done, we can finally start.
|
// Now that argv conversion is done, we can finally start.
|
||||||
base::AtExitManager atexit_manager;
|
base::AtExitManager atexit_manager;
|
||||||
base::i18n::InitializeICU();
|
base::i18n::InitializeICU();
|
||||||
return atom::NodeMain(argc, argv);
|
return atom::NodeMain(argc, argv);
|
||||||
} else if (env->GetVar("ATOM_SHELL_INTERNAL_CRASH_SERVICE",
|
} else if (IsEnvSet("ATOM_SHELL_INTERNAL_CRASH_SERVICE")) {
|
||||||
&crash_service_indicator) &&
|
|
||||||
crash_service_indicator == "1") {
|
|
||||||
return crash_service::Main(cmd);
|
return crash_service::Main(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,8 +170,7 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
|
||||||
#elif defined(OS_LINUX) // defined(OS_WIN)
|
#elif defined(OS_LINUX) // defined(OS_WIN)
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
char* node_indicator = getenv("ATOM_SHELL_INTERNAL_RUN_AS_NODE");
|
if (IsRunAsNode()) {
|
||||||
if (node_indicator != NULL && strcmp(node_indicator, "1") == 0) {
|
|
||||||
base::i18n::InitializeICU();
|
base::i18n::InitializeICU();
|
||||||
base::AtExitManager atexit_manager;
|
base::AtExitManager atexit_manager;
|
||||||
return atom::NodeMain(argc, const_cast<char**>(argv));
|
return atom::NodeMain(argc, const_cast<char**>(argv));
|
||||||
|
@ -182,8 +187,7 @@ int main(int argc, const char* argv[]) {
|
||||||
#else // defined(OS_LINUX)
|
#else // defined(OS_LINUX)
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
char* node_indicator = getenv("ATOM_SHELL_INTERNAL_RUN_AS_NODE");
|
if (IsRunAsNode()) {
|
||||||
if (node_indicator != NULL && strcmp(node_indicator, "1") == 0) {
|
|
||||||
return AtomInitializeICUandStartNode(argc, const_cast<char**>(argv));
|
return AtomInitializeICUandStartNode(argc, const_cast<char**>(argv));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
#include "chrome/common/chrome_paths.h"
|
#include "chrome/common/chrome_paths.h"
|
||||||
#include "content/public/common/content_switches.h"
|
#include "content/public/common/content_switches.h"
|
||||||
|
#include "ui/base/l10n/l10n_util.h"
|
||||||
#include "ui/base/resource/resource_bundle.h"
|
#include "ui/base/resource/resource_bundle.h"
|
||||||
|
|
||||||
namespace atom {
|
namespace atom {
|
||||||
|
@ -137,16 +138,4 @@ scoped_ptr<brightray::ContentClient> AtomMainDelegate::CreateContentClient() {
|
||||||
return scoped_ptr<brightray::ContentClient>(new AtomContentClient).Pass();
|
return scoped_ptr<brightray::ContentClient>(new AtomContentClient).Pass();
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace atom
|
} // namespace atom
|
||||||
|
|
|
@ -25,8 +25,6 @@ class AtomMainDelegate : public brightray::MainDelegate {
|
||||||
|
|
||||||
// brightray::MainDelegate:
|
// brightray::MainDelegate:
|
||||||
scoped_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)
|
#if defined(OS_MACOSX)
|
||||||
void OverrideChildProcessPath() override;
|
void OverrideChildProcessPath() override;
|
||||||
void OverrideFrameworkBundlePath() override;
|
void OverrideFrameworkBundlePath() override;
|
||||||
|
|
|
@ -181,7 +181,8 @@ void App::OnWindowAllClosed() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::OnQuit() {
|
void App::OnQuit() {
|
||||||
Emit("quit");
|
int exitCode = AtomBrowserMainParts::Get()->GetExitCode();
|
||||||
|
Emit("quit", exitCode);
|
||||||
|
|
||||||
if (process_singleton_.get()) {
|
if (process_singleton_.get()) {
|
||||||
process_singleton_->Cleanup();
|
process_singleton_->Cleanup();
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
#include "atom/common/native_mate_converters/callback.h"
|
#include "atom/common/native_mate_converters/callback.h"
|
||||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||||
#include "atom/common/native_mate_converters/value_converter.h"
|
#include "atom/common/native_mate_converters/value_converter.h"
|
||||||
#include "base/bind.h"
|
|
||||||
#include "base/time/time.h"
|
#include "base/time/time.h"
|
||||||
#include "base/values.h"
|
#include "base/values.h"
|
||||||
#include "content/public/browser/browser_context.h"
|
#include "content/public/browser/browser_context.h"
|
||||||
|
@ -20,139 +19,21 @@
|
||||||
#include "net/url_request/url_request_context.h"
|
#include "net/url_request/url_request_context.h"
|
||||||
#include "net/url_request/url_request_context_getter.h"
|
#include "net/url_request/url_request_context_getter.h"
|
||||||
|
|
||||||
using atom::api::Cookies;
|
|
||||||
using content::BrowserThread;
|
using content::BrowserThread;
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
bool GetCookieListFromStore(
|
|
||||||
net::CookieStore* cookie_store,
|
|
||||||
const std::string& url,
|
|
||||||
const net::CookieMonster::GetCookieListCallback& callback) {
|
|
||||||
DCHECK(cookie_store);
|
|
||||||
GURL gurl(url);
|
|
||||||
net::CookieMonster* monster = cookie_store->GetCookieMonster();
|
|
||||||
// Empty url will match all url cookies.
|
|
||||||
if (url.empty()) {
|
|
||||||
monster->GetAllCookiesAsync(callback);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!gurl.is_valid())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
monster->GetAllCookiesForURLAsync(gurl, callback);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RunGetCookiesCallbackOnUIThread(v8::Isolate* isolate,
|
|
||||||
const std::string& error_message,
|
|
||||||
const net::CookieList& cookie_list,
|
|
||||||
const Cookies::CookiesCallback& callback) {
|
|
||||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
||||||
|
|
||||||
v8::Locker locker(isolate);
|
|
||||||
v8::HandleScope handle_scope(isolate);
|
|
||||||
|
|
||||||
if (!error_message.empty()) {
|
|
||||||
v8::Local<v8::Value> error = mate::ConvertToV8(isolate, error_message);
|
|
||||||
callback.Run(error, v8::Null(isolate));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
callback.Run(v8::Null(isolate), mate::ConvertToV8(isolate, cookie_list));
|
|
||||||
}
|
|
||||||
|
|
||||||
void RunRemoveCookiesCallbackOnUIThread(
|
|
||||||
v8::Isolate* isolate,
|
|
||||||
const std::string& error_message,
|
|
||||||
const Cookies::CookiesCallback& callback) {
|
|
||||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
||||||
|
|
||||||
v8::Locker locker(isolate);
|
|
||||||
v8::HandleScope handle_scope(isolate);
|
|
||||||
|
|
||||||
if (!error_message.empty()) {
|
|
||||||
v8::Local<v8::Value> error = mate::ConvertToV8(isolate, error_message);
|
|
||||||
callback.Run(error, v8::Null(isolate));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
callback.Run(v8::Null(isolate), v8::Null(isolate));
|
|
||||||
}
|
|
||||||
|
|
||||||
void RunSetCookiesCallbackOnUIThread(v8::Isolate* isolate,
|
|
||||||
const std::string& error_message,
|
|
||||||
bool set_success,
|
|
||||||
const Cookies::CookiesCallback& callback) {
|
|
||||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
||||||
|
|
||||||
v8::Locker locker(isolate);
|
|
||||||
v8::HandleScope handle_scope(isolate);
|
|
||||||
|
|
||||||
if (!error_message.empty()) {
|
|
||||||
v8::Local<v8::Value> error = mate::ConvertToV8(isolate, error_message);
|
|
||||||
callback.Run(error, v8::Null(isolate));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!set_success) {
|
|
||||||
v8::Local<v8::Value> error = mate::ConvertToV8(
|
|
||||||
isolate, "Failed to set cookies");
|
|
||||||
callback.Run(error, v8::Null(isolate));
|
|
||||||
}
|
|
||||||
|
|
||||||
callback.Run(v8::Null(isolate), v8::Null(isolate));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MatchesDomain(const base::DictionaryValue* filter,
|
|
||||||
const std::string& cookie_domain) {
|
|
||||||
std::string filter_domain;
|
|
||||||
if (!filter->GetString("domain", &filter_domain))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// Add a leading '.' character to the filter domain if it doesn't exist.
|
|
||||||
if (net::cookie_util::DomainIsHostOnly(filter_domain))
|
|
||||||
filter_domain.insert(0, ".");
|
|
||||||
|
|
||||||
std::string sub_domain(cookie_domain);
|
|
||||||
// Strip any leading '.' character from the input cookie domain.
|
|
||||||
if (!net::cookie_util::DomainIsHostOnly(sub_domain))
|
|
||||||
sub_domain = sub_domain.substr(1);
|
|
||||||
|
|
||||||
// Now check whether the domain argument is a subdomain of the filter domain.
|
|
||||||
for (sub_domain.insert(0, ".");
|
|
||||||
sub_domain.length() >= filter_domain.length();) {
|
|
||||||
if (sub_domain == filter_domain) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
const size_t next_dot = sub_domain.find('.', 1); // Skip over leading dot.
|
|
||||||
sub_domain.erase(0, next_dot);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MatchesCookie(const base::DictionaryValue* filter,
|
|
||||||
const net::CanonicalCookie& cookie) {
|
|
||||||
std::string name, domain, path;
|
|
||||||
bool is_secure, session;
|
|
||||||
if (filter->GetString("name", &name) && name != cookie.Name())
|
|
||||||
return false;
|
|
||||||
if (filter->GetString("path", &path) && path != cookie.Path())
|
|
||||||
return false;
|
|
||||||
if (!MatchesDomain(filter, cookie.Domain()))
|
|
||||||
return false;
|
|
||||||
if (filter->GetBoolean("secure", &is_secure) &&
|
|
||||||
is_secure != cookie.IsSecure())
|
|
||||||
return false;
|
|
||||||
if (filter->GetBoolean("session", &session) &&
|
|
||||||
session != cookie.IsPersistent())
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
namespace mate {
|
namespace mate {
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct Converter<atom::api::Cookies::Error> {
|
||||||
|
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||||
|
atom::api::Cookies::Error val) {
|
||||||
|
if (val == atom::api::Cookies::SUCCESS)
|
||||||
|
return v8::Null(isolate);
|
||||||
|
else
|
||||||
|
return v8::Exception::Error(StringToV8(isolate, "failed"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct Converter<net::CanonicalCookie> {
|
struct Converter<net::CanonicalCookie> {
|
||||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||||
|
@ -161,11 +42,11 @@ struct Converter<net::CanonicalCookie> {
|
||||||
dict.Set("name", val.Name());
|
dict.Set("name", val.Name());
|
||||||
dict.Set("value", val.Value());
|
dict.Set("value", val.Value());
|
||||||
dict.Set("domain", val.Domain());
|
dict.Set("domain", val.Domain());
|
||||||
dict.Set("host_only", net::cookie_util::DomainIsHostOnly(val.Domain()));
|
dict.Set("hostOnly", net::cookie_util::DomainIsHostOnly(val.Domain()));
|
||||||
dict.Set("path", val.Path());
|
dict.Set("path", val.Path());
|
||||||
dict.Set("secure", val.IsSecure());
|
dict.Set("secure", val.IsSecure());
|
||||||
dict.Set("http_only", val.IsHttpOnly());
|
dict.Set("httpOnly", val.IsHttpOnly());
|
||||||
dict.Set("session", val.IsPersistent());
|
dict.Set("session", !val.IsPersistent());
|
||||||
if (!val.IsPersistent())
|
if (!val.IsPersistent())
|
||||||
dict.Set("expirationDate", val.ExpiryDate().ToDoubleT());
|
dict.Set("expirationDate", val.ExpiryDate().ToDoubleT());
|
||||||
return dict.GetHandle();
|
return dict.GetHandle();
|
||||||
|
@ -178,121 +59,117 @@ namespace atom {
|
||||||
|
|
||||||
namespace api {
|
namespace api {
|
||||||
|
|
||||||
Cookies::Cookies(content::BrowserContext* browser_context)
|
namespace {
|
||||||
: request_context_getter_(browser_context->GetRequestContext()) {
|
|
||||||
}
|
|
||||||
|
|
||||||
Cookies::~Cookies() {
|
// 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, ".");
|
||||||
|
|
||||||
void Cookies::Get(const base::DictionaryValue& options,
|
std::string sub_domain(domain);
|
||||||
const CookiesCallback& callback) {
|
// Strip any leading '.' character from the input cookie domain.
|
||||||
scoped_ptr<base::DictionaryValue> filter(
|
if (!net::cookie_util::DomainIsHostOnly(sub_domain))
|
||||||
options.DeepCopyWithoutEmptyChildren());
|
sub_domain = sub_domain.substr(1);
|
||||||
|
|
||||||
content::BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
// Now check whether the domain argument is a subdomain of the filter domain.
|
||||||
base::Bind(&Cookies::GetCookiesOnIOThread, base::Unretained(this),
|
for (sub_domain.insert(0, "."); sub_domain.length() >= filter.length();) {
|
||||||
Passed(&filter), callback));
|
if (sub_domain == filter)
|
||||||
}
|
return true;
|
||||||
|
const size_t next_dot = sub_domain.find('.', 1); // Skip over leading dot.
|
||||||
void Cookies::GetCookiesOnIOThread(scoped_ptr<base::DictionaryValue> filter,
|
sub_domain.erase(0, next_dot);
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cookies::OnGetCookies(scoped_ptr<base::DictionaryValue> filter,
|
// Returns whether |cookie| matches |filter|.
|
||||||
const CookiesCallback& callback,
|
bool MatchesCookie(const base::DictionaryValue* filter,
|
||||||
const net::CookieList& cookie_list) {
|
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(scoped_ptr<base::DictionaryValue> filter,
|
||||||
|
const Cookies::GetCallback& callback,
|
||||||
|
const net::CookieList& list) {
|
||||||
net::CookieList result;
|
net::CookieList result;
|
||||||
for (const auto& cookie : cookie_list) {
|
for (const auto& cookie : list) {
|
||||||
if (MatchesCookie(filter.get(), cookie))
|
if (MatchesCookie(filter.get(), cookie))
|
||||||
result.push_back(cookie);
|
result.push_back(cookie);
|
||||||
}
|
}
|
||||||
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
|
RunCallbackInUI(base::Bind(callback, Cookies::SUCCESS, result));
|
||||||
&RunGetCookiesCallbackOnUIThread, isolate(), "", result, callback));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cookies::Remove(const mate::Dictionary& details,
|
// Receives cookies matching |filter| in IO thread.
|
||||||
const CookiesCallback& callback) {
|
void GetCookiesOnIO(scoped_refptr<net::URLRequestContextGetter> getter,
|
||||||
GURL url;
|
scoped_ptr<base::DictionaryValue> filter,
|
||||||
std::string name;
|
const Cookies::GetCallback& callback) {
|
||||||
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;
|
std::string url;
|
||||||
std::string error_message;
|
filter->GetString("url", &url);
|
||||||
if (!options.GetString("url", &url)) {
|
|
||||||
error_message = "The url field is required.";
|
|
||||||
}
|
|
||||||
|
|
||||||
GURL gurl(url);
|
auto filtered_callback =
|
||||||
if (error_message.empty() && !gurl.is_valid()) {
|
base::Bind(FilterCookies, base::Passed(&filter), callback);
|
||||||
error_message = "URL is not valid.";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!error_message.empty()) {
|
net::CookieMonster* monster = GetCookieStore(getter)->GetCookieMonster();
|
||||||
RunSetCookiesCallbackOnUIThread(isolate(), error_message, false, callback);
|
// Empty url will match all url cookies.
|
||||||
return;
|
if (url.empty())
|
||||||
}
|
monster->GetAllCookiesAsync(filtered_callback);
|
||||||
|
else
|
||||||
scoped_ptr<base::DictionaryValue> details(
|
monster->GetAllCookiesForURLAsync(GURL(url), filtered_callback);
|
||||||
options.DeepCopyWithoutEmptyChildren());
|
|
||||||
|
|
||||||
content::BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
|
||||||
base::Bind(&Cookies::SetCookiesOnIOThread, base::Unretained(this),
|
|
||||||
Passed(&details), gurl, callback));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cookies::SetCookiesOnIOThread(scoped_ptr<base::DictionaryValue> details,
|
// Removes cookie with |url| and |name| in IO thread.
|
||||||
const GURL& url,
|
void RemoveCookieOnIOThread(scoped_refptr<net::URLRequestContextGetter> getter,
|
||||||
const CookiesCallback& callback) {
|
const GURL& url, const std::string& name,
|
||||||
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
const base::Closure& callback) {
|
||||||
|
GetCookieStore(getter)->DeleteCookieAsync(
|
||||||
|
url, name, base::Bind(RunCallbackInUI, callback));
|
||||||
|
}
|
||||||
|
|
||||||
std::string name, value, domain, path;
|
// Callback of SetCookie.
|
||||||
|
void OnSetCookie(const Cookies::SetCallback& callback, bool success) {
|
||||||
|
RunCallbackInUI(
|
||||||
|
base::Bind(callback, success ? Cookies::SUCCESS : Cookies::FAILED));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets cookie with |details| in IO thread.
|
||||||
|
void SetCookieOnIO(scoped_refptr<net::URLRequestContextGetter> getter,
|
||||||
|
scoped_ptr<base::DictionaryValue> details,
|
||||||
|
const Cookies::SetCallback& callback) {
|
||||||
|
std::string url, name, value, domain, path;
|
||||||
bool secure = false;
|
bool secure = false;
|
||||||
bool http_only = false;
|
bool http_only = false;
|
||||||
double expiration_date;
|
double expiration_date;
|
||||||
|
details->GetString("url", &url);
|
||||||
details->GetString("name", &name);
|
details->GetString("name", &name);
|
||||||
details->GetString("value", &value);
|
details->GetString("value", &value);
|
||||||
details->GetString("domain", &domain);
|
details->GetString("domain", &domain);
|
||||||
details->GetString("path", &path);
|
details->GetString("path", &path);
|
||||||
details->GetBoolean("secure", &secure);
|
details->GetBoolean("secure", &secure);
|
||||||
details->GetBoolean("http_only", &http_only);
|
details->GetBoolean("httpOnly", &http_only);
|
||||||
|
|
||||||
base::Time expiration_time;
|
base::Time expiration_time;
|
||||||
if (details->GetDouble("expirationDate", &expiration_date)) {
|
if (details->GetDouble("expirationDate", &expiration_date)) {
|
||||||
|
@ -301,37 +178,44 @@ void Cookies::SetCookiesOnIOThread(scoped_ptr<base::DictionaryValue> details,
|
||||||
base::Time::FromDoubleT(expiration_date);
|
base::Time::FromDoubleT(expiration_date);
|
||||||
}
|
}
|
||||||
|
|
||||||
GetCookieStore()->GetCookieMonster()->SetCookieWithDetailsAsync(
|
GetCookieStore(getter)->GetCookieMonster()->SetCookieWithDetailsAsync(
|
||||||
url,
|
GURL(url), name, value, domain, path, expiration_time, secure, http_only,
|
||||||
name,
|
false, net::COOKIE_PRIORITY_DEFAULT, base::Bind(OnSetCookie, callback));
|
||||||
value,
|
|
||||||
domain,
|
|
||||||
path,
|
|
||||||
expiration_time,
|
|
||||||
secure,
|
|
||||||
http_only,
|
|
||||||
false,
|
|
||||||
net::COOKIE_PRIORITY_DEFAULT,
|
|
||||||
base::Bind(&Cookies::OnSetCookies, base::Unretained(this), callback));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cookies::OnSetCookies(const CookiesCallback& callback,
|
} // namespace
|
||||||
bool set_success) {
|
|
||||||
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
|
Cookies::Cookies(content::BrowserContext* browser_context)
|
||||||
base::Bind(&RunSetCookiesCallbackOnUIThread, isolate(), "", set_success,
|
: request_context_getter_(browser_context->GetRequestContext()) {
|
||||||
callback));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mate::ObjectTemplateBuilder Cookies::GetObjectTemplateBuilder(
|
Cookies::~Cookies() {
|
||||||
v8::Isolate* isolate) {
|
|
||||||
return mate::ObjectTemplateBuilder(isolate)
|
|
||||||
.SetMethod("get", &Cookies::Get)
|
|
||||||
.SetMethod("remove", &Cookies::Remove)
|
|
||||||
.SetMethod("set", &Cookies::Set);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
net::CookieStore* Cookies::GetCookieStore() {
|
void Cookies::Get(const base::DictionaryValue& filter,
|
||||||
return request_context_getter_->GetURLRequestContext()->cookie_store();
|
const GetCallback& callback) {
|
||||||
|
scoped_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) {
|
||||||
|
scoped_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));
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
@ -341,6 +225,15 @@ mate::Handle<Cookies> Cookies::Create(
|
||||||
return mate::CreateHandle(isolate, new Cookies(browser_context));
|
return mate::CreateHandle(isolate, new Cookies(browser_context));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void Cookies::BuildPrototype(v8::Isolate* isolate,
|
||||||
|
v8::Local<v8::ObjectTemplate> prototype) {
|
||||||
|
mate::ObjectTemplateBuilder(isolate, prototype)
|
||||||
|
.SetMethod("get", &Cookies::Get)
|
||||||
|
.SetMethod("remove", &Cookies::Remove)
|
||||||
|
.SetMethod("set", &Cookies::Set);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace api
|
} // namespace api
|
||||||
|
|
||||||
} // namespace atom
|
} // namespace atom
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "atom/browser/api/trackable_object.h"
|
||||||
#include "base/callback.h"
|
#include "base/callback.h"
|
||||||
#include "native_mate/wrappable.h"
|
|
||||||
#include "native_mate/handle.h"
|
#include "native_mate/handle.h"
|
||||||
#include "net/cookies/canonical_cookie.h"
|
#include "net/cookies/canonical_cookie.h"
|
||||||
|
|
||||||
|
@ -20,12 +20,7 @@ namespace content {
|
||||||
class BrowserContext;
|
class BrowserContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace mate {
|
|
||||||
class Dictionary;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace net {
|
namespace net {
|
||||||
class CookieStore;
|
|
||||||
class URLRequestContextGetter;
|
class URLRequestContextGetter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,51 +28,33 @@ namespace atom {
|
||||||
|
|
||||||
namespace api {
|
namespace api {
|
||||||
|
|
||||||
class Cookies : public mate::Wrappable {
|
class Cookies : public mate::TrackableObject<Cookies> {
|
||||||
public:
|
public:
|
||||||
// node.js style callback function(error, result)
|
enum Error {
|
||||||
typedef base::Callback<void(v8::Local<v8::Value>, v8::Local<v8::Value>)>
|
SUCCESS,
|
||||||
CookiesCallback;
|
FAILED,
|
||||||
|
};
|
||||||
|
|
||||||
|
using GetCallback = base::Callback<void(Error, const net::CookieList&)>;
|
||||||
|
using SetCallback = base::Callback<void(Error)>;
|
||||||
|
|
||||||
static mate::Handle<Cookies> Create(v8::Isolate* isolate,
|
static mate::Handle<Cookies> Create(v8::Isolate* isolate,
|
||||||
content::BrowserContext* browser_context);
|
content::BrowserContext* browser_context);
|
||||||
|
|
||||||
|
// mate::TrackableObject:
|
||||||
|
static void BuildPrototype(v8::Isolate* isolate,
|
||||||
|
v8::Local<v8::ObjectTemplate> prototype);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
explicit Cookies(content::BrowserContext* browser_context);
|
explicit Cookies(content::BrowserContext* browser_context);
|
||||||
~Cookies();
|
~Cookies();
|
||||||
|
|
||||||
void Get(const base::DictionaryValue& options,
|
void Get(const base::DictionaryValue& filter, const GetCallback& callback);
|
||||||
const CookiesCallback& callback);
|
void Remove(const GURL& url, const std::string& name,
|
||||||
void Remove(const mate::Dictionary& details,
|
const base::Closure& callback);
|
||||||
const CookiesCallback& callback);
|
void Set(const base::DictionaryValue& details, const SetCallback& callback);
|
||||||
void Set(const base::DictionaryValue& details,
|
|
||||||
const CookiesCallback& callback);
|
|
||||||
|
|
||||||
void GetCookiesOnIOThread(scoped_ptr<base::DictionaryValue> filter,
|
|
||||||
const CookiesCallback& callback);
|
|
||||||
void OnGetCookies(scoped_ptr<base::DictionaryValue> filter,
|
|
||||||
const CookiesCallback& callback,
|
|
||||||
const net::CookieList& cookie_list);
|
|
||||||
|
|
||||||
void RemoveCookiesOnIOThread(const GURL& url,
|
|
||||||
const std::string& name,
|
|
||||||
const CookiesCallback& callback);
|
|
||||||
void OnRemoveCookies(const CookiesCallback& callback);
|
|
||||||
|
|
||||||
void SetCookiesOnIOThread(scoped_ptr<base::DictionaryValue> details,
|
|
||||||
const GURL& url,
|
|
||||||
const CookiesCallback& callback);
|
|
||||||
void OnSetCookies(const CookiesCallback& callback,
|
|
||||||
bool set_success);
|
|
||||||
|
|
||||||
// mate::Wrappable:
|
|
||||||
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
|
||||||
v8::Isolate* isolate) override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Must be called on IO thread.
|
|
||||||
net::CookieStore* GetCookieStore();
|
|
||||||
|
|
||||||
net::URLRequestContextGetter* request_context_getter_;
|
net::URLRequestContextGetter* request_context_getter_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(Cookies);
|
DISALLOW_COPY_AND_ASSIGN(Cookies);
|
||||||
|
|
120
atom/browser/api/atom_api_desktop_capturer.cc
Normal file
120
atom/browser/api/atom_api_desktop_capturer.cc
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
// 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/node_includes.h"
|
||||||
|
#include "atom/common/native_mate_converters/gfx_converter.h"
|
||||||
|
#include "base/strings/utf_string_conversions.h"
|
||||||
|
#include "chrome/browser/media/desktop_media_list.h"
|
||||||
|
#include "native_mate/dictionary.h"
|
||||||
|
#include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
|
||||||
|
#include "third_party/webrtc/modules/desktop_capture/screen_capturer.h"
|
||||||
|
#include "third_party/webrtc/modules/desktop_capture/window_capturer.h"
|
||||||
|
|
||||||
|
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() {
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
scoped_ptr<webrtc::ScreenCapturer> screen_capturer(
|
||||||
|
capture_screen ? webrtc::ScreenCapturer::Create(options) : nullptr);
|
||||||
|
scoped_ptr<webrtc::WindowCapturer> window_capturer(
|
||||||
|
capture_window ? webrtc::WindowCapturer::Create(options) : nullptr);
|
||||||
|
media_list_.reset(new NativeDesktopMediaList(screen_capturer.Pass(),
|
||||||
|
window_capturer.Pass()));
|
||||||
|
|
||||||
|
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());
|
||||||
|
media_list_.reset();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mate::ObjectTemplateBuilder DesktopCapturer::GetObjectTemplateBuilder(
|
||||||
|
v8::Isolate* isolate) {
|
||||||
|
return mate::ObjectTemplateBuilder(isolate)
|
||||||
|
.SetMethod("startHandling", &DesktopCapturer::StartHandling);
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
mate::Handle<DesktopCapturer> DesktopCapturer::Create(v8::Isolate* isolate) {
|
||||||
|
return mate::CreateHandle(isolate, new DesktopCapturer);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // 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);
|
52
atom/browser/api/atom_api_desktop_capturer.h
Normal file
52
atom/browser/api/atom_api_desktop_capturer.h
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
// 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,
|
||||||
|
public DesktopMediaListObserver {
|
||||||
|
public:
|
||||||
|
static mate::Handle<DesktopCapturer> Create(v8::Isolate* isolate);
|
||||||
|
|
||||||
|
void StartHandling(bool capture_window,
|
||||||
|
bool capture_screen,
|
||||||
|
const gfx::Size& thumbnail_size);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
DesktopCapturer();
|
||||||
|
~DesktopCapturer();
|
||||||
|
|
||||||
|
// 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:
|
||||||
|
// mate::Wrappable:
|
||||||
|
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
||||||
|
v8::Isolate* isolate) override;
|
||||||
|
|
||||||
|
scoped_ptr<DesktopMediaList> media_list_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(DesktopCapturer);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace api
|
||||||
|
|
||||||
|
} // namespace atom
|
||||||
|
|
||||||
|
#endif // ATOM_BROWSER_API_ATOM_API_DESKTOP_CAPTURER_H_
|
|
@ -70,29 +70,20 @@ DownloadItem::DownloadItem(content::DownloadItem* download_item) :
|
||||||
}
|
}
|
||||||
|
|
||||||
DownloadItem::~DownloadItem() {
|
DownloadItem::~DownloadItem() {
|
||||||
Destroy();
|
if (download_item_)
|
||||||
}
|
OnDownloadDestroyed(download_item_);
|
||||||
|
|
||||||
void DownloadItem::Destroy() {
|
|
||||||
if (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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DownloadItem::IsDestroyed() const {
|
|
||||||
return download_item_ == nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DownloadItem::OnDownloadUpdated(content::DownloadItem* item) {
|
void DownloadItem::OnDownloadUpdated(content::DownloadItem* item) {
|
||||||
download_item_->IsDone() ? Emit("done", item->GetState()) : Emit("updated");
|
download_item_->IsDone() ? Emit("done", item->GetState()) : Emit("updated");
|
||||||
}
|
}
|
||||||
|
|
||||||
void DownloadItem::OnDownloadDestroyed(content::DownloadItem* download) {
|
void DownloadItem::OnDownloadDestroyed(content::DownloadItem* download_item) {
|
||||||
Destroy();
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64 DownloadItem::GetReceivedBytes() {
|
int64 DownloadItem::GetReceivedBytes() {
|
||||||
|
@ -144,9 +135,11 @@ void DownloadItem::Cancel() {
|
||||||
download_item_->Cancel(true);
|
download_item_->Cancel(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
mate::ObjectTemplateBuilder DownloadItem::GetObjectTemplateBuilder(
|
// static
|
||||||
v8::Isolate* isolate) {
|
void DownloadItem::BuildPrototype(v8::Isolate* isolate,
|
||||||
return mate::ObjectTemplateBuilder(isolate)
|
v8::Local<v8::ObjectTemplate> prototype) {
|
||||||
|
mate::ObjectTemplateBuilder(isolate, prototype)
|
||||||
|
.MakeDestroyable()
|
||||||
.SetMethod("pause", &DownloadItem::Pause)
|
.SetMethod("pause", &DownloadItem::Pause)
|
||||||
.SetMethod("resume", &DownloadItem::Resume)
|
.SetMethod("resume", &DownloadItem::Resume)
|
||||||
.SetMethod("cancel", &DownloadItem::Cancel)
|
.SetMethod("cancel", &DownloadItem::Cancel)
|
||||||
|
|
|
@ -17,7 +17,7 @@ namespace atom {
|
||||||
|
|
||||||
namespace api {
|
namespace api {
|
||||||
|
|
||||||
class DownloadItem : public mate::EventEmitter,
|
class DownloadItem : public mate::TrackableObject<DownloadItem>,
|
||||||
public content::DownloadItem::Observer {
|
public content::DownloadItem::Observer {
|
||||||
public:
|
public:
|
||||||
class SavePathData : public base::SupportsUserData::Data {
|
class SavePathData : public base::SupportsUserData::Data {
|
||||||
|
@ -32,6 +32,10 @@ class DownloadItem : public mate::EventEmitter,
|
||||||
content::DownloadItem* item);
|
content::DownloadItem* item);
|
||||||
static void* UserDataKey();
|
static void* UserDataKey();
|
||||||
|
|
||||||
|
// mate::TrackableObject:
|
||||||
|
static void BuildPrototype(v8::Isolate* isolate,
|
||||||
|
v8::Local<v8::ObjectTemplate> prototype);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
explicit DownloadItem(content::DownloadItem* download_item);
|
explicit DownloadItem(content::DownloadItem* download_item);
|
||||||
~DownloadItem();
|
~DownloadItem();
|
||||||
|
@ -53,13 +57,6 @@ class DownloadItem : public mate::EventEmitter,
|
||||||
void SetSavePath(const base::FilePath& path);
|
void SetSavePath(const base::FilePath& path);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// mate::Wrappable:
|
|
||||||
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
|
||||||
v8::Isolate* isolate) override;
|
|
||||||
bool IsDestroyed() const override;
|
|
||||||
|
|
||||||
void Destroy();
|
|
||||||
|
|
||||||
content::DownloadItem* download_item_;
|
content::DownloadItem* download_item_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(DownloadItem);
|
DISALLOW_COPY_AND_ASSIGN(DownloadItem);
|
||||||
|
|
|
@ -23,9 +23,6 @@ GlobalShortcut::GlobalShortcut() {
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalShortcut::~GlobalShortcut() {
|
GlobalShortcut::~GlobalShortcut() {
|
||||||
}
|
|
||||||
|
|
||||||
void GlobalShortcut::Destroy() {
|
|
||||||
UnregisterAll();
|
UnregisterAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,9 +27,6 @@ class GlobalShortcut : public extensions::GlobalShortcutListener::Observer,
|
||||||
GlobalShortcut();
|
GlobalShortcut();
|
||||||
~GlobalShortcut() override;
|
~GlobalShortcut() override;
|
||||||
|
|
||||||
// mate::TrackableObject:
|
|
||||||
void Destroy() override;
|
|
||||||
|
|
||||||
// mate::Wrappable implementations:
|
// mate::Wrappable implementations:
|
||||||
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
||||||
v8::Isolate* isolate) override;
|
v8::Isolate* isolate) override;
|
||||||
|
|
|
@ -27,14 +27,6 @@ Menu::Menu()
|
||||||
Menu::~Menu() {
|
Menu::~Menu() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::Destroy() {
|
|
||||||
model_.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Menu::IsDestroyed() const {
|
|
||||||
return !model_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Menu::AfterInit(v8::Isolate* isolate) {
|
void Menu::AfterInit(v8::Isolate* isolate) {
|
||||||
mate::Dictionary wrappable(isolate, GetWrapper(isolate));
|
mate::Dictionary wrappable(isolate, GetWrapper(isolate));
|
||||||
mate::Dictionary delegate;
|
mate::Dictionary delegate;
|
||||||
|
@ -159,6 +151,7 @@ bool Menu::IsVisibleAt(int index) const {
|
||||||
void Menu::BuildPrototype(v8::Isolate* isolate,
|
void Menu::BuildPrototype(v8::Isolate* isolate,
|
||||||
v8::Local<v8::ObjectTemplate> prototype) {
|
v8::Local<v8::ObjectTemplate> prototype) {
|
||||||
mate::ObjectTemplateBuilder(isolate, prototype)
|
mate::ObjectTemplateBuilder(isolate, prototype)
|
||||||
|
.MakeDestroyable()
|
||||||
.SetMethod("insertItem", &Menu::InsertItemAt)
|
.SetMethod("insertItem", &Menu::InsertItemAt)
|
||||||
.SetMethod("insertCheckItem", &Menu::InsertCheckItemAt)
|
.SetMethod("insertCheckItem", &Menu::InsertCheckItemAt)
|
||||||
.SetMethod("insertRadioItem", &Menu::InsertRadioItemAt)
|
.SetMethod("insertRadioItem", &Menu::InsertRadioItemAt)
|
||||||
|
|
|
@ -39,11 +39,7 @@ class Menu : public mate::TrackableObject<Menu>,
|
||||||
Menu();
|
Menu();
|
||||||
~Menu() override;
|
~Menu() override;
|
||||||
|
|
||||||
// mate::TrackableObject:
|
|
||||||
void Destroy() override;
|
|
||||||
|
|
||||||
// mate::Wrappable:
|
// mate::Wrappable:
|
||||||
bool IsDestroyed() const override;
|
|
||||||
void AfterInit(v8::Isolate* isolate) override;
|
void AfterInit(v8::Isolate* isolate) override;
|
||||||
|
|
||||||
// ui::SimpleMenuModel::Delegate:
|
// ui::SimpleMenuModel::Delegate:
|
||||||
|
|
|
@ -19,7 +19,6 @@ class MenuMac : public Menu {
|
||||||
protected:
|
protected:
|
||||||
MenuMac();
|
MenuMac();
|
||||||
|
|
||||||
void Destroy() override;
|
|
||||||
void Popup(Window* window) override;
|
void Popup(Window* window) override;
|
||||||
void PopupAt(Window* window, int x, int y) override;
|
void PopupAt(Window* window, int x, int y) override;
|
||||||
|
|
||||||
|
|
|
@ -18,11 +18,6 @@ namespace api {
|
||||||
MenuMac::MenuMac() {
|
MenuMac::MenuMac() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuMac::Destroy() {
|
|
||||||
menu_controller_.reset();
|
|
||||||
Menu::Destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuMac::Popup(Window* window) {
|
void MenuMac::Popup(Window* window) {
|
||||||
NativeWindow* native_window = window->window();
|
NativeWindow* native_window = window->window();
|
||||||
if (!native_window)
|
if (!native_window)
|
||||||
|
|
|
@ -19,9 +19,6 @@ PowerMonitor::PowerMonitor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
PowerMonitor::~PowerMonitor() {
|
PowerMonitor::~PowerMonitor() {
|
||||||
}
|
|
||||||
|
|
||||||
void PowerMonitor::Destroy() {
|
|
||||||
base::PowerMonitor::Get()->RemoveObserver(this);
|
base::PowerMonitor::Get()->RemoveObserver(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,9 +23,6 @@ class PowerMonitor : public mate::TrackableObject<PowerMonitor>,
|
||||||
PowerMonitor();
|
PowerMonitor();
|
||||||
~PowerMonitor() override;
|
~PowerMonitor() override;
|
||||||
|
|
||||||
// mate::TrackableObject:
|
|
||||||
void Destroy() override;
|
|
||||||
|
|
||||||
// base::PowerObserver implementations:
|
// base::PowerObserver implementations:
|
||||||
void OnPowerStateChange(bool on_battery_power) override;
|
void OnPowerStateChange(bool on_battery_power) override;
|
||||||
void OnSuspend() override;
|
void OnSuspend() override;
|
||||||
|
|
|
@ -45,11 +45,6 @@ PowerSaveBlocker::PowerSaveBlocker()
|
||||||
PowerSaveBlocker::~PowerSaveBlocker() {
|
PowerSaveBlocker::~PowerSaveBlocker() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PowerSaveBlocker::Destroy() {
|
|
||||||
power_save_blocker_types_.clear();
|
|
||||||
power_save_blocker_.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PowerSaveBlocker::UpdatePowerSaveBlocker() {
|
void PowerSaveBlocker::UpdatePowerSaveBlocker() {
|
||||||
if (power_save_blocker_types_.empty()) {
|
if (power_save_blocker_types_.empty()) {
|
||||||
power_save_blocker_.reset();
|
power_save_blocker_.reset();
|
||||||
|
|
|
@ -28,9 +28,6 @@ class PowerSaveBlocker : public mate::TrackableObject<PowerSaveBlocker> {
|
||||||
PowerSaveBlocker();
|
PowerSaveBlocker();
|
||||||
~PowerSaveBlocker() override;
|
~PowerSaveBlocker() override;
|
||||||
|
|
||||||
// mate::TrackableObject:
|
|
||||||
void Destroy() override;
|
|
||||||
|
|
||||||
// mate::Wrappable implementations:
|
// mate::Wrappable implementations:
|
||||||
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
||||||
v8::Isolate* isolate) override;
|
v8::Isolate* isolate) override;
|
||||||
|
|
|
@ -32,6 +32,8 @@ mate::ObjectTemplateBuilder Protocol::GetObjectTemplateBuilder(
|
||||||
v8::Isolate* isolate) {
|
v8::Isolate* isolate) {
|
||||||
return mate::ObjectTemplateBuilder(isolate)
|
return mate::ObjectTemplateBuilder(isolate)
|
||||||
.SetMethod("registerStandardSchemes", &Protocol::RegisterStandardSchemes)
|
.SetMethod("registerStandardSchemes", &Protocol::RegisterStandardSchemes)
|
||||||
|
.SetMethod("registerServiceWorkerSchemes",
|
||||||
|
&Protocol::RegisterServiceWorkerSchemes)
|
||||||
.SetMethod("registerStringProtocol",
|
.SetMethod("registerStringProtocol",
|
||||||
&Protocol::RegisterProtocol<URLRequestStringJob>)
|
&Protocol::RegisterProtocol<URLRequestStringJob>)
|
||||||
.SetMethod("registerBufferProtocol",
|
.SetMethod("registerBufferProtocol",
|
||||||
|
@ -58,6 +60,11 @@ void Protocol::RegisterStandardSchemes(
|
||||||
atom::AtomBrowserClient::SetCustomSchemes(schemes);
|
atom::AtomBrowserClient::SetCustomSchemes(schemes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Protocol::RegisterServiceWorkerSchemes(
|
||||||
|
const std::vector<std::string>& schemes) {
|
||||||
|
atom::AtomBrowserClient::SetCustomServiceWorkerSchemes(schemes);
|
||||||
|
}
|
||||||
|
|
||||||
void Protocol::UnregisterProtocol(
|
void Protocol::UnregisterProtocol(
|
||||||
const std::string& scheme, mate::Arguments* args) {
|
const std::string& scheme, mate::Arguments* args) {
|
||||||
CompletionCallback callback;
|
CompletionCallback callback;
|
||||||
|
|
|
@ -92,6 +92,9 @@ class Protocol : public mate::Wrappable {
|
||||||
// Register schemes to standard scheme list.
|
// Register schemes to standard scheme list.
|
||||||
void RegisterStandardSchemes(const std::vector<std::string>& schemes);
|
void RegisterStandardSchemes(const std::vector<std::string>& schemes);
|
||||||
|
|
||||||
|
// Register schemes that can handle service worker.
|
||||||
|
void RegisterServiceWorkerSchemes(const std::vector<std::string>& schemes);
|
||||||
|
|
||||||
// Register the protocol with certain request job.
|
// Register the protocol with certain request job.
|
||||||
template<typename RequestJob>
|
template<typename RequestJob>
|
||||||
void RegisterProtocol(const std::string& scheme,
|
void RegisterProtocol(const std::string& scheme,
|
||||||
|
|
|
@ -41,7 +41,7 @@ std::vector<std::string> MetricsToArray(uint32_t metrics) {
|
||||||
if (metrics & gfx::DisplayObserver::DISPLAY_METRIC_DEVICE_SCALE_FACTOR)
|
if (metrics & gfx::DisplayObserver::DISPLAY_METRIC_DEVICE_SCALE_FACTOR)
|
||||||
array.push_back("scaleFactor");
|
array.push_back("scaleFactor");
|
||||||
if (metrics & gfx::DisplayObserver::DISPLAY_METRIC_ROTATION)
|
if (metrics & gfx::DisplayObserver::DISPLAY_METRIC_ROTATION)
|
||||||
array.push_back("rotaion");
|
array.push_back("rotation");
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "atom/browser/api/atom_api_cookies.h"
|
#include "atom/browser/api/atom_api_cookies.h"
|
||||||
#include "atom/browser/api/atom_api_download_item.h"
|
#include "atom/browser/api/atom_api_download_item.h"
|
||||||
#include "atom/browser/api/atom_api_web_contents.h"
|
#include "atom/browser/api/atom_api_web_contents.h"
|
||||||
|
#include "atom/browser/api/atom_api_web_request.h"
|
||||||
#include "atom/browser/api/save_page_handler.h"
|
#include "atom/browser/api/save_page_handler.h"
|
||||||
#include "atom/browser/atom_browser_context.h"
|
#include "atom/browser/atom_browser_context.h"
|
||||||
#include "atom/browser/atom_browser_main_parts.h"
|
#include "atom/browser/atom_browser_main_parts.h"
|
||||||
|
@ -51,7 +52,7 @@ struct ClearStorageDataOptions {
|
||||||
uint32 GetStorageMask(const std::vector<std::string>& storage_types) {
|
uint32 GetStorageMask(const std::vector<std::string>& storage_types) {
|
||||||
uint32 storage_mask = 0;
|
uint32 storage_mask = 0;
|
||||||
for (const auto& it : storage_types) {
|
for (const auto& it : storage_types) {
|
||||||
auto type = base::StringToLowerASCII(it);
|
auto type = base::ToLowerASCII(it);
|
||||||
if (type == "appcache")
|
if (type == "appcache")
|
||||||
storage_mask |= StoragePartition::REMOVE_DATA_MASK_APPCACHE;
|
storage_mask |= StoragePartition::REMOVE_DATA_MASK_APPCACHE;
|
||||||
else if (type == "cookies")
|
else if (type == "cookies")
|
||||||
|
@ -75,7 +76,7 @@ uint32 GetStorageMask(const std::vector<std::string>& storage_types) {
|
||||||
uint32 GetQuotaMask(const std::vector<std::string>& quota_types) {
|
uint32 GetQuotaMask(const std::vector<std::string>& quota_types) {
|
||||||
uint32 quota_mask = 0;
|
uint32 quota_mask = 0;
|
||||||
for (const auto& it : quota_types) {
|
for (const auto& it : quota_types) {
|
||||||
auto type = base::StringToLowerASCII(it);
|
auto type = base::ToLowerASCII(it);
|
||||||
if (type == "temporary")
|
if (type == "temporary")
|
||||||
quota_mask |= StoragePartition::QUOTA_MANAGED_STORAGE_MASK_TEMPORARY;
|
quota_mask |= StoragePartition::QUOTA_MANAGED_STORAGE_MASK_TEMPORARY;
|
||||||
else if (type == "persistent")
|
else if (type == "persistent")
|
||||||
|
@ -233,7 +234,8 @@ void SetProxyInIO(net::URLRequestContextGetter* getter,
|
||||||
const net::ProxyConfig& config,
|
const net::ProxyConfig& config,
|
||||||
const base::Closure& callback) {
|
const base::Closure& callback) {
|
||||||
auto proxy_service = getter->GetURLRequestContext()->proxy_service();
|
auto proxy_service = getter->GetURLRequestContext()->proxy_service();
|
||||||
proxy_service->ResetConfigService(new net::ProxyConfigServiceFixed(config));
|
proxy_service->ResetConfigService(make_scoped_ptr(
|
||||||
|
new net::ProxyConfigServiceFixed(config)));
|
||||||
// Refetches and applies the new pac script if provided.
|
// Refetches and applies the new pac script if provided.
|
||||||
proxy_service->ForceReloadProxyConfig();
|
proxy_service->ForceReloadProxyConfig();
|
||||||
RunCallbackInUI(callback);
|
RunCallbackInUI(callback);
|
||||||
|
@ -253,7 +255,6 @@ Session::Session(AtomBrowserContext* browser_context)
|
||||||
Session::~Session() {
|
Session::~Session() {
|
||||||
content::BrowserContext::GetDownloadManager(browser_context())->
|
content::BrowserContext::GetDownloadManager(browser_context())->
|
||||||
RemoveObserver(this);
|
RemoveObserver(this);
|
||||||
Destroy();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::OnDownloadCreated(content::DownloadManager* manager,
|
void Session::OnDownloadCreated(content::DownloadManager* manager,
|
||||||
|
@ -271,14 +272,6 @@ void Session::OnDownloadCreated(content::DownloadManager* manager,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Session::IsDestroyed() const {
|
|
||||||
return !browser_context_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Session::Destroy() {
|
|
||||||
browser_context_ = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Session::ResolveProxy(const GURL& url, ResolveProxyCallback callback) {
|
void Session::ResolveProxy(const GURL& url, ResolveProxyCallback callback) {
|
||||||
new ResolveProxyHelper(browser_context(), url, callback);
|
new ResolveProxyHelper(browser_context(), url, callback);
|
||||||
}
|
}
|
||||||
|
@ -376,18 +369,12 @@ v8::Local<v8::Value> Session::Cookies(v8::Isolate* isolate) {
|
||||||
return v8::Local<v8::Value>::New(isolate, cookies_);
|
return v8::Local<v8::Value>::New(isolate, cookies_);
|
||||||
}
|
}
|
||||||
|
|
||||||
mate::ObjectTemplateBuilder Session::GetObjectTemplateBuilder(
|
v8::Local<v8::Value> Session::WebRequest(v8::Isolate* isolate) {
|
||||||
v8::Isolate* isolate) {
|
if (web_request_.IsEmpty()) {
|
||||||
return mate::ObjectTemplateBuilder(isolate)
|
auto handle = atom::api::WebRequest::Create(isolate, browser_context());
|
||||||
.SetMethod("resolveProxy", &Session::ResolveProxy)
|
web_request_.Reset(isolate, handle.ToV8());
|
||||||
.SetMethod("clearCache", &Session::ClearCache)
|
}
|
||||||
.SetMethod("clearStorageData", &Session::ClearStorageData)
|
return v8::Local<v8::Value>::New(isolate, web_request_);
|
||||||
.SetMethod("setProxy", &Session::SetProxy)
|
|
||||||
.SetMethod("setDownloadPath", &Session::SetDownloadPath)
|
|
||||||
.SetMethod("enableNetworkEmulation", &Session::EnableNetworkEmulation)
|
|
||||||
.SetMethod("disableNetworkEmulation", &Session::DisableNetworkEmulation)
|
|
||||||
.SetMethod("setCertificateVerifyProc", &Session::SetCertVerifyProc)
|
|
||||||
.SetProperty("cookies", &Session::Cookies);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
@ -410,6 +397,23 @@ mate::Handle<Session> Session::FromPartition(
|
||||||
static_cast<AtomBrowserContext*>(browser_context.get()));
|
static_cast<AtomBrowserContext*>(browser_context.get()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void Session::BuildPrototype(v8::Isolate* isolate,
|
||||||
|
v8::Local<v8::ObjectTemplate> prototype) {
|
||||||
|
mate::ObjectTemplateBuilder(isolate, prototype)
|
||||||
|
.MakeDestroyable()
|
||||||
|
.SetMethod("resolveProxy", &Session::ResolveProxy)
|
||||||
|
.SetMethod("clearCache", &Session::ClearCache)
|
||||||
|
.SetMethod("clearStorageData", &Session::ClearStorageData)
|
||||||
|
.SetMethod("setProxy", &Session::SetProxy)
|
||||||
|
.SetMethod("setDownloadPath", &Session::SetDownloadPath)
|
||||||
|
.SetMethod("enableNetworkEmulation", &Session::EnableNetworkEmulation)
|
||||||
|
.SetMethod("disableNetworkEmulation", &Session::DisableNetworkEmulation)
|
||||||
|
.SetMethod("setCertificateVerifyProc", &Session::SetCertVerifyProc)
|
||||||
|
.SetProperty("cookies", &Session::Cookies)
|
||||||
|
.SetProperty("webRequest", &Session::WebRequest);
|
||||||
|
}
|
||||||
|
|
||||||
void ClearWrapSession() {
|
void ClearWrapSession() {
|
||||||
g_wrap_session.Reset();
|
g_wrap_session.Reset();
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,10 @@ class Session: public mate::TrackableObject<Session>,
|
||||||
|
|
||||||
AtomBrowserContext* browser_context() const { return browser_context_.get(); }
|
AtomBrowserContext* browser_context() const { return browser_context_.get(); }
|
||||||
|
|
||||||
|
// mate::TrackableObject:
|
||||||
|
static void BuildPrototype(v8::Isolate* isolate,
|
||||||
|
v8::Local<v8::ObjectTemplate> prototype);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
explicit Session(AtomBrowserContext* browser_context);
|
explicit Session(AtomBrowserContext* browser_context);
|
||||||
~Session();
|
~Session();
|
||||||
|
@ -56,15 +60,7 @@ class Session: public mate::TrackableObject<Session>,
|
||||||
void OnDownloadCreated(content::DownloadManager* manager,
|
void OnDownloadCreated(content::DownloadManager* manager,
|
||||||
content::DownloadItem* item) override;
|
content::DownloadItem* item) override;
|
||||||
|
|
||||||
// mate::Wrappable:
|
|
||||||
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
|
||||||
v8::Isolate* isolate) override;
|
|
||||||
bool IsDestroyed() const override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// mate::TrackableObject:
|
|
||||||
void Destroy() override;
|
|
||||||
|
|
||||||
void ResolveProxy(const GURL& url, ResolveProxyCallback callback);
|
void ResolveProxy(const GURL& url, ResolveProxyCallback callback);
|
||||||
void ClearCache(const net::CompletionCallback& callback);
|
void ClearCache(const net::CompletionCallback& callback);
|
||||||
void ClearStorageData(mate::Arguments* args);
|
void ClearStorageData(mate::Arguments* args);
|
||||||
|
@ -74,9 +70,11 @@ class Session: public mate::TrackableObject<Session>,
|
||||||
void DisableNetworkEmulation();
|
void DisableNetworkEmulation();
|
||||||
void SetCertVerifyProc(v8::Local<v8::Value> proc, mate::Arguments* args);
|
void SetCertVerifyProc(v8::Local<v8::Value> proc, mate::Arguments* args);
|
||||||
v8::Local<v8::Value> Cookies(v8::Isolate* isolate);
|
v8::Local<v8::Value> Cookies(v8::Isolate* isolate);
|
||||||
|
v8::Local<v8::Value> WebRequest(v8::Isolate* isolate);
|
||||||
|
|
||||||
// Cached object for cookies API.
|
// Cached object.
|
||||||
v8::Global<v8::Value> cookies_;
|
v8::Global<v8::Value> cookies_;
|
||||||
|
v8::Global<v8::Value> web_request_;
|
||||||
|
|
||||||
scoped_refptr<AtomBrowserContext> browser_context_;
|
scoped_refptr<AtomBrowserContext> browser_context_;
|
||||||
|
|
||||||
|
|
|
@ -94,14 +94,6 @@ void Tray::OnDragEnded() {
|
||||||
Emit("drag-end");
|
Emit("drag-end");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Tray::IsDestroyed() const {
|
|
||||||
return !tray_icon_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Tray::Destroy() {
|
|
||||||
tray_icon_.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Tray::SetImage(mate::Arguments* args, const gfx::Image& image) {
|
void Tray::SetImage(mate::Arguments* args, const gfx::Image& image) {
|
||||||
tray_icon_->SetImage(image);
|
tray_icon_->SetImage(image);
|
||||||
}
|
}
|
||||||
|
@ -137,9 +129,11 @@ void Tray::DisplayBalloon(mate::Arguments* args,
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tray::PopUpContextMenu(mate::Arguments* args) {
|
void Tray::PopUpContextMenu(mate::Arguments* args) {
|
||||||
|
mate::Handle<Menu> menu;
|
||||||
|
args->GetNext(&menu);
|
||||||
gfx::Point pos;
|
gfx::Point pos;
|
||||||
args->GetNext(&pos);
|
args->GetNext(&pos);
|
||||||
tray_icon_->PopUpContextMenu(pos);
|
tray_icon_->PopUpContextMenu(pos, menu.IsEmpty() ? nullptr : menu->model());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tray::SetContextMenu(mate::Arguments* args, Menu* menu) {
|
void Tray::SetContextMenu(mate::Arguments* args, Menu* menu) {
|
||||||
|
@ -160,8 +154,7 @@ v8::Local<v8::Object> Tray::ModifiersToObject(v8::Isolate* isolate,
|
||||||
void Tray::BuildPrototype(v8::Isolate* isolate,
|
void Tray::BuildPrototype(v8::Isolate* isolate,
|
||||||
v8::Local<v8::ObjectTemplate> prototype) {
|
v8::Local<v8::ObjectTemplate> prototype) {
|
||||||
mate::ObjectTemplateBuilder(isolate, prototype)
|
mate::ObjectTemplateBuilder(isolate, prototype)
|
||||||
.SetMethod("destroy", &Tray::Destroy, true)
|
.MakeDestroyable()
|
||||||
.SetMethod("isDestroyed", &Tray::IsDestroyed, true)
|
|
||||||
.SetMethod("setImage", &Tray::SetImage)
|
.SetMethod("setImage", &Tray::SetImage)
|
||||||
.SetMethod("setPressedImage", &Tray::SetPressedImage)
|
.SetMethod("setPressedImage", &Tray::SetPressedImage)
|
||||||
.SetMethod("setToolTip", &Tray::SetToolTip)
|
.SetMethod("setToolTip", &Tray::SetToolTip)
|
||||||
|
|
|
@ -54,12 +54,6 @@ class Tray : public mate::TrackableObject<Tray>,
|
||||||
void OnDragExited() override;
|
void OnDragExited() override;
|
||||||
void OnDragEnded() override;
|
void OnDragEnded() override;
|
||||||
|
|
||||||
// mate::Wrappable:
|
|
||||||
bool IsDestroyed() const override;
|
|
||||||
|
|
||||||
// mate::TrackableObject:
|
|
||||||
void Destroy() override;
|
|
||||||
|
|
||||||
void SetImage(mate::Arguments* args, const gfx::Image& image);
|
void SetImage(mate::Arguments* args, const gfx::Image& image);
|
||||||
void SetPressedImage(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 SetToolTip(mate::Arguments* args, const std::string& tool_tip);
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "atom/browser/api/atom_api_web_contents.h"
|
#include "atom/browser/api/atom_api_web_contents.h"
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "atom/browser/api/atom_api_session.h"
|
#include "atom/browser/api/atom_api_session.h"
|
||||||
#include "atom/browser/api/atom_api_window.h"
|
#include "atom/browser/api/atom_api_window.h"
|
||||||
|
@ -148,7 +149,7 @@ struct Converter<net::HttpResponseHeaders*> {
|
||||||
std::string key;
|
std::string key;
|
||||||
std::string value;
|
std::string value;
|
||||||
while (headers->EnumerateHeaderLines(&iter, &key, &value)) {
|
while (headers->EnumerateHeaderLines(&iter, &key, &value)) {
|
||||||
key = base::StringToLowerASCII(key);
|
key = base::ToLowerASCII(key);
|
||||||
if (response_headers.HasKey(key)) {
|
if (response_headers.HasKey(key)) {
|
||||||
base::ListValue* values = nullptr;
|
base::ListValue* values = nullptr;
|
||||||
if (response_headers.GetList(key, &values))
|
if (response_headers.GetList(key, &values))
|
||||||
|
@ -171,7 +172,7 @@ struct Converter<content::SavePageType> {
|
||||||
std::string save_type;
|
std::string save_type;
|
||||||
if (!ConvertFromV8(isolate, val, &save_type))
|
if (!ConvertFromV8(isolate, val, &save_type))
|
||||||
return false;
|
return false;
|
||||||
save_type = base::StringToLowerASCII(save_type);
|
save_type = base::ToLowerASCII(save_type);
|
||||||
if (save_type == "htmlonly") {
|
if (save_type == "htmlonly") {
|
||||||
*out = content::SAVE_PAGE_TYPE_AS_ONLY_HTML;
|
*out = content::SAVE_PAGE_TYPE_AS_ONLY_HTML;
|
||||||
} else if (save_type == "htmlcomplete") {
|
} else if (save_type == "htmlcomplete") {
|
||||||
|
@ -194,8 +195,6 @@ namespace api {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
v8::Persistent<v8::ObjectTemplate> template_;
|
|
||||||
|
|
||||||
// The wrapWebContents function which is implemented in JavaScript
|
// The wrapWebContents function which is implemented in JavaScript
|
||||||
using WrapWebContentsCallback = base::Callback<void(v8::Local<v8::Value>)>;
|
using WrapWebContentsCallback = base::Callback<void(v8::Local<v8::Value>)>;
|
||||||
WrapWebContentsCallback g_wrap_web_contents;
|
WrapWebContentsCallback g_wrap_web_contents;
|
||||||
|
@ -225,7 +224,8 @@ WebContents::WebContents(content::WebContents* web_contents)
|
||||||
}
|
}
|
||||||
|
|
||||||
WebContents::WebContents(v8::Isolate* isolate,
|
WebContents::WebContents(v8::Isolate* isolate,
|
||||||
const mate::Dictionary& options) {
|
const mate::Dictionary& options)
|
||||||
|
: request_id_(0) {
|
||||||
// Whether it is a guest WebContents.
|
// Whether it is a guest WebContents.
|
||||||
bool is_guest = false;
|
bool is_guest = false;
|
||||||
options.Get("isGuest", &is_guest);
|
options.Get("isGuest", &is_guest);
|
||||||
|
@ -290,7 +290,15 @@ WebContents::WebContents(v8::Isolate* isolate,
|
||||||
}
|
}
|
||||||
|
|
||||||
WebContents::~WebContents() {
|
WebContents::~WebContents() {
|
||||||
Destroy();
|
if (type_ == WEB_VIEW && managed_web_contents()) {
|
||||||
|
// When force destroying the "destroyed" event is not emitted.
|
||||||
|
WebContentsDestroyed();
|
||||||
|
|
||||||
|
guest_delegate_->Destroy();
|
||||||
|
|
||||||
|
Observe(nullptr);
|
||||||
|
DestroyWebContents();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebContents::AddMessageToConsole(content::WebContents* source,
|
bool WebContents::AddMessageToConsole(content::WebContents* source,
|
||||||
|
@ -414,6 +422,34 @@ bool WebContents::HandleContextMenu(const content::ContextMenuParams& params) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WebContents::OnGoToEntryOffset(int offset) {
|
||||||
|
GoToOffset(offset);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebContents::FindReply(content::WebContents* web_contents,
|
||||||
|
int request_id,
|
||||||
|
int number_of_matches,
|
||||||
|
const gfx::Rect& selection_rect,
|
||||||
|
int active_match_ordinal,
|
||||||
|
bool final_update) {
|
||||||
|
v8::Locker locker(isolate());
|
||||||
|
v8::HandleScope handle_scope(isolate());
|
||||||
|
|
||||||
|
mate::Dictionary result = mate::Dictionary::CreateEmpty(isolate());
|
||||||
|
if (number_of_matches == -1) {
|
||||||
|
result.Set("requestId", request_id);
|
||||||
|
result.Set("selectionArea", selection_rect);
|
||||||
|
result.Set("finalUpdate", final_update);
|
||||||
|
Emit("found-in-page", result);
|
||||||
|
} else if (final_update) {
|
||||||
|
result.Set("requestId", request_id);
|
||||||
|
result.Set("matches", number_of_matches);
|
||||||
|
result.Set("finalUpdate", final_update);
|
||||||
|
Emit("found-in-page", result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void WebContents::BeforeUnloadFired(const base::TimeTicks& proceed_time) {
|
void WebContents::BeforeUnloadFired(const base::TimeTicks& proceed_time) {
|
||||||
// Do nothing, we override this method just to avoid compilation error since
|
// Do nothing, we override this method just to avoid compilation error since
|
||||||
// there are two virtual functions named BeforeUnloadFired.
|
// there are two virtual functions named BeforeUnloadFired.
|
||||||
|
@ -445,6 +481,22 @@ void WebContents::PluginCrashed(const base::FilePath& plugin_path,
|
||||||
Emit("plugin-crashed", info.name, info.version);
|
Emit("plugin-crashed", info.name, info.version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WebContents::MediaStartedPlaying() {
|
||||||
|
Emit("media-started-playing");
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebContents::MediaPaused() {
|
||||||
|
Emit("media-paused");
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebContents::DidChangeThemeColor(SkColor theme_color) {
|
||||||
|
std::string hex_theme_color = base::StringPrintf("#%02X%02X%02X",
|
||||||
|
SkColorGetR(theme_color),
|
||||||
|
SkColorGetG(theme_color),
|
||||||
|
SkColorGetB(theme_color));
|
||||||
|
Emit("did-change-theme-color", hex_theme_color);
|
||||||
|
}
|
||||||
|
|
||||||
void WebContents::DocumentLoadedInFrame(
|
void WebContents::DocumentLoadedInFrame(
|
||||||
content::RenderFrameHost* render_frame_host) {
|
content::RenderFrameHost* render_frame_host) {
|
||||||
if (!render_frame_host->GetParent())
|
if (!render_frame_host->GetParent())
|
||||||
|
@ -460,14 +512,13 @@ void WebContents::DidFinishLoad(content::RenderFrameHost* render_frame_host,
|
||||||
Emit("did-finish-load");
|
Emit("did-finish-load");
|
||||||
}
|
}
|
||||||
|
|
||||||
// this error occurs when host could not be found
|
|
||||||
void WebContents::DidFailProvisionalLoad(
|
void WebContents::DidFailProvisionalLoad(
|
||||||
content::RenderFrameHost* render_frame_host,
|
content::RenderFrameHost* render_frame_host,
|
||||||
const GURL& validated_url,
|
const GURL& url,
|
||||||
int error_code,
|
int error_code,
|
||||||
const base::string16& error_description,
|
const base::string16& error_description,
|
||||||
bool was_ignored_by_handler) {
|
bool was_ignored_by_handler) {
|
||||||
Emit("did-fail-load", error_code, error_description, validated_url);
|
Emit("did-fail-provisional-load", error_code, error_description, url);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebContents::DidFailLoad(content::RenderFrameHost* render_frame_host,
|
void WebContents::DidFailLoad(content::RenderFrameHost* render_frame_host,
|
||||||
|
@ -515,14 +566,17 @@ void WebContents::DidNavigateMainFrame(
|
||||||
const content::LoadCommittedDetails& details,
|
const content::LoadCommittedDetails& details,
|
||||||
const content::FrameNavigateParams& params) {
|
const content::FrameNavigateParams& params) {
|
||||||
if (details.is_navigation_to_different_page())
|
if (details.is_navigation_to_different_page())
|
||||||
Emit("did-navigate-to-different-page");
|
Emit("did-navigate", params.url);
|
||||||
|
else if (details.is_in_page)
|
||||||
|
Emit("did-navigate-in-page", params.url);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebContents::TitleWasSet(content::NavigationEntry* entry,
|
void WebContents::TitleWasSet(content::NavigationEntry* entry,
|
||||||
bool explicit_set) {
|
bool explicit_set) {
|
||||||
// Back/Forward navigation may have pruned entries.
|
|
||||||
if (entry)
|
if (entry)
|
||||||
Emit("page-title-set", entry->GetTitle(), explicit_set);
|
Emit("-page-title-updated", entry->GetTitle(), explicit_set);
|
||||||
|
else
|
||||||
|
Emit("-page-title-updated", "", explicit_set);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebContents::DidUpdateFaviconURL(
|
void WebContents::DidUpdateFaviconURL(
|
||||||
|
@ -591,19 +645,6 @@ void WebContents::NavigationEntryCommitted(
|
||||||
details.is_in_page, details.did_replace_entry);
|
details.is_in_page, details.did_replace_entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebContents::Destroy() {
|
|
||||||
session_.Reset();
|
|
||||||
if (type_ == WEB_VIEW && managed_web_contents()) {
|
|
||||||
// When force destroying the "destroyed" event is not emitted.
|
|
||||||
WebContentsDestroyed();
|
|
||||||
|
|
||||||
guest_delegate_->Destroy();
|
|
||||||
|
|
||||||
Observe(nullptr);
|
|
||||||
DestroyWebContents();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int WebContents::GetID() const {
|
int WebContents::GetID() const {
|
||||||
return web_contents()->GetRenderProcessHost()->GetID();
|
return web_contents()->GetRenderProcessHost()->GetID();
|
||||||
}
|
}
|
||||||
|
@ -634,6 +675,15 @@ void WebContents::LoadURL(const GURL& url, const mate::Dictionary& options) {
|
||||||
web_contents()->GetController().LoadURLWithParams(params);
|
web_contents()->GetController().LoadURLWithParams(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WebContents::DownloadURL(const GURL& url) {
|
||||||
|
auto browser_context = web_contents()->GetBrowserContext();
|
||||||
|
auto download_manager =
|
||||||
|
content::BrowserContext::GetDownloadManager(browser_context);
|
||||||
|
|
||||||
|
download_manager->DownloadUrl(
|
||||||
|
content::DownloadUrlParameters::FromWebContents(web_contents(), url));
|
||||||
|
}
|
||||||
|
|
||||||
GURL WebContents::GetURL() const {
|
GURL WebContents::GetURL() const {
|
||||||
return web_contents()->GetURL();
|
return web_contents()->GetURL();
|
||||||
}
|
}
|
||||||
|
@ -732,6 +782,13 @@ bool WebContents::IsDevToolsOpened() {
|
||||||
return managed_web_contents()->IsDevToolsViewShowing();
|
return managed_web_contents()->IsDevToolsViewShowing();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WebContents::IsDevToolsFocused() {
|
||||||
|
if (type_ == REMOTE)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return managed_web_contents()->GetView()->IsDevToolsViewFocused();
|
||||||
|
}
|
||||||
|
|
||||||
void WebContents::EnableDeviceEmulation(
|
void WebContents::EnableDeviceEmulation(
|
||||||
const blink::WebDeviceEmulationParams& params) {
|
const blink::WebDeviceEmulationParams& params) {
|
||||||
if (type_ == REMOTE)
|
if (type_ == REMOTE)
|
||||||
|
@ -886,6 +943,25 @@ void WebContents::ReplaceMisspelling(const base::string16& word) {
|
||||||
web_contents()->ReplaceMisspelling(word);
|
web_contents()->ReplaceMisspelling(word);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32 WebContents::FindInPage(mate::Arguments* args) {
|
||||||
|
uint32 request_id = GetNextRequestId();
|
||||||
|
base::string16 search_text;
|
||||||
|
blink::WebFindOptions options;
|
||||||
|
if (!args->GetNext(&search_text) || search_text.empty()) {
|
||||||
|
args->ThrowError("Must provide a non-empty search content");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
args->GetNext(&options);
|
||||||
|
|
||||||
|
web_contents()->Find(request_id, search_text, options);
|
||||||
|
return request_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebContents::StopFindInPage(content::StopFindAction action) {
|
||||||
|
web_contents()->StopFinding(action);
|
||||||
|
}
|
||||||
|
|
||||||
void WebContents::Focus() {
|
void WebContents::Focus() {
|
||||||
web_contents()->Focus();
|
web_contents()->Focus();
|
||||||
}
|
}
|
||||||
|
@ -987,82 +1063,76 @@ v8::Local<v8::Value> WebContents::DevToolsWebContents(v8::Isolate* isolate) {
|
||||||
return v8::Local<v8::Value>::New(isolate, devtools_web_contents_);
|
return v8::Local<v8::Value>::New(isolate, devtools_web_contents_);
|
||||||
}
|
}
|
||||||
|
|
||||||
mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
|
// static
|
||||||
v8::Isolate* isolate) {
|
void WebContents::BuildPrototype(v8::Isolate* isolate,
|
||||||
if (template_.IsEmpty())
|
v8::Local<v8::ObjectTemplate> prototype) {
|
||||||
template_.Reset(isolate, mate::ObjectTemplateBuilder(isolate)
|
mate::ObjectTemplateBuilder(isolate, prototype)
|
||||||
.SetMethod("destroy", &WebContents::Destroy, true)
|
.MakeDestroyable()
|
||||||
.SetMethod("isDestroyed", &WebContents::IsDestroyed, true)
|
.SetMethod("getId", &WebContents::GetID)
|
||||||
.SetMethod("getId", &WebContents::GetID)
|
.SetMethod("equal", &WebContents::Equal)
|
||||||
.SetMethod("equal", &WebContents::Equal)
|
.SetMethod("_loadURL", &WebContents::LoadURL)
|
||||||
.SetMethod("_loadURL", &WebContents::LoadURL)
|
.SetMethod("downloadURL", &WebContents::DownloadURL)
|
||||||
.SetMethod("_getURL", &WebContents::GetURL)
|
.SetMethod("_getURL", &WebContents::GetURL)
|
||||||
.SetMethod("getTitle", &WebContents::GetTitle)
|
.SetMethod("getTitle", &WebContents::GetTitle)
|
||||||
.SetMethod("isLoading", &WebContents::IsLoading)
|
.SetMethod("isLoading", &WebContents::IsLoading)
|
||||||
.SetMethod("isWaitingForResponse", &WebContents::IsWaitingForResponse)
|
.SetMethod("isWaitingForResponse", &WebContents::IsWaitingForResponse)
|
||||||
.SetMethod("_stop", &WebContents::Stop)
|
.SetMethod("_stop", &WebContents::Stop)
|
||||||
.SetMethod("_goBack", &WebContents::GoBack)
|
.SetMethod("_goBack", &WebContents::GoBack)
|
||||||
.SetMethod("_goForward", &WebContents::GoForward)
|
.SetMethod("_goForward", &WebContents::GoForward)
|
||||||
.SetMethod("_goToOffset", &WebContents::GoToOffset)
|
.SetMethod("_goToOffset", &WebContents::GoToOffset)
|
||||||
.SetMethod("isCrashed", &WebContents::IsCrashed)
|
.SetMethod("isCrashed", &WebContents::IsCrashed)
|
||||||
.SetMethod("setUserAgent", &WebContents::SetUserAgent)
|
.SetMethod("setUserAgent", &WebContents::SetUserAgent)
|
||||||
.SetMethod("getUserAgent", &WebContents::GetUserAgent)
|
.SetMethod("getUserAgent", &WebContents::GetUserAgent)
|
||||||
.SetMethod("insertCSS", &WebContents::InsertCSS)
|
.SetMethod("insertCSS", &WebContents::InsertCSS)
|
||||||
.SetMethod("savePage", &WebContents::SavePage)
|
.SetMethod("savePage", &WebContents::SavePage)
|
||||||
.SetMethod("_executeJavaScript", &WebContents::ExecuteJavaScript)
|
.SetMethod("_executeJavaScript", &WebContents::ExecuteJavaScript)
|
||||||
.SetMethod("openDevTools", &WebContents::OpenDevTools)
|
.SetMethod("openDevTools", &WebContents::OpenDevTools)
|
||||||
.SetMethod("closeDevTools", &WebContents::CloseDevTools)
|
.SetMethod("closeDevTools", &WebContents::CloseDevTools)
|
||||||
.SetMethod("isDevToolsOpened", &WebContents::IsDevToolsOpened)
|
.SetMethod("isDevToolsOpened", &WebContents::IsDevToolsOpened)
|
||||||
.SetMethod("enableDeviceEmulation",
|
.SetMethod("isDevToolsFocused", &WebContents::IsDevToolsFocused)
|
||||||
&WebContents::EnableDeviceEmulation)
|
.SetMethod("enableDeviceEmulation",
|
||||||
.SetMethod("disableDeviceEmulation",
|
&WebContents::EnableDeviceEmulation)
|
||||||
&WebContents::DisableDeviceEmulation)
|
.SetMethod("disableDeviceEmulation",
|
||||||
.SetMethod("toggleDevTools", &WebContents::ToggleDevTools)
|
&WebContents::DisableDeviceEmulation)
|
||||||
.SetMethod("inspectElement", &WebContents::InspectElement)
|
.SetMethod("toggleDevTools", &WebContents::ToggleDevTools)
|
||||||
.SetMethod("setAudioMuted", &WebContents::SetAudioMuted)
|
.SetMethod("inspectElement", &WebContents::InspectElement)
|
||||||
.SetMethod("isAudioMuted", &WebContents::IsAudioMuted)
|
.SetMethod("setAudioMuted", &WebContents::SetAudioMuted)
|
||||||
.SetMethod("undo", &WebContents::Undo)
|
.SetMethod("isAudioMuted", &WebContents::IsAudioMuted)
|
||||||
.SetMethod("redo", &WebContents::Redo)
|
.SetMethod("undo", &WebContents::Undo)
|
||||||
.SetMethod("cut", &WebContents::Cut)
|
.SetMethod("redo", &WebContents::Redo)
|
||||||
.SetMethod("copy", &WebContents::Copy)
|
.SetMethod("cut", &WebContents::Cut)
|
||||||
.SetMethod("paste", &WebContents::Paste)
|
.SetMethod("copy", &WebContents::Copy)
|
||||||
.SetMethod("pasteAndMatchStyle", &WebContents::PasteAndMatchStyle)
|
.SetMethod("paste", &WebContents::Paste)
|
||||||
.SetMethod("delete", &WebContents::Delete)
|
.SetMethod("pasteAndMatchStyle", &WebContents::PasteAndMatchStyle)
|
||||||
.SetMethod("selectAll", &WebContents::SelectAll)
|
.SetMethod("delete", &WebContents::Delete)
|
||||||
.SetMethod("unselect", &WebContents::Unselect)
|
.SetMethod("selectAll", &WebContents::SelectAll)
|
||||||
.SetMethod("replace", &WebContents::Replace)
|
.SetMethod("unselect", &WebContents::Unselect)
|
||||||
.SetMethod("replaceMisspelling", &WebContents::ReplaceMisspelling)
|
.SetMethod("replace", &WebContents::Replace)
|
||||||
.SetMethod("focus", &WebContents::Focus)
|
.SetMethod("replaceMisspelling", &WebContents::ReplaceMisspelling)
|
||||||
.SetMethod("tabTraverse", &WebContents::TabTraverse)
|
.SetMethod("findInPage", &WebContents::FindInPage)
|
||||||
.SetMethod("_send", &WebContents::SendIPCMessage, true)
|
.SetMethod("stopFindInPage", &WebContents::StopFindInPage)
|
||||||
.SetMethod("sendInputEvent", &WebContents::SendInputEvent)
|
.SetMethod("focus", &WebContents::Focus)
|
||||||
.SetMethod("beginFrameSubscription",
|
.SetMethod("tabTraverse", &WebContents::TabTraverse)
|
||||||
&WebContents::BeginFrameSubscription)
|
.SetMethod("_send", &WebContents::SendIPCMessage)
|
||||||
.SetMethod("endFrameSubscription", &WebContents::EndFrameSubscription)
|
.SetMethod("sendInputEvent", &WebContents::SendInputEvent)
|
||||||
.SetMethod("setSize", &WebContents::SetSize)
|
.SetMethod("beginFrameSubscription",
|
||||||
.SetMethod("setAllowTransparency", &WebContents::SetAllowTransparency)
|
&WebContents::BeginFrameSubscription)
|
||||||
.SetMethod("isGuest", &WebContents::IsGuest)
|
.SetMethod("endFrameSubscription", &WebContents::EndFrameSubscription)
|
||||||
.SetMethod("getWebPreferences", &WebContents::GetWebPreferences)
|
.SetMethod("setSize", &WebContents::SetSize)
|
||||||
.SetMethod("getOwnerBrowserWindow", &WebContents::GetOwnerBrowserWindow)
|
.SetMethod("setAllowTransparency", &WebContents::SetAllowTransparency)
|
||||||
.SetMethod("hasServiceWorker", &WebContents::HasServiceWorker)
|
.SetMethod("isGuest", &WebContents::IsGuest)
|
||||||
.SetMethod("unregisterServiceWorker",
|
.SetMethod("getWebPreferences", &WebContents::GetWebPreferences)
|
||||||
&WebContents::UnregisterServiceWorker)
|
.SetMethod("getOwnerBrowserWindow", &WebContents::GetOwnerBrowserWindow)
|
||||||
.SetMethod("inspectServiceWorker", &WebContents::InspectServiceWorker)
|
.SetMethod("hasServiceWorker", &WebContents::HasServiceWorker)
|
||||||
.SetMethod("print", &WebContents::Print)
|
.SetMethod("unregisterServiceWorker",
|
||||||
.SetMethod("_printToPDF", &WebContents::PrintToPDF)
|
&WebContents::UnregisterServiceWorker)
|
||||||
.SetMethod("addWorkSpace", &WebContents::AddWorkSpace)
|
.SetMethod("inspectServiceWorker", &WebContents::InspectServiceWorker)
|
||||||
.SetMethod("removeWorkSpace", &WebContents::RemoveWorkSpace)
|
.SetMethod("print", &WebContents::Print)
|
||||||
.SetProperty("session", &WebContents::Session, true)
|
.SetMethod("_printToPDF", &WebContents::PrintToPDF)
|
||||||
.SetProperty("devToolsWebContents",
|
.SetMethod("addWorkSpace", &WebContents::AddWorkSpace)
|
||||||
&WebContents::DevToolsWebContents, true)
|
.SetMethod("removeWorkSpace", &WebContents::RemoveWorkSpace)
|
||||||
.Build());
|
.SetProperty("session", &WebContents::Session)
|
||||||
|
.SetProperty("devToolsWebContents", &WebContents::DevToolsWebContents);
|
||||||
return mate::ObjectTemplateBuilder(
|
|
||||||
isolate, v8::Local<v8::ObjectTemplate>::New(isolate, template_));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WebContents::IsDestroyed() const {
|
|
||||||
return !web_contents();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AtomBrowserContext* WebContents::GetBrowserContext() const {
|
AtomBrowserContext* WebContents::GetBrowserContext() const {
|
||||||
|
|
|
@ -54,12 +54,10 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||||
static mate::Handle<WebContents> Create(
|
static mate::Handle<WebContents> Create(
|
||||||
v8::Isolate* isolate, const mate::Dictionary& options);
|
v8::Isolate* isolate, const mate::Dictionary& options);
|
||||||
|
|
||||||
// mate::TrackableObject:
|
|
||||||
void Destroy() override;
|
|
||||||
|
|
||||||
int GetID() const;
|
int GetID() const;
|
||||||
bool Equal(const WebContents* web_contents) const;
|
bool Equal(const WebContents* web_contents) const;
|
||||||
void LoadURL(const GURL& url, const mate::Dictionary& options);
|
void LoadURL(const GURL& url, const mate::Dictionary& options);
|
||||||
|
void DownloadURL(const GURL& url);
|
||||||
GURL GetURL() const;
|
GURL GetURL() const;
|
||||||
base::string16 GetTitle() const;
|
base::string16 GetTitle() const;
|
||||||
bool IsLoading() const;
|
bool IsLoading() const;
|
||||||
|
@ -81,6 +79,7 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||||
void OpenDevTools(mate::Arguments* args);
|
void OpenDevTools(mate::Arguments* args);
|
||||||
void CloseDevTools();
|
void CloseDevTools();
|
||||||
bool IsDevToolsOpened();
|
bool IsDevToolsOpened();
|
||||||
|
bool IsDevToolsFocused();
|
||||||
void ToggleDevTools();
|
void ToggleDevTools();
|
||||||
void EnableDeviceEmulation(const blink::WebDeviceEmulationParams& params);
|
void EnableDeviceEmulation(const blink::WebDeviceEmulationParams& params);
|
||||||
void DisableDeviceEmulation();
|
void DisableDeviceEmulation();
|
||||||
|
@ -112,6 +111,8 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||||
void Unselect();
|
void Unselect();
|
||||||
void Replace(const base::string16& word);
|
void Replace(const base::string16& word);
|
||||||
void ReplaceMisspelling(const base::string16& word);
|
void ReplaceMisspelling(const base::string16& word);
|
||||||
|
uint32 FindInPage(mate::Arguments* args);
|
||||||
|
void StopFindInPage(content::StopFindAction action);
|
||||||
|
|
||||||
// Focus.
|
// Focus.
|
||||||
void Focus();
|
void Focus();
|
||||||
|
@ -144,16 +145,15 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||||
v8::Local<v8::Value> Session(v8::Isolate* isolate);
|
v8::Local<v8::Value> Session(v8::Isolate* isolate);
|
||||||
v8::Local<v8::Value> DevToolsWebContents(v8::Isolate* isolate);
|
v8::Local<v8::Value> DevToolsWebContents(v8::Isolate* isolate);
|
||||||
|
|
||||||
|
// mate::TrackableObject:
|
||||||
|
static void BuildPrototype(v8::Isolate* isolate,
|
||||||
|
v8::Local<v8::ObjectTemplate> prototype);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
explicit WebContents(content::WebContents* web_contents);
|
explicit WebContents(content::WebContents* web_contents);
|
||||||
WebContents(v8::Isolate* isolate, const mate::Dictionary& options);
|
WebContents(v8::Isolate* isolate, const mate::Dictionary& options);
|
||||||
~WebContents();
|
~WebContents();
|
||||||
|
|
||||||
// mate::Wrappable:
|
|
||||||
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
|
||||||
v8::Isolate* isolate) override;
|
|
||||||
bool IsDestroyed() const override;
|
|
||||||
|
|
||||||
// content::WebContentsDelegate:
|
// content::WebContentsDelegate:
|
||||||
bool AddMessageToConsole(content::WebContents* source,
|
bool AddMessageToConsole(content::WebContents* source,
|
||||||
int32 level,
|
int32 level,
|
||||||
|
@ -189,6 +189,13 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||||
void RendererUnresponsive(content::WebContents* source) override;
|
void RendererUnresponsive(content::WebContents* source) override;
|
||||||
void RendererResponsive(content::WebContents* source) override;
|
void RendererResponsive(content::WebContents* source) override;
|
||||||
bool HandleContextMenu(const content::ContextMenuParams& params) 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;
|
||||||
|
|
||||||
// content::WebContentsObserver:
|
// content::WebContentsObserver:
|
||||||
void BeforeUnloadFired(const base::TimeTicks& proceed_time) override;
|
void BeforeUnloadFired(const base::TimeTicks& proceed_time) override;
|
||||||
|
@ -227,6 +234,9 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||||
const std::vector<content::FaviconURL>& urls) override;
|
const std::vector<content::FaviconURL>& urls) override;
|
||||||
void PluginCrashed(const base::FilePath& plugin_path,
|
void PluginCrashed(const base::FilePath& plugin_path,
|
||||||
base::ProcessId plugin_pid) override;
|
base::ProcessId plugin_pid) override;
|
||||||
|
void MediaStartedPlaying() override;
|
||||||
|
void MediaPaused() override;
|
||||||
|
void DidChangeThemeColor(SkColor theme_color) override;
|
||||||
|
|
||||||
// brightray::InspectableWebContentsViewDelegate:
|
// brightray::InspectableWebContentsViewDelegate:
|
||||||
void DevToolsFocused() override;
|
void DevToolsFocused() override;
|
||||||
|
@ -242,6 +252,10 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||||
|
|
||||||
AtomBrowserContext* GetBrowserContext() const;
|
AtomBrowserContext* GetBrowserContext() const;
|
||||||
|
|
||||||
|
uint32 GetNextRequestId() {
|
||||||
|
return ++request_id_;
|
||||||
|
}
|
||||||
|
|
||||||
// Called when received a message from renderer.
|
// Called when received a message from renderer.
|
||||||
void OnRendererMessage(const base::string16& channel,
|
void OnRendererMessage(const base::string16& channel,
|
||||||
const base::ListValue& args);
|
const base::ListValue& args);
|
||||||
|
@ -263,6 +277,9 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||||
// The type of current WebContents.
|
// The type of current WebContents.
|
||||||
Type type_;
|
Type type_;
|
||||||
|
|
||||||
|
// Request id used for findInPage request.
|
||||||
|
uint32 request_id_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(WebContents);
|
DISALLOW_COPY_AND_ASSIGN(WebContents);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
119
atom/browser/api/atom_api_web_request.cc
Normal file
119
atom/browser/api/atom_api_web_request.cc
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
// Copyright (c) 2015 GitHub, Inc.
|
||||||
|
// Use of this source code is governed by the MIT license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "atom/browser/api/atom_api_web_request.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "atom/browser/atom_browser_context.h"
|
||||||
|
#include "atom/browser/net/atom_network_delegate.h"
|
||||||
|
#include "atom/common/native_mate_converters/callback.h"
|
||||||
|
#include "atom/common/native_mate_converters/net_converter.h"
|
||||||
|
#include "atom/common/native_mate_converters/value_converter.h"
|
||||||
|
#include "content/public/browser/browser_thread.h"
|
||||||
|
#include "native_mate/dictionary.h"
|
||||||
|
#include "native_mate/object_template_builder.h"
|
||||||
|
|
||||||
|
using content::BrowserThread;
|
||||||
|
|
||||||
|
namespace mate {
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct Converter<extensions::URLPattern> {
|
||||||
|
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
|
||||||
|
extensions::URLPattern* out) {
|
||||||
|
std::string pattern;
|
||||||
|
if (!ConvertFromV8(isolate, val, &pattern))
|
||||||
|
return false;
|
||||||
|
return out->Parse(pattern) == extensions::URLPattern::PARSE_SUCCESS;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mate
|
||||||
|
|
||||||
|
namespace atom {
|
||||||
|
|
||||||
|
namespace api {
|
||||||
|
|
||||||
|
WebRequest::WebRequest(AtomBrowserContext* browser_context)
|
||||||
|
: browser_context_(browser_context) {
|
||||||
|
}
|
||||||
|
|
||||||
|
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(browser_context));
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void WebRequest::BuildPrototype(v8::Isolate* isolate,
|
||||||
|
v8::Local<v8::ObjectTemplate> prototype) {
|
||||||
|
mate::ObjectTemplateBuilder(isolate, prototype)
|
||||||
|
.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
|
50
atom/browser/api/atom_api_web_request.h
Normal file
50
atom/browser/api/atom_api_web_request.h
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// mate::TrackableObject:
|
||||||
|
static void BuildPrototype(v8::Isolate* isolate,
|
||||||
|
v8::Local<v8::ObjectTemplate> prototype);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
explicit WebRequest(AtomBrowserContext* browser_context);
|
||||||
|
~WebRequest();
|
||||||
|
|
||||||
|
// 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_
|
|
@ -157,13 +157,12 @@ Window::Window(v8::Isolate* isolate, const mate::Dictionary& options) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Window::~Window() {
|
Window::~Window() {
|
||||||
if (window_)
|
if (!window_->IsClosed())
|
||||||
Destroy();
|
window_->CloseContents(nullptr);
|
||||||
}
|
|
||||||
|
|
||||||
void Window::OnPageTitleUpdated(bool* prevent_default,
|
// Destroy the native window in next tick because the native code might be
|
||||||
const std::string& title) {
|
// iterating all windows.
|
||||||
*prevent_default = Emit("page-title-updated", title);
|
base::MessageLoop::current()->DeleteSoon(FROM_HERE, window_.release());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::WillCloseWindow(bool* prevent_default) {
|
void Window::WillCloseWindow(bool* prevent_default) {
|
||||||
|
@ -171,19 +170,19 @@ void Window::WillCloseWindow(bool* prevent_default) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::OnWindowClosed() {
|
void Window::OnWindowClosed() {
|
||||||
if (api_web_contents_) {
|
api_web_contents_->DestroyWebContents();
|
||||||
api_web_contents_->DestroyWebContents();
|
|
||||||
api_web_contents_ = nullptr;
|
|
||||||
web_contents_.Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
RemoveFromWeakMap();
|
RemoveFromWeakMap();
|
||||||
window_->RemoveObserver(this);
|
window_->RemoveObserver(this);
|
||||||
|
|
||||||
|
// We can not call Destroy here because we need to call Emit first, but we
|
||||||
|
// also do not want any method to be used, so just mark as destroyed here.
|
||||||
|
MarkDestroyed();
|
||||||
|
|
||||||
Emit("closed");
|
Emit("closed");
|
||||||
|
|
||||||
// Clean up the resources after window has been closed.
|
// Destroy the native class when window is closed.
|
||||||
base::MessageLoop::current()->DeleteSoon(FROM_HERE, window_.release());
|
base::MessageLoop::current()->PostTask(FROM_HERE, GetDestroyClosure());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::OnWindowBlur() {
|
void Window::OnWindowBlur() {
|
||||||
|
@ -261,25 +260,26 @@ void Window::OnWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// static
|
// static
|
||||||
mate::Wrappable* Window::New(v8::Isolate* isolate,
|
mate::Wrappable* Window::New(v8::Isolate* isolate, mate::Arguments* args) {
|
||||||
const mate::Dictionary& options) {
|
|
||||||
if (!Browser::Get()->is_ready()) {
|
if (!Browser::Get()->is_ready()) {
|
||||||
isolate->ThrowException(v8::Exception::Error(mate::StringToV8(
|
isolate->ThrowException(v8::Exception::Error(mate::StringToV8(
|
||||||
isolate, "Cannot create BrowserWindow before app is ready")));
|
isolate, "Cannot create BrowserWindow before app is ready")));
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (args->Length() > 1) {
|
||||||
|
args->ThrowError();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
mate::Dictionary options;
|
||||||
|
if (!(args->Length() == 1 && args->GetNext(&options))) {
|
||||||
|
options = mate::Dictionary::CreateEmpty(isolate);
|
||||||
|
}
|
||||||
|
|
||||||
return new Window(isolate, options);
|
return new Window(isolate, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Window::IsDestroyed() const {
|
|
||||||
return !window_ || window_->IsClosed();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::Destroy() {
|
|
||||||
if (window_)
|
|
||||||
window_->CloseContents(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::Close() {
|
void Window::Close() {
|
||||||
window_->Close();
|
window_->Close();
|
||||||
}
|
}
|
||||||
|
@ -468,10 +468,6 @@ bool Window::IsWebViewFocused() {
|
||||||
return window_->IsWebViewFocused();
|
return window_->IsWebViewFocused();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Window::IsDevToolsFocused() {
|
|
||||||
return window_->IsDevToolsFocused();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::SetRepresentedFilename(const std::string& filename) {
|
void Window::SetRepresentedFilename(const std::string& filename) {
|
||||||
window_->SetRepresentedFilename(filename);
|
window_->SetRepresentedFilename(filename);
|
||||||
}
|
}
|
||||||
|
@ -488,6 +484,10 @@ bool Window::IsDocumentEdited() {
|
||||||
return window_->IsDocumentEdited();
|
return window_->IsDocumentEdited();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Window::SetIgnoreMouseEvents(bool ignore) {
|
||||||
|
return window_->SetIgnoreMouseEvents(ignore);
|
||||||
|
}
|
||||||
|
|
||||||
void Window::CapturePage(mate::Arguments* args) {
|
void Window::CapturePage(mate::Arguments* args) {
|
||||||
gfx::Rect rect;
|
gfx::Rect rect;
|
||||||
base::Callback<void(const gfx::Image&)> callback;
|
base::Callback<void(const gfx::Image&)> callback;
|
||||||
|
@ -617,8 +617,7 @@ v8::Local<v8::Value> Window::WebContents(v8::Isolate* isolate) {
|
||||||
void Window::BuildPrototype(v8::Isolate* isolate,
|
void Window::BuildPrototype(v8::Isolate* isolate,
|
||||||
v8::Local<v8::ObjectTemplate> prototype) {
|
v8::Local<v8::ObjectTemplate> prototype) {
|
||||||
mate::ObjectTemplateBuilder(isolate, prototype)
|
mate::ObjectTemplateBuilder(isolate, prototype)
|
||||||
.SetMethod("destroy", &Window::Destroy, true)
|
.MakeDestroyable()
|
||||||
.SetMethod("isDestroyed", &Window::IsDestroyed, true)
|
|
||||||
.SetMethod("close", &Window::Close)
|
.SetMethod("close", &Window::Close)
|
||||||
.SetMethod("focus", &Window::Focus)
|
.SetMethod("focus", &Window::Focus)
|
||||||
.SetMethod("isFocused", &Window::IsFocused)
|
.SetMethod("isFocused", &Window::IsFocused)
|
||||||
|
@ -663,10 +662,10 @@ void Window::BuildPrototype(v8::Isolate* isolate,
|
||||||
.SetMethod("getRepresentedFilename", &Window::GetRepresentedFilename)
|
.SetMethod("getRepresentedFilename", &Window::GetRepresentedFilename)
|
||||||
.SetMethod("setDocumentEdited", &Window::SetDocumentEdited)
|
.SetMethod("setDocumentEdited", &Window::SetDocumentEdited)
|
||||||
.SetMethod("isDocumentEdited", &Window::IsDocumentEdited)
|
.SetMethod("isDocumentEdited", &Window::IsDocumentEdited)
|
||||||
|
.SetMethod("setIgnoreMouseEvents", &Window::SetIgnoreMouseEvents)
|
||||||
.SetMethod("focusOnWebView", &Window::FocusOnWebView)
|
.SetMethod("focusOnWebView", &Window::FocusOnWebView)
|
||||||
.SetMethod("blurWebView", &Window::BlurWebView)
|
.SetMethod("blurWebView", &Window::BlurWebView)
|
||||||
.SetMethod("isWebViewFocused", &Window::IsWebViewFocused)
|
.SetMethod("isWebViewFocused", &Window::IsWebViewFocused)
|
||||||
.SetMethod("isDevToolsFocused", &Window::IsDevToolsFocused)
|
|
||||||
.SetMethod("capturePage", &Window::CapturePage)
|
.SetMethod("capturePage", &Window::CapturePage)
|
||||||
.SetMethod("setProgressBar", &Window::SetProgressBar)
|
.SetMethod("setProgressBar", &Window::SetProgressBar)
|
||||||
.SetMethod("setOverlayIcon", &Window::SetOverlayIcon)
|
.SetMethod("setOverlayIcon", &Window::SetOverlayIcon)
|
||||||
|
@ -690,8 +689,8 @@ void Window::BuildPrototype(v8::Isolate* isolate,
|
||||||
.SetMethod("showDefinitionForSelection",
|
.SetMethod("showDefinitionForSelection",
|
||||||
&Window::ShowDefinitionForSelection)
|
&Window::ShowDefinitionForSelection)
|
||||||
#endif
|
#endif
|
||||||
.SetProperty("id", &Window::ID, true)
|
.SetProperty("id", &Window::ID)
|
||||||
.SetProperty("webContents", &Window::WebContents, true);
|
.SetProperty("webContents", &Window::WebContents);
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
|
|
@ -38,8 +38,7 @@ class WebContents;
|
||||||
class Window : public mate::TrackableObject<Window>,
|
class Window : public mate::TrackableObject<Window>,
|
||||||
public NativeWindowObserver {
|
public NativeWindowObserver {
|
||||||
public:
|
public:
|
||||||
static mate::Wrappable* New(v8::Isolate* isolate,
|
static mate::Wrappable* New(v8::Isolate* isolate, mate::Arguments* args);
|
||||||
const mate::Dictionary& options);
|
|
||||||
|
|
||||||
static void BuildPrototype(v8::Isolate* isolate,
|
static void BuildPrototype(v8::Isolate* isolate,
|
||||||
v8::Local<v8::ObjectTemplate> prototype);
|
v8::Local<v8::ObjectTemplate> prototype);
|
||||||
|
@ -55,8 +54,6 @@ class Window : public mate::TrackableObject<Window>,
|
||||||
virtual ~Window();
|
virtual ~Window();
|
||||||
|
|
||||||
// NativeWindowObserver:
|
// NativeWindowObserver:
|
||||||
void OnPageTitleUpdated(bool* prevent_default,
|
|
||||||
const std::string& title) override;
|
|
||||||
void WillCloseWindow(bool* prevent_default) override;
|
void WillCloseWindow(bool* prevent_default) override;
|
||||||
void OnWindowClosed() override;
|
void OnWindowClosed() override;
|
||||||
void OnWindowBlur() override;
|
void OnWindowBlur() override;
|
||||||
|
@ -80,13 +77,7 @@ class Window : public mate::TrackableObject<Window>,
|
||||||
void OnWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) override;
|
void OnWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) override;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// mate::Wrappable:
|
|
||||||
bool IsDestroyed() const override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// mate::TrackableObject:
|
|
||||||
void Destroy() override;
|
|
||||||
|
|
||||||
// APIs for NativeWindow.
|
// APIs for NativeWindow.
|
||||||
void Close();
|
void Close();
|
||||||
void Focus();
|
void Focus();
|
||||||
|
@ -130,11 +121,11 @@ class Window : public mate::TrackableObject<Window>,
|
||||||
void FocusOnWebView();
|
void FocusOnWebView();
|
||||||
void BlurWebView();
|
void BlurWebView();
|
||||||
bool IsWebViewFocused();
|
bool IsWebViewFocused();
|
||||||
bool IsDevToolsFocused();
|
|
||||||
void SetRepresentedFilename(const std::string& filename);
|
void SetRepresentedFilename(const std::string& filename);
|
||||||
std::string GetRepresentedFilename();
|
std::string GetRepresentedFilename();
|
||||||
void SetDocumentEdited(bool edited);
|
void SetDocumentEdited(bool edited);
|
||||||
bool IsDocumentEdited();
|
bool IsDocumentEdited();
|
||||||
|
void SetIgnoreMouseEvents(bool ignore);
|
||||||
void CapturePage(mate::Arguments* args);
|
void CapturePage(mate::Arguments* args);
|
||||||
void SetProgressBar(double progress);
|
void SetProgressBar(double progress);
|
||||||
void SetOverlayIcon(const gfx::Image& overlay,
|
void SetOverlayIcon(const gfx::Image& overlay,
|
||||||
|
|
|
@ -24,12 +24,11 @@ bool FrameSubscriber::ShouldCaptureFrame(
|
||||||
base::TimeTicks present_time,
|
base::TimeTicks present_time,
|
||||||
scoped_refptr<media::VideoFrame>* storage,
|
scoped_refptr<media::VideoFrame>* storage,
|
||||||
DeliverFrameCallback* callback) {
|
DeliverFrameCallback* callback) {
|
||||||
*storage = media::VideoFrame::CreateFrame(media::VideoFrame::YV12, size_,
|
*storage = media::VideoFrame::CreateFrame(
|
||||||
gfx::Rect(size_), size_,
|
media::PIXEL_FORMAT_YV12,
|
||||||
base::TimeDelta());
|
size_, gfx::Rect(size_), size_, base::TimeDelta());
|
||||||
*callback = base::Bind(&FrameSubscriber::OnFrameDelivered,
|
*callback = base::Bind(&FrameSubscriber::OnFrameDelivered,
|
||||||
base::Unretained(this),
|
base::Unretained(this), *storage);
|
||||||
*storage);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ deprecate.event app, 'finish-launching', 'ready', ->
|
||||||
setImmediate => # give default app a chance to setup default menu.
|
setImmediate => # give default app a chance to setup default menu.
|
||||||
@emit 'finish-launching'
|
@emit 'finish-launching'
|
||||||
deprecate.event app, 'activate-with-no-open-windows', 'activate', (event, hasVisibleWindows) ->
|
deprecate.event app, 'activate-with-no-open-windows', 'activate', (event, hasVisibleWindows) ->
|
||||||
@emit 'activate-with-no-open-windows' if not hasVisibleWindows
|
@emit 'activate-with-no-open-windows', event if not hasVisibleWindows
|
||||||
deprecate.event app, 'select-certificate', 'select-client-certificate'
|
deprecate.event app, 'select-certificate', 'select-client-certificate'
|
||||||
|
|
||||||
# Wrappers for native classes.
|
# Wrappers for native classes.
|
||||||
|
@ -65,7 +65,6 @@ wrapDownloadItem = (downloadItem) ->
|
||||||
deprecate.property downloadItem, 'url', 'getURL'
|
deprecate.property downloadItem, 'url', 'getURL'
|
||||||
deprecate.property downloadItem, 'filename', 'getFilename'
|
deprecate.property downloadItem, 'filename', 'getFilename'
|
||||||
deprecate.property downloadItem, 'mimeType', 'getMimeType'
|
deprecate.property downloadItem, 'mimeType', 'getMimeType'
|
||||||
deprecate.property downloadItem, 'hasUserGesture', 'hasUserGesture'
|
|
||||||
deprecate.rename downloadItem, 'getUrl', 'getURL'
|
deprecate.rename downloadItem, 'getUrl', 'getURL'
|
||||||
downloadItemBindings._setWrapDownloadItem wrapDownloadItem
|
downloadItemBindings._setWrapDownloadItem wrapDownloadItem
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,11 @@ BrowserWindow::_init = ->
|
||||||
@webContents.on 'crashed', =>
|
@webContents.on 'crashed', =>
|
||||||
@emit '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
|
# 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
|
# 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,
|
# when we first start to load URL, if we do it earlier it won't have effect,
|
||||||
|
@ -78,6 +83,7 @@ BrowserWindow::send = -> @webContents.send.apply @webContents, arguments
|
||||||
BrowserWindow::openDevTools = -> @webContents.openDevTools.apply @webContents, arguments
|
BrowserWindow::openDevTools = -> @webContents.openDevTools.apply @webContents, arguments
|
||||||
BrowserWindow::closeDevTools = -> @webContents.closeDevTools()
|
BrowserWindow::closeDevTools = -> @webContents.closeDevTools()
|
||||||
BrowserWindow::isDevToolsOpened = -> @webContents.isDevToolsOpened()
|
BrowserWindow::isDevToolsOpened = -> @webContents.isDevToolsOpened()
|
||||||
|
BrowserWindow::isDevToolsFocused = -> @webContents.isDevToolsFocused()
|
||||||
BrowserWindow::toggleDevTools = -> @webContents.toggleDevTools()
|
BrowserWindow::toggleDevTools = -> @webContents.toggleDevTools()
|
||||||
BrowserWindow::inspectElement = -> @webContents.inspectElement.apply @webContents, arguments
|
BrowserWindow::inspectElement = -> @webContents.inspectElement.apply @webContents, arguments
|
||||||
BrowserWindow::inspectServiceWorker = -> @webContents.inspectServiceWorker()
|
BrowserWindow::inspectServiceWorker = -> @webContents.inspectServiceWorker()
|
||||||
|
@ -90,16 +96,18 @@ deprecate.member BrowserWindow, 'copy', 'webContents'
|
||||||
deprecate.member BrowserWindow, 'paste', 'webContents'
|
deprecate.member BrowserWindow, 'paste', 'webContents'
|
||||||
deprecate.member BrowserWindow, 'selectAll', 'webContents'
|
deprecate.member BrowserWindow, 'selectAll', 'webContents'
|
||||||
deprecate.member BrowserWindow, 'reloadIgnoringCache', 'webContents'
|
deprecate.member BrowserWindow, 'reloadIgnoringCache', 'webContents'
|
||||||
deprecate.member BrowserWindow, 'getPageTitle', 'webContents'
|
|
||||||
deprecate.member BrowserWindow, 'isLoading', 'webContents'
|
deprecate.member BrowserWindow, 'isLoading', 'webContents'
|
||||||
deprecate.member BrowserWindow, 'isWaitingForResponse', 'webContents'
|
deprecate.member BrowserWindow, 'isWaitingForResponse', 'webContents'
|
||||||
deprecate.member BrowserWindow, 'stop', 'webContents'
|
deprecate.member BrowserWindow, 'stop', 'webContents'
|
||||||
deprecate.member BrowserWindow, 'isCrashed', 'webContents'
|
deprecate.member BrowserWindow, 'isCrashed', 'webContents'
|
||||||
deprecate.member BrowserWindow, 'executeJavaScriptInDevTools', 'webContents'
|
|
||||||
deprecate.member BrowserWindow, 'print', 'webContents'
|
deprecate.member BrowserWindow, 'print', 'webContents'
|
||||||
deprecate.member BrowserWindow, 'printToPDF', 'webContents'
|
deprecate.member BrowserWindow, 'printToPDF', 'webContents'
|
||||||
deprecate.rename BrowserWindow, 'restart', 'reload'
|
deprecate.rename BrowserWindow, 'restart', 'reload'
|
||||||
deprecate.rename BrowserWindow, 'loadUrl', 'loadURL'
|
deprecate.rename BrowserWindow, 'loadUrl', 'loadURL'
|
||||||
deprecate.rename BrowserWindow, 'getUrl', 'getURL'
|
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
|
module.exports = BrowserWindow
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
# Import common modules.
|
common = require '../../../../common/api/lib/exports/electron'
|
||||||
module.exports = require '../../../../common/api/lib/exports/electron'
|
|
||||||
|
|
||||||
Object.defineProperties module.exports,
|
# Import common modules.
|
||||||
|
common.defineProperties exports
|
||||||
|
|
||||||
|
Object.defineProperties exports,
|
||||||
# Browser side modules, please sort with alphabet order.
|
# Browser side modules, please sort with alphabet order.
|
||||||
app:
|
app:
|
||||||
enumerable: true
|
enumerable: true
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{deprecate, ipcMain} = require 'electron'
|
{deprecate, ipcMain} = require 'electron'
|
||||||
|
|
||||||
# This module is deprecated, we mirror everything from ipcMain.
|
# This module is deprecated, we mirror everything from ipcMain.
|
||||||
deprecate.warn 'ipc module', 'ipcMain module'
|
deprecate.warn 'ipc module', 'require("electron").ipcMain'
|
||||||
|
|
||||||
module.exports = ipcMain
|
module.exports = ipcMain
|
||||||
|
|
|
@ -13,6 +13,11 @@ rolesMap =
|
||||||
minimize: 'minimize'
|
minimize: 'minimize'
|
||||||
close: 'close'
|
close: 'close'
|
||||||
|
|
||||||
|
# Maps methods that should be called directly on the BrowserWindow instance
|
||||||
|
methodInBrowserWindow =
|
||||||
|
minimize: true
|
||||||
|
close: true
|
||||||
|
|
||||||
class MenuItem
|
class MenuItem
|
||||||
@types = ['normal', 'separator', 'submenu', 'checkbox', 'radio']
|
@types = ['normal', 'separator', 'submenu', 'checkbox', 'radio']
|
||||||
|
|
||||||
|
@ -21,6 +26,8 @@ class MenuItem
|
||||||
|
|
||||||
{click, @selector, @type, @role, @label, @sublabel, @accelerator, @icon, @enabled, @visible, @checked, @submenu} = options
|
{click, @selector, @type, @role, @label, @sublabel, @accelerator, @icon, @enabled, @visible, @checked, @submenu} = options
|
||||||
|
|
||||||
|
if @submenu? and @submenu.constructor isnt Menu
|
||||||
|
@submenu = Menu.buildFromTemplate @submenu
|
||||||
@type = 'submenu' if not @type? and @submenu?
|
@type = 'submenu' if not @type? and @submenu?
|
||||||
throw new Error('Invalid submenu') if @type is 'submenu' and @submenu?.constructor isnt Menu
|
throw new Error('Invalid submenu') if @type is 'submenu' and @submenu?.constructor isnt Menu
|
||||||
|
|
||||||
|
@ -42,8 +49,12 @@ class MenuItem
|
||||||
# Manually flip the checked flags when clicked.
|
# Manually flip the checked flags when clicked.
|
||||||
@checked = !@checked if @type in ['checkbox', 'radio']
|
@checked = !@checked if @type in ['checkbox', 'radio']
|
||||||
|
|
||||||
if @role and rolesMap[@role] and process.platform isnt 'darwin'
|
if @role and rolesMap[@role] and process.platform isnt 'darwin' and focusedWindow?
|
||||||
focusedWindow?[rolesMap[@role]]()
|
methodName = rolesMap[@role]
|
||||||
|
if methodInBrowserWindow[methodName]
|
||||||
|
focusedWindow[methodName]()
|
||||||
|
else
|
||||||
|
focusedWindow.webContents?[methodName]()
|
||||||
else if typeof click is 'function'
|
else if typeof click is 'function'
|
||||||
click this, focusedWindow
|
click this, focusedWindow
|
||||||
else if typeof @selector is 'string'
|
else if typeof @selector is 'string'
|
||||||
|
|
|
@ -169,9 +169,8 @@ Menu.buildFromTemplate = (template) ->
|
||||||
for item in positionedTemplate
|
for item in positionedTemplate
|
||||||
throw new TypeError('Invalid template for MenuItem') unless typeof item is 'object'
|
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 = new MenuItem(item)
|
||||||
menuItem[key] = value for key, value of item when not menuItem[key]?
|
menuItem[key] ?= value for key, value of item
|
||||||
menu.append menuItem
|
menu.append menuItem
|
||||||
|
|
||||||
menu
|
menu
|
||||||
|
|
|
@ -6,6 +6,7 @@ PERSIST_PERFIX = 'persist:'
|
||||||
|
|
||||||
# Returns the Session from |partition| string.
|
# Returns the Session from |partition| string.
|
||||||
exports.fromPartition = (partition='') ->
|
exports.fromPartition = (partition='') ->
|
||||||
|
return exports.defaultSession if partition is ''
|
||||||
if partition.startsWith PERSIST_PERFIX
|
if partition.startsWith PERSIST_PERFIX
|
||||||
bindings.fromPartition partition.substr(PERSIST_PERFIX.length), false
|
bindings.fromPartition partition.substr(PERSIST_PERFIX.length), false
|
||||||
else
|
else
|
||||||
|
@ -14,7 +15,7 @@ exports.fromPartition = (partition='') ->
|
||||||
# Returns the default session.
|
# Returns the default session.
|
||||||
Object.defineProperty exports, 'defaultSession',
|
Object.defineProperty exports, 'defaultSession',
|
||||||
enumerable: true
|
enumerable: true
|
||||||
get: -> exports.fromPartition ''
|
get: -> bindings.fromPartition '', false
|
||||||
|
|
||||||
wrapSession = (session) ->
|
wrapSession = (session) ->
|
||||||
# session is an EventEmitter.
|
# session is an EventEmitter.
|
||||||
|
|
|
@ -7,6 +7,11 @@ nextId = 0
|
||||||
getNextId = -> ++nextId
|
getNextId = -> ++nextId
|
||||||
|
|
||||||
PDFPageSize =
|
PDFPageSize =
|
||||||
|
A5:
|
||||||
|
custom_display_name: "A5"
|
||||||
|
height_microns: 210000
|
||||||
|
name: "ISO_A5"
|
||||||
|
width_microns: 148000
|
||||||
A4:
|
A4:
|
||||||
custom_display_name: "A4"
|
custom_display_name: "A4"
|
||||||
height_microns: 297000
|
height_microns: 297000
|
||||||
|
@ -70,9 +75,21 @@ wrapWebContents = (webContents) ->
|
||||||
menu = Menu.buildFromTemplate params.menu
|
menu = Menu.buildFromTemplate params.menu
|
||||||
menu.popup params.x, params.y
|
menu.popup params.x, params.y
|
||||||
|
|
||||||
|
# This error occurs when host could not be found.
|
||||||
|
webContents.on 'did-fail-provisional-load', (args...) ->
|
||||||
|
# Calling loadURL during this event might cause crash, so delay the event
|
||||||
|
# until next tick.
|
||||||
|
setImmediate => @emit 'did-fail-load', args...
|
||||||
|
|
||||||
|
# Delays the page-title-updated event to next tick.
|
||||||
|
webContents.on '-page-title-updated', (args...) ->
|
||||||
|
setImmediate => @emit 'page-title-updated', args...
|
||||||
|
|
||||||
# Deprecated.
|
# Deprecated.
|
||||||
deprecate.rename webContents, 'loadUrl', 'loadURL'
|
deprecate.rename webContents, 'loadUrl', 'loadURL'
|
||||||
deprecate.rename webContents, 'getUrl', 'getURL'
|
deprecate.rename webContents, 'getUrl', 'getURL'
|
||||||
|
deprecate.event webContents, 'page-title-set', 'page-title-updated', (args...) ->
|
||||||
|
@emit 'page-title-set', args...
|
||||||
|
|
||||||
webContents.printToPDF = (options, callback) ->
|
webContents.printToPDF = (options, callback) ->
|
||||||
printingSetting =
|
printingSetting =
|
||||||
|
|
|
@ -30,11 +30,11 @@ class IDUserData : public base::SupportsUserData::Data {
|
||||||
|
|
||||||
TrackableObjectBase::TrackableObjectBase()
|
TrackableObjectBase::TrackableObjectBase()
|
||||||
: weak_map_id_(0), wrapped_(nullptr), weak_factory_(this) {
|
: weak_map_id_(0), wrapped_(nullptr), weak_factory_(this) {
|
||||||
RegisterDestructionCallback(
|
cleanup_ = RegisterDestructionCallback(GetDestroyClosure());
|
||||||
base::Bind(&TrackableObjectBase::Destroy, weak_factory_.GetWeakPtr()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TrackableObjectBase::~TrackableObjectBase() {
|
TrackableObjectBase::~TrackableObjectBase() {
|
||||||
|
cleanup_.Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrackableObjectBase::AfterInit(v8::Isolate* isolate) {
|
void TrackableObjectBase::AfterInit(v8::Isolate* isolate) {
|
||||||
|
@ -42,6 +42,18 @@ void TrackableObjectBase::AfterInit(v8::Isolate* isolate) {
|
||||||
AttachAsUserData(wrapped_);
|
AttachAsUserData(wrapped_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TrackableObjectBase::MarkDestroyed() {
|
||||||
|
GetWrapper(isolate())->SetAlignedPointerInInternalField(0, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
base::Closure TrackableObjectBase::GetDestroyClosure() {
|
||||||
|
return base::Bind(&TrackableObjectBase::Destroy, weak_factory_.GetWeakPtr());
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrackableObjectBase::Destroy() {
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
void TrackableObjectBase::AttachAsUserData(base::SupportsUserData* wrapped) {
|
void TrackableObjectBase::AttachAsUserData(base::SupportsUserData* wrapped) {
|
||||||
if (weak_map_id_ != 0) {
|
if (weak_map_id_ != 0) {
|
||||||
wrapped->SetUserData(kTrackedObjectKey, new IDUserData(weak_map_id_));
|
wrapped->SetUserData(kTrackedObjectKey, new IDUserData(weak_map_id_));
|
||||||
|
@ -63,9 +75,9 @@ int32_t TrackableObjectBase::GetIDFromWrappedClass(base::SupportsUserData* w) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
void TrackableObjectBase::RegisterDestructionCallback(
|
base::Closure TrackableObjectBase::RegisterDestructionCallback(
|
||||||
const base::Closure& closure) {
|
const base::Closure& c) {
|
||||||
atom::AtomBrowserMainParts::Get()->RegisterDestructionCallback(closure);
|
return atom::AtomBrowserMainParts::Get()->RegisterDestructionCallback(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mate
|
} // namespace mate
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "base/bind.h"
|
#include "base/bind.h"
|
||||||
#include "base/memory/scoped_ptr.h"
|
#include "base/memory/scoped_ptr.h"
|
||||||
#include "base/memory/weak_ptr.h"
|
#include "base/memory/weak_ptr.h"
|
||||||
|
#include "native_mate/object_template_builder.h"
|
||||||
|
|
||||||
namespace base {
|
namespace base {
|
||||||
class SupportsUserData;
|
class SupportsUserData;
|
||||||
|
@ -30,26 +31,32 @@ class TrackableObjectBase : public mate::EventEmitter {
|
||||||
// Wrap TrackableObject into a class that SupportsUserData.
|
// Wrap TrackableObject into a class that SupportsUserData.
|
||||||
void AttachAsUserData(base::SupportsUserData* wrapped);
|
void AttachAsUserData(base::SupportsUserData* wrapped);
|
||||||
|
|
||||||
// Subclasses should implement this to destroy their native types.
|
|
||||||
virtual void Destroy() = 0;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
~TrackableObjectBase() override;
|
~TrackableObjectBase() override;
|
||||||
|
|
||||||
// mate::Wrappable:
|
// mate::Wrappable:
|
||||||
void AfterInit(v8::Isolate* isolate) override;
|
void AfterInit(v8::Isolate* isolate) override;
|
||||||
|
|
||||||
|
// Mark the JS object as destroyed.
|
||||||
|
void MarkDestroyed();
|
||||||
|
|
||||||
|
// Returns a closure that can destroy the native class.
|
||||||
|
base::Closure GetDestroyClosure();
|
||||||
|
|
||||||
// Get the weak_map_id from SupportsUserData.
|
// Get the weak_map_id from SupportsUserData.
|
||||||
static int32_t GetIDFromWrappedClass(base::SupportsUserData* wrapped);
|
static int32_t GetIDFromWrappedClass(base::SupportsUserData* wrapped);
|
||||||
|
|
||||||
// Register a callback that should be destroyed before JavaScript environment
|
// Register a callback that should be destroyed before JavaScript environment
|
||||||
// gets destroyed.
|
// gets destroyed.
|
||||||
static void RegisterDestructionCallback(const base::Closure& closure);
|
static base::Closure RegisterDestructionCallback(const base::Closure& c);
|
||||||
|
|
||||||
int32_t weak_map_id_;
|
int32_t weak_map_id_;
|
||||||
base::SupportsUserData* wrapped_;
|
base::SupportsUserData* wrapped_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void Destroy();
|
||||||
|
|
||||||
|
base::Closure cleanup_;
|
||||||
base::WeakPtrFactory<TrackableObjectBase> weak_factory_;
|
base::WeakPtrFactory<TrackableObjectBase> weak_factory_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(TrackableObjectBase);
|
DISALLOW_COPY_AND_ASSIGN(TrackableObjectBase);
|
||||||
|
@ -91,11 +98,6 @@ class TrackableObject : public TrackableObjectBase {
|
||||||
return std::vector<v8::Local<v8::Object>>();
|
return std::vector<v8::Local<v8::Object>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
TrackableObject() {
|
|
||||||
RegisterDestructionCallback(
|
|
||||||
base::Bind(&TrackableObject<T>::ReleaseAllWeakReferences));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Removes this instance from the weak map.
|
// Removes this instance from the weak map.
|
||||||
void RemoveFromWeakMap() {
|
void RemoveFromWeakMap() {
|
||||||
if (weak_map_ && weak_map_->Has(weak_map_id()))
|
if (weak_map_ && weak_map_->Has(weak_map_id()))
|
||||||
|
@ -103,28 +105,49 @@ class TrackableObject : public TrackableObjectBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
TrackableObject() {}
|
||||||
~TrackableObject() override {
|
~TrackableObject() override {
|
||||||
RemoveFromWeakMap();
|
RemoveFromWeakMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AfterInit(v8::Isolate* isolate) override {
|
void AfterInit(v8::Isolate* isolate) override {
|
||||||
if (!weak_map_)
|
if (!weak_map_) {
|
||||||
weak_map_.reset(new atom::IDWeakMap);
|
weak_map_.reset(new atom::IDWeakMap);
|
||||||
|
RegisterDestructionCallback(
|
||||||
|
base::Bind(&TrackableObject<T>::ReleaseAllWeakReferences));
|
||||||
|
}
|
||||||
weak_map_id_ = weak_map_->Add(isolate, GetWrapper(isolate));
|
weak_map_id_ = weak_map_->Add(isolate, GetWrapper(isolate));
|
||||||
TrackableObjectBase::AfterInit(isolate);
|
TrackableObjectBase::AfterInit(isolate);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// mate::Wrappable:
|
||||||
|
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
||||||
|
v8::Isolate* isolate) override {
|
||||||
|
if (template_.IsEmpty()) {
|
||||||
|
auto templ = v8::ObjectTemplate::New(isolate);
|
||||||
|
T::BuildPrototype(isolate, templ);
|
||||||
|
template_.Reset(isolate, templ);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ObjectTemplateBuilder(
|
||||||
|
isolate, v8::Local<v8::ObjectTemplate>::New(isolate, template_));
|
||||||
|
}
|
||||||
|
|
||||||
// Releases all weak references in weak map, called when app is terminating.
|
// Releases all weak references in weak map, called when app is terminating.
|
||||||
static void ReleaseAllWeakReferences() {
|
static void ReleaseAllWeakReferences() {
|
||||||
weak_map_.reset();
|
weak_map_.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static v8::Persistent<v8::ObjectTemplate> template_;
|
||||||
static scoped_ptr<atom::IDWeakMap> weak_map_;
|
static scoped_ptr<atom::IDWeakMap> weak_map_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(TrackableObject);
|
DISALLOW_COPY_AND_ASSIGN(TrackableObject);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
v8::Persistent<v8::ObjectTemplate> TrackableObject<T>::template_;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
scoped_ptr<atom::IDWeakMap> TrackableObject<T>::weak_map_;
|
scoped_ptr<atom::IDWeakMap> TrackableObject<T>::weak_map_;
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "base/strings/string_number_conversions.h"
|
#include "base/strings/string_number_conversions.h"
|
||||||
#include "chrome/browser/printing/printing_message_filter.h"
|
#include "chrome/browser/printing/printing_message_filter.h"
|
||||||
#include "chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h"
|
#include "chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h"
|
||||||
|
#include "chrome/browser/renderer_host/pepper/widevine_cdm_message_filter.h"
|
||||||
#include "chrome/browser/speech/tts_message_filter.h"
|
#include "chrome/browser/speech/tts_message_filter.h"
|
||||||
#include "content/public/browser/browser_ppapi_host.h"
|
#include "content/public/browser/browser_ppapi_host.h"
|
||||||
#include "content/public/browser/client_certificate_delegate.h"
|
#include "content/public/browser/client_certificate_delegate.h"
|
||||||
|
@ -54,6 +55,8 @@ bool g_suppress_renderer_process_restart = false;
|
||||||
|
|
||||||
// Custom schemes to be registered to standard.
|
// Custom schemes to be registered to standard.
|
||||||
std::string g_custom_schemes = "";
|
std::string g_custom_schemes = "";
|
||||||
|
// Custom schemes to be registered to handle service worker.
|
||||||
|
std::string g_custom_service_worker_schemes = "";
|
||||||
|
|
||||||
scoped_refptr<net::X509Certificate> ImportCertFromFile(
|
scoped_refptr<net::X509Certificate> ImportCertFromFile(
|
||||||
const base::FilePath& path) {
|
const base::FilePath& path) {
|
||||||
|
@ -84,7 +87,12 @@ void AtomBrowserClient::SuppressRendererProcessRestartForOnce() {
|
||||||
|
|
||||||
void AtomBrowserClient::SetCustomSchemes(
|
void AtomBrowserClient::SetCustomSchemes(
|
||||||
const std::vector<std::string>& schemes) {
|
const std::vector<std::string>& schemes) {
|
||||||
g_custom_schemes = JoinString(schemes, ',');
|
g_custom_schemes = base::JoinString(schemes, ",");
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtomBrowserClient::SetCustomServiceWorkerSchemes(
|
||||||
|
const std::vector<std::string>& schemes) {
|
||||||
|
g_custom_service_worker_schemes = base::JoinString(schemes, ",");
|
||||||
}
|
}
|
||||||
|
|
||||||
AtomBrowserClient::AtomBrowserClient() : delegate_(nullptr) {
|
AtomBrowserClient::AtomBrowserClient() : delegate_(nullptr) {
|
||||||
|
@ -98,6 +106,8 @@ void AtomBrowserClient::RenderProcessWillLaunch(
|
||||||
int process_id = host->GetID();
|
int process_id = host->GetID();
|
||||||
host->AddFilter(new printing::PrintingMessageFilter(process_id));
|
host->AddFilter(new printing::PrintingMessageFilter(process_id));
|
||||||
host->AddFilter(new TtsMessageFilter(process_id, host->GetBrowserContext()));
|
host->AddFilter(new TtsMessageFilter(process_id, host->GetBrowserContext()));
|
||||||
|
host->AddFilter(
|
||||||
|
new WidevineCdmMessageFilter(process_id, host->GetBrowserContext()));
|
||||||
}
|
}
|
||||||
|
|
||||||
content::SpeechRecognitionManagerDelegate*
|
content::SpeechRecognitionManagerDelegate*
|
||||||
|
@ -116,7 +126,6 @@ void AtomBrowserClient::OverrideWebkitPrefs(
|
||||||
prefs->javascript_can_open_windows_automatically = true;
|
prefs->javascript_can_open_windows_automatically = true;
|
||||||
prefs->plugins_enabled = true;
|
prefs->plugins_enabled = true;
|
||||||
prefs->dom_paste_enabled = true;
|
prefs->dom_paste_enabled = true;
|
||||||
prefs->java_enabled = false;
|
|
||||||
prefs->allow_scripts_to_close_windows = true;
|
prefs->allow_scripts_to_close_windows = true;
|
||||||
prefs->javascript_can_access_clipboard = true;
|
prefs->javascript_can_access_clipboard = true;
|
||||||
prefs->local_storage_enabled = true;
|
prefs->local_storage_enabled = true;
|
||||||
|
@ -173,6 +182,11 @@ void AtomBrowserClient::AppendExtraCommandLineSwitches(
|
||||||
command_line->AppendSwitchASCII(switches::kRegisterStandardSchemes,
|
command_line->AppendSwitchASCII(switches::kRegisterStandardSchemes,
|
||||||
g_custom_schemes);
|
g_custom_schemes);
|
||||||
|
|
||||||
|
// The registered service worker schemes.
|
||||||
|
if (!g_custom_service_worker_schemes.empty())
|
||||||
|
command_line->AppendSwitchASCII(switches::kRegisterServiceWorkerSchemes,
|
||||||
|
g_custom_service_worker_schemes);
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
#if defined(OS_WIN)
|
||||||
// Append --app-user-model-id.
|
// Append --app-user-model-id.
|
||||||
PWSTR current_app_id;
|
PWSTR current_app_id;
|
||||||
|
@ -186,9 +200,16 @@ void AtomBrowserClient::AppendExtraCommandLineSwitches(
|
||||||
if (ContainsKey(pending_processes_, process_id))
|
if (ContainsKey(pending_processes_, process_id))
|
||||||
process_id = pending_processes_[process_id];
|
process_id = pending_processes_[process_id];
|
||||||
|
|
||||||
|
|
||||||
|
// Certain render process will be created with no associated render view,
|
||||||
|
// for example: ServiceWorker.
|
||||||
|
auto rvh = content::RenderViewHost::FromID(process_id, kDefaultRoutingID);
|
||||||
|
if (!rvh)
|
||||||
|
return;
|
||||||
|
|
||||||
// Get the WebContents of the render process.
|
// Get the WebContents of the render process.
|
||||||
content::WebContents* web_contents = content::WebContents::FromRenderViewHost(
|
content::WebContents* web_contents =
|
||||||
content::RenderViewHost::FromID(process_id, kDefaultRoutingID));
|
content::WebContents::FromRenderViewHost(rvh);
|
||||||
if (!web_contents)
|
if (!web_contents)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,9 @@ class AtomBrowserClient : public brightray::BrowserClient,
|
||||||
static void SuppressRendererProcessRestartForOnce();
|
static void SuppressRendererProcessRestartForOnce();
|
||||||
// Custom schemes to be registered to standard.
|
// Custom schemes to be registered to standard.
|
||||||
static void SetCustomSchemes(const std::vector<std::string>& schemes);
|
static void SetCustomSchemes(const std::vector<std::string>& schemes);
|
||||||
|
// Custom schemes to be registered to handle service worker.
|
||||||
|
static void SetCustomServiceWorkerSchemes(
|
||||||
|
const std::vector<std::string>& schemes);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// content::ContentBrowserClient:
|
// content::ContentBrowserClient:
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "atom/browser/atom_download_manager_delegate.h"
|
#include "atom/browser/atom_download_manager_delegate.h"
|
||||||
#include "atom/browser/browser.h"
|
#include "atom/browser/browser.h"
|
||||||
#include "atom/browser/net/atom_cert_verifier.h"
|
#include "atom/browser/net/atom_cert_verifier.h"
|
||||||
|
#include "atom/browser/net/atom_network_delegate.h"
|
||||||
#include "atom/browser/net/atom_ssl_config_service.h"
|
#include "atom/browser/net/atom_ssl_config_service.h"
|
||||||
#include "atom/browser/net/atom_url_request_job_factory.h"
|
#include "atom/browser/net/atom_url_request_job_factory.h"
|
||||||
#include "atom/browser/net/asar/asar_protocol_handler.h"
|
#include "atom/browser/net/asar/asar_protocol_handler.h"
|
||||||
|
@ -61,14 +62,19 @@ std::string RemoveWhitespace(const std::string& str) {
|
||||||
AtomBrowserContext::AtomBrowserContext(const std::string& partition,
|
AtomBrowserContext::AtomBrowserContext(const std::string& partition,
|
||||||
bool in_memory)
|
bool in_memory)
|
||||||
: brightray::BrowserContext(partition, in_memory),
|
: brightray::BrowserContext(partition, in_memory),
|
||||||
cert_verifier_(new AtomCertVerifier),
|
cert_verifier_(nullptr),
|
||||||
job_factory_(new AtomURLRequestJobFactory),
|
job_factory_(new AtomURLRequestJobFactory),
|
||||||
|
network_delegate_(new AtomNetworkDelegate),
|
||||||
allow_ntlm_everywhere_(false) {
|
allow_ntlm_everywhere_(false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
AtomBrowserContext::~AtomBrowserContext() {
|
AtomBrowserContext::~AtomBrowserContext() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
net::NetworkDelegate* AtomBrowserContext::CreateNetworkDelegate() {
|
||||||
|
return network_delegate_;
|
||||||
|
}
|
||||||
|
|
||||||
std::string AtomBrowserContext::GetUserAgent() {
|
std::string AtomBrowserContext::GetUserAgent() {
|
||||||
Browser* browser = Browser::Get();
|
Browser* browser = Browser::Get();
|
||||||
std::string name = RemoveWhitespace(browser->GetName());
|
std::string name = RemoveWhitespace(browser->GetName());
|
||||||
|
@ -86,7 +92,8 @@ std::string AtomBrowserContext::GetUserAgent() {
|
||||||
return content::BuildUserAgentFromProduct(user_agent);
|
return content::BuildUserAgentFromProduct(user_agent);
|
||||||
}
|
}
|
||||||
|
|
||||||
net::URLRequestJobFactory* AtomBrowserContext::CreateURLRequestJobFactory(
|
scoped_ptr<net::URLRequestJobFactory>
|
||||||
|
AtomBrowserContext::CreateURLRequestJobFactory(
|
||||||
content::ProtocolHandlerMap* handlers,
|
content::ProtocolHandlerMap* handlers,
|
||||||
content::URLRequestInterceptorScopedVector* interceptors) {
|
content::URLRequestInterceptorScopedVector* interceptors) {
|
||||||
scoped_ptr<AtomURLRequestJobFactory> job_factory(job_factory_);
|
scoped_ptr<AtomURLRequestJobFactory> job_factory(job_factory_);
|
||||||
|
@ -131,7 +138,7 @@ net::URLRequestJobFactory* AtomBrowserContext::CreateURLRequestJobFactory(
|
||||||
top_job_factory.Pass(), make_scoped_ptr(*it)));
|
top_job_factory.Pass(), make_scoped_ptr(*it)));
|
||||||
interceptors->weak_clear();
|
interceptors->weak_clear();
|
||||||
|
|
||||||
return top_job_factory.release();
|
return top_job_factory.Pass();
|
||||||
}
|
}
|
||||||
|
|
||||||
net::HttpCache::BackendFactory*
|
net::HttpCache::BackendFactory*
|
||||||
|
@ -160,8 +167,10 @@ content::BrowserPluginGuestManager* AtomBrowserContext::GetGuestManager() {
|
||||||
return guest_manager_.get();
|
return guest_manager_.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
net::CertVerifier* AtomBrowserContext::CreateCertVerifier() {
|
scoped_ptr<net::CertVerifier> AtomBrowserContext::CreateCertVerifier() {
|
||||||
return cert_verifier_;
|
DCHECK(!cert_verifier_);
|
||||||
|
cert_verifier_ = new AtomCertVerifier;
|
||||||
|
return make_scoped_ptr(cert_verifier_);
|
||||||
}
|
}
|
||||||
|
|
||||||
net::SSLConfigService* AtomBrowserContext::CreateSSLConfigService() {
|
net::SSLConfigService* AtomBrowserContext::CreateSSLConfigService() {
|
||||||
|
|
|
@ -13,6 +13,7 @@ namespace atom {
|
||||||
|
|
||||||
class AtomDownloadManagerDelegate;
|
class AtomDownloadManagerDelegate;
|
||||||
class AtomCertVerifier;
|
class AtomCertVerifier;
|
||||||
|
class AtomNetworkDelegate;
|
||||||
class AtomURLRequestJobFactory;
|
class AtomURLRequestJobFactory;
|
||||||
class WebViewManager;
|
class WebViewManager;
|
||||||
|
|
||||||
|
@ -22,13 +23,14 @@ class AtomBrowserContext : public brightray::BrowserContext {
|
||||||
~AtomBrowserContext() override;
|
~AtomBrowserContext() override;
|
||||||
|
|
||||||
// brightray::URLRequestContextGetter::Delegate:
|
// brightray::URLRequestContextGetter::Delegate:
|
||||||
|
net::NetworkDelegate* CreateNetworkDelegate() override;
|
||||||
std::string GetUserAgent() override;
|
std::string GetUserAgent() override;
|
||||||
net::URLRequestJobFactory* CreateURLRequestJobFactory(
|
scoped_ptr<net::URLRequestJobFactory> CreateURLRequestJobFactory(
|
||||||
content::ProtocolHandlerMap* handlers,
|
content::ProtocolHandlerMap* handlers,
|
||||||
content::URLRequestInterceptorScopedVector* interceptors) override;
|
content::URLRequestInterceptorScopedVector* interceptors) override;
|
||||||
net::HttpCache::BackendFactory* CreateHttpCacheBackendFactory(
|
net::HttpCache::BackendFactory* CreateHttpCacheBackendFactory(
|
||||||
const base::FilePath& base_path) override;
|
const base::FilePath& base_path) override;
|
||||||
net::CertVerifier* CreateCertVerifier() override;
|
scoped_ptr<net::CertVerifier> CreateCertVerifier() override;
|
||||||
net::SSLConfigService* CreateSSLConfigService() override;
|
net::SSLConfigService* CreateSSLConfigService() override;
|
||||||
bool AllowNTLMCredentialsForDomain(const GURL& auth_origin) override;
|
bool AllowNTLMCredentialsForDomain(const GURL& auth_origin) override;
|
||||||
|
|
||||||
|
@ -45,6 +47,8 @@ class AtomBrowserContext : public brightray::BrowserContext {
|
||||||
|
|
||||||
AtomURLRequestJobFactory* job_factory() const { return job_factory_; }
|
AtomURLRequestJobFactory* job_factory() const { return job_factory_; }
|
||||||
|
|
||||||
|
AtomNetworkDelegate* network_delegate() const { return network_delegate_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
scoped_ptr<AtomDownloadManagerDelegate> download_manager_delegate_;
|
scoped_ptr<AtomDownloadManagerDelegate> download_manager_delegate_;
|
||||||
scoped_ptr<WebViewManager> guest_manager_;
|
scoped_ptr<WebViewManager> guest_manager_;
|
||||||
|
@ -52,6 +56,7 @@ class AtomBrowserContext : public brightray::BrowserContext {
|
||||||
// Managed by brightray::BrowserContext.
|
// Managed by brightray::BrowserContext.
|
||||||
AtomCertVerifier* cert_verifier_;
|
AtomCertVerifier* cert_verifier_;
|
||||||
AtomURLRequestJobFactory* job_factory_;
|
AtomURLRequestJobFactory* job_factory_;
|
||||||
|
AtomNetworkDelegate* network_delegate_;
|
||||||
|
|
||||||
bool allow_ntlm_everywhere_;
|
bool allow_ntlm_everywhere_;
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,11 @@
|
||||||
|
|
||||||
namespace atom {
|
namespace atom {
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void Erase(T* container, typename T::iterator iter) {
|
||||||
|
container->erase(iter);
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
AtomBrowserMainParts* AtomBrowserMainParts::self_ = NULL;
|
AtomBrowserMainParts* AtomBrowserMainParts::self_ = NULL;
|
||||||
|
|
||||||
|
@ -56,9 +61,14 @@ bool AtomBrowserMainParts::SetExitCode(int code) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AtomBrowserMainParts::RegisterDestructionCallback(
|
int AtomBrowserMainParts::GetExitCode() {
|
||||||
|
return exit_code_ != nullptr ? *exit_code_ : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
base::Closure AtomBrowserMainParts::RegisterDestructionCallback(
|
||||||
const base::Closure& callback) {
|
const base::Closure& callback) {
|
||||||
destruction_callbacks_.push_back(callback);
|
auto iter = destructors_.insert(destructors_.end(), callback);
|
||||||
|
return base::Bind(&Erase<std::list<base::Closure>>, &destructors_, iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AtomBrowserMainParts::PreEarlyInitialization() {
|
void AtomBrowserMainParts::PreEarlyInitialization() {
|
||||||
|
@ -114,7 +124,8 @@ void AtomBrowserMainParts::PreMainMessageLoopRun() {
|
||||||
1000));
|
1000));
|
||||||
|
|
||||||
brightray::BrowserMainParts::PreMainMessageLoopRun();
|
brightray::BrowserMainParts::PreMainMessageLoopRun();
|
||||||
BridgeTaskRunner::MessageLoopIsReady();
|
bridge_task_runner_->MessageLoopIsReady();
|
||||||
|
bridge_task_runner_ = nullptr;
|
||||||
|
|
||||||
#if defined(USE_X11)
|
#if defined(USE_X11)
|
||||||
libgtk2ui::GtkInitFromCommandLine(*base::CommandLine::ForCurrentProcess());
|
libgtk2ui::GtkInitFromCommandLine(*base::CommandLine::ForCurrentProcess());
|
||||||
|
@ -149,8 +160,13 @@ void AtomBrowserMainParts::PostMainMessageLoopRun() {
|
||||||
// Make sure destruction callbacks are called before message loop is
|
// Make sure destruction callbacks are called before message loop is
|
||||||
// destroyed, otherwise some objects that need to be deleted on IO thread
|
// destroyed, otherwise some objects that need to be deleted on IO thread
|
||||||
// won't be freed.
|
// won't be freed.
|
||||||
for (const auto& callback : destruction_callbacks_)
|
// We don't use ranged for loop because iterators are getting invalided when
|
||||||
|
// the callback runs.
|
||||||
|
for (auto iter = destructors_.begin(); iter != destructors_.end();) {
|
||||||
|
base::Closure& callback = *iter;
|
||||||
|
++iter;
|
||||||
callback.Run();
|
callback.Run();
|
||||||
|
}
|
||||||
|
|
||||||
// Destroy JavaScript environment immediately after running destruction
|
// Destroy JavaScript environment immediately after running destruction
|
||||||
// callbacks.
|
// callbacks.
|
||||||
|
|
|
@ -34,9 +34,13 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts {
|
||||||
// Sets the exit code, will fail if the the message loop is not ready.
|
// Sets the exit code, will fail if the the message loop is not ready.
|
||||||
bool SetExitCode(int code);
|
bool SetExitCode(int code);
|
||||||
|
|
||||||
|
// Gets the exit code
|
||||||
|
int GetExitCode();
|
||||||
|
|
||||||
// Register a callback that should be destroyed before JavaScript environment
|
// Register a callback that should be destroyed before JavaScript environment
|
||||||
// gets destroyed.
|
// gets destroyed.
|
||||||
void RegisterDestructionCallback(const base::Closure& callback);
|
// Returns a closure that can be used to remove |callback| from the list.
|
||||||
|
base::Closure RegisterDestructionCallback(const base::Closure& callback);
|
||||||
|
|
||||||
Browser* browser() { return browser_.get(); }
|
Browser* browser() { return browser_.get(); }
|
||||||
|
|
||||||
|
@ -82,7 +86,7 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts {
|
||||||
base::Timer gc_timer_;
|
base::Timer gc_timer_;
|
||||||
|
|
||||||
// List of callbacks should be executed before destroying JS env.
|
// List of callbacks should be executed before destroying JS env.
|
||||||
std::list<base::Closure> destruction_callbacks_;
|
std::list<base::Closure> destructors_;
|
||||||
|
|
||||||
static AtomBrowserMainParts* self_;
|
static AtomBrowserMainParts* self_;
|
||||||
|
|
||||||
|
|
|
@ -13,20 +13,14 @@
|
||||||
namespace atom {
|
namespace atom {
|
||||||
|
|
||||||
void AtomBrowserMainParts::PreMainMessageLoopStart() {
|
void AtomBrowserMainParts::PreMainMessageLoopStart() {
|
||||||
// Initialize locale setting.
|
|
||||||
l10n_util::OverrideLocaleWithCocoaLocale();
|
|
||||||
|
|
||||||
// Force the NSApplication subclass to be used.
|
// Force the NSApplication subclass to be used.
|
||||||
NSApplication* application = [AtomApplication sharedApplication];
|
[AtomApplication sharedApplication];
|
||||||
|
|
||||||
|
// Set our own application delegate.
|
||||||
AtomApplicationDelegate* delegate = [[AtomApplicationDelegate alloc] init];
|
AtomApplicationDelegate* delegate = [[AtomApplicationDelegate alloc] init];
|
||||||
[NSApp setDelegate:(id<NSFileManagerDelegate>)delegate];
|
[NSApp setDelegate:(id<NSFileManagerDelegate>)delegate];
|
||||||
|
|
||||||
NSBundle* frameworkBundle = base::mac::FrameworkBundle();
|
brightray::BrowserMainParts::PreMainMessageLoopStart();
|
||||||
NSNib* mainNib = [[NSNib alloc] initWithNibNamed:@"MainMenu"
|
|
||||||
bundle:frameworkBundle];
|
|
||||||
[mainNib instantiateWithOwner:application topLevelObjects:nil];
|
|
||||||
[mainNib release];
|
|
||||||
|
|
||||||
// Prevent Cocoa from turning command-line arguments into
|
// Prevent Cocoa from turning command-line arguments into
|
||||||
// |-application:openFiles:|, since we already handle them directly.
|
// |-application:openFiles:|, since we already handle them directly.
|
||||||
|
|
|
@ -8,11 +8,6 @@
|
||||||
|
|
||||||
namespace atom {
|
namespace atom {
|
||||||
|
|
||||||
// static
|
|
||||||
std::vector<BridgeTaskRunner::TaskPair> BridgeTaskRunner::tasks_;
|
|
||||||
std::vector<BridgeTaskRunner::TaskPair> BridgeTaskRunner::non_nestable_tasks_;
|
|
||||||
|
|
||||||
// static
|
|
||||||
void BridgeTaskRunner::MessageLoopIsReady() {
|
void BridgeTaskRunner::MessageLoopIsReady() {
|
||||||
auto message_loop = base::MessageLoop::current();
|
auto message_loop = base::MessageLoop::current();
|
||||||
CHECK(message_loop);
|
CHECK(message_loop);
|
||||||
|
|
|
@ -20,7 +20,7 @@ class BridgeTaskRunner : public base::SingleThreadTaskRunner {
|
||||||
~BridgeTaskRunner() override {}
|
~BridgeTaskRunner() override {}
|
||||||
|
|
||||||
// Called when message loop is ready.
|
// Called when message loop is ready.
|
||||||
static void MessageLoopIsReady();
|
void MessageLoopIsReady();
|
||||||
|
|
||||||
// base::SingleThreadTaskRunner:
|
// base::SingleThreadTaskRunner:
|
||||||
bool PostDelayedTask(const tracked_objects::Location& from_here,
|
bool PostDelayedTask(const tracked_objects::Location& from_here,
|
||||||
|
@ -35,8 +35,8 @@ class BridgeTaskRunner : public base::SingleThreadTaskRunner {
|
||||||
private:
|
private:
|
||||||
using TaskPair = base::Tuple<
|
using TaskPair = base::Tuple<
|
||||||
tracked_objects::Location, base::Closure, base::TimeDelta>;
|
tracked_objects::Location, base::Closure, base::TimeDelta>;
|
||||||
static std::vector<TaskPair> tasks_;
|
std::vector<TaskPair> tasks_;
|
||||||
static std::vector<TaskPair> non_nestable_tasks_;
|
std::vector<TaskPair> non_nestable_tasks_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(BridgeTaskRunner);
|
DISALLOW_COPY_AND_ASSIGN(BridgeTaskRunner);
|
||||||
};
|
};
|
||||||
|
|
|
@ -55,7 +55,7 @@ void Browser::Exit(int code) {
|
||||||
// Must destroy windows before quitting, otherwise bad things can happen.
|
// Must destroy windows before quitting, otherwise bad things can happen.
|
||||||
atom::WindowList* window_list = atom::WindowList::GetInstance();
|
atom::WindowList* window_list = atom::WindowList::GetInstance();
|
||||||
if (window_list->size() == 0) {
|
if (window_list->size() == 0) {
|
||||||
NotifyAndShutdown();
|
Shutdown();
|
||||||
} else {
|
} else {
|
||||||
// Unlike Quit(), we do not ask to close window, but destroy the window
|
// Unlike Quit(), we do not ask to close window, but destroy the window
|
||||||
// without asking.
|
// without asking.
|
||||||
|
|
|
@ -19,11 +19,17 @@ void Browser::Focus() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Browser::AddRecentDocument(const base::FilePath& path) {
|
void Browser::AddRecentDocument(const base::FilePath& path) {
|
||||||
NSURL* u = [NSURL fileURLWithPath:base::mac::FilePathToNSString(path)];
|
NSString* path_string = base::mac::FilePathToNSString(path);
|
||||||
|
if (!path_string)
|
||||||
|
return;
|
||||||
|
NSURL* u = [NSURL fileURLWithPath:path_string];
|
||||||
|
if (!u)
|
||||||
|
return;
|
||||||
[[NSDocumentController sharedDocumentController] noteNewRecentDocumentURL:u];
|
[[NSDocumentController sharedDocumentController] noteNewRecentDocumentURL:u];
|
||||||
}
|
}
|
||||||
|
|
||||||
void Browser::ClearRecentDocuments() {
|
void Browser::ClearRecentDocuments() {
|
||||||
|
[[NSDocumentController sharedDocumentController] clearRecentDocuments:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
void Browser::SetAppUserModelID(const base::string16& name) {
|
void Browser::SetAppUserModelID(const base::string16& name) {
|
||||||
|
@ -38,7 +44,8 @@ std::string Browser::GetExecutableFileProductName() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
int Browser::DockBounce(BounceType type) {
|
int Browser::DockBounce(BounceType type) {
|
||||||
return [[AtomApplication sharedApplication] requestUserAttention:(NSRequestUserAttentionType)type];
|
return [[AtomApplication sharedApplication]
|
||||||
|
requestUserAttention:(NSRequestUserAttentionType)type];
|
||||||
}
|
}
|
||||||
|
|
||||||
void Browser::DockCancelBounce(int rid) {
|
void Browser::DockCancelBounce(int rid) {
|
||||||
|
@ -65,8 +72,29 @@ void Browser::DockHide() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Browser::DockShow() {
|
void Browser::DockShow() {
|
||||||
|
BOOL active = [[NSRunningApplication currentApplication] isActive];
|
||||||
ProcessSerialNumber psn = { 0, kCurrentProcess };
|
ProcessSerialNumber psn = { 0, kCurrentProcess };
|
||||||
TransformProcessType(&psn, kProcessTransformToForegroundApplication);
|
if (active) {
|
||||||
|
// Workaround buggy behavior of TransformProcessType.
|
||||||
|
// http://stackoverflow.com/questions/7596643/
|
||||||
|
NSArray* runningApps = [NSRunningApplication
|
||||||
|
runningApplicationsWithBundleIdentifier:@"com.apple.dock"];
|
||||||
|
for (NSRunningApplication* app in runningApps) {
|
||||||
|
[app activateWithOptions:NSApplicationActivateIgnoringOtherApps];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dispatch_time_t one_ms = dispatch_time(DISPATCH_TIME_NOW, USEC_PER_SEC);
|
||||||
|
dispatch_after(one_ms, dispatch_get_main_queue(), ^{
|
||||||
|
TransformProcessType(&psn, kProcessTransformToForegroundApplication);
|
||||||
|
dispatch_time_t one_ms = dispatch_time(DISPATCH_TIME_NOW, USEC_PER_SEC);
|
||||||
|
dispatch_after(one_ms, dispatch_get_main_queue(), ^{
|
||||||
|
[[NSRunningApplication currentApplication]
|
||||||
|
activateWithOptions:NSApplicationActivateIgnoringOtherApps];
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
TransformProcessType(&psn, kProcessTransformToForegroundApplication);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Browser::DockSetMenu(ui::MenuModel* model) {
|
void Browser::DockSetMenu(ui::MenuModel* model) {
|
||||||
|
|
|
@ -127,7 +127,7 @@ void Browser::SetUserTasks(const std::vector<UserTask>& tasks) {
|
||||||
|
|
||||||
PCWSTR Browser::GetAppUserModelID() {
|
PCWSTR Browser::GetAppUserModelID() {
|
||||||
if (app_user_model_id_.empty()) {
|
if (app_user_model_id_.empty()) {
|
||||||
SetAppUserModelID(ReplaceStringPlaceholders(
|
SetAppUserModelID(base::ReplaceStringPlaceholders(
|
||||||
kAppUserModelIDFormat, base::UTF8ToUTF16(GetName()), nullptr));
|
kAppUserModelIDFormat, base::UTF8ToUTF16(GetName()), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -380,7 +380,7 @@ gfx::ImageSkia CommonWebContentsDelegate::GetDevToolsWindowIcon() {
|
||||||
void CommonWebContentsDelegate::GetDevToolsWindowWMClass(
|
void CommonWebContentsDelegate::GetDevToolsWindowWMClass(
|
||||||
std::string* name, std::string* class_name) {
|
std::string* name, std::string* class_name) {
|
||||||
*class_name = Browser::Get()->GetName();
|
*class_name = Browser::Get()->GetName();
|
||||||
*name = base::StringToLowerASCII(*class_name);
|
*name = base::ToLowerASCII(*class_name);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,11 @@
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<h2 style="-webkit-app-region: drag">Welcome to Electron</h2>
|
<h2>
|
||||||
|
<script>
|
||||||
|
document.write(`Welcome to Electron (v${process.versions.electron})`)
|
||||||
|
</script>
|
||||||
|
</h2>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
To run your app with Electron, execute the following command under your
|
To run your app with Electron, execute the following command under your
|
||||||
|
@ -87,8 +91,18 @@
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The <code>path-to-your-app</code> should be the path to your own Electron
|
The <code>path-to-your-app</code> should be the path to your own Electron
|
||||||
app, you can read the <a href='https://github.com/atom/electron/blob/master/docs/tutorial/quick-start.md'>quick start</a>
|
app, you can read the
|
||||||
guide in Electron's <a href='https://github.com/atom/electron/blob/master/docs'>docs</a>
|
<script>
|
||||||
|
document.write(
|
||||||
|
`<a href='https://github.com/atom/electron/blob/v${process.versions.electron}/docs/tutorial/quick-start.md'>quick start</a>`
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
guide in Electron's
|
||||||
|
<script>
|
||||||
|
document.write(
|
||||||
|
`<a href='https://github.com/atom/electron/tree/v${process.versions.electron}/docs#readme'>docs</a>`
|
||||||
|
);
|
||||||
|
</script>
|
||||||
on how to write one.
|
on how to write one.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
|
@ -148,7 +148,11 @@ app.once('ready', function() {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Documentation',
|
label: 'Documentation',
|
||||||
click: function() { shell.openExternal('https://github.com/atom/electron/tree/master/docs#readme') }
|
click: function() {
|
||||||
|
shell.openExternal(
|
||||||
|
`https://github.com/atom/electron/tree/v${process.versions.electron}/docs#readme`
|
||||||
|
)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Community Discussions',
|
label: 'Community Discussions',
|
||||||
|
@ -189,11 +193,11 @@ app.once('ready', function() {
|
||||||
{
|
{
|
||||||
label: 'Hide Others',
|
label: 'Hide Others',
|
||||||
accelerator: 'Command+Shift+H',
|
accelerator: 'Command+Shift+H',
|
||||||
role: 'hideothers:'
|
role: 'hideothers'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Show All',
|
label: 'Show All',
|
||||||
role: 'unhide:'
|
role: 'unhide'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'separator'
|
type: 'separator'
|
||||||
|
@ -249,7 +253,11 @@ if (option.file && !option.webdriver) {
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
if (e.code == 'MODULE_NOT_FOUND') {
|
if (e.code == 'MODULE_NOT_FOUND') {
|
||||||
app.focus();
|
app.focus();
|
||||||
dialog.showErrorBox('Error opening app', 'The app provided is not a valid electron app, please read the docs on how to write one:\nhttps://github.com/atom/electron/tree/master/docs\n\n' + e.toString());
|
dialog.showErrorBox(
|
||||||
|
'Error opening app',
|
||||||
|
'The app provided is not a valid Electron app, please read the docs on how to write one:\n' +
|
||||||
|
`https://github.com/atom/electron/tree/v${process.versions.electron}/docs\n\n${e.toString()}`
|
||||||
|
);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
} else {
|
} else {
|
||||||
console.error('App threw an error when running', e);
|
console.error('App threw an error when running', e);
|
||||||
|
|
37
atom/browser/lib/desktop-capturer.coffee
Normal file
37
atom/browser/lib/desktop-capturer.coffee
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
{ipcMain} = require 'electron'
|
||||||
|
{desktopCapturer} = process.atomBinding 'desktop_capturer'
|
||||||
|
|
||||||
|
deepEqual = (opt1, opt2) ->
|
||||||
|
return JSON.stringify(opt1) is JSON.stringify(opt2)
|
||||||
|
|
||||||
|
# A queue for holding all requests from renderer process.
|
||||||
|
requestsQueue = []
|
||||||
|
|
||||||
|
ipcMain.on 'ATOM_BROWSER_DESKTOP_CAPTURER_GET_SOURCES', (event, captureWindow, captureScreen, thumbnailSize, id) ->
|
||||||
|
request = id: id, options: {captureWindow, captureScreen, thumbnailSize}, webContents: event.sender
|
||||||
|
requestsQueue.push request
|
||||||
|
desktopCapturer.startHandling captureWindow, captureScreen, thumbnailSize if requestsQueue.length is 1
|
||||||
|
# If the WebContents is destroyed before receiving result, just remove the
|
||||||
|
# reference from requestsQueue to make the module not send the result to it.
|
||||||
|
event.sender.once 'destroyed', ->
|
||||||
|
request.webContents = null
|
||||||
|
|
||||||
|
desktopCapturer.emit = (event, name, sources) ->
|
||||||
|
# Receiving sources result from main process, now send them back to renderer.
|
||||||
|
handledRequest = requestsQueue.shift 0
|
||||||
|
result = ({ id: source.id, name: source.name, thumbnail: source.thumbnail.toDataUrl() } for source in sources)
|
||||||
|
handledRequest.webContents?.send "ATOM_RENDERER_DESKTOP_CAPTURER_RESULT_#{handledRequest.id}", result
|
||||||
|
|
||||||
|
# Check the queue to see whether there is other same request. If has, handle
|
||||||
|
# it for reducing redunplicated `desktopCaptuer.startHandling` calls.
|
||||||
|
unhandledRequestsQueue = []
|
||||||
|
for request in requestsQueue
|
||||||
|
if deepEqual handledRequest.options, request.options
|
||||||
|
request.webContents?.send "ATOM_RENDERER_DESKTOP_CAPTURER_RESULT_#{request.id}", errorMessage, result
|
||||||
|
else
|
||||||
|
unhandledRequestsQueue.push request
|
||||||
|
requestsQueue = unhandledRequestsQueue
|
||||||
|
# If the requestsQueue is not empty, start a new request handling.
|
||||||
|
if requestsQueue.length > 0
|
||||||
|
{captureWindow, captureScreen, thumbnailSize} = requestsQueue[0].options
|
||||||
|
desktopCapturer.startHandling captureWindow, captureScreen, thumbnailSize
|
|
@ -13,16 +13,26 @@ supportedWebViewEvents = [
|
||||||
'did-get-redirect-request'
|
'did-get-redirect-request'
|
||||||
'dom-ready'
|
'dom-ready'
|
||||||
'console-message'
|
'console-message'
|
||||||
|
'devtools-opened'
|
||||||
|
'devtools-closed'
|
||||||
|
'devtools-focused'
|
||||||
'new-window'
|
'new-window'
|
||||||
|
'will-navigate'
|
||||||
|
'did-navigate'
|
||||||
|
'did-navigate-in-page'
|
||||||
'close'
|
'close'
|
||||||
'crashed'
|
'crashed'
|
||||||
'gpu-crashed'
|
'gpu-crashed'
|
||||||
'plugin-crashed'
|
'plugin-crashed'
|
||||||
'destroyed'
|
'destroyed'
|
||||||
'page-title-set'
|
'page-title-updated'
|
||||||
'page-favicon-updated'
|
'page-favicon-updated'
|
||||||
'enter-html-full-screen'
|
'enter-html-full-screen'
|
||||||
'leave-html-full-screen'
|
'leave-html-full-screen'
|
||||||
|
'media-started-playing'
|
||||||
|
'media-paused'
|
||||||
|
'found-in-page'
|
||||||
|
'did-change-theme-color'
|
||||||
]
|
]
|
||||||
|
|
||||||
nextInstanceId = 0
|
nextInstanceId = 0
|
||||||
|
@ -47,7 +57,7 @@ createGuest = (embedder, params) ->
|
||||||
guestInstances[id] = {guest, embedder}
|
guestInstances[id] = {guest, embedder}
|
||||||
|
|
||||||
# Destroy guest when the embedder is gone or navigated.
|
# Destroy guest when the embedder is gone or navigated.
|
||||||
destroyEvents = ['destroyed', 'crashed', 'did-navigate-to-different-page']
|
destroyEvents = ['destroyed', 'crashed', 'did-navigate']
|
||||||
destroy = ->
|
destroy = ->
|
||||||
destroyGuest embedder, id if guestInstances[id]?
|
destroyGuest embedder, id if guestInstances[id]?
|
||||||
for event in destroyEvents
|
for event in destroyEvents
|
||||||
|
|
|
@ -5,7 +5,7 @@ frameToGuest = {}
|
||||||
|
|
||||||
# Copy attribute of |parent| to |child| if it is not defined in |child|.
|
# Copy attribute of |parent| to |child| if it is not defined in |child|.
|
||||||
mergeOptions = (child, parent) ->
|
mergeOptions = (child, parent) ->
|
||||||
for own key, value of parent when key not in child
|
for own key, value of parent when key not of child
|
||||||
if typeof value is 'object'
|
if typeof value is 'object'
|
||||||
child[key] = mergeOptions {}, value
|
child[key] = mergeOptions {}, value
|
||||||
else
|
else
|
||||||
|
@ -30,20 +30,22 @@ createGuest = (embedder, url, frameName, options) ->
|
||||||
guest.loadURL url
|
guest.loadURL url
|
||||||
return guest.id
|
return guest.id
|
||||||
|
|
||||||
|
# Remember the embedder window's id.
|
||||||
|
options.webPreferences ?= {}
|
||||||
|
options.webPreferences.openerId = BrowserWindow.fromWebContents(embedder)?.id
|
||||||
|
|
||||||
guest = new BrowserWindow(options)
|
guest = new BrowserWindow(options)
|
||||||
guest.loadURL url
|
guest.loadURL url
|
||||||
|
|
||||||
# Remember the embedder, will be used by window.opener methods.
|
|
||||||
v8Util.setHiddenValue guest.webContents, 'embedder', embedder
|
|
||||||
|
|
||||||
# When |embedder| is destroyed we should also destroy attached guest, and if
|
# When |embedder| is destroyed we should also destroy attached guest, and if
|
||||||
# guest is closed by user then we should prevent |embedder| from double
|
# guest is closed by user then we should prevent |embedder| from double
|
||||||
# closing guest.
|
# closing guest.
|
||||||
|
guestId = guest.id
|
||||||
closedByEmbedder = ->
|
closedByEmbedder = ->
|
||||||
guest.removeListener 'closed', closedByUser
|
guest.removeListener 'closed', closedByUser
|
||||||
guest.destroy()
|
guest.destroy()
|
||||||
closedByUser = ->
|
closedByUser = ->
|
||||||
embedder.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSED', guest.id
|
embedder.send "ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSED_#{guestId}"
|
||||||
embedder.removeListener 'render-view-deleted', closedByEmbedder
|
embedder.removeListener 'render-view-deleted', closedByEmbedder
|
||||||
embedder.once 'render-view-deleted', closedByEmbedder
|
embedder.once 'render-view-deleted', closedByEmbedder
|
||||||
guest.once 'closed', closedByUser
|
guest.once 'closed', closedByUser
|
||||||
|
@ -72,24 +74,13 @@ ipcMain.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSE', (event, guestId) ->
|
||||||
ipcMain.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_METHOD', (event, guestId, method, args...) ->
|
ipcMain.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_METHOD', (event, guestId, method, args...) ->
|
||||||
BrowserWindow.fromId(guestId)?[method] args...
|
BrowserWindow.fromId(guestId)?[method] args...
|
||||||
|
|
||||||
ipcMain.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', (event, guestId, message, targetOrigin) ->
|
ipcMain.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', (event, guestId, message, targetOrigin, sourceOrigin) ->
|
||||||
|
sourceId = BrowserWindow.fromWebContents(event.sender)?.id
|
||||||
|
return unless sourceId?
|
||||||
|
|
||||||
guestContents = BrowserWindow.fromId(guestId)?.webContents
|
guestContents = BrowserWindow.fromId(guestId)?.webContents
|
||||||
if guestContents?.getURL().indexOf(targetOrigin) is 0 or targetOrigin is '*'
|
if guestContents?.getURL().indexOf(targetOrigin) is 0 or targetOrigin is '*'
|
||||||
guestContents.send 'ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', guestId, message, targetOrigin
|
guestContents?.send 'ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', sourceId, message, sourceOrigin
|
||||||
|
|
||||||
ipcMain.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPENER_POSTMESSAGE', (event, guestId, message, targetOrigin, sourceOrigin) ->
|
|
||||||
embedder = v8Util.getHiddenValue event.sender, 'embedder'
|
|
||||||
if embedder?.getURL().indexOf(targetOrigin) is 0 or targetOrigin is '*'
|
|
||||||
embedder.send 'ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', guestId, message, sourceOrigin
|
|
||||||
|
|
||||||
ipcMain.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD', (event, guestId, method, args...) ->
|
ipcMain.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD', (event, guestId, method, args...) ->
|
||||||
BrowserWindow.fromId(guestId)?.webContents?[method] args...
|
BrowserWindow.fromId(guestId)?.webContents?[method] args...
|
||||||
|
|
||||||
ipcMain.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_GET_GUEST_ID', (event) ->
|
|
||||||
embedder = v8Util.getHiddenValue event.sender, 'embedder'
|
|
||||||
if embedder?
|
|
||||||
guest = BrowserWindow.fromWebContents event.sender
|
|
||||||
if guest?
|
|
||||||
event.returnValue = guest.id
|
|
||||||
return
|
|
||||||
event.returnValue = null
|
|
||||||
|
|
|
@ -53,8 +53,8 @@ process.on 'uncaughtException', (error) ->
|
||||||
|
|
||||||
# Emit 'exit' event on quit.
|
# Emit 'exit' event on quit.
|
||||||
{app} = require 'electron'
|
{app} = require 'electron'
|
||||||
app.on 'quit', ->
|
app.on 'quit', (event, exitCode) ->
|
||||||
process.emit 'exit'
|
process.emit 'exit', exitCode
|
||||||
|
|
||||||
# Map process.exit to app.exit, which quits gracefully.
|
# Map process.exit to app.exit, which quits gracefully.
|
||||||
process.exit = app.exit
|
process.exit = app.exit
|
||||||
|
@ -108,6 +108,9 @@ app.setAppPath packagePath
|
||||||
# Load the chrome extension support.
|
# Load the chrome extension support.
|
||||||
require './chrome-extension'
|
require './chrome-extension'
|
||||||
|
|
||||||
|
# Load internal desktop-capturer module.
|
||||||
|
require './desktop-capturer'
|
||||||
|
|
||||||
# Set main startup script of the app.
|
# Set main startup script of the app.
|
||||||
mainStartupScript = packageJson.main or 'index.js'
|
mainStartupScript = packageJson.main or 'index.js'
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,8 @@ valueToMeta = (sender, value, optimizeSimpleObject=false) ->
|
||||||
meta.then = valueToMeta sender, value.then.bind(value)
|
meta.then = valueToMeta sender, value.then.bind(value)
|
||||||
else if meta.type is 'error'
|
else if meta.type is 'error'
|
||||||
meta.members = plainObjectToMeta value
|
meta.members = plainObjectToMeta value
|
||||||
|
# Error.name is not part of own properties.
|
||||||
|
meta.members.push {name: 'name', value: value.name}
|
||||||
else if meta.type is 'date'
|
else if meta.type is 'date'
|
||||||
meta.value = value.getTime()
|
meta.value = value.getTime()
|
||||||
else
|
else
|
||||||
|
@ -67,6 +69,7 @@ unwrapArgs = (sender, args) ->
|
||||||
when 'remote-object' then objectsRegistry.get meta.id
|
when 'remote-object' then objectsRegistry.get meta.id
|
||||||
when 'array' then unwrapArgs sender, meta.value
|
when 'array' then unwrapArgs sender, meta.value
|
||||||
when 'buffer' then new Buffer(meta.value)
|
when 'buffer' then new Buffer(meta.value)
|
||||||
|
when 'date' then new Date(meta.value)
|
||||||
when 'promise' then Promise.resolve(then: metaToValue(meta.then))
|
when 'promise' then Promise.resolve(then: metaToValue(meta.then))
|
||||||
when 'object'
|
when 'object'
|
||||||
ret = v8Util.createObjectWithName meta.name
|
ret = v8Util.createObjectWithName meta.name
|
||||||
|
@ -107,7 +110,7 @@ unwrapArgs = (sender, args) ->
|
||||||
# style function and the caller didn't pass a callback.
|
# style function and the caller didn't pass a callback.
|
||||||
callFunction = (event, func, caller, args) ->
|
callFunction = (event, func, caller, args) ->
|
||||||
funcMarkedAsync = v8Util.getHiddenValue(func, 'asynchronous')
|
funcMarkedAsync = v8Util.getHiddenValue(func, 'asynchronous')
|
||||||
funcPassedCallback = args[args.length - 1] is 'function'
|
funcPassedCallback = typeof args[args.length - 1] is 'function'
|
||||||
|
|
||||||
try
|
try
|
||||||
if funcMarkedAsync and not funcPassedCallback
|
if funcMarkedAsync and not funcPassedCallback
|
||||||
|
@ -219,5 +222,10 @@ ipcMain.on 'ATOM_BROWSER_GUEST_WEB_CONTENTS', (event, guestInstanceId) ->
|
||||||
catch e
|
catch e
|
||||||
event.returnValue = exceptionToMeta e
|
event.returnValue = exceptionToMeta e
|
||||||
|
|
||||||
ipcMain.on 'ATOM_BROWSER_LIST_MODULES', (event) ->
|
ipcMain.on 'ATOM_BROWSER_ASYNC_CALL_TO_GUEST_VIEW', (event, guestInstanceId, method, args...) ->
|
||||||
event.returnValue = (name for name of electron)
|
try
|
||||||
|
guestViewManager = require './guest-view-manager'
|
||||||
|
guest = guestViewManager.getGuest(guestInstanceId)
|
||||||
|
guest[method].apply(guest, args)
|
||||||
|
catch e
|
||||||
|
event.returnValue = exceptionToMeta e
|
||||||
|
|
|
@ -21,6 +21,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)applicationWillFinishLaunching:(NSNotification*)notify {
|
- (void)applicationWillFinishLaunching:(NSNotification*)notify {
|
||||||
|
// Don't add the "Enter Full Screen" menu item automatically.
|
||||||
|
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"NSFullScreenMenuItemEverywhere"];
|
||||||
|
|
||||||
atom::Browser::Get()->WillFinishLaunching();
|
atom::Browser::Get()->WillFinishLaunching();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,10 +32,10 @@
|
||||||
#include "ipc/ipc_message_macros.h"
|
#include "ipc/ipc_message_macros.h"
|
||||||
#include "native_mate/dictionary.h"
|
#include "native_mate/dictionary.h"
|
||||||
#include "ui/gfx/codec/png_codec.h"
|
#include "ui/gfx/codec/png_codec.h"
|
||||||
#include "ui/gfx/geometry/size_conversions.h"
|
|
||||||
#include "ui/gfx/geometry/point.h"
|
#include "ui/gfx/geometry/point.h"
|
||||||
#include "ui/gfx/geometry/rect.h"
|
#include "ui/gfx/geometry/rect.h"
|
||||||
#include "ui/gfx/geometry/size.h"
|
#include "ui/gfx/geometry/size.h"
|
||||||
|
#include "ui/gfx/geometry/size_conversions.h"
|
||||||
#include "ui/gfx/screen.h"
|
#include "ui/gfx/screen.h"
|
||||||
#include "ui/gl/gpu_switching_manager.h"
|
#include "ui/gl/gpu_switching_manager.h"
|
||||||
|
|
||||||
|
@ -245,6 +245,9 @@ bool NativeWindow::IsDocumentEdited() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NativeWindow::SetIgnoreMouseEvents(bool ignore) {
|
||||||
|
}
|
||||||
|
|
||||||
void NativeWindow::SetMenu(ui::MenuModel* menu) {
|
void NativeWindow::SetMenu(ui::MenuModel* menu) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,10 +268,6 @@ bool NativeWindow::IsWebViewFocused() {
|
||||||
return host_view && host_view->HasFocus();
|
return host_view && host_view->HasFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NativeWindow::IsDevToolsFocused() {
|
|
||||||
return inspectable_web_contents_->GetView()->IsDevToolsViewFocused();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NativeWindow::CapturePage(const gfx::Rect& rect,
|
void NativeWindow::CapturePage(const gfx::Rect& rect,
|
||||||
const CapturePageCallback& callback) {
|
const CapturePageCallback& callback) {
|
||||||
const auto view = web_contents()->GetRenderWidgetHostView();
|
const auto view = web_contents()->GetRenderWidgetHostView();
|
||||||
|
@ -291,10 +290,10 @@ void NativeWindow::CapturePage(const gfx::Rect& rect,
|
||||||
const float scale =
|
const float scale =
|
||||||
screen->GetDisplayNearestWindow(native_view).device_scale_factor();
|
screen->GetDisplayNearestWindow(native_view).device_scale_factor();
|
||||||
if (scale > 1.0f)
|
if (scale > 1.0f)
|
||||||
bitmap_size = gfx::ToCeiledSize(gfx::ScaleSize(view_size, scale));
|
bitmap_size = gfx::ScaleToCeiledSize(view_size, scale);
|
||||||
|
|
||||||
host->CopyFromBackingStore(
|
host->CopyFromBackingStore(
|
||||||
rect.IsEmpty() ? gfx::Rect(view_size) : rect,
|
gfx::Rect(rect.origin(), view_size),
|
||||||
bitmap_size,
|
bitmap_size,
|
||||||
base::Bind(&NativeWindow::OnCapturePageDone,
|
base::Bind(&NativeWindow::OnCapturePageDone,
|
||||||
weak_factory_.GetWeakPtr(),
|
weak_factory_.GetWeakPtr(),
|
||||||
|
@ -505,17 +504,6 @@ void NativeWindow::BeforeUnloadDialogCancelled() {
|
||||||
window_unresposive_closure_.Cancel();
|
window_unresposive_closure_.Cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NativeWindow::TitleWasSet(content::NavigationEntry* entry,
|
|
||||||
bool explicit_set) {
|
|
||||||
bool prevent_default = false;
|
|
||||||
std::string text = entry ? base::UTF16ToUTF8(entry->GetTitle()) : "";
|
|
||||||
FOR_EACH_OBSERVER(NativeWindowObserver,
|
|
||||||
observers_,
|
|
||||||
OnPageTitleUpdated(&prevent_default, text));
|
|
||||||
if (!prevent_default && !is_closed_)
|
|
||||||
SetTitle(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NativeWindow::OnMessageReceived(const IPC::Message& message) {
|
bool NativeWindow::OnMessageReceived(const IPC::Message& message) {
|
||||||
bool handled = true;
|
bool handled = true;
|
||||||
IPC_BEGIN_MESSAGE_MAP(NativeWindow, message)
|
IPC_BEGIN_MESSAGE_MAP(NativeWindow, message)
|
||||||
|
|
|
@ -139,6 +139,7 @@ class NativeWindow : public base::SupportsUserData,
|
||||||
virtual std::string GetRepresentedFilename();
|
virtual std::string GetRepresentedFilename();
|
||||||
virtual void SetDocumentEdited(bool edited);
|
virtual void SetDocumentEdited(bool edited);
|
||||||
virtual bool IsDocumentEdited();
|
virtual bool IsDocumentEdited();
|
||||||
|
virtual void SetIgnoreMouseEvents(bool ignore);
|
||||||
virtual void SetMenu(ui::MenuModel* menu);
|
virtual void SetMenu(ui::MenuModel* menu);
|
||||||
virtual bool HasModalDialog();
|
virtual bool HasModalDialog();
|
||||||
virtual gfx::NativeWindow GetNativeWindow() = 0;
|
virtual gfx::NativeWindow GetNativeWindow() = 0;
|
||||||
|
@ -156,7 +157,6 @@ class NativeWindow : public base::SupportsUserData,
|
||||||
virtual void FocusOnWebView();
|
virtual void FocusOnWebView();
|
||||||
virtual void BlurWebView();
|
virtual void BlurWebView();
|
||||||
virtual bool IsWebViewFocused();
|
virtual bool IsWebViewFocused();
|
||||||
virtual bool IsDevToolsFocused();
|
|
||||||
|
|
||||||
// Captures the page with |rect|, |callback| would be called when capturing is
|
// Captures the page with |rect|, |callback| would be called when capturing is
|
||||||
// done.
|
// done.
|
||||||
|
@ -262,7 +262,6 @@ class NativeWindow : public base::SupportsUserData,
|
||||||
// content::WebContentsObserver:
|
// content::WebContentsObserver:
|
||||||
void RenderViewCreated(content::RenderViewHost* render_view_host) override;
|
void RenderViewCreated(content::RenderViewHost* render_view_host) override;
|
||||||
void BeforeUnloadDialogCancelled() override;
|
void BeforeUnloadDialogCancelled() override;
|
||||||
void TitleWasSet(content::NavigationEntry* entry, bool explicit_set) override;
|
|
||||||
bool OnMessageReceived(const IPC::Message& message) override;
|
bool OnMessageReceived(const IPC::Message& message) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -62,6 +62,7 @@ class NativeWindowMac : public NativeWindow {
|
||||||
std::string GetRepresentedFilename() override;
|
std::string GetRepresentedFilename() override;
|
||||||
void SetDocumentEdited(bool edited) override;
|
void SetDocumentEdited(bool edited) override;
|
||||||
bool IsDocumentEdited() override;
|
bool IsDocumentEdited() override;
|
||||||
|
void SetIgnoreMouseEvents(bool ignore) override;
|
||||||
bool HasModalDialog() override;
|
bool HasModalDialog() override;
|
||||||
gfx::NativeWindow GetNativeWindow() override;
|
gfx::NativeWindow GetNativeWindow() override;
|
||||||
void SetProgressBar(double progress) override;
|
void SetProgressBar(double progress) override;
|
||||||
|
@ -77,6 +78,10 @@ class NativeWindowMac : public NativeWindow {
|
||||||
UpdateDraggableRegionViews(draggable_regions_);
|
UpdateDraggableRegionViews(draggable_regions_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool should_hide_native_toolbar_in_fullscreen() const {
|
||||||
|
return should_hide_native_toolbar_in_fullscreen_;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// NativeWindow:
|
// NativeWindow:
|
||||||
void HandleKeyboardEvent(
|
void HandleKeyboardEvent(
|
||||||
|
@ -117,6 +122,8 @@ class NativeWindowMac : public NativeWindow {
|
||||||
// The presentation options before entering kiosk mode.
|
// The presentation options before entering kiosk mode.
|
||||||
NSApplicationPresentationOptions kiosk_options_;
|
NSApplicationPresentationOptions kiosk_options_;
|
||||||
|
|
||||||
|
bool should_hide_native_toolbar_in_fullscreen_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(NativeWindowMac);
|
DISALLOW_COPY_AND_ASSIGN(NativeWindowMac);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#import "atom/browser/ui/cocoa/event_processing_window.h"
|
|
||||||
#include "atom/common/draggable_region.h"
|
#include "atom/common/draggable_region.h"
|
||||||
#include "atom/common/options_switches.h"
|
#include "atom/common/options_switches.h"
|
||||||
#include "base/mac/mac_util.h"
|
#include "base/mac/mac_util.h"
|
||||||
|
@ -177,8 +176,27 @@ bool ScopedDisableResize::disable_resize_ = false;
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)windowWillEnterFullScreen:(NSNotification*)notification {
|
||||||
|
// Hide the native toolbar before entering fullscreen, so there is no visual
|
||||||
|
// artifacts.
|
||||||
|
if (shell_->should_hide_native_toolbar_in_fullscreen()) {
|
||||||
|
NSWindow* window = shell_->GetNativeWindow();
|
||||||
|
[window setToolbar:nil];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void)windowDidEnterFullScreen:(NSNotification*)notification {
|
- (void)windowDidEnterFullScreen:(NSNotification*)notification {
|
||||||
shell_->NotifyWindowEnterFullScreen();
|
shell_->NotifyWindowEnterFullScreen();
|
||||||
|
|
||||||
|
// Restore the native toolbar immediately after entering fullscreen, if we do
|
||||||
|
// this before leaving fullscreen, traffic light buttons will be jumping.
|
||||||
|
if (shell_->should_hide_native_toolbar_in_fullscreen()) {
|
||||||
|
NSWindow* window = shell_->GetNativeWindow();
|
||||||
|
base::scoped_nsobject<NSToolbar> toolbar(
|
||||||
|
[[NSToolbar alloc] initWithIdentifier:@"titlebarStylingToolbar"]);
|
||||||
|
[toolbar setShowsBaselineSeparator:NO];
|
||||||
|
[window setToolbar:toolbar];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)windowDidExitFullScreen:(NSNotification*)notification {
|
- (void)windowDidExitFullScreen:(NSNotification*)notification {
|
||||||
|
@ -192,6 +210,11 @@ bool ScopedDisableResize::disable_resize_ = false;
|
||||||
|
|
||||||
- (void)windowWillClose:(NSNotification*)notification {
|
- (void)windowWillClose:(NSNotification*)notification {
|
||||||
shell_->NotifyWindowClosed();
|
shell_->NotifyWindowClosed();
|
||||||
|
|
||||||
|
// Clears the delegate when window is going to be closed, since EL Capitan it
|
||||||
|
// is possible that the methods of delegate would get called after the window
|
||||||
|
// has been closed.
|
||||||
|
[shell_->GetNativeWindow() setDelegate:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)windowShouldClose:(id)window {
|
- (BOOL)windowShouldClose:(id)window {
|
||||||
|
@ -204,7 +227,7 @@ bool ScopedDisableResize::disable_resize_ = false;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface AtomNSWindow : EventProcessingWindow {
|
@interface AtomNSWindow : NSWindow {
|
||||||
@private
|
@private
|
||||||
atom::NativeWindowMac* shell_;
|
atom::NativeWindowMac* shell_;
|
||||||
bool enable_larger_than_screen_;
|
bool enable_larger_than_screen_;
|
||||||
|
@ -227,6 +250,8 @@ bool ScopedDisableResize::disable_resize_ = false;
|
||||||
enable_larger_than_screen_ = enable;
|
enable_larger_than_screen_ = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NSWindow overrides.
|
||||||
|
|
||||||
- (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen*)screen {
|
- (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen*)screen {
|
||||||
// Resizing is disabled.
|
// Resizing is disabled.
|
||||||
if (ScopedDisableResize::IsResizeDisabled())
|
if (ScopedDisableResize::IsResizeDisabled())
|
||||||
|
@ -328,7 +353,8 @@ NativeWindowMac::NativeWindowMac(
|
||||||
const mate::Dictionary& options)
|
const mate::Dictionary& options)
|
||||||
: NativeWindow(web_contents, options),
|
: NativeWindow(web_contents, options),
|
||||||
is_kiosk_(false),
|
is_kiosk_(false),
|
||||||
attention_request_id_(0) {
|
attention_request_id_(0),
|
||||||
|
should_hide_native_toolbar_in_fullscreen_(false) {
|
||||||
int width = 800, height = 600;
|
int width = 800, height = 600;
|
||||||
options.Get(options::kWidth, &width);
|
options.Get(options::kWidth, &width);
|
||||||
options.Get(options::kHeight, &height);
|
options.Get(options::kHeight, &height);
|
||||||
|
@ -371,6 +397,12 @@ NativeWindowMac::NativeWindowMac(
|
||||||
styleMask |= NSFullSizeContentViewWindowMask;
|
styleMask |= NSFullSizeContentViewWindowMask;
|
||||||
styleMask |= NSUnifiedTitleAndToolbarWindowMask;
|
styleMask |= NSUnifiedTitleAndToolbarWindowMask;
|
||||||
}
|
}
|
||||||
|
// We capture this because we need to access the option later when
|
||||||
|
// entering/exiting fullscreen and since the options dict is only passed to
|
||||||
|
// the constructor but not stored, let’s store this option this way.
|
||||||
|
if (titleBarStyle == "hidden-inset") {
|
||||||
|
should_hide_native_toolbar_in_fullscreen_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
window_.reset([[AtomNSWindow alloc]
|
window_.reset([[AtomNSWindow alloc]
|
||||||
initWithContentRect:cocoa_bounds
|
initWithContentRect:cocoa_bounds
|
||||||
|
@ -437,12 +469,17 @@ NativeWindowMac::NativeWindowMac(
|
||||||
[window_ setDisableAutoHideCursor:disableAutoHideCursor];
|
[window_ setDisableAutoHideCursor:disableAutoHideCursor];
|
||||||
|
|
||||||
// Disable fullscreen button when 'fullscreen' is specified to false.
|
// Disable fullscreen button when 'fullscreen' is specified to false.
|
||||||
bool fullscreen;
|
bool fullscreen = false;
|
||||||
if (!(options.Get(options::kFullscreen, &fullscreen) &&
|
if (!(options.Get(options::kFullscreen, &fullscreen) &&
|
||||||
!fullscreen)) {
|
!fullscreen)) {
|
||||||
NSUInteger collectionBehavior = [window_ collectionBehavior];
|
NSUInteger collectionBehavior = [window_ collectionBehavior];
|
||||||
collectionBehavior |= NSWindowCollectionBehaviorFullScreenPrimary;
|
collectionBehavior |= NSWindowCollectionBehaviorFullScreenPrimary;
|
||||||
[window_ setCollectionBehavior:collectionBehavior];
|
[window_ setCollectionBehavior:collectionBehavior];
|
||||||
|
} else if (base::mac::IsOSElCapitanOrLater()) {
|
||||||
|
// On EL Capitan this flag is required to hide fullscreen button.
|
||||||
|
NSUInteger collectionBehavior = [window_ collectionBehavior];
|
||||||
|
collectionBehavior |= NSWindowCollectionBehaviorFullScreenAuxiliary;
|
||||||
|
[window_ setCollectionBehavior:collectionBehavior];
|
||||||
}
|
}
|
||||||
|
|
||||||
NSView* view = inspectable_web_contents()->GetView()->GetNativeView();
|
NSView* view = inspectable_web_contents()->GetView()->GetNativeView();
|
||||||
|
@ -682,6 +719,10 @@ bool NativeWindowMac::IsDocumentEdited() {
|
||||||
return [window_ isDocumentEdited];
|
return [window_ isDocumentEdited];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NativeWindowMac::SetIgnoreMouseEvents(bool ignore) {
|
||||||
|
[window_ setIgnoresMouseEvents:ignore];
|
||||||
|
}
|
||||||
|
|
||||||
bool NativeWindowMac::HasModalDialog() {
|
bool NativeWindowMac::HasModalDialog() {
|
||||||
return [window_ attachedSheet] != nil;
|
return [window_ attachedSheet] != nil;
|
||||||
}
|
}
|
||||||
|
@ -761,20 +802,14 @@ void NativeWindowMac::HandleKeyboardEvent(
|
||||||
event.type == content::NativeWebKeyboardEvent::Char)
|
event.type == content::NativeWebKeyboardEvent::Char)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (event.os_event.window == window_.get()) {
|
BOOL handled = [[NSApp mainMenu] performKeyEquivalent:event.os_event];
|
||||||
EventProcessingWindow* event_window =
|
if (!handled && event.os_event.window != window_.get()) {
|
||||||
static_cast<EventProcessingWindow*>(window_);
|
|
||||||
DCHECK([event_window isKindOfClass:[EventProcessingWindow class]]);
|
|
||||||
[event_window redispatchKeyEvent:event.os_event];
|
|
||||||
} else {
|
|
||||||
// The event comes from detached devtools view, and it has already been
|
// The event comes from detached devtools view, and it has already been
|
||||||
// handled by the devtools itself, we now send it to application menu to
|
|
||||||
// make menu acclerators work.
|
|
||||||
BOOL handled = [[NSApp mainMenu] performKeyEquivalent:event.os_event];
|
|
||||||
// Handle the cmd+~ shortcut.
|
|
||||||
if (!handled && (event.os_event.modifierFlags & NSCommandKeyMask) &&
|
if (!handled && (event.os_event.modifierFlags & NSCommandKeyMask) &&
|
||||||
(event.os_event.keyCode == 50 /* ~ key */))
|
(event.os_event.keyCode == 50 /* ~ key */)) {
|
||||||
|
// Handle the cmd+~ shortcut.
|
||||||
Focus(true);
|
Focus(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,10 +21,6 @@ class NativeWindowObserver {
|
||||||
public:
|
public:
|
||||||
virtual ~NativeWindowObserver() {}
|
virtual ~NativeWindowObserver() {}
|
||||||
|
|
||||||
// Called when the web page of the window has updated it's document title.
|
|
||||||
virtual void OnPageTitleUpdated(bool* prevent_default,
|
|
||||||
const std::string& title) {}
|
|
||||||
|
|
||||||
// Called when the web page in window wants to create a popup window.
|
// Called when the web page in window wants to create a popup window.
|
||||||
virtual void WillCreatePopupWindow(const base::string16& frame_name,
|
virtual void WillCreatePopupWindow(const base::string16& frame_name,
|
||||||
const GURL& target_url,
|
const GURL& target_url,
|
||||||
|
|
|
@ -60,12 +60,7 @@ const int kMenuBarHeight = 25;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool IsAltKey(const content::NativeWebKeyboardEvent& event) {
|
bool IsAltKey(const content::NativeWebKeyboardEvent& event) {
|
||||||
#if defined(USE_X11)
|
|
||||||
// 164 and 165 represent VK_LALT and VK_RALT.
|
|
||||||
return event.windowsKeyCode == 164 || event.windowsKeyCode == 165;
|
|
||||||
#else
|
|
||||||
return event.windowsKeyCode == ui::VKEY_MENU;
|
return event.windowsKeyCode == ui::VKEY_MENU;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsAltModifier(const content::NativeWebKeyboardEvent& event) {
|
bool IsAltModifier(const content::NativeWebKeyboardEvent& event) {
|
||||||
|
@ -180,7 +175,7 @@ NativeWindowViews::NativeWindowViews(
|
||||||
// Set WM_WINDOW_ROLE.
|
// Set WM_WINDOW_ROLE.
|
||||||
params.wm_role_name = "browser-window";
|
params.wm_role_name = "browser-window";
|
||||||
// Set WM_CLASS.
|
// Set WM_CLASS.
|
||||||
params.wm_class_name = base::StringToLowerASCII(name);
|
params.wm_class_name = base::ToLowerASCII(name);
|
||||||
params.wm_class_class = name;
|
params.wm_class_class = name;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -429,12 +424,14 @@ void NativeWindowViews::SetResizable(bool resizable) {
|
||||||
// WS_MAXIMIZEBOX => Maximize button
|
// WS_MAXIMIZEBOX => Maximize button
|
||||||
// WS_MINIMIZEBOX => Minimize button
|
// WS_MINIMIZEBOX => Minimize button
|
||||||
// WS_THICKFRAME => Resize handle
|
// WS_THICKFRAME => Resize handle
|
||||||
DWORD style = ::GetWindowLong(GetAcceleratedWidget(), GWL_STYLE);
|
if (!transparent()) {
|
||||||
if (resizable)
|
DWORD style = ::GetWindowLong(GetAcceleratedWidget(), GWL_STYLE);
|
||||||
style |= WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_THICKFRAME;
|
if (resizable)
|
||||||
else
|
style |= WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_THICKFRAME;
|
||||||
style = (style & ~(WS_MAXIMIZEBOX | WS_THICKFRAME)) | WS_MINIMIZEBOX;
|
else
|
||||||
::SetWindowLong(GetAcceleratedWidget(), GWL_STYLE, style);
|
style = (style & ~(WS_MAXIMIZEBOX | WS_THICKFRAME)) | WS_MINIMIZEBOX;
|
||||||
|
::SetWindowLong(GetAcceleratedWidget(), GWL_STYLE, style);
|
||||||
|
}
|
||||||
#elif defined(USE_X11)
|
#elif defined(USE_X11)
|
||||||
if (resizable != resizable_) {
|
if (resizable != resizable_) {
|
||||||
// On Linux there is no "resizable" property of a window, we have to set
|
// On Linux there is no "resizable" property of a window, we have to set
|
||||||
|
|
|
@ -84,20 +84,6 @@ bool NativeWindowViews::PreHandleMSG(
|
||||||
NotifyWindowMessage(message, w_param, l_param);
|
NotifyWindowMessage(message, w_param, l_param);
|
||||||
|
|
||||||
switch (message) {
|
switch (message) {
|
||||||
// Screen readers send WM_GETOBJECT in order to get the accessibility
|
|
||||||
// object, so take this opportunity to push Chromium into accessible
|
|
||||||
// mode if it isn't already, always say we didn't handle the message
|
|
||||||
// because we still want Chromium to handle returning the actual
|
|
||||||
// accessibility object.
|
|
||||||
case WM_GETOBJECT: {
|
|
||||||
const DWORD obj_id = static_cast<DWORD>(l_param);
|
|
||||||
if (obj_id == OBJID_CLIENT) {
|
|
||||||
const auto axState = content::BrowserAccessibilityState::GetInstance();
|
|
||||||
if (axState && !axState->IsAccessibleBrowser())
|
|
||||||
axState->OnScreenReaderDetected();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
case WM_COMMAND:
|
case WM_COMMAND:
|
||||||
// Handle thumbar button click message.
|
// Handle thumbar button click message.
|
||||||
if (HIWORD(w_param) == THBN_CLICKED)
|
if (HIWORD(w_param) == THBN_CLICKED)
|
||||||
|
|
|
@ -7,13 +7,14 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "atom/common/asar/archive.h"
|
||||||
|
#include "atom/common/asar/asar_util.h"
|
||||||
|
#include "atom/common/atom_constants.h"
|
||||||
#include "base/bind.h"
|
#include "base/bind.h"
|
||||||
#include "base/files/file_util.h"
|
#include "base/files/file_util.h"
|
||||||
#include "base/strings/string_util.h"
|
#include "base/strings/string_util.h"
|
||||||
#include "base/synchronization/lock.h"
|
#include "base/synchronization/lock.h"
|
||||||
#include "base/task_runner.h"
|
#include "base/task_runner.h"
|
||||||
#include "atom/common/asar/archive.h"
|
|
||||||
#include "atom/common/asar/asar_util.h"
|
|
||||||
#include "net/base/file_stream.h"
|
#include "net/base/file_stream.h"
|
||||||
#include "net/base/filename_util.h"
|
#include "net/base/filename_util.h"
|
||||||
#include "net/base/io_buffer.h"
|
#include "net/base/io_buffer.h"
|
||||||
|
@ -227,6 +228,19 @@ void URLRequestAsarJob::SetExtraRequestHeaders(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int URLRequestAsarJob::GetResponseCode() const {
|
||||||
|
// Request Job gets created only if path exists.
|
||||||
|
return 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
void URLRequestAsarJob::GetResponseInfo(net::HttpResponseInfo* info) {
|
||||||
|
std::string status("HTTP/1.1 200 OK");
|
||||||
|
net::HttpResponseHeaders* headers = new net::HttpResponseHeaders(status);
|
||||||
|
|
||||||
|
headers->AddHeader(atom::kCORSHeader);
|
||||||
|
info->headers = headers;
|
||||||
|
}
|
||||||
|
|
||||||
void URLRequestAsarJob::FetchMetaInfo(const base::FilePath& file_path,
|
void URLRequestAsarJob::FetchMetaInfo(const base::FilePath& file_path,
|
||||||
FileMetaInfo* meta_info) {
|
FileMetaInfo* meta_info) {
|
||||||
base::File::Info file_info;
|
base::File::Info file_info;
|
||||||
|
|
|
@ -61,6 +61,8 @@ class URLRequestAsarJob : public net::URLRequestJob {
|
||||||
net::Filter* SetupFilter() const override;
|
net::Filter* SetupFilter() const override;
|
||||||
bool GetMimeType(std::string* mime_type) const override;
|
bool GetMimeType(std::string* mime_type) const override;
|
||||||
void SetExtraRequestHeaders(const net::HttpRequestHeaders& headers) override;
|
void SetExtraRequestHeaders(const net::HttpRequestHeaders& headers) override;
|
||||||
|
int GetResponseCode() const override;
|
||||||
|
void GetResponseInfo(net::HttpResponseInfo* info) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Meta information about the file. It's used as a member in the
|
// Meta information about the file. It's used as a member in the
|
||||||
|
|
397
atom/browser/net/atom_network_delegate.cc
Normal file
397
atom/browser/net/atom_network_delegate.cc
Normal file
|
@ -0,0 +1,397 @@
|
||||||
|
// 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/net/atom_network_delegate.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "atom/common/native_mate_converters/net_converter.h"
|
||||||
|
#include "base/stl_util.h"
|
||||||
|
#include "base/strings/string_util.h"
|
||||||
|
#include "content/public/browser/browser_thread.h"
|
||||||
|
#include "content/public/browser/resource_request_info.h"
|
||||||
|
#include "net/url_request/url_request.h"
|
||||||
|
|
||||||
|
using content::BrowserThread;
|
||||||
|
|
||||||
|
namespace atom {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
const char* ResourceTypeToString(content::ResourceType type) {
|
||||||
|
switch (type) {
|
||||||
|
case content::RESOURCE_TYPE_MAIN_FRAME:
|
||||||
|
return "mainFrame";
|
||||||
|
case content::RESOURCE_TYPE_SUB_FRAME:
|
||||||
|
return "subFrame";
|
||||||
|
case content::RESOURCE_TYPE_STYLESHEET:
|
||||||
|
return "stylesheet";
|
||||||
|
case content::RESOURCE_TYPE_SCRIPT:
|
||||||
|
return "script";
|
||||||
|
case content::RESOURCE_TYPE_IMAGE:
|
||||||
|
return "image";
|
||||||
|
case content::RESOURCE_TYPE_OBJECT:
|
||||||
|
return "object";
|
||||||
|
case content::RESOURCE_TYPE_XHR:
|
||||||
|
return "xhr";
|
||||||
|
default:
|
||||||
|
return "other";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunSimpleListener(const AtomNetworkDelegate::SimpleListener& listener,
|
||||||
|
scoped_ptr<base::DictionaryValue> details) {
|
||||||
|
return listener.Run(*(details.get()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunResponseListener(
|
||||||
|
const AtomNetworkDelegate::ResponseListener& listener,
|
||||||
|
scoped_ptr<base::DictionaryValue> details,
|
||||||
|
const AtomNetworkDelegate::ResponseCallback& callback) {
|
||||||
|
return listener.Run(*(details.get()), callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test whether the URL of |request| matches |patterns|.
|
||||||
|
bool MatchesFilterCondition(net::URLRequest* request,
|
||||||
|
const URLPatterns& patterns) {
|
||||||
|
if (patterns.empty())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
for (const auto& pattern : patterns) {
|
||||||
|
if (pattern.MatchesURL(request->url()))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overloaded by multiple types to fill the |details| object.
|
||||||
|
void ToDictionary(base::DictionaryValue* details, net::URLRequest* request) {
|
||||||
|
details->SetInteger("id", request->identifier());
|
||||||
|
details->SetString("url", request->url().spec());
|
||||||
|
details->SetString("method", request->method());
|
||||||
|
details->SetDouble("timestamp", base::Time::Now().ToDoubleT() * 1000);
|
||||||
|
auto info = content::ResourceRequestInfo::ForRequest(request);
|
||||||
|
details->SetString("resourceType",
|
||||||
|
info ? ResourceTypeToString(info->GetResourceType())
|
||||||
|
: "other");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ToDictionary(base::DictionaryValue* details,
|
||||||
|
const net::HttpRequestHeaders& headers) {
|
||||||
|
scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
|
||||||
|
net::HttpRequestHeaders::Iterator it(headers);
|
||||||
|
while (it.GetNext())
|
||||||
|
dict->SetString(it.name(), it.value());
|
||||||
|
details->Set("requestHeaders", dict.Pass());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ToDictionary(base::DictionaryValue* details,
|
||||||
|
const net::HttpResponseHeaders* headers) {
|
||||||
|
if (!headers)
|
||||||
|
return;
|
||||||
|
|
||||||
|
scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
|
||||||
|
void* iter = nullptr;
|
||||||
|
std::string key;
|
||||||
|
std::string value;
|
||||||
|
while (headers->EnumerateHeaderLines(&iter, &key, &value)) {
|
||||||
|
if (dict->HasKey(key)) {
|
||||||
|
base::ListValue* values = nullptr;
|
||||||
|
if (dict->GetList(key, &values))
|
||||||
|
values->AppendString(value);
|
||||||
|
} else {
|
||||||
|
scoped_ptr<base::ListValue> values(new base::ListValue);
|
||||||
|
values->AppendString(value);
|
||||||
|
dict->Set(key, values.Pass());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
details->Set("responseHeaders", dict.Pass());
|
||||||
|
details->SetString("statusLine", headers->GetStatusLine());
|
||||||
|
details->SetInteger("statusCode", headers->response_code());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ToDictionary(base::DictionaryValue* details, const GURL& location) {
|
||||||
|
details->SetString("redirectURL", location.spec());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ToDictionary(base::DictionaryValue* details,
|
||||||
|
const net::HostPortPair& host_port) {
|
||||||
|
if (host_port.host().empty())
|
||||||
|
details->SetString("ip", host_port.host());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ToDictionary(base::DictionaryValue* details, bool from_cache) {
|
||||||
|
details->SetBoolean("fromCache", from_cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ToDictionary(base::DictionaryValue* details,
|
||||||
|
const net::URLRequestStatus& status) {
|
||||||
|
details->SetString("error", net::ErrorToString(status.error()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to fill |details| with arbitrary |args|.
|
||||||
|
template<typename Arg>
|
||||||
|
void FillDetailsObject(base::DictionaryValue* details, Arg arg) {
|
||||||
|
ToDictionary(details, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Arg, typename... Args>
|
||||||
|
void FillDetailsObject(base::DictionaryValue* details, Arg arg, Args... args) {
|
||||||
|
ToDictionary(details, arg);
|
||||||
|
FillDetailsObject(details, args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill the native types with the result from the response object.
|
||||||
|
void ReadFromResponseObject(const base::DictionaryValue& response,
|
||||||
|
GURL* new_location) {
|
||||||
|
std::string url;
|
||||||
|
if (response.GetString("redirectURL", &url))
|
||||||
|
*new_location = GURL(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReadFromResponseObject(const base::DictionaryValue& response,
|
||||||
|
net::HttpRequestHeaders* headers) {
|
||||||
|
const base::DictionaryValue* dict;
|
||||||
|
if (response.GetDictionary("requestHeaders", &dict)) {
|
||||||
|
headers->Clear();
|
||||||
|
for (base::DictionaryValue::Iterator it(*dict);
|
||||||
|
!it.IsAtEnd();
|
||||||
|
it.Advance()) {
|
||||||
|
std::string value;
|
||||||
|
if (it.value().GetAsString(&value))
|
||||||
|
headers->SetHeader(it.key(), value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReadFromResponseObject(const base::DictionaryValue& response,
|
||||||
|
scoped_refptr<net::HttpResponseHeaders>* headers) {
|
||||||
|
const base::DictionaryValue* dict;
|
||||||
|
if (response.GetDictionary("responseHeaders", &dict)) {
|
||||||
|
*headers = new net::HttpResponseHeaders("");
|
||||||
|
for (base::DictionaryValue::Iterator it(*dict);
|
||||||
|
!it.IsAtEnd();
|
||||||
|
it.Advance()) {
|
||||||
|
const base::ListValue* list;
|
||||||
|
if (it.value().GetAsList(&list)) {
|
||||||
|
(*headers)->RemoveHeader(it.key());
|
||||||
|
for (size_t i = 0; i < list->GetSize(); ++i) {
|
||||||
|
std::string value;
|
||||||
|
if (list->GetString(i, &value))
|
||||||
|
(*headers)->AddHeader(it.key() + " : " + value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
AtomNetworkDelegate::AtomNetworkDelegate() {
|
||||||
|
}
|
||||||
|
|
||||||
|
AtomNetworkDelegate::~AtomNetworkDelegate() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtomNetworkDelegate::SetSimpleListenerInIO(
|
||||||
|
SimpleEvent type,
|
||||||
|
const URLPatterns& patterns,
|
||||||
|
const SimpleListener& callback) {
|
||||||
|
if (callback.is_null())
|
||||||
|
simple_listeners_.erase(type);
|
||||||
|
else
|
||||||
|
simple_listeners_[type] = { patterns, callback };
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtomNetworkDelegate::SetResponseListenerInIO(
|
||||||
|
ResponseEvent type,
|
||||||
|
const URLPatterns& patterns,
|
||||||
|
const ResponseListener& callback) {
|
||||||
|
if (callback.is_null())
|
||||||
|
response_listeners_.erase(type);
|
||||||
|
else
|
||||||
|
response_listeners_[type] = { patterns, callback };
|
||||||
|
}
|
||||||
|
|
||||||
|
int AtomNetworkDelegate::OnBeforeURLRequest(
|
||||||
|
net::URLRequest* request,
|
||||||
|
const net::CompletionCallback& callback,
|
||||||
|
GURL* new_url) {
|
||||||
|
if (!ContainsKey(response_listeners_, kOnBeforeRequest))
|
||||||
|
return brightray::NetworkDelegate::OnBeforeURLRequest(
|
||||||
|
request, callback, new_url);
|
||||||
|
|
||||||
|
return HandleResponseEvent(kOnBeforeRequest, request, callback, new_url);
|
||||||
|
}
|
||||||
|
|
||||||
|
int AtomNetworkDelegate::OnBeforeSendHeaders(
|
||||||
|
net::URLRequest* request,
|
||||||
|
const net::CompletionCallback& callback,
|
||||||
|
net::HttpRequestHeaders* headers) {
|
||||||
|
if (!ContainsKey(response_listeners_, kOnBeforeSendHeaders))
|
||||||
|
return brightray::NetworkDelegate::OnBeforeSendHeaders(
|
||||||
|
request, callback, headers);
|
||||||
|
|
||||||
|
return HandleResponseEvent(
|
||||||
|
kOnBeforeSendHeaders, request, callback, headers, *headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtomNetworkDelegate::OnSendHeaders(
|
||||||
|
net::URLRequest* request,
|
||||||
|
const net::HttpRequestHeaders& headers) {
|
||||||
|
if (!ContainsKey(simple_listeners_, kOnSendHeaders)) {
|
||||||
|
brightray::NetworkDelegate::OnSendHeaders(request, headers);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
HandleSimpleEvent(kOnSendHeaders, request, headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
int AtomNetworkDelegate::OnHeadersReceived(
|
||||||
|
net::URLRequest* request,
|
||||||
|
const net::CompletionCallback& callback,
|
||||||
|
const net::HttpResponseHeaders* original,
|
||||||
|
scoped_refptr<net::HttpResponseHeaders>* override,
|
||||||
|
GURL* allowed) {
|
||||||
|
if (!ContainsKey(response_listeners_, kOnHeadersReceived))
|
||||||
|
return brightray::NetworkDelegate::OnHeadersReceived(
|
||||||
|
request, callback, original, override, allowed);
|
||||||
|
|
||||||
|
return HandleResponseEvent(
|
||||||
|
kOnHeadersReceived, request, callback, override, original);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtomNetworkDelegate::OnBeforeRedirect(net::URLRequest* request,
|
||||||
|
const GURL& new_location) {
|
||||||
|
if (!ContainsKey(simple_listeners_, kOnBeforeRedirect)) {
|
||||||
|
brightray::NetworkDelegate::OnBeforeRedirect(request, new_location);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
HandleSimpleEvent(kOnBeforeRedirect, request, new_location,
|
||||||
|
request->response_headers(), request->GetSocketAddress(),
|
||||||
|
request->was_cached());
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtomNetworkDelegate::OnResponseStarted(net::URLRequest* request) {
|
||||||
|
if (!ContainsKey(simple_listeners_, kOnResponseStarted)) {
|
||||||
|
brightray::NetworkDelegate::OnResponseStarted(request);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request->status().status() != net::URLRequestStatus::SUCCESS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
HandleSimpleEvent(kOnResponseStarted, request, request->response_headers(),
|
||||||
|
request->was_cached());
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtomNetworkDelegate::OnCompleted(net::URLRequest* request, bool started) {
|
||||||
|
// OnCompleted may happen before other events.
|
||||||
|
callbacks_.erase(request->identifier());
|
||||||
|
|
||||||
|
if (request->status().status() == net::URLRequestStatus::FAILED ||
|
||||||
|
request->status().status() == net::URLRequestStatus::CANCELED) {
|
||||||
|
// Error event.
|
||||||
|
OnErrorOccurred(request, started);
|
||||||
|
return;
|
||||||
|
} else if (request->response_headers() &&
|
||||||
|
net::HttpResponseHeaders::IsRedirectResponseCode(
|
||||||
|
request->response_headers()->response_code())) {
|
||||||
|
// Redirect event.
|
||||||
|
brightray::NetworkDelegate::OnCompleted(request, started);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ContainsKey(simple_listeners_, kOnCompleted)) {
|
||||||
|
brightray::NetworkDelegate::OnCompleted(request, started);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
HandleSimpleEvent(kOnCompleted, request, request->response_headers(),
|
||||||
|
request->was_cached());
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtomNetworkDelegate::OnURLRequestDestroyed(net::URLRequest* request) {
|
||||||
|
callbacks_.erase(request->identifier());
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtomNetworkDelegate::OnErrorOccurred(
|
||||||
|
net::URLRequest* request, bool started) {
|
||||||
|
if (!ContainsKey(simple_listeners_, kOnErrorOccurred)) {
|
||||||
|
brightray::NetworkDelegate::OnCompleted(request, started);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
HandleSimpleEvent(kOnErrorOccurred, request, request->was_cached(),
|
||||||
|
request->status());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Out, typename... Args>
|
||||||
|
int AtomNetworkDelegate::HandleResponseEvent(
|
||||||
|
ResponseEvent type,
|
||||||
|
net::URLRequest* request,
|
||||||
|
const net::CompletionCallback& callback,
|
||||||
|
Out out,
|
||||||
|
Args... args) {
|
||||||
|
const auto& info = response_listeners_[type];
|
||||||
|
if (!MatchesFilterCondition(request, info.url_patterns))
|
||||||
|
return net::OK;
|
||||||
|
|
||||||
|
scoped_ptr<base::DictionaryValue> details(new base::DictionaryValue);
|
||||||
|
FillDetailsObject(details.get(), request, args...);
|
||||||
|
|
||||||
|
// The |request| could be destroyed before the |callback| is called.
|
||||||
|
callbacks_[request->identifier()] = callback;
|
||||||
|
|
||||||
|
ResponseCallback response =
|
||||||
|
base::Bind(&AtomNetworkDelegate::OnListenerResultInUI<Out>,
|
||||||
|
base::Unretained(this), request->identifier(), out);
|
||||||
|
BrowserThread::PostTask(
|
||||||
|
BrowserThread::UI, FROM_HERE,
|
||||||
|
base::Bind(RunResponseListener, info.listener, base::Passed(&details),
|
||||||
|
response));
|
||||||
|
return net::ERR_IO_PENDING;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename...Args>
|
||||||
|
void AtomNetworkDelegate::HandleSimpleEvent(
|
||||||
|
SimpleEvent type, net::URLRequest* request, Args... args) {
|
||||||
|
const auto& info = simple_listeners_[type];
|
||||||
|
if (!MatchesFilterCondition(request, info.url_patterns))
|
||||||
|
return;
|
||||||
|
|
||||||
|
scoped_ptr<base::DictionaryValue> details(new base::DictionaryValue);
|
||||||
|
FillDetailsObject(details.get(), request, args...);
|
||||||
|
|
||||||
|
BrowserThread::PostTask(
|
||||||
|
BrowserThread::UI, FROM_HERE,
|
||||||
|
base::Bind(RunSimpleListener, info.listener, base::Passed(&details)));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void AtomNetworkDelegate::OnListenerResultInIO(
|
||||||
|
uint64_t id, T out, scoped_ptr<base::DictionaryValue> response) {
|
||||||
|
// The request has been destroyed.
|
||||||
|
if (!ContainsKey(callbacks_, id))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ReadFromResponseObject(*response.get(), out);
|
||||||
|
|
||||||
|
bool cancel = false;
|
||||||
|
response->GetBoolean("cancel", &cancel);
|
||||||
|
callbacks_[id].Run(cancel ? net::ERR_BLOCKED_BY_CLIENT : net::OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void AtomNetworkDelegate::OnListenerResultInUI(
|
||||||
|
uint64_t id, T out, const base::DictionaryValue& response) {
|
||||||
|
scoped_ptr<base::DictionaryValue> copy = response.CreateDeepCopy();
|
||||||
|
BrowserThread::PostTask(
|
||||||
|
BrowserThread::IO, FROM_HERE,
|
||||||
|
base::Bind(&AtomNetworkDelegate::OnListenerResultInIO<T>,
|
||||||
|
base::Unretained(this), id, out, base::Passed(©)));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace atom
|
121
atom/browser/net/atom_network_delegate.h
Normal file
121
atom/browser/net/atom_network_delegate.h
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
// 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_NET_ATOM_NETWORK_DELEGATE_H_
|
||||||
|
#define ATOM_BROWSER_NET_ATOM_NETWORK_DELEGATE_H_
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
#include "brightray/browser/network_delegate.h"
|
||||||
|
#include "base/callback.h"
|
||||||
|
#include "base/values.h"
|
||||||
|
#include "extensions/common/url_pattern.h"
|
||||||
|
#include "net/base/net_errors.h"
|
||||||
|
#include "net/http/http_request_headers.h"
|
||||||
|
#include "net/http/http_response_headers.h"
|
||||||
|
|
||||||
|
namespace extensions {
|
||||||
|
class URLPattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace atom {
|
||||||
|
|
||||||
|
using URLPatterns = std::set<extensions::URLPattern>;
|
||||||
|
|
||||||
|
class AtomNetworkDelegate : public brightray::NetworkDelegate {
|
||||||
|
public:
|
||||||
|
using ResponseCallback = base::Callback<void(const base::DictionaryValue&)>;
|
||||||
|
using SimpleListener = base::Callback<void(const base::DictionaryValue&)>;
|
||||||
|
using ResponseListener = base::Callback<void(const base::DictionaryValue&,
|
||||||
|
const ResponseCallback&)>;
|
||||||
|
|
||||||
|
enum SimpleEvent {
|
||||||
|
kOnSendHeaders,
|
||||||
|
kOnBeforeRedirect,
|
||||||
|
kOnResponseStarted,
|
||||||
|
kOnCompleted,
|
||||||
|
kOnErrorOccurred,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ResponseEvent {
|
||||||
|
kOnBeforeRequest,
|
||||||
|
kOnBeforeSendHeaders,
|
||||||
|
kOnHeadersReceived,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SimpleListenerInfo {
|
||||||
|
URLPatterns url_patterns;
|
||||||
|
SimpleListener listener;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ResponseListenerInfo {
|
||||||
|
URLPatterns url_patterns;
|
||||||
|
ResponseListener listener;
|
||||||
|
};
|
||||||
|
|
||||||
|
AtomNetworkDelegate();
|
||||||
|
~AtomNetworkDelegate() override;
|
||||||
|
|
||||||
|
void SetSimpleListenerInIO(SimpleEvent type,
|
||||||
|
const URLPatterns& patterns,
|
||||||
|
const SimpleListener& callback);
|
||||||
|
void SetResponseListenerInIO(ResponseEvent type,
|
||||||
|
const URLPatterns& patterns,
|
||||||
|
const ResponseListener& callback);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// net::NetworkDelegate:
|
||||||
|
int OnBeforeURLRequest(net::URLRequest* request,
|
||||||
|
const net::CompletionCallback& callback,
|
||||||
|
GURL* new_url) override;
|
||||||
|
int OnBeforeSendHeaders(net::URLRequest* request,
|
||||||
|
const net::CompletionCallback& callback,
|
||||||
|
net::HttpRequestHeaders* headers) override;
|
||||||
|
void OnSendHeaders(net::URLRequest* request,
|
||||||
|
const net::HttpRequestHeaders& headers) override;
|
||||||
|
int OnHeadersReceived(
|
||||||
|
net::URLRequest* request,
|
||||||
|
const net::CompletionCallback& callback,
|
||||||
|
const net::HttpResponseHeaders* original_response_headers,
|
||||||
|
scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
|
||||||
|
GURL* allowed_unsafe_redirect_url) override;
|
||||||
|
void OnBeforeRedirect(net::URLRequest* request,
|
||||||
|
const GURL& new_location) override;
|
||||||
|
void OnResponseStarted(net::URLRequest* request) override;
|
||||||
|
void OnCompleted(net::URLRequest* request, bool started) override;
|
||||||
|
void OnURLRequestDestroyed(net::URLRequest* request) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void OnErrorOccurred(net::URLRequest* request, bool started);
|
||||||
|
|
||||||
|
template<typename...Args>
|
||||||
|
void HandleSimpleEvent(SimpleEvent type,
|
||||||
|
net::URLRequest* request,
|
||||||
|
Args... args);
|
||||||
|
template<typename Out, typename... Args>
|
||||||
|
int HandleResponseEvent(ResponseEvent type,
|
||||||
|
net::URLRequest* request,
|
||||||
|
const net::CompletionCallback& callback,
|
||||||
|
Out out,
|
||||||
|
Args... args);
|
||||||
|
|
||||||
|
// Deal with the results of Listener.
|
||||||
|
template<typename T>
|
||||||
|
void OnListenerResultInIO(
|
||||||
|
uint64_t id, T out, scoped_ptr<base::DictionaryValue> response);
|
||||||
|
template<typename T>
|
||||||
|
void OnListenerResultInUI(
|
||||||
|
uint64_t id, T out, const base::DictionaryValue& response);
|
||||||
|
|
||||||
|
std::map<SimpleEvent, SimpleListenerInfo> simple_listeners_;
|
||||||
|
std::map<ResponseEvent, ResponseListenerInfo> response_listeners_;
|
||||||
|
std::map<uint64_t, net::CompletionCallback> callbacks_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(AtomNetworkDelegate);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace atom
|
||||||
|
|
||||||
|
#endif // ATOM_BROWSER_NET_ATOM_NETWORK_DELEGATE_H_
|
|
@ -4,6 +4,10 @@
|
||||||
|
|
||||||
#include "atom/browser/net/url_request_async_asar_job.h"
|
#include "atom/browser/net/url_request_async_asar_job.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "atom/common/atom_constants.h"
|
||||||
|
|
||||||
namespace atom {
|
namespace atom {
|
||||||
|
|
||||||
URLRequestAsyncAsarJob::URLRequestAsyncAsarJob(
|
URLRequestAsyncAsarJob::URLRequestAsyncAsarJob(
|
||||||
|
@ -34,4 +38,12 @@ void URLRequestAsyncAsarJob::StartAsync(scoped_ptr<base::Value> options) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void URLRequestAsyncAsarJob::GetResponseInfo(net::HttpResponseInfo* info) {
|
||||||
|
std::string status("HTTP/1.1 200 OK");
|
||||||
|
net::HttpResponseHeaders* headers = new net::HttpResponseHeaders(status);
|
||||||
|
|
||||||
|
headers->AddHeader(kCORSHeader);
|
||||||
|
info->headers = headers;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace atom
|
} // namespace atom
|
||||||
|
|
|
@ -18,6 +18,9 @@ class URLRequestAsyncAsarJob : public JsAsker<asar::URLRequestAsarJob> {
|
||||||
// JsAsker:
|
// JsAsker:
|
||||||
void StartAsync(scoped_ptr<base::Value> options) override;
|
void StartAsync(scoped_ptr<base::Value> options) override;
|
||||||
|
|
||||||
|
// URLRequestJob:
|
||||||
|
void GetResponseInfo(net::HttpResponseInfo* info) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DISALLOW_COPY_AND_ASSIGN(URLRequestAsyncAsarJob);
|
DISALLOW_COPY_AND_ASSIGN(URLRequestAsyncAsarJob);
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "atom/common/atom_constants.h"
|
||||||
#include "base/strings/string_number_conversions.h"
|
#include "base/strings/string_number_conversions.h"
|
||||||
#include "net/base/net_errors.h"
|
#include "net/base/net_errors.h"
|
||||||
|
|
||||||
|
@ -50,6 +51,8 @@ void URLRequestBufferJob::GetResponseInfo(net::HttpResponseInfo* info) {
|
||||||
status.append("\0\0", 2);
|
status.append("\0\0", 2);
|
||||||
net::HttpResponseHeaders* headers = new net::HttpResponseHeaders(status);
|
net::HttpResponseHeaders* headers = new net::HttpResponseHeaders(status);
|
||||||
|
|
||||||
|
headers->AddHeader(kCORSHeader);
|
||||||
|
|
||||||
if (!mime_type_.empty()) {
|
if (!mime_type_.empty()) {
|
||||||
std::string content_type_header(net::HttpRequestHeaders::kContentType);
|
std::string content_type_header(net::HttpRequestHeaders::kContentType);
|
||||||
content_type_header.append(": ");
|
content_type_header.append(": ");
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "net/http/http_response_headers.h"
|
#include "net/http/http_response_headers.h"
|
||||||
#include "net/url_request/url_fetcher.h"
|
#include "net/url_request/url_fetcher.h"
|
||||||
#include "net/url_request/url_fetcher_response_writer.h"
|
#include "net/url_request/url_fetcher_response_writer.h"
|
||||||
|
#include "net/url_request/url_request_context.h"
|
||||||
#include "net/url_request/url_request_context_builder.h"
|
#include "net/url_request/url_request_context_builder.h"
|
||||||
#include "net/url_request/url_request_status.h"
|
#include "net/url_request/url_request_status.h"
|
||||||
|
|
||||||
|
@ -23,7 +24,7 @@ namespace {
|
||||||
|
|
||||||
// Convert string to RequestType.
|
// Convert string to RequestType.
|
||||||
net::URLFetcher::RequestType GetRequestType(const std::string& raw) {
|
net::URLFetcher::RequestType GetRequestType(const std::string& raw) {
|
||||||
std::string method = base::StringToUpperASCII(raw);
|
std::string method = base::ToUpperASCII(raw);
|
||||||
if (method.empty() || method == "GET")
|
if (method.empty() || method == "GET")
|
||||||
return net::URLFetcher::GET;
|
return net::URLFetcher::GET;
|
||||||
else if (method == "POST")
|
else if (method == "POST")
|
||||||
|
@ -89,12 +90,14 @@ void URLRequestFetchJob::StartAsync(scoped_ptr<base::Value> options) {
|
||||||
|
|
||||||
std::string url, method, referrer;
|
std::string url, method, referrer;
|
||||||
base::Value* session = nullptr;
|
base::Value* session = nullptr;
|
||||||
|
base::DictionaryValue* upload_data = nullptr;
|
||||||
base::DictionaryValue* dict =
|
base::DictionaryValue* dict =
|
||||||
static_cast<base::DictionaryValue*>(options.get());
|
static_cast<base::DictionaryValue*>(options.get());
|
||||||
dict->GetString("url", &url);
|
dict->GetString("url", &url);
|
||||||
dict->GetString("method", &method);
|
dict->GetString("method", &method);
|
||||||
dict->GetString("referrer", &referrer);
|
dict->GetString("referrer", &referrer);
|
||||||
dict->Get("session", &session);
|
dict->Get("session", &session);
|
||||||
|
dict->GetDictionary("uploadData", &upload_data);
|
||||||
|
|
||||||
// Check if URL is valid.
|
// Check if URL is valid.
|
||||||
GURL formated_url(url);
|
GURL formated_url(url);
|
||||||
|
@ -126,6 +129,14 @@ void URLRequestFetchJob::StartAsync(scoped_ptr<base::Value> options) {
|
||||||
else
|
else
|
||||||
fetcher_->SetReferrer(referrer);
|
fetcher_->SetReferrer(referrer);
|
||||||
|
|
||||||
|
// Set the data needed for POSTs.
|
||||||
|
if (upload_data && request_type == net::URLFetcher::POST) {
|
||||||
|
std::string content_type, data;
|
||||||
|
upload_data->GetString("contentType", &content_type);
|
||||||
|
upload_data->GetString("data", &data);
|
||||||
|
fetcher_->SetUploadData(content_type, data);
|
||||||
|
}
|
||||||
|
|
||||||
// Use |request|'s headers.
|
// Use |request|'s headers.
|
||||||
fetcher_->SetExtraRequestHeaders(
|
fetcher_->SetExtraRequestHeaders(
|
||||||
request()->extra_request_headers().ToString());
|
request()->extra_request_headers().ToString());
|
||||||
|
@ -138,8 +149,9 @@ net::URLRequestContextGetter* URLRequestFetchJob::CreateRequestContext() {
|
||||||
auto task_runner = base::ThreadTaskRunnerHandle::Get();
|
auto task_runner = base::ThreadTaskRunnerHandle::Get();
|
||||||
net::URLRequestContextBuilder builder;
|
net::URLRequestContextBuilder builder;
|
||||||
builder.set_proxy_service(net::ProxyService::CreateDirect());
|
builder.set_proxy_service(net::ProxyService::CreateDirect());
|
||||||
url_request_context_getter_ =
|
request_context_ = builder.Build();
|
||||||
new net::TrivialURLRequestContextGetter(builder.Build(), task_runner);
|
url_request_context_getter_ = new net::TrivialURLRequestContextGetter(
|
||||||
|
request_context_.get(), task_runner);
|
||||||
}
|
}
|
||||||
return url_request_context_getter_.get();
|
return url_request_context_getter_.get();
|
||||||
}
|
}
|
||||||
|
@ -181,6 +193,11 @@ void URLRequestFetchJob::Kill() {
|
||||||
bool URLRequestFetchJob::ReadRawData(net::IOBuffer* dest,
|
bool URLRequestFetchJob::ReadRawData(net::IOBuffer* dest,
|
||||||
int dest_size,
|
int dest_size,
|
||||||
int* bytes_read) {
|
int* bytes_read) {
|
||||||
|
if (GetResponseCode() == 204) {
|
||||||
|
*bytes_read = 0;
|
||||||
|
request()->set_received_response_content_length(prefilter_bytes_read());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
pending_buffer_ = dest;
|
pending_buffer_ = dest;
|
||||||
pending_buffer_size_ = dest_size;
|
pending_buffer_size_ = dest_size;
|
||||||
SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
|
SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
|
||||||
|
@ -188,7 +205,7 @@ bool URLRequestFetchJob::ReadRawData(net::IOBuffer* dest,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool URLRequestFetchJob::GetMimeType(std::string* mime_type) const {
|
bool URLRequestFetchJob::GetMimeType(std::string* mime_type) const {
|
||||||
if (!response_info_)
|
if (!response_info_ || !response_info_->headers)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return response_info_->headers->GetMimeType(mime_type);
|
return response_info_->headers->GetMimeType(mime_type);
|
||||||
|
@ -200,13 +217,21 @@ void URLRequestFetchJob::GetResponseInfo(net::HttpResponseInfo* info) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int URLRequestFetchJob::GetResponseCode() const {
|
int URLRequestFetchJob::GetResponseCode() const {
|
||||||
if (!response_info_)
|
if (!response_info_ || !response_info_->headers)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return response_info_->headers->response_code();
|
return response_info_->headers->response_code();
|
||||||
}
|
}
|
||||||
|
|
||||||
void URLRequestFetchJob::OnURLFetchComplete(const net::URLFetcher* source) {
|
void URLRequestFetchJob::OnURLFetchComplete(const net::URLFetcher* source) {
|
||||||
|
if (!response_info_) {
|
||||||
|
// Since we notify header completion only after first write there will be
|
||||||
|
// no response object constructed for http respones with no content 204.
|
||||||
|
// We notify header completion here.
|
||||||
|
HeadersCompleted();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
pending_buffer_ = nullptr;
|
pending_buffer_ = nullptr;
|
||||||
pending_buffer_size_ = 0;
|
pending_buffer_size_ = 0;
|
||||||
NotifyDone(fetcher_->GetStatus());
|
NotifyDone(fetcher_->GetStatus());
|
||||||
|
|
|
@ -45,6 +45,7 @@ class URLRequestFetchJob : public JsAsker<net::URLRequestJob>,
|
||||||
// Create a independent request context.
|
// Create a independent request context.
|
||||||
net::URLRequestContextGetter* CreateRequestContext();
|
net::URLRequestContextGetter* CreateRequestContext();
|
||||||
|
|
||||||
|
scoped_ptr<net::URLRequestContext> request_context_;
|
||||||
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
|
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
|
||||||
scoped_ptr<net::URLFetcher> fetcher_;
|
scoped_ptr<net::URLFetcher> fetcher_;
|
||||||
scoped_refptr<net::IOBuffer> pending_buffer_;
|
scoped_refptr<net::IOBuffer> pending_buffer_;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "atom/common/atom_constants.h"
|
||||||
#include "net/base/net_errors.h"
|
#include "net/base/net_errors.h"
|
||||||
|
|
||||||
namespace atom {
|
namespace atom {
|
||||||
|
@ -32,6 +33,8 @@ void URLRequestStringJob::GetResponseInfo(net::HttpResponseInfo* info) {
|
||||||
std::string status("HTTP/1.1 200 OK");
|
std::string status("HTTP/1.1 200 OK");
|
||||||
net::HttpResponseHeaders* headers = new net::HttpResponseHeaders(status);
|
net::HttpResponseHeaders* headers = new net::HttpResponseHeaders(status);
|
||||||
|
|
||||||
|
headers->AddHeader(kCORSHeader);
|
||||||
|
|
||||||
if (!mime_type_.empty()) {
|
if (!mime_type_.empty()) {
|
||||||
std::string content_type_header(net::HttpRequestHeaders::kContentType);
|
std::string content_type_header(net::HttpRequestHeaders::kContentType);
|
||||||
content_type_header.append(": ");
|
content_type_header.append(": ");
|
||||||
|
|
|
@ -17,9 +17,9 @@
|
||||||
<key>CFBundleIconFile</key>
|
<key>CFBundleIconFile</key>
|
||||||
<string>atom.icns</string>
|
<string>atom.icns</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>0.35.1</string>
|
<string>0.36.2</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>0.35.1</string>
|
<string>0.36.2</string>
|
||||||
<key>LSApplicationCategoryType</key>
|
<key>LSApplicationCategoryType</key>
|
||||||
<string>public.app-category.developer-tools</string>
|
<string>public.app-category.developer-tools</string>
|
||||||
<key>LSMinimumSystemVersion</key>
|
<key>LSMinimumSystemVersion</key>
|
||||||
|
|
|
@ -56,8 +56,8 @@ END
|
||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 0,35,1,0
|
FILEVERSION 0,36,2,0
|
||||||
PRODUCTVERSION 0,35,1,0
|
PRODUCTVERSION 0,36,2,0
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
|
@ -74,12 +74,12 @@ BEGIN
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "GitHub, Inc."
|
VALUE "CompanyName", "GitHub, Inc."
|
||||||
VALUE "FileDescription", "Electron"
|
VALUE "FileDescription", "Electron"
|
||||||
VALUE "FileVersion", "0.35.1"
|
VALUE "FileVersion", "0.36.2"
|
||||||
VALUE "InternalName", "electron.exe"
|
VALUE "InternalName", "electron.exe"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
|
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
|
||||||
VALUE "OriginalFilename", "electron.exe"
|
VALUE "OriginalFilename", "electron.exe"
|
||||||
VALUE "ProductName", "Electron"
|
VALUE "ProductName", "Electron"
|
||||||
VALUE "ProductVersion", "0.35.1"
|
VALUE "ProductVersion", "0.36.2"
|
||||||
VALUE "SquirrelAwareVersion", "1"
|
VALUE "SquirrelAwareVersion", "1"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
|
|
|
@ -24,10 +24,10 @@ bool StringToAccelerator(const std::string& description,
|
||||||
LOG(ERROR) << "The accelerator string can only contain ASCII characters";
|
LOG(ERROR) << "The accelerator string can only contain ASCII characters";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::string shortcut(base::StringToLowerASCII(description));
|
std::string shortcut(base::ToLowerASCII(description));
|
||||||
|
|
||||||
std::vector<std::string> tokens;
|
std::vector<std::string> tokens = base::SplitString(
|
||||||
base::SplitString(shortcut, '+', &tokens);
|
shortcut, "+", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
|
||||||
|
|
||||||
// Now, parse it into an accelerator.
|
// Now, parse it into an accelerator.
|
||||||
int modifiers = ui::EF_NONE;
|
int modifiers = ui::EF_NONE;
|
||||||
|
|
|
@ -148,10 +148,11 @@ Role kRolesMap[] = {
|
||||||
|
|
||||||
// Set submenu's role.
|
// Set submenu's role.
|
||||||
base::string16 role = model->GetRoleAt(index);
|
base::string16 role = model->GetRoleAt(index);
|
||||||
if (role == base::ASCIIToUTF16("window"))
|
if (role == base::ASCIIToUTF16("window") && [submenu numberOfItems])
|
||||||
[NSApp setWindowsMenu:submenu];
|
[NSApp setWindowsMenu:submenu];
|
||||||
else if (role == base::ASCIIToUTF16("help"))
|
else if (role == base::ASCIIToUTF16("help"))
|
||||||
[NSApp setHelpMenu:submenu];
|
[NSApp setHelpMenu:submenu];
|
||||||
|
|
||||||
if (role == base::ASCIIToUTF16("services"))
|
if (role == base::ASCIIToUTF16("services"))
|
||||||
[NSApp setServicesMenu:submenu];
|
[NSApp setServicesMenu:submenu];
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
// Copyright (c) 2013 GitHub, Inc.
|
|
||||||
// Use of this source code is governed by the MIT license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
#ifndef ATOM_BROWSER_UI_COCOA_EVENT_PROCESSING_WINDOW_H_
|
|
||||||
#define ATOM_BROWSER_UI_COCOA_EVENT_PROCESSING_WINDOW_H_
|
|
||||||
|
|
||||||
#import <Cocoa/Cocoa.h>
|
|
||||||
|
|
||||||
// Override NSWindow to access unhandled keyboard events (for command
|
|
||||||
// processing); subclassing NSWindow is the only method to do
|
|
||||||
// this.
|
|
||||||
@interface EventProcessingWindow : NSWindow {
|
|
||||||
@private
|
|
||||||
BOOL redispatchingEvent_;
|
|
||||||
BOOL eventHandled_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sends a key event to |NSApp sendEvent:|, but also makes sure that it's not
|
|
||||||
// short-circuited to the RWHV. This is used to send keyboard events to the menu
|
|
||||||
// and the cmd-` handler if a keyboard event comes back unhandled from the
|
|
||||||
// renderer. The event must be of type |NSKeyDown|, |NSKeyUp|, or
|
|
||||||
// |NSFlagsChanged|.
|
|
||||||
// Returns |YES| if |event| has been handled.
|
|
||||||
- (BOOL)redispatchKeyEvent:(NSEvent*)event;
|
|
||||||
|
|
||||||
- (BOOL)performKeyEquivalent:(NSEvent*)theEvent;
|
|
||||||
@end
|
|
||||||
|
|
||||||
#endif // ATOM_BROWSER_UI_COCOA_EVENT_PROCESSING_WINDOW_H_
|
|
|
@ -1,106 +0,0 @@
|
||||||
// Copyright (c) 2013 GitHub, Inc.
|
|
||||||
// Use of this source code is governed by the MIT license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
#import "atom/browser/ui/cocoa/event_processing_window.h"
|
|
||||||
|
|
||||||
#include "base/logging.h"
|
|
||||||
#import "content/public/browser/render_widget_host_view_mac_base.h"
|
|
||||||
|
|
||||||
@interface EventProcessingWindow ()
|
|
||||||
// Duplicate the given key event, but changing the associated window.
|
|
||||||
- (NSEvent*)keyEventForWindow:(NSWindow*)window fromKeyEvent:(NSEvent*)event;
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation EventProcessingWindow
|
|
||||||
|
|
||||||
- (BOOL)redispatchKeyEvent:(NSEvent*)event {
|
|
||||||
DCHECK(event);
|
|
||||||
NSEventType eventType = [event type];
|
|
||||||
if (eventType != NSKeyDown &&
|
|
||||||
eventType != NSKeyUp &&
|
|
||||||
eventType != NSFlagsChanged) {
|
|
||||||
NOTREACHED();
|
|
||||||
return YES; // Pretend it's been handled in an effort to limit damage.
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ordinarily, the event's window should be this window. However, when
|
|
||||||
// switching between normal and fullscreen mode, we switch out the window, and
|
|
||||||
// the event's window might be the previous window (or even an earlier one if
|
|
||||||
// the renderer is running slowly and several mode switches occur). In this
|
|
||||||
// rare case, we synthesize a new key event so that its associate window
|
|
||||||
// (number) is our own.
|
|
||||||
if ([event window] != self)
|
|
||||||
event = [self keyEventForWindow:self fromKeyEvent:event];
|
|
||||||
|
|
||||||
// Redispatch the event.
|
|
||||||
eventHandled_ = YES;
|
|
||||||
redispatchingEvent_ = YES;
|
|
||||||
[NSApp sendEvent:event];
|
|
||||||
redispatchingEvent_ = NO;
|
|
||||||
|
|
||||||
// If the event was not handled by [NSApp sendEvent:], the sendEvent:
|
|
||||||
// method below will be called, and because |redispatchingEvent_| is YES,
|
|
||||||
// |eventHandled_| will be set to NO.
|
|
||||||
return eventHandled_;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)sendEvent:(NSEvent*)event {
|
|
||||||
if (!redispatchingEvent_)
|
|
||||||
[super sendEvent:event];
|
|
||||||
else
|
|
||||||
eventHandled_ = NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSEvent*)keyEventForWindow:(NSWindow*)window fromKeyEvent:(NSEvent*)event {
|
|
||||||
NSEventType eventType = [event type];
|
|
||||||
|
|
||||||
// Convert the event's location from the original window's coordinates into
|
|
||||||
// our own.
|
|
||||||
NSPoint eventLoc = [event locationInWindow];
|
|
||||||
eventLoc = [self convertRectFromScreen:
|
|
||||||
[[event window] convertRectToScreen:NSMakeRect(eventLoc.x, eventLoc.y, 0, 0)]].origin;
|
|
||||||
|
|
||||||
// Various things *only* apply to key down/up.
|
|
||||||
BOOL eventIsARepeat = NO;
|
|
||||||
NSString* eventCharacters = nil;
|
|
||||||
NSString* eventUnmodCharacters = nil;
|
|
||||||
if (eventType == NSKeyDown || eventType == NSKeyUp) {
|
|
||||||
eventIsARepeat = [event isARepeat];
|
|
||||||
eventCharacters = [event characters];
|
|
||||||
eventUnmodCharacters = [event charactersIgnoringModifiers];
|
|
||||||
}
|
|
||||||
|
|
||||||
// This synthesis may be slightly imperfect: we provide nil for the context,
|
|
||||||
// since I (viettrungluu) am sceptical that putting in the original context
|
|
||||||
// (if one is given) is valid.
|
|
||||||
return [NSEvent keyEventWithType:eventType
|
|
||||||
location:eventLoc
|
|
||||||
modifierFlags:[event modifierFlags]
|
|
||||||
timestamp:[event timestamp]
|
|
||||||
windowNumber:[window windowNumber]
|
|
||||||
context:nil
|
|
||||||
characters:eventCharacters
|
|
||||||
charactersIgnoringModifiers:eventUnmodCharacters
|
|
||||||
isARepeat:eventIsARepeat
|
|
||||||
keyCode:[event keyCode]];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
- (BOOL)performKeyEquivalent:(NSEvent*)event {
|
|
||||||
if (redispatchingEvent_)
|
|
||||||
return NO;
|
|
||||||
|
|
||||||
// Give the web site a chance to handle the event. If it doesn't want to
|
|
||||||
// handle it, it will call us back with one of the |handle*| methods above.
|
|
||||||
NSResponder* r = [self firstResponder];
|
|
||||||
if ([r conformsToProtocol:@protocol(RenderWidgetHostViewMacBase)])
|
|
||||||
return [r performKeyEquivalent:event];
|
|
||||||
|
|
||||||
if ([super performKeyEquivalent:event])
|
|
||||||
return YES;
|
|
||||||
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end // EventProcessingWindow
|
|
|
@ -22,7 +22,9 @@ gboolean FileFilterCaseInsensitive(const GtkFileFilterInfo* file_info,
|
||||||
// Makes .* file extension matches all file types.
|
// Makes .* file extension matches all file types.
|
||||||
if (*file_extension == ".*")
|
if (*file_extension == ".*")
|
||||||
return true;
|
return true;
|
||||||
return base::EndsWith(file_info->filename, *file_extension, false);
|
return base::EndsWith(
|
||||||
|
file_info->filename,
|
||||||
|
*file_extension, base::CompareCase::INSENSITIVE_ASCII);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deletes |data| when gtk_file_filter_add_custom() is done with it.
|
// Deletes |data| when gtk_file_filter_add_custom() is done with it.
|
||||||
|
|
|
@ -34,7 +34,13 @@ void SetAllowedFileTypes(NSSavePanel* dialog, const Filters& filters) {
|
||||||
[file_type_set addObject:base::mac::CFToNSCast(ext_cf.get())];
|
[file_type_set addObject:base::mac::CFToNSCast(ext_cf.get())];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[dialog setAllowedFileTypes:[file_type_set allObjects]];
|
|
||||||
|
// Passing empty array to setAllowedFileTypes will cause exception.
|
||||||
|
NSArray* file_types = nil;
|
||||||
|
if ([file_type_set count])
|
||||||
|
file_types = [file_type_set allObjects];
|
||||||
|
|
||||||
|
[dialog setAllowedFileTypes:file_types];
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupDialog(NSSavePanel* dialog,
|
void SetupDialog(NSSavePanel* dialog,
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue