Compare commits

...

51 Commits

Author SHA1 Message Date
Electron Bot
f97ce86d08 Bump v10.0.0-nightly.20200213 2020-02-13 07:52:52 -08:00
John Kleinschmidt
2510607658 Revert "Bump v10.0.0-nightly.20200213"
This reverts commit d40a2a8982.
2020-02-13 10:49:37 -05:00
Electron Bot
d40a2a8982 Bump v10.0.0-nightly.20200213 2020-02-13 07:32:44 -08:00
Jeremy Apthorp
d590f2efe3 feat: enable pdf viewer (#21794) 2020-02-12 16:39:12 -08:00
Electron Bot
85f9c779a8 Bump v10.0.0-nightly.20200212 2020-02-12 09:56:46 -08:00
Electron Bot
493dcf279b Revert "Bump v10.0.0-nightly.20200212"
This reverts commit 22d7b4049c.
2020-02-12 09:53:05 -08:00
Electron Bot
22d7b4049c Bump v10.0.0-nightly.20200212 2020-02-12 09:51:17 -08:00
Electron Bot
592848ed3d Revert "Bump v10.0.0-nightly.20200212"
This reverts commit 2edbff6e6c.
2020-02-12 09:48:33 -08:00
Shelley Vohr
5e7c594691 fix: no-arg console.log is undefined (#22165) 2020-02-12 09:25:11 -08:00
John Kleinschmidt
d1fd237e61 build: fix release script to work with sudowoodo (#22170) 2020-02-12 11:53:14 -05:00
Electron Bot
2edbff6e6c Bump v10.0.0-nightly.20200212 2020-02-12 07:32:14 -08:00
Andrea Brancaleoni
730b77189a ci: fix script to initialize Windows VM (#22140)
* ci: fix script to initialize Windows VM

* remove python3 rename statements, python3 is not required nor
installed

* fix a chicken-egg condition where refreshenv is not installed, after
chocolatey install.

* ci: update script to initialize Windows VM

* Add needed component to vc_buildTools install

  - Microsoft.VisualStudio.Workload.VCTools
  - Microsoft.VisualStudio.Component.VC.140

* Do not install vcredist140 from chocolotey
2020-02-12 09:45:41 -05:00
Tony
fe5318d753 fix RTL bug when used with traffic light repositioning (#22132) 2020-02-12 07:34:55 +00:00
John Kleinschmidt
023a3ca722 ci: Speed up release (#22126)
* build: speed up release builds by using workflows

* Don't get depot-tools twice

* Do not use source from cache

* Checkout boto and requests for release builds

* Make sure vendor dirs are persisted.

* Use git cache for releases.

* show sccache stats right after build

* Make messages easier for sudowoodo to consume.
2020-02-11 15:42:37 -05:00
Alexey Kuzmin
8b89c3cade build: fix spellchecker deps (#22142) 2020-02-11 12:35:50 -05:00
Shelley Vohr
43ca62cad0 refactor: use NSVisualEffectMaterial* constants directly (#22121) 2020-02-11 16:23:10 +00:00
Electron Bot
b66db2f268 Bump v10.0.0-nightly.20200211 2020-02-11 07:31:19 -08:00
Cheng Zhao
c608d6d7fb fix: make webRequest work with WebSocket (#22040)
* fix: web request support proxying websocket

* fix: make tests work

* chore: do not use api:: code outside api/ folder

* chore: do not create proxy when no listener

* test: use separate session to avoid conflicts

* chore: address review
2020-02-11 14:56:09 +09:00
Shelley Vohr
80dd16aa78 spec: unskip webview.printToPDF (#22122) 2020-02-11 03:35:05 +00:00
Electron Bot
2bfe66bcfd chore: bump node to v12.15.0 (master) (#22063)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-02-11 01:48:29 +00:00
Cheng Zhao
9ad6f06831 fix: remove cyclic references of BrowserWindow (#22006)
* fix: remove cyclic references in BrowserWindow

* fix: prevent TopLevelWindow from garbage collection

* test: garbage collection of BrowserWindow

* chore: createIDWeakMap is used in tests
2020-02-11 09:37:46 +09:00
Erick Zhao
9942149f3c feat: add session.listWordsFromSpellCheckerDictionary API (#22101)
* doesn't work yet but compiles.

* works

* fixup
2020-02-10 14:08:53 -08:00
Erick Zhao
6fe7d65c9d chore: Revert "notes: Adding Github CI to testing documentation (#21996)" (#22123)
This reverts commit 385388dd6b.
2020-02-10 14:07:58 -08:00
Erick Zhao
17abeca8b7 feat: add session.removeWordFromSpellCheckerDictionary API (#22039)
* feat: add session.removeWordFromSpellCheckerDictionary API

* rebase fixup
2020-02-10 14:07:25 -08:00
Andy Dill
8ca4e761fd fix: explicitly specify typeRoots to avoid crawling parent directories (#22078) 2020-02-10 20:17:04 +00:00
Jeremy Apthorp
b77f701aeb feat: disable the remote module by default (#22091) 2020-02-10 10:49:09 -08:00
Jeremy Apthorp
af631f8204 fix: disallow loading extensions in temp sessions (#22090)
* fix: disallow loading extensions in temp sessions

* docs
2020-02-10 10:28:03 -06:00
Electron Bot
c2cd588e70 Bump v10.0.0-nightly.20200210 2020-02-10 07:31:57 -08:00
CoderPoet
97cf24ac98 docs: modify the showMessageBox method to showMessageBoxSync (#22080)
In handling the will-prevent-unload event, preventDefault should be executed synchronously, and here should also be showMessageBoxSync
2020-02-10 17:12:30 +09:00
Shelley Vohr
d5e7904610 refactor: remove use of Node's DebugOptions (#22083) 2020-02-09 18:42:02 +00:00
Electron Bot
099246f0e4 Bump v10.0.0-nightly.20200209 2020-02-09 07:32:49 -08:00
Samuel Attard
dafbf04b9a fix: use a WeakPtr so we do not UAF the store in FunctionLifetimeMonitor (#22056) 2020-02-08 20:49:38 -08:00
t57ser
43592f8b71 fix: flash plugin (#22072)
* fix: flash plugin

Fixes https://github.com/electron/electron/issues/20744

* cleanup

* fix linting issue
2020-02-08 17:50:07 -08:00
John Kleinschmidt
058222a9f1 build: try using newer version of xcode/macOS sdk (#22104) 2020-02-08 16:38:14 -05:00
Electron Bot
f989faab5c Bump v10.0.0-nightly.20200208 2020-02-08 07:31:55 -08:00
John Kleinschmidt
5e49aafe55 build: preserve timestamps when stripping files (#22094)
* build: preserve timestamps when stripping files

Resolves an issue where the binaries in mksnapshot.zip were not getting stripped.

* Add missing comma

* Update script/strip-binaries.py

Co-Authored-By: Jeremy Apthorp <jeremya@chromium.org>

* Don't try to run strip on macOS

Co-authored-by: Jeremy Apthorp <nornagon@nornagon.net>
2020-02-07 17:05:04 -05:00
Jeremy Apthorp
ea89120c9e chore: remove debugging log (#22093) 2020-02-07 12:31:08 -08:00
John Kleinschmidt
c6cec97287 build: copy chromedriver to correct location (#22074)
* build: copy chromedriver to correct location

* build: try to free up disk space for macos releases

* get verbose mode working on strip-binaries

* Only use separate chromedriver build arm/arm64
2020-02-07 13:52:36 -05:00
John Kleinschmidt
45591e31ce ci: fix build failure on doc only changes (#22075)
* ci: fix build failure on doc only changes

* ci: fix doc-only check when CI fires on branch before PR is created
2020-02-07 12:58:47 -05:00
Jeremy Apthorp
e2a5de9248 refactor: saner blink_initialization_order.patch (#22054) 2020-02-07 09:45:13 -08:00
Electron Bot
6a7d722c06 Bump v10.0.0-nightly.20200207 2020-02-07 07:32:49 -08:00
John Kleinschmidt
f1f185ee93 test: get native unit tests running (#21914) 2020-02-07 07:56:54 -05:00
Shelley Vohr
83124889e5 feat: enable passing Node.js cli flags (#21110)
* feat: enable passing Node.js cli flags

* Allow cli flags in ELECTRON_RUN_AS_NODE mode
2020-02-07 02:59:38 +00:00
Jeremy Apthorp
9107157073 feat: [extensions] support extension.getBackgroundPage (#21951)
* feat: [extensions] support extension.getBackgroundPage

* cleanup

* how does c++

* tests

* test for runtime.getBackgroundPage too
2020-02-06 16:42:34 -05:00
Jeremy Apthorp
eca1dd7f8b docs: document supported extensions apis (#22021)
* docs: document supported extensions apis

* Update extensions.md

* Update README.md

* Apply suggestions from code review

Co-Authored-By: Mark Lee <malept@users.noreply.github.com>

Co-authored-by: Mark Lee <malept@users.noreply.github.com>
2020-02-06 16:36:02 -05:00
Sesh Sadasivam
c8273e375c fix: add Chromium patch to fix RTL window buttons (#22016)
Classes that inherit from `NSThemeFrame` seem to show window buttons in the
incorrect position when the primary MacOS language is set to an RTL
(right-to-left) language like Arabic or Hebrew. The fix in this commit mirrors
that of `tabbed_browser_window.mm`
(https://chromium-review.googlesource.com/c/chromium/src/+/562603/10/chrome/browser/ui/cocoa/tabbed_browser_window.mm#88).

This change should be upstreamed, and then this patch can be removed.
2020-02-06 16:14:18 -05:00
John Kleinschmidt
f4fd939409 build: copy chromedriver to proper directory for release (#22070) 2020-02-06 14:20:14 -05:00
John Kleinschmidt
e7982623ec ci: enable goma for all testing builds (#21992)
* ci: enable goma for all testing builds

* Use powershell script to start goma on Windows

* Only run ensure_start from PS script.

* add missing percent

* Run stats via command instead of powershell

* use command env var

* Use out cache for faster mac builds

* Disable unneeded logging

* .git directories need to be delete before gn gen

Even though gn gen shows and error about a missing .git directory, the .git delete needs to happen before gn gen.
2020-02-06 12:56:18 -05:00
Erick Zhao
3f880fb7c7 chore: remove teams without write access from CODEOWNERS (#22043)
* chore: update CODEOWNERS for Ecosystem WG

* chore: remove teams w/o write access from CODEOWNERS
2020-02-06 11:31:25 -06:00
Erick Zhao
070e312e8b docs: clarify requirements for GOOGLE_API_KEY (#22034)
* docs: clarify requirements for GOOGLE_API_KEY

* Update docs/api/environment-variables.md

Co-Authored-By: Mark Lee <malept@users.noreply.github.com>

* Update docs/api/environment-variables.md

Co-Authored-By: Mark Lee <malept@users.noreply.github.com>

* Update docs/api/environment-variables.md

Co-Authored-By: Mark Lee <malept@users.noreply.github.com>

* update

Co-authored-by: Mark Lee <malept@users.noreply.github.com>
2020-02-06 11:28:06 -06:00
Cheng Zhao
629c2121ba chore: print more logging for failed tests (#22060) 2020-02-06 11:15:55 -05:00
139 changed files with 4277 additions and 1087 deletions

View File

@@ -41,6 +41,14 @@ parameters:
type: boolean
default: false
run-linux-publish:
type: boolean
default: false
run-macos-publish:
type: boolean
default: false
# The config expects the following environment variables to be set:
# - "SLACK_WEBHOOK" Slack hook URL to send notifications.
#
@@ -65,12 +73,12 @@ machine-linux-2xlarge: &machine-linux-2xlarge
machine-mac: &machine-mac
macos:
xcode: "10.3.0"
xcode: "11.1.0"
machine-mac-large: &machine-mac-large
resource_class: large
macos:
xcode: "10.3.0"
xcode: "11.1.0"
# Build configurations options.
env-testing-build: &env-testing-build
@@ -228,15 +236,6 @@ step-setup-env-for-build: &step-setup-env-for-build
command: |
# To find `gn` executable.
echo 'export CHROMIUM_BUILDTOOLS_PATH="'"$PWD"'/src/buildtools"' >> $BASH_ENV
# Setup Goma if applicable
if [ ! -z "$RAW_GOMA_AUTH" ] && [ "`uname`" == "Linux" ]; then
export USE_SCCACHE="false"
echo 'export USE_SCCACHE=false' >> $BASH_ENV
echo 'export USE_GOMA=true' >> $BASH_ENV
echo 'export NUMBER_OF_NINJA_PROCESSES=300' >> $BASH_ENV
echo $RAW_GOMA_AUTH > ~/.goma_oauth2_config
src/electron/external_binaries/goma/goma_ctl.py ensure_start
fi
if [ "$USE_SCCACHE" == "true" ]; then
# https://github.com/mozilla/sccache
@@ -249,6 +248,29 @@ step-setup-env-for-build: &step-setup-env-for-build
fi
fi
step-setup-goma-for-build: &step-setup-goma-for-build
run:
name: Setup Goma
command: |
echo 'export USE_GOMA=true' >> $BASH_ENV
if [ "`uname`" == "Linux" ]; then
echo 'export NUMBER_OF_NINJA_PROCESSES=300' >> $BASH_ENV
else
echo 'export NUMBER_OF_NINJA_PROCESSES=25' >> $BASH_ENV
fi
if [ ! -z "$RAW_GOMA_AUTH" ]; then
echo $RAW_GOMA_AUTH > ~/.goma_oauth2_config
fi
git clone https://github.com/electron/build-tools.git
cd build-tools
npm install
mkdir third_party
node -e "require('./src/utils/goma.js').downloadAndPrepare()"
node -e "require('./src/utils/goma.js').ensure()"
echo 'export GN_GOMA_FILE='`node -e "console.log(require('./src/utils/goma.js').gnFilePath)"` >> $BASH_ENV
echo 'export LOCAL_GOMA_DIR='`node -e "console.log(require('./src/utils/goma.js').dir)"` >> $BASH_ENV
cd ..
step-restore-brew-cache: &step-restore-brew-cache
restore_cache:
paths:
@@ -339,7 +361,7 @@ step-gn-gen-default: &step-gn-gen-default
command: |
cd src
if [ "$USE_GOMA" == "true" ]; then
gn gen out/Default --args="import(\"$GN_CONFIG\") import(\"//electron/build/args/goma.gn\") $GN_EXTRA_ARGS $GN_BUILDFLAG_ARGS"
gn gen out/Default --args="import(\"$GN_CONFIG\") import(\"$GN_GOMA_FILE\") $GN_EXTRA_ARGS $GN_BUILDFLAG_ARGS"
else
gn gen out/Default --args="import(\"$GN_CONFIG\") cc_wrapper=\"$SCCACHE_PATH\" $GN_EXTRA_ARGS $GN_BUILDFLAG_ARGS"
fi
@@ -432,15 +454,17 @@ step-electron-dist-store: &step-electron-dist-store
path: src/out/Default/dist.zip
destination: dist.zip
step-electron-chromedriver-gn-gen: &step-electron-chromedriver-gn-gen
step-electron-maybe-chromedriver-gn-gen: &step-electron-maybe-chromedriver-gn-gen
run:
name: chromedriver GN gen
command: |
cd src
if [ "$USE_GOMA" == "true" ]; then
gn gen out/chromedriver --args="import(\"$GN_CONFIG\") import(\"//electron/build/args/goma.gn\") is_component_ffmpeg=false proprietary_codecs=false $GN_EXTRA_ARGS $GN_BUILDFLAG_ARGS"
else
gn gen out/chromedriver --args="import(\"$GN_CONFIG\") cc_wrapper=\"$SCCACHE_PATH\" is_component_ffmpeg=false proprietary_codecs=false $GN_EXTRA_ARGS $GN_BUILDFLAG_ARGS"
if [ "$TARGET_ARCH" == "arm" ] || [ "$TARGET_ARCH" == "arm64" ]; then
if [ "$USE_GOMA" == "true" ]; then
gn gen out/chromedriver --args="import(\"$GN_CONFIG\") import(\"//electron/build/args/goma.gn\") is_component_ffmpeg=false proprietary_codecs=false $GN_EXTRA_ARGS $GN_BUILDFLAG_ARGS"
else
gn gen out/chromedriver --args="import(\"$GN_CONFIG\") cc_wrapper=\"$SCCACHE_PATH\" is_component_ffmpeg=false proprietary_codecs=false $GN_EXTRA_ARGS $GN_BUILDFLAG_ARGS"
fi
fi
step-electron-chromedriver-build: &step-electron-chromedriver-build
@@ -448,13 +472,23 @@ step-electron-chromedriver-build: &step-electron-chromedriver-build
name: Build chromedriver.zip
command: |
cd src
ninja -C out/chromedriver electron:electron_chromedriver -j $NUMBER_OF_NINJA_PROCESSES
electron/script/strip-binaries.py --target-cpu="$TARGET_ARCH" --file $PWD/out/chromedriver/chromedriver
ninja -C out/chromedriver electron:electron_chromedriver_zip
if [ "$TARGET_ARCH" == "arm" ] || [ "$TARGET_ARCH" == "arm64" ]; then
export CHROMEDRIVER_DIR="out/chromedriver"
else
export CHROMEDRIVER_DIR="out/Default"
fi
ninja -C $CHROMEDRIVER_DIR electron:electron_chromedriver -j $NUMBER_OF_NINJA_PROCESSES
if [ "`uname`" == "Linux" ]; then
electron/script/strip-binaries.py --target-cpu="$TARGET_ARCH" --file $PWD/$CHROMEDRIVER_DIR/chromedriver
fi
ninja -C $CHROMEDRIVER_DIR electron:electron_chromedriver_zip
if [ "$TARGET_ARCH" == "arm" ] || [ "$TARGET_ARCH" == "arm64" ]; then
cp out/chromedriver/chromedriver.zip out/Default
fi
step-electron-chromedriver-store: &step-electron-chromedriver-store
store_artifacts:
path: src/out/chromedriver/chromedriver.zip
path: src/out/Default/chromedriver.zip
destination: chromedriver.zip
step-nodejs-headers-build: &step-nodejs-headers-build
@@ -481,6 +515,7 @@ step-electron-publish: &step-electron-publish
if [ "`uname`" == "Darwin" ]; then
rm -rf src/out/Default/obj
fi
cd src/electron
if [ "$UPLOAD_TO_S3" == "1" ]; then
echo 'Uploading Electron release distribution to S3'
@@ -497,7 +532,7 @@ step-persist-data-for-tests: &step-persist-data-for-tests
# Build artifacts
- src/out/Default/dist.zip
- src/out/Default/mksnapshot.zip
- src/out/chromedriver/chromedriver.zip
- src/out/Default/chromedriver.zip
- src/out/Default/shell_browser_ui_unittests
- src/out/Default/gen/node_headers
- src/out/ffmpeg/ffmpeg.zip
@@ -532,7 +567,7 @@ step-chromedriver-unzip: &step-chromedriver-unzip
run:
name: Unzip chromedriver.zip
command: |
cd src/out/chromedriver
cd src/out/Default
unzip -o chromedriver.zip
step-ffmpeg-gn-gen: &step-ffmpeg-gn-gen
@@ -577,7 +612,7 @@ step-verify-chromedriver: &step-verify-chromedriver
name: Verify ChromeDriver
command: |
cd src
python electron/script/verify-chromedriver.py --source-root "$PWD" --build-dir out/chromedriver
python electron/script/verify-chromedriver.py --source-root "$PWD" --build-dir out/Default
step-setup-linux-for-headless-testing: &step-setup-linux-for-headless-testing
run:
@@ -595,7 +630,7 @@ step-show-sccache-stats: &step-show-sccache-stats
$SCCACHE_PATH -s
fi
if [ "$USE_GOMA" == "true" ]; then
src/electron/external_binaries/goma/goma_ctl.py stat
$LOCAL_GOMA_DIR/goma_ctl.py stat
fi
step-mksnapshot-build: &step-mksnapshot-build
@@ -833,7 +868,7 @@ step-check-for-doc-only-change: &step-check-for-doc-only-change
command: |
cd src/electron
node script/yarn install --frozen-lockfile
if node script/doc-only-change.js --prNumber=$CIRCLE_PR_NUMBER --prURL=$CIRCLE_PULL_REQUEST; then
if node script/doc-only-change.js --prNumber=$CIRCLE_PR_NUMBER --prURL=$CIRCLE_PULL_REQUEST --prBranch=$CIRCLE_BRANCH; then
#PR is doc only change; save file with value true to indicate doc only change
echo "true" > .skip-ci-build
else
@@ -869,7 +904,7 @@ step-ts-compile: &step-ts-compile
command: |
cd src
ninja -C out/Default electron:default_app_js -j $NUMBER_OF_NINJA_PROCESSES
ninja -C out/Default electron:atom_js2c -j $NUMBER_OF_NINJA_PROCESSES
ninja -C out/Default electron:electron_js2c -j $NUMBER_OF_NINJA_PROCESSES
# Lists of steps.
steps-lint: &steps-lint
@@ -964,69 +999,6 @@ steps-electron-gn-check: &steps-electron-gn-check
- *step-gn-gen-default
- *step-gn-check
steps-electron-build: &steps-electron-build
steps:
- attach_workspace:
at: .
- *step-maybe-early-exit-doc-only-change
- *step-depot-tools-add-to-path
- *step-setup-env-for-build
- *step-restore-brew-cache
- *step-get-more-space-on-mac
- *step-install-npm-deps-on-mac
- *step-fix-sync-on-mac
- *step-delete-git-directories
- *step-gn-gen-default
# Electron app
- *step-electron-build
- *step-maybe-electron-dist-strip
- *step-electron-dist-build
- *step-electron-dist-store
- *step-ninja-summary
# Native test targets
- *step-native-unittests-build
- *step-native-unittests-store
# Node.js headers
- *step-nodejs-headers-build
- *step-nodejs-headers-store
- *step-show-sccache-stats
# mksnapshot
- *step-mksnapshot-build
- *step-mksnapshot-store
- *step-maybe-cross-arch-snapshot
- *step-maybe-cross-arch-snapshot-store
# chromedriver
- *step-electron-chromedriver-gn-gen
- *step-electron-chromedriver-build
- *step-electron-chromedriver-store
# ffmpeg
- *step-ffmpeg-gn-gen
- *step-ffmpeg-build
- *step-ffmpeg-store
# hunspell
- *step-hunspell-build
- *step-hunspell-store
# Save all data needed for a further tests run.
- *step-persist-data-for-tests
- *step-maybe-generate-breakpad-symbols
- *step-maybe-zip-symbols
- *step-symbols-store
# Trigger tests on arm hardware if needed
- *step-maybe-trigger-arm-test
- *step-maybe-notify-slack-failure
steps-electron-ts-compile-for-doc-change: &steps-electron-ts-compile-for-doc-change
steps:
# Checkout - Copied ffrom steps-checkout
@@ -1066,56 +1038,6 @@ steps-electron-ts-compile-for-doc-change: &steps-electron-ts-compile-for-doc-cha
#Compile ts/js to verify doc change didn't break anything
- *step-ts-compile
steps-electron-build-for-publish: &steps-electron-build-for-publish
steps:
- *step-checkout-electron
- *step-depot-tools-get
- *step-depot-tools-add-to-path
- *step-restore-brew-cache
- *step-get-more-space-on-mac
- *step-gclient-sync
- *step-setup-env-for-build
- *step-delete-git-directories
- *step-minimize-workspace-size-from-checkout
- *step-gn-gen-default
# Electron app
- *step-electron-build
- *step-maybe-generate-breakpad-symbols
- *step-maybe-electron-dist-strip
- *step-electron-dist-build
- *step-electron-dist-store
- *step-maybe-zip-symbols
- *step-symbols-store
# mksnapshot
- *step-mksnapshot-build
- *step-mksnapshot-store
# chromedriver
- *step-electron-chromedriver-gn-gen
- *step-electron-chromedriver-build
- *step-electron-chromedriver-store
# Node.js headers
- *step-nodejs-headers-build
- *step-nodejs-headers-store
# ffmpeg
- *step-ffmpeg-gn-gen
- *step-ffmpeg-build
- *step-ffmpeg-store
# hunspell
- *step-hunspell-build
- *step-hunspell-store
# typescript defs
- *step-maybe-generate-typescript-defs
# Publish
- *step-electron-publish
steps-chromedriver-build: &steps-chromedriver-build
steps:
- attach_workspace:
@@ -1124,7 +1046,7 @@ steps-chromedriver-build: &steps-chromedriver-build
- *step-setup-env-for-build
- *step-fix-sync-on-mac
- *step-electron-chromedriver-gn-gen
- *step-electron-maybe-chromedriver-gn-gen
- *step-electron-chromedriver-build
- *step-electron-chromedriver-store
@@ -1340,6 +1262,12 @@ commands:
use-out-cache:
type: boolean
default: true
restore-src-cache:
type: boolean
default: true
preserve-vendor-dirs:
type: boolean
default: false
steps:
- when:
condition: << parameters.attach >>
@@ -1366,17 +1294,38 @@ commands:
- *step-get-more-space-on-mac
- *step-generate-deps-hash
- *step-touch-sync-done
- maybe-restore-portaled-src-cache
- when:
condition: << parameters.restore-src-cache >>
steps:
- maybe-restore-portaled-src-cache
- *step-maybe-restore-git-cache
- *step-set-git-cache-path
# This sync call only runs if .circle-sync-done is an EMPTY file
- *step-gclient-sync
# These next few steps reset Electron to the correct commit regardless of which cache was restored
- when:
condition: << parameters.preserve-vendor-dirs >>
steps:
- run:
name: Preserve vendor dirs for release
command: |
mv src/electron/vendor/boto .
mv src/electron/vendor/requests .
- run:
name: Wipe Electron
command: rm -rf src/electron
- *step-checkout-electron
- *step-run-electron-only-hooks
- when:
condition: << parameters.preserve-vendor-dirs >>
steps:
- run:
name: Preserve vendor dirs for release
command: |
rm -rf src/electron/vendor/boto
rm -rf src/electron/vendor/requests
mv boto src/electron/vendor
mv requests src/electron/vendor/requests
- *step-generate-deps-hash-cleanly
- *step-mark-sync-done
- *step-minimize-workspace-size-from-checkout
@@ -1394,10 +1343,10 @@ commands:
steps:
- *step-depot-tools-add-to-path
- *step-setup-env-for-build
- *step-setup-goma-for-build
- *step-get-more-space-on-mac
- *step-fix-sync-on-mac
- *step-delete-git-directories
- *step-gn-gen-default
# Electron app
- when:
@@ -1429,7 +1378,7 @@ commands:
- *step-maybe-cross-arch-snapshot-store
# chromedriver
- *step-electron-chromedriver-gn-gen
- *step-electron-maybe-chromedriver-gn-gen
- *step-electron-chromedriver-build
- *step-electron-chromedriver-store
@@ -1475,10 +1424,80 @@ commands:
steps:
- *step-save-out-cache
# Trigger tests on arm hardware if needed
- *step-maybe-trigger-arm-test
# Trigger tests on arm hardware if needed
- *step-maybe-trigger-arm-test
- *step-maybe-notify-slack-failure
- *step-maybe-notify-slack-failure
electron-publish:
parameters:
attach:
type: boolean
default: false
checkout:
type: boolean
default: true
steps:
- when:
condition: << parameters.attach >>
steps:
- attach_workspace:
at: .
- when:
condition: << parameters.checkout >>
steps:
- *step-depot-tools-get
- *step-depot-tools-add-to-path
- *step-restore-brew-cache
- *step-get-more-space-on-mac
- when:
condition: << parameters.checkout >>
steps:
- *step-checkout-electron
- *step-gclient-sync
- *step-delete-git-directories
- *step-minimize-workspace-size-from-checkout
- *step-fix-sync-on-mac
- *step-setup-env-for-build
- *step-gn-gen-default
# Electron app
- *step-electron-build
- *step-show-sccache-stats
- *step-maybe-generate-breakpad-symbols
- *step-maybe-electron-dist-strip
- *step-electron-dist-build
- *step-electron-dist-store
- *step-maybe-zip-symbols
- *step-symbols-store
# mksnapshot
- *step-mksnapshot-build
- *step-mksnapshot-store
# chromedriver
- *step-electron-maybe-chromedriver-gn-gen
- *step-electron-chromedriver-build
- *step-electron-chromedriver-store
# Node.js headers
- *step-nodejs-headers-build
- *step-nodejs-headers-store
# ffmpeg
- *step-ffmpeg-gn-gen
- *step-ffmpeg-build
- *step-ffmpeg-store
# hunspell
- *step-hunspell-build
- *step-hunspell-store
# typescript defs
- *step-maybe-generate-typescript-defs
# Publish
- *step-electron-publish
# List of all jobs.
jobs:
@@ -1497,6 +1516,20 @@ jobs:
<<: *steps-electron-ts-compile-for-doc-change
# Layer 1: Checkout.
linux-checkout:
<<: *machine-linux-2xlarge
environment:
<<: *env-linux-2xlarge
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True --custom-var=checkout_boto=True --custom-var=checkout_requests=True'
steps:
- electron-build:
persist: false
build: false
checkout: true
persist-checkout: true
restore-src-cache: false
preserve-vendor-dirs: true
linux-checkout-fast:
<<: *machine-linux-2xlarge
environment:
@@ -1540,6 +1573,22 @@ jobs:
checkout: true
persist-checkout: true
mac-checkout:
<<: *machine-linux-2xlarge
environment:
<<: *env-linux-2xlarge
<<: *env-testing-build
<<: *env-macos-build
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_mac=True --custom-var=host_os=mac --custom-var=checkout_boto=True --custom-var=checkout_requests=True'
steps:
- electron-build:
persist: false
build: false
checkout: true
persist-checkout: true
restore-src-cache: false
preserve-vendor-dirs: true
mac-checkout-fast:
<<: *machine-linux-2xlarge
environment:
@@ -1569,7 +1618,6 @@ jobs:
environment:
<<: *env-linux-2xlarge
<<: *env-testing-build
<<: *env-enable-sccache
<<: *env-ninja-status
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
steps:
@@ -1583,7 +1631,6 @@ jobs:
environment:
<<: *env-linux-2xlarge
<<: *env-testing-build
<<: *env-enable-sccache
<<: *env-ninja-status
<<: *env-disable-run-as-node
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
@@ -1605,7 +1652,6 @@ jobs:
environment:
<<: *env-linux-medium
<<: *env-release-build
<<: *env-enable-sccache
<<: *env-send-slack-notifications
<<: *steps-chromedriver-build
@@ -1614,10 +1660,13 @@ jobs:
environment:
<<: *env-linux-2xlarge-release
<<: *env-release-build
<<: *env-enable-sccache
<<: *env-send-slack-notifications
<<: *env-ninja-status
<<: *steps-electron-build
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
steps:
- electron-build:
persist: true
checkout: true
linux-x64-publish:
<<: *machine-linux-2xlarge
@@ -1627,7 +1676,22 @@ jobs:
<<: *env-release-build
<<: *env-enable-sccache
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
<<: *steps-electron-build-for-publish
steps:
- electron-publish:
attach: false
checkout: true
linux-x64-publish-skip-checkout:
<<: *machine-linux-2xlarge
environment:
<<: *env-linux-2xlarge-release
<<: *env-release-build
<<: *env-enable-sccache
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
steps:
- electron-publish:
attach: true
checkout: false
linux-ia32-testing:
<<: *machine-linux-2xlarge
@@ -1635,7 +1699,6 @@ jobs:
<<: *env-linux-2xlarge
<<: *env-ia32
<<: *env-testing-build
<<: *env-enable-sccache
<<: *env-ninja-status
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
steps:
@@ -1650,7 +1713,6 @@ jobs:
<<: *env-linux-medium
<<: *env-ia32
<<: *env-release-build
<<: *env-enable-sccache
<<: *env-send-slack-notifications
<<: *steps-chromedriver-build
@@ -1660,10 +1722,13 @@ jobs:
<<: *env-linux-2xlarge-release
<<: *env-ia32
<<: *env-release-build
<<: *env-enable-sccache
<<: *env-send-slack-notifications
<<: *env-ninja-status
<<: *steps-electron-build
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
steps:
- electron-build:
persist: true
checkout: true
linux-ia32-publish:
<<: *machine-linux-2xlarge
@@ -1675,7 +1740,24 @@ jobs:
<<: *env-enable-sccache
<<: *env-32bit-release
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
<<: *steps-electron-build-for-publish
steps:
- electron-publish:
attach: false
checkout: true
linux-ia32-publish-skip-checkout:
<<: *machine-linux-2xlarge
environment:
<<: *env-linux-2xlarge-release
<<: *env-ia32
<<: *env-release-build
<<: *env-enable-sccache
<<: *env-32bit-release
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
steps:
- electron-publish:
attach: true
checkout: false
linux-arm-testing:
<<: *machine-linux-2xlarge
@@ -1683,7 +1765,6 @@ jobs:
<<: *env-linux-2xlarge
<<: *env-arm
<<: *env-testing-build
<<: *env-enable-sccache
<<: *env-ninja-status
TRIGGER_ARM_TEST: true
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
@@ -1699,7 +1780,6 @@ jobs:
<<: *env-linux-medium
<<: *env-arm
<<: *env-release-build
<<: *env-enable-sccache
<<: *env-send-slack-notifications
<<: *steps-chromedriver-build
@@ -1709,10 +1789,13 @@ jobs:
<<: *env-linux-2xlarge-release
<<: *env-arm
<<: *env-release-build
<<: *env-enable-sccache
<<: *env-send-slack-notifications
<<: *env-ninja-status
<<: *steps-electron-build
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
steps:
- electron-build:
persist: false
checkout: true
linux-arm-publish:
<<: *machine-linux-2xlarge
@@ -1724,7 +1807,24 @@ jobs:
<<: *env-32bit-release
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_boto=True --custom-var=checkout_requests=True'
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
<<: *steps-electron-build-for-publish
steps:
- electron-publish:
attach: false
checkout: true
linux-arm-publish-skip-checkout:
<<: *machine-linux-2xlarge
environment:
<<: *env-linux-2xlarge-release
<<: *env-arm
<<: *env-release-build
<<: *env-enable-sccache
<<: *env-32bit-release
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
steps:
- electron-publish:
attach: true
checkout: false
linux-arm64-testing:
<<: *machine-linux-2xlarge
@@ -1732,7 +1832,6 @@ jobs:
<<: *env-linux-2xlarge
<<: *env-arm64
<<: *env-testing-build
<<: *env-enable-sccache
<<: *env-ninja-status
TRIGGER_ARM_TEST: true
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
@@ -1756,7 +1855,6 @@ jobs:
<<: *env-linux-medium
<<: *env-arm64
<<: *env-release-build
<<: *env-enable-sccache
<<: *env-send-slack-notifications
<<: *steps-chromedriver-build
@@ -1766,10 +1864,13 @@ jobs:
<<: *env-linux-2xlarge-release
<<: *env-arm64
<<: *env-release-build
<<: *env-enable-sccache
<<: *env-send-slack-notifications
<<: *env-ninja-status
<<: *steps-electron-build
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
steps:
- electron-build:
persist: false
checkout: true
linux-arm64-publish:
<<: *machine-linux-2xlarge
@@ -1780,14 +1881,29 @@ jobs:
<<: *env-enable-sccache
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm64=True --custom-var=checkout_boto=True --custom-var=checkout_requests=True'
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
<<: *steps-electron-build-for-publish
steps:
- electron-publish:
attach: false
checkout: true
linux-arm64-publish-skip-checkout:
<<: *machine-linux-2xlarge
environment:
<<: *env-linux-2xlarge-release
<<: *env-arm64
<<: *env-release-build
<<: *env-enable-sccache
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
steps:
- electron-publish:
attach: true
checkout: false
osx-testing:
<<: *machine-mac-large
environment:
<<: *env-mac-large
<<: *env-testing-build
<<: *env-enable-sccache
<<: *env-ninja-status
<<: *env-macos-build
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_mac=True --custom-var=host_os=mac'
@@ -1810,7 +1926,6 @@ jobs:
environment:
<<: *env-machine-mac
<<: *env-release-build
<<: *env-enable-sccache
<<: *env-send-slack-notifications
<<: *steps-chromedriver-build
@@ -1819,9 +1934,14 @@ jobs:
environment:
<<: *env-mac-large
<<: *env-release-build
<<: *env-enable-sccache
<<: *env-ninja-status
<<: *steps-electron-build
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_mac=True --custom-var=host_os=mac'
steps:
- electron-build:
persist: true
checkout: false
checkout-and-assume-cache: true
attach: false
osx-publish:
<<: *machine-mac-large
@@ -1831,7 +1951,22 @@ jobs:
<<: *env-enable-sccache
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_boto=True --custom-var=checkout_requests=True'
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
<<: *steps-electron-build-for-publish
steps:
- electron-publish:
attach: false
checkout: true
osx-publish-skip-checkout:
<<: *machine-mac-large
environment:
<<: *env-mac-large-release
<<: *env-release-build
<<: *env-enable-sccache
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
steps:
- electron-publish:
attach: true
checkout: false
mas-testing:
<<: *machine-mac-large
@@ -1839,7 +1974,6 @@ jobs:
<<: *env-mac-large
<<: *env-mas
<<: *env-testing-build
<<: *env-enable-sccache
<<: *env-ninja-status
<<: *env-macos-build
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_mac=True --custom-var=host_os=mac'
@@ -1863,7 +1997,6 @@ jobs:
environment:
<<: *env-machine-mac
<<: *env-release-build
<<: *env-enable-sccache
<<: *env-send-slack-notifications
<<: *steps-chromedriver-build
@@ -1873,10 +2006,15 @@ jobs:
<<: *env-mac-large
<<: *env-mas
<<: *env-release-build
<<: *env-enable-sccache
<<: *env-ninja-status
<<: *steps-electron-build
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_mac=True --custom-var=host_os=mac'
steps:
- electron-build:
persist: true
checkout: false
checkout-and-assume-cache: true
attach: false
mas-publish:
<<: *machine-mac-large
environment:
@@ -1886,7 +2024,23 @@ jobs:
<<: *env-enable-sccache
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_boto=True --custom-var=checkout_requests=True'
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
<<: *steps-electron-build-for-publish
steps:
- electron-publish:
attach: false
checkout: true
mas-publish-skip-checkout:
<<: *machine-mac-large
environment:
<<: *env-mac-large-release
<<: *env-mas
<<: *env-release-build
<<: *env-enable-sccache
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
steps:
- electron-publish:
attach: true
checkout: false
# Layer 3: Tests.
linux-x64-unittests:
@@ -1894,7 +2048,6 @@ jobs:
environment:
<<: *env-linux-2xlarge
<<: *env-unittests
<<: *env-enable-sccache
<<: *env-headless-testing
<<: *steps-native-tests
@@ -1903,7 +2056,6 @@ jobs:
environment:
<<: *env-linux-2xlarge
<<: *env-unittests
<<: *env-enable-sccache
<<: *env-headless-testing
TESTS_ARGS: '--only-disabled-tests'
<<: *steps-native-tests
@@ -1913,7 +2065,6 @@ jobs:
environment:
<<: *env-linux-2xlarge
<<: *env-unittests
<<: *env-enable-sccache
<<: *env-headless-testing
TESTS_ARGS: '--include-disabled-tests'
<<: *steps-native-tests
@@ -1924,7 +2075,6 @@ jobs:
<<: *env-linux-2xlarge
<<: *env-browsertests
<<: *env-testing-build
<<: *env-enable-sccache
<<: *env-headless-testing
<<: *steps-native-tests
@@ -2180,6 +2330,27 @@ workflows:
# will need to be updated and there will most likely need to be changes to
# sudowoodo
publish-linux:
when: << pipeline.parameters.run-linux-publish >>
jobs:
- linux-checkout
- linux-x64-publish-skip-checkout:
requires:
- linux-checkout
context: release-env
- linux-ia32-publish-skip-checkout:
requires:
- linux-checkout
context: release-env
- linux-arm-publish-skip-checkout:
requires:
- linux-checkout
context: release-env
- linux-arm64-publish-skip-checkout:
requires:
- linux-checkout
context: release-env
publish-x64-linux:
when: << pipeline.parameters.run-linux-x64-publish >>
jobs:
@@ -2216,6 +2387,17 @@ workflows:
- mas-publish:
context: release-env
publish-macos:
when: << pipeline.parameters.run-macos-publish >>
jobs:
- mac-checkout
- osx-publish-skip-checkout:
requires:
- mac-checkout
- mas-publish-skip-checkout:
requires:
- mac-checkout
lint:
when: << pipeline.parameters.run-lint >>
jobs:
@@ -2302,10 +2484,9 @@ workflows:
- *chromium-upgrade-branches
jobs:
- linux-checkout-fast
- linux-checkout-and-save-cache
- linux-x64-release:
requires:
- linux-checkout-fast
- linux-x64-release
- linux-x64-release-tests:
requires:
- linux-x64-release
@@ -2329,9 +2510,7 @@ workflows:
- linux-x64-verify-ffmpeg
- linux-x64-chromedriver
- linux-ia32-release:
requires:
- linux-checkout-fast
- linux-ia32-release
- linux-ia32-release-tests:
requires:
- linux-ia32-release
@@ -2355,9 +2534,7 @@ workflows:
- linux-ia32-verify-ffmpeg
- linux-ia32-chromedriver
- linux-arm-release:
requires:
- linux-checkout-fast
- linux-arm-release
- linux-arm-chromedriver:
requires:
- linux-checkout-fast
@@ -2366,10 +2543,7 @@ workflows:
- linux-arm-release
- linux-arm-chromedriver
- linux-arm64-release:
requires:
- linux-checkout-fast
- linux-arm64-release
- linux-arm64-chromedriver:
requires:
- linux-checkout-fast
@@ -2389,10 +2563,11 @@ workflows:
- *chromium-upgrade-branches
jobs:
- mac-checkout-fast
- mac-checkout-and-save-cache
- osx-release:
requires:
- mac-checkout-fast
- mac-checkout-and-save-cache
- osx-release-tests:
requires:
- osx-release
@@ -2418,7 +2593,7 @@ workflows:
- mas-release:
requires:
- mac-checkout-fast
- mac-checkout-and-save-cache
- mas-release-tests:
requires:
- mas-release

12
.github/CODEOWNERS vendored
View File

@@ -3,20 +3,10 @@
# https://help.github.com/articles/about-codeowners
# https://git-scm.com/docs/gitignore
# Most stuff in here is owned by the Community & Safety WG...
/.github/* @electron/wg-community
# ...except the Admin WG maintains this file.
/.github/CODEOWNERS @electron/wg-admin
# Upgrades WG
/patches/ @electron/wg-upgrades
DEPS @electron/wg-upgrades
# Docs & Tooling WG
/default_app/ @electron/wg-docs-tools
/docs/ @electron/wg-docs-tools
# Releases WG
/npm/ @electron/wg-releases
/script/release @electron/wg-releases
/script/release @electron/wg-releases

View File

@@ -629,8 +629,6 @@ source_set("electron_lib") {
deps += [ "//components/printing/common:mojo_interfaces" ]
}
deps += [ "shell/common/extensions/api:extensions_features" ]
deps += [ "shell/common/extensions/api" ]
deps += [
"//components/pref_registry",
"//components/user_prefs",
@@ -642,12 +640,22 @@ source_set("electron_lib") {
]
if (enable_electron_extensions) {
sources += filenames.lib_sources_extensions
deps += [
"shell/browser/extensions/api:api_registration",
"shell/common/extensions/api",
"shell/common/extensions/api:extensions_features",
"//chrome/browser/resources:component_extension_resources",
"//components/zoom",
]
}
if (enable_pdf) {
# Printing depends on some //pdf code, so it needs to be built even if the
# pdf viewer isn't enabled.
deps += [ "//pdf" ]
deps += [
"//pdf",
"//pdf:features",
]
}
if (enable_pdf_viewer) {
deps += [

2
DEPS
View File

@@ -14,7 +14,7 @@ vars = {
'chromium_version':
'ddac4c3cc1528254008f9e7a2aea5d4426906bfd',
'node_version':
'v12.14.1',
'v12.15.0',
'nan_version':
'2ee313aaca52e2b478965ac50eb5082520380d1b',

View File

@@ -1 +1 @@
10.0.0-nightly.20200206
10.0.0-nightly.20200213

View File

@@ -118,19 +118,29 @@ build_script:
}
}
- ps: >-
if (Test-Path 'env:RAW_GOMA_AUTH') {
$env:GOMA_OAUTH2_CONFIG_FILE = "$pwd\.goma_oauth2_config"
$env:RAW_GOMA_AUTH | Set-Content $env:GOMA_OAUTH2_CONFIG_FILE
.\src\electron\script\start-goma.ps1 -gomaDir "$pwd\src\electron\external_binaries\goma"
if ($env:GN_CONFIG -ne 'release') {
if (Test-Path 'env:RAW_GOMA_AUTH') {
$env:GOMA_OAUTH2_CONFIG_FILE = "$pwd\.goma_oauth2_config"
$env:RAW_GOMA_AUTH | Set-Content $env:GOMA_OAUTH2_CONFIG_FILE
}
git clone https://github.com/electron/build-tools.git
cd build-tools
npm install
mkdir third_party
node -e "require('./src/utils/goma.js').downloadAndPrepare()"
$env:GN_GOMA_FILE = node -e "console.log(require('./src/utils/goma.js').gnFilePath)"
$env:LOCAL_GOMA_DIR = node -e "console.log(require('./src/utils/goma.js').dir)"
cd ..
.\src\electron\script\start-goma.ps1 -gomaDir $env:LOCAL_GOMA_DIR
}
- cd src
- set BUILD_CONFIG_PATH=//electron/build/args/%GN_CONFIG%.gn
- if DEFINED RAW_GOMA_AUTH (gn gen out/Default "--args=import(\"%BUILD_CONFIG_PATH%\") import(\"//electron/build/args/goma.gn\") %GN_EXTRA_ARGS% ") else (gn gen out/Default "--args=import(\"%BUILD_CONFIG_PATH%\") %GN_EXTRA_ARGS% cc_wrapper=\"%SCCACHE_PATH%\"")
- if DEFINED GN_GOMA_FILE (gn gen out/Default "--args=import(\"%BUILD_CONFIG_PATH%\") import(\"%GN_GOMA_FILE%\") %GN_EXTRA_ARGS% ") else (gn gen out/Default "--args=import(\"%BUILD_CONFIG_PATH%\") %GN_EXTRA_ARGS% cc_wrapper=\"%SCCACHE_PATH%\"")
- gn check out/Default //electron:electron_lib
- gn check out/Default //electron:electron_app
- gn check out/Default //electron:manifests
- gn check out/Default //electron/shell/common/api:mojo
- if DEFINED RAW_GOMA_AUTH (ninja -j 300 -C out/Default electron:electron_app) else (ninja -C out/Default electron:electron_app)
- if DEFINED GN_GOMA_FILE (ninja -j 300 -C out/Default electron:electron_app) else (ninja -C out/Default electron:electron_app)
- if "%GN_CONFIG%"=="testing" ( python C:\depot_tools\post_build_ninja_summary.py -C out\Default )
- gn gen out/ffmpeg "--args=import(\"//electron/build/args/ffmpeg.gn\") %GN_EXTRA_ARGS%"
- ninja -C out/ffmpeg electron:electron_ffmpeg_zip
@@ -140,7 +150,7 @@ build_script:
- ninja -C out/Default electron:hunspell_dictionaries_zip
- ninja -C out/Default electron:electron_chromedriver_zip
- ninja -C out/Default third_party/electron_node:headers
- if DEFINED RAW_GOMA_AUTH (python electron\external_binaries\goma\goma_ctl.py stat)
- if "%GN_CONFIG%"=="testing" ( python %LOCAL_GOMA_DIR%\goma_ctl.py stat )
- python electron/build/profile_toolchain.py --output-json=out/Default/windows_toolchain_profile.json
- appveyor PushArtifact out/Default/windows_toolchain_profile.json
- appveyor PushArtifact out/Default/dist.zip

View File

@@ -14,7 +14,7 @@ declare_args() {
enable_view_api = false
enable_pdf_viewer = false
enable_pdf_viewer = true
enable_tts = true

View File

@@ -232,6 +232,12 @@ static_library("chrome") {
if (enable_electron_extensions) {
sources += [
"//chrome/browser/extensions/chrome_url_request_util.cc",
"//chrome/browser/extensions/chrome_url_request_util.h",
"//chrome/browser/pdf/pdf_extension_util.cc",
"//chrome/browser/pdf/pdf_extension_util.h",
"//chrome/browser/plugins/plugin_response_interceptor_url_loader_throttle.cc",
"//chrome/browser/plugins/plugin_response_interceptor_url_loader_throttle.h",
"//chrome/renderer/extensions/extension_hooks_delegate.cc",
"//chrome/renderer/extensions/extension_hooks_delegate.h",
"//chrome/renderer/extensions/tabs_hooks_delegate.cc",

View File

@@ -112,6 +112,7 @@ These individual tutorials expand on topics discussed in the guide above.
* [Process Object](api/process.md)
* [Supported Command Line Switches](api/command-line-switches.md)
* [Environment Variables](api/environment-variables.md)
* [Chrome Extensions Support](api/extensions.md)
* [Breaking API Changes](breaking-changes.md)
### Custom DOM Elements:

View File

@@ -16,80 +16,66 @@ app.whenReady().then(() => {
})
```
## --ignore-connections-limit=`domains`
## Electron CLI Flags
Ignore the connections limit for `domains` list separated by `,`.
### --auth-server-whitelist=`url`
## --disable-http-cache
Disables the disk cache for HTTP requests.
## --disable-http2
Disable HTTP/2 and SPDY/3.1 protocols.
## --lang
Set a custom locale.
## --inspect=`port` and --inspect-brk=`port`
Debug-related flags, see the [Debugging the Main Process][debugging-main-process] guide for details.
## --remote-debugging-port=`port`
Enables remote debugging over HTTP on the specified `port`.
## --disk-cache-size=`size`
Forces the maximum disk space to be used by the disk cache, in bytes.
## --js-flags=`flags`
Specifies the flags passed to the Node.js engine. It has to be passed when starting
Electron if you want to enable the `flags` in the main process.
```sh
$ electron --js-flags="--harmony_proxies --harmony_collections" your-app
```
See the [Node.js documentation][node-cli] or run `node --help` in your terminal for a list of available flags. Additionally, run `node --v8-options` to see a list of flags that specifically refer to Node.js's V8 JavaScript engine.
## --proxy-server=`address:port`
Use a specified proxy server, which overrides the system setting. This switch
only affects requests with HTTP protocol, including HTTPS and WebSocket
requests. It is also noteworthy that not all proxy servers support HTTPS and
WebSocket requests. The proxy URL does not support username and password
authentication [per Chromium issue](https://bugs.chromium.org/p/chromium/issues/detail?id=615947).
## --proxy-bypass-list=`hosts`
Instructs Electron to bypass the proxy server for the given semi-colon-separated
list of hosts. This flag has an effect only if used in tandem with
`--proxy-server`.
A comma-separated list of servers for which integrated authentication is enabled.
For example:
```javascript
const { app } = require('electron')
app.commandLine.appendSwitch('proxy-bypass-list', '<local>;*.google.com;*foo.com;1.2.3.4:5678')
```sh
--auth-server-whitelist='*example.com, *foobar.com, *baz'
```
Will use the proxy server for all hosts except for local addresses (`localhost`,
`127.0.0.1` etc.), `google.com` subdomains, hosts that contain the suffix
`foo.com` and anything at `1.2.3.4:5678`.
then any `url` ending with `example.com`, `foobar.com`, `baz` will be considered
for integrated authentication. Without `*` prefix the URL has to match exactly.
## --proxy-pac-url=`url`
### --auth-negotiate-delegate-whitelist=`url`
Uses the PAC script at the specified `url`.
A comma-separated list of servers for which delegation of user credentials is required.
Without `*` prefix the URL has to match exactly.
## --no-proxy-server
### --disable-http-cache
Don't use a proxy server and always make direct connections. Overrides any other
proxy server flags that are passed.
Disables the disk cache for HTTP requests.
## --host-rules=`rules`
### --disable-http2
Disable HTTP/2 and SPDY/3.1 protocols.
### --disable-renderer-backgrounding
Prevents Chromium from lowering the priority of invisible pages' renderer
processes.
This flag is global to all renderer processes, if you only want to disable
throttling in one window, you can take the hack of
[playing silent audio][play-silent-audio].
### --disk-cache-size=`size`
Forces the maximum disk space to be used by the disk cache, in bytes.
### --enable-api-filtering-logging
Enables caller stack logging for the following APIs (filtering events):
- `desktopCapturer.getSources()` / `desktop-capturer-get-sources`
- `remote.require()` / `remote-require`
- `remote.getGlobal()` / `remote-get-builtin`
- `remote.getBuiltin()` / `remote-get-global`
- `remote.getCurrentWindow()` / `remote-get-current-window`
- `remote.getCurrentWebContents()` / `remote-get-current-web-contents`
### --enable-logging
Prints Chromium's logging into console.
This switch can not be used in `app.commandLine.appendSwitch` since it is parsed
earlier than user's app is loaded, but you can set the `ELECTRON_ENABLE_LOGGING`
environment variable to achieve the same effect.
### --host-rules=`rules`
A comma-separated list of `rules` that control how hostnames are mapped.
@@ -107,69 +93,96 @@ These mappings apply to the endpoint host in a net request (the TCP connect
and host resolver in a direct connection, and the `CONNECT` in an HTTP proxy
connection, and the endpoint host in a `SOCKS` proxy connection).
## --host-resolver-rules=`rules`
### --host-resolver-rules=`rules`
Like `--host-rules` but these `rules` only apply to the host resolver.
## --auth-server-whitelist=`url`
A comma-separated list of servers for which integrated authentication is enabled.
For example:
```sh
--auth-server-whitelist='*example.com, *foobar.com, *baz'
```
then any `url` ending with `example.com`, `foobar.com`, `baz` will be considered
for integrated authentication. Without `*` prefix the URL has to match exactly.
## --auth-negotiate-delegate-whitelist=`url`
A comma-separated list of servers for which delegation of user credentials is required.
Without `*` prefix the URL has to match exactly.
## --ignore-certificate-errors
### --ignore-certificate-errors
Ignores certificate related errors.
## --ppapi-flash-path=`path`
### --ignore-connections-limit=`domains`
Sets the `path` of the pepper flash plugin.
Ignore the connections limit for `domains` list separated by `,`.
## --ppapi-flash-version=`version`
### --js-flags=`flags`
Sets the `version` of the pepper flash plugin.
Specifies the flags passed to the Node.js engine. It has to be passed when starting
Electron if you want to enable the `flags` in the main process.
## --log-net-log=`path`
```sh
$ electron --js-flags="--harmony_proxies --harmony_collections" your-app
```
See the [Node.js documentation][node-cli] or run `node --help` in your terminal for a list of available flags. Additionally, run `node --v8-options` to see a list of flags that specifically refer to Node.js's V8 JavaScript engine.
### --lang
Set a custom locale.
### --log-net-log=`path`
Enables net log events to be saved and writes them to `path`.
## --disable-renderer-backgrounding
### --no-proxy-server
Prevents Chromium from lowering the priority of invisible pages' renderer
processes.
Don't use a proxy server and always make direct connections. Overrides any other
proxy server flags that are passed.
This flag is global to all renderer processes, if you only want to disable
throttling in one window, you can take the hack of
[playing silent audio][play-silent-audio].
### --no-sandbox
## --enable-logging
Disables Chromium sandbox, which is now enabled by default.
Should only be used for testing.
Prints Chromium's logging into console.
### --proxy-bypass-list=`hosts`
This switch can not be used in `app.commandLine.appendSwitch` since it is parsed
earlier than user's app is loaded, but you can set the `ELECTRON_ENABLE_LOGGING`
environment variable to achieve the same effect.
Instructs Electron to bypass the proxy server for the given semi-colon-separated
list of hosts. This flag has an effect only if used in tandem with
`--proxy-server`.
## --v=`log_level`
For example:
```javascript
const { app } = require('electron')
app.commandLine.appendSwitch('proxy-bypass-list', '<local>;*.google.com;*foo.com;1.2.3.4:5678')
```
Will use the proxy server for all hosts except for local addresses (`localhost`,
`127.0.0.1` etc.), `google.com` subdomains, hosts that contain the suffix
`foo.com` and anything at `1.2.3.4:5678`.
### --proxy-pac-url=`url`
Uses the PAC script at the specified `url`.
### --proxy-server=`address:port`
Use a specified proxy server, which overrides the system setting. This switch
only affects requests with HTTP protocol, including HTTPS and WebSocket
requests. It is also noteworthy that not all proxy servers support HTTPS and
WebSocket requests. The proxy URL does not support username and password
authentication [per Chromium issue](https://bugs.chromium.org/p/chromium/issues/detail?id=615947).
### --remote-debugging-port=`port`
Enables remote debugging over HTTP on the specified `port`.
### --ppapi-flash-path=`path`
Sets the `path` of the pepper flash plugin.
### --ppapi-flash-version=`version`
Sets the `version` of the pepper flash plugin.
### --v=`log_level`
Gives the default maximal active V-logging level; 0 is the default. Normally
positive values are used for V-logging levels.
This switch only works when `--enable-logging` is also passed.
## --vmodule=`pattern`
### --vmodule=`pattern`
Gives the per-module maximal V-logging levels to override the value given by
`--v`. E.g. `my_module=2,foo*=3` would change the logging level for all code in
@@ -181,20 +194,38 @@ logging level for all code in the source files under a `foo/bar` directory.
This switch only works when `--enable-logging` is also passed.
## --enable-api-filtering-logging
## Node.js Flags
Enables caller stack logging for the following APIs (filtering events):
- `desktopCapturer.getSources()` / `desktop-capturer-get-sources`
- `remote.require()` / `remote-require`
- `remote.getGlobal()` / `remote-get-builtin`
- `remote.getBuiltin()` / `remote-get-global`
- `remote.getCurrentWindow()` / `remote-get-current-window`
- `remote.getCurrentWebContents()` / `remote-get-current-web-contents`
Electron supports some of the [CLI flags][node-cli] supported by Node.js.
## --no-sandbox
**Note:** Passing unsupported command line switches to Electron when it is not running in `ELECTRON_RUN_AS_NODE` will have no effect.
Disables Chromium sandbox, which is now enabled by default.
Should only be used for testing.
### --inspect-brk[=[host:]port]
Activate inspector on host:port and break at start of user script. Default host:port is 127.0.0.1:9229.
Aliased to `--debug-brk=[host:]port`.
### --inspect-port=[host:]port
Set the `host:port` to be used when the inspector is activated. Useful when activating the inspector by sending the SIGUSR1 signal. Default host is `127.0.0.1`.
Aliased to `--debug-port=[host:]port`.
### --inspect[=[host:]port]
Activate inspector on `host:port`. Default is `127.0.0.1:9229`.
V8 inspector integration allows tools such as Chrome DevTools and IDEs to debug and profile Electron instances. The tools attach to Electron instances via a tcp port and communicate using the [Chrome DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/).
See the [Debugging the Main Process][debugging-main-process] guide for more details.
Aliased to `--debug[=[host:]port`.
### --inspect-publish-uid=stderr,http
Specify ways of the inspector web socket url exposure.
By default inspector websocket url is available in stderr and under /json/list endpoint on http://host:port/json/list.
[app]: app.md
[append-switch]: app.md#appcommandlineappendswitchswitch-value

View File

@@ -53,16 +53,23 @@ Unsupported options are:
### `GOOGLE_API_KEY`
You can provide an API key for making requests to Google's geocoding webservice. To do this, place the following code in your main process
file, before opening any browser windows that will make geocoding requests:
Geolocation support in Electron requires the use of Google Cloud Platform's
geolocation webservice. To enable this feature, acquire a
[Google API key](https://developers.google.com/maps/documentation/geolocation/get-api-key)
and place the following code in your main process file, before opening any
browser windows that will make geolocation requests:
```javascript
process.env.GOOGLE_API_KEY = 'YOUR_KEY_HERE'
```
For instructions on how to acquire a Google API key, visit [this page](https://developers.google.com/maps/documentation/javascript/get-api-key).
By default, a newly generated Google API key may not be allowed to make
geocoding requests. To enable geocoding requests, visit [this page](https://developers.google.com/maps/documentation/geocoding/get-api-key).
By default, a newly generated Google API key may not be allowed to make geolocation requests.
To enable the geolocation webservice for your project, enable it through the
[API library](https://console.cloud.google.com/apis/library).
N.B. You will need to add a
[Billing Account](https://cloud.google.com/billing/docs/how-to/payment-methods#add_a_payment_method)
to the project associated to the API key for the geolocation webservice to work.
### `ELECTRON_NO_ASAR`
@@ -73,6 +80,18 @@ and spawned child processes that set `ELECTRON_RUN_AS_NODE`.
Starts the process as a normal Node.js process.
In this mode, you will be able to pass [cli options](https://nodejs.org/api/cli.html) to Node.js as
you would when running the normal Node.js executable, with the exception of the following flags:
* "--openssl-config"
* "--use-bundled-ca"
* "--use-openssl-ca",
* "--force-fips"
* "--enable-fips"
These flags are disabled owing to the fact that Electron uses BoringSSL instead of OpenSSL when building Node.js'
`crypto` module, and so will not work as designed.
### `ELECTRON_NO_ATTACH_CONSOLE` _Windows_
Don't attach to the current console session.

104
docs/api/extensions.md Normal file
View File

@@ -0,0 +1,104 @@
# Chrome Extension Support
Electron supports a subset of the [Chrome Extensions
API][chrome-extensions-api-index], primarily to support DevTools extensions and
Chromium-internal extensions, but it also happens to support some other
extension capabilities.
[chrome-extensions-api-index]: https://developer.chrome.com/extensions/api_index
> **Note:** Electron does not support arbitrary Chrome extensions from the
> store, and it is a **non-goal** of the Electron project to be perfectly
> compatible with Chrome's implementation of Extensions.
## Loading extensions
Electron only supports loading unpacked extensions (i.e., `.crx` files do not
work). Extensions are installed per-`session`. To load an extension, call
[`ses.loadExtension`](session.md#sesloadextensionpath):
```js
const { session } = require('electron')
session.loadExtension('path/to/unpacked/extension').then(({ id }) => {
// ...
})
```
Loaded extensions will not be automatically remembered across exits; if you do
not call `loadExtension` when the app runs, the extension will not be loaded.
Note that loading extensions is only supported in persistent sessions.
Attempting to load an extension into an in-memory session will throw an error.
See the [`session`](session.md) documentation for more information about
loading, unloading, and querying active extensions.
## Supported Extensions APIs
We support the following extensions APIs, with some caveats. Other APIs may
additionally be supported, but support for any APIs not listed here is
provisional and may be removed.
### `chrome.devtools.inspectedWindow`
All features of this API are supported.
### `chrome.devtools.network`
All features of this API are supported.
### `chrome.devtools.panels`
All features of this API are supported.
### `chrome.extension`
The following properties of `chrome.extension` are supported:
- `chrome.extension.lastError`
The following methods of `chrome.extension` are supported:
- `chrome.extension.getURL`
- `chrome.extension.getBackgroundPage`
### `chrome.runtime`
The following properties of `chrome.runtime` are supported:
- `chrome.runtime.lastError`
- `chrome.runtime.id`
The following methods of `chrome.runtime` are supported:
- `chrome.runtime.getBackgroundPage`
- `chrome.runtime.getManifest`
- `chrome.runtime.getURL`
- `chrome.runtime.connect`
- `chrome.runtime.sendMessage`
The following events of `chrome.runtime` are supported:
- `chrome.runtime.onStartup`
- `chrome.runtime.onInstalled`
- `chrome.runtime.onSuspend`
- `chrome.runtime.onSuspendCanceled`
- `chrome.runtime.onConnect`
- `chrome.runtime.onMessage`
### `chrome.storage`
Only `chrome.storage.local` is supported; `chrome.storage.sync` and
`chrome.storage.managed` are not.
### `chrome.tabs`
The following methods of `chrome.tabs` are supported:
- `chrome.tabs.sendMessage`
- `chrome.tabs.executeScript`
> **Note:** In Chrome, passing `-1` as a tab ID signifies the "currently active
> tab". Since Electron has no such concept, passing `-1` as a tab ID is not
> supported and will raise an error.

View File

@@ -487,6 +487,11 @@ to host here.
**Note:** On macOS the OS spellchecker is used and therefore we do not download any dictionary files. This API is a no-op on macOS.
#### `ses.listWordsInSpellCheckerDictionary()`
Returns `Promise<String[]>` - An array of all words in app's custom dictionary.
Resolves when the full dictionary is loaded from disk.
#### `ses.addWordToSpellCheckerDictionary(word)`
* `word` String - The word you want to add to the dictionary
@@ -495,6 +500,14 @@ Returns `Boolean` - Whether the word was successfully written to the custom dict
**Note:** On macOS and Windows 10 this word will be written to the OS custom dictionary as well
#### `ses.removeWordFromSpellCheckerDictionary(word)`
* `word` String - The word you want to remove from the dictionary
Returns `Boolean` - Whether the word was successfully removed from the custom dictionary.
**Note:** On macOS and Windows 10 this word will be removed from the OS custom dictionary as well
#### `ses.loadExtension(path)`
* `path` String - Path to a directory containing an unpacked Chrome extension
@@ -507,6 +520,8 @@ requests an API that Electron does not support) then they will be logged to the
console.
Note that Electron does not support the full range of Chrome extensions APIs.
See [Supported Extensions APIs](extensions.md#supported-extensions-apis) for
more details on what is supported.
Note that in previous versions of Electron, extensions that were loaded would
be remembered for future runs of the application. This is no longer the case:
@@ -529,6 +544,9 @@ This API does not support loading packed (.crx) extensions.
**Note:** This API cannot be called before the `ready` event of the `app` module
is emitted.
**Note:** Loading extensions into in-memory (non-persistent) sessions is not
supported and will throw an error.
#### `ses.removeExtension(extensionId)`
* `extensionId` String - ID of extension to remove

View File

@@ -310,7 +310,7 @@ and allow the page to be unloaded.
const { BrowserWindow, dialog } = require('electron')
const win = new BrowserWindow({ width: 800, height: 600 })
win.webContents.on('will-prevent-unload', (event) => {
const choice = dialog.showMessageBox(win, {
const choice = dialog.showMessageBoxSync(win, {
type: 'question',
buttons: ['Leave', 'Stay'],
title: 'Do you want to leave this site?',

View File

@@ -146,6 +146,7 @@ response are visible by the time this listener is fired.
* `timestamp` Double
* `statusLine` String
* `statusCode` Integer
* `requestHeaders` Record<string, string>
* `responseHeaders` Record<string, string[]> (optional)
* `callback` Function
* `headersReceivedResponse` Object
@@ -228,6 +229,7 @@ redirect is about to occur.
* `fromCache` Boolean
* `statusCode` Integer
* `statusLine` String
* `error` String
The `listener` will be called with `listener(details)` when a request is
completed.

View File

@@ -6,6 +6,26 @@ Breaking changes will be documented here, and deprecation warnings added to JS c
The `FIXME` string is used in code comments to denote things that should be fixed for future releases. See https://github.com/electron/electron/search?q=fixme
## Planned Breaking API Changes (10.0)
### `enableRemoteModule` defaults to `false`
In Electron 9, using the remote module without explicitly enabling it via the
`enableRemoteModule` WebPreferences option began emitting a warning. In
Electron 10, the remote module is now disabled by default. To use the remote
module, `enableRemoteModule: true` must be specified in WebPreferences:
```js
const w = new BrowserWindow({
webPreferences: {
enableRemoteModule: true
}
})
```
We [recommend moving away from the remote
module](https://medium.com/@nornagon/electrons-remote-module-considered-harmful-70d69500f31).
## Planned Breaking API Changes (9.0)
### `<webview>.getWebContents()`

View File

@@ -1,4 +1,4 @@
# Testing on Headless CI Systems (Travis CI, Github Actions, Jenkins)
# Testing on Headless CI Systems (Travis CI, Jenkins)
Being based on Chromium, Electron requires a display driver to function.
If Chromium can't find a display driver, Electron will fail to launch -
@@ -45,10 +45,6 @@ install:
- Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
```
### Github Actions
For Github Actions, a [Xvfb action is available](https://github.com/marketplace/actions/gabrielbb-xvfb-action).
### Jenkins
For Jenkins, a [Xvfb plugin is available](https://wiki.jenkins-ci.org/display/JENKINS/Xvfb+Plugin).

View File

@@ -92,10 +92,14 @@ template("electron_extra_paks") {
}
if (enable_electron_extensions) {
sources += [
"$root_gen_dir/chrome/component_extension_resources.pak",
"$root_gen_dir/extensions/extensions_renderer_resources.pak",
"$root_gen_dir/extensions/extensions_resources.pak",
]
deps += [ "//extensions:extensions_resources" ]
deps += [
"//chrome/browser/resources:component_extension_resources",
"//extensions:extensions_resources",
]
}
}
}

View File

@@ -17,7 +17,8 @@
<part file="electron_strings.grdp" />
</messages>
<includes>
<include name="IDR_CONTENT_SHELL_DEVTOOLS_DISCOVERY_PAGE" file="${target_gen_dir}\shell_devtools_discovery_page.html" use_base_dir="false" type="BINDATA" />
<include name="IDR_CONTENT_SHELL_DEVTOOLS_DISCOVERY_PAGE" file="${target_gen_dir}/shell_devtools_discovery_page.html" use_base_dir="false" type="BINDATA" />
<include name="IDR_PDF_MANIFEST" file="../chrome/browser/resources/pdf/manifest.json" type="BINDATA" />
</includes>
</release>
</grit>

View File

@@ -21,6 +21,7 @@ auto_filenames = {
"docs/api/dock.md",
"docs/api/download-item.md",
"docs/api/environment-variables.md",
"docs/api/extensions.md",
"docs/api/file-object.md",
"docs/api/frameless-window.md",
"docs/api/global-shortcut.md",

View File

@@ -234,12 +234,15 @@ filenames = {
"shell/browser/net/node_stream_loader.h",
"shell/browser/net/proxying_url_loader_factory.cc",
"shell/browser/net/proxying_url_loader_factory.h",
"shell/browser/net/proxying_websocket.cc",
"shell/browser/net/proxying_websocket.h",
"shell/browser/net/resolve_proxy_helper.cc",
"shell/browser/net/resolve_proxy_helper.h",
"shell/browser/net/system_network_context_manager.cc",
"shell/browser/net/system_network_context_manager.h",
"shell/browser/net/url_pipe_loader.cc",
"shell/browser/net/url_pipe_loader.h",
"shell/browser/net/web_request_api_interface.h",
"shell/browser/network_hints_handler_impl.cc",
"shell/browser/network_hints_handler_impl.h",
"shell/browser/node_debugger.cc",
@@ -276,6 +279,8 @@ filenames = {
"shell/browser/notifications/win/win32_notification.h",
"shell/browser/notifications/win/windows_toast_notification.cc",
"shell/browser/notifications/win/windows_toast_notification.h",
"shell/browser/plugins/plugin_utils.cc",
"shell/browser/plugins/plugin_utils.h",
"shell/browser/pref_store_delegate.cc",
"shell/browser/pref_store_delegate.h",
"shell/browser/relauncher.cc",
@@ -591,14 +596,18 @@ filenames = {
]
lib_sources_extensions = [
"shell/browser/extensions/api/resources_private/resources_private_api.cc",
"shell/browser/extensions/api/resources_private/resources_private_api.h",
"shell/browser/extensions/api/runtime/electron_runtime_api_delegate.cc",
"shell/browser/extensions/api/runtime/electron_runtime_api_delegate.h",
"shell/browser/extensions/api/tabs/tabs_api.cc",
"shell/browser/extensions/api/tabs/tabs_api.h",
"shell/browser/extensions/electron_extensions_browser_client.cc",
"shell/browser/extensions/electron_extensions_browser_client.h",
"shell/browser/extensions/api/streams_private/streams_private_api.cc",
"shell/browser/extensions/api/streams_private/streams_private_api.h",
"shell/browser/extensions/electron_browser_context_keyed_service_factories.cc",
"shell/browser/extensions/electron_browser_context_keyed_service_factories.h",
"shell/browser/extensions/electron_component_extension_resource_manager.cc",
"shell/browser/extensions/electron_component_extension_resource_manager.h",
"shell/browser/extensions/electron_display_info_provider.cc",
"shell/browser/extensions/electron_display_info_provider.h",
"shell/browser/extensions/electron_extension_host_delegate.cc",
@@ -611,24 +620,26 @@ filenames = {
"shell/browser/extensions/electron_extension_system_factory.h",
"shell/browser/extensions/electron_extension_web_contents_observer.cc",
"shell/browser/extensions/electron_extension_web_contents_observer.h",
"shell/browser/extensions/electron_navigation_ui_data.cc",
"shell/browser/extensions/electron_navigation_ui_data.h",
"shell/browser/extensions/electron_process_manager_delegate.cc",
"shell/browser/extensions/electron_process_manager_delegate.h",
"shell/browser/extensions/electron_extensions_api_client.cc",
"shell/browser/extensions/electron_extensions_api_client.h",
"shell/browser/extensions/electron_extensions_browser_api_provider.cc",
"shell/browser/extensions/electron_extensions_browser_api_provider.h",
"shell/browser/extensions/electron_extensions_browser_client.cc",
"shell/browser/extensions/electron_extensions_browser_client.h",
"shell/browser/extensions/electron_messaging_delegate.cc",
"shell/browser/extensions/electron_messaging_delegate.h",
"shell/browser/extensions/electron_navigation_ui_data.cc",
"shell/browser/extensions/electron_navigation_ui_data.h",
"shell/browser/extensions/electron_process_manager_delegate.cc",
"shell/browser/extensions/electron_process_manager_delegate.h",
"shell/common/extensions/electron_extensions_api_provider.cc",
"shell/common/extensions/electron_extensions_api_provider.h",
"shell/common/extensions/electron_extensions_client.cc",
"shell/common/extensions/electron_extensions_client.h",
"shell/renderer/extensions/electron_extensions_renderer_client.cc",
"shell/renderer/extensions/electron_extensions_renderer_client.h",
"shell/renderer/extensions/electron_extensions_dispatcher_delegate.cc",
"shell/renderer/extensions/electron_extensions_dispatcher_delegate.h",
"shell/renderer/extensions/electron_extensions_renderer_client.cc",
"shell/renderer/extensions/electron_extensions_renderer_client.h",
]
app_sources = [

View File

@@ -25,26 +25,6 @@ BrowserWindow.prototype._init = function () {
nativeSetBounds.call(this, bounds, ...opts)
}
// window.resizeTo(...)
// window.moveTo(...)
this.webContents.on('move', (event, size) => {
this.setBounds(size)
})
// Hide the auto-hide menu when webContents is focused.
this.webContents.on('activate', () => {
if (process.platform !== 'darwin' && this.autoHideMenuBar && this.isMenuBarVisible()) {
this.setMenuBarVisibility(false)
}
})
// Change window title to page title.
this.webContents.on('page-title-updated', (event, title, ...args) => {
// Route the event to BrowserWindow.
this.emit('page-title-updated', event, title, ...args)
if (!this.isDestroyed() && !event.defaultPrevented) this.setTitle(title)
})
// Sometimes the webContents doesn't get focus when window is shown, so we
// have to force focusing on webContents in this case. The safest way is to
// focus it when we first start to load URL, if we do it earlier it won't

View File

@@ -18,8 +18,10 @@ require('@electron/internal/common/init')
if (process.platform === 'win32') {
// Redirect node's console to use our own implementations, since node can not
// handle console output when running as GUI program.
const consoleLog = (format: any, ...args: any[]) => {
return process.log(util.format(format, ...args) + '\n')
const consoleLog = (...args: any[]) => {
// @ts-ignore this typing is incorrect; 'format' is an optional parameter
// See https://nodejs.org/api/util.html#util_util_format_format_args
return process.log(util.format(...args) + '\n')
}
const streamWrite: NodeJS.WritableStream['write'] = function (chunk: Buffer | string, encoding?: any, callback?: Function) {
if (Buffer.isBuffer(chunk)) {

View File

@@ -321,7 +321,7 @@ const unwrapArgs = function (sender: electron.WebContents, frameId: number, cont
const isRemoteModuleEnabledImpl = function (contents: electron.WebContents) {
const webPreferences = (contents as any).getLastWebPreferences() || {}
return webPreferences.enableRemoteModule != null ? !!webPreferences.enableRemoteModule : true
return webPreferences.enableRemoteModule != null ? !!webPreferences.enableRemoteModule : false
}
const isRemoteModuleEnabledCache = new WeakMap()

View File

@@ -13,15 +13,6 @@ const remoteObjectCache = v8Util.createIDWeakMap()
// An unique ID that can represent current context.
const contextId = v8Util.getHiddenValue(global, 'contextId')
ipcRendererInternal.invoke('ELECTRON_BROWSER_GET_LAST_WEB_PREFERENCES').then(preferences => {
console.log(preferences)
if (!preferences.enableRemoteModule) {
console.warn('%cElectron Deprecation Warning', 'font-weight: bold', "The 'remote' module is deprecated and will be disabled by default in a future version of Electron. To ensure a smooth upgrade and silence this warning, specify {enableRemoteModule: true} in the WebPreferences for this window.")
}
}, (err) => {
console.error('Failed to get web preferences:', err)
})
// Notify the main process when current context is going to be released.
// Note that when the renderer process is destroyed, the message may not be
// sent, we also listen to the "render-view-deleted" event in the main process

View File

@@ -1,6 +1,6 @@
{
"name": "electron",
"version": "10.0.0-nightly.20200206",
"version": "10.0.0-nightly.20200213",
"repository": "https://github.com/electron/electron",
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
"devDependencies": {

View File

@@ -35,7 +35,7 @@ mas_disable_remote_accessibility.patch
mas_disable_custom_window_frame.patch
chrome_key_systems.patch
allow_nested_error_trackers.patch
blink_initialization_order.patch
add_didinstallconditionalfeatures.patch
ssl_security_state_tab_helper.patch
desktop_media_list.patch
proxy_config_monitor.patch
@@ -81,3 +81,6 @@ feat_allow_disabling_blink_scheduler_throttling_per_renderview.patch
accessible_pane_view.patch
fixme_grit_conflicts.patch
fix_use_the_new_mediaplaypause_key_listener_for_internal_chrome.patch
fix_use_native_window_button_positions_when_macos_locale_is_rtl.patch
use_electron_resources_in_pdf_util.patch
hack_plugin_response_interceptor_to_point_to_electron.patch

View File

@@ -0,0 +1,137 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jeremy Apthorp <nornagon@nornagon.net>
Date: Wed, 15 Jan 2020 16:35:18 -0800
Subject: add DidInstallConditionalFeatures
This adds a hook on script context creation _after conditional features
have been installed_. Electron uses this to run preload scripts and
various other initialization. This is necessary because at the time
DidCreateScriptContext is called, not all JS APIs are available in the
context, which can cause some preload scripts to trip.
diff --git a/content/public/renderer/render_frame_observer.h b/content/public/renderer/render_frame_observer.h
index 68654a3e7d5ec6caddccb667f9f8fa2feabfa71b..650ce53e112bd65e1901a09480452855a0c16dda 100644
--- a/content/public/renderer/render_frame_observer.h
+++ b/content/public/renderer/render_frame_observer.h
@@ -115,6 +115,8 @@ class CONTENT_EXPORT RenderFrameObserver : public IPC::Listener,
virtual void DidHandleOnloadEvents() {}
virtual void DidCreateScriptContext(v8::Local<v8::Context> context,
int32_t world_id) {}
+ virtual void DidInstallConditionalFeatures(v8::Local<v8::Context> context,
+ int32_t world_id) {}
virtual void WillReleaseScriptContext(v8::Local<v8::Context> context,
int32_t world_id) {}
virtual void DidClearWindowObject() {}
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 6730d6f6eb8448452991ebf5968a8c5a398b6a88..b87f9c7ac0f31ec33f03c36131c3255c8a31c22c 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -5187,6 +5187,12 @@ void RenderFrameImpl::DidCreateScriptContext(v8::Local<v8::Context> context,
observer.DidCreateScriptContext(context, world_id);
}
+void RenderFrameImpl::DidInstallConditionalFeatures(
+ v8::Local<v8::Context> context, int world_id) {
+ for (auto& observer : observers_)
+ observer.DidInstallConditionalFeatures(context, world_id);
+}
+
void RenderFrameImpl::WillReleaseScriptContext(v8::Local<v8::Context> context,
int world_id) {
for (auto& observer : observers_)
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index bc896201057832415b5d54dc8987bb74bf7aa778..5c96af71646722b1108a8d6eafba1adaddf0a05a 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -773,6 +773,8 @@ class CONTENT_EXPORT RenderFrameImpl
bool ShouldTrackUseCounter(const blink::WebURL& url) override;
void DidCreateScriptContext(v8::Local<v8::Context> context,
int world_id) override;
+ void DidInstallConditionalFeatures(v8::Local<v8::Context> context,
+ int world_id) override;
void WillReleaseScriptContext(v8::Local<v8::Context> context,
int world_id) override;
void DidChangeScrollOffset() override;
diff --git a/third_party/blink/public/web/web_local_frame_client.h b/third_party/blink/public/web/web_local_frame_client.h
index 30638c31e30d98bb23292115b25b528ff8e8f62c..e0f2f786b75f861851d1194f57b253a173053299 100644
--- a/third_party/blink/public/web/web_local_frame_client.h
+++ b/third_party/blink/public/web/web_local_frame_client.h
@@ -652,6 +652,9 @@ class BLINK_EXPORT WebLocalFrameClient {
virtual void DidCreateScriptContext(v8::Local<v8::Context>,
int32_t world_id) {}
+ virtual void DidInstallConditionalFeatures(v8::Local<v8::Context>,
+ int32_t world_id) {}
+
// WebKit is about to release its reference to a v8 context for a frame.
virtual void WillReleaseScriptContext(v8::Local<v8::Context>,
int32_t world_id) {}
diff --git a/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc b/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc
index 8095edd988c171a8ad7382d1c2f9fa63ee9e5ffc..510dae593d2a0e2ce13a2879dde5c31e01d21c21 100644
--- a/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc
+++ b/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc
@@ -231,6 +231,7 @@ void LocalWindowProxy::Initialize() {
}
InstallConditionalFeatures();
+ GetFrame()->Client()->DidInstallConditionalFeatures(context, world_->GetWorldId());
if (World().IsMainWorld()) {
GetFrame()->Loader().DispatchDidClearWindowObjectInMainWorld();
diff --git a/third_party/blink/renderer/core/exported/local_frame_client_impl.cc b/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
index f8c512c9db0b88904a562b7d4195790d4b0f86a6..d31ef9bd5b98f584a3296638662ae0d27aa37b65 100644
--- a/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
+++ b/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
@@ -267,6 +267,13 @@ void LocalFrameClientImpl::DidCreateScriptContext(
web_frame_->Client()->DidCreateScriptContext(context, world_id);
}
+void LocalFrameClientImpl::DidInstallConditionalFeatures(
+ v8::Local<v8::Context> context,
+ int32_t world_id) {
+ if (web_frame_->Client())
+ web_frame_->Client()->DidInstallConditionalFeatures(context, world_id);
+}
+
void LocalFrameClientImpl::WillReleaseScriptContext(
v8::Local<v8::Context> context,
int32_t world_id) {
diff --git a/third_party/blink/renderer/core/exported/local_frame_client_impl.h b/third_party/blink/renderer/core/exported/local_frame_client_impl.h
index a055f4b0cc1ccc30752b65d6dc54e638e9b63001..0e6501adbf6f9696429c3fa95357de399ee30a9d 100644
--- a/third_party/blink/renderer/core/exported/local_frame_client_impl.h
+++ b/third_party/blink/renderer/core/exported/local_frame_client_impl.h
@@ -79,6 +79,8 @@ class LocalFrameClientImpl final : public LocalFrameClient {
void DidCreateScriptContext(v8::Local<v8::Context>,
int32_t world_id) override;
+ void DidInstallConditionalFeatures(v8::Local<v8::Context>,
+ int32_t world_id) override;
void WillReleaseScriptContext(v8::Local<v8::Context>,
int32_t world_id) override;
diff --git a/third_party/blink/renderer/core/frame/local_frame_client.h b/third_party/blink/renderer/core/frame/local_frame_client.h
index 1d6facb9ec63abebc5b79a57860765bc8b3f6638..0b58cb679ed34c54e39af661d4a432d482db8c3c 100644
--- a/third_party/blink/renderer/core/frame/local_frame_client.h
+++ b/third_party/blink/renderer/core/frame/local_frame_client.h
@@ -303,6 +303,8 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
virtual void DidCreateScriptContext(v8::Local<v8::Context>,
int32_t world_id) = 0;
+ virtual void DidInstallConditionalFeatures(v8::Local<v8::Context>,
+ int32_t world_id) = 0;
virtual void WillReleaseScriptContext(v8::Local<v8::Context>,
int32_t world_id) = 0;
virtual bool AllowScriptExtensions() = 0;
diff --git a/third_party/blink/renderer/core/loader/empty_clients.h b/third_party/blink/renderer/core/loader/empty_clients.h
index f3f00e7d6ac44d77dd75997abf8b93eb59476eb3..2010792697b3443dd6f5058bed5ccd0026c4a152 100644
--- a/third_party/blink/renderer/core/loader/empty_clients.h
+++ b/third_party/blink/renderer/core/loader/empty_clients.h
@@ -370,6 +370,8 @@ class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient {
void DidCreateScriptContext(v8::Local<v8::Context>,
int32_t world_id) override {}
+ void DidInstallConditionalFeatures(v8::Local<v8::Context>,
+ int32_t world_id) override {}
void WillReleaseScriptContext(v8::Local<v8::Context>,
int32_t world_id) override {}
bool AllowScriptExtensions() override { return false; }

View File

@@ -1,28 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Samuel Attard <samuel.r.attard@gmail.com>
Date: Thu, 20 Sep 2018 17:50:24 -0700
Subject: blink_initialization_order.patch
Backport of https://chromium-review.googlesource.com/c/chromium/src/+/1030530
to fix the order of V8 and Blink initialization. Also fixes order
of DidCreateScriptContext notification with initialization of window globals
to fix electron/electron#13787. The backport landed in Chromium 67 but the
DidCreateScriptContext re-ordering needs to be upstreamed or kept indefinitely
diff --git a/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc b/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc
index c845acb8321e94c916798826a168e06df34ffff4..941ca9d3905c0c2f36606655bf60e9e9bd1f9196 100644
--- a/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc
+++ b/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc
@@ -211,11 +211,10 @@ void LocalWindowProxy::Initialize() {
GetFrame()->IsMainFrame());
MainThreadDebugger::Instance()->ContextCreated(script_state_, GetFrame(),
origin);
+ InstallConditionalFeatures();
GetFrame()->Client()->DidCreateScriptContext(context, world_->GetWorldId());
}
- InstallConditionalFeatures();
-
if (World().IsMainWorld()) {
GetFrame()->Loader().DispatchDidClearWindowObjectInMainWorld();
}

View File

@@ -6,6 +6,18 @@ Subject: chore: use electron resources not chrome for spellchecker
spellchecker uses a few IDS_ resources. We need to load these from
Electrons grit header instead of Chromes
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index d730660c086f..ba9b098d848e 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -5049,6 +5049,7 @@ jumbo_split_static_library("browser") {
deps += [
"//components/spellcheck/browser",
"//components/spellcheck/common",
+ "//electron:resources",
]
if (!is_android) {
diff --git a/chrome/browser/spellchecker/spellcheck_factory.cc b/chrome/browser/spellchecker/spellcheck_factory.cc
index 48ac0a24efde0cb7d3ba71c8b8bdf5178f606e80..e2beefc276098fdc8f1cdab2e0edb8fae4ee67ca 100644
--- a/chrome/browser/spellchecker/spellcheck_factory.cc
@@ -19,6 +31,18 @@ index 48ac0a24efde0cb7d3ba71c8b8bdf5178f606e80..e2beefc276098fdc8f1cdab2e0edb8fa
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_service.h"
diff --git a/components/language/core/browser/BUILD.gn b/components/language/core/browser/BUILD.gn
index f28230ea94fe..c10eea103852 100644
--- a/components/language/core/browser/BUILD.gn
+++ b/components/language/core/browser/BUILD.gn
@@ -31,6 +31,7 @@ static_library("browser") {
"//components/pref_registry",
"//components/prefs",
"//components/strings",
+ "//electron:resources",
"//ui/base",
]
}
diff --git a/components/language/core/browser/language_prefs.cc b/components/language/core/browser/language_prefs.cc
index 7e06f689632ae67e3e17d7985c6e7b6ea0057f3c..0b4676f4c40b4a0eda927a51016ec91ec230291d 100644
--- a/components/language/core/browser/language_prefs.cc

View File

@@ -0,0 +1,31 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sesh Sadasivam <sesh@fb.com>
Date: Fri, 31 Jan 2020 19:02:27 -0800
Subject: fix: use native window button positions when MacOS locale is RTL
Classes that inherit from `NSThemeFrame` seem to show window buttons in the
incorrect position when the primary MacOS language is set to an RTL
(right-to-left) language like Arabic or Hebrew. The fix in this commit mirrors
that of `tabbed_browser_window.mm`
(https://chromium-review.googlesource.com/c/chromium/src/+/562603/10/chrome/browser/ui/cocoa/tabbed_browser_window.mm#88).
This change should be upstreamed, and then this patch can be removed.
diff --git a/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm b/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
index 9905e1c8914f852e250480797f43d17bf9d7f794..0016cc129805726d6518036fb181a2a9715af8c5 100644
--- a/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
+++ b/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
@@ -69,6 +69,13 @@ - (void)mouseDown:(NSEvent*)event {
- (BOOL)usesCustomDrawing {
return NO;
}
+// AppKit's implementation only returns YES if [self class] == [NSThemeFrame
+// class]. See:
+// https://chromium-review.googlesource.com/c/chromium/src/+/562603/10/chrome/browser/ui/cocoa/tabbed_browser_window.mm#88
+- (BOOL)_shouldFlipTrafficLightsForRTL API_AVAILABLE(macosx(10.13)) {
+ return self.window.windowTitlebarLayoutDirection ==
+ NSUserInterfaceLayoutDirectionRightToLeft;
+}
@end
@implementation NativeWidgetMacNSWindowBorderlessFrame

View File

@@ -0,0 +1,24 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jeremy Apthorp <nornagon@nornagon.net>
Date: Mon, 10 Feb 2020 11:52:23 -0800
Subject: hack plugin response interceptor to point to electron
chrome's streams_private_api does prerender and other things and would
require a largeish patch to get working, so just redirect it to our
implementation instead.
diff --git a/chrome/browser/plugins/plugin_response_interceptor_url_loader_throttle.cc b/chrome/browser/plugins/plugin_response_interceptor_url_loader_throttle.cc
index 1c9aeb8fa71d054159c2ccccccbe57aa474d417e..0bd6412f2c79f77f936720b1a0795b50ecefd26c 100644
--- a/chrome/browser/plugins/plugin_response_interceptor_url_loader_throttle.cc
+++ b/chrome/browser/plugins/plugin_response_interceptor_url_loader_throttle.cc
@@ -8,8 +8,8 @@
#include "base/feature_list.h"
#include "base/guid.h"
#include "base/task/post_task.h"
-#include "chrome/browser/extensions/api/streams_private/streams_private_api.h"
-#include "chrome/browser/plugins/plugin_utils.h"
+#include "electron/shell/browser/extensions/api/streams_private/streams_private_api.h"
+#include "electron/shell/browser/plugins/plugin_utils.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_utils.h"

View File

@@ -0,0 +1,22 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jeremy Apthorp <nornagon@nornagon.net>
Date: Mon, 10 Feb 2020 10:37:48 -0800
Subject: use electron resources in pdf_util
Without this, the ID for IDR_PDF_MANIFEST will be wrong on linux
and cause a DCHECK(), since the resource will be loaded as an empty
string.
diff --git a/chrome/browser/pdf/pdf_extension_util.cc b/chrome/browser/pdf/pdf_extension_util.cc
index 877d0ba2f48359243527ddebf1d91132b3d5c455..cd69de498c4968ade0ffabf45b72d4d63b70b10f 100644
--- a/chrome/browser/pdf/pdf_extension_util.cc
+++ b/chrome/browser/pdf/pdf_extension_util.cc
@@ -6,7 +6,7 @@
#include "base/strings/string_util.h"
#include "chrome/common/chrome_content_client.h"
-#include "chrome/grit/browser_resources.h"
+#include "electron/grit/electron_resources.h"
#include "ui/base/resource/resource_bundle.h"
namespace pdf_extension_util {

View File

@@ -7,7 +7,6 @@ expose_get_builtin_module_function.patch
fix_build_and_expose_inspector_agent.patch
fix_expose_internalcallbackscope.patch
build_add_gn_build_files.patch
fix_export_debugoptions.patch
fix_add_default_values_for_enable_lto_and_build_v8_with_gn_in.patch
feat_add_new_built_with_electron_variable_to_config_gypi.patch
feat_add_flags_for_low-level_hooks_and_exceptions.patch
@@ -18,7 +17,6 @@ fixme_use_redefined_version_of_internalmodulestat.patch
fixme_remove_async_id_assertion_check.patch
fixme_comment_trace_event_macro.patch
fix_key_gen_apis_are_not_available_in_boringssl.patch
fix_do_not_define_debugoptions_s_constructors_in_header.patch
build_modify_js2c_py_to_allow_injection_of_original-fs_and_custom_embedder_js.patch
refactor_allow_embedder_overriding_of_internal_fs_calls.patch
chore_prevent_warn_non_context-aware_native_modules_being_loaded.patch
@@ -29,10 +27,10 @@ build_bring_back_node_with_ltcg_configuration.patch
revert_crypto_add_oaeplabel_option.patch
refactor_transferrablemodule_is_deprecated_use_compiledwasmmodule.patch
enable_31_bit_smis_on_64bit_arch_and_ptr_compression.patch
fix_remove_unused_llhttp_variables.patch
fix_include_libuv_header_in_node_binding.patch
remove_deprecated_task_api_override_removed_in_latest_v8.patch
remove_serialization_deserialization_of_wasmmoduleobject.patch
64bit_bump_typedarray_max_length_to_2_32-1_elements.patch
test_use_tmpdir_refresh_in_test-esm-windows_js.patch
override_existing_v8_reallocate.patch
feat_enable_passing_cli_flags.patch

View File

@@ -0,0 +1,108 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shelley Vohr <shelley.vohr@gmail.com>
Date: Wed, 13 Nov 2019 15:39:48 +0000
Subject: feat: enable passing cli flags
This patches enables passing safelisted cli flags to Node.js.
Upstreamed in https://github.com/nodejs/node/pull/30466.
diff --git a/src/node.cc b/src/node.cc
index 461f736beacec67b35c89a42319f99178a1e38e9..c00bfb6ccbe603604fca29268d15d67b208b2e6a 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -113,8 +113,6 @@
namespace node {
using native_module::NativeModuleEnv;
-using options_parser::kAllowedInEnvironment;
-using options_parser::kDisallowedInEnvironment;
using v8::Boolean;
using v8::EscapableHandleScope;
@@ -670,7 +668,7 @@ void ResetStdio() {
int ProcessGlobalArgs(std::vector<std::string>* args,
std::vector<std::string>* exec_args,
std::vector<std::string>* errors,
- bool is_env) {
+ OptionEnvvarSettings settings) {
// Parse a few arguments which are specific to Node.
std::vector<std::string> v8_args;
@@ -680,7 +678,7 @@ int ProcessGlobalArgs(std::vector<std::string>* args,
exec_args,
&v8_args,
per_process::cli_options.get(),
- is_env ? kAllowedInEnvironment : kDisallowedInEnvironment,
+ settings,
errors);
if (!errors->empty()) return 9;
@@ -851,7 +849,7 @@ int InitializeNodeWithArgs(std::vector<std::string>* argv,
return 9;
}
- const int exit_code = ProcessGlobalArgs(&env_argv, nullptr, errors, true);
+ const int exit_code = ProcessGlobalArgs(&env_argv, nullptr, errors, kAllowedInEnvironment);
if (exit_code != 0) return exit_code;
}
#endif
@@ -859,7 +857,7 @@ int InitializeNodeWithArgs(std::vector<std::string>* argv,
if (g_upstream_node_mode) {
// NOTE(jeremy): indentation is intentionally wrong here, to ease rebasing.
- const int exit_code = ProcessGlobalArgs(argv, exec_argv, errors, false);
+ const int exit_code = ProcessGlobalArgs(argv, exec_argv, errors, kDisallowedInEnvironment);
if (exit_code != 0) return exit_code;
// Set the process.title immediately after processing argv if --title is set.
diff --git a/src/node.h b/src/node.h
index 9c6dcbf7014f7cf87f7f66886cbf255978c244fa..4f2da9a46966199465a33c1fa275d0116d395a56 100644
--- a/src/node.h
+++ b/src/node.h
@@ -223,6 +223,16 @@ NODE_EXTERN void Init(int* argc,
int* exec_argc,
const char*** exec_argv);
+enum OptionEnvvarSettings {
+ kAllowedInEnvironment,
+ kDisallowedInEnvironment
+};
+
+NODE_EXTERN int ProcessGlobalArgs(std::vector<std::string>* args,
+ std::vector<std::string>* exec_args,
+ std::vector<std::string>* errors,
+ OptionEnvvarSettings settings);
+
class NodeArrayBufferAllocator;
// An ArrayBuffer::Allocator class with some Node.js-specific tweaks. If you do
diff --git a/src/node_options.h b/src/node_options.h
index 4ce5551284bb5b1b4194905a9fe619f852933405..404cb72536cdaf8f0320770392e02ac75c303cae 100644
--- a/src/node_options.h
+++ b/src/node_options.h
@@ -248,11 +248,6 @@ HostPort NODE_EXTERN SplitHostPort(const std::string& arg,
std::vector<std::string>* errors);
void GetOptions(const v8::FunctionCallbackInfo<v8::Value>& args);
-enum OptionEnvvarSettings {
- kAllowedInEnvironment,
- kDisallowedInEnvironment
-};
-
enum OptionType {
kNoOp,
kV8Option,
diff --git a/src/node_worker.cc b/src/node_worker.cc
index c8b2e1699f26ac9bfeb373653d35271f9b6c841f..a4db86ad99c75e07960a95247a41ed78e5bf55ca 100644
--- a/src/node_worker.cc
+++ b/src/node_worker.cc
@@ -16,7 +16,7 @@
#include <string>
#include <vector>
-using node::options_parser::kDisallowedInEnvironment;
+using node::kDisallowedInEnvironment;
using v8::Array;
using v8::Boolean;
using v8::Context;

View File

@@ -1,54 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Cheng Zhao <zcbenz@gmail.com>
Date: Fri, 29 Mar 2019 17:17:30 +0900
Subject: fix: do not define DebugOptions's constructors in header
The e3ca89ef49 changed NODE_EXTERN to always expose symbols for
DebugOptions, and since the constructors of DebugOptions are defined in
header, the compiler would end up generating no constructor
implementations for DebugOptions.
Which means we would encounter crash when constructors of DebugOptions
is called.
By putting the definitions of constructors into the implementation file,
we can avoid this problem.
diff --git a/src/node_options.cc b/src/node_options.cc
index 2dd90e9a8cf9381c8608b73ead247bcf86b72ab9..051e7b084b6770215bd009b0e37feabbb7df7389 100644
--- a/src/node_options.cc
+++ b/src/node_options.cc
@@ -26,6 +26,12 @@ Mutex cli_options_mutex;
std::shared_ptr<PerProcessOptions> cli_options{new PerProcessOptions()};
} // namespace per_process
+DebugOptions::DebugOptions() = default;
+DebugOptions::DebugOptions(const DebugOptions&) = default;
+DebugOptions::DebugOptions(DebugOptions&&) = default;
+DebugOptions& DebugOptions::operator=(const DebugOptions&) = default;
+DebugOptions& DebugOptions::operator=(DebugOptions&&) = default;
+
void DebugOptions::CheckOptions(std::vector<std::string>* errors) {
#if !NODE_USE_V8_PLATFORM && !HAVE_INSPECTOR
if (inspector_enabled) {
diff --git a/src/node_options.h b/src/node_options.h
index 40c19ea6ff4d98a1a1da59bca76087209445af81..4ce5551284bb5b1b4194905a9fe619f852933405 100644
--- a/src/node_options.h
+++ b/src/node_options.h
@@ -61,11 +61,11 @@ struct InspectPublishUid {
// per-Isolate, rather than per-Environment.
class NODE_EXTERN DebugOptions : public Options {
public:
- DebugOptions() = default;
- DebugOptions(const DebugOptions&) = default;
- DebugOptions& operator=(const DebugOptions&) = default;
- DebugOptions(DebugOptions&&) = default;
- DebugOptions& operator=(DebugOptions&&) = default;
+ DebugOptions();
+ DebugOptions(const DebugOptions&);
+ DebugOptions& operator=(const DebugOptions&);
+ DebugOptions(DebugOptions&&);
+ DebugOptions& operator=(DebugOptions&&);
// --inspect
bool inspector_enabled = false;

View File

@@ -1,57 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nitish Sakhawalkar <nitsakh@icloud.com>
Date: Thu, 11 Apr 2019 11:50:49 -0700
Subject: fix: export DebugOptions
This exports DebugOptions so we can parse args like `--inspect-brk`.
diff --git a/src/node_options.cc b/src/node_options.cc
index 35cac18a916c2ce104a3e7b6760d0280b33c2892..2dd90e9a8cf9381c8608b73ead247bcf86b72ab9 100644
--- a/src/node_options.cc
+++ b/src/node_options.cc
@@ -210,11 +210,6 @@ void EnvironmentOptions::CheckOptions(std::vector<std::string>* errors) {
namespace options_parser {
-class DebugOptionsParser : public OptionsParser<DebugOptions> {
- public:
- DebugOptionsParser();
-};
-
class EnvironmentOptionsParser : public OptionsParser<EnvironmentOptions> {
public:
EnvironmentOptionsParser();
diff --git a/src/node_options.h b/src/node_options.h
index 8937bfd9011e4795d22e232886e18183d698b8d4..40c19ea6ff4d98a1a1da59bca76087209445af81 100644
--- a/src/node_options.h
+++ b/src/node_options.h
@@ -59,7 +59,7 @@ struct InspectPublishUid {
// to keep them separate since they are a group of options applying to a very
// specific part of Node. It might also make more sense for them to be
// per-Isolate, rather than per-Environment.
-class DebugOptions : public Options {
+class NODE_EXTERN DebugOptions : public Options {
public:
DebugOptions() = default;
DebugOptions(const DebugOptions&) = default;
@@ -244,7 +244,7 @@ class PerProcessOptions : public Options {
namespace options_parser {
-HostPort SplitHostPort(const std::string& arg,
+HostPort NODE_EXTERN SplitHostPort(const std::string& arg,
std::vector<std::string>* errors);
void GetOptions(const v8::FunctionCallbackInfo<v8::Value>& args);
@@ -437,6 +437,11 @@ class OptionsParser {
friend void GetOptions(const v8::FunctionCallbackInfo<v8::Value>& args);
};
+class NODE_EXTERN DebugOptionsParser : public OptionsParser<DebugOptions> {
+ public:
+ DebugOptionsParser();
+};
+
using StringVector = std::vector<std::string>;
template <class OptionsType, class = Options>
void Parse(

View File

@@ -1,48 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shelley Vohr <shelley.vohr@gmail.com>
Date: Wed, 8 Jan 2020 10:12:46 -0800
Subject: fix: remove unused llhttp variables
Node.js updated llhttps in https://github.com/nodejs/node/pull/30553,
which updated some of the llparse_blobs. To keep numbering consistency,
it left the newly unused ones, which causes compilation failures in Electron
as we do not allow unused variables.
Fixed in https://github.com/nodejs/llparse/pull/34; this patch can be removed
as soon as llparse v6.2.1 is rolled into Node.js
diff --git a/deps/llhttp/src/llhttp.c b/deps/llhttp/src/llhttp.c
index 698230f93fe08f347a9e6e9f7194663c9b5318c3..664b563ad1ccf69794f0e86245e91d0bc26c1d58 100644
--- a/deps/llhttp/src/llhttp.c
+++ b/deps/llhttp/src/llhttp.c
@@ -24,10 +24,6 @@ typedef int (*llhttp__internal__span_cb)(
static const unsigned char llparse_blob0[] = {
'C', 'L'
};
-static const unsigned char ALIGN(16) llparse_blob1[] = {
- 0x9, 0x9, 0xc, 0xc, '!', '"', '$', '>', '@', '~', 0x80,
- 0xff
-};
static const unsigned char llparse_blob2[] = {
'o', 'n'
};
@@ -43,19 +39,9 @@ static const unsigned char llparse_blob5[] = {
static const unsigned char llparse_blob6[] = {
'p', 'g', 'r', 'a', 'd', 'e'
};
-static const unsigned char ALIGN(16) llparse_blob7[] = {
- 0x9, 0x9, ' ', '~', 0x80, 0xfe
-};
static const unsigned char llparse_blob8[] = {
'h', 'u', 'n', 'k', 'e', 'd'
};
-static const unsigned char ALIGN(16) llparse_blob9[] = {
- ' ', '!', '#', '\'', '*', '+', '-', '.', '0', '9', 'A',
- 'Z', '^', 'z', '|', '|'
-};
-static const unsigned char ALIGN(16) llparse_blob10[] = {
- '~', '~'
-};
static const unsigned char llparse_blob11[] = {
'e', 'n', 't', '-', 'l', 'e', 'n', 'g', 't', 'h'
};

View File

@@ -9,7 +9,11 @@ async function checkIfDocOnlyChange () {
try {
let pullRequestNumber = args.prNumber
if (!pullRequestNumber || isNaN(pullRequestNumber)) {
if (args.prBranch) {
if (args.prURL) {
// CircleCI doesn't provide the PR number for branch builds, but it does provide the PR URL
const pullRequestParts = args.prURL.split('/')
pullRequestNumber = pullRequestParts[pullRequestParts.length - 1]
} else if (args.prBranch) {
// AppVeyor doesn't provide a PR number for branch builds - figure it out from the branch
const prsForBranch = await octokit.pulls.list({
owner: 'electron',
@@ -23,10 +27,6 @@ async function checkIfDocOnlyChange () {
// If there are 0 PRs or more than one PR on a branch, just assume that this is more than a doc change
process.exit(1)
}
} else if (args.prURL) {
// CircleCI doesn't provide the PR number for branch builds, but it does provide the PR URL
const pullRequestParts = args.prURL.split('/')
pullRequestNumber = pullRequestParts[pullRequestParts.length - 1]
}
}
const filesChanged = await octokit.pulls.listFiles({

View File

@@ -51,14 +51,8 @@
"parallel/test-buffer-constructor-node-modules-paths",
"parallel/test-buffer-constructor-outside-node-modules",
"parallel/test-child-process-fork-exec-path",
"parallel/test-child-process-windows-hide",
"parallel/test-cli-bad-options",
"parallel/test-cli-eval",
"parallel/test-cli-node-options",
"parallel/test-cli-node-print-help",
"parallel/test-cli-syntax-eval",
"parallel/test-cli-syntax-piped-bad",
"parallel/test-cli-syntax-piped-good",
"parallel/test-cli-eval",
"parallel/test-code-cache",
"parallel/test-common-gc",
"parallel/test-crypto",
@@ -86,7 +80,6 @@
"parallel/test-debug-usage",
"parallel/test-debugger-pid",
"parallel/test-domain-abort-on-uncaught",
"parallel/test-domain-async-id-map-leak",
"parallel/test-domain-with-abort-on-uncaught-exception",
"parallel/test-dummy-stdio",
"parallel/test-freeze-intrinsics",
@@ -108,8 +101,7 @@
"parallel/test-inspector-tracing-domain",
"parallel/test-inspector-vm-global-accessors-getter-sideeffect",
"parallel/test-inspector-vm-global-accessors-sideeffects",
"parallel/test-inspector-workers-flat-list",
"parallel/test-internal-util-weakreference",
"parallel/test-inspector-heap-allocation-tracker",
"parallel/test-module-loading-globalpaths",
"parallel/test-module-version",
"parallel/test-openssl-ca-options",
@@ -121,12 +113,11 @@
"parallel/test-process-exception-capture",
"parallel/test-process-exception-capture-should-abort-on-uncaught",
"parallel/test-process-exception-capture-should-abort-on-uncaught-setflagsfromstring",
"parallel/test-process-exec-argv",
"parallel/test-process-exit-code",
"parallel/test-process-external-stdio-close",
"parallel/test-process-external-stdio-close-spawn",
"parallel/test-process-versions",
"parallel/test-readline-interface",
"parallel/test-inspector-tracing-domain",
"parallel/test-repl",
"parallel/test-repl-harmony",
"parallel/test-repl-pretty-custom-stack",
@@ -136,7 +127,6 @@
"parallel/test-repl-tab-complete",
"parallel/test-repl-uncaught-exception",
"parallel/test-repl-underscore",
"parallel/test-security-revert-unknown",
"parallel/test-signal-handler",
"parallel/test-source-map",
"parallel/test-stdout-close-catch",
@@ -242,9 +232,6 @@
"report/test-report-uncaught-exception",
"report/test-report-writereport",
"sequential/test-child-process-execsync",
"sequential/test-cli-syntax-bad",
"sequential/test-cli-syntax-good",
"sequential/test-cli-syntax-require",
"sequential/test-cpu-prof-default",
"sequential/test-cpu-prof-dir-absolute",
"sequential/test-cpu-prof-dir-and-name",
@@ -252,11 +239,9 @@
"sequential/test-cpu-prof-dir-worker",
"sequential/test-cpu-prof-drained",
"sequential/test-cpu-prof-exit",
"sequential/test-cpu-prof-invalid-options",
"sequential/test-cpu-prof-kill",
"sequential/test-cpu-prof-name",
"sequential/test-cpu-prof-worker-argv",
"sequential/test-deprecation-flags",
"sequential/test-fs-watch",
"sequential/test-heap-prof",
"sequential/test-heapdump",

View File

@@ -23,6 +23,11 @@ const circleCIJobs = [
'osx-publish'
]
const circleCIPublishWorkflows = [
'linux-publish',
'macos-publish'
]
const vstsArmJobs = [
'electron-arm-testing',
'electron-arm64-testing',
@@ -87,13 +92,18 @@ async function circleCIcall (targetBranch, job, options) {
if (workflowId === -1) {
return
}
console.log(`CircleCI release build workflow running at https://circleci.com/workflow-run/${workflowId} for ${job}.`)
const jobNumber = await getCircleCIJobNumber(workflowId)
if (jobNumber === -1) {
return
const workFlowUrl = `https://circleci.com/workflow-run/${workflowId}`
if (options.runningPublishWorkflows) {
console.log(`CircleCI release workflow request for ${job} successful. Check ${workFlowUrl} for status.`)
} else {
console.log(`CircleCI release build workflow running at https://circleci.com/workflow-run/${workflowId} for ${job}.`)
const jobNumber = await getCircleCIJobNumber(workflowId)
if (jobNumber === -1) {
return
}
const jobUrl = `https://circleci.com/gh/electron/electron/${jobNumber}`
console.log(`CircleCI release build request for ${job} successful. Check ${jobUrl} for status.`)
}
const jobUrl = `https://circleci.com/gh/electron/electron/${jobNumber}`
console.log(`CircleCI release build request for ${job} successful. Check ${jobUrl} for status.`)
} catch (err) {
console.log('Error calling CircleCI: ', err)
}
@@ -232,7 +242,8 @@ function buildCircleCI (targetBranch, options) {
assert(circleCIJobs.includes(options.job), `Unknown CircleCI job name: ${options.job}. Valid values are: ${circleCIJobs}.`)
circleCIcall(targetBranch, options.job, options)
} else {
circleCIJobs.forEach((job) => circleCIcall(targetBranch, job, options))
options.runningPublishWorkflows = true
circleCIPublishWorkflows.forEach((job) => circleCIcall(targetBranch, job, options))
}
}

View File

@@ -50,7 +50,8 @@ powershell -command "& { iwr %buildtools_link% -OutFile C:\TEMP\vs_buildtools.ex
REM Install Visual Studio Toolchain
C:\TEMP\vs_buildtools.exe --quiet --wait --norestart --nocache ^
--installPath "%ProgramFiles(x86)%/Microsoft Visual Studio/2019/Community" ^
--add Microsoft.VisualStudio.Workload.NativeDesktop ^
--add Microsoft.VisualStudio.Workload.VCTools ^
--add Microsoft.VisualStudio.Component.VC.140 ^
--add Microsoft.VisualStudio.Component.VC.ATLMFC ^
--add Microsoft.VisualStudio.Component.VC.Tools.ARM64 ^
--add Microsoft.VisualStudio.Component.VC.MFC.ARM64 ^
@@ -69,14 +70,12 @@ set chocolateyUseWindowsCompression='true'
SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin"
REM Install nodejs python git and yarn needed dependencies
choco install -y nodejs python2 git yarn vcredist140 windows-sdk-10-version-1903-windbg
cmd /c refreshenv
choco install -y nodejs python2 git yarn windows-sdk-10-version-1903-windbg
cmd /c C:\ProgramData\chocolatey\bin\RefreshEnv.cmd
SET PATH=C:\Python27\;C:\Python27\Scripts;%PATH%
pip install pywin32
rename C:\Python38\python.exe python3.exe
rename C:\Python38\pythonw.exe pythonw3.exe
cmd /c refreshenv
cmd /c C:\ProgramData\chocolatey\bin\RefreshEnv.cmd
pip2 install pywin32
REM Setup Depot Tools

View File

@@ -35,9 +35,8 @@ const NPX_CMD = process.platform === 'win32' ? 'npx.cmd' : 'npx'
const runners = new Map([
['main', { description: 'Main process specs', run: runMainProcessElectronTests }],
['remote', { description: 'Remote based specs', run: runRemoteBasedElectronTests }]
// TODO(codebytere): refactor native tests to only depend on what we need
/* ['native', { description: 'Native specs', run: runNativeElectronTests }] */
['remote', { description: 'Remote based specs', run: runRemoteBasedElectronTests }],
['native', { description: 'Native specs', run: runNativeElectronTests }]
])
const specHashPath = path.resolve(__dirname, '../spec/.hash')

View File

@@ -1,7 +1,6 @@
param([string]$gomaDir=$PWD)
$cmdPath = Join-Path -Path $gomaDir -ChildPath "goma_ctl.py"
Start-Process -FilePath cmd -ArgumentList "/C", "python", "$cmdPath", "ensure_start"
$env:GLOG_logtostderr = "true"
$timedOut = $false; $waitTime = 0; $waitIncrement = 5; $timeout=120;
Do { sleep $waitIncrement; $timedOut = (($waitTime+=$waitIncrement) -gt $timeout); iex "$gomaDir\gomacc.exe port 2" > $null; } Until(($LASTEXITCODE -eq 0) -or $timedOut)
if ($timedOut) {

View File

@@ -4,7 +4,7 @@ import argparse
import os
import sys
from lib.config import LINUX_BINARIES
from lib.config import LINUX_BINARIES, enable_verbose_mode
from lib.util import execute, get_out_dir
def strip_binaries(directory, target_cpu):
@@ -22,10 +22,12 @@ def strip_binary(binary_path, target_cpu):
strip = 'mips64el-redhat-linux-strip'
else:
strip = 'strip'
execute([strip, binary_path])
execute([strip, '--preserve-dates', binary_path])
def main():
args = parse_args()
if args.verbose:
enable_verbose_mode()
if args.file:
strip_binary(args.file, args.target_cpu)
else:

View File

@@ -33,12 +33,13 @@
#endif // defined(WIDEVINE_CDM_AVAILABLE)
#if BUILDFLAG(ENABLE_PDF_VIEWER)
#include "pdf/pdf.h" // nogncheck
#include "pdf/pdf_ppapi.h" // nogncheck
#include "shell/common/electron_constants.h" // nogncheck
#endif // BUILDFLAG(ENABLE_PDF_VIEWER)
#include "pdf/pdf.h" // nogncheck
#include "pdf/pdf_ppapi.h" // nogncheck
#include "shell/common/electron_constants.h"
#endif // BUILDFLAG(ENABLE_PDF_VIEWER)
#if BUILDFLAG(ENABLE_PLUGINS)
#include "content/public/browser/plugin_service.h"
#include "content/public/common/pepper_plugin_info.h"
#include "ppapi/shared_impl/ppapi_permissions.h"
#endif // BUILDFLAG(ENABLE_PLUGINS)
@@ -155,7 +156,8 @@ void ComputeBuiltInPlugins(std::vector<content::PepperPluginInfo>* plugins) {
pdf_info.is_out_of_process = true;
pdf_info.name = "Chromium PDF Viewer";
pdf_info.description = "Portable Document Format";
pdf_info.path = base::FilePath(FILE_PATH_LITERAL("internal-pdf-viewer"));
// This isn't a real file path; it's just used as a unique identifier.
pdf_info.path = base::FilePath(kPdfPluginPath);
content::WebPluginMimeType pdf_mime_type(kPdfPluginMimeType, "pdf",
"Portable Document Format");
pdf_info.mime_types.push_back(pdf_mime_type);
@@ -166,6 +168,21 @@ void ComputeBuiltInPlugins(std::vector<content::PepperPluginInfo>* plugins) {
chrome_pdf::PPP_ShutdownModule;
pdf_info.permissions = ppapi::PERMISSION_PDF | ppapi::PERMISSION_DEV;
plugins->push_back(pdf_info);
// NB. in Chrome, this plugin isn't registered until the PDF extension is
// loaded. However, in Electron, we load the PDF extension unconditionally
// when it is enabled in the build, so we're OK to load the plugin eagerly
// here.
content::WebPluginInfo info;
info.type = content::WebPluginInfo::PLUGIN_TYPE_BROWSER_PLUGIN;
info.name = base::UTF8ToUTF16("Chromium PDF Viewer");
// This isn't a real file path; it's just used as a unique identifier.
info.path = base::FilePath::FromUTF8Unsafe(extension_misc::kPdfExtensionId);
info.background_color = content::WebPluginInfo::kDefaultBackgroundColor;
info.mime_types.emplace_back("application/pdf", "pdf",
"Portable Document Format");
content::PluginService::GetInstance()->RefreshPlugins();
content::PluginService::GetInstance()->RegisterInternalPlugin(info, true);
#endif // BUILDFLAG(ENABLE_PDF_VIEWER)
}
#endif // BUILDFLAG(ENABLE_PLUGINS)

View File

@@ -118,15 +118,6 @@ void LoadResourceBundle(const std::string& locale) {
bundle.ReloadLocaleResources(locale);
bundle.AddDataPackFromPath(pak_dir.Append(FILE_PATH_LITERAL("resources.pak")),
ui::SCALE_FACTOR_NONE);
#if BUILDFLAG(ENABLE_PDF_VIEWER)
NOTIMPLEMENTED()
<< "Hi, whoever's fixing PDF support! Thanks! The pdf "
"viewer resources haven't been ported over to the GN build yet, so "
"you'll probably need to change this bit of code.";
bundle.AddDataPackFromPath(
pak_dir.Append(FILE_PATH_LITERAL("pdf_viewer_resources.pak")),
ui::GetSupportedScaleFactors()[0]);
#endif // BUILDFLAG(ENABLE_PDF_VIEWER)
}
ElectronMainDelegate::ElectronMainDelegate() = default;

View File

@@ -6,10 +6,14 @@
#include <memory>
#include <string>
#include <unordered_set>
#include <utility>
#include <vector>
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/thread_pool/thread_pool_instance.h"
#include "base/threading/thread_task_runner_handle.h"
#include "electron/electron_version.h"
@@ -29,6 +33,49 @@
#include "shell/common/crash_reporter/crash_reporter_win.h"
#endif
namespace {
// Initialize Node.js cli options to pass to Node.js
// See https://nodejs.org/api/cli.html#cli_options
void SetNodeCliFlags() {
// Options that are unilaterally disallowed
const std::unordered_set<base::StringPiece, base::StringPieceHash>
disallowed = {"--openssl-config", "--use-bundled-ca", "--use-openssl-ca",
"--force-fips", "--enable-fips"};
const auto argv = base::CommandLine::ForCurrentProcess()->argv();
std::vector<std::string> args;
// TODO(codebytere): We need to set the first entry in args to the
// process name owing to src/node_options-inl.h#L286-L290 but this is
// redundant and so should be refactored upstream.
args.reserve(argv.size() + 1);
args.emplace_back("electron");
for (const auto& arg : argv) {
#if defined(OS_WIN)
const auto& option = base::UTF16ToUTF8(arg);
#else
const auto& option = arg;
#endif
const auto stripped = base::StringPiece(option).substr(0, option.find('='));
if (disallowed.count(stripped) != 0) {
LOG(ERROR) << "The Node.js cli flag " << stripped
<< " is not supported in Electron";
} else {
args.push_back(option);
}
}
std::vector<std::string> errors;
// Node.js itself will output parsing errors to
// console so we don't need to handle that ourselves
ProcessGlobalArgs(&args, nullptr, &errors, node::kDisallowedInEnvironment);
}
} // namespace
namespace electron {
#if !defined(OS_LINUX)
@@ -64,6 +111,9 @@ int NodeMain(int argc, char* argv[]) {
// Explicitly register electron's builtin modules.
NodeBindings::RegisterBuiltinModules();
// Parse and set Node.js cli flags.
SetNodeCliFlags();
int exec_argc;
const char** exec_argv;
node::Init(&argc, const_cast<const char**>(argv), &exec_argc, &exec_argv);

View File

@@ -222,6 +222,31 @@ void BrowserWindow::OnDraggableRegionsUpdated(
UpdateDraggableRegions(regions);
}
void BrowserWindow::OnSetContentBounds(const gfx::Rect& rect) {
// window.resizeTo(...)
// window.moveTo(...)
window()->SetBounds(rect, false);
}
void BrowserWindow::OnActivateContents() {
// Hide the auto-hide menu when webContents is focused.
#if !defined(OS_MACOSX)
if (IsMenuBarAutoHide() && IsMenuBarVisible())
window()->SetMenuBarVisibility(false);
#endif
}
void BrowserWindow::OnPageTitleUpdated(const base::string16& title,
bool explicit_set) {
// Change window title to page title.
auto self = GetWeakPtr();
if (!Emit("page-title-updated", title, explicit_set)) {
// |this| might be deleted, or marked as destroyed by close().
if (self && !IsDestroyed())
SetTitle(base::UTF16ToUTF8(title));
}
}
void BrowserWindow::RequestPreferredWidth(int* width) {
*width = web_contents()->GetPreferredSize().width();
}
@@ -251,6 +276,8 @@ void BrowserWindow::OnCloseButtonClicked(bool* prevent_default) {
void BrowserWindow::OnWindowClosed() {
Cleanup();
// See TopLevelWindow::OnWindowClosed on why calling InvalidateWeakPtrs.
weak_factory_.InvalidateWeakPtrs();
TopLevelWindow::OnWindowClosed();
}

View File

@@ -57,6 +57,10 @@ class BrowserWindow : public TopLevelWindow,
void OnRendererResponsive() override;
void OnDraggableRegionsUpdated(
const std::vector<mojom::DraggableRegionPtr>& regions) override;
void OnSetContentBounds(const gfx::Rect& rect) override;
void OnActivateContents() override;
void OnPageTitleUpdated(const base::string16& title,
bool explicit_set) override;
// NativeWindowObserver:
void RequestPreferredWidth(int* width) override;

View File

@@ -7,6 +7,7 @@
#include <algorithm>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>
@@ -226,6 +227,42 @@ void DestroyGlobalHandle(v8::Isolate* isolate,
}
}
class DictionaryObserver final : public SpellcheckCustomDictionary::Observer {
private:
std::unique_ptr<gin_helper::Promise<std::set<std::string>>> promise_;
base::WeakPtr<SpellcheckService> spellcheck_;
public:
DictionaryObserver(gin_helper::Promise<std::set<std::string>> promise,
base::WeakPtr<SpellcheckService> spellcheck)
: spellcheck_(spellcheck) {
promise_ = std::make_unique<gin_helper::Promise<std::set<std::string>>>(
std::move(promise));
if (spellcheck_)
spellcheck_->GetCustomDictionary()->AddObserver(this);
}
~DictionaryObserver() {
if (spellcheck_)
spellcheck_->GetCustomDictionary()->RemoveObserver(this);
}
void OnCustomDictionaryLoaded() override {
if (spellcheck_) {
promise_->Resolve(spellcheck_->GetCustomDictionary()->GetWords());
} else {
promise_->RejectWithErrorMessage(
"Spellcheck in unexpected state: failed to load custom dictionary.");
}
delete this;
}
void OnCustomDictionaryChanged(
const SpellcheckCustomDictionary::Change& dictionary_change) override {
// noop
}
};
} // namespace
Session::Session(v8::Isolate* isolate, ElectronBrowserContext* browser_context)
@@ -613,6 +650,11 @@ v8::Local<v8::Promise> Session::LoadExtension(
const base::FilePath& extension_path) {
gin_helper::Promise<const extensions::Extension*> promise(isolate());
v8::Local<v8::Promise> handle = promise.GetHandle();
if (browser_context()->IsOffTheRecord()) {
promise.RejectWithErrorMessage(
"Extensions cannot be loaded in a temporary session");
return handle;
}
auto* extension_system = static_cast<extensions::ElectronExtensionSystem*>(
extensions::ExtensionSystem::Get(browser_context()));
@@ -660,7 +702,8 @@ v8::Local<v8::Value> Session::GetAllExtensions() {
auto installed_extensions = registry->GenerateInstalledExtensionsSet();
std::vector<const extensions::Extension*> extensions_vector;
for (const auto& extension : *installed_extensions) {
extensions_vector.emplace_back(extension.get());
if (extension->location() != extensions::Manifest::COMPONENT)
extensions_vector.emplace_back(extension.get());
}
return gin::ConvertToV8(isolate(), extensions_vector);
}
@@ -766,6 +809,29 @@ void SetSpellCheckerDictionaryDownloadURL(gin_helper::ErrorThrower thrower,
SpellcheckHunspellDictionary::SetDownloadURLForTesting(url);
}
v8::Local<v8::Promise> Session::ListWordsInSpellCheckerDictionary() {
gin_helper::Promise<std::set<std::string>> promise(isolate());
v8::Local<v8::Promise> handle = promise.GetHandle();
SpellcheckService* spellcheck =
SpellcheckServiceFactory::GetForContext(browser_context_.get());
if (!spellcheck)
promise.RejectWithErrorMessage(
"Spellcheck in unexpected state: failed to load custom dictionary.");
if (spellcheck->GetCustomDictionary()->IsLoaded()) {
promise.Resolve(spellcheck->GetCustomDictionary()->GetWords());
} else {
new DictionaryObserver(std::move(promise), spellcheck->GetWeakPtr());
// Dictionary loads by default asynchronously,
// call the load function anyways just to be sure.
spellcheck->GetCustomDictionary()->Load();
}
return handle;
}
bool Session::AddWordToSpellCheckerDictionary(const std::string& word) {
SpellcheckService* service =
SpellcheckServiceFactory::GetForContext(browser_context_.get());
@@ -780,6 +846,21 @@ bool Session::AddWordToSpellCheckerDictionary(const std::string& word) {
#endif
return service->GetCustomDictionary()->AddWord(word);
}
bool Session::RemoveWordFromSpellCheckerDictionary(const std::string& word) {
SpellcheckService* service =
SpellcheckServiceFactory::GetForContext(browser_context_.get());
if (!service)
return false;
#if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
if (spellcheck::UseBrowserSpellChecker()) {
spellcheck_platform::RemoveWord(service->platform_spell_checker(),
base::UTF8ToUTF16(word));
}
#endif
return service->GetCustomDictionary()->RemoveWord(word);
}
#endif
// static
@@ -866,8 +947,12 @@ void Session::BuildPrototype(v8::Isolate* isolate,
&spellcheck::SpellCheckLanguages)
.SetMethod("setSpellCheckerDictionaryDownloadURL",
&SetSpellCheckerDictionaryDownloadURL)
.SetMethod("listWordsInSpellCheckerDictionary",
&Session::ListWordsInSpellCheckerDictionary)
.SetMethod("addWordToSpellCheckerDictionary",
&Session::AddWordToSpellCheckerDictionary)
.SetMethod("removeWordFromSpellCheckerDictionary",
&Session::RemoveWordFromSpellCheckerDictionary)
#endif
.SetMethod("preconnect", &Session::Preconnect)
.SetProperty("cookies", &Session::Cookies)

View File

@@ -95,7 +95,9 @@ class Session : public gin_helper::TrackableObject<Session>,
base::Value GetSpellCheckerLanguages();
void SetSpellCheckerLanguages(gin_helper::ErrorThrower thrower,
const std::vector<std::string>& languages);
v8::Local<v8::Promise> ListWordsInSpellCheckerDictionary();
bool AddWordToSpellCheckerDictionary(const std::string& word);
bool RemoveWordFromSpellCheckerDictionary(const std::string& word);
#endif
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)

View File

@@ -99,8 +99,6 @@ class SystemPreferences : public gin_helper::EventEmitter<SystemPreferences>
static bool IsTrustedAccessibilityClient(bool prompt);
// TODO(codebytere): Write tests for these methods once we
// are running tests on a Mojave machine
std::string GetMediaAccessStatus(const std::string& media_type,
gin_helper::Arguments* args);
v8::Local<v8::Promise> AskForMediaAccess(v8::Isolate* isolate,

View File

@@ -120,6 +120,9 @@ TopLevelWindow::~TopLevelWindow() {
// Destroy the native window in next tick because the native code might be
// iterating all windows.
base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, window_.release());
// Remove global reference so the JS object can be garbage collected.
self_ref_.Reset();
}
void TopLevelWindow::InitWith(v8::Isolate* isolate,
@@ -135,6 +138,9 @@ void TopLevelWindow::InitWith(v8::Isolate* isolate,
DCHECK(!parent.IsEmpty());
parent->child_windows_.Set(isolate, weak_map_id(), wrapper);
}
// Reference this object in case it got garbage collected.
self_ref_.Reset(isolate, wrapper);
}
void TopLevelWindow::WillCloseWindow(bool* prevent_default) {

View File

@@ -259,6 +259,9 @@ class TopLevelWindow : public gin_helper::TrackableObject<TopLevelWindow>,
std::unique_ptr<NativeWindow> window_;
// Reference to JS wrapper to prevent garbage collection.
v8::Global<v8::Value> self_ref_;
base::WeakPtrFactory<TopLevelWindow> weak_factory_;
};

View File

@@ -705,8 +705,9 @@ void WebContents::BeforeUnloadFired(content::WebContents* tab,
}
void WebContents::SetContentsBounds(content::WebContents* source,
const gfx::Rect& pos) {
Emit("move", pos);
const gfx::Rect& rect) {
for (ExtendedWebContentsObserver& observer : observers_)
observer.OnSetContentBounds(rect);
}
void WebContents::CloseContents(content::WebContents* source) {
@@ -725,7 +726,8 @@ void WebContents::CloseContents(content::WebContents* source) {
}
void WebContents::ActivateContents(content::WebContents* source) {
Emit("activate");
for (ExtendedWebContentsObserver& observer : observers_)
observer.OnActivateContents();
}
void WebContents::UpdateTargetURL(content::WebContents* source,
@@ -1228,6 +1230,8 @@ void WebContents::TitleWasSet(content::NavigationEntry* entry) {
final_title = title;
}
}
for (ExtendedWebContentsObserver& observer : observers_)
observer.OnPageTitleUpdated(final_title, explicit_set);
Emit("page-title-updated", final_title, explicit_set);
}

View File

@@ -81,6 +81,10 @@ class ExtendedWebContentsObserver : public base::CheckedObserver {
virtual void OnRendererResponsive() {}
virtual void OnDraggableRegionsUpdated(
const std::vector<mojom::DraggableRegionPtr>& regions) {}
virtual void OnSetContentBounds(const gfx::Rect& rect) {}
virtual void OnActivateContents() {}
virtual void OnPageTitleUpdated(const base::string16& title,
bool explicit_set) {}
protected:
~ExtendedWebContentsObserver() override {}

View File

@@ -13,7 +13,7 @@
#include "gin/arguments.h"
#include "gin/handle.h"
#include "gin/wrappable.h"
#include "shell/browser/net/proxying_url_loader_factory.h"
#include "shell/browser/net/web_request_api_interface.h"
namespace content {
class BrowserContext;
@@ -49,10 +49,6 @@ class WebRequest : public gin::Wrappable<WebRequest>, public WebRequestAPI {
v8::Isolate* isolate) override;
const char* GetTypeName() override;
private:
WebRequest(v8::Isolate* isolate, content::BrowserContext* browser_context);
~WebRequest() override;
// WebRequestAPI:
bool HasListener() const override;
int OnBeforeRequest(extensions::WebRequestInfo* info,
@@ -86,6 +82,10 @@ class WebRequest : public gin::Wrappable<WebRequest>, public WebRequestAPI {
int net_error) override;
void OnRequestWillBeDestroyed(extensions::WebRequestInfo* info) override;
private:
WebRequest(v8::Isolate* isolate, content::BrowserContext* browser_context);
~WebRequest() override;
enum SimpleEvent {
kOnSendHeaders,
kOnBeforeRedirect,

View File

@@ -49,6 +49,7 @@
#include "extensions/common/constants.h"
#include "net/base/escape.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "ppapi/buildflags/buildflags.h"
#include "ppapi/host/ppapi_host.h"
#include "printing/buildflags/buildflags.h"
#include "services/device/public/cpp/geolocation/location_provider.h"
@@ -75,6 +76,7 @@
#include "shell/browser/net/network_context_service.h"
#include "shell/browser/net/network_context_service_factory.h"
#include "shell/browser/net/proxying_url_loader_factory.h"
#include "shell/browser/net/proxying_websocket.h"
#include "shell/browser/net/system_network_context_manager.h"
#include "shell/browser/network_hints_handler_impl.h"
#include "shell/browser/notifications/notification_presenter.h"
@@ -128,13 +130,29 @@
#endif // BUILDFLAG(ENABLE_PRINTING)
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
#include "chrome/common/webui_url_constants.h"
#include "content/public/browser/child_process_security_policy.h"
#include "content/public/browser/file_url_loader.h"
#include "content/public/browser/web_ui_url_loader_factory.h"
#include "extensions/browser/api/mime_handler_private/mime_handler_private.h"
#include "extensions/browser/extension_host.h"
#include "extensions/browser/extension_message_filter.h"
#include "extensions/browser/extension_navigation_throttle.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/guest_view/extensions_guest_view_message_filter.h"
#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
#include "extensions/browser/info_map.h"
#include "extensions/browser/process_manager.h"
#include "extensions/browser/process_map.h"
#include "extensions/common/api/mime_handler.mojom.h"
#include "extensions/common/extension.h"
#include "shell/browser/extensions/electron_extension_system.h"
#include "shell/browser/extensions/electron_extension_web_contents_observer.h"
#endif
#if BUILDFLAG(ENABLE_PLUGINS)
#include "chrome/browser/plugins/plugin_response_interceptor_url_loader_throttle.h" // nogncheck
#include "shell/browser/plugins/plugin_utils.h"
#endif
#if defined(OS_MACOSX)
@@ -186,6 +204,63 @@ const base::FilePath::StringPieceType kPathDelimiter = FILE_PATH_LITERAL(";");
const base::FilePath::StringPieceType kPathDelimiter = FILE_PATH_LITERAL(":");
#endif
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
// Used by the GetPrivilegeRequiredByUrl() and GetProcessPrivilege() functions
// below. Extension, and isolated apps require different privileges to be
// granted to their RenderProcessHosts. This classification allows us to make
// sure URLs are served by hosts with the right set of privileges.
enum RenderProcessHostPrivilege {
PRIV_NORMAL,
PRIV_HOSTED,
PRIV_ISOLATED,
PRIV_EXTENSION,
};
RenderProcessHostPrivilege GetPrivilegeRequiredByUrl(
const GURL& url,
extensions::ExtensionRegistry* registry) {
// Default to a normal renderer cause it is lower privileged. This should only
// occur if the URL on a site instance is either malformed, or uninitialized.
// If it is malformed, then there is no need for better privileges anyways.
// If it is uninitialized, but eventually settles on being an a scheme other
// than normal webrenderer, the navigation logic will correct us out of band
// anyways.
if (!url.is_valid())
return PRIV_NORMAL;
if (!url.SchemeIs(extensions::kExtensionScheme))
return PRIV_NORMAL;
return PRIV_EXTENSION;
}
RenderProcessHostPrivilege GetProcessPrivilege(
content::RenderProcessHost* process_host,
extensions::ProcessMap* process_map,
extensions::ExtensionRegistry* registry) {
std::set<std::string> extension_ids =
process_map->GetExtensionsInProcess(process_host->GetID());
if (extension_ids.empty())
return PRIV_NORMAL;
return PRIV_EXTENSION;
}
const extensions::Extension* GetEnabledExtensionFromEffectiveURL(
content::BrowserContext* context,
const GURL& effective_url) {
if (!effective_url.SchemeIs(extensions::kExtensionScheme))
return nullptr;
extensions::ExtensionRegistry* registry =
extensions::ExtensionRegistry::Get(context);
if (!registry)
return nullptr;
return registry->enabled_extensions().GetByID(effective_url.host());
}
#endif // BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
} // namespace
// static
@@ -385,6 +460,8 @@ void ElectronBrowserClient::RenderProcessWillLaunch(
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
host->AddFilter(
new extensions::ExtensionMessageFilter(process_id, browser_context));
host->AddFilter(new extensions::ExtensionsGuestViewMessageFilter(
process_id, browser_context));
#endif
ProcessPreferences prefs;
@@ -727,6 +804,7 @@ void ElectronBrowserClient::GetAdditionalAllowedSchemesForFileSystem(
additional_schemes->insert(additional_schemes->end(), schemes_list.begin(),
schemes_list.end());
additional_schemes->push_back(content::kChromeDevToolsScheme);
additional_schemes->push_back(content::kChromeUIScheme);
}
void ElectronBrowserClient::GetAdditionalWebUISchemes(
@@ -760,6 +838,40 @@ void ElectronBrowserClient::SiteInstanceGotProcess(
#endif // BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
}
bool ElectronBrowserClient::IsSuitableHost(
content::RenderProcessHost* process_host,
const GURL& site_url) {
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
auto* browser_context = process_host->GetBrowserContext();
extensions::ExtensionRegistry* registry =
extensions::ExtensionRegistry::Get(browser_context);
extensions::ProcessMap* process_map =
extensions::ProcessMap::Get(browser_context);
// Otherwise, just make sure the process privilege matches the privilege
// required by the site.
RenderProcessHostPrivilege privilege_required =
GetPrivilegeRequiredByUrl(site_url, registry);
return GetProcessPrivilege(process_host, process_map, registry) ==
privilege_required;
#else
return content::ContentBrowserClient::IsSuitableHost(process_host, site_url);
#endif
}
bool ElectronBrowserClient::ShouldUseProcessPerSite(
content::BrowserContext* browser_context,
const GURL& effective_url) {
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
const extensions::Extension* extension =
GetEnabledExtensionFromEffectiveURL(browser_context, effective_url);
return extension != nullptr;
#else
return content::ContentBrowserClient::ShouldUseProcessPerSite(browser_context,
effective_url);
#endif
}
void ElectronBrowserClient::SiteInstanceDeleting(
content::SiteInstance* site_instance) {
// We are storing weak_ptr, is it fundamental to maintain the map up-to-date
@@ -1052,28 +1164,160 @@ void ElectronBrowserClient::RegisterNonNetworkNavigationURLLoaderFactories(
protocol->RegisterURLLoaderFactories(factories);
}
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
namespace {
// The FileURLLoaderFactory provided to the extension background pages.
// Checks with the ChildProcessSecurityPolicy to validate the file access.
class FileURLLoaderFactory : public network::mojom::URLLoaderFactory {
public:
explicit FileURLLoaderFactory(int child_id) : child_id_(child_id) {}
private:
// network::mojom::URLLoaderFactory:
void CreateLoaderAndStart(
mojo::PendingReceiver<network::mojom::URLLoader> loader,
int32_t routing_id,
int32_t request_id,
uint32_t options,
const network::ResourceRequest& request,
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation)
override {
if (!content::ChildProcessSecurityPolicy::GetInstance()->CanRequestURL(
child_id_, request.url)) {
mojo::Remote<network::mojom::URLLoaderClient>(std::move(client))
->OnComplete(
network::URLLoaderCompletionStatus(net::ERR_ACCESS_DENIED));
return;
}
content::CreateFileURLLoaderBypassingSecurityChecks(
request, std::move(loader), std::move(client),
/*observer=*/nullptr,
/* allow_directory_listing */ true);
}
void Clone(
mojo::PendingReceiver<network::mojom::URLLoaderFactory> loader) override {
receivers_.Add(this, std::move(loader));
}
int child_id_;
mojo::ReceiverSet<network::mojom::URLLoaderFactory> receivers_;
DISALLOW_COPY_AND_ASSIGN(FileURLLoaderFactory);
};
} // namespace
#endif // BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
void ElectronBrowserClient::RegisterNonNetworkSubresourceURLLoaderFactories(
int render_process_id,
int render_frame_id,
NonNetworkURLLoaderFactoryMap* factories) {
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
auto factory = extensions::CreateExtensionURLLoaderFactory(render_process_id,
render_frame_id);
if (factory)
factories->emplace(extensions::kExtensionScheme, std::move(factory));
#endif
// Chromium may call this even when NetworkService is not enabled.
content::RenderFrameHost* frame_host =
content::RenderFrameHost::FromID(render_process_id, render_frame_id);
content::WebContents* web_contents =
content::WebContents::FromRenderFrameHost(frame_host);
if (web_contents) {
api::Protocol* protocol = api::Protocol::FromWrappedClass(
v8::Isolate::GetCurrent(), web_contents->GetBrowserContext());
if (protocol)
protocol->RegisterURLLoaderFactories(factories);
}
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
auto factory = extensions::CreateExtensionURLLoaderFactory(render_process_id,
render_frame_id);
if (factory)
factories->emplace(extensions::kExtensionScheme, std::move(factory));
if (!web_contents)
return;
extensions::ElectronExtensionWebContentsObserver* web_observer =
extensions::ElectronExtensionWebContentsObserver::FromWebContents(
web_contents);
// There is nothing to do if no ElectronExtensionWebContentsObserver is
// attached to the |web_contents|.
if (!web_observer)
return;
const extensions::Extension* extension =
web_observer->GetExtensionFromFrame(frame_host, false);
if (!extension)
return;
// Support for chrome:// scheme if appropriate.
if (extension->is_extension() &&
extensions::Manifest::IsComponentLocation(extension->location())) {
// Components of chrome that are implemented as extensions or platform apps
// are allowed to use chrome://resources/ and chrome://theme/ URLs.
factories->emplace(
content::kChromeUIScheme,
content::CreateWebUIURLLoader(frame_host, content::kChromeUIScheme,
{content::kChromeUIResourcesHost}));
}
// Extension with a background page get file access that gets approval from
// ChildProcessSecurityPolicy.
extensions::ExtensionHost* host =
extensions::ProcessManager::Get(web_contents->GetBrowserContext())
->GetBackgroundHostForExtension(extension->id());
if (host) {
factories->emplace(url::kFileScheme, std::make_unique<FileURLLoaderFactory>(
render_process_id));
}
#endif
}
bool ElectronBrowserClient::ShouldTreatURLSchemeAsFirstPartyWhenTopLevel(
base::StringPiece scheme,
bool is_embedded_origin_secure) {
if (is_embedded_origin_secure && scheme == content::kChromeUIScheme)
return true;
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
return scheme == extensions::kExtensionScheme;
#else
return false;
#endif
}
bool ElectronBrowserClient::WillInterceptWebSocket(
content::RenderFrameHost* frame) {
if (!frame)
return false;
v8::Isolate* isolate = v8::Isolate::GetCurrent();
auto* browser_context = frame->GetProcess()->GetBrowserContext();
auto web_request = api::WebRequest::FromOrCreate(isolate, browser_context);
// NOTE: Some unit test environments do not initialize
// BrowserContextKeyedAPI factories for e.g. WebRequest.
if (!web_request.get())
return false;
return web_request->HasListener();
}
void ElectronBrowserClient::CreateWebSocket(
content::RenderFrameHost* frame,
WebSocketFactory factory,
const GURL& url,
const net::SiteForCookies& site_for_cookies,
const base::Optional<std::string>& user_agent,
mojo::PendingRemote<network::mojom::WebSocketHandshakeClient>
handshake_client) {
v8::Isolate* isolate = v8::Isolate::GetCurrent();
auto* browser_context = frame->GetProcess()->GetBrowserContext();
auto web_request = api::WebRequest::FromOrCreate(isolate, browser_context);
DCHECK(web_request.get());
ProxyingWebSocket::StartProxying(
web_request.get(), std::move(factory), url,
site_for_cookies.RepresentativeUrl(), user_agent,
std::move(handshake_client), true, frame->GetProcess()->GetID(),
frame->GetRoutingID(), frame->GetLastCommittedOrigin(), browser_context,
&next_id_);
}
bool ElectronBrowserClient::WillCreateURLLoaderFactory(
@@ -1118,7 +1362,7 @@ bool ElectronBrowserClient::WillCreateURLLoaderFactory(
new ProxyingURLLoaderFactory(
web_request.get(), protocol->intercept_handlers(), browser_context,
render_process_id, std::move(navigation_ui_data),
render_process_id, &next_id_, std::move(navigation_ui_data),
std::move(navigation_id), std::move(proxied_receiver),
std::move(target_factory_remote), std::move(header_client_receiver),
type);
@@ -1202,11 +1446,31 @@ void ElectronBrowserClient::BindHostReceiverForRenderer(
#endif
}
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
void BindMimeHandlerService(
content::RenderFrameHost* frame_host,
mojo::PendingReceiver<extensions::mime_handler::MimeHandlerService>
receiver) {
content::WebContents* contents =
content::WebContents::FromRenderFrameHost(frame_host);
auto* guest_view =
extensions::MimeHandlerViewGuest::FromWebContents(contents);
if (!guest_view)
return;
extensions::MimeHandlerServiceImpl::Create(guest_view->GetStreamWeakPtr(),
std::move(receiver));
}
#endif
void ElectronBrowserClient::RegisterBrowserInterfaceBindersForFrame(
content::RenderFrameHost* render_frame_host,
service_manager::BinderMapWithContext<content::RenderFrameHost*>* map) {
map->Add<network_hints::mojom::NetworkHintsHandler>(
base::BindRepeating(&BindNetworkHintsHandler));
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
map->Add<extensions::mime_handler::MimeHandlerService>(
base::BindRepeating(&BindMimeHandlerService));
#endif
}
std::unique_ptr<content::LoginDelegate>
@@ -1224,4 +1488,35 @@ ElectronBrowserClient::CreateLoginDelegate(
first_auth_attempt, std::move(auth_required_callback));
}
std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
ElectronBrowserClient::CreateURLLoaderThrottles(
const network::ResourceRequest& request,
content::BrowserContext* browser_context,
const base::RepeatingCallback<content::WebContents*()>& wc_getter,
content::NavigationUIData* navigation_ui_data,
int frame_tree_node_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
std::vector<std::unique_ptr<blink::URLLoaderThrottle>> result;
#if BUILDFLAG(ENABLE_PLUGINS) && BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
result.push_back(std::make_unique<PluginResponseInterceptorURLLoaderThrottle>(
request.resource_type, frame_tree_node_id));
#endif
return result;
}
base::flat_set<std::string>
ElectronBrowserClient::GetPluginMimeTypesWithExternalHandlers(
content::BrowserContext* browser_context) {
base::flat_set<std::string> mime_types;
#if BUILDFLAG(ENABLE_PLUGINS) && BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
auto map = PluginUtils::GetMimeTypeToExtensionIdMap(browser_context);
for (const auto& pair : map)
mime_types.insert(pair.first);
#endif
return mime_types;
}
} // namespace electron

View File

@@ -173,6 +173,15 @@ class ElectronBrowserClient : public content::ContentBrowserClient,
int render_process_id,
int render_frame_id,
NonNetworkURLLoaderFactoryMap* factories) override;
void CreateWebSocket(
content::RenderFrameHost* frame,
WebSocketFactory factory,
const GURL& url,
const net::SiteForCookies& site_for_cookies,
const base::Optional<std::string>& user_agent,
mojo::PendingRemote<network::mojom::WebSocketHandshakeClient>
handshake_client) override;
bool WillInterceptWebSocket(content::RenderFrameHost*) override;
bool WillCreateURLLoaderFactory(
content::BrowserContext* browser_context,
content::RenderFrameHost* frame,
@@ -186,6 +195,9 @@ class ElectronBrowserClient : public content::ContentBrowserClient,
bool* bypass_redirect_checks,
bool* disable_secure_dns,
network::mojom::URLLoaderFactoryOverridePtr* factory_override) override;
bool ShouldTreatURLSchemeAsFirstPartyWhenTopLevel(
base::StringPiece scheme,
bool is_embedded_origin_secure) override;
void OverrideURLLoaderFactoryParams(
content::BrowserContext* browser_context,
const url::Origin& origin,
@@ -221,6 +233,19 @@ class ElectronBrowserClient : public content::ContentBrowserClient,
bool first_auth_attempt,
LoginAuthRequiredCallback auth_required_callback) override;
void SiteInstanceGotProcess(content::SiteInstance* site_instance) override;
std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
CreateURLLoaderThrottles(
const network::ResourceRequest& request,
content::BrowserContext* browser_context,
const base::RepeatingCallback<content::WebContents*()>& wc_getter,
content::NavigationUIData* navigation_ui_data,
int frame_tree_node_id) override;
base::flat_set<std::string> GetPluginMimeTypesWithExternalHandlers(
content::BrowserContext* browser_context) override;
bool IsSuitableHost(content::RenderProcessHost* process_host,
const GURL& site_url) override;
bool ShouldUseProcessPerSite(content::BrowserContext* browser_context,
const GURL& effective_url) override;
// content::RenderProcessHostObserver:
void RenderProcessHostDestroyed(content::RenderProcessHost* host) override;
@@ -286,6 +311,10 @@ class ElectronBrowserClient : public content::ContentBrowserClient,
bool disable_process_restart_tricks_ = false;
// Simple shared ID generator, used by ProxyingURLLoaderFactory and
// ProxyingWebSocket classes.
uint64_t next_id_ = 0;
DISALLOW_COPY_AND_ASSIGN(ElectronBrowserClient);
};

View File

@@ -0,0 +1,35 @@
# Copyright 2018 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//extensions/buildflags/buildflags.gni")
import("//tools/json_schema_compiler/json_schema_api.gni")
assert(enable_extensions,
"Cannot depend on extensions because enable_extensions=false.")
function_registration("api_registration") {
sources = [
"//electron/shell/common/extensions/api/extension.json",
"//electron/shell/common/extensions/api/resources_private.idl",
"//electron/shell/common/extensions/api/tabs.json",
]
impl_dir = "//electron/shell/browser/extensions/api"
configs = [ "//build/config:precompiled_headers" ]
bundle_name = "Electron"
root_namespace = "extensions::api::%(namespace)s"
schema_include_rules = "extensions/common/api:extensions::api::%(namespace)s"
deps = [
# Different APIs include headers from these targets.
"//components/zoom",
"//content/public/browser",
"//extensions/browser",
# Different APIs include some headers from chrome/common that in turn
# include generated headers from these targets.
# TODO(brettw) this should be made unnecessary if possible.
"//electron/shell/common/extensions/api",
]
deps += [ "//extensions/common/api" ]
}

View File

@@ -0,0 +1,113 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "shell/browser/extensions/api/resources_private/resources_private_api.h"
#include <memory>
#include <string>
#include <utility>
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/common/extensions/api/resources_private.h"
#include "chrome/grit/generated_resources.h"
#include "components/strings/grit/components_strings.h"
#include "components/zoom/page_zoom_constants.h"
#include "pdf/buildflags.h"
#include "printing/buildflags/buildflags.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/webui/web_ui_util.h"
#if BUILDFLAG(ENABLE_PDF)
#include "pdf/pdf_features.h"
#endif // BUILDFLAG(ENABLE_PDF)
// To add a new component to this API, simply:
// 1. Add your component to the Component enum in
// chrome/common/extensions/api/resources_private.idl
// 2. Create an AddStringsForMyComponent(base::DictionaryValue * dict) method.
// 3. Tie in that method to the switch statement in Run()
namespace extensions {
namespace {
void AddStringsForPdf(base::DictionaryValue* dict) {
#if BUILDFLAG(ENABLE_PDF)
static constexpr webui::LocalizedString kPdfResources[] = {
{"passwordDialogTitle", IDS_PDF_PASSWORD_DIALOG_TITLE},
{"passwordPrompt", IDS_PDF_NEED_PASSWORD},
{"passwordSubmit", IDS_PDF_PASSWORD_SUBMIT},
{"passwordInvalid", IDS_PDF_PASSWORD_INVALID},
{"pageLoading", IDS_PDF_PAGE_LOADING},
{"pageLoadFailed", IDS_PDF_PAGE_LOAD_FAILED},
{"errorDialogTitle", IDS_PDF_ERROR_DIALOG_TITLE},
{"pageReload", IDS_PDF_PAGE_RELOAD_BUTTON},
{"bookmarks", IDS_PDF_BOOKMARKS},
{"labelPageNumber", IDS_PDF_LABEL_PAGE_NUMBER},
{"tooltipRotateCW", IDS_PDF_TOOLTIP_ROTATE_CW},
{"tooltipDownload", IDS_PDF_TOOLTIP_DOWNLOAD},
{"tooltipPrint", IDS_PDF_TOOLTIP_PRINT},
{"tooltipFitToPage", IDS_PDF_TOOLTIP_FIT_PAGE},
{"tooltipFitToWidth", IDS_PDF_TOOLTIP_FIT_WIDTH},
{"tooltipZoomIn", IDS_PDF_TOOLTIP_ZOOM_IN},
{"tooltipZoomOut", IDS_PDF_TOOLTIP_ZOOM_OUT},
};
for (const auto& resource : kPdfResources)
dict->SetString(resource.name, l10n_util::GetStringUTF16(resource.id));
dict->SetString("presetZoomFactors", zoom::GetPresetZoomFactorsAsJSON());
#endif // BUILDFLAG(ENABLE_PDF)
}
void AddAdditionalDataForPdf(base::DictionaryValue* dict) {
#if BUILDFLAG(ENABLE_PDF)
dict->SetKey("pdfFormSaveEnabled",
base::Value(base::FeatureList::IsEnabled(
chrome_pdf::features::kSaveEditedPDFForm)));
dict->SetKey("pdfAnnotationsEnabled",
base::Value(base::FeatureList::IsEnabled(
chrome_pdf::features::kPDFAnnotations)));
// TODO(nornagon): enable printing once it works.
bool enable_printing = false;
dict->SetKey("printingEnabled", base::Value(enable_printing));
#endif // BUILDFLAG(ENABLE_PDF)
}
} // namespace
namespace get_strings = api::resources_private::GetStrings;
ResourcesPrivateGetStringsFunction::ResourcesPrivateGetStringsFunction() {}
ResourcesPrivateGetStringsFunction::~ResourcesPrivateGetStringsFunction() {}
ExtensionFunction::ResponseAction ResourcesPrivateGetStringsFunction::Run() {
std::unique_ptr<get_strings::Params> params(
get_strings::Params::Create(*args_));
auto dict = std::make_unique<base::DictionaryValue>();
api::resources_private::Component component = params->component;
switch (component) {
case api::resources_private::COMPONENT_PDF:
AddStringsForPdf(dict.get());
AddAdditionalDataForPdf(dict.get());
break;
case api::resources_private::COMPONENT_IDENTITY:
NOTREACHED();
break;
case api::resources_private::COMPONENT_NONE:
NOTREACHED();
break;
}
const std::string& app_locale = g_browser_process->GetApplicationLocale();
webui::SetLoadTimeDataDefaults(app_locale, dict.get());
return RespondNow(OneArgument(std::move(dict)));
}
} // namespace extensions

View File

@@ -0,0 +1,31 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SHELL_BROWSER_EXTENSIONS_API_RESOURCES_PRIVATE_RESOURCES_PRIVATE_API_H_
#define SHELL_BROWSER_EXTENSIONS_API_RESOURCES_PRIVATE_RESOURCES_PRIVATE_API_H_
#include "base/macros.h"
#include "extensions/browser/extension_function.h"
namespace extensions {
class ResourcesPrivateGetStringsFunction : public ExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("resourcesPrivate.getStrings",
RESOURCESPRIVATE_GETSTRINGS)
ResourcesPrivateGetStringsFunction();
protected:
~ResourcesPrivateGetStringsFunction() override;
// Override from ExtensionFunction:
ExtensionFunction::ResponseAction Run() override;
private:
DISALLOW_COPY_AND_ASSIGN(ResourcesPrivateGetStringsFunction);
};
} // namespace extensions
#endif // SHELL_BROWSER_EXTENSIONS_API_RESOURCES_PRIVATE_RESOURCES_PRIVATE_API_H_

View File

@@ -0,0 +1,74 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "electron/shell/browser/extensions/api/streams_private/streams_private_api.h"
#include <utility>
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/guest_view/mime_handler_view/mime_handler_stream_manager.h"
#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
#include "extensions/common/manifest_handlers/mime_types_handler.h"
#include "shell/browser/api/electron_api_web_contents.h"
namespace extensions {
void StreamsPrivateAPI::SendExecuteMimeTypeHandlerEvent(
const std::string& extension_id,
const std::string& view_id,
bool embedded,
int frame_tree_node_id,
int render_process_id,
int render_frame_id,
content::mojom::TransferrableURLLoaderPtr transferrable_loader,
const GURL& original_url) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
content::WebContents* web_contents = nullptr;
if (frame_tree_node_id != -1) {
web_contents =
content::WebContents::FromFrameTreeNodeId(frame_tree_node_id);
} else {
web_contents = content::WebContents::FromRenderFrameHost(
content::RenderFrameHost::FromID(render_process_id, render_frame_id));
}
if (!web_contents)
return;
auto* browser_context = web_contents->GetBrowserContext();
const extensions::Extension* extension =
extensions::ExtensionRegistry::Get(browser_context)
->enabled_extensions()
.GetByID(extension_id);
if (!extension)
return;
MimeTypesHandler* handler = MimeTypesHandler::GetHandler(extension);
if (!handler->HasPlugin())
return;
// If the mime handler uses MimeHandlerViewGuest, the MimeHandlerViewGuest
// will take ownership of the stream.
GURL handler_url(
extensions::Extension::GetBaseURLFromExtensionId(extension_id).spec() +
handler->handler_url());
int tab_id = -1;
auto* api_contents = electron::api::WebContents::FromWrappedClass(
v8::Isolate::GetCurrent(), web_contents);
if (api_contents)
tab_id = api_contents->ID();
std::unique_ptr<extensions::StreamContainer> stream_container(
new extensions::StreamContainer(
tab_id, embedded, handler_url, extension_id,
std::move(transferrable_loader), original_url));
extensions::MimeHandlerStreamManager::Get(browser_context)
->AddStream(view_id, std::move(stream_container), frame_tree_node_id,
render_process_id, render_frame_id);
}
} // namespace extensions

View File

@@ -0,0 +1,44 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SHELL_BROWSER_EXTENSIONS_API_STREAMS_PRIVATE_STREAMS_PRIVATE_API_H_
#define SHELL_BROWSER_EXTENSIONS_API_STREAMS_PRIVATE_STREAMS_PRIVATE_API_H_
#include <memory>
#include <string>
#include "base/macros.h"
#include "content/public/common/transferrable_url_loader.mojom.h"
namespace extensions {
// TODO(devlin): This is now only used for the MimeTypesHandler API. We should
// rename and move it to make that clear. https://crbug.com/890401.
class StreamsPrivateAPI {
public:
// Send the onExecuteMimeTypeHandler event to |extension_id|. If the viewer is
// being opened in a BrowserPlugin, specify a non-empty |view_id| of the
// plugin. |embedded| should be set to whether the document is embedded
// within another document. The |frame_tree_node_id| parameter is used for the
// top level plugins case. (PDF, etc). If this parameter has a valid value
// then it overrides the |render_process_id| and |render_frame_id| parameters.
// The |render_process_id| is the id of the renderer process. The
// |render_frame_id| is the routing id of the RenderFrameHost.
//
// If the network service is not enabled, |stream| is used; otherwise,
// |transferrable_loader| and |original_url| are used instead.
static void SendExecuteMimeTypeHandlerEvent(
const std::string& extension_id,
const std::string& view_id,
bool embedded,
int frame_tree_node_id,
int render_process_id,
int render_frame_id,
content::mojom::TransferrableURLLoaderPtr transferrable_loader,
const GURL& original_url);
};
} // namespace extensions
#endif // SHELL_BROWSER_EXTENSIONS_API_STREAMS_PRIVATE_STREAMS_PRIVATE_API_H_

View File

@@ -12,13 +12,48 @@
#include "extensions/common/manifest_constants.h"
#include "extensions/common/permissions/permissions_data.h"
#include "shell/browser/api/electron_api_web_contents.h"
#include "shell/browser/web_contents_zoom_controller.h"
#include "shell/common/extensions/api/tabs.h"
#include "third_party/blink/public/common/page/page_zoom.h"
using electron::WebContentsZoomController;
namespace extensions {
namespace tabs = api::tabs;
const char kFrameNotFoundError[] = "No frame with id * in tab *.";
const char kPerOriginOnlyInAutomaticError[] =
"Can only set scope to "
"\"per-origin\" in \"automatic\" mode.";
using api::extension_types::InjectDetails;
namespace {
void ZoomModeToZoomSettings(WebContentsZoomController::ZoomMode zoom_mode,
api::tabs::ZoomSettings* zoom_settings) {
DCHECK(zoom_settings);
switch (zoom_mode) {
case WebContentsZoomController::ZoomMode::DEFAULT:
zoom_settings->mode = api::tabs::ZOOM_SETTINGS_MODE_AUTOMATIC;
zoom_settings->scope = api::tabs::ZOOM_SETTINGS_SCOPE_PER_ORIGIN;
break;
case WebContentsZoomController::ZoomMode::ISOLATED:
zoom_settings->mode = api::tabs::ZOOM_SETTINGS_MODE_AUTOMATIC;
zoom_settings->scope = api::tabs::ZOOM_SETTINGS_SCOPE_PER_TAB;
break;
case WebContentsZoomController::ZoomMode::MANUAL:
zoom_settings->mode = api::tabs::ZOOM_SETTINGS_MODE_MANUAL;
zoom_settings->scope = api::tabs::ZOOM_SETTINGS_SCOPE_PER_TAB;
break;
case WebContentsZoomController::ZoomMode::DISABLED:
zoom_settings->mode = api::tabs::ZOOM_SETTINGS_MODE_DISABLED;
zoom_settings->scope = api::tabs::ZOOM_SETTINGS_SCOPE_PER_TAB;
break;
}
}
} // namespace
ExecuteCodeInTabFunction::ExecuteCodeInTabFunction() : execute_tab_id_(-1) {}
ExecuteCodeInTabFunction::~ExecuteCodeInTabFunction() {}
@@ -130,4 +165,149 @@ bool TabsExecuteScriptFunction::ShouldInsertCSS() const {
return false;
}
ExtensionFunction::ResponseAction TabsGetFunction::Run() {
std::unique_ptr<tabs::Get::Params> params(tabs::Get::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
int tab_id = params->tab_id;
auto* contents = electron::api::WebContents::FromWeakMapID(
v8::Isolate::GetCurrent(), tab_id);
if (!contents)
return RespondNow(Error("No such tab"));
tabs::Tab tab;
tab.id.reset(new int(tab_id));
// TODO(nornagon): in Chrome, the tab URL is only available to extensions
// that have the "tabs" (or "activeTab") permission. We should do the same
// permission check here.
tab.url = std::make_unique<std::string>(
contents->web_contents()->GetLastCommittedURL().spec());
return RespondNow(ArgumentList(tabs::Get::Results::Create(std::move(tab))));
}
ExtensionFunction::ResponseAction TabsSetZoomFunction::Run() {
std::unique_ptr<tabs::SetZoom::Params> params(
tabs::SetZoom::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
int tab_id = params->tab_id ? *params->tab_id : -1;
auto* contents = electron::api::WebContents::FromWeakMapID(
v8::Isolate::GetCurrent(), tab_id);
if (!contents)
return RespondNow(Error("No such tab"));
auto* web_contents = contents->web_contents();
GURL url(web_contents->GetVisibleURL());
std::string error;
if (extension()->permissions_data()->IsRestrictedUrl(url, &error))
return RespondNow(Error(error));
auto* zoom_controller = contents->GetZoomController();
double zoom_level =
params->zoom_factor > 0
? blink::PageZoomFactorToZoomLevel(params->zoom_factor)
: blink::PageZoomFactorToZoomLevel(
zoom_controller->GetDefaultZoomFactor());
zoom_controller->SetZoomLevel(zoom_level);
return RespondNow(NoArguments());
}
ExtensionFunction::ResponseAction TabsGetZoomFunction::Run() {
std::unique_ptr<tabs::GetZoom::Params> params(
tabs::GetZoom::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
int tab_id = params->tab_id ? *params->tab_id : -1;
auto* contents = electron::api::WebContents::FromWeakMapID(
v8::Isolate::GetCurrent(), tab_id);
if (!contents)
return RespondNow(Error("No such tab"));
double zoom_level = contents->GetZoomController()->GetZoomLevel();
double zoom_factor = blink::PageZoomLevelToZoomFactor(zoom_level);
return RespondNow(ArgumentList(tabs::GetZoom::Results::Create(zoom_factor)));
}
ExtensionFunction::ResponseAction TabsGetZoomSettingsFunction::Run() {
std::unique_ptr<tabs::GetZoomSettings::Params> params(
tabs::GetZoomSettings::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
int tab_id = params->tab_id ? *params->tab_id : -1;
auto* contents = electron::api::WebContents::FromWeakMapID(
v8::Isolate::GetCurrent(), tab_id);
if (!contents)
return RespondNow(Error("No such tab"));
auto* zoom_controller = contents->GetZoomController();
WebContentsZoomController::ZoomMode zoom_mode =
contents->GetZoomController()->zoom_mode();
api::tabs::ZoomSettings zoom_settings;
ZoomModeToZoomSettings(zoom_mode, &zoom_settings);
zoom_settings.default_zoom_factor.reset(
new double(blink::PageZoomLevelToZoomFactor(
zoom_controller->GetDefaultZoomLevel())));
return RespondNow(
ArgumentList(api::tabs::GetZoomSettings::Results::Create(zoom_settings)));
}
ExtensionFunction::ResponseAction TabsSetZoomSettingsFunction::Run() {
using api::tabs::ZoomSettings;
std::unique_ptr<tabs::SetZoomSettings::Params> params(
tabs::SetZoomSettings::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
int tab_id = params->tab_id ? *params->tab_id : -1;
auto* contents = electron::api::WebContents::FromWeakMapID(
v8::Isolate::GetCurrent(), tab_id);
if (!contents)
return RespondNow(Error("No such tab"));
std::string error;
GURL url(contents->web_contents()->GetVisibleURL());
if (extension()->permissions_data()->IsRestrictedUrl(url, &error))
return RespondNow(Error(error));
// "per-origin" scope is only available in "automatic" mode.
if (params->zoom_settings.scope == tabs::ZOOM_SETTINGS_SCOPE_PER_ORIGIN &&
params->zoom_settings.mode != tabs::ZOOM_SETTINGS_MODE_AUTOMATIC &&
params->zoom_settings.mode != tabs::ZOOM_SETTINGS_MODE_NONE) {
return RespondNow(Error(kPerOriginOnlyInAutomaticError));
}
// Determine the correct internal zoom mode to set |web_contents| to from the
// user-specified |zoom_settings|.
WebContentsZoomController::ZoomMode zoom_mode =
WebContentsZoomController::ZoomMode::DEFAULT;
switch (params->zoom_settings.mode) {
case tabs::ZOOM_SETTINGS_MODE_NONE:
case tabs::ZOOM_SETTINGS_MODE_AUTOMATIC:
switch (params->zoom_settings.scope) {
case tabs::ZOOM_SETTINGS_SCOPE_NONE:
case tabs::ZOOM_SETTINGS_SCOPE_PER_ORIGIN:
zoom_mode = WebContentsZoomController::ZoomMode::DEFAULT;
break;
case tabs::ZOOM_SETTINGS_SCOPE_PER_TAB:
zoom_mode = WebContentsZoomController::ZoomMode::ISOLATED;
}
break;
case tabs::ZOOM_SETTINGS_MODE_MANUAL:
zoom_mode = WebContentsZoomController::ZoomMode::MANUAL;
break;
case tabs::ZOOM_SETTINGS_MODE_DISABLED:
zoom_mode = WebContentsZoomController::ZoomMode::DISABLED;
}
contents->GetZoomController()->SetZoomMode(zoom_mode);
return RespondNow(NoArguments());
}
} // namespace extensions

View File

@@ -44,6 +44,48 @@ class TabsExecuteScriptFunction : public ExecuteCodeInTabFunction {
DECLARE_EXTENSION_FUNCTION("tabs.executeScript", TABS_EXECUTESCRIPT)
};
class TabsGetFunction : public ExtensionFunction {
~TabsGetFunction() override {}
ResponseAction Run() override;
DECLARE_EXTENSION_FUNCTION("tabs.get", TABS_GET)
};
class TabsSetZoomFunction : public ExtensionFunction {
private:
~TabsSetZoomFunction() override {}
ResponseAction Run() override;
DECLARE_EXTENSION_FUNCTION("tabs.setZoom", TABS_SETZOOM)
};
class TabsGetZoomFunction : public ExtensionFunction {
private:
~TabsGetZoomFunction() override {}
ResponseAction Run() override;
DECLARE_EXTENSION_FUNCTION("tabs.getZoom", TABS_GETZOOM)
};
class TabsSetZoomSettingsFunction : public ExtensionFunction {
private:
~TabsSetZoomSettingsFunction() override {}
ResponseAction Run() override;
DECLARE_EXTENSION_FUNCTION("tabs.setZoomSettings", TABS_SETZOOMSETTINGS)
};
class TabsGetZoomSettingsFunction : public ExtensionFunction {
private:
~TabsGetZoomSettingsFunction() override {}
ResponseAction Run() override;
DECLARE_EXTENSION_FUNCTION("tabs.getZoomSettings", TABS_GETZOOMSETTINGS)
};
} // namespace extensions
#endif // SHELL_BROWSER_EXTENSIONS_API_TABS_TABS_API_H_

View File

@@ -5,15 +5,12 @@
#include "shell/browser/extensions/electron_browser_context_keyed_service_factories.h"
#include "extensions/browser/updater/update_service_factory.h"
// #include "extensions/shell/browser/api/identity/identity_api.h"
#include "shell/browser/extensions/electron_extension_system_factory.h"
namespace extensions {
namespace electron {
void EnsureBrowserContextKeyedServiceFactoriesBuilt() {
// IdentityAPI::GetFactoryInstance();
// TODO(rockot): Remove this once UpdateService is supported across all
// extensions embedders (and namely chrome.)
UpdateServiceFactory::GetInstance();

View File

@@ -0,0 +1,89 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "shell/browser/extensions/electron_component_extension_resource_manager.h"
#include <string>
#include "base/logging.h"
#include "base/path_service.h"
#include "base/stl_util.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/grit/component_extension_resources_map.h"
namespace extensions {
ElectronComponentExtensionResourceManager::
ElectronComponentExtensionResourceManager() {
AddComponentResourceEntries(kComponentExtensionResources,
kComponentExtensionResourcesSize);
}
ElectronComponentExtensionResourceManager::
~ElectronComponentExtensionResourceManager() {}
bool ElectronComponentExtensionResourceManager::IsComponentExtensionResource(
const base::FilePath& extension_path,
const base::FilePath& resource_path,
int* resource_id) const {
base::FilePath directory_path = extension_path;
base::FilePath resources_dir;
base::FilePath relative_path;
if (!base::PathService::Get(chrome::DIR_RESOURCES, &resources_dir) ||
!resources_dir.AppendRelativePath(directory_path, &relative_path)) {
return false;
}
relative_path = relative_path.Append(resource_path);
relative_path = relative_path.NormalizePathSeparators();
auto entry = path_to_resource_id_.find(relative_path);
if (entry != path_to_resource_id_.end()) {
*resource_id = entry->second;
return true;
}
return false;
}
const ui::TemplateReplacements*
ElectronComponentExtensionResourceManager::GetTemplateReplacementsForExtension(
const std::string& extension_id) const {
auto it = extension_template_replacements_.find(extension_id);
if (it == extension_template_replacements_.end()) {
return nullptr;
}
return &it->second;
}
void ElectronComponentExtensionResourceManager::AddComponentResourceEntries(
const GritResourceMap* entries,
size_t size) {
base::FilePath gen_folder_path = base::FilePath().AppendASCII(
"@out_folder@/gen/chrome/browser/resources/");
gen_folder_path = gen_folder_path.NormalizePathSeparators();
for (size_t i = 0; i < size; ++i) {
base::FilePath resource_path =
base::FilePath().AppendASCII(entries[i].name);
resource_path = resource_path.NormalizePathSeparators();
if (!gen_folder_path.IsParent(resource_path)) {
DCHECK(!base::Contains(path_to_resource_id_, resource_path));
path_to_resource_id_[resource_path] = entries[i].value;
} else {
// If the resource is a generated file, strip the generated folder's path,
// so that it can be served from a normal URL (as if it were not
// generated).
base::FilePath effective_path =
base::FilePath().AppendASCII(resource_path.AsUTF8Unsafe().substr(
gen_folder_path.value().length()));
DCHECK(!base::Contains(path_to_resource_id_, effective_path));
path_to_resource_id_[effective_path] = entries[i].value;
}
}
}
} // namespace extensions

View File

@@ -0,0 +1,50 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SHELL_BROWSER_EXTENSIONS_ELECTRON_COMPONENT_EXTENSION_RESOURCE_MANAGER_H_
#define SHELL_BROWSER_EXTENSIONS_ELECTRON_COMPONENT_EXTENSION_RESOURCE_MANAGER_H_
#include <stddef.h>
#include <map>
#include <string>
#include "base/files/file_path.h"
#include "base/macros.h"
#include "extensions/browser/component_extension_resource_manager.h"
struct GritResourceMap;
namespace extensions {
class ElectronComponentExtensionResourceManager
: public ComponentExtensionResourceManager {
public:
ElectronComponentExtensionResourceManager();
~ElectronComponentExtensionResourceManager() override;
// Overridden from ComponentExtensionResourceManager:
bool IsComponentExtensionResource(const base::FilePath& extension_path,
const base::FilePath& resource_path,
int* resource_id) const override;
const ui::TemplateReplacements* GetTemplateReplacementsForExtension(
const std::string& extension_id) const override;
private:
void AddComponentResourceEntries(const GritResourceMap* entries, size_t size);
// A map from a resource path to the resource ID. Used by
// IsComponentExtensionResource.
std::map<base::FilePath, int> path_to_resource_id_;
// A map from an extension ID to its i18n template replacements.
std::map<std::string, ui::TemplateReplacements>
extension_template_replacements_;
DISALLOW_COPY_AND_ASSIGN(ElectronComponentExtensionResourceManager);
};
} // namespace extensions
#endif // SHELL_BROWSER_EXTENSIONS_ELECTRON_COMPONENT_EXTENSION_RESOURCE_MANAGER_H_

View File

@@ -49,6 +49,8 @@ class ElectronExtensionLoader : public ExtensionRegistrar::Delegate {
void UnloadExtension(const ExtensionId& extension_id,
extensions::UnloadedExtensionReason reason);
ExtensionRegistrar* registrar() { return &extension_registrar_; }
private:
// If the extension loaded successfully, enables it. If it's an app, launches
// it. If the load failed, updates ShellKeepAliveRequester.

View File

@@ -11,7 +11,11 @@
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/json/json_string_value_serializer.h"
#include "base/path_service.h"
#include "base/task/post_task.h"
#include "chrome/browser/pdf/pdf_extension_util.h"
#include "chrome/common/chrome_paths.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
@@ -84,6 +88,35 @@ void ElectronExtensionSystem::InitForRegularProfile(bool extensions_enabled) {
app_sorting_ = std::make_unique<NullAppSorting>();
extension_loader_ =
std::make_unique<ElectronExtensionLoader>(browser_context_);
if (!browser_context_->IsOffTheRecord())
LoadComponentExtensions();
}
std::unique_ptr<base::DictionaryValue> ParseManifest(
base::StringPiece manifest_contents) {
JSONStringValueDeserializer deserializer(manifest_contents);
std::unique_ptr<base::Value> manifest = deserializer.Deserialize(NULL, NULL);
if (!manifest.get() || !manifest->is_dict()) {
LOG(ERROR) << "Failed to parse extension manifest.";
return std::unique_ptr<base::DictionaryValue>();
}
return base::DictionaryValue::From(std::move(manifest));
}
void ElectronExtensionSystem::LoadComponentExtensions() {
std::string utf8_error;
std::string pdf_manifest_string = pdf_extension_util::GetManifest();
std::unique_ptr<base::DictionaryValue> pdf_manifest =
ParseManifest(pdf_manifest_string);
base::FilePath root_directory;
CHECK(base::PathService::Get(chrome::DIR_RESOURCES, &root_directory));
root_directory = root_directory.Append(FILE_PATH_LITERAL("pdf"));
scoped_refptr<const Extension> pdf_extension = extensions::Extension::Create(
root_directory, extensions::Manifest::COMPONENT, *pdf_manifest,
extensions::Extension::REQUIRE_KEY, &utf8_error);
extension_loader_->registrar()->AddExtension(pdf_extension);
}
ExtensionService* ElectronExtensionSystem::extension_service() {

View File

@@ -88,6 +88,8 @@ class ElectronExtensionSystem : public ExtensionSystem {
private:
void OnExtensionRegisteredWithRequestContexts(
scoped_refptr<Extension> extension);
void LoadComponentExtensions();
content::BrowserContext* browser_context_; // Not owned.
// Data to be accessed on the IO thread. Must outlive process_manager_.

View File

@@ -5,12 +5,34 @@
#include "shell/browser/extensions/electron_extensions_api_client.h"
#include <memory>
#include <string>
#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest_delegate.h"
#include "shell/browser/extensions/electron_extension_web_contents_observer.h"
#include "shell/browser/extensions/electron_messaging_delegate.h"
namespace extensions {
class ElectronMimeHandlerViewGuestDelegate
: public MimeHandlerViewGuestDelegate {
public:
ElectronMimeHandlerViewGuestDelegate() {}
~ElectronMimeHandlerViewGuestDelegate() override {}
// MimeHandlerViewGuestDelegate.
bool HandleContextMenu(content::WebContents* web_contents,
const content::ContextMenuParams& params) override {
// TODO(nornagon): surface this event to JS
LOG(INFO) << "HCM";
return true;
}
void RecordLoadMetric(bool in_main_frame,
const std::string& mime_type) override {}
private:
DISALLOW_COPY_AND_ASSIGN(ElectronMimeHandlerViewGuestDelegate);
};
ElectronExtensionsAPIClient::ElectronExtensionsAPIClient() = default;
ElectronExtensionsAPIClient::~ElectronExtensionsAPIClient() = default;
@@ -26,4 +48,10 @@ void ElectronExtensionsAPIClient::AttachWebContentsHelpers(
web_contents);
}
std::unique_ptr<MimeHandlerViewGuestDelegate>
ElectronExtensionsAPIClient::CreateMimeHandlerViewGuestDelegate(
MimeHandlerViewGuest* guest) const {
return std::make_unique<ElectronMimeHandlerViewGuestDelegate>();
}
} // namespace extensions

View File

@@ -22,6 +22,9 @@ class ElectronExtensionsAPIClient : public ExtensionsAPIClient {
MessagingDelegate* GetMessagingDelegate() override;
void AttachWebContentsHelpers(
content::WebContents* web_contents) const override;
std::unique_ptr<MimeHandlerViewGuestDelegate>
CreateMimeHandlerViewGuestDelegate(
MimeHandlerViewGuest* guest) const override;
private:
std::unique_ptr<ElectronMessagingDelegate> messaging_delegate_;

View File

@@ -5,6 +5,7 @@
#include "shell/browser/extensions/electron_extensions_browser_api_provider.h"
#include "extensions/browser/extension_function_registry.h"
#include "shell/browser/extensions/api/generated_api_registration.h"
#include "shell/browser/extensions/api/tabs/tabs_api.h"
namespace extensions {
@@ -16,11 +17,8 @@ ElectronExtensionsBrowserAPIProvider::~ElectronExtensionsBrowserAPIProvider() =
void ElectronExtensionsBrowserAPIProvider::RegisterExtensionFunctions(
ExtensionFunctionRegistry* registry) {
registry->RegisterFunction<TabsExecuteScriptFunction>();
/*
// Generated APIs from Electron.
api::ElectronGeneratedFunctionRegistry::RegisterAll(registry);
*/
}
} // namespace extensions

View File

@@ -8,8 +8,12 @@
#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "base/path_service.h"
#include "base/task/post_task.h"
#include "build/build_config.h"
#include "chrome/browser/extensions/chrome_url_request_util.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/extensions/chrome_manifest_url_handlers.h"
#include "components/version_info/version_info.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
@@ -20,17 +24,21 @@
#include "extensions/browser/component_extension_resource_manager.h"
#include "extensions/browser/core_extensions_browser_api_provider.h"
#include "extensions/browser/event_router.h"
#include "extensions/browser/extension_protocols.h"
#include "extensions/browser/null_app_sorting.h"
#include "extensions/browser/updater/null_extension_cache.h"
#include "extensions/browser/url_request_util.h"
#include "extensions/common/features/feature_channel.h"
#include "extensions/common/file_util.h"
#include "extensions/common/manifest_constants.h"
#include "extensions/common/manifest_url_handlers.h"
#include "net/base/mime_util.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "shell/browser/browser.h"
#include "shell/browser/electron_browser_client.h"
#include "shell/browser/electron_browser_context.h"
#include "shell/browser/extensions/api/runtime/electron_runtime_api_delegate.h"
#include "shell/browser/extensions/electron_component_extension_resource_manager.h"
#include "shell/browser/extensions/electron_extension_host_delegate.h"
#include "shell/browser/extensions/electron_extension_system_factory.h"
#include "shell/browser/extensions/electron_extension_web_contents_observer.h"
@@ -38,9 +46,11 @@
#include "shell/browser/extensions/electron_extensions_browser_api_provider.h"
#include "shell/browser/extensions/electron_navigation_ui_data.h"
#include "shell/browser/extensions/electron_process_manager_delegate.h"
#include "ui/base/resource/resource_bundle.h"
using content::BrowserContext;
using content::BrowserThread;
using extensions::ExtensionsBrowserClient;
namespace electron {
@@ -51,6 +61,8 @@ ElectronExtensionsBrowserClient::ElectronExtensionsBrowserClient()
// Electron does not have a concept of channel, so leave UNKNOWN to
// enable all channel-dependent extension APIs.
extensions::SetCurrentChannel(version_info::Channel::UNKNOWN);
resource_manager_.reset(
new extensions::ElectronComponentExtensionResourceManager());
AddAPIProvider(
std::make_unique<extensions::CoreExtensionsBrowserAPIProvider>());
@@ -127,7 +139,28 @@ base::FilePath ElectronExtensionsBrowserClient::GetBundleResourcePath(
const base::FilePath& extension_resources_path,
int* resource_id) const {
*resource_id = 0;
return base::FilePath();
base::FilePath chrome_resources_path;
if (!base::PathService::Get(chrome::DIR_RESOURCES, &chrome_resources_path))
return base::FilePath();
// Since component extension resources are included in
// component_extension_resources.pak file in |chrome_resources_path|,
// calculate the extension |request_relative_path| against
// |chrome_resources_path|.
if (!chrome_resources_path.IsParent(extension_resources_path))
return base::FilePath();
const base::FilePath request_relative_path =
extensions::file_util::ExtensionURLToRelativeFilePath(request.url);
if (!ExtensionsBrowserClient::Get()
->GetComponentExtensionResourceManager()
->IsComponentExtensionResource(extension_resources_path,
request_relative_path, resource_id)) {
return base::FilePath();
}
DCHECK_NE(0, *resource_id);
return request_relative_path;
}
void ElectronExtensionsBrowserClient::LoadResourceFromResourceBundle(
@@ -138,7 +171,9 @@ void ElectronExtensionsBrowserClient::LoadResourceFromResourceBundle(
const std::string& content_security_policy,
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
bool send_cors_header) {
NOTREACHED() << "Load resources from bundles not supported.";
extensions::chrome_url_request_util::LoadResourceFromResourceBundle(
request, std::move(loader), resource_relative_path, resource_id,
content_security_policy, std::move(client), send_cors_header);
}
namespace {
@@ -160,8 +195,7 @@ bool AllowCrossRendererResourceLoad(const GURL& url,
// If there aren't any explicitly marked web accessible resources, the
// load should be allowed only if it is by DevTools. A close approximation is
// checking if the extension contains a DevTools page.
if (extension && !extensions::ManifestURL::Get(
extension, extensions::manifest_keys::kDevToolsPage)
if (extension && !extensions::chrome_manifest_urls::GetDevToolsPage(extension)
.is_empty()) {
*allowed = true;
return true;
@@ -255,7 +289,7 @@ ElectronExtensionsBrowserClient::CreateRuntimeAPIDelegate(
const extensions::ComponentExtensionResourceManager*
ElectronExtensionsBrowserClient::GetComponentExtensionResourceManager() {
return NULL;
return resource_manager_.get();
}
void ElectronExtensionsBrowserClient::BroadcastEventToRenderers(

View File

@@ -24,6 +24,7 @@ class KioskDelegate;
class ProcessManagerDelegate;
class ElectronProcessManagerDelegate;
class ProcessMap;
class ElectronComponentExtensionResourceManager;
} // namespace extensions
namespace electron {
@@ -139,6 +140,9 @@ class ElectronExtensionsBrowserClient
// The extension cache used for download and installation.
std::unique_ptr<extensions::ExtensionCache> extension_cache_;
std::unique_ptr<extensions::ElectronComponentExtensionResourceManager>
resource_manager_;
DISALLOW_COPY_AND_ASSIGN(ElectronExtensionsBrowserClient);
};

View File

@@ -542,17 +542,27 @@ void NativeWindowMac::RepositionTrafficLights() {
CGFloat buttonHeight = [close frame].size.height;
CGFloat titleBarFrameHeight = buttonHeight + traffic_light_position_.y();
CGRect titleBarRect = titleBarContainerView.frame;
CGFloat titleBarWidth = NSWidth(titleBarRect);
titleBarRect.size.height = titleBarFrameHeight;
titleBarRect.origin.y = window.frame.size.height - titleBarFrameHeight;
[titleBarContainerView setFrame:titleBarRect];
BOOL isRTL = [titleBarContainerView userInterfaceLayoutDirection] ==
NSUserInterfaceLayoutDirectionRightToLeft;
NSArray* windowButtons = @[ close, miniaturize, zoom ];
const CGFloat space_between =
[miniaturize frame].origin.x - [close frame].origin.x;
for (NSUInteger i = 0; i < windowButtons.count; i++) {
NSView* view = [windowButtons objectAtIndex:i];
CGRect rect = [view frame];
rect.origin.x = traffic_light_position_.x() + (i * space_between);
if (isRTL) {
CGFloat buttonWidth = NSWidth(rect);
// origin is always top-left, even in RTL
rect.origin.x = titleBarWidth - traffic_light_position_.x() +
(i * space_between) - buttonWidth;
} else {
rect.origin.x = traffic_light_position_.x() + (i * space_between);
}
rect.origin.y = (titleBarFrameHeight - rect.size.height) / 2;
[view setFrameOrigin:rect.origin];
}
@@ -1455,8 +1465,7 @@ void NativeWindowMac::SetVibrancy(const std::string& type) {
relativeTo:nil];
}
std::string dep_warn =
" has been deprecated and will be removed in a future version of macOS.";
std::string dep_warn = " has been deprecated and removed as of macOS 10.15.";
node::Environment* env =
node::Environment::GetCurrent(v8::Isolate::GetCurrent());
@@ -1477,61 +1486,44 @@ void NativeWindowMac::SetVibrancy(const std::string& type) {
}
if (@available(macOS 10.11, *)) {
// TODO(codebytere): Use NSVisualEffectMaterial* constants directly once
// they are available in the minimum SDK version
if (type == "selection") {
// NSVisualEffectMaterialSelection
vibrancyType = static_cast<NSVisualEffectMaterial>(4);
vibrancyType = NSVisualEffectMaterialSelection;
} else if (type == "menu") {
// NSVisualEffectMaterialMenu
vibrancyType = static_cast<NSVisualEffectMaterial>(5);
vibrancyType = NSVisualEffectMaterialMenu;
} else if (type == "popover") {
// NSVisualEffectMaterialPopover
vibrancyType = static_cast<NSVisualEffectMaterial>(6);
vibrancyType = NSVisualEffectMaterialPopover;
} else if (type == "sidebar") {
// NSVisualEffectMaterialSidebar
vibrancyType = static_cast<NSVisualEffectMaterial>(7);
vibrancyType = NSVisualEffectMaterialSidebar;
} else if (type == "medium-light") {
// NSVisualEffectMaterialMediumLight
EmitWarning(env, "NSVisualEffectMaterialMediumLight" + dep_warn,
"electron");
vibrancyType = static_cast<NSVisualEffectMaterial>(8);
vibrancyType = NSVisualEffectMaterialMediumLight;
} else if (type == "ultra-dark") {
// NSVisualEffectMaterialUltraDark
EmitWarning(env, "NSVisualEffectMaterialUltraDark" + dep_warn,
"electron");
vibrancyType = static_cast<NSVisualEffectMaterial>(9);
vibrancyType = NSVisualEffectMaterialUltraDark;
}
}
if (@available(macOS 10.14, *)) {
if (type == "header") {
// NSVisualEffectMaterialHeaderView
vibrancyType = static_cast<NSVisualEffectMaterial>(10);
vibrancyType = NSVisualEffectMaterialHeaderView;
} else if (type == "sheet") {
// NSVisualEffectMaterialSheet
vibrancyType = static_cast<NSVisualEffectMaterial>(11);
vibrancyType = NSVisualEffectMaterialSheet;
} else if (type == "window") {
// NSVisualEffectMaterialWindowBackground
vibrancyType = static_cast<NSVisualEffectMaterial>(12);
vibrancyType = NSVisualEffectMaterialWindowBackground;
} else if (type == "hud") {
// NSVisualEffectMaterialHUDWindow
vibrancyType = static_cast<NSVisualEffectMaterial>(13);
vibrancyType = NSVisualEffectMaterialHUDWindow;
} else if (type == "fullscreen-ui") {
// NSVisualEffectMaterialFullScreenUI
vibrancyType = static_cast<NSVisualEffectMaterial>(16);
vibrancyType = NSVisualEffectMaterialFullScreenUI;
} else if (type == "tooltip") {
// NSVisualEffectMaterialToolTip
vibrancyType = static_cast<NSVisualEffectMaterial>(17);
vibrancyType = NSVisualEffectMaterialToolTip;
} else if (type == "content") {
// NSVisualEffectMaterialContentBackground
vibrancyType = static_cast<NSVisualEffectMaterial>(18);
vibrancyType = NSVisualEffectMaterialContentBackground;
} else if (type == "under-window") {
// NSVisualEffectMaterialUnderWindowBackground
vibrancyType = static_cast<NSVisualEffectMaterial>(21);
vibrancyType = NSVisualEffectMaterialUnderWindowBackground;
} else if (type == "under-page") {
// NSVisualEffectMaterialUnderPageBackground
vibrancyType = static_cast<NSVisualEffectMaterial>(22);
vibrancyType = NSVisualEffectMaterialUnderPageBackground;
}
}

View File

@@ -20,13 +20,6 @@
#include "shell/common/options_switches.h"
namespace electron {
namespace {
int64_t g_request_id = 0;
} // namespace
ProxyingURLLoaderFactory::InProgressRequest::FollowRedirectParams::
FollowRedirectParams() = default;
ProxyingURLLoaderFactory::InProgressRequest::FollowRedirectParams::
@@ -677,6 +670,7 @@ ProxyingURLLoaderFactory::ProxyingURLLoaderFactory(
const HandlersMap& intercepted_handlers,
content::BrowserContext* browser_context,
int render_process_id,
uint64_t* request_id_generator,
std::unique_ptr<extensions::ExtensionNavigationUIData> navigation_ui_data,
base::Optional<int64_t> navigation_id,
network::mojom::URLLoaderFactoryRequest loader_request,
@@ -688,6 +682,7 @@ ProxyingURLLoaderFactory::ProxyingURLLoaderFactory(
intercepted_handlers_(intercepted_handlers),
browser_context_(browser_context),
render_process_id_(render_process_id),
request_id_generator_(request_id_generator),
navigation_ui_data_(std::move(navigation_ui_data)),
navigation_id_(std::move(navigation_id)),
loader_factory_type_(loader_factory_type) {
@@ -765,7 +760,7 @@ void ProxyingURLLoaderFactory::CreateLoaderAndStart(
// per-BrowserContext so extensions can make sense of it. Note that
// |network_service_request_id_| by contrast is not necessarily unique, so we
// don't use it for identity here.
const uint64_t web_request_id = ++g_request_id;
const uint64_t web_request_id = ++(*request_id_generator_);
// Notes: Chromium assumes that requests with zero-ID would never use the
// "extraHeaders" code path, however in Electron requests started from

View File

@@ -23,53 +23,12 @@
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
#include "shell/browser/api/electron_api_web_request.h"
#include "shell/browser/net/electron_url_loader_factory.h"
#include "shell/browser/net/web_request_api_interface.h"
namespace electron {
// Defines the interface for WebRequest API, implemented by api::WebRequest.
class WebRequestAPI {
public:
virtual ~WebRequestAPI() {}
using BeforeSendHeadersCallback =
base::OnceCallback<void(const std::set<std::string>& removed_headers,
const std::set<std::string>& set_headers,
int error_code)>;
virtual bool HasListener() const = 0;
virtual int OnBeforeRequest(extensions::WebRequestInfo* info,
const network::ResourceRequest& request,
net::CompletionOnceCallback callback,
GURL* new_url) = 0;
virtual int OnBeforeSendHeaders(extensions::WebRequestInfo* info,
const network::ResourceRequest& request,
BeforeSendHeadersCallback callback,
net::HttpRequestHeaders* headers) = 0;
virtual int OnHeadersReceived(
extensions::WebRequestInfo* info,
const network::ResourceRequest& request,
net::CompletionOnceCallback callback,
const net::HttpResponseHeaders* original_response_headers,
scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
GURL* allowed_unsafe_redirect_url) = 0;
virtual void OnSendHeaders(extensions::WebRequestInfo* info,
const network::ResourceRequest& request,
const net::HttpRequestHeaders& headers) = 0;
virtual void OnBeforeRedirect(extensions::WebRequestInfo* info,
const network::ResourceRequest& request,
const GURL& new_location) = 0;
virtual void OnResponseStarted(extensions::WebRequestInfo* info,
const network::ResourceRequest& request) = 0;
virtual void OnErrorOccurred(extensions::WebRequestInfo* info,
const network::ResourceRequest& request,
int net_error) = 0;
virtual void OnCompleted(extensions::WebRequestInfo* info,
const network::ResourceRequest& request,
int net_error) = 0;
virtual void OnRequestWillBeDestroyed(extensions::WebRequestInfo* info) = 0;
};
// This class is responsible for following tasks when NetworkService is enabled:
// 1. handling intercepted protocols;
// 2. implementing webRequest module;
@@ -210,6 +169,7 @@ class ProxyingURLLoaderFactory
const HandlersMap& intercepted_handlers,
content::BrowserContext* browser_context,
int render_process_id,
uint64_t* request_id_generator,
std::unique_ptr<extensions::ExtensionNavigationUIData> navigation_ui_data,
base::Optional<int64_t> navigation_id,
network::mojom::URLLoaderFactoryRequest loader_request,
@@ -269,6 +229,7 @@ class ProxyingURLLoaderFactory
content::BrowserContext* const browser_context_;
const int render_process_id_;
uint64_t* request_id_generator_; // managed by AtomBrowserClient
std::unique_ptr<extensions::ExtensionNavigationUIData> navigation_ui_data_;
base::Optional<int64_t> navigation_id_;
mojo::ReceiverSet<network::mojom::URLLoaderFactory> proxy_receivers_;

View File

@@ -0,0 +1,456 @@
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "electron/shell/browser/net/proxying_websocket.h"
#include <utility>
#include "base/bind.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "components/keyed_service/content/browser_context_keyed_service_shutdown_notifier_factory.h"
#include "content/public/browser/browser_thread.h"
#include "extensions/browser/extension_navigation_ui_data.h"
#include "net/base/ip_endpoint.h"
#include "net/http/http_util.h"
namespace electron {
ProxyingWebSocket::ProxyingWebSocket(
WebRequestAPI* web_request_api,
WebSocketFactory factory,
const network::ResourceRequest& request,
mojo::PendingRemote<network::mojom::WebSocketHandshakeClient>
handshake_client,
bool has_extra_headers,
int process_id,
int render_frame_id,
content::BrowserContext* browser_context,
uint64_t* request_id_generator)
: web_request_api_(web_request_api),
request_(request),
factory_(std::move(factory)),
forwarding_handshake_client_(std::move(handshake_client)),
request_headers_(request.headers),
response_(network::mojom::URLResponseHead::New()),
has_extra_headers_(has_extra_headers),
info_(extensions::WebRequestInfoInitParams(
++(*request_id_generator),
process_id,
render_frame_id,
nullptr,
MSG_ROUTING_NONE,
request,
/*is_download=*/false,
/*is_async=*/true,
/*is_service_worker_script=*/false,
/*navigation_id=*/base::nullopt)) {}
ProxyingWebSocket::~ProxyingWebSocket() {
if (on_before_send_headers_callback_) {
std::move(on_before_send_headers_callback_)
.Run(net::ERR_ABORTED, base::nullopt);
}
if (on_headers_received_callback_) {
std::move(on_headers_received_callback_)
.Run(net::ERR_ABORTED, base::nullopt, GURL());
}
}
void ProxyingWebSocket::Start() {
// If the header client will be used, we start the request immediately, and
// OnBeforeSendHeaders and OnSendHeaders will be handled there. Otherwise,
// send these events before the request starts.
base::RepeatingCallback<void(int)> continuation;
if (has_extra_headers_) {
continuation = base::BindRepeating(
&ProxyingWebSocket::ContinueToStartRequest, weak_factory_.GetWeakPtr());
} else {
continuation =
base::BindRepeating(&ProxyingWebSocket::OnBeforeRequestComplete,
weak_factory_.GetWeakPtr());
}
int result = web_request_api_->OnBeforeRequest(&info_, request_, continuation,
&redirect_url_);
if (result == net::ERR_BLOCKED_BY_CLIENT) {
OnError(result);
return;
}
if (result == net::ERR_IO_PENDING) {
return;
}
DCHECK_EQ(net::OK, result);
continuation.Run(net::OK);
}
void ProxyingWebSocket::OnOpeningHandshakeStarted(
network::mojom::WebSocketHandshakeRequestPtr request) {
DCHECK(forwarding_handshake_client_);
forwarding_handshake_client_->OnOpeningHandshakeStarted(std::move(request));
}
void ProxyingWebSocket::ContinueToHeadersReceived() {
auto continuation =
base::BindRepeating(&ProxyingWebSocket::OnHeadersReceivedComplete,
weak_factory_.GetWeakPtr());
info_.AddResponseInfoFromResourceResponse(*response_);
int result = web_request_api_->OnHeadersReceived(
&info_, request_, continuation, response_->headers.get(),
&override_headers_, &redirect_url_);
if (result == net::ERR_BLOCKED_BY_CLIENT) {
OnError(result);
return;
}
PauseIncomingMethodCallProcessing();
if (result == net::ERR_IO_PENDING)
return;
DCHECK_EQ(net::OK, result);
OnHeadersReceivedComplete(net::OK);
}
void ProxyingWebSocket::OnConnectionEstablished(
mojo::PendingRemote<network::mojom::WebSocket> websocket,
mojo::PendingReceiver<network::mojom::WebSocketClient> client_receiver,
network::mojom::WebSocketHandshakeResponsePtr response,
mojo::ScopedDataPipeConsumerHandle readable) {
DCHECK(forwarding_handshake_client_);
DCHECK(!is_done_);
is_done_ = true;
websocket_ = std::move(websocket);
client_receiver_ = std::move(client_receiver);
handshake_response_ = std::move(response);
readable_ = std::move(readable);
response_->remote_endpoint = handshake_response_->remote_endpoint;
// response_->headers will be set in OnBeforeSendHeaders if
// |receiver_as_header_client_| is set.
if (receiver_as_header_client_.is_bound()) {
ContinueToCompleted();
return;
}
response_->headers =
base::MakeRefCounted<net::HttpResponseHeaders>(base::StringPrintf(
"HTTP/%d.%d %d %s", handshake_response_->http_version.major_value(),
handshake_response_->http_version.minor_value(),
handshake_response_->status_code,
handshake_response_->status_text.c_str()));
for (const auto& header : handshake_response_->headers)
response_->headers->AddHeader(header->name + ": " + header->value);
ContinueToHeadersReceived();
}
void ProxyingWebSocket::ContinueToCompleted() {
DCHECK(forwarding_handshake_client_);
DCHECK(is_done_);
web_request_api_->OnCompleted(&info_, request_, net::ERR_WS_UPGRADE);
forwarding_handshake_client_->OnConnectionEstablished(
std::move(websocket_), std::move(client_receiver_),
std::move(handshake_response_), std::move(readable_));
// Deletes |this|.
delete this;
}
void ProxyingWebSocket::OnAuthRequired(
const net::AuthChallengeInfo& auth_info,
const scoped_refptr<net::HttpResponseHeaders>& headers,
const net::IPEndPoint& remote_endpoint,
OnAuthRequiredCallback callback) {
if (!callback) {
OnError(net::ERR_FAILED);
return;
}
response_->headers = headers;
response_->remote_endpoint = remote_endpoint;
auth_required_callback_ = std::move(callback);
auto continuation =
base::BindRepeating(&ProxyingWebSocket::OnHeadersReceivedCompleteForAuth,
weak_factory_.GetWeakPtr(), auth_info);
info_.AddResponseInfoFromResourceResponse(*response_);
int result = web_request_api_->OnHeadersReceived(
&info_, request_, continuation, response_->headers.get(),
&override_headers_, &redirect_url_);
if (result == net::ERR_BLOCKED_BY_CLIENT) {
OnError(result);
return;
}
PauseIncomingMethodCallProcessing();
if (result == net::ERR_IO_PENDING)
return;
DCHECK_EQ(net::OK, result);
OnHeadersReceivedCompleteForAuth(auth_info, net::OK);
}
void ProxyingWebSocket::OnBeforeSendHeaders(
const net::HttpRequestHeaders& headers,
OnBeforeSendHeadersCallback callback) {
DCHECK(receiver_as_header_client_.is_bound());
request_headers_ = headers;
on_before_send_headers_callback_ = std::move(callback);
OnBeforeRequestComplete(net::OK);
}
void ProxyingWebSocket::OnHeadersReceived(const std::string& headers,
const net::IPEndPoint& endpoint,
OnHeadersReceivedCallback callback) {
DCHECK(receiver_as_header_client_.is_bound());
on_headers_received_callback_ = std::move(callback);
response_->headers = base::MakeRefCounted<net::HttpResponseHeaders>(headers);
ContinueToHeadersReceived();
}
void ProxyingWebSocket::StartProxying(
WebRequestAPI* web_request_api,
WebSocketFactory factory,
const GURL& url,
const GURL& site_for_cookies,
const base::Optional<std::string>& user_agent,
mojo::PendingRemote<network::mojom::WebSocketHandshakeClient>
handshake_client,
bool has_extra_headers,
int process_id,
int render_frame_id,
const url::Origin& origin,
content::BrowserContext* browser_context,
uint64_t* request_id_generator) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
network::ResourceRequest request;
request.url = url;
request.site_for_cookies = net::SiteForCookies::FromUrl(site_for_cookies);
if (user_agent) {
request.headers.SetHeader(net::HttpRequestHeaders::kUserAgent, *user_agent);
}
request.request_initiator = origin;
auto* proxy = new ProxyingWebSocket(
web_request_api, std::move(factory), request, std::move(handshake_client),
has_extra_headers, process_id, render_frame_id, browser_context,
request_id_generator);
proxy->Start();
}
void ProxyingWebSocket::OnBeforeRequestComplete(int error_code) {
DCHECK(receiver_as_header_client_.is_bound() ||
!receiver_as_handshake_client_.is_bound());
DCHECK(info_.url.SchemeIsWSOrWSS());
if (error_code != net::OK) {
OnError(error_code);
return;
}
auto continuation =
base::BindRepeating(&ProxyingWebSocket::OnBeforeSendHeadersComplete,
weak_factory_.GetWeakPtr());
info_.AddResponseInfoFromResourceResponse(*response_);
int result = web_request_api_->OnBeforeSendHeaders(
&info_, request_, continuation, &request_headers_);
if (result == net::ERR_BLOCKED_BY_CLIENT) {
OnError(result);
return;
}
if (result == net::ERR_IO_PENDING)
return;
DCHECK_EQ(net::OK, result);
OnBeforeSendHeadersComplete(std::set<std::string>(), std::set<std::string>(),
net::OK);
}
void ProxyingWebSocket::OnBeforeSendHeadersComplete(
const std::set<std::string>& removed_headers,
const std::set<std::string>& set_headers,
int error_code) {
DCHECK(receiver_as_header_client_.is_bound() ||
!receiver_as_handshake_client_.is_bound());
if (error_code != net::OK) {
OnError(error_code);
return;
}
if (receiver_as_header_client_.is_bound()) {
CHECK(on_before_send_headers_callback_);
std::move(on_before_send_headers_callback_)
.Run(error_code, request_headers_);
}
info_.AddResponseInfoFromResourceResponse(*response_);
web_request_api_->OnSendHeaders(&info_, request_, request_headers_);
if (!receiver_as_header_client_.is_bound())
ContinueToStartRequest(net::OK);
}
void ProxyingWebSocket::ContinueToStartRequest(int error_code) {
if (error_code != net::OK) {
OnError(error_code);
return;
}
base::flat_set<std::string> used_header_names;
std::vector<network::mojom::HttpHeaderPtr> additional_headers;
for (net::HttpRequestHeaders::Iterator it(request_headers_); it.GetNext();) {
additional_headers.push_back(
network::mojom::HttpHeader::New(it.name(), it.value()));
used_header_names.insert(base::ToLowerASCII(it.name()));
}
for (const auto& header : additional_headers_) {
if (!used_header_names.contains(base::ToLowerASCII(header->name))) {
additional_headers.push_back(
network::mojom::HttpHeader::New(header->name, header->value));
}
}
mojo::PendingRemote<network::mojom::TrustedHeaderClient>
trusted_header_client = mojo::NullRemote();
if (has_extra_headers_) {
trusted_header_client =
receiver_as_header_client_.BindNewPipeAndPassRemote();
}
std::move(factory_).Run(
info_.url, std::move(additional_headers),
receiver_as_handshake_client_.BindNewPipeAndPassRemote(),
receiver_as_auth_handler_.BindNewPipeAndPassRemote(),
std::move(trusted_header_client));
// Here we detect mojo connection errors on |receiver_as_handshake_client_|.
// See also CreateWebSocket in
// //network/services/public/mojom/network_context.mojom.
receiver_as_handshake_client_.set_disconnect_with_reason_handler(
base::BindOnce(&ProxyingWebSocket::OnMojoConnectionErrorWithCustomReason,
base::Unretained(this)));
forwarding_handshake_client_.set_disconnect_handler(base::BindOnce(
&ProxyingWebSocket::OnMojoConnectionError, base::Unretained(this)));
}
void ProxyingWebSocket::OnHeadersReceivedComplete(int error_code) {
if (error_code != net::OK) {
OnError(error_code);
return;
}
if (on_headers_received_callback_) {
base::Optional<std::string> headers;
if (override_headers_)
headers = override_headers_->raw_headers();
std::move(on_headers_received_callback_)
.Run(net::OK, headers, base::nullopt);
}
if (override_headers_) {
response_->headers = override_headers_;
override_headers_ = nullptr;
}
ResumeIncomingMethodCallProcessing();
info_.AddResponseInfoFromResourceResponse(*response_);
web_request_api_->OnResponseStarted(&info_, request_);
if (!receiver_as_header_client_.is_bound())
ContinueToCompleted();
}
void ProxyingWebSocket::OnAuthRequiredComplete(
extensions::ExtensionWebRequestEventRouter::AuthRequiredResponse rv) {
CHECK(auth_required_callback_);
ResumeIncomingMethodCallProcessing();
switch (rv) {
case extensions::ExtensionWebRequestEventRouter::AuthRequiredResponse::
AUTH_REQUIRED_RESPONSE_NO_ACTION:
case extensions::ExtensionWebRequestEventRouter::AuthRequiredResponse::
AUTH_REQUIRED_RESPONSE_CANCEL_AUTH:
std::move(auth_required_callback_).Run(base::nullopt);
break;
case extensions::ExtensionWebRequestEventRouter::AuthRequiredResponse::
AUTH_REQUIRED_RESPONSE_SET_AUTH:
std::move(auth_required_callback_).Run(auth_credentials_);
break;
case extensions::ExtensionWebRequestEventRouter::AuthRequiredResponse::
AUTH_REQUIRED_RESPONSE_IO_PENDING:
NOTREACHED();
break;
}
}
void ProxyingWebSocket::OnHeadersReceivedCompleteForAuth(
const net::AuthChallengeInfo& auth_info,
int rv) {
if (rv != net::OK) {
OnError(rv);
return;
}
ResumeIncomingMethodCallProcessing();
info_.AddResponseInfoFromResourceResponse(*response_);
auto continuation = base::BindRepeating(
&ProxyingWebSocket::OnAuthRequiredComplete, weak_factory_.GetWeakPtr());
auto auth_rv = extensions::ExtensionWebRequestEventRouter::
AuthRequiredResponse::AUTH_REQUIRED_RESPONSE_IO_PENDING;
PauseIncomingMethodCallProcessing();
OnAuthRequiredComplete(auth_rv);
}
void ProxyingWebSocket::PauseIncomingMethodCallProcessing() {
receiver_as_handshake_client_.Pause();
receiver_as_auth_handler_.Pause();
if (receiver_as_header_client_.is_bound())
receiver_as_header_client_.Pause();
}
void ProxyingWebSocket::ResumeIncomingMethodCallProcessing() {
receiver_as_handshake_client_.Resume();
receiver_as_auth_handler_.Resume();
if (receiver_as_header_client_.is_bound())
receiver_as_header_client_.Resume();
}
void ProxyingWebSocket::OnError(int error_code) {
if (!is_done_) {
is_done_ = true;
web_request_api_->OnErrorOccurred(&info_, request_, error_code);
}
// Deletes |this|.
delete this;
}
void ProxyingWebSocket::OnMojoConnectionErrorWithCustomReason(
uint32_t custom_reason,
const std::string& description) {
// Here we want to nofiy the custom reason to the client, which is why
// we reset |forwarding_handshake_client_| manually.
forwarding_handshake_client_.ResetWithReason(custom_reason, description);
OnError(net::ERR_FAILED);
// Deletes |this|.
}
void ProxyingWebSocket::OnMojoConnectionError() {
OnError(net::ERR_FAILED);
// Deletes |this|.
}
} // namespace electron

View File

@@ -0,0 +1,165 @@
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SHELL_BROWSER_NET_PROXYING_WEBSOCKET_H_
#define SHELL_BROWSER_NET_PROXYING_WEBSOCKET_H_
#include <memory>
#include <set>
#include <string>
#include <vector>
#include "base/optional.h"
#include "components/keyed_service/core/keyed_service_shutdown_notifier.h"
#include "extensions/browser/api/web_request/web_request_api.h"
#include "extensions/browser/api/web_request/web_request_info.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/websocket.mojom.h"
#include "shell/browser/net/web_request_api_interface.h"
#include "url/gurl.h"
#include "url/origin.h"
namespace electron {
// A ProxyingWebSocket proxies a WebSocket connection and dispatches
// WebRequest API events.
//
// The code is referenced from the
// extensions::WebRequestProxyingWebSocket class.
class ProxyingWebSocket : public network::mojom::WebSocketHandshakeClient,
public network::mojom::AuthenticationHandler,
public network::mojom::TrustedHeaderClient {
public:
using WebSocketFactory = content::ContentBrowserClient::WebSocketFactory;
ProxyingWebSocket(
WebRequestAPI* web_request_api,
WebSocketFactory factory,
const network::ResourceRequest& request,
mojo::PendingRemote<network::mojom::WebSocketHandshakeClient>
handshake_client,
bool has_extra_headers,
int process_id,
int render_frame_id,
content::BrowserContext* browser_context,
uint64_t* request_id_generator);
~ProxyingWebSocket() override;
void Start();
// network::mojom::WebSocketHandshakeClient methods:
void OnOpeningHandshakeStarted(
network::mojom::WebSocketHandshakeRequestPtr request) override;
void OnConnectionEstablished(
mojo::PendingRemote<network::mojom::WebSocket> websocket,
mojo::PendingReceiver<network::mojom::WebSocketClient> client_receiver,
network::mojom::WebSocketHandshakeResponsePtr response,
mojo::ScopedDataPipeConsumerHandle readable) override;
// network::mojom::AuthenticationHandler method:
void OnAuthRequired(const net::AuthChallengeInfo& auth_info,
const scoped_refptr<net::HttpResponseHeaders>& headers,
const net::IPEndPoint& remote_endpoint,
OnAuthRequiredCallback callback) override;
// network::mojom::TrustedHeaderClient methods:
void OnBeforeSendHeaders(const net::HttpRequestHeaders& headers,
OnBeforeSendHeadersCallback callback) override;
void OnHeadersReceived(const std::string& headers,
const net::IPEndPoint& endpoint,
OnHeadersReceivedCallback callback) override;
static void StartProxying(
WebRequestAPI* web_request_api,
WebSocketFactory factory,
const GURL& url,
const GURL& site_for_cookies,
const base::Optional<std::string>& user_agent,
mojo::PendingRemote<network::mojom::WebSocketHandshakeClient>
handshake_client,
bool has_extra_headers,
int process_id,
int render_frame_id,
const url::Origin& origin,
content::BrowserContext* browser_context,
uint64_t* request_id_generator);
WebRequestAPI* web_request_api() { return web_request_api_; }
private:
void OnBeforeRequestComplete(int error_code);
void OnBeforeSendHeadersComplete(const std::set<std::string>& removed_headers,
const std::set<std::string>& set_headers,
int error_code);
void ContinueToStartRequest(int error_code);
void OnHeadersReceivedComplete(int error_code);
void ContinueToHeadersReceived();
void OnAuthRequiredComplete(
extensions::ExtensionWebRequestEventRouter::AuthRequiredResponse rv);
void OnHeadersReceivedCompleteForAuth(const net::AuthChallengeInfo& auth_info,
int rv);
void ContinueToCompleted();
void PauseIncomingMethodCallProcessing();
void ResumeIncomingMethodCallProcessing();
void OnError(int result);
// This is used for detecting errors on mojo connection with the network
// service.
void OnMojoConnectionErrorWithCustomReason(uint32_t custom_reason,
const std::string& description);
// This is used for detecting errors on mojo connection with original client
// (i.e., renderer).
void OnMojoConnectionError();
// Passed from api::WebRequest.
WebRequestAPI* web_request_api_;
// Saved to feed the api::WebRequest.
network::ResourceRequest request_;
WebSocketFactory factory_;
mojo::Remote<network::mojom::WebSocketHandshakeClient>
forwarding_handshake_client_;
mojo::Receiver<network::mojom::WebSocketHandshakeClient>
receiver_as_handshake_client_{this};
mojo::Receiver<network::mojom::AuthenticationHandler>
receiver_as_auth_handler_{this};
mojo::Receiver<network::mojom::TrustedHeaderClient>
receiver_as_header_client_{this};
net::HttpRequestHeaders request_headers_;
network::mojom::URLResponseHeadPtr response_;
net::AuthCredentials auth_credentials_;
OnAuthRequiredCallback auth_required_callback_;
scoped_refptr<net::HttpResponseHeaders> override_headers_;
std::vector<network::mojom::HttpHeaderPtr> additional_headers_;
OnBeforeSendHeadersCallback on_before_send_headers_callback_;
OnHeadersReceivedCallback on_headers_received_callback_;
GURL redirect_url_;
bool is_done_ = false;
bool has_extra_headers_;
mojo::PendingRemote<network::mojom::WebSocket> websocket_;
mojo::PendingReceiver<network::mojom::WebSocketClient> client_receiver_;
network::mojom::WebSocketHandshakeResponsePtr handshake_response_ = nullptr;
mojo::ScopedDataPipeConsumerHandle readable_;
extensions::WebRequestInfo info_;
// Notifies the proxy that the browser context has been shutdown.
std::unique_ptr<KeyedServiceShutdownNotifier::Subscription>
shutdown_notifier_;
base::WeakPtrFactory<ProxyingWebSocket> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(ProxyingWebSocket);
};
} // namespace electron
#endif // SHELL_BROWSER_NET_PROXYING_WEBSOCKET_H_

View File

@@ -11,6 +11,7 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/net/chrome_mojo_proxy_resolver_factory.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/cors_exempt_headers.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/common/content_features.h"
#include "content/public/common/service_names.mojom.h"
@@ -154,6 +155,10 @@ SystemNetworkContextManager::CreateDefaultNetworkContextParams() {
network::mojom::NetworkContextParamsPtr network_context_params =
network::mojom::NetworkContextParams::New();
// This is required to avoid blocking X-Requested-With headers sent by PPAPI
// plugins, more info crbug.com/940331
content::UpdateCorsExemptHeader(network_context_params.get());
network_context_params->enable_brotli = true;
network_context_params->enable_referrers = true;

View File

@@ -0,0 +1,61 @@
// Copyright (c) 2020 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef SHELL_BROWSER_NET_WEB_REQUEST_API_INTERFACE_H_
#define SHELL_BROWSER_NET_WEB_REQUEST_API_INTERFACE_H_
#include <set>
#include <string>
#include "extensions/browser/api/web_request/web_request_info.h"
#include "services/network/public/cpp/resource_request.h"
namespace electron {
// Defines the interface for WebRequest API, implemented by api::WebRequestNS.
class WebRequestAPI {
public:
virtual ~WebRequestAPI() {}
using BeforeSendHeadersCallback =
base::OnceCallback<void(const std::set<std::string>& removed_headers,
const std::set<std::string>& set_headers,
int error_code)>;
virtual bool HasListener() const = 0;
virtual int OnBeforeRequest(extensions::WebRequestInfo* info,
const network::ResourceRequest& request,
net::CompletionOnceCallback callback,
GURL* new_url) = 0;
virtual int OnBeforeSendHeaders(extensions::WebRequestInfo* info,
const network::ResourceRequest& request,
BeforeSendHeadersCallback callback,
net::HttpRequestHeaders* headers) = 0;
virtual int OnHeadersReceived(
extensions::WebRequestInfo* info,
const network::ResourceRequest& request,
net::CompletionOnceCallback callback,
const net::HttpResponseHeaders* original_response_headers,
scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
GURL* allowed_unsafe_redirect_url) = 0;
virtual void OnSendHeaders(extensions::WebRequestInfo* info,
const network::ResourceRequest& request,
const net::HttpRequestHeaders& headers) = 0;
virtual void OnBeforeRedirect(extensions::WebRequestInfo* info,
const network::ResourceRequest& request,
const GURL& new_location) = 0;
virtual void OnResponseStarted(extensions::WebRequestInfo* info,
const network::ResourceRequest& request) = 0;
virtual void OnErrorOccurred(extensions::WebRequestInfo* info,
const network::ResourceRequest& request,
int net_error) = 0;
virtual void OnCompleted(extensions::WebRequestInfo* info,
const network::ResourceRequest& request,
int net_error) = 0;
virtual void OnRequestWillBeDestroyed(extensions::WebRequestInfo* info) = 0;
};
} // namespace electron
#endif // SHELL_BROWSER_NET_WEB_REQUEST_API_INTERFACE_H_

View File

@@ -27,34 +27,13 @@ void NodeDebugger::Start() {
if (inspector == nullptr)
return;
std::vector<std::string> args;
for (auto& arg : base::CommandLine::ForCurrentProcess()->argv()) {
#if defined(OS_WIN)
args.push_back(base::UTF16ToUTF8(arg));
#else
args.push_back(arg);
#endif
}
node::DebugOptions options;
std::vector<std::string> exec_args;
std::vector<std::string> v8_args;
std::vector<std::string> errors;
node::options_parser::Parse(&args, &exec_args, &v8_args, &options,
node::options_parser::kDisallowedInEnvironment,
&errors);
if (!errors.empty()) {
// TODO(jeremy): what's the appropriate behaviour here?
LOG(ERROR) << "Error parsing node options: "
<< base::JoinString(errors, " ");
}
const char* path = "";
if (inspector->Start(path, options,
std::make_shared<node::HostPort>(options.host_port),
true /* is_main */))
// DebugOptions will already have been set by ProcessGlobalArgs,
// so just pull the ones from there to pass to the InspectorAgent
const auto debug_options = env_->options()->debug_options();
if (inspector->Start(
"" /* path */, debug_options,
std::make_shared<node::HostPort>(debug_options.host_port),
true /* is_main */))
DCHECK(env_->inspector_agent()->IsListening());
}

View File

@@ -0,0 +1,63 @@
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "shell/browser/plugins/plugin_utils.h"
#include <vector>
#include "base/values.h"
#include "content/public/common/webplugininfo.h"
#include "extensions/buildflags/buildflags.h"
#include "url/gurl.h"
#include "url/origin.h"
#if BUILDFLAG(ENABLE_EXTENSIONS)
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_util.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension.h"
#include "extensions/common/manifest_handlers/mime_types_handler.h"
#endif
// static
std::string PluginUtils::GetExtensionIdForMimeType(
content::BrowserContext* browser_context,
const std::string& mime_type) {
auto map = GetMimeTypeToExtensionIdMap(browser_context);
auto it = map.find(mime_type);
if (it != map.end())
return it->second;
return std::string();
}
base::flat_map<std::string, std::string>
PluginUtils::GetMimeTypeToExtensionIdMap(
content::BrowserContext* browser_context) {
base::flat_map<std::string, std::string> mime_type_to_extension_id_map;
#if BUILDFLAG(ENABLE_EXTENSIONS)
std::vector<std::string> whitelist = MimeTypesHandler::GetMIMETypeWhitelist();
// Go through the white-listed extensions and try to use them to intercept
// the URL request.
for (const std::string& extension_id : whitelist) {
const extensions::Extension* extension =
extensions::ExtensionRegistry::Get(browser_context)
->enabled_extensions()
.GetByID(extension_id);
// The white-listed extension may not be installed, so we have to nullptr
// check |extension|.
if (!extension) {
continue;
}
if (MimeTypesHandler* handler = MimeTypesHandler::GetHandler(extension)) {
for (const auto& supported_mime_type : handler->mime_type_set()) {
DCHECK(!base::Contains(mime_type_to_extension_id_map,
supported_mime_type));
mime_type_to_extension_id_map[supported_mime_type] = extension_id;
}
}
}
#endif
return mime_type_to_extension_id_map;
}

View File

@@ -0,0 +1,34 @@
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SHELL_BROWSER_PLUGINS_PLUGIN_UTILS_H_
#define SHELL_BROWSER_PLUGINS_PLUGIN_UTILS_H_
#include <string>
#include "base/containers/flat_map.h"
#include "base/macros.h"
namespace content {
class BrowserContext;
}
class PluginUtils {
public:
// If there's an extension that is allowed to handle |mime_type|, returns its
// ID. Otherwise returns an empty string.
static std::string GetExtensionIdForMimeType(
content::BrowserContext* browser_context,
const std::string& mime_type);
// Returns a map populated with MIME types that are handled by an extension as
// keys and the corresponding extensions Ids as values.
static base::flat_map<std::string, std::string> GetMimeTypeToExtensionIdMap(
content::BrowserContext* browser_context);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(PluginUtils);
};
#endif // SHELL_BROWSER_PLUGINS_PLUGIN_UTILS_H_

View File

@@ -50,8 +50,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 10,0,0,20200206
PRODUCTVERSION 10,0,0,20200206
FILEVERSION 10,0,0,20200213
PRODUCTVERSION 10,0,0,20200213
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L

View File

@@ -50,11 +50,10 @@
#include "ui/display/screen.h"
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
#include "chrome/common/extensions/chrome_manifest_url_handlers.h"
#include "content/public/browser/child_process_security_policy.h"
#include "content/public/browser/render_process_host.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/common/manifest_constants.h"
#include "extensions/common/manifest_url_handlers.h"
#include "extensions/common/permissions/permissions_data.h"
#include "shell/browser/electron_browser_context.h"
#endif
@@ -601,8 +600,8 @@ void InspectableWebContentsImpl::AddDevToolsExtensionsToClient() {
base::ListValue results;
for (auto& extension : registry->enabled_extensions()) {
auto devtools_page_url = extensions::ManifestURL::Get(
extension.get(), extensions::manifest_keys::kDevToolsPage);
auto devtools_page_url =
extensions::chrome_manifest_urls::GetDevToolsPage(extension.get());
if (devtools_page_url.is_empty())
continue;

View File

@@ -327,7 +327,7 @@ void WebContentsPreferences::AppendCommandLineSwitches(
#if BUILDFLAG(ENABLE_REMOTE_MODULE)
// Whether to enable the remote module
if (IsEnabled(options::kEnableRemoteModule, true))
if (IsEnabled(options::kEnableRemoteModule, false))
command_line->AppendSwitch(switches::kEnableRemoteModule);
#endif

View File

@@ -126,12 +126,12 @@ void Initialize(v8::Local<v8::Object> exports,
&electron::RemoteCallbackFreer::BindTo);
dict.SetMethod("setRemoteObjectFreer", &electron::RemoteObjectFreer::BindTo);
dict.SetMethod("addRemoteObjectRef", &electron::RemoteObjectFreer::AddRef);
dict.SetMethod("createIDWeakMap",
&electron::api::KeyWeakMap<int32_t>::Create);
dict.SetMethod(
"createDoubleIDWeakMap",
&electron::api::KeyWeakMap<std::pair<std::string, int32_t>>::Create);
#endif
dict.SetMethod("createIDWeakMap",
&electron::api::KeyWeakMap<int32_t>::Create);
dict.SetMethod("requestGarbageCollectionForTesting",
&RequestGarbageCollectionForTesting);
dict.SetMethod("isSameOrigin", &IsSameOrigin);

View File

@@ -37,11 +37,8 @@ const char kRunAsNode[] = "ELECTRON_RUN_AS_NODE";
#if BUILDFLAG(ENABLE_PDF_VIEWER)
const char kPdfPluginMimeType[] = "application/x-google-chrome-pdf";
const char kPdfPluginPath[] = "chrome://pdf-viewer/";
const char kPdfPluginSrc[] = "src";
const char kPdfViewerUIOrigin[] = "chrome://pdf-viewer/";
const char kPdfViewerUIHost[] = "pdf-viewer";
const base::FilePath::CharType kPdfPluginPath[] =
FILE_PATH_LITERAL("internal-pdf-viewer");
#endif // BUILDFLAG(ENABLE_PDF_VIEWER)
} // namespace electron

View File

@@ -5,6 +5,7 @@
#ifndef SHELL_COMMON_ELECTRON_CONSTANTS_H_
#define SHELL_COMMON_ELECTRON_CONSTANTS_H_
#include "base/files/file_path.h"
#include "build/build_config.h"
#include "electron/buildflags/buildflags.h"
@@ -39,12 +40,7 @@ extern const char kRunAsNode[];
#if BUILDFLAG(ENABLE_PDF_VIEWER)
// The MIME type used for the PDF plugin.
extern const char kPdfPluginMimeType[];
extern const char kPdfPluginPath[];
extern const char kPdfPluginSrc[];
// Constants for PDF viewer webui.
extern const char kPdfViewerUIOrigin[];
extern const char kPdfViewerUIHost[];
extern const base::FilePath::CharType kPdfPluginPath[];
#endif // BUILDFLAG(ENABLE_PDF_VIEWER)
} // namespace electron

View File

@@ -22,6 +22,7 @@ group("extensions_features") {
public_deps = [
":api_features",
":manifest_features",
":permission_features",
# TODO(devlin): It would be nicer to have this dependency hoisted up to
# //extensions/common (since that's where it's consumed), but there's some
@@ -36,6 +37,7 @@ group("extensions_features") {
generated_json_strings("generated_api_json_strings") {
sources = [
"extension.json",
"resources_private.idl",
"tabs.json",
]
@@ -50,7 +52,10 @@ generated_json_strings("generated_api_json_strings") {
}
generated_types("generated_api_types") {
sources = [ "tabs.json" ]
sources = [
"resources_private.idl",
"tabs.json",
]
configs = [ "//build/config:precompiled_headers" ]
schema_include_rules = "extensions/common/api:extensions::api::%(namespace)s"
@@ -73,3 +78,10 @@ json_features("api_features") {
sources = [ "_api_features.json" ]
visibility = [ ":extensions_features" ]
}
json_features("permission_features") {
feature_type = "PermissionFeature"
method_name = "AddElectronPermissionFeatures"
sources = [ "_permission_features.json" ]
visibility = [ ":extensions_features" ]
}

View File

@@ -9,7 +9,27 @@
"extension_types": ["extension"],
"contexts": ["blessed_extension"]
},
"extension.getBackgroundPage": {
"contexts": ["blessed_extension"],
"disallow_for_service_workers": true
},
"extension.getURL": {
"contexts": ["blessed_extension", "unblessed_extension", "content_script"]
}
},
"mimeHandlerViewGuestInternal": {
"internal": true,
"contexts": "all",
"channel": "stable",
"matches": ["<all_urls>"]
},
"resourcesPrivate": [{
"dependencies": ["permission:resourcesPrivate"],
"contexts": ["blessed_extension"]
}, {
"channel": "stable",
"contexts": ["webui"],
"matches": [
"chrome://print/*"
]
}]
}

View File

@@ -0,0 +1,9 @@
{
"resourcesPrivate": {
"channel": "stable",
"extension_types": [
"extension"
],
"location": "component"
}
}

View File

@@ -12,6 +12,20 @@
"properties": {
},
"functions": [
{
"name": "getBackgroundPage",
"nocompile": true,
"type": "function",
"description": "Returns the JavaScript 'window' object for the background page running inside the current extension. Returns null if the extension has no background page.",
"parameters": [],
"returns": {
"type": "object",
"optional": true,
"name": "backgroundPageGlobal",
"isInstanceOf": "Window",
"additionalProperties": { "type": "any" }
}
},
{
"name": "getURL",
"deprecated": "Please use $(ref:runtime.getURL).",

View File

@@ -0,0 +1,23 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// resourcesPrivate.
namespace resourcesPrivate {
enum Component { identity, pdf };
callback GetStringsCallback = void (object result);
interface Functions {
// Gets localized strings for a component extension. Includes default WebUI
// loadTimeData values for text and language settings (fontsize, fontfamily,
// language, textdirection). See
// chrome/browser/extensions/api/resources_private/resources_private_api.cc
// for instructions on adding a new component to this API.
//
// |component| : Internal chrome component to get strings for.
// |callback| : Called with a dictionary mapping names to strings.
static void getStrings(Component component,
GetStringsCallback callback);
};
};

View File

@@ -1,7 +1,143 @@
[
{
"namespace": "tabs",
"description": "Use the <code>chrome.tabs</code> API to interact with the browser's tab system. You can use this API to create, modify, and rearrange tabs in the browser.",
"types": [
{ "id": "MutedInfoReason",
"type": "string",
"description": "An event that caused a muted state change.",
"enum": [
{"name": "user", "description": "A user input action set the muted state."},
{"name": "capture", "description": "Tab capture was started, forcing a muted state change."},
{"name": "extension", "description": "An extension, identified by the extensionId field, set the muted state."}
]
},
{
"id": "MutedInfo",
"type": "object",
"description": "The tab's muted state and the reason for the last state change.",
"properties": {
"muted": {
"type": "boolean",
"description": "Whether the tab is muted (prevented from playing sound). The tab may be muted even if it has not played or is not currently playing sound. Equivalent to whether the 'muted' audio indicator is showing."
},
"reason": {
"$ref": "MutedInfoReason",
"optional": true,
"description": "The reason the tab was muted or unmuted. Not set if the tab's mute state has never been changed."
},
"extensionId": {
"type": "string",
"optional": true,
"description": "The ID of the extension that changed the muted state. Not set if an extension was not the reason the muted state last changed."
}
}
},
{
"id": "Tab",
"type": "object",
"properties": {
"id": {"type": "integer", "minimum": -1, "optional": true, "description": "The ID of the tab. Tab IDs are unique within a browser session. Under some circumstances a tab may not be assigned an ID; for example, when querying foreign tabs using the $(ref:sessions) API, in which case a session ID may be present. Tab ID can also be set to <code>chrome.tabs.TAB_ID_NONE</code> for apps and devtools windows."},
// TODO(kalman): Investigate how this is ending up as -1 (based on window type? a bug?) and whether it should be optional instead.
"index": {"type": "integer", "minimum": -1, "description": "The zero-based index of the tab within its window."},
"windowId": {"type": "integer", "minimum": 0, "description": "The ID of the window that contains the tab."},
"openerTabId": {"type": "integer", "minimum": 0, "optional": true, "description": "The ID of the tab that opened this tab, if any. This property is only present if the opener tab still exists."},
"selected": {"type": "boolean", "description": "Whether the tab is selected.", "deprecated": "Please use $(ref:tabs.Tab.highlighted)."},
"highlighted": {"type": "boolean", "description": "Whether the tab is highlighted."},
"active": {"type": "boolean", "description": "Whether the tab is active in its window. Does not necessarily mean the window is focused."},
"pinned": {"type": "boolean", "description": "Whether the tab is pinned."},
"audible": {"type": "boolean", "optional": true, "description": "Whether the tab has produced sound over the past couple of seconds (but it might not be heard if also muted). Equivalent to whether the 'speaker audio' indicator is showing."},
"discarded": {"type": "boolean", "description": "Whether the tab is discarded. A discarded tab is one whose content has been unloaded from memory, but is still visible in the tab strip. Its content is reloaded the next time it is activated."},
"autoDiscardable": {"type": "boolean", "description": "Whether the tab can be discarded automatically by the browser when resources are low."},
"mutedInfo": {"$ref": "MutedInfo", "optional": true, "description": "The tab's muted state and the reason for the last state change."},
"url": {"type": "string", "optional": true, "description": "The last committed URL of the main frame of the tab. This property is only present if the extension's manifest includes the <code>\"tabs\"</code> permission and may be an empty string if the tab has not yet committed. See also $(ref:Tab.pendingUrl)."},
"pendingUrl": {"type": "string", "optional": true, "description": "The URL the tab is navigating to, before it has committed. This property is only present if the extension's manifest includes the <code>\"tabs\"</code> permission and there is a pending navigation."},
"title": {"type": "string", "optional": true, "description": "The title of the tab. This property is only present if the extension's manifest includes the <code>\"tabs\"</code> permission."},
"favIconUrl": {"type": "string", "optional": true, "description": "The URL of the tab's favicon. This property is only present if the extension's manifest includes the <code>\"tabs\"</code> permission. It may also be an empty string if the tab is loading."},
"status": {"type": "string", "optional": true, "description": "Either <em>loading</em> or <em>complete</em>."},
"incognito": {"type": "boolean", "description": "Whether the tab is in an incognito window."},
"width": {"type": "integer", "optional": true, "description": "The width of the tab in pixels."},
"height": {"type": "integer", "optional": true, "description": "The height of the tab in pixels."},
"sessionId": {"type": "string", "optional": true, "description": "The session ID used to uniquely identify a tab obtained from the $(ref:sessions) API."}
}
},
{
"id": "ZoomSettingsMode",
"type": "string",
"description": "Defines how zoom changes are handled, i.e., which entity is responsible for the actual scaling of the page; defaults to <code>automatic</code>.",
"enum": [
{
"name": "automatic",
"description": "Zoom changes are handled automatically by the browser."
},
{
"name": "manual",
"description": "Overrides the automatic handling of zoom changes. The <code>onZoomChange</code> event will still be dispatched, and it is the extension's responsibility to listen for this event and manually scale the page. This mode does not support <code>per-origin</code> zooming, and thus ignores the <code>scope</code> zoom setting and assumes <code>per-tab</code>."
},
{
"name": "disabled",
"description": "Disables all zooming in the tab. The tab reverts to the default zoom level, and all attempted zoom changes are ignored."
}
]
},
{
"id": "ZoomSettingsScope",
"type": "string",
"description": "Defines whether zoom changes persist for the page's origin, or only take effect in this tab; defaults to <code>per-origin</code> when in <code>automatic</code> mode, and <code>per-tab</code> otherwise.",
"enum": [
{
"name": "per-origin",
"description": "Zoom changes persist in the zoomed page's origin, i.e., all other tabs navigated to that same origin are zoomed as well. Moreover, <code>per-origin</code> zoom changes are saved with the origin, meaning that when navigating to other pages in the same origin, they are all zoomed to the same zoom factor. The <code>per-origin</code> scope is only available in the <code>automatic</code> mode."
},
{
"name": "per-tab",
"description": "Zoom changes only take effect in this tab, and zoom changes in other tabs do not affect the zooming of this tab. Also, <code>per-tab</code> zoom changes are reset on navigation; navigating a tab always loads pages with their <code>per-origin</code> zoom factors."
}
]
},
{
"id": "ZoomSettings",
"type": "object",
"description": "Defines how zoom changes in a tab are handled and at what scope.",
"properties": {
"mode": {
"$ref": "ZoomSettingsMode",
"description": "Defines how zoom changes are handled, i.e., which entity is responsible for the actual scaling of the page; defaults to <code>automatic</code>.",
"optional": true
},
"scope": {
"$ref": "ZoomSettingsScope",
"description": "Defines whether zoom changes persist for the page's origin, or only take effect in this tab; defaults to <code>per-origin</code> when in <code>automatic</code> mode, and <code>per-tab</code> otherwise.",
"optional": true
},
"defaultZoomFactor": {
"type": "number",
"optional": true,
"description": "Used to return the default zoom level for the current tab in calls to tabs.getZoomSettings."
}
}
}
],
"functions": [
{
"name": "get",
"type": "function",
"description": "Retrieves details about the specified tab.",
"parameters": [
{
"type": "integer",
"name": "tabId",
"minimum": 0
},
{
"type": "function",
"name": "callback",
"parameters": [
{"name": "tab", "$ref": "Tab"}
]
}
]
},
{
"name": "executeScript",
"type": "function",
@@ -80,6 +216,127 @@
]
}
]
},
{
"name": "setZoom",
"type": "function",
"description": "Zooms a specified tab.",
"parameters": [
{
"type": "integer",
"name": "tabId",
"minimum": 0,
"optional": true,
"description": "The ID of the tab to zoom; defaults to the active tab of the current window."
},
{
"type": "number",
"name": "zoomFactor",
"description": "The new zoom factor. A value of <code>0</code> sets the tab to its current default zoom factor. Values greater than <code>0</code> specify a (possibly non-default) zoom factor for the tab."
},
{
"type": "function",
"name": "callback",
"optional": true,
"description": "Called after the zoom factor has been changed.",
"parameters": []
}
]
},
{
"name": "getZoom",
"type": "function",
"description": "Gets the current zoom factor of a specified tab.",
"parameters": [
{
"type": "integer",
"name": "tabId",
"minimum": 0,
"optional": true,
"description": "The ID of the tab to get the current zoom factor from; defaults to the active tab of the current window."
},
{
"type": "function",
"name": "callback",
"description": "Called with the tab's current zoom factor after it has been fetched.",
"parameters": [
{
"type": "number",
"name": "zoomFactor",
"description": "The tab's current zoom factor."
}
]
}
]
},
{
"name": "setZoomSettings",
"type": "function",
"description": "Sets the zoom settings for a specified tab, which define how zoom changes are handled. These settings are reset to defaults upon navigating the tab.",
"parameters": [
{
"type": "integer",
"name": "tabId",
"optional": true,
"minimum": 0,
"description": "The ID of the tab to change the zoom settings for; defaults to the active tab of the current window."
},
{
"$ref": "ZoomSettings",
"name": "zoomSettings",
"description": "Defines how zoom changes are handled and at what scope."
},
{
"type": "function",
"name": "callback",
"optional": true,
"description": "Called after the zoom settings are changed.",
"parameters": []
}
]
},
{
"name": "getZoomSettings",
"type": "function",
"description": "Gets the current zoom settings of a specified tab.",
"parameters": [
{
"type": "integer",
"name": "tabId",
"optional": true,
"minimum": 0,
"description": "The ID of the tab to get the current zoom settings from; defaults to the active tab of the current window."
},
{
"type": "function",
"name": "callback",
"description": "Called with the tab's current zoom settings.",
"parameters": [
{
"$ref": "ZoomSettings",
"name": "zoomSettings",
"description": "The tab's current zoom settings."
}
]
}
]
}
],
"events": [
{
"name": "onZoomChange",
"type": "function",
"description": "Fired when a tab is zoomed.",
"parameters": [{
"type": "object",
"name": "ZoomChangeInfo",
"properties": {
"tabId": {"type": "integer", "minimum": 0},
"oldZoomFactor": {"type": "number"},
"newZoomFactor": {"type": "number"},
"zoomSettings": {"$ref": "ZoomSettings"}
}
}]
}
]
}

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