Merge branch 'master' into add-env-to-release-docs

This commit is contained in:
Charles Kerr 2018-03-07 16:38:14 +09:00
commit 35a512310a
453 changed files with 13682 additions and 6855 deletions

View file

@ -3,7 +3,7 @@ version: 2
jobs: jobs:
electron-linux-arm: electron-linux-arm:
docker: docker:
- image: electronbuilds/electron:0.0.3 - image: electronbuilds/electron:0.0.4
environment: environment:
TARGET_ARCH: arm TARGET_ARCH: arm
resource_class: 2xlarge resource_class: 2xlarge
@ -58,9 +58,45 @@ jobs:
else else
echo 'Skipping upload distribution because build is not for release' echo 'Skipping upload distribution because build is not for release'
fi fi
- run:
name: Zip out directory
command: |
if [ "$ELECTRON_RELEASE" != "1" ]; then
zip -r electron.zip out/D
fi
- persist_to_workspace:
root: /home/builduser
paths:
- project/out
- store_artifacts:
path: electron.zip
electron-linux-arm-test:
machine: true
steps:
- attach_workspace:
at: /tmp/workspace
- checkout
- run:
name: Test in ARM docker container
command: |
if [ "$ELECTRON_RELEASE" != "1" ]; then
docker run --rm --privileged multiarch/qemu-user-static:register --reset
docker run -it \
--mount type=bind,source=/tmp/workspace,target=/tmp/workspace \
--rm electronbuilds/electronarm7:0.0.4 > version.txt
cat version.txt
if grep -q `script/get-version.py` version.txt; then
echo "Versions match"
else
echo "Versions do not match"
exit 1
fi
else
echo "Skipping test for release build"
fi
electron-linux-arm64: electron-linux-arm64:
docker: docker:
- image: electronbuilds/electron:0.0.3 - image: electronbuilds/electron:0.0.4
environment: environment:
TARGET_ARCH: arm64 TARGET_ARCH: arm64
resource_class: 2xlarge resource_class: 2xlarge
@ -115,14 +151,54 @@ jobs:
else else
echo 'Skipping upload distribution because build is not for release' echo 'Skipping upload distribution because build is not for release'
fi fi
- run:
name: Zip out directory
command: |
if [ "$ELECTRON_RELEASE" != "1" ]; then
zip -r electron.zip out/D
fi
- persist_to_workspace:
root: /home/builduser
paths:
- project/out
- store_artifacts:
path: electron.zip
electron-linux-arm64-test:
machine: true
steps:
- attach_workspace:
at: /tmp/workspace
- checkout
- run:
name: Test in ARM64 docker container
command: |
if [ "$ELECTRON_RELEASE" != "1" ]; then
docker run --rm --privileged multiarch/qemu-user-static:register --reset
docker run -it \
--mount type=bind,source=/tmp/workspace,target=/tmp/workspace \
--rm electronbuilds/electronarm64:0.0.5 > version.txt
cat version.txt
if grep -q `script/get-version.py` version.txt; then
echo "Versions match"
else
echo "Versions do not match"
exit 1
fi
else
echo "Skipping test for release build"
fi
electron-linux-ia32: electron-linux-ia32:
docker: docker:
- image: electronbuilds/electron:0.0.3 - image: electronbuilds/electron:0.0.4
environment: environment:
TARGET_ARCH: ia32 TARGET_ARCH: ia32
DISPLAY: ':99.0'
resource_class: xlarge resource_class: xlarge
steps: steps:
- checkout - checkout
- run:
name: Setup for headless testing
command: sh -e /etc/init.d/xvfb start
- run: - run:
name: Check for release name: Check for release
command: | command: |
@ -172,9 +248,32 @@ jobs:
else else
echo 'Skipping upload distribution because build is not for release' echo 'Skipping upload distribution because build is not for release'
fi fi
- run:
name: Test
environment:
MOCHA_FILE: junit/test-results.xml
MOCHA_REPORTER: mocha-junit-reporter
command: |
if [ "$ELECTRON_RELEASE" != "1" ]; then
echo 'Testing Electron debug build'
out/D/electron --version
mkdir junit
script/test.py --ci --rebuild_native_modules
else
echo 'Skipping testing on release build'
fi
- run:
name: Verify FFmpeg
command: |
if [ "$ELECTRON_RELEASE" != "1" ]; then
echo 'Verifying ffmpeg on debug build'
script/verify-ffmpeg.py
else
echo 'Skipping verify ffmpeg on release build'
fi
electron-linux-mips64el: electron-linux-mips64el:
docker: docker:
- image: electronbuilds/electron:0.0.3 - image: electronbuilds/electron:0.0.4
environment: environment:
TARGET_ARCH: mips64el TARGET_ARCH: mips64el
resource_class: xlarge resource_class: xlarge
@ -232,7 +331,7 @@ jobs:
electron-linux-x64: electron-linux-x64:
docker: docker:
- image: electronbuilds/electron:0.0.3 - image: electronbuilds/electron:0.0.4
environment: environment:
TARGET_ARCH: x64 TARGET_ARCH: x64
DISPLAY: ':99.0' DISPLAY: ':99.0'
@ -330,12 +429,18 @@ workflows:
build-arm: build-arm:
jobs: jobs:
- electron-linux-arm - electron-linux-arm
- electron-linux-arm-test:
requires:
- electron-linux-arm
build-arm64: build-arm64:
jobs: jobs:
- electron-linux-arm64 - electron-linux-arm64
- electron-linux-arm64-test:
requires:
- electron-linux-arm64
build-ia32: build-ia32:
jobs: jobs:
- electron-linux-ia32 - electron-linux-ia32
build-x64: build-x64:
jobs: jobs:
- electron-linux-x64 - electron-linux-x64

View file

@ -1,2 +1,3 @@
* *
!tools/xvfb-init.sh !tools/xvfb-init.sh
!tools/run-electron.sh

8
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View file

@ -0,0 +1,8 @@
<!--
Thank you for your Pull Request. Please provide a description above and review
the requirements below.
Bug fixes and new features should include tests and possibly benchmarks.
Contributors guide: https://github.com/electron/electron/blob/master/CONTRIBUTING.md
-->

4
.github/config.yml vendored
View file

