mirror of
https://github.com/electron/electron.git
synced 2026-04-10 03:01:51 -04:00
Compare commits
132 Commits
v5.0.7
...
v6.0.0-nig
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
98b05b8428 | ||
|
|
bf276ecc69 | ||
|
|
5a44cc50cf | ||
|
|
01c442de64 | ||
|
|
cfbdc40814 | ||
|
|
83894dc5db | ||
|
|
deb36d5008 | ||
|
|
8141a26ba9 | ||
|
|
9deaacb454 | ||
|
|
6a47089c78 | ||
|
|
7baa218ca9 | ||
|
|
c92233cbc8 | ||
|
|
20d9f4b2b5 | ||
|
|
dc0be294dd | ||
|
|
9dd3338ede | ||
|
|
d8ba1278d1 | ||
|
|
a3cdf46fb6 | ||
|
|
5301808926 | ||
|
|
ccc60a1f33 | ||
|
|
36ce3e9546 | ||
|
|
3effa6f20c | ||
|
|
d57b9cb47f | ||
|
|
90ebd8eb12 | ||
|
|
c77e187742 | ||
|
|
7a3d220347 | ||
|
|
1898f91620 | ||
|
|
d16b581140 | ||
|
|
3f52e18a38 | ||
|
|
70042d2597 | ||
|
|
72f3a22ecc | ||
|
|
c80c3c18dc | ||
|
|
10607f7e86 | ||
|
|
ccf46a57bc | ||
|
|
062778c031 | ||
|
|
833daaa2b2 | ||
|
|
1632c4b837 | ||
|
|
b97f6bd7d4 | ||
|
|
23b84917e0 | ||
|
|
e790dbd737 | ||
|
|
c8282efb75 | ||
|
|
27bd47a333 | ||
|
|
db11b9b13b | ||
|
|
4989ecc5e0 | ||
|
|
9ebba76c03 | ||
|
|
4f8ebafa97 | ||
|
|
29501dbd01 | ||
|
|
acabf6f5ab | ||
|
|
c6fc5a23fc | ||
|
|
c8a1231ad7 | ||
|
|
6d68026c6c | ||
|
|
2d1438456b | ||
|
|
dd5264b4d1 | ||
|
|
e8608c2dbd | ||
|
|
a569dad8c5 | ||
|
|
17c240a639 | ||
|
|
fc06458038 | ||
|
|
84eef16755 | ||
|
|
c76459738e | ||
|
|
76d919fff5 | ||
|
|
26df9992cf | ||
|
|
858781ba83 | ||
|
|
4211a9c69f | ||
|
|
b7d8234a86 | ||
|
|
d53b51607c | ||
|
|
ff461d9d26 | ||
|
|
b7afec0743 | ||
|
|
8946cfd4f1 | ||
|
|
793d6c3691 | ||
|
|
b29e8d18a8 | ||
|
|
6d674eebb1 | ||
|
|
c486ab207a | ||
|
|
b202ad1e24 | ||
|
|
8582325e85 | ||
|
|
9b7eb0eecb | ||
|
|
e098d08728 | ||
|
|
f303caa87c | ||
|
|
3aa8ec0818 | ||
|
|
758d709c7a | ||
|
|
698d348168 | ||
|
|
f142aae9eb | ||
|
|
a9991f5451 | ||
|
|
af64140100 | ||
|
|
cacb56b103 | ||
|
|
24f1eac84f | ||
|
|
0a047194b6 | ||
|
|
7dc565fc2e | ||
|
|
392458b252 | ||
|
|
efe52f66e4 | ||
|
|
52952f7d51 | ||
|
|
bae09643c1 | ||
|
|
31c7ed9b8c | ||
|
|
ab503c7e43 | ||
|
|
c8c1be7ae5 | ||
|
|
2f35c98e76 | ||
|
|
d71f1fb30c | ||
|
|
6c77c220f7 | ||
|
|
76dcbcd6ea | ||
|
|
ba57e1d991 | ||
|
|
cbb5164cc8 | ||
|
|
49ec7e1582 | ||
|
|
927aac306f | ||
|
|
bd4e14dcee | ||
|
|
641b47f384 | ||
|
|
9ed89ace97 | ||
|
|
c7677b23e6 | ||
|
|
6e131f2121 | ||
|
|
dfcee48f81 | ||
|
|
56c6a51cd2 | ||
|
|
8af532ba98 | ||
|
|
8da91523d0 | ||
|
|
323b688ab8 | ||
|
|
940c4c0787 | ||
|
|
257de6a963 | ||
|
|
fa5442f211 | ||
|
|
a25f82c91f | ||
|
|
138ba53511 | ||
|
|
d105dcc0d3 | ||
|
|
5a35c3a279 | ||
|
|
63bf370cc0 | ||
|
|
8396a2d504 | ||
|
|
e2516dc808 | ||
|
|
74c29fb610 | ||
|
|
b66b5561ee | ||
|
|
713df08e3e | ||
|
|
fef262f829 | ||
|
|
e6952e2a16 | ||
|
|
1db4dd68a7 | ||
|
|
90151879cc | ||
|
|
f431ce4971 | ||
|
|
ad3ea6ec53 | ||
|
|
cc90919384 | ||
|
|
0a5adfe365 |
File diff suppressed because it is too large
Load Diff
@@ -1,12 +1,21 @@
|
||||
{
|
||||
"extends": "standard",
|
||||
"parser": "typescript-eslint-parser",
|
||||
"plugins": ["typescript"],
|
||||
"env": {
|
||||
"browser": true
|
||||
},
|
||||
"rules": {
|
||||
"no-var": "error",
|
||||
"no-unused-vars": 0,
|
||||
"no-global-assign": 0,
|
||||
"typescript/no-unused-vars": "error",
|
||||
"prefer-const": ["error", {
|
||||
"destructuring": "all"
|
||||
}]
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 6,
|
||||
"sourceType": "module"
|
||||
}
|
||||
}
|
||||
|
||||
34
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
34
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
@@ -4,29 +4,39 @@ about: Create a report to help us improve Electron
|
||||
|
||||
---
|
||||
|
||||
* Output of `node_modules/.bin/electron --version`:
|
||||
* Operating System (Platform and Version):
|
||||
* Output of `node_modules/.bin/electron --version` on last known working Electron version (if applicable):
|
||||
* **Electron Version** (output of `node_modules/.bin/electron --version`):
|
||||
* <!-- e.g. 4.0.3 -->
|
||||
* **Operating System** (Platform and Version):
|
||||
* <!-- e.g. macOS 10.13.6 / Windows 10 (1803) / Ubuntu 18.04 x64 -->
|
||||
* **Last known working Electron version** (if applicable):
|
||||
* <!-- e.g. 3.1.0 -->
|
||||
|
||||
**Expected Behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
### Expected Behavior
|
||||
<!-- A clear and concise description of what you expected to happen. -->
|
||||
|
||||
**Actual behavior**
|
||||
A clear and concise description of what actually happened.
|
||||
### Actual behavior
|
||||
<!-- A clear and concise description of what actually happened. -->
|
||||
|
||||
**To Reproduce**
|
||||
### To Reproduce
|
||||
<!--
|
||||
Your best chance of getting this bug looked at quickly is to provide a REPOSITORY that can be cloned and run.
|
||||
-->
|
||||
|
||||
<!--
|
||||
You can fork [electron-quick-start](https://github.com/electron/electron-quick-start) and include a link to the branch with your changes.
|
||||
-->
|
||||
|
||||
<!--
|
||||
If you provide a URL, please list the commands required to clone/setup/run your repo e.g.
|
||||
```sh
|
||||
$ git clone $YOUR_URL -b $BRANCH
|
||||
$ npm install
|
||||
$ npm start || electron .
|
||||
```
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
-->
|
||||
|
||||
**Additional Information**
|
||||
Add any other context about the problem here.
|
||||
### Screenshots
|
||||
<!-- If applicable, add screenshots to help explain your problem. -->
|
||||
|
||||
### Additional Information
|
||||
<!-- Add any other context about the problem here. -->
|
||||
|
||||
1
.github/config.yml
vendored
1
.github/config.yml
vendored
@@ -50,6 +50,7 @@ authorizedUsers:
|
||||
- deepak1556
|
||||
- jkleinsc
|
||||
- MarshallOfSound
|
||||
- miniak
|
||||
- nitsakh
|
||||
- nornagon
|
||||
- zcbenz
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -59,3 +59,6 @@ spec/.hash
|
||||
|
||||
# Generated native addon files
|
||||
/spec/fixtures/native-addon/echo/build/
|
||||
|
||||
# If someone runs tsc this is where stuff will end up
|
||||
ts-gen
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
pool:
|
||||
vmImage: 'Ubuntu 16.04'
|
||||
|
||||
steps:
|
||||
- bash: |
|
||||
# "depot_tools" has to be checkout into "//third_party/depot_tools" so pylint.py can a "pylintrc" file.
|
||||
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "${AGENT_BUILDDIRECTORY}/third_party/depot_tools"
|
||||
echo "##vso[task.setvariable variable=PATH]$PATH:${AGENT_BUILDDIRECTORY}/third_party/depot_tools"
|
||||
displayName: Setup Depot Tools
|
||||
|
||||
- bash: |
|
||||
chromium_revision="$(grep -A1 chromium_version DEPS | tr -d '\n' | cut -d\' -f4)"
|
||||
buildtools_revision="$(curl -sL "https://chromium.googlesource.com/chromium/src/+/${chromium_revision}/DEPS?format=TEXT" | base64 -d | grep buildtools_revision -A1 | tr -d '\n' | cut -d\' -f4)"
|
||||
|
||||
git clone https://chromium.googlesource.com/chromium/buildtools "${AGENT_TEMPDIRECTORY}/buildtools"
|
||||
(cd "${AGENT_TEMPDIRECTORY}/buildtools" && git checkout "$buildtools_revision")
|
||||
echo "##vso[task.setvariable variable=CHROMIUM_BUILDTOOLS_PATH]$AGENT_TEMPDIRECTORY/buildtools"
|
||||
|
||||
download_from_google_storage --bucket chromium-gn -s "${AGENT_TEMPDIRECTORY}/buildtools/linux64/gn.sha1"
|
||||
displayName: Download gn binary
|
||||
|
||||
- bash: |
|
||||
# gn.py tries to find a gclient root folder starting from the current dir.
|
||||
# When it fails and returns "None" path, the whole script fails. Let's "fix" it.
|
||||
touch .gclient
|
||||
# Another option would be to checkout "buildtools" inside the Electron checkout,
|
||||
# but then we would lint its contents (at least gn format), and it doesn't pass it.
|
||||
|
||||
npm install
|
||||
npm run lint
|
||||
displayName: Run Lint
|
||||
120
BUILD.gn
120
BUILD.gn
@@ -11,8 +11,10 @@ import("//tools/v8_context_snapshot/v8_context_snapshot.gni")
|
||||
import("//v8/snapshot_toolchain.gni")
|
||||
import("build/asar.gni")
|
||||
import("build/npm.gni")
|
||||
import("build/tsc.gni")
|
||||
import("buildflags/buildflags.gni")
|
||||
import("electron_paks.gni")
|
||||
import("filenames.auto.gni")
|
||||
import("filenames.gni")
|
||||
|
||||
if (is_mac) {
|
||||
@@ -53,8 +55,26 @@ config("branding") {
|
||||
]
|
||||
}
|
||||
|
||||
# We geneate the definitions twice here, once in //electron/electron.d.ts
|
||||
# and once in $target_gen_dir
|
||||
# The one in $target_gen_dir is used for the actual TSC build later one
|
||||
# and the one in //electron/electron.d.ts is used by your IDE (vscode)
|
||||
# for typescript prompting
|
||||
npm_action("build_electron_definitions") {
|
||||
script = "gn-typescript-definitions"
|
||||
args = [ rebase_path("$target_gen_dir/tsc/typings/electron.d.ts") ]
|
||||
inputs = auto_filenames.api_docs + [ "package-lock.json" ]
|
||||
|
||||
outputs = [
|
||||
"$target_gen_dir/tsc/typings/electron.d.ts",
|
||||
]
|
||||
}
|
||||
|
||||
npm_action("atom_browserify_sandbox") {
|
||||
script = "browserify"
|
||||
deps = [
|
||||
":build_electron_definitions",
|
||||
]
|
||||
|
||||
inputs = [
|
||||
# FIXME(zcbenz): The dependencies of these files are not listed here, so
|
||||
@@ -62,6 +82,8 @@ npm_action("atom_browserify_sandbox") {
|
||||
# Use a script to generate all dependencies and put them here.
|
||||
"lib/sandboxed_renderer/init.js",
|
||||
"lib/sandboxed_renderer/api/exports/electron.js",
|
||||
"tsconfig.electron.json",
|
||||
"tsconfig.json",
|
||||
]
|
||||
|
||||
outputs = [
|
||||
@@ -74,6 +96,12 @@ npm_action("atom_browserify_sandbox") {
|
||||
"./lib/sandboxed_renderer/api/exports/electron.js:electron",
|
||||
"-t",
|
||||
"aliasify",
|
||||
"-p",
|
||||
"[",
|
||||
"tsify",
|
||||
"-p",
|
||||
"tsconfig.electron.json",
|
||||
"]",
|
||||
"-o",
|
||||
rebase_path(outputs[0]),
|
||||
]
|
||||
@@ -81,9 +109,14 @@ npm_action("atom_browserify_sandbox") {
|
||||
|
||||
npm_action("atom_browserify_isolated") {
|
||||
script = "browserify"
|
||||
deps = [
|
||||
":build_electron_definitions",
|
||||
]
|
||||
|
||||
inputs = [
|
||||
"lib/isolated_renderer/init.js",
|
||||
"tsconfig.electron.json",
|
||||
"tsconfig.json",
|
||||
]
|
||||
|
||||
outputs = [
|
||||
@@ -94,6 +127,12 @@ npm_action("atom_browserify_isolated") {
|
||||
"lib/isolated_renderer/init.js",
|
||||
"-t",
|
||||
"aliasify",
|
||||
"-p",
|
||||
"[",
|
||||
"tsify",
|
||||
"-p",
|
||||
"tsconfig.electron.json",
|
||||
"]",
|
||||
"-o",
|
||||
rebase_path(outputs[0]),
|
||||
]
|
||||
@@ -137,7 +176,15 @@ action("atom_js2c") {
|
||||
rebase_path(sources, root_build_dir)
|
||||
}
|
||||
|
||||
asar("js2asar") {
|
||||
target_gen_electron_js = "$target_gen_dir/js/electron"
|
||||
target_gen_default_app_js = "$target_gen_dir/js/default_app"
|
||||
|
||||
typescript_build("lib_js") {
|
||||
deps = [
|
||||
":build_electron_definitions",
|
||||
]
|
||||
type_root = rebase_path("$target_gen_dir/tsc/electron/typings")
|
||||
|
||||
sources = filenames.js_sources
|
||||
if (enable_desktop_capturer) {
|
||||
sources += [
|
||||
@@ -156,18 +203,65 @@ asar("js2asar") {
|
||||
"lib/browser/api/views/text-field.js",
|
||||
]
|
||||
}
|
||||
|
||||
output_gen_dir = target_gen_electron_js
|
||||
output_dir_name = "lib"
|
||||
tsconfig = "tsconfig.electron.json"
|
||||
}
|
||||
|
||||
asar("electron_asar") {
|
||||
deps = [
|
||||
":lib_js",
|
||||
]
|
||||
|
||||
root = "$target_gen_electron_js/electron/lib"
|
||||
sources = get_target_outputs(":lib_js")
|
||||
outputs = [
|
||||
"$root_out_dir/resources/electron.asar",
|
||||
]
|
||||
root = "lib"
|
||||
}
|
||||
|
||||
asar("app2asar") {
|
||||
sources = filenames.default_app_sources
|
||||
typescript_build("default_app_js") {
|
||||
deps = [
|
||||
":build_electron_definitions",
|
||||
]
|
||||
type_root = rebase_path("$target_gen_dir/tsc/electron/typings")
|
||||
|
||||
sources = filenames.default_app_ts_sources
|
||||
|
||||
output_gen_dir = target_gen_default_app_js
|
||||
output_dir_name = "default_app"
|
||||
tsconfig = "tsconfig.default_app.json"
|
||||
}
|
||||
|
||||
copy("default_app_static") {
|
||||
sources = filenames.default_app_static_sources
|
||||
outputs = [
|
||||
"$target_gen_default_app_js/{{source}}",
|
||||
]
|
||||
}
|
||||
|
||||
copy("default_app_octicon_deps") {
|
||||
sources = filenames.default_app_octicon_sources
|
||||
outputs = [
|
||||
"$target_gen_default_app_js/electron/default_app/octicon/{{source_file_part}}",
|
||||
]
|
||||
}
|
||||
|
||||
asar("default_app_asar") {
|
||||
deps = [
|
||||
":default_app_js",
|
||||
":default_app_octicon_deps",
|
||||
":default_app_static",
|
||||
]
|
||||
|
||||
root = "$target_gen_default_app_js/electron/default_app"
|
||||
sources = get_target_outputs(":default_app_js") +
|
||||
get_target_outputs(":default_app_static") +
|
||||
get_target_outputs(":default_app_octicon_deps")
|
||||
outputs = [
|
||||
"$root_out_dir/resources/default_app.asar",
|
||||
]
|
||||
root = "default_app"
|
||||
}
|
||||
|
||||
grit("resources") {
|
||||
@@ -261,8 +355,10 @@ static_library("electron_lib") {
|
||||
"//ppapi/host",
|
||||
"//ppapi/proxy",
|
||||
"//ppapi/shared_impl",
|
||||
"//services/audio/public/mojom:constants",
|
||||
"//services/device/public/mojom",
|
||||
"//services/proxy_resolver:lib",
|
||||
"//services/video_capture/public/mojom:constants",
|
||||
"//services/viz/privileged/interfaces/compositing",
|
||||
"//skia",
|
||||
"//third_party/blink/public:blink",
|
||||
@@ -323,8 +419,6 @@ static_library("electron_lib") {
|
||||
"*_views.cc",
|
||||
"*_views.h",
|
||||
"*\bviews/*",
|
||||
"*/autofill_popup.cc",
|
||||
"*/autofill_popup.h",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -349,6 +443,10 @@ static_library("electron_lib") {
|
||||
"//third_party/crashpad/crashpad/client",
|
||||
"//ui/accelerated_widget_mac",
|
||||
]
|
||||
sources += [
|
||||
"atom/browser/ui/views/autofill_popup_view.cc",
|
||||
"atom/browser/ui/views/autofill_popup_view.h",
|
||||
]
|
||||
include_dirs += [
|
||||
# NOTE(nornagon): other chromium files use the full path to include
|
||||
# crashpad; this is just here for compatibility between GN and GYP, so that
|
||||
@@ -712,9 +810,9 @@ if (is_mac) {
|
||||
|
||||
bundle_data("electron_app_resources") {
|
||||
public_deps = [
|
||||
":app2asar",
|
||||
":default_app_asar",
|
||||
":electron_app_strings_bundle_data",
|
||||
":js2asar",
|
||||
":electron_asar",
|
||||
]
|
||||
sources = [
|
||||
"$root_out_dir/resources/default_app.asar",
|
||||
@@ -760,10 +858,10 @@ if (is_mac) {
|
||||
sources = filenames.app_sources
|
||||
include_dirs = [ "." ]
|
||||
deps = [
|
||||
":app2asar",
|
||||
":default_app_asar",
|
||||
":electron_app_manifest",
|
||||
":electron_asar",
|
||||
":electron_lib",
|
||||
":js2asar",
|
||||
":packed_resources",
|
||||
"//content:sandbox_helper_win",
|
||||
"//ui/strings",
|
||||
|
||||
10
DEPS
10
DEPS
@@ -10,7 +10,7 @@ gclient_gn_args = [
|
||||
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'72.0.3626.52',
|
||||
'72.0.3626.107',
|
||||
'node_version':
|
||||
'ad2c89ec3be0f5db3ea02b0f591d36a5d84c51ad',
|
||||
|
||||
@@ -107,7 +107,7 @@ hooks = [
|
||||
'action': [
|
||||
'python',
|
||||
'-c',
|
||||
'import os; os.chdir("src"); os.chdir("electron"); os.system("npm install")',
|
||||
'import os, subprocess; os.chdir(os.path.join("src", "electron")); subprocess.check_call(["python", "script/lib/npm.py", "install"]);',
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -117,7 +117,7 @@ hooks = [
|
||||
'action': [
|
||||
'python',
|
||||
'-c',
|
||||
'import os; os.chdir("src"); os.chdir("electron"); os.chdir("vendor"); os.chdir("boto"); os.system("python setup.py build");',
|
||||
'import os, subprocess; os.chdir(os.path.join("src", "electron", "vendor", "boto")); subprocess.check_call(["python", "setup.py", "build"]);',
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -127,9 +127,9 @@ hooks = [
|
||||
'action': [
|
||||
'python',
|
||||
'-c',
|
||||
'import os; os.chdir("src"); os.chdir("electron"); os.chdir("vendor"); os.chdir("requests"); os.system("python setup.py build");',
|
||||
'import os, subprocess; os.chdir(os.path.join("src", "electron", "vendor", "requests")); subprocess.check_call(["python", "setup.py", "build"]);',
|
||||
],
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
recursedeps = [
|
||||
|
||||
@@ -1 +1 @@
|
||||
5.0.0-nightly.20190122
|
||||
6.0.0-nightly.20190212
|
||||
@@ -7,7 +7,7 @@
|
||||
[](https://david-dm.org/electron/electron?type=dev)
|
||||
[](https://atom-slack.herokuapp.com/)
|
||||
|
||||
:memo: Available Translations: 🇨🇳 🇹🇼 🇧🇷 🇪🇸 🇰🇷 🇯🇵 🇷🇺 🇫🇷 🇹🇭 🇳🇱 🇹🇷 🇮🇩 🇺🇦 🇨🇿 🇮🇹.
|
||||
:memo: Available Translations: 🇨🇳 🇹🇼 🇧🇷 🇪🇸 🇰🇷 🇯🇵 🇷🇺 🇫🇷 🇹🇭 🇳🇱 🇹🇷 🇮🇩 🇺🇦 🇨🇿 🇮🇹 🇵🇱.
|
||||
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
|
||||
|
||||
@@ -81,8 +81,6 @@ test_script:
|
||||
if ((-Not (Test-Path Env:\ELECTRON_RELEASE)) -And ($env:GN_CONFIG -in "testing", "release")) {
|
||||
$env:RUN_TESTS="true"
|
||||
}
|
||||
- if "%RUN_TESTS%"=="true" ( echo Verifying non proprietary ffmpeg & python electron\script\verify-ffmpeg.py --build-dir out\Default --source-root %cd% --ffmpeg-path out\ffmpeg )
|
||||
- if "%RUN_TESTS%"=="true" ( echo Verifying mksnapshot & python electron\script\verify-mksnapshot.py --build-dir out\Default --source-root %cd% )
|
||||
- ps: >-
|
||||
if ($env:RUN_TESTS -eq 'true') {
|
||||
New-Item .\out\Default\gen\node_headers\Release -Type directory
|
||||
@@ -91,8 +89,12 @@ test_script:
|
||||
echo "Skipping tests for $env:GN_CONFIG build"
|
||||
}
|
||||
- cd electron
|
||||
- if "%RUN_TESTS%"=="true" ( echo Running test suite & npm run test -- --ci )
|
||||
- if "%RUN_TESTS%"=="true" ( echo Running test suite & npm run test -- --ci --enable-logging)
|
||||
- cd ..
|
||||
- if "%RUN_TESTS%"=="true" ( echo Verifying non proprietary ffmpeg & python electron\script\verify-ffmpeg.py --build-dir out\Default --source-root %cd% --ffmpeg-path out\ffmpeg )
|
||||
- echo "About to verify mksnapshot"
|
||||
- if "%RUN_TESTS%"=="true" ( echo Verifying mksnapshot & python electron\script\verify-mksnapshot.py --build-dir out\Default --source-root %cd% )
|
||||
- echo "Done verifying mksnapshot"
|
||||
deploy_script:
|
||||
- cd electron
|
||||
- ps: >-
|
||||
|
||||
@@ -213,18 +213,30 @@ base::RefCountedMemory* AtomContentClient::GetDataResourceBytes(
|
||||
}
|
||||
|
||||
void AtomContentClient::AddAdditionalSchemes(Schemes* schemes) {
|
||||
schemes->standard_schemes.push_back("chrome-extension");
|
||||
|
||||
std::vector<std::string> splited;
|
||||
ConvertStringWithSeparatorToVector(&splited, ",",
|
||||
switches::kRegisterServiceWorkerSchemes);
|
||||
switches::kServiceWorkerSchemes);
|
||||
for (const std::string& scheme : splited)
|
||||
schemes->service_worker_schemes.push_back(scheme);
|
||||
schemes->service_worker_schemes.push_back(url::kFileScheme);
|
||||
|
||||
ConvertStringWithSeparatorToVector(&splited, ",", switches::kStandardSchemes);
|
||||
for (const std::string& scheme : splited)
|
||||
schemes->standard_schemes.push_back(scheme);
|
||||
schemes->standard_schemes.push_back("chrome-extension");
|
||||
|
||||
ConvertStringWithSeparatorToVector(&splited, ",", switches::kSecureSchemes);
|
||||
for (const std::string& scheme : splited)
|
||||
schemes->secure_schemes.push_back(scheme);
|
||||
|
||||
ConvertStringWithSeparatorToVector(&splited, ",",
|
||||
switches::kBypassCSPSchemes);
|
||||
for (const std::string& scheme : splited)
|
||||
schemes->csp_bypassing_schemes.push_back(scheme);
|
||||
|
||||
ConvertStringWithSeparatorToVector(&splited, ",", switches::kCORSSchemes);
|
||||
for (const std::string& scheme : splited)
|
||||
schemes->cors_enabled_schemes.push_back(scheme);
|
||||
}
|
||||
|
||||
void AtomContentClient::AddPepperPlugins(
|
||||
|
||||
@@ -164,6 +164,9 @@ bool AtomMainDelegate::BasicStartupComplete(int* exit_code) {
|
||||
if (env->HasVar("ELECTRON_ENABLE_STACK_DUMPING"))
|
||||
base::debug::EnableInProcessStackDumping();
|
||||
|
||||
if (env->HasVar("ELECTRON_DISABLE_SANDBOX"))
|
||||
command_line->AppendSwitch(service_manager::switches::kNoSandbox);
|
||||
|
||||
chrome::RegisterPathProvider();
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "atom/browser/javascript_environment.h"
|
||||
#include "atom/browser/node_debugger.h"
|
||||
#include "atom/common/api/atom_bindings.h"
|
||||
#include "atom/common/atom_version.h"
|
||||
#include "atom/common/crash_reporter/crash_reporter.h"
|
||||
#include "atom/common/native_mate_converters/string16_converter.h"
|
||||
#include "atom/common/node_bindings.h"
|
||||
@@ -79,6 +80,11 @@ int NodeMain(int argc, char* argv[]) {
|
||||
reporter.SetMethod("start", &crash_reporter::CrashReporter::StartInstance);
|
||||
process.Set("crashReporter", reporter);
|
||||
|
||||
mate::Dictionary versions;
|
||||
if (process.Get("versions", &versions)) {
|
||||
versions.SetReadOnly(ATOM_PROJECT_NAME, ATOM_VERSION_STRING);
|
||||
}
|
||||
|
||||
node::LoadEnvironment(env);
|
||||
|
||||
bool more;
|
||||
|
||||
@@ -1154,6 +1154,7 @@ v8::Local<v8::Promise> App::GetFileIcon(const base::FilePath& path,
|
||||
|
||||
std::vector<mate::Dictionary> App::GetAppMetrics(v8::Isolate* isolate) {
|
||||
std::vector<mate::Dictionary> result;
|
||||
result.reserve(app_metrics_.size());
|
||||
int processor_count = base::SysInfo::NumberOfProcessors();
|
||||
|
||||
for (const auto& process_metric : app_metrics_) {
|
||||
|
||||
@@ -37,6 +37,14 @@ struct Converter<atom::AutoResizeFlags> {
|
||||
if (params.Get("height", &height) && height) {
|
||||
flags |= atom::kAutoResizeHeight;
|
||||
}
|
||||
bool horizontal = false;
|
||||
if (params.Get("horizontal", &horizontal) && horizontal) {
|
||||
flags |= atom::kAutoResizeHorizontal;
|
||||
}
|
||||
bool vertical = false;
|
||||
if (params.Get("vertical", &vertical) && vertical) {
|
||||
flags |= atom::kAutoResizeVertical;
|
||||
}
|
||||
|
||||
*auto_resize_flags = static_cast<atom::AutoResizeFlags>(flags);
|
||||
return true;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/file_path_converter.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "atom/common/promise_util.h"
|
||||
#include "base/bind.h"
|
||||
#include "base/files/file_util.h"
|
||||
#include "content/public/browser/tracing_controller.h"
|
||||
@@ -65,23 +66,53 @@ scoped_refptr<TracingController::TraceDataEndpoint> GetTraceDataEndpoint(
|
||||
result_file_path, base::Bind(callback, result_file_path));
|
||||
}
|
||||
|
||||
void StopRecording(const base::FilePath& path,
|
||||
const CompletionCallback& callback) {
|
||||
void OnRecordingStopped(scoped_refptr<atom::util::Promise> promise,
|
||||
const base::FilePath& path) {
|
||||
promise->Resolve(path);
|
||||
}
|
||||
|
||||
v8::Local<v8::Promise> StopRecording(v8::Isolate* isolate,
|
||||
const base::FilePath& path) {
|
||||
scoped_refptr<atom::util::Promise> promise = new atom::util::Promise(isolate);
|
||||
|
||||
TracingController::GetInstance()->StopTracing(
|
||||
GetTraceDataEndpoint(path, callback));
|
||||
GetTraceDataEndpoint(path, base::Bind(&OnRecordingStopped, promise)));
|
||||
|
||||
return promise->GetHandle();
|
||||
}
|
||||
|
||||
bool GetCategories(
|
||||
const base::RepeatingCallback<void(const std::set<std::string>&)>&
|
||||
callback) {
|
||||
return TracingController::GetInstance()->GetCategories(
|
||||
base::BindOnce(callback));
|
||||
void OnCategoriesAvailable(scoped_refptr<atom::util::Promise> promise,
|
||||
const std::set<std::string>& categories) {
|
||||
promise->Resolve(categories);
|
||||
}
|
||||
|
||||
bool StartTracing(const base::trace_event::TraceConfig& trace_config,
|
||||
const base::RepeatingCallback<void()>& callback) {
|
||||
return TracingController::GetInstance()->StartTracing(
|
||||
trace_config, base::BindOnce(callback));
|
||||
v8::Local<v8::Promise> GetCategories(v8::Isolate* isolate) {
|
||||
scoped_refptr<atom::util::Promise> promise = new atom::util::Promise(isolate);
|
||||
bool success = TracingController::GetInstance()->GetCategories(
|
||||
base::BindOnce(&OnCategoriesAvailable, promise));
|
||||
|
||||
if (!success)
|
||||
promise->RejectWithErrorMessage("Could not get categories.");
|
||||
|
||||
return promise->GetHandle();
|
||||
}
|
||||
|
||||
void OnTracingStarted(scoped_refptr<atom::util::Promise> promise) {
|
||||
promise->Resolve();
|
||||
}
|
||||
|
||||
v8::Local<v8::Promise> StartTracing(
|
||||
v8::Isolate* isolate,
|
||||
const base::trace_event::TraceConfig& trace_config) {
|
||||
scoped_refptr<atom::util::Promise> promise = new atom::util::Promise(isolate);
|
||||
|
||||
bool success = TracingController::GetInstance()->StartTracing(
|
||||
trace_config, base::BindOnce(&OnTracingStarted, promise));
|
||||
|
||||
if (!success)
|
||||
promise->RejectWithErrorMessage("Could not start tracing");
|
||||
|
||||
return promise->GetHandle();
|
||||
}
|
||||
|
||||
bool GetTraceBufferUsage(
|
||||
|
||||
@@ -136,6 +136,21 @@ inline net::CookieStore* GetCookieStore(
|
||||
return getter->GetURLRequestContext()->cookie_store();
|
||||
}
|
||||
|
||||
void ResolvePromiseWithCookies(scoped_refptr<util::Promise> promise,
|
||||
net::CookieList cookieList) {
|
||||
promise->Resolve(cookieList);
|
||||
}
|
||||
|
||||
void ResolvePromise(scoped_refptr<util::Promise> promise) {
|
||||
promise->Resolve();
|
||||
}
|
||||
|
||||
// Resolve |promise| in UI thread.
|
||||
void ResolvePromiseInUI(scoped_refptr<util::Promise> promise) {
|
||||
base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
|
||||
base::BindOnce(ResolvePromise, std::move(promise)));
|
||||
}
|
||||
|
||||
// Run |callback| on UI thread.
|
||||
void RunCallbackInUI(const base::Closure& callback) {
|
||||
base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, callback);
|
||||
@@ -143,25 +158,28 @@ void RunCallbackInUI(const base::Closure& callback) {
|
||||
|
||||
// Remove cookies from |list| not matching |filter|, and pass it to |callback|.
|
||||
void FilterCookies(std::unique_ptr<base::DictionaryValue> filter,
|
||||
const Cookies::GetCallback& callback,
|
||||
scoped_refptr<util::Promise> promise,
|
||||
const net::CookieList& list) {
|
||||
net::CookieList result;
|
||||
for (const auto& cookie : list) {
|
||||
if (MatchesCookie(filter.get(), cookie))
|
||||
result.push_back(cookie);
|
||||
}
|
||||
RunCallbackInUI(base::Bind(callback, Cookies::SUCCESS, result));
|
||||
|
||||
base::PostTaskWithTraits(
|
||||
FROM_HERE, {BrowserThread::UI},
|
||||
base::BindOnce(ResolvePromiseWithCookies, std::move(promise), result));
|
||||
}
|
||||
|
||||
// Receives cookies matching |filter| in IO thread.
|
||||
void GetCookiesOnIO(scoped_refptr<net::URLRequestContextGetter> getter,
|
||||
std::unique_ptr<base::DictionaryValue> filter,
|
||||
const Cookies::GetCallback& callback) {
|
||||
scoped_refptr<util::Promise> promise) {
|
||||
std::string url;
|
||||
filter->GetString("url", &url);
|
||||
|
||||
auto filtered_callback =
|
||||
base::Bind(FilterCookies, base::Passed(&filter), callback);
|
||||
base::Bind(FilterCookies, base::Passed(&filter), std::move(promise));
|
||||
|
||||
// Empty url will match all url cookies.
|
||||
if (url.empty())
|
||||
@@ -172,31 +190,42 @@ void GetCookiesOnIO(scoped_refptr<net::URLRequestContextGetter> getter,
|
||||
}
|
||||
|
||||
// Removes cookie with |url| and |name| in IO thread.
|
||||
void RemoveCookieOnIOThread(scoped_refptr<net::URLRequestContextGetter> getter,
|
||||
const GURL& url,
|
||||
const std::string& name,
|
||||
const base::Closure& callback) {
|
||||
void RemoveCookieOnIO(scoped_refptr<net::URLRequestContextGetter> getter,
|
||||
const GURL& url,
|
||||
const std::string& name,
|
||||
scoped_refptr<util::Promise> promise) {
|
||||
GetCookieStore(getter)->DeleteCookieAsync(
|
||||
url, name, base::BindOnce(RunCallbackInUI, callback));
|
||||
url, name, base::BindOnce(ResolvePromiseInUI, std::move(promise)));
|
||||
}
|
||||
|
||||
// Resolves/rejects the |promise| in UI thread.
|
||||
void SettlePromiseInUI(scoped_refptr<util::Promise> promise,
|
||||
const std::string& errmsg) {
|
||||
if (errmsg.empty()) {
|
||||
promise->Resolve();
|
||||
} else {
|
||||
promise->RejectWithErrorMessage(errmsg);
|
||||
}
|
||||
}
|
||||
|
||||
// Callback of SetCookie.
|
||||
void OnSetCookie(const Cookies::SetCallback& callback, bool success) {
|
||||
RunCallbackInUI(
|
||||
base::Bind(callback, success ? Cookies::SUCCESS : Cookies::FAILED));
|
||||
void OnSetCookie(scoped_refptr<util::Promise> promise, bool success) {
|
||||
const std::string errmsg = success ? "" : "Setting cookie failed";
|
||||
RunCallbackInUI(base::Bind(SettlePromiseInUI, std::move(promise), errmsg));
|
||||
}
|
||||
|
||||
// Flushes cookie store in IO thread.
|
||||
void FlushCookieStoreOnIOThread(
|
||||
scoped_refptr<net::URLRequestContextGetter> getter,
|
||||
const base::Closure& callback) {
|
||||
GetCookieStore(getter)->FlushStore(base::BindOnce(RunCallbackInUI, callback));
|
||||
scoped_refptr<util::Promise> promise) {
|
||||
GetCookieStore(getter)->FlushStore(
|
||||
base::BindOnce(ResolvePromiseInUI, std::move(promise)));
|
||||
}
|
||||
|
||||
// Sets cookie with |details| in IO thread.
|
||||
void SetCookieOnIO(scoped_refptr<net::URLRequestContextGetter> getter,
|
||||
std::unique_ptr<base::DictionaryValue> details,
|
||||
const Cookies::SetCallback& callback) {
|
||||
scoped_refptr<util::Promise> promise) {
|
||||
std::string url, name, value, domain, path;
|
||||
bool secure = false;
|
||||
bool http_only = false;
|
||||
@@ -237,7 +266,7 @@ void SetCookieOnIO(scoped_refptr<net::URLRequestContextGetter> getter,
|
||||
GURL(url), name, value, domain, path, creation_time, expiration_time,
|
||||
last_access_time, secure, http_only,
|
||||
net::CookieSameSite::DEFAULT_MODE, net::COOKIE_PRIORITY_DEFAULT));
|
||||
auto completion_callback = base::BindOnce(OnSetCookie, callback);
|
||||
auto completion_callback = base::BindOnce(OnSetCookie, std::move(promise));
|
||||
if (!canonical_cookie || !canonical_cookie->IsCanonical()) {
|
||||
std::move(completion_callback).Run(false);
|
||||
return;
|
||||
@@ -267,43 +296,56 @@ Cookies::Cookies(v8::Isolate* isolate, AtomBrowserContext* browser_context)
|
||||
|
||||
Cookies::~Cookies() {}
|
||||
|
||||
void Cookies::Get(const base::DictionaryValue& filter,
|
||||
const GetCallback& callback) {
|
||||
v8::Local<v8::Promise> Cookies::Get(const base::DictionaryValue& filter) {
|
||||
scoped_refptr<util::Promise> promise = new util::Promise(isolate());
|
||||
|
||||
auto copy = base::DictionaryValue::From(
|
||||
base::Value::ToUniquePtrValue(filter.Clone()));
|
||||
auto* getter = browser_context_->GetRequestContext();
|
||||
base::PostTaskWithTraits(
|
||||
FROM_HERE, {BrowserThread::IO},
|
||||
base::BindOnce(GetCookiesOnIO, base::RetainedRef(getter), std::move(copy),
|
||||
callback));
|
||||
promise));
|
||||
|
||||
return promise->GetHandle();
|
||||
}
|
||||
|
||||
void Cookies::Remove(const GURL& url,
|
||||
const std::string& name,
|
||||
const base::Closure& callback) {
|
||||
v8::Local<v8::Promise> Cookies::Remove(const GURL& url,
|
||||
const std::string& name) {
|
||||
scoped_refptr<util::Promise> promise = new util::Promise(isolate());
|
||||
|
||||
auto* getter = browser_context_->GetRequestContext();
|
||||
base::PostTaskWithTraits(
|
||||
FROM_HERE, {BrowserThread::IO},
|
||||
base::BindOnce(RemoveCookieOnIOThread, base::RetainedRef(getter), url,
|
||||
name, callback));
|
||||
base::BindOnce(RemoveCookieOnIO, base::RetainedRef(getter), url, name,
|
||||
promise));
|
||||
|
||||
return promise->GetHandle();
|
||||
}
|
||||
|
||||
void Cookies::Set(const base::DictionaryValue& details,
|
||||
const SetCallback& callback) {
|
||||
v8::Local<v8::Promise> Cookies::Set(const base::DictionaryValue& details) {
|
||||
scoped_refptr<util::Promise> promise = new util::Promise(isolate());
|
||||
|
||||
auto copy = base::DictionaryValue::From(
|
||||
base::Value::ToUniquePtrValue(details.Clone()));
|
||||
auto* getter = browser_context_->GetRequestContext();
|
||||
base::PostTaskWithTraits(
|
||||
FROM_HERE, {BrowserThread::IO},
|
||||
base::BindOnce(SetCookieOnIO, base::RetainedRef(getter), std::move(copy),
|
||||
callback));
|
||||
promise));
|
||||
|
||||
return promise->GetHandle();
|
||||
}
|
||||
|
||||
void Cookies::FlushStore(const base::Closure& callback) {
|
||||
v8::Local<v8::Promise> Cookies::FlushStore() {
|
||||
scoped_refptr<util::Promise> promise = new util::Promise(isolate());
|
||||
|
||||
auto* getter = browser_context_->GetRequestContext();
|
||||
base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
|
||||
base::BindOnce(FlushCookieStoreOnIOThread,
|
||||
base::RetainedRef(getter), callback));
|
||||
base::RetainedRef(getter), promise));
|
||||
|
||||
return promise->GetHandle();
|
||||
}
|
||||
|
||||
void Cookies::OnCookieChanged(const CookieDetails* details) {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "atom/browser/net/cookie_details.h"
|
||||
#include "atom/common/promise_util.h"
|
||||
#include "base/callback_list.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "net/cookies/canonical_cookie.h"
|
||||
@@ -35,9 +36,6 @@ class Cookies : public mate::TrackableObject<Cookies> {
|
||||
FAILED,
|
||||
};
|
||||
|
||||
using GetCallback = base::Callback<void(Error, const net::CookieList&)>;
|
||||
using SetCallback = base::Callback<void(Error)>;
|
||||
|
||||
static mate::Handle<Cookies> Create(v8::Isolate* isolate,
|
||||
AtomBrowserContext* browser_context);
|
||||
|
||||
@@ -49,12 +47,10 @@ class Cookies : public mate::TrackableObject<Cookies> {
|
||||
Cookies(v8::Isolate* isolate, AtomBrowserContext* browser_context);
|
||||
~Cookies() override;
|
||||
|
||||
void Get(const base::DictionaryValue& filter, const GetCallback& callback);
|
||||
void Remove(const GURL& url,
|
||||
const std::string& name,
|
||||
const base::Closure& callback);
|
||||
void Set(const base::DictionaryValue& details, const SetCallback& callback);
|
||||
void FlushStore(const base::Closure& callback);
|
||||
v8::Local<v8::Promise> Get(const base::DictionaryValue& filter);
|
||||
v8::Local<v8::Promise> Set(const base::DictionaryValue& details);
|
||||
v8::Local<v8::Promise> Remove(const GURL& url, const std::string& name);
|
||||
v8::Local<v8::Promise> FlushStore();
|
||||
|
||||
// CookieChangeNotifier subscription:
|
||||
void OnCookieChanged(const CookieDetails*);
|
||||
|
||||
@@ -137,11 +137,12 @@ bool DesktopCapturer::ShouldScheduleNextRefresh(DesktopMediaList* list) {
|
||||
}
|
||||
|
||||
void DesktopCapturer::UpdateSourcesList(DesktopMediaList* list) {
|
||||
std::vector<DesktopCapturer::Source> window_sources;
|
||||
if (capture_window_ &&
|
||||
list->GetMediaListType() == content::DesktopMediaID::TYPE_WINDOW) {
|
||||
capture_window_ = false;
|
||||
const auto& media_list_sources = list->GetSources();
|
||||
std::vector<DesktopCapturer::Source> window_sources;
|
||||
window_sources.reserve(media_list_sources.size());
|
||||
for (const auto& media_list_source : media_list_sources) {
|
||||
window_sources.emplace_back(DesktopCapturer::Source{
|
||||
media_list_source, std::string(), fetch_window_icons_});
|
||||
@@ -150,11 +151,12 @@ void DesktopCapturer::UpdateSourcesList(DesktopMediaList* list) {
|
||||
std::back_inserter(captured_sources_));
|
||||
}
|
||||
|
||||
std::vector<DesktopCapturer::Source> screen_sources;
|
||||
if (capture_screen_ &&
|
||||
list->GetMediaListType() == content::DesktopMediaID::TYPE_SCREEN) {
|
||||
capture_screen_ = false;
|
||||
const auto& media_list_sources = list->GetSources();
|
||||
std::vector<DesktopCapturer::Source> screen_sources;
|
||||
screen_sources.reserve(media_list_sources.size());
|
||||
for (const auto& media_list_source : media_list_sources) {
|
||||
screen_sources.emplace_back(
|
||||
DesktopCapturer::Source{media_list_source, std::string()});
|
||||
|
||||
@@ -24,47 +24,119 @@
|
||||
|
||||
using content::BrowserThread;
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
namespace {
|
||||
|
||||
// List of registered custom standard schemes.
|
||||
std::vector<std::string> g_standard_schemes;
|
||||
|
||||
struct SchemeOptions {
|
||||
bool standard = false;
|
||||
bool secure = false;
|
||||
bool bypassCSP = false;
|
||||
bool allowServiceWorkers = false;
|
||||
bool supportFetchAPI = false;
|
||||
bool corsEnabled = false;
|
||||
};
|
||||
|
||||
struct CustomScheme {
|
||||
std::string scheme;
|
||||
SchemeOptions options;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace mate {
|
||||
|
||||
template <>
|
||||
struct Converter<CustomScheme> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
CustomScheme* out) {
|
||||
mate::Dictionary dict;
|
||||
if (!ConvertFromV8(isolate, val, &dict))
|
||||
return false;
|
||||
if (!dict.Get("scheme", &(out->scheme)))
|
||||
return false;
|
||||
mate::Dictionary opt;
|
||||
// options are optional. Default values specified in SchemeOptions are used
|
||||
if (dict.Get("privileges", &opt)) {
|
||||
opt.Get("standard", &(out->options.standard));
|
||||
opt.Get("supportFetchAPI", &(out->options.supportFetchAPI));
|
||||
opt.Get("secure", &(out->options.secure));
|
||||
opt.Get("bypassCSP", &(out->options.bypassCSP));
|
||||
opt.Get("allowServiceWorkers", &(out->options.allowServiceWorkers));
|
||||
opt.Get("supportFetchAPI", &(out->options.supportFetchAPI));
|
||||
opt.Get("corsEnabled", &(out->options.corsEnabled));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
std::vector<std::string> GetStandardSchemes() {
|
||||
return g_standard_schemes;
|
||||
}
|
||||
|
||||
void RegisterStandardSchemes(const std::vector<std::string>& schemes,
|
||||
mate::Arguments* args) {
|
||||
g_standard_schemes = schemes;
|
||||
void RegisterSchemesAsPrivileged(v8::Local<v8::Value> val,
|
||||
mate::Arguments* args) {
|
||||
std::vector<CustomScheme> custom_schemes;
|
||||
if (!mate::ConvertFromV8(args->isolate(), val, &custom_schemes)) {
|
||||
args->ThrowError("Argument must be an array of custom schemes.");
|
||||
return;
|
||||
}
|
||||
|
||||
mate::Dictionary opts;
|
||||
bool secure = false;
|
||||
args->GetNext(&opts) && opts.Get("secure", &secure);
|
||||
|
||||
// Dynamically register the schemes.
|
||||
auto* policy = content::ChildProcessSecurityPolicy::GetInstance();
|
||||
for (const std::string& scheme : schemes) {
|
||||
url::AddStandardScheme(scheme.c_str(), url::SCHEME_WITH_HOST);
|
||||
if (secure) {
|
||||
url::AddSecureScheme(scheme.c_str());
|
||||
std::vector<std::string> secure_schemes, cspbypassing_schemes, fetch_schemes,
|
||||
service_worker_schemes, cors_schemes;
|
||||
for (const auto& custom_scheme : custom_schemes) {
|
||||
// Register scheme to privileged list (https, wss, data, chrome-extension)
|
||||
if (custom_scheme.options.standard) {
|
||||
auto* policy = content::ChildProcessSecurityPolicy::GetInstance();
|
||||
url::AddStandardScheme(custom_scheme.scheme.c_str(),
|
||||
url::SCHEME_WITH_HOST);
|
||||
g_standard_schemes.push_back(custom_scheme.scheme);
|
||||
policy->RegisterWebSafeScheme(custom_scheme.scheme);
|
||||
}
|
||||
if (custom_scheme.options.secure) {
|
||||
secure_schemes.push_back(custom_scheme.scheme);
|
||||
url::AddSecureScheme(custom_scheme.scheme.c_str());
|
||||
}
|
||||
if (custom_scheme.options.bypassCSP) {
|
||||
cspbypassing_schemes.push_back(custom_scheme.scheme);
|
||||
url::AddCSPBypassingScheme(custom_scheme.scheme.c_str());
|
||||
}
|
||||
if (custom_scheme.options.corsEnabled) {
|
||||
cors_schemes.push_back(custom_scheme.scheme);
|
||||
url::AddCorsEnabledScheme(custom_scheme.scheme.c_str());
|
||||
}
|
||||
if (custom_scheme.options.supportFetchAPI) {
|
||||
fetch_schemes.push_back(custom_scheme.scheme);
|
||||
}
|
||||
if (custom_scheme.options.allowServiceWorkers) {
|
||||
service_worker_schemes.push_back(custom_scheme.scheme);
|
||||
}
|
||||
policy->RegisterWebSafeScheme(scheme);
|
||||
}
|
||||
|
||||
// Add the schemes to command line switches, so child processes can also
|
||||
// register them.
|
||||
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
|
||||
atom::switches::kStandardSchemes, base::JoinString(schemes, ","));
|
||||
if (secure) {
|
||||
const auto AppendSchemesToCmdLine = [](const char* switch_name,
|
||||
std::vector<std::string> schemes) {
|
||||
// Add the schemes to command line switches, so child processes can also
|
||||
// register them.
|
||||
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
|
||||
atom::switches::kSecureSchemes, base::JoinString(schemes, ","));
|
||||
}
|
||||
switch_name, base::JoinString(schemes, ","));
|
||||
};
|
||||
|
||||
AppendSchemesToCmdLine(atom::switches::kSecureSchemes, secure_schemes);
|
||||
AppendSchemesToCmdLine(atom::switches::kBypassCSPSchemes,
|
||||
cspbypassing_schemes);
|
||||
AppendSchemesToCmdLine(atom::switches::kCORSSchemes, cors_schemes);
|
||||
AppendSchemesToCmdLine(atom::switches::kFetchSchemes, fetch_schemes);
|
||||
AppendSchemesToCmdLine(atom::switches::kServiceWorkerSchemes,
|
||||
service_worker_schemes);
|
||||
AppendSchemesToCmdLine(atom::switches::kStandardSchemes, g_standard_schemes);
|
||||
}
|
||||
|
||||
Protocol::Protocol(v8::Isolate* isolate, AtomBrowserContext* browser_context)
|
||||
@@ -73,12 +145,6 @@ Protocol::Protocol(v8::Isolate* isolate, AtomBrowserContext* browser_context)
|
||||
}
|
||||
|
||||
Protocol::~Protocol() {}
|
||||
|
||||
void Protocol::RegisterServiceWorkerSchemes(
|
||||
const std::vector<std::string>& schemes) {
|
||||
atom::AtomBrowserClient::SetCustomServiceWorkerSchemes(schemes);
|
||||
}
|
||||
|
||||
void Protocol::UnregisterProtocol(const std::string& scheme,
|
||||
mate::Arguments* args) {
|
||||
CompletionCallback callback;
|
||||
@@ -195,8 +261,6 @@ void Protocol::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "Protocol"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetMethod("registerServiceWorkerSchemes",
|
||||
&Protocol::RegisterServiceWorkerSchemes)
|
||||
.SetMethod("registerStringProtocol",
|
||||
&Protocol::RegisterProtocol<URLRequestStringJob>)
|
||||
.SetMethod("registerBufferProtocol",
|
||||
@@ -228,16 +292,16 @@ void Protocol::BuildPrototype(v8::Isolate* isolate,
|
||||
|
||||
namespace {
|
||||
|
||||
void RegisterStandardSchemes(const std::vector<std::string>& schemes,
|
||||
mate::Arguments* args) {
|
||||
void RegisterSchemesAsPrivileged(v8::Local<v8::Value> val,
|
||||
mate::Arguments* args) {
|
||||
if (atom::Browser::Get()->is_ready()) {
|
||||
args->ThrowError(
|
||||
"protocol.registerStandardSchemes should be called before "
|
||||
"protocol.registerSchemesAsPrivileged should be called before "
|
||||
"app is ready");
|
||||
return;
|
||||
}
|
||||
|
||||
atom::api::RegisterStandardSchemes(schemes, args);
|
||||
atom::api::RegisterSchemesAsPrivileged(val, args);
|
||||
}
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
@@ -246,7 +310,7 @@ void Initialize(v8::Local<v8::Object> exports,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.SetMethod("registerStandardSchemes", &RegisterStandardSchemes);
|
||||
dict.SetMethod("registerSchemesAsPrivileged", &RegisterSchemesAsPrivileged);
|
||||
dict.SetMethod("getStandardSchemes", &atom::api::GetStandardSchemes);
|
||||
}
|
||||
|
||||
|
||||
@@ -34,8 +34,9 @@ namespace atom {
|
||||
namespace api {
|
||||
|
||||
std::vector<std::string> GetStandardSchemes();
|
||||
void RegisterStandardSchemes(const std::vector<std::string>& schemes,
|
||||
mate::Arguments* args);
|
||||
|
||||
void RegisterSchemesAsPrivileged(v8::Local<v8::Value> val,
|
||||
mate::Arguments* args);
|
||||
|
||||
class Protocol : public mate::TrackableObject<Protocol> {
|
||||
public:
|
||||
@@ -94,9 +95,6 @@ class Protocol : public mate::TrackableObject<Protocol> {
|
||||
DISALLOW_COPY_AND_ASSIGN(CustomProtocolHandler);
|
||||
};
|
||||
|
||||
// Register schemes that can handle service worker.
|
||||
void RegisterServiceWorkerSchemes(const std::vector<std::string>& schemes);
|
||||
|
||||
// Register the protocol with certain request job.
|
||||
template <typename RequestJob>
|
||||
void RegisterProtocol(const std::string& scheme,
|
||||
|
||||
@@ -548,11 +548,9 @@ std::vector<int> TopLevelWindow::GetPosition() {
|
||||
return result;
|
||||
}
|
||||
|
||||
#if defined(OS_WIN) || defined(OS_MACOSX)
|
||||
void TopLevelWindow::MoveTop() {
|
||||
window_->MoveTop();
|
||||
}
|
||||
#endif
|
||||
|
||||
void TopLevelWindow::SetTitle(const std::string& title) {
|
||||
window_->SetTitle(title);
|
||||
@@ -659,6 +657,11 @@ void TopLevelWindow::SetMenu(v8::Isolate* isolate, v8::Local<v8::Value> value) {
|
||||
}
|
||||
}
|
||||
|
||||
void TopLevelWindow::RemoveMenu() {
|
||||
menu_.Reset();
|
||||
window_->SetMenu(nullptr);
|
||||
}
|
||||
|
||||
void TopLevelWindow::SetParentWindow(v8::Local<v8::Value> value,
|
||||
mate::Arguments* args) {
|
||||
if (IsModal()) {
|
||||
@@ -1062,9 +1065,7 @@ void TopLevelWindow::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("setResizable", &TopLevelWindow::SetResizable)
|
||||
.SetMethod("isResizable", &TopLevelWindow::IsResizable)
|
||||
.SetMethod("setMovable", &TopLevelWindow::SetMovable)
|
||||
#if defined(OS_WIN) || defined(OS_MACOSX)
|
||||
.SetMethod("moveTop", &TopLevelWindow::MoveTop)
|
||||
#endif
|
||||
.SetMethod("isMovable", &TopLevelWindow::IsMovable)
|
||||
.SetMethod("setMinimizable", &TopLevelWindow::SetMinimizable)
|
||||
.SetMethod("isMinimizable", &TopLevelWindow::IsMinimizable)
|
||||
@@ -1103,6 +1104,7 @@ void TopLevelWindow::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("setContentProtection", &TopLevelWindow::SetContentProtection)
|
||||
.SetMethod("setFocusable", &TopLevelWindow::SetFocusable)
|
||||
.SetMethod("setMenu", &TopLevelWindow::SetMenu)
|
||||
.SetMethod("removeMenu", &TopLevelWindow::RemoveMenu)
|
||||
.SetMethod("setParentWindow", &TopLevelWindow::SetParentWindow)
|
||||
.SetMethod("setBrowserView", &TopLevelWindow::SetBrowserView)
|
||||
.SetMethod("addBrowserView", &TopLevelWindow::AddBrowserView)
|
||||
|
||||
@@ -126,9 +126,7 @@ class TopLevelWindow : public mate::TrackableObject<TopLevelWindow>,
|
||||
void SetResizable(bool resizable);
|
||||
bool IsResizable();
|
||||
void SetMovable(bool movable);
|
||||
#if defined(OS_WIN) || defined(OS_MACOSX)
|
||||
void MoveTop();
|
||||
#endif
|
||||
bool IsMovable();
|
||||
void SetMinimizable(bool minimizable);
|
||||
bool IsMinimizable();
|
||||
@@ -165,6 +163,7 @@ class TopLevelWindow : public mate::TrackableObject<TopLevelWindow>,
|
||||
void SetContentProtection(bool enable);
|
||||
void SetFocusable(bool focusable);
|
||||
void SetMenu(v8::Isolate* isolate, v8::Local<v8::Value> menu);
|
||||
void RemoveMenu();
|
||||
void SetParentWindow(v8::Local<v8::Value> value, mate::Arguments* args);
|
||||
virtual void SetBrowserView(v8::Local<v8::Value> value);
|
||||
virtual void AddBrowserView(v8::Local<v8::Value> value);
|
||||
|
||||
@@ -240,21 +240,6 @@ namespace api {
|
||||
|
||||
namespace {
|
||||
|
||||
content::ServiceWorkerContext* GetServiceWorkerContext(
|
||||
content::WebContents* web_contents) {
|
||||
auto* context = web_contents->GetBrowserContext();
|
||||
auto* site_instance = web_contents->GetSiteInstance();
|
||||
if (!context || !site_instance)
|
||||
return nullptr;
|
||||
|
||||
auto* storage_partition =
|
||||
content::BrowserContext::GetStoragePartition(context, site_instance);
|
||||
if (!storage_partition)
|
||||
return nullptr;
|
||||
|
||||
return storage_partition->GetServiceWorkerContext();
|
||||
}
|
||||
|
||||
// Called when CapturePage is done.
|
||||
void OnCapturePageDone(scoped_refptr<util::Promise> promise,
|
||||
const SkBitmap& bitmap) {
|
||||
@@ -280,10 +265,12 @@ struct WebContents::FrameDispatchHelper {
|
||||
api_web_contents->OnGetZoomLevel(rfh, reply_msg);
|
||||
}
|
||||
|
||||
void OnRendererMessageSync(const std::string& channel,
|
||||
void OnRendererMessageSync(bool internal,
|
||||
const std::string& channel,
|
||||
const base::ListValue& args,
|
||||
IPC::Message* message) {
|
||||
api_web_contents->OnRendererMessageSync(rfh, channel, args, message);
|
||||
api_web_contents->OnRendererMessageSync(rfh, internal, channel, args,
|
||||
message);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -599,7 +586,7 @@ void WebContents::SetContentsBounds(content::WebContents* source,
|
||||
|
||||
void WebContents::CloseContents(content::WebContents* source) {
|
||||
Emit("close");
|
||||
#if defined(TOOLKIT_VIEWS) && !defined(OS_MACOSX)
|
||||
#if defined(TOOLKIT_VIEWS)
|
||||
HideAutofillPopup();
|
||||
#endif
|
||||
if (managed_web_contents())
|
||||
@@ -1028,7 +1015,7 @@ void WebContents::DevToolsClosed() {
|
||||
Emit("devtools-closed");
|
||||
}
|
||||
|
||||
#if defined(TOOLKIT_VIEWS) && !defined(OS_MACOSX)
|
||||
#if defined(TOOLKIT_VIEWS)
|
||||
void WebContents::ShowAutofillPopup(content::RenderFrameHost* frame_host,
|
||||
const gfx::RectF& bounds,
|
||||
const std::vector<base::string16>& values,
|
||||
@@ -1070,12 +1057,13 @@ bool WebContents::OnMessageReceived(const IPC::Message& message,
|
||||
IPC_MESSAGE_FORWARD_DELAY_REPLY(AtomFrameHostMsg_Message_Sync, &helper,
|
||||
FrameDispatchHelper::OnRendererMessageSync)
|
||||
IPC_MESSAGE_HANDLER(AtomFrameHostMsg_Message_To, OnRendererMessageTo)
|
||||
IPC_MESSAGE_HANDLER(AtomFrameHostMsg_Message_Host, OnRendererMessageHost)
|
||||
IPC_MESSAGE_FORWARD_DELAY_REPLY(
|
||||
AtomFrameHostMsg_SetTemporaryZoomLevel, &helper,
|
||||
FrameDispatchHelper::OnSetTemporaryZoomLevel)
|
||||
IPC_MESSAGE_FORWARD_DELAY_REPLY(AtomFrameHostMsg_GetZoomLevel, &helper,
|
||||
FrameDispatchHelper::OnGetZoomLevel)
|
||||
#if defined(TOOLKIT_VIEWS) && !defined(OS_MACOSX)
|
||||
#if defined(TOOLKIT_VIEWS)
|
||||
IPC_MESSAGE_HANDLER(AtomAutofillFrameHostMsg_ShowPopup, ShowAutofillPopup)
|
||||
IPC_MESSAGE_HANDLER(AtomAutofillFrameHostMsg_HidePopup, HideAutofillPopup)
|
||||
#endif
|
||||
@@ -1413,6 +1401,23 @@ void WebContents::InspectElement(int x, int y) {
|
||||
managed_web_contents()->InspectElement(x, y);
|
||||
}
|
||||
|
||||
void WebContents::InspectSharedWorker() {
|
||||
if (type_ == REMOTE)
|
||||
return;
|
||||
|
||||
if (!enable_devtools_)
|
||||
return;
|
||||
|
||||
for (const auto& agent_host : content::DevToolsAgentHost::GetOrCreateAll()) {
|
||||
if (agent_host->GetType() ==
|
||||
content::DevToolsAgentHost::kTypeSharedWorker) {
|
||||
OpenDevTools(nullptr);
|
||||
managed_web_contents()->AttachTo(agent_host);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WebContents::InspectServiceWorker() {
|
||||
if (type_ == REMOTE)
|
||||
return;
|
||||
@@ -1430,40 +1435,6 @@ void WebContents::InspectServiceWorker() {
|
||||
}
|
||||
}
|
||||
|
||||
void WebContents::HasServiceWorker(const base::Callback<void(bool)>& callback) {
|
||||
auto* context = GetServiceWorkerContext(web_contents());
|
||||
if (!context)
|
||||
return;
|
||||
|
||||
struct WrappedCallback {
|
||||
base::Callback<void(bool)> callback_;
|
||||
explicit WrappedCallback(const base::Callback<void(bool)>& callback)
|
||||
: callback_(callback) {}
|
||||
void Run(content::ServiceWorkerCapability capability) {
|
||||
callback_.Run(capability !=
|
||||
content::ServiceWorkerCapability::NO_SERVICE_WORKER);
|
||||
delete this;
|
||||
}
|
||||
};
|
||||
|
||||
auto* wrapped_callback = new WrappedCallback(callback);
|
||||
|
||||
context->CheckHasServiceWorker(
|
||||
web_contents()->GetLastCommittedURL(), GURL::EmptyGURL(),
|
||||
base::BindOnce(&WrappedCallback::Run,
|
||||
base::Unretained(wrapped_callback)));
|
||||
}
|
||||
|
||||
void WebContents::UnregisterServiceWorker(
|
||||
const base::Callback<void(bool)>& callback) {
|
||||
auto* context = GetServiceWorkerContext(web_contents());
|
||||
if (!context)
|
||||
return;
|
||||
|
||||
context->UnregisterServiceWorker(web_contents()->GetLastCommittedURL(),
|
||||
callback);
|
||||
}
|
||||
|
||||
void WebContents::SetIgnoreMenuShortcuts(bool ignore) {
|
||||
auto* web_preferences = WebContentsPreferences::From(web_contents());
|
||||
DCHECK(web_preferences);
|
||||
@@ -1528,11 +1499,12 @@ std::vector<printing::PrinterBasicInfo> WebContents::GetPrinterList() {
|
||||
return printers;
|
||||
}
|
||||
|
||||
void WebContents::PrintToPDF(
|
||||
const base::DictionaryValue& settings,
|
||||
const PrintPreviewMessageHandler::PrintToPDFCallback& callback) {
|
||||
v8::Local<v8::Promise> WebContents::PrintToPDF(
|
||||
const base::DictionaryValue& settings) {
|
||||
scoped_refptr<util::Promise> promise = new util::Promise(isolate());
|
||||
PrintPreviewMessageHandler::FromWebContents(web_contents())
|
||||
->PrintToPDF(settings, callback);
|
||||
->PrintToPDF(settings, promise);
|
||||
return promise->GetHandle();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1988,6 +1960,9 @@ v8::Local<v8::Value> WebContents::GetLastWebPreferences(
|
||||
}
|
||||
|
||||
bool WebContents::IsRemoteModuleEnabled() const {
|
||||
if (web_contents()->GetVisibleURL().SchemeIs("chrome-devtools")) {
|
||||
return false;
|
||||
}
|
||||
if (auto* web_preferences = WebContentsPreferences::From(web_contents())) {
|
||||
return web_preferences->IsRemoteModuleEnabled();
|
||||
}
|
||||
@@ -2170,10 +2145,8 @@ void WebContents::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("getLastWebPreferences", &WebContents::GetLastWebPreferences)
|
||||
.SetMethod("_isRemoteModuleEnabled", &WebContents::IsRemoteModuleEnabled)
|
||||
.SetMethod("getOwnerBrowserWindow", &WebContents::GetOwnerBrowserWindow)
|
||||
.SetMethod("hasServiceWorker", &WebContents::HasServiceWorker)
|
||||
.SetMethod("unregisterServiceWorker",
|
||||
&WebContents::UnregisterServiceWorker)
|
||||
.SetMethod("inspectServiceWorker", &WebContents::InspectServiceWorker)
|
||||
.SetMethod("inspectSharedWorker", &WebContents::InspectSharedWorker)
|
||||
#if BUILDFLAG(ENABLE_PRINTING)
|
||||
.SetMethod("_print", &WebContents::Print)
|
||||
.SetMethod("_getPrinters", &WebContents::GetPrinterList)
|
||||
@@ -2206,18 +2179,22 @@ AtomBrowserContext* WebContents::GetBrowserContext() const {
|
||||
}
|
||||
|
||||
void WebContents::OnRendererMessage(content::RenderFrameHost* frame_host,
|
||||
bool internal,
|
||||
const std::string& channel,
|
||||
const base::ListValue& args) {
|
||||
// webContents.emit(channel, new Event(), args...);
|
||||
EmitWithSender(channel, frame_host, nullptr, args);
|
||||
// webContents.emit('-ipc-message', new Event(), internal, channel, args);
|
||||
EmitWithSender("-ipc-message", frame_host, nullptr, internal, channel, args);
|
||||
}
|
||||
|
||||
void WebContents::OnRendererMessageSync(content::RenderFrameHost* frame_host,
|
||||
bool internal,
|
||||
const std::string& channel,
|
||||
const base::ListValue& args,
|
||||
IPC::Message* message) {
|
||||
// webContents.emit(channel, new Event(sender, message), args...);
|
||||
EmitWithSender(channel, frame_host, message, args);
|
||||
// webContents.emit('-ipc-message-sync', new Event(sender, message), internal,
|
||||
// channel, args);
|
||||
EmitWithSender("-ipc-message-sync", frame_host, message, internal, channel,
|
||||
args);
|
||||
}
|
||||
|
||||
void WebContents::OnRendererMessageTo(content::RenderFrameHost* frame_host,
|
||||
@@ -2235,6 +2212,13 @@ void WebContents::OnRendererMessageTo(content::RenderFrameHost* frame_host,
|
||||
}
|
||||
}
|
||||
|
||||
void WebContents::OnRendererMessageHost(content::RenderFrameHost* frame_host,
|
||||
const std::string& channel,
|
||||
const base::ListValue& args) {
|
||||
// webContents.emit('ipc-message-host', new Event(), channel, args);
|
||||
EmitWithSender("ipc-message-host", frame_host, nullptr, channel, args);
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<WebContents> WebContents::Create(v8::Isolate* isolate,
|
||||
const mate::Dictionary& options) {
|
||||
|
||||
@@ -160,9 +160,8 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
void EnableDeviceEmulation(const blink::WebDeviceEmulationParams& params);
|
||||
void DisableDeviceEmulation();
|
||||
void InspectElement(int x, int y);
|
||||
void InspectSharedWorker();
|
||||
void InspectServiceWorker();
|
||||
void HasServiceWorker(const base::Callback<void(bool)>&);
|
||||
void UnregisterServiceWorker(const base::Callback<void(bool)>&);
|
||||
void SetIgnoreMenuShortcuts(bool ignore);
|
||||
void SetAudioMuted(bool muted);
|
||||
bool IsAudioMuted();
|
||||
@@ -175,9 +174,7 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
void Print(mate::Arguments* args);
|
||||
std::vector<printing::PrinterBasicInfo> GetPrinterList();
|
||||
// Print current page as PDF.
|
||||
void PrintToPDF(
|
||||
const base::DictionaryValue& settings,
|
||||
const PrintPreviewMessageHandler::PrintToPDFCallback& callback);
|
||||
v8::Local<v8::Promise> PrintToPDF(const base::DictionaryValue& settings);
|
||||
#endif
|
||||
|
||||
// DevTools workspace api.
|
||||
@@ -480,11 +477,13 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
|
||||
// Called when received a message from renderer.
|
||||
void OnRendererMessage(content::RenderFrameHost* frame_host,
|
||||
bool internal,
|
||||
const std::string& channel,
|
||||
const base::ListValue& args);
|
||||
|
||||
// Called when received a synchronous message from renderer.
|
||||
void OnRendererMessageSync(content::RenderFrameHost* frame_host,
|
||||
bool internal,
|
||||
const std::string& channel,
|
||||
const base::ListValue& args,
|
||||
IPC::Message* message);
|
||||
@@ -497,6 +496,11 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
const std::string& channel,
|
||||
const base::ListValue& args);
|
||||
|
||||
// Called when received a message from renderer to host.
|
||||
void OnRendererMessageHost(content::RenderFrameHost* frame_host,
|
||||
const std::string& channel,
|
||||
const base::ListValue& args);
|
||||
|
||||
// Called when received a synchronous message from renderer to
|
||||
// set temporary zoom level.
|
||||
void OnSetTemporaryZoomLevel(content::RenderFrameHost* frame_host,
|
||||
|
||||
@@ -82,6 +82,8 @@
|
||||
#include "net/ssl/client_cert_store_win.h"
|
||||
#elif defined(OS_MACOSX)
|
||||
#include "net/ssl/client_cert_store_mac.h"
|
||||
#include "services/audio/public/mojom/constants.mojom.h"
|
||||
#include "services/video_capture/public/mojom/constants.mojom.h"
|
||||
#elif defined(USE_OPENSSL)
|
||||
#include "net/ssl/client_cert_store.h"
|
||||
#endif
|
||||
@@ -114,9 +116,6 @@ namespace {
|
||||
// Next navigation should not restart renderer process.
|
||||
bool g_suppress_renderer_process_restart = false;
|
||||
|
||||
// Custom schemes to be registered to handle service worker.
|
||||
base::NoDestructor<std::string> g_custom_service_worker_schemes;
|
||||
|
||||
bool IsSameWebSite(content::BrowserContext* browser_context,
|
||||
const GURL& src_url,
|
||||
const GURL& dest_url) {
|
||||
@@ -148,11 +147,6 @@ void AtomBrowserClient::SuppressRendererProcessRestartForOnce() {
|
||||
g_suppress_renderer_process_restart = true;
|
||||
}
|
||||
|
||||
void AtomBrowserClient::SetCustomServiceWorkerSchemes(
|
||||
const std::vector<std::string>& schemes) {
|
||||
*g_custom_service_worker_schemes = base::JoinString(schemes, ",");
|
||||
}
|
||||
|
||||
AtomBrowserClient* AtomBrowserClient::Get() {
|
||||
return g_browser_client;
|
||||
}
|
||||
@@ -477,18 +471,15 @@ void AtomBrowserClient::AppendExtraCommandLineSwitches(
|
||||
return;
|
||||
|
||||
// Copy following switches to child process.
|
||||
static const char* const kCommonSwitchNames[] = {switches::kStandardSchemes,
|
||||
switches::kEnableSandbox,
|
||||
switches::kSecureSchemes};
|
||||
static const char* const kCommonSwitchNames[] = {
|
||||
switches::kStandardSchemes, switches::kEnableSandbox,
|
||||
switches::kSecureSchemes, switches::kBypassCSPSchemes,
|
||||
switches::kCORSSchemes, switches::kFetchSchemes,
|
||||
switches::kServiceWorkerSchemes};
|
||||
command_line->CopySwitchesFrom(*base::CommandLine::ForCurrentProcess(),
|
||||
kCommonSwitchNames,
|
||||
arraysize(kCommonSwitchNames));
|
||||
|
||||
// The registered service worker schemes.
|
||||
if (!g_custom_service_worker_schemes->empty())
|
||||
command_line->AppendSwitchASCII(switches::kRegisterServiceWorkerSchemes,
|
||||
*g_custom_service_worker_schemes);
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// Append --app-user-model-id.
|
||||
PWSTR current_app_id;
|
||||
@@ -514,6 +505,7 @@ void AtomBrowserClient::AppendExtraCommandLineSwitches(
|
||||
if (web_contents->GetVisibleURL().SchemeIs("chrome-devtools")) {
|
||||
command_line->AppendSwitch(service_manager::switches::kNoSandbox);
|
||||
command_line->AppendSwitch(::switches::kNoZygote);
|
||||
command_line->AppendSwitch(switches::kDisableRemoteModule);
|
||||
}
|
||||
auto* web_preferences = WebContentsPreferences::From(web_contents);
|
||||
if (web_preferences)
|
||||
@@ -523,6 +515,16 @@ void AtomBrowserClient::AppendExtraCommandLineSwitches(
|
||||
}
|
||||
}
|
||||
|
||||
void AtomBrowserClient::AdjustUtilityServiceProcessCommandLine(
|
||||
const service_manager::Identity& identity,
|
||||
base::CommandLine* command_line) {
|
||||
#if defined(OS_MACOSX)
|
||||
if (identity.name() == video_capture::mojom::kServiceName ||
|
||||
identity.name() == audio::mojom::kServiceName)
|
||||
command_line->AppendSwitch(::switches::kMessageLoopTypeUi);
|
||||
#endif
|
||||
}
|
||||
|
||||
void AtomBrowserClient::DidCreatePpapiPlugin(content::BrowserPpapiHost* host) {
|
||||
#if BUILDFLAG(ENABLE_PEPPER_FLASH)
|
||||
host->GetPpapiHost()->AddHostFactoryFilter(
|
||||
|
||||
@@ -49,10 +49,6 @@ class AtomBrowserClient : public content::ContentBrowserClient,
|
||||
// Don't force renderer process to restart for once.
|
||||
static void SuppressRendererProcessRestartForOnce();
|
||||
|
||||
// Custom schemes to be registered to handle service worker.
|
||||
static void SetCustomServiceWorkerSchemes(
|
||||
const std::vector<std::string>& schemes);
|
||||
|
||||
NotificationPresenter* GetNotificationPresenter();
|
||||
|
||||
void WebNotificationAllowed(int render_process_id,
|
||||
@@ -89,6 +85,9 @@ class AtomBrowserClient : public content::ContentBrowserClient,
|
||||
content::SiteInstance* pending_site_instance) override;
|
||||
void AppendExtraCommandLineSwitches(base::CommandLine* command_line,
|
||||
int child_process_id) override;
|
||||
void AdjustUtilityServiceProcessCommandLine(
|
||||
const service_manager::Identity& identity,
|
||||
base::CommandLine* command_line) override;
|
||||
void DidCreatePpapiPlugin(content::BrowserPpapiHost* browser_host) override;
|
||||
std::string GetGeolocationApiKey() override;
|
||||
content::QuotaPermissionContext* CreateQuotaPermissionContext() override;
|
||||
|
||||
@@ -455,7 +455,7 @@ bool AtomBrowserMainParts::MainMessageLoopRun(int* result_code) {
|
||||
|
||||
void AtomBrowserMainParts::PreDefaultMainMessageLoopRun(
|
||||
base::OnceClosure quit_closure) {
|
||||
Browser::SetMainMessageLoopQuitClosure(std::move(quit_closure));
|
||||
Browser::Get()->SetMainMessageLoopQuitClosure(std::move(quit_closure));
|
||||
}
|
||||
|
||||
void AtomBrowserMainParts::PostMainMessageLoopStart() {
|
||||
|
||||
@@ -100,23 +100,58 @@ void AtomDownloadManagerDelegate::OnDownloadPathGenerated(
|
||||
if (relay)
|
||||
window = relay->GetNativeWindow();
|
||||
|
||||
auto* web_preferences = WebContentsPreferences::From(web_contents);
|
||||
bool offscreen =
|
||||
!web_preferences || web_preferences->IsEnabled(options::kOffscreen);
|
||||
|
||||
// Show save dialog if save path was not set already on item
|
||||
base::FilePath path;
|
||||
GetItemSavePath(item, &path);
|
||||
// Show save dialog if save path was not set already on item
|
||||
file_dialog::DialogSettings settings;
|
||||
GetItemSaveDialogOptions(item, &settings);
|
||||
if (!settings.parent_window)
|
||||
settings.parent_window = window;
|
||||
settings.force_detached = offscreen;
|
||||
if (settings.title.size() == 0)
|
||||
settings.title = item->GetURL().spec();
|
||||
if (!settings.default_path.empty())
|
||||
settings.default_path = default_path;
|
||||
if (path.empty() && file_dialog::ShowSaveDialog(settings, &path)) {
|
||||
if (path.empty()) {
|
||||
file_dialog::DialogSettings settings;
|
||||
GetItemSaveDialogOptions(item, &settings);
|
||||
|
||||
if (!settings.parent_window)
|
||||
settings.parent_window = window;
|
||||
if (settings.title.size() == 0)
|
||||
settings.title = item->GetURL().spec();
|
||||
if (!settings.default_path.empty())
|
||||
settings.default_path = default_path;
|
||||
|
||||
auto* web_preferences = WebContentsPreferences::From(web_contents);
|
||||
const bool offscreen =
|
||||
!web_preferences || web_preferences->IsEnabled(options::kOffscreen);
|
||||
settings.force_detached = offscreen;
|
||||
|
||||
auto dialog_callback =
|
||||
base::Bind(&AtomDownloadManagerDelegate::OnDownloadSaveDialogDone,
|
||||
base::Unretained(this), download_id, callback);
|
||||
file_dialog::ShowSaveDialog(settings, dialog_callback);
|
||||
} else {
|
||||
callback.Run(path, download::DownloadItem::TARGET_DISPOSITION_PROMPT,
|
||||
download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, path,
|
||||
download::DOWNLOAD_INTERRUPT_REASON_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(MAS_BUILD)
|
||||
void AtomDownloadManagerDelegate::OnDownloadSaveDialogDone(
|
||||
uint32_t download_id,
|
||||
const content::DownloadTargetCallback& download_callback,
|
||||
bool result,
|
||||
const base::FilePath& path,
|
||||
const std::string& bookmark)
|
||||
#else
|
||||
void AtomDownloadManagerDelegate::OnDownloadSaveDialogDone(
|
||||
uint32_t download_id,
|
||||
const content::DownloadTargetCallback& download_callback,
|
||||
bool result,
|
||||
const base::FilePath& path)
|
||||
#endif
|
||||
{
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||
|
||||
auto* item = download_manager_->GetDownload(download_id);
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
if (result) {
|
||||
// Remember the last selected download directory.
|
||||
AtomBrowserContext* browser_context = static_cast<AtomBrowserContext*>(
|
||||
download_manager_->GetBrowserContext());
|
||||
@@ -133,12 +168,16 @@ void AtomDownloadManagerDelegate::OnDownloadPathGenerated(
|
||||
}
|
||||
|
||||
// Running the DownloadTargetCallback with an empty FilePath signals that the
|
||||
// download should be cancelled.
|
||||
// If user cancels the file save dialog, run the callback with empty FilePath.
|
||||
callback.Run(path, download::DownloadItem::TARGET_DISPOSITION_PROMPT,
|
||||
download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, path,
|
||||
path.empty() ? download::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED
|
||||
: download::DOWNLOAD_INTERRUPT_REASON_NONE);
|
||||
// download should be cancelled. If user cancels the file save dialog, run
|
||||
// the callback with empty FilePath.
|
||||
const base::FilePath download_path = result ? path : base::FilePath();
|
||||
const auto interrupt_reason =
|
||||
download_path.empty() ? download::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED
|
||||
: download::DOWNLOAD_INTERRUPT_REASON_NONE;
|
||||
download_callback.Run(download_path,
|
||||
download::DownloadItem::TARGET_DISPOSITION_PROMPT,
|
||||
download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
|
||||
download_path, interrupt_reason);
|
||||
}
|
||||
|
||||
void AtomDownloadManagerDelegate::Shutdown() {
|
||||
|
||||
@@ -25,10 +25,6 @@ class AtomDownloadManagerDelegate : public content::DownloadManagerDelegate {
|
||||
explicit AtomDownloadManagerDelegate(content::DownloadManager* manager);
|
||||
~AtomDownloadManagerDelegate() override;
|
||||
|
||||
void OnDownloadPathGenerated(uint32_t download_id,
|
||||
const content::DownloadTargetCallback& callback,
|
||||
const base::FilePath& default_path);
|
||||
|
||||
// content::DownloadManagerDelegate:
|
||||
void Shutdown() override;
|
||||
bool DetermineDownloadTarget(
|
||||
@@ -45,6 +41,25 @@ class AtomDownloadManagerDelegate : public content::DownloadManagerDelegate {
|
||||
void GetItemSaveDialogOptions(download::DownloadItem* item,
|
||||
file_dialog::DialogSettings* settings);
|
||||
|
||||
void OnDownloadPathGenerated(uint32_t download_id,
|
||||
const content::DownloadTargetCallback& callback,
|
||||
const base::FilePath& default_path);
|
||||
|
||||
#if defined(MAS_BUILD)
|
||||
void OnDownloadSaveDialogDone(
|
||||
uint32_t download_id,
|
||||
const content::DownloadTargetCallback& download_callback,
|
||||
bool result,
|
||||
const base::FilePath& path,
|
||||
const std::string& bookmark);
|
||||
#else
|
||||
void OnDownloadSaveDialogDone(
|
||||
uint32_t download_id,
|
||||
const content::DownloadTargetCallback& download_callback,
|
||||
bool result,
|
||||
const base::FilePath& path);
|
||||
#endif
|
||||
|
||||
content::DownloadManager* download_manager_;
|
||||
base::WeakPtrFactory<AtomDownloadManagerDelegate> weak_ptr_factory_;
|
||||
|
||||
|
||||
@@ -25,9 +25,6 @@
|
||||
|
||||
namespace atom {
|
||||
|
||||
// Null until/unless the default main message loop is running.
|
||||
base::NoDestructor<base::OnceClosure> g_quit_main_message_loop;
|
||||
|
||||
Browser::LoginItemSettings::LoginItemSettings() = default;
|
||||
Browser::LoginItemSettings::~LoginItemSettings() = default;
|
||||
Browser::LoginItemSettings::LoginItemSettings(const LoginItemSettings& other) =
|
||||
@@ -95,11 +92,12 @@ void Browser::Shutdown() {
|
||||
for (BrowserObserver& observer : observers_)
|
||||
observer.OnQuit();
|
||||
|
||||
if (*g_quit_main_message_loop) {
|
||||
std::move(*g_quit_main_message_loop).Run();
|
||||
if (quit_main_message_loop_) {
|
||||
std::move(quit_main_message_loop_).Run();
|
||||
} else {
|
||||
// There is no message loop available so we are in early stage.
|
||||
exit(0);
|
||||
// There is no message loop available so we are in early stage, wait until
|
||||
// the quit_main_message_loop_ is available.
|
||||
// Exiting now would leave defunct processes behind.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,7 +194,10 @@ void Browser::PreMainMessageLoopRun() {
|
||||
}
|
||||
|
||||
void Browser::SetMainMessageLoopQuitClosure(base::OnceClosure quit_closure) {
|
||||
*g_quit_main_message_loop = std::move(quit_closure);
|
||||
if (is_shutdown_)
|
||||
std::move(quit_closure).Run();
|
||||
else
|
||||
quit_main_message_loop_ = std::move(quit_closure);
|
||||
}
|
||||
|
||||
void Browser::NotifyAndShutdown() {
|
||||
|
||||
@@ -244,7 +244,7 @@ class Browser : public WindowListObserver {
|
||||
|
||||
// Stores the supplied |quit_closure|, to be run when the last Browser
|
||||
// instance is destroyed.
|
||||
static void SetMainMessageLoopQuitClosure(base::OnceClosure quit_closure);
|
||||
void SetMainMessageLoopQuitClosure(base::OnceClosure quit_closure);
|
||||
|
||||
void AddObserver(BrowserObserver* obs) { observers_.AddObserver(obs); }
|
||||
|
||||
@@ -287,6 +287,9 @@ class Browser : public WindowListObserver {
|
||||
// The browser is being shutdown.
|
||||
bool is_shutdown_ = false;
|
||||
|
||||
// Null until/unless the default main message loop is running.
|
||||
base::OnceClosure quit_main_message_loop_;
|
||||
|
||||
int badge_count_ = 0;
|
||||
|
||||
util::Promise* ready_promise_ = nullptr;
|
||||
|
||||
@@ -206,7 +206,7 @@ void CommonWebContentsDelegate::SetOwnerWindow(
|
||||
NativeWindow* owner_window) {
|
||||
if (owner_window) {
|
||||
owner_window_ = owner_window->GetWeakPtr();
|
||||
#if defined(TOOLKIT_VIEWS) && !defined(OS_MACOSX)
|
||||
#if defined(TOOLKIT_VIEWS)
|
||||
autofill_popup_.reset(new AutofillPopup());
|
||||
#endif
|
||||
NativeWindowRelay::CreateForWebContents(web_contents,
|
||||
@@ -619,4 +619,24 @@ void CommonWebContentsDelegate::SetHtmlApiFullscreen(bool enter_fullscreen) {
|
||||
native_fullscreen_ = false;
|
||||
}
|
||||
|
||||
void CommonWebContentsDelegate::ShowAutofillPopup(
|
||||
content::RenderFrameHost* frame_host,
|
||||
content::RenderFrameHost* embedder_frame_host,
|
||||
bool offscreen,
|
||||
const gfx::RectF& bounds,
|
||||
const std::vector<base::string16>& values,
|
||||
const std::vector<base::string16>& labels) {
|
||||
if (!owner_window())
|
||||
return;
|
||||
|
||||
autofill_popup_->CreateView(frame_host, embedder_frame_host, offscreen,
|
||||
owner_window()->content_view(), bounds);
|
||||
autofill_popup_->SetItems(values, labels);
|
||||
}
|
||||
|
||||
void CommonWebContentsDelegate::HideAutofillPopup() {
|
||||
if (autofill_popup_)
|
||||
autofill_popup_->Hide();
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include "content/public/browser/web_contents_delegate.h"
|
||||
#include "electron/buildflags/buildflags.h"
|
||||
|
||||
#if defined(TOOLKIT_VIEWS) && !defined(OS_MACOSX)
|
||||
#if defined(TOOLKIT_VIEWS)
|
||||
#include "atom/browser/ui/autofill_popup.h"
|
||||
#endif
|
||||
|
||||
@@ -105,7 +105,7 @@ class CommonWebContentsDelegate : public content::WebContentsDelegate,
|
||||
const content::NativeWebKeyboardEvent& event) override;
|
||||
|
||||
// Autofill related events.
|
||||
#if defined(TOOLKIT_VIEWS) && !defined(OS_MACOSX)
|
||||
#if defined(TOOLKIT_VIEWS)
|
||||
void ShowAutofillPopup(content::RenderFrameHost* frame_host,
|
||||
content::RenderFrameHost* embedder_frame_host,
|
||||
bool offscreen,
|
||||
@@ -175,7 +175,7 @@ class CommonWebContentsDelegate : public content::WebContentsDelegate,
|
||||
bool native_fullscreen_ = false;
|
||||
|
||||
// UI related helper classes.
|
||||
#if defined(TOOLKIT_VIEWS) && !defined(OS_MACOSX)
|
||||
#if defined(TOOLKIT_VIEWS)
|
||||
std::unique_ptr<AutofillPopup> autofill_popup_;
|
||||
#endif
|
||||
std::unique_ptr<WebDialogHelper> web_dialog_helper_;
|
||||
|
||||
@@ -41,27 +41,6 @@ bool CommonWebContentsDelegate::HandleKeyboardEvent(
|
||||
return false;
|
||||
}
|
||||
|
||||
void CommonWebContentsDelegate::ShowAutofillPopup(
|
||||
content::RenderFrameHost* frame_host,
|
||||
content::RenderFrameHost* embedder_frame_host,
|
||||
bool offscreen,
|
||||
const gfx::RectF& bounds,
|
||||
const std::vector<base::string16>& values,
|
||||
const std::vector<base::string16>& labels) {
|
||||
if (!owner_window())
|
||||
return;
|
||||
|
||||
auto* window = static_cast<NativeWindowViews*>(owner_window());
|
||||
autofill_popup_->CreateView(frame_host, embedder_frame_host, offscreen,
|
||||
window->content_view(), bounds);
|
||||
autofill_popup_->SetItems(values, labels);
|
||||
}
|
||||
|
||||
void CommonWebContentsDelegate::HideAutofillPopup() {
|
||||
if (autofill_popup_)
|
||||
autofill_popup_->Hide();
|
||||
}
|
||||
|
||||
gfx::ImageSkia CommonWebContentsDelegate::GetDevToolsWindowIcon() {
|
||||
if (!owner_window())
|
||||
return gfx::ImageSkia();
|
||||
|
||||
@@ -21,6 +21,8 @@ namespace atom {
|
||||
enum AutoResizeFlags {
|
||||
kAutoResizeWidth = 0x1,
|
||||
kAutoResizeHeight = 0x2,
|
||||
kAutoResizeHorizontal = 0x4,
|
||||
kAutoResizeVertical = 0x8,
|
||||
};
|
||||
|
||||
class InspectableWebContents;
|
||||
|
||||
@@ -175,6 +175,14 @@ void NativeBrowserViewMac::SetAutoResizeFlags(uint8_t flags) {
|
||||
if (flags & kAutoResizeHeight) {
|
||||
autoresizing_mask |= NSViewHeightSizable;
|
||||
}
|
||||
if (flags & kAutoResizeHorizontal) {
|
||||
autoresizing_mask |=
|
||||
NSViewMaxXMargin | NSViewMinXMargin | NSViewWidthSizable;
|
||||
}
|
||||
if (flags & kAutoResizeVertical) {
|
||||
autoresizing_mask |=
|
||||
NSViewMaxYMargin | NSViewMinYMargin | NSViewHeightSizable;
|
||||
}
|
||||
|
||||
auto* view =
|
||||
GetInspectableWebContentsView()->GetNativeView().GetNativeNSView();
|
||||
|
||||
@@ -19,11 +19,82 @@ NativeBrowserViewViews::~NativeBrowserViewViews() {}
|
||||
|
||||
void NativeBrowserViewViews::SetAutoResizeFlags(uint8_t flags) {
|
||||
auto_resize_flags_ = flags;
|
||||
ResetAutoResizeProportions();
|
||||
}
|
||||
|
||||
void NativeBrowserViewViews::SetAutoResizeProportions(
|
||||
const gfx::Size& window_size) {
|
||||
if ((auto_resize_flags_ & AutoResizeFlags::kAutoResizeHorizontal) &&
|
||||
!auto_horizontal_proportion_set_) {
|
||||
auto* view = GetInspectableWebContentsView()->GetView();
|
||||
auto view_bounds = view->bounds();
|
||||
auto_horizontal_proportion_width_ =
|
||||
static_cast<float>(window_size.width()) /
|
||||
static_cast<float>(view_bounds.width());
|
||||
auto_horizontal_proportion_left_ = static_cast<float>(window_size.width()) /
|
||||
static_cast<float>(view_bounds.x());
|
||||
auto_horizontal_proportion_set_ = true;
|
||||
}
|
||||
if ((auto_resize_flags_ & AutoResizeFlags::kAutoResizeVertical) &&
|
||||
!auto_vertical_proportion_set_) {
|
||||
auto* view = GetInspectableWebContentsView()->GetView();
|
||||
auto view_bounds = view->bounds();
|
||||
auto_vertical_proportion_height_ =
|
||||
static_cast<float>(window_size.height()) /
|
||||
static_cast<float>(view_bounds.height());
|
||||
auto_vertical_proportion_top_ = static_cast<float>(window_size.height()) /
|
||||
static_cast<float>(view_bounds.y());
|
||||
auto_vertical_proportion_set_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void NativeBrowserViewViews::AutoResize(const gfx::Rect& new_window,
|
||||
int width_delta,
|
||||
int height_delta) {
|
||||
auto* view = GetInspectableWebContentsView()->GetView();
|
||||
const auto flags = GetAutoResizeFlags();
|
||||
if (!(flags & kAutoResizeWidth)) {
|
||||
width_delta = 0;
|
||||
}
|
||||
if (!(flags & kAutoResizeHeight)) {
|
||||
height_delta = 0;
|
||||
}
|
||||
if (height_delta || width_delta) {
|
||||
auto new_view_size = view->size();
|
||||
new_view_size.set_width(new_view_size.width() + width_delta);
|
||||
new_view_size.set_height(new_view_size.height() + height_delta);
|
||||
view->SetSize(new_view_size);
|
||||
}
|
||||
auto new_view_bounds = view->bounds();
|
||||
if (flags & kAutoResizeHorizontal) {
|
||||
new_view_bounds.set_width(new_window.width() /
|
||||
auto_horizontal_proportion_width_);
|
||||
new_view_bounds.set_x(new_window.width() /
|
||||
auto_horizontal_proportion_left_);
|
||||
}
|
||||
if (flags & kAutoResizeVertical) {
|
||||
new_view_bounds.set_height(new_window.height() /
|
||||
auto_vertical_proportion_height_);
|
||||
new_view_bounds.set_y(new_window.height() / auto_vertical_proportion_top_);
|
||||
}
|
||||
if ((flags & kAutoResizeHorizontal) || (flags & kAutoResizeVertical)) {
|
||||
view->SetBoundsRect(new_view_bounds);
|
||||
}
|
||||
}
|
||||
|
||||
void NativeBrowserViewViews::ResetAutoResizeProportions() {
|
||||
if (auto_resize_flags_ & AutoResizeFlags::kAutoResizeHorizontal) {
|
||||
auto_horizontal_proportion_set_ = false;
|
||||
}
|
||||
if (auto_resize_flags_ & AutoResizeFlags::kAutoResizeVertical) {
|
||||
auto_vertical_proportion_set_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
void NativeBrowserViewViews::SetBounds(const gfx::Rect& bounds) {
|
||||
auto* view = GetInspectableWebContentsView()->GetView();
|
||||
view->SetBoundsRect(bounds);
|
||||
ResetAutoResizeProportions();
|
||||
}
|
||||
|
||||
void NativeBrowserViewViews::SetBackgroundColor(SkColor color) {
|
||||
|
||||
@@ -15,13 +15,29 @@ class NativeBrowserViewViews : public NativeBrowserView {
|
||||
InspectableWebContents* inspectable_web_contents);
|
||||
~NativeBrowserViewViews() override;
|
||||
|
||||
void SetAutoResizeProportions(const gfx::Size& window_size);
|
||||
void AutoResize(const gfx::Rect& new_window,
|
||||
int width_delta,
|
||||
int height_delta);
|
||||
uint8_t GetAutoResizeFlags() { return auto_resize_flags_; }
|
||||
|
||||
// NativeBrowserView:
|
||||
void SetAutoResizeFlags(uint8_t flags) override;
|
||||
void SetBounds(const gfx::Rect& bounds) override;
|
||||
void SetBackgroundColor(SkColor color) override;
|
||||
|
||||
private:
|
||||
uint8_t auto_resize_flags_;
|
||||
void ResetAutoResizeProportions();
|
||||
|
||||
uint8_t auto_resize_flags_ = 0;
|
||||
|
||||
bool auto_horizontal_proportion_set_ = false;
|
||||
float auto_horizontal_proportion_width_ = 0.;
|
||||
float auto_horizontal_proportion_left_ = 0.;
|
||||
|
||||
bool auto_vertical_proportion_set_ = false;
|
||||
float auto_vertical_proportion_height_ = 0.;
|
||||
float auto_vertical_proportion_top_ = 0.;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(NativeBrowserViewViews);
|
||||
};
|
||||
|
||||
@@ -82,8 +82,13 @@ void NativeWindow::InitFromOptions(const mate::Dictionary& options) {
|
||||
} else if (options.Get(options::kCenter, ¢er) && center) {
|
||||
Center();
|
||||
}
|
||||
|
||||
bool use_content_size = false;
|
||||
options.Get(options::kUseContentSize, &use_content_size);
|
||||
|
||||
// On Linux and Window we may already have maximum size defined.
|
||||
extensions::SizeConstraints size_constraints(GetContentSizeConstraints());
|
||||
extensions::SizeConstraints size_constraints(
|
||||
use_content_size ? GetContentSizeConstraints() : GetSizeConstraints());
|
||||
int min_height = 0, min_width = 0;
|
||||
if (options.Get(options::kMinHeight, &min_height) |
|
||||
options.Get(options::kMinWidth, &min_width)) {
|
||||
@@ -94,8 +99,6 @@ void NativeWindow::InitFromOptions(const mate::Dictionary& options) {
|
||||
options.Get(options::kMaxWidth, &max_width)) {
|
||||
size_constraints.set_maximum_size(gfx::Size(max_width, max_height));
|
||||
}
|
||||
bool use_content_size = false;
|
||||
options.Get(options::kUseContentSize, &use_content_size);
|
||||
if (use_content_size) {
|
||||
SetContentSizeConstraints(size_constraints);
|
||||
} else {
|
||||
|
||||
@@ -113,9 +113,7 @@ class NativeWindow : public base::SupportsUserData,
|
||||
virtual double GetSheetOffsetX();
|
||||
virtual double GetSheetOffsetY();
|
||||
virtual void SetResizable(bool resizable) = 0;
|
||||
#if defined(OS_WIN) || defined(OS_MACOSX)
|
||||
virtual void MoveTop() = 0;
|
||||
#endif
|
||||
virtual bool IsResizable() = 0;
|
||||
virtual void SetMovable(bool movable) = 0;
|
||||
virtual bool IsMovable() = 0;
|
||||
|
||||
@@ -1131,17 +1131,23 @@ void NativeWindowMac::SetProgressBar(double progress,
|
||||
const NativeWindow::ProgressState state) {
|
||||
NSDockTile* dock_tile = [NSApp dockTile];
|
||||
|
||||
// Sometimes macOS would install a default contentView for dock, we must
|
||||
// verify whether NSProgressIndicator has been installed.
|
||||
bool first_time = !dock_tile.contentView ||
|
||||
[[dock_tile.contentView subviews] count] == 0 ||
|
||||
![[[dock_tile.contentView subviews] lastObject]
|
||||
isKindOfClass:[NSProgressIndicator class]];
|
||||
|
||||
// For the first time API invoked, we need to create a ContentView in
|
||||
// DockTile.
|
||||
if (dock_tile.contentView == nullptr) {
|
||||
NSImageView* image_view = [[NSImageView alloc] init];
|
||||
if (first_time) {
|
||||
NSImageView* image_view = [[[NSImageView alloc] init] autorelease];
|
||||
[image_view setImage:[NSApp applicationIconImage]];
|
||||
[dock_tile setContentView:image_view];
|
||||
}
|
||||
|
||||
if ([[dock_tile.contentView subviews] count] == 0) {
|
||||
NSProgressIndicator* progress_indicator = [[AtomProgressBar alloc]
|
||||
initWithFrame:NSMakeRect(0.0f, 0.0f, dock_tile.size.width, 15.0)];
|
||||
NSRect frame = NSMakeRect(0.0f, 0.0f, dock_tile.size.width, 15.0);
|
||||
NSProgressIndicator* progress_indicator =
|
||||
[[[AtomProgressBar alloc] initWithFrame:frame] autorelease];
|
||||
[progress_indicator setStyle:NSProgressIndicatorBarStyle];
|
||||
[progress_indicator setIndeterminate:NO];
|
||||
[progress_indicator setBezeled:YES];
|
||||
@@ -1152,7 +1158,7 @@ void NativeWindowMac::SetProgressBar(double progress,
|
||||
}
|
||||
|
||||
NSProgressIndicator* progress_indicator = static_cast<NSProgressIndicator*>(
|
||||
[[[dock_tile contentView] subviews] objectAtIndex:0]);
|
||||
[[[dock_tile contentView] subviews] lastObject]);
|
||||
if (progress < 0) {
|
||||
[progress_indicator setHidden:YES];
|
||||
} else if (progress > 1) {
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "ui/aura/window_tree_host.h"
|
||||
#include "ui/base/hit_test.h"
|
||||
#include "ui/gfx/image/image.h"
|
||||
#include "ui/gfx/native_widget_types.h"
|
||||
#include "ui/views/background.h"
|
||||
#include "ui/views/controls/webview/unhandled_keyboard_event_handler.h"
|
||||
#include "ui/views/controls/webview/webview.h"
|
||||
@@ -80,6 +81,27 @@ void FlipWindowStyle(HWND handle, bool on, DWORD flag) {
|
||||
style &= ~flag;
|
||||
::SetWindowLong(handle, GWL_STYLE, style);
|
||||
}
|
||||
|
||||
// Similar to the ones in display::win::ScreenWin, but with rounded values
|
||||
// These help to avoid problems that arise from unresizable windows where the
|
||||
// original ceil()-ed values can cause calculation errors, since converting
|
||||
// both ways goes through a ceil() call. Related issue: #15816
|
||||
gfx::Rect ScreenToDIPRect(HWND hwnd, const gfx::Rect& pixel_bounds) {
|
||||
float scale_factor = display::win::ScreenWin::GetScaleFactorForHWND(hwnd);
|
||||
gfx::Rect dip_rect = ScaleToRoundedRect(pixel_bounds, 1.0f / scale_factor);
|
||||
dip_rect.set_origin(
|
||||
display::win::ScreenWin::ScreenToDIPRect(hwnd, pixel_bounds).origin());
|
||||
return dip_rect;
|
||||
}
|
||||
|
||||
gfx::Rect DIPToScreenRect(HWND hwnd, const gfx::Rect& pixel_bounds) {
|
||||
float scale_factor = display::win::ScreenWin::GetScaleFactorForHWND(hwnd);
|
||||
gfx::Rect screen_rect = ScaleToRoundedRect(pixel_bounds, scale_factor);
|
||||
screen_rect.set_origin(
|
||||
display::win::ScreenWin::DIPToScreenRect(hwnd, pixel_bounds).origin());
|
||||
return screen_rect;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
class NativeWindowClientView : public views::ClientView {
|
||||
@@ -238,7 +260,7 @@ NativeWindowViews::NativeWindowViews(const mate::Dictionary& options,
|
||||
if (!has_frame()) {
|
||||
// Set Window style so that we get a minimize and maximize animation when
|
||||
// frameless.
|
||||
DWORD frame_style = WS_CAPTION;
|
||||
DWORD frame_style = WS_CAPTION | WS_OVERLAPPED;
|
||||
if (resizable_)
|
||||
frame_style |= WS_THICKFRAME;
|
||||
if (minimizable_)
|
||||
@@ -635,15 +657,19 @@ void NativeWindowViews::SetResizable(bool resizable) {
|
||||
resizable_ = resizable;
|
||||
}
|
||||
|
||||
#if defined(OS_WIN)
|
||||
void NativeWindowViews::MoveTop() {
|
||||
// TODO(julien.isorce): fix chromium in order to use existing
|
||||
// widget()->StackAtTop().
|
||||
#if defined(OS_WIN)
|
||||
gfx::Point pos = GetPosition();
|
||||
gfx::Size size = GetSize();
|
||||
::SetWindowPos(GetAcceleratedWidget(), HWND_TOP, pos.x(), pos.y(),
|
||||
size.width(), size.height(),
|
||||
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
|
||||
}
|
||||
#elif defined(USE_X11)
|
||||
atom::MoveWindowToForeground(GetAcceleratedWidget());
|
||||
#endif
|
||||
}
|
||||
|
||||
bool NativeWindowViews::IsResizable() {
|
||||
#if defined(OS_WIN)
|
||||
@@ -1076,7 +1102,10 @@ bool NativeWindowViews::IsVisibleOnAllWorkspaces() {
|
||||
}
|
||||
|
||||
gfx::AcceleratedWidget NativeWindowViews::GetAcceleratedWidget() const {
|
||||
return GetNativeWindow()->GetHost()->GetAcceleratedWidget();
|
||||
if (GetNativeWindow() && GetNativeWindow()->GetHost())
|
||||
return GetNativeWindow()->GetHost()->GetAcceleratedWidget();
|
||||
else
|
||||
return gfx::kNullAcceleratedWidget;
|
||||
}
|
||||
|
||||
NativeWindowHandle NativeWindowViews::GetNativeWindowHandle() const {
|
||||
@@ -1091,8 +1120,8 @@ gfx::Rect NativeWindowViews::ContentBoundsToWindowBounds(
|
||||
gfx::Rect window_bounds(bounds);
|
||||
#if defined(OS_WIN)
|
||||
HWND hwnd = GetAcceleratedWidget();
|
||||
gfx::Rect dpi_bounds = display::win::ScreenWin::DIPToScreenRect(hwnd, bounds);
|
||||
window_bounds = display::win::ScreenWin::ScreenToDIPRect(
|
||||
gfx::Rect dpi_bounds = DIPToScreenRect(hwnd, bounds);
|
||||
window_bounds = ScreenToDIPRect(
|
||||
hwnd,
|
||||
widget()->non_client_view()->GetWindowBoundsForClientBounds(dpi_bounds));
|
||||
#endif
|
||||
@@ -1113,8 +1142,7 @@ gfx::Rect NativeWindowViews::WindowBoundsToContentBounds(
|
||||
gfx::Rect content_bounds(bounds);
|
||||
#if defined(OS_WIN)
|
||||
HWND hwnd = GetAcceleratedWidget();
|
||||
content_bounds.set_size(
|
||||
display::win::ScreenWin::DIPToScreenSize(hwnd, content_bounds.size()));
|
||||
content_bounds.set_size(DIPToScreenRect(hwnd, content_bounds).size());
|
||||
RECT rect;
|
||||
SetRectEmpty(&rect);
|
||||
DWORD style = ::GetWindowLong(hwnd, GWL_STYLE);
|
||||
@@ -1122,8 +1150,7 @@ gfx::Rect NativeWindowViews::WindowBoundsToContentBounds(
|
||||
AdjustWindowRectEx(&rect, style, FALSE, ex_style);
|
||||
content_bounds.set_width(content_bounds.width() - (rect.right - rect.left));
|
||||
content_bounds.set_height(content_bounds.height() - (rect.bottom - rect.top));
|
||||
content_bounds.set_size(
|
||||
display::win::ScreenWin::ScreenToDIPSize(hwnd, content_bounds.size()));
|
||||
content_bounds.set_size(ScreenToDIPRect(hwnd, content_bounds).size());
|
||||
#endif
|
||||
|
||||
if (root_view_->HasMenu() && root_view_->IsMenuBarVisible()) {
|
||||
@@ -1176,26 +1203,6 @@ void NativeWindowViews::OnWidgetActivationChanged(views::Widget* changed_widget,
|
||||
root_view_->ResetAltState();
|
||||
}
|
||||
|
||||
void NativeWindowViews::AutoresizeBrowserView(int width_delta,
|
||||
int height_delta,
|
||||
NativeBrowserView* browser_view) {
|
||||
const auto flags =
|
||||
static_cast<NativeBrowserViewViews*>(browser_view)->GetAutoResizeFlags();
|
||||
if (!(flags & kAutoResizeWidth)) {
|
||||
width_delta = 0;
|
||||
}
|
||||
if (!(flags & kAutoResizeHeight)) {
|
||||
height_delta = 0;
|
||||
}
|
||||
if (height_delta || width_delta) {
|
||||
auto* view = browser_view->GetInspectableWebContentsView()->GetView();
|
||||
auto new_view_size = view->size();
|
||||
new_view_size.set_width(new_view_size.width() + width_delta);
|
||||
new_view_size.set_height(new_view_size.height() + height_delta);
|
||||
view->SetSize(new_view_size);
|
||||
}
|
||||
}
|
||||
|
||||
void NativeWindowViews::OnWidgetBoundsChanged(views::Widget* changed_widget,
|
||||
const gfx::Rect& bounds) {
|
||||
if (changed_widget != widget())
|
||||
@@ -1208,7 +1215,10 @@ void NativeWindowViews::OnWidgetBoundsChanged(views::Widget* changed_widget,
|
||||
int width_delta = new_bounds.width() - widget_size_.width();
|
||||
int height_delta = new_bounds.height() - widget_size_.height();
|
||||
for (NativeBrowserView* item : browser_views()) {
|
||||
AutoresizeBrowserView(width_delta, height_delta, item);
|
||||
NativeBrowserViewViews* native_view =
|
||||
static_cast<NativeBrowserViewViews*>(item);
|
||||
native_view->SetAutoResizeProportions(widget_size_);
|
||||
native_view->AutoResize(new_bounds, width_delta, height_delta);
|
||||
}
|
||||
|
||||
NotifyWindowResize();
|
||||
|
||||
@@ -74,9 +74,7 @@ class NativeWindowViews : public NativeWindow,
|
||||
void SetContentSizeConstraints(
|
||||
const extensions::SizeConstraints& size_constraints) override;
|
||||
void SetResizable(bool resizable) override;
|
||||
#if defined(OS_WIN)
|
||||
void MoveTop() override;
|
||||
#endif
|
||||
bool IsResizable() override;
|
||||
void SetMovable(bool movable) override;
|
||||
bool IsMovable() override;
|
||||
@@ -158,10 +156,8 @@ class NativeWindowViews : public NativeWindow,
|
||||
void OnWidgetActivationChanged(views::Widget* widget, bool active) override;
|
||||
void OnWidgetBoundsChanged(views::Widget* widget,
|
||||
const gfx::Rect& bounds) override;
|
||||
void AutoresizeBrowserView(int width_delta,
|
||||
int height_delta,
|
||||
NativeBrowserView* browser_view);
|
||||
void OnWidgetDestroying(views::Widget* widget) override;
|
||||
|
||||
// views::WidgetDelegate:
|
||||
void DeleteDelegate() override;
|
||||
views::View* GetInitiallyFocusedView() override;
|
||||
@@ -244,6 +240,8 @@ class NativeWindowViews : public NativeWindow,
|
||||
|
||||
ui::WindowShowState last_window_state_;
|
||||
|
||||
gfx::Rect last_normal_placement_bounds_;
|
||||
|
||||
// There's an issue with restore on Windows, that sometimes causes the Window
|
||||
// to receive the wrong size (#2498). To circumvent that, we keep tabs on the
|
||||
// size of the window while in the normal state (not maximized, minimized or
|
||||
|
||||
@@ -4,9 +4,12 @@
|
||||
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/browser/native_window_views.h"
|
||||
#include "atom/browser/ui/views/root_view.h"
|
||||
#include "atom/common/atom_constants.h"
|
||||
#include "content/public/browser/browser_accessibility_state.h"
|
||||
#include "ui/base/win/accessibility_misc_utils.h"
|
||||
#include "ui/display/win/screen_win.h"
|
||||
#include "ui/gfx/geometry/insets.h"
|
||||
|
||||
// Must be included after other Windows headers.
|
||||
#include <UIAutomationCoreApi.h>
|
||||
@@ -183,6 +186,48 @@ bool NativeWindowViews::PreHandleMSG(UINT message,
|
||||
|
||||
return false;
|
||||
}
|
||||
case WM_GETMINMAXINFO: {
|
||||
WINDOWPLACEMENT wp;
|
||||
wp.length = sizeof(WINDOWPLACEMENT);
|
||||
|
||||
// We do this to work around a Windows bug, where the minimized Window
|
||||
// would report that the closest display to it is not the one that it was
|
||||
// previously on (but the leftmost one instead). We restore the position
|
||||
// of the window during the restore operation, this way chromium can
|
||||
// use the proper display to calculate the scale factor to use.
|
||||
if (!last_normal_placement_bounds_.IsEmpty() &&
|
||||
GetWindowPlacement(GetAcceleratedWidget(), &wp)) {
|
||||
last_normal_placement_bounds_.set_size(gfx::Size(0, 0));
|
||||
wp.rcNormalPosition = last_normal_placement_bounds_.ToRECT();
|
||||
SetWindowPlacement(GetAcceleratedWidget(), &wp);
|
||||
|
||||
last_normal_placement_bounds_ = gfx::Rect();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
case WM_NCCALCSIZE: {
|
||||
if (!has_frame() && w_param == TRUE) {
|
||||
NCCALCSIZE_PARAMS* params =
|
||||
reinterpret_cast<NCCALCSIZE_PARAMS*>(l_param);
|
||||
RECT PROPOSED = params->rgrc[0];
|
||||
RECT BEFORE = params->rgrc[1];
|
||||
|
||||
// We need to call the default to have cascade and tile windows
|
||||
// working
|
||||
// (https://github.com/rossy/borderless-window/blob/master/borderless-window.c#L239),
|
||||
// but we need to provide the proposed original value as suggested in
|
||||
// https://blogs.msdn.microsoft.com/wpfsdk/2008/09/08/custom-window-chrome-in-wpf/
|
||||
DefWindowProcW(GetAcceleratedWidget(), WM_NCCALCSIZE, w_param, l_param);
|
||||
|
||||
params->rgrc[0] = PROPOSED;
|
||||
params->rgrc[1] = BEFORE;
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
case WM_COMMAND:
|
||||
// Handle thumbar button click message.
|
||||
if (HIWORD(w_param) == THBN_CLICKED)
|
||||
@@ -258,15 +303,40 @@ void NativeWindowViews::HandleSizeEvent(WPARAM w_param, LPARAM l_param) {
|
||||
// Here we handle the WM_SIZE event in order to figure out what is the current
|
||||
// window state and notify the user accordingly.
|
||||
switch (w_param) {
|
||||
case SIZE_MAXIMIZED:
|
||||
case SIZE_MAXIMIZED: {
|
||||
// Frameless maximized windows are size compensated by Windows for a
|
||||
// border that's not actually there, so we must conter-compensate.
|
||||
// https://blogs.msdn.microsoft.com/wpfsdk/2008/09/08/custom-window-chrome-in-wpf/
|
||||
if (!has_frame()) {
|
||||
float scale_factor = display::win::ScreenWin::GetScaleFactorForHWND(
|
||||
GetAcceleratedWidget());
|
||||
|
||||
int border =
|
||||
GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
|
||||
if (!thick_frame_) {
|
||||
border -= GetSystemMetrics(SM_CXBORDER);
|
||||
}
|
||||
root_view_->SetInsets(gfx::Insets(border).Scale(1.0f / scale_factor));
|
||||
}
|
||||
|
||||
last_window_state_ = ui::SHOW_STATE_MAXIMIZED;
|
||||
if (consecutive_moves_) {
|
||||
last_normal_bounds_ = last_normal_bounds_before_move_;
|
||||
}
|
||||
|
||||
NotifyWindowMaximize();
|
||||
break;
|
||||
}
|
||||
case SIZE_MINIMIZED:
|
||||
last_window_state_ = ui::SHOW_STATE_MINIMIZED;
|
||||
|
||||
WINDOWPLACEMENT wp;
|
||||
wp.length = sizeof(WINDOWPLACEMENT);
|
||||
|
||||
if (GetWindowPlacement(GetAcceleratedWidget(), &wp)) {
|
||||
last_normal_placement_bounds_ = gfx::Rect(wp.rcNormalPosition);
|
||||
}
|
||||
|
||||
NotifyWindowMinimize();
|
||||
break;
|
||||
case SIZE_RESTORED:
|
||||
@@ -278,10 +348,7 @@ void NativeWindowViews::HandleSizeEvent(WPARAM w_param, LPARAM l_param) {
|
||||
switch (last_window_state_) {
|
||||
case ui::SHOW_STATE_MAXIMIZED:
|
||||
last_window_state_ = ui::SHOW_STATE_NORMAL;
|
||||
|
||||
// Don't force out last known bounds onto the window as Windows
|
||||
// actually gets these correct
|
||||
|
||||
root_view_->SetInsets(gfx::Insets(0));
|
||||
NotifyWindowUnmaximize();
|
||||
break;
|
||||
case ui::SHOW_STATE_MINIMIZED:
|
||||
@@ -293,7 +360,9 @@ void NativeWindowViews::HandleSizeEvent(WPARAM w_param, LPARAM l_param) {
|
||||
|
||||
// When the window is restored we resize it to the previous known
|
||||
// normal size.
|
||||
SetBounds(last_normal_bounds_, false);
|
||||
if (has_frame()) {
|
||||
SetBounds(last_normal_bounds_, false);
|
||||
}
|
||||
|
||||
NotifyWindowRestore();
|
||||
}
|
||||
|
||||
@@ -141,6 +141,7 @@ void URLRequestStreamJob::StartAsync(
|
||||
}
|
||||
|
||||
void URLRequestStreamJob::OnData(std::vector<char>&& buffer) { // NOLINT
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
||||
if (write_buffer_.empty()) {
|
||||
// Quick branch without copying.
|
||||
write_buffer_ = std::move(buffer);
|
||||
@@ -175,7 +176,7 @@ void URLRequestStreamJob::OnError(int error) {
|
||||
int URLRequestStreamJob::ReadRawData(net::IOBuffer* dest, int dest_size) {
|
||||
response_start_time_ = base::TimeTicks::Now();
|
||||
|
||||
if (ended_)
|
||||
if (ended_ && write_buffer_.empty())
|
||||
return 0;
|
||||
|
||||
// When write_buffer_ is empty, there is no data valable yet, we have to save
|
||||
|
||||
@@ -252,6 +252,50 @@ class AtomBeginFrameTimer : public viz::DelayBasedTimeSourceClient {
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomBeginFrameTimer);
|
||||
};
|
||||
|
||||
#if !defined(OS_MACOSX)
|
||||
class AtomDelegatedFrameHostClient : public content::DelegatedFrameHostClient {
|
||||
public:
|
||||
explicit AtomDelegatedFrameHostClient(OffScreenRenderWidgetHostView* view)
|
||||
: view_(view) {}
|
||||
|
||||
ui::Layer* DelegatedFrameHostGetLayer() const override {
|
||||
return view_->GetRootLayer();
|
||||
}
|
||||
|
||||
bool DelegatedFrameHostIsVisible() const override {
|
||||
return view_->IsShowing();
|
||||
}
|
||||
|
||||
SkColor DelegatedFrameHostGetGutterColor() const override {
|
||||
if (view_->render_widget_host()->delegate() &&
|
||||
view_->render_widget_host()->delegate()->IsFullscreenForCurrentTab()) {
|
||||
return SK_ColorWHITE;
|
||||
}
|
||||
return *view_->GetBackgroundColor();
|
||||
}
|
||||
|
||||
void OnFrameTokenChanged(uint32_t frame_token) override {
|
||||
view_->render_widget_host()->DidProcessFrame(frame_token);
|
||||
}
|
||||
|
||||
float GetDeviceScaleFactor() const override {
|
||||
return view_->GetDeviceScaleFactor();
|
||||
}
|
||||
|
||||
std::vector<viz::SurfaceId> CollectSurfaceIdsForEviction() override {
|
||||
return view_->render_widget_host()->CollectSurfaceIdsForEviction();
|
||||
}
|
||||
|
||||
void OnBeginFrame(base::TimeTicks frame_time) override {}
|
||||
void InvalidateLocalSurfaceIdOnEviction() override {}
|
||||
|
||||
private:
|
||||
OffScreenRenderWidgetHostView* const view_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomDelegatedFrameHostClient);
|
||||
};
|
||||
#endif // !defined(OS_MACOSX)
|
||||
|
||||
OffScreenRenderWidgetHostView::OffScreenRenderWidgetHostView(
|
||||
bool transparent,
|
||||
bool painting,
|
||||
@@ -274,18 +318,22 @@ OffScreenRenderWidgetHostView::OffScreenRenderWidgetHostView(
|
||||
weak_ptr_factory_(this) {
|
||||
DCHECK(render_widget_host_);
|
||||
bool is_guest_view_hack = parent_host_view_ != nullptr;
|
||||
|
||||
current_device_scale_factor_ = kDefaultScaleFactor;
|
||||
|
||||
#if !defined(OS_MACOSX)
|
||||
local_surface_id_allocator_.GenerateId();
|
||||
local_surface_id_allocation_ =
|
||||
local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation();
|
||||
delegated_frame_host_client_.reset(new AtomDelegatedFrameHostClient(this));
|
||||
delegated_frame_host_ = std::make_unique<content::DelegatedFrameHost>(
|
||||
AllocateFrameSinkId(is_guest_view_hack), this,
|
||||
AllocateFrameSinkId(is_guest_view_hack),
|
||||
delegated_frame_host_client_.get(),
|
||||
true /* should_register_frame_sink_id */);
|
||||
|
||||
root_layer_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR));
|
||||
#endif
|
||||
|
||||
current_device_scale_factor_ = kDefaultScaleFactor;
|
||||
|
||||
local_surface_id_ = local_surface_id_allocator_.GenerateId();
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
last_frame_root_background_color_ = SK_ColorTRANSPARENT;
|
||||
CreatePlatformWidget(is_guest_view_hack);
|
||||
@@ -374,7 +422,7 @@ void OffScreenRenderWidgetHostView::SendBeginFrame(
|
||||
begin_frame_number_++;
|
||||
|
||||
if (renderer_compositor_frame_sink_)
|
||||
renderer_compositor_frame_sink_->OnBeginFrame(begin_frame_args);
|
||||
renderer_compositor_frame_sink_->OnBeginFrame(begin_frame_args, {});
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::InitAsChild(gfx::NativeView) {
|
||||
@@ -433,8 +481,9 @@ void OffScreenRenderWidgetHostView::Show() {
|
||||
browser_compositor_->SetRenderWidgetHostIsHidden(false);
|
||||
#else
|
||||
delegated_frame_host_->AttachToCompositor(compositor_.get());
|
||||
delegated_frame_host_->WasShown(GetLocalSurfaceId(),
|
||||
GetRootLayer()->bounds().size(), false);
|
||||
delegated_frame_host_->WasShown(
|
||||
GetLocalSurfaceIdAllocation().local_surface_id(),
|
||||
GetRootLayer()->bounds().size(), false);
|
||||
#endif
|
||||
|
||||
if (render_widget_host_)
|
||||
@@ -525,19 +574,22 @@ void OffScreenRenderWidgetHostView::TakeFallbackContentFrom(
|
||||
void OffScreenRenderWidgetHostView::DidCreateNewRendererCompositorFrameSink(
|
||||
viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) {
|
||||
renderer_compositor_frame_sink_ = renderer_compositor_frame_sink;
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
browser_compositor_->DidCreateNewRendererCompositorFrameSink(
|
||||
renderer_compositor_frame_sink_);
|
||||
#else
|
||||
if (GetDelegatedFrameHost()) {
|
||||
GetDelegatedFrameHost()->DidCreateNewRendererCompositorFrameSink(
|
||||
renderer_compositor_frame_sink_);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::SubmitCompositorFrame(
|
||||
const viz::LocalSurfaceId& local_surface_id,
|
||||
viz::CompositorFrame frame,
|
||||
base::Optional<viz::HitTestRegionList> hit_test_region_list) {
|
||||
TRACE_EVENT0("electron",
|
||||
"OffScreenRenderWidgetHostView::SubmitCompositorFrame");
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
last_frame_root_background_color_ = frame.metadata.root_background_color;
|
||||
#endif
|
||||
@@ -587,7 +639,7 @@ void OffScreenRenderWidgetHostView::SubmitCompositorFrame(
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::ClearCompositorFrame() {
|
||||
GetDelegatedFrameHost()->ClearDelegatedFrame();
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::ResetFallbackToFirstNavigationSurface() {
|
||||
@@ -667,9 +719,6 @@ void OffScreenRenderWidgetHostView::Destroy() {
|
||||
|
||||
void OffScreenRenderWidgetHostView::SetTooltipText(const base::string16&) {}
|
||||
|
||||
void OffScreenRenderWidgetHostView::SelectionBoundsChanged(
|
||||
const ViewHostMsg_SelectionBounds_Params&) {}
|
||||
|
||||
uint32_t OffScreenRenderWidgetHostView::GetCaptureSequenceNumber() const {
|
||||
return latest_capture_sequence_number_;
|
||||
}
|
||||
@@ -698,7 +747,6 @@ void OffScreenRenderWidgetHostView::InitAsGuest(
|
||||
content::RenderWidgetHostView* parent_host_view,
|
||||
content::RenderWidgetHostViewGuest* guest_view) {
|
||||
parent_host_view_->AddGuestHostView(this);
|
||||
parent_host_view_->RegisterGuestViewFrameSwappedCallback(guest_view);
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::TransformPointToRootSurface(
|
||||
@@ -745,40 +793,6 @@ OffScreenRenderWidgetHostView::CreateViewForWidget(
|
||||
render_widget_host, embedder_host_view, size());
|
||||
}
|
||||
|
||||
#if !defined(OS_MACOSX)
|
||||
ui::Layer* OffScreenRenderWidgetHostView::DelegatedFrameHostGetLayer() const {
|
||||
return const_cast<ui::Layer*>(root_layer_.get());
|
||||
}
|
||||
|
||||
bool OffScreenRenderWidgetHostView::DelegatedFrameHostIsVisible() const {
|
||||
return is_showing_;
|
||||
}
|
||||
|
||||
SkColor OffScreenRenderWidgetHostView::DelegatedFrameHostGetGutterColor()
|
||||
const {
|
||||
if (render_widget_host_->delegate() &&
|
||||
render_widget_host_->delegate()->IsFullscreenForCurrentTab()) {
|
||||
return SK_ColorWHITE;
|
||||
}
|
||||
return background_color_;
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::OnFirstSurfaceActivation(
|
||||
const viz::SurfaceInfo& surface_info) {}
|
||||
|
||||
void OffScreenRenderWidgetHostView::OnBeginFrame(base::TimeTicks frame_time) {}
|
||||
|
||||
void OffScreenRenderWidgetHostView::OnFrameTokenChanged(uint32_t frame_token) {
|
||||
render_widget_host_->DidProcessFrame(frame_token);
|
||||
}
|
||||
|
||||
const viz::LocalSurfaceId& OffScreenRenderWidgetHostView::GetLocalSurfaceId()
|
||||
const {
|
||||
return local_surface_id_;
|
||||
}
|
||||
|
||||
#endif // !defined(OS_MACOSX)
|
||||
|
||||
const viz::FrameSinkId& OffScreenRenderWidgetHostView::GetFrameSinkId() const {
|
||||
return GetDelegatedFrameHost()->frame_sink_id();
|
||||
}
|
||||
@@ -875,21 +889,6 @@ void OffScreenRenderWidgetHostView::ProxyViewDestroyed(
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::RegisterGuestViewFrameSwappedCallback(
|
||||
content::RenderWidgetHostViewGuest* guest_host_view) {
|
||||
guest_host_view->RegisterFrameSwappedCallback(base::BindOnce(
|
||||
&OffScreenRenderWidgetHostView::OnGuestViewFrameSwapped,
|
||||
weak_ptr_factory_.GetWeakPtr(), base::Unretained(guest_host_view)));
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::OnGuestViewFrameSwapped(
|
||||
content::RenderWidgetHostViewGuest* guest_host_view) {
|
||||
InvalidateBounds(gfx::ConvertRectToPixel(current_device_scale_factor_,
|
||||
guest_host_view->GetViewBounds()));
|
||||
|
||||
RegisterGuestViewFrameSwappedCallback(guest_host_view);
|
||||
}
|
||||
|
||||
std::unique_ptr<viz::SoftwareOutputDevice>
|
||||
OffScreenRenderWidgetHostView::CreateSoftwareOutputDevice(
|
||||
ui::Compositor* compositor) {
|
||||
@@ -925,7 +924,7 @@ void OffScreenRenderWidgetHostView::SetNeedsBeginFrames(
|
||||
begin_frame_timer_->SetActive(needs_begin_frames);
|
||||
|
||||
if (software_output_device_) {
|
||||
software_output_device_->SetActive(needs_begin_frames && painting_, false);
|
||||
software_output_device_->SetActive(painting_, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -937,8 +936,6 @@ void OffScreenRenderWidgetHostView::SetWantsAnimateOnlyBeginFrames() {
|
||||
|
||||
void OffScreenRenderWidgetHostView::OnPaint(const gfx::Rect& damage_rect,
|
||||
const SkBitmap& bitmap) {
|
||||
TRACE_EVENT0("electron", "OffScreenRenderWidgetHostView::OnPaint");
|
||||
|
||||
HoldResize();
|
||||
|
||||
if (parent_callback_) {
|
||||
@@ -1023,10 +1020,6 @@ void OffScreenRenderWidgetHostView::SynchronizeVisualProperties() {
|
||||
}
|
||||
|
||||
ResizeRootLayer(false);
|
||||
if (render_widget_host_)
|
||||
render_widget_host_->SynchronizeVisualProperties();
|
||||
GetDelegatedFrameHost()->EmbedSurface(
|
||||
local_surface_id_, size_, cc::DeadlinePolicy::UseDefaultDeadline());
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::SendMouseEvent(
|
||||
@@ -1192,6 +1185,13 @@ ui::Layer* OffScreenRenderWidgetHostView::GetRootLayer() const {
|
||||
return root_layer_.get();
|
||||
}
|
||||
|
||||
#if !defined(OS_MACOSX)
|
||||
const viz::LocalSurfaceIdAllocation&
|
||||
OffScreenRenderWidgetHostView::GetLocalSurfaceIdAllocation() const {
|
||||
return local_surface_id_allocation_;
|
||||
}
|
||||
#endif // defined(OS_MACOSX)
|
||||
|
||||
content::DelegatedFrameHost*
|
||||
OffScreenRenderWidgetHostView::GetDelegatedFrameHost() const {
|
||||
return delegated_frame_host_.get();
|
||||
@@ -1204,11 +1204,6 @@ void OffScreenRenderWidgetHostView::SetupFrameRate(bool force) {
|
||||
|
||||
frame_rate_threshold_us_ = 1000000 / frame_rate_;
|
||||
|
||||
if (GetCompositor()) {
|
||||
GetCompositor()->SetAuthoritativeVSyncInterval(
|
||||
base::TimeDelta::FromMicroseconds(frame_rate_threshold_us_));
|
||||
}
|
||||
|
||||
if (copy_frame_generator_.get()) {
|
||||
copy_frame_generator_->set_frame_rate_threshold_us(
|
||||
frame_rate_threshold_us_);
|
||||
@@ -1257,28 +1252,32 @@ void OffScreenRenderWidgetHostView::ResizeRootLayer(bool force) {
|
||||
size == GetRootLayer()->bounds().size())
|
||||
return;
|
||||
|
||||
const gfx::Size& size_in_pixels =
|
||||
gfx::ConvertSizeToPixel(current_device_scale_factor_, size);
|
||||
|
||||
local_surface_id_ = local_surface_id_allocator_.GenerateId();
|
||||
|
||||
GetRootLayer()->SetBounds(gfx::Rect(size));
|
||||
GetCompositor()->SetScaleAndSize(current_device_scale_factor_, size_in_pixels,
|
||||
local_surface_id_);
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
bool resized = UpdateNSViewAndDisplay();
|
||||
#else
|
||||
const gfx::Size& size_in_pixels =
|
||||
gfx::ConvertSizeToPixel(current_device_scale_factor_, size);
|
||||
|
||||
local_surface_id_allocator_.GenerateId();
|
||||
local_surface_id_allocation_ =
|
||||
local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation();
|
||||
|
||||
GetCompositor()->SetScaleAndSize(current_device_scale_factor_, size_in_pixels,
|
||||
local_surface_id_allocation_);
|
||||
bool resized = true;
|
||||
GetDelegatedFrameHost()->EmbedSurface(
|
||||
local_surface_id_, size, cc::DeadlinePolicy::UseDefaultDeadline());
|
||||
local_surface_id_allocation_.local_surface_id(), size,
|
||||
cc::DeadlinePolicy::UseDefaultDeadline());
|
||||
#endif
|
||||
|
||||
// Note that |render_widget_host_| will retrieve resize parameters from the
|
||||
// DelegatedFrameHost, so it must have SynchronizeVisualProperties called
|
||||
// after.
|
||||
if (resized && render_widget_host_)
|
||||
if (resized && render_widget_host_) {
|
||||
render_widget_host_->SynchronizeVisualProperties();
|
||||
}
|
||||
}
|
||||
|
||||
viz::FrameSinkId OffScreenRenderWidgetHostView::AllocateFrameSinkId(
|
||||
|
||||
@@ -66,13 +66,12 @@ class AtomBeginFrameTimer;
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
class MacHelper;
|
||||
#else
|
||||
class AtomDelegatedFrameHostClient;
|
||||
#endif
|
||||
|
||||
class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
|
||||
public ui::CompositorDelegate,
|
||||
#if !defined(OS_MACOSX)
|
||||
public content::DelegatedFrameHostClient,
|
||||
#endif
|
||||
public OffscreenViewProxyObserver {
|
||||
public:
|
||||
OffScreenRenderWidgetHostView(bool transparent,
|
||||
@@ -118,7 +117,6 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
|
||||
void SetActive(bool active) override;
|
||||
void ShowDefinitionForSelection() override;
|
||||
void SpeakSelection() override;
|
||||
bool ShouldContinueToPauseForFrame() override;
|
||||
bool UpdateNSViewAndDisplay();
|
||||
#endif // defined(OS_MACOSX)
|
||||
|
||||
@@ -144,8 +142,6 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
|
||||
void Destroy(void) override;
|
||||
void SetTooltipText(const base::string16&) override;
|
||||
content::CursorManager* GetCursorManager() override;
|
||||
void SelectionBoundsChanged(
|
||||
const ViewHostMsg_SelectionBounds_Params&) override;
|
||||
void CopyFromSurface(
|
||||
const gfx::Rect& src_rect,
|
||||
const gfx::Size& output_size,
|
||||
@@ -170,18 +166,8 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
|
||||
content::RenderWidgetHost*,
|
||||
content::WebContentsView*) override;
|
||||
|
||||
#if !defined(OS_MACOSX)
|
||||
// content::DelegatedFrameHostClient:
|
||||
int DelegatedFrameHostGetGpuMemoryBufferClientId(void) const;
|
||||
ui::Layer* DelegatedFrameHostGetLayer(void) const override;
|
||||
bool DelegatedFrameHostIsVisible(void) const override;
|
||||
SkColor DelegatedFrameHostGetGutterColor() const override;
|
||||
void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override;
|
||||
void OnBeginFrame(base::TimeTicks frame_time) override;
|
||||
void OnFrameTokenChanged(uint32_t frame_token) override;
|
||||
#endif // !defined(OS_MACOSX)
|
||||
|
||||
const viz::LocalSurfaceId& GetLocalSurfaceId() const override;
|
||||
const viz::LocalSurfaceIdAllocation& GetLocalSurfaceIdAllocation()
|
||||
const override;
|
||||
const viz::FrameSinkId& GetFrameSinkId() const override;
|
||||
|
||||
void DidNavigate() override;
|
||||
@@ -220,16 +206,13 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
|
||||
void RemoveViewProxy(OffscreenViewProxy* proxy);
|
||||
void ProxyViewDestroyed(OffscreenViewProxy* proxy) override;
|
||||
|
||||
void RegisterGuestViewFrameSwappedCallback(
|
||||
content::RenderWidgetHostViewGuest* guest_host_view);
|
||||
void OnGuestViewFrameSwapped(
|
||||
content::RenderWidgetHostViewGuest* guest_host_view);
|
||||
|
||||
void OnPaint(const gfx::Rect& damage_rect, const SkBitmap& bitmap);
|
||||
void OnPopupPaint(const gfx::Rect& damage_rect, const SkBitmap& bitmap);
|
||||
void OnProxyViewPaint(const gfx::Rect& damage_rect) override;
|
||||
|
||||
bool IsPopupWidget() const { return popup_type_ != blink::kWebPopupTypeNone; }
|
||||
bool IsPopupWidget() const {
|
||||
return widget_type_ == content::WidgetType::kPopup;
|
||||
}
|
||||
|
||||
void HoldResize();
|
||||
void ReleaseResize();
|
||||
@@ -322,7 +305,7 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
|
||||
|
||||
bool paint_callback_running_ = false;
|
||||
|
||||
viz::LocalSurfaceId local_surface_id_;
|
||||
viz::LocalSurfaceIdAllocation local_surface_id_allocation_;
|
||||
viz::ParentLocalSurfaceIdAllocator local_surface_id_allocator_;
|
||||
|
||||
std::unique_ptr<ui::Layer> root_layer_;
|
||||
@@ -349,6 +332,8 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
|
||||
|
||||
// Selected text on the renderer.
|
||||
std::string selected_text_;
|
||||
#else
|
||||
std::unique_ptr<AtomDelegatedFrameHostClient> delegated_frame_host_client_;
|
||||
#endif
|
||||
|
||||
content::MouseWheelPhaseHandler mouse_wheel_phase_handler_;
|
||||
|
||||
@@ -11,13 +11,15 @@
|
||||
#include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
|
||||
#include "ui/display/screen.h"
|
||||
|
||||
#include "components/viz/common/features.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
class MacHelper : public content::BrowserCompositorMacClient,
|
||||
public ui::AcceleratedWidgetMacNSView {
|
||||
public:
|
||||
explicit MacHelper(OffScreenRenderWidgetHostView* view) : view_(view) {
|
||||
[view_->GetNativeView() setWantsLayer:YES];
|
||||
[view_->GetNativeView().GetNativeNSView() setWantsLayer:YES];
|
||||
}
|
||||
|
||||
virtual ~MacHelper() {}
|
||||
@@ -44,25 +46,14 @@ class MacHelper : public content::BrowserCompositorMacClient,
|
||||
|
||||
void DestroyCompositorForShutdown() override {}
|
||||
|
||||
bool SynchronizeVisualProperties(
|
||||
const base::Optional<viz::LocalSurfaceId>&
|
||||
child_allocated_local_surface_id) override {
|
||||
auto* browser_compositor = view_->browser_compositor();
|
||||
if (child_allocated_local_surface_id) {
|
||||
browser_compositor->UpdateRendererLocalSurfaceIdFromChild(
|
||||
*child_allocated_local_surface_id);
|
||||
} else {
|
||||
browser_compositor->AllocateNewRendererLocalSurfaceId();
|
||||
}
|
||||
|
||||
if (auto* host = browser_compositor->GetDelegatedFrameHost()) {
|
||||
host->EmbedSurface(browser_compositor->GetRendererLocalSurfaceId(),
|
||||
browser_compositor->GetRendererSize(),
|
||||
cc::DeadlinePolicy::UseDefaultDeadline());
|
||||
}
|
||||
bool OnBrowserCompositorSurfaceIdChanged() override {
|
||||
return view_->render_widget_host()->SynchronizeVisualProperties();
|
||||
}
|
||||
|
||||
std::vector<viz::SurfaceId> CollectSurfaceIdsForEviction() override {
|
||||
return view_->render_widget_host()->CollectSurfaceIdsForEviction();
|
||||
}
|
||||
|
||||
private:
|
||||
OffScreenRenderWidgetHostView* view_;
|
||||
|
||||
@@ -76,20 +67,20 @@ void OffScreenRenderWidgetHostView::ShowDefinitionForSelection() {}
|
||||
void OffScreenRenderWidgetHostView::SpeakSelection() {}
|
||||
|
||||
bool OffScreenRenderWidgetHostView::UpdateNSViewAndDisplay() {
|
||||
return browser_compositor_->UpdateNSViewAndDisplay(
|
||||
return browser_compositor_->UpdateSurfaceFromNSView(
|
||||
GetRootLayer()->bounds().size(), GetDisplay());
|
||||
}
|
||||
|
||||
bool OffScreenRenderWidgetHostView::ShouldContinueToPauseForFrame() {
|
||||
return browser_compositor_->ShouldContinueToPauseForFrame();
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::CreatePlatformWidget(
|
||||
bool is_guest_view_hack) {
|
||||
mac_helper_ = new MacHelper(this);
|
||||
browser_compositor_.reset(new content::BrowserCompositorMac(
|
||||
mac_helper_, mac_helper_, render_widget_host_->is_hidden(), GetDisplay(),
|
||||
AllocateFrameSinkId(is_guest_view_hack)));
|
||||
|
||||
if (!base::FeatureList::IsEnabled(features::kVizDisplayCompositor)) {
|
||||
SetNeedsBeginFrames(true);
|
||||
}
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::DestroyPlatformWidget() {
|
||||
@@ -132,14 +123,15 @@ display::Display OffScreenRenderWidgetHostView::GetDisplay() {
|
||||
void OffScreenRenderWidgetHostView::OnDidUpdateVisualPropertiesComplete(
|
||||
const cc::RenderFrameMetadata& metadata) {
|
||||
DCHECK_EQ(current_device_scale_factor_, metadata.device_scale_factor);
|
||||
browser_compositor_->SynchronizeVisualProperties(
|
||||
browser_compositor_->UpdateSurfaceFromChild(
|
||||
metadata.device_scale_factor, metadata.viewport_size_in_pixels,
|
||||
metadata.local_surface_id.value_or(viz::LocalSurfaceId()));
|
||||
metadata.local_surface_id_allocation.value_or(
|
||||
viz::LocalSurfaceIdAllocation()));
|
||||
}
|
||||
|
||||
const viz::LocalSurfaceId& OffScreenRenderWidgetHostView::GetLocalSurfaceId()
|
||||
const {
|
||||
return browser_compositor_->GetRendererLocalSurfaceId();
|
||||
const viz::LocalSurfaceIdAllocation&
|
||||
OffScreenRenderWidgetHostView::GetLocalSurfaceIdAllocation() const {
|
||||
return browser_compositor_->GetRendererLocalSurfaceIdAllocation();
|
||||
}
|
||||
|
||||
ui::Compositor* OffScreenRenderWidgetHostView::GetCompositor() const {
|
||||
|
||||
@@ -128,7 +128,7 @@ OffScreenWebContentsView::CreateViewForWidget(
|
||||
}
|
||||
|
||||
content::RenderWidgetHostViewBase*
|
||||
OffScreenWebContentsView::CreateViewForPopupWidget(
|
||||
OffScreenWebContentsView::CreateViewForChildWidget(
|
||||
content::RenderWidgetHost* render_widget_host) {
|
||||
content::WebContentsImpl* web_contents_impl =
|
||||
static_cast<content::WebContentsImpl*>(web_contents_);
|
||||
|
||||
@@ -57,7 +57,7 @@ class OffScreenWebContentsView : public content::WebContentsView,
|
||||
content::RenderWidgetHostViewBase* CreateViewForWidget(
|
||||
content::RenderWidgetHost* render_widget_host,
|
||||
bool is_guest_view_hack) override;
|
||||
content::RenderWidgetHostViewBase* CreateViewForPopupWidget(
|
||||
content::RenderWidgetHostViewBase* CreateViewForChildWidget(
|
||||
content::RenderWidgetHost* render_widget_host) override;
|
||||
void SetPageTitle(const base::string16& title) override;
|
||||
void RenderViewCreated(content::RenderViewHost* host) override;
|
||||
|
||||
@@ -89,7 +89,7 @@ void PrintPreviewMessageHandler::OnMetafileReadyForPrinting(
|
||||
const PrintHostMsg_DidPrintContent_Params& content = params.content;
|
||||
if (!content.metafile_data_region.IsValid() ||
|
||||
params.expected_pages_count <= 0) {
|
||||
RunPrintToPDFCallback(ids.request_id, nullptr);
|
||||
RejectPromise(ids.request_id);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -102,10 +102,9 @@ void PrintPreviewMessageHandler::OnMetafileReadyForPrinting(
|
||||
base::BindOnce(&PrintPreviewMessageHandler::OnCompositePdfDocumentDone,
|
||||
weak_ptr_factory_.GetWeakPtr(), ids));
|
||||
} else {
|
||||
RunPrintToPDFCallback(
|
||||
ids.request_id,
|
||||
base::RefCountedSharedMemoryMapping::CreateFromWholeRegion(
|
||||
content.metafile_data_region));
|
||||
ResolvePromise(ids.request_id,
|
||||
base::RefCountedSharedMemoryMapping::CreateFromWholeRegion(
|
||||
content.metafile_data_region));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,11 +116,11 @@ void PrintPreviewMessageHandler::OnCompositePdfDocumentDone(
|
||||
|
||||
if (status != printing::mojom::PdfCompositor::Status::SUCCESS) {
|
||||
DLOG(ERROR) << "Compositing pdf failed with error " << status;
|
||||
RunPrintToPDFCallback(ids.request_id, nullptr);
|
||||
RejectPromise(ids.request_id);
|
||||
return;
|
||||
}
|
||||
|
||||
RunPrintToPDFCallback(
|
||||
ResolvePromise(
|
||||
ids.request_id,
|
||||
base::RefCountedSharedMemoryMapping::CreateFromWholeRegion(region));
|
||||
}
|
||||
@@ -131,7 +130,7 @@ void PrintPreviewMessageHandler::OnPrintPreviewFailed(
|
||||
const PrintHostMsg_PreviewIds& ids) {
|
||||
StopWorker(document_cookie);
|
||||
|
||||
RunPrintToPDFCallback(ids.request_id, nullptr);
|
||||
RejectPromise(ids.request_id);
|
||||
}
|
||||
|
||||
void PrintPreviewMessageHandler::OnPrintPreviewCancelled(
|
||||
@@ -139,15 +138,15 @@ void PrintPreviewMessageHandler::OnPrintPreviewCancelled(
|
||||
const PrintHostMsg_PreviewIds& ids) {
|
||||
StopWorker(document_cookie);
|
||||
|
||||
RunPrintToPDFCallback(ids.request_id, nullptr);
|
||||
RejectPromise(ids.request_id);
|
||||
}
|
||||
|
||||
void PrintPreviewMessageHandler::PrintToPDF(
|
||||
const base::DictionaryValue& options,
|
||||
const PrintToPDFCallback& callback) {
|
||||
scoped_refptr<atom::util::Promise> promise) {
|
||||
int request_id;
|
||||
options.GetInteger(printing::kPreviewRequestID, &request_id);
|
||||
print_to_pdf_callback_map_[request_id] = callback;
|
||||
promise_map_[request_id] = std::move(promise);
|
||||
|
||||
auto* focused_frame = web_contents()->GetFocusedFrame();
|
||||
auto* rfh = focused_frame && focused_frame->HasSelection()
|
||||
@@ -156,28 +155,44 @@ void PrintPreviewMessageHandler::PrintToPDF(
|
||||
rfh->Send(new PrintMsg_PrintPreview(rfh->GetRoutingID(), options));
|
||||
}
|
||||
|
||||
void PrintPreviewMessageHandler::RunPrintToPDFCallback(
|
||||
scoped_refptr<atom::util::Promise> PrintPreviewMessageHandler::GetPromise(
|
||||
int request_id) {
|
||||
auto it = promise_map_.find(request_id);
|
||||
DCHECK(it != promise_map_.end());
|
||||
|
||||
auto promise = it->second;
|
||||
promise_map_.erase(it);
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
void PrintPreviewMessageHandler::ResolvePromise(
|
||||
int request_id,
|
||||
scoped_refptr<base::RefCountedMemory> data_bytes) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
|
||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||
v8::Locker locker(isolate);
|
||||
auto promise = GetPromise(request_id);
|
||||
|
||||
v8::Isolate* isolate = promise->isolate();
|
||||
mate::Locker locker(isolate);
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
if (data_bytes && data_bytes->size()) {
|
||||
v8::Local<v8::Value> buffer =
|
||||
node::Buffer::Copy(isolate,
|
||||
reinterpret_cast<const char*>(data_bytes->front()),
|
||||
data_bytes->size())
|
||||
.ToLocalChecked();
|
||||
print_to_pdf_callback_map_[request_id].Run(v8::Null(isolate), buffer);
|
||||
} else {
|
||||
v8::Local<v8::String> error_message =
|
||||
v8::String::NewFromUtf8(isolate, "Failed to generate PDF");
|
||||
print_to_pdf_callback_map_[request_id].Run(
|
||||
v8::Exception::Error(error_message), v8::Null(isolate));
|
||||
}
|
||||
print_to_pdf_callback_map_.erase(request_id);
|
||||
v8::Context::Scope context_scope(
|
||||
v8::Local<v8::Context>::New(isolate, promise->GetContext()));
|
||||
|
||||
v8::Local<v8::Value> buffer =
|
||||
node::Buffer::Copy(isolate,
|
||||
reinterpret_cast<const char*>(data_bytes->front()),
|
||||
data_bytes->size())
|
||||
.ToLocalChecked();
|
||||
|
||||
promise->Resolve(buffer);
|
||||
}
|
||||
|
||||
void PrintPreviewMessageHandler::RejectPromise(int request_id) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
|
||||
auto promise = GetPromise(request_id);
|
||||
promise->RejectWithErrorMessage("Failed to generate PDF");
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "atom/common/promise_util.h"
|
||||
#include "base/memory/ref_counted_memory.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "components/services/pdf_compositor/public/interfaces/pdf_compositor.mojom.h"
|
||||
@@ -28,13 +29,10 @@ class PrintPreviewMessageHandler
|
||||
: public content::WebContentsObserver,
|
||||
public content::WebContentsUserData<PrintPreviewMessageHandler> {
|
||||
public:
|
||||
using PrintToPDFCallback =
|
||||
base::Callback<void(v8::Local<v8::Value>, v8::Local<v8::Value>)>;
|
||||
|
||||
~PrintPreviewMessageHandler() override;
|
||||
|
||||
void PrintToPDF(const base::DictionaryValue& options,
|
||||
const PrintToPDFCallback& callback);
|
||||
scoped_refptr<atom::util::Promise> promise);
|
||||
|
||||
protected:
|
||||
// content::WebContentsObserver implementation.
|
||||
@@ -57,11 +55,15 @@ class PrintPreviewMessageHandler
|
||||
const PrintHostMsg_PreviewIds& ids);
|
||||
void OnPrintPreviewCancelled(int document_cookie,
|
||||
const PrintHostMsg_PreviewIds& ids);
|
||||
void RunPrintToPDFCallback(int request_id,
|
||||
scoped_refptr<base::RefCountedMemory> data_bytes);
|
||||
|
||||
using PrintToPDFCallbackMap = std::map<int, PrintToPDFCallback>;
|
||||
PrintToPDFCallbackMap print_to_pdf_callback_map_;
|
||||
scoped_refptr<atom::util::Promise> GetPromise(int request_id);
|
||||
|
||||
void ResolvePromise(int request_id,
|
||||
scoped_refptr<base::RefCountedMemory> data_bytes);
|
||||
void RejectPromise(int request_id);
|
||||
|
||||
using PromiseMap = std::map<int, scoped_refptr<atom::util::Promise>>;
|
||||
PromiseMap promise_map_;
|
||||
|
||||
base::WeakPtrFactory<PrintPreviewMessageHandler> weak_ptr_factory_;
|
||||
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>electron.icns</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>5.0.0-nightly.20190122</string>
|
||||
<string>6.0.0-nightly.20190212</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>5.0.0-nightly.20190122</string>
|
||||
<string>6.0.0-nightly.20190212</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.developer-tools</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
|
||||
@@ -50,8 +50,8 @@ END
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 5,0,0,20190122
|
||||
PRODUCTVERSION 5,0,0,20190122
|
||||
FILEVERSION 6,0,0,20190212
|
||||
PRODUCTVERSION 6,0,0,20190212
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@@ -68,12 +68,12 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "GitHub, Inc."
|
||||
VALUE "FileDescription", "Electron"
|
||||
VALUE "FileVersion", "5.0.0"
|
||||
VALUE "FileVersion", "6.0.0"
|
||||
VALUE "InternalName", "electron.exe"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
|
||||
VALUE "OriginalFilename", "electron.exe"
|
||||
VALUE "ProductName", "Electron"
|
||||
VALUE "ProductVersion", "5.0.0"
|
||||
VALUE "ProductVersion", "6.0.0"
|
||||
VALUE "SquirrelAwareVersion", "1"
|
||||
END
|
||||
END
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include "atom/browser/native_window_views.h"
|
||||
#include "atom/browser/ui/autofill_popup.h"
|
||||
#include "atom/common/api/api_messages.h"
|
||||
#include "base/i18n/rtl.h"
|
||||
#include "chrome/browser/ui/autofill/popup_view_common.h"
|
||||
#include "electron/buildflags/buildflags.h"
|
||||
#include "ui/display/display.h"
|
||||
#include "ui/display/screen.h"
|
||||
@@ -25,85 +27,18 @@
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
class PopupViewCommon : public autofill::PopupViewCommon {
|
||||
public:
|
||||
explicit PopupViewCommon(const gfx::Rect& window_bounds)
|
||||
: window_bounds_(window_bounds) {}
|
||||
|
||||
std::pair<int, int> CalculatePopupXAndWidth(
|
||||
const display::Display& left_display,
|
||||
const display::Display& right_display,
|
||||
int popup_required_width,
|
||||
const gfx::Rect& element_bounds,
|
||||
bool is_rtl) {
|
||||
int leftmost_display_x = left_display.bounds().x();
|
||||
int rightmost_display_x =
|
||||
right_display.GetSizeInPixel().width() + right_display.bounds().x();
|
||||
|
||||
// Calculate the start coordinates for the popup if it is growing right or
|
||||
// the end position if it is growing to the left, capped to screen space.
|
||||
int right_growth_start = std::max(
|
||||
leftmost_display_x, std::min(rightmost_display_x, element_bounds.x()));
|
||||
int left_growth_end =
|
||||
std::max(leftmost_display_x,
|
||||
std::min(rightmost_display_x, element_bounds.right()));
|
||||
|
||||
int right_available = rightmost_display_x - right_growth_start;
|
||||
int left_available = left_growth_end - leftmost_display_x;
|
||||
|
||||
int popup_width =
|
||||
std::min(popup_required_width, std::max(right_available, left_available));
|
||||
|
||||
std::pair<int, int> grow_right(right_growth_start, popup_width);
|
||||
std::pair<int, int> grow_left(left_growth_end - popup_width, popup_width);
|
||||
|
||||
// Prefer to grow towards the end (right for LTR, left for RTL). But if there
|
||||
// is not enough space available in the desired direction and more space in
|
||||
// the other direction, reverse it.
|
||||
if (is_rtl) {
|
||||
return left_available >= popup_width || left_available >= right_available
|
||||
? grow_left
|
||||
: grow_right;
|
||||
gfx::Rect GetWindowBounds(gfx::NativeView container_view) override {
|
||||
return window_bounds_;
|
||||
}
|
||||
return right_available >= popup_width || right_available >= left_available
|
||||
? grow_right
|
||||
: grow_left;
|
||||
}
|
||||
|
||||
std::pair<int, int> CalculatePopupYAndHeight(
|
||||
const display::Display& top_display,
|
||||
const display::Display& bottom_display,
|
||||
int popup_required_height,
|
||||
const gfx::Rect& element_bounds) {
|
||||
int topmost_display_y = top_display.bounds().y();
|
||||
int bottommost_display_y =
|
||||
bottom_display.GetSizeInPixel().height() + bottom_display.bounds().y();
|
||||
|
||||
// Calculate the start coordinates for the popup if it is growing down or
|
||||
// the end position if it is growing up, capped to screen space.
|
||||
int top_growth_end = std::max(
|
||||
topmost_display_y, std::min(bottommost_display_y, element_bounds.y()));
|
||||
int bottom_growth_start =
|
||||
std::max(topmost_display_y,
|
||||
std::min(bottommost_display_y, element_bounds.bottom()));
|
||||
|
||||
int top_available = bottom_growth_start - topmost_display_y;
|
||||
int bottom_available = bottommost_display_y - top_growth_end;
|
||||
|
||||
// TODO(csharp): Restrict the popup height to what is available.
|
||||
if (bottom_available >= popup_required_height ||
|
||||
bottom_available >= top_available) {
|
||||
// The popup can appear below the field.
|
||||
return std::make_pair(bottom_growth_start, popup_required_height);
|
||||
} else {
|
||||
// The popup must appear above the field.
|
||||
return std::make_pair(top_growth_end - popup_required_height,
|
||||
popup_required_height);
|
||||
}
|
||||
}
|
||||
|
||||
display::Display GetDisplayNearestPoint(const gfx::Point& point) {
|
||||
return display::Screen::GetScreen()->GetDisplayNearestPoint(point);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
private:
|
||||
gfx::Rect window_bounds_;
|
||||
};
|
||||
|
||||
AutofillPopup::AutofillPopup() {
|
||||
bold_font_list_ = gfx::FontList().DeriveWithWeight(gfx::Font::Weight::BOLD);
|
||||
@@ -181,34 +116,14 @@ void AutofillPopup::UpdatePopupBounds() {
|
||||
DCHECK(parent_);
|
||||
gfx::Point origin(element_bounds_.origin());
|
||||
views::View::ConvertPointToScreen(parent_, &origin);
|
||||
|
||||
gfx::Rect bounds(origin, element_bounds_.size());
|
||||
gfx::Rect window_bounds = parent_->GetBoundsInScreen();
|
||||
|
||||
int desired_width = GetDesiredPopupWidth();
|
||||
int desired_height = GetDesiredPopupHeight();
|
||||
bool is_rtl = false;
|
||||
|
||||
gfx::Point top_left_corner_of_popup =
|
||||
origin + gfx::Vector2d(bounds.width() - desired_width, -desired_height);
|
||||
|
||||
// This is the bottom right point of the popup if the popup is below the
|
||||
// element and grows to the right (since the is the lowest and furthest right
|
||||
// the popup could go).
|
||||
gfx::Point bottom_right_corner_of_popup =
|
||||
origin + gfx::Vector2d(desired_width, bounds.height() + desired_height);
|
||||
|
||||
display::Display top_left_display =
|
||||
GetDisplayNearestPoint(top_left_corner_of_popup);
|
||||
display::Display bottom_right_display =
|
||||
GetDisplayNearestPoint(bottom_right_corner_of_popup);
|
||||
|
||||
std::pair<int, int> popup_x_and_width = CalculatePopupXAndWidth(
|
||||
top_left_display, bottom_right_display, desired_width, bounds, is_rtl);
|
||||
std::pair<int, int> popup_y_and_height = CalculatePopupYAndHeight(
|
||||
top_left_display, bottom_right_display, desired_height, bounds);
|
||||
|
||||
popup_bounds_ =
|
||||
gfx::Rect(popup_x_and_width.first, popup_y_and_height.first,
|
||||
popup_x_and_width.second, popup_y_and_height.second);
|
||||
PopupViewCommon popup_view_common(window_bounds);
|
||||
popup_bounds_ = popup_view_common.CalculatePopupBounds(
|
||||
GetDesiredPopupWidth(), GetDesiredPopupHeight(), bounds,
|
||||
gfx::NativeView(), base::i18n::IsRTL());
|
||||
}
|
||||
|
||||
gfx::Rect AutofillPopup::popup_bounds_in_view() {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "ui/base/l10n/l10n_util_mac.h"
|
||||
#include "ui/events/cocoa/cocoa_event_utils.h"
|
||||
#include "ui/gfx/image/image.h"
|
||||
#include "ui/strings/grit/ui_strings.h"
|
||||
|
||||
using content::BrowserThread;
|
||||
|
||||
@@ -58,6 +59,29 @@ Role kRolesMap[] = {
|
||||
{@selector(clearRecentDocuments:), "clearrecentdocuments"},
|
||||
};
|
||||
|
||||
// Called when adding a submenu to the menu and checks if the submenu, via its
|
||||
// |model|, has visible child items.
|
||||
bool MenuHasVisibleItems(const atom::AtomMenuModel* model) {
|
||||
int count = model->GetItemCount();
|
||||
for (int index = 0; index < count; index++) {
|
||||
if (model->IsVisibleAt(index))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Called when an empty submenu is created. This inserts a menu item labeled
|
||||
// "(empty)" into the submenu. Matches Windows behavior.
|
||||
NSMenu* MakeEmptySubmenu() {
|
||||
base::scoped_nsobject<NSMenu> submenu([[NSMenu alloc] initWithTitle:@""]);
|
||||
NSString* empty_menu_title =
|
||||
l10n_util::GetNSString(IDS_APP_MENU_EMPTY_SUBMENU);
|
||||
|
||||
[submenu addItemWithTitle:empty_menu_title action:NULL keyEquivalent:@""];
|
||||
[[submenu itemAtIndex:0] setEnabled:NO];
|
||||
return submenu.autorelease();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// Menu item is located for ease of removing it from the parent owner
|
||||
@@ -220,13 +244,21 @@ static base::scoped_nsobject<NSMenu> recentDocumentsMenuSwap_;
|
||||
NSMenu* submenu = [[NSMenu alloc] initWithTitle:label];
|
||||
[item setSubmenu:submenu];
|
||||
[NSApp setServicesMenu:submenu];
|
||||
} else if (type == atom::AtomMenuModel::TYPE_SUBMENU) {
|
||||
} else if (type == atom::AtomMenuModel::TYPE_SUBMENU &&
|
||||
model->IsVisibleAt(index)) {
|
||||
// We need to specifically check that the submenu top-level item has been
|
||||
// enabled as it's not validated by validateUserInterfaceItem
|
||||
if (!model->IsEnabledAt(index))
|
||||
[item setEnabled:NO];
|
||||
|
||||
// Recursively build a submenu from the sub-model at this index.
|
||||
[item setTarget:nil];
|
||||
[item setAction:nil];
|
||||
atom::AtomMenuModel* submenuModel =
|
||||
static_cast<atom::AtomMenuModel*>(model->GetSubmenuModelAt(index));
|
||||
NSMenu* submenu = [self menuFromModel:submenuModel];
|
||||
NSMenu* submenu = MenuHasVisibleItems(submenuModel)
|
||||
? [self menuFromModel:submenuModel]
|
||||
: MakeEmptySubmenu();
|
||||
[submenu setTitle:[item title]];
|
||||
[item setSubmenu:submenu];
|
||||
|
||||
|
||||
@@ -16,7 +16,19 @@ ViewsDelegateMac::~ViewsDelegateMac() {}
|
||||
void ViewsDelegateMac::OnBeforeWidgetInit(
|
||||
views::Widget::InitParams* params,
|
||||
views::internal::NativeWidgetDelegate* delegate) {
|
||||
DCHECK(params->native_widget);
|
||||
// If we already have a native_widget, we don't have to try to come
|
||||
// up with one.
|
||||
if (params->native_widget)
|
||||
return;
|
||||
|
||||
if (!native_widget_factory().is_null()) {
|
||||
params->native_widget = native_widget_factory().Run(*params, delegate);
|
||||
if (params->native_widget)
|
||||
return;
|
||||
}
|
||||
|
||||
// Setting null here causes Widget to create the default NativeWidget implementation.
|
||||
params->native_widget = nullptr;
|
||||
}
|
||||
|
||||
ui::ContextFactory* ViewsDelegateMac::GetContextFactory() {
|
||||
|
||||
@@ -56,19 +56,12 @@ AutofillPopupView::~AutofillPopupView() {
|
||||
}
|
||||
|
||||
void AutofillPopupView::Show() {
|
||||
if (!popup_)
|
||||
if (!popup_ || !parent_widget_->IsVisible() || parent_widget_->IsClosed())
|
||||
return;
|
||||
|
||||
const bool initialize_widget = !GetWidget();
|
||||
if (initialize_widget) {
|
||||
parent_widget_->AddObserver(this);
|
||||
views::FocusManager* focus_manager = parent_widget_->GetFocusManager();
|
||||
focus_manager->RegisterAccelerator(
|
||||
ui::Accelerator(ui::VKEY_RETURN, ui::EF_NONE),
|
||||
ui::AcceleratorManager::kNormalPriority, this);
|
||||
focus_manager->RegisterAccelerator(
|
||||
ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE),
|
||||
ui::AcceleratorManager::kNormalPriority, this);
|
||||
|
||||
// The widget is destroyed by the corresponding NativeWidget, so we use
|
||||
// a weak pointer to hold the reference and don't have to worry about
|
||||
@@ -487,7 +480,6 @@ void AutofillPopupView::ClearSelection() {
|
||||
}
|
||||
|
||||
void AutofillPopupView::RemoveObserver() {
|
||||
parent_widget_->GetFocusManager()->UnregisterAccelerators(this);
|
||||
parent_widget_->RemoveObserver(this);
|
||||
views::WidgetFocusManager::GetInstance()->RemoveFocusChangeListener(this);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include "atom/browser/ui/views/submenu_button.h"
|
||||
#include "atom/common/keyboard_util.h"
|
||||
#include "ui/aura/window.h"
|
||||
#include "ui/base/models/menu_model.h"
|
||||
#include "ui/views/background.h"
|
||||
#include "ui/views/layout/box_layout.h"
|
||||
@@ -174,6 +175,27 @@ bool MenuBar::AcceleratorPressed(const ui::Accelerator& accelerator) {
|
||||
}
|
||||
|
||||
bool MenuBar::SetPaneFocus(views::View* initial_focus) {
|
||||
// TODO(zcbenz): Submit patch to upstream Chromium to fix the crash.
|
||||
//
|
||||
// Without this check, Electron would crash when running tests.
|
||||
//
|
||||
// Check failed: rules_->CanFocusWindow(window, nullptr).
|
||||
// logging::LogMessage::~LogMessage
|
||||
// wm::FocusController::SetFocusedWindow
|
||||
// wm::FocusController::ResetFocusWithinActiveWindow
|
||||
// views::View::OnFocus
|
||||
// views::Button::OnFocus
|
||||
// views::LabelButton::OnFocus
|
||||
// views::View::Focus
|
||||
// views::FocusManager::SetFocusedViewWithReason
|
||||
// views::AccessiblePaneView::SetPaneFocus
|
||||
// atom::MenuBar::SetPaneFocus
|
||||
if (initial_focus && initial_focus->GetWidget()) {
|
||||
aura::Window* window = initial_focus->GetWidget()->GetNativeWindow();
|
||||
if (!window || !window->GetRootWindow())
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = views::AccessiblePaneView::SetPaneFocus(initial_focus);
|
||||
|
||||
if (result) {
|
||||
|
||||
@@ -173,14 +173,18 @@ void RootView::Layout() {
|
||||
return;
|
||||
|
||||
const auto menu_bar_bounds =
|
||||
menu_bar_visible_ ? gfx::Rect(0, 0, size().width(), kMenuBarHeight)
|
||||
: gfx::Rect();
|
||||
menu_bar_visible_
|
||||
? gfx::Rect(insets_.left(), insets_.top(),
|
||||
size().width() - insets_.width(), kMenuBarHeight)
|
||||
: gfx::Rect();
|
||||
if (menu_bar_)
|
||||
menu_bar_->SetBoundsRect(menu_bar_bounds);
|
||||
|
||||
window_->content_view()->SetBoundsRect(
|
||||
gfx::Rect(0, menu_bar_bounds.height(), size().width(),
|
||||
size().height() - menu_bar_bounds.height()));
|
||||
gfx::Rect(insets_.left(),
|
||||
menu_bar_visible_ ? menu_bar_bounds.bottom() : insets_.top(),
|
||||
size().width() - insets_.width(),
|
||||
size().height() - menu_bar_bounds.height() - insets_.height()));
|
||||
}
|
||||
|
||||
gfx::Size RootView::GetMinimumSize() const {
|
||||
@@ -217,4 +221,11 @@ void RootView::UnregisterAcceleratorsWithFocusManager() {
|
||||
focus_manager->UnregisterAccelerators(this);
|
||||
}
|
||||
|
||||
void RootView::SetInsets(const gfx::Insets& insets) {
|
||||
if (insets != insets_) {
|
||||
insets_ = insets;
|
||||
Layout();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <memory>
|
||||
|
||||
#include "atom/browser/ui/accelerator_util.h"
|
||||
#include "ui/gfx/geometry/insets.h"
|
||||
#include "ui/views/view.h"
|
||||
#include "ui/views/view_tracker.h"
|
||||
|
||||
@@ -39,6 +40,8 @@ class RootView : public views::View {
|
||||
// Register/Unregister accelerators supported by the menu model.
|
||||
void RegisterAcceleratorsWithFocusManager(AtomMenuModel* menu_model);
|
||||
void UnregisterAcceleratorsWithFocusManager();
|
||||
void SetInsets(const gfx::Insets& insets);
|
||||
gfx::Insets insets() const { return insets_; }
|
||||
|
||||
// views::View:
|
||||
void Layout() override;
|
||||
@@ -56,6 +59,8 @@ class RootView : public views::View {
|
||||
bool menu_bar_visible_ = false;
|
||||
bool menu_bar_alt_pressed_ = false;
|
||||
|
||||
gfx::Insets insets_;
|
||||
|
||||
// Map from accelerator to menu item's command id.
|
||||
accelerator_util::AcceleratorTable accelerator_table_;
|
||||
|
||||
|
||||
@@ -88,4 +88,25 @@ bool ShouldUseGlobalMenuBar() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void MoveWindowToForeground(::Window xwindow) {
|
||||
XDisplay* xdisplay = gfx::GetXDisplay();
|
||||
XEvent xclient;
|
||||
memset(&xclient, 0, sizeof(xclient));
|
||||
|
||||
xclient.type = ClientMessage;
|
||||
xclient.xclient.display = xdisplay;
|
||||
xclient.xclient.window = xwindow;
|
||||
xclient.xclient.message_type = GetAtom("_NET_RESTACK_WINDOW");
|
||||
xclient.xclient.format = 32;
|
||||
xclient.xclient.data.l[0] = 2;
|
||||
xclient.xclient.data.l[1] = 0;
|
||||
xclient.xclient.data.l[2] = Above;
|
||||
xclient.xclient.data.l[3] = 0;
|
||||
xclient.xclient.data.l[4] = 0;
|
||||
|
||||
XSendEvent(xdisplay, DefaultRootWindow(xdisplay), x11::False,
|
||||
SubstructureRedirectMask | SubstructureNotifyMask, &xclient);
|
||||
XFlush(xdisplay);
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -23,6 +23,9 @@ void SetWindowType(::Window xwindow, const std::string& type);
|
||||
// Returns true if the bus name "com.canonical.AppMenu.Registrar" is available.
|
||||
bool ShouldUseGlobalMenuBar();
|
||||
|
||||
// Bring the given window to the front and give it the focus.
|
||||
void MoveWindowToForeground(::Window xwindow);
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_UI_X_X_WINDOW_UTILS_H_
|
||||
|
||||
@@ -128,6 +128,7 @@ WebContentsPreferences::WebContentsPreferences(
|
||||
SetDefaultBoolIfUndefined(options::kWebviewTag, false);
|
||||
SetDefaultBoolIfUndefined(options::kSandbox, false);
|
||||
SetDefaultBoolIfUndefined(options::kNativeWindowOpen, false);
|
||||
SetDefaultBoolIfUndefined(options::kEnableRemoteModule, true);
|
||||
SetDefaultBoolIfUndefined(options::kContextIsolation, false);
|
||||
SetDefaultBoolIfUndefined("javascript", true);
|
||||
SetDefaultBoolIfUndefined("images", true);
|
||||
|
||||
@@ -25,11 +25,13 @@ IPC_STRUCT_TRAITS_BEGIN(atom::DraggableRegion)
|
||||
IPC_STRUCT_TRAITS_MEMBER(bounds)
|
||||
IPC_STRUCT_TRAITS_END()
|
||||
|
||||
IPC_MESSAGE_ROUTED2(AtomFrameHostMsg_Message,
|
||||
IPC_MESSAGE_ROUTED3(AtomFrameHostMsg_Message,
|
||||
bool /* internal */,
|
||||
std::string /* channel */,
|
||||
base::ListValue /* arguments */)
|
||||
|
||||
IPC_SYNC_MESSAGE_ROUTED2_1(AtomFrameHostMsg_Message_Sync,
|
||||
IPC_SYNC_MESSAGE_ROUTED3_1(AtomFrameHostMsg_Message_Sync,
|
||||
bool /* internal */,
|
||||
std::string /* channel */,
|
||||
base::ListValue /* arguments */,
|
||||
base::ListValue /* result */)
|
||||
@@ -41,6 +43,10 @@ IPC_MESSAGE_ROUTED5(AtomFrameHostMsg_Message_To,
|
||||
std::string /* channel */,
|
||||
base::ListValue /* arguments */)
|
||||
|
||||
IPC_MESSAGE_ROUTED2(AtomFrameHostMsg_Message_Host,
|
||||
std::string /* channel */,
|
||||
base::ListValue /* arguments */)
|
||||
|
||||
IPC_MESSAGE_ROUTED5(AtomFrameMsg_Message,
|
||||
bool /* internal */,
|
||||
bool /* send_to_all */,
|
||||
|
||||
@@ -56,13 +56,12 @@ void RemoteObjectFreer::RunDestructor() {
|
||||
if (!render_frame)
|
||||
return;
|
||||
|
||||
auto* channel = "ipc-internal-message";
|
||||
auto* channel = "ELECTRON_BROWSER_DEREFERENCE";
|
||||
base::ListValue args;
|
||||
args.AppendString("ELECTRON_BROWSER_DEREFERENCE");
|
||||
args.AppendString(context_id_);
|
||||
args.AppendInteger(object_id_);
|
||||
render_frame->Send(new AtomFrameHostMsg_Message(render_frame->GetRoutingID(),
|
||||
channel, args));
|
||||
true, channel, args));
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
#ifndef ATOM_COMMON_ATOM_VERSION_H_
|
||||
#define ATOM_COMMON_ATOM_VERSION_H_
|
||||
|
||||
#define ATOM_MAJOR_VERSION 5
|
||||
#define ATOM_MAJOR_VERSION 6
|
||||
#define ATOM_MINOR_VERSION 0
|
||||
#define ATOM_PATCH_VERSION 0
|
||||
// clang-format off
|
||||
#define ATOM_PRE_RELEASE_VERSION -nightly.20190122
|
||||
#define ATOM_PRE_RELEASE_VERSION -nightly.20190212
|
||||
// clang-format on
|
||||
|
||||
#ifndef ATOM_STRINGIFY
|
||||
|
||||
@@ -38,6 +38,12 @@ ui::KeyboardCode KeyboardCodeFromKeyIdentifier(const std::string& s,
|
||||
} else if (str == "plus") {
|
||||
*shifted = true;
|
||||
return ui::VKEY_OEM_PLUS;
|
||||
} else if (str == "capslock") {
|
||||
return ui::VKEY_CAPITAL;
|
||||
} else if (str == "numlock") {
|
||||
return ui::VKEY_NUMLOCK;
|
||||
} else if (str == "scrolllock") {
|
||||
return ui::VKEY_SCROLL;
|
||||
} else if (str == "tab") {
|
||||
return ui::VKEY_TAB;
|
||||
} else if (str == "num0") {
|
||||
|
||||
@@ -105,6 +105,22 @@ bool Converter<gfx::Rect>::FromV8(v8::Isolate* isolate,
|
||||
return true;
|
||||
}
|
||||
|
||||
template <>
|
||||
struct Converter<display::Display::AccelerometerSupport> {
|
||||
static v8::Local<v8::Value> ToV8(
|
||||
v8::Isolate* isolate,
|
||||
const display::Display::AccelerometerSupport& val) {
|
||||
switch (val) {
|
||||
case display::Display::AccelerometerSupport::AVAILABLE:
|
||||
return StringToV8(isolate, "available");
|
||||
case display::Display::AccelerometerSupport::UNAVAILABLE:
|
||||
return StringToV8(isolate, "unavailable");
|
||||
default:
|
||||
return StringToV8(isolate, "unknown");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<display::Display::TouchSupport> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
@@ -128,10 +144,15 @@ v8::Local<v8::Value> Converter<display::Display>::ToV8(
|
||||
dict.Set("id", val.id());
|
||||
dict.Set("bounds", val.bounds());
|
||||
dict.Set("workArea", val.work_area());
|
||||
dict.Set("accelerometerSupport", val.accelerometer_support());
|
||||
dict.Set("monochrome", val.is_monochrome());
|
||||
dict.Set("colorDepth", val.color_depth());
|
||||
dict.Set("depthPerComponent", val.depth_per_component());
|
||||
dict.Set("size", val.size());
|
||||
dict.Set("workAreaSize", val.work_area_size());
|
||||
dict.Set("scaleFactor", val.device_scale_factor());
|
||||
dict.Set("rotation", val.RotationAsDegree());
|
||||
dict.Set("internal", val.IsInternal());
|
||||
dict.Set("touchSupport", val.touch_support());
|
||||
return dict.GetHandle();
|
||||
}
|
||||
|
||||
@@ -179,11 +179,20 @@ const char kDisableHttpCache[] = "disable-http-cache";
|
||||
const char kStandardSchemes[] = "standard-schemes";
|
||||
|
||||
// Register schemes to handle service worker.
|
||||
const char kRegisterServiceWorkerSchemes[] = "register-service-worker-schemes";
|
||||
const char kServiceWorkerSchemes[] = "service-worker-schemes";
|
||||
|
||||
// Register schemes as secure.
|
||||
const char kSecureSchemes[] = "secure-schemes";
|
||||
|
||||
// Register schemes as bypassing CSP.
|
||||
const char kBypassCSPSchemes[] = "bypasscsp-schemes";
|
||||
|
||||
// Register schemes as support fetch API.
|
||||
const char kFetchSchemes[] = "fetch-schemes";
|
||||
|
||||
// Register schemes as CORS enabled.
|
||||
const char kCORSSchemes[] = "cors-schemes";
|
||||
|
||||
// The browser process app model ID
|
||||
const char kAppUserModelId[] = "app-user-model-id";
|
||||
|
||||
|
||||
@@ -89,8 +89,11 @@ extern const char kPpapiFlashPath[];
|
||||
extern const char kPpapiFlashVersion[];
|
||||
extern const char kDisableHttpCache[];
|
||||
extern const char kStandardSchemes[];
|
||||
extern const char kRegisterServiceWorkerSchemes[];
|
||||
extern const char kServiceWorkerSchemes[];
|
||||
extern const char kSecureSchemes[];
|
||||
extern const char kBypassCSPSchemes[];
|
||||
extern const char kFetchSchemes[];
|
||||
extern const char kCORSSchemes[];
|
||||
extern const char kAppUserModelId[];
|
||||
extern const char kAppPath[];
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include <string>
|
||||
|
||||
#include "atom/common/api/api_messages.h"
|
||||
#include "atom/common/native_mate_converters/string16_converter.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "atom/common/node_bindings.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
@@ -29,6 +28,7 @@ RenderFrame* GetCurrentRenderFrame() {
|
||||
}
|
||||
|
||||
void Send(mate::Arguments* args,
|
||||
bool internal,
|
||||
const std::string& channel,
|
||||
const base::ListValue& arguments) {
|
||||
RenderFrame* render_frame = GetCurrentRenderFrame();
|
||||
@@ -36,13 +36,14 @@ void Send(mate::Arguments* args,
|
||||
return;
|
||||
|
||||
bool success = render_frame->Send(new AtomFrameHostMsg_Message(
|
||||
render_frame->GetRoutingID(), channel, arguments));
|
||||
render_frame->GetRoutingID(), internal, channel, arguments));
|
||||
|
||||
if (!success)
|
||||
args->ThrowError("Unable to send AtomFrameHostMsg_Message");
|
||||
}
|
||||
|
||||
base::ListValue SendSync(mate::Arguments* args,
|
||||
bool internal,
|
||||
const std::string& channel,
|
||||
const base::ListValue& arguments) {
|
||||
base::ListValue result;
|
||||
@@ -52,7 +53,7 @@ base::ListValue SendSync(mate::Arguments* args,
|
||||
return result;
|
||||
|
||||
IPC::SyncMessage* message = new AtomFrameHostMsg_Message_Sync(
|
||||
render_frame->GetRoutingID(), channel, arguments, &result);
|
||||
render_frame->GetRoutingID(), internal, channel, arguments, &result);
|
||||
bool success = render_frame->Send(message);
|
||||
|
||||
if (!success)
|
||||
@@ -79,6 +80,20 @@ void SendTo(mate::Arguments* args,
|
||||
args->ThrowError("Unable to send AtomFrameHostMsg_Message_To");
|
||||
}
|
||||
|
||||
void SendToHost(mate::Arguments* args,
|
||||
const std::string& channel,
|
||||
const base::ListValue& arguments) {
|
||||
RenderFrame* render_frame = GetCurrentRenderFrame();
|
||||
if (render_frame == nullptr)
|
||||
return;
|
||||
|
||||
bool success = render_frame->Send(new AtomFrameHostMsg_Message_Host(
|
||||
render_frame->GetRoutingID(), channel, arguments));
|
||||
|
||||
if (!success)
|
||||
args->ThrowError("Unable to send AtomFrameHostMsg_Message_Host");
|
||||
}
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
@@ -87,6 +102,7 @@ void Initialize(v8::Local<v8::Object> exports,
|
||||
dict.SetMethod("send", &Send);
|
||||
dict.SetMethod("sendSync", &SendSync);
|
||||
dict.SetMethod("sendTo", &SendTo);
|
||||
dict.SetMethod("sendToHost", &SendToHost);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/renderer/api/atom_api_web_frame.h"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/common/api/api_messages.h"
|
||||
#include "atom/common/api/event_emitter_caller.h"
|
||||
@@ -29,7 +32,6 @@
|
||||
#include "third_party/blink/public/web/web_script_execution_callback.h"
|
||||
#include "third_party/blink/public/web/web_script_source.h"
|
||||
#include "third_party/blink/public/web/web_view.h"
|
||||
#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
|
||||
#include "url/url_util.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
@@ -111,15 +113,15 @@ class ScriptExecutionCallback : public blink::WebScriptExecutionCallback {
|
||||
DISALLOW_COPY_AND_ASSIGN(ScriptExecutionCallback);
|
||||
};
|
||||
|
||||
class FrameSpellChecker : public content::RenderFrameVisitor {
|
||||
class FrameSetSpellChecker : public content::RenderFrameVisitor {
|
||||
public:
|
||||
explicit FrameSpellChecker(SpellCheckClient* spell_check_client,
|
||||
content::RenderFrame* main_frame)
|
||||
: spell_check_client_(spell_check_client), main_frame_(main_frame) {}
|
||||
~FrameSpellChecker() override {
|
||||
spell_check_client_ = nullptr;
|
||||
main_frame_ = nullptr;
|
||||
FrameSetSpellChecker(SpellCheckClient* spell_check_client,
|
||||
content::RenderFrame* main_frame)
|
||||
: spell_check_client_(spell_check_client), main_frame_(main_frame) {
|
||||
content::RenderFrame::ForEach(this);
|
||||
main_frame->GetWebFrame()->SetSpellCheckPanelHostClient(spell_check_client);
|
||||
}
|
||||
|
||||
bool Visit(content::RenderFrame* render_frame) override {
|
||||
auto* view = render_frame->GetRenderView();
|
||||
if (view->GetMainRenderFrame() == main_frame_ ||
|
||||
@@ -132,75 +134,129 @@ class FrameSpellChecker : public content::RenderFrameVisitor {
|
||||
private:
|
||||
SpellCheckClient* spell_check_client_;
|
||||
content::RenderFrame* main_frame_;
|
||||
DISALLOW_COPY_AND_ASSIGN(FrameSpellChecker);
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(FrameSetSpellChecker);
|
||||
};
|
||||
|
||||
class SpellCheckerHolder : public content::RenderFrameObserver {
|
||||
public:
|
||||
// Find existing holder for the |render_frame|.
|
||||
static SpellCheckerHolder* FromRenderFrame(
|
||||
content::RenderFrame* render_frame) {
|
||||
for (auto* holder : instances_) {
|
||||
if (holder->render_frame() == render_frame)
|
||||
return holder;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SpellCheckerHolder(content::RenderFrame* render_frame,
|
||||
std::unique_ptr<SpellCheckClient> spell_check_client)
|
||||
: content::RenderFrameObserver(render_frame),
|
||||
spell_check_client_(std::move(spell_check_client)) {
|
||||
DCHECK(!FromRenderFrame(render_frame));
|
||||
instances_.insert(this);
|
||||
}
|
||||
|
||||
~SpellCheckerHolder() final { instances_.erase(this); }
|
||||
|
||||
void UnsetAndDestroy() {
|
||||
FrameSetSpellChecker set_spell_checker(nullptr, render_frame());
|
||||
delete this;
|
||||
}
|
||||
|
||||
// RenderFrameObserver implementation.
|
||||
void OnDestruct() final {
|
||||
// Since we delete this in WillReleaseScriptContext, this method is unlikely
|
||||
// to be called, but override anyway since I'm not sure if there are some
|
||||
// corner cases.
|
||||
//
|
||||
// Note that while there are two "delete this", it is totally fine as the
|
||||
// observer unsubscribes automatically in destructor and the other one won't
|
||||
// be called.
|
||||
//
|
||||
// Also note that we should not call UnsetAndDestroy here, as the render
|
||||
// frame is going to be destroyed.
|
||||
delete this;
|
||||
}
|
||||
|
||||
void WillReleaseScriptContext(v8::Local<v8::Context> context,
|
||||
int world_id) final {
|
||||
// Unset spell checker when the script context is going to be released, as
|
||||
// the spell check implementation lives there.
|
||||
UnsetAndDestroy();
|
||||
}
|
||||
|
||||
private:
|
||||
static std::set<SpellCheckerHolder*> instances_;
|
||||
|
||||
std::unique_ptr<SpellCheckClient> spell_check_client_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
WebFrame::WebFrame(v8::Isolate* isolate)
|
||||
: web_frame_(blink::WebLocalFrame::FrameForCurrentContext()) {
|
||||
Init(isolate);
|
||||
// static
|
||||
std::set<SpellCheckerHolder*> SpellCheckerHolder::instances_;
|
||||
|
||||
void SetName(v8::Local<v8::Value> window, const std::string& name) {
|
||||
GetRenderFrame(window)->GetWebFrame()->SetName(
|
||||
blink::WebString::FromUTF8(name));
|
||||
}
|
||||
|
||||
WebFrame::WebFrame(v8::Isolate* isolate, blink::WebLocalFrame* blink_frame)
|
||||
: web_frame_(blink_frame) {
|
||||
Init(isolate);
|
||||
}
|
||||
|
||||
WebFrame::~WebFrame() {}
|
||||
|
||||
void WebFrame::SetName(const std::string& name) {
|
||||
web_frame_->SetName(blink::WebString::FromUTF8(name));
|
||||
}
|
||||
|
||||
double WebFrame::SetZoomLevel(double level) {
|
||||
double SetZoomLevel(v8::Local<v8::Value> window, double level) {
|
||||
double result = 0.0;
|
||||
content::RenderFrame* render_frame =
|
||||
content::RenderFrame::FromWebFrame(web_frame_);
|
||||
content::RenderFrame* render_frame = GetRenderFrame(window);
|
||||
render_frame->Send(new AtomFrameHostMsg_SetTemporaryZoomLevel(
|
||||
render_frame->GetRoutingID(), level, &result));
|
||||
return result;
|
||||
}
|
||||
|
||||
double WebFrame::GetZoomLevel() const {
|
||||
double GetZoomLevel(v8::Local<v8::Value> window) {
|
||||
double result = 0.0;
|
||||
content::RenderFrame* render_frame =
|
||||
content::RenderFrame::FromWebFrame(web_frame_);
|
||||
content::RenderFrame* render_frame = GetRenderFrame(window);
|
||||
render_frame->Send(
|
||||
new AtomFrameHostMsg_GetZoomLevel(render_frame->GetRoutingID(), &result));
|
||||
return result;
|
||||
}
|
||||
|
||||
double WebFrame::SetZoomFactor(double factor) {
|
||||
double SetZoomFactor(v8::Local<v8::Value> window, double factor) {
|
||||
return blink::WebView::ZoomLevelToZoomFactor(
|
||||
SetZoomLevel(blink::WebView::ZoomFactorToZoomLevel(factor)));
|
||||
SetZoomLevel(window, blink::WebView::ZoomFactorToZoomLevel(factor)));
|
||||
}
|
||||
|
||||
double WebFrame::GetZoomFactor() const {
|
||||
return blink::WebView::ZoomLevelToZoomFactor(GetZoomLevel());
|
||||
double GetZoomFactor(v8::Local<v8::Value> window) {
|
||||
return blink::WebView::ZoomLevelToZoomFactor(GetZoomLevel(window));
|
||||
}
|
||||
|
||||
void WebFrame::SetVisualZoomLevelLimits(double min_level, double max_level) {
|
||||
web_frame_->View()->SetDefaultPageScaleLimits(min_level, max_level);
|
||||
web_frame_->View()->SetIgnoreViewportTagScaleLimits(true);
|
||||
void SetVisualZoomLevelLimits(v8::Local<v8::Value> window,
|
||||
double min_level,
|
||||
double max_level) {
|
||||
blink::WebFrame* web_frame = GetRenderFrame(window)->GetWebFrame();
|
||||
web_frame->View()->SetDefaultPageScaleLimits(min_level, max_level);
|
||||
web_frame->View()->SetIgnoreViewportTagScaleLimits(true);
|
||||
}
|
||||
|
||||
void WebFrame::SetLayoutZoomLevelLimits(double min_level, double max_level) {
|
||||
web_frame_->View()->ZoomLimitsChanged(min_level, max_level);
|
||||
void SetLayoutZoomLevelLimits(v8::Local<v8::Value> window,
|
||||
double min_level,
|
||||
double max_level) {
|
||||
blink::WebFrame* web_frame = GetRenderFrame(window)->GetWebFrame();
|
||||
web_frame->View()->ZoomLimitsChanged(min_level, max_level);
|
||||
}
|
||||
|
||||
void WebFrame::AllowGuestViewElementDefinition(
|
||||
v8::Local<v8::Object> context,
|
||||
v8::Local<v8::Function> register_cb) {
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
void AllowGuestViewElementDefinition(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> window,
|
||||
v8::Local<v8::Object> context,
|
||||
v8::Local<v8::Function> register_cb) {
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
v8::Context::Scope context_scope(context->CreationContext());
|
||||
blink::WebCustomElement::EmbedderNamesAllowedScope embedder_names_scope;
|
||||
web_frame_->RequestExecuteV8Function(context->CreationContext(), register_cb,
|
||||
v8::Null(isolate()), 0, nullptr,
|
||||
nullptr);
|
||||
GetRenderFrame(context)->GetWebFrame()->RequestExecuteV8Function(
|
||||
context->CreationContext(), register_cb, v8::Null(isolate), 0, nullptr,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
int WebFrame::GetWebFrameId(v8::Local<v8::Value> content_window) {
|
||||
int GetWebFrameId(v8::Local<v8::Value> window,
|
||||
v8::Local<v8::Value> content_window) {
|
||||
// Get the WebLocalFrame before (possibly) executing any user-space JS while
|
||||
// getting the |params|. We track the status of the RenderFrame via an
|
||||
// observer in case it is deleted during user code execution.
|
||||
@@ -219,9 +275,10 @@ int WebFrame::GetWebFrameId(v8::Local<v8::Value> content_window) {
|
||||
return render_frame->GetRoutingID();
|
||||
}
|
||||
|
||||
void WebFrame::SetSpellCheckProvider(mate::Arguments* args,
|
||||
const std::string& language,
|
||||
v8::Local<v8::Object> provider) {
|
||||
void SetSpellCheckProvider(mate::Arguments* args,
|
||||
v8::Local<v8::Value> window,
|
||||
const std::string& language,
|
||||
v8::Local<v8::Object> provider) {
|
||||
auto context = args->isolate()->GetCurrentContext();
|
||||
if (!provider->Has(context, mate::StringToV8(args->isolate(), "spellCheck"))
|
||||
.ToChecked()) {
|
||||
@@ -229,92 +286,61 @@ void WebFrame::SetSpellCheckProvider(mate::Arguments* args,
|
||||
return;
|
||||
}
|
||||
|
||||
auto client =
|
||||
std::make_unique<SpellCheckClient>(language, args->isolate(), provider);
|
||||
// Remove the old client.
|
||||
content::RenderFrame* render_frame = GetRenderFrame(window);
|
||||
auto* existing = SpellCheckerHolder::FromRenderFrame(render_frame);
|
||||
if (existing)
|
||||
existing->UnsetAndDestroy();
|
||||
|
||||
// Set spellchecker for all live frames in the same process or
|
||||
// in the sandbox mode for all live sub frames to this WebFrame.
|
||||
FrameSpellChecker spell_checker(
|
||||
client.get(), content::RenderFrame::FromWebFrame(web_frame_));
|
||||
content::RenderFrame::ForEach(&spell_checker);
|
||||
spell_check_client_.swap(client);
|
||||
web_frame_->SetSpellCheckPanelHostClient(spell_check_client_.get());
|
||||
auto spell_check_client =
|
||||
std::make_unique<SpellCheckClient>(language, args->isolate(), provider);
|
||||
FrameSetSpellChecker spell_checker(spell_check_client.get(), render_frame);
|
||||
|
||||
// Attach the spell checker to RenderFrame.
|
||||
new SpellCheckerHolder(render_frame, std::move(spell_check_client));
|
||||
}
|
||||
|
||||
void WebFrame::RegisterURLSchemeAsBypassingCSP(const std::string& scheme) {
|
||||
// Register scheme to bypass pages's Content Security Policy.
|
||||
blink::SchemeRegistry::RegisterURLSchemeAsBypassingContentSecurityPolicy(
|
||||
WTF::String::FromUTF8(scheme.data(), scheme.length()));
|
||||
}
|
||||
|
||||
void WebFrame::RegisterURLSchemeAsPrivileged(const std::string& scheme,
|
||||
mate::Arguments* args) {
|
||||
// TODO(deepak1556): blink::SchemeRegistry methods should be called
|
||||
// before any renderer threads are created. Fixing this would break
|
||||
// current api. Change it with 2.0.
|
||||
|
||||
// Read optional flags
|
||||
bool secure = true;
|
||||
bool bypassCSP = true;
|
||||
bool allowServiceWorkers = true;
|
||||
bool supportFetchAPI = true;
|
||||
bool corsEnabled = true;
|
||||
if (args->Length() == 2) {
|
||||
mate::Dictionary options;
|
||||
if (args->GetNext(&options)) {
|
||||
options.Get("secure", &secure);
|
||||
options.Get("bypassCSP", &bypassCSP);
|
||||
options.Get("allowServiceWorkers", &allowServiceWorkers);
|
||||
options.Get("supportFetchAPI", &supportFetchAPI);
|
||||
options.Get("corsEnabled", &corsEnabled);
|
||||
}
|
||||
}
|
||||
// Register scheme to privileged list (https, wss, data, chrome-extension)
|
||||
WTF::String privileged_scheme(
|
||||
WTF::String::FromUTF8(scheme.data(), scheme.length()));
|
||||
if (bypassCSP) {
|
||||
blink::SchemeRegistry::RegisterURLSchemeAsBypassingContentSecurityPolicy(
|
||||
privileged_scheme);
|
||||
}
|
||||
if (allowServiceWorkers) {
|
||||
blink::SchemeRegistry::RegisterURLSchemeAsAllowingServiceWorkers(
|
||||
privileged_scheme);
|
||||
}
|
||||
if (supportFetchAPI) {
|
||||
blink::SchemeRegistry::RegisterURLSchemeAsSupportingFetchAPI(
|
||||
privileged_scheme);
|
||||
}
|
||||
if (corsEnabled) {
|
||||
url::AddCorsEnabledScheme(scheme.c_str());
|
||||
void InsertText(v8::Local<v8::Value> window, const std::string& text) {
|
||||
blink::WebFrame* web_frame = GetRenderFrame(window)->GetWebFrame();
|
||||
if (web_frame->IsWebLocalFrame()) {
|
||||
web_frame->ToWebLocalFrame()
|
||||
->FrameWidget()
|
||||
->GetActiveWebInputMethodController()
|
||||
->CommitText(blink::WebString::FromUTF8(text),
|
||||
blink::WebVector<blink::WebImeTextSpan>(),
|
||||
blink::WebRange(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
void WebFrame::InsertText(const std::string& text) {
|
||||
web_frame_->FrameWidget()->GetActiveWebInputMethodController()->CommitText(
|
||||
blink::WebString::FromUTF8(text),
|
||||
blink::WebVector<blink::WebImeTextSpan>(), blink::WebRange(), 0);
|
||||
void InsertCSS(v8::Local<v8::Value> window, const std::string& css) {
|
||||
blink::WebFrame* web_frame = GetRenderFrame(window)->GetWebFrame();
|
||||
if (web_frame->IsWebLocalFrame()) {
|
||||
web_frame->ToWebLocalFrame()->GetDocument().InsertStyleSheet(
|
||||
blink::WebString::FromUTF8(css));
|
||||
}
|
||||
}
|
||||
|
||||
void WebFrame::InsertCSS(const std::string& css) {
|
||||
web_frame_->GetDocument().InsertStyleSheet(blink::WebString::FromUTF8(css));
|
||||
}
|
||||
|
||||
void WebFrame::ExecuteJavaScript(const base::string16& code,
|
||||
mate::Arguments* args) {
|
||||
void ExecuteJavaScript(mate::Arguments* args,
|
||||
v8::Local<v8::Value> window,
|
||||
const base::string16& code) {
|
||||
bool has_user_gesture = false;
|
||||
args->GetNext(&has_user_gesture);
|
||||
ScriptExecutionCallback::CompletionCallback completion_callback;
|
||||
args->GetNext(&completion_callback);
|
||||
std::unique_ptr<blink::WebScriptExecutionCallback> callback(
|
||||
new ScriptExecutionCallback(completion_callback));
|
||||
web_frame_->RequestExecuteScriptAndReturnValue(
|
||||
GetRenderFrame(window)->GetWebFrame()->RequestExecuteScriptAndReturnValue(
|
||||
blink::WebScriptSource(blink::WebString::FromUTF16(code)),
|
||||
has_user_gesture, callback.release());
|
||||
}
|
||||
|
||||
void WebFrame::ExecuteJavaScriptInIsolatedWorld(
|
||||
void ExecuteJavaScriptInIsolatedWorld(
|
||||
mate::Arguments* args,
|
||||
v8::Local<v8::Value> window,
|
||||
int world_id,
|
||||
const std::vector<mate::Dictionary>& scripts,
|
||||
mate::Arguments* args) {
|
||||
const std::vector<mate::Dictionary>& scripts) {
|
||||
std::vector<blink::WebScriptSource> sources;
|
||||
|
||||
for (const auto& script : scripts) {
|
||||
@@ -346,186 +372,132 @@ void WebFrame::ExecuteJavaScriptInIsolatedWorld(
|
||||
std::unique_ptr<blink::WebScriptExecutionCallback> callback(
|
||||
new ScriptExecutionCallback(completion_callback));
|
||||
|
||||
web_frame_->RequestExecuteScriptInIsolatedWorld(
|
||||
GetRenderFrame(window)->GetWebFrame()->RequestExecuteScriptInIsolatedWorld(
|
||||
world_id, &sources.front(), sources.size(), has_user_gesture,
|
||||
scriptExecutionType, callback.release());
|
||||
}
|
||||
|
||||
void WebFrame::SetIsolatedWorldSecurityOrigin(int world_id,
|
||||
const std::string& origin_url) {
|
||||
web_frame_->SetIsolatedWorldSecurityOrigin(
|
||||
void SetIsolatedWorldSecurityOrigin(v8::Local<v8::Value> window,
|
||||
int world_id,
|
||||
const std::string& origin_url) {
|
||||
GetRenderFrame(window)->GetWebFrame()->SetIsolatedWorldSecurityOrigin(
|
||||
world_id, blink::WebSecurityOrigin::CreateFromString(
|
||||
blink::WebString::FromUTF8(origin_url)));
|
||||
}
|
||||
|
||||
void WebFrame::SetIsolatedWorldContentSecurityPolicy(
|
||||
int world_id,
|
||||
const std::string& security_policy) {
|
||||
web_frame_->SetIsolatedWorldContentSecurityPolicy(
|
||||
void SetIsolatedWorldContentSecurityPolicy(v8::Local<v8::Value> window,
|
||||
int world_id,
|
||||
const std::string& security_policy) {
|
||||
GetRenderFrame(window)->GetWebFrame()->SetIsolatedWorldContentSecurityPolicy(
|
||||
world_id, blink::WebString::FromUTF8(security_policy));
|
||||
}
|
||||
|
||||
void WebFrame::SetIsolatedWorldHumanReadableName(int world_id,
|
||||
const std::string& name) {
|
||||
web_frame_->SetIsolatedWorldHumanReadableName(
|
||||
void SetIsolatedWorldHumanReadableName(v8::Local<v8::Value> window,
|
||||
int world_id,
|
||||
const std::string& name) {
|
||||
GetRenderFrame(window)->GetWebFrame()->SetIsolatedWorldHumanReadableName(
|
||||
world_id, blink::WebString::FromUTF8(name));
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<WebFrame> WebFrame::Create(v8::Isolate* isolate) {
|
||||
return mate::CreateHandle(isolate, new WebFrame(isolate));
|
||||
}
|
||||
|
||||
blink::WebCache::ResourceTypeStats WebFrame::GetResourceUsage(
|
||||
v8::Isolate* isolate) {
|
||||
blink::WebCache::ResourceTypeStats GetResourceUsage(v8::Isolate* isolate) {
|
||||
blink::WebCache::ResourceTypeStats stats;
|
||||
blink::WebCache::GetResourceTypeStats(&stats);
|
||||
return stats;
|
||||
}
|
||||
|
||||
void WebFrame::ClearCache(v8::Isolate* isolate) {
|
||||
void ClearCache(v8::Isolate* isolate) {
|
||||
isolate->IdleNotificationDeadline(0.5);
|
||||
blink::WebCache::Clear();
|
||||
base::MemoryPressureListener::NotifyMemoryPressure(
|
||||
base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> WebFrame::Opener() const {
|
||||
blink::WebFrame* frame = web_frame_->Opener();
|
||||
if (frame && frame->IsWebLocalFrame())
|
||||
return mate::CreateHandle(isolate(),
|
||||
new WebFrame(isolate(), frame->ToWebLocalFrame()))
|
||||
.ToV8();
|
||||
else
|
||||
return v8::Null(isolate());
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> WebFrame::Parent() const {
|
||||
blink::WebFrame* frame = web_frame_->Parent();
|
||||
if (frame && frame->IsWebLocalFrame())
|
||||
return mate::CreateHandle(isolate(),
|
||||
new WebFrame(isolate(), frame->ToWebLocalFrame()))
|
||||
.ToV8();
|
||||
else
|
||||
return v8::Null(isolate());
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> WebFrame::Top() const {
|
||||
blink::WebFrame* frame = web_frame_->Top();
|
||||
if (frame && frame->IsWebLocalFrame())
|
||||
return mate::CreateHandle(isolate(),
|
||||
new WebFrame(isolate(), frame->ToWebLocalFrame()))
|
||||
.ToV8();
|
||||
else
|
||||
return v8::Null(isolate());
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> WebFrame::FirstChild() const {
|
||||
blink::WebFrame* frame = web_frame_->FirstChild();
|
||||
if (frame && frame->IsWebLocalFrame())
|
||||
return mate::CreateHandle(isolate(),
|
||||
new WebFrame(isolate(), frame->ToWebLocalFrame()))
|
||||
.ToV8();
|
||||
else
|
||||
return v8::Null(isolate());
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> WebFrame::NextSibling() const {
|
||||
blink::WebFrame* frame = web_frame_->NextSibling();
|
||||
if (frame && frame->IsWebLocalFrame())
|
||||
return mate::CreateHandle(isolate(),
|
||||
new WebFrame(isolate(), frame->ToWebLocalFrame()))
|
||||
.ToV8();
|
||||
else
|
||||
return v8::Null(isolate());
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> WebFrame::GetFrameForSelector(
|
||||
const std::string& selector) const {
|
||||
blink::WebElement element = web_frame_->GetDocument().QuerySelector(
|
||||
blink::WebString::FromUTF8(selector));
|
||||
blink::WebLocalFrame* element_frame =
|
||||
blink::WebLocalFrame::FromFrameOwnerElement(element);
|
||||
if (element_frame)
|
||||
return mate::CreateHandle(isolate(), new WebFrame(isolate(), element_frame))
|
||||
.ToV8();
|
||||
else
|
||||
return v8::Null(isolate());
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> WebFrame::FindFrameByName(const std::string& name) const {
|
||||
blink::WebLocalFrame* local_frame =
|
||||
web_frame_->FindFrameByName(blink::WebString::FromUTF8(name))
|
||||
->ToWebLocalFrame();
|
||||
if (local_frame)
|
||||
return mate::CreateHandle(isolate(), new WebFrame(isolate(), local_frame))
|
||||
.ToV8();
|
||||
else
|
||||
return v8::Null(isolate());
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> WebFrame::FindFrameByRoutingId(int routing_id) const {
|
||||
v8::Local<v8::Value> FindFrameByRoutingId(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> window,
|
||||
int routing_id) {
|
||||
content::RenderFrame* render_frame =
|
||||
content::RenderFrame::FromRoutingID(routing_id);
|
||||
blink::WebLocalFrame* local_frame = nullptr;
|
||||
if (render_frame)
|
||||
local_frame = render_frame->GetWebFrame();
|
||||
if (local_frame)
|
||||
return mate::CreateHandle(isolate(), new WebFrame(isolate(), local_frame))
|
||||
.ToV8();
|
||||
return render_frame->GetWebFrame()->MainWorldScriptContext()->Global();
|
||||
else
|
||||
return v8::Null(isolate());
|
||||
return v8::Null(isolate);
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> WebFrame::RoutingId() const {
|
||||
int routing_id = content::RenderFrame::GetRoutingIdForWebFrame(web_frame_);
|
||||
return v8::Number::New(isolate(), routing_id);
|
||||
v8::Local<v8::Value> GetOpener(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> window) {
|
||||
blink::WebFrame* frame = GetRenderFrame(window)->GetWebFrame()->Opener();
|
||||
if (frame && frame->IsWebLocalFrame())
|
||||
return frame->ToWebLocalFrame()->MainWorldScriptContext()->Global();
|
||||
else
|
||||
return v8::Null(isolate);
|
||||
}
|
||||
|
||||
// static
|
||||
void WebFrame::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "WebFrame"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetMethod("setName", &WebFrame::SetName)
|
||||
.SetMethod("setZoomLevel", &WebFrame::SetZoomLevel)
|
||||
.SetMethod("getZoomLevel", &WebFrame::GetZoomLevel)
|
||||
.SetMethod("setZoomFactor", &WebFrame::SetZoomFactor)
|
||||
.SetMethod("getZoomFactor", &WebFrame::GetZoomFactor)
|
||||
.SetMethod("setVisualZoomLevelLimits",
|
||||
&WebFrame::SetVisualZoomLevelLimits)
|
||||
.SetMethod("setLayoutZoomLevelLimits",
|
||||
&WebFrame::SetLayoutZoomLevelLimits)
|
||||
.SetMethod("allowGuestViewElementDefinition",
|
||||
&WebFrame::AllowGuestViewElementDefinition)
|
||||
.SetMethod("getWebFrameId", &WebFrame::GetWebFrameId)
|
||||
.SetMethod("setSpellCheckProvider", &WebFrame::SetSpellCheckProvider)
|
||||
.SetMethod("registerURLSchemeAsBypassingCSP",
|
||||
&WebFrame::RegisterURLSchemeAsBypassingCSP)
|
||||
.SetMethod("registerURLSchemeAsPrivileged",
|
||||
&WebFrame::RegisterURLSchemeAsPrivileged)
|
||||
.SetMethod("insertText", &WebFrame::InsertText)
|
||||
.SetMethod("insertCSS", &WebFrame::InsertCSS)
|
||||
.SetMethod("executeJavaScript", &WebFrame::ExecuteJavaScript)
|
||||
.SetMethod("executeJavaScriptInIsolatedWorld",
|
||||
&WebFrame::ExecuteJavaScriptInIsolatedWorld)
|
||||
.SetMethod("setIsolatedWorldSecurityOrigin",
|
||||
&WebFrame::SetIsolatedWorldSecurityOrigin)
|
||||
.SetMethod("setIsolatedWorldContentSecurityPolicy",
|
||||
&WebFrame::SetIsolatedWorldContentSecurityPolicy)
|
||||
.SetMethod("setIsolatedWorldHumanReadableName",
|
||||
&WebFrame::SetIsolatedWorldHumanReadableName)
|
||||
.SetMethod("getResourceUsage", &WebFrame::GetResourceUsage)
|
||||
.SetMethod("clearCache", &WebFrame::ClearCache)
|
||||
.SetMethod("getFrameForSelector", &WebFrame::GetFrameForSelector)
|
||||
.SetMethod("findFrameByName", &WebFrame::FindFrameByName)
|
||||
.SetProperty("opener", &WebFrame::Opener)
|
||||
.SetProperty("parent", &WebFrame::Parent)
|
||||
.SetProperty("top", &WebFrame::Top)
|
||||
.SetProperty("firstChild", &WebFrame::FirstChild)
|
||||
.SetProperty("nextSibling", &WebFrame::NextSibling)
|
||||
.SetProperty("routingId", &WebFrame::RoutingId)
|
||||
.SetMethod("findFrameByRoutingId", &WebFrame::FindFrameByRoutingId);
|
||||
// Don't name it as GetParent, Windows has API with same name.
|
||||
v8::Local<v8::Value> GetFrameParent(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> window) {
|
||||
blink::WebFrame* frame = GetRenderFrame(window)->GetWebFrame()->Parent();
|
||||
if (frame && frame->IsWebLocalFrame())
|
||||
return frame->ToWebLocalFrame()->MainWorldScriptContext()->Global();
|
||||
else
|
||||
return v8::Null(isolate);
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> GetTop(v8::Isolate* isolate, v8::Local<v8::Value> window) {
|
||||
blink::WebFrame* frame = GetRenderFrame(window)->GetWebFrame()->Top();
|
||||
if (frame && frame->IsWebLocalFrame())
|
||||
return frame->ToWebLocalFrame()->MainWorldScriptContext()->Global();
|
||||
else
|
||||
return v8::Null(isolate);
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> GetFirstChild(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> window) {
|
||||
blink::WebFrame* frame = GetRenderFrame(window)->GetWebFrame()->FirstChild();
|
||||
if (frame && frame->IsWebLocalFrame())
|
||||
return frame->ToWebLocalFrame()->MainWorldScriptContext()->Global();
|
||||
else
|
||||
return v8::Null(isolate);
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> GetNextSibling(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> window) {
|
||||
blink::WebFrame* frame = GetRenderFrame(window)->GetWebFrame()->NextSibling();
|
||||
if (frame && frame->IsWebLocalFrame())
|
||||
return frame->ToWebLocalFrame()->MainWorldScriptContext()->Global();
|
||||
else
|
||||
return v8::Null(isolate);
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> GetFrameForSelector(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> window,
|
||||
const std::string& selector) {
|
||||
blink::WebElement element =
|
||||
GetRenderFrame(window)->GetWebFrame()->GetDocument().QuerySelector(
|
||||
blink::WebString::FromUTF8(selector));
|
||||
if (element.IsNull()) // not found
|
||||
return v8::Null(isolate);
|
||||
|
||||
blink::WebFrame* frame = blink::WebFrame::FromFrameOwnerElement(element);
|
||||
if (frame && frame->IsWebLocalFrame())
|
||||
return frame->ToWebLocalFrame()->MainWorldScriptContext()->Global();
|
||||
else
|
||||
return v8::Null(isolate);
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> FindFrameByName(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> window,
|
||||
const std::string& name) {
|
||||
blink::WebFrame* frame =
|
||||
GetRenderFrame(window)->GetWebFrame()->FindFrameByName(
|
||||
blink::WebString::FromUTF8(name));
|
||||
if (frame && frame->IsWebLocalFrame())
|
||||
return frame->ToWebLocalFrame()->MainWorldScriptContext()->Global();
|
||||
else
|
||||
return v8::Null(isolate);
|
||||
}
|
||||
|
||||
int GetRoutingId(v8::Local<v8::Value> window) {
|
||||
return GetRenderFrame(window)->GetRoutingID();
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
@@ -534,18 +506,47 @@ void WebFrame::BuildPrototype(v8::Isolate* isolate,
|
||||
|
||||
namespace {
|
||||
|
||||
using atom::api::WebFrame;
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
using namespace atom::api; // NOLINT(build/namespaces)
|
||||
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("webFrame", WebFrame::Create(isolate));
|
||||
dict.Set(
|
||||
"WebFrame",
|
||||
WebFrame::GetConstructor(isolate)->GetFunction(context).ToLocalChecked());
|
||||
dict.SetMethod("setName", &SetName);
|
||||
dict.SetMethod("setZoomLevel", &SetZoomLevel);
|
||||
dict.SetMethod("getZoomLevel", &GetZoomLevel);
|
||||
dict.SetMethod("setZoomFactor", &SetZoomFactor);
|
||||
dict.SetMethod("getZoomFactor", &GetZoomFactor);
|
||||
dict.SetMethod("setVisualZoomLevelLimits", &SetVisualZoomLevelLimits);
|
||||
dict.SetMethod("setLayoutZoomLevelLimits", &SetLayoutZoomLevelLimits);
|
||||
dict.SetMethod("allowGuestViewElementDefinition",
|
||||
&AllowGuestViewElementDefinition);
|
||||
dict.SetMethod("getWebFrameId", &GetWebFrameId);
|
||||
dict.SetMethod("setSpellCheckProvider", &SetSpellCheckProvider);
|
||||
dict.SetMethod("insertText", &InsertText);
|
||||
dict.SetMethod("insertCSS", &InsertCSS);
|
||||
dict.SetMethod("executeJavaScript", &ExecuteJavaScript);
|
||||
dict.SetMethod("executeJavaScriptInIsolatedWorld",
|
||||
&ExecuteJavaScriptInIsolatedWorld);
|
||||
dict.SetMethod("setIsolatedWorldSecurityOrigin",
|
||||
&SetIsolatedWorldSecurityOrigin);
|
||||
dict.SetMethod("setIsolatedWorldContentSecurityPolicy",
|
||||
&SetIsolatedWorldContentSecurityPolicy);
|
||||
dict.SetMethod("setIsolatedWorldHumanReadableName",
|
||||
&SetIsolatedWorldHumanReadableName);
|
||||
dict.SetMethod("getResourceUsage", &GetResourceUsage);
|
||||
dict.SetMethod("clearCache", &ClearCache);
|
||||
dict.SetMethod("_findFrameByRoutingId", &FindFrameByRoutingId);
|
||||
dict.SetMethod("_getFrameForSelector", &GetFrameForSelector);
|
||||
dict.SetMethod("_findFrameByName", &FindFrameByName);
|
||||
dict.SetMethod("_getOpener", &GetOpener);
|
||||
dict.SetMethod("_getParent", &GetFrameParent);
|
||||
dict.SetMethod("_getTop", &GetTop);
|
||||
dict.SetMethod("_getFirstChild", &GetFirstChild);
|
||||
dict.SetMethod("_getNextSibling", &GetNextSibling);
|
||||
dict.SetMethod("_getRoutingId", &GetRoutingId);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
// Copyright (c) 2014 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_RENDERER_API_ATOM_API_WEB_FRAME_H_
|
||||
#define ATOM_RENDERER_API_ATOM_API_WEB_FRAME_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "native_mate/handle.h"
|
||||
#include "native_mate/wrappable.h"
|
||||
#include "third_party/blink/public/platform/web_cache.h"
|
||||
|
||||
namespace blink {
|
||||
class WebLocalFrame;
|
||||
}
|
||||
|
||||
namespace mate {
|
||||
class Dictionary;
|
||||
class Arguments;
|
||||
} // namespace mate
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class SpellCheckClient;
|
||||
|
||||
class WebFrame : public mate::Wrappable<WebFrame> {
|
||||
public:
|
||||
static mate::Handle<WebFrame> Create(v8::Isolate* isolate);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
private:
|
||||
explicit WebFrame(v8::Isolate* isolate);
|
||||
explicit WebFrame(v8::Isolate* isolate, blink::WebLocalFrame* blink_frame);
|
||||
~WebFrame() override;
|
||||
|
||||
void SetName(const std::string& name);
|
||||
|
||||
double SetZoomLevel(double level);
|
||||
double GetZoomLevel() const;
|
||||
double SetZoomFactor(double factor);
|
||||
double GetZoomFactor() const;
|
||||
|
||||
void SetVisualZoomLevelLimits(double min_level, double max_level);
|
||||
void SetLayoutZoomLevelLimits(double min_level, double max_level);
|
||||
|
||||
void AllowGuestViewElementDefinition(v8::Local<v8::Object> context,
|
||||
v8::Local<v8::Function> register_cb);
|
||||
int GetWebFrameId(v8::Local<v8::Value> content_window);
|
||||
|
||||
// Set the provider that will be used by SpellCheckClient for spell check.
|
||||
void SetSpellCheckProvider(mate::Arguments* args,
|
||||
const std::string& language,
|
||||
v8::Local<v8::Object> provider);
|
||||
|
||||
void RegisterURLSchemeAsBypassingCSP(const std::string& scheme);
|
||||
void RegisterURLSchemeAsPrivileged(const std::string& scheme,
|
||||
mate::Arguments* args);
|
||||
|
||||
// Editing.
|
||||
void InsertText(const std::string& text);
|
||||
void InsertCSS(const std::string& css);
|
||||
|
||||
// Executing scripts.
|
||||
void ExecuteJavaScript(const base::string16& code, mate::Arguments* args);
|
||||
void ExecuteJavaScriptInIsolatedWorld(
|
||||
int world_id,
|
||||
const std::vector<mate::Dictionary>& scripts,
|
||||
mate::Arguments* args);
|
||||
|
||||
// Isolated world related methods
|
||||
void SetIsolatedWorldSecurityOrigin(int world_id,
|
||||
const std::string& origin_url);
|
||||
void SetIsolatedWorldContentSecurityPolicy(
|
||||
int world_id,
|
||||
const std::string& security_policy);
|
||||
void SetIsolatedWorldHumanReadableName(int world_id, const std::string& name);
|
||||
|
||||
// Resource related methods
|
||||
blink::WebCache::ResourceTypeStats GetResourceUsage(v8::Isolate* isolate);
|
||||
void ClearCache(v8::Isolate* isolate);
|
||||
|
||||
// Frame navigation
|
||||
v8::Local<v8::Value> Opener() const;
|
||||
v8::Local<v8::Value> Parent() const;
|
||||
v8::Local<v8::Value> Top() const;
|
||||
v8::Local<v8::Value> FirstChild() const;
|
||||
v8::Local<v8::Value> NextSibling() const;
|
||||
v8::Local<v8::Value> GetFrameForSelector(const std::string& selector) const;
|
||||
v8::Local<v8::Value> FindFrameByName(const std::string& name) const;
|
||||
v8::Local<v8::Value> FindFrameByRoutingId(int routing_id) const;
|
||||
v8::Local<v8::Value> RoutingId() const;
|
||||
|
||||
std::unique_ptr<SpellCheckClient> spell_check_client_;
|
||||
|
||||
blink::WebLocalFrame* web_frame_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(WebFrame);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_RENDERER_API_ATOM_API_WEB_FRAME_H_
|
||||
@@ -212,11 +212,10 @@ void AtomRenderFrameObserver::OnTakeHeapSnapshot(
|
||||
bool success = TakeHeapSnapshot(blink::MainThreadIsolate(), &file);
|
||||
|
||||
base::ListValue args;
|
||||
args.AppendString(channel);
|
||||
args.AppendBoolean(success);
|
||||
|
||||
render_frame_->Send(new AtomFrameHostMsg_Message(
|
||||
render_frame_->GetRoutingID(), "ipc-internal-message", args));
|
||||
render_frame_->GetRoutingID(), true, channel, args));
|
||||
}
|
||||
|
||||
void AtomRenderFrameObserver::EmitIPCEvent(blink::WebLocalFrame* frame,
|
||||
|
||||
@@ -114,11 +114,12 @@ class AtomSandboxedRenderFrameObserver : public AtomRenderFrameObserver {
|
||||
auto context = renderer_client_->GetContext(frame, isolate);
|
||||
v8::Context::Scope context_scope(context);
|
||||
|
||||
v8::Local<v8::Value> argv[] = {mate::ConvertToV8(isolate, channel),
|
||||
v8::Local<v8::Value> argv[] = {mate::ConvertToV8(isolate, internal),
|
||||
mate::ConvertToV8(isolate, channel),
|
||||
mate::ConvertToV8(isolate, args),
|
||||
mate::ConvertToV8(isolate, sender_id)};
|
||||
renderer_client_->InvokeIpcCallback(
|
||||
context, internal ? "onInternalMessage" : "onMessage",
|
||||
context, "onMessage",
|
||||
std::vector<v8::Local<v8::Value>>(argv, argv + node::arraysize(argv)));
|
||||
}
|
||||
|
||||
|
||||
@@ -163,6 +163,25 @@ void RendererClientBase::RenderThreadStarted() {
|
||||
blink::SchemeRegistry::RegisterURLSchemeAsSecure(
|
||||
WTF::String::FromUTF8(scheme.data(), scheme.length()));
|
||||
|
||||
std::vector<std::string> fetch_enabled_schemes =
|
||||
ParseSchemesCLISwitch(command_line, switches::kFetchSchemes);
|
||||
for (const std::string& scheme : fetch_enabled_schemes) {
|
||||
blink::WebSecurityPolicy::RegisterURLSchemeAsSupportingFetchAPI(
|
||||
blink::WebString::FromASCII(scheme));
|
||||
}
|
||||
|
||||
std::vector<std::string> service_worker_schemes =
|
||||
ParseSchemesCLISwitch(command_line, switches::kServiceWorkerSchemes);
|
||||
for (const std::string& scheme : service_worker_schemes)
|
||||
blink::WebSecurityPolicy::RegisterURLSchemeAsAllowingServiceWorkers(
|
||||
blink::WebString::FromASCII(scheme));
|
||||
|
||||
std::vector<std::string> csp_bypassing_schemes =
|
||||
ParseSchemesCLISwitch(command_line, switches::kBypassCSPSchemes);
|
||||
for (const std::string& scheme : csp_bypassing_schemes)
|
||||
blink::SchemeRegistry::RegisterURLSchemeAsBypassingContentSecurityPolicy(
|
||||
WTF::String::FromUTF8(scheme.data(), scheme.length()));
|
||||
|
||||
// Allow file scheme to handle service worker by default.
|
||||
// FIXME(zcbenz): Can this be moved elsewhere?
|
||||
blink::WebSecurityPolicy::RegisterURLSchemeAsAllowingServiceWorkers("file");
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import("npm.gni")
|
||||
import("node.gni")
|
||||
|
||||
# TODO(MarshallOfSound): Move to electron/node, this is the only place it is used now
|
||||
# Run an action with a given working directory. Behaves identically to the
|
||||
# action() target type, with the exception that it changes directory before
|
||||
# running the script.
|
||||
@@ -32,19 +33,28 @@ template("chdir_action") {
|
||||
|
||||
template("asar") {
|
||||
assert(defined(invoker.sources),
|
||||
"Need sources in $target_name listing the JS files.")
|
||||
"Need sources in $target_name listing the source files")
|
||||
assert(defined(invoker.outputs),
|
||||
"Need asar name (as 1-element array, e.g. \$root_out_dir/foo.asar)")
|
||||
assert(defined(invoker.root), "Need asar root directory")
|
||||
asar_root = invoker.root
|
||||
assert(defined(invoker.root), "Need the base dir for generating the ASAR")
|
||||
|
||||
# js2asar.py expects relative paths to its inputs, so we must run it in a
|
||||
# working directory in which those relative paths make sense.
|
||||
chdir_action(target_name) {
|
||||
sources = invoker.sources
|
||||
outputs = invoker.outputs
|
||||
script = "//electron/tools/js2asar.py"
|
||||
cwd = rebase_path(get_path_info(".", "abspath"))
|
||||
args = rebase_path(outputs, cwd) + [ asar_root ] + rebase_path(sources, ".")
|
||||
node_action(target_name) {
|
||||
forward_variables_from(invoker,
|
||||
"*",
|
||||
[
|
||||
"script",
|
||||
"args",
|
||||
])
|
||||
|
||||
script = "//electron/script/gn-asar.js"
|
||||
args = [
|
||||
"--base",
|
||||
rebase_path(root),
|
||||
"--files",
|
||||
] + rebase_path(sources) +
|
||||
[
|
||||
"--out",
|
||||
rebase_path(outputs[0]),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
21
build/node.gni
Normal file
21
build/node.gni
Normal file
@@ -0,0 +1,21 @@
|
||||
template("node_action") {
|
||||
assert(defined(invoker.script), "Need script path to run")
|
||||
assert(defined(invoker.args), "Need script argumets")
|
||||
|
||||
action(target_name) {
|
||||
forward_variables_from(invoker,
|
||||
[
|
||||
"deps",
|
||||
"public_deps",
|
||||
"sources",
|
||||
"inputs",
|
||||
"outputs",
|
||||
])
|
||||
if (!defined(inputs)) {
|
||||
inputs = []
|
||||
}
|
||||
inputs += [ invoker.script ]
|
||||
script = "//electron/build/run-node.py"
|
||||
args = [ rebase_path(invoker.script) ] + invoker.args
|
||||
}
|
||||
}
|
||||
14
build/run-node.py
Normal file
14
build/run-node.py
Normal file
@@ -0,0 +1,14 @@
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
SOURCE_ROOT = os.path.dirname(os.path.dirname(__file__))
|
||||
|
||||
def main():
|
||||
# Proxy all args to node script
|
||||
script = os.path.join(SOURCE_ROOT, sys.argv[1])
|
||||
subprocess.check_call(['node', script] + [str(x) for x in sys.argv[2:]])
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
50
build/tsc.gni
Normal file
50
build/tsc.gni
Normal file
@@ -0,0 +1,50 @@
|
||||
import("npm.gni")
|
||||
|
||||
template("typescript_build") {
|
||||
assert(defined(invoker.tsconfig), "Need tsconfig name to run")
|
||||
assert(defined(invoker.sources), "Need tsc sources to run")
|
||||
assert(defined(invoker.output_dir_name),
|
||||
"Need output_dir_name to run, should be 'lib' or other top level dir")
|
||||
assert(defined(invoker.output_gen_dir),
|
||||
"Need output_gen_dir to run, should be relative to the root gen dir")
|
||||
|
||||
npm_action(target_name) {
|
||||
forward_variables_from(invoker,
|
||||
[
|
||||
"deps",
|
||||
"public_deps",
|
||||
"outputs",
|
||||
])
|
||||
script = "tsc"
|
||||
|
||||
sources = invoker.sources
|
||||
inputs = [
|
||||
invoker.tsconfig,
|
||||
"//electron/tsconfig.json",
|
||||
"//electron/package-lock.json",
|
||||
]
|
||||
|
||||
type_roots = "node_modules/@types,typings"
|
||||
if (defined(invoker.type_root)) {
|
||||
type_roots += "," + invoker.type_root
|
||||
}
|
||||
|
||||
base_out_path = invoker.output_gen_dir + "/electron/"
|
||||
args = [
|
||||
"-p",
|
||||
rebase_path(invoker.tsconfig),
|
||||
"--outDir",
|
||||
rebase_path("$base_out_path" + invoker.output_dir_name),
|
||||
"--typeRoots",
|
||||
type_roots,
|
||||
]
|
||||
|
||||
outputs = []
|
||||
|
||||
foreach(invoker_source, invoker.sources) {
|
||||
# The output of TSC is all inputs but with JS instead of TS as the extension
|
||||
outputs += [ "$base_out_path" + get_path_info(invoker_source, "dir") +
|
||||
"/" + get_path_info(invoker_source, "name") + ".js" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ declare_args() {
|
||||
# Allow running Electron as a node binary.
|
||||
enable_run_as_node = true
|
||||
|
||||
enable_osr = false
|
||||
enable_osr = true
|
||||
|
||||
enable_view_api = false
|
||||
|
||||
|
||||
@@ -41,6 +41,8 @@ static_library("chrome") {
|
||||
"//chrome/browser/net/proxy_service_factory.h",
|
||||
"//chrome/browser/ssl/security_state_tab_helper.cc",
|
||||
"//chrome/browser/ssl/security_state_tab_helper.h",
|
||||
"//chrome/browser/ui/autofill/popup_view_common.cc",
|
||||
"//chrome/browser/ui/autofill/popup_view_common.h",
|
||||
"//chrome/browser/win/chrome_process_finder.cc",
|
||||
"//chrome/browser/win/chrome_process_finder.h",
|
||||
"//extensions/browser/app_window/size_constraints.cc",
|
||||
@@ -51,6 +53,7 @@ static_library("chrome") {
|
||||
]
|
||||
deps = [
|
||||
"//chrome/common",
|
||||
"//components/feature_engagement:buildflags",
|
||||
"//components/keyed_service/content",
|
||||
"//components/proxy_config",
|
||||
"//components/security_state/content",
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
'use strict'
|
||||
import { app, BrowserWindow, BrowserWindowConstructorOptions } from 'electron'
|
||||
import * as path from 'path'
|
||||
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
let mainWindow = null
|
||||
let mainWindow: BrowserWindow | null = null
|
||||
|
||||
// Quit when all windows are closed.
|
||||
app.on('window-all-closed', () => {
|
||||
app.quit()
|
||||
})
|
||||
|
||||
exports.load = async (appUrl) => {
|
||||
export const load = async (appUrl: string) => {
|
||||
await app.whenReady()
|
||||
|
||||
const options = {
|
||||
const options: BrowserWindowConstructorOptions = {
|
||||
width: 900,
|
||||
height: 600,
|
||||
autoHideMenuBar: true,
|
||||
@@ -33,7 +31,7 @@ exports.load = async (appUrl) => {
|
||||
|
||||
mainWindow = new BrowserWindow(options)
|
||||
|
||||
mainWindow.on('ready-to-show', () => mainWindow.show())
|
||||
mainWindow.on('ready-to-show', () => mainWindow!.show())
|
||||
|
||||
mainWindow.loadURL(appUrl)
|
||||
mainWindow.focus()
|
||||
@@ -4,7 +4,7 @@
|
||||
<title>Electron</title>
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self'" />
|
||||
<link href="./styles.css" type="text/css" rel="stylesheet" />
|
||||
<link href="./node_modules/octicons/build/build.css" type="text/css" rel="stylesheet" />
|
||||
<link href="./octicon/build.css" type="text/css" rel="stylesheet" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
@@ -1,20 +1,31 @@
|
||||
'use strict'
|
||||
import { app, dialog } from 'electron'
|
||||
|
||||
const { app, dialog } = require('electron')
|
||||
import * as fs from 'fs'
|
||||
import * as path from 'path'
|
||||
import * as url from 'url'
|
||||
|
||||
type DefaultAppOptions = {
|
||||
file: null | string;
|
||||
noHelp: boolean;
|
||||
version: boolean;
|
||||
webdriver: boolean;
|
||||
interactive: boolean;
|
||||
abi: boolean;
|
||||
modules: string[];
|
||||
}
|
||||
|
||||
const fs = require('fs')
|
||||
const Module = require('module')
|
||||
const path = require('path')
|
||||
const url = require('url')
|
||||
|
||||
// Parse command line options.
|
||||
const argv = process.argv.slice(1)
|
||||
|
||||
const option = {
|
||||
const option: DefaultAppOptions = {
|
||||
file: null,
|
||||
noHelp: Boolean(process.env.ELECTRON_NO_HELP),
|
||||
version: null,
|
||||
webdriver: null,
|
||||
version: false,
|
||||
webdriver: false,
|
||||
interactive: false,
|
||||
abi: false,
|
||||
modules: []
|
||||
}
|
||||
|
||||
@@ -62,7 +73,7 @@ if (option.modules.length > 0) {
|
||||
Module._preloadModules(option.modules)
|
||||
}
|
||||
|
||||
function loadApplicationPackage (packagePath) {
|
||||
function loadApplicationPackage (packagePath: string) {
|
||||
// Add a flag indicating app is started from default app.
|
||||
Object.defineProperty(process, 'defaultApp', {
|
||||
configurable: false,
|
||||
@@ -112,14 +123,15 @@ function loadApplicationPackage (packagePath) {
|
||||
}
|
||||
}
|
||||
|
||||
function showErrorMessage (message) {
|
||||
function showErrorMessage (message: string) {
|
||||
app.focus()
|
||||
dialog.showErrorBox('Error launching app', message)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
function loadApplicationByUrl (appUrl) {
|
||||
require('./default_app').load(appUrl)
|
||||
async function loadApplicationByUrl (appUrl: string) {
|
||||
const { load } = await import('./default_app')
|
||||
load(appUrl)
|
||||
}
|
||||
|
||||
function startRepl () {
|
||||
@@ -1,67 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
const { remote, shell } = require('electron')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const URL = require('url')
|
||||
|
||||
function initialize () {
|
||||
// Find the shortest path to the electron binary
|
||||
const absoluteElectronPath = remote.process.execPath
|
||||
const relativeElectronPath = path.relative(process.cwd(), absoluteElectronPath)
|
||||
const electronPath = absoluteElectronPath.length < relativeElectronPath.length
|
||||
? absoluteElectronPath
|
||||
: relativeElectronPath
|
||||
|
||||
for (const link of document.querySelectorAll('a[href]')) {
|
||||
// safely add `?utm_source=default_app
|
||||
const parsedUrl = URL.parse(link.getAttribute('href'), true)
|
||||
parsedUrl.query = { ...parsedUrl.query, utm_source: 'default_app' }
|
||||
const url = URL.format(parsedUrl)
|
||||
|
||||
const openLinkExternally = (e) => {
|
||||
e.preventDefault()
|
||||
shell.openExternalSync(url)
|
||||
}
|
||||
|
||||
link.addEventListener('click', openLinkExternally)
|
||||
link.addEventListener('auxclick', openLinkExternally)
|
||||
}
|
||||
|
||||
document.querySelector('.electron-version').innerText = `Electron v${process.versions.electron}`
|
||||
document.querySelector('.chrome-version').innerText = `Chromium v${process.versions.chrome}`
|
||||
document.querySelector('.node-version').innerText = `Node v${process.versions.node}`
|
||||
document.querySelector('.v8-version').innerText = `v8 v${process.versions.v8}`
|
||||
document.querySelector('.command-example').innerText = `${electronPath} path-to-app`
|
||||
|
||||
function getOcticonSvg (name) {
|
||||
const octiconPath = path.resolve(__dirname, 'node_modules', 'octicons', 'build', 'svg', `${name}.svg`)
|
||||
if (fs.existsSync(octiconPath)) {
|
||||
const content = fs.readFileSync(octiconPath, 'utf8')
|
||||
const div = document.createElement('div')
|
||||
div.innerHTML = content
|
||||
return div
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function loadSVG (element) {
|
||||
for (const cssClass of element.classList) {
|
||||
if (cssClass.startsWith('octicon-')) {
|
||||
const icon = getOcticonSvg(cssClass.substr(8))
|
||||
if (icon) {
|
||||
icon.classList = element.classList
|
||||
element.parentNode.insertBefore(icon, element)
|
||||
element.remove()
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const element of document.querySelectorAll('.octicon')) {
|
||||
loadSVG(element)
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('load', initialize)
|
||||
67
default_app/renderer.ts
Normal file
67
default_app/renderer.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import { remote, shell } from 'electron'
|
||||
import * as fs from 'fs'
|
||||
import * as path from 'path'
|
||||
import * as URL from 'url'
|
||||
|
||||
function initialize () {
|
||||
// Find the shortest path to the electron binary
|
||||
const absoluteElectronPath = remote.process.execPath
|
||||
const relativeElectronPath = path.relative(process.cwd(), absoluteElectronPath)
|
||||
const electronPath = absoluteElectronPath.length < relativeElectronPath.length
|
||||
? absoluteElectronPath
|
||||
: relativeElectronPath
|
||||
|
||||
for (const link of document.querySelectorAll<HTMLLinkElement>('a[href]')) {
|
||||
// safely add `?utm_source=default_app
|
||||
const parsedUrl = URL.parse(link.getAttribute('href')!, true)
|
||||
parsedUrl.query = { ...parsedUrl.query, utm_source: 'default_app' }
|
||||
const url = URL.format(parsedUrl)
|
||||
|
||||
const openLinkExternally = (e: Event) => {
|
||||
e.preventDefault()
|
||||
shell.openExternalSync(url)
|
||||
}
|
||||
|
||||
link.addEventListener('click', openLinkExternally)
|
||||
link.addEventListener('auxclick', openLinkExternally)
|
||||
}
|
||||
|
||||
document.querySelector<HTMLAnchorElement>('.electron-version')!.innerText = `Electron v${process.versions.electron}`
|
||||
document.querySelector<HTMLAnchorElement>('.chrome-version')!.innerText = `Chromium v${process.versions.chrome}`
|
||||
document.querySelector<HTMLAnchorElement>('.node-version')!.innerText = `Node v${process.versions.node}`
|
||||
document.querySelector<HTMLAnchorElement>('.v8-version')!.innerText = `v8 v${process.versions.v8}`
|
||||
document.querySelector<HTMLAnchorElement>('.command-example')!.innerText = `${electronPath} path-to-app`
|
||||
|
||||
function getOcticonSvg (name: string) {
|
||||
const octiconPath = path.resolve(__dirname, 'octicon', `${name}.svg`)
|
||||
if (fs.existsSync(octiconPath)) {
|
||||
const content = fs.readFileSync(octiconPath, 'utf8')
|
||||
const div = document.createElement('div')
|
||||
div.innerHTML = content
|
||||
return div
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function loadSVG (element: HTMLSpanElement) {
|
||||
for (const cssClass of element.classList) {
|
||||
if (cssClass.startsWith('octicon-')) {
|
||||
const icon = getOcticonSvg(cssClass.substr(8))
|
||||
if (icon) {
|
||||
for (const elemClass of element.classList) {
|
||||
icon.classList.add(elemClass)
|
||||
}
|
||||
element.before(icon)
|
||||
element.remove()
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const element of document.querySelectorAll<HTMLSpanElement>('.octicon')) {
|
||||
loadSVG(element)
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('load', initialize)
|
||||
@@ -58,6 +58,9 @@ The `Super` key is mapped to the `Windows` key on Windows and Linux and
|
||||
* `Plus`
|
||||
* `Space`
|
||||
* `Tab`
|
||||
* `Capslock`
|
||||
* `Numlock`
|
||||
* `Scrolllock`
|
||||
* `Backspace`
|
||||
* `Delete`
|
||||
* `Insert`
|
||||
|
||||
@@ -606,7 +606,7 @@ You can request the following paths by the name:
|
||||
|
||||
Fetches a path's associated icon.
|
||||
|
||||
On _Windows_, there a 2 kinds of icons:
|
||||
On _Windows_, there are 2 kinds of icons:
|
||||
|
||||
- Icons associated with certain file extensions, like `.mp3`, `.png`, etc.
|
||||
- Icons inside the file itself, like `.exe`, `.dll`, `.ico`.
|
||||
@@ -725,6 +725,11 @@ your app's `info.plist`, which can not be modified at runtime. You can however
|
||||
change the file with a simple text editor or script during build time.
|
||||
Please refer to [Apple's documentation][CFBundleURLTypes] for details.
|
||||
|
||||
**Note:** In a Windows Store environment (when packaged as an `appx`) this API
|
||||
will return `true` for all calls but the registry key it sets won't be accessible
|
||||
by other applications. In order to register your Windows Store application
|
||||
as a default protocol handler you must [declare the protocol in your manifest](https://docs.microsoft.com/en-us/uwp/schemas/appxpackage/uapmanifestschema/element-uap-protocol).
|
||||
|
||||
The API uses the Windows Registry and LSSetDefaultHandlerForURLScheme internally.
|
||||
|
||||
### `app.removeAsDefaultProtocolClient(protocol[, path, args])` _macOS_ _Windows_
|
||||
@@ -1188,22 +1193,25 @@ Start accessing a security scoped resource. With this method Electron applicatio
|
||||
|
||||
### `app.commandLine.appendSwitch(switch[, value])`
|
||||
|
||||
* `switch` String - A command-line switch
|
||||
* `switch` String - A command-line switch, without the leading `--`
|
||||
* `value` String (optional) - A value for the given switch
|
||||
|
||||
Append a switch (with optional `value`) to Chromium's command line.
|
||||
|
||||
**Note:** This will not affect `process.argv`, and is mainly used by developers
|
||||
to control some low-level Chromium behaviors.
|
||||
**Note:** This will not affect `process.argv`. The intended usage of this function is to
|
||||
control Chromium's behavior.
|
||||
|
||||
### `app.commandLine.appendArgument(value)`
|
||||
|
||||
* `value` String - The argument to append to the command line
|
||||
|
||||
Append an argument to Chromium's command line. The argument will be quoted
|
||||
correctly.
|
||||
correctly. Switches will precede arguments regardless of appending order.
|
||||
|
||||
**Note:** This will not affect `process.argv`.
|
||||
If you're appending an argument like `--switch=value`, consider using `appendSwitch('switch', 'value')` instead.
|
||||
|
||||
**Note:** This will not affect `process.argv`. The intended usage of this function is to
|
||||
control Chromium's behavior.
|
||||
|
||||
### `app.commandLine.hasSwitch(switch)`
|
||||
|
||||
@@ -1217,7 +1225,7 @@ Returns `Boolean` - Whether the command-line switch is present.
|
||||
|
||||
Returns `String` - The command-line switch value.
|
||||
|
||||
**Note:** When the switch is not present, it returns empty string.
|
||||
**Note:** When the switch is not present or has no value, it returns empty string.
|
||||
|
||||
### `app.enableSandbox()` _Experimental_ _macOS_ _Windows_
|
||||
|
||||
|
||||
@@ -8,6 +8,15 @@ The `FIXME` string is used in code comments to denote things that should be fixe
|
||||
|
||||
# Planned Breaking API Changes (6.0)
|
||||
|
||||
## `win.setMenu(null)`
|
||||
|
||||
```js
|
||||
// Deprecated
|
||||
win.setMenu(null)
|
||||
// Replace with
|
||||
win.removeMenu()
|
||||
```
|
||||
|
||||
## `electron.screen` in renderer process
|
||||
|
||||
```js
|
||||
@@ -57,9 +66,14 @@ The following `webPreferences` option default values are deprecated in favor of
|
||||
|
||||
Child windows opened with the `nativeWindowOpen` option will always have Node.js integration disabled.
|
||||
|
||||
## Privileged Schemes Registration
|
||||
|
||||
Renderer process APIs `webFrame.setRegisterURLSchemeAsPrivileged` and `webFrame.registerURLSchemeAsBypassingCSP` as well as browser process API `protocol.registerStandardSchemes` have been removed.
|
||||
A new API, `protocol.registerSchemesAsPrivileged` has been added and should be used for registering custom schemes with the required privileges. Custom schemes are required to be registered before app ready.
|
||||
|
||||
# Planned Breaking API Changes (4.0)
|
||||
|
||||
The following list includes the breaking API changes planned for Electron 4.0.
|
||||
The following list includes the breaking API changes made in Electron 4.0.
|
||||
|
||||
## `app.makeSingleInstance`
|
||||
|
||||
|
||||
@@ -83,6 +83,10 @@ Returns `Boolean` - Whether the view is destroyed.
|
||||
with the window. `false` by default.
|
||||
* `height` Boolean - If `true`, the view's height will grow and shrink
|
||||
together with the window. `false` by default.
|
||||
* `horizontal` Boolean - If `true`, the view's x position and width will grow
|
||||
and shrink proportionly with the window. `false` by default.
|
||||
* `vertical` Boolean - If `true`, the view's y position and height will grow
|
||||
and shrink proportinaly with the window. `false` by default.
|
||||
|
||||
#### `view.setBounds(bounds)` _Experimental_
|
||||
|
||||
|
||||
@@ -1089,7 +1089,7 @@ can not be focused on.
|
||||
|
||||
Returns `Boolean` - Whether the window is always on top of other windows.
|
||||
|
||||
#### `win.moveTop()` _macOS_ _Windows_
|
||||
#### `win.moveTop()`
|
||||
|
||||
Moves window to top(z-order) regardless of focus
|
||||
|
||||
@@ -1308,8 +1308,11 @@ Same as `webContents.reload`.
|
||||
|
||||
* `menu` Menu | null
|
||||
|
||||
Sets the `menu` as the window's menu bar, setting it to `null` will remove the
|
||||
menu bar.
|
||||
Sets the `menu` as the window's menu bar.
|
||||
|
||||
#### `win.removeMenu()` _Linux_ _Windows_
|
||||
|
||||
Remove the window's menu bar.
|
||||
|
||||
#### `win.setProgressBar(progress[, options])`
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ result.
|
||||
**Note:** You should not use this module until the `ready` event of the app
|
||||
module is emitted.
|
||||
|
||||
|
||||
```javascript
|
||||
const { app, contentTracing } = require('electron')
|
||||
|
||||
@@ -43,11 +42,18 @@ The `contentTracing` module has the following methods:
|
||||
* `callback` Function
|
||||
* `categories` String[]
|
||||
|
||||
Get a set of category groups. The category groups can change as new code paths
|
||||
are reached.
|
||||
Get a set of category groups. The category groups can change as new code paths are reached.
|
||||
|
||||
Once all child processes have acknowledged the `getCategories` request the `callback` is invoked with an array of category groups.
|
||||
|
||||
**[Deprecated Soon](promisification.md)**
|
||||
|
||||
### `contentTracing.getCategories()`
|
||||
|
||||
Returns `Promise<String[]>` - resolves with an array of category groups once all child processes have acknowledged the `getCategories` request
|
||||
|
||||
Get a set of category groups. The category groups can change as new code paths are reached.
|
||||
|
||||
Once all child processes have acknowledged the `getCategories` request the
|
||||
`callback` is invoked with an array of category groups.
|
||||
|
||||
### `contentTracing.startRecording(options, callback)`
|
||||
|
||||
@@ -60,6 +66,19 @@ Recording begins immediately locally and asynchronously on child processes
|
||||
as soon as they receive the EnableRecording request. The `callback` will be
|
||||
called once all child processes have acknowledged the `startRecording` request.
|
||||
|
||||
**[Deprecated Soon](promisification.md)**
|
||||
|
||||
### `contentTracing.startRecording(options)`
|
||||
|
||||
* `options` ([TraceCategoriesAndOptions](structures/trace-categories-and-options.md) | [TraceConfig](structures/trace-config.md))
|
||||
|
||||
Returns `Promise<void>` - resolved once all child processes have acknowledged the `startRecording` request.
|
||||
|
||||
Start recording on all processes.
|
||||
|
||||
Recording begins immediately locally and asynchronously on child processes
|
||||
as soon as they receive the EnableRecording request.
|
||||
|
||||
### `contentTracing.stopRecording(resultFilePath, callback)`
|
||||
|
||||
* `resultFilePath` String
|
||||
@@ -81,47 +100,24 @@ Trace data will be written into `resultFilePath` if it is not empty or into a
|
||||
temporary file. The actual file path will be passed to `callback` if it's not
|
||||
`null`.
|
||||
|
||||
### `contentTracing.startMonitoring(options, callback)`
|
||||
**[Deprecated Soon](promisification.md)**
|
||||
|
||||
* `options` Object
|
||||
* `categoryFilter` String
|
||||
* `traceOptions` String
|
||||
* `callback` Function
|
||||
|
||||
Start monitoring on all processes.
|
||||
|
||||
Monitoring begins immediately locally and asynchronously on child processes as
|
||||
soon as they receive the `startMonitoring` request.
|
||||
|
||||
Once all child processes have acknowledged the `startMonitoring` request the
|
||||
`callback` will be called.
|
||||
|
||||
### `contentTracing.stopMonitoring(callback)`
|
||||
|
||||
* `callback` Function
|
||||
|
||||
Stop monitoring on all processes.
|
||||
|
||||
Once all child processes have acknowledged the `stopMonitoring` request the
|
||||
`callback` is called.
|
||||
|
||||
### `contentTracing.captureMonitoringSnapshot(resultFilePath, callback)`
|
||||
### `contentTracing.stopRecording(resultFilePath)`
|
||||
|
||||
* `resultFilePath` String
|
||||
* `callback` Function
|
||||
* `resultFilePath` String
|
||||
|
||||
Get the current monitoring traced data.
|
||||
Returns `Promise<String>` - resolves with a file that contains the traced data once all child processes have acknowledged the `stopRecording` request
|
||||
|
||||
Stop recording on all processes.
|
||||
|
||||
Child processes typically cache trace data and only rarely flush and send
|
||||
trace data back to the main process. This is because it may be an expensive
|
||||
operation to send the trace data over IPC and we would like to avoid unneeded
|
||||
runtime overhead from tracing. So, to end tracing, we must asynchronously ask
|
||||
all child processes to flush any pending trace data.
|
||||
|
||||
Once all child processes have acknowledged the `captureMonitoringSnapshot`
|
||||
request the `callback` will be called with a file that contains the traced data.
|
||||
trace data back to the main process. This helps to minimize the runtime overhead
|
||||
of tracing since sending trace data over IPC can be an expensive operation. So,
|
||||
to end tracing, we must asynchronously ask all child processes to flush any
|
||||
pending trace data.
|
||||
|
||||
Trace data will be written into `resultFilePath` if it is not empty or into a
|
||||
temporary file.
|
||||
|
||||
### `contentTracing.getTraceBufferUsage(callback)`
|
||||
|
||||
|
||||
@@ -13,21 +13,30 @@ For example:
|
||||
const { session } = require('electron')
|
||||
|
||||
// Query all cookies.
|
||||
session.defaultSession.cookies.get({}, (error, cookies) => {
|
||||
console.log(error, cookies)
|
||||
})
|
||||
session.defaultSession.cookies.get({})
|
||||
.then((cookies) => {
|
||||
console.log(cookies)
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
|
||||
// Query all cookies associated with a specific url.
|
||||
session.defaultSession.cookies.get({ url: 'http://www.github.com' }, (error, cookies) => {
|
||||
console.log(error, cookies)
|
||||
})
|
||||
session.defaultSession.cookies.get({ url: 'http://www.github.com' })
|
||||
.then((cookies) => {
|
||||
console.log(cookies)
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
|
||||
// Set a cookie with the given cookie data;
|
||||
// may overwrite equivalent cookies if they exist.
|
||||
const cookie = { url: 'http://www.github.com', name: 'dummy_name', value: 'dummy' }
|
||||
session.defaultSession.cookies.set(cookie, (error) => {
|
||||
if (error) console.error(error)
|
||||
})
|
||||
session.defaultSession.cookies.set(cookie)
|
||||
.then(() => {
|
||||
// success
|
||||
}, (error) => {
|
||||
console.error(error)
|
||||
})
|
||||
```
|
||||
|
||||
### Instance Events
|
||||
@@ -55,6 +64,23 @@ expired.
|
||||
|
||||
The following methods are available on instances of `Cookies`:
|
||||
|
||||
#### `cookies.get(filter)`
|
||||
|
||||
* `filter` Object
|
||||
* `url` String (optional) - Retrieves cookies which are associated with
|
||||
`url`. Empty implies retrieving cookies of all urls.
|
||||
* `name` String (optional) - Filters cookies by name.
|
||||
* `domain` String (optional) - Retrieves cookies whose domains match or are
|
||||
subdomains of `domains`.
|
||||
* `path` String (optional) - Retrieves cookies whose path matches `path`.
|
||||
* `secure` Boolean (optional) - Filters cookies by their Secure property.
|
||||
* `session` Boolean (optional) - Filters out session or persistent cookies.
|
||||
|
||||
Returns `Promise<Cookie[]>` - A promise which resolves an array of cookie objects.
|
||||
|
||||
Sends a request to get all cookies matching `filter`, and resolves a promise with
|
||||
the response.
|
||||
|
||||
#### `cookies.get(filter, callback)`
|
||||
|
||||
* `filter` Object
|
||||
@@ -73,6 +99,28 @@ The following methods are available on instances of `Cookies`:
|
||||
Sends a request to get all cookies matching `filter`, `callback` will be called
|
||||
with `callback(error, cookies)` on complete.
|
||||
|
||||
**[Deprecated Soon](promisification.md)**
|
||||
|
||||
#### `cookies.set(details)`
|
||||
|
||||
* `details` Object
|
||||
* `url` String - The url to associate the cookie with.
|
||||
* `name` String (optional) - The name of the cookie. Empty by default if omitted.
|
||||
* `value` String (optional) - The value of the cookie. Empty by default if omitted.
|
||||
* `domain` String (optional) - The domain of the cookie. Empty by default if omitted.
|
||||
* `path` String (optional) - The path of the cookie. Empty by default if omitted.
|
||||
* `secure` Boolean (optional) - Whether the cookie should be marked as Secure. Defaults to
|
||||
false.
|
||||
* `httpOnly` Boolean (optional) - Whether the cookie should be marked as HTTP only.
|
||||
Defaults to false.
|
||||
* `expirationDate` Double (optional) - The expiration date of the cookie as the number of
|
||||
seconds since the UNIX epoch. If omitted then the cookie becomes a session
|
||||
cookie and will not be retained between sessions.
|
||||
|
||||
Returns `Promise<void>` - A promise which resolves when the cookie has been set
|
||||
|
||||
Sets a cookie with `details`.
|
||||
|
||||
#### `cookies.set(details, callback)`
|
||||
|
||||
* `details` Object
|
||||
@@ -94,6 +142,17 @@ with `callback(error, cookies)` on complete.
|
||||
Sets a cookie with `details`, `callback` will be called with `callback(error)`
|
||||
on complete.
|
||||
|
||||
**[Deprecated Soon](promisification.md)**
|
||||
|
||||
#### `cookies.remove(url, name)`
|
||||
|
||||
* `url` String - The URL associated with the cookie.
|
||||
* `name` String - The name of cookie to remove.
|
||||
|
||||
Returns `Promise<void>` - A promise which resolves when the cookie has been removed
|
||||
|
||||
Removes the cookies matching `url` and `name`
|
||||
|
||||
#### `cookies.remove(url, name, callback)`
|
||||
|
||||
* `url` String - The URL associated with the cookie.
|
||||
@@ -103,8 +162,18 @@ on complete.
|
||||
Removes the cookies matching `url` and `name`, `callback` will called with
|
||||
`callback()` on complete.
|
||||
|
||||
**[Deprecated Soon](promisification.md)**
|
||||
|
||||
#### `cookies.flushStore()`
|
||||
|
||||
Returns `Promise<void>` - A promise which resolves when the cookie store has been flushed
|
||||
|
||||
Writes any unwritten cookies data to disk.
|
||||
|
||||
#### `cookies.flushStore(callback)`
|
||||
|
||||
* `callback` Function
|
||||
|
||||
Writes any unwritten cookies data to disk.
|
||||
|
||||
**[Deprecated Soon](promisification.md)**
|
||||
|
||||
@@ -62,14 +62,14 @@ Therefore, to collect crash reports from them, use `process.crashReporter.start`
|
||||
along with an additional one called `crashesDirectory` that should point to a directory to store the crash
|
||||
reports temporarily. You can test this out by calling `process.crash()` to crash the child process.
|
||||
|
||||
**Note:** To collect crash reports from child process in Windows, you need to add this extra code as well.
|
||||
This will start the process that will monitor and send the crash reports. Replace `submitURL`, `productName`
|
||||
and `crashesDirectory` with appropriate values.
|
||||
|
||||
**Note:** If you need send additional/updated `extra` parameters after your
|
||||
first call `start` you can call `addExtraParameter` on macOS or call `start`
|
||||
again with the new/updated `extra` parameters on Linux and Windows.
|
||||
|
||||
**Note:** To collect crash reports from child process in Windows, you need to add this extra code as well.
|
||||
This will start the process that will monitor and send the crash reports. Replace `submitURL`, `productName`
|
||||
and `crashesDirectory` with appropriate values.
|
||||
|
||||
```js
|
||||
const args = [
|
||||
`--reporter-url=${submitURL}`,
|
||||
|
||||
@@ -117,6 +117,9 @@ The `filters` specifies an array of file types that can be displayed, see
|
||||
If a `callback` is passed, the API call will be asynchronous and the result
|
||||
will be passed via `callback(filename)`.
|
||||
|
||||
**Note:** On macOS, using the `callback` is recommended to avoid issues when
|
||||
expanding and collapsing the dialog.
|
||||
|
||||
### `dialog.showMessageBox([browserWindow, ]options[, callback])`
|
||||
|
||||
* `browserWindow` [BrowserWindow](browser-window.md) (optional)
|
||||
|
||||
@@ -14,7 +14,7 @@ See [`Menu`](menu.md) for examples.
|
||||
* `menuItem` MenuItem
|
||||
* `browserWindow` [BrowserWindow](browser-window.md)
|
||||
* `event` Event
|
||||
* `role` String (optional) - Can be `undo`, `redo`, `cut`, `copy`, `paste`, `pasteandmatchstyle`, `delete`, `selectall`, `reload`, `forcereload`, `toggledevtools`, `resetzoom`, `zoomin`, `zoomout`, `togglefullscreen`, `window`, `minimize`, `close`, `help`, `about`, `services`, `hide`, `hideothers`, `unhide`, `quit`, `startspeaking`, `stopspeaking`, `close`, `minimize`, `zoom` or `front` - Define the action of the menu item, when specified the
|
||||
* `role` String (optional) - Can be `undo`, `redo`, `cut`, `copy`, `paste`, `pasteandmatchstyle`, `delete`, `selectall`, `reload`, `forcereload`, `toggledevtools`, `resetzoom`, `zoomin`, `zoomout`, `togglefullscreen`, `window`, `minimize`, `close`, `help`, `about`, `services`, `hide`, `hideothers`, `unhide`, `quit`, `startspeaking`, `stopspeaking`, `close`, `minimize`, `zoom`, `front`, `appMenu`, `fileMenu`, `editMenu`, `viewMenu` or `windowMenu` - Define the action of the menu item, when specified the
|
||||
`click` property will be ignored. See [roles](#roles).
|
||||
* `type` String (optional) - Can be `normal`, `separator`, `submenu`, `checkbox` or
|
||||
`radio`.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user