Compare commits

..

92 Commits

Author SHA1 Message Date
Electron Bot
fe2ca6e6e7 Bump v8.0.0-nightly.20191108 2019-11-08 07:32:00 -08:00
Shelley Vohr
d3622f9c37 feat: convert shell.openItem to async shell.openPath (#20682) 2019-11-07 23:08:43 -08:00
Jeremy Apthorp
fd70ac1173 refactor: always initialize api::Protocol (#21009) 2019-11-07 15:35:12 -08:00
Samuel Attard
b06a479240 build: remove debug builds (#21016)
* build: remove debug builds

* Update docs/development/debugging-instructions-macos.md

Co-Authored-By: Robo <hop2deep@gmail.com>
2019-11-07 11:51:44 -08:00
Milan Burda
f1e7393e30 feat: deprecate <webview>.getWebContents() (#20726) 2019-11-07 09:43:19 -08:00
Robo
c716ecb916 fix: check for validity of guest webcontents (#21019) 2019-11-07 07:39:48 -08:00
Electron Bot
7625202891 Bump v8.0.0-nightly.20191107 2019-11-07 07:32:31 -08:00
Andrew MacDonald
9b01bb00d2 feat: add app.getApplicationNameForProtocol API (#20399)
* Add GetApplicationNameForProtocol.

* Fix Windows implementation.

* Fix up test.

* Add documentation.

* Implement for real on Linux using xdg-mime.

Also ensure we allow blocking calls here to avoid errant DCHECKing.

* Improve docs for Linux.

* Clean up tests.

* Add a note about not relying on the precise format.

* Update docs/api/app.md

Co-Authored-By: Shelley Vohr <codebytere@github.com>

* Remove needless `done()`s from tests.

* Use vector list initialization.

* Add a simple test for isDefaultProtocolClient.

* Remove unneeded include and skip a test on Linux CI.

* We no longer differentiate between CI and non-CI test runs.
2019-11-06 17:50:33 -08:00
Samuel Attard
24939e8fa4 build: speedy tests on circle by splitting the test files into multiple jobs (#21015)
* build: let circleci divide our test suites in two

* well our tests rely on side affects, thats cool I guess
2019-11-06 16:15:55 -08:00
Samuel Attard
bbfb32b136 build: store the ninja log for our builds (#21011) 2019-11-06 16:13:39 -08:00
Yaser
e5ba6c5406 docs: Adds Desktop notifications Fiddle example (#20525)
* docs: Adds Desktop notifications Fiddle example

* Update index.html

Removed the classes
2019-11-06 09:24:41 -08:00
Electron Bot
b563cd1235 Bump v8.0.0-nightly.20191106 2019-11-06 07:33:12 -08:00
Samuel Attard
d91cc257f9 chore: emit the document-start and document-end events in a sandboxed renderer (#20987) 2019-11-05 17:53:03 -08:00
Samuel Attard
5b7382765c feat: allow TouchBarButton instances to be disabled (#20945)
* feat: allow TouchBarButton instances to be disabled

* Update touch-bar-button.md
2019-11-05 15:56:36 -08:00
Electron Bot
9a198e8ef4 chore: bump chromium to f30828899e4cd7161f6dc6507023f (master) (#20824)
* chore: bump chromium in DEPS to 0476932294da8809a19189b9f54cee11d50cc512

* update chromium patches (#20838)

* chore: bump chromium in DEPS to 838863f5ec9e8a12132a10bb47be8382ad9756a7

* IsRendererTransferNeededForNavigation went away

https://chromium-review.googlesource.com/c/chromium/src/+/1867031

* [arraybuffer] Move the ArrayBuffer implementation from wtf to core

https://chromium-review.googlesource.com/c/chromium/src/+/1875731

* URLLoaderRequest new mojo types

* context menu enums moved around

https://chromium-review.googlesource.com/c/chromium/src/+/1872004

https://chromium-review.googlesource.com/c/chromium/src/+/1876088

https://chromium-review.googlesource.com/c/chromium/src/+/1866520

* chore: bump chromium in DEPS to dc9525d251bf30828899e4cd7161f6dc6507023f

* update chromium patches

* [WIP] Convert network hints IPC to Mojo

https://chromium-review.googlesource.com/c/chromium/src/+/1881967

* jumbo build is no longer supported

https://chromium-review.googlesource.com/c/chromium/src/+/1881967

* fix disable-color-correct-rendering

* [FIXME] fix printing patch

compiles but prob doesn't work

* explicitly include ax_enums

https://chromium-review.googlesource.com/c/chromium/src/+/1759821

* fixup! [WIP] Convert network hints IPC to Mojo

* fix base::span

* fix AsarURLLoader to not double-std::move

* fix debug build

* fix msstl patch

* lint

* more fix msstl

* mooooore fix msstl

* fix compile

* update backport_fix_msstl_compat_in_ui_events.patch

* update msstl compat patch

* don't try to build chrome's prefetch predictor

* build: fix compilation on windows

* Fixup patches for MAS build

* Free up disk space for mac debug builds

* fix: apply custom site instance only for main frame

* Fixup from rebase

* Try not generating symbols for mac debug builds

* Remove double entry of patch

* FIx compile errors

* Trigger CI

* Set symbol_level to 1 for mac debug builds
2019-11-05 18:41:20 -05:00
John Kleinschmidt
f18fca0729 build: speed up windows source retrieval (#20955)
* ci: speed up src retrieval

* Don't save zip on ia32

* Update external binaries if src zip already exists

* Apply suggestions from code review

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

* Update appveyor.yml
2019-11-05 17:18:08 -05:00
Birunthan Mohanathas
ac69b89e82 fix: Fix broken globalShortcuts.registerAll() on non-macOS platforms (#20963)
This was a regression in #16125, which unintentionally put
`GlobalShortcutListener::RegisterAccelerator` into a
`#if defined(OS_MACOSX)` block.

Notes: Fix broken `globalShortcut.registerAll()` on Windows and Linux
2019-11-05 13:47:23 -08:00
Shelley Vohr
05de7277ab docs: fix win.setIcon ts type (#20950)
* docs: fix win.setIcon ts type

* test: update smoke tests
2019-11-05 13:47:08 -08:00
Mark Lee
d871598d20 docs: update installation instructions for proxies (#20780) 2019-11-05 13:40:43 -08:00
CezaryKulakowski
00a1cd9395 fix: changed crlf to lf in some docs files (#20832) 2019-11-05 13:39:39 -08:00
loc
15dffb3dde fix: allow iframe-initiated HTML fullscreen to exit while in macOS fullscreen (#20962)
* fix: explicitly resize the contents when exiting html fullscreen while in OS fullscreen

* test: ensure HTML fullscreen toggles while in OS fullscreen
2019-11-05 13:34:45 -08:00
Samuel Attard
fcee7212ce chore: upgrade ts generator for better type safety (#20975)
* chore: upgrade ts generator for better type safety

* spec: fix tests
2019-11-05 13:34:04 -08:00
Jeremy Apthorp
6e5ac301ce test: don't require 'q' until the test that needs it (#20958)
this stops a failure to require from blocking all tests from running
2019-11-05 11:36:25 -05:00
Electron Bot
56d6c1657a Bump v8.0.0-nightly.20191105 2019-11-05 07:31:41 -08:00
Jeremy Apthorp
afaa1e73ab chore: fix build with enable_electron_extensions (#20959) 2019-11-04 15:59:31 -08:00
Milan Burda
a034f5db0d refactor: add Error to isSerializableObject() (#20886) 2019-11-04 14:35:57 -08:00
Shelley Vohr
584a494b83 fix: proper i18n of recentDocuments item (#20948) 2019-11-04 14:20:31 -08:00
Milan Burda
01e18c2fc3 fix: cannot access nativeTheme via electron.remote (#20938) 2019-11-04 14:17:03 -08:00
Milan Burda
ee7ce3954a fix: don't export __esModule = true by electron.ts (#20939) 2019-11-04 14:16:42 -08:00
Samuel Attard
267821831c fix: capture the promise global to avoid userland mutation (#20925) 2019-11-04 11:16:51 -08:00
Jeremy Apthorp
4de04da27a chore: lint patch descriptions (#20919) 2019-11-04 11:04:18 -08:00
John Kleinschmidt
04da8a10eb docs: document JS constant naming (#20892) 2019-11-04 13:25:43 -05:00
Jeremy Apthorp
85647dfced refactor: remove references to non-existent webui (#20867) 2019-11-04 09:50:31 -08:00
Electron Bot
f645ca015f Bump v8.0.0-nightly.20191104 2019-11-04 07:32:27 -08:00
Milan Burda
f808f50fa6 chore: remove no longer needed macOS SDK forward declarations (#19918)
* chore: remove no longer needed macOS SDK forward declarations
* fix: linter errors in spec-main/node-spec.ts
2019-11-03 21:46:12 +03:00
Electron Bot
5f27c1fa25 Bump v8.0.0-nightly.20191103 2019-11-03 07:31:11 -08:00
Shelley Vohr
ba47c9b925 fix: don't copy tray image when it's set (#20904) 2019-11-02 15:14:44 -07:00
Shelley Vohr
b194d5d0e2 chore: fix IsolateData handling (#20918) 2019-11-02 15:14:11 -07:00
Electron Bot
776cab96b1 Bump v8.0.0-nightly.20191102 2019-11-02 08:31:56 -07:00
Shelley Vohr
38711233c5 feat: allow some NODE_OPTIONS in packaged apps (#20857)
* feat: allow some NODE_OPTIONS in packaged apps

* fix: correctly detect packaged app
2019-11-01 18:06:15 -07:00
Jeremy Apthorp
ecd9e1f26e chore: lint spec-main (#20835) 2019-11-01 13:37:02 -07:00
Shelley Vohr
1fed1ed577 chore: add patch info for setAspectRatio (#20920) 2019-11-01 13:26:57 -07:00
Amarnath Karthi
0fe718b1d9 docs: add Synchronous Messages Fiddle example (#20451)
* docs: add Synchronous Messages Fiddle example

* Code review changes

* Add OS support info
2019-11-01 14:02:42 -04:00
Erick Zhao
dcf6f046d9 feat: implement win.setAspectRatio() on Linux (#19516) 2019-11-01 09:22:07 -07:00
John Kleinschmidt
4240017cb6 build: allow CircleCI timeout and retry to be set via env variables (#20896)
* build: allow circleci timeout and retry to be set via env variables

* check for more statuses and run indefinitely
2019-11-01 11:47:45 -04:00
Electron Bot
d8aaaeb378 Bump v8.0.0-nightly.20191101 2019-11-01 08:30:48 -07:00
Amarnath Karthi
06285f0bf1 docs: add app information example (#20487)
* docs: add app information example

* Code review changes

* Remove demo-control css class, link href change
2019-11-01 08:04:47 -07:00
Cheng Zhao
eaf2c61bef refactor: migrates util::Promise to gin (#20871)
* refactor: use gin in Promise

* refactor: separate Promise impl that returns nothing

* refactor: use Promise<void> for promise that returns nothing

* fix: methods should be able to run on both browser and renderer process

* fix: should not pass base::StringPiece across threads

* refactor: no more need to use different ResolvePromise for empty Promise

* refactor: move Promise to gin_helper
2019-11-01 15:10:32 +09:00
Milan Burda
bff113760a fix: use Unicode version of ShellExecute() in OpenExternalOnWorkerThread() (#20879) 2019-11-01 14:38:56 +09:00
Samuel Attard
7ae8538847 build: enable sccache on windows (#20790)
* build: enable sccache on windows

* chore: temporarily disable the docs only check

* build: fix escaping in sccache path on windows

* Update appveyor.yml

* Update appveyor.yml

* Use sccache settings from CI

* Use Azure enabled sccache for Windows
2019-10-31 17:08:27 -04:00
Robo
d9b058c694 ci: fix release build on windows (#20859) 2019-10-31 13:24:24 -07:00
Samuel Attard
6bcf67e051 feat: enable builtin spellchecker (#20692)
* chore: add code required to use chromes spellchecker

* chore: fix linting

* chore: manifests needs buildflags now

* chore: add dictionarySuggestions to the context menu event when the spellchecker is active

* chore: enable by default for windows builds

* chore: add patch to remove incognito usage in the spellchecker

* chore: add dependencies on spellcheck common and flags

* chore: conditionally include spell check panel impl

* chore: fix deps for spellcheck feature flags

* chore: add patch for electron resources

* chore: add dependency on //components/language/core/browser

* chore: patches to make hunspell work on windows

* build: collect hunspell dictionaries into a zip file and publish

* chore: clean up patches

* chore: add docs and set spell checker url method

* chore: fix error handling

* chore: fix hash logic

* build: update hunspell filename generator

* fix: default spellchecker list to the current system locale if we can

* docs: document the language getter

* chore: patch IDS_ resources for linux builds

* feat: add spellcheck webpref flag to disable the builtin spellchecker

* chore: fix docs typo

* chore: clean up spellchecker impl as per feedback

* remove unneeded deps
2019-10-31 13:11:51 -07:00
John Kleinschmidt
23ca7e3733 build: lengthen wait times and retries for CircleCI releases (#20889)
* build: lengthen wait times and retries for CircleCI releases

* Review suggestions
2019-10-31 14:25:11 -04:00
Yaser
b060cbf4ec docs: Adds Dialogs Fiddle example (#20473) 2019-10-31 11:04:24 -07:00
Mark Lee
2bbf32a18b docs: clean up performance checklist formatting (#20830)
* docs: fix list formatting in performance checklist

* docs: remove unused link ref
2019-10-31 08:41:18 -07:00
Electron Bot
206e94d20c Bump v8.0.0-nightly.20191031 2019-10-31 08:32:15 -07:00
Shelley Vohr
f0b0614dd7 fix: swapped labels on open/save gtkdialog (#20861) 2019-10-31 07:55:39 -07:00
John Kleinschmidt
dfdf1b54c6 build: do not try to run non existent VSTS release builds (#20866) 2019-10-31 09:58:56 -04:00
Cheng Zhao
3ae3233e65 chore: remove native_mate (Part 12) (#20869)
* refactor: move mate::Event to gin

* refactor: move mate::Locker to gin

* refactor: convert contextBridge to gin

* refactor: convert contentTracing to gin

* refactor: remove callback converter of native_mate

* refactor: remove file_dialog_converter and native_window_converter from native_mate

* refactor: convert webFrame to gin

* refactor: move blink_converter to gin

* refactor: remove net_converter from native_mate

* refactor: remove event_emitter_caller_deprecated

* refactor: remove gurl_converter from native_mate

* refactor: remove file_path and string16_converter from native_mate

* refactor: remove image_converter from native_mate

* refactor: move value_converter to gin
2019-10-31 16:56:00 +09:00
Jeremy Apthorp
6781d5e3c8 test: there is only --ci (#20794) 2019-10-30 16:38:21 -07:00
Birunthan Mohanathas
b275273044 fix: Disable compositor recycling only for attached views (#20829)
In #19873, we completely disabled compositor recycling. This has adverse
effects in our tabbed app where switching tabs (i.e. `BrowserView`s) now
results in a flicker because we now also switch compositors.

To fix this without regressing the original fix, we now recycle the
compositor when the view is removed from a window. This situation can
only happen with `BrowserView`s and the common case with `BrowserWindow`
is unaffected.
2019-10-30 13:47:12 -07:00
Jeremy Apthorp
8dfc896cfa refactor: send the 'close' message asynchronously (#20796) 2019-10-30 13:13:01 -07:00
Electron Bot
70fa9ff4c0 Bump v8.0.0-nightly.20191030 2019-10-30 08:31:54 -07:00
Milan Burda
3d56e13b38 fix: devtools extensions not loading (#20791) 2019-10-30 14:46:52 +09:00
Cheng Zhao
0ab9cc30d2 refactor: pass base::Value by value in JS API implementations (#20809)
* refactor: move the arg instead of const reference it

* refactor: avoid unnecessary copies of base::Value in arg

* refactor: pass-by-value in dict_util

* refactor: avoid unnecessary reference
2019-10-30 14:30:59 +09:00
Samuel Attard
c03ed6d3a1 build: change to download sysroots from the new sysroot bucket (#20803)
* build: change to download sysroots from the new sysroot bucket

* build: add json config files to deps hash to can influence the src dir

* build: update to latest sysroot hash
2019-10-29 17:50:24 -07:00
Shelley Vohr
5d00494f8d fix: do not DCHECK non-const methods (#20833) 2019-10-29 13:35:38 -07:00
Electron Bot
79d3901859 Bump v8.0.0-nightly.20191029 2019-10-29 08:31:39 -07:00
Milan Burda
0f7ebff81e fix: pass frameId to v8Util.setRemoteCallbackFreer() (#20732) 2019-10-29 15:40:09 +09:00
Samuel Attard
375e612ac5 docs: the ipc main listener being removed can have args (#20712) 2019-10-29 13:18:39 +09:00
Jeremy Apthorp
baaf058380 test: remove last usages of spec/window-helpers (#20792)
* test: remove last usages of spec/window-helpers

* move fixture
2019-10-29 13:16:42 +09:00
Milan Burda
0c870775c4 fix: deprecation warnings in Electron code (#20793) 2019-10-29 13:16:10 +09:00
Milan Burda
bd5a5b3ae6 fix: properly generate requestID in webContents.printToPDF() (#20769) 2019-10-29 11:36:29 +09:00
Electron Bot
b6246dcf12 chore: bump chromium to f5b345dd470f14eef6e44732ccf23 (master) (#20649) 2019-10-28 15:12:35 -07:00
Shelley Vohr
fb8b1fd1c9 fix: prevent menu gc during popup (#20745) 2019-10-28 14:26:48 -04:00
Electron Bot
d0cdd12521 Bump v8.0.0-nightly.20191028 2019-10-28 08:31:41 -07:00
Alexey Kuzmin
0eff02dab9 chore: fix formatting of a few Python files (#20743) 2019-10-28 10:02:16 -04:00
John Kleinschmidt
73da4b7215 build: fix doc only change when there isn't a PR (#20749)
* build: fix doc only change when there isn't a PR

Fixes issue where CI was mistakenly marking a PR as a doc only change because the CI was kicked off before the PR was created.
2019-10-28 09:40:21 -04:00
Shelley Vohr
cdff1bde22 docs: fix process.getSystemVersion() type (#20736) 2019-10-27 09:40:41 -07:00
Electron Bot
e8d85b6ded Bump v8.0.0-nightly.20191027 2019-10-27 08:31:07 -07:00
Electron Bot
8f1ad8a4e5 Bump v8.0.0-nightly.20191026 2019-10-26 08:32:27 -07:00
Mark Lee
57883eed0f docs: add the performance doc to the table of contents (#20727) 2019-10-25 15:58:20 -04:00
Electron Bot
4ec6d10969 Bump v8.0.0-nightly.20191025 2019-10-25 08:31:50 -07:00
Cheng Zhao
0fe6767d6b chore: remove native_mate (Part 11) (#20719)
* refactor: convert Menu and globalShortcut to gin

* refactor: convert api::Cookies to gin

* refactor: convert View and WebContentsView to gin

* refactor: convert WebContents related classes to gin

* refactor: convert powerMonitor to gin

* refactor: prepare for header change

* refactor: remove last uses of mate::EventEmitter

* refactor: remove mate::EventEmitter

* refactor: move trackable_object to gin_helper

* fix: custom converter should not use Handle

* fix: no more need to check if icon is empty

It was a bug that the Handle<NativeImage> can be non-empty when the
image file does not exist. The bug was caused by the converter code
writing out the image even when the convertion fails.

The bug was work-arounded by adding an additional check, but since the
original bug had been fixed, the additional check is no longer needed.

* fix: should always set frameId even when callback is null

* fix: do not mix gin/mate handles for NativeImage
2019-10-25 22:03:28 +09:00
Shelley Vohr
0e0d4fe990 chore: shrink RSA-PSS BoringSSL patch (#20713) 2019-10-24 13:32:43 -07:00
Electron Bot
e196a397ad Bump v8.0.0-nightly.20191024 2019-10-24 08:32:48 -07:00
CezaryKulakowski
510a916f82 fix: return proper values for WM_GETMINMAXINFO (#20519)
* fix: set proper constraints for windows with defined maxWidth

When BrowserWindow has set constraints for width (max or min) it
won't behave correctly during first attempt of resizing it. When
maxWidth is defined and maxWidth equals its width it will shrink
rapidly when user tries to expand its width. On the other hand
when minWidth is defined and minWidth equals its width it's
possible to decrease its width with a few pixels.

Notes: Fixed improper behaviour of window with width constraint set during resize.

* fix: prevent crash when WM_GETMINMAXINFO is called on initing window
2019-10-24 15:06:04 +09:00
Cheng Zhao
be955a9721 chore: remove native_mate (Part 10) (#20696)
* refactor: remove direct uses of event_emitter_deprecated.h

* refactor: remove event_emitter_deprecated.h in api::App

* refactor: use std::move to save a copy

* fix: windows and linux builds
2019-10-24 14:47:58 +09:00
Jeremy Apthorp
77414813b4 chore: remove _ns suffixes (#20691)
* chore: remove _ns suffixes

* lint
2019-10-24 09:51:06 +09:00
John Kleinschmidt
cc278cea00 ci: skip build on doc only changes (#20542)
* ci: skip build on doc only changes

* Try using exit codes on doc-only-change

* Fixup

* Fixup circleci doc-only check

* Update appveyor.yml

Co-Authored-By: Samuel Attard <sattard@slack-corp.com>

* Properly detect doc only change on Windows

* Flip exit code per review
2019-10-23 19:36:26 -04:00
Samuel Attard
fadd7e056d build: handle -x-y format for getCurrentBranch (#20706) 2019-10-23 12:51:44 -07:00
Robo
6dc101ffec chore: update build_bring_back_node_with_ltcg_configuration.patch (#20672)
* chore: update build_bring_back_node_with_ltcg_configuration.patch

set default value for node_with_ltcg=true

* fix: move ltcg definition to Release configuration
2019-10-23 12:48:12 -07:00
1007 changed files with 23650 additions and 28866 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -6,11 +6,9 @@
"browser": true
},
"rules": {
"semi": ["error", "always"],
"no-var": "error",
"no-unused-vars": 0,
"no-global-assign": 0,
"guard-for-in": 2,
"@typescript-eslint/no-unused-vars": ["error", {
"vars": "all",
"args": "after-used",
@@ -19,18 +17,29 @@
"prefer-const": ["error", {
"destructuring": "all"
}],
"standard/no-callback-literal": "off",
"node/no-deprecated-api": 0
},
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module"
},
"globals": {
"standardScheme": "readonly"
},
"overrides": [
{
"files": "*.js",
"rules": {
"@typescript-eslint/no-unused-vars": "off"
}
},
{
"files": "*.d.ts",
"rules": {
"no-useless-constructor": "off",
"@typescript-eslint/no-unused-vars": "off"
}
}
]
}

103
BUILD.gn
View File

@@ -4,6 +4,7 @@ import("//build/config/win/manifest.gni")
import("//components/spellcheck/spellcheck_build_features.gni")
import("//content/public/app/mac_helpers.gni")
import("//pdf/features.gni")
import("//ppapi/buildflags/buildflags.gni")
import("//printing/buildflags/buildflags.gni")
import("//testing/test.gni")
import("//third_party/ffmpeg/ffmpeg_options.gni")
@@ -149,7 +150,7 @@ webpack_build("electron_content_script_bundle") {
out_file = "$target_gen_dir/js2c/content_script_bundle.js"
}
copy("electron_js2c_copy") {
copy("atom_js2c_copy") {
sources = [
"lib/common/asar.js",
"lib/common/asar_init.js",
@@ -159,12 +160,12 @@ copy("electron_js2c_copy") {
]
}
action("electron_js2c") {
action("atom_js2c") {
deps = [
":atom_js2c_copy",
":electron_browser_bundle",
":electron_content_script_bundle",
":electron_isolated_renderer_bundle",
":electron_js2c_copy",
":electron_renderer_bundle",
":electron_sandboxed_renderer_bundle",
":electron_worker_bundle",
@@ -186,7 +187,7 @@ action("electron_js2c") {
inputs = sources + [ "//third_party/electron_node/tools/js2c.py" ]
outputs = [
"$root_gen_dir/electron_natives.cc",
"$root_gen_dir/atom_natives.cc",
]
script = "tools/js2c.py"
@@ -347,13 +348,12 @@ source_set("electron_lib") {
]
deps = [
":electron_js2c",
":atom_js2c",
":electron_version_header",
":manifests",
":resources",
"buildflags",
"chromium_src:chrome",
"chromium_src:chrome_spellchecker",
"native_mate",
"shell/common/api:mojo",
"//base:base_static",
@@ -383,10 +383,12 @@ source_set("electron_lib") {
"//media/mojo/mojom",
"//net:extras",
"//net:net_resources",
"//net:net_with_v8",
"//ppapi/host",
"//ppapi/proxy",
"//ppapi/shared_impl",
"//printing/buildflags",
"//services/audio/public/mojom:constants",
"//services/device/public/cpp/geolocation",
"//services/device/public/mojom",
"//services/proxy_resolver:lib",
@@ -398,7 +400,7 @@ source_set("electron_lib") {
"//third_party/electron_node:node_lib",
"//third_party/leveldatabase",
"//third_party/libyuv",
"//third_party/webrtc_overrides:webrtc_component",
"//third_party/webrtc_overrides:init_webrtc",
"//third_party/widevine/cdm:headers",
"//ui/base/idle",
"//ui/events:dom_keycode_converter",
@@ -480,6 +482,10 @@ source_set("electron_lib") {
]
}
if (enable_builtin_spellchecker) {
deps += [ "chromium_src:chrome_spellchecker" ]
}
if (is_mac) {
deps += [
"//components/remote_cocoa/app_shim",
@@ -504,7 +510,7 @@ source_set("electron_lib") {
"shell/browser/ui/views/autofill_popup_view.h",
]
if (is_mas_build) {
sources += [ "shell/browser/api/electron_api_app_mas.mm" ]
sources += [ "shell/browser/api/atom_api_app_mas.mm" ]
sources -= [
"shell/browser/auto_updater_mac.mm",
"shell/common/crash_reporter/crash_reporter_mac.h",
@@ -575,8 +581,12 @@ source_set("electron_lib") {
deps += [ "//third_party/crashpad/crashpad/client" ]
}
if (enable_pdf) {
deps += [ "//pdf" ]
if (enable_plugins) {
deps += [ "chromium_src:plugins" ]
sources += [
"shell/renderer/pepper_helper.cc",
"shell/renderer/pepper_helper.h",
]
}
if (enable_run_as_node) {
@@ -627,27 +637,27 @@ source_set("electron_lib") {
deps += [ "//third_party/webrtc/modules/desktop_capture" ]
}
sources += [
"shell/browser/api/electron_api_desktop_capturer.cc",
"shell/browser/api/electron_api_desktop_capturer.h",
"shell/browser/api/atom_api_desktop_capturer.cc",
"shell/browser/api/atom_api_desktop_capturer.h",
]
}
if (enable_view_api) {
sources += [
"shell/browser/api/views/electron_api_box_layout.cc",
"shell/browser/api/views/electron_api_box_layout.h",
"shell/browser/api/views/electron_api_button.cc",
"shell/browser/api/views/electron_api_button.h",
"shell/browser/api/views/electron_api_label_button.cc",
"shell/browser/api/views/electron_api_label_button.h",
"shell/browser/api/views/electron_api_layout_manager.cc",
"shell/browser/api/views/electron_api_layout_manager.h",
"shell/browser/api/views/electron_api_md_text_button.cc",
"shell/browser/api/views/electron_api_md_text_button.h",
"shell/browser/api/views/electron_api_resize_area.cc",
"shell/browser/api/views/electron_api_resize_area.h",
"shell/browser/api/views/electron_api_text_field.cc",
"shell/browser/api/views/electron_api_text_field.h",
"shell/browser/api/views/atom_api_box_layout.cc",
"shell/browser/api/views/atom_api_box_layout.h",
"shell/browser/api/views/atom_api_button.cc",
"shell/browser/api/views/atom_api_button.h",
"shell/browser/api/views/atom_api_label_button.cc",
"shell/browser/api/views/atom_api_label_button.h",
"shell/browser/api/views/atom_api_layout_manager.cc",
"shell/browser/api/views/atom_api_layout_manager.h",
"shell/browser/api/views/atom_api_md_text_button.cc",
"shell/browser/api/views/atom_api_md_text_button.h",
"shell/browser/api/views/atom_api_resize_area.cc",
"shell/browser/api/views/atom_api_resize_area.h",
"shell/browser/api/views/atom_api_text_field.cc",
"shell/browser/api/views/atom_api_text_field.h",
]
}
@@ -660,10 +670,6 @@ source_set("electron_lib") {
]
}
if (enable_pepper_flash) {
deps += [ "components/pepper_flash" ]
}
public_deps += [ "shell/common/extensions/api:extensions_features" ]
deps += [
"//components/pref_registry",
@@ -677,6 +683,22 @@ source_set("electron_lib") {
if (enable_electron_extensions) {
sources += filenames.lib_sources_extensions
}
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" ]
}
if (enable_pdf_viewer) {
deps += [
"//components/pdf/browser",
"//components/pdf/renderer",
]
sources += [
"shell/browser/electron_pdf_web_contents_helper_client.cc",
"shell/browser/electron_pdf_web_contents_helper_client.h",
]
}
}
electron_paks("packed_resources") {
@@ -829,7 +851,6 @@ if (is_mac) {
include_dirs = [ "." ]
sources = filenames.framework_sources
libs = []
if (enable_osr) {
libs += [ "IOSurface.framework" ]
@@ -863,7 +884,7 @@ if (is_mac) {
}
defines = [ "HELPER_EXECUTABLE" ]
sources = filenames.app_sources
sources += [ "shell/common/electron_constants.cc" ]
sources += [ "shell/common/atom_constants.cc" ]
include_dirs = [ "." ]
info_plist = "shell/renderer/resources/mac/Info.plist"
extra_substitutions =
@@ -984,7 +1005,7 @@ if (is_mac) {
mac_app_bundle("electron_app") {
output_name = electron_product_name
sources = filenames.app_sources
sources += [ "shell/common/electron_constants.cc" ]
sources += [ "shell/common/atom_constants.cc" ]
include_dirs = [ "." ]
deps = [
":electron_app_framework_bundle_data",
@@ -1353,18 +1374,12 @@ dist_zip("electron_chromedriver_zip") {
]
}
mksnapshot_deps = [
":licenses",
"//tools/v8_context_snapshot:v8_context_snapshot_generator",
"//v8:mksnapshot($v8_snapshot_toolchain)",
]
group("electron_mksnapshot") {
public_deps = mksnapshot_deps
}
dist_zip("electron_mksnapshot_zip") {
data_deps = mksnapshot_deps
data_deps = [
"//v8:mksnapshot($v8_snapshot_toolchain)",
"//tools/v8_context_snapshot:v8_context_snapshot_generator",
":licenses",
]
outputs = [
"$root_build_dir/mksnapshot.zip",
]

4
DEPS
View File

@@ -11,7 +11,7 @@ gclient_gn_args = [
vars = {
'chromium_version':
'80.0.3987.163',
'dc9525d251bf30828899e4cd7161f6dc6507023f',
'node_version':
'v12.13.0',
'nan_version':
@@ -114,7 +114,7 @@ hooks = [
'pattern': 'src/electron/script/update-external-binaries.py',
'condition': 'download_external_binaries',
'action': [
'python3',
'python',
'src/electron/script/update-external-binaries.py',
],
},

View File

@@ -43,7 +43,7 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \
&& rm -rf /var/lib/apt/lists/*
# Install Node.js
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - \
RUN curl -sL https://deb.nodesource.com/setup_13.x | bash - \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y nodejs \
&& rm -rf /var/lib/apt/lists/*

View File

@@ -1 +1 @@
8.2.1
8.0.0-nightly.20191108

View File

@@ -1,5 +1,5 @@
# The config expects the following environment variables to be set:
# - "GN_CONFIG" Build type. One of {'debug', 'testing', 'release'}.
# - "GN_CONFIG" Build type. One of {'testing', 'release'}.
# - "GN_EXTRA_ARGS" Additional gn arguments for a build config,
# e.g. 'target_cpu="x86"' to build for a 32bit platform.
# https://gn.googlesource.com/gn/+/master/docs/reference.md#target_cpu
@@ -76,40 +76,39 @@ build_script:
--unmanaged
%GCLIENT_EXTRA_ARGS%
"https://github.com/electron/electron"
- gclient sync --with_branch_heads --with_tags --ignore_locks --break_repo_locks
- ps: >-
if ($env:SAVE_GCLIENT_SRC -eq 'true') {
# archive current source for future use
# only run on x64/woa to avoid contention saving
if ($(7z a $zipfile src -xr!android_webview -xr!electron -xr'!*\.git' -xr!third_party\WebKit\LayoutTests! -xr!third_party\blink\web_tests -xr!third_party\blink\perf_tests -slp -t7z -mmt=30;$LASTEXITCODE -ne 0)) {
Write-warning "Could not save source to shared drive; continuing anyway"
if ($env:GN_CONFIG -eq 'release') {
gclient sync --with_branch_heads --with_tags --reset
} else {
cd src\electron
node script\generate-deps-hash.js
$depshash = Get-Content .\.depshash -Raw
$zipfile = "Z:\$depshash.7z"
cd ..\..
if (Test-Path -Path $zipfile) {
# file exists, unzip and then gclient sync
7z x -y $zipfile -mmt=30 -aoa
# update external binaries
python src/electron/script/update-external-binaries.py
} else {
# file does not exist, gclient sync, then zip
gclient sync --with_branch_heads --with_tags --reset
if ($env:TARGET_ARCH -ne 'ia32') {
# archive current source for future use
# only run on x64/woa to avoid contention saving
7z a $zipfile src -xr!android_webview -xr!electron -xr'!*\.git' -xr!third_party\WebKit\LayoutTests! -xr!third_party\blink\web_tests -xr!third_party\blink\perf_tests -slp -t7z -mmt=30
}
}
}
- ps: >-
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 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%\"")
- ps: $env:BUILD_CONFIG_PATH="//electron/build/args/%GN_CONFIG%.gn"
- 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 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:\Users\electron\depot_tools\post_build_ninja_summary.py -C out\Default )
- ninja -C out/Default electron:electron_app
- if "%GN_CONFIG%"=="testing" ( python C:\Users\electron\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
- ninja -C out/Default electron:electron_dist_zip
@@ -118,7 +117,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 "%GN_CONFIG%"=="testing" ( python %LOCAL_GOMA_DIR%\goma_ctl.py stat )
- cmd /C %SCCACHE_PATH% --show-stats
- appveyor PushArtifact out/Default/dist.zip
- appveyor PushArtifact out/Default/shell_browser_ui_unittests.exe
- appveyor PushArtifact out/Default/chromedriver.zip
@@ -160,7 +159,7 @@ test_script:
echo "Skipping tests for $env:GN_CONFIG build"
}
- cd electron
- if "%RUN_TESTS%"=="true" ( echo Running test suite & node script/yarn test -- --ci --enable-logging)
- if "%RUN_TESTS%"=="true" ( echo Running test suite & node script/yarn test -- --enable-logging)
- cd ..
- if "%RUN_TESTS%"=="true" ( echo Verifying non proprietary ffmpeg & python electron\script\verify-ffmpeg.py --build-dir out\Default --source-root %cd% --ffmpeg-path out\ffmpeg )
- echo "About to verify mksnapshot"

View File

@@ -63,7 +63,7 @@ steps:
set npm_config_nodedir=%cd%\out\Default\gen\node_headers
set npm_config_arch=arm64
cd electron
node script/yarn test -- --ci --enable-logging --verbose
node script/yarn test -- --enable-logging --verbose
displayName: 'Run Electron tests'
env:
ELECTRON_OUT_DIR: Default
@@ -89,4 +89,4 @@ steps:
Get-Process | Where Name Like "electron*" | Stop-Process
Get-Process | Where Name Like "MicrosoftEdge*" | Stop-Process
displayName: 'Kill processes left running from last test run'
condition: always()
condition: always()

View File

@@ -8,12 +8,6 @@ v8_promise_internal_field_count = 1
v8_typed_array_max_size_in_heap = 0
v8_embedder_string = "-electron.0"
# TODO: this breaks native modules. See e.g. https://www.github.com/nodejs/node/pull/30463
# We can probably enable this as long as we make sure node native modules
# also build with the relevant #defines (V8_COMPRESS_POINTERS etc.)
v8_enable_pointer_compression = false
v8_enable_31bit_smis_on_64bit_arch = false
# TODO: this breaks mksnapshot
v8_enable_snapshot_native_code_counters = false
@@ -23,8 +17,8 @@ ffmpeg_branding = "Chrome"
enable_basic_printing = true
angle_enable_vulkan_validation_layers = false
dawn_enable_vulkan_validation_layers = false
is_cfi = false
enable_osr = true
# TODO: disabled due to crashes. re-enable.
enable_osr = false

View File

@@ -1,10 +0,0 @@
import("all.gn")
is_debug = true
is_component_build = true
# This may be guarded behind is_chrome_branded alongside
# proprietary_codecs https://webrtc-review.googlesource.com/c/src/+/36321,
# explicitly override here to build OpenH264 encoder/FFmpeg decoder.
# The initialization of the decoder depends on whether ffmpeg has
# been built with H.264 support.
rtc_use_h264 = proprietary_codecs

View File

@@ -16,10 +16,6 @@ PATHS_TO_SKIP = [
'./libVkICD_mock_', #Skipping because these are outputs that we don't need
'./VkICD_mock_', #Skipping because these are outputs that we don't need
# Skipping because its an output of create_bundle from //build/config/mac/rules.gni
# that we don't need
'Electron.dSYM',
# //chrome/browser:resources depends on this via
# //chrome/browser/resources/ssl/ssl_error_assistant, but we don't need to
# ship it.
@@ -56,13 +52,14 @@ def main(argv):
with open(runtime_deps) as f:
for dep in f.readlines():
dep = dep.strip()
if not skip_path(dep, dist_zip, target_cpu):
dist_files.add(dep)
dist_files.add(dep)
if sys.platform == 'darwin' and not should_flatten:
execute(['zip', '-r', '-y', dist_zip] + list(dist_files))
else:
with zipfile.ZipFile(dist_zip, 'w', zipfile.ZIP_DEFLATED, allowZip64=True) as z:
for dep in dist_files:
if skip_path(dep, dist_zip, target_cpu):
continue
if os.path.isdir(dep):
for root, dirs, files in os.walk(dep):
for file in files:

View File

@@ -32,8 +32,6 @@ static_library("chrome") {
"//chrome/browser/icon_loader_win.cc",
"//chrome/browser/icon_manager.cc",
"//chrome/browser/icon_manager.h",
"//chrome/browser/media/webrtc/system_media_capture_permissions_mac.h",
"//chrome/browser/media/webrtc/system_media_capture_permissions_mac.mm",
"//chrome/browser/net/chrome_mojo_proxy_resolver_factory.cc",
"//chrome/browser/net/chrome_mojo_proxy_resolver_factory.h",
"//chrome/browser/net/proxy_config_monitor.cc",
@@ -231,53 +229,121 @@ static_library("chrome") {
}
}
# This source set is just so we don't have to depend on all of //chrome/browser
# You may have to add new files here during the upgrade if //chrome/browser/spellchecker
# gets more files
source_set("chrome_spellchecker") {
source_set("plugins") {
sources = []
deps = []
libs = []
if (enable_builtin_spellchecker) {
# browser side
sources += [
"//chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.cc",
"//chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h",
"//chrome/browser/renderer_host/pepper/pepper_broker_message_filter.cc",
"//chrome/browser/renderer_host/pepper/pepper_broker_message_filter.h",
"//chrome/browser/renderer_host/pepper/pepper_isolated_file_system_message_filter.cc",
"//chrome/browser/renderer_host/pepper/pepper_isolated_file_system_message_filter.h",
]
deps += [
"//media:media_buildflags",
"//ppapi/buildflags",
"//ppapi/proxy:ipc",
"//services/device/public/mojom",
]
if (enable_pepper_flash) {
sources += [
"//chrome/browser/spellchecker/spell_check_host_chrome_impl.cc",
"//chrome/browser/spellchecker/spell_check_host_chrome_impl.h",
"//chrome/browser/spellchecker/spellcheck_custom_dictionary.cc",
"//chrome/browser/spellchecker/spellcheck_custom_dictionary.h",
"//chrome/browser/spellchecker/spellcheck_factory.cc",
"//chrome/browser/spellchecker/spellcheck_factory.h",
"//chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc",
"//chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h",
"//chrome/browser/spellchecker/spellcheck_language_blacklist_policy_handler.cc",
"//chrome/browser/spellchecker/spellcheck_language_blacklist_policy_handler.h",
"//chrome/browser/spellchecker/spellcheck_language_policy_handler.cc",
"//chrome/browser/spellchecker/spellcheck_language_policy_handler.h",
"//chrome/browser/spellchecker/spellcheck_service.cc",
"//chrome/browser/spellchecker/spellcheck_service.h",
"//chrome/browser/renderer_host/pepper/pepper_flash_browser_host.cc",
"//chrome/browser/renderer_host/pepper/pepper_flash_browser_host.h",
"//chrome/browser/renderer_host/pepper/pepper_flash_clipboard_message_filter.cc",
"//chrome/browser/renderer_host/pepper/pepper_flash_clipboard_message_filter.h",
"//chrome/browser/renderer_host/pepper/pepper_flash_drm_host.cc",
"//chrome/browser/renderer_host/pepper/pepper_flash_drm_host.h",
]
if (has_spellcheck_panel) {
if (is_mac) {
sources += [
"//chrome/browser/spellchecker/spell_check_panel_host_impl.cc",
"//chrome/browser/spellchecker/spell_check_panel_host_impl.h",
"//chrome/browser/renderer_host/pepper/monitor_finder_mac.h",
"//chrome/browser/renderer_host/pepper/monitor_finder_mac.mm",
]
libs += [ "CoreGraphics.framework" ]
}
if (use_browser_spellchecker) {
sources += [
"//chrome/browser/spellchecker/spelling_request.cc",
"//chrome/browser/spellchecker/spelling_request.h",
]
if (is_linux) {
deps += [ "//components/services/font/public/cpp" ]
}
}
deps += [
"//base:base_static",
"//components/language/core/browser",
"//components/spellcheck:buildflags",
"//components/sync",
# renderer side
sources += [
"//chrome/renderer/pepper/chrome_renderer_pepper_host_factory.cc",
"//chrome/renderer/pepper/chrome_renderer_pepper_host_factory.h",
"//chrome/renderer/pepper/pepper_shared_memory_message_filter.cc",
"//chrome/renderer/pepper/pepper_shared_memory_message_filter.h",
]
if (enable_pepper_flash) {
sources += [
"//chrome/renderer/pepper/pepper_flash_drm_renderer_host.cc",
"//chrome/renderer/pepper/pepper_flash_drm_renderer_host.h",
"//chrome/renderer/pepper/pepper_flash_font_file_host.cc",
"//chrome/renderer/pepper/pepper_flash_font_file_host.h",
"//chrome/renderer/pepper/pepper_flash_fullscreen_host.cc",
"//chrome/renderer/pepper/pepper_flash_fullscreen_host.h",
"//chrome/renderer/pepper/pepper_flash_menu_host.cc",
"//chrome/renderer/pepper/pepper_flash_menu_host.h",
"//chrome/renderer/pepper/pepper_flash_renderer_host.cc",
"//chrome/renderer/pepper/pepper_flash_renderer_host.h",
]
}
deps += [
"//components/strings",
"//media:media_buildflags",
"//ppapi/host",
"//ppapi/proxy",
"//ppapi/proxy:ipc",
"//ppapi/shared_impl",
"//skia",
]
}
# This source set is just so we don't have to depend on all of //chrome/browser
# You may have to add new files here during the upgrade if //chrome/browser/spellchecker
# gets more files
source_set("chrome_spellchecker") {
sources = [
"//chrome/browser/spellchecker/spell_check_host_chrome_impl.cc",
"//chrome/browser/spellchecker/spell_check_host_chrome_impl.h",
"//chrome/browser/spellchecker/spellcheck_custom_dictionary.cc",
"//chrome/browser/spellchecker/spellcheck_custom_dictionary.h",
"//chrome/browser/spellchecker/spellcheck_factory.cc",
"//chrome/browser/spellchecker/spellcheck_factory.h",
"//chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc",
"//chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h",
"//chrome/browser/spellchecker/spellcheck_language_blacklist_policy_handler.cc",
"//chrome/browser/spellchecker/spellcheck_language_blacklist_policy_handler.h",
"//chrome/browser/spellchecker/spellcheck_language_policy_handler.cc",
"//chrome/browser/spellchecker/spellcheck_language_policy_handler.h",
"//chrome/browser/spellchecker/spellcheck_service.cc",
"//chrome/browser/spellchecker/spellcheck_service.h",
"//chrome/common/pref_names.h",
]
if (has_spellcheck_panel) {
sources += [
"//chrome/browser/spellchecker/spell_check_panel_host_impl.cc",
"//chrome/browser/spellchecker/spell_check_panel_host_impl.h",
]
}
if (use_browser_spellchecker) {
sources += [
"//chrome/browser/spellchecker/spelling_request.cc",
"//chrome/browser/spellchecker/spelling_request.h",
]
}
deps = [
"//base:base_static",
"//components/language/core/browser",
"//components/spellcheck:buildflags",
"//components/sync",
]
public_deps = [
"//components/spellcheck/browser",

View File

@@ -56,7 +56,7 @@
#include <stddef.h>
#include "shell/browser/browser.h"
#include "shell/common/electron_command_line.h"
#include "shell/common/atom_command_line.h"
#include "base/base_paths.h"
#include "base/bind.h"
@@ -826,7 +826,7 @@ ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessWithTimeout(
return PROCESS_NONE;
to_send.append(current_dir.value());
const std::vector<std::string>& argv = electron::ElectronCommandLine::argv();
const std::vector<std::string>& argv = electron::AtomCommandLine::argv();
for (std::vector<std::string>::const_iterator it = argv.begin();
it != argv.end(); ++it) {
to_send.push_back(kTokenDelimiter);

View File

@@ -1,62 +0,0 @@
# Copyright (c) 2018 GitHub, Inc.
# Use of this source code is governed by the MIT license that can be
# found in the LICENSE file.
component("pepper_flash") {
visibility = [ "//electron:electron_lib" ]
defines = [ "IS_PEPPER_FLASH_IMPL" ]
sources = [
"//chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.cc",
"//chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h",
"//chrome/browser/renderer_host/pepper/pepper_broker_message_filter.cc",
"//chrome/browser/renderer_host/pepper/pepper_broker_message_filter.h",
"//chrome/browser/renderer_host/pepper/pepper_flash_browser_host.cc",
"//chrome/browser/renderer_host/pepper/pepper_flash_browser_host.h",
"//chrome/browser/renderer_host/pepper/pepper_flash_clipboard_message_filter.cc",
"//chrome/browser/renderer_host/pepper/pepper_flash_clipboard_message_filter.h",
"//chrome/browser/renderer_host/pepper/pepper_flash_drm_host.cc",
"//chrome/browser/renderer_host/pepper/pepper_flash_drm_host.h",
"//chrome/browser/renderer_host/pepper/pepper_isolated_file_system_message_filter.cc",
"//chrome/browser/renderer_host/pepper/pepper_isolated_file_system_message_filter.h",
"//chrome/renderer/pepper/chrome_renderer_pepper_host_factory.cc",
"//chrome/renderer/pepper/chrome_renderer_pepper_host_factory.h",
"//chrome/renderer/pepper/pepper_flash_drm_renderer_host.cc",
"//chrome/renderer/pepper/pepper_flash_drm_renderer_host.h",
"//chrome/renderer/pepper/pepper_flash_font_file_host.cc",
"//chrome/renderer/pepper/pepper_flash_font_file_host.h",
"//chrome/renderer/pepper/pepper_flash_fullscreen_host.cc",
"//chrome/renderer/pepper/pepper_flash_fullscreen_host.h",
"//chrome/renderer/pepper/pepper_flash_menu_host.cc",
"//chrome/renderer/pepper/pepper_flash_menu_host.h",
"//chrome/renderer/pepper/pepper_flash_renderer_host.cc",
"//chrome/renderer/pepper/pepper_flash_renderer_host.h",
"//chrome/renderer/pepper/pepper_helper.cc",
"//chrome/renderer/pepper/pepper_helper.h",
"//chrome/renderer/pepper/pepper_shared_memory_message_filter.cc",
"//chrome/renderer/pepper/pepper_shared_memory_message_filter.h",
]
deps = [
"//content/public/browser",
"//content/public/renderer",
"//media:media_buildflags",
"//ppapi/host",
"//ppapi/proxy",
"//ppapi/proxy:ipc",
"//ppapi/shared_impl",
"//services/device/public/mojom",
"//skia",
"//third_party/adobe/flash:flapper_version_h",
"//ui/base",
"//ui/base/clipboard",
]
if (is_mac) {
sources += [
"//chrome/browser/renderer_host/pepper/monitor_finder_mac.h",
"//chrome/browser/renderer_host/pepper/monitor_finder_mac.mm",
]
libs = [ "CoreGraphics.framework" ]
}
if (is_linux) {
deps += [ "//components/services/font/public/cpp" ]
}
}

View File

@@ -1,50 +1,48 @@
import { app, dialog, BrowserWindow, shell, ipcMain } from 'electron';
import * as path from 'path';
import { app, dialog, BrowserWindow, shell, ipcMain } from 'electron'
import * as path from 'path'
let mainWindow: BrowserWindow | null = null;
app.allowRendererProcessReuse = true;
let mainWindow: BrowserWindow | null = null
// Quit when all windows are closed.
app.on('window-all-closed', () => {
app.quit();
});
app.quit()
})
function decorateURL (url: string) {
// safely add `?utm_source=default_app
const parsedUrl = new URL(url);
parsedUrl.searchParams.append('utm_source', 'default_app');
return parsedUrl.toString();
const parsedUrl = new URL(url)
parsedUrl.searchParams.append('utm_source', 'default_app')
return parsedUrl.toString()
}
// Find the shortest path to the electron binary
const absoluteElectronPath = process.execPath;
const relativeElectronPath = path.relative(process.cwd(), absoluteElectronPath);
const absoluteElectronPath = process.execPath
const relativeElectronPath = path.relative(process.cwd(), absoluteElectronPath)
const electronPath = absoluteElectronPath.length < relativeElectronPath.length
? absoluteElectronPath
: relativeElectronPath;
: relativeElectronPath
const indexPath = path.resolve(app.getAppPath(), 'index.html');
const indexPath = path.resolve(app.getAppPath(), 'index.html')
function isTrustedSender (webContents: Electron.WebContents) {
if (webContents !== (mainWindow && mainWindow.webContents)) {
return false;
return false
}
const parsedUrl = new URL(webContents.getURL());
const parsedUrl = new URL(webContents.getURL())
const urlPath = process.platform === 'win32'
// Strip the prefixed "/" that occurs on windows
? path.resolve(parsedUrl.pathname.substr(1))
: parsedUrl.pathname;
return parsedUrl.protocol === 'file:' && urlPath === indexPath;
: parsedUrl.pathname
return parsedUrl.protocol === 'file:' && urlPath === indexPath
}
ipcMain.handle('bootstrap', (event) => {
return isTrustedSender(event.sender) ? electronPath : null;
});
return isTrustedSender(event.sender) ? electronPath : null
})
async function createWindow () {
await app.whenReady();
await app.whenReady()
const options: Electron.BrowserWindowConstructorOptions = {
width: 900,
@@ -59,46 +57,46 @@ async function createWindow () {
},
useContentSize: true,
show: false
};
if (process.platform === 'linux') {
options.icon = path.join(__dirname, 'icon.png');
}
mainWindow = new BrowserWindow(options);
mainWindow.on('ready-to-show', () => mainWindow!.show());
if (process.platform === 'linux') {
options.icon = path.join(__dirname, 'icon.png')
}
mainWindow = new BrowserWindow(options)
mainWindow.on('ready-to-show', () => mainWindow!.show())
mainWindow.webContents.on('new-window', (event, url) => {
event.preventDefault();
shell.openExternal(decorateURL(url));
});
event.preventDefault()
shell.openExternal(decorateURL(url))
})
mainWindow.webContents.session.setPermissionRequestHandler((webContents, permission, done) => {
const parsedUrl = new URL(webContents.getURL());
const parsedUrl = new URL(webContents.getURL())
const options: Electron.MessageBoxOptions = {
title: 'Permission Request',
message: `Allow '${parsedUrl.origin}' to access '${permission}'?`,
buttons: ['OK', 'Cancel'],
cancelId: 1
};
}
dialog.showMessageBox(mainWindow!, options).then(({ response }) => {
done(response === 0);
});
});
done(response === 0)
})
})
return mainWindow;
return mainWindow
}
export const loadURL = async (appUrl: string) => {
mainWindow = await createWindow();
mainWindow.loadURL(appUrl);
mainWindow.focus();
};
mainWindow = await createWindow()
mainWindow.loadURL(appUrl)
mainWindow.focus()
}
export const loadFile = async (appPath: string) => {
mainWindow = await createWindow();
mainWindow.loadFile(appPath);
mainWindow.focus();
};
mainWindow = await createWindow()
mainWindow.loadFile(appPath)
mainWindow.focus()
}

View File

@@ -1,8 +1,8 @@
import { app, dialog } from 'electron';
import { app, dialog } from 'electron'
import * as fs from 'fs';
import * as path from 'path';
import * as url from 'url';
import * as fs from 'fs'
import * as path from 'path'
import * as url from 'url'
type DefaultAppOptions = {
file: null | string;
@@ -14,10 +14,10 @@ type DefaultAppOptions = {
modules: string[];
}
const Module = require('module');
const Module = require('module')
// Parse command line options.
const argv = process.argv.slice(1);
const argv = process.argv.slice(1)
const option: DefaultAppOptions = {
file: null,
@@ -27,50 +27,50 @@ const option: DefaultAppOptions = {
interactive: false,
abi: false,
modules: []
};
}
let nextArgIsRequire = false;
let nextArgIsRequire = false
for (const arg of argv) {
if (nextArgIsRequire) {
option.modules.push(arg);
nextArgIsRequire = false;
continue;
option.modules.push(arg)
nextArgIsRequire = false
continue
} else if (arg === '--version' || arg === '-v') {
option.version = true;
break;
option.version = true
break
} else if (arg.match(/^--app=/)) {
option.file = arg.split('=')[1];
break;
option.file = arg.split('=')[1]
break
} else if (arg === '--interactive' || arg === '-i' || arg === '-repl') {
option.interactive = true;
option.interactive = true
} else if (arg === '--test-type=webdriver') {
option.webdriver = true;
option.webdriver = true
} else if (arg === '--require' || arg === '-r') {
nextArgIsRequire = true;
continue;
nextArgIsRequire = true
continue
} else if (arg === '--abi' || arg === '-a') {
option.abi = true;
continue;
option.abi = true
continue
} else if (arg === '--no-help') {
option.noHelp = true;
continue;
option.noHelp = true
continue
} else if (arg[0] === '-') {
continue;
continue
} else {
option.file = arg;
break;
option.file = arg
break
}
}
if (nextArgIsRequire) {
console.error('Invalid Usage: --require [file]\n\n"file" is required');
process.exit(1);
console.error('Invalid Usage: --require [file]\n\n"file" is required')
process.exit(1)
}
// Set up preload modules
if (option.modules.length > 0) {
Module._preloadModules(option.modules);
Module._preloadModules(option.modules)
}
function loadApplicationPackage (packagePath: string) {
@@ -79,102 +79,102 @@ function loadApplicationPackage (packagePath: string) {
configurable: false,
enumerable: true,
value: true
});
})
try {
// Override app name and version.
packagePath = path.resolve(packagePath);
const packageJsonPath = path.join(packagePath, 'package.json');
let appPath;
packagePath = path.resolve(packagePath)
const packageJsonPath = path.join(packagePath, 'package.json')
let appPath
if (fs.existsSync(packageJsonPath)) {
let packageJson;
let packageJson
try {
packageJson = require(packageJsonPath);
packageJson = require(packageJsonPath)
} catch (e) {
showErrorMessage(`Unable to parse ${packageJsonPath}\n\n${e.message}`);
return;
showErrorMessage(`Unable to parse ${packageJsonPath}\n\n${e.message}`)
return
}
if (packageJson.version) {
app.setVersion(packageJson.version);
app.setVersion(packageJson.version)
}
if (packageJson.productName) {
app.name = packageJson.productName;
app.name = packageJson.productName
} else if (packageJson.name) {
app.name = packageJson.name;
app.name = packageJson.name
}
appPath = packagePath;
appPath = packagePath
}
try {
const filePath = Module._resolveFilename(packagePath, module, true);
app._setDefaultAppPaths(appPath || path.dirname(filePath));
const filePath = Module._resolveFilename(packagePath, module, true)
app._setDefaultAppPaths(appPath || path.dirname(filePath))
} catch (e) {
showErrorMessage(`Unable to find Electron app at ${packagePath}\n\n${e.message}`);
return;
showErrorMessage(`Unable to find Electron app at ${packagePath}\n\n${e.message}`)
return
}
// Run the app.
Module._load(packagePath, module, true);
Module._load(packagePath, module, true)
} catch (e) {
console.error('App threw an error during load');
console.error(e.stack || e);
throw e;
console.error('App threw an error during load')
console.error(e.stack || e)
throw e
}
}
function showErrorMessage (message: string) {
app.focus();
dialog.showErrorBox('Error launching app', message);
process.exit(1);
app.focus()
dialog.showErrorBox('Error launching app', message)
process.exit(1)
}
async function loadApplicationByURL (appUrl: string) {
const { loadURL } = await import('./default_app');
loadURL(appUrl);
const { loadURL } = await import('./default_app')
loadURL(appUrl)
}
async function loadApplicationByFile (appPath: string) {
const { loadFile } = await import('./default_app');
loadFile(appPath);
const { loadFile } = await import('./default_app')
loadFile(appPath)
}
function startRepl () {
if (process.platform === 'win32') {
console.error('Electron REPL not currently supported on Windows');
process.exit(1);
console.error('Electron REPL not currently supported on Windows')
process.exit(1)
}
// prevent quitting
app.on('window-all-closed', () => {});
app.on('window-all-closed', () => {})
const repl = require('repl');
const repl = require('repl')
repl.start('> ').on('exit', () => {
process.exit(0);
});
process.exit(0)
})
}
// Start the specified app if there is one specified in command line, otherwise
// start the default app.
if (option.file && !option.webdriver) {
const file = option.file;
const protocol = url.parse(file).protocol;
const extension = path.extname(file);
const file = option.file
const protocol = url.parse(file).protocol
const extension = path.extname(file)
if (protocol === 'http:' || protocol === 'https:' || protocol === 'file:' || protocol === 'chrome:') {
loadApplicationByURL(file);
loadApplicationByURL(file)
} else if (extension === '.html' || extension === '.htm') {
loadApplicationByFile(path.resolve(file));
loadApplicationByFile(path.resolve(file))
} else {
loadApplicationPackage(file);
loadApplicationPackage(file)
}
} else if (option.version) {
console.log('v' + process.versions.electron);
process.exit(0);
console.log('v' + process.versions.electron)
process.exit(0)
} else if (option.abi) {
console.log(process.versions.modules);
process.exit(0);
console.log(process.versions.modules)
process.exit(0)
} else if (option.interactive) {
startRepl();
startRepl()
} else {
if (!option.noHelp) {
const welcomeMessage = `
@@ -192,10 +192,10 @@ Options:
-i, --interactive Open a REPL to the main process.
-r, --require Module to preload (option can be repeated).
-v, --version Print the version.
-a, --abi Print the Node ABI version.`;
-a, --abi Print the Node ABI version.`
console.log(welcomeMessage);
console.log(welcomeMessage)
}
loadApplicationByFile('index.html');
loadApplicationByFile('index.html')
}

View File

@@ -1,53 +1,53 @@
import { ipcRenderer, contextBridge } from 'electron';
import { ipcRenderer, contextBridge } from 'electron'
async function getOcticonSvg (name: string) {
try {
const response = await fetch(`octicon/${name}.svg`);
const div = document.createElement('div');
div.innerHTML = await response.text();
return div;
const response = await fetch(`octicon/${name}.svg`)
const div = document.createElement('div')
div.innerHTML = await response.text()
return div
} catch {
return null;
return null
}
}
async function loadSVG (element: HTMLSpanElement) {
for (const cssClass of element.classList) {
if (cssClass.startsWith('octicon-')) {
const icon = await getOcticonSvg(cssClass.substr(8));
const icon = await getOcticonSvg(cssClass.substr(8))
if (icon) {
for (const elemClass of element.classList) {
icon.classList.add(elemClass);
icon.classList.add(elemClass)
}
element.before(icon);
element.remove();
break;
element.before(icon)
element.remove()
break
}
}
}
}
async function initialize () {
const electronPath = await ipcRenderer.invoke('bootstrap');
const electronPath = await ipcRenderer.invoke('bootstrap')
function replaceText (selector: string, text: string) {
const element = document.querySelector<HTMLElement>(selector);
const element = document.querySelector<HTMLElement>(selector)
if (element) {
element.innerText = text;
element.innerText = text
}
}
replaceText('.electron-version', `Electron v${process.versions.electron}`);
replaceText('.chrome-version', `Chromium v${process.versions.chrome}`);
replaceText('.node-version', `Node v${process.versions.node}`);
replaceText('.v8-version', `v8 v${process.versions.v8}`);
replaceText('.command-example', `${electronPath} path-to-app`);
replaceText('.electron-version', `Electron v${process.versions.electron}`)
replaceText('.chrome-version', `Chromium v${process.versions.chrome}`)
replaceText('.node-version', `Node v${process.versions.node}`)
replaceText('.v8-version', `v8 v${process.versions.v8}`)
replaceText('.command-example', `${electronPath} path-to-app`)
for (const element of document.querySelectorAll<HTMLSpanElement>('.octicon')) {
loadSVG(element);
loadSVG(element)
}
}
contextBridge.exposeInMainWorld('electronDefaultApp', {
initialize
});
})

View File

@@ -39,6 +39,7 @@ an issue:
* [Using Electron's APIs](tutorial/application-architecture.md#using-electron-apis)
* [Using Node.js APIs](tutorial/application-architecture.md#using-nodejs-apis)
* [Using Native Node.js Modules](tutorial/using-native-node-modules.md)
* [Performance Strategies](tutorial/performance.md)
* Adding Features to Your App
* [Notifications](tutorial/notifications.md)
* [Recent Documents](tutorial/recent-documents.md)

View File

@@ -314,8 +314,10 @@ Returns:
* `event` Event
* `webContents` [WebContents](web-contents.md)
* `authenticationResponseDetails` Object
* `request` Object
* `method` String
* `url` URL
* `referrer` URL
* `authInfo` Object
* `isProxy` Boolean
* `scheme` String
@@ -323,8 +325,8 @@ Returns:
* `port` Integer
* `realm` String
* `callback` Function
* `username` String (optional)
* `password` String (optional)
* `username` String
* `password` String
Emitted when `webContents` wants to do basic auth.
@@ -335,16 +337,12 @@ should prevent the default behavior with `event.preventDefault()` and call
```javascript
const { app } = require('electron')
app.on('login', (event, webContents, details, authInfo, callback) => {
app.on('login', (event, webContents, request, authInfo, callback) => {
event.preventDefault()
callback('username', 'secret')
})
```
If `callback` is called without a username or password, the authentication
request will be cancelled and the authentication error will be returned to the
page.
### Event: 'gpu-info-update'
Emitted whenever there is a GPU info update.
@@ -713,34 +711,34 @@ Clears the recent documents list.
### `app.setAsDefaultProtocolClient(protocol[, path, args])`
* `protocol` String - The name of your protocol, without `://`. For example,
if you want your app to handle `electron://` links, call this method with
`electron` as the parameter.
* `path` String (optional) _Windows_ - The path to the Electron executable.
Defaults to `process.execPath`
* `args` String[] (optional) _Windows_ - Arguments passed to the executable.
Defaults to an empty array
* `protocol` String - The name of your protocol, without `://`. If you want your
app to handle `electron://` links, call this method with `electron` as the
parameter.
* `path` String (optional) _Windows_ - Defaults to `process.execPath`
* `args` String[] (optional) _Windows_ - Defaults to an empty array
Returns `Boolean` - Whether the call succeeded.
Sets the current executable as the default handler for a protocol (aka URI
scheme). It allows you to integrate your app deeper into the operating system.
Once registered, all links with `your-protocol://` will be opened with the
current executable. The whole link, including protocol, will be passed to your
application as a parameter.
This method sets the current executable as the default handler for a protocol
(aka URI scheme). It allows you to integrate your app deeper into the operating
system. Once registered, all links with `your-protocol://` will be opened with
the current executable. The whole link, including protocol, will be passed to
your application as a parameter.
On Windows, you can provide optional parameters path, the path to your executable,
and args, an array of arguments to be passed to your executable when it launches.
**Note:** On macOS, you can only register protocols that have been added to
your app's `info.plist`, which cannot be modified at runtime. However, you can
change the file during build time via [Electron Forge][electron-forge],
[Electron Packager][electron-packager], or by editing `info.plist` with a text
editor. Please refer to [Apple's documentation][CFBundleURLTypes] for details.
your app's `info.plist`, which can not be modified at runtime. You can however
change the file with a simple text editor or script during build time.
Please refer to [Apple's documentation][CFBundleURLTypes] for details.
**Note:** In a Windows Store environment (when packaged as an `appx`) this API
will return `true` for all calls but the registry key it sets won't be accessible
by other applications. In order to register your Windows Store application
as a default protocol handler you must [declare the protocol in your manifest](https://docs.microsoft.com/en-us/uwp/schemas/appxpackage/uapmanifestschema/element-uap-protocol).
The API uses the Windows Registry and `LSSetDefaultHandlerForURLScheme` internally.
The API uses the Windows Registry and LSSetDefaultHandlerForURLScheme internally.
### `app.removeAsDefaultProtocolClient(protocol[, path, args])` _macOS_ _Windows_
@@ -759,8 +757,10 @@ protocol (aka URI scheme). If so, it will remove the app as the default handler.
* `path` String (optional) _Windows_ - Defaults to `process.execPath`
* `args` String[] (optional) _Windows_ - Defaults to an empty array
Returns `Boolean` - Whether the current executable is the default handler for a
protocol (aka URI scheme).
Returns `Boolean`
This method checks if the current executable is the default handler for a protocol
(aka URI scheme). If so, it will return true. Otherwise, it will return false.
**Note:** On macOS, you can use this method to check if the app has been
registered as the default protocol handler for a protocol. You can also verify
@@ -768,7 +768,7 @@ this by checking `~/Library/Preferences/com.apple.LaunchServices.plist` on the
macOS machine. Please refer to
[Apple's documentation][LSCopyDefaultHandlerForURLScheme] for details.
The API uses the Windows Registry and `LSCopyDefaultHandlerForURLScheme` internally.
The API uses the Windows Registry and LSCopyDefaultHandlerForURLScheme internally.
### `app.getApplicationNameForProtocol(url)`
@@ -1201,9 +1201,8 @@ Show the app's about panel options. These options can be overridden with `app.se
* `website` String (optional) _Linux_ - The app's website.
* `iconPath` String (optional) _Linux_ _Windows_ - Path to the app's icon. On Linux, will be shown as 64x64 pixels while retaining aspect ratio.
Set the about panel options. This will override the values defined in the app's `.plist` file on MacOS. See the [Apple docs][about-panel-options] for more details. On Linux, values must be set in order to be shown; there are no defaults.
If you do not set `credits` but still wish to surface them in your app, AppKit will look for a file named "Credits.html", "Credits.rtf", and "Credits.rtfd", in that order, in the bundle returned by the NSBundle class method main. The first file found is used, and if none is found, the info area is left blank. See Apple [documentation](https://developer.apple.com/documentation/appkit/nsaboutpaneloptioncredits?language=objc) for more information.
Set the about panel options. This will override the values defined in the app's
`.plist` file on MacOS. See the [Apple docs][about-panel-options] for more details. On Linux, values must be set in order to be shown; there are no defaults.
### `app.isEmojiPanelSupported()`
@@ -1324,8 +1323,6 @@ A `Boolean` property that returns `true` if the app is packaged, `false` otherw
[dock-menu]:https://developer.apple.com/macos/human-interface-guidelines/menus/dock-menus/
[tasks]:https://msdn.microsoft.com/en-us/library/windows/desktop/dd378460(v=vs.85).aspx#tasks
[app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx
[electron-forge]: https://www.electronforge.io/
[electron-packager]: https://github.com/electron/electron-packager
[CFBundleURLTypes]: https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/TP40009249-102207-TPXREF115
[LSCopyDefaultHandlerForURLScheme]: https://developer.apple.com/library/mac/documentation/Carbon/Reference/LaunchServicesReference/#//apple_ref/c/func/LSCopyDefaultHandlerForURLScheme
[handoff]: https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/Handoff/HandoffFundamentals/HandoffFundamentals.html

View File

@@ -100,14 +100,6 @@ const { ipcRenderer } = require('electron')
ipcRenderer.invoke('openDevTools', webview.getWebContentsId())
```
### `webFrame.setLayoutZoomLevelLimits()`
Chromium has removed support for changing the layout zoom level limits, and it
is beyond Electron's capacity to maintain it. The function will emit a warning
in Electron 8.x, and cease to exist in Electron 9.x. The layout zoom level
limits are now fixed at a minimum of 0.25 and a maximum of 5.0, as defined
[here](https://chromium.googlesource.com/chromium/src/+/938b37a6d2886bf8335fc7db792f1eb46c65b2ae/third_party/blink/common/page/page_zoom.cc#11).
## Planned Breaking API Changes (7.0)
### Node Headers URL
@@ -152,7 +144,7 @@ const idleTime = getSystemIdleTime()
### webFrame Isolated World APIs
```js
// Removed in Electron 7.0
// Removed in Elecron 7.0
webFrame.setIsolatedWorldContentSecurityPolicy(worldId, csp)
webFrame.setIsolatedWorldHumanReadableName(worldId, name)
webFrame.setIsolatedWorldSecurityOrigin(worldId, securityOrigin)
@@ -170,40 +162,6 @@ webFrame.setIsolatedWorldInfo(
This property was removed in Chromium 77, and as such is no longer available.
### `webkitdirectory` attribute for `<input type="file"/>`
The `webkitdirectory` property on HTML file inputs allows them to select folders.
Previous versions of Electron had an incorrect implementation where the `event.target.files`
of the input returned a `FileList` that returned one `File` corresponding to the selected folder.
As of Electron 7, that `FileList` is now list of all files contained within
the folder, similarly to Chrome, Firefox, and Edge
([link to MDN docs](https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/webkitdirectory)).
As an illustration, take a folder with this structure:
```console
folder
├── file1
├── file2
└── file3
```
In Electron <=6, this would return a `FileList` with a `File` object for:
```console
path/to/folder
```
In Electron 7, this now returns a `FileList` with a `File` object for:
```console
/path/to/folder/file3
/path/to/folder/file2
/path/to/folder/file1
```
Note that `webkitdirectory` no longer exposes the path to the selected folder.
If you require the path to the selected folder rather than the folder contents,
see the `dialog.showOpenDialog` API ([link](https://github.com/electron/electron/blob/master/docs/api/dialog.md#dialogshowopendialogbrowserwindow-options)).
## Planned Breaking API Changes (6.0)
### `win.setMenu(null)`

View File

@@ -229,7 +229,6 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
unless hovered over in the top left of the window. These custom buttons prevent
issues with mouse events that occur with the standard window toolbar buttons.
**Note:** This option is currently experimental.
* `trafficLightPosition` [Point](structures/point.md) (optional) - Set a custom position for the traffic light buttons. Can only be used with `titleBarStyle` set to `hidden`
* `fullscreenWindowTitle` Boolean (optional) - Shows the title in the
title bar in full screen mode on macOS for all `titleBarStyle` options.
Default is `false`.
@@ -273,6 +272,8 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
OS-level sandbox and disabling the Node.js engine. This is not the same as
the `nodeIntegration` option and the APIs available to the preload script
are more limited. Read more about the option [here](sandbox-option.md).
**Note:** This option is currently experimental and may change or be
removed in future Electron releases.
* `enableRemoteModule` Boolean (optional) - Whether to enable the [`remote`](remote.md) module.
Default is `true`.
* `session` [Session](session.md#class-session) (optional) - Sets the session used by the
@@ -372,8 +373,6 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
consecutive dialog protection is triggered. If not defined the default
message would be used, note that currently the default message is in
English and not localized.
* `disableDialogs` Boolean (optional) - Whether to disable dialogs
completely. Overrides `safeDialogs`. Default is `false`.
* `navigateOnDragDrop` Boolean (optional) - Whether dragging and dropping a
file or link onto the page causes a navigation. Default is `false`.
* `autoplayPolicy` String (optional) - Autoplay policy to apply to
@@ -387,7 +386,7 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
to accessibility tools such as screen readers. This string is not directly
visible to users.
* `spellcheck` Boolean (optional) - Whether to enable the builtin spellchecker.
Default is `false`.
Default is `true`.
When setting minimum or maximum window size with `minWidth`/`maxWidth`/
`minHeight`/`maxHeight`, it only constrains the users. It won't prevent you from
@@ -518,7 +517,7 @@ Emitted when the window is restored from a minimized state.
Returns:
* `event` Event
* `newBounds` [Rectangle](structures/rectangle.md) - Size the window is being resized to.
* `newBounds` [`Rectangle`](structures/rectangle.md) - Size the window is being resized to.
Emitted before the window is resized. Calling `event.preventDefault()` will prevent the window from being resized.
@@ -533,7 +532,7 @@ Emitted after the window has been resized.
Returns:
* `event` Event
* `newBounds` [Rectangle](structures/rectangle.md) - Location the window is being moved to.
* `newBounds` [`Rectangle`](structures/rectangle.md) - Location the window is being moved to.
Emitted before the window is moved. On Windows, calling `event.preventDefault()` will prevent the window from being moved.
@@ -947,11 +946,11 @@ Returns `Boolean` - Whether the window is in simple (pre-Lion) fullscreen mode.
Returns `Boolean` - Whether the window is in normal state (not maximized, not minimized, not in fullscreen mode).
#### `win.setAspectRatio(aspectRatio[, extraSize])` _macOS_
#### `win.setAspectRatio(aspectRatio[, extraSize])` _macOS_ _Linux_
* `aspectRatio` Float - The aspect ratio to maintain for some portion of the
content view.
* `extraSize` [Size](structures/size.md) (optional) - The extra size not to be included while
* `extraSize` [Size](structures/size.md) (optional) _macOS_ - The extra size not to be included while
maintaining the aspect ratio.
This will make a window maintain an aspect ratio. The extra size allows a
@@ -1628,7 +1627,7 @@ Returns `Boolean` - Whether the menu bar is visible.
* `visible` Boolean
* `options` Object (optional)
* `visibleOnFullScreen` Boolean (optional) _macOS_ - Sets whether
the window should be visible above fullscreen windows _deprecated_
the window should be visible above fullscreen windows
Sets whether the window should be visible on all workspaces.
@@ -1736,17 +1735,6 @@ will remove the vibrancy effect on the window.
Note that `appearance-based`, `light`, `dark`, `medium-light`, and `ultra-dark` have been
deprecated and will be removed in an upcoming version of macOS.
#### `win.setTrafficLightPosition(position)` _macOS_
* `position` [Point](structures/point.md)
Set a custom position for the traffic light buttons. Can only be used with `titleBarStyle` set to `hidden`.
#### `win.getTrafficLightPosition()` _macOS_
Returns `Point` - The current position for the traffic light buttons. Can only be used with `titleBarStyle`
set to `hidden`.
#### `win.setTouchBar(touchBar)` _macOS_ _Experimental_
* `touchBar` TouchBar | null

View File

@@ -22,9 +22,6 @@ which the request is associated.
with which the request is associated. Defaults to the empty string. The
`session` option prevails on `partition`. Thus if a `session` is explicitly
specified, `partition` is ignored.
* `useSessionCookies` Boolean (optional) - Whether to send cookies with this
request from the provided session. This will make the `net` request's
cookie behavior match a `fetch` request. Default is `false`.
* `protocol` String (optional) - The protocol scheme in the form 'scheme:'.
Currently supported values are 'http:' or 'https:'. Defaults to 'http:'.
* `host` String (optional) - The server host provided as a concatenation of
@@ -35,8 +32,8 @@ the hostname and the port number 'hostname:port'.
* `redirect` String (optional) - The redirect mode for this request. Should be
one of `follow`, `error` or `manual`. Defaults to `follow`. When mode is `error`,
any redirection will be aborted. When mode is `manual` the redirection will be
cancelled unless [`request.followRedirect`](#requestfollowredirect) is invoked
synchronously during the [`redirect`](#event-redirect) event.
deferred until [`request.followRedirect`](#requestfollowredirect) is invoked. Listen for the [`redirect`](#event-redirect) event in
this mode to get more details about the redirect request.
`options` properties such as `protocol`, `host`, `hostname`, `port` and `path`
strictly follow the Node.js model as described in the
@@ -73,8 +70,8 @@ Returns:
* `port` Integer
* `realm` String
* `callback` Function
* `username` String (optional)
* `password` String (optional)
* `username` String
* `password` String
Emitted when an authenticating proxy is asking for user credentials.
@@ -139,11 +136,8 @@ Returns:
* `redirectUrl` String
* `responseHeaders` Record<String, String[]>
Emitted when the server returns a redirect response (e.g. 301 Moved
Permanently). Calling [`request.followRedirect`](#requestfollowredirect) will
continue with the redirection. If this event is handled,
[`request.followRedirect`](#requestfollowredirect) must be called
**synchronously**, otherwise the request will be cancelled.
Emitted when there is redirection and the mode is `manual`. Calling
[`request.followRedirect`](#requestfollowredirect) will continue with the redirection.
### Instance Properties
@@ -220,8 +214,7 @@ response object,it will emit the `aborted` event.
#### `request.followRedirect()`
Continues any pending redirection. Can only be called during a `'redirect'`
event.
Continues any deferred redirection request when the redirection mode is `manual`.
#### `request.getUploadProgress()`

View File

@@ -28,14 +28,13 @@ window.electron.doThing()
### Main World
The "Main World" is the JavaScript context that your main renderer code runs in. By default, the
page you load in your renderer executes code in this world.
The "Main World" is the javascript context that your main renderer code runs in. By default the page you load in your renderer
executes code in this world.
### Isolated World
When `contextIsolation` is enabled in your `webPreferences`, your `preload` scripts run in an
"Isolated World". You can read more about context isolation and what it affects in the
[security](../tutorial/security.md#3-enable-context-isolation-for-remote-content) docs.
When `contextIsolation` is enabled in your `webPreferences` your `preload` scripts run in an "Isolated World". You can read more about
context isolation and what it affects in the [BrowserWindow](browser-window.md) docs.
## Methods
@@ -51,12 +50,12 @@ The `contextBridge` module has the following methods:
### API Objects
The `api` object provided to [`exposeInMainWorld`](#contextbridgeexposeinmainworldapikey-api-experimental) must be an object
whose keys are strings and values are a `Function`, `String`, `Number`, `Array`, `Boolean`, or another nested object that meets the same conditions.
whose keys are strings and values are a `Function`, `String`, `Number`, `Array`, `Boolean` or another nested object that meets the same conditions.
`Function` values are proxied to the other context and all other values are **copied** and **frozen**. Any data / primitives sent in
`Function` values are proxied to the other context and all other values are **copied** and **frozen**. I.e. Any data / primitives sent in
the API object become immutable and updates on either side of the bridge do not result in an update on the other side.
An example of a complex API object is shown below:
An example of a complex API object is shown below.
```javascript
const { contextBridge } = require('electron')
@@ -91,22 +90,22 @@ results in some key limitations that we've outlined below.
#### Parameter / Error / Return Type support
Because parameters, errors and return values are **copied** when they are sent over the bridge, there are only certain types that can be used.
At a high level, if the type you want to use can be serialized and deserialized into the same object it will work. A table of type support
has been included below for completeness:
Because parameters, errors and return values are **copied** when they are sent over the bridge there are only certain types that can be used.
At a high level if the type you want to use can be serialized and un-serialized into the same object it will work. A table of type support
has been included below for completeness.
| Type | Complexity | Parameter Support | Return Value Support | Limitations |
| ---- | ---------- | ----------------- | -------------------- | ----------- |
| `String` | Simple | ✅ | ✅ | N/A |
| `Number` | Simple | ✅ | ✅ | N/A |
| `Boolean` | Simple | ✅ | ✅ | N/A |
| `Object` | Complex | ✅ | ✅ | Keys must be supported using only "Simple" types in this table. Values must be supported in this table. Prototype modifications are dropped. Sending custom classes will copy values but not the prototype. |
| `Object` | Complex | ✅ | ✅ | Keys must be supported "Simple" types in this table. Values must be supported in this table. Prototype modifications are dropped. Sending custom classes will copy values but not the prototype. |
| `Array` | Complex | ✅ | ✅ | Same limitations as the `Object` type |
| `Error` | Complex | ✅ | ✅ | Errors that are thrown are also copied, this can result in the message and stack trace of the error changing slightly due to being thrown in a different context |
| `Promise` | Complex | ✅ | ✅ | Promises are only proxied if they are the return value or exact parameter. Promises nested in arrays or objects will be dropped. |
| `Promise` | Complex | ✅ | ✅ | Promises are only proxied if they are a the return value or exact parameter. Promises nested in arrays or obejcts will be dropped. |
| `Function` | Complex | ✅ | ✅ | Prototype modifications are dropped. Sending classes or constructors will not work. |
| [Cloneable Types](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm) | Simple | ✅ | ✅ | See the linked document on cloneable types |
| `Symbol` | N/A | ❌ | ❌ | Symbols cannot be copied across contexts so they are dropped |
If the type you care about is not in the above table, it is probably not supported.
If the type you care about is not in the above table it is probably not supported.

View File

@@ -91,11 +91,7 @@ The `desktopCapturer` module has the following methods:
Returns `Promise<DesktopCapturerSource[]>` - Resolves with an array of [`DesktopCapturerSource`](structures/desktop-capturer-source.md) objects, each `DesktopCapturerSource` represents a screen or an individual window that can be captured.
**Note** Capturing the screen contents requires user consent on macOS 10.15 Catalina or higher,
which can detected by [`systemPreferences.getMediaAccessStatus`].
[`navigator.mediaDevices.getUserMedia`]: https://developer.mozilla.org/en/docs/Web/API/MediaDevices/getUserMedia
[`systemPreferences.getMediaAccessStatus`]: system-preferences.md#systempreferencesgetmediaaccessstatusmediatype-macos
## Caveats

View File

@@ -120,7 +120,7 @@ Returns `Promise<Object>` - Resolve with an object containing the following:
* `canceled` Boolean - whether or not the dialog was canceled.
* `filePaths` String[] - An array of file paths chosen by the user. If the dialog is cancelled this will be an empty array.
* `bookmarks` String[] (optional) _macOS_ _mas_ - An array matching the `filePaths` array of base64 encoded strings which contains security scoped bookmark data. `securityScopedBookmarks` must be enabled for this to be populated. (For return values, see [table here](#bookmarks-array).)
* `bookmarks` String[] (optional) _macOS_ _mas_ - An array matching the `filePaths` array of base64 encoded strings which contains security scoped bookmark data. `securityScopedBookmarks` must be enabled for this to be populated.
The `browserWindow` argument allows the dialog to attach itself to a parent window, making it modal.
@@ -215,7 +215,7 @@ The `filters` specifies an array of file types that can be displayed, see
Returns `Promise<Object>` - Resolve with an object containing the following:
* `canceled` Boolean - whether or not the dialog was canceled.
* `filePath` String (optional) - If the dialog is canceled, this will be `undefined`.
* `bookmark` String (optional) _macOS_ _mas_ - Base64 encoded string which contains the security scoped bookmark data for the saved file. `securityScopedBookmarks` must be enabled for this to be present. (For return values, see [table here](#bookmarks-array).)
* `bookmark` String (optional) _macOS_ _mas_ - Base64 encoded string which contains the security scoped bookmark data for the saved file. `securityScopedBookmarks` must be enabled for this to be present.
The `browserWindow` argument allows the dialog to attach itself to a parent window, making it modal.
@@ -350,17 +350,6 @@ On Windows the options are more limited, due to the Win32 APIs used:
* The `browserWindow` argument is ignored since it is not possible to make
this confirmation dialog modal.
## Bookmarks array
`showOpenDialog`, `showOpenDialogSync`, `showSaveDialog`, and `showSaveDialogSync` will return a `bookmarks` array.
| Build Type | securityScopedBookmarks boolean | Return Type | Return Value |
|------------|---------------------------------|:-----------:|--------------------------------|
| macOS mas | True | Success | `['LONGBOOKMARKSTRING']` |
| macOS mas | True | Error | `['']` (array of empty string) |
| macOS mas | False | NA | `[]` (empty array) |
| non mas | any | NA | `[]` (empty array) |
## Sheets
On macOS, dialogs are presented as sheets attached to a window if you provide

View File

@@ -48,7 +48,6 @@ Unsupported options are:
```sh
--max-http-header-size
--http-parser
```
### `GOOGLE_API_KEY`
@@ -126,5 +125,5 @@ the `electron` command to use the specified build of Electron instead of
the one downloaded by `npm install`. Usage:
```sh
export ELECTRON_OVERRIDE_DIST_PATH=/Users/username/projects/electron/out/Debug
export ELECTRON_OVERRIDE_DIST_PATH=/Users/username/projects/electron/out/Testing
```

View File

@@ -329,9 +329,9 @@ can be called on empty images.
[buffer]: https://nodejs.org/api/buffer.html#buffer_class_buffer
### Instance Properties
## Properties
#### `nativeImage.isMacTemplateImage` _macOS_
### `nativeImage.isMacTemplateImage` _macOS_
A `Boolean` property that determines whether the image is considered a [template image](https://developer.apple.com/documentation/appkit/nsimage/1520017-template).

View File

@@ -105,45 +105,6 @@ Returns:
Emitted when a render process requests preconnection to a URL, generally due to
a [resource hint](https://w3c.github.io/resource-hints/).
#### Event: 'spellcheck-dictionary-initialized'
Returns:
* `event` Event
* `languageCode` String - The language code of the dictionary file
Emitted when a hunspell dictionary file has been successfully initialized. This
occurs after the file has been downloaded.
#### Event: 'spellcheck-dictionary-download-begin'
Returns:
* `event` Event
* `languageCode` String - The language code of the dictionary file
Emitted when a hunspell dictionary file starts downloading
#### Event: 'spellcheck-dictionary-download-success'
Returns:
* `event` Event
* `languageCode` String - The language code of the dictionary file
Emitted when a hunspell dictionary file has been successfully downloaded
#### Event: 'spellcheck-dictionary-download-failure'
Returns:
* `event` Event
* `languageCode` String - The language code of the dictionary file
Emitted when a hunspell dictionary file download fails. For details
on the failure you should collect a netlog and inspect the download
request.
### Instance Methods
The following methods are available on instances of `Session`:
@@ -503,16 +464,12 @@ The built in spellchecker does not automatically detect what language a user is
spell checker to correctly check their words you must call this API with an array of language codes. You can
get the list of supported language codes with the `ses.availableSpellCheckerLanguages` property.
**Note:** On macOS the OS spellchecker is used and will detect your language automatically. This API is a no-op on macOS.
#### `ses.getSpellCheckerLanguages()`
Returns `String[]` - An array of language codes the spellchecker is enabled for. If this list is empty the spellchecker
will fallback to using `en-US`. By default on launch if this setting is an empty list Electron will try to populate this
setting with the current OS locale. This setting is persisted across restarts.
**Note:** On macOS the OS spellchecker is used and has it's own list of languages. This API is a no-op on macOS.
#### `ses.setSpellCheckerDictionaryDownloadURL(url)`
* `url` String - A base URL for Electron to download hunspell dictionaries from.
@@ -520,22 +477,7 @@ setting with the current OS locale. This setting is persisted across restarts.
By default Electron will download hunspell dictionaries from the Chromium CDN. If you want to override this
behavior you can use this API to point the dictionary downloader at your own hosted version of the hunspell
dictionaries. We publish a `hunspell_dictionaries.zip` file with each release which contains the files you need
to host here, the file server must be **case insensitive** you must upload each file twice, once with the case it
has in the ZIP file and once with the filename as all lower case.
If the files present in `hunspell_dictionaries.zip` are available at `https://example.com/dictionaries/language-code.bdic`
then you should call this api with `ses.setSpellCheckerDictionaryDownloadURL('https://example.com/dictionaries/')`. Please
note the trailing slash. The URL to the dictionaries is formed as `${url}${filename}`.
**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.addWordToSpellCheckerDictionary(word)`
* `word` String - The word you want to add to the dictionary
Returns `Boolean` - Whether the word was successfully written to the custom dictionary.
**Note:** On macOS and Windows 10 this word will be written to the OS custom dictionary as well
to host here.
### Instance Properties

View File

@@ -24,11 +24,14 @@ The `shell` module has the following methods:
Show the given file in a file manager. If possible, select the file.
### `shell.openItem(fullPath)`
### `shell.openPath(path)`
* `fullPath` String
* `path` String
Returns `Boolean` - Whether the item was successfully opened.
Returns `Promise<Object>` - Resolve with an object containing the following:
* `success` Boolean - whether or not the path was successfully opened in the desktop's default manner.
* `errorMessage` String (optional) - The error message corresponding to the failure if a failure occurred, otherwise empty string.
Open the given file in the desktop's default manner.

View File

@@ -369,6 +369,14 @@ Returns `String` - Can be `dark`, `light` or `unknown`.
Gets the macOS appearance setting that is currently applied to your application,
maps to [NSApplication.effectiveAppearance](https://developer.apple.com/documentation/appkit/nsapplication/2967171-effectiveappearance?language=objc)
Please note that until Electron is built targeting the 10.14 SDK, your application's
`effectiveAppearance` will default to 'light' and won't inherit the OS preference. In
the interim in order for your application to inherit the OS preference you must set the
`NSRequiresAquaSystemAppearance` key in your apps `Info.plist` to `false`. If you are
using `electron-packager` or `electron-forge` just set the `enableDarwinDarkMode`
packager option to `true`. See the [Electron Packager API](https://github.com/electron/electron-packager/blob/master/docs/api.md#darwindarkmodesupport)
for more details.
**[Deprecated](modernization/property-updates.md)**
### `systemPreferences.getAppLevelAppearance()` _macOS_ _Deprecated_
@@ -396,6 +404,8 @@ Returns `Boolean` - whether or not this device has the ability to use Touch ID.
**NOTE:** This API will return `false` on macOS systems older than Sierra 10.12.2.
**[Deprecated](modernization/property-updates.md)**
### `systemPreferences.promptTouchID(reason)` _macOS_
* `reason` String - The reason you are asking for Touch ID authentication
@@ -424,13 +434,11 @@ Returns `Boolean` - `true` if the current process is a trusted accessibility cli
### `systemPreferences.getMediaAccessStatus(mediaType)` _macOS_
* `mediaType` String - Can be `microphone`, `camera` or `screen`.
* `mediaType` String - `microphone` or `camera`.
Returns `String` - Can be `not-determined`, `granted`, `denied`, `restricted` or `unknown`.
This user consent was not required on macOS 10.13 High Sierra or lower so this method will always return `granted`.
macOS 10.14 Mojave or higher requires consent for `microphone` and `camera` access.
macOS 10.15 Catalina or higher requires consent for `screen` access.
This user consent was not required until macOS 10.14 Mojave, so this method will always return `granted` if your system is running 10.13 High Sierra or lower.
### `systemPreferences.askForMediaAccess(mediaType)` _macOS_
@@ -470,3 +478,11 @@ A `String` property that can be `dark`, `light` or `unknown`.
Returns the macOS appearance setting that is currently applied to your application,
maps to [NSApplication.effectiveAppearance](https://developer.apple.com/documentation/appkit/nsapplication/2967171-effectiveappearance?language=objc)
Please note that until Electron is built targeting the 10.14 SDK, your application's
`effectiveAppearance` will default to 'light' and won't inherit the OS preference. In
the interim in order for your application to inherit the OS preference you must set the
`NSRequiresAquaSystemAppearance` key in your apps `Info.plist` to `false`. If you are
using `electron-packager` or `electron-forge` just set the `enableDarwinDarkMode`
packager option to `true`. See the [Electron Packager API](https://github.com/electron/electron-packager/blob/master/docs/api.md#darwindarkmodesupport)
for more details.

View File

@@ -14,6 +14,7 @@ Process: [Main](../tutorial/application-architecture.md#main-and-renderer-proces
* `icon` [NativeImage](native-image.md) | String (optional) - Button icon.
* `iconPosition` String (optional) - Can be `left`, `right` or `overlay`. Defaults to `overlay`.
* `click` Function (optional) - Function to call when the button is clicked.
* `enabled` Boolean (optional) - Whether the button is in an enabled state. Default is `true`.
When defining `accessibilityLabel`, ensure you have considered macOS [best practices](https://developer.apple.com/documentation/appkit/nsaccessibilitybutton/1524910-accessibilitylabel?language=objc).
@@ -39,3 +40,7 @@ the button in the touch bar.
A `NativeImage` representing the button's current icon. Changing this value immediately updates the button
in the touch bar.
#### `touchBarButton.enabled`
A `Boolean` representing whether the button is in an enabled state.

View File

@@ -454,8 +454,10 @@ The usage is the same with [the `select-client-certificate` event of
Returns:
* `event` Event
* `authenticationResponseDetails` Object
* `request` Object
* `method` String
* `url` URL
* `referrer` URL
* `authInfo` Object
* `isProxy` Boolean
* `scheme` String
@@ -463,8 +465,8 @@ Returns:
* `port` Integer
* `realm` String
* `callback` Function
* `username` String (optional)
* `password` String (optional)
* `username` String
* `password` String
Emitted when `webContents` wants to do basic auth.
@@ -1042,17 +1044,6 @@ contents.executeJavaScript('fetch("https://jsonplaceholder.typicode.com/users/1"
})
```
#### `contents.executeJavaScriptInIsolatedWorld(worldId, scripts[, userGesture])`
* `worldId` Integer - The ID of the world to run the javascript in, `0` is the default world, `999` is the world used by Electron's `contextIsolation` feature. You can provide any integer here.
* `scripts` [WebSource[]](structures/web-source.md)
* `userGesture` Boolean (optional) - Default is `false`.
Returns `Promise<any>` - A promise that resolves with the result of the executed code
or is rejected if the result of the code is a rejected promise.
Works like `executeJavaScript` but evaluates `scripts` in an isolated context.
#### `contents.setIgnoreMenuShortcuts(ignore)` _Experimental_
* `ignore` Boolean
@@ -1079,13 +1070,11 @@ Returns `Boolean` - Whether audio is currently playing.
#### `contents.setZoomFactor(factor)`
* `factor` Double - Zoom factor; default is 1.0.
* `factor` Number - Zoom factor.
Changes the zoom factor to the specified factor. Zoom factor is
zoom percent divided by 100, so 300% = 3.0.
The factor must be greater than 0.0.
**[Deprecated](modernization/property-updates.md)**
#### `contents.getZoomFactor()`
@@ -1126,7 +1115,7 @@ Sets the maximum and minimum pinch-to-zoom level.
> contents.setVisualZoomLevelLimits(1, 3)
> ```
#### `contents.setLayoutZoomLevelLimits(minimumLevel, maximumLevel)` _Deprecated_
#### `contents.setLayoutZoomLevelLimits(minimumLevel, maximumLevel)`
* `minimumLevel` Number
* `maximumLevel` Number
@@ -1135,8 +1124,6 @@ Returns `Promise<void>`
Sets the maximum and minimum layout-based (i.e. non-visual) zoom level.
**Deprecated:** This API is no longer supported by Chromium.
#### `contents.undo()`
Executes the editing command `undo` in web page.
@@ -1249,34 +1236,11 @@ Returns `Promise<NativeImage>` - Resolves with a [NativeImage](native-image.md)
Captures a snapshot of the page within `rect`. Omitting `rect` will capture the whole visible page.
#### `contents.isBeingCaptured()`
Returns `Boolean` - Whether this page is being captured. It returns true when the capturer count
is large then 0.
#### `contents.incrementCapturerCount([size, stayHidden])`
* `size` [Size](structures/size.md) (optional) - The perferred size for the capturer.
* `stayHidden` Boolean (optional) - Keep the page hidden instead of visible.
Increase the capturer count by one. The page is considered visible when its browser window is
hidden and the capturer count is non-zero. If you would like the page to stay hidden, you should ensure that `stayHidden` is set to true.
This also affects the Page Visibility API.
#### `contents.decrementCapturerCount([stayHidden])`
* `stayHidden` Boolean (optional) - Keep the page in hidden state instead of visible.
Decrease the capturer count by one. The page will be set to hidden or occluded state when its
browser window is hidden or occluded and the capturer count reaches zero. If you want to
decrease the hidden capturer count instead you should set `stayHidden` to true.
#### `contents.getPrinters()`
Get the system printer list.
Returns [`PrinterInfo[]`](structures/printer-info.md)
Returns [`PrinterInfo[]`](structures/printer-info.md).
#### `contents.print([options], [callback])`
@@ -1284,7 +1248,7 @@ Returns [`PrinterInfo[]`](structures/printer-info.md)
* `silent` Boolean (optional) - Don't ask user for print settings. Default is `false`.
* `printBackground` Boolean (optional) - Prints the background color and image of
the web page. Default is `false`.
* `deviceName` String (optional) - Set the printer device name to use. Must be the system-defined name and not the 'friendly' name, e.g 'Brother_QL_820NWB' and not 'Brother QL-820NWB'.
* `deviceName` String (optional) - Set the printer device name to use. Default is `''`.
* `color` Boolean (optional) - Set whether the printed web page will be in color or grayscale. Default is `true`.
* `margins` Object (optional)
* `marginType` String (optional) - Can be `default`, `none`, `printableArea`, or `custom`. If `custom` is chosen, you will also need to specify `top`, `bottom`, `left`, and `right`.
@@ -1306,7 +1270,7 @@ Returns [`PrinterInfo[]`](structures/printer-info.md)
* `footer` String (optional) - String to be printed as page footer.
* `callback` Function (optional)
* `success` Boolean - Indicates success of the print call.
* `failureReason` String - Error description called back if the print fails.
* `failureReason` String - Called back if the print fails; can be `cancelled` or `failed`.
Prints window's web page. When `silent` is set to `true`, Electron will pick
the system's default printer if `deviceName` is empty and the default settings for printing.
@@ -1365,13 +1329,12 @@ win.loadURL('http://github.com')
win.webContents.on('did-finish-load', () => {
// Use default printing options
win.webContents.printToPDF({}).then(data => {
win.webContents.printToPDF({}, (error, data) => {
if (error) throw error
fs.writeFile('/tmp/print.pdf', data, (error) => {
if (error) throw error
console.log('Write PDF successfully.')
})
}).catch(error => {
console.log(error)
})
})
```

View File

@@ -22,13 +22,11 @@ The `WebFrame` class has the following instance methods:
### `webFrame.setZoomFactor(factor)`
* `factor` Double - Zoom factor; default is 1.0.
* `factor` Number - Zoom factor.
Changes the zoom factor to the specified factor. Zoom factor is
zoom percent divided by 100, so 300% = 3.0.
The factor must be greater than 0.0.
### `webFrame.getZoomFactor()`
Returns `Number` - The current zoom factor.
@@ -58,15 +56,13 @@ Sets the maximum and minimum pinch-to-zoom level.
> webFrame.setVisualZoomLevelLimits(1, 3)
> ```
### `webFrame.setLayoutZoomLevelLimits(minimumLevel, maximumLevel)` _Deprecated_
### `webFrame.setLayoutZoomLevelLimits(minimumLevel, maximumLevel)`
* `minimumLevel` Number
* `maximumLevel` Number
Sets the maximum and minimum layout-based (i.e. non-visual) zoom level.
**Deprecated:** This API is no longer supported by Chromium.
### `webFrame.setSpellCheckProvider(language, provider)`
* `language` String

View File

@@ -146,8 +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)
* `responseHeaders` Record<string, string> (optional)
* `callback` Function
* `headersReceivedResponse` Object
* `cancel` Boolean (optional)
@@ -176,7 +175,7 @@ The `callback` has to be called with a `response` object.
* `resourceType` String
* `referrer` String
* `timestamp` Double
* `responseHeaders` Record<string, string[]> (optional)
* `responseHeaders` Record<string, string> (optional)
* `fromCache` Boolean - Indicates whether the response was fetched from disk
cache.
* `statusCode` Integer
@@ -206,7 +205,7 @@ and response headers are available.
* `ip` String (optional) - The server IP address that the request was
actually sent to.
* `fromCache` Boolean
* `responseHeaders` Record<string, string[]> (optional)
* `responseHeaders` Record<string, string> (optional)
The `listener` will be called with `listener(details)` when a server initiated
redirect is about to occur.
@@ -225,11 +224,10 @@ redirect is about to occur.
* `resourceType` String
* `referrer` String
* `timestamp` Double
* `responseHeaders` Record<string, string[]> (optional)
* `responseHeaders` Record<string, string> (optional)
* `fromCache` Boolean
* `statusCode` Integer
* `statusLine` String
* `error` String
The `listener` will be called with `listener(details)` when a request is
completed.

View File

@@ -635,7 +635,7 @@ Returns `Promise<void>`
Sets the maximum and minimum pinch-to-zoom level.
### `<webview>.setLayoutZoomLevelLimits(minimumLevel, maximumLevel)` _Deprecated_
### `<webview>.setLayoutZoomLevelLimits(minimumLevel, maximumLevel)`
* `minimumLevel` Number
* `maximumLevel` Number
@@ -644,8 +644,6 @@ Returns `Promise<void>`
Sets the maximum and minimum layout-based (i.e. non-visual) zoom level.
**Deprecated:** This API is no longer supported by Chromium.
### `<webview>.showDefinitionForSelection()` _macOS_
Shows pop-up dictionary that searches the selected word on the page.

View File

@@ -96,30 +96,30 @@ $ cd src
$ export CHROMIUM_BUILDTOOLS_PATH=`pwd`/buildtools
# this next line is needed only if building with sccache
$ export GN_EXTRA_ARGS="${GN_EXTRA_ARGS} cc_wrapper=\"${PWD}/electron/external_binaries/sccache\""
$ gn gen out/Debug --args="import(\"//electron/build/args/debug.gn\") $GN_EXTRA_ARGS"
$ gn gen out/Testing --args="import(\"//electron/build/args/testing.gn\") $GN_EXTRA_ARGS"
```
Or on Windows (without the optional argument):
```sh
$ cd src
$ set CHROMIUM_BUILDTOOLS_PATH=%cd%\buildtools
$ gn gen out/Debug --args="import(\"//electron/build/args/debug.gn\")"
$ gn gen out/Testing --args="import(\"//electron/build/args/testing.gn\")"
```
This will generate a build directory `out/Debug` under `src/` with
debug build configuration. You can replace `Debug` with another name,
This will generate a build directory `out/Testing` under `src/` with
the testing build configuration. You can replace `Testing` with another name,
but it should be a subdirectory of `out`.
Also you shouldn't have to run `gn gen` again—if you want to change the
build arguments, you can run `gn args out/Debug` to bring up an editor.
build arguments, you can run `gn args out/Testing` to bring up an editor.
To see the list of available build configuration options, run `gn args
out/Debug --list`.
out/Testing --list`.
**For generating Debug (aka "component" or "shared") build config of
**For generating Testing build config of
Electron:**
```sh
$ gn gen out/Debug --args="import(\"//electron/build/args/debug.gn\") $GN_EXTRA_ARGS"
$ gn gen out/Testing --args="import(\"//electron/build/args/testing.gn\") $GN_EXTRA_ARGS"
```
**For generating Release (aka "non-component" or "static") build config of
@@ -132,9 +132,9 @@ $ gn gen out/Release --args="import(\"//electron/build/args/release.gn\") $GN_EX
**To build, run `ninja` with the `electron` target:**
Nota Bene: This will also take a while and probably heat up your lap.
For the debug configuration:
For the testing configuration:
```sh
$ ninja -C out/Debug electron
$ ninja -C out/Testing electron
```
For the release configuration:
@@ -147,19 +147,19 @@ This will build all of what was previously 'libchromiumcontent' (i.e. the
so it will take a while.
To speed up subsequent builds, you can use [sccache][sccache]. Add the GN arg
`cc_wrapper = "sccache"` by running `gn args out/Debug` to bring up an
`cc_wrapper = "sccache"` by running `gn args out/Testing` to bring up an
editor and adding a line to the end of the file.
[sccache]: https://github.com/mozilla/sccache
The built executable will be under `./out/Debug`:
The built executable will be under `./out/Testing`:
```sh
$ ./out/Debug/Electron.app/Contents/MacOS/Electron
$ ./out/Testing/Electron.app/Contents/MacOS/Electron
# or, on Windows
$ ./out/Debug/electron.exe
$ ./out/Testing/electron.exe
# or, on Linux
$ ./out/Debug/electron
$ ./out/Testing/electron
```
### Packaging
@@ -181,7 +181,7 @@ set the `target_cpu` and `target_os` GN arguments. For example, to compile an
x86 target from an x64 host, specify `target_cpu = "x86"` in `gn args`.
```sh
$ gn gen out/Debug-x86 --args='... target_cpu = "x86"'
$ gn gen out/Testing-x86 --args='... target_cpu = "x86"'
```
Not all combinations of source and target CPU/OS are supported by Chromium.
@@ -226,7 +226,7 @@ generate build headers for the modules to compile against, run the following
under `src/` directory.
```sh
$ ninja -C out/Debug third_party/electron_node:headers
$ ninja -C out/Testing third_party/electron_node:headers
```
You can now [run the tests](testing.md#unit-tests).
@@ -235,8 +235,8 @@ If you're debugging something, it can be helpful to pass some extra flags to
the Electron binary:
```sh
$ ./out/Debug/Electron.app/Contents/MacOS/Electron electron/spec \
--ci --enable-logging -g 'BrowserWindow module'
$ npm run test -- \
--enable-logging -g 'BrowserWindow module'
```
## Sharing the git cache between multiple machines

View File

@@ -79,7 +79,7 @@ And to cross-compile for `arm` or `ia32` targets, you should pass the
`target_cpu` parameter to `gn gen`:
```sh
$ gn gen out/Debug --args='import(...) target_cpu="arm"'
$ gn gen out/Testing --args='import(...) target_cpu="arm"'
```
## Building
@@ -114,7 +114,7 @@ GN args.
For example if you installed `clang` under `/usr/local/bin/clang`:
```sh
$ gn gen out/Debug --args='import("//electron/build/args/debug.gn") clang_base_path = "/usr/local/bin"'
$ gn gen out/Testing --args='import("//electron/build/args/testing.gn") clang_base_path = "/usr/local/bin"'
```
### Using compilers other than `clang`

View File

@@ -74,7 +74,7 @@ To generate a Visual Studio project, you can pass the `--ide=vs2017` parameter
to `gn gen`:
```powershell
$ gn gen out/Debug --ide=vs2017
$ gn gen out/Testing --ide=vs2017
```
## Troubleshooting

View File

@@ -54,7 +54,7 @@ formatted correctly.
the `module-name` form. This rule only applies to `.js` files.
* Use newer ES6/ES2015 syntax where appropriate
* [`const`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const)
for requires and other constants
for requires and other constants. If the value is a primitive, use uppercase naming (eg `const NUMBER_OF_RETRIES = 5`).
* [`let`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let)
for defining variables
* [Arrow functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions)

View File

@@ -36,7 +36,7 @@ To start a debugging session, open up PowerShell/CMD and execute your debug
build of Electron, using the application to open as a parameter.
```powershell
$ ./out/Debug/electron.exe ~/my-electron-app/
$ ./out/Testing/electron.exe ~/my-electron-app/
```
### Setting Breakpoints

View File

@@ -3,7 +3,7 @@
### Generate xcode project for debugging sources (cannot build code from xcode)
Run `gn gen` with the --ide=xcode argument.
```sh
$ gn gen out/Debug --ide=xcode
$ gn gen out/Testing --ide=xcode
```
This will generate the electron.ninja.xcworkspace. You will have to open this workspace
to set breakpoints and inspect.

View File

@@ -25,13 +25,13 @@ you prefer a graphical interface.
## Attaching to and Debugging Electron
To start a debugging session, open up Terminal and start `lldb`, passing a debug
To start a debugging session, open up Terminal and start `lldb`, passing a non-release
build of Electron as a parameter.
```sh
$ lldb ./out/Debug/Electron.app
(lldb) target create "./out/Debug/Electron.app"
Current executable set to './out/Debug/Electron.app' (x86_64).
$ lldb ./out/Testing/Electron.app
(lldb) target create "./out/Testing/Electron.app"
Current executable set to './out/Testing/Electron.app' (x86_64).
```
### Setting Breakpoints
@@ -62,7 +62,7 @@ The app will immediately be paused, since Electron sets the app's name on launch
```sh
(lldb) run
Process 25244 launched: '/Users/fr/Code/electron/out/Debug/Electron.app/Contents/MacOS/Electron' (x86_64)
Process 25244 launched: '/Users/fr/Code/electron/out/Testing/Electron.app/Contents/MacOS/Electron' (x86_64)
Process 25244 stopped
* thread #1: tid = 0x839a4c, 0x0000000100162db4 Electron Framework`atom::Browser::SetName(this=0x0000000108b14f20, name="Electron") + 20 at browser.cc:118, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x0000000100162db4 Electron Framework`atom::Browser::SetName(this=0x0000000108b14f20, name="Electron") + 20 at browser.cc:118

View File

@@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<div>
<div>
<h1>Synchronous messages</h1>
<i>Supports: Win, macOS, Linux <span>|</span> Process: Both</i>
<div>
<div>
<button id="sync-msg">Ping</button>
<span id="sync-reply"></span>
</div>
<p>You can use the <code>ipc</code> module to send synchronous messages between processes as well, but note that the synchronous nature of this method means that it <b>will block</b> other operations while completing its task.</p>
<p>This example sends a synchronous message, "ping", from this process (renderer) to the main process. The main process then replies with "pong".</p>
</div>
</div>
</div>
<script>
// You can also require other files to run in this process
require('./renderer.js')
</script>
</body>
</html>

View File

@@ -0,0 +1,29 @@
const { app, BrowserWindow, ipcMain } = require('electron')
let mainWindow = null
function createWindow () {
const windowOptions = {
width: 600,
height: 400,
title: 'Synchronous Messages',
webPreferences: {
nodeIntegration: true
}
}
mainWindow = new BrowserWindow(windowOptions)
mainWindow.loadFile('index.html')
mainWindow.on('closed', () => {
mainWindow = null
})
}
app.on('ready', () => {
createWindow()
})
ipcMain.on('synchronous-message', (event, arg) => {
event.returnValue = 'pong'
})

View File

@@ -0,0 +1,9 @@
const { ipcRenderer } = require('electron')
const syncMsgBtn = document.getElementById('sync-msg')
syncMsgBtn.addEventListener('click', () => {
const reply = ipcRenderer.sendSync('synchronous-message', 'ping')
const message = `Synchronous message reply: ${reply}`
document.getElementById('sync-reply').innerHTML = message
})

View File

@@ -1,360 +1,360 @@
// Modules to control application life and create native browser window
const {
BrowserWindow,
Menu,
MenuItem,
ipcMain,
app,
shell,
dialog
} = require('electron')
const menu = new Menu()
menu.append(new MenuItem({ label: 'Hello' }))
menu.append(new MenuItem({ type: 'separator' }))
menu.append(
new MenuItem({ label: 'Electron', type: 'checkbox', checked: true })
)
const template = [
{
label: 'Edit',
submenu: [
{
label: 'Undo',
accelerator: 'CmdOrCtrl+Z',
role: 'undo'
},
{
label: 'Redo',
accelerator: 'Shift+CmdOrCtrl+Z',
role: 'redo'
},
{
type: 'separator'
},
{
label: 'Cut',
accelerator: 'CmdOrCtrl+X',
role: 'cut'
},
{
label: 'Copy',
accelerator: 'CmdOrCtrl+C',
role: 'copy'
},
{
label: 'Paste',
accelerator: 'CmdOrCtrl+V',
role: 'paste'
},
{
label: 'Select All',
accelerator: 'CmdOrCtrl+A',
role: 'selectall'
}
]
},
{
label: 'View',
submenu: [
{
label: 'Reload',
accelerator: 'CmdOrCtrl+R',
click: (item, focusedWindow) => {
if (focusedWindow) {
// on reload, start fresh and close any old
// open secondary windows
if (focusedWindow.id === 1) {
BrowserWindow.getAllWindows().forEach(win => {
if (win.id > 1) win.close()
})
}
focusedWindow.reload()
}
}
},
{
label: 'Toggle Full Screen',
accelerator: (() => {
if (process.platform === 'darwin') {
return 'Ctrl+Command+F'
} else {
return 'F11'
}
})(),
click: (item, focusedWindow) => {
if (focusedWindow) {
focusedWindow.setFullScreen(!focusedWindow.isFullScreen())
}
}
},
{
label: 'Toggle Developer Tools',
accelerator: (() => {
if (process.platform === 'darwin') {
return 'Alt+Command+I'
} else {
return 'Ctrl+Shift+I'
}
})(),
click: (item, focusedWindow) => {
if (focusedWindow) {
focusedWindow.toggleDevTools()
}
}
},
{
type: 'separator'
},
{
label: 'App Menu Demo',
click: function (item, focusedWindow) {
if (focusedWindow) {
const options = {
type: 'info',
title: 'Application Menu Demo',
buttons: ['Ok'],
message:
'This demo is for the Menu section, showing how to create a clickable menu item in the application menu.'
}
dialog.showMessageBox(focusedWindow, options, function () {})
}
}
}
]
},
{
label: 'Window',
role: 'window',
submenu: [
{
label: 'Minimize',
accelerator: 'CmdOrCtrl+M',
role: 'minimize'
},
{
label: 'Close',
accelerator: 'CmdOrCtrl+W',
role: 'close'
},
{
type: 'separator'
},
{
label: 'Reopen Window',
accelerator: 'CmdOrCtrl+Shift+T',
enabled: false,
key: 'reopenMenuItem',
click: () => {
app.emit('activate')
}
}
]
},
{
label: 'Help',
role: 'help',
submenu: [
{
label: 'Learn More',
click: () => {
shell.openExternal('http://electron.atom.io')
}
}
]
}
]
function addUpdateMenuItems (items, position) {
if (process.mas) return
const version = app.getVersion()
const updateItems = [
{
label: `Version ${version}`,
enabled: false
},
{
label: 'Checking for Update',
enabled: false,
key: 'checkingForUpdate'
},
{
label: 'Check for Update',
visible: false,
key: 'checkForUpdate',
click: () => {
require('electron').autoUpdater.checkForUpdates()
}
},
{
label: 'Restart and Install Update',
enabled: true,
visible: false,
key: 'restartToUpdate',
click: () => {
require('electron').autoUpdater.quitAndInstall()
}
}
]
items.splice.apply(items, [position, 0].concat(updateItems))
}
function findReopenMenuItem () {
const menu = Menu.getApplicationMenu()
if (!menu) return
let reopenMenuItem
menu.items.forEach(item => {
if (item.submenu) {
item.submenu.items.forEach(item => {
if (item.key === 'reopenMenuItem') {
reopenMenuItem = item
}
})
}
})
return reopenMenuItem
}
if (process.platform === 'darwin') {
const name = app.getName()
template.unshift({
label: name,
submenu: [
{
label: `About ${name}`,
role: 'about'
},
{
type: 'separator'
},
{
label: 'Services',
role: 'services',
submenu: []
},
{
type: 'separator'
},
{
label: `Hide ${name}`,
accelerator: 'Command+H',
role: 'hide'
},
{
label: 'Hide Others',
accelerator: 'Command+Alt+H',
role: 'hideothers'
},
{
label: 'Show All',
role: 'unhide'
},
{
type: 'separator'
},
{
label: 'Quit',
accelerator: 'Command+Q',
click: () => {
app.quit()
}
}
]
})
// Window menu.
template[3].submenu.push(
{
type: 'separator'
},
{
label: 'Bring All to Front',
role: 'front'
}
)
addUpdateMenuItems(template[0].submenu, 1)
}
if (process.platform === 'win32') {
const helpMenu = template[template.length - 1].submenu
addUpdateMenuItems(helpMenu, 0)
}
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null
})
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', () => {
createWindow()
const menu = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(menu)
})
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
const reopenMenuItem = findReopenMenuItem()
if (reopenMenuItem) reopenMenuItem.enabled = true
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow()
}
})
app.on('browser-window-created', (event, win) => {
const reopenMenuItem = findReopenMenuItem()
if (reopenMenuItem) reopenMenuItem.enabled = false
win.webContents.on('context-menu', (e, params) => {
menu.popup(win, params.x, params.y)
})
})
ipcMain.on('show-context-menu', event => {
const win = BrowserWindow.fromWebContents(event.sender)
menu.popup(win)
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
// Modules to control application life and create native browser window
const {
BrowserWindow,
Menu,
MenuItem,
ipcMain,
app,
shell,
dialog
} = require('electron')
const menu = new Menu()
menu.append(new MenuItem({ label: 'Hello' }))
menu.append(new MenuItem({ type: 'separator' }))
menu.append(
new MenuItem({ label: 'Electron', type: 'checkbox', checked: true })
)
const template = [
{
label: 'Edit',
submenu: [
{
label: 'Undo',
accelerator: 'CmdOrCtrl+Z',
role: 'undo'
},
{
label: 'Redo',
accelerator: 'Shift+CmdOrCtrl+Z',
role: 'redo'
},
{
type: 'separator'
},
{
label: 'Cut',
accelerator: 'CmdOrCtrl+X',
role: 'cut'
},
{
label: 'Copy',
accelerator: 'CmdOrCtrl+C',
role: 'copy'
},
{
label: 'Paste',
accelerator: 'CmdOrCtrl+V',
role: 'paste'
},
{
label: 'Select All',
accelerator: 'CmdOrCtrl+A',
role: 'selectall'
}
]
},
{
label: 'View',
submenu: [
{
label: 'Reload',
accelerator: 'CmdOrCtrl+R',
click: (item, focusedWindow) => {
if (focusedWindow) {
// on reload, start fresh and close any old
// open secondary windows
if (focusedWindow.id === 1) {
BrowserWindow.getAllWindows().forEach(win => {
if (win.id > 1) win.close()
})
}
focusedWindow.reload()
}
}
},
{
label: 'Toggle Full Screen',
accelerator: (() => {
if (process.platform === 'darwin') {
return 'Ctrl+Command+F'
} else {
return 'F11'
}
})(),
click: (item, focusedWindow) => {
if (focusedWindow) {
focusedWindow.setFullScreen(!focusedWindow.isFullScreen())
}
}
},
{
label: 'Toggle Developer Tools',
accelerator: (() => {
if (process.platform === 'darwin') {
return 'Alt+Command+I'
} else {
return 'Ctrl+Shift+I'
}
})(),
click: (item, focusedWindow) => {
if (focusedWindow) {
focusedWindow.toggleDevTools()
}
}
},
{
type: 'separator'
},
{
label: 'App Menu Demo',
click: function (item, focusedWindow) {
if (focusedWindow) {
const options = {
type: 'info',
title: 'Application Menu Demo',
buttons: ['Ok'],
message:
'This demo is for the Menu section, showing how to create a clickable menu item in the application menu.'
}
dialog.showMessageBox(focusedWindow, options, function () {})
}
}
}
]
},
{
label: 'Window',
role: 'window',
submenu: [
{
label: 'Minimize',
accelerator: 'CmdOrCtrl+M',
role: 'minimize'
},
{
label: 'Close',
accelerator: 'CmdOrCtrl+W',
role: 'close'
},
{
type: 'separator'
},
{
label: 'Reopen Window',
accelerator: 'CmdOrCtrl+Shift+T',
enabled: false,
key: 'reopenMenuItem',
click: () => {
app.emit('activate')
}
}
]
},
{
label: 'Help',
role: 'help',
submenu: [
{
label: 'Learn More',
click: () => {
shell.openExternal('http://electron.atom.io')
}
}
]
}
]
function addUpdateMenuItems (items, position) {
if (process.mas) return
const version = app.getVersion()
const updateItems = [
{
label: `Version ${version}`,
enabled: false
},
{
label: 'Checking for Update',
enabled: false,
key: 'checkingForUpdate'
},
{
label: 'Check for Update',
visible: false,
key: 'checkForUpdate',
click: () => {
require('electron').autoUpdater.checkForUpdates()
}
},
{
label: 'Restart and Install Update',
enabled: true,
visible: false,
key: 'restartToUpdate',
click: () => {
require('electron').autoUpdater.quitAndInstall()
}
}
]
items.splice.apply(items, [position, 0].concat(updateItems))
}
function findReopenMenuItem () {
const menu = Menu.getApplicationMenu()
if (!menu) return
let reopenMenuItem
menu.items.forEach(item => {
if (item.submenu) {
item.submenu.items.forEach(item => {
if (item.key === 'reopenMenuItem') {
reopenMenuItem = item
}
})
}
})
return reopenMenuItem
}
if (process.platform === 'darwin') {
const name = app.getName()
template.unshift({
label: name,
submenu: [
{
label: `About ${name}`,
role: 'about'
},
{
type: 'separator'
},
{
label: 'Services',
role: 'services',
submenu: []
},
{
type: 'separator'
},
{
label: `Hide ${name}`,
accelerator: 'Command+H',
role: 'hide'
},
{
label: 'Hide Others',
accelerator: 'Command+Alt+H',
role: 'hideothers'
},
{
label: 'Show All',
role: 'unhide'
},
{
type: 'separator'
},
{
label: 'Quit',
accelerator: 'Command+Q',
click: () => {
app.quit()
}
}
]
})
// Window menu.
template[3].submenu.push(
{
type: 'separator'
},
{
label: 'Bring All to Front',
role: 'front'
}
)
addUpdateMenuItems(template[0].submenu, 1)
}
if (process.platform === 'win32') {
const helpMenu = template[template.length - 1].submenu
addUpdateMenuItems(helpMenu, 0)
}
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null
})
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', () => {
createWindow()
const menu = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(menu)
})
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
const reopenMenuItem = findReopenMenuItem()
if (reopenMenuItem) reopenMenuItem.enabled = true
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow()
}
})
app.on('browser-window-created', (event, win) => {
const reopenMenuItem = findReopenMenuItem()
if (reopenMenuItem) reopenMenuItem.enabled = false
win.webContents.on('context-menu', (e, params) => {
menu.popup(win, params.x, params.y)
})
})
ipcMain.on('show-context-menu', event => {
const win = BrowserWindow.fromWebContents(event.sender)
menu.popup(win)
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.

View File

@@ -1,8 +1,8 @@
const { ipcRenderer } = require('electron')
// Tell main process to show the menu when demo button is clicked
const contextMenuBtn = document.getElementById('context-menu')
contextMenuBtn.addEventListener('click', () => {
ipcRenderer.send('show-context-menu')
})
const { ipcRenderer } = require('electron')
// Tell main process to show the menu when demo button is clicked
const contextMenuBtn = document.getElementById('context-menu')
contextMenuBtn.addEventListener('click', () => {
ipcRenderer.send('show-context-menu')
})

View File

@@ -0,0 +1,81 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Error Dialog</title>
</head>
<body>
<div>
<h1>Use system dialogs</h1>
<h3>
The <code>dialog</code> module in Electron allows you to use native
system dialogs for opening files or directories, saving a file or
displaying informational messages.
</h3>
<p>
This is a main process module because this process is more efficient
with native utilities and it allows the call to happen without
interrupting the visible elements in your page's renderer process.
</p>
<p>
Open the
<a href="http://electron.atom.io/docs/api/dialog/">
full API documentation (opens in new window)
</a>
in your browser.
</p>
</div>
<div>
<div>
<h2>Error Dialog</h2>
<div>
<div>
<button id="error-dialog">View Demo</button>
</div>
<p>
In this demo, the <code>ipc</code> module is used to send a message
from the renderer process instructing the main process to launch the
error dialog.
</p>
<p>
You can use an error dialog before the app's
<code>ready</code> event, which is useful for showing errors upon
startup.
</p>
<h5>Renderer Process</h5>
<pre>
<code>
const {ipcRenderer} = require('electron')
const errorBtn = document.getElementById('error-dialog')
errorBtn.addEventListener('click', (event) => {
ipcRenderer.send('open-error-dialog')
})
</code></pre>
<h5>Main Process</h5>
<pre>
<code>
const {ipcMain, dialog} = require('electron')
ipcMain.on('open-error-dialog', (event) => {
dialog.showErrorBox('An Error Message', 'Demonstrating an error message.')
})
</code>
</pre>
</div>
</div>
</div>
<script>
// You can also require other files to run in this process
require("./renderer.js");
</script>
</body>
</html>

View File

@@ -0,0 +1,95 @@
// Modules to control application life and create native browser window
const { app, BrowserWindow, ipcMain, dialog } = require('electron')
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null
})
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow)
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow()
}
})
ipcMain.on('open-error-dialog', event => {
dialog.showErrorBox('An Error Message', 'Demonstrating an error message.')
})
ipcMain.on('open-information-dialog', event => {
const options = {
type: 'info',
title: 'Information',
message: "This is an information dialog. Isn't it nice?",
buttons: ['Yes', 'No']
}
dialog.showMessageBox(options, index => {
event.sender.send('information-dialog-selection', index)
})
})
ipcMain.on('open-file-dialog', event => {
dialog.showOpenDialog(
{
properties: ['openFile', 'openDirectory']
},
files => {
if (files) {
event.sender.send('selected-directory', files)
}
}
)
})
ipcMain.on('save-dialog', event => {
const options = {
title: 'Save an Image',
filters: [{ name: 'Images', extensions: ['jpg', 'png', 'gif'] }]
}
dialog.showSaveDialog(options, filename => {
event.sender.send('saved-file', filename)
})
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.

View File

@@ -0,0 +1,18 @@
const { ipcRenderer, shell } = require('electron')
const links = document.querySelectorAll('a[href]')
const errorBtn = document.getElementById('error-dialog')
errorBtn.addEventListener('click', event => {
ipcRenderer.send('open-error-dialog')
})
Array.prototype.forEach.call(links, (link) => {
const url = link.getAttribute('href')
if (url.indexOf('http') === 0) {
link.addEventListener('click', (e) => {
e.preventDefault()
shell.openExternal(url)
})
}
})

View File

@@ -0,0 +1,104 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Information Dialog</title>
</head>
<body>
<div class="section-wrapper">
<h1>Use system dialogs</h1>
<h3>
The <code>dialog</code> module in Electron allows you to use native
system dialogs for opening files or directories, saving a file or
displaying informational messages.
</h3>
<p>
This is a main process module because this process is more efficient
with native utilities and it allows the call to happen without
interrupting the visible elements in your page's renderer process.
</p>
<p>
Open the
<a href="http://electron.atom.io/docs/api/dialog/">
full API documentation (opens in new window)
</a>
in your browser.
</p>
</div>
<div>
<div>
<h2>Information Dialog</h2>
<div>
<div>
<button id="information-dialog">
View Demo
</button>
<span id="info-selection"></span>
</div>
<p>
In this demo, the <code>ipc</code> module is used to send a message
from the renderer process instructing the main process to launch the
information dialog. Options may be provided for responses which can
then be relayed back to the renderer process.
</p>
<p>
Note: The <code>title</code> property is not displayed in macOS.
</p>
<p>
An information dialog can contain an icon, your choice of buttons,
title and message.
</p>
<h5>Renderer Process</h5>
<pre>
<code>
const {ipcRenderer} = require('electron')
const informationBtn = document.getElementById('information-dialog')
informationBtn.addEventListener('click', (event) => {
ipcRenderer.send('open-information-dialog')
})
ipcRenderer.on('information-dialog-selection', (event, index) => {
let message = 'You selected '
if (index === 0) message += 'yes.'
else message += 'no.'
document.getElementById('info-selection').innerHTML = message
})
</code>
</pre>
<h5>Main Process</h5>
<pre>
<code>
const {ipcMain, dialog} = require('electron')
ipcMain.on('open-information-dialog', (event) => {
const options = {
type: 'info',
title: 'Information',
message: "This is an information dialog. Isn't it nice?",
buttons: ['Yes', 'No']
}
dialog.showMessageBox(options, (index) => {
event.sender.send('information-dialog-selection', index)
})
})
</code>
</pre>
</div>
</div>
</div>
<script>
// You can also require other files to run in this process
require("./renderer.js");
</script>
</body>
</html>

View File

@@ -0,0 +1,70 @@
// Modules to control application life and create native browser window
const { app, BrowserWindow, ipcMain, dialog } = require('electron')
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null
})
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow)
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow()
}
})
ipcMain.on('open-information-dialog', event => {
const options = {
type: 'info',
title: 'Information',
message: "This is an information dialog. Isn't it nice?",
buttons: ['Yes', 'No']
}
dialog.showMessageBox(options, index => {
event.sender.send('information-dialog-selection', index)
})
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.

View File

@@ -0,0 +1,25 @@
const { ipcRenderer, shell } = require('electron')
const informationBtn = document.getElementById('information-dialog')
const links = document.querySelectorAll('a[href]')
informationBtn.addEventListener('click', event => {
ipcRenderer.send('open-information-dialog')
})
ipcRenderer.on('information-dialog-selection', (event, index) => {
let message = 'You selected '
if (index === 0) message += 'yes.'
else message += 'no.'
document.getElementById('info-selection').innerHTML = message
})
Array.prototype.forEach.call(links, (link) => {
const url = link.getAttribute('href')
if (url.indexOf('http') === 0) {
link.addEventListener('click', (e) => {
e.preventDefault()
shell.openExternal(url)
})
}
})

View File

@@ -0,0 +1,108 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Open File or Directory</title>
</head>
<body>
<div class="section-wrapper">
<h1>Use system dialogs</h1>
<h3>
The <code>dialog</code> module in Electron allows you to use native
system dialogs for opening files or directories, saving a file or
displaying informational messages.
</h3>
<p>
This is a main process module because this process is more efficient
with native utilities and it allows the call to happen without
interrupting the visible elements in your page's renderer process.
</p>
<p>
Open the
<a href="http://electron.atom.io/docs/api/dialog/">
full API documentation (opens in new window)
</a>
in your browser.
</p>
</div>
<div>
<div>
<h2>Open a File or Directory</h2>
<div>
<div>
<button id="select-directory">View Demo</button>
<span id="selected-file"></span>
</div>
<p>
In this demo, the <code>ipc</code> module is used to send a message
from the renderer process instructing the main process to launch the
open file (or directory) dialog. If a file is selected, the main
process can send that information back to the renderer process.
</p>
<h5>Renderer Process</h5>
<pre>
<code>
const {ipcRenderer} = require('electron')
const selectDirBtn = document.getElementById('select-directory')
selectDirBtn.addEventListener('click', (event) => {
ipcRenderer.send('open-file-dialog')
})
ipcRenderer.on('selected-directory', (event, path) => {
document.getElementById('selected-file').innerHTML = `You selected: ${path}`
})
</code>
</pre>
<h5>Main Process</h5>
<pre>
<code>
const {ipcMain, dialog} = require('electron')
ipcMain.on('open-file-dialog', (event) => {
dialog.showOpenDialog({
properties: ['openFile', 'openDirectory']
}, (files) => {
if (files) {
event.sender.send('selected-directory', files)
}
})
})
</code>
</pre>
<div>
<h2>ProTip</h2>
<strong>The sheet-style dialog on macOS.</strong>
<p>
On macOS you can choose between a "sheet" dialog or a default
dialog. The sheet version descends from the top of the window. To
use sheet version, pass the <code>window</code> as the first
argument in the dialog method.
</p>
<pre><code class="language-js">const ipc = require('electron').ipcMain
const dialog = require('electron').dialog
const BrowserWindow = require('electron').BrowserWindow
ipc.on('open-file-dialog-sheet', function (event) {
const window = BrowserWindow.fromWebContents(event.sender)
const files = dialog.showOpenDialog(window, { properties: [ 'openFile' ]})
})</code></pre>
</div>
</div>
</div>
</div>
<script>
// You can also require other files to run in this process
require("./renderer.js");
</script>
</body>
</html>

View File

@@ -0,0 +1,70 @@
// Modules to control application life and create native browser window
const { app, BrowserWindow, ipcMain, dialog } = require('electron')
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null
})
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow)
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow()
}
})
ipcMain.on('open-file-dialog', event => {
dialog.showOpenDialog(
{
properties: ['openFile', 'openDirectory']
},
files => {
if (files) {
event.sender.send('selected-directory', files)
}
}
)
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.

View File

@@ -0,0 +1,22 @@
const { ipcRenderer, shell } = require('electron')
const selectDirBtn = document.getElementById('select-directory')
const links = document.querySelectorAll('a[href]')
selectDirBtn.addEventListener('click', event => {
ipcRenderer.send('open-file-dialog')
})
ipcRenderer.on('selected-directory', (event, path) => {
document.getElementById('selected-file').innerHTML = `You selected: ${path}`
})
Array.prototype.forEach.call(links, (link) => {
const url = link.getAttribute('href')
if (url.indexOf('http') === 0) {
link.addEventListener('click', (e) => {
e.preventDefault()
shell.openExternal(url)
})
}
})

View File

@@ -0,0 +1,91 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Save Dialog</title>
</head>
<body>
<div>
<h1>Use system dialogs</h1>
<h3>
The <code>dialog</code> module in Electron allows you to use native
system dialogs for opening files or directories, saving a file or
displaying informational messages.
</h3>
<p>
This is a main process module because this process is more efficient
with native utilities and it allows the call to happen without
interrupting the visible elements in your page's renderer process.
</p>
<p>
Open the
<a href="http://electron.atom.io/docs/api/dialog/">
full API documentation (opens in new window)
</a>
in your browser.
</p>
</div>
<div>
<div>
<h2>Save Dialog</h2>
<div>
<div>
<button button id="save-dialog">View Demo</button>
<span id="file-saved"></span>
</div>
<p>
In this demo, the <code>ipc</code> module is used to send a message
from the renderer process instructing the main process to launch the
save dialog. It returns the path selected by the user which can be
relayed back to the renderer process.
</p>
<h5>Renderer Process</h5>
<pre>
<code>
const {ipcRenderer} = require('electron')
const saveBtn = document.getElementById('save-dialog')
saveBtn.addEventListener('click', (event) => {
ipcRenderer.send('save-dialog')
})
ipcRenderer.on('saved-file', (event, path) => {
if (!path) path = 'No path'
document.getElementById('file-saved').innerHTML = `Path selected: ${path}`
})
</code>
</pre>
<h5>Main Process</h5>
<pre>
<code>
const {ipcMain, dialog} = require('electron')
ipcMain.on('save-dialog', (event) => {
const options = {
title: 'Save an Image',
filters: [
{ name: 'Images', extensions: ['jpg', 'png', 'gif'] }
]
}
dialog.showSaveDialog(options, (filename) => {
event.sender.send('saved-file', filename)
})
})
</code>
</pre>
</div>
</div>
</div>
<script>
// You can also require other files to run in this process
require("./renderer.js");
</script>
</body>
</html>

View File

@@ -0,0 +1,66 @@
// Modules to control application life and create native browser window
const { app, BrowserWindow, ipcMain, dialog } = require('electron')
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null
})
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow)
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow()
}
})
ipcMain.on('save-dialog', event => {
const options = {
title: 'Save an Image',
filters: [{ name: 'Images', extensions: ['jpg', 'png', 'gif'] }]
}
dialog.showSaveDialog(options, filename => {
event.sender.send('saved-file', filename)
})
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.

View File

@@ -0,0 +1,23 @@
const { ipcRenderer, shell } = require('electron')
const saveBtn = document.getElementById('save-dialog')
const links = document.querySelectorAll('a[href]')
saveBtn.addEventListener('click', event => {
ipcRenderer.send('save-dialog')
})
ipcRenderer.on('saved-file', (event, path) => {
if (!path) path = 'No path'
document.getElementById('file-saved').innerHTML = `Path selected: ${path}`
})
Array.prototype.forEach.call(links, (link) => {
const url = link.getAttribute('href')
if (url.indexOf('http') === 0) {
link.addEventListener('click', (e) => {
e.preventDefault()
shell.openExternal(url)
})
}
})

View File

@@ -1,64 +1,64 @@
// Modules to control application life and create native browser window
const { app, BrowserWindow, ipcMain, nativeImage } = require('electron')
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null
})
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow)
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow()
}
})
ipcMain.on('ondragstart', (event, filepath) => {
const icon = nativeImage.createFromDataURL('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAVlpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KTMInWQAACsZJREFUWAmtWFlsXFcZ/u82++Jt7IyT2Em6ZFHTpAtWIzspEgjEUhA8VNAiIYEQUvuABBIUwUMkQIVKPCIoEiABLShISEBbhFJwIGRpIKRpbNeJ7bh2HHvssR3PPnPnLnzfmRlju6EQqUc+c++c8y/fv54z1uQOh+/7Glh0TD59TE/TND7lnfa4/64OKsM071QoeZpA/y9WWvk/B4XCC06TUC+Xyw8HTXNQ1+Ww6PpOrMebewXxvBueJ6/XHOdMJBL5J9Y97m2R0SS/wweE6JxkGx5dilWr1S/7dXsEa2o4+LyFmcFcaL5zbX3Y9gh5hpeWYpSB9XV5/H678V89BGYDXnHJlCsWn4gHrGc1K9CXxferOdvPOOKUfF8cH7nUyCtklQZXih/VNNlmirk3GdBSoIcRswW7/vVkLPYi5W2Uze8bh7J+4wLfh4dViFx5/nmrUi7/MhGNvrCkBfpeWqnW/7BUdadqntQ8zwr6vhUV34xpYnDynWvcmwQNaclDXsqgLMqkocPDw7fNx7d5qIX+/PmJxKGD6VdDkeh7ztyqOFfrokGCEWiiZ1mp0uITnuKAosaT7+pNxMYTyefutcQfbA+b1XLpH5fnF97/yD335Fu6mqTqsclDINBVmI4fDxw80KPAvJSt1MZtMcLiGxYUu83p4UkgnJZlqcl3LAj3WnTkIS9lUBYNPJjueVWgg7qocyOgliFqjZsg8gq5tRdiieQTf1gq15Y8CUbRZtyWOzZwc8lEqS3PTCtgqd13ieO68BQ2uNl64tXAewktrFuX2mPdkWAxn3sxnmx7sqUTJGqso8MGS9tbXFz8DMH8bblUX3T9QARVi8RV8qljfcJy0zRlaf6mzHEuzEtmekqCoZB4rqp0OmudHtUnlEWZlE0d1EWd1N3EozourcO65pw4eTIZQTW9VazJtbqvw9XwKVFQMsKDBuNhtp4uvGGFI+IDgKnpMjYyIis3ZsQMBIR7pONsIaMsyqRs6ohY1rPUSd3EQFDqo+kdZ3Fh4aupbdu+99uFQr2A1CBs4uEAjZjIFUMHi4dVxMXzCdCXQj4vBrwVCofl0ulTcv/DAxJJJBUPc8mpoyI2JDw7bFyT+ifTcSubyXytJ51+roWBxwG9Q73WWjZ7eSUU3//nXM0NI+x0PBGrTSgsLS9JFuFxHFrvSqIrJV279gi6tjiVspTza3JjZhY+0CQZj0mlWJSeHTslCro6eFqymCcVVN77kkGjs1p4sy2VOoSlOrFwT+XR+PjkgGaZ+ycKVbRTYUdVrmaImCvzk1dlFCEJdHRJ284+ie/ol0h7p7jFvExcvCCXzp2Rqem3pAMAiqWS6JGYhFI9Mjo6KjevXVUyKEuFHrKpY6JQ8TXT3D8+OTkAHBw6o6LCFo9ag3o4JtlCyTHEt5AxKvS6YUi5kJeZG3Py0NAxlLcJ9xti+K7Mjo/JfGZRuvv6Ze+9+yWEhDZAvzg3JyhX2d6/S7q6e+TimdOS7ElLKBZDwqvmj6rztayr1fVI1IoXi4PAcYZY1tPEEO1wEVlXgRFBDcmIXTqJsS+XyhKLJ5A/OpIVXXptWUYv/UvaenfIocEhMQ2EzHHErlXFCgQl3paU1eVl6QAY8sQTCSmVihKJx1V/ogvgIYF/pACdcMBhqONoHhF88/2d+bojyA6cRvje2IdFjoSjUSnBS8hgyS9lZOzKFdmPxO3o6gQIGzwuDn1dVSCtCKPy1pZXlATXqUsVYMLRmKo87vP4Y1ioqwCdCegmMYx3W/VPn8RrSDwwIMMbcEjkYo29JZVOy+ybI7K4eksODx1VSqvligpReSVLgySM/FI5h2q062jNyL3s7FtoAyGJIlx1225UmwJF6aJRJ3XzHXO9bWvsJa3jQFlBJkz6iuXdu32HzM7MyP0PPNgAU6ko4Qzp6b+flr8MD9OYJg9CwtzL5+T65ITs2bsP3mGxN/ZbBcOn0sk20gAkLQ+huXpFi8vkoY9AoyDjxTR1mbo6Ltt275HpN0dlNxQE40mVM8Ajjxx9VAGhAvQR1akZFCq799ADysMuQqOxh2FNmamEaz51ItGLfFD9+oUJoZkLowHoFA2mljUacqOMflKuVmHpfmnfvlMuvXZeStmMBIMhcWEdjgFJtrUjXI0KchAuAg0ilxLJNoRVBxhIBm0TjjKAuqjTqTs3CQZ6QUUMGFW7eiWMUg6w+yo8YMW7DqtqlZLkUDV2ISfd29KyDwk9MjYmMyOXxQIIKuShqo4VGFNBEgeDQYqVam5N5tEePFQgURIUBCsd1EWd1XrtDUUMLARD9bKaK5ytQ2Gb75g8WMiEP6VkfnZGevv6UF1vSBW5E0PFDAweFRvlfun8WVmamhDNrkmweQ0pwaPt6M4m8mgKTTFXqcrV0ZH1FKBg6qAu6qTuJiCV1Cp2Q0NDr9Uq5Ym+oMEDlSewsoRwrVBEaij7AJ4s7zrOpumxEdm15y6558GHJVe1Zezy6zJx6aJkpq5JFB4z6zVZmBiX1VWUP0IY4CFMYcpQdZ3xqIs6oftCE5DHKwd0q/tzOV8svdDb3nk8VnG9qmgQC0ZURz8Ur91alXgSByZ6ES9kZZTr/PR16UOCh+7dq0CWyyXJ4xqCQ0nKt9YQSlPue2gAeYZzD7yNLk0wmqAreb2WYSxAJ8Dget64wxtEBlDaqVOn/K5dB67t6+t5MhoMJuc8w8UPKiQ9CQR9JK5czhZAQxPt7TKF3OiAIisUViAD2Lg5d0P2HDgoKeRaW0enyqVwBJcO5fFG5dqa7h406qaeX8384uTZL5w9+UqxhYHFp0YLIYA9ddfu3T+4UJF6Rg+YAc9D0+RoIGP1ULhpWspr10evyK7+ftWTrk9PS/++A9KZSm26cih2mMOErem6n/ZsZwA2TM/MPHXs2LEftnSTbh0Q36mIIbx44cLvOnu3f+xUwbWLmoHTCUlF6g2jBQo/GnFrnGNqSHdvr+rIKGMW1KahwEBdzHft98aNwMr8zd8/NDDwccihc0hLi3GubRjY0Bm6H19fPvnZI4c/fHd7PJ2peXYZ+WQ26JufZELjQ6lbAQtnWre0d3apY8TFIdtAo+Qri6mupsB49lBMC+QXF0YefObZT8j0eKWlswVjEyCCOXHihPGb575VCvVuf3lvetsH9rXF0rla3cnhpoIGjgsUPhR3I4TMKYJQV1Z6WO02aEjHa5mNe3OPW3OPRHVrbXFh9Ocvv/KR1372owx1Pf3005uc35Ddgtd8rsf06IdS5777zZ+mUqmPzjm6TPpmvayZOq4LyATeCzkanmiy4qEuC/yXiO8CSMRzvLs1x9phepLNZl868sy3Pyen/5hd1/EfRvWmuvSWNeaRS/RkPDI4+NjE1NSXEoXlpaNB1zqo20abi59/vu/UfM2pie7WUDVq8l3wTwnskeZ+zTbIQ17KoCzKpGzq2KqX32/roRbh8ePHdUzl0s9/5Rv9n/7go19MxCKfCkZiu3V06wrO5gocxL7Dgd/IEobEMH6rejg+auXidL5Y/vWv/vTX53/y/e/MkGajTH7fOt4RUJOY1df4RdtY6ICFRzqTySOhUOA+3Ai3o31H1ZbnlXBruFmt2iMrudy5xx9//BzWV7nXDBGN2xpjbt/5oGUEdhtO3iD47xZOvm8a5CHvpsV38wsUaMwBWsz3rbK5xr0mzdv2t9Jv/f5vhsF4J+Q63IUAAAAASUVORK5CYII=')
event.sender.startDrag({
file: filepath,
icon
})
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
// Modules to control application life and create native browser window
const { app, BrowserWindow, ipcMain, nativeImage } = require('electron')
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null
})
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow)
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow()
}
})
ipcMain.on('ondragstart', (event, filepath) => {
const icon = nativeImage.createFromDataURL('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAVlpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KTMInWQAACsZJREFUWAmtWFlsXFcZ/u82++Jt7IyT2Em6ZFHTpAtWIzspEgjEUhA8VNAiIYEQUvuABBIUwUMkQIVKPCIoEiABLShISEBbhFJwIGRpIKRpbNeJ7bh2HHvssR3PPnPnLnzfmRlju6EQqUc+c++c8y/fv54z1uQOh+/7Glh0TD59TE/TND7lnfa4/64OKsM071QoeZpA/y9WWvk/B4XCC06TUC+Xyw8HTXNQ1+Ww6PpOrMebewXxvBueJ6/XHOdMJBL5J9Y97m2R0SS/wweE6JxkGx5dilWr1S/7dXsEa2o4+LyFmcFcaL5zbX3Y9gh5hpeWYpSB9XV5/H678V89BGYDXnHJlCsWn4gHrGc1K9CXxferOdvPOOKUfF8cH7nUyCtklQZXih/VNNlmirk3GdBSoIcRswW7/vVkLPYi5W2Uze8bh7J+4wLfh4dViFx5/nmrUi7/MhGNvrCkBfpeWqnW/7BUdadqntQ8zwr6vhUV34xpYnDynWvcmwQNaclDXsqgLMqkocPDw7fNx7d5qIX+/PmJxKGD6VdDkeh7ztyqOFfrokGCEWiiZ1mp0uITnuKAosaT7+pNxMYTyefutcQfbA+b1XLpH5fnF97/yD335Fu6mqTqsclDINBVmI4fDxw80KPAvJSt1MZtMcLiGxYUu83p4UkgnJZlqcl3LAj3WnTkIS9lUBYNPJjueVWgg7qocyOgliFqjZsg8gq5tRdiieQTf1gq15Y8CUbRZtyWOzZwc8lEqS3PTCtgqd13ieO68BQ2uNl64tXAewktrFuX2mPdkWAxn3sxnmx7sqUTJGqso8MGS9tbXFz8DMH8bblUX3T9QARVi8RV8qljfcJy0zRlaf6mzHEuzEtmekqCoZB4rqp0OmudHtUnlEWZlE0d1EWd1N3EozourcO65pw4eTIZQTW9VazJtbqvw9XwKVFQMsKDBuNhtp4uvGGFI+IDgKnpMjYyIis3ZsQMBIR7pONsIaMsyqRs6ohY1rPUSd3EQFDqo+kdZ3Fh4aupbdu+99uFQr2A1CBs4uEAjZjIFUMHi4dVxMXzCdCXQj4vBrwVCofl0ulTcv/DAxJJJBUPc8mpoyI2JDw7bFyT+ifTcSubyXytJ51+roWBxwG9Q73WWjZ7eSUU3//nXM0NI+x0PBGrTSgsLS9JFuFxHFrvSqIrJV279gi6tjiVspTza3JjZhY+0CQZj0mlWJSeHTslCro6eFqymCcVVN77kkGjs1p4sy2VOoSlOrFwT+XR+PjkgGaZ+ycKVbRTYUdVrmaImCvzk1dlFCEJdHRJ284+ie/ol0h7p7jFvExcvCCXzp2Rqem3pAMAiqWS6JGYhFI9Mjo6KjevXVUyKEuFHrKpY6JQ8TXT3D8+OTkAHBw6o6LCFo9ag3o4JtlCyTHEt5AxKvS6YUi5kJeZG3Py0NAxlLcJ9xti+K7Mjo/JfGZRuvv6Ze+9+yWEhDZAvzg3JyhX2d6/S7q6e+TimdOS7ElLKBZDwqvmj6rztayr1fVI1IoXi4PAcYZY1tPEEO1wEVlXgRFBDcmIXTqJsS+XyhKLJ5A/OpIVXXptWUYv/UvaenfIocEhMQ2EzHHErlXFCgQl3paU1eVl6QAY8sQTCSmVihKJx1V/ogvgIYF/pACdcMBhqONoHhF88/2d+bojyA6cRvje2IdFjoSjUSnBS8hgyS9lZOzKFdmPxO3o6gQIGzwuDn1dVSCtCKPy1pZXlATXqUsVYMLRmKo87vP4Y1ioqwCdCegmMYx3W/VPn8RrSDwwIMMbcEjkYo29JZVOy+ybI7K4eksODx1VSqvligpReSVLgySM/FI5h2q062jNyL3s7FtoAyGJIlx1225UmwJF6aJRJ3XzHXO9bWvsJa3jQFlBJkz6iuXdu32HzM7MyP0PPNgAU6ko4Qzp6b+flr8MD9OYJg9CwtzL5+T65ITs2bsP3mGxN/ZbBcOn0sk20gAkLQ+huXpFi8vkoY9AoyDjxTR1mbo6Ltt275HpN0dlNxQE40mVM8Ajjxx9VAGhAvQR1akZFCq799ADysMuQqOxh2FNmamEaz51ItGLfFD9+oUJoZkLowHoFA2mljUacqOMflKuVmHpfmnfvlMuvXZeStmMBIMhcWEdjgFJtrUjXI0KchAuAg0ilxLJNoRVBxhIBm0TjjKAuqjTqTs3CQZ6QUUMGFW7eiWMUg6w+yo8YMW7DqtqlZLkUDV2ISfd29KyDwk9MjYmMyOXxQIIKuShqo4VGFNBEgeDQYqVam5N5tEePFQgURIUBCsd1EWd1XrtDUUMLARD9bKaK5ytQ2Gb75g8WMiEP6VkfnZGevv6UF1vSBW5E0PFDAweFRvlfun8WVmamhDNrkmweQ0pwaPt6M4m8mgKTTFXqcrV0ZH1FKBg6qAu6qTuJiCV1Cp2Q0NDr9Uq5Ym+oMEDlSewsoRwrVBEaij7AJ4s7zrOpumxEdm15y6558GHJVe1Zezy6zJx6aJkpq5JFB4z6zVZmBiX1VWUP0IY4CFMYcpQdZ3xqIs6oftCE5DHKwd0q/tzOV8svdDb3nk8VnG9qmgQC0ZURz8Ur91alXgSByZ6ES9kZZTr/PR16UOCh+7dq0CWyyXJ4xqCQ0nKt9YQSlPue2gAeYZzD7yNLk0wmqAreb2WYSxAJ8Dget64wxtEBlDaqVOn/K5dB67t6+t5MhoMJuc8w8UPKiQ9CQR9JK5czhZAQxPt7TKF3OiAIisUViAD2Lg5d0P2HDgoKeRaW0enyqVwBJcO5fFG5dqa7h406qaeX8384uTZL5w9+UqxhYHFp0YLIYA9ddfu3T+4UJF6Rg+YAc9D0+RoIGP1ULhpWspr10evyK7+ftWTrk9PS/++A9KZSm26cih2mMOErem6n/ZsZwA2TM/MPHXs2LEftnSTbh0Q36mIIbx44cLvOnu3f+xUwbWLmoHTCUlF6g2jBQo/GnFrnGNqSHdvr+rIKGMW1KahwEBdzHft98aNwMr8zd8/NDDwccihc0hLi3GubRjY0Bm6H19fPvnZI4c/fHd7PJ2peXYZ+WQ26JufZELjQ6lbAQtnWre0d3apY8TFIdtAo+Qri6mupsB49lBMC+QXF0YefObZT8j0eKWlswVjEyCCOXHihPGb575VCvVuf3lvetsH9rXF0rla3cnhpoIGjgsUPhR3I4TMKYJQV1Z6WO02aEjHa5mNe3OPW3OPRHVrbXFh9Ocvv/KR1372owx1Pf3005uc35Ddgtd8rsf06IdS5777zZ+mUqmPzjm6TPpmvayZOq4LyATeCzkanmiy4qEuC/yXiO8CSMRzvLs1x9phepLNZl868sy3Pyen/5hd1/EfRvWmuvSWNeaRS/RkPDI4+NjE1NSXEoXlpaNB1zqo20abi59/vu/UfM2pie7WUDVq8l3wTwnskeZ+zTbIQ17KoCzKpGzq2KqX32/roRbh8ePHdUzl0s9/5Rv9n/7go19MxCKfCkZiu3V06wrO5gocxL7Dgd/IEobEMH6rejg+auXidL5Y/vWv/vTX53/y/e/MkGajTH7fOt4RUJOY1df4RdtY6ICFRzqTySOhUOA+3Ai3o31H1ZbnlXBruFmt2iMrudy5xx9//BzWV7nXDBGN2xpjbt/5oGUEdhtO3iD47xZOvm8a5CHvpsV38wsUaMwBWsz3rbK5xr0mzdv2t9Jv/f5vhsF4J+Q63IUAAAAASUVORK5CYII=')
event.sender.startDrag({
file: filepath,
icon
})
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.

View File

@@ -1,21 +1,21 @@
const { ipcRenderer } = require('electron')
const shell = require('electron').shell
const links = document.querySelectorAll('a[href]')
Array.prototype.forEach.call(links, (link) => {
const url = link.getAttribute('href')
if (url.indexOf('http') === 0) {
link.addEventListener('click', (e) => {
e.preventDefault()
shell.openExternal(url)
})
}
})
const dragFileLink = document.getElementById('drag-file-link')
dragFileLink.addEventListener('dragstart', event => {
event.preventDefault()
ipcRenderer.send('ondragstart', __filename)
})
const { ipcRenderer } = require('electron')
const shell = require('electron').shell
const links = document.querySelectorAll('a[href]')
Array.prototype.forEach.call(links, (link) => {
const url = link.getAttribute('href')
if (url.indexOf('http') === 0) {
link.addEventListener('click', (e) => {
e.preventDefault()
shell.openExternal(url)
})
}
})
const dragFileLink = document.getElementById('drag-file-link')
dragFileLink.addEventListener('dragstart', event => {
event.preventDefault()
ipcRenderer.send('ondragstart', __filename)
})

View File

@@ -0,0 +1,67 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Desktop notifications</title>
</head>
<body>
<div>
<h1>Desktop notifications</h1>
<h3>
The <code>notification</code> module in Electron allows you to add basic
desktop notifications.
</h3>
<p>
Electron conveniently allows developers to send notifications with the
<a href="https://notifications.spec.whatwg.org/">HTML5 Notification API</a>,
using the currently running operating systems native notification
APIs to display it.
</p>
<p>
<b>Note:</b> Since this is an HTML5 API it is only available in the
renderer process.
</p>
<p>
Open the
<a href="https://electron.atom.io/docs/all/#notifications-windows-linux-macos">
full API documentation<span>(opens in new window)</span>
</a>
in your browser.
</p>
</div>
<div>
<div>
<h2>Basic notification</h2>
<div>
<div>
<button id="basic-noti">View demo</button>
</div>
<p>This demo demonstrates a basic notification. Text only.</p>
</div>
</div>
</div>
<div>
<div>
<h2>Notification with image</h2>
<div>
<div>
<button id="advanced-noti">View demo</button>
</div>
<p>
This demo demonstrates a basic notification. Both text and a image
</p>
</div>
</div>
</div>
<script>
// You can also require other files to run in this process
require("./renderer.js");
</script>
</body>
</html>

View File

@@ -0,0 +1,56 @@
// Modules to control application life and create native browser window
const { app, BrowserWindow } = require('electron')
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null
})
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow)
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow()
}
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.

View File

@@ -0,0 +1,29 @@
const basicNotification = {
title: 'Basic Notification',
body: 'Short message part'
}
const notification = {
title: 'Notification with image',
body: 'Short message plus a custom image',
icon: 'https://via.placeholder.com/150'
}
const basicNotificationButton = document.getElementById('basic-noti')
const notificationButton = document.getElementById('advanced-noti')
notificationButton.addEventListener('click', () => {
const myNotification = new window.Notification(notification.title, notification)
myNotification.onclick = () => {
console.log('Notification clicked')
}
})
basicNotificationButton.addEventListener('click', () => {
const myNotification = new window.Notification(basicNotification.title, basicNotification)
myNotification.onclick = () => {
console.log('Notification clicked')
}
})

View File

@@ -0,0 +1,26 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<div>
<div>
<h1>App Information</h1>
<div>
<div>
<button id="app-info">View Demo</button>
<span id="got-app-info"></span>
</div>
<p>The main process <code>app</code> module can be used to get the path at which your app is located on the user's computer.</p>
<p>In this example, to get that information from the renderer process, we use the <code>ipc</code> module to send a message to the main process requesting the app's path.</p>
<p>See the <a id="electron-docs" href="https://electronjs.org/docs/api/app">app module documentation<span class="u-visible-to-screen-reader">(opens in new window)</span></a> for more.</p>
</div>
</div>
</div>
<script>
// You can also require other files to run in this process
require('./renderer.js')
</script>
</body>
</html>

View File

@@ -0,0 +1,5 @@
const {app, ipcMain} = require('electron')
ipcMain.on('get-app-path', (event) => {
event.sender.send('got-app-path', app.getAppPath())
})

View File

@@ -0,0 +1,18 @@
const {ipcRenderer} = require('electron')
const appInfoBtn = document.getElementById('app-info')
const electron_doc_link = document.querySelectorAll('a[href]')
appInfoBtn.addEventListener('click', () => {
ipcRenderer.send('get-app-path')
})
ipcRenderer.on('got-app-path', (event, path) => {
const message = `This app is located at: ${path}`
document.getElementById('got-app-info').innerHTML = message
})
electron_doc_link.addEventListener('click', (e) => {
e.preventDefault()
shell.openExternal(url)
})

View File

@@ -56,7 +56,7 @@ can do so by either providing a mirror or an existing cache directory.
#### Mirror
You can use environment variables to override the base URL, the path at which to
look for Electron binaries, and the binary filename. The url used by `@electron/get`
look for Electron binaries, and the binary filename. The url used by `electron-download`
is composed as follows:
```plaintext
@@ -66,11 +66,11 @@ url = ELECTRON_MIRROR + ELECTRON_CUSTOM_DIR + '/' + ELECTRON_CUSTOM_FILENAME
For instance, to use the China mirror:
```plaintext
ELECTRON_MIRROR="https://cdn.npm.taobao.org/dist/electron/"
ELECTRON_MIRROR="https://npm.taobao.org/mirrors/electron/"
```
#### Cache
Alternatively, you can override the local cache. `@electron/get` will cache
Alternatively, you can override the local cache. `electron-download` will cache
downloaded binaries in a local directory to not stress your network. You can use
that cache folder to provide custom builds of Electron or to avoid making contact
with the network at all.
@@ -89,26 +89,16 @@ The cache contains the version's official zip file as well as a checksum, stored
a text file. A typical cache might look like this:
```sh
├── httpsgithub.comelectronelectronreleasesdownloadv1.7.9electron-v1.7.9-darwin-x64.zip
│ └── electron-v1.7.9-darwin-x64.zip
├── httpsgithub.comelectronelectronreleasesdownloadv1.7.9SHASUMS256.txt
│ └── SHASUMS256.txt
├── httpsgithub.comelectronelectronreleasesdownloadv1.8.1electron-v1.8.1-darwin-x64.zip
│ └── electron-v1.8.1-darwin-x64.zip
├── httpsgithub.comelectronelectronreleasesdownloadv1.8.1SHASUMS256.txt
│ └── SHASUMS256.txt
├── httpsgithub.comelectronelectronreleasesdownloadv1.8.2-beta.1electron-v1.8.2-beta.1-darwin-x64.zip
│ └── electron-v1.8.2-beta.1-darwin-x64.zip
├── httpsgithub.comelectronelectronreleasesdownloadv1.8.2-beta.1SHASUMS256.txt
│ └── SHASUMS256.txt
├── httpsgithub.comelectronelectronreleasesdownloadv1.8.2-beta.2electron-v1.8.2-beta.2-darwin-x64.zip
│ └── electron-v1.8.2-beta.2-darwin-x64.zip
├── httpsgithub.comelectronelectronreleasesdownloadv1.8.2-beta.2SHASUMS256.txt
│ └── SHASUMS256.txt
├── httpsgithub.comelectronelectronreleasesdownloadv1.8.2-beta.3electron-v1.8.2-beta.3-darwin-x64.zip
│ └── electron-v1.8.2-beta.3-darwin-x64.zip
└── httpsgithub.comelectronelectronreleasesdownloadv1.8.2-beta.3SHASUMS256.txt
└── SHASUMS256.txt
├── electron-v1.7.9-darwin-x64.zip
── electron-v1.8.1-darwin-x64.zip
├── electron-v1.8.2-beta.1-darwin-x64.zip
├── electron-v1.8.2-beta.2-darwin-x64.zip
├── electron-v1.8.2-beta.3-darwin-x64.zip
├── SHASUMS256.txt-1.7.9
├── SHASUMS256.txt-1.8.1
── SHASUMS256.txt-1.8.2-beta.1
├── SHASUMS256.txt-1.8.2-beta.2
├── SHASUMS256.txt-1.8.2-beta.3
```
## Skip binary download

View File

@@ -135,10 +135,11 @@ auto_filenames = {
"lib/common/api/module-list.ts",
"lib/common/api/native-image.js",
"lib/common/api/shell.js",
"lib/common/clipboard-utils.ts",
"lib/common/crash-reporter.js",
"lib/common/define-properties.ts",
"lib/common/electron-binding-setup.ts",
"lib/common/type-utils.ts",
"lib/common/remote/type-utils.ts",
"lib/common/web-view-methods.ts",
"lib/common/webpack-globals-provider.ts",
"lib/renderer/api/context-bridge.ts",
@@ -165,7 +166,6 @@ auto_filenames = {
"lib/renderer/web-view/web-view-element.ts",
"lib/renderer/web-view/web-view-impl.ts",
"lib/renderer/web-view/web-view-init.ts",
"lib/renderer/window-setup.ts",
"lib/sandboxed_renderer/api/exports/electron.ts",
"lib/sandboxed_renderer/api/module-list.ts",
"lib/sandboxed_renderer/init.js",
@@ -268,13 +268,14 @@ auto_filenames = {
"lib/common/api/module-list.ts",
"lib/common/api/native-image.js",
"lib/common/api/shell.js",
"lib/common/clipboard-utils.ts",
"lib/common/crash-reporter.js",
"lib/common/define-properties.ts",
"lib/common/electron-binding-setup.ts",
"lib/common/init.ts",
"lib/common/parse-features-string.js",
"lib/common/remote/type-utils.ts",
"lib/common/reset-search-paths.ts",
"lib/common/type-utils.ts",
"lib/common/web-view-methods.ts",
"lib/common/webpack-globals-provider.ts",
"lib/renderer/ipc-renderer-internal-utils.ts",
@@ -291,12 +292,13 @@ auto_filenames = {
"lib/common/api/module-list.ts",
"lib/common/api/native-image.js",
"lib/common/api/shell.js",
"lib/common/clipboard-utils.ts",
"lib/common/crash-reporter.js",
"lib/common/define-properties.ts",
"lib/common/electron-binding-setup.ts",
"lib/common/init.ts",
"lib/common/remote/type-utils.ts",
"lib/common/reset-search-paths.ts",
"lib/common/type-utils.ts",
"lib/common/web-view-methods.ts",
"lib/common/webpack-globals-provider.ts",
"lib/renderer/api/context-bridge.ts",
@@ -340,12 +342,13 @@ auto_filenames = {
"lib/common/api/module-list.ts",
"lib/common/api/native-image.js",
"lib/common/api/shell.js",
"lib/common/clipboard-utils.ts",
"lib/common/crash-reporter.js",
"lib/common/define-properties.ts",
"lib/common/electron-binding-setup.ts",
"lib/common/init.ts",
"lib/common/remote/type-utils.ts",
"lib/common/reset-search-paths.ts",
"lib/common/type-utils.ts",
"lib/common/webpack-globals-provider.ts",
"lib/renderer/api/context-bridge.ts",
"lib/renderer/api/crash-reporter.js",

View File

@@ -27,94 +27,92 @@ filenames = {
"chromium_src/chrome/browser/process_singleton_win.cc",
"chromium_src/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.cc",
"chromium_src/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.h",
"shell/app/electron_content_client.cc",
"shell/app/electron_content_client.h",
"shell/app/electron_main_delegate.cc",
"shell/app/electron_main_delegate.h",
"shell/app/electron_main_delegate_mac.h",
"shell/app/electron_main_delegate_mac.mm",
"shell/app/atom_content_client.cc",
"shell/app/atom_content_client.h",
"shell/app/atom_main_delegate.cc",
"shell/app/atom_main_delegate.h",
"shell/app/atom_main_delegate_mac.h",
"shell/app/atom_main_delegate_mac.mm",
"shell/app/command_line_args.cc",
"shell/app/command_line_args.h",
"shell/app/uv_task_runner.cc",
"shell/app/uv_task_runner.h",
"shell/browser/api/electron_api_app.cc",
"shell/browser/api/electron_api_app.h",
"shell/browser/api/electron_api_app_mac.mm",
"shell/browser/api/electron_api_auto_updater.cc",
"shell/browser/api/electron_api_auto_updater.h",
"shell/browser/api/electron_api_browser_view.cc",
"shell/browser/api/electron_api_browser_view.h",
"shell/browser/api/electron_api_browser_window.cc",
"shell/browser/api/electron_api_browser_window.h",
"shell/browser/api/electron_api_browser_window_mac.mm",
"shell/browser/api/electron_api_browser_window_views.cc",
"shell/browser/api/electron_api_content_tracing.cc",
"shell/browser/api/electron_api_cookies.cc",
"shell/browser/api/electron_api_cookies.h",
"shell/browser/api/electron_api_data_pipe_holder.cc",
"shell/browser/api/electron_api_data_pipe_holder.h",
"shell/browser/api/electron_api_debugger.cc",
"shell/browser/api/electron_api_debugger.h",
"shell/browser/api/electron_api_dialog.cc",
"shell/browser/api/electron_api_download_item.cc",
"shell/browser/api/electron_api_download_item.h",
"shell/browser/api/electron_api_event.cc",
"shell/browser/api/electron_api_global_shortcut.cc",
"shell/browser/api/electron_api_global_shortcut.h",
"shell/browser/api/electron_api_in_app_purchase.cc",
"shell/browser/api/electron_api_in_app_purchase.h",
"shell/browser/api/electron_api_menu.cc",
"shell/browser/api/electron_api_menu.h",
"shell/browser/api/electron_api_menu_mac.h",
"shell/browser/api/electron_api_menu_mac.mm",
"shell/browser/api/electron_api_menu_views.cc",
"shell/browser/api/electron_api_menu_views.h",
"shell/browser/api/electron_api_native_theme.cc",
"shell/browser/api/electron_api_native_theme.h",
"shell/browser/api/electron_api_native_theme_mac.mm",
"shell/browser/api/electron_api_net.cc",
"shell/browser/api/electron_api_net.h",
"shell/browser/api/electron_api_net_log.cc",
"shell/browser/api/electron_api_net_log.h",
"shell/browser/api/electron_api_notification.cc",
"shell/browser/api/electron_api_notification.h",
"shell/browser/api/electron_api_power_monitor.cc",
"shell/browser/api/electron_api_power_monitor.h",
"shell/browser/api/electron_api_power_monitor_mac.mm",
"shell/browser/api/electron_api_power_monitor_win.cc",
"shell/browser/api/electron_api_power_save_blocker.cc",
"shell/browser/api/electron_api_power_save_blocker.h",
"shell/browser/api/electron_api_protocol_ns.cc",
"shell/browser/api/electron_api_protocol_ns.h",
"shell/browser/api/electron_api_screen.cc",
"shell/browser/api/electron_api_screen.h",
"shell/browser/api/electron_api_session.cc",
"shell/browser/api/electron_api_session.h",
"shell/browser/api/electron_api_system_preferences.cc",
"shell/browser/api/electron_api_system_preferences.h",
"shell/browser/api/electron_api_system_preferences_mac.mm",
"shell/browser/api/electron_api_system_preferences_win.cc",
"shell/browser/api/electron_api_top_level_window.cc",
"shell/browser/api/electron_api_top_level_window.h",
"shell/browser/api/electron_api_tray.cc",
"shell/browser/api/electron_api_tray.h",
"shell/browser/api/electron_api_url_loader.cc",
"shell/browser/api/electron_api_url_loader.h",
"shell/browser/api/electron_api_view.cc",
"shell/browser/api/electron_api_view.h",
"shell/browser/api/electron_api_web_contents.cc",
"shell/browser/api/electron_api_web_contents.h",
"shell/browser/api/electron_api_web_contents_impl.cc",
"shell/browser/api/electron_api_web_contents_mac.mm",
"shell/browser/api/electron_api_web_contents_view.cc",
"shell/browser/api/electron_api_web_contents_view.h",
"shell/browser/api/electron_api_web_request_ns.cc",
"shell/browser/api/electron_api_web_request_ns.h",
"shell/browser/api/electron_api_web_view_manager.cc",
"shell/browser/api/atom_api_app.cc",
"shell/browser/api/atom_api_app.h",
"shell/browser/api/atom_api_app_mac.mm",
"shell/browser/api/atom_api_auto_updater.cc",
"shell/browser/api/atom_api_auto_updater.h",
"shell/browser/api/atom_api_browser_view.cc",
"shell/browser/api/atom_api_browser_view.h",
"shell/browser/api/atom_api_browser_window.cc",
"shell/browser/api/atom_api_browser_window.h",
"shell/browser/api/atom_api_browser_window_mac.mm",
"shell/browser/api/atom_api_browser_window_views.cc",
"shell/browser/api/atom_api_content_tracing.cc",
"shell/browser/api/atom_api_cookies.cc",
"shell/browser/api/atom_api_cookies.h",
"shell/browser/api/atom_api_data_pipe_holder.cc",
"shell/browser/api/atom_api_data_pipe_holder.h",
"shell/browser/api/atom_api_debugger.cc",
"shell/browser/api/atom_api_debugger.h",
"shell/browser/api/atom_api_dialog.cc",
"shell/browser/api/atom_api_download_item.cc",
"shell/browser/api/atom_api_download_item.h",
"shell/browser/api/atom_api_event.cc",
"shell/browser/api/atom_api_global_shortcut.cc",
"shell/browser/api/atom_api_global_shortcut.h",
"shell/browser/api/atom_api_in_app_purchase.cc",
"shell/browser/api/atom_api_in_app_purchase.h",
"shell/browser/api/atom_api_menu.cc",
"shell/browser/api/atom_api_menu.h",
"shell/browser/api/atom_api_menu_mac.h",
"shell/browser/api/atom_api_menu_mac.mm",
"shell/browser/api/atom_api_menu_views.cc",
"shell/browser/api/atom_api_menu_views.h",
"shell/browser/api/atom_api_native_theme.cc",
"shell/browser/api/atom_api_native_theme.h",
"shell/browser/api/atom_api_native_theme_mac.mm",
"shell/browser/api/atom_api_net.cc",
"shell/browser/api/atom_api_net.h",
"shell/browser/api/atom_api_net_log.cc",
"shell/browser/api/atom_api_net_log.h",
"shell/browser/api/atom_api_notification.cc",
"shell/browser/api/atom_api_notification.h",
"shell/browser/api/atom_api_power_monitor.cc",
"shell/browser/api/atom_api_power_monitor.h",
"shell/browser/api/atom_api_power_monitor_mac.mm",
"shell/browser/api/atom_api_power_monitor_win.cc",
"shell/browser/api/atom_api_power_save_blocker.cc",
"shell/browser/api/atom_api_power_save_blocker.h",
"shell/browser/api/atom_api_protocol.cc",
"shell/browser/api/atom_api_protocol.h",
"shell/browser/api/atom_api_screen.cc",
"shell/browser/api/atom_api_screen.h",
"shell/browser/api/atom_api_session.cc",
"shell/browser/api/atom_api_session.h",
"shell/browser/api/atom_api_system_preferences.cc",
"shell/browser/api/atom_api_system_preferences.h",
"shell/browser/api/atom_api_system_preferences_mac.mm",
"shell/browser/api/atom_api_system_preferences_win.cc",
"shell/browser/api/atom_api_top_level_window.cc",
"shell/browser/api/atom_api_top_level_window.h",
"shell/browser/api/atom_api_tray.cc",
"shell/browser/api/atom_api_tray.h",
"shell/browser/api/atom_api_url_request.cc",
"shell/browser/api/atom_api_url_request.h",
"shell/browser/api/atom_api_view.cc",
"shell/browser/api/atom_api_view.h",
"shell/browser/api/atom_api_web_contents.cc",
"shell/browser/api/atom_api_web_contents.h",
"shell/browser/api/atom_api_web_contents_impl.cc",
"shell/browser/api/atom_api_web_contents_mac.mm",
"shell/browser/api/atom_api_web_contents_view.cc",
"shell/browser/api/atom_api_web_contents_view.h",
"shell/browser/api/atom_api_web_request.cc",
"shell/browser/api/atom_api_web_request.h",
"shell/browser/api/atom_api_web_view_manager.cc",
"shell/browser/api/event.cc",
"shell/browser/api/event.h",
"shell/browser/api/event_emitter_deprecated.cc",
"shell/browser/api/event_emitter_deprecated.h",
"shell/browser/api/frame_subscriber.cc",
"shell/browser/api/frame_subscriber.h",
"shell/browser/api/gpu_info_enumerator.cc",
@@ -125,37 +123,35 @@ filenames = {
"shell/browser/api/process_metric.h",
"shell/browser/api/save_page_handler.cc",
"shell/browser/api/save_page_handler.h",
"shell/browser/api/trackable_object.cc",
"shell/browser/api/trackable_object.h",
"shell/browser/electron_autofill_driver.cc",
"shell/browser/electron_autofill_driver.h",
"shell/browser/electron_autofill_driver_factory.cc",
"shell/browser/electron_autofill_driver_factory.h",
"shell/browser/electron_browser_client.cc",
"shell/browser/electron_browser_client.h",
"shell/browser/electron_browser_context.cc",
"shell/browser/electron_browser_context.h",
"shell/browser/electron_browser_main_parts.cc",
"shell/browser/electron_browser_main_parts.h",
"shell/browser/electron_browser_main_parts_mac.mm",
"shell/browser/electron_browser_main_parts_posix.cc",
"shell/browser/electron_download_manager_delegate.cc",
"shell/browser/electron_download_manager_delegate.h",
"shell/browser/electron_gpu_client.cc",
"shell/browser/electron_gpu_client.h",
"shell/browser/electron_javascript_dialog_manager.cc",
"shell/browser/electron_javascript_dialog_manager.h",
"shell/browser/electron_navigation_throttle.cc",
"shell/browser/electron_navigation_throttle.h",
"shell/browser/electron_paths.h",
"shell/browser/electron_permission_manager.cc",
"shell/browser/electron_permission_manager.h",
"shell/browser/electron_quota_permission_context.cc",
"shell/browser/electron_quota_permission_context.h",
"shell/browser/electron_speech_recognition_manager_delegate.cc",
"shell/browser/electron_speech_recognition_manager_delegate.h",
"shell/browser/electron_web_ui_controller_factory.cc",
"shell/browser/electron_web_ui_controller_factory.h",
"shell/browser/atom_autofill_driver.cc",
"shell/browser/atom_autofill_driver_factory.cc",
"shell/browser/atom_autofill_driver_factory.h",
"shell/browser/atom_autofill_driver.h",
"shell/browser/atom_browser_client.cc",
"shell/browser/atom_browser_client.h",
"shell/browser/atom_browser_context.cc",
"shell/browser/atom_browser_context.h",
"shell/browser/atom_browser_main_parts.cc",
"shell/browser/atom_browser_main_parts.h",
"shell/browser/atom_browser_main_parts_mac.mm",
"shell/browser/atom_browser_main_parts_posix.cc",
"shell/browser/atom_download_manager_delegate.cc",
"shell/browser/atom_download_manager_delegate.h",
"shell/browser/atom_gpu_client.cc",
"shell/browser/atom_gpu_client.h",
"shell/browser/atom_javascript_dialog_manager.cc",
"shell/browser/atom_javascript_dialog_manager.h",
"shell/browser/atom_navigation_throttle.cc",
"shell/browser/atom_navigation_throttle.h",
"shell/browser/atom_paths.h",
"shell/browser/atom_permission_manager.cc",
"shell/browser/atom_permission_manager.h",
"shell/browser/atom_quota_permission_context.cc",
"shell/browser/atom_quota_permission_context.h",
"shell/browser/atom_speech_recognition_manager_delegate.cc",
"shell/browser/atom_speech_recognition_manager_delegate.h",
"shell/browser/atom_web_ui_controller_factory.cc",
"shell/browser/atom_web_ui_controller_factory.h",
"shell/browser/auto_updater.cc",
"shell/browser/auto_updater.h",
"shell/browser/auto_updater_mac.mm",
@@ -190,10 +186,10 @@ filenames = {
"shell/browser/linux/unity_service.h",
"shell/browser/login_handler.cc",
"shell/browser/login_handler.h",
"shell/browser/mac/electron_application.h",
"shell/browser/mac/electron_application.mm",
"shell/browser/mac/electron_application_delegate.h",
"shell/browser/mac/electron_application_delegate.mm",
"shell/browser/mac/atom_application_delegate.h",
"shell/browser/mac/atom_application_delegate.mm",
"shell/browser/mac/atom_application.h",
"shell/browser/mac/atom_application.mm",
"shell/browser/mac/dict_util.h",
"shell/browser/mac/dict_util.mm",
"shell/browser/mac/in_app_purchase.h",
@@ -226,27 +222,24 @@ filenames = {
"shell/browser/native_window_views_win.cc",
"shell/browser/net/asar/asar_url_loader.cc",
"shell/browser/net/asar/asar_url_loader.h",
"shell/browser/net/electron_url_loader_factory.cc",
"shell/browser/net/electron_url_loader_factory.h",
"shell/browser/net/atom_url_loader_factory.cc",
"shell/browser/net/atom_url_loader_factory.h",
"shell/browser/net/cert_verifier_client.cc",
"shell/browser/net/cert_verifier_client.h",
"shell/browser/net/network_context_service.cc",
"shell/browser/net/network_context_service.h",
"shell/browser/net/network_context_service_factory.cc",
"shell/browser/net/network_context_service_factory.h",
"shell/browser/net/network_context_service.h",
"shell/browser/net/node_stream_loader.cc",
"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",
@@ -262,16 +255,16 @@ filenames = {
"shell/browser/notifications/mac/notification_presenter_mac.h",
"shell/browser/notifications/mac/notification_presenter_mac.mm",
"shell/browser/notifications/notification.cc",
"shell/browser/notifications/notification.h",
"shell/browser/notifications/notification_delegate.h",
"shell/browser/notifications/notification.h",
"shell/browser/notifications/notification_presenter.cc",
"shell/browser/notifications/notification_presenter.h",
"shell/browser/notifications/platform_notification_service.cc",
"shell/browser/notifications/platform_notification_service.h",
"shell/browser/notifications/win/notification_presenter_win.cc",
"shell/browser/notifications/win/notification_presenter_win.h",
"shell/browser/notifications/win/notification_presenter_win7.cc",
"shell/browser/notifications/win/notification_presenter_win7.h",
"shell/browser/notifications/win/notification_presenter_win.cc",
"shell/browser/notifications/win/notification_presenter_win.h",
"shell/browser/notifications/win/win32_desktop_notifications/common.h",
"shell/browser/notifications/win/win32_desktop_notifications/desktop_notification_controller.cc",
"shell/browser/notifications/win/win32_desktop_notifications/desktop_notification_controller.h",
@@ -296,37 +289,37 @@ filenames = {
"shell/browser/special_storage_policy.h",
"shell/browser/ui/accelerator_util.cc",
"shell/browser/ui/accelerator_util.h",
"shell/browser/ui/electron_menu_model.cc",
"shell/browser/ui/electron_menu_model.h",
"shell/browser/ui/atom_menu_model.cc",
"shell/browser/ui/atom_menu_model.h",
"shell/browser/ui/autofill_popup.cc",
"shell/browser/ui/autofill_popup.h",
"shell/browser/ui/certificate_trust.h",
"shell/browser/ui/certificate_trust_mac.mm",
"shell/browser/ui/certificate_trust_win.cc",
"shell/browser/ui/cocoa/NSColor+Hex.h",
"shell/browser/ui/cocoa/NSColor+Hex.mm",
"shell/browser/ui/cocoa/NSString+ANSI.h",
"shell/browser/ui/cocoa/NSString+ANSI.mm",
"shell/browser/ui/cocoa/electron_bundle_mover.h",
"shell/browser/ui/cocoa/electron_bundle_mover.mm",
"shell/browser/ui/cocoa/electron_inspectable_web_contents_view.h",
"shell/browser/ui/cocoa/electron_inspectable_web_contents_view.mm",
"shell/browser/ui/cocoa/electron_menu_controller.h",
"shell/browser/ui/cocoa/electron_menu_controller.mm",
"shell/browser/ui/cocoa/electron_native_widget_mac.h",
"shell/browser/ui/cocoa/electron_native_widget_mac.mm",
"shell/browser/ui/cocoa/electron_ns_window.h",
"shell/browser/ui/cocoa/electron_ns_window.mm",
"shell/browser/ui/cocoa/electron_ns_window_delegate.h",
"shell/browser/ui/cocoa/electron_ns_window_delegate.mm",
"shell/browser/ui/cocoa/electron_preview_item.h",
"shell/browser/ui/cocoa/electron_preview_item.mm",
"shell/browser/ui/cocoa/electron_touch_bar.h",
"shell/browser/ui/cocoa/electron_touch_bar.mm",
"shell/browser/ui/cocoa/atom_bundle_mover.h",
"shell/browser/ui/cocoa/atom_bundle_mover.mm",
"shell/browser/ui/cocoa/atom_inspectable_web_contents_view.h",
"shell/browser/ui/cocoa/atom_inspectable_web_contents_view.mm",
"shell/browser/ui/cocoa/atom_menu_controller.h",
"shell/browser/ui/cocoa/atom_menu_controller.mm",
"shell/browser/ui/cocoa/atom_native_widget_mac.h",
"shell/browser/ui/cocoa/atom_native_widget_mac.mm",
"shell/browser/ui/cocoa/atom_ns_window_delegate.h",
"shell/browser/ui/cocoa/atom_ns_window_delegate.mm",
"shell/browser/ui/cocoa/atom_ns_window.h",
"shell/browser/ui/cocoa/atom_ns_window.mm",
"shell/browser/ui/cocoa/atom_preview_item.h",
"shell/browser/ui/cocoa/atom_preview_item.mm",
"shell/browser/ui/cocoa/atom_touch_bar.h",
"shell/browser/ui/cocoa/atom_touch_bar.mm",
"shell/browser/ui/cocoa/delayed_native_view_host.cc",
"shell/browser/ui/cocoa/delayed_native_view_host.h",
"shell/browser/ui/cocoa/event_dispatching_window.h",
"shell/browser/ui/cocoa/event_dispatching_window.mm",
"shell/browser/ui/cocoa/NSColor+Hex.h",
"shell/browser/ui/cocoa/NSColor+Hex.mm",
"shell/browser/ui/cocoa/NSString+ANSI.h",
"shell/browser/ui/cocoa/NSString+ANSI.mm",
"shell/browser/ui/cocoa/root_view_mac.h",
"shell/browser/ui/cocoa/root_view_mac.mm",
"shell/browser/ui/cocoa/views_delegate_mac.h",
@@ -338,35 +331,34 @@ filenames = {
"shell/browser/ui/drag_util.h",
"shell/browser/ui/drag_util_mac.mm",
"shell/browser/ui/drag_util_views.cc",
"shell/browser/ui/file_dialog.h",
"shell/browser/ui/file_dialog_gtk.cc",
"shell/browser/ui/file_dialog.h",
"shell/browser/ui/file_dialog_mac.mm",
"shell/browser/ui/file_dialog_win.cc",
"shell/browser/ui/inspectable_web_contents.cc",
"shell/browser/ui/inspectable_web_contents.h",
"shell/browser/ui/inspectable_web_contents_delegate.h",
"shell/browser/ui/inspectable_web_contents.h",
"shell/browser/ui/inspectable_web_contents_impl.cc",
"shell/browser/ui/inspectable_web_contents_impl.h",
"shell/browser/ui/inspectable_web_contents_view.h",
"shell/browser/ui/inspectable_web_contents_view_delegate.cc",
"shell/browser/ui/inspectable_web_contents_view_delegate.h",
"shell/browser/ui/inspectable_web_contents_view.h",
"shell/browser/ui/inspectable_web_contents_view_mac.h",
"shell/browser/ui/inspectable_web_contents_view_mac.mm",
"shell/browser/ui/message_box.h",
"shell/browser/ui/message_box_gtk.cc",
"shell/browser/ui/message_box.h",
"shell/browser/ui/message_box_mac.mm",
"shell/browser/ui/message_box_win.cc",
"shell/browser/ui/tray_icon.cc",
"shell/browser/ui/tray_icon.h",
"shell/browser/ui/tray_icon_cocoa.h",
"shell/browser/ui/tray_icon_cocoa.mm",
"shell/browser/ui/tray_icon_gtk.cc",
"shell/browser/ui/tray_icon_gtk.h",
"shell/browser/ui/tray_icon.h",
"shell/browser/ui/tray_icon_observer.h",
"shell/browser/ui/tray_icon_win.cc",
"shell/browser/ui/views/electron_views_delegate.cc",
"shell/browser/ui/views/electron_views_delegate_win.cc",
"shell/browser/ui/views/electron_views_delegate.h",
"shell/browser/ui/views/atom_views_delegate.cc",
"shell/browser/ui/views/atom_views_delegate.h",
"shell/browser/ui/views/autofill_popup_view.cc",
"shell/browser/ui/views/autofill_popup_view.h",
"shell/browser/ui/views/frameless_view.cc",
@@ -389,10 +381,10 @@ filenames = {
"shell/browser/ui/views/submenu_button.h",
"shell/browser/ui/views/win_frame_view.cc",
"shell/browser/ui/views/win_frame_view.h",
"shell/browser/ui/win/electron_desktop_native_widget_aura.cc",
"shell/browser/ui/win/electron_desktop_native_widget_aura.h",
"shell/browser/ui/win/electron_desktop_window_tree_host_win.cc",
"shell/browser/ui/win/electron_desktop_window_tree_host_win.h",
"shell/browser/ui/win/atom_desktop_native_widget_aura.cc",
"shell/browser/ui/win/atom_desktop_native_widget_aura.h",
"shell/browser/ui/win/atom_desktop_window_tree_host_win.cc",
"shell/browser/ui/win/atom_desktop_window_tree_host_win.h",
"shell/browser/ui/win/jump_list.cc",
"shell/browser/ui/win/jump_list.h",
"shell/browser/ui/win/notify_icon.cc",
@@ -421,33 +413,30 @@ filenames = {
"shell/browser/web_view_guest_delegate.h",
"shell/browser/web_view_manager.cc",
"shell/browser/web_view_manager.h",
"shell/browser/win/scoped_hstring.cc",
"shell/browser/win/scoped_hstring.h",
"shell/browser/window_list.cc",
"shell/browser/window_list.h",
"shell/browser/window_list_observer.h",
"shell/browser/win/scoped_hstring.cc",
"shell/browser/win/scoped_hstring.h",
"shell/browser/zoom_level_delegate.cc",
"shell/browser/zoom_level_delegate.h",
"shell/common/api/electron_api_asar.cc",
"shell/common/api/electron_api_clipboard.cc",
"shell/common/api/electron_api_clipboard.h",
"shell/common/api/electron_api_clipboard_mac.mm",
"shell/common/api/electron_api_command_line.cc",
"shell/common/api/electron_api_crash_reporter.cc",
"shell/common/api/electron_api_key_weak_map.h",
"shell/common/api/electron_api_native_image.cc",
"shell/common/api/electron_api_native_image.h",
"shell/common/api/electron_api_native_image_mac.mm",
"shell/common/api/electron_api_shell.cc",
"shell/common/api/electron_api_v8_util.cc",
"shell/common/api/atom_api_asar.cc",
"shell/common/api/atom_api_clipboard.cc",
"shell/common/api/atom_api_clipboard.h",
"shell/common/api/atom_api_clipboard_mac.mm",
"shell/common/api/atom_api_command_line.cc",
"shell/common/api/atom_api_crash_reporter.cc",
"shell/common/api/atom_api_key_weak_map.h",
"shell/common/api/atom_api_native_image.cc",
"shell/common/api/atom_api_native_image.h",
"shell/common/api/atom_api_native_image_mac.mm",
"shell/common/api/atom_api_shell.cc",
"shell/common/api/atom_api_v8_util.cc",
"shell/common/api/constructor.h",
"shell/common/api/electron_bindings.cc",
"shell/common/api/electron_bindings.h",
"shell/common/api/event_emitter_caller_deprecated.cc",
"shell/common/api/event_emitter_caller_deprecated.h",
"shell/common/api/constructor.h",
"shell/common/api/features.cc",
"shell/common/api/locker.cc",
"shell/common/api/locker.h",
"shell/common/application_info.cc",
"shell/common/application_info.h",
"shell/common/application_info_linux.cc",
@@ -459,10 +448,10 @@ filenames = {
"shell/common/asar/asar_util.h",
"shell/common/asar/scoped_temporary_file.cc",
"shell/common/asar/scoped_temporary_file.h",
"shell/common/electron_command_line.cc",
"shell/common/electron_command_line.h",
"shell/common/electron_constants.cc",
"shell/common/electron_constants.h",
"shell/common/atom_command_line.cc",
"shell/common/atom_command_line.h",
"shell/common/atom_constants.cc",
"shell/common/atom_constants.h",
"shell/common/color_util.cc",
"shell/common/color_util.h",
"shell/common/crash_reporter/crash_reporter.cc",
@@ -479,8 +468,13 @@ filenames = {
"shell/common/crash_reporter/win/crash_service_main.h",
"shell/common/deprecate_util.cc",
"shell/common/deprecate_util.h",
"shell/common/gin_converters/blink_converter_gin_adapter.h",
"shell/common/gin_converters/accelerator_converter.cc",
"shell/common/gin_converters/accelerator_converter.h",
"shell/common/gin_converters/blink_converter.cc",
"shell/common/gin_converters/blink_converter.h",
"shell/common/gin_converters/callback_converter.h",
"shell/common/gin_converters/content_converter.cc",
"shell/common/gin_converters/content_converter.h",
"shell/common/gin_converters/file_dialog_converter.cc",
"shell/common/gin_converters/file_dialog_converter.h",
"shell/common/gin_converters/file_path_converter.h",
@@ -495,7 +489,8 @@ filenames = {
"shell/common/gin_converters/net_converter.cc",
"shell/common/gin_converters/net_converter.h",
"shell/common/gin_converters/std_converter.h",
"shell/common/gin_converters/value_converter_gin_adapter.h",
"shell/common/gin_converters/value_converter.cc",
"shell/common/gin_converters/value_converter.h",
"shell/common/gin_helper/arguments.cc",
"shell/common/gin_helper/arguments.h",
"shell/common/gin_helper/callback.cc",
@@ -505,46 +500,31 @@ filenames = {
"shell/common/gin_helper/dictionary.h",
"shell/common/gin_helper/error_thrower.cc",
"shell/common/gin_helper/error_thrower.h",
"shell/common/gin_helper/event_emitter.cc",
"shell/common/gin_helper/event_emitter.h",
"shell/common/gin_helper/event_emitter_caller.cc",
"shell/common/gin_helper/event_emitter_caller.h",
"shell/common/gin_helper/event_emitter.cc",
"shell/common/gin_helper/event_emitter.h",
"shell/common/gin_helper/function_template.cc",
"shell/common/gin_helper/function_template.h",
"shell/common/gin_helper/locker.cc",
"shell/common/gin_helper/locker.h",
"shell/common/gin_helper/object_template_builder.cc",
"shell/common/gin_helper/object_template_builder.h",
"shell/common/gin_helper/persistent_dictionary.cc",
"shell/common/gin_helper/persistent_dictionary.h",
"shell/common/gin_helper/promise.h",
"shell/common/gin_helper/promise.cc",
"shell/common/gin_helper/trackable_object.cc",
"shell/common/gin_helper/trackable_object.h",
"shell/common/heap_snapshot.cc",
"shell/common/heap_snapshot.h",
"shell/common/key_weak_map.h",
"shell/common/keyboard_util.cc",
"shell/common/keyboard_util.h",
"shell/common/key_weak_map.h",
"shell/common/mac/main_application_bundle.h",
"shell/common/mac/main_application_bundle.mm",
"shell/common/mouse_util.cc",
"shell/common/mouse_util.h",
"shell/common/native_mate_converters/accelerator_converter.cc",
"shell/common/native_mate_converters/accelerator_converter.h",
"shell/common/native_mate_converters/blink_converter.cc",
"shell/common/native_mate_converters/blink_converter.h",
"shell/common/native_mate_converters/callback_converter_deprecated.cc",
"shell/common/native_mate_converters/callback_converter_deprecated.h",
"shell/common/native_mate_converters/content_converter.cc",
"shell/common/native_mate_converters/content_converter.h",
"shell/common/native_mate_converters/file_dialog_converter.h",
"shell/common/native_mate_converters/file_path_converter.h",
"shell/common/native_mate_converters/gurl_converter.h",
"shell/common/native_mate_converters/image_converter.h",
"shell/common/native_mate_converters/native_window_converter.h",
"shell/common/native_mate_converters/net_converter.h",
"shell/common/native_mate_converters/network_converter.cc",
"shell/common/native_mate_converters/network_converter.h",
"shell/common/native_mate_converters/once_callback.h",
"shell/common/native_mate_converters/string16_converter.h",
"shell/common/native_mate_converters/ui_base_types_converter.h",
"shell/common/native_mate_converters/v8_value_converter.cc",
"shell/common/native_mate_converters/v8_value_converter.h",
"shell/common/native_mate_converters/value_converter.cc",
"shell/common/native_mate_converters/value_converter.h",
"shell/common/node_bindings.cc",
"shell/common/node_bindings.h",
"shell/common/node_bindings_linux.cc",
@@ -562,42 +542,40 @@ filenames = {
"shell/common/platform_util_linux.cc",
"shell/common/platform_util_mac.mm",
"shell/common/platform_util_win.cc",
"shell/common/promise_util.cc",
"shell/common/promise_util.h",
"shell/common/skia_util.cc",
"shell/common/skia_util.h",
"shell/renderer/api/context_bridge/object_cache.cc",
"shell/renderer/api/context_bridge/object_cache.h",
"shell/renderer/api/context_bridge/render_frame_function_store.cc",
"shell/renderer/api/context_bridge/render_frame_function_store.h",
"shell/renderer/api/electron_api_context_bridge.cc",
"shell/renderer/api/electron_api_context_bridge.h",
"shell/renderer/api/electron_api_renderer_ipc.cc",
"shell/renderer/api/electron_api_spell_check_client.cc",
"shell/renderer/api/electron_api_spell_check_client.h",
"shell/renderer/api/electron_api_web_frame.cc",
"shell/renderer/electron_autofill_agent.cc",
"shell/renderer/electron_autofill_agent.h",
"shell/renderer/electron_render_frame_observer.cc",
"shell/renderer/electron_render_frame_observer.h",
"shell/renderer/electron_renderer_client.cc",
"shell/renderer/electron_renderer_client.h",
"shell/renderer/electron_sandboxed_renderer_client.cc",
"shell/renderer/electron_sandboxed_renderer_client.h",
"shell/renderer/browser_exposed_renderer_interfaces.cc",
"shell/renderer/browser_exposed_renderer_interfaces.h",
"shell/common/v8_value_converter.cc",
"shell/common/v8_value_converter.h",
"shell/renderer/api/atom_api_context_bridge.cc",
"shell/renderer/api/atom_api_context_bridge.h",
"shell/renderer/api/atom_api_renderer_ipc.cc",
"shell/renderer/api/atom_api_spell_check_client.cc",
"shell/renderer/api/atom_api_spell_check_client.h",
"shell/renderer/api/atom_api_web_frame.cc",
"shell/renderer/api/context_bridge/render_frame_context_bridge_store.cc",
"shell/renderer/api/context_bridge/render_frame_context_bridge_store.h",
"shell/renderer/atom_autofill_agent.cc",
"shell/renderer/atom_autofill_agent.h",
"shell/renderer/atom_renderer_client.cc",
"shell/renderer/atom_renderer_client.h",
"shell/renderer/atom_render_frame_observer.cc",
"shell/renderer/atom_render_frame_observer.h",
"shell/renderer/atom_sandboxed_renderer_client.cc",
"shell/renderer/atom_sandboxed_renderer_client.h",
"shell/renderer/content_settings_observer.cc",
"shell/renderer/content_settings_observer.h",
"shell/renderer/electron_api_service_impl.cc",
"shell/renderer/electron_api_service_impl.h",
"shell/renderer/electron_renderer_pepper_host_factory.cc",
"shell/renderer/electron_renderer_pepper_host_factory.h",
"shell/renderer/guest_view_container.cc",
"shell/renderer/guest_view_container.h",
"shell/renderer/renderer_client_base.cc",
"shell/renderer/renderer_client_base.h",
"shell/renderer/web_worker_observer.cc",
"shell/renderer/web_worker_observer.h",
"shell/utility/electron_content_utility_client.cc",
"shell/utility/electron_content_utility_client.h",
"shell/utility/atom_content_utility_client.cc",
"shell/utility/atom_content_utility_client.h",
]
lib_sources_nss = [
@@ -606,43 +584,43 @@ filenames = {
]
lib_sources_extensions = [
"shell/browser/extensions/api/runtime/electron_runtime_api_delegate.cc",
"shell/browser/extensions/api/runtime/electron_runtime_api_delegate.h",
"shell/browser/extensions/electron_extensions_browser_client.cc",
"shell/browser/extensions/electron_extensions_browser_client.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_display_info_provider.cc",
"shell/browser/extensions/electron_display_info_provider.h",
"shell/browser/extensions/electron_extension_host_delegate.cc",
"shell/browser/extensions/electron_extension_host_delegate.h",
"shell/browser/extensions/electron_extension_loader.cc",
"shell/browser/extensions/electron_extension_loader.h",
"shell/browser/extensions/electron_extension_system.cc",
"shell/browser/extensions/electron_extension_system.h",
"shell/browser/extensions/electron_extension_system_factory.cc",
"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/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/browser/extensions/api/runtime/atom_runtime_api_delegate.cc",
"shell/browser/extensions/api/runtime/atom_runtime_api_delegate.h",
"shell/browser/extensions/atom_extensions_browser_client.cc",
"shell/browser/extensions/atom_extensions_browser_client.h",
"shell/browser/extensions/atom_browser_context_keyed_service_factories.cc",
"shell/browser/extensions/atom_browser_context_keyed_service_factories.h",
"shell/browser/extensions/atom_display_info_provider.cc",
"shell/browser/extensions/atom_display_info_provider.h",
"shell/browser/extensions/atom_extension_host_delegate.cc",
"shell/browser/extensions/atom_extension_host_delegate.h",
"shell/browser/extensions/atom_extension_loader.cc",
"shell/browser/extensions/atom_extension_loader.h",
"shell/browser/extensions/atom_extension_system.cc",
"shell/browser/extensions/atom_extension_system.h",
"shell/browser/extensions/atom_extension_system_factory.cc",
"shell/browser/extensions/atom_extension_system_factory.h",
"shell/browser/extensions/atom_extension_web_contents_observer.cc",
"shell/browser/extensions/atom_extension_web_contents_observer.h",
"shell/browser/extensions/atom_navigation_ui_data.cc",
"shell/browser/extensions/atom_navigation_ui_data.h",
"shell/common/extensions/atom_extensions_api_provider.cc",
"shell/common/extensions/atom_extensions_api_provider.h",
"shell/common/extensions/atom_extensions_client.cc",
"shell/common/extensions/atom_extensions_client.h",
"shell/renderer/extensions/atom_extensions_renderer_client.cc",
"shell/renderer/extensions/atom_extensions_renderer_client.h",
]
app_sources = [
"shell/app/electron_main.cc",
"shell/app/electron_main.h",
"shell/app/atom_main.cc",
"shell/app/atom_main.h",
]
framework_sources = [
"shell/app/electron_library_main.h",
"shell/app/electron_library_main.mm",
"shell/app/atom_library_main.h",
"shell/app/atom_library_main.mm",
]
login_helper_sources = [ "shell/app/electron_login_helper.mm" ]
login_helper_sources = [ "shell/app/atom_login_helper.mm" ]
}

View File

@@ -1,21 +1,21 @@
import * as fs from 'fs';
import * as path from 'path';
import * as fs from 'fs'
import * as path from 'path'
import { deprecate, Menu } from 'electron';
import { EventEmitter } from 'events';
import { deprecate, Menu } from 'electron'
import { EventEmitter } from 'events'
const bindings = process.electronBinding('app');
const commandLine = process.electronBinding('command_line');
const { app, App } = bindings;
const bindings = process.electronBinding('app')
const commandLine = process.electronBinding('command_line')
const { app, App } = bindings
// Only one app object permitted.
export default app;
export default app
let dockMenu: Electron.Menu | null = null;
let dockMenu: Electron.Menu | null = null
// App is an EventEmitter.
Object.setPrototypeOf(App.prototype, EventEmitter.prototype);
EventEmitter.call(app as any);
Object.setPrototypeOf(App.prototype, EventEmitter.prototype)
EventEmitter.call(app as any)
Object.assign(app, {
commandLine: {
@@ -24,99 +24,99 @@ Object.assign(app, {
appendSwitch: (theSwitch: string, value?: string) => commandLine.appendSwitch(String(theSwitch), typeof value === 'undefined' ? value : String(value)),
appendArgument: (arg: string) => commandLine.appendArgument(String(arg))
} as Electron.CommandLine
});
})
// we define this here because it'd be overly complicated to
// do in native land
Object.defineProperty(app, 'applicationMenu', {
get () {
return Menu.getApplicationMenu();
return Menu.getApplicationMenu()
},
set (menu: Electron.Menu | null) {
return Menu.setApplicationMenu(menu);
return Menu.setApplicationMenu(menu)
}
});
})
App.prototype.isPackaged = (() => {
const execFile = path.basename(process.execPath).toLowerCase();
const execFile = path.basename(process.execPath).toLowerCase()
if (process.platform === 'win32') {
return execFile !== 'electron.exe';
return execFile !== 'electron.exe'
}
return execFile !== 'electron';
})();
return execFile !== 'electron'
})()
app._setDefaultAppPaths = (packagePath) => {
// Set the user path according to application's name.
app.setPath('userData', path.join(app.getPath('appData'), app.name!));
app.setPath('userCache', path.join(app.getPath('cache'), app.name!));
app.setAppPath(packagePath);
app.setPath('userData', path.join(app.getPath('appData'), app.name!))
app.setPath('userCache', path.join(app.getPath('cache'), app.name!))
app.setAppPath(packagePath)
// Add support for --user-data-dir=
if (app.commandLine.hasSwitch('user-data-dir')) {
const userDataDir = app.commandLine.getSwitchValue('user-data-dir');
if (path.isAbsolute(userDataDir)) app.setPath('userData', userDataDir);
const userDataDir = app.commandLine.getSwitchValue('user-data-dir')
if (path.isAbsolute(userDataDir)) app.setPath('userData', userDataDir)
}
};
}
if (process.platform === 'darwin') {
const setDockMenu = app.dock!.setMenu;
const setDockMenu = app.dock!.setMenu
app.dock!.setMenu = (menu) => {
dockMenu = menu;
setDockMenu(menu);
};
app.dock!.getMenu = () => dockMenu;
dockMenu = menu
setDockMenu(menu)
}
app.dock!.getMenu = () => dockMenu
}
if (process.platform === 'linux') {
const patternVmRSS = /^VmRSS:\s*(\d+) kB$/m;
const patternVmHWM = /^VmHWM:\s*(\d+) kB$/m;
const patternVmRSS = /^VmRSS:\s*(\d+) kB$/m
const patternVmHWM = /^VmHWM:\s*(\d+) kB$/m
const getStatus = (pid: number) => {
try {
return fs.readFileSync(`/proc/${pid}/status`, 'utf8');
return fs.readFileSync(`/proc/${pid}/status`, 'utf8')
} catch {
return '';
return ''
}
};
}
const getEntry = (file: string, pattern: RegExp) => {
const match = file.match(pattern);
return match ? parseInt(match[1], 10) : 0;
};
const match = file.match(pattern)
return match ? parseInt(match[1], 10) : 0
}
const getProcessMemoryInfo = (pid: number) => {
const file = getStatus(pid);
const file = getStatus(pid)
return {
workingSetSize: getEntry(file, patternVmRSS),
peakWorkingSetSize: getEntry(file, patternVmHWM)
};
};
}
}
const nativeFn = app.getAppMetrics;
const nativeFn = app.getAppMetrics
app.getAppMetrics = () => {
const metrics = nativeFn.call(app);
const metrics = nativeFn.call(app)
for (const metric of metrics) {
metric.memory = getProcessMemoryInfo(metric.pid);
metric.memory = getProcessMemoryInfo(metric.pid)
}
return metrics;
};
return metrics
}
}
// Routes the events to webContents.
const events = ['certificate-error', 'select-client-certificate'];
const events = ['login', 'certificate-error', 'select-client-certificate']
for (const name of events) {
app.on(name as 'certificate-error', (event, webContents, ...args: any[]) => {
webContents.emit(name, event, ...args);
});
app.on(name as 'login', (event, webContents, ...args: any[]) => {
webContents.emit(name, event, ...args)
})
}
// Property Deprecations
deprecate.fnToProperty(App.prototype, 'accessibilitySupportEnabled', '_isAccessibilitySupportEnabled', '_setAccessibilitySupportEnabled');
deprecate.fnToProperty(App.prototype, 'badgeCount', '_getBadgeCount', '_setBadgeCount');
deprecate.fnToProperty(App.prototype, 'name', '_getName', '_setName');
deprecate.fnToProperty(App.prototype, 'accessibilitySupportEnabled', '_isAccessibilitySupportEnabled', '_setAccessibilitySupportEnabled')
deprecate.fnToProperty(App.prototype, 'badgeCount', '_getBadgeCount', '_setBadgeCount')
deprecate.fnToProperty(App.prototype, 'name', '_getName', '_setName')
// Wrappers for native classes.
const { DownloadItem } = process.electronBinding('download_item');
Object.setPrototypeOf(DownloadItem.prototype, EventEmitter.prototype);
const { DownloadItem } = process.electronBinding('download_item')
Object.setPrototypeOf(DownloadItem.prototype, EventEmitter.prototype)

View File

@@ -1,7 +1,7 @@
'use strict';
'use strict'
if (process.platform === 'win32') {
module.exports = require('@electron/internal/browser/api/auto-updater/auto-updater-win');
module.exports = require('@electron/internal/browser/api/auto-updater/auto-updater-win')
} else {
module.exports = require('@electron/internal/browser/api/auto-updater/auto-updater-native');
module.exports = require('@electron/internal/browser/api/auto-updater/auto-updater-native')
}

View File

@@ -1,10 +1,10 @@
'use strict';
'use strict'
const EventEmitter = require('events').EventEmitter;
const { autoUpdater, AutoUpdater } = process.electronBinding('auto_updater');
const EventEmitter = require('events').EventEmitter
const { autoUpdater, AutoUpdater } = process.electronBinding('auto_updater')
// AutoUpdater is an EventEmitter.
Object.setPrototypeOf(AutoUpdater.prototype, EventEmitter.prototype);
EventEmitter.call(autoUpdater);
Object.setPrototypeOf(AutoUpdater.prototype, EventEmitter.prototype)
EventEmitter.call(autoUpdater)
module.exports = autoUpdater;
module.exports = autoUpdater

View File

@@ -1,74 +1,74 @@
'use strict';
'use strict'
const { app } = require('electron');
const { EventEmitter } = require('events');
const squirrelUpdate = require('@electron/internal/browser/api/auto-updater/squirrel-update-win');
const { app } = require('electron')
const { EventEmitter } = require('events')
const squirrelUpdate = require('@electron/internal/browser/api/auto-updater/squirrel-update-win')
class AutoUpdater extends EventEmitter {
quitAndInstall () {
if (!this.updateAvailable) {
return this.emitError('No update available, can\'t quit and install');
return this.emitError('No update available, can\'t quit and install')
}
squirrelUpdate.processStart();
app.quit();
squirrelUpdate.processStart()
app.quit()
}
getFeedURL () {
return this.updateURL;
return this.updateURL
}
setFeedURL (options) {
let updateURL;
let updateURL
if (typeof options === 'object') {
if (typeof options.url === 'string') {
updateURL = options.url;
updateURL = options.url
} else {
throw new Error('Expected options object to contain a \'url\' string property in setFeedUrl call');
throw new Error('Expected options object to contain a \'url\' string property in setFeedUrl call')
}
} else if (typeof options === 'string') {
updateURL = options;
updateURL = options
} else {
throw new Error('Expected an options object with a \'url\' property to be provided');
throw new Error('Expected an options object with a \'url\' property to be provided')
}
this.updateURL = updateURL;
this.updateURL = updateURL
}
checkForUpdates () {
if (!this.updateURL) {
return this.emitError('Update URL is not set');
return this.emitError('Update URL is not set')
}
if (!squirrelUpdate.supported()) {
return this.emitError('Can not find Squirrel');
return this.emitError('Can not find Squirrel')
}
this.emit('checking-for-update');
this.emit('checking-for-update')
squirrelUpdate.checkForUpdate(this.updateURL, (error, update) => {
if (error != null) {
return this.emitError(error);
return this.emitError(error)
}
if (update == null) {
return this.emit('update-not-available');
return this.emit('update-not-available')
}
this.updateAvailable = true;
this.emit('update-available');
this.updateAvailable = true
this.emit('update-available')
squirrelUpdate.update(this.updateURL, (error) => {
if (error != null) {
return this.emitError(error);
return this.emitError(error)
}
const { releaseNotes, version } = update;
const { releaseNotes, version } = update
// Date is not available on Windows, so fake it.
const date = new Date();
const date = new Date()
this.emit('update-downloaded', {}, releaseNotes, version, date, this.updateURL, () => {
this.quitAndInstall();
});
});
});
this.quitAndInstall()
})
})
})
}
// Private: Emit both error object and message, this is to keep compatibility
// with Old APIs.
emitError (message) {
this.emit('error', new Error(message), message);
this.emit('error', new Error(message), message)
}
}
module.exports = new AutoUpdater();
module.exports = new AutoUpdater()

View File

@@ -1,24 +1,24 @@
'use strict';
'use strict'
const fs = require('fs');
const path = require('path');
const spawn = require('child_process').spawn;
const fs = require('fs')
const path = require('path')
const spawn = require('child_process').spawn
// i.e. my-app/app-0.1.13/
const appFolder = path.dirname(process.execPath);
const appFolder = path.dirname(process.execPath)
// i.e. my-app/Update.exe
const updateExe = path.resolve(appFolder, '..', 'Update.exe');
const exeName = path.basename(process.execPath);
let spawnedArgs = [];
let spawnedProcess;
const updateExe = path.resolve(appFolder, '..', 'Update.exe')
const exeName = path.basename(process.execPath)
let spawnedArgs = []
let spawnedProcess
const isSameArgs = (args) => args.length === spawnedArgs.length && args.every((e, i) => e === spawnedArgs[i]);
const isSameArgs = (args) => args.length === spawnedArgs.length && args.every((e, i) => e === spawnedArgs[i])
// Spawn a command and invoke the callback when it completes with an error
// and the output from standard out.
const spawnUpdate = function (args, detached, callback) {
let error, errorEmitted, stderr, stdout;
let error, errorEmitted, stderr, stdout
try {
// Ensure we don't spawn multiple squirrel processes
@@ -28,92 +28,92 @@ const spawnUpdate = function (args, detached, callback) {
if (spawnedProcess && !isSameArgs(args)) {
// Disabled for backwards compatibility:
// eslint-disable-next-line standard/no-callback-literal
return callback(`AutoUpdater process with arguments ${args} is already running`);
return callback(`AutoUpdater process with arguments ${args} is already running`)
} else if (!spawnedProcess) {
spawnedProcess = spawn(updateExe, args, {
detached: detached,
windowsHide: true
});
spawnedArgs = args || [];
})
spawnedArgs = args || []
}
} catch (error1) {
error = error1;
error = error1
// Shouldn't happen, but still guard it.
process.nextTick(function () {
return callback(error);
});
return;
return callback(error)
})
return
}
stdout = '';
stderr = '';
stdout = ''
stderr = ''
spawnedProcess.stdout.on('data', (data) => { stdout += data; });
spawnedProcess.stderr.on('data', (data) => { stderr += data; });
spawnedProcess.stdout.on('data', (data) => { stdout += data })
spawnedProcess.stderr.on('data', (data) => { stderr += data })
errorEmitted = false;
errorEmitted = false
spawnedProcess.on('error', (error) => {
errorEmitted = true;
callback(error);
});
errorEmitted = true
callback(error)
})
return spawnedProcess.on('exit', function (code, signal) {
spawnedProcess = undefined;
spawnedArgs = [];
spawnedProcess = undefined
spawnedArgs = []
// We may have already emitted an error.
if (errorEmitted) {
return;
return
}
// Process terminated with error.
if (code !== 0) {
// Disabled for backwards compatibility:
// eslint-disable-next-line standard/no-callback-literal
return callback(`Command failed: ${signal != null ? signal : code}\n${stderr}`);
return callback(`Command failed: ${signal != null ? signal : code}\n${stderr}`)
}
// Success.
callback(null, stdout);
});
};
callback(null, stdout)
})
}
// Start an instance of the installed app.
exports.processStart = function () {
return spawnUpdate(['--processStartAndWait', exeName], true, function () {});
};
return spawnUpdate(['--processStartAndWait', exeName], true, function () {})
}
// Download the releases specified by the URL and write new results to stdout.
exports.checkForUpdate = function (updateURL, callback) {
return spawnUpdate(['--checkForUpdate', updateURL], false, function (error, stdout) {
let ref, ref1, update;
let ref, ref1, update
if (error != null) {
return callback(error);
return callback(error)
}
try {
// Last line of output is the JSON details about the releases
const json = stdout.trim().split('\n').pop();
update = (ref = JSON.parse(json)) != null ? (ref1 = ref.releasesToApply) != null ? typeof ref1.pop === 'function' ? ref1.pop() : void 0 : void 0 : void 0;
const json = stdout.trim().split('\n').pop()
update = (ref = JSON.parse(json)) != null ? (ref1 = ref.releasesToApply) != null ? typeof ref1.pop === 'function' ? ref1.pop() : void 0 : void 0 : void 0
} catch {
// Disabled for backwards compatibility:
// eslint-disable-next-line standard/no-callback-literal
return callback(`Invalid result:\n${stdout}`);
return callback(`Invalid result:\n${stdout}`)
}
return callback(null, update);
});
};
return callback(null, update)
})
}
// Update the application to the latest remote version specified by URL.
exports.update = function (updateURL, callback) {
return spawnUpdate(['--update', updateURL], false, callback);
};
return spawnUpdate(['--update', updateURL], false, callback)
}
// Is the Update.exe installed with the current application?
exports.supported = function () {
try {
fs.accessSync(updateExe, fs.R_OK);
return true;
fs.accessSync(updateExe, fs.R_OK)
return true
} catch {
return false;
return false
}
};
}

View File

@@ -1,16 +1,16 @@
'use strict';
'use strict'
const { EventEmitter } = require('events');
const { BrowserView } = process.electronBinding('browser_view');
const { EventEmitter } = require('events')
const { BrowserView } = process.electronBinding('browser_view')
Object.setPrototypeOf(BrowserView.prototype, EventEmitter.prototype);
Object.setPrototypeOf(BrowserView.prototype, EventEmitter.prototype)
BrowserView.fromWebContents = (webContents) => {
for (const view of BrowserView.getAllViews()) {
if (view.webContents.equal(webContents)) return view;
if (view.webContents.equal(webContents)) return view
}
return null;
};
return null
}
module.exports = BrowserView;
module.exports = BrowserView

View File

@@ -1,49 +1,49 @@
'use strict';
'use strict'
const electron = require('electron');
const { WebContentsView, TopLevelWindow, deprecate } = electron;
const { BrowserWindow } = process.electronBinding('window');
const electron = require('electron')
const { WebContentsView, TopLevelWindow, deprecate } = electron
const { BrowserWindow } = process.electronBinding('window')
Object.setPrototypeOf(BrowserWindow.prototype, TopLevelWindow.prototype);
Object.setPrototypeOf(BrowserWindow.prototype, TopLevelWindow.prototype)
BrowserWindow.prototype._init = function () {
// Call parent class's _init.
TopLevelWindow.prototype._init.call(this);
TopLevelWindow.prototype._init.call(this)
// Avoid recursive require.
const { app } = electron;
const { app } = electron
// Create WebContentsView.
this.setContentView(new WebContentsView(this.webContents));
this.setContentView(new WebContentsView(this.webContents))
const nativeSetBounds = this.setBounds;
const nativeSetBounds = this.setBounds
this.setBounds = (bounds, ...opts) => {
bounds = {
...this.getBounds(),
...bounds
};
nativeSetBounds.call(this, bounds, ...opts);
};
}
nativeSetBounds.call(this, bounds, ...opts)
}
// window.resizeTo(...)
// window.moveTo(...)
this.webContents.on('move', (event, size) => {
this.setBounds(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);
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);
});
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
@@ -54,144 +54,144 @@ BrowserWindow.prototype._init = function () {
// Finder, we still do it on all platforms in case of other bugs we don't
// know.
this.webContents.once('load-url', function () {
this.focus();
});
this.focus()
})
// Redirect focus/blur event to app instance too.
this.on('blur', (event) => {
app.emit('browser-window-blur', event, this);
});
app.emit('browser-window-blur', event, this)
})
this.on('focus', (event) => {
app.emit('browser-window-focus', event, this);
});
app.emit('browser-window-focus', event, this)
})
// Subscribe to visibilityState changes and pass to renderer process.
let isVisible = this.isVisible() && !this.isMinimized();
let isVisible = this.isVisible() && !this.isMinimized()
const visibilityChanged = () => {
const newState = this.isVisible() && !this.isMinimized();
const newState = this.isVisible() && !this.isMinimized()
if (isVisible !== newState) {
isVisible = newState;
const visibilityState = isVisible ? 'visible' : 'hidden';
this.webContents.emit('-window-visibility-change', visibilityState);
isVisible = newState
const visibilityState = isVisible ? 'visible' : 'hidden'
this.webContents.emit('-window-visibility-change', visibilityState)
}
};
}
const visibilityEvents = ['show', 'hide', 'minimize', 'maximize', 'restore'];
const visibilityEvents = ['show', 'hide', 'minimize', 'maximize', 'restore']
for (const event of visibilityEvents) {
this.on(event, visibilityChanged);
this.on(event, visibilityChanged)
}
// Notify the creation of the window.
const event = process.electronBinding('event').createEmpty();
app.emit('browser-window-created', event, this);
const event = process.electronBinding('event').createEmpty()
app.emit('browser-window-created', event, this)
Object.defineProperty(this, 'devToolsWebContents', {
enumerable: true,
configurable: false,
get () {
return this.webContents.devToolsWebContents;
return this.webContents.devToolsWebContents
}
});
};
})
}
const isBrowserWindow = (win) => {
return win && win.constructor.name === 'BrowserWindow';
};
return win && win.constructor.name === 'BrowserWindow'
}
BrowserWindow.fromId = (id) => {
const win = TopLevelWindow.fromId(id);
return isBrowserWindow(win) ? win : null;
};
const win = TopLevelWindow.fromId(id)
return isBrowserWindow(win) ? win : null
}
BrowserWindow.getAllWindows = () => {
return TopLevelWindow.getAllWindows().filter(isBrowserWindow);
};
return TopLevelWindow.getAllWindows().filter(isBrowserWindow)
}
BrowserWindow.getFocusedWindow = () => {
for (const window of BrowserWindow.getAllWindows()) {
if (window.isFocused() || window.isDevToolsFocused()) return window;
if (window.isFocused() || window.isDevToolsFocused()) return window
}
return null;
};
return null
}
BrowserWindow.fromWebContents = (webContents) => {
for (const window of BrowserWindow.getAllWindows()) {
if (window.webContents && window.webContents.equal(webContents)) return window;
if (window.webContents.equal(webContents)) return window
}
return null;
};
return null
}
BrowserWindow.fromBrowserView = (browserView) => {
for (const window of BrowserWindow.getAllWindows()) {
if (window.getBrowserView() === browserView) return window;
if (window.getBrowserView() === browserView) return window
}
return null;
};
return null
}
// Helpers.
Object.assign(BrowserWindow.prototype, {
loadURL (...args) {
return this.webContents.loadURL(...args);
return this.webContents.loadURL(...args)
},
getURL (...args) {
return this.webContents.getURL();
return this.webContents.getURL()
},
loadFile (...args) {
return this.webContents.loadFile(...args);
return this.webContents.loadFile(...args)
},
reload (...args) {
return this.webContents.reload(...args);
return this.webContents.reload(...args)
},
send (...args) {
return this.webContents.send(...args);
return this.webContents.send(...args)
},
openDevTools (...args) {
return this.webContents.openDevTools(...args);
return this.webContents.openDevTools(...args)
},
closeDevTools () {
return this.webContents.closeDevTools();
return this.webContents.closeDevTools()
},
isDevToolsOpened () {
return this.webContents.isDevToolsOpened();
return this.webContents.isDevToolsOpened()
},
isDevToolsFocused () {
return this.webContents.isDevToolsFocused();
return this.webContents.isDevToolsFocused()
},
toggleDevTools () {
return this.webContents.toggleDevTools();
return this.webContents.toggleDevTools()
},
inspectElement (...args) {
return this.webContents.inspectElement(...args);
return this.webContents.inspectElement(...args)
},
inspectSharedWorker () {
return this.webContents.inspectSharedWorker();
return this.webContents.inspectSharedWorker()
},
inspectServiceWorker () {
return this.webContents.inspectServiceWorker();
return this.webContents.inspectServiceWorker()
},
showDefinitionForSelection () {
return this.webContents.showDefinitionForSelection();
return this.webContents.showDefinitionForSelection()
},
capturePage (...args) {
return this.webContents.capturePage(...args);
return this.webContents.capturePage(...args)
},
setTouchBar (touchBar) {
electron.TouchBar._setOnWindow(touchBar, this);
electron.TouchBar._setOnWindow(touchBar, this)
},
setBackgroundThrottling (allowed) {
this.webContents.setBackgroundThrottling(allowed);
this.webContents.setBackgroundThrottling(allowed)
}
});
})
// Deprecations
deprecate.fnToProperty(BrowserWindow.prototype, 'autoHideMenuBar', '_isMenuBarAutoHide', '_setAutoHideMenuBar');
deprecate.fnToProperty(BrowserWindow.prototype, 'minimizable', '_isMinimizable', '_setMinimizable');
deprecate.fnToProperty(BrowserWindow.prototype, 'maximizable', '_isMaximizable', '_setMaximizable');
deprecate.fnToProperty(BrowserWindow.prototype, 'resizable', '_isResizable', '_setResizable');
deprecate.fnToProperty(BrowserWindow.prototype, 'fullScreenable', '_isFullScreenable', '_setFullScreenable');
deprecate.fnToProperty(BrowserWindow.prototype, 'closable', '_isClosable', '_setClosable');
deprecate.fnToProperty(BrowserWindow.prototype, 'movable', '_isMovable', '_setMovable');
deprecate.fnToProperty(BrowserWindow.prototype, 'autoHideMenuBar', '_isMenuBarAutoHide', '_setAutoHideMenuBar')
deprecate.fnToProperty(BrowserWindow.prototype, 'minimizable', '_isMinimizable', '_setMinimizable')
deprecate.fnToProperty(BrowserWindow.prototype, 'maximizable', '_isMaximizable', '_setMaximizable')
deprecate.fnToProperty(BrowserWindow.prototype, 'resizable', '_isResizable', '_setResizable')
deprecate.fnToProperty(BrowserWindow.prototype, 'fullScreenable', '_isFullScreenable', '_setFullScreenable')
deprecate.fnToProperty(BrowserWindow.prototype, 'closable', '_isClosable', '_setClosable')
deprecate.fnToProperty(BrowserWindow.prototype, 'movable', '_isMovable', '_setMovable')
module.exports = BrowserWindow;
module.exports = BrowserWindow

View File

@@ -1,2 +1,2 @@
'use strict';
module.exports = process.electronBinding('content_tracing');
'use strict'
module.exports = process.electronBinding('content_tracing')

View File

@@ -1,12 +1,12 @@
'use strict';
'use strict'
const CrashReporter = require('@electron/internal/common/crash-reporter');
const { crashReporterInit } = require('@electron/internal/browser/crash-reporter-init');
const CrashReporter = require('@electron/internal/common/crash-reporter')
const { crashReporterInit } = require('@electron/internal/browser/crash-reporter-init')
class CrashReporterMain extends CrashReporter {
init (options) {
return crashReporterInit(options);
return crashReporterInit(options)
}
}
module.exports = new CrashReporterMain();
module.exports = new CrashReporterMain()

View File

@@ -1,13 +1,13 @@
'use strict';
'use strict'
const { app, BrowserWindow, deprecate } = require('electron');
const binding = process.electronBinding('dialog');
const v8Util = process.electronBinding('v8_util');
const { app, BrowserWindow, deprecate } = require('electron')
const binding = process.electronBinding('dialog')
const v8Util = process.electronBinding('v8_util')
const DialogType = {
OPEN: 'OPEN',
SAVE: 'SAVE'
};
}
const saveFileDialogProperties = {
createDirectory: 1 << 0,
@@ -15,7 +15,7 @@ const saveFileDialogProperties = {
treatPackageAsDirectory: 1 << 2,
showOverwriteConfirmation: 1 << 3,
dontAddToRecent: 1 << 4
};
}
const openFileDialogProperties = {
openFile: 1 << 0,
@@ -27,15 +27,15 @@ const openFileDialogProperties = {
noResolveAliases: 1 << 6, // macOS
treatPackageAsDirectory: 1 << 7, // macOS
dontAddToRecent: 1 << 8 // Windows
};
}
const normalizeAccessKey = (text) => {
if (typeof text !== 'string') return text;
if (typeof text !== 'string') return text
// macOS does not have access keys so remove single ampersands
// and replace double ampersands with a single ampersand
if (process.platform === 'darwin') {
return text.replace(/&(&?)/g, '$1');
return text.replace(/&(&?)/g, '$1')
}
// Linux uses a single underscore as an access key prefix so escape
@@ -44,41 +44,41 @@ const normalizeAccessKey = (text) => {
// a single underscore
if (process.platform === 'linux') {
return text.replace(/_/g, '__').replace(/&(.?)/g, (match, after) => {
if (after === '&') return after;
return `_${after}`;
});
if (after === '&') return after
return `_${after}`
})
}
return text;
};
return text
}
const checkAppInitialized = function () {
if (!app.isReady()) {
throw new Error('dialog module can only be used after app is ready');
throw new Error('dialog module can only be used after app is ready')
}
};
}
const setupDialogProperties = (type, properties) => {
const dialogPropertiesTypes = (type === DialogType.OPEN) ? openFileDialogProperties : saveFileDialogProperties;
let dialogProperties = 0;
const dialogPropertiesTypes = (type === DialogType.OPEN) ? openFileDialogProperties : saveFileDialogProperties
let dialogProperties = 0
for (const prop in dialogPropertiesTypes) {
if (properties.includes(prop)) {
dialogProperties |= dialogPropertiesTypes[prop];
dialogProperties |= dialogPropertiesTypes[prop]
}
}
return dialogProperties;
};
return dialogProperties
}
const saveDialog = (sync, window, options) => {
checkAppInitialized();
checkAppInitialized()
if (window && window.constructor !== BrowserWindow) {
options = window;
window = null;
options = window
window = null
}
if (options == null) options = { title: 'Save' };
if (options == null) options = { title: 'Save' }
const {
buttonLabel = '',
@@ -90,33 +90,33 @@ const saveDialog = (sync, window, options) => {
securityScopedBookmarks = false,
nameFieldLabel = '',
showsTagField = true
} = options;
} = options
if (typeof title !== 'string') throw new TypeError('Title must be a string');
if (typeof buttonLabel !== 'string') throw new TypeError('Button label must be a string');
if (typeof defaultPath !== 'string') throw new TypeError('Default path must be a string');
if (typeof message !== 'string') throw new TypeError('Message must be a string');
if (typeof nameFieldLabel !== 'string') throw new TypeError('Name field label must be a string');
if (typeof title !== 'string') throw new TypeError('Title must be a string')
if (typeof buttonLabel !== 'string') throw new TypeError('Button label must be a string')
if (typeof defaultPath !== 'string') throw new TypeError('Default path must be a string')
if (typeof message !== 'string') throw new TypeError('Message must be a string')
if (typeof nameFieldLabel !== 'string') throw new TypeError('Name field label must be a string')
const settings = { buttonLabel, defaultPath, filters, title, message, securityScopedBookmarks, nameFieldLabel, showsTagField, window };
settings.properties = setupDialogProperties(DialogType.SAVE, properties);
const settings = { buttonLabel, defaultPath, filters, title, message, securityScopedBookmarks, nameFieldLabel, showsTagField, window }
settings.properties = setupDialogProperties(DialogType.SAVE, properties)
return (sync) ? binding.showSaveDialogSync(settings) : binding.showSaveDialog(settings);
};
return (sync) ? binding.showSaveDialogSync(settings) : binding.showSaveDialog(settings)
}
const openDialog = (sync, window, options) => {
checkAppInitialized();
checkAppInitialized()
if (window && window.constructor !== BrowserWindow) {
options = window;
window = null;
options = window
window = null
}
if (options == null) {
options = {
title: 'Open',
properties: ['openFile']
};
}
}
const {
@@ -127,33 +127,33 @@ const openDialog = (sync, window, options) => {
title = '',
message = '',
securityScopedBookmarks = false
} = options;
} = options
if (!Array.isArray(properties)) throw new TypeError('Properties must be an array');
if (!Array.isArray(properties)) throw new TypeError('Properties must be an array')
if (typeof title !== 'string') throw new TypeError('Title must be a string');
if (typeof buttonLabel !== 'string') throw new TypeError('Button label must be a string');
if (typeof defaultPath !== 'string') throw new TypeError('Default path must be a string');
if (typeof message !== 'string') throw new TypeError('Message must be a string');
if (typeof title !== 'string') throw new TypeError('Title must be a string')
if (typeof buttonLabel !== 'string') throw new TypeError('Button label must be a string')
if (typeof defaultPath !== 'string') throw new TypeError('Default path must be a string')
if (typeof message !== 'string') throw new TypeError('Message must be a string')
const settings = { title, buttonLabel, defaultPath, filters, message, securityScopedBookmarks, window };
settings.properties = setupDialogProperties(DialogType.OPEN, properties);
const settings = { title, buttonLabel, defaultPath, filters, message, securityScopedBookmarks, window }
settings.properties = setupDialogProperties(DialogType.OPEN, properties)
return (sync) ? binding.showOpenDialogSync(settings) : binding.showOpenDialog(settings);
};
return (sync) ? binding.showOpenDialogSync(settings) : binding.showOpenDialog(settings)
}
const messageBox = (sync, window, options) => {
checkAppInitialized();
checkAppInitialized()
if (window && window.constructor !== BrowserWindow) {
options = window;
window = null;
options = window
window = null
}
if (options == null) options = { type: 'none' };
if (options == null) options = { type: 'none' }
const messageBoxTypes = ['none', 'info', 'warning', 'error', 'question'];
const messageBoxOptions = { noLink: 1 << 0 };
const messageBoxTypes = ['none', 'info', 'warning', 'error', 'question']
const messageBoxOptions = { noLink: 1 << 0 }
let {
buttons = [],
@@ -163,104 +163,101 @@ const messageBox = (sync, window, options) => {
defaultId = -1,
detail = '',
icon = null,
noLink = false,
message = '',
title = '',
type = 'none'
} = options;
} = options
const messageBoxType = messageBoxTypes.indexOf(type);
if (messageBoxType === -1) throw new TypeError('Invalid message box type');
if (!Array.isArray(buttons)) throw new TypeError('Buttons must be an array');
if (options.normalizeAccessKeys) buttons = buttons.map(normalizeAccessKey);
if (typeof title !== 'string') throw new TypeError('Title must be a string');
if (typeof noLink !== 'boolean') throw new TypeError('noLink must be a boolean');
if (typeof message !== 'string') throw new TypeError('Message must be a string');
if (typeof detail !== 'string') throw new TypeError('Detail must be a string');
if (typeof checkboxLabel !== 'string') throw new TypeError('checkboxLabel must be a string');
const messageBoxType = messageBoxTypes.indexOf(type)
if (messageBoxType === -1) throw new TypeError('Invalid message box type')
if (!Array.isArray(buttons)) throw new TypeError('Buttons must be an array')
if (options.normalizeAccessKeys) buttons = buttons.map(normalizeAccessKey)
if (typeof title !== 'string') throw new TypeError('Title must be a string')
if (typeof message !== 'string') throw new TypeError('Message must be a string')
if (typeof detail !== 'string') throw new TypeError('Detail must be a string')
if (typeof checkboxLabel !== 'string') throw new TypeError('checkboxLabel must be a string')
checkboxChecked = !!checkboxChecked;
if (checkboxChecked && !checkboxLabel) {
throw new Error('checkboxChecked requires that checkboxLabel also be passed');
}
checkboxChecked = !!checkboxChecked
// Choose a default button to get selected when dialog is cancelled.
if (cancelId == null) {
// If the defaultId is set to 0, ensure the cancel button is a different index (1)
cancelId = (defaultId === 0 && buttons.length > 1) ? 1 : 0;
cancelId = (defaultId === 0 && buttons.length > 1) ? 1 : 0
for (let i = 0; i < buttons.length; i++) {
const text = buttons[i].toLowerCase();
const text = buttons[i].toLowerCase()
if (text === 'cancel' || text === 'no') {
cancelId = i;
break;
cancelId = i
break
}
}
}
const flags = options.noLink ? messageBoxOptions.noLink : 0
const settings = {
window,
messageBoxType,
buttons,
defaultId,
cancelId,
noLink,
flags,
title,
message,
detail,
checkboxLabel,
checkboxChecked,
icon
};
}
if (sync) {
return binding.showMessageBoxSync(settings);
return binding.showMessageBoxSync(settings)
} else {
return binding.showMessageBox(settings);
return binding.showMessageBox(settings)
}
};
}
module.exports = {
showOpenDialog: function (window, options) {
return openDialog(false, window, options);
return openDialog(false, window, options)
},
showOpenDialogSync: function (window, options) {
return openDialog(true, window, options);
return openDialog(true, window, options)
},
showSaveDialog: function (window, options) {
return saveDialog(false, window, options);
return saveDialog(false, window, options)
},
showSaveDialogSync: function (window, options) {
return saveDialog(true, window, options);
return saveDialog(true, window, options)
},
showMessageBox: function (window, options) {
return messageBox(false, window, options);
return messageBox(false, window, options)
},
showMessageBoxSync: function (window, options) {
return messageBox(true, window, options);
return messageBox(true, window, options)
},
showErrorBox: function (...args) {
return binding.showErrorBox(...args);
return binding.showErrorBox(...args)
},
showCertificateTrustDialog: function (window, options) {
if (window && window.constructor !== BrowserWindow) options = window;
if (window && window.constructor !== BrowserWindow) options = window
if (options == null || typeof options !== 'object') {
throw new TypeError('options must be an object');
throw new TypeError('options must be an object')
}
const { certificate, message = '' } = options;
const { certificate, message = '' } = options
if (certificate == null || typeof certificate !== 'object') {
throw new TypeError('certificate must be an object');
throw new TypeError('certificate must be an object')
}
if (typeof message !== 'string') throw new TypeError('message must be a string');
if (typeof message !== 'string') throw new TypeError('message must be a string')
return binding.showCertificateTrustDialog(window, certificate, message);
return binding.showCertificateTrustDialog(window, certificate, message)
}
};
}

View File

@@ -1,8 +1,8 @@
import { defineProperties } from '@electron/internal/common/define-properties';
import { commonModuleList } from '@electron/internal/common/api/module-list';
import { browserModuleList } from '@electron/internal/browser/api/module-list';
import { defineProperties } from '@electron/internal/common/define-properties'
import { commonModuleList } from '@electron/internal/common/api/module-list'
import { browserModuleList } from '@electron/internal/browser/api/module-list'
module.exports = {};
module.exports = {}
defineProperties(module.exports, commonModuleList);
defineProperties(module.exports, browserModuleList);
defineProperties(module.exports, commonModuleList)
defineProperties(module.exports, browserModuleList)

View File

@@ -1,3 +1,3 @@
'use strict';
'use strict'
module.exports = process.electronBinding('global_shortcut').globalShortcut;
module.exports = process.electronBinding('global_shortcut').globalShortcut

View File

@@ -1,22 +1,22 @@
'use strict';
'use strict'
const { deprecate } = require('electron');
const { deprecate } = require('electron')
if (process.platform === 'darwin') {
const { EventEmitter } = require('events');
const { inAppPurchase, InAppPurchase } = process.electronBinding('in_app_purchase');
const { EventEmitter } = require('events')
const { inAppPurchase, InAppPurchase } = process.electronBinding('in_app_purchase')
// inAppPurchase is an EventEmitter.
Object.setPrototypeOf(InAppPurchase.prototype, EventEmitter.prototype);
EventEmitter.call(inAppPurchase);
Object.setPrototypeOf(InAppPurchase.prototype, EventEmitter.prototype)
EventEmitter.call(inAppPurchase)
module.exports = inAppPurchase;
module.exports = inAppPurchase
} else {
module.exports = {
purchaseProduct: (productID, quantity, callback) => {
throw new Error('The inAppPurchase module can only be used on macOS');
throw new Error('The inAppPurchase module can only be used on macOS')
},
canMakePayments: () => false,
getReceiptURL: () => ''
};
}
}

View File

@@ -1,8 +1,8 @@
import { IpcMainImpl } from '@electron/internal/browser/ipc-main-impl';
import { IpcMainImpl } from '@electron/internal/browser/ipc-main-impl'
const ipcMain = new IpcMainImpl();
const ipcMain = new IpcMainImpl()
// Do not throw exception when channel name is "error".
ipcMain.on('error', () => {});
ipcMain.on('error', () => {})
export default ipcMain;
export default ipcMain

View File

@@ -1,15 +1,15 @@
'use strict';
'use strict'
const { app } = require('electron');
const { app } = require('electron')
const isMac = process.platform === 'darwin';
const isWindows = process.platform === 'win32';
const isLinux = process.platform === 'linux';
const isMac = process.platform === 'darwin'
const isWindows = process.platform === 'win32'
const isLinux = process.platform === 'linux'
const roles = {
about: {
get label () {
return isLinux ? 'About' : `About ${app.name}`;
return isLinux ? 'About' : `About ${app.name}`
}
},
close: {
@@ -38,7 +38,7 @@ const roles = {
accelerator: 'Shift+CmdOrCtrl+R',
nonNativeMacOSRole: true,
windowMethod: (window) => {
window.webContents.reloadIgnoringCache();
window.webContents.reloadIgnoringCache()
}
},
front: {
@@ -49,7 +49,7 @@ const roles = {
},
hide: {
get label () {
return `Hide ${app.name}`;
return `Hide ${app.name}`
},
accelerator: 'Command+H'
},
@@ -77,9 +77,9 @@ const roles = {
quit: {
get label () {
switch (process.platform) {
case 'darwin': return `Quit ${app.name}`;
case 'win32': return 'Exit';
default: return 'Quit';
case 'darwin': return `Quit ${app.name}`
case 'win32': return 'Exit'
default: return 'Quit'
}
},
accelerator: isWindows ? undefined : 'CommandOrControl+Q',
@@ -101,7 +101,7 @@ const roles = {
accelerator: 'CommandOrControl+0',
nonNativeMacOSRole: true,
webContentsMethod: (webContents) => {
webContents.zoomLevel = 0;
webContents.zoomLevel = 0
}
},
selectall: {
@@ -134,7 +134,7 @@ const roles = {
label: 'Toggle Full Screen',
accelerator: isMac ? 'Control+Command+F' : 'F11',
windowMethod: (window) => {
window.setFullScreen(!window.isFullScreen());
window.setFullScreen(!window.isFullScreen())
}
},
undo: {
@@ -156,7 +156,7 @@ const roles = {
accelerator: 'CommandOrControl+Plus',
nonNativeMacOSRole: true,
webContentsMethod: (webContents) => {
webContents.zoomLevel += 0.5;
webContents.zoomLevel += 0.5
}
},
zoomout: {
@@ -164,13 +164,13 @@ const roles = {
accelerator: 'CommandOrControl+-',
nonNativeMacOSRole: true,
webContentsMethod: (webContents) => {
webContents.zoomLevel -= 0.5;
webContents.zoomLevel -= 0.5
}
},
// App submenu should be used for Mac only
appmenu: {
get label () {
return app.name;
return app.name
},
submenu: [
{ role: 'about' },
@@ -249,71 +249,71 @@ const roles = {
])
]
}
};
}
exports.roleList = roles;
exports.roleList = roles
const canExecuteRole = (role) => {
if (!roles.hasOwnProperty(role)) return false;
if (!isMac) return true;
if (!roles.hasOwnProperty(role)) return false
if (!isMac) return true
// macOS handles all roles natively except for a few
return roles[role].nonNativeMacOSRole;
};
return roles[role].nonNativeMacOSRole
}
exports.getDefaultLabel = (role) => {
return roles.hasOwnProperty(role) ? roles[role].label : '';
};
return roles.hasOwnProperty(role) ? roles[role].label : ''
}
exports.getDefaultAccelerator = (role) => {
if (roles.hasOwnProperty(role)) return roles[role].accelerator;
};
if (roles.hasOwnProperty(role)) return roles[role].accelerator
}
exports.shouldRegisterAccelerator = (role) => {
const hasRoleRegister = roles.hasOwnProperty(role) && roles[role].registerAccelerator !== undefined;
return hasRoleRegister ? roles[role].registerAccelerator : true;
};
const hasRoleRegister = roles.hasOwnProperty(role) && roles[role].registerAccelerator !== undefined
return hasRoleRegister ? roles[role].registerAccelerator : true
}
exports.getDefaultSubmenu = (role) => {
if (!roles.hasOwnProperty(role)) return;
if (!roles.hasOwnProperty(role)) return
let { submenu } = roles[role];
let { submenu } = roles[role]
// remove null items from within the submenu
if (Array.isArray(submenu)) {
submenu = submenu.filter((item) => item != null);
submenu = submenu.filter((item) => item != null)
}
return submenu;
};
return submenu
}
exports.execute = (role, focusedWindow, focusedWebContents) => {
if (!canExecuteRole(role)) return false;
if (!canExecuteRole(role)) return false
const { appMethod, webContentsMethod, windowMethod } = roles[role];
const { appMethod, webContentsMethod, windowMethod } = roles[role]
if (appMethod) {
app[appMethod]();
return true;
app[appMethod]()
return true
}
if (windowMethod && focusedWindow != null) {
if (typeof windowMethod === 'function') {
windowMethod(focusedWindow);
windowMethod(focusedWindow)
} else {
focusedWindow[windowMethod]();
focusedWindow[windowMethod]()
}
return true;
return true
}
if (webContentsMethod && focusedWebContents != null) {
if (typeof webContentsMethod === 'function') {
webContentsMethod(focusedWebContents);
webContentsMethod(focusedWebContents)
} else {
focusedWebContents[webContentsMethod]();
focusedWebContents[webContentsMethod]()
}
return true;
return true
}
return false;
};
return false
}

View File

@@ -1,87 +1,87 @@
'use strict';
'use strict'
const roles = require('@electron/internal/browser/api/menu-item-roles');
const roles = require('@electron/internal/browser/api/menu-item-roles')
let nextCommandId = 0;
let nextCommandId = 0
const MenuItem = function (options) {
const { Menu } = require('electron');
const { Menu } = require('electron')
// Preserve extra fields specified by user
for (const key in options) {
if (!(key in this)) this[key] = options[key];
if (!(key in this)) this[key] = options[key]
}
if (typeof this.role === 'string' || this.role instanceof String) {
this.role = this.role.toLowerCase();
this.role = this.role.toLowerCase()
}
this.submenu = this.submenu || roles.getDefaultSubmenu(this.role);
this.submenu = this.submenu || roles.getDefaultSubmenu(this.role)
if (this.submenu != null && this.submenu.constructor !== Menu) {
this.submenu = Menu.buildFromTemplate(this.submenu);
this.submenu = Menu.buildFromTemplate(this.submenu)
}
if (this.type == null && this.submenu != null) {
this.type = 'submenu';
this.type = 'submenu'
}
if (this.type === 'submenu' && (this.submenu == null || this.submenu.constructor !== Menu)) {
throw new Error('Invalid submenu');
throw new Error('Invalid submenu')
}
this.overrideReadOnlyProperty('type', 'normal');
this.overrideReadOnlyProperty('role');
this.overrideReadOnlyProperty('accelerator');
this.overrideReadOnlyProperty('icon');
this.overrideReadOnlyProperty('submenu');
this.overrideReadOnlyProperty('type', 'normal')
this.overrideReadOnlyProperty('role')
this.overrideReadOnlyProperty('accelerator')
this.overrideReadOnlyProperty('icon')
this.overrideReadOnlyProperty('submenu')
this.overrideProperty('label', roles.getDefaultLabel(this.role));
this.overrideProperty('sublabel', '');
this.overrideProperty('toolTip', '');
this.overrideProperty('enabled', true);
this.overrideProperty('visible', true);
this.overrideProperty('checked', false);
this.overrideProperty('acceleratorWorksWhenHidden', true);
this.overrideProperty('registerAccelerator', roles.shouldRegisterAccelerator(this.role));
this.overrideProperty('label', roles.getDefaultLabel(this.role))
this.overrideProperty('sublabel', '')
this.overrideProperty('toolTip', '')
this.overrideProperty('enabled', true)
this.overrideProperty('visible', true)
this.overrideProperty('checked', false)
this.overrideProperty('acceleratorWorksWhenHidden', true)
this.overrideProperty('registerAccelerator', roles.shouldRegisterAccelerator(this.role))
if (!MenuItem.types.includes(this.type)) {
throw new Error(`Unknown menu item type: ${this.type}`);
throw new Error(`Unknown menu item type: ${this.type}`)
}
this.overrideReadOnlyProperty('commandId', ++nextCommandId);
this.overrideReadOnlyProperty('commandId', ++nextCommandId)
const click = options.click;
const click = options.click
this.click = (event, focusedWindow, focusedWebContents) => {
// Manually flip the checked flags when clicked.
if (this.type === 'checkbox' || this.type === 'radio') {
this.checked = !this.checked;
this.checked = !this.checked
}
if (!roles.execute(this.role, focusedWindow, focusedWebContents)) {
if (typeof click === 'function') {
click(this, focusedWindow, event);
click(this, focusedWindow, event)
} else if (typeof this.selector === 'string' && process.platform === 'darwin') {
Menu.sendActionToFirstResponder(this.selector);
Menu.sendActionToFirstResponder(this.selector)
}
}
};
};
}
}
MenuItem.types = ['normal', 'separator', 'submenu', 'checkbox', 'radio'];
MenuItem.types = ['normal', 'separator', 'submenu', 'checkbox', 'radio']
MenuItem.prototype.getDefaultRoleAccelerator = function () {
return roles.getDefaultAccelerator(this.role);
};
return roles.getDefaultAccelerator(this.role)
}
MenuItem.prototype.overrideProperty = function (name, defaultValue = null) {
if (this[name] == null) {
this[name] = defaultValue;
this[name] = defaultValue
}
};
}
MenuItem.prototype.overrideReadOnlyProperty = function (name, defaultValue) {
this.overrideProperty(name, defaultValue);
this.overrideProperty(name, defaultValue)
Object.defineProperty(this, name, {
enumerable: true,
writable: false,
value: this[name]
});
};
})
}
module.exports = MenuItem;
module.exports = MenuItem

View File

@@ -1,41 +1,41 @@
'use strict';
'use strict'
function splitArray (arr, predicate) {
const result = arr.reduce((multi, item) => {
const current = multi[multi.length - 1];
const current = multi[multi.length - 1]
if (predicate(item)) {
if (current.length > 0) multi.push([]);
if (current.length > 0) multi.push([])
} else {
current.push(item);
current.push(item)
}
return multi;
}, [[]]);
return multi
}, [[]])
if (result[result.length - 1].length === 0) {
return result.slice(0, result.length - 1);
return result.slice(0, result.length - 1)
}
return result;
return result
}
function joinArrays (arrays, joinIDs) {
return arrays.reduce((joined, arr, i) => {
if (i > 0 && arr.length) {
if (joinIDs.length > 0) {
joined.push(joinIDs[0]);
joinIDs.splice(0, 1);
joined.push(joinIDs[0])
joinIDs.splice(0, 1)
} else {
joined.push({ type: 'separator' });
joined.push({ type: 'separator' })
}
}
return joined.concat(arr);
}, []);
return joined.concat(arr)
}, [])
}
function pushOntoMultiMap (map, key, value) {
if (!map.has(key)) {
map.set(key, []);
map.set(key, [])
}
map.get(key).push(value);
map.get(key).push(value)
}
function indexOfGroupContainingID (groups, id, ignoreGroup) {
@@ -45,102 +45,102 @@ function indexOfGroupContainingID (groups, id, ignoreGroup) {
candidateGroup.some(
candidateItem => candidateItem.id === id
)
);
)
}
// Sort nodes topologically using a depth-first approach. Encountered cycles
// are broken.
function sortTopologically (originalOrder, edgesById) {
const sorted = [];
const marked = new Set();
const sorted = []
const marked = new Set()
const visit = (mark) => {
if (marked.has(mark)) return;
marked.add(mark);
const edges = edgesById.get(mark);
if (marked.has(mark)) return
marked.add(mark)
const edges = edgesById.get(mark)
if (edges != null) {
edges.forEach(visit);
edges.forEach(visit)
}
sorted.push(mark);
};
sorted.push(mark)
}
originalOrder.forEach(visit);
return sorted;
originalOrder.forEach(visit)
return sorted
}
function attemptToMergeAGroup (groups) {
for (let i = 0; i < groups.length; i++) {
const group = groups[i];
const group = groups[i]
for (const item of group) {
const toIDs = [...(item.before || []), ...(item.after || [])];
const toIDs = [...(item.before || []), ...(item.after || [])]
for (const id of toIDs) {
const index = indexOfGroupContainingID(groups, id, group);
if (index === -1) continue;
const mergeTarget = groups[index];
const index = indexOfGroupContainingID(groups, id, group)
if (index === -1) continue
const mergeTarget = groups[index]
mergeTarget.push(...group);
groups.splice(i, 1);
return true;
mergeTarget.push(...group)
groups.splice(i, 1)
return true
}
}
}
return false;
return false
}
function mergeGroups (groups) {
let merged = true;
let merged = true
while (merged) {
merged = attemptToMergeAGroup(groups);
merged = attemptToMergeAGroup(groups)
}
return groups;
return groups
}
function sortItemsInGroup (group) {
const originalOrder = group.map((node, i) => i);
const edges = new Map();
const idToIndex = new Map(group.map((item, i) => [item.id, i]));
const originalOrder = group.map((node, i) => i)
const edges = new Map()
const idToIndex = new Map(group.map((item, i) => [item.id, i]))
group.forEach((item, i) => {
if (item.before) {
item.before.forEach(toID => {
const to = idToIndex.get(toID);
const to = idToIndex.get(toID)
if (to != null) {
pushOntoMultiMap(edges, to, i);
pushOntoMultiMap(edges, to, i)
}
});
})
}
if (item.after) {
item.after.forEach(toID => {
const to = idToIndex.get(toID);
const to = idToIndex.get(toID)
if (to != null) {
pushOntoMultiMap(edges, i, to);
pushOntoMultiMap(edges, i, to)
}
});
})
}
});
})
const sortedNodes = sortTopologically(originalOrder, edges);
return sortedNodes.map(i => group[i]);
const sortedNodes = sortTopologically(originalOrder, edges)
return sortedNodes.map(i => group[i])
}
function findEdgesInGroup (groups, i, edges) {
const group = groups[i];
const group = groups[i]
for (const item of group) {
if (item.beforeGroupContaining) {
for (const id of item.beforeGroupContaining) {
const to = indexOfGroupContainingID(groups, id, group);
const to = indexOfGroupContainingID(groups, id, group)
if (to !== -1) {
pushOntoMultiMap(edges, to, i);
return;
pushOntoMultiMap(edges, to, i)
return
}
}
}
if (item.afterGroupContaining) {
for (const id of item.afterGroupContaining) {
const to = indexOfGroupContainingID(groups, id, group);
const to = indexOfGroupContainingID(groups, id, group)
if (to !== -1) {
pushOntoMultiMap(edges, i, to);
return;
pushOntoMultiMap(edges, i, to)
return
}
}
}
@@ -148,29 +148,29 @@ function findEdgesInGroup (groups, i, edges) {
}
function sortGroups (groups) {
const originalOrder = groups.map((item, i) => i);
const edges = new Map();
const originalOrder = groups.map((item, i) => i)
const edges = new Map()
for (let i = 0; i < groups.length; i++) {
findEdgesInGroup(groups, i, edges);
findEdgesInGroup(groups, i, edges)
}
const sortedGroupIndexes = sortTopologically(originalOrder, edges);
return sortedGroupIndexes.map(i => groups[i]);
const sortedGroupIndexes = sortTopologically(originalOrder, edges)
return sortedGroupIndexes.map(i => groups[i])
}
function sortMenuItems (menuItems) {
const isSeparator = (item) => item.type === 'separator';
const separators = menuItems.filter(i => i.type === 'separator');
const isSeparator = (item) => item.type === 'separator'
const separators = menuItems.filter(i => i.type === 'separator')
// Split the items into their implicit groups based upon separators.
const groups = splitArray(menuItems, isSeparator);
const mergedGroups = mergeGroups(groups);
const mergedGroupsWithSortedItems = mergedGroups.map(sortItemsInGroup);
const sortedGroups = sortGroups(mergedGroupsWithSortedItems);
const groups = splitArray(menuItems, isSeparator)
const mergedGroups = mergeGroups(groups)
const mergedGroupsWithSortedItems = mergedGroups.map(sortItemsInGroup)
const sortedGroups = sortGroups(mergedGroupsWithSortedItems)
const joined = joinArrays(sortedGroups, separators);
return joined;
const joined = joinArrays(sortedGroups, separators)
return joined
}
module.exports = { sortMenuItems };
module.exports = { sortMenuItems }

View File

@@ -1,16 +1,16 @@
'use strict';
'use strict'
const { TopLevelWindow, MenuItem, webContents } = require('electron');
const { sortMenuItems } = require('@electron/internal/browser/api/menu-utils');
const EventEmitter = require('events').EventEmitter;
const v8Util = process.electronBinding('v8_util');
const bindings = process.electronBinding('menu');
const { TopLevelWindow, MenuItem, webContents } = require('electron')
const { sortMenuItems } = require('@electron/internal/browser/api/menu-utils')
const EventEmitter = require('events').EventEmitter
const v8Util = process.electronBinding('v8_util')
const bindings = process.electronBinding('menu')
const { Menu } = bindings;
let applicationMenu = null;
let groupIdIndex = 0;
const { Menu } = bindings
let applicationMenu = null
let groupIdIndex = 0
Object.setPrototypeOf(Menu.prototype, EventEmitter.prototype);
Object.setPrototypeOf(Menu.prototype, EventEmitter.prototype)
// Menu Delegate.
// This object should hold no reference to |Menu| to avoid cyclic reference.
@@ -20,172 +20,172 @@ const delegate = {
shouldCommandIdWorkWhenHidden: (menu, id) => menu.commandsMap[id] ? menu.commandsMap[id].acceleratorWorksWhenHidden : undefined,
isCommandIdVisible: (menu, id) => menu.commandsMap[id] ? menu.commandsMap[id].visible : undefined,
getAcceleratorForCommandId: (menu, id, useDefaultAccelerator) => {
const command = menu.commandsMap[id];
if (!command) return;
if (command.accelerator != null) return command.accelerator;
if (useDefaultAccelerator) return command.getDefaultRoleAccelerator();
const command = menu.commandsMap[id]
if (!command) return
if (command.accelerator != null) return command.accelerator
if (useDefaultAccelerator) return command.getDefaultRoleAccelerator()
},
shouldRegisterAcceleratorForCommandId: (menu, id) => menu.commandsMap[id] ? menu.commandsMap[id].registerAccelerator : undefined,
executeCommand: (menu, event, id) => {
const command = menu.commandsMap[id];
if (!command) return;
command.click(event, TopLevelWindow.getFocusedWindow(), webContents.getFocusedWebContents());
const command = menu.commandsMap[id]
if (!command) return
command.click(event, TopLevelWindow.getFocusedWindow(), webContents.getFocusedWebContents())
},
menuWillShow: (menu) => {
// Ensure radio groups have at least one menu item selected
for (const id of Object.keys(menu.groupsMap)) {
const found = menu.groupsMap[id].find(item => item.checked) || null;
if (!found) v8Util.setHiddenValue(menu.groupsMap[id][0], 'checked', true);
for (const id in menu.groupsMap) {
const found = menu.groupsMap[id].find(item => item.checked) || null
if (!found) v8Util.setHiddenValue(menu.groupsMap[id][0], 'checked', true)
}
}
};
}
/* Instance Methods */
Menu.prototype._init = function () {
this.commandsMap = {};
this.groupsMap = {};
this.items = [];
this.delegate = delegate;
};
this.commandsMap = {}
this.groupsMap = {}
this.items = []
this.delegate = delegate
}
Menu.prototype.popup = function (options = {}) {
if (options == null || typeof options !== 'object') {
throw new TypeError('Options must be an object');
throw new TypeError('Options must be an object')
}
let { window, x, y, positioningItem, callback } = options;
let { window, x, y, positioningItem, callback } = options
// no callback passed
if (!callback || typeof callback !== 'function') callback = () => {};
if (!callback || typeof callback !== 'function') callback = () => {}
// set defaults
if (typeof x !== 'number') x = -1;
if (typeof y !== 'number') y = -1;
if (typeof positioningItem !== 'number') positioningItem = -1;
if (typeof x !== 'number') x = -1
if (typeof y !== 'number') y = -1
if (typeof positioningItem !== 'number') positioningItem = -1
// find which window to use
const wins = TopLevelWindow.getAllWindows();
const wins = TopLevelWindow.getAllWindows()
if (!wins || wins.indexOf(window) === -1) {
window = TopLevelWindow.getFocusedWindow();
window = TopLevelWindow.getFocusedWindow()
if (!window && wins && wins.length > 0) {
window = wins[0];
window = wins[0]
}
if (!window) {
throw new Error(`Cannot open Menu without a TopLevelWindow present`);
throw new Error(`Cannot open Menu without a TopLevelWindow present`)
}
}
this.popupAt(window, x, y, positioningItem, callback);
return { browserWindow: window, x, y, position: positioningItem };
};
this.popupAt(window, x, y, positioningItem, callback)
return { browserWindow: window, x, y, position: positioningItem }
}
Menu.prototype.closePopup = function (window) {
if (window instanceof TopLevelWindow) {
this.closePopupAt(window.id);
this.closePopupAt(window.id)
} else {
// Passing -1 (invalid) would make closePopupAt close the all menu runners
// belong to this menu.
this.closePopupAt(-1);
this.closePopupAt(-1)
}
};
}
Menu.prototype.getMenuItemById = function (id) {
const items = this.items;
const items = this.items
let found = items.find(item => item.id === id) || null;
let found = items.find(item => item.id === id) || null
for (let i = 0; !found && i < items.length; i++) {
if (items[i].submenu) {
found = items[i].submenu.getMenuItemById(id);
found = items[i].submenu.getMenuItemById(id)
}
}
return found;
};
return found
}
Menu.prototype.append = function (item) {
return this.insert(this.getItemCount(), item);
};
return this.insert(this.getItemCount(), item)
}
Menu.prototype.insert = function (pos, item) {
if ((item ? item.constructor : void 0) !== MenuItem) {
throw new TypeError('Invalid item');
throw new TypeError('Invalid item')
}
if (pos < 0) {
throw new RangeError(`Position ${pos} cannot be less than 0`);
throw new RangeError(`Position ${pos} cannot be less than 0`)
} else if (pos > this.getItemCount()) {
throw new RangeError(`Position ${pos} cannot be greater than the total MenuItem count`);
throw new RangeError(`Position ${pos} cannot be greater than the total MenuItem count`)
}
// insert item depending on its type
insertItemByType.call(this, item, pos);
insertItemByType.call(this, item, pos)
// set item properties
if (item.sublabel) this.setSublabel(pos, item.sublabel);
if (item.toolTip) this.setToolTip(pos, item.toolTip);
if (item.icon) this.setIcon(pos, item.icon);
if (item.role) this.setRole(pos, item.role);
if (item.sublabel) this.setSublabel(pos, item.sublabel)
if (item.toolTip) this.setToolTip(pos, item.toolTip)
if (item.icon) this.setIcon(pos, item.icon)
if (item.role) this.setRole(pos, item.role)
// Make menu accessable to items.
item.overrideReadOnlyProperty('menu', this);
item.overrideReadOnlyProperty('menu', this)
// Remember the items.
this.items.splice(pos, 0, item);
this.commandsMap[item.commandId] = item;
};
this.items.splice(pos, 0, item)
this.commandsMap[item.commandId] = item
}
Menu.prototype._callMenuWillShow = function () {
if (this.delegate) this.delegate.menuWillShow(this);
if (this.delegate) this.delegate.menuWillShow(this)
this.items.forEach(item => {
if (item.submenu) item.submenu._callMenuWillShow();
});
};
if (item.submenu) item.submenu._callMenuWillShow()
})
}
/* Static Methods */
Menu.getApplicationMenu = () => applicationMenu;
Menu.getApplicationMenu = () => applicationMenu
Menu.sendActionToFirstResponder = bindings.sendActionToFirstResponder;
Menu.sendActionToFirstResponder = bindings.sendActionToFirstResponder
// set application menu with a preexisting menu
Menu.setApplicationMenu = function (menu) {
if (menu && menu.constructor !== Menu) {
throw new TypeError('Invalid menu');
throw new TypeError('Invalid menu')
}
applicationMenu = menu;
v8Util.setHiddenValue(global, 'applicationMenuSet', true);
applicationMenu = menu
v8Util.setHiddenValue(global, 'applicationMenuSet', true)
if (process.platform === 'darwin') {
if (!menu) return;
menu._callMenuWillShow();
bindings.setApplicationMenu(menu);
if (!menu) return
menu._callMenuWillShow()
bindings.setApplicationMenu(menu)
} else {
const windows = TopLevelWindow.getAllWindows();
return windows.map(w => w.setMenu(menu));
const windows = TopLevelWindow.getAllWindows()
return windows.map(w => w.setMenu(menu))
}
};
}
Menu.buildFromTemplate = function (template) {
if (!Array.isArray(template)) {
throw new TypeError('Invalid template for Menu: Menu template must be an array');
throw new TypeError('Invalid template for Menu: Menu template must be an array')
}
if (!areValidTemplateItems(template)) {
throw new TypeError('Invalid template for MenuItem: must have at least one of label, role or type');
throw new TypeError('Invalid template for MenuItem: must have at least one of label, role or type')
}
const filtered = removeExtraSeparators(template);
const sorted = sortTemplate(filtered);
const filtered = removeExtraSeparators(template)
const sorted = sortTemplate(filtered)
const menu = new Menu();
const menu = new Menu()
sorted.forEach(item => {
if (item instanceof MenuItem) {
menu.append(item);
menu.append(item)
} else {
menu.append(new MenuItem(item));
menu.append(new MenuItem(item))
}
});
})
return menu;
};
return menu
}
/* Helper Functions */
@@ -196,50 +196,51 @@ function areValidTemplateItems (template) {
typeof item === 'object' &&
(item.hasOwnProperty('label') ||
item.hasOwnProperty('role') ||
item.type === 'separator'));
item.type === 'separator'))
}
function sortTemplate (template) {
const sorted = sortMenuItems(template);
for (const item of sorted) {
const sorted = sortMenuItems(template)
for (const id in sorted) {
const item = sorted[id]
if (Array.isArray(item.submenu)) {
item.submenu = sortTemplate(item.submenu);
item.submenu = sortTemplate(item.submenu)
}
}
return sorted;
return sorted
}
// Search between separators to find a radio menu item and return its group id
function generateGroupId (items, pos) {
if (pos > 0) {
for (let idx = pos - 1; idx >= 0; idx--) {
if (items[idx].type === 'radio') return items[idx].groupId;
if (items[idx].type === 'separator') break;
if (items[idx].type === 'radio') return items[idx].groupId
if (items[idx].type === 'separator') break
}
} else if (pos < items.length) {
for (let idx = pos; idx <= items.length - 1; idx++) {
if (items[idx].type === 'radio') return items[idx].groupId;
if (items[idx].type === 'separator') break;
if (items[idx].type === 'radio') return items[idx].groupId
if (items[idx].type === 'separator') break
}
}
groupIdIndex += 1;
return groupIdIndex;
groupIdIndex += 1
return groupIdIndex
}
function removeExtraSeparators (items) {
// fold adjacent separators together
let ret = items.filter((e, idx, arr) => {
if (e.visible === false) return true;
return e.type !== 'separator' || idx === 0 || arr[idx - 1].type !== 'separator';
});
if (e.visible === false) return true
return e.type !== 'separator' || idx === 0 || arr[idx - 1].type !== 'separator'
})
// remove edge separators
ret = ret.filter((e, idx, arr) => {
if (e.visible === false) return true;
return e.type !== 'separator' || (idx !== 0 && idx !== arr.length - 1);
});
if (e.visible === false) return true
return e.type !== 'separator' || (idx !== 0 && idx !== arr.length - 1)
})
return ret;
return ret
}
function insertItemByType (item, pos) {
@@ -250,28 +251,28 @@ function insertItemByType (item, pos) {
submenu: () => this.insertSubMenu(pos, item.commandId, item.label, item.submenu),
radio: () => {
// Grouping radio menu items
item.overrideReadOnlyProperty('groupId', generateGroupId(this.items, pos));
item.overrideReadOnlyProperty('groupId', generateGroupId(this.items, pos))
if (this.groupsMap[item.groupId] == null) {
this.groupsMap[item.groupId] = [];
this.groupsMap[item.groupId] = []
}
this.groupsMap[item.groupId].push(item);
this.groupsMap[item.groupId].push(item)
// Setting a radio menu item should flip other items in the group.
v8Util.setHiddenValue(item, 'checked', item.checked);
v8Util.setHiddenValue(item, 'checked', item.checked)
Object.defineProperty(item, 'checked', {
enumerable: true,
get: () => v8Util.getHiddenValue(item, 'checked'),
set: () => {
this.groupsMap[item.groupId].forEach(other => {
if (other !== item) v8Util.setHiddenValue(other, 'checked', false);
});
v8Util.setHiddenValue(item, 'checked', true);
if (other !== item) v8Util.setHiddenValue(other, 'checked', false)
})
v8Util.setHiddenValue(item, 'checked', true)
}
});
this.insertRadioItem(pos, item.commandId, item.label, item.groupId);
})
this.insertRadioItem(pos, item.commandId, item.label, item.groupId)
}
};
types[item.type]();
}
types[item.type]()
}
module.exports = Menu;
module.exports = Menu

View File

@@ -1,11 +1,11 @@
'use strict';
'use strict'
// TODO: Figure out a way to not duplicate this information between here and module-list
// It is currently duplicated as module-list "require"s all the browser API file and the
// remote module in the renderer process depends on that file. As a result webpack
// includes all the browser API files in the renderer process as well and we want to avoid that
const features = process.electronBinding('features');
const features = process.electronBinding('features')
// Browser side modules, please sort alphabetically.
module.exports = [
@@ -37,7 +37,7 @@ module.exports = [
{ name: 'View' },
{ name: 'webContents' },
{ name: 'WebContentsView' }
];
]
if (features.isViewApiEnabled()) {
module.exports.push(
@@ -48,5 +48,5 @@ if (features.isViewApiEnabled()) {
{ name: 'MdTextButton' },
{ name: 'ResizeArea' },
{ name: 'TextField' }
);
)
}

View File

@@ -1,6 +1,6 @@
// TODO: Updating this file also required updating the module-keys file
const features = process.electronBinding('features');
const features = process.electronBinding('features')
// Browser side modules, please sort alphabetically.
export const browserModuleList: ElectronInternal.ModuleEntry[] = [
@@ -32,7 +32,7 @@ export const browserModuleList: ElectronInternal.ModuleEntry[] = [
{ name: 'View', loader: () => require('./view') },
{ name: 'webContents', loader: () => require('./web-contents') },
{ name: 'WebContentsView', loader: () => require('./web-contents-view') }
];
]
if (features.isViewApiEnabled()) {
browserModuleList.push(
@@ -43,5 +43,5 @@ if (features.isViewApiEnabled()) {
{ name: 'MdTextButton', loader: () => require('./views/md-text-button') },
{ name: 'ResizeArea', loader: () => require('./views/resize-area') },
{ name: 'TextField', loader: () => require('./views/text-field') }
);
)
}

View File

@@ -1,8 +1,8 @@
import { EventEmitter } from 'events';
import { EventEmitter } from 'events'
const { NativeTheme, nativeTheme } = process.electronBinding('native_theme');
const { NativeTheme, nativeTheme } = process.electronBinding('native_theme')
Object.setPrototypeOf(NativeTheme.prototype, EventEmitter.prototype);
EventEmitter.call(nativeTheme as any);
Object.setPrototypeOf(NativeTheme.prototype, EventEmitter.prototype)
EventEmitter.call(nativeTheme as any)
module.exports = nativeTheme;
module.exports = nativeTheme

View File

@@ -1,32 +1,32 @@
'use strict';
'use strict'
// TODO(deepak1556): Deprecate and remove standalone netLog module,
// it is now a property of session module.
const { app, session } = require('electron');
const { app, session } = require('electron')
// Fallback to default session.
Object.setPrototypeOf(module.exports, new Proxy({}, {
get (target, property) {
if (!app.isReady()) return;
if (!app.isReady()) return
const netLog = session.defaultSession.netLog;
const netLog = session.defaultSession.netLog
if (!Object.getPrototypeOf(netLog).hasOwnProperty(property)) return;
if (!Object.getPrototypeOf(netLog).hasOwnProperty(property)) return
// check for properties on the prototype chain that aren't functions
if (typeof netLog[property] !== 'function') return netLog[property];
if (typeof netLog[property] !== 'function') return netLog[property]
// Returning a native function directly would throw error.
return (...args) => netLog[property](...args);
return (...args) => netLog[property](...args)
},
ownKeys () {
if (!app.isReady()) return [];
if (!app.isReady()) return []
return Object.getOwnPropertyNames(Object.getPrototypeOf(session.defaultSession.netLog));
return Object.getOwnPropertyNames(Object.getPrototypeOf(session.defaultSession.netLog))
},
getOwnPropertyDescriptor (target) {
return { configurable: true, enumerable: true };
return { configurable: true, enumerable: true }
}
}));
}))

View File

@@ -1,16 +1,20 @@
'use strict';
'use strict'
const url = require('url');
const { EventEmitter } = require('events');
const { Readable, Writable } = require('stream');
const { app } = require('electron');
const { Session } = process.electronBinding('session');
const { net, Net, _isValidHeaderName, _isValidHeaderValue } = process.electronBinding('net');
const { URLLoader } = net;
const url = require('url')
const { EventEmitter } = require('events')
const { Readable } = require('stream')
const { app } = require('electron')
const { Session } = process.electronBinding('session')
const { net, Net } = process.electronBinding('net')
const { URLRequest } = net
Object.setPrototypeOf(URLLoader.prototype, EventEmitter.prototype);
// Net is an EventEmitter.
Object.setPrototypeOf(Net.prototype, EventEmitter.prototype)
EventEmitter.call(net)
const kSupportedProtocols = new Set(['http:', 'https:']);
Object.setPrototypeOf(URLRequest.prototype, EventEmitter.prototype)
const kSupportedProtocols = new Set(['http:', 'https:'])
// set of headers that Node.js discards duplicates for
// see https://nodejs.org/api/http.html#http_message_headers
@@ -33,445 +37,375 @@ const discardableDuplicateHeaders = new Set([
'server',
'age',
'expires'
]);
])
class IncomingMessage extends Readable {
constructor (responseHead) {
super();
this._shouldPush = false;
this._data = [];
this._responseHead = responseHead;
constructor (urlRequest) {
super()
this.urlRequest = urlRequest
this.shouldPush = false
this.data = []
this.urlRequest.on('data', (event, chunk) => {
this._storeInternalData(chunk)
this._pushInternalData()
})
this.urlRequest.on('end', () => {
this._storeInternalData(null)
this._pushInternalData()
})
}
get statusCode () {
return this._responseHead.statusCode;
return this.urlRequest.statusCode
}
get statusMessage () {
return this._responseHead.statusMessage;
return this.urlRequest.statusMessage
}
get headers () {
const filteredHeaders = {};
const { rawHeaders } = this._responseHead;
rawHeaders.forEach(header => {
if (Object.prototype.hasOwnProperty.call(filteredHeaders, header.key) &&
discardableDuplicateHeaders.has(header.key)) {
const filteredHeaders = {}
const rawHeaders = this.urlRequest.rawResponseHeaders
Object.keys(rawHeaders).forEach(header => {
if (header in filteredHeaders && discardableDuplicateHeaders.has(header)) {
// do nothing with discardable duplicate headers
} else {
if (header.key === 'set-cookie') {
if (header === 'set-cookie') {
// keep set-cookie as an array per Node.js rules
// see https://nodejs.org/api/http.html#http_message_headers
if (Object.prototype.hasOwnProperty.call(filteredHeaders, header.key)) {
filteredHeaders[header.key].push(header.value);
} else {
filteredHeaders[header.key] = [header.value];
}
filteredHeaders[header] = rawHeaders[header]
} else {
// for non-cookie headers, the values are joined together with ', '
if (Object.prototype.hasOwnProperty.call(filteredHeaders, header.key)) {
filteredHeaders[header.key] += `, ${header.value}`;
} else {
filteredHeaders[header.key] = header.value;
}
filteredHeaders[header] = rawHeaders[header].join(', ')
}
}
});
return filteredHeaders;
})
return filteredHeaders
}
get httpVersion () {
return `${this.httpVersionMajor}.${this.httpVersionMinor}`;
return `${this.httpVersionMajor}.${this.httpVersionMinor}`
}
get httpVersionMajor () {
return this._responseHead.httpVersion.major;
return this.urlRequest.httpVersionMajor
}
get httpVersionMinor () {
return this._responseHead.httpVersion.minor;
return this.urlRequest.httpVersionMinor
}
get rawTrailers () {
throw new Error('HTTP trailers are not supported');
throw new Error('HTTP trailers are not supported')
}
get trailers () {
throw new Error('HTTP trailers are not supported');
throw new Error('HTTP trailers are not supported')
}
_storeInternalData (chunk) {
this._data.push(chunk);
this._pushInternalData();
this.data.push(chunk)
}
_pushInternalData () {
while (this._shouldPush && this._data.length > 0) {
const chunk = this._data.shift();
this._shouldPush = this.push(chunk);
while (this.shouldPush && this.data.length > 0) {
const chunk = this.data.shift()
this.shouldPush = this.push(chunk)
}
}
_read () {
this._shouldPush = true;
this._pushInternalData();
this.shouldPush = true
this._pushInternalData()
}
}
/** Writable stream that buffers up everything written to it. */
class SlurpStream extends Writable {
constructor () {
super();
this._data = Buffer.alloc(0);
}
_write (chunk, encoding, callback) {
this._data = Buffer.concat([this._data, chunk]);
callback();
}
data () { return this._data; }
}
class ChunkedBodyStream extends Writable {
constructor (clientRequest) {
super();
this._clientRequest = clientRequest;
}
_write (chunk, encoding, callback) {
if (this._downstream) {
this._downstream.write(chunk).then(callback, callback);
} else {
// the contract of _write is that we won't be called again until we call
// the callback, so we're good to just save a single chunk.
this._pendingChunk = chunk;
this._pendingCallback = callback;
// The first write to a chunked body stream begins the request.
this._clientRequest._startRequest();
}
}
_final (callback) {
this._downstream.done();
callback();
}
startReading (pipe) {
if (this._downstream) {
throw new Error('two startReading calls???');
}
this._downstream = pipe;
if (this._pendingChunk) {
const doneWriting = (maybeError) => {
const cb = this._pendingCallback;
delete this._pendingCallback;
delete this._pendingChunk;
cb(maybeError);
};
this._downstream.write(this._pendingChunk).then(doneWriting, doneWriting);
}
}
}
function parseOptions (options) {
if (typeof options === 'string') {
options = url.parse(options);
URLRequest.prototype._emitRequestEvent = function (isAsync, ...rest) {
if (isAsync) {
process.nextTick(() => {
this.clientRequest.emit(...rest)
})
} else {
options = { ...options };
this.clientRequest.emit(...rest)
}
const method = (options.method || 'GET').toUpperCase();
let urlStr = options.url;
if (!urlStr) {
const urlObj = {};
const protocol = options.protocol || 'http:';
if (!kSupportedProtocols.has(protocol)) {
throw new Error('Protocol "' + protocol + '" not supported');
}
urlObj.protocol = protocol;
if (options.host) {
urlObj.host = options.host;
} else {
if (options.hostname) {
urlObj.hostname = options.hostname;
} else {
urlObj.hostname = 'localhost';
}
if (options.port) {
urlObj.port = options.port;
}
}
if (options.path && / /.test(options.path)) {
// The actual regex is more like /[^A-Za-z0-9\-._~!$&'()*+,;=/:@]/
// with an additional rule for ignoring percentage-escaped characters
// but that's a) hard to capture in a regular expression that performs
// well, and b) possibly too restrictive for real-world usage. That's
// why it only scans for spaces because those are guaranteed to create
// an invalid request.
throw new TypeError('Request path contains unescaped characters');
}
const pathObj = url.parse(options.path || '/');
urlObj.pathname = pathObj.pathname;
urlObj.search = pathObj.search;
urlObj.hash = pathObj.hash;
urlStr = url.format(urlObj);
}
const redirectPolicy = options.redirect || 'follow';
if (!['follow', 'error', 'manual'].includes(redirectPolicy)) {
throw new Error('redirect mode should be one of follow, error or manual');
}
if (options.headers != null && typeof options.headers !== 'object') {
throw new TypeError('headers must be an object');
}
const urlLoaderOptions = {
method: method,
url: urlStr,
redirectPolicy,
extraHeaders: options.headers || {},
useSessionCookies: options.useSessionCookies || false
};
for (const [name, value] of Object.entries(urlLoaderOptions.extraHeaders)) {
if (!_isValidHeaderName(name)) {
throw new Error(`Invalid header name: '${name}'`);
}
if (!_isValidHeaderValue(value.toString())) {
throw new Error(`Invalid value for header '${name}': '${value}'`);
}
}
if (options.session) {
if (options.session instanceof Session) {
urlLoaderOptions.session = options.session;
} else {
throw new TypeError('`session` should be an instance of the Session class');
}
} else if (options.partition) {
if (typeof options.partition === 'string') {
urlLoaderOptions.partition = options.partition;
} else {
throw new TypeError('`partition` should be a string');
}
}
return urlLoaderOptions;
}
class ClientRequest extends Writable {
URLRequest.prototype._emitResponseEvent = function (isAsync, ...rest) {
if (isAsync) {
process.nextTick(() => {
this._response.emit(...rest)
})
} else {
this._response.emit(...rest)
}
}
class ClientRequest extends EventEmitter {
constructor (options, callback) {
super({ autoDestroy: true });
super()
if (!app.isReady()) {
throw new Error('net module can only be used after app is ready');
throw new Error('net module can only be used after app is ready')
}
if (typeof options === 'string') {
options = url.parse(options)
} else {
options = Object.assign({}, options)
}
const method = (options.method || 'GET').toUpperCase()
let urlStr = options.url
if (!urlStr) {
const urlObj = {}
const protocol = options.protocol || 'http:'
if (!kSupportedProtocols.has(protocol)) {
throw new Error('Protocol "' + protocol + '" not supported')
}
urlObj.protocol = protocol
if (options.host) {
urlObj.host = options.host
} else {
if (options.hostname) {
urlObj.hostname = options.hostname
} else {
urlObj.hostname = 'localhost'
}
if (options.port) {
urlObj.port = options.port
}
}
if (options.path && / /.test(options.path)) {
// The actual regex is more like /[^A-Za-z0-9\-._~!$&'()*+,;=/:@]/
// with an additional rule for ignoring percentage-escaped characters
// but that's a) hard to capture in a regular expression that performs
// well, and b) possibly too restrictive for real-world usage. That's
// why it only scans for spaces because those are guaranteed to create
// an invalid request.
throw new TypeError('Request path contains unescaped characters')
}
const pathObj = url.parse(options.path || '/')
urlObj.pathname = pathObj.pathname
urlObj.search = pathObj.search
urlObj.hash = pathObj.hash
urlStr = url.format(urlObj)
}
const redirectPolicy = options.redirect || 'follow'
if (!['follow', 'error', 'manual'].includes(redirectPolicy)) {
throw new Error('redirect mode should be one of follow, error or manual')
}
const urlRequestOptions = {
method: method,
url: urlStr,
redirect: redirectPolicy
}
if (options.session) {
if (options.session instanceof Session) {
urlRequestOptions.session = options.session
} else {
throw new TypeError('`session` should be an instance of the Session class')
}
} else if (options.partition) {
if (typeof options.partition === 'string') {
urlRequestOptions.partition = options.partition
} else {
throw new TypeError('`partition` should be a string')
}
}
const urlRequest = new URLRequest(urlRequestOptions)
// Set back and forward links.
this.urlRequest = urlRequest
urlRequest.clientRequest = this
// This is a copy of the extra headers structure held by the native
// net::URLRequest. The main reason is to keep the getHeader API synchronous
// after the request starts.
this.extraHeaders = {}
if (options.headers) {
for (const key in options.headers) {
this.setHeader(key, options.headers[key])
}
}
// Set when the request uses chunked encoding. Can be switched
// to true only once and never set back to false.
this.chunkedEncodingEnabled = false
urlRequest.on('response', () => {
const response = new IncomingMessage(urlRequest)
urlRequest._response = response
this.emit('response', response)
})
urlRequest.on('login', (event, authInfo, callback) => {
this.emit('login', authInfo, (username, password) => {
// If null or undefined username/password, force to empty string.
if (username === null || username === undefined) {
username = ''
}
if (typeof username !== 'string') {
throw new Error('username must be a string')
}
if (password === null || password === undefined) {
password = ''
}
if (typeof password !== 'string') {
throw new Error('password must be a string')
}
callback(username, password)
})
})
if (callback) {
this.once('response', callback);
this.once('response', callback)
}
}
const { redirectPolicy, ...urlLoaderOptions } = parseOptions(options);
this._urlLoaderOptions = urlLoaderOptions;
this._redirectPolicy = redirectPolicy;
this._started = false;
get chunkedEncoding () {
return this.chunkedEncodingEnabled
}
set chunkedEncoding (value) {
if (this._started) {
throw new Error('chunkedEncoding can only be set before the request is started');
}
if (typeof this._chunkedEncoding !== 'undefined') {
throw new Error('chunkedEncoding can only be set once');
}
this._chunkedEncoding = !!value;
if (this._chunkedEncoding) {
this._body = new ChunkedBodyStream(this);
this._urlLoaderOptions.body = (pipe) => {
this._body.startReading(pipe);
};
if (!this.urlRequest.notStarted) {
throw new Error('Can\'t set the transfer encoding, headers have been sent')
}
this.chunkedEncodingEnabled = value
}
setHeader (name, value) {
if (typeof name !== 'string') {
throw new TypeError('`name` should be a string in setHeader(name, value)');
throw new TypeError('`name` should be a string in setHeader(name, value)')
}
if (value == null) {
throw new Error('`value` required in setHeader("' + name + '", value)');
throw new Error('`value` required in setHeader("' + name + '", value)')
}
if (this._started || this._firstWrite) {
throw new Error('Can\'t set headers after they are sent');
}
if (!_isValidHeaderName(name)) {
throw new Error(`Invalid header name: '${name}'`);
}
if (!_isValidHeaderValue(value.toString())) {
throw new Error(`Invalid value for header '${name}': '${value}'`);
if (!this.urlRequest.notStarted) {
throw new Error('Can\'t set headers after they are sent')
}
const key = name.toLowerCase();
this._urlLoaderOptions.extraHeaders[key] = value;
const key = name.toLowerCase()
this.extraHeaders[key] = value
this.urlRequest.setExtraHeader(name, value.toString())
}
getHeader (name) {
if (name == null) {
throw new Error('`name` is required for getHeader(name)');
throw new Error('`name` is required for getHeader(name)')
}
const key = name.toLowerCase();
return this._urlLoaderOptions.extraHeaders[key];
if (!this.extraHeaders) {
return
}
const key = name.toLowerCase()
return this.extraHeaders[key]
}
removeHeader (name) {
if (name == null) {
throw new Error('`name` is required for removeHeader(name)');
throw new Error('`name` is required for removeHeader(name)')
}
if (this._started || this._firstWrite) {
throw new Error('Can\'t remove headers after they are sent');
if (!this.urlRequest.notStarted) {
throw new Error('Can\'t remove headers after they are sent')
}
const key = name.toLowerCase();
delete this._urlLoaderOptions.extraHeaders[key];
const key = name.toLowerCase()
delete this.extraHeaders[key]
this.urlRequest.removeExtraHeader(name)
}
_write (chunk, encoding, callback) {
this._firstWrite = true;
if (!this._body) {
this._body = new SlurpStream();
this._body.on('finish', () => {
this._urlLoaderOptions.body = this._body.data();
this._startRequest();
});
_write (chunk, encoding, callback, isLast) {
const chunkIsString = typeof chunk === 'string'
const chunkIsBuffer = chunk instanceof Buffer
if (!chunkIsString && !chunkIsBuffer) {
throw new TypeError('First argument must be a string or Buffer')
}
// TODO: is this the right way to forward to another stream?
this._body.write(chunk, encoding, callback);
if (chunkIsString) {
// We convert all strings into binary buffers.
chunk = Buffer.from(chunk, encoding)
}
// Since writing to the network is asynchronous, we conservatively
// assume that request headers are written after delivering the first
// buffer to the network IO thread.
if (this.urlRequest.notStarted) {
this.urlRequest.setChunkedUpload(this.chunkedEncoding)
}
// Headers are assumed to be sent on first call to _writeBuffer,
// i.e. after the first call to write or end.
const result = this.urlRequest.write(chunk, isLast)
// The write callback is fired asynchronously to mimic Node.js.
if (callback) {
process.nextTick(callback)
}
return result
}
_final (callback) {
if (this._body) {
// TODO: is this the right way to forward to another stream?
this._body.end(callback);
} else {
// end() called without a body, go ahead and start the request
this._startRequest();
callback();
write (data, encoding, callback) {
if (this.urlRequest.finished) {
const error = new Error('Write after end')
process.nextTick(writeAfterEndNT, this, error, callback)
return true
}
return this._write(data, encoding, callback, false)
}
_startRequest () {
this._started = true;
const stringifyValues = (obj) => {
const ret = {};
for (const k of Object.keys(obj)) {
ret[k] = obj[k].toString();
}
return ret;
};
const opts = { ...this._urlLoaderOptions, extraHeaders: stringifyValues(this._urlLoaderOptions.extraHeaders) };
this._urlLoader = new URLLoader(opts);
this._urlLoader.on('response-started', (event, finalUrl, responseHead) => {
const response = this._response = new IncomingMessage(responseHead);
this.emit('response', response);
});
this._urlLoader.on('data', (event, data) => {
this._response._storeInternalData(Buffer.from(data));
});
this._urlLoader.on('complete', () => {
if (this._response) { this._response._storeInternalData(null); }
});
this._urlLoader.on('error', (event, netErrorString) => {
const error = new Error(netErrorString);
if (this._response) this._response.destroy(error);
this._die(error);
});
end (data, encoding, callback) {
if (this.urlRequest.finished) {
return false
}
this._urlLoader.on('login', (event, authInfo, callback) => {
const handled = this.emit('login', authInfo, callback);
if (!handled) {
// If there were no listeners, cancel the authentication request.
callback();
}
});
if (typeof data === 'function') {
callback = data
encoding = null
data = null
} else if (typeof encoding === 'function') {
callback = encoding
encoding = null
}
this._urlLoader.on('redirect', (event, redirectInfo, headers) => {
const { statusCode, newMethod, newUrl } = redirectInfo;
if (this._redirectPolicy === 'error') {
this._die(new Error(`Attempted to redirect, but redirect policy was 'error'`));
} else if (this._redirectPolicy === 'manual') {
let _followRedirect = false;
this._followRedirectCb = () => { _followRedirect = true; };
try {
this.emit('redirect', statusCode, newMethod, newUrl, headers);
} finally {
this._followRedirectCb = null;
if (!_followRedirect && !this._aborted) {
this._die(new Error('Redirect was cancelled'));
}
}
} else if (this._redirectPolicy === 'follow') {
// Calling followRedirect() when the redirect policy is 'follow' is
// allowed but does nothing. (Perhaps it should throw an error
// though...? Since the redirect will happen regardless.)
try {
this._followRedirectCb = () => {};
this.emit('redirect', statusCode, newMethod, newUrl, headers);
} finally {
this._followRedirectCb = null;
}
} else {
this._die(new Error(`Unexpected redirect policy '${this._redirectPolicy}'`));
}
});
data = data || ''
this._urlLoader.on('upload-progress', (event, position, total) => {
this._uploadProgress = { active: true, started: true, current: position, total };
this.emit('upload-progress', position, total); // Undocumented, for now
});
this._urlLoader.on('download-progress', (event, current) => {
if (this._response) {
this._response.emit('download-progress', current); // Undocumented, for now
}
});
return this._write(data, encoding, callback, true)
}
followRedirect () {
if (this._followRedirectCb) {
this._followRedirectCb();
} else {
throw new Error('followRedirect() called, but was not waiting for a redirect');
}
this.urlRequest.followRedirect()
}
abort () {
if (!this._aborted) {
process.nextTick(() => { this.emit('abort'); });
}
this._aborted = true;
this._die();
}
_die (err) {
this.destroy(err);
if (this._urlLoader) {
this._urlLoader.cancel();
if (this._response) this._response.destroy(err);
}
this.urlRequest.cancel()
}
getUploadProgress () {
return this._uploadProgress ? { ...this._uploadProgress } : { active: false };
return this.urlRequest.getUploadProgress()
}
}
function writeAfterEndNT (self, error, callback) {
self.emit('error', error)
if (callback) callback(error)
}
Net.prototype.request = function (options, callback) {
return new ClientRequest(options, callback);
};
return new ClientRequest(options, callback)
}
net.ClientRequest = ClientRequest;
net.ClientRequest = ClientRequest
module.exports = net;
module.exports = net

View File

@@ -1,10 +1,10 @@
'use strict';
'use strict'
const { EventEmitter } = require('events');
const { Notification, isSupported } = process.electronBinding('notification');
const { EventEmitter } = require('events')
const { Notification, isSupported } = process.electronBinding('notification')
Object.setPrototypeOf(Notification.prototype, EventEmitter.prototype);
Object.setPrototypeOf(Notification.prototype, EventEmitter.prototype)
Notification.isSupported = isSupported;
Notification.isSupported = isSupported
module.exports = Notification;
module.exports = Notification

View File

@@ -1,38 +1,28 @@
'use strict';
'use strict'
import { createLazyInstance } from '../utils';
import { createLazyInstance } from '../utils'
const { EventEmitter } = require('events');
const { createPowerMonitor, PowerMonitor } = process.electronBinding('power_monitor');
const { EventEmitter } = require('events')
const { createPowerMonitor, PowerMonitor } = process.electronBinding('power_monitor')
// PowerMonitor is an EventEmitter.
Object.setPrototypeOf(PowerMonitor.prototype, EventEmitter.prototype);
Object.setPrototypeOf(PowerMonitor.prototype, EventEmitter.prototype)
const powerMonitor = createLazyInstance(createPowerMonitor, PowerMonitor, true);
const powerMonitor = createLazyInstance(createPowerMonitor, PowerMonitor, true)
// On Linux we need to call blockShutdown() to subscribe to shutdown event.
if (process.platform === 'linux') {
// In order to delay system shutdown when e.preventDefault() is invoked
// on a powerMonitor 'shutdown' event, we need an org.freedesktop.login1
// shutdown delay lock. For more details see the "Taking Delay Locks"
// section of https://www.freedesktop.org/wiki/Software/systemd/inhibit/
//
// So here we watch for 'shutdown' listeners to be added or removed and
// set or unset our shutdown delay lock accordingly.
const { app } = require('electron');
app.whenReady().then(() => {
powerMonitor.on('newListener', (event: string) => {
// whenever the listener count is incremented to one...
if (event === 'shutdown' && powerMonitor.listenerCount('shutdown') === 0) {
powerMonitor.blockShutdown();
}
});
powerMonitor.on('removeListener', (event: string) => {
// whenever the listener count is decremented to zero...
if (event === 'shutdown' && powerMonitor.listenerCount('shutdown') === 0) {
powerMonitor.unblockShutdown();
}
});
});
powerMonitor.on('newListener', (event:string) => {
if (event === 'shutdown' && powerMonitor.listenerCount('shutdown') === 0) {
powerMonitor.blockShutdown()
}
})
powerMonitor.on('removeListener', (event: string) => {
if (event === 'shutdown' && powerMonitor.listenerCount('shutdown') === 0) {
powerMonitor.unblockShutdown()
}
})
}
module.exports = powerMonitor;
module.exports = powerMonitor

View File

@@ -1,3 +1,3 @@
'use strict';
'use strict'
module.exports = process.electronBinding('power_save_blocker').powerSaveBlocker;
module.exports = process.electronBinding('power_save_blocker').powerSaveBlocker

View File

@@ -1,29 +1,29 @@
import { app, session } from 'electron';
import { app, session } from 'electron'
// Global protocol APIs.
const protocol = process.electronBinding('protocol');
const protocol = process.electronBinding('protocol')
// Fallback protocol APIs of default session.
Object.setPrototypeOf(protocol, new Proxy({}, {
get (_target, property) {
if (!app.isReady()) return;
if (!app.isReady()) return
const protocol = session.defaultSession!.protocol;
if (!Object.getPrototypeOf(protocol).hasOwnProperty(property)) return;
const protocol = session.defaultSession!.protocol
if (!Object.getPrototypeOf(protocol).hasOwnProperty(property)) return
// Returning a native function directly would throw error.
return (...args: any[]) => (protocol[property as keyof Electron.Protocol] as Function)(...args);
return (...args: any[]) => (protocol[property as keyof Electron.Protocol] as Function)(...args)
},
ownKeys () {
if (!app.isReady()) return [];
if (!app.isReady()) return []
return Object.getOwnPropertyNames(Object.getPrototypeOf(session.defaultSession!.protocol));
return Object.getOwnPropertyNames(Object.getPrototypeOf(session.defaultSession!.protocol))
},
getOwnPropertyDescriptor () {
return { configurable: true, enumerable: true };
return { configurable: true, enumerable: true }
}
}));
}))
export default protocol;
export default protocol

View File

@@ -1,10 +1,10 @@
'use strict';
'use strict'
import { createLazyInstance } from '../utils';
const { EventEmitter } = require('events');
const { Screen, createScreen } = process.electronBinding('screen');
import { createLazyInstance } from '../utils'
const { EventEmitter } = require('events')
const { Screen, createScreen } = process.electronBinding('screen')
// Screen is an EventEmitter.
Object.setPrototypeOf(Screen.prototype, EventEmitter.prototype);
Object.setPrototypeOf(Screen.prototype, EventEmitter.prototype)
module.exports = createLazyInstance(createScreen, Screen, true);
module.exports = createLazyInstance(createScreen, Screen, true)

View File

@@ -1,53 +1,52 @@
'use strict';
'use strict'
const { EventEmitter } = require('events');
const { app, deprecate } = require('electron');
const { fromPartition, Session, Cookies, NetLog, Protocol } = process.electronBinding('session');
const { EventEmitter } = require('events')
const { app, deprecate } = require('electron')
const { fromPartition, Session, Cookies, NetLog, Protocol } = process.electronBinding('session')
// Public API.
Object.defineProperties(exports, {
defaultSession: {
enumerable: true,
get () { return fromPartition(''); }
get () { return fromPartition('') }
},
fromPartition: {
enumerable: true,
value: fromPartition
}
});
})
Object.setPrototypeOf(Session.prototype, EventEmitter.prototype);
Object.setPrototypeOf(Cookies.prototype, EventEmitter.prototype);
Object.setPrototypeOf(Session.prototype, EventEmitter.prototype)
Object.setPrototypeOf(Cookies.prototype, EventEmitter.prototype)
Session.prototype._init = function () {
app.emit('session-created', this);
};
app.emit('session-created', this)
}
const _originalStartLogging = NetLog.prototype.startLogging;
const _originalStartLogging = NetLog.prototype.startLogging
NetLog.prototype.startLogging = function (path, ...args) {
this._currentlyLoggingPath = path;
this._currentlyLoggingPath = path
try {
return _originalStartLogging.call(this, path, ...args);
return _originalStartLogging.call(this, path, ...args)
} catch (e) {
this._currentlyLoggingPath = null;
throw e;
this._currentlyLoggingPath = null
throw e
}
};
}
const _originalStopLogging = NetLog.prototype.stopLogging;
const _originalStopLogging = NetLog.prototype.stopLogging
NetLog.prototype.stopLogging = function () {
const logPath = this._currentlyLoggingPath;
this._currentlyLoggingPath = null;
return _originalStopLogging.call(this).then(() => logPath);
};
this._currentlyLoggingPath = null
return _originalStopLogging.call(this)
}
const currentlyLoggingPathDeprecated = deprecate.warnOnce('currentlyLoggingPath');
const currentlyLoggingPathDeprecated = deprecate.warnOnce('currentlyLoggingPath')
Object.defineProperties(NetLog.prototype, {
currentlyLoggingPath: {
enumerable: true,
get () {
currentlyLoggingPathDeprecated();
return this._currentlyLoggingPath == null ? '' : this._currentlyLoggingPath;
currentlyLoggingPathDeprecated()
return this._currentlyLoggingPath == null ? '' : this._currentlyLoggingPath
}
}
});
})

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