@ -12,6 +12,8 @@ newIssueWelcomeComment: |
newPRWelcomeComment: | newPRWelcomeComment: |
💖 Thanks for opening this pull request! 💖 💖 Thanks for opening this pull request! 💖
![typing cat](https://user-images.githubusercontent.com/2289/36400158-2c7c589e-1584-11e8-81c7-bd34fd3c392b.gif)
Here is a list of things that will help get it across the finish line: Here is a list of things that will help get it across the finish line:
- Follow the JavaScript, C++, and Python [coding style](https://github.com/electron/electron/blob/master/docs/development/coding-style.md). - Follow the JavaScript, C++, and Python [coding style](https://github.com/electron/electron/blob/master/docs/development/coding-style.md).
- Run `npm run lint` locally to catch formatting errors earlier. - Run `npm run lint` locally to catch formatting errors earlier.
@ -26,4 +28,4 @@ newPRWelcomeComment: |
firstPRMergeComment: > firstPRMergeComment: >
Congrats on merging your first pull request! 🎉🎉🎉 Congrats on merging your first pull request! 🎉🎉🎉
# It is recommend to include as many gifs and emojis as possiblec # It is recommend to include as many gifs and emojis as possible

15
.gitignore vendored
View file

@ -1,7 +1,7 @@
.DS_Store .DS_Store
.env .env
.gclient_done .gclient_done
.npmrc **/.npmrc
.tags* .tags*
.vs/ .vs/
.vscode/ .vscode/
@ -28,21 +28,18 @@
/external_binaries/ /external_binaries/
/out/ /out/
/vendor/.gclient /vendor/.gclient
/vendor/debian_jessie_amd64-sysroot/
/vendor/debian_jessie_arm-sysroot/
/vendor/debian_jessie_arm64-sysroot/
/vendor/debian_jessie_i386-sysroot/
/vendor/debian_jessie_mips64-sysroot/ /vendor/debian_jessie_mips64-sysroot/
/vendor/debian_wheezy_amd64-sysroot/ /vendor/debian_stretch_amd64-sysroot/
/vendor/debian_wheezy_arm-sysroot/ /vendor/debian_stretch_arm-sysroot/
/vendor/debian_wheezy_i386-sysroot/ /vendor/debian_stretch_arm64-sysroot/
/vendor/debian_stretch_i386-sysroot/
/vendor/gcc-4.8.3-d197-n64-loongson/ /vendor/gcc-4.8.3-d197-n64-loongson/
/vendor/readme-gcc483-loongson.txt /vendor/readme-gcc483-loongson.txt
/vendor/download/ /vendor/download/
/vendor/llvm-build/ /vendor/llvm-build/
/vendor/llvm/ /vendor/llvm/
/vendor/node/deps/node-inspect/.npmrc
/vendor/npm/ /vendor/npm/
/vendor/python_26/ /vendor/python_26/
node_modules/ node_modules/
SHASUMS256.txt SHASUMS256.txt
**/package-lock.json

View file

@ -10,21 +10,15 @@ 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
propose changes to this document in a pull request. propose changes to this document in a pull request.
## Submitting Issues ## [Issues](https://electronjs.org/docs/development/issues)
### Creating Issues Issues are created [here](https://github.com/electron/electron/issues/new).
* You can create an issue [here](https://github.com/electron/electron/issues/new),
but before doing that please read the notes below and include as many details as * [How to Contribute in Issues](https://electronjs.org/docs/development/issues#how-to-contribute-in-issues)
possible with your report. If you can, please include: * [Asking for General Help](https://electronjs.org/docs/development/issues#asking-for-general-help)
* The version of Electron you are using * [Submitting a Bug Report](https://electronjs.org/docs/development/issues#submitting-a-bug-report)
* The operating system you are using * [Triaging a Bug Report](https://electronjs.org/docs/development/issues#triaging-a-bug-report)
* If applicable, what you were doing when the issue arose and what you * [Resolving a Bug Report](https://electronjs.org/docs/development/issues#resolving-a-bug-report)
expected to happen
* Other things that will help resolve your issue:
* Screenshots and animated GIFs
* Error output that appears in your terminal, dev tools or as an alert
* Perform a [cursory search](https://github.com/electron/electron/issues?utf8=✓&q=is%3Aissue+)
to see if a similar issue has already been submitted
### Issue Maintenance and Closure ### Issue Maintenance and Closure
* If an issue is inactive for 45 days (no activity of any kind), it will be * If an issue is inactive for 45 days (no activity of any kind), it will be
@ -34,54 +28,29 @@ the issue will be closed.
* If an issue has been closed and you still feel it's relevant, feel free to * If an issue has been closed and you still feel it's relevant, feel free to
ping a maintainer or add a comment! ping a maintainer or add a comment!
## [Pull Requests](https://electronjs.org/docs/development/pull-requests)
## Submitting Pull Requests Pull Requests are the way concrete changes are made to the code, documentation,
dependencies, and tools contained in the `electron/electron` repository.
* Include screenshots and animated GIFs in your pull request whenever possible. * [Setting up your local environment](https://electronjs.org/docs/development/pull-requests#setting-up-your-local-environment)
* Follow the JavaScript, C++, and Python [coding style defined in docs](/docs/development/coding-style.md). * [Step 1: Fork](https://electronjs.org/docs/development/pull-requests#step-1-fork)
* Write documentation in [Markdown](https://daringfireball.net/projects/markdown). * [Step 2: Build](https://electronjs.org/docs/development/pull-requests#step-2-build)
See the [Documentation Styleguide](/docs/styleguide.md). * [Step 3: Branch](https://electronjs.org/docs/development/pull-requests#step-3-branch)
* Use short, present tense commit messages. See [Commit Message Styleguide](#git-commit-messages). * [The Process of Making Changes](https://electronjs.org/docs/development/pull-requests#the-process-of-making-changes)
* [Step 4: Code](https://electronjs.org/docs/development/pull-requests#step-4-code)
* [Step 5: Commit](https://electronjs.org/docs/development/pull-requests#step-5-commit)
* [Commit message guidelines](https://electronjs.org/docs/development/pull-requests#commit-message-guidelines)
* [Step 6: Rebase](https://electronjs.org/docs/development/pull-requests#step-6-rebase)
* [Step 7: Test](https://electronjs.org/docs/development/pull-requests#step-7-test)
* [Step 8: Push](https://electronjs.org/docs/development/pull-requests#step-8-push)
* [Step 8: Opening the Pull Request](https://electronjs.org/docs/development/pull-requests#step-8-opening-the-pull-request)
* [Step 9: Discuss and Update](#step-9-discuss-and-update)
* [Approval and Request Changes Workflow](https://electronjs.org/docs/development/pull-requests#approval-and-request-changes-workflow)
* [Step 10: Landing](https://electronjs.org/docs/development/pull-requests#step-10-landing)
* [Continuous Integration Testing](https://electronjs.org/docs/development/pull-requests#continuous-integration-testing)
## Styleguides ## Style Guides
### General Code See [Coding Style](https://electronjs.org/docs/development/coding-style) for information about which standards Electron adheres to in different parts of its codebase.
* End files with a newline.
* Place requires in the following order:
* Built in Node Modules (such as `path`)
* Built in Electron Modules (such as `ipc`, `app`)
* Local Modules (using relative paths)
* Place class properties in the following order:
* Class methods and properties (methods starting with a `@`)
* Instance methods and properties
* Avoid platform-dependent code:
* Use `path.join()` to concatenate filenames.
* Use `os.tmpdir()` rather than `/tmp` when you need to reference the
temporary directory.
* Using a plain `return` when returning explicitly at the end of a function.
* Not `return null`, `return undefined`, `null`, or `undefined`
### Git Commit Messages
* Use the present tense ("Add feature" not "Added feature")
* Use the imperative mood ("Move cursor to..." not "Moves cursor to...")
* Limit the first line to 72 characters or less
* Reference issues and pull requests liberally
* When only changing documentation, include `[ci skip]` in the commit description
* Consider starting the commit message with an applicable emoji:
* :art: `:art:` when improving the format/structure of the code
* :racehorse: `:racehorse:` when improving performance
* :non-potable_water: `:non-potable_water:` when plugging memory leaks
* :memo: `:memo:` when writing docs
* :penguin: `:penguin:` when fixing something on Linux
* :apple: `:apple:` when fixing something on macOS
* :checkered_flag: `:checkered_flag:` when fixing something on Windows
* :bug: `:bug:` when fixing a bug
* :fire: `:fire:` when removing code or files
* :green_heart: `:green_heart:` when fixing the CI build
* :white_check_mark: `:white_check_mark:` when adding tests
* :lock: `:lock:` when dealing with security
* :arrow_up: `:arrow_up:` when upgrading dependencies
* :arrow_down: `:arrow_down:` when downgrading dependencies
* :shirt: `:shirt:` when removing linter warnings

View file

@ -8,10 +8,13 @@ RUN chmod a+rwx /home
# Install node.js # Install node.js
RUN curl -sL https://deb.nodesource.com/setup_6.x | bash - RUN curl -sL https://deb.nodesource.com/setup_6.x | bash -
RUN apt-get update && apt-get install -y --force-yes nodejs RUN apt-get update && apt-get install -y nodejs
# Install wget used by crash reporter # Install wget used by crash reporter
RUN apt-get install -y --force-yes wget RUN apt-get install -y wget
# Install python-dbusmock
RUN apt-get install -y python-dbusmock
# Add xvfb init script # Add xvfb init script
ADD tools/xvfb-init.sh /etc/init.d/xvfb ADD tools/xvfb-init.sh /etc/init.d/xvfb

34
Dockerfile.arm64 Normal file
View file

@ -0,0 +1,34 @@
FROM multiarch/debian-debootstrap:arm64-jessie
RUN apt-get update && apt-get install -y\
bison \
build-essential \
clang \
curl \
gperf \
libasound2 \
libasound2-dev \
libcap-dev \
libcups2-dev \
libdbus-1-dev \
libgconf-2-4 \
libgconf2-dev \
libgnome-keyring-dev \
libgtk-3-0 \
libgtk-3-dev \
libnotify-dev \
libnss3 \
libnss3-dev \
libx11-xcb-dev \
libxss1 \
libxtst-dev \
libxtst6 \
python-dbusmock \
wget \
xvfb
ADD tools/xvfb-init.sh /etc/init.d/xvfb
RUN chmod a+x /etc/init.d/xvfb
ADD tools/run-electron.sh /run-electron.sh
RUN chmod a+x /run-electron.sh
CMD sh /run-electron.sh

40
Dockerfile.armv7 Normal file
View file

@ -0,0 +1,40 @@
FROM multiarch/debian-debootstrap:armhf-jessie
RUN apt-get update && apt-get install -y\
bison \
build-essential \
clang \
curl \
gperf \
libasound2 \
libasound2-dev \
libcap-dev \
libcups2-dev \
libdbus-1-dev \
libgconf-2-4 \
libgconf2-dev \
libgnome-keyring-dev \
libgtk-3-0 \
libgtk-3-dev \
libnotify-dev \
libnss3 \
libnss3-dev \
libx11-xcb-dev \
libxss1 \
libxtst-dev \
libxtst6 \
python-dbusmock \
git \
wget \
xvfb
# Install node.js
RUN curl -sL https://deb.nodesource.com/setup_6.x | bash -
RUN apt-get update && apt-get install -y nodejs
ADD tools/xvfb-init.sh /etc/init.d/xvfb
RUN chmod a+x /etc/init.d/xvfb
ADD tools/run-electron.sh /run-electron.sh
RUN chmod a+x /run-electron.sh
CMD sh /run-electron.sh

View file

@ -4,10 +4,13 @@ USER root
# Install node.js # Install node.js
RUN curl -sL https://deb.nodesource.com/setup_6.x | bash - RUN curl -sL https://deb.nodesource.com/setup_6.x | bash -
RUN apt-get update && apt-get install -y --force-yes nodejs RUN apt-get update && apt-get install -y nodejs
# Install wget used by crash reporter # Install wget used by crash reporter
RUN apt-get install -y --force-yes wget RUN apt-get install -y wget
# Install python-dbusmock
RUN apt-get install -y python-dbusmock
# Add xvfb init script # Add xvfb init script
ADD tools/xvfb-init.sh /etc/init.d/xvfb ADD tools/xvfb-init.sh /etc/init.d/xvfb

20
Jenkinsfile vendored
View file

@ -8,10 +8,12 @@ pipeline {
label 'osx' label 'osx'
} }
steps { steps {
sh 'script/bootstrap.py --target_arch=x64 --dev' timeout(60) {
sh 'npm run lint' sh 'script/bootstrap.py --target_arch=x64 --dev'
sh 'script/build.py -c D' sh 'npm run lint'
sh 'script/test.py --ci --rebuild_native_modules' sh 'script/build.py -c D'
sh 'script/test.py --ci --rebuild_native_modules'
}
} }
post { post {
always { always {
@ -27,10 +29,12 @@ pipeline {
MAS_BUILD = '1' MAS_BUILD = '1'
} }
steps { steps {
sh 'script/bootstrap.py --target_arch=x64 --dev' timeout(60) {
sh 'npm run lint' sh 'script/bootstrap.py --target_arch=x64 --dev'
sh 'script/build.py -c D' sh 'npm run lint'
sh 'script/test.py --ci --rebuild_native_modules' sh 'script/build.py -c D'
sh 'script/test.py --ci --rebuild_native_modules'
}
} }
post { post {
always { always {

View file

@ -1,4 +1,4 @@
Copyright (c) 2013-2017 GitHub Inc. Copyright (c) 2013-2018 GitHub Inc.
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the a copy of this software and associated documentation files (the

View file

@ -1,12 +1,14 @@
[![Electron Logo](https://electronjs.org/images/electron-logo.svg)](https://electronjs.org) [![Electron Logo](https://electronjs.org/images/electron-logo.svg)](https://electronjs.org)
[![Travis Build Status](https://travis-ci.org/electron/electron.svg?branch=master)](https://travis-ci.org/electron/electron)
[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/bc56v83355fi3369/branch/master?svg=true)](https://ci.appveyor.com/project/electron-bot/electron/branch/master) [![CircleCI Build Status](https://circleci.com/gh/electron/electron/tree/master.svg?style=shield)](https://circleci.com/gh/electron/electron/tree/master)
[![AppVeyor Build Status](https://windows-ci.electronjs.org/api/projects/status/nilyf07hcef14dvj/branch/master?svg=true)](https://windows-ci.electronjs.org/project/AppVeyor/electron/branch/master)
[![Jenkins Build Status](https://mac-ci.electronjs.org/buildStatus/icon?job=Electron%20org/electron/master)](https://mac-ci.electronjs.org/blue/organizations/jenkins/Electron%20org%2Felectron/activity?branch=master)
[![devDependency Status](https://david-dm.org/electron/electron/dev-status.svg)](https://david-dm.org/electron/electron?type=dev) [![devDependency Status](https://david-dm.org/electron/electron/dev-status.svg)](https://david-dm.org/electron/electron?type=dev)
[![Join the Electron Community on Slack](https://atom-slack.herokuapp.com/badge.svg)](https://atom-slack.herokuapp.com/) [![Join the Electron Community on Slack](https://atom-slack.herokuapp.com/badge.svg)](https://atom-slack.herokuapp.com/)
:memo: Available Translations: 🇨🇳 🇹🇼 🇧🇷 🇪🇸 🇰🇷 🇯🇵 🇷🇺 🇫🇷 🇹🇭 🇳🇱 🇹🇷 🇮🇩 🇺🇦 🇨🇿 🇮🇹. :memo: Available Translations: 🇨🇳 🇹🇼 🇧🇷 🇪🇸 🇰🇷 🇯🇵 🇷🇺 🇫🇷 🇹🇭 🇳🇱 🇹🇷 🇮🇩 🇺🇦 🇨🇿 🇮🇹.
View these docs in other languages at [electron/electron-i18n](https://github.com/electron/electron-i18n/tree/master/content/). View these docs in other languages at [electron/i18n](https://github.com/electron/i18n/tree/master/content/).
The Electron framework lets you write cross-platform desktop applications The Electron framework lets you write cross-platform desktop applications
using JavaScript, HTML and CSS. It is based on [Node.js](https://nodejs.org/) and using JavaScript, HTML and CSS. It is based on [Node.js](https://nodejs.org/) and
@ -33,10 +35,10 @@ npm install electron --save-dev --save-exact
The `--save-exact` flag is recommended as Electron does not follow semantic The `--save-exact` flag is recommended as Electron does not follow semantic
versioning. For info on how to manage Electron versions in your apps, see versioning. For info on how to manage Electron versions in your apps, see
[Electron versioning](https://electronjs.org/docs/tutorial/electron-versioning). [Electron versioning](docs/tutorial/electron-versioning.md).
For more installation options and troubleshooting tips, see For more installation options and troubleshooting tips, see
[installation](https://electronjs.org/docs/tutorial/installation). [installation](docs/tutorial/installation.md).
## Quick start ## Quick start
@ -83,7 +85,7 @@ const child = proc.spawn(electron)
## Documentation Translations ## Documentation Translations
Find documentation translations in [electron/electron-i18n](https://github.com/electron/electron-i18n). Find documentation translations in [electron/i18n](https://github.com/electron/i18n).
## Community ## Community
@ -99,6 +101,7 @@ forums
- [`electron-jp`](https://electron-jp.slack.com) *(Japanese)* - [`electron-jp`](https://electron-jp.slack.com) *(Japanese)*
- [`electron-tr`](https://electron-tr.herokuapp.com) *(Turkish)* - [`electron-tr`](https://electron-tr.herokuapp.com) *(Turkish)*
- [`electron-id`](https://electron-id.slack.com) *(Indonesia)* - [`electron-id`](https://electron-id.slack.com) *(Indonesia)*
- [`electron-pl`](https://electronpl.github.io) *(Poland)*
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.

View file

@ -7,3 +7,6 @@ To report a security issue, email [electron@github.com](mailto:electron@github.c
The Electron team will send a response indicating the next steps in handling your report. After the initial reply to your report, the security team will keep you informed of the progress towards a fix and full announcement, and may ask for additional information or guidance. The Electron team will send a response indicating the next steps in handling your report. After the initial reply to your report, the security team will keep you informed of the progress towards a fix and full announcement, and may ask for additional information or guidance.
Report security bugs in third-party modules to the person or team maintaining the module. You can also report a vulnerability through the [Node Security Project](https://nodesecurity.io/report). Report security bugs in third-party modules to the person or team maintaining the module. You can also report a vulnerability through the [Node Security Project](https://nodesecurity.io/report).
## Learning More About Security
To learn more about securing an Electron application, please see the [security tutorial](docs/tutorial/security.md).

View file

@ -1,25 +0,0 @@
# appveyor file
# http://www.appveyor.com/docs/appveyor-yml
version: "{build}"
os: Visual Studio 2015
init:
- git config --global core.autocrlf input
platform:
- x86
- x64
install:
- cmd: SET PATH=C:\Program Files (x86)\MSBuild\14.0\bin\;%PATH%
- cmd: SET PATH=C:\python27;%PATH%
- cmd: python script/cibuild
branches:
only:
- master
# disable build and test phases
build: off
test: off

View file

@ -19,13 +19,14 @@
#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 "media/media_features.h"
#include "pdf/pdf.h" #include "pdf/pdf.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 "third_party/widevine/cdm/stub/widevine_cdm_version.h"
#include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util.h"
#include "url/url_constants.h" #include "url/url_constants.h"
#if defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_PEPPER_CDMS) #if defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_LIBRARY_CDMS)
#include "chrome/common/widevine_cdm_constants.h" #include "chrome/common/widevine_cdm_constants.h"
#endif #endif
@ -73,7 +74,7 @@ content::PepperPluginInfo CreatePepperFlashInfo(const base::FilePath& path,
return plugin; return plugin;
} }
#if defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_PEPPER_CDMS) #if defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_LIBRARY_CDMS)
content::PepperPluginInfo CreateWidevineCdmInfo(const base::FilePath& path, content::PepperPluginInfo CreateWidevineCdmInfo(const base::FilePath& path,
const std::string& version) { const std::string& version) {
content::PepperPluginInfo widevine_cdm; content::PepperPluginInfo widevine_cdm;
@ -108,7 +109,7 @@ content::PepperPluginInfo CreateWidevineCdmInfo(const base::FilePath& path,
return widevine_cdm; return widevine_cdm;
} }
#endif #endif // defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_LIBRARY_CDMS)
void ComputeBuiltInPlugins(std::vector<content::PepperPluginInfo>* plugins) { void ComputeBuiltInPlugins(std::vector<content::PepperPluginInfo>* plugins) {
content::PepperPluginInfo pdf_info; content::PepperPluginInfo pdf_info;
@ -156,7 +157,7 @@ void AddPepperFlashFromCommandLine(
plugins->push_back(CreatePepperFlashInfo(flash_path, flash_version)); plugins->push_back(CreatePepperFlashInfo(flash_path, flash_version));
} }
#if defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_PEPPER_CDMS) #if defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_LIBRARY_CDMS)
void AddWidevineCdmFromCommandLine( void AddWidevineCdmFromCommandLine(
std::vector<content::PepperPluginInfo>* plugins) { std::vector<content::PepperPluginInfo>* plugins) {
auto command_line = base::CommandLine::ForCurrentProcess(); auto command_line = base::CommandLine::ForCurrentProcess();
@ -176,7 +177,7 @@ void AddWidevineCdmFromCommandLine(
plugins->push_back(CreateWidevineCdmInfo(widevine_cdm_path, plugins->push_back(CreateWidevineCdmInfo(widevine_cdm_path,
widevine_cdm_version)); widevine_cdm_version));
} }
#endif #endif // defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_LIBRARY_CDMS)
AtomContentClient::AtomContentClient() { AtomContentClient::AtomContentClient() {
} }
@ -216,9 +217,9 @@ void AtomContentClient::AddAdditionalSchemes(Schemes* schemes) {
void AtomContentClient::AddPepperPlugins( void AtomContentClient::AddPepperPlugins(
std::vector<content::PepperPluginInfo>* plugins) { std::vector<content::PepperPluginInfo>* plugins) {
AddPepperFlashFromCommandLine(plugins); AddPepperFlashFromCommandLine(plugins);
#if defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_PEPPER_CDMS) #if defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_LIBRARY_CDMS)
AddWidevineCdmFromCommandLine(plugins); AddWidevineCdmFromCommandLine(plugins);
#endif #endif // defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_LIBRARY_CDMS)
ComputeBuiltInPlugins(plugins); ComputeBuiltInPlugins(plugins);
} }

View file

@ -10,7 +10,7 @@
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
extern "C" { extern "C" {
__attribute__((visibility("default"))) __attribute__((visibility("default")))
int AtomMain(int argc, const char* argv[]); int AtomMain(int argc, char* argv[]);
__attribute__((visibility("default"))) __attribute__((visibility("default")))
int AtomInitializeICUandStartNode(int argc, char *argv[]); int AtomInitializeICUandStartNode(int argc, char *argv[]);

View file

@ -15,11 +15,11 @@
#include "content/public/app/content_main.h" #include "content/public/app/content_main.h"
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
int AtomMain(int argc, const char* argv[]) { int AtomMain(int argc, char* argv[]) {
atom::AtomMainDelegate delegate; atom::AtomMainDelegate delegate;
content::ContentMainParams params(&delegate); content::ContentMainParams params(&delegate);
params.argc = argc; params.argc = argc;
params.argv = argv; params.argv = const_cast<const char**>(argv);
atom::AtomCommandLine::Init(argc, argv); atom::AtomCommandLine::Init(argc, argv);
return content::ContentMain(params); return content::ContentMain(params);
} }

View file

@ -4,7 +4,8 @@
#include "atom/app/atom_main.h" #include "atom/app/atom_main.h"
#include <stdlib.h> #include <cstdlib>
#include <vector>
#if defined(OS_WIN) #if defined(OS_WIN)
#include <windows.h> // windows.h must be included first #include <windows.h> // windows.h must be included first
@ -15,9 +16,11 @@
#include <tchar.h> #include <tchar.h>
#include "atom/app/atom_main_delegate.h" #include "atom/app/atom_main_delegate.h"
#include "atom/app/command_line_args.h"
#include "atom/common/crash_reporter/win/crash_service_main.h" #include "atom/common/crash_reporter/win/crash_service_main.h"
#include "base/environment.h" #include "base/environment.h"
#include "base/process/launch.h" #include "base/process/launch.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/windows_version.h" #include "base/win/windows_version.h"
#include "content/public/app/sandbox_helper_win.h" #include "content/public/app/sandbox_helper_win.h"
#include "sandbox/win/src/sandbox_types.h" #include "sandbox/win/src/sandbox_types.h"
@ -35,7 +38,9 @@
namespace { namespace {
#ifdef ENABLE_RUN_AS_NODE
const auto kRunAsNode = "ELECTRON_RUN_AS_NODE"; const auto kRunAsNode = "ELECTRON_RUN_AS_NODE";
#endif
bool IsEnvSet(const char* name) { bool IsEnvSet(const char* name) {
#if defined(OS_WIN) #if defined(OS_WIN)
@ -52,18 +57,23 @@ bool IsEnvSet(const char* name) {
#if defined(OS_WIN) #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; struct Arguments {
wchar_t** wargv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); int argc = 0;
wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
bool run_as_node = IsEnvSet(kRunAsNode); ~Arguments() { LocalFree(argv); }
} arguments;
if (!arguments.argv)
return -1;
#ifdef _DEBUG #ifdef _DEBUG
// Don't display assert dialog boxes in CI test runs // Don't display assert dialog boxes in CI test runs
static const auto kCI = "ELECTRON_CI"; static const auto kCI = "ELECTRON_CI";
bool is_ci = IsEnvSet(kCI); bool is_ci = IsEnvSet(kCI);
if (!is_ci) { if (!is_ci) {
for (int i = 0; i < argc; ++i) { for (int i = 0; i < arguments.argc; ++i) {
if (!_wcsicmp(wargv[i], L"--ci")) { if (!_wcsicmp(arguments.argv[i], L"--ci")) {
is_ci = true; is_ci = true;
_putenv_s(kCI, "1"); // set flag for child processes _putenv_s(kCI, "1"); // set flag for child processes
break; break;
@ -81,44 +91,16 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
} }
#endif #endif
#ifdef ENABLE_RUN_AS_NODE
bool run_as_node = IsEnvSet(kRunAsNode);
#else
bool run_as_node = false;
#endif
// Make sure the output is printed to console. // Make sure the output is printed to console.
if (run_as_node || !IsEnvSet("ELECTRON_NO_ATTACH_CONSOLE")) if (run_as_node || !IsEnvSet("ELECTRON_NO_ATTACH_CONSOLE"))
base::RouteStdioToConsole(false); base::RouteStdioToConsole(false);
// Convert argv to to UTF8
char** argv = new char*[argc];
for (int i = 0; i < argc; i++) {
// Compute the size of the required buffer
DWORD size = WideCharToMultiByte(CP_UTF8,
0,
wargv[i],
-1,
NULL,
0,
NULL,
NULL);
if (size == 0) {
// This should never happen.
fprintf(stderr, "Could not convert arguments to utf8.");
exit(1);
}
// Do the actual conversion
argv[i] = new char[size];
DWORD result = WideCharToMultiByte(CP_UTF8,
0,
wargv[i],
-1,
argv[i],
size,
NULL,
NULL);
if (result == 0) {
// This should never happen.
fprintf(stderr, "Could not convert arguments to utf8.");
exit(1);
}
}
#ifndef DEBUG #ifndef DEBUG
// Chromium has its own TLS subsystem which supports automatic destruction // Chromium has its own TLS subsystem which supports automatic destruction
// of thread-local data, and also depends on memory allocation routines // of thread-local data, and also depends on memory allocation routines
@ -138,15 +120,28 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
}); });
#endif #endif
#ifdef ENABLE_RUN_AS_NODE
if (run_as_node) { if (run_as_node) {
// Now that argv conversion is done, we can finally start. std::vector<char*> argv(arguments.argc);
std::transform(
arguments.argv, arguments.argv + arguments.argc, argv.begin(),
[](auto& a) { return _strdup(base::WideToUTF8(a).c_str()); });
base::AtExitManager atexit_manager; base::AtExitManager atexit_manager;
base::i18n::InitializeICU(); base::i18n::InitializeICU();
return atom::NodeMain(argc, argv); auto ret = atom::NodeMain(argv.size(), argv.data());
} else if (IsEnvSet("ELECTRON_INTERNAL_CRASH_SERVICE")) { std::for_each(argv.begin(), argv.end(), free);
return ret;
}
#endif
if (IsEnvSet("ELECTRON_INTERNAL_CRASH_SERVICE")) {
return crash_service::Main(cmd); return crash_service::Main(cmd);
} }
if (!atom::CheckCommandLineArguments(arguments.argc, arguments.argv))
return -1;
sandbox::SandboxInterfaceInfo sandbox_info = {0}; sandbox::SandboxInterfaceInfo sandbox_info = {0};
content::InitializeSandboxInfo(&sandbox_info); content::InitializeSandboxInfo(&sandbox_info);
atom::AtomMainDelegate delegate; atom::AtomMainDelegate delegate;
@ -154,34 +149,37 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
content::ContentMainParams params(&delegate); content::ContentMainParams params(&delegate);
params.instance = instance; params.instance = instance;
params.sandbox_info = &sandbox_info; params.sandbox_info = &sandbox_info;
atom::AtomCommandLine::Init(argc, argv); atom::AtomCommandLine::Init(arguments.argc, arguments.argv);
atom::AtomCommandLine::InitW(argc, wargv);
return content::ContentMain(params); return content::ContentMain(params);
} }
#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, char* argv[]) {
#ifdef ENABLE_RUN_AS_NODE
if (IsEnvSet(kRunAsNode)) { if (IsEnvSet(kRunAsNode)) {
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, argv);
} }
#endif
atom::AtomMainDelegate delegate; atom::AtomMainDelegate delegate;
content::ContentMainParams params(&delegate); content::ContentMainParams params(&delegate);
params.argc = argc; params.argc = argc;
params.argv = argv; params.argv = const_cast<const char**>(argv);
atom::AtomCommandLine::Init(argc, argv); atom::AtomCommandLine::Init(argc, argv);
return content::ContentMain(params); return content::ContentMain(params);
} }
#else // defined(OS_LINUX) #else // defined(OS_LINUX)
int main(int argc, const char* argv[]) { int main(int argc, char* argv[]) {
#ifdef ENABLE_RUN_AS_NODE
if (IsEnvSet(kRunAsNode)) { if (IsEnvSet(kRunAsNode)) {
return AtomInitializeICUandStartNode(argc, const_cast<char**>(argv)); return AtomInitializeICUandStartNode(argc, argv);
} }
#endif
return AtomMain(argc, argv); return AtomMain(argc, argv);
} }

View file

@ -21,9 +21,18 @@
#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 "ipc/ipc_features.h"
#include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h" #include "ui/base/resource/resource_bundle.h"
#if BUILDFLAG(IPC_MESSAGE_LOG_ENABLED)
#define IPC_MESSAGE_MACROS_LOG_ENABLED
#include "content/public/common/content_ipc_logging.h"
#define IPC_LOG_TABLE_ADD_ENTRY(msg_id, logger) \
content::RegisterIPCLogger(msg_id, logger)
#include "atom/common/common_message_generator.h"
#endif
namespace atom { namespace atom {
namespace { namespace {
@ -86,9 +95,15 @@ bool AtomMainDelegate::BasicStartupComplete(int* exit_code) {
logging::SetLogItems(true, false, true, false); logging::SetLogItems(true, false, true, false);
// Enable convient stack printing. // Enable convient stack printing.
bool enable_stack_dumping = env->HasVar("ELECTRON_ENABLE_STACK_DUMPING");
#if defined(DEBUG) && defined(OS_LINUX) #if defined(DEBUG) && defined(OS_LINUX)
enable_stack_dumping = true; bool enable_stack_dumping = true;
#else
bool enable_stack_dumping = env->HasVar("ELECTRON_ENABLE_STACK_DUMPING");
#endif
#if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
// For 32bit ARM enabling stack printing would end up crashing.
// https://github.com/electron/electron/pull/11230#issuecomment-363232482
enable_stack_dumping = false;
#endif #endif
if (enable_stack_dumping) if (enable_stack_dumping)
base::debug::EnableInProcessStackDumping(); base::debug::EnableInProcessStackDumping();

View file

@ -44,7 +44,6 @@ class AtomMainDelegate : public brightray::MainDelegate {
void SetUpBundleOverrides(); void SetUpBundleOverrides();
#endif #endif
brightray::ContentClient content_client_;
std::unique_ptr<content::ContentBrowserClient> browser_client_; std::unique_ptr<content::ContentBrowserClient> browser_client_;
std::unique_ptr<content::ContentRendererClient> renderer_client_; std::unique_ptr<content::ContentRendererClient> renderer_client_;
std::unique_ptr<content::ContentUtilityClient> utility_client_; std::unique_ptr<content::ContentUtilityClient> utility_client_;

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,17 @@
// Copyright (c) 2018 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_APP_COMMAND_LINE_ARGS_H_
#define ATOM_APP_COMMAND_LINE_ARGS_H_
#include "base/command_line.h"
namespace atom {
bool CheckCommandLineArguments(int argc, base::CommandLine::CharType** argv);
} // namespace atom
#endif // ATOM_APP_COMMAND_LINE_ARGS_H_

View file

@ -2,6 +2,8 @@
// Use of this source code is governed by the MIT license that can be // Use of this source code is governed by the MIT license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifdef ENABLE_RUN_AS_NODE
#include "atom/app/node_main.h" #include "atom/app/node_main.h"
#include "atom/app/uv_task_runner.h" #include "atom/app/uv_task_runner.h"
@ -10,6 +12,7 @@
#include "atom/common/api/atom_bindings.h" #include "atom/common/api/atom_bindings.h"
#include "atom/common/crash_reporter/crash_reporter.h" #include "atom/common/crash_reporter/crash_reporter.h"
#include "atom/common/native_mate_converters/string16_converter.h" #include "atom/common/native_mate_converters/string16_converter.h"
#include "atom/common/node_bindings.h"
#include "base/command_line.h" #include "base/command_line.h"
#include "base/feature_list.h" #include "base/feature_list.h"
#include "base/task_scheduler/task_scheduler.h" #include "base/task_scheduler/task_scheduler.h"
@ -45,20 +48,23 @@ int NodeMain(int argc, char *argv[]) {
// V8 requires a task scheduler apparently // V8 requires a task scheduler apparently
base::TaskScheduler::CreateAndStartWithDefaultParams("Electron"); base::TaskScheduler::CreateAndStartWithDefaultParams("Electron");
// Initialize gin::IsolateHolder.
JavascriptEnvironment gin_env; JavascriptEnvironment gin_env;
// Explicitly register electron's builtin modules.
NodeBindings::RegisterBuiltinModules();
int exec_argc; int exec_argc;
const char** exec_argv; const char** exec_argv;
node::Init(&argc, const_cast<const char**>(argv), &exec_argc, &exec_argv); node::Init(&argc, const_cast<const char**>(argv), &exec_argc, &exec_argv);
node::IsolateData isolate_data(gin_env.isolate(), loop);
node::Environment* env = node::CreateEnvironment( node::Environment* env = node::CreateEnvironment(
&isolate_data, gin_env.context(), argc, argv, node::CreateIsolateData(gin_env.isolate(), loop, gin_env.platform()),
exec_argc, exec_argv); gin_env.context(), argc, argv, exec_argc, exec_argv);
// Enable support for v8 inspector. // Enable support for v8 inspector.
NodeDebugger node_debugger(env); NodeDebugger node_debugger(env);
node_debugger.Start(); node_debugger.Start(gin_env.platform());
mate::Dictionary process(gin_env.isolate(), env->process_object()); mate::Dictionary process(gin_env.isolate(), env->process_object());
#if defined(OS_WIN) #if defined(OS_WIN)
@ -76,6 +82,7 @@ int NodeMain(int argc, char *argv[]) {
bool more; bool more;
do { do {
more = uv_run(env->event_loop(), UV_RUN_ONCE); more = uv_run(env->event_loop(), UV_RUN_ONCE);
gin_env.platform()->DrainBackgroundTasks(env->isolate());
if (more == false) { if (more == false) {
node::EmitBeforeExit(env); node::EmitBeforeExit(env);
@ -89,6 +96,8 @@ int NodeMain(int argc, char *argv[]) {
exit_code = node::EmitExit(env); exit_code = node::EmitExit(env);
node::RunAtExit(env); node::RunAtExit(env);
gin_env.platform()->DrainBackgroundTasks(env->isolate());
gin_env.platform()->CancelPendingDelayedTasks(env->isolate());
node::FreeEnvironment(env); node::FreeEnvironment(env);
} }
@ -106,3 +115,5 @@ int NodeMain(int argc, char *argv[]) {
} }
} // namespace atom } // namespace atom
#endif // ENABLE_RUN_AS_NODE

View file

@ -5,10 +5,14 @@
#ifndef ATOM_APP_NODE_MAIN_H_ #ifndef ATOM_APP_NODE_MAIN_H_
#define ATOM_APP_NODE_MAIN_H_ #define ATOM_APP_NODE_MAIN_H_
#ifdef ENABLE_RUN_AS_NODE
namespace atom { namespace atom {
int NodeMain(int argc, char *argv[]); int NodeMain(int argc, char *argv[]);
} // namespace atom } // namespace atom
#endif // ENABLE_RUN_AS_NODE
#endif // ATOM_APP_NODE_MAIN_H_ #endif // ATOM_APP_NODE_MAIN_H_

View file

@ -532,7 +532,6 @@ App::App(v8::Isolate* isolate) {
static_cast<AtomBrowserClient*>(AtomBrowserClient::Get())->set_delegate(this); static_cast<AtomBrowserClient*>(AtomBrowserClient::Get())->set_delegate(this);
Browser::Get()->AddObserver(this); Browser::Get()->AddObserver(this);
content::GpuDataManager::GetInstance()->AddObserver(this); content::GpuDataManager::GetInstance()->AddObserver(this);
content::BrowserChildProcessObserver::Add(this);
base::ProcessId pid = base::GetCurrentProcId(); base::ProcessId pid = base::GetCurrentProcId();
std::unique_ptr<atom::ProcessMetric> process_metric( std::unique_ptr<atom::ProcessMetric> process_metric(
new atom::ProcessMetric( new atom::ProcessMetric(
@ -599,6 +598,7 @@ void App::OnFinishLaunching(const base::DictionaryValue& launch_info) {
} }
void App::OnPreMainMessageLoopRun() { void App::OnPreMainMessageLoopRun() {
content::BrowserChildProcessObserver::Add(this);
if (process_singleton_) { if (process_singleton_) {
process_singleton_->OnBrowserReady(); process_singleton_->OnBrowserReady();
} }
@ -667,25 +667,33 @@ void App::OnLogin(LoginHandler* login_handler,
login_handler->CancelAuth(); login_handler->CancelAuth();
} }
void App::OnCreateWindow( bool App::CanCreateWindow(
content::RenderFrameHost* opener,
const GURL& opener_url,
const GURL& opener_top_level_frame_url,
const GURL& source_origin,
content::mojom::WindowContainerType container_type,
const GURL& target_url, const GURL& target_url,
const content::Referrer& referrer,
const std::string& frame_name, const std::string& frame_name,
WindowOpenDisposition disposition, WindowOpenDisposition disposition,
const std::vector<std::string>& features, const blink::mojom::WindowFeatures& features,
const std::vector<std::string>& additional_features,
const scoped_refptr<content::ResourceRequestBody>& body, const scoped_refptr<content::ResourceRequestBody>& body,
content::RenderFrameHost* opener) { bool user_gesture,
bool opener_suppressed,
bool* no_javascript_access) {
v8::Locker locker(isolate()); v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate()); v8::HandleScope handle_scope(isolate());
content::WebContents* web_contents = content::WebContents* web_contents =
content::WebContents::FromRenderFrameHost(opener); content::WebContents::FromRenderFrameHost(opener);
if (web_contents) { if (web_contents) {
auto api_web_contents = WebContents::CreateFrom(isolate(), web_contents); auto api_web_contents = WebContents::CreateFrom(isolate(), web_contents);
api_web_contents->OnCreateWindow(target_url, api_web_contents->OnCreateWindow(target_url, frame_name, disposition,
frame_name, additional_features, body);
disposition,
features,
body);
} }
return false;
} }
void App::AllowCertificateError( void App::AllowCertificateError(
@ -843,7 +851,7 @@ void App::SetDesktopName(const std::string& desktop_name) {
} }
std::string App::GetLocale() { std::string App::GetLocale() {
return l10n_util::GetApplicationLocale(""); return g_browser_process->GetApplicationLocale();
} }
bool App::MakeSingleInstance( bool App::MakeSingleInstance(
@ -859,9 +867,10 @@ bool App::MakeSingleInstance(
switch (process_singleton_->NotifyOtherProcessOrCreate()) { switch (process_singleton_->NotifyOtherProcessOrCreate()) {
case ProcessSingleton::NotifyResult::LOCK_ERROR: case ProcessSingleton::NotifyResult::LOCK_ERROR:
case ProcessSingleton::NotifyResult::PROFILE_IN_USE: case ProcessSingleton::NotifyResult::PROFILE_IN_USE:
case ProcessSingleton::NotifyResult::PROCESS_NOTIFIED: case ProcessSingleton::NotifyResult::PROCESS_NOTIFIED: {
process_singleton_.reset(); process_singleton_.reset();
return true; return true;
}
case ProcessSingleton::NotifyResult::PROCESS_NONE: case ProcessSingleton::NotifyResult::PROCESS_NONE:
default: // Shouldn't be needed, but VS warns if it is not there. default: // Shouldn't be needed, but VS warns if it is not there.
return false; return false;
@ -888,11 +897,7 @@ bool App::Relaunch(mate::Arguments* js_args) {
} }
if (!override_argv) { if (!override_argv) {
#if defined(OS_WIN)
const relauncher::StringVector& argv = atom::AtomCommandLine::wargv();
#else
const relauncher::StringVector& argv = atom::AtomCommandLine::argv(); const relauncher::StringVector& argv = atom::AtomCommandLine::argv();
#endif
return relauncher::RelaunchApp(argv); return relauncher::RelaunchApp(argv);
} }
@ -1128,8 +1133,8 @@ std::vector<mate::Dictionary> App::GetAppMetrics(v8::Isolate* isolate) {
v8::Local<v8::Value> App::GetGPUFeatureStatus(v8::Isolate* isolate) { v8::Local<v8::Value> App::GetGPUFeatureStatus(v8::Isolate* isolate) {
auto status = content::GetFeatureStatus(); auto status = content::GetFeatureStatus();
return mate::ConvertToV8(isolate, base::DictionaryValue temp;
status ? *status : base::DictionaryValue()); return mate::ConvertToV8(isolate, status ? *status : temp);
} }
void App::EnableMixedSandbox(mate::Arguments* args) { void App::EnableMixedSandbox(mate::Arguments* args) {
@ -1251,13 +1256,16 @@ void App::BuildPrototype(
.SetMethod("getFileIcon", &App::GetFileIcon) .SetMethod("getFileIcon", &App::GetFileIcon)
.SetMethod("getAppMetrics", &App::GetAppMetrics) .SetMethod("getAppMetrics", &App::GetAppMetrics)
.SetMethod("getGPUFeatureStatus", &App::GetGPUFeatureStatus) .SetMethod("getGPUFeatureStatus", &App::GetGPUFeatureStatus)
.SetMethod("enableMixedSandbox", &App::EnableMixedSandbox)
// TODO(juturu): Remove in 2.0, deprecate before then with warnings // TODO(juturu): Remove in 2.0, deprecate before then with warnings
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
.SetMethod("moveToApplicationsFolder", &App::MoveToApplicationsFolder) .SetMethod("moveToApplicationsFolder", &App::MoveToApplicationsFolder)
.SetMethod("isInApplicationsFolder", &App::IsInApplicationsFolder) .SetMethod("isInApplicationsFolder", &App::IsInApplicationsFolder)
#endif #endif
.SetMethod("getAppMemoryInfo", &App::GetAppMetrics); #if defined(MAS_BUILD)
.SetMethod("startAccessingSecurityScopedResource",
&App::StartAccessingSecurityScopedResource)
#endif
.SetMethod("enableMixedSandbox", &App::EnableMixedSandbox);
} }
} // namespace api } // namespace api
@ -1334,4 +1342,4 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
} // namespace } // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_app, Initialize) NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_app, Initialize)

View file

@ -75,15 +75,6 @@ class App : public AtomBrowserClient::Delegate,
static void BuildPrototype(v8::Isolate* isolate, static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype); v8::Local<v8::FunctionTemplate> prototype);
// Called when window with disposition needs to be created.
void OnCreateWindow(
const GURL& target_url,
const std::string& frame_name,
WindowOpenDisposition disposition,
const std::vector<std::string>& features,
const scoped_refptr<content::ResourceRequestBody>& body,
content::RenderFrameHost* opener);
#if defined(USE_NSS_CERTS) #if defined(USE_NSS_CERTS)
void OnCertificateManagerModelCreated( void OnCertificateManagerModelCreated(
std::unique_ptr<base::DictionaryValue> options, std::unique_ptr<base::DictionaryValue> options,
@ -152,6 +143,21 @@ class App : public AtomBrowserClient::Delegate,
net::SSLCertRequestInfo* cert_request_info, net::SSLCertRequestInfo* cert_request_info,
net::ClientCertIdentityList client_certs, net::ClientCertIdentityList client_certs,
std::unique_ptr<content::ClientCertificateDelegate> delegate) override; std::unique_ptr<content::ClientCertificateDelegate> delegate) override;
bool CanCreateWindow(content::RenderFrameHost* opener,
const GURL& opener_url,
const GURL& opener_top_level_frame_url,
const GURL& source_origin,
content::mojom::WindowContainerType container_type,
const GURL& target_url,
const content::Referrer& referrer,
const std::string& frame_name,
WindowOpenDisposition disposition,
const blink::mojom::WindowFeatures& features,
const std::vector<std::string>& additional_features,
const scoped_refptr<content::ResourceRequestBody>& body,
bool user_gesture,
bool opener_suppressed,
bool* no_javascript_access) override;
// content::GpuDataManagerObserver: // content::GpuDataManagerObserver:
void OnGpuProcessCrashed(base::TerminationStatus status) override; void OnGpuProcessCrashed(base::TerminationStatus status) override;
@ -203,6 +209,10 @@ class App : public AtomBrowserClient::Delegate,
bool MoveToApplicationsFolder(mate::Arguments* args); bool MoveToApplicationsFolder(mate::Arguments* args);
bool IsInApplicationsFolder(); bool IsInApplicationsFolder();
#endif #endif
#if defined(MAS_BUILD)
base::Callback<void()> StartAccessingSecurityScopedResource(
mate::Arguments* args);
#endif
#if defined(OS_WIN) #if defined(OS_WIN)
// Get the current Jump List settings. // Get the current Jump List settings.

View file

@ -0,0 +1,59 @@
// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/api/atom_api_app.h"
#import <Cocoa/Cocoa.h>
#include "base/strings/sys_string_conversions.h"
namespace atom {
namespace api {
// Callback passed to js which will stop accessing the given bookmark.
void OnStopAccessingSecurityScopedResource(NSURL* bookmarkUrl) {
[bookmarkUrl stopAccessingSecurityScopedResource];
[bookmarkUrl release];
}
// Get base64 encoded NSData, create a bookmark for it and start accessing it.
base::Callback<void ()> App::StartAccessingSecurityScopedResource(mate::Arguments* args) {
std::string data;
args->GetNext(&data);
NSString *base64str = base::SysUTF8ToNSString(data);
NSData *bookmarkData = [[NSData alloc] initWithBase64EncodedString: base64str options: 0];
// Create bookmarkUrl from NSData.
BOOL isStale = false;
NSError *error = nil;
NSURL *bookmarkUrl = [NSURL URLByResolvingBookmarkData: bookmarkData
options: NSURLBookmarkResolutionWithSecurityScope
relativeToURL: nil
bookmarkDataIsStale: &isStale
error: &error];
if (error != nil) {
NSString *err = [NSString stringWithFormat: @"NSError: %@ %@", error, [error userInfo]];
args->ThrowError(base::SysNSStringToUTF8(err));
}
if (isStale) {
args->ThrowError("bookmarkDataIsStale - try recreating the bookmark");
}
if (error == nil && isStale == false) {
[bookmarkUrl startAccessingSecurityScopedResource];
}
// Stop the NSURL from being GC'd.
[bookmarkUrl retain];
// Return a js callback which will close the bookmark.
return base::Bind(&OnStopAccessingSecurityScopedResource, bookmarkUrl);
}
} // namespace atom
} // namespace api

View file

@ -99,10 +99,8 @@ void AutoUpdater::OnWindowAllClosed() {
QuitAndInstall(); QuitAndInstall();
} }
void AutoUpdater::SetFeedURL(const std::string& url, mate::Arguments* args) { void AutoUpdater::SetFeedURL(mate::Arguments* args) {
auto_updater::AutoUpdater::HeaderMap headers; auto_updater::AutoUpdater::SetFeedURL(args);
args->GetNext(&headers);
auto_updater::AutoUpdater::SetFeedURL(url, headers);
} }
void AutoUpdater::QuitAndInstall() { void AutoUpdater::QuitAndInstall() {
@ -152,4 +150,4 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
} // namespace } // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_auto_updater, Initialize) NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_auto_updater, Initialize)

View file

@ -47,7 +47,7 @@ class AutoUpdater : public mate::EventEmitter<AutoUpdater>,
private: private:
std::string GetFeedURL(); std::string GetFeedURL();
void SetFeedURL(const std::string& url, mate::Arguments* args); void SetFeedURL(mate::Arguments* args);
void QuitAndInstall(); void QuitAndInstall();
DISALLOW_COPY_AND_ASSIGN(AutoUpdater); DISALLOW_COPY_AND_ASSIGN(AutoUpdater);

View file

@ -162,4 +162,4 @@ void Initialize(v8::Local<v8::Object> exports,
} // namespace } // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_browser_view, Initialize) NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_browser_view, Initialize)

File diff suppressed because it is too large Load diff

View file

@ -2,22 +2,23 @@
// Use of this source code is governed by the MIT license that can be // Use of this source code is governed by the MIT license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef ATOM_BROWSER_API_ATOM_API_WINDOW_H_ #ifndef ATOM_BROWSER_API_ATOM_API_BROWSER_WINDOW_H_
#define ATOM_BROWSER_API_ATOM_API_WINDOW_H_ #define ATOM_BROWSER_API_ATOM_API_BROWSER_WINDOW_H_
#include <map> #include <map>
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
#include "atom/browser/api/trackable_object.h" #include "atom/browser/api/atom_api_web_contents.h"
#include "atom/browser/native_window.h" #include "atom/browser/native_window.h"
#include "atom/browser/native_window_observer.h" #include "atom/browser/native_window_observer.h"
#include "atom/common/api/atom_api_native_image.h" #include "atom/common/api/atom_api_native_image.h"
#include "atom/common/key_weak_map.h" #include "atom/common/key_weak_map.h"
#include "native_mate/handle.h" #include "base/cancelable_callback.h"
#include "base/memory/weak_ptr.h"
#include "content/public/browser/render_widget_host.h"
#include "native_mate/persistent_dictionary.h" #include "native_mate/persistent_dictionary.h"
#include "ui/gfx/image/image.h"
class GURL; class GURL;
@ -36,10 +37,11 @@ class NativeWindow;
namespace api { namespace api {
class WebContents; class BrowserWindow : public mate::TrackableObject<BrowserWindow>,
public content::RenderWidgetHost::InputEventObserver,
class Window : public mate::TrackableObject<Window>, public content::WebContentsObserver,
public NativeWindowObserver { public ExtendedWebContentsObserver,
public NativeWindowObserver {
public: public:
static mate::WrappableBase* New(mate::Arguments* args); static mate::WrappableBase* New(mate::Arguments* args);
@ -55,20 +57,38 @@ class Window : public mate::TrackableObject<Window>,
int32_t ID() const; int32_t ID() const;
protected: protected:
Window(v8::Isolate* isolate, v8::Local<v8::Object> wrapper, BrowserWindow(v8::Isolate* isolate,
const mate::Dictionary& options); v8::Local<v8::Object> wrapper,
~Window() override; const mate::Dictionary& options);
~BrowserWindow() override;
// content::RenderWidgetHost::InputEventObserver:
void OnInputEvent(const blink::WebInputEvent& event) override;
// content::WebContentsObserver:
void RenderViewHostChanged(content::RenderViewHost* old_host,
content::RenderViewHost* new_host) override;
void RenderViewCreated(content::RenderViewHost* render_view_host) override;
void DidFirstVisuallyNonEmptyPaint() override;
void BeforeUnloadDialogCancelled() override;
void OnRendererUnresponsive(content::RenderWidgetHost*) override;
bool OnMessageReceived(const IPC::Message& message,
content::RenderFrameHost* rfh) override;
// ExtendedWebContentsObserver:
void OnCloseContents() override;
void OnRendererResponsive() override;
// NativeWindowObserver: // NativeWindowObserver:
void WillCloseWindow(bool* prevent_default) override; void WillCloseWindow(bool* prevent_default) override;
void WillDestroyNativeObject() override; void RequestPreferredWidth(int* width) override;
void OnCloseButtonClicked(bool* prevent_default) override;
void OnWindowClosed() override; void OnWindowClosed() override;
void OnWindowEndSession() override; void OnWindowEndSession() override;
void OnWindowBlur() override; void OnWindowBlur() override;
void OnWindowFocus() override; void OnWindowFocus() override;
void OnWindowShow() override; void OnWindowShow() override;
void OnWindowHide() override; void OnWindowHide() override;
void OnReadyToShow() override;
void OnWindowMaximize() override; void OnWindowMaximize() override;
void OnWindowUnmaximize() override; void OnWindowUnmaximize() override;
void OnWindowMinimize() override; void OnWindowMinimize() override;
@ -78,7 +98,6 @@ class Window : public mate::TrackableObject<Window>,
void OnWindowMoved() override; void OnWindowMoved() override;
void OnWindowScrollTouchBegin() override; void OnWindowScrollTouchBegin() override;
void OnWindowScrollTouchEnd() override; void OnWindowScrollTouchEnd() override;
void OnWindowScrollTouchEdge() override;
void OnWindowSwipe(const std::string& direction) override; void OnWindowSwipe(const std::string& direction) override;
void OnWindowSheetBegin() override; void OnWindowSheetBegin() override;
void OnWindowSheetEnd() override; void OnWindowSheetEnd() override;
@ -86,8 +105,6 @@ class Window : public mate::TrackableObject<Window>,
void OnWindowLeaveFullScreen() override; void OnWindowLeaveFullScreen() override;
void OnWindowEnterHtmlFullScreen() override; void OnWindowEnterHtmlFullScreen() override;
void OnWindowLeaveHtmlFullScreen() override; void OnWindowLeaveHtmlFullScreen() override;
void OnRendererUnresponsive() override;
void OnRendererResponsive() override;
void OnExecuteWindowsCommand(const std::string& command_name) override; void OnExecuteWindowsCommand(const std::string& command_name) override;
void OnTouchBarItemResult(const std::string& item_id, void OnTouchBarItemResult(const std::string& item_id,
const base::DictionaryValue& details) override; const base::DictionaryValue& details) override;
@ -97,11 +114,16 @@ 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
base::WeakPtr<BrowserWindow> GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
private: private:
void Init(v8::Isolate* isolate, void Init(v8::Isolate* isolate,
v8::Local<v8::Object> wrapper, v8::Local<v8::Object> wrapper,
const mate::Dictionary& options, const mate::Dictionary& options,
mate::Handle<class WebContents> web_contents); mate::Handle<class WebContents> web_contents);
// APIs for NativeWindow. // APIs for NativeWindow.
void Close(); void Close();
void Focus(); void Focus();
@ -112,6 +134,7 @@ class Window : public mate::TrackableObject<Window>,
void Hide(); void Hide();
bool IsVisible(); bool IsVisible();
bool IsEnabled(); bool IsEnabled();
void SetEnabled(bool enable);
void Maximize(); void Maximize();
void Unmaximize(); void Unmaximize();
bool IsMaximized(); bool IsMaximized();
@ -221,7 +244,7 @@ class Window : public mate::TrackableObject<Window>,
void MergeAllWindows(); void MergeAllWindows();
void MoveTabToNewWindow(); void MoveTabToNewWindow();
void ToggleTabBar(); void ToggleTabBar();
void AddTabbedWindow(NativeWindow* window); void AddTabbedWindow(NativeWindow* window, mate::Arguments* args);
void SetVibrancy(mate::Arguments* args); void SetVibrancy(mate::Arguments* args);
void SetTouchBar(const std::vector<mate::PersistentDictionary>& items); void SetTouchBar(const std::vector<mate::PersistentDictionary>& items);
@ -233,11 +256,34 @@ class Window : public mate::TrackableObject<Window>,
// Remove this window from parent window's |child_windows_|. // Remove this window from parent window's |child_windows_|.
void RemoveFromParentChildWindows(); void RemoveFromParentChildWindows();
// Called when the window needs to update its draggable region.
void UpdateDraggableRegions(
content::RenderFrameHost* rfh,
const std::vector<DraggableRegion>& regions);
// Convert draggable regions in raw format to SkRegion format.
std::unique_ptr<SkRegion> DraggableRegionsToSkRegion(
const std::vector<DraggableRegion>& regions);
// Schedule a notification unresponsive event.
void ScheduleUnresponsiveEvent(int ms);
// Dispatch unresponsive event to observers.
void NotifyWindowUnresponsive();
#if defined(OS_WIN) #if defined(OS_WIN)
typedef std::map<UINT, MessageCallback> MessageCallbackMap; typedef std::map<UINT, MessageCallback> MessageCallbackMap;
MessageCallbackMap messages_callback_map_; MessageCallbackMap messages_callback_map_;
#endif #endif
#if defined(OS_MACOSX)
std::vector<DraggableRegion> draggable_regions_;
#endif
// Closure that would be called when window is unresponsive when closing,
// it should be cancelled when we can prove that the window is responsive.
base::CancelableClosure window_unresponsive_closure_;
v8::Global<v8::Value> browser_view_; v8::Global<v8::Value> browser_view_;
v8::Global<v8::Value> web_contents_; v8::Global<v8::Value> web_contents_;
v8::Global<v8::Value> menu_; v8::Global<v8::Value> menu_;
@ -248,7 +294,9 @@ class Window : public mate::TrackableObject<Window>,
std::unique_ptr<NativeWindow> window_; std::unique_ptr<NativeWindow> window_;
DISALLOW_COPY_AND_ASSIGN(Window); base::WeakPtrFactory<BrowserWindow> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(BrowserWindow);
}; };
} // namespace api } // namespace api
@ -268,8 +316,8 @@ struct Converter<atom::NativeWindow*> {
return true; return true;
} }
atom::api::Window* window; atom::api::BrowserWindow* window;
if (!Converter<atom::api::Window*>::FromV8(isolate, val, &window)) if (!Converter<atom::api::BrowserWindow*>::FromV8(isolate, val, &window))
return false; return false;
*out = window->window(); *out = window->window();
return true; return true;
@ -278,4 +326,4 @@ struct Converter<atom::NativeWindow*> {
} // namespace mate } // namespace mate
#endif // ATOM_BROWSER_API_ATOM_API_WINDOW_H_ #endif // ATOM_BROWSER_API_ATOM_API_BROWSER_WINDOW_H_

View file

@ -0,0 +1,120 @@
// Copyright (c) 2018 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/api/atom_api_browser_window.h"
#import <Cocoa/Cocoa.h>
#include "atom/browser/native_browser_view.h"
#include "atom/common/draggable_region.h"
#include "base/mac/scoped_nsobject.h"
@interface NSView (WebContentsView)
- (void)setMouseDownCanMoveWindow:(BOOL)can_move;
@end
@interface ControlRegionView : NSView
@end
@implementation ControlRegionView
- (BOOL)mouseDownCanMoveWindow {
return NO;
}
- (NSView*)hitTest:(NSPoint)aPoint {
return nil;
}
@end
namespace atom {
namespace api {
namespace {
// Return a vector of non-draggable regions that fill a window of size
// |width| by |height|, but leave gaps where the window should be draggable.
std::vector<gfx::Rect> CalculateNonDraggableRegions(
std::unique_ptr<SkRegion> draggable, int width, int height) {
std::vector<gfx::Rect> result;
std::unique_ptr<SkRegion> non_draggable(new SkRegion);
non_draggable->op(0, 0, width, height, SkRegion::kUnion_Op);
non_draggable->op(*draggable, SkRegion::kDifference_Op);
for (SkRegion::Iterator it(*non_draggable); !it.done(); it.next()) {
result.push_back(gfx::SkIRectToRect(it.rect()));
}
return result;
}
} // namespace
void BrowserWindow::UpdateDraggableRegions(
content::RenderFrameHost* rfh,
const std::vector<DraggableRegion>& regions) {
if (window_->has_frame())
return;
// All ControlRegionViews should be added as children of the WebContentsView,
// because WebContentsView will be removed and re-added when entering and
// leaving fullscreen mode.
NSView* webView = web_contents()->GetNativeView();
NSInteger webViewWidth = NSWidth([webView bounds]);
NSInteger webViewHeight = NSHeight([webView bounds]);
if ([webView respondsToSelector:@selector(setMouseDownCanMoveWindow:)]) {
[webView setMouseDownCanMoveWindow:YES];
}
// Remove all ControlRegionViews that are added last time.
// Note that [webView subviews] returns the view's mutable internal array and
// it should be copied to avoid mutating the original array while enumerating
// it.
base::scoped_nsobject<NSArray> subviews([[webView subviews] copy]);
for (NSView* subview in subviews.get())
if ([subview isKindOfClass:[ControlRegionView class]])
[subview removeFromSuperview];
// Draggable regions is implemented by having the whole web view draggable
// (mouseDownCanMoveWindow) and overlaying regions that are not draggable.
draggable_regions_ = regions;
std::vector<gfx::Rect> system_drag_exclude_areas;
if (regions.empty()) {
system_drag_exclude_areas.push_back(
gfx::Rect(0, 0, webViewWidth, webViewHeight));
} else {
CalculateNonDraggableRegions(
DraggableRegionsToSkRegion(regions), webViewWidth, webViewHeight);
}
if (window_->browser_view())
window_->browser_view()->UpdateDraggableRegions(system_drag_exclude_areas);
// Create and add a ControlRegionView for each region that needs to be
// excluded from the dragging.
for (std::vector<gfx::Rect>::const_iterator iter =
system_drag_exclude_areas.begin();
iter != system_drag_exclude_areas.end();
++iter) {
base::scoped_nsobject<NSView> controlRegion(
[[ControlRegionView alloc] initWithFrame:NSZeroRect]);
[controlRegion setFrame:NSMakeRect(iter->x(),
webViewHeight - iter->bottom(),
iter->width(),
iter->height())];
[webView addSubview:controlRegion];
}
// AppKit will not update its cache of mouseDownCanMoveWindow unless something
// changes. Previously we tried adding an NSView and removing it, but for some
// reason it required reposting the mouse-down event, and didn't always work.
// Calling the below seems to be an effective solution.
[[webView window] setMovableByWindowBackground:NO];
[[webView window] setMovableByWindowBackground:YES];
}
} // namespace api
} // namespace atom

View file

@ -0,0 +1,24 @@
// Copyright (c) 2018 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/api/atom_api_browser_window.h"
#include "atom/browser/native_window_views.h"
namespace atom {
namespace api {
void BrowserWindow::UpdateDraggableRegions(
content::RenderFrameHost* rfh,
const std::vector<DraggableRegion>& regions) {
if (window_->has_frame())
return;
static_cast<NativeWindowViews*>(window_.get())->UpdateDraggableRegions(
DraggableRegionsToSkRegion(regions));
}
} // namespace api
} // namespace atom

View file

@ -73,4 +73,4 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
} // namespace } // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_content_tracing, Initialize) NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_content_tracing, Initialize)

View file

@ -20,7 +20,6 @@
#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::AtomCookieDelegate;
using content::BrowserThread; using content::BrowserThread;
namespace mate { namespace mate {
@ -238,17 +237,15 @@ void SetCookieOnIO(scoped_refptr<net::URLRequestContextGetter> getter,
} // namespace } // namespace
Cookies::Cookies(v8::Isolate* isolate, Cookies::Cookies(v8::Isolate* isolate, AtomBrowserContext* browser_context)
AtomBrowserContext* browser_context) : browser_context_(browser_context),
: request_context_getter_(browser_context->url_request_context_getter()), request_context_getter_(browser_context->url_request_context_getter()) {
cookie_delegate_(browser_context->cookie_delegate()) {
Init(isolate); Init(isolate);
cookie_delegate_->AddObserver(this); cookie_change_subscription_ = browser_context->RegisterCookieChangeCallback(
base::Bind(&Cookies::OnCookieChanged, base::Unretained(this)));
} }
Cookies::~Cookies() { Cookies::~Cookies() {}
cookie_delegate_->RemoveObserver(this);
}
void Cookies::Get(const base::DictionaryValue& filter, void Cookies::Get(const base::DictionaryValue& filter,
const GetCallback& callback) { const GetCallback& callback) {
@ -283,10 +280,8 @@ void Cookies::FlushStore(const base::Closure& callback) {
base::Bind(FlushCookieStoreOnIOThread, getter, callback)); base::Bind(FlushCookieStoreOnIOThread, getter, callback));
} }
void Cookies::OnCookieChanged(const net::CanonicalCookie& cookie, void Cookies::OnCookieChanged(const CookieDetails* details) {
bool removed, Emit("changed", *(details->cookie), details->cause, details->removed);
net::CookieStore::ChangeCause cause) {
Emit("changed", cookie, cause, removed);
} }

View file

@ -8,7 +8,7 @@
#include <string> #include <string>
#include "atom/browser/api/trackable_object.h" #include "atom/browser/api/trackable_object.h"
#include "atom/browser/net/atom_cookie_delegate.h" #include "atom/browser/net/cookie_details.h"
#include "base/callback.h" #include "base/callback.h"
#include "native_mate/handle.h" #include "native_mate/handle.h"
#include "net/cookies/canonical_cookie.h" #include "net/cookies/canonical_cookie.h"
@ -27,8 +27,7 @@ class AtomBrowserContext;
namespace api { namespace api {
class Cookies : public mate::TrackableObject<Cookies>, class Cookies : public mate::TrackableObject<Cookies> {
public AtomCookieDelegate::Observer {
public: public:
enum Error { enum Error {
SUCCESS, SUCCESS,
@ -55,14 +54,16 @@ class Cookies : public mate::TrackableObject<Cookies>,
void Set(const base::DictionaryValue& details, const SetCallback& callback); void Set(const base::DictionaryValue& details, const SetCallback& callback);
void FlushStore(const base::Closure& callback); void FlushStore(const base::Closure& callback);
// AtomCookieDelegate::Observer: // AtomBrowserContext::RegisterCookieChangeCallback subscription:
void OnCookieChanged(const net::CanonicalCookie& cookie, void OnCookieChanged(const CookieDetails*);
bool removed,
net::CookieStore::ChangeCause cause) override;
private: private:
// Store a reference to ensure this class gets destroyed before the context.
scoped_refptr<AtomBrowserContext> browser_context_;
std::unique_ptr<base::CallbackList<void(const CookieDetails*)>::Subscription>
cookie_change_subscription_;
net::URLRequestContextGetter* request_context_getter_; net::URLRequestContextGetter* request_context_getter_;
scoped_refptr<AtomCookieDelegate> cookie_delegate_;
DISALLOW_COPY_AND_ASSIGN(Cookies); DISALLOW_COPY_AND_ASSIGN(Cookies);
}; };

View file

@ -9,6 +9,7 @@
#include "atom/browser/atom_browser_main_parts.h" #include "atom/browser/atom_browser_main_parts.h"
#include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/callback.h"
#include "atom/common/native_mate_converters/value_converter.h" #include "atom/common/native_mate_converters/value_converter.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h" #include "base/json/json_writer.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "content/public/browser/devtools_agent_host.h" #include "content/public/browser/devtools_agent_host.h"
@ -48,20 +49,11 @@ void Debugger::DispatchProtocolMessage(DevToolsAgentHost* agent_host,
v8::Locker locker(isolate()); v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate()); v8::HandleScope handle_scope(isolate());
v8::Local<v8::String> local_message = std::unique_ptr<base::Value> parsed_message = base::JSONReader::Read(message);
v8::String::NewFromUtf8(isolate(), message.data()); if (!parsed_message || !parsed_message->is_dict())
v8::MaybeLocal<v8::Value> parsed_message = v8::JSON::Parse(
isolate()->GetCurrentContext(), local_message);
if (parsed_message.IsEmpty()) {
return; return;
} base::DictionaryValue* dict =
static_cast<base::DictionaryValue*>(parsed_message.get());
std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
if (!mate::ConvertFromV8(isolate(), parsed_message.ToLocalChecked(),
dict.get())) {
return;
}
int id; int id;
if (!dict->GetInteger("id", &id)) { if (!dict->GetInteger("id", &id)) {
std::string method; std::string method;
@ -186,4 +178,4 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
} // namespace } // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_debugger, Initialize); NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_debugger, Initialize);

View file

@ -10,6 +10,7 @@ using base::PlatformThreadRef;
#include "atom/common/native_mate_converters/gfx_converter.h" #include "atom/common/native_mate_converters/gfx_converter.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "chrome/browser/media/desktop_media_list.h" #include "chrome/browser/media/desktop_media_list.h"
#include "content/public/browser/desktop_capture.h"
#include "native_mate/dictionary.h" #include "native_mate/dictionary.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h" #include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h" #include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
@ -50,17 +51,7 @@ void DesktopCapturer::StartHandling(bool capture_window,
bool capture_screen, bool capture_screen,
const gfx::Size& thumbnail_size) { const gfx::Size& thumbnail_size) {
webrtc::DesktopCaptureOptions options = webrtc::DesktopCaptureOptions options =
webrtc::DesktopCaptureOptions::CreateDefault(); content::CreateDesktopCaptureOptions();
#if defined(OS_WIN)
// On windows, desktop effects (e.g. Aero) will be disabled when the Desktop
// capture API is active by default.
// We keep the desktop effects in most times. Howerver, the screen still
// fickers when the API is capturing the window due to limitation of current
// implemetation. This is a known and wontFix issue in webrtc (see:
// http://code.google.com/p/webrtc/issues/detail?id=3373)
options.set_disable_effects(false);
#endif
std::unique_ptr<webrtc::DesktopCapturer> screen_capturer( std::unique_ptr<webrtc::DesktopCapturer> screen_capturer(
capture_screen ? webrtc::DesktopCapturer::CreateScreenCapturer(options) capture_screen ? webrtc::DesktopCapturer::CreateScreenCapturer(options)
@ -123,4 +114,4 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
} // namespace } // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_desktop_capturer, Initialize); NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_desktop_capturer, Initialize);

View file

@ -6,7 +6,7 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "atom/browser/api/atom_api_window.h" #include "atom/browser/api/atom_api_browser_window.h"
#include "atom/browser/native_window.h" #include "atom/browser/native_window.h"
#include "atom/browser/ui/certificate_trust.h" #include "atom/browser/ui/certificate_trust.h"
#include "atom/browser/ui/file_dialog.h" #include "atom/browser/ui/file_dialog.h"
@ -54,6 +54,9 @@ struct Converter<file_dialog::DialogSettings> {
dict.Get("filters", &(out->filters)); dict.Get("filters", &(out->filters));
dict.Get("properties", &(out->properties)); dict.Get("properties", &(out->properties));
dict.Get("showsTagField", &(out->shows_tag_field)); dict.Get("showsTagField", &(out->shows_tag_field));
#if defined(MAS_BUILD)
dict.Get("securityScopedBookmarks", &(out->security_scoped_bookmarks));
#endif
return true; return true;
} }
}; };
@ -137,4 +140,4 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
} // namespace } // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_dialog, Initialize) NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_dialog, Initialize)

View file

@ -236,4 +236,4 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
} // namespace } // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_download_item, Initialize); NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_download_item, Initialize);

View file

@ -98,4 +98,4 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
} // namespace } // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_global_shortcut, Initialize) NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_global_shortcut, Initialize)

View file

@ -0,0 +1,115 @@
// Copyright (c) 2017 Amaplex Software, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/api/atom_api_in_app_purchase.h"
#include <string>
#include <utility>
#include <vector>
#include "atom/common/native_mate_converters/callback.h"
#include "native_mate/dictionary.h"
#include "atom/common/node_includes.h"
namespace mate {
template <>
struct Converter<in_app_purchase::Payment> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const in_app_purchase::Payment& payment) {
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
dict.SetHidden("simple", true);
dict.Set("productIdentifier", payment.productIdentifier);
dict.Set("quantity", payment.quantity);
return dict.GetHandle();
}
};
template <>
struct Converter<in_app_purchase::Transaction> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const in_app_purchase::Transaction& val) {
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
dict.SetHidden("simple", true);
dict.Set("transactionIdentifier", val.transactionIdentifier);
dict.Set("transactionDate", val.transactionDate);
dict.Set("originalTransactionIdentifier",
val.originalTransactionIdentifier);
dict.Set("transactionState", val.transactionState);
dict.Set("errorCode", val.errorCode);
dict.Set("errorMessage", val.errorMessage);
dict.Set("payment", val.payment);
return dict.GetHandle();
}
};
} // namespace mate
namespace atom {
namespace api {
#if defined(OS_MACOSX)
// static
mate::Handle<InAppPurchase> InAppPurchase::Create(v8::Isolate* isolate) {
return mate::CreateHandle(isolate, new InAppPurchase(isolate));
}
// static
void InAppPurchase::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(mate::StringToV8(isolate, "InAppPurchase"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("canMakePayments", &in_app_purchase::CanMakePayments)
.SetMethod("getReceiptURL", &in_app_purchase::GetReceiptURL)
.SetMethod("purchaseProduct", &InAppPurchase::PurchaseProduct);
}
InAppPurchase::InAppPurchase(v8::Isolate* isolate) {
Init(isolate);
}
InAppPurchase::~InAppPurchase() {
}
void InAppPurchase::PurchaseProduct(const std::string& product_id,
mate::Arguments* args) {
int quantity = 1;
in_app_purchase::InAppPurchaseCallback callback;
args->GetNext(&quantity);
args->GetNext(&callback);
in_app_purchase::PurchaseProduct(product_id, quantity, callback);
}
void InAppPurchase::OnTransactionsUpdated(
const std::vector<in_app_purchase::Transaction>& transactions) {
Emit("transactions-updated", transactions);
}
#endif
} // namespace api
} // namespace atom
namespace {
using atom::api::InAppPurchase;
void Initialize(v8::Local<v8::Object> exports,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv) {
#if defined(OS_MACOSX)
v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary dict(isolate, exports);
dict.Set("inAppPurchase", InAppPurchase::Create(isolate));
dict.Set("InAppPurchase",
InAppPurchase::GetConstructor(isolate)->GetFunction());
#endif
}
} // namespace
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_in_app_purchase, Initialize)

View file

@ -0,0 +1,46 @@
// Copyright (c) 2017 Amaplex Software, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_BROWSER_API_ATOM_API_IN_APP_PURCHASE_H_
#define ATOM_BROWSER_API_ATOM_API_IN_APP_PURCHASE_H_
#include <string>
#include <vector>
#include "atom/browser/api/event_emitter.h"
#include "atom/browser/mac/in_app_purchase.h"
#include "atom/browser/mac/in_app_purchase_observer.h"
#include "native_mate/handle.h"
namespace atom {
namespace api {
class InAppPurchase: public mate::EventEmitter<InAppPurchase>,
public in_app_purchase::TransactionObserver {
public:
static mate::Handle<InAppPurchase> Create(v8::Isolate* isolate);
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype);
protected:
explicit InAppPurchase(v8::Isolate* isolate);
~InAppPurchase() override;
void PurchaseProduct(const std::string& product_id, mate::Arguments* args);
// TransactionObserver:
void OnTransactionsUpdated(
const std::vector<in_app_purchase::Transaction>& transactions) override;
private:
DISALLOW_COPY_AND_ASSIGN(InAppPurchase);
};
} // namespace api
} // namespace atom
#endif // ATOM_BROWSER_API_ATOM_API_IN_APP_PURCHASE_H_

View file

@ -23,9 +23,13 @@ Menu::Menu(v8::Isolate* isolate, v8::Local<v8::Object> wrapper)
: model_(new AtomMenuModel(this)), : model_(new AtomMenuModel(this)),
parent_(nullptr) { parent_(nullptr) {
InitWith(isolate, wrapper); InitWith(isolate, wrapper);
model_->AddObserver(this);
} }
Menu::~Menu() { Menu::~Menu() {
if (model_) {
model_->RemoveObserver(this);
}
} }
void Menu::AfterInit(v8::Isolate* isolate) { void Menu::AfterInit(v8::Isolate* isolate) {
@ -43,15 +47,21 @@ void Menu::AfterInit(v8::Isolate* isolate) {
} }
bool Menu::IsCommandIdChecked(int command_id) const { bool Menu::IsCommandIdChecked(int command_id) const {
return is_checked_.Run(command_id); v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
return is_checked_.Run(GetWrapper(), command_id);
} }
bool Menu::IsCommandIdEnabled(int command_id) const { bool Menu::IsCommandIdEnabled(int command_id) const {
return is_enabled_.Run(command_id); v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
return is_enabled_.Run(GetWrapper(), command_id);
} }
bool Menu::IsCommandIdVisible(int command_id) const { bool Menu::IsCommandIdVisible(int command_id) const {
return is_visible_.Run(command_id); v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
return is_visible_.Run(GetWrapper(), command_id);
} }
bool Menu::GetAcceleratorForCommandIdWithParams( bool Menu::GetAcceleratorForCommandIdWithParams(
@ -61,18 +71,23 @@ bool Menu::GetAcceleratorForCommandIdWithParams(
v8::Locker locker(isolate()); v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate()); v8::HandleScope handle_scope(isolate());
v8::Local<v8::Value> val = get_accelerator_.Run( v8::Local<v8::Value> val = get_accelerator_.Run(
command_id, use_default_accelerator); GetWrapper(), command_id, use_default_accelerator);
return mate::ConvertFromV8(isolate(), val, accelerator); return mate::ConvertFromV8(isolate(), val, accelerator);
} }
void Menu::ExecuteCommand(int command_id, int flags) { void Menu::ExecuteCommand(int command_id, int flags) {
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
execute_command_.Run( execute_command_.Run(
GetWrapper(),
mate::internal::CreateEventFromFlags(isolate(), flags), mate::internal::CreateEventFromFlags(isolate(), flags),
command_id); command_id);
} }
void Menu::MenuWillShow(ui::SimpleMenuModel* source) { void Menu::MenuWillShow(ui::SimpleMenuModel* source) {
menu_will_show_.Run(); v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
menu_will_show_.Run(GetWrapper());
} }
void Menu::InsertItemAt( void Menu::InsertItemAt(
@ -153,6 +168,14 @@ bool Menu::IsVisibleAt(int index) const {
return model_->IsVisibleAt(index); return model_->IsVisibleAt(index);
} }
void Menu::OnMenuWillClose() {
Emit("menu-will-close");
}
void Menu::OnMenuWillShow() {
Emit("menu-will-show");
}
// static // static
void Menu::BuildPrototype(v8::Isolate* isolate, void Menu::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) { v8::Local<v8::FunctionTemplate> prototype) {
@ -205,4 +228,4 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
} // namespace } // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_menu, Initialize) NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_menu, Initialize)

View file

@ -8,7 +8,7 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include "atom/browser/api/atom_api_window.h" #include "atom/browser/api/atom_api_browser_window.h"
#include "atom/browser/api/trackable_object.h" #include "atom/browser/api/trackable_object.h"
#include "atom/browser/ui/atom_menu_model.h" #include "atom/browser/ui/atom_menu_model.h"
#include "base/callback.h" #include "base/callback.h"
@ -18,7 +18,8 @@ namespace atom {
namespace api { namespace api {
class Menu : public mate::TrackableObject<Menu>, class Menu : public mate::TrackableObject<Menu>,
public AtomMenuModel::Delegate { public AtomMenuModel::Delegate,
public AtomMenuModel::Observer {
public: public:
static mate::WrappableBase* New(mate::Arguments* args); static mate::WrappableBase* New(mate::Arguments* args);
@ -53,12 +54,18 @@ class Menu : public mate::TrackableObject<Menu>,
void ExecuteCommand(int command_id, int event_flags) override; void ExecuteCommand(int command_id, int event_flags) override;
void MenuWillShow(ui::SimpleMenuModel* source) override; void MenuWillShow(ui::SimpleMenuModel* source) override;
virtual void PopupAt(Window* window, int x, int y, int positioning_item) = 0; virtual void PopupAt(BrowserWindow* window,
int x, int y, int positioning_item,
const base::Closure& callback) = 0;
virtual void ClosePopupAt(int32_t window_id) = 0; virtual void ClosePopupAt(int32_t window_id) = 0;
std::unique_ptr<AtomMenuModel> model_; std::unique_ptr<AtomMenuModel> model_;
Menu* parent_; Menu* parent_;
// Observable:
void OnMenuWillClose() override;
void OnMenuWillShow() override;
private: private:
void InsertItemAt(int index, int command_id, const base::string16& label); void InsertItemAt(int index, int command_id, const base::string16& label);
void InsertSeparatorAt(int index); void InsertSeparatorAt(int index);
@ -87,12 +94,14 @@ class Menu : public mate::TrackableObject<Menu>,
bool IsVisibleAt(int index) const; bool IsVisibleAt(int index) const;
// Stored delegate methods. // Stored delegate methods.
base::Callback<bool(int)> is_checked_; base::Callback<bool(v8::Local<v8::Value>, int)> is_checked_;
base::Callback<bool(int)> is_enabled_; base::Callback<bool(v8::Local<v8::Value>, int)> is_enabled_;
base::Callback<bool(int)> is_visible_; base::Callback<bool(v8::Local<v8::Value>, int)> is_visible_;
base::Callback<v8::Local<v8::Value>(int, bool)> get_accelerator_; base::Callback<v8::Local<v8::Value>(v8::Local<v8::Value>, int, bool)>
base::Callback<void(v8::Local<v8::Value>, int)> execute_command_; get_accelerator_;
base::Callback<void()> menu_will_show_; base::Callback<void(v8::Local<v8::Value>, v8::Local<v8::Value>, int)>
execute_command_;
base::Callback<void(v8::Local<v8::Value>)> menu_will_show_;
DISALLOW_COPY_AND_ASSIGN(Menu); DISALLOW_COPY_AND_ASSIGN(Menu);
}; };

View file

@ -22,18 +22,21 @@ class MenuMac : public Menu {
protected: protected:
MenuMac(v8::Isolate* isolate, v8::Local<v8::Object> wrapper); MenuMac(v8::Isolate* isolate, v8::Local<v8::Object> wrapper);
void PopupAt(Window* window, int x, int y, int positioning_item) override; void PopupAt(BrowserWindow* window,
int x, int y, int positioning_item,
const base::Closure& callback) override;
void PopupOnUI(const base::WeakPtr<NativeWindow>& native_window, void PopupOnUI(const base::WeakPtr<NativeWindow>& native_window,
int32_t window_id, int32_t window_id,
int x, int x,
int y, int y,
int positioning_item); int positioning_item,
base::Closure callback);
void ClosePopupAt(int32_t window_id) override; void ClosePopupAt(int32_t window_id) override;
private: private:
friend class Menu; friend class Menu;
static void SendActionToFirstResponder(const std::string& action); void OnClosed(int32_t window_id, base::Closure callback);
scoped_nsobject<AtomMenuController> menu_controller_; scoped_nsobject<AtomMenuController> menu_controller_;

View file

@ -27,14 +27,16 @@ MenuMac::MenuMac(v8::Isolate* isolate, v8::Local<v8::Object> wrapper)
weak_factory_(this) { weak_factory_(this) {
} }
void MenuMac::PopupAt(Window* window, int x, int y, int positioning_item) { void MenuMac::PopupAt(BrowserWindow* window,
int x, int y, int positioning_item,
const base::Closure& callback) {
NativeWindow* native_window = window->window(); NativeWindow* native_window = window->window();
if (!native_window) if (!native_window)
return; return;
auto popup = base::Bind(&MenuMac::PopupOnUI, weak_factory_.GetWeakPtr(), auto popup = base::Bind(&MenuMac::PopupOnUI, weak_factory_.GetWeakPtr(),
native_window->GetWeakPtr(), window->ID(), x, y, native_window->GetWeakPtr(), window->ID(), x, y,
positioning_item); positioning_item, callback);
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, popup); BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, popup);
} }
@ -42,21 +44,19 @@ void MenuMac::PopupOnUI(const base::WeakPtr<NativeWindow>& native_window,
int32_t window_id, int32_t window_id,
int x, int x,
int y, int y,
int positioning_item) { int positioning_item,
base::Closure callback) {
if (!native_window) if (!native_window)
return; return;
brightray::InspectableWebContents* web_contents = NSWindow* nswindow = native_window->GetNativeWindow();
native_window->inspectable_web_contents();
if (!web_contents)
return;
auto close_callback = base::Bind(&MenuMac::ClosePopupAt, auto close_callback = base::Bind(
weak_factory_.GetWeakPtr(), window_id); &MenuMac::OnClosed, weak_factory_.GetWeakPtr(), window_id, callback);
popup_controllers_[window_id] = base::scoped_nsobject<AtomMenuController>( popup_controllers_[window_id] = base::scoped_nsobject<AtomMenuController>(
[[AtomMenuController alloc] initWithModel:model() [[AtomMenuController alloc] initWithModel:model()
useDefaultAccelerator:NO]); useDefaultAccelerator:NO]);
NSMenu* menu = [popup_controllers_[window_id] menu]; NSMenu* menu = [popup_controllers_[window_id] menu];
NSView* view = web_contents->GetView()->GetNativeView(); NSView* view = [nswindow contentView];
// Which menu item to show. // Which menu item to show.
NSMenuItem* item = nil; NSMenuItem* item = nil;
@ -66,7 +66,6 @@ void MenuMac::PopupOnUI(const base::WeakPtr<NativeWindow>& native_window,
// (-1, -1) means showing on mouse location. // (-1, -1) means showing on mouse location.
NSPoint position; NSPoint position;
if (x == -1 || y == -1) { if (x == -1 || y == -1) {
NSWindow* nswindow = native_window->GetNativeWindow();
position = [view convertPoint:[nswindow mouseLocationOutsideOfEventStream] position = [view convertPoint:[nswindow mouseLocationOutsideOfEventStream]
fromView:nil]; fromView:nil];
} else { } else {
@ -108,7 +107,23 @@ void MenuMac::PopupOnUI(const base::WeakPtr<NativeWindow>& native_window,
} }
void MenuMac::ClosePopupAt(int32_t window_id) { void MenuMac::ClosePopupAt(int32_t window_id) {
auto controller = popup_controllers_.find(window_id);
if (controller != popup_controllers_.end()) {
// Close the controller for the window.
[controller->second cancel];
} else if (window_id == -1) {
// Or just close all opened controllers.
for (auto it = popup_controllers_.begin();
it != popup_controllers_.end();) {
// The iterator is invalidated after the call.
[(it++)->second cancel];
}
}
}
void MenuMac::OnClosed(int32_t window_id, base::Closure callback) {
popup_controllers_.erase(window_id); popup_controllers_.erase(window_id);
callback.Run();
} }
// static // static

View file

@ -6,7 +6,8 @@
#include "atom/browser/native_window_views.h" #include "atom/browser/native_window_views.h"
#include "atom/browser/unresponsive_suppressor.h" #include "atom/browser/unresponsive_suppressor.h"
#include "content/public/browser/render_widget_host_view.h" #include "brightray/browser/inspectable_web_contents.h"
#include "brightray/browser/inspectable_web_contents_view.h"
#include "ui/display/screen.h" #include "ui/display/screen.h"
using views::MenuRunner; using views::MenuRunner;
@ -20,23 +21,20 @@ MenuViews::MenuViews(v8::Isolate* isolate, v8::Local<v8::Object> wrapper)
weak_factory_(this) { weak_factory_(this) {
} }
void MenuViews::PopupAt(Window* window, int x, int y, int positioning_item) { void MenuViews::PopupAt(BrowserWindow* window,
NativeWindow* native_window = static_cast<NativeWindow*>(window->window()); int x, int y, int positioning_item,
const base::Closure& callback) {
auto* native_window = static_cast<NativeWindowViews*>(window->window());
if (!native_window) if (!native_window)
return; return;
content::WebContents* web_contents = native_window->web_contents();
if (!web_contents)
return;
content::RenderWidgetHostView* view = web_contents->GetRenderWidgetHostView();
if (!view)
return;
// (-1, -1) means showing on mouse location. // (-1, -1) means showing on mouse location.
gfx::Point location; gfx::Point location;
if (x == -1 || y == -1) { if (x == -1 || y == -1) {
location = display::Screen::GetScreen()->GetCursorScreenPoint(); location = display::Screen::GetScreen()->GetCursorScreenPoint();
} else { } else {
gfx::Point origin = view->GetViewBounds().origin(); views::View* view = native_window; // the instance is also its content view
gfx::Point origin = view->bounds().origin();
location = gfx::Point(origin.x() + x, origin.y() + y); location = gfx::Point(origin.x() + x, origin.y() + y);
} }
@ -48,11 +46,11 @@ void MenuViews::PopupAt(Window* window, int x, int y, int positioning_item) {
// Show the menu. // Show the menu.
int32_t window_id = window->ID(); int32_t window_id = window->ID();
auto close_callback = base::Bind( auto close_callback = base::Bind(
&MenuViews::ClosePopupAt, weak_factory_.GetWeakPtr(), window_id); &MenuViews::OnClosed, weak_factory_.GetWeakPtr(), window_id, callback);
menu_runners_[window_id] = std::unique_ptr<MenuRunner>(new MenuRunner( menu_runners_[window_id] = std::unique_ptr<MenuRunner>(new MenuRunner(
model(), flags, close_callback)); model(), flags, close_callback));
menu_runners_[window_id]->RunMenuAt( menu_runners_[window_id]->RunMenuAt(
static_cast<NativeWindowViews*>(window->window())->widget(), native_window->widget(),
NULL, NULL,
gfx::Rect(location, gfx::Size()), gfx::Rect(location, gfx::Size()),
views::MENU_ANCHOR_TOPLEFT, views::MENU_ANCHOR_TOPLEFT,
@ -60,7 +58,22 @@ void MenuViews::PopupAt(Window* window, int x, int y, int positioning_item) {
} }
void MenuViews::ClosePopupAt(int32_t window_id) { void MenuViews::ClosePopupAt(int32_t window_id) {
auto runner = menu_runners_.find(window_id);
if (runner != menu_runners_.end()) {
// Close the runner for the window.
runner->second->Cancel();
} else if (window_id == -1) {
// Or just close all opened runners.
for (auto it = menu_runners_.begin(); it != menu_runners_.end();) {
// The iterator is invalidated after the call.
(it++)->second->Cancel();
}
}
}
void MenuViews::OnClosed(int32_t window_id, base::Closure callback) {
menu_runners_.erase(window_id); menu_runners_.erase(window_id);
callback.Run();
} }
// static // static

View file

@ -21,10 +21,14 @@ class MenuViews : public Menu {
MenuViews(v8::Isolate* isolate, v8::Local<v8::Object> wrapper); MenuViews(v8::Isolate* isolate, v8::Local<v8::Object> wrapper);
protected: protected:
void PopupAt(Window* window, int x, int y, int positioning_item) override; void PopupAt(BrowserWindow* window,
int x, int y, int positioning_item,
const base::Closure& callback) override;
void ClosePopupAt(int32_t window_id) override; void ClosePopupAt(int32_t window_id) override;
private: private:
void OnClosed(int32_t window_id, base::Closure callback);
// window ID -> open context menu // window ID -> open context menu
std::map<int32_t, std::unique_ptr<views::MenuRunner>> menu_runners_; std::map<int32_t, std::unique_ptr<views::MenuRunner>> menu_runners_;

View file

@ -58,4 +58,4 @@ void Initialize(v8::Local<v8::Object> exports,
} // namespace } // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_net, Initialize) NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_net, Initialize)

View file

@ -70,6 +70,7 @@ Notification::Notification(v8::Isolate* isolate,
opts.Get("hasReply", &has_reply_); opts.Get("hasReply", &has_reply_);
opts.Get("actions", &actions_); opts.Get("actions", &actions_);
opts.Get("sound", &sound_); opts.Get("sound", &sound_);
opts.Get("closeButtonText", &close_button_text_);
} }
} }
@ -104,20 +105,24 @@ bool Notification::GetSilent() const {
return silent_; return silent_;
} }
bool Notification::GetHasReply() const {
return has_reply_;
}
base::string16 Notification::GetReplyPlaceholder() const { base::string16 Notification::GetReplyPlaceholder() const {
return reply_placeholder_; return reply_placeholder_;
} }
bool Notification::GetHasReply() const { base::string16 Notification::GetSound() const {
return has_reply_; return sound_;
} }
std::vector<brightray::NotificationAction> Notification::GetActions() const { std::vector<brightray::NotificationAction> Notification::GetActions() const {
return actions_; return actions_;
} }
base::string16 Notification::GetSound() const { base::string16 Notification::GetCloseButtonText() const {
return sound_; return close_button_text_;
} }
// Setters // Setters
@ -137,12 +142,16 @@ void Notification::SetSilent(bool new_silent) {
silent_ = new_silent; silent_ = new_silent;
} }
void Notification::SetHasReply(bool new_has_reply) {
has_reply_ = new_has_reply;
}
void Notification::SetReplyPlaceholder(const base::string16& new_placeholder) { void Notification::SetReplyPlaceholder(const base::string16& new_placeholder) {
reply_placeholder_ = new_placeholder; reply_placeholder_ = new_placeholder;
} }
void Notification::SetHasReply(bool new_has_reply) { void Notification::SetSound(const base::string16& new_sound) {
has_reply_ = new_has_reply; sound_ = new_sound;
} }
void Notification::SetActions( void Notification::SetActions(
@ -150,8 +159,8 @@ void Notification::SetActions(
actions_ = actions; actions_ = actions;
} }
void Notification::SetSound(const base::string16& new_sound) { void Notification::SetCloseButtonText(const base::string16& text) {
sound_ = new_sound; close_button_text_ = text;
} }
void Notification::NotificationAction(int index) { void Notification::NotificationAction(int index) {
@ -201,6 +210,7 @@ void Notification::Show() {
options.reply_placeholder = reply_placeholder_; options.reply_placeholder = reply_placeholder_;
options.actions = actions_; options.actions = actions_;
options.sound = sound_; options.sound = sound_;
options.close_button_text = close_button_text_;
notification_->Show(options); notification_->Show(options);
} }
} }
@ -222,15 +232,18 @@ void Notification::BuildPrototype(v8::Isolate* isolate,
.SetProperty("subtitle", &Notification::GetSubtitle, .SetProperty("subtitle", &Notification::GetSubtitle,
&Notification::SetSubtitle) &Notification::SetSubtitle)
.SetProperty("body", &Notification::GetBody, &Notification::SetBody) .SetProperty("body", &Notification::GetBody, &Notification::SetBody)
.SetProperty("silent", &Notification::GetSilent, &Notification::SetSilent) .SetProperty("silent", &Notification::GetSilent,
.SetProperty("replyPlaceholder", &Notification::GetReplyPlaceholder, &Notification::SetSilent)
&Notification::SetReplyPlaceholder)
.SetProperty("hasReply", &Notification::GetHasReply, .SetProperty("hasReply", &Notification::GetHasReply,
&Notification::SetHasReply) &Notification::SetHasReply)
.SetProperty("replyPlaceholder", &Notification::GetReplyPlaceholder,
&Notification::SetReplyPlaceholder)
.SetProperty("sound", &Notification::GetSound,
&Notification::SetSound)
.SetProperty("actions", &Notification::GetActions, .SetProperty("actions", &Notification::GetActions,
&Notification::SetActions) &Notification::SetActions)
.SetProperty("sound", &Notification::GetSound, .SetProperty("closeButtonText", &Notification::GetCloseButtonText,
&Notification::SetSound); &Notification::SetCloseButtonText);
} }
} // namespace api } // namespace api
@ -257,4 +270,4 @@ void Initialize(v8::Local<v8::Object> exports,
} // namespace } // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_common_notification, Initialize) NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_common_notification, Initialize)

View file

@ -52,20 +52,22 @@ class Notification : public mate::TrackableObject<Notification>,
base::string16 GetSubtitle() const; base::string16 GetSubtitle() const;
base::string16 GetBody() const; base::string16 GetBody() const;
bool GetSilent() const; bool GetSilent() const;
base::string16 GetReplyPlaceholder() const;
bool GetHasReply() const; bool GetHasReply() const;
std::vector<brightray::NotificationAction> GetActions() const; base::string16 GetReplyPlaceholder() const;
base::string16 GetSound() const; base::string16 GetSound() const;
std::vector<brightray::NotificationAction> GetActions() const;
base::string16 GetCloseButtonText() const;
// Prop Setters // Prop Setters
void SetTitle(const base::string16& new_title); void SetTitle(const base::string16& new_title);
void SetSubtitle(const base::string16& new_subtitle); void SetSubtitle(const base::string16& new_subtitle);
void SetBody(const base::string16& new_body); void SetBody(const base::string16& new_body);
void SetSilent(bool new_silent); void SetSilent(bool new_silent);
void SetReplyPlaceholder(const base::string16& new_reply_placeholder);
void SetHasReply(bool new_has_reply); void SetHasReply(bool new_has_reply);
void SetActions(const std::vector<brightray::NotificationAction>& actions); void SetReplyPlaceholder(const base::string16& new_reply_placeholder);
void SetSound(const base::string16& sound); void SetSound(const base::string16& sound);
void SetActions(const std::vector<brightray::NotificationAction>& actions);
void SetCloseButtonText(const base::string16& text);
private: private:
base::string16 title_; base::string16 title_;
@ -75,10 +77,11 @@ class Notification : public mate::TrackableObject<Notification>,
base::string16 icon_path_; base::string16 icon_path_;
bool has_icon_ = false; bool has_icon_ = false;
bool silent_ = false; bool silent_ = false;
base::string16 reply_placeholder_;
bool has_reply_ = false; bool has_reply_ = false;
std::vector<brightray::NotificationAction> actions_; base::string16 reply_placeholder_;
base::string16 sound_; base::string16 sound_;
std::vector<brightray::NotificationAction> actions_;
base::string16 close_button_text_;
brightray::NotificationPresenter* presenter_; brightray::NotificationPresenter* presenter_;

View file

@ -16,6 +16,13 @@ namespace atom {
namespace api { namespace api {
PowerMonitor::PowerMonitor(v8::Isolate* isolate) { PowerMonitor::PowerMonitor(v8::Isolate* isolate) {
#if defined(OS_LINUX)
SetShutdownHandler(base::Bind(&PowerMonitor::ShouldShutdown,
base::Unretained(this)));
#elif defined(OS_MACOSX)
Browser::Get()->SetShutdownHandler(base::Bind(&PowerMonitor::ShouldShutdown,
base::Unretained(this)));
#endif
base::PowerMonitor::Get()->AddObserver(this); base::PowerMonitor::Get()->AddObserver(this);
Init(isolate); Init(isolate);
} }
@ -24,6 +31,20 @@ PowerMonitor::~PowerMonitor() {
base::PowerMonitor::Get()->RemoveObserver(this); base::PowerMonitor::Get()->RemoveObserver(this);
} }
bool PowerMonitor::ShouldShutdown() {
return !Emit("shutdown");
}
#if defined(OS_LINUX)
void PowerMonitor::BlockShutdown() {
PowerObserverLinux::BlockShutdown();
}
void PowerMonitor::UnblockShutdown() {
PowerObserverLinux::UnblockShutdown();
}
#endif
void PowerMonitor::OnPowerStateChange(bool on_battery_power) { void PowerMonitor::OnPowerStateChange(bool on_battery_power) {
if (on_battery_power) if (on_battery_power)
Emit("on-battery"); Emit("on-battery");
@ -55,6 +76,11 @@ v8::Local<v8::Value> PowerMonitor::Create(v8::Isolate* isolate) {
void PowerMonitor::BuildPrototype( void PowerMonitor::BuildPrototype(
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) { v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(mate::StringToV8(isolate, "PowerMonitor")); prototype->SetClassName(mate::StringToV8(isolate, "PowerMonitor"));
#if defined(OS_LINUX)
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("blockShutdown", &PowerMonitor::BlockShutdown)
.SetMethod("unblockShutdown", &PowerMonitor::UnblockShutdown);
#endif
} }
} // namespace api } // namespace api
@ -68,10 +94,6 @@ using atom::api::PowerMonitor;
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused, void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) { v8::Local<v8::Context> context, void* priv) {
#if defined(OS_MACOSX)
base::PowerMonitorDeviceSource::AllocateSystemIOPorts();
#endif
v8::Isolate* isolate = context->GetIsolate(); v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary dict(isolate, exports); mate::Dictionary dict(isolate, exports);
dict.Set("powerMonitor", PowerMonitor::Create(isolate)); dict.Set("powerMonitor", PowerMonitor::Create(isolate));
@ -81,4 +103,4 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
} // namespace } // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_power_monitor, Initialize) NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_power_monitor, Initialize)

View file

@ -6,8 +6,8 @@
#define ATOM_BROWSER_API_ATOM_API_POWER_MONITOR_H_ #define ATOM_BROWSER_API_ATOM_API_POWER_MONITOR_H_
#include "atom/browser/api/trackable_object.h" #include "atom/browser/api/trackable_object.h"
#include "atom/browser/lib/power_observer.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/power_monitor/power_observer.h"
#include "native_mate/handle.h" #include "native_mate/handle.h"
namespace atom { namespace atom {
@ -15,7 +15,7 @@ namespace atom {
namespace api { namespace api {
class PowerMonitor : public mate::TrackableObject<PowerMonitor>, class PowerMonitor : public mate::TrackableObject<PowerMonitor>,
public base::PowerObserver { public PowerObserver {
public: public:
static v8::Local<v8::Value> Create(v8::Isolate* isolate); static v8::Local<v8::Value> Create(v8::Isolate* isolate);
@ -26,6 +26,15 @@ class PowerMonitor : public mate::TrackableObject<PowerMonitor>,
explicit PowerMonitor(v8::Isolate* isolate); explicit PowerMonitor(v8::Isolate* isolate);
~PowerMonitor() override; ~PowerMonitor() override;
// Called by native calles.
bool ShouldShutdown();
#if defined(OS_LINUX)
// Private JS APIs.
void BlockShutdown();
void UnblockShutdown();
#endif
// 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;

View file

@ -133,4 +133,4 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
} // namespace } // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_power_save_blocker, Initialize); NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_power_save_blocker, Initialize);

View file

@ -253,4 +253,4 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
} // namespace } // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_protocol, Initialize) NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_protocol, Initialize)

View file

@ -78,10 +78,6 @@ class Protocol : public mate::TrackableObject<Protocol> {
net::URLRequestJob* MaybeCreateJob( net::URLRequestJob* MaybeCreateJob(
net::URLRequest* request, net::URLRequest* request,
net::NetworkDelegate* network_delegate) const override { net::NetworkDelegate* network_delegate) const override {
if (!request->initiator().has_value()) {
// Don't intercept this request as it was created by `net.request`.
return nullptr;
}
RequestJob* request_job = new RequestJob(request, network_delegate); RequestJob* request_job = new RequestJob(request, network_delegate);
request_job->SetHandlerInfo(isolate_, request_context_.get(), handler_); request_job->SetHandlerInfo(isolate_, request_context_.get(), handler_);
return request_job; return request_job;

View file

@ -86,5 +86,5 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
} // namespace } // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_render_process_preferences, NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_render_process_preferences,
Initialize) Initialize)

View file

@ -144,4 +144,4 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
} // namespace } // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_common_screen, Initialize) NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_common_screen, Initialize)

View file

@ -9,6 +9,7 @@ namespace atom {
namespace api { namespace api {
//TODO(codebytere): deprecated; remove in 3.0
int Screen::getMenuBarHeight() { int Screen::getMenuBarHeight() {
return [[NSApp mainMenu] menuBarHeight]; return [[NSApp mainMenu] menuBarHeight];
} }

View file

@ -17,6 +17,7 @@
#include "atom/browser/atom_permission_manager.h" #include "atom/browser/atom_permission_manager.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/session_preferences.h"
#include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/callback.h"
#include "atom/common/native_mate_converters/content_converter.h" #include "atom/common/native_mate_converters/content_converter.h"
#include "atom/common/native_mate_converters/file_path_converter.h" #include "atom/common/native_mate_converters/file_path_converter.h"
@ -32,6 +33,7 @@
#include "brightray/browser/media/media_device_id_salt.h" #include "brightray/browser/media/media_device_id_salt.h"
#include "brightray/browser/net/devtools_network_conditions.h" #include "brightray/browser/net/devtools_network_conditions.h"
#include "brightray/browser/net/devtools_network_controller_handle.h" #include "brightray/browser/net/devtools_network_controller_handle.h"
#include "chrome/browser/browser_process.h"
#include "chrome/common/pref_names.h" #include "chrome/common/pref_names.h"
#include "components/prefs/pref_service.h" #include "components/prefs/pref_service.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
@ -438,6 +440,18 @@ void DownloadIdCallback(content::DownloadManager* download_manager,
std::vector<content::DownloadItem::ReceivedSlice>()); std::vector<content::DownloadItem::ReceivedSlice>());
} }
void SetDevToolsNetworkEmulationClientIdInIO(
brightray::URLRequestContextGetter* url_request_context_getter,
const std::string& client_id) {
if (!url_request_context_getter)
return;
net::URLRequestContext* context =
url_request_context_getter->GetURLRequestContext();
AtomNetworkDelegate* network_delegate =
static_cast<AtomNetworkDelegate*>(context->network_delegate());
network_delegate->SetDevToolsNetworkEmulationClientId(client_id);
}
} // namespace } // namespace
Session::Session(v8::Isolate* isolate, AtomBrowserContext* browser_context) Session::Session(v8::Isolate* isolate, AtomBrowserContext* browser_context)
@ -447,6 +461,8 @@ Session::Session(v8::Isolate* isolate, AtomBrowserContext* browser_context)
content::BrowserContext::GetDownloadManager(browser_context)-> content::BrowserContext::GetDownloadManager(browser_context)->
AddObserver(this); AddObserver(this);
new SessionPreferences(browser_context);
Init(isolate); Init(isolate);
AttachAsUserData(browser_context); AttachAsUserData(browser_context);
} }
@ -545,16 +561,24 @@ void Session::EnableNetworkEmulation(const mate::Dictionary& options) {
browser_context_->network_controller_handle()->SetNetworkState( browser_context_->network_controller_handle()->SetNetworkState(
devtools_network_emulation_client_id_, std::move(conditions)); devtools_network_emulation_client_id_, std::move(conditions));
browser_context_->network_delegate()->SetDevToolsNetworkEmulationClientId( BrowserThread::PostTask(
devtools_network_emulation_client_id_); BrowserThread::IO, FROM_HERE,
base::Bind(
&SetDevToolsNetworkEmulationClientIdInIO,
base::RetainedRef(browser_context_->url_request_context_getter()),
devtools_network_emulation_client_id_));
} }
void Session::DisableNetworkEmulation() { void Session::DisableNetworkEmulation() {
std::unique_ptr<brightray::DevToolsNetworkConditions> conditions; std::unique_ptr<brightray::DevToolsNetworkConditions> conditions;
browser_context_->network_controller_handle()->SetNetworkState( browser_context_->network_controller_handle()->SetNetworkState(
devtools_network_emulation_client_id_, std::move(conditions)); devtools_network_emulation_client_id_, std::move(conditions));
browser_context_->network_delegate()->SetDevToolsNetworkEmulationClientId( BrowserThread::PostTask(
std::string()); BrowserThread::IO, FROM_HERE,
base::Bind(
&SetDevToolsNetworkEmulationClientIdInIO,
base::RetainedRef(browser_context_->url_request_context_getter()),
std::string()));
} }
void Session::SetCertVerifyProc(v8::Local<v8::Value> val, void Session::SetCertVerifyProc(v8::Local<v8::Value> val,
@ -620,7 +644,7 @@ void Session::SetUserAgent(const std::string& user_agent,
mate::Arguments* args) { mate::Arguments* args) {
browser_context_->SetUserAgent(user_agent); browser_context_->SetUserAgent(user_agent);
std::string accept_lang = l10n_util::GetApplicationLocale(""); std::string accept_lang = g_browser_process->GetApplicationLocale();
args->GetNext(&accept_lang); args->GetNext(&accept_lang);
scoped_refptr<brightray::URLRequestContextGetter> getter( scoped_refptr<brightray::URLRequestContextGetter> getter(
@ -680,6 +704,19 @@ void Session::CreateInterruptedDownload(const mate::Dictionary& options) {
length, last_modified, etag, base::Time::FromDoubleT(start_time))); length, last_modified, etag, base::Time::FromDoubleT(start_time)));
} }
void Session::SetPreloads(
const std::vector<base::FilePath::StringType>& preloads) {
auto* prefs = SessionPreferences::FromBrowserContext(browser_context());
DCHECK(prefs);
prefs->set_preloads(preloads);
}
std::vector<base::FilePath::StringType> Session::GetPreloads() const {
auto* prefs = SessionPreferences::FromBrowserContext(browser_context());
DCHECK(prefs);
return prefs->preloads();
}
v8::Local<v8::Value> Session::Cookies(v8::Isolate* isolate) { v8::Local<v8::Value> Session::Cookies(v8::Isolate* isolate) {
if (cookies_.IsEmpty()) { if (cookies_.IsEmpty()) {
auto handle = Cookies::Create(isolate, browser_context()); auto handle = Cookies::Create(isolate, browser_context());
@ -766,6 +803,8 @@ void Session::BuildPrototype(v8::Isolate* isolate,
.SetMethod("getBlobData", &Session::GetBlobData) .SetMethod("getBlobData", &Session::GetBlobData)
.SetMethod("createInterruptedDownload", .SetMethod("createInterruptedDownload",
&Session::CreateInterruptedDownload) &Session::CreateInterruptedDownload)
.SetMethod("setPreloads", &Session::SetPreloads)
.SetMethod("getPreloads", &Session::GetPreloads)
.SetProperty("cookies", &Session::Cookies) .SetProperty("cookies", &Session::Cookies)
.SetProperty("protocol", &Session::Protocol) .SetProperty("protocol", &Session::Protocol)
.SetProperty("webRequest", &Session::WebRequest); .SetProperty("webRequest", &Session::WebRequest);
@ -801,4 +840,4 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
} // namespace } // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_session, Initialize) NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_session, Initialize)

View file

@ -6,6 +6,7 @@
#define ATOM_BROWSER_API_ATOM_API_SESSION_H_ #define ATOM_BROWSER_API_ATOM_API_SESSION_H_
#include <string> #include <string>
#include <vector>
#include "atom/browser/api/trackable_object.h" #include "atom/browser/api/trackable_object.h"
#include "atom/browser/atom_blob_reader.h" #include "atom/browser/atom_blob_reader.h"
@ -81,6 +82,8 @@ class Session: public mate::TrackableObject<Session>,
void GetBlobData(const std::string& uuid, void GetBlobData(const std::string& uuid,
const AtomBlobReader::CompletionCallback& callback); const AtomBlobReader::CompletionCallback& callback);
void CreateInterruptedDownload(const mate::Dictionary& options); void CreateInterruptedDownload(const mate::Dictionary& options);
void SetPreloads(const std::vector<base::FilePath::StringType>& preloads);
std::vector<base::FilePath::StringType> GetPreloads() const;
v8::Local<v8::Value> Cookies(v8::Isolate* isolate); v8::Local<v8::Value> Cookies(v8::Isolate* isolate);
v8::Local<v8::Value> Protocol(v8::Isolate* isolate); v8::Local<v8::Value> Protocol(v8::Isolate* isolate);
v8::Local<v8::Value> WebRequest(v8::Isolate* isolate); v8::Local<v8::Value> WebRequest(v8::Isolate* isolate);

View file

@ -65,6 +65,7 @@ void SystemPreferences::BuildPrototype(
&SystemPreferences::SubscribeLocalNotification) &SystemPreferences::SubscribeLocalNotification)
.SetMethod("unsubscribeLocalNotification", .SetMethod("unsubscribeLocalNotification",
&SystemPreferences::UnsubscribeLocalNotification) &SystemPreferences::UnsubscribeLocalNotification)
.SetMethod("registerDefaults", &SystemPreferences::RegisterDefaults)
.SetMethod("getUserDefault", &SystemPreferences::GetUserDefault) .SetMethod("getUserDefault", &SystemPreferences::GetUserDefault)
.SetMethod("setUserDefault", &SystemPreferences::SetUserDefault) .SetMethod("setUserDefault", &SystemPreferences::SetUserDefault)
.SetMethod("removeUserDefault", &SystemPreferences::RemoveUserDefault) .SetMethod("removeUserDefault", &SystemPreferences::RemoveUserDefault)
@ -95,4 +96,4 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
} // namespace } // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_system_preferences, Initialize); NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_system_preferences, Initialize);

View file

@ -73,6 +73,7 @@ class SystemPreferences : public mate::EventEmitter<SystemPreferences>
void UnsubscribeLocalNotification(int request_id); void UnsubscribeLocalNotification(int request_id);
v8::Local<v8::Value> GetUserDefault(const std::string& name, v8::Local<v8::Value> GetUserDefault(const std::string& name,
const std::string& type); const std::string& type);
void RegisterDefaults(mate::Arguments* args);
void SetUserDefault(const std::string& name, void SetUserDefault(const std::string& name,
const std::string& type, const std::string& type,
mate::Arguments* args); mate::Arguments* args);

View file

@ -144,6 +144,28 @@ v8::Local<v8::Value> SystemPreferences::GetUserDefault(
} }
} }
void SystemPreferences::RegisterDefaults(mate::Arguments* args) {
base::DictionaryValue value;
if(!args->GetNext(&value)) {
args->ThrowError("Invalid userDefault data provided");
} else {
@try {
NSDictionary* dict = DictionaryValueToNSDictionary(value);
for (id key in dict) {
id value = [dict objectForKey:key];
if ([value isKindOfClass:[NSNull class]] || value == nil) {
args->ThrowError("Invalid userDefault data provided");
return;
}
}
[[NSUserDefaults standardUserDefaults] registerDefaults:dict];
} @catch (NSException* exception) {
args->ThrowError("Invalid userDefault data provided");
}
}
}
void SystemPreferences::SetUserDefault(const std::string& name, void SystemPreferences::SetUserDefault(const std::string& name,
const std::string& type, const std::string& type,
mate::Arguments* args) { mate::Arguments* args) {

View file

@ -2,6 +2,8 @@
// Use of this source code is governed by the MIT license that can be // Use of this source code is governed by the MIT license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include <iomanip>
#include "atom/browser/api/atom_api_system_preferences.h" #include "atom/browser/api/atom_api_system_preferences.h"
#include "atom/common/color_util.h" #include "atom/common/color_util.h"
@ -26,10 +28,10 @@ bool SystemPreferences::IsAeroGlassEnabled() {
} }
std::string hexColorDWORDToRGBA(DWORD color) { std::string hexColorDWORDToRGBA(DWORD color) {
DWORD rgba = color << 8 | color >> 24;
std::ostringstream stream; std::ostringstream stream;
stream << std::hex << color; stream << std::hex << std::setw(8) << std::setfill('0') << rgba;
std::string hexColor = stream.str(); return stream.str();
return hexColor.substr(2) + hexColor.substr(0, 2);
} }
std::string SystemPreferences::GetAccentColor() { std::string SystemPreferences::GetAccentColor() {

View file

@ -40,8 +40,6 @@ struct Converter<atom::TrayIcon::HighlightMode> {
} }
} }
// Support old boolean parameter
// TODO(kevinsawicki): Remove in 2.0, deprecate before then with warnings
bool highlight; bool highlight;
if (ConvertFromV8(isolate, val, &highlight)) { if (ConvertFromV8(isolate, val, &highlight)) {
if (highlight) if (highlight)
@ -252,4 +250,4 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
} // namespace } // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_tray, Initialize) NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_tray, Initialize)

View file

@ -7,9 +7,9 @@
#include <set> #include <set>
#include <string> #include <string>
#include "atom/browser/api/atom_api_browser_window.h"
#include "atom/browser/api/atom_api_debugger.h" #include "atom/browser/api/atom_api_debugger.h"
#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/atom_browser_client.h" #include "atom/browser/atom_browser_client.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"
@ -89,6 +89,11 @@
#include "ui/aura/window.h" #include "ui/aura/window.h"
#endif #endif
#if defined(OS_LINUX) || defined(OS_WIN)
#include "content/public/common/renderer_preferences.h"
#include "ui/gfx/font_render_params.h"
#endif
#include "atom/common/node_includes.h" #include "atom/common/node_includes.h"
namespace { namespace {
@ -340,7 +345,7 @@ WebContents::WebContents(v8::Isolate* isolate, const mate::Dictionary& options)
// Obtain the session. // Obtain the session.
std::string partition; std::string partition;
mate::Handle<api::Session> session; mate::Handle<api::Session> session;
if (options.Get("session", &session)) { if (options.Get("session", &session) && !session.IsEmpty()) {
} else if (options.Get("partition", &partition)) { } else if (options.Get("partition", &partition)) {
session = Session::FromPartition(isolate, partition); session = Session::FromPartition(isolate, partition);
} else { } else {
@ -378,8 +383,8 @@ WebContents::WebContents(v8::Isolate* isolate, const mate::Dictionary& options)
options.Get("transparent", &transparent); options.Get("transparent", &transparent);
content::WebContents::CreateParams params(session->browser_context()); content::WebContents::CreateParams params(session->browser_context());
auto* view = new OffScreenWebContentsView( auto* view = new OffScreenWebContentsView(transparent,
transparent, base::Bind(&WebContents::OnPaint, base::Unretained(this))); base::Bind(&WebContents::OnPaint, base::Unretained(this)));
params.view = view; params.view = view;
params.delegate_view = view; params.delegate_view = view;
@ -412,6 +417,19 @@ void WebContents::InitWithSessionAndOptions(v8::Isolate* isolate,
managed_web_contents()->GetView()->SetDelegate(this); managed_web_contents()->GetView()->SetDelegate(this);
#if defined(OS_LINUX) || defined(OS_WIN)
// Update font settings.
auto* prefs = web_contents->GetMutableRendererPrefs();
CR_DEFINE_STATIC_LOCAL(const gfx::FontRenderParams, params,
(gfx::GetFontRenderParams(gfx::FontRenderParamsQuery(), nullptr)));
prefs->should_antialias_text = params.antialiasing;
prefs->use_subpixel_positioning = params.subpixel_positioning;
prefs->hinting = params.hinting;
prefs->use_autohinter = params.autohinter;
prefs->use_bitmaps = params.use_bitmaps;
prefs->subpixel_rendering = params.subpixel_rendering;
#endif
// Save the preferences in C++. // Save the preferences in C++.
new WebContentsPreferences(web_contents, options); new WebContentsPreferences(web_contents, options);
@ -446,6 +464,8 @@ void WebContents::InitWithSessionAndOptions(v8::Isolate* isolate,
WebContents::~WebContents() { WebContents::~WebContents() {
// The destroy() is called. // The destroy() is called.
if (managed_web_contents()) { if (managed_web_contents()) {
managed_web_contents()->GetView()->SetDelegate(nullptr);
// For webview we need to tell content module to do some cleanup work before // For webview we need to tell content module to do some cleanup work before
// destroying it. // destroying it.
if (type_ == WEB_VIEW) if (type_ == WEB_VIEW)
@ -457,7 +477,8 @@ WebContents::~WebContents() {
DestroyWebContents(false /* async */); DestroyWebContents(false /* async */);
} else { } else {
if (type_ == BROWSER_WINDOW && owner_window()) { if (type_ == BROWSER_WINDOW && owner_window()) {
owner_window()->CloseContents(nullptr); for (ExtendedWebContentsObserver& observer : observers_)
observer.OnCloseContents();
} else { } else {
DestroyWebContents(true /* async */); DestroyWebContents(true /* async */);
} }
@ -481,12 +502,7 @@ bool WebContents::DidAddMessageToConsole(content::WebContents* source,
const base::string16& message, const base::string16& message,
int32_t line_no, int32_t line_no,
const base::string16& source_id) { const base::string16& source_id) {
if (type_ == OFF_SCREEN) { return Emit("console-message", level, message, line_no, source_id);
return false;
} else {
Emit("console-message", level, message, line_no, source_id);
return true;
}
} }
void WebContents::OnCreateWindow( void WebContents::OnCreateWindow(
@ -570,9 +586,10 @@ void WebContents::MoveContents(content::WebContents* source,
void WebContents::CloseContents(content::WebContents* source) { void WebContents::CloseContents(content::WebContents* source) {
Emit("close"); Emit("close");
if (managed_web_contents())
if ((type_ == BROWSER_WINDOW || type_ == OFF_SCREEN) && owner_window()) managed_web_contents()->GetView()->SetDelegate(nullptr);
owner_window()->CloseContents(source); for (ExtendedWebContentsObserver& observer : observers_)
observer.OnCloseContents();
} }
void WebContents::ActivateContents(content::WebContents* source) { void WebContents::ActivateContents(content::WebContents* source) {
@ -641,20 +658,20 @@ void WebContents::RendererUnresponsive(
content::WebContents* source, content::WebContents* source,
const content::WebContentsUnresponsiveState& unresponsive_state) { const content::WebContentsUnresponsiveState& unresponsive_state) {
Emit("unresponsive"); Emit("unresponsive");
if ((type_ == BROWSER_WINDOW || type_ == OFF_SCREEN) && owner_window())
owner_window()->RendererUnresponsive(source);
} }
void WebContents::RendererResponsive(content::WebContents* source) { void WebContents::RendererResponsive(content::WebContents* source) {
Emit("responsive"); Emit("responsive");
if ((type_ == BROWSER_WINDOW || type_ == OFF_SCREEN) && owner_window()) for (ExtendedWebContentsObserver& observer : observers_)
owner_window()->RendererResponsive(source); observer.OnRendererResponsive();
} }
bool WebContents::HandleContextMenu(const content::ContextMenuParams& params) { bool WebContents::HandleContextMenu(const content::ContextMenuParams& params) {
if (params.custom_context.is_pepper_menu) { if (params.custom_context.is_pepper_menu) {
Emit("pepper-context-menu", std::make_pair(params, web_contents())); Emit("pepper-context-menu",
web_contents()->NotifyContextMenuClosed(params.custom_context); std::make_pair(params, web_contents()),
base::Bind(&content::WebContents::NotifyContextMenuClosed,
base::Unretained(web_contents()), params.custom_context));
} else { } else {
Emit("context-menu", std::make_pair(params, web_contents())); Emit("context-menu", std::make_pair(params, web_contents()));
} }
@ -794,8 +811,7 @@ void WebContents::DidFinishLoad(content::RenderFrameHost* render_frame_host,
void WebContents::DidFailLoad(content::RenderFrameHost* render_frame_host, void WebContents::DidFailLoad(content::RenderFrameHost* render_frame_host,
const GURL& 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 is_main_frame = !render_frame_host->GetParent(); bool is_main_frame = !render_frame_host->GetParent();
Emit("did-fail-load", error_code, error_description, url, is_main_frame); Emit("did-fail-load", error_code, error_description, url, is_main_frame);
} }
@ -895,10 +911,11 @@ void WebContents::DevToolsOpened() {
managed_web_contents()->CallClientFunction( managed_web_contents()->CallClientFunction(
"DevToolsAPI.setInspectedTabId", &tab_id, nullptr, nullptr); "DevToolsAPI.setInspectedTabId", &tab_id, nullptr, nullptr);
// Inherit owner window in devtools. // Inherit owner window in devtools when it doesn't have one.
if (owner_window()) auto* devtools = managed_web_contents()->GetDevToolsWebContents();
handle->SetOwnerWindow(managed_web_contents()->GetDevToolsWebContents(), bool has_window = devtools->GetUserData(NativeWindowRelay::UserDataKey());
owner_window()); if (owner_window() && !has_window)
handle->SetOwnerWindow(devtools, owner_window());
Emit("devtools-opened"); Emit("devtools-opened");
} }
@ -965,7 +982,7 @@ bool WebContents::OnMessageReceived(const IPC::Message& message,
// For webview only #1 will happen, for BrowserWindow both #1 and #3 may // For webview only #1 will happen, for BrowserWindow both #1 and #3 may
// happen. The #2 should never happen for webContents, because webview is // happen. The #2 should never happen for webContents, because webview is
// managed by GuestViewManager, and BrowserWindow's webContents is managed // managed by GuestViewManager, and BrowserWindow's webContents is managed
// by api::Window. // by api::BrowserWindow.
// For #1, the destructor will do the cleanup work and we only need to make // For #1, the destructor will do the cleanup work and we only need to make
// sure "destroyed" event is emitted. For #3, the content::WebContents will // sure "destroyed" event is emitted. For #3, the content::WebContents will
// be destroyed on close, and WebContentsDestroyed would be called for it, so // be destroyed on close, and WebContentsDestroyed would be called for it, so
@ -1178,7 +1195,8 @@ void WebContents::OpenDevTools(mate::Arguments* args) {
std::string state; std::string state;
if (type_ == WEB_VIEW || !owner_window()) { if (type_ == WEB_VIEW || !owner_window()) {
state = "detach"; state = "detach";
} else if (args && args->Length() == 1) { }
if (args && args->Length() == 1) {
bool detach = false; bool detach = false;
mate::Dictionary options; mate::Dictionary options;
if (args->GetNext(&options)) { if (args->GetNext(&options)) {
@ -1337,6 +1355,7 @@ void WebContents::Print(mate::Arguments* args) {
std::vector<printing::PrinterBasicInfo> WebContents::GetPrinterList() { std::vector<printing::PrinterBasicInfo> WebContents::GetPrinterList() {
std::vector<printing::PrinterBasicInfo> printers; std::vector<printing::PrinterBasicInfo> printers;
auto print_backend = printing::PrintBackend::CreateInstance(nullptr); auto print_backend = printing::PrintBackend::CreateInstance(nullptr);
base::ThreadRestrictions::ScopedAllowIO allow_io;
print_backend->EnumeratePrinters(&printers); print_backend->EnumeratePrinters(&printers);
return printers; return printers;
} }
@ -1647,10 +1666,10 @@ void WebContents::StartPainting() {
return; return;
#if defined(ENABLE_OSR) #if defined(ENABLE_OSR)
auto* osr_rwhv = static_cast<OffScreenRenderWidgetHostView*>( const auto* wc_impl = static_cast<content::WebContentsImpl*>(web_contents());
web_contents()->GetRenderWidgetHostView()); auto* osr_wcv = static_cast<OffScreenWebContentsView*>(wc_impl->GetView());
if (osr_rwhv) if (osr_wcv)
osr_rwhv->SetPainting(true); osr_wcv->SetPainting(true);
#endif #endif
} }
@ -1659,10 +1678,10 @@ void WebContents::StopPainting() {
return; return;
#if defined(ENABLE_OSR) #if defined(ENABLE_OSR)
auto* osr_rwhv = static_cast<OffScreenRenderWidgetHostView*>( const auto* wc_impl = static_cast<content::WebContentsImpl*>(web_contents());
web_contents()->GetRenderWidgetHostView()); auto* osr_wcv = static_cast<OffScreenWebContentsView*>(wc_impl->GetView());
if (osr_rwhv) if (osr_wcv)
osr_rwhv->SetPainting(false); osr_wcv->SetPainting(false);
#endif #endif
} }
@ -1671,9 +1690,10 @@ bool WebContents::IsPainting() const {
return false; return false;
#if defined(ENABLE_OSR) #if defined(ENABLE_OSR)
const auto* osr_rwhv = static_cast<OffScreenRenderWidgetHostView*>( const auto* wc_impl = static_cast<content::WebContentsImpl*>(web_contents());
web_contents()->GetRenderWidgetHostView()); auto* osr_wcv = static_cast<OffScreenWebContentsView*>(wc_impl->GetView());
return osr_rwhv && osr_rwhv->IsPainting();
return osr_wcv && osr_wcv->IsPainting();
#else #else
return false; return false;
#endif #endif
@ -1684,10 +1704,11 @@ void WebContents::SetFrameRate(int frame_rate) {
return; return;
#if defined(ENABLE_OSR) #if defined(ENABLE_OSR)
auto* osr_rwhv = static_cast<OffScreenRenderWidgetHostView*>( const auto* wc_impl = static_cast<content::WebContentsImpl*>(web_contents());
web_contents()->GetRenderWidgetHostView()); auto* osr_wcv = static_cast<OffScreenWebContentsView*>(wc_impl->GetView());
if (osr_rwhv)
osr_rwhv->SetFrameRate(frame_rate); if (osr_wcv)
osr_wcv->SetFrameRate(frame_rate);
#endif #endif
} }
@ -1696,9 +1717,10 @@ int WebContents::GetFrameRate() const {
return 0; return 0;
#if defined(ENABLE_OSR) #if defined(ENABLE_OSR)
const auto* osr_rwhv = static_cast<OffScreenRenderWidgetHostView*>( const auto* wc_impl = static_cast<content::WebContentsImpl*>(web_contents());
web_contents()->GetRenderWidgetHostView()); auto* osr_wcv = static_cast<OffScreenWebContentsView*>(wc_impl->GetView());
return osr_rwhv ? osr_rwhv->GetFrameRate() : 0;
return osr_wcv ? osr_wcv->GetFrameRate() : 0;
#else #else
return 0; return 0;
#endif #endif
@ -1770,7 +1792,7 @@ v8::Local<v8::Value> WebContents::GetWebPreferences(v8::Isolate* isolate) {
v8::Local<v8::Value> WebContents::GetOwnerBrowserWindow() { v8::Local<v8::Value> WebContents::GetOwnerBrowserWindow() {
if (owner_window()) if (owner_window())
return Window::From(isolate(), owner_window()); return BrowserWindow::From(isolate(), owner_window());
else else
return v8::Null(isolate()); return v8::Null(isolate());
} }
@ -1808,6 +1830,11 @@ void WebContents::SetEmbedder(const WebContents* embedder) {
} }
} }
void WebContents::SetDevToolsWebContents(const WebContents* devtools) {
if (managed_web_contents())
managed_web_contents()->SetDevToolsWebContents(devtools->web_contents());
}
v8::Local<v8::Value> WebContents::GetNativeView() const { v8::Local<v8::Value> WebContents::GetNativeView() const {
gfx::NativeView ptr = web_contents()->GetNativeView(); gfx::NativeView ptr = web_contents()->GetNativeView();
auto buffer = node::Buffer::Copy( auto buffer = node::Buffer::Copy(
@ -1929,6 +1956,7 @@ void WebContents::BuildPrototype(v8::Isolate* isolate,
.SetMethod("copyImageAt", &WebContents::CopyImageAt) .SetMethod("copyImageAt", &WebContents::CopyImageAt)
.SetMethod("capturePage", &WebContents::CapturePage) .SetMethod("capturePage", &WebContents::CapturePage)
.SetMethod("setEmbedder", &WebContents::SetEmbedder) .SetMethod("setEmbedder", &WebContents::SetEmbedder)
.SetMethod("setDevToolsWebContents", &WebContents::SetDevToolsWebContents)
.SetMethod("getNativeView", &WebContents::GetNativeView) .SetMethod("getNativeView", &WebContents::GetNativeView)
.SetMethod("setWebRTCIPHandlingPolicy", .SetMethod("setWebRTCIPHandlingPolicy",
&WebContents::SetWebRTCIPHandlingPolicy) &WebContents::SetWebRTCIPHandlingPolicy)
@ -2006,4 +2034,4 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
} // namespace } // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_web_contents, Initialize) NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_web_contents, Initialize)

View file

@ -13,6 +13,7 @@
#include "atom/browser/api/trackable_object.h" #include "atom/browser/api/trackable_object.h"
#include "atom/browser/common_web_contents_delegate.h" #include "atom/browser/common_web_contents_delegate.h"
#include "atom/browser/ui/autofill_popup.h" #include "atom/browser/ui/autofill_popup.h"
#include "base/observer_list.h"
#include "content/common/cursors/webcursor.h" #include "content/common/cursors/webcursor.h"
#include "content/public/browser/keyboard_event_processing_result.h" #include "content/public/browser/keyboard_event_processing_result.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
@ -49,6 +50,15 @@ class WebViewGuestDelegate;
namespace api { namespace api {
// Certain events are only in WebContentsDelegate, provide our own Observer to
// dispatch those events.
class ExtendedWebContentsObserver {
public:
virtual void OnCloseContents() {}
virtual void OnRendererResponsive() {}
};
// Wrapper around the content::WebContents.
class WebContents : public mate::TrackableObject<WebContents>, class WebContents : public mate::TrackableObject<WebContents>,
public CommonWebContentsDelegate, public CommonWebContentsDelegate,
public content::WebContentsObserver { public content::WebContentsObserver {
@ -126,6 +136,7 @@ class WebContents : public mate::TrackableObject<WebContents>,
void Print(mate::Arguments* args); void Print(mate::Arguments* args);
std::vector<printing::PrinterBasicInfo> GetPrinterList(); std::vector<printing::PrinterBasicInfo> GetPrinterList();
void SetEmbedder(const WebContents* embedder); void SetEmbedder(const WebContents* embedder);
void SetDevToolsWebContents(const WebContents* devtools);
v8::Local<v8::Value> GetNativeView() const; v8::Local<v8::Value> GetNativeView() const;
// Print current page as PDF. // Print current page as PDF.
@ -230,6 +241,13 @@ class WebContents : public mate::TrackableObject<WebContents>,
WebContentsZoomController* GetZoomController() { return zoom_controller_; } WebContentsZoomController* GetZoomController() { return zoom_controller_; }
void AddObserver(ExtendedWebContentsObserver* obs) {
observers_.AddObserver(obs);
}
void RemoveObserver(ExtendedWebContentsObserver* obs) {
observers_.RemoveObserver(obs);
}
protected: protected:
WebContents(v8::Isolate* isolate, WebContents(v8::Isolate* isolate,
content::WebContents* web_contents, content::WebContents* web_contents,
@ -325,8 +343,7 @@ class WebContents : public mate::TrackableObject<WebContents>,
void DidFailLoad(content::RenderFrameHost* render_frame_host, void DidFailLoad(content::RenderFrameHost* render_frame_host,
const GURL& validated_url, const GURL& validated_url,
int error_code, int error_code,
const base::string16& error_description, const base::string16& error_description) override;
bool was_ignored_by_handler) override;
void DidStartLoading() override; void DidStartLoading() override;
void DidStopLoading() override; void DidStopLoading() override;
void DidGetResourceResponseStart( void DidGetResourceResponseStart(
@ -420,6 +437,9 @@ class WebContents : public mate::TrackableObject<WebContents>,
// Whether to enable devtools. // Whether to enable devtools.
bool enable_devtools_; bool enable_devtools_;
// Observers of this WebContents.
base::ObserverList<ExtendedWebContentsObserver> observers_;
DISALLOW_COPY_AND_ASSIGN(WebContents); DISALLOW_COPY_AND_ASSIGN(WebContents);
}; };

View file

@ -37,6 +37,26 @@ namespace atom {
namespace api { namespace api {
namespace {
template<typename Method, typename Event, typename Listener>
void CallNetworkDelegateMethod(
brightray::URLRequestContextGetter* url_request_context_getter,
Method method,
Event type,
URLPatterns patterns,
Listener listener) {
// Force creating network delegate.
net::URLRequestContext* context =
url_request_context_getter->GetURLRequestContext();
// Then call the method.
AtomNetworkDelegate* network_delegate =
static_cast<AtomNetworkDelegate*>(context->network_delegate());
(network_delegate->*method)(type, std::move(patterns), std::move(listener));
}
} // namespace
WebRequest::WebRequest(v8::Isolate* isolate, WebRequest::WebRequest(v8::Isolate* isolate,
AtomBrowserContext* browser_context) AtomBrowserContext* browser_context)
: browser_context_(browser_context) { : browser_context_(browser_context) {
@ -74,10 +94,15 @@ void WebRequest::SetListener(Method method, Event type, mate::Arguments* args) {
return; return;
} }
auto delegate = browser_context_->network_delegate(); brightray::URLRequestContextGetter* url_request_context_getter =
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, browser_context_->url_request_context_getter();
base::Bind(method, base::Unretained(delegate), type, if (!url_request_context_getter)
patterns, listener)); return;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&CallNetworkDelegateMethod<Method, Event, Listener>,
base::RetainedRef(url_request_context_getter),
method, type, std::move(patterns), std::move(listener)));
} }
// static // static

View file

@ -52,4 +52,4 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
} // namespace } // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_web_view_manager, Initialize) NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_web_view_manager, Initialize)

File diff suppressed because it is too large Load diff

View file

@ -42,8 +42,10 @@ class EventEmitter : public Wrappable<T> {
// Make the convinient methods visible: // Make the convinient methods visible:
// https://isocpp.org/wiki/faq/templates#nondependent-name-lookup-members // https://isocpp.org/wiki/faq/templates#nondependent-name-lookup-members
v8::Local<v8::Object> GetWrapper() { return Wrappable<T>::GetWrapper(); }
v8::Isolate* isolate() const { return Wrappable<T>::isolate(); } v8::Isolate* isolate() const { return Wrappable<T>::isolate(); }
v8::Local<v8::Object> GetWrapper() const {
return Wrappable<T>::GetWrapper();
}
// this.emit(name, event, args...); // this.emit(name, event, args...);
template<typename... Args> template<typename... Args>

View file

@ -73,6 +73,13 @@ class EventSubscriber : internal::EventSubscriberBase {
content::BrowserThread::UI, FROM_HERE, content::BrowserThread::UI, FROM_HERE,
base::Bind( base::Bind(
[](EventSubscriber<HandlerType>* subscriber) { [](EventSubscriber<HandlerType>* subscriber) {
{
// It is possible that this function will execute in the UI
// thread before the outer function has returned and destroyed
// its auto_lock. We need to acquire the lock before deleting
// or risk a crash.
base::AutoLock auto_lock(subscriber->handler_lock_);
}
delete subscriber; delete subscriber;
}, },
ptr)); ptr));

View file

@ -54,7 +54,6 @@ class GeoURLRequestContextGetter : public net::URLRequestContextGetter {
AtomAccessTokenStore::AtomAccessTokenStore() AtomAccessTokenStore::AtomAccessTokenStore()
: request_context_getter_(new internal::GeoURLRequestContextGetter) { : request_context_getter_(new internal::GeoURLRequestContextGetter) {
device::GeolocationProvider::GetInstance()->UserDidOptIntoLocationServices();
} }
AtomAccessTokenStore::~AtomAccessTokenStore() { AtomAccessTokenStore::~AtomAccessTokenStore() {

View file

@ -17,6 +17,7 @@
#include "atom/browser/atom_speech_recognition_manager_delegate.h" #include "atom/browser/atom_speech_recognition_manager_delegate.h"
#include "atom/browser/child_web_contents_tracker.h" #include "atom/browser/child_web_contents_tracker.h"
#include "atom/browser/native_window.h" #include "atom/browser/native_window.h"
#include "atom/browser/session_preferences.h"
#include "atom/browser/web_contents_permission_helper.h" #include "atom/browser/web_contents_permission_helper.h"
#include "atom/browser/web_contents_preferences.h" #include "atom/browser/web_contents_preferences.h"
#include "atom/browser/window_list.h" #include "atom/browser/window_list.h"
@ -32,11 +33,13 @@
#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"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h" #include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h" #include "content/public/browser/render_view_host.h"
#include "content/public/browser/resource_dispatcher_host.h" #include "content/public/browser/resource_dispatcher_host.h"
#include "content/public/browser/site_instance.h" #include "content/public/browser/site_instance.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "content/public/common/content_paths.h"
#include "content/public/common/content_switches.h" #include "content/public/common/content_switches.h"
#include "content/public/common/resource_request_body.h" #include "content/public/common/resource_request_body.h"
#include "content/public/common/url_constants.h" #include "content/public/common/url_constants.h"
@ -165,11 +168,14 @@ void AtomBrowserClient::RenderProcessWillLaunch(
content::WebContents* web_contents = GetWebContentsFromProcessID(process_id); content::WebContents* web_contents = GetWebContentsFromProcessID(process_id);
ProcessPreferences process_prefs; ProcessPreferences process_prefs;
process_prefs.sandbox = WebContentsPreferences::IsSandboxed(web_contents); process_prefs.sandbox =
process_prefs.native_window_open WebContentsPreferences::IsPreferenceEnabled("sandbox", web_contents);
= WebContentsPreferences::UsesNativeWindowOpen(web_contents); process_prefs.native_window_open =
process_prefs.disable_popups WebContentsPreferences::IsPreferenceEnabled("nativeWindowOpen",
= WebContentsPreferences::DisablePopups(web_contents); web_contents);
process_prefs.disable_popups =
WebContentsPreferences::IsPreferenceEnabled("disablePopups",
web_contents);
AddProcessPreferences(host->GetID(), process_prefs); AddProcessPreferences(host->GetID(), process_prefs);
// ensure the ProcessPreferences is removed later // ensure the ProcessPreferences is removed later
host->AddObserver(this); host->AddObserver(this);
@ -201,12 +207,8 @@ void AtomBrowserClient::OverrideWebkitPrefs(
WebContentsPreferences::OverrideWebkitPrefs(web_contents, prefs); WebContentsPreferences::OverrideWebkitPrefs(web_contents, prefs);
} }
std::string AtomBrowserClient::GetApplicationLocale() {
return l10n_util::GetApplicationLocale("");
}
void AtomBrowserClient::OverrideSiteInstanceForNavigation( void AtomBrowserClient::OverrideSiteInstanceForNavigation(
content::RenderFrameHost* render_frame_host, content::RenderFrameHost* rfh,
content::BrowserContext* browser_context, content::BrowserContext* browser_context,
content::SiteInstance* current_instance, content::SiteInstance* current_instance,
const GURL& url, const GURL& url,
@ -216,32 +218,67 @@ void AtomBrowserClient::OverrideSiteInstanceForNavigation(
return; return;
} }
if (!ShouldCreateNewSiteInstance(render_frame_host, browser_context, if (!ShouldCreateNewSiteInstance(rfh, browser_context, current_instance, url))
current_instance, url))
return; return;
scoped_refptr<content::SiteInstance> site_instance = bool is_new_instance = true;
content::SiteInstance::CreateForURL(browser_context, url); scoped_refptr<content::SiteInstance> site_instance;
// Do we have an affinity site to manage ?
std::string affinity;
auto* web_contents = content::WebContents::FromRenderFrameHost(rfh);
auto* web_preferences = web_contents ?
WebContentsPreferences::FromWebContents(web_contents) : nullptr;
if (web_preferences &&
web_preferences->web_preferences()->GetString("affinity", &affinity) &&
!affinity.empty()) {
affinity = base::ToLowerASCII(affinity);
auto iter = site_per_affinities.find(affinity);
if (iter != site_per_affinities.end()) {
site_instance = iter->second;
is_new_instance = false;
} else {
// We must not provide the url.
// This site is "isolated" and must not be taken into account
// when Chromium looking at a candidate for an url.
site_instance = content::SiteInstance::Create(
browser_context);
site_per_affinities[affinity] = site_instance.get();
}
} else {
site_instance = content::SiteInstance::CreateForURL(
browser_context,
url);
}
*new_instance = site_instance.get(); *new_instance = site_instance.get();
// Make sure the |site_instance| is not freed when this function returns. if (is_new_instance) {
// FIXME(zcbenz): We should adjust OverrideSiteInstanceForNavigation's // Make sure the |site_instance| is not freed
// interface to solve this. // when this function returns.
content::BrowserThread::PostTask( // FIXME(zcbenz): We should adjust
content::BrowserThread::UI, FROM_HERE, // OverrideSiteInstanceForNavigation's interface to solve this.
base::Bind(&Noop, base::RetainedRef(site_instance))); content::BrowserThread::PostTask(
content::BrowserThread::UI, FROM_HERE,
base::Bind(&Noop, base::RetainedRef(site_instance)));
// Remember the original web contents for the pending renderer process. // Remember the original web contents for the pending renderer process.
auto pending_process = (*new_instance)->GetProcess(); auto pending_process = site_instance->GetProcess();
pending_processes_[pending_process->GetID()] = pending_processes_[pending_process->GetID()] = web_contents;
content::WebContents::FromRenderFrameHost(render_frame_host);; }
// Clear the entry in map when process ends.
pending_process->AddObserver(this);
} }
void AtomBrowserClient::AppendExtraCommandLineSwitches( void AtomBrowserClient::AppendExtraCommandLineSwitches(
base::CommandLine* command_line, base::CommandLine* command_line,
int process_id) { int process_id) {
// Make sure we're about to launch a known executable
{
base::FilePath child_path;
PathService::Get(content::CHILD_PROCESS_EXE, &child_path);
base::ThreadRestrictions::ScopedAllowIO allow_io;
CHECK(base::MakeAbsoluteFilePath(command_line->GetProgram()) == child_path);
}
std::string process_type = std::string process_type =
command_line->GetSwitchValueASCII(::switches::kProcessType); command_line->GetSwitchValueASCII(::switches::kProcessType);
if (process_type != ::switches::kRendererProcess) if (process_type != ::switches::kRendererProcess)
@ -277,9 +314,12 @@ void AtomBrowserClient::AppendExtraCommandLineSwitches(
} }
content::WebContents* web_contents = GetWebContentsFromProcessID(process_id); content::WebContents* web_contents = GetWebContentsFromProcessID(process_id);
if (web_contents) if (web_contents) {
WebContentsPreferences::AppendExtraCommandLineSwitches( WebContentsPreferences::AppendExtraCommandLineSwitches(
web_contents, command_line); web_contents, command_line);
SessionPreferences::AppendExtraCommandLineSwitches(
web_contents->GetBrowserContext(), command_line);
}
} }
void AtomBrowserClient::DidCreatePpapiPlugin( void AtomBrowserClient::DidCreatePpapiPlugin(
@ -347,8 +387,7 @@ bool AtomBrowserClient::CanCreateWindow(
bool user_gesture, bool user_gesture,
bool opener_suppressed, bool opener_suppressed,
bool* no_javascript_access) { bool* no_javascript_access) {
// FIXME: Ensure the DCHECK doesn't fail and then re-enable DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
// DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
int opener_render_process_id = opener->GetProcess()->GetID(); int opener_render_process_id = opener->GetProcess()->GetID();
@ -369,15 +408,11 @@ bool AtomBrowserClient::CanCreateWindow(
} }
if (delegate_) { if (delegate_) {
content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, return delegate_->CanCreateWindow(
base::Bind(&api::App::OnCreateWindow, opener, opener_url, opener_top_level_frame_url, source_origin,
base::Unretained(static_cast<api::App*>(delegate_)), container_type, target_url, referrer, frame_name, disposition, features,
target_url, additional_features, body, user_gesture, opener_suppressed,
frame_name, no_javascript_access);
disposition,
additional_features,
body,
opener));
} }
return false; return false;
@ -393,6 +428,19 @@ void AtomBrowserClient::GetAdditionalAllowedSchemesForFileSystem(
additional_schemes->push_back(content::kChromeDevToolsScheme); additional_schemes->push_back(content::kChromeDevToolsScheme);
} }
void AtomBrowserClient::SiteInstanceDeleting(
content::SiteInstance* site_instance) {
// We are storing weak_ptr, is it fundamental to maintain the map up-to-date
// when an instance is destroyed.
for (auto iter = site_per_affinities.begin();
iter != site_per_affinities.end(); ++iter) {
if (iter->second == site_instance) {
site_per_affinities.erase(iter);
break;
}
}
}
brightray::BrowserMainParts* AtomBrowserClient::OverrideCreateBrowserMainParts( brightray::BrowserMainParts* AtomBrowserClient::OverrideCreateBrowserMainParts(
const content::MainFunctionParams&) { const content::MainFunctionParams&) {
v8::V8::Initialize(); // Init V8 before creating main parts. v8::V8::Initialize(); // Init V8 before creating main parts.

View file

@ -53,7 +53,6 @@ class AtomBrowserClient : public brightray::BrowserClient,
CreateSpeechRecognitionManagerDelegate() override; CreateSpeechRecognitionManagerDelegate() override;
void OverrideWebkitPrefs(content::RenderViewHost* render_view_host, void OverrideWebkitPrefs(content::RenderViewHost* render_view_host,
content::WebPreferences* prefs) override; content::WebPreferences* prefs) override;
std::string GetApplicationLocale() override;
void OverrideSiteInstanceForNavigation( void OverrideSiteInstanceForNavigation(
content::RenderFrameHost* render_frame_host, content::RenderFrameHost* render_frame_host,
content::BrowserContext* browser_context, content::BrowserContext* browser_context,
@ -99,6 +98,7 @@ class AtomBrowserClient : public brightray::BrowserClient,
bool* no_javascript_access) override; bool* no_javascript_access) override;
void GetAdditionalAllowedSchemesForFileSystem( void GetAdditionalAllowedSchemesForFileSystem(
std::vector<std::string>* schemes) override; std::vector<std::string>* schemes) override;
void SiteInstanceDeleting(content::SiteInstance* site_instance) override;
// brightray::BrowserClient: // brightray::BrowserClient:
brightray::BrowserMainParts* OverrideCreateBrowserMainParts( brightray::BrowserMainParts* OverrideCreateBrowserMainParts(
@ -120,9 +120,9 @@ class AtomBrowserClient : public brightray::BrowserClient,
content::SiteInstance* current_instance, content::SiteInstance* current_instance,
const GURL& dest_url); const GURL& dest_url);
struct ProcessPreferences { struct ProcessPreferences {
bool sandbox; bool sandbox = false;
bool native_window_open; bool native_window_open = false;
bool disable_popups; bool disable_popups = false;
}; };
void AddProcessPreferences(int process_id, ProcessPreferences prefs); void AddProcessPreferences(int process_id, ProcessPreferences prefs);
void RemoveProcessPreferences(int process_id); void RemoveProcessPreferences(int process_id);
@ -135,6 +135,10 @@ class AtomBrowserClient : public brightray::BrowserClient,
std::map<int, ProcessPreferences> process_preferences_; std::map<int, ProcessPreferences> process_preferences_;
std::map<int, base::ProcessId> render_process_host_pids_; std::map<int, base::ProcessId> render_process_host_pids_;
// list of site per affinity. weak_ptr to prevent instance locking
std::map<std::string, content::SiteInstance*> site_per_affinities;
base::Lock process_preferences_lock_; base::Lock process_preferences_lock_;
std::unique_ptr<AtomResourceDispatcherHostDelegate> std::unique_ptr<AtomResourceDispatcherHostDelegate>

View file

@ -15,6 +15,7 @@
#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_network_delegate.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/cookie_details.h"
#include "atom/browser/net/http_protocol_handler.h" #include "atom/browser/net/http_protocol_handler.h"
#include "atom/browser/web_view_manager.h" #include "atom/browser/web_view_manager.h"
#include "atom/common/atom_version.h" #include "atom/common/atom_version.h"
@ -70,9 +71,7 @@ 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,
const base::DictionaryValue& options) const base::DictionaryValue& options)
: brightray::BrowserContext(partition, in_memory), : brightray::BrowserContext(partition, in_memory) {
network_delegate_(new AtomNetworkDelegate),
cookie_delegate_(new AtomCookieDelegate) {
// Construct user agent string. // Construct user agent string.
Browser* browser = Browser::Get(); Browser* browser = Browser::Get();
std::string name = RemoveWhitespace(browser->GetName()); std::string name = RemoveWhitespace(browser->GetName());
@ -104,12 +103,15 @@ void AtomBrowserContext::SetUserAgent(const std::string& user_agent) {
user_agent_ = user_agent; user_agent_ = user_agent;
} }
net::NetworkDelegate* AtomBrowserContext::CreateNetworkDelegate() { std::unique_ptr<base::CallbackList<void(const CookieDetails*)>::Subscription>
return network_delegate_; AtomBrowserContext::RegisterCookieChangeCallback(
const base::Callback<void(const CookieDetails*)>& cb) {
return cookie_change_sub_list_.Add(cb);
} }
net::CookieMonsterDelegate* AtomBrowserContext::CreateCookieDelegate() { std::unique_ptr<net::NetworkDelegate>
return cookie_delegate(); AtomBrowserContext::CreateNetworkDelegate() {
return base::MakeUnique<AtomNetworkDelegate>();
} }
std::string AtomBrowserContext::GetUserAgent() { std::string AtomBrowserContext::GetUserAgent() {
@ -203,6 +205,14 @@ std::vector<std::string> AtomBrowserContext::GetCookieableSchemes() {
return default_schemes; return default_schemes;
} }
void AtomBrowserContext::NotifyCookieChange(
const net::CanonicalCookie& cookie,
bool removed,
net::CookieStore::ChangeCause cause) {
CookieDetails cookie_details(&cookie, removed, cause);
cookie_change_sub_list_.Notify(&cookie_details);
}
void AtomBrowserContext::RegisterPrefs(PrefRegistrySimple* pref_registry) { void AtomBrowserContext::RegisterPrefs(PrefRegistrySimple* pref_registry) {
pref_registry->RegisterFilePathPref(prefs::kSelectFileLastDirectory, pref_registry->RegisterFilePathPref(prefs::kSelectFileLastDirectory,
base::FilePath()); base::FilePath());

View file

@ -8,9 +8,8 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "atom/browser/net/atom_cookie_delegate.h" #include "base/callback_list.h"
#include "brightray/browser/browser_context.h" #include "brightray/browser/browser_context.h"
#include "net/cookies/cookie_monster.h"
namespace atom { namespace atom {
@ -19,6 +18,7 @@ class AtomDownloadManagerDelegate;
class AtomNetworkDelegate; class AtomNetworkDelegate;
class AtomPermissionManager; class AtomPermissionManager;
class WebViewManager; class WebViewManager;
struct CookieDetails;
class AtomBrowserContext : public brightray::BrowserContext { class AtomBrowserContext : public brightray::BrowserContext {
public: public:
@ -30,10 +30,13 @@ class AtomBrowserContext : public brightray::BrowserContext {
const base::DictionaryValue& options = base::DictionaryValue()); const base::DictionaryValue& options = base::DictionaryValue());
void SetUserAgent(const std::string& user_agent); void SetUserAgent(const std::string& user_agent);
// Register callbacks that needs to notified on any cookie store changes.
std::unique_ptr<base::CallbackList<void(const CookieDetails*)>::Subscription>
RegisterCookieChangeCallback(
const base::Callback<void(const CookieDetails*)>& cb);
// brightray::URLRequestContextGetter::Delegate: // brightray::URLRequestContextGetter::Delegate:
net::NetworkDelegate* CreateNetworkDelegate() override; std::unique_ptr<net::NetworkDelegate> CreateNetworkDelegate() override;
net::CookieMonsterDelegate* CreateCookieDelegate() override;
std::string GetUserAgent() override; std::string GetUserAgent() override;
std::unique_ptr<net::URLRequestJobFactory> CreateURLRequestJobFactory( std::unique_ptr<net::URLRequestJobFactory> CreateURLRequestJobFactory(
content::ProtocolHandlerMap* protocol_handlers) override; content::ProtocolHandlerMap* protocol_handlers) override;
@ -42,6 +45,9 @@ class AtomBrowserContext : public brightray::BrowserContext {
std::unique_ptr<net::CertVerifier> CreateCertVerifier( std::unique_ptr<net::CertVerifier> CreateCertVerifier(
brightray::RequireCTDelegate* ct_delegate) override; brightray::RequireCTDelegate* ct_delegate) override;
std::vector<std::string> GetCookieableSchemes() override; std::vector<std::string> GetCookieableSchemes() override;
void NotifyCookieChange(const net::CanonicalCookie& cookie,
bool removed,
net::CookieStore::ChangeCause cause) override;
// content::BrowserContext: // content::BrowserContext:
content::DownloadManagerDelegate* GetDownloadManagerDelegate() override; content::DownloadManagerDelegate* GetDownloadManagerDelegate() override;
@ -52,10 +58,6 @@ class AtomBrowserContext : public brightray::BrowserContext {
void RegisterPrefs(PrefRegistrySimple* pref_registry) override; void RegisterPrefs(PrefRegistrySimple* pref_registry) override;
AtomBlobReader* GetBlobReader(); AtomBlobReader* GetBlobReader();
AtomNetworkDelegate* network_delegate() const { return network_delegate_; }
AtomCookieDelegate* cookie_delegate() const {
return cookie_delegate_.get();
}
protected: protected:
AtomBrowserContext(const std::string& partition, bool in_memory, AtomBrowserContext(const std::string& partition, bool in_memory,
@ -70,9 +72,7 @@ class AtomBrowserContext : public brightray::BrowserContext {
std::string user_agent_; std::string user_agent_;
bool use_cache_; bool use_cache_;
// Managed by brightray::BrowserContext. base::CallbackList<void(const CookieDetails*)> cookie_change_sub_list_;
AtomNetworkDelegate* network_delegate_;
scoped_refptr<AtomCookieDelegate> cookie_delegate_;
DISALLOW_COPY_AND_ASSIGN(AtomBrowserContext); DISALLOW_COPY_AND_ASSIGN(AtomBrowserContext);
}; };

View file

@ -24,6 +24,7 @@
#include "content/public/browser/child_process_security_policy.h" #include "content/public/browser/child_process_security_policy.h"
#include "device/geolocation/geolocation_delegate.h" #include "device/geolocation/geolocation_delegate.h"
#include "device/geolocation/geolocation_provider.h" #include "device/geolocation/geolocation_provider.h"
#include "ui/base/l10n/l10n_util.h"
#include "v8/include/v8-debug.h" #include "v8/include/v8-debug.h"
#if defined(USE_X11) #if defined(USE_X11)
@ -38,7 +39,10 @@ namespace {
// A provider of Geolocation services to override AccessTokenStore. // A provider of Geolocation services to override AccessTokenStore.
class AtomGeolocationDelegate : public device::GeolocationDelegate { class AtomGeolocationDelegate : public device::GeolocationDelegate {
public: public:
AtomGeolocationDelegate() = default; AtomGeolocationDelegate() {
device::GeolocationProvider::GetInstance()
->UserDidOptIntoLocationServices();
}
scoped_refptr<device::AccessTokenStore> CreateAccessTokenStore() final { scoped_refptr<device::AccessTokenStore> CreateAccessTokenStore() final {
return new AtomAccessTokenStore(); return new AtomAccessTokenStore();
@ -131,13 +135,13 @@ void AtomBrowserMainParts::PostEarlyInitialization() {
node_bindings_->Initialize(); node_bindings_->Initialize();
// Create the global environment. // Create the global environment.
node::Environment* env = node::Environment* env = node_bindings_->CreateEnvironment(
node_bindings_->CreateEnvironment(js_env_->context()); js_env_->context(), js_env_->platform());
node_env_.reset(new NodeEnvironment(env)); node_env_.reset(new NodeEnvironment(env));
// Enable support for v8 inspector // Enable support for v8 inspector
node_debugger_.reset(new NodeDebugger(env)); node_debugger_.reset(new NodeDebugger(env));
node_debugger_->Start(); node_debugger_->Start(js_env_->platform());
// Add Electron extended APIs. // Add Electron extended APIs.
atom_bindings_->BindTo(js_env_->isolate(), env->process_object()); atom_bindings_->BindTo(js_env_->isolate(), env->process_object());
@ -149,6 +153,15 @@ void AtomBrowserMainParts::PostEarlyInitialization() {
node_bindings_->set_uv_env(env); node_bindings_->set_uv_env(env);
} }
int AtomBrowserMainParts::PreCreateThreads() {
const int result = brightray::BrowserMainParts::PreCreateThreads();
if (!result) {
fake_browser_process_->SetApplicationLocale(
brightray::BrowserClient::Get()->GetApplicationLocale());
}
return result;
}
void AtomBrowserMainParts::PreMainMessageLoopRun() { void AtomBrowserMainParts::PreMainMessageLoopRun() {
js_env_->OnMessageLoopCreated(); js_env_->OnMessageLoopCreated();
@ -185,6 +198,7 @@ void AtomBrowserMainParts::PreMainMessageLoopRun() {
Browser::Get()->DidFinishLaunching(*empty_info); Browser::Get()->DidFinishLaunching(*empty_info);
#endif #endif
// Notify observers that main thread message loop was initialized.
Browser::Get()->PreMainMessageLoopRun(); Browser::Get()->PreMainMessageLoopRun();
} }

View file

@ -49,6 +49,7 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts {
// content::BrowserMainParts: // content::BrowserMainParts:
void PreEarlyInitialization() override; void PreEarlyInitialization() override;
void PostEarlyInitialization() override; void PostEarlyInitialization() override;
int PreCreateThreads() override;
void PreMainMessageLoopRun() override; void PreMainMessageLoopRun() override;
bool MainMessageLoopRun(int* result_code) override; bool MainMessageLoopRun(int* result_code) override;
void PostMainMessageLoopStart() override; void PostMainMessageLoopStart() override;

View file

@ -119,9 +119,8 @@ void ShutdownDetector::ThreadMain() {
int signal; int signal;
size_t bytes_read = 0; size_t bytes_read = 0;
ssize_t ret;
do { do {
ret = HANDLE_EINTR( ssize_t ret = HANDLE_EINTR(
read(shutdown_fd_, read(shutdown_fd_,
reinterpret_cast<char*>(&signal) + bytes_read, reinterpret_cast<char*>(&signal) + bytes_read,
sizeof(signal) - bytes_read)); sizeof(signal) - bytes_read));

View file

@ -21,6 +21,32 @@
namespace atom { namespace atom {
namespace {
// Generate default file path to save the download.
void CreateDownloadPath(
const GURL& url,
const std::string& content_disposition,
const std::string& suggested_filename,
const std::string& mime_type,
const base::FilePath& default_download_path,
const AtomDownloadManagerDelegate::CreateDownloadPathCallback& callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
auto generated_name =
net::GenerateFileName(url, content_disposition, std::string(),
suggested_filename, mime_type, "download");
if (!base::PathExists(default_download_path))
base::CreateDirectory(default_download_path);
base::FilePath path(default_download_path.Append(generated_name));
content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
base::Bind(callback, path));
}
} // namespace
AtomDownloadManagerDelegate::AtomDownloadManagerDelegate( AtomDownloadManagerDelegate::AtomDownloadManagerDelegate(
content::DownloadManager* manager) content::DownloadManager* manager)
: download_manager_(manager), : download_manager_(manager),
@ -46,30 +72,6 @@ void AtomDownloadManagerDelegate::GetItemSavePath(content::DownloadItem* item,
*path = download->GetSavePath(); *path = download->GetSavePath();
} }
void AtomDownloadManagerDelegate::CreateDownloadPath(
const GURL& url,
const std::string& content_disposition,
const std::string& suggested_filename,
const std::string& mime_type,
const base::FilePath& default_download_path,
const CreateDownloadPathCallback& callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
auto generated_name = net::GenerateFileName(url,
content_disposition,
std::string(),
suggested_filename,
mime_type,
"download");
if (!base::PathExists(default_download_path))
base::CreateDirectory(default_download_path);
base::FilePath path(default_download_path.Append(generated_name));
content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
base::Bind(callback, path));
}
void AtomDownloadManagerDelegate::OnDownloadPathGenerated( void AtomDownloadManagerDelegate::OnDownloadPathGenerated(
uint32_t download_id, uint32_t download_id,
const content::DownloadTargetCallback& callback, const content::DownloadTargetCallback& callback,
@ -164,14 +166,10 @@ bool AtomDownloadManagerDelegate::DetermineDownloadTarget(
content::BrowserThread::PostTask( content::BrowserThread::PostTask(
content::BrowserThread::FILE, FROM_HERE, content::BrowserThread::FILE, FROM_HERE,
base::Bind(&AtomDownloadManagerDelegate::CreateDownloadPath, base::Bind(&CreateDownloadPath, download->GetURL(),
weak_ptr_factory_.GetWeakPtr(),
download->GetURL(),
download->GetContentDisposition(), download->GetContentDisposition(),
download->GetSuggestedFilename(), download->GetSuggestedFilename(), download->GetMimeType(),
download->GetMimeType(), default_download_path, download_path_callback));
default_download_path,
download_path_callback));
return true; return true;
} }

View file

@ -24,13 +24,6 @@ class AtomDownloadManagerDelegate : public content::DownloadManagerDelegate {
explicit AtomDownloadManagerDelegate(content::DownloadManager* manager); explicit AtomDownloadManagerDelegate(content::DownloadManager* manager);
virtual ~AtomDownloadManagerDelegate(); virtual ~AtomDownloadManagerDelegate();
// Generate default file path to save the download.
void CreateDownloadPath(const GURL& url,
const std::string& suggested_filename,
const std::string& content_disposition,
const std::string& mime_type,
const base::FilePath& path,
const CreateDownloadPathCallback& callback);
void OnDownloadPathGenerated(uint32_t download_id, void OnDownloadPathGenerated(uint32_t download_id,
const content::DownloadTargetCallback& callback, const content::DownloadTargetCallback& callback,
const base::FilePath& default_path); const base::FilePath& default_path);

View file

@ -10,6 +10,7 @@
#include "atom/browser/api/atom_api_web_contents.h" #include "atom/browser/api/atom_api_web_contents.h"
#include "atom/browser/native_window.h" #include "atom/browser/native_window.h"
#include "atom/browser/ui/message_box.h" #include "atom/browser/ui/message_box.h"
#include "atom/browser/web_contents_preferences.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_skia.h"
@ -18,6 +19,12 @@ using content::JavaScriptDialogType;
namespace atom { namespace atom {
namespace {
constexpr int kUserWantsNoMoreDialogs = -1;
} // namespace
AtomJavaScriptDialogManager::AtomJavaScriptDialogManager( AtomJavaScriptDialogManager::AtomJavaScriptDialogManager(
api::WebContents* api_web_contents) api::WebContents* api_web_contents)
: api_web_contents_(api_web_contents) {} : api_web_contents_(api_web_contents) {}
@ -30,6 +37,11 @@ void AtomJavaScriptDialogManager::RunJavaScriptDialog(
const base::string16& default_prompt_text, const base::string16& default_prompt_text,
const DialogClosedCallback& callback, const DialogClosedCallback& callback,
bool* did_suppress_message) { bool* did_suppress_message) {
const std::string origin = origin_url.GetOrigin().spec();
if (origin_counts_[origin] == kUserWantsNoMoreDialogs) {
return callback.Run(false, base::string16());
}
if (dialog_type != JavaScriptDialogType::JAVASCRIPT_DIALOG_TYPE_ALERT && if (dialog_type != JavaScriptDialogType::JAVASCRIPT_DIALOG_TYPE_ALERT &&
dialog_type != JavaScriptDialogType::JAVASCRIPT_DIALOG_TYPE_CONFIRM) { dialog_type != JavaScriptDialogType::JAVASCRIPT_DIALOG_TYPE_CONFIRM) {
callback.Run(false, base::string16()); callback.Run(false, base::string16());
@ -41,12 +53,27 @@ void AtomJavaScriptDialogManager::RunJavaScriptDialog(
buttons.push_back("Cancel"); buttons.push_back("Cancel");
} }
atom::ShowMessageBox(NativeWindow::FromWebContents(web_contents), origin_counts_[origin]++;
atom::MessageBoxType::MESSAGE_BOX_TYPE_NONE, buttons, -1,
0, atom::MessageBoxOptions::MESSAGE_BOX_NONE, "", std::string checkbox_string;
base::UTF16ToUTF8(message_text), "", "", false, if (origin_counts_[origin] > 1 &&
gfx::ImageSkia(), WebContentsPreferences::IsPreferenceEnabled("safeDialogs",
base::Bind(&OnMessageBoxCallback, callback)); web_contents)) {
if (!WebContentsPreferences::GetString("safeDialogsMessage",
&checkbox_string, web_contents)) {
checkbox_string = "Prevent this app from creating additional dialogs";
}
}
auto* relay = NativeWindowRelay::FromWebContents(web_contents);
atom::ShowMessageBox(
relay ? relay->window.get() : nullptr,
atom::MessageBoxType::MESSAGE_BOX_TYPE_NONE, buttons, -1, 0,
atom::MessageBoxOptions::MESSAGE_BOX_NONE, "",
base::UTF16ToUTF8(message_text), "", checkbox_string,
false, gfx::ImageSkia(),
base::Bind(&AtomJavaScriptDialogManager::OnMessageBoxCallback,
base::Unretained(this), callback, origin));
} }
void AtomJavaScriptDialogManager::RunBeforeUnloadDialog( void AtomJavaScriptDialogManager::RunBeforeUnloadDialog(
@ -63,11 +90,13 @@ void AtomJavaScriptDialogManager::CancelDialogs(
bool reset_state) { bool reset_state) {
} }
// static
void AtomJavaScriptDialogManager::OnMessageBoxCallback( void AtomJavaScriptDialogManager::OnMessageBoxCallback(
const DialogClosedCallback& callback, const DialogClosedCallback& callback,
const std::string& origin,
int code, int code,
bool checkbox_checked) { bool checkbox_checked) {
if (checkbox_checked)
origin_counts_[origin] = kUserWantsNoMoreDialogs;
callback.Run(code == 0, base::string16()); callback.Run(code == 0, base::string16());
} }

View file

@ -5,6 +5,7 @@
#ifndef ATOM_BROWSER_ATOM_JAVASCRIPT_DIALOG_MANAGER_H_ #ifndef ATOM_BROWSER_ATOM_JAVASCRIPT_DIALOG_MANAGER_H_
#define ATOM_BROWSER_ATOM_JAVASCRIPT_DIALOG_MANAGER_H_ #define ATOM_BROWSER_ATOM_JAVASCRIPT_DIALOG_MANAGER_H_
#include <map>
#include <string> #include <string>
#include "content/public/browser/javascript_dialog_manager.h" #include "content/public/browser/javascript_dialog_manager.h"
@ -36,10 +37,13 @@ class AtomJavaScriptDialogManager : public content::JavaScriptDialogManager {
bool reset_state) override; bool reset_state) override;
private: private:
static void OnMessageBoxCallback(const DialogClosedCallback& callback, void OnMessageBoxCallback(const DialogClosedCallback& callback,
int code, const std::string& origin,
bool checkbox_checked); int code,
bool checkbox_checked);
api::WebContents* api_web_contents_; api::WebContents* api_web_contents_;
std::map<std::string, int> origin_counts_;
}; };
} // namespace atom } // namespace atom

View file

@ -97,11 +97,28 @@ int AtomPermissionManager::RequestPermission(
const GURL& requesting_origin, const GURL& requesting_origin,
bool user_gesture, bool user_gesture,
const StatusCallback& response_callback) { const StatusCallback& response_callback) {
return RequestPermissions( return RequestPermissionWithDetails(
permission,
render_frame_host,
requesting_origin,
user_gesture,
nullptr,
response_callback);
}
int AtomPermissionManager::RequestPermissionWithDetails(
content::PermissionType permission,
content::RenderFrameHost* render_frame_host,
const GURL& requesting_origin,
bool user_gesture,
const base::DictionaryValue* details,
const StatusCallback& response_callback) {
return RequestPermissionsWithDetails(
std::vector<content::PermissionType>(1, permission), std::vector<content::PermissionType>(1, permission),
render_frame_host, render_frame_host,
requesting_origin, requesting_origin,
user_gesture, user_gesture,
details,
base::Bind(&PermissionRequestResponseCallbackWrapper, response_callback)); base::Bind(&PermissionRequestResponseCallbackWrapper, response_callback));
} }
@ -111,6 +128,18 @@ int AtomPermissionManager::RequestPermissions(
const GURL& requesting_origin, const GURL& requesting_origin,
bool user_gesture, bool user_gesture,
const StatusesCallback& response_callback) { const StatusesCallback& response_callback) {
return RequestPermissionsWithDetails(
permissions, render_frame_host, requesting_origin,
user_gesture, nullptr, response_callback);
}
int AtomPermissionManager::RequestPermissionsWithDetails(
const std::vector<content::PermissionType>& permissions,
content::RenderFrameHost* render_frame_host,
const GURL& requesting_origin,
bool user_gesture,
const base::DictionaryValue* details,
const StatusesCallback& response_callback) {
if (permissions.empty()) { if (permissions.empty()) {
response_callback.Run(std::vector<blink::mojom::PermissionStatus>()); response_callback.Run(std::vector<blink::mojom::PermissionStatus>());
return kNoPendingOperation; return kNoPendingOperation;
@ -143,7 +172,12 @@ int AtomPermissionManager::RequestPermissions(
const auto callback = const auto callback =
base::Bind(&AtomPermissionManager::OnPermissionResponse, base::Bind(&AtomPermissionManager::OnPermissionResponse,
base::Unretained(this), request_id, i); base::Unretained(this), request_id, i);
request_handler_.Run(web_contents, permission, callback); if (details == nullptr) {
request_handler_.Run(web_contents, permission, callback,
base::DictionaryValue());
} else {
request_handler_.Run(web_contents, permission, callback, *details);
}
} }
return request_id; return request_id;

View file

@ -9,7 +9,8 @@
#include <vector> #include <vector>
#include "base/callback.h" #include "base/callback.h"
#include "base/id_map.h" #include "base/containers/id_map.h"
#include "base/values.h"
#include "content/public/browser/permission_manager.h" #include "content/public/browser/permission_manager.h"
namespace content { namespace content {
@ -30,7 +31,8 @@ class AtomPermissionManager : public content::PermissionManager {
using RequestHandler = using RequestHandler =
base::Callback<void(content::WebContents*, base::Callback<void(content::WebContents*,
content::PermissionType, content::PermissionType,
const StatusCallback&)>; const StatusCallback&,
const base::DictionaryValue&)>;
// Handler to dispatch permission requests in JS. // Handler to dispatch permission requests in JS.
void SetPermissionRequestHandler(const RequestHandler& handler); void SetPermissionRequestHandler(const RequestHandler& handler);
@ -43,6 +45,13 @@ class AtomPermissionManager : public content::PermissionManager {
bool user_gesture, bool user_gesture,
const base::Callback<void(blink::mojom::PermissionStatus)>& callback) const base::Callback<void(blink::mojom::PermissionStatus)>& callback)
override; override;
int RequestPermissionWithDetails(
content::PermissionType permission,
content::RenderFrameHost* render_frame_host,
const GURL& requesting_origin,
bool user_gesture,
const base::DictionaryValue* details,
const base::Callback<void(blink::mojom::PermissionStatus)>& callback);
int RequestPermissions( int RequestPermissions(
const std::vector<content::PermissionType>& permissions, const std::vector<content::PermissionType>& permissions,
content::RenderFrameHost* render_frame_host, content::RenderFrameHost* render_frame_host,
@ -51,6 +60,14 @@ class AtomPermissionManager : public content::PermissionManager {
const base::Callback<void( const base::Callback<void(
const std::vector<blink::mojom::PermissionStatus>&)>& callback) const std::vector<blink::mojom::PermissionStatus>&)>& callback)
override; override;
int RequestPermissionsWithDetails(
const std::vector<content::PermissionType>& permissions,
content::RenderFrameHost* render_frame_host,
const GURL& requesting_origin,
bool user_gesture,
const base::DictionaryValue* details,
const base::Callback<void(
const std::vector<blink::mojom::PermissionStatus>&)>& callback);
protected: protected:
void OnPermissionResponse(int request_id, void OnPermissionResponse(int request_id,
@ -76,7 +93,7 @@ class AtomPermissionManager : public content::PermissionManager {
private: private:
class PendingRequest; class PendingRequest;
using PendingRequestsMap = IDMap<std::unique_ptr<PendingRequest>>; using PendingRequestsMap = base::IDMap<std::unique_ptr<PendingRequest>>;
RequestHandler request_handler_; RequestHandler request_handler_;

View file

@ -61,7 +61,8 @@ void HandleExternalProtocolInUI(
GURL escaped_url(net::EscapeExternalHandlerValue(url.spec())); GURL escaped_url(net::EscapeExternalHandlerValue(url.spec()));
auto callback = base::Bind(&OnOpenExternal, escaped_url); auto callback = base::Bind(&OnOpenExternal, escaped_url);
permission_helper->RequestOpenExternalPermission(callback, has_user_gesture); permission_helper->RequestOpenExternalPermission(callback, has_user_gesture,
url);
} }
void OnPdfResourceIntercepted( void OnPdfResourceIntercepted(
@ -74,7 +75,7 @@ void OnPdfResourceIntercepted(
if (!web_contents) if (!web_contents)
return; return;
if (!WebContentsPreferences::IsPluginsEnabled(web_contents)) { if (!WebContentsPreferences::IsPreferenceEnabled("plugins", web_contents)) {
auto browser_context = web_contents->GetBrowserContext(); auto browser_context = web_contents->GetBrowserContext();
auto download_manager = auto download_manager =
content::BrowserContext::GetDownloadManager(browser_context); content::BrowserContext::GetDownloadManager(browser_context);

View file

@ -52,7 +52,7 @@ AtomWebUIControllerFactory::CreateWebUIControllerForURL(content::WebUI* web_ui,
if (url.host() == kPdfViewerUIHost) { if (url.host() == kPdfViewerUIHost) {
base::StringPairs toplevel_params; base::StringPairs toplevel_params;
base::SplitStringIntoKeyValuePairs(url.query(), '=', '&', &toplevel_params); base::SplitStringIntoKeyValuePairs(url.query(), '=', '&', &toplevel_params);
std::string stream_id, src; std::string src;
const net::UnescapeRule::Type unescape_rules = const net::UnescapeRule::Type unescape_rules =
net::UnescapeRule::SPACES | net::UnescapeRule::PATH_SEPARATORS | net::UnescapeRule::SPACES | net::UnescapeRule::PATH_SEPARATORS |

View file

@ -21,8 +21,7 @@ std::string AutoUpdater::GetFeedURL() {
return ""; return "";
} }
void AutoUpdater::SetFeedURL(const std::string& url, void AutoUpdater::SetFeedURL(mate::Arguments* args) {
const HeaderMap& requestHeaders) {
} }
void AutoUpdater::CheckForUpdates() { void AutoUpdater::CheckForUpdates() {

View file

@ -10,6 +10,7 @@
#include "base/macros.h" #include "base/macros.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "native_mate/arguments.h"
namespace base { namespace base {
class Time; class Time;
@ -53,8 +54,7 @@ class AutoUpdater {
static void SetDelegate(Delegate* delegate); static void SetDelegate(Delegate* delegate);
static std::string GetFeedURL(); static std::string GetFeedURL();
static void SetFeedURL(const std::string& url, static void SetFeedURL(mate::Arguments* args);
const HeaderMap& requestHeaders);
static void CheckForUpdates(); static void CheckForUpdates();
static void QuitAndInstall(); static void QuitAndInstall();

View file

@ -9,9 +9,13 @@
#import <ReactiveCocoa/NSObject+RACPropertySubscribing.h> #import <ReactiveCocoa/NSObject+RACPropertySubscribing.h>
#import <Squirrel/Squirrel.h> #import <Squirrel/Squirrel.h>
#include "atom/browser/browser.h"
#include "atom/common/native_mate_converters/value_converter.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "base/strings/sys_string_conversions.h" #include "base/strings/sys_string_conversions.h"
#include "native_mate/converter.h"
#include "native_mate/dictionary.h"
namespace auto_updater { namespace auto_updater {
@ -34,8 +38,29 @@ std::string AutoUpdater::GetFeedURL() {
} }
// static // static
void AutoUpdater::SetFeedURL(const std::string& feed, void AutoUpdater::SetFeedURL(mate::Arguments* args) {
const HeaderMap& requestHeaders) { mate::Dictionary opts;
std::string feed;
HeaderMap requestHeaders;
std::string serverType = "default";
if (args->GetNext(&opts)) {
if (!opts.Get("url", &feed)) {
args->ThrowError("Expected options object to contain a 'url' string property in setFeedUrl call");
return;
}
opts.Get("headers", &requestHeaders);
opts.Get("serverType", &serverType);
if (serverType != "default" && serverType != "json") {
args->ThrowError("Expected serverType to be 'default' or 'json'");
return;
}
} else if (args->GetNext(&feed)) {
args->GetNext(&requestHeaders);
} else {
args->ThrowError("Expected an options object with a 'url' property to be provided");
return;
}
Delegate* delegate = GetDelegate(); Delegate* delegate = GetDelegate();
if (!delegate) if (!delegate)
return; return;
@ -55,7 +80,13 @@ void AutoUpdater::SetFeedURL(const std::string& feed,
// Initialize the SQRLUpdater. // Initialize the SQRLUpdater.
@try { @try {
g_updater = [[SQRLUpdater alloc] initWithUpdateRequest:urlRequest]; if (serverType == "json") {
NSString* nsAppVersion = base::SysUTF8ToNSString(atom::Browser::Get()->GetVersion());
g_updater = [[SQRLUpdater alloc] initWithUpdateRequest:urlRequest forVersion:nsAppVersion];
} else {
// default
g_updater = [[SQRLUpdater alloc] initWithUpdateRequest:urlRequest];
}
} @catch (NSException* error) { } @catch (NSException* error) {
delegate->OnError(base::SysNSStringToUTF8(error.reason)); delegate->OnError(base::SysNSStringToUTF8(error.reason));
return; return;

View file

@ -14,8 +14,10 @@
#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop.h"
#include "base/path_service.h" #include "base/path_service.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/threading/thread_restrictions.h"
#include "base/threading/thread_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h"
#include "brightray/browser/brightray_paths.h" #include "brightray/browser/brightray_paths.h"
#include "brightray/common/application_info.h"
namespace atom { namespace atom {
@ -95,31 +97,26 @@ void Browser::Shutdown() {
} }
std::string Browser::GetVersion() const { std::string Browser::GetVersion() const {
if (version_override_.empty()) { std::string ret = brightray::GetOverriddenApplicationVersion();
std::string version = GetExecutableFileVersion(); if (ret.empty())
if (!version.empty()) ret = GetExecutableFileVersion();
return version; return ret;
}
return version_override_;
} }
void Browser::SetVersion(const std::string& version) { void Browser::SetVersion(const std::string& version) {
version_override_ = version; brightray::OverrideApplicationVersion(version);
} }
std::string Browser::GetName() const { std::string Browser::GetName() const {
if (name_override_.empty()) { std::string ret = name_override_;
std::string name = GetExecutableFileProductName(); if (ret.empty())
if (!name.empty()) ret = GetExecutableFileProductName();
return name; return ret;
}
return name_override_;
} }
void Browser::SetName(const std::string& name) { void Browser::SetName(const std::string& name) {
name_override_ = name; name_override_ = name;
brightray::OverrideApplicationName(name);
} }
int Browser::GetBadgeCount() { int Browser::GetBadgeCount() {
@ -151,6 +148,7 @@ void Browser::WillFinishLaunching() {
void Browser::DidFinishLaunching(const base::DictionaryValue& launch_info) { void Browser::DidFinishLaunching(const base::DictionaryValue& launch_info) {
// Make sure the userData directory is created. // Make sure the userData directory is created.
base::ThreadRestrictions::ScopedAllowIO allow_io;
base::FilePath user_data; base::FilePath user_data;
if (PathService::Get(brightray::DIR_USER_DATA, &user_data)) if (PathService::Get(brightray::DIR_USER_DATA, &user_data))
base::CreateDirectoryAndGetError(user_data, nullptr); base::CreateDirectoryAndGetError(user_data, nullptr);

View file

@ -105,6 +105,9 @@ class Browser : public WindowListObserver {
LoginItemSettings GetLoginItemSettings(const LoginItemSettings& options); LoginItemSettings GetLoginItemSettings(const LoginItemSettings& options);
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
// Set the handler which decides whether to shutdown.
void SetShutdownHandler(base::Callback<bool()> handler);
// Hide the application. // Hide the application.
void Hide(); void Hide();
@ -270,15 +273,10 @@ class Browser : public WindowListObserver {
// The browser is being shutdown. // The browser is being shutdown.
bool is_shutdown_; bool is_shutdown_;
std::string version_override_;
std::string name_override_; std::string name_override_;
int badge_count_ = 0; int badge_count_ = 0;
#if defined(OS_WIN)
base::string16 app_user_model_id_;
#endif
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
base::DictionaryValue about_panel_options_; base::DictionaryValue about_panel_options_;
#endif #endif

View file

@ -31,10 +31,7 @@ bool LaunchXdgUtility(const std::vector<std::string>& argv, int* exit_code) {
if (devnull < 0) return false; if (devnull < 0) return false;
base::LaunchOptions options; base::LaunchOptions options;
options.fds_to_remap.push_back(std::make_pair(devnull, STDIN_FILENO));
base::FileHandleMappingVector remap;
remap.push_back(std::make_pair(devnull, STDIN_FILENO));
options.fds_to_remap = &remap;
base::Process process = base::LaunchProcess(argv, options); base::Process process = base::LaunchProcess(argv, options);
close(devnull); close(devnull);

View file

@ -17,10 +17,15 @@
#include "base/strings/sys_string_conversions.h" #include "base/strings/sys_string_conversions.h"
#include "brightray/common/application_info.h" #include "brightray/common/application_info.h"
#include "net/base/mac/url_conversions.h" #include "net/base/mac/url_conversions.h"
#include "ui/gfx/image/image.h"
#include "url/gurl.h" #include "url/gurl.h"
namespace atom { namespace atom {
void Browser::SetShutdownHandler(base::Callback<bool()> handler) {
[[AtomApplication sharedApplication] setShutdownHandler:std::move(handler)];
}
void Browser::Focus() { void Browser::Focus() {
[[AtomApplication sharedApplication] activateIgnoringOtherApps:YES]; [[AtomApplication sharedApplication] activateIgnoringOtherApps:YES];
} }

View file

@ -20,16 +20,16 @@
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_restrictions.h"
#include "base/win/registry.h" #include "base/win/registry.h"
#include "base/win/win_util.h" #include "base/win/win_util.h"
#include "base/win/windows_version.h" #include "base/win/windows_version.h"
#include "brightray/common/application_info.h"
namespace atom { namespace atom {
namespace { namespace {
const wchar_t kAppUserModelIDFormat[] = L"electron.app.$1";
BOOL CALLBACK WindowsEnumerationHandler(HWND hwnd, LPARAM param) { BOOL CALLBACK WindowsEnumerationHandler(HWND hwnd, LPARAM param) {
DWORD target_process_id = *reinterpret_cast<DWORD*>(param); DWORD target_process_id = *reinterpret_cast<DWORD*>(param);
DWORD process_id = 0; DWORD process_id = 0;
@ -118,8 +118,7 @@ void Browser::ClearRecentDocuments() {
} }
void Browser::SetAppUserModelID(const base::string16& name) { void Browser::SetAppUserModelID(const base::string16& name) {
app_user_model_id_ = name; brightray::SetAppUserModelID(name);
SetCurrentProcessExplicitAppUserModelID(app_user_model_id_.c_str());
} }
bool Browser::SetUserTasks(const std::vector<UserTask>& tasks) { bool Browser::SetUserTasks(const std::vector<UserTask>& tasks) {
@ -153,15 +152,19 @@ bool Browser::RemoveAsDefaultProtocolClient(const std::string& protocol,
// Main Registry Key // Main Registry Key
HKEY root = HKEY_CURRENT_USER; HKEY root = HKEY_CURRENT_USER;
base::string16 keyPath = base::UTF8ToUTF16("Software\\Classes\\" + protocol); base::string16 keyPath = L"Software\\Classes\\";
// Command Key // Command Key
base::string16 cmdPath = keyPath + L"\\shell\\open\\command"; base::string16 wprotocol = base::UTF8ToUTF16(protocol);
base::string16 shellPath = wprotocol + L"\\shell";
base::string16 cmdPath = keyPath + shellPath + L"\\open\\command";
base::win::RegKey key; base::win::RegKey classesKey;
base::win::RegKey commandKey; base::win::RegKey commandKey;
if (FAILED(key.Open(root, keyPath.c_str(), KEY_ALL_ACCESS)))
// Key doesn't even exist, we can confirm that it is not set if (FAILED(classesKey.Open(root, keyPath.c_str(), KEY_ALL_ACCESS)))
// Classes key doesn't exist, that's concerning, but I guess
// we're not the default handler
return true; return true;
if (FAILED(commandKey.Open(root, cmdPath.c_str(), KEY_ALL_ACCESS))) if (FAILED(commandKey.Open(root, cmdPath.c_str(), KEY_ALL_ACCESS)))
@ -179,9 +182,25 @@ bool Browser::RemoveAsDefaultProtocolClient(const std::string& protocol,
if (keyVal == exe) { if (keyVal == exe) {
// Let's kill the key // Let's kill the key
if (FAILED(key.DeleteKey(L"shell"))) if (FAILED(classesKey.DeleteKey(shellPath.c_str())))
return false; return false;
// Let's clean up after ourselves
base::win::RegKey protocolKey;
base::string16 protocolPath = keyPath + wprotocol;
if (SUCCEEDED(protocolKey
.Open(root, protocolPath.c_str(), KEY_ALL_ACCESS))) {
protocolKey.DeleteValue(L"URL Protocol");
// Overwrite the default value to be empty, we can't delete it right away
protocolKey.WriteValue(L"", L"");
protocolKey.DeleteValue(L"");
}
// If now empty, delete the whole key
classesKey.DeleteEmptyKey(wprotocol.c_str());
return true; return true;
} else { } else {
return true; return true;
@ -303,17 +322,13 @@ Browser::LoginItemSettings Browser::GetLoginItemSettings(
} }
PCWSTR Browser::GetAppUserModelID() { PCWSTR Browser::GetAppUserModelID() {
if (app_user_model_id_.empty()) { return brightray::GetRawAppUserModelID();
SetAppUserModelID(base::ReplaceStringPlaceholders(
kAppUserModelIDFormat, base::UTF8ToUTF16(GetName()), nullptr));
}
return app_user_model_id_.c_str();
} }
std::string Browser::GetExecutableFileVersion() const { std::string Browser::GetExecutableFileVersion() const {
base::FilePath path; base::FilePath path;
if (PathService::Get(base::FILE_EXE, &path)) { if (PathService::Get(base::FILE_EXE, &path)) {
base::ThreadRestrictions::ScopedAllowIO allow_io;
std::unique_ptr<FileVersionInfo> version_info( std::unique_ptr<FileVersionInfo> version_info(
FileVersionInfo::CreateFileVersionInfo(path)); FileVersionInfo::CreateFileVersionInfo(path));
return base::UTF16ToUTF8(version_info->product_version()); return base::UTF16ToUTF8(version_info->product_version());
@ -323,14 +338,7 @@ std::string Browser::GetExecutableFileVersion() const {
} }
std::string Browser::GetExecutableFileProductName() const { std::string Browser::GetExecutableFileProductName() const {
base::FilePath path; return brightray::GetApplicationName();
if (PathService::Get(base::FILE_EXE, &path)) {
std::unique_ptr<FileVersionInfo> version_info(
FileVersionInfo::CreateFileVersionInfo(path));
return base::UTF16ToUTF8(version_info->product_name());
}
return ATOM_PRODUCT_NAME;
} }
} // namespace atom } // namespace atom

Some files were not shown because too many files have changed in this diff Show more