Compare commits

..

118 Commits

Author SHA1 Message Date
Electron Bot
56e926ce23 Bump v11.2.0 2021-01-11 14:54:54 -08:00
Shelley Vohr
5e0e91510a Revert "Bump v11.1.2"
This reverts commit 9bfd5d4a4b.
2021-01-11 14:27:05 -08:00
Electron Bot
9bfd5d4a4b Bump v11.1.2 2021-01-11 09:32:26 -08:00
trop[bot]
8afd7877f6 test: skip PictureInPicture video when media not supported (#27235)
Co-authored-by: Milan Burda <milan.burda@gmail.com>
2021-01-07 21:38:48 -08:00
trop[bot]
bf0b82dc8e test: skip media-started-playing media-paused events test when media not supported (#27237)
Co-authored-by: Milan Burda <milan.burda@gmail.com>
2021-01-07 21:38:05 -08:00
Shelley Vohr
122d8910d5 refactor: remove path from nativeImage converter (#27217) 2021-01-07 13:14:29 -08:00
trop[bot]
cb281b7954 test: skip protocol.registerSchemesAsPrivileged stream test when media not supported (#27229)
Co-authored-by: Milan Burda <milan.burda@gmail.com>
2021-01-07 13:04:24 -08:00
Electron Bot
91cfa96c80 chore: bump chromium in DEPS to 87.0.4280.141 (#27213) 2021-01-07 11:48:53 -08:00
trop[bot]
a21ed83751 feat: make win.setAspectRatio() work on Windows (#27203) 2021-01-07 11:46:04 -08:00
Shelley Vohr
c0b48658d8 fix: handle BrowserView reparenting (#27219) 2021-01-07 11:43:46 -08:00
trop[bot]
c68f0f04d0 docs: document frameId meaning (#27189)
Co-authored-by: Jeremy Rose <nornagon@nornagon.net>
2021-01-05 17:19:19 +09:00
Eryk Rakowski
a2b61f9b97 feat: add support for webContents option in BrowserView (#26802) (#27095)
* feat: add support for webContents option in BrowserView

* tests: add tests
2021-01-05 17:17:50 +09:00
trop[bot]
fc478f4e96 fix: default offset when no drag regions (#27183)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2021-01-05 12:13:54 +09:00
trop[bot]
b710412e7b fix: unclickable regions in some draggable BrowserViews (#27178)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2021-01-05 11:44:12 +09:00
Eryk Rakowski
9a7bda51a3 fix(extensions): implement missing web_request hooks (#22655) (#27096)
Co-authored-by: Jeremy Apthorp <nornagon@nornagon.net>
Co-authored-by: samuelmaddock <samuel.maddock@gmail.com>

Co-authored-by: Jeremy Apthorp <nornagon@nornagon.net>
Co-authored-by: samuelmaddock <samuel.maddock@gmail.com>
2021-01-05 11:27:48 +09:00
trop[bot]
615e467a15 fix: make webContents.id work even after destroy (#27069)
Co-authored-by: Jeremy Rose <nornagon@nornagon.net>
2021-01-05 11:13:21 +09:00
trop[bot]
f8a900fdde docs: update broken Chrome webview URL (#27180)
Co-authored-by: Erick Zhao <erick@hotmail.ca>
2021-01-04 14:05:26 -08:00
trop[bot]
c188ed065d fix: sync devtools frontend mime types with upstream (#27102)
* fix: sync devtools frontend mime types with upstream

* fix header

Co-authored-by: Jeremy Rose <nornagon@nornagon.net>
2020-12-22 14:13:17 -08:00
Electron Bot
dcd216984f Bump v11.1.1 2020-12-21 09:33:17 -08:00
Shelley Vohr
e012f61aee refactor: remove last use of InternalCallbackScope (#27050)
* refactor: remove last use of InternalCallbackScope

* update patches

Co-authored-by: Electron Bot <electron@github.com>
2020-12-17 13:06:33 -06:00
Erick Zhao
50e3a2ae20 docs: update OSR max FPS number (#26805) (#27059) 2020-12-17 20:30:31 +09:00
trop[bot]
b4413e9398 fix: memory leak in desktopCapturer.getSources (#27056)
Co-authored-by: Jeremy Rose <nornagon@nornagon.net>
2020-12-16 20:47:57 -08:00
trop[bot]
25df0f5d31 fix: throw when using globalShortcut before ready (#27021)
* fix: throw when using globalShortcut before ready

* fix

Co-authored-by: Jeremy Rose <nornagon@nornagon.net>
2020-12-17 10:07:10 +09:00
trop[bot]
6b91371b6e fix: make protocol wrapper remote-friendly again (#27044)
Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2020-12-16 12:10:07 -08:00
trop[bot]
8e6d332e96 fix: crash on exit in Event destructor (#27035)
Co-authored-by: Jeremy Rose <nornagon@nornagon.net>
2020-12-16 17:29:57 +09:00
trop[bot]
eebd7cfa05 refactor: use public node::CallbackScope where possible (#27027)
* refactor: use public node::CallbackScope where possible

* Remove unused node_env() getter

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-12-16 08:39:49 +09:00
Shelley Vohr
a4d73be9c5 fix: stack traces in non-Node.js contexts (#26997)
* fix: stack traces in non-Node.js contexts

* update patches

Co-authored-by: Electron Bot <electron@github.com>
2020-12-16 08:38:39 +09:00
trop[bot]
0e9214a82b fix(asar): readdir(withFileTypes) fails on deep directory when using readdirSync on a deep directory within the archive, the code fails to get the stats of child paths. (#27010)
Co-authored-by: Avi Vahl <avi.vahl@wix.com>
2020-12-15 09:18:00 -08:00
trop[bot]
24c7365bef fix: add SafeForTerminationScopes for SIGINT interruptions (#26972)
* fix: add SafeForTerminationScopes for SIGINT interruptions

* update patches

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
Co-authored-by: Electron Bot <electron@github.com>
2020-12-14 16:43:56 -08:00
trop[bot]
686aefb2cd ci: ignore failures on Ninja summary (#26996)
Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
2020-12-14 13:44:49 -05:00
Shelley Vohr
0e0a1421fd fix: screen EventEmitter methods with remote (#26989) 2020-12-14 10:39:43 -08:00
trop[bot]
c4e8c0fd0e fix: properly emit after hooks after exception (#26991)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-12-14 10:24:25 -08:00
Electron Bot
101a2282ab Bump v11.1.0 2020-12-11 13:03:56 -08:00
Jeremy Rose
429400040e fix: restrict sendToFrame to same-process frames by default (#26875) (#26926) 2020-12-11 13:01:31 -08:00
trop[bot]
ca7528a2d0 fix: Upload all *.dll.pdb to symbol server (#26965)
Fixes #26961.

Notes: Add Electron DLLs like libGLESv2.dll to symbol server

Co-authored-by: Biru Mohanathas <birunthan@mohanathas.com>
2020-12-11 12:53:27 -08:00
trop[bot]
d58812b517 fix: Avoid crashing in NativeViewHost::SetParentAccessible on Windows 10 (#26951)
* fix: Avoid crashing in NativeViewHost::SetParentAccessible on Windows

This fixes #26905. The patch was obtained from @deepak1556, who in turn
got it from the Microsoft Teams folks.

I believe the crash started happening due to the changes in
5c6c8e994b%5E!/#F15

This affects Electron 9 and later.

Notes: Fix occasional crash on Windows

* update patches

Co-authored-by: Biru Mohanathas <birunthan@mohanathas.com>
Co-authored-by: Electron Bot <electron@github.com>
2020-12-11 12:51:23 -08:00
trop[bot]
5942c84288 docs: add missing deprecated systemPreferences APIs to breaking-changes (#26936)
Co-authored-by: Milan Burda <milan.burda@gmail.com>
2020-12-11 10:59:00 -08:00
trop[bot]
f920463b47 fix: message box missing an "OK" button in GTK (#26916)
Co-authored-by: Mimi <1119186082@qq.com>
2020-12-10 13:06:03 -08:00
Electron Bot
296cba563e Bump v11.0.5 2020-12-10 09:47:04 -08:00
trop[bot]
90a96c0b73 fix: systemPreferences.effectiveAppearance returning systemPreferences.getAppLevelAppearance() (#26878)
Co-authored-by: Milan Burda <milan.burda@gmail.com>
2020-12-09 14:58:44 +09:00
Milan Burda
2c325cd654 fix: send IPC_MESSAGES.RENDERER_RELEASE_CALLBACK as internal message (#26808) (#26836) 2020-12-08 13:29:50 +09:00
Electron Bot
c26b78bbc0 chore: bump chromium to 87.0.4280.88 (11-x-y) (#26817)
* chore: bump chromium in DEPS to 87.0.4280.88

* update patches

Co-authored-by: John Kleinschmidt <jkleinsc@github.com>
2020-12-07 16:46:44 -08:00
Alexey Kuzmin
6951c09b61 fix: add a "set" trap to the "screen" module proxy (#26873) 2020-12-07 16:46:05 -08:00
trop[bot]
fe21892974 fix: handle security warnings promise when JS is disabled (#26870)
Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2020-12-07 13:03:40 -08:00
Electron Bot
0fd6a8ca83 Bump v11.0.4 2020-12-07 10:06:44 -08:00
Erick Zhao
de12232df5 docs: added fiddle support for code samples (#26766)
Co-authored-by: Antonio <bandantonio@users.noreply.github.com>
2020-12-03 15:54:49 +09:00
trop[bot]
d12674f9f1 docs: fix contentTracing code sample (#26777)
According to the API docs, the property is called included_categories, not include_categories.

Co-authored-by: Jim Fisher <jameshfisher@gmail.com>
2020-12-02 14:29:00 -05:00
Samuel Attard
75cdd02697 build: use all-for-one goma (#26699) (#26770)
* Revert "Revert "build: use one-for-all goma (#26679)" (#26689)"

This reverts commit 38ab829ea6.

* build: ensure file descriptor limit is higher on macOS
2020-12-02 11:18:56 -05:00
trop[bot]
08b7f5a569 fix: draggable views on BrowserViews on Windows (#26774) 2020-12-01 21:35:53 -08:00
trop[bot]
a5077e2586 docs: BrowserWindow extension APIs are deprecated in Electron 9 (#26782)
Co-authored-by: Milan Burda <milan.burda@gmail.com>
2020-12-01 21:31:57 -08:00
trop[bot]
4fa9122151 fix: add check in IsMaximized for non-WS_THICKFRAME windows (#26780)
Co-authored-by: mlaurencin <mlaurencin@electronjs.org>
2020-12-01 21:30:59 -08:00
Vadim
56fa037a46 fix: internalModuleReadJSON for unpacked JSON (#26751) 2020-12-01 18:24:22 -06:00
trop[bot]
13a9e15a27 fix: Add default Bluetooth permission strings (#26768) 2020-12-01 15:02:25 -08:00
trop[bot]
badc01c2d8 fix: draggable regions calculation in BrowserWindow/BrowserView (#26754) 2020-12-01 11:29:55 -08:00
Electron Bot
b0862a6e63 Bump v11.0.3 2020-11-23 17:01:12 -08:00
trop[bot]
18cde2ef04 fix: make screen wrapper remote-friendly again (#26660)
This restores accessibility of screen methods via remote.screen.

Fixes #26610.

Signed-off-by: Anders Kaseorg <andersk@mit.edu>

Co-authored-by: Anders Kaseorg <andersk@mit.edu>
2020-11-23 18:27:16 -05:00
Jeremy Rose
e6c94854a0 chore: cherry-pick 47e21abe349a from chromium (#26654)
* chore: cherry-pick 47e21abe349a from chromium

* resolve conflicts
2020-11-23 17:23:57 -05:00
trop[bot]
94d8b7d4c1 fix: reject contentTracing.stopRecording on failure (#26655)
* fix: reject contentTracing.stopRecording on failure

* hacks to account for std::moved promise

Co-authored-by: Jeremy Rose <nornagon@nornagon.net>
2020-11-23 15:36:17 -05:00
John Kleinschmidt
c0769d77e5 build: remove no longer needed arm64 macos patches (#26650) 2020-11-23 12:13:25 -08:00
Jeremy Rose
2a6c3bb7d1 fix: segfault on webContents.fromId(xxx) (#26652) 2020-11-23 11:41:09 -08:00
Milan Burda
d892fde98b fix: <webview> render-process-gone event dispatch (#26578)
Co-authored-by: Milan Burda <miburda@microsoft.com>
2020-11-19 10:29:58 -08:00
Electron Bot
edb6723157 Bump v11.0.2 2020-11-19 10:19:12 -08:00
Samuel Attard
9dda9a894a Revert "Bump v11.0.2"
This reverts commit 4dc98f1347.
2020-11-19 10:17:40 -08:00
Electron Bot
90ab868b50 chore: bump chromium to 87.0.4280.67 (11-x-y) (#26565)
* chore: bump chromium in DEPS to 87.0.4280.66

* chore: bump chromium in DEPS to 87.0.4280.67
2020-11-19 11:25:16 -05:00
Electron Bot
4dc98f1347 Bump v11.0.2 2020-11-18 13:06:12 -08:00
trop[bot]
2189ddb14e fix: LC_ALL env should not be changed (#26551)
Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2020-11-18 11:44:04 -08:00
trop[bot]
680569e404 test: support for adding extra module paths (#26543)
Co-authored-by: David Sanders <dsanders11@ucsbalum.com>
2020-11-18 11:43:53 -08:00
trop[bot]
e119699ae2 revert: disable rosetta as Electron does not run under rosetta
This reverts commit 4829b0f816.

Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2020-11-18 11:18:49 -08:00
trop[bot]
63e6f08768 fix: use public APIs in place of private CTFontDescriptorIsSystemUIFont in ui/gfx (#26574)
* fix: use public APIs in place of private CTFontDescriptorIsSystemUIFont in ui/gfx

* Update .patches

Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
Co-authored-by: Samuel Attard <sam@electronjs.org>
2020-11-18 11:18:05 -08:00
trop[bot]
b14c57e30c fix: getLoginItemSettings() on windows (#26538)
* find by exe, detect taskmgr enable/disable

* tests

* revert

* oops

Co-authored-by: Jan Hannemann <jan.hannemann@outlook.com>
2020-11-18 11:15:24 +09:00
Electron Bot
8a68a304e0 chore: bump chromium to 87.0.4280.63 (11-x-y) (#26534)
* chore: bump chromium in DEPS to 87.0.4280.63

* update patches
2020-11-17 14:29:42 -05:00
trop[bot]
60cef385d5 fix: webContents interaction with draggable browserviews (#26528)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-11-17 10:16:53 -05:00
Electron Bot
4f281e3d31 Bump v11.0.1 2020-11-17 02:20:52 -08:00
trop[bot]
eb2710e483 fix: Cannot read property 'setDockSide' of undefined (#26514)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-11-16 16:05:51 -05:00
trop[bot]
7a15dca09c fix: do not use crashpad APIs in the MAS build (#26513)
Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2020-11-16 11:39:56 -08:00
Electron Bot
387a15f582 Bump v11.0.0 2020-11-16 06:29:41 -08:00
Jeremy Rose
38fab63863 chore: cherry-pick 275865e8c237 from chromium (#26470)
* chore: cherry-pick 275865e8c237 from chromium

* resolve conflict

* update patches

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
Co-authored-by: Electron Bot <electron@github.com>
2020-11-16 09:27:25 -05:00
Milan Burda
1b156c53fd fix: ensure that internal messages are sent from the main process (#26440) 2020-11-16 15:30:47 +09:00
Electron Bot
e4f3f9e1db chore: bump chromium to 87.0.4280.60 (11-x-y) (#26483) 2020-11-13 15:36:26 -08:00
Jeremy Rose
612acc04b0 fix: cherry-pick 8f5a08079948 from chromium (#26469) 2020-11-13 15:14:18 -08:00
Electron Bot
717271095e Bump v11.0.0-beta.23 2020-11-13 13:53:04 -08:00
trop[bot]
76e54ae0c8 feat: add app.runningUnderRosettaTranslation to detect running under rosetta (#26492)
* feat: add app.isRunningUnderRosettaTranslation to detect running under rosetta

* chore: fixup

* chore: make const

* chore: add missing import

Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2020-11-13 13:51:05 -08:00
Electron Bot
0c21ce02c1 Bump v11.0.0-beta.22 2020-11-12 07:01:59 -08:00
trop[bot]
01fa45fc50 feat: add 'resized' event to BrowserWindow (#26454)
Also adds 'moved' event to BrowserWindow on Windows.

Co-authored-by: samuelmaddock <samuel.maddock@gmail.com>
2020-11-12 09:47:01 -05:00
trop[bot]
832ce14bda build: fix usage of octokit/rest and make uploading better (#26389)
* build: fix usage of octokit/rest and make uploading better

* Pull in change from #26414

* Update with changes from #26425

Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
2020-11-11 14:30:58 -05:00
trop[bot]
07318e5146 fix: renderer crash on setImmediate (#26424)
* fix: renderer crash on setImmediate

* spec: add a crash case

* fix: ensure env exists

* Update spec-main/fixtures/crash-cases/setimmediate-renderer-crash/index.js

Co-authored-by: Jeremy Rose <jeremya@chromium.org>

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
Co-authored-by: Jeremy Rose <jeremya@chromium.org>
2020-11-11 10:23:30 -05:00
trop[bot]
79dff5f782 chore(extensions): remove old renderer code (#26441)
Co-authored-by: samuelmaddock <samuel.maddock@gmail.com>
2020-11-11 10:15:27 -05:00
Samuel Attard
9c9e40294e build: auto-push patch file changes (#26235) (#26431)
* build: auto-push patch file changes

* chore: change patch for testing purposes

* build: remove stray log

* build: push as electron bot

* build: suppress all output of the push-patch script

* chore: fix linting
2020-11-10 13:47:51 -08:00
trop[bot]
5b617a7f39 chore: synchronously destroy WebContents on event prevented (#26418)
Co-authored-by: Jeremy Rose <jeremya@chromium.org>
2020-11-10 11:27:32 -05:00
trop[bot]
ff717d4a93 chore: cleanup inline HTML in docs (#26392)
Co-authored-by: David Sanders <dsanders11@ucsbalum.com>
2020-11-10 10:49:47 -05:00
trop[bot]
51bced4ee3 fix: make draggable regions work when devtools is opened on macOS (#26395)
* fix: make draggable region work when devtools is open

* fix: update draggable regions when resizing

Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2020-11-10 10:46:40 -05:00
Shelley Vohr
b0fd7cf430 fix: honor pageRanges when printing (#25600)
* fix: honor pageRanges when printing

* Update docs/api/web-contents.md

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
2020-11-10 10:06:57 -05:00
Electron Bot
a56c1d3f2f Bump v11.0.0-beta.21 2020-11-09 07:02:10 -08:00
John Kleinschmidt
98b6403e3b feat: correctly identify permissions when using setPermissionRequestHandler (#26172) (#26353)
(cherry picked from commit 7f9b21daa0)
2020-11-09 09:58:35 -05:00
trop[bot]
e9c12688e6 refactor: store <webview> attributes as typed Map (#26330)
Co-authored-by: Milan Burda <milan.burda@gmail.com>
2020-11-05 15:29:06 -05:00
Electron Bot
8d88d1e2ed chore: bump chromium to 87.0.4280.47 (11-x-y) (#26351)
* chore: bump chromium in DEPS to 87.0.4280.47

* update patches

* Make sure angle has full git info

Co-authored-by: Electron Bot <anonymous@electronjs.org>
Co-authored-by: John Kleinschmidt <jkleinsc@github.com>
2020-11-05 15:11:11 -05:00
Electron Bot
2e730fe48b Bump v11.0.0-beta.20 2020-11-05 07:01:36 -08:00
Electron Bot
88de23b241 chore: bump chromium to 87.0.4280.40 (11-x-y) (#26280)
* chore: bump chromium in DEPS to 87.0.4280.40

* update patches

Co-authored-by: Electron Bot <anonymous@electronjs.org>
2020-11-04 15:35:28 -05:00
trop[bot]
3faa2c2a46 fix: window.open not accepting size values with "px" at the end (#26334)
* fix: use parseInt to parse sizes

* fix: pass radix to parseInt

Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>

Co-authored-by: Abhishek Shingane <abhisheks@iitbhilai.ac.in>
Co-authored-by: Cheng Zhao <github@zcbenz.com>
Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2020-11-04 10:59:49 -08:00
trop[bot]
cab14277b8 fix: draggable region edge calculation on resize (#26320)
* fix: draggable region edge calculation on resize

* Feedback from review

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-11-04 11:17:14 +09:00
Electron Bot
ce243f8172 Bump v11.0.0-beta.19 2020-11-02 07:01:23 -08:00
Shelley Vohr
da4790d944 build: only check patch diffs in testing builds (#26283)
* build: only check patch diffs in testing builds

* Fixup patch indices
2020-11-02 18:56:13 +09:00
Charles Kerr
4088566a4d fix: nativeTheme.themeSource = 'dark' on windows (#26238)
Manually backports #25373.
2020-11-02 16:20:57 +09:00
Shelley Vohr
ac425c0cf3 fix: draggable regions exclusively on BrowserViews (#26259) 2020-11-02 16:07:04 +09:00
trop[bot]
ccb471e5d5 chore: change some for loops to range-based (#26263)
Co-authored-by: David Sanders <dsanders11@ucsbalum.com>
2020-10-30 09:58:39 -07:00
Robo
f44880f065 fix: Initialize logging for crashpad (#26250)
* fix: Initialize logging for crashpad

* chore: update mini_chromium

* conditionally access CommandLine because crashpad doesn't initialize one.

https://chromium-review.googlesource.com/c/chromium/src/+/2490880
2020-10-29 16:23:51 -07:00
trop[bot]
7ec001486e fix: hover text only working when VO enabled (#26246)
* fix: hover text only working when VO enabled

* chore: simplify conditional

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-10-29 08:51:45 -07:00
David Sanders
dd3fbae447 chore: use auto to avoid repeating type (#26254) 2020-10-29 08:50:27 -07:00
Electron Bot
e9710f6a77 Bump v11.0.0-beta.18 2020-10-29 08:01:25 -07:00
trop[bot]
699a771288 fix: transparently package bundles as zip archives (#26217)
* refactor: move FileSelectHelper to own file

* fix: zip packages on macOS

* Thread safety, it's good actually

* misc cleanup

* Remove some unused includes

* Better ref management

* Use upstream file_select_helper_mac

* Small fixes

* Put back file_select_helper_mac

* observe RenderWidgetHost

* fix ref-counting and add some guards

* Address review

* Remove refcounting for FileSelectHelper

* Remove unnecessary GetWeakPtr

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
Co-authored-by: deepak1556 <hop2deep@gmail.com>
2020-10-29 10:01:32 -04:00
trop[bot]
f679dd8ad7 fix: build with printing disabled (#26249)
Co-authored-by: deepak1556 <hop2deep@gmail.com>
2020-10-29 02:18:26 -07:00
trop[bot]
9f1b913793 fix: set app locale after user's script is loaded (#26226)
* fix: set app locale after user's script is loaded

* fix: set LC_ALL env on Linux

Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2020-10-28 15:20:10 -04:00
Charles Kerr
9328725e93 perf: improve heap snapshot performance (#26230)
Fixes #24509.

cherry-pick 2e2dc98 from v8
2020-10-28 12:07:48 -07:00
trop[bot]
cea757f59c fix: delay emitting powerMonitor events on windows (#26181)
* fix: delay emitting powerMonitor events

* Update electron_api_power_monitor_win.cc

* Update electron_api_power_monitor_win.cc

* syntax

* Update electron_api_power_monitor_win.cc

* Update electron_api_power_monitor_win.cc

Co-authored-by: Jeremy Rose <nornagon@nornagon.net>
Co-authored-by: Jeremy Rose <jeremya@chromium.org>
2020-10-28 12:39:49 -05:00
trop[bot]
d93cb942fc build: rename the v8 context snapshot on arm64 macOS builds (#26202)
* chore: rename the v8 context snapshot on arm64 macOS builds

* build: update zip manifests

* build: update to upstream patch

* chore: update patches

Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2020-10-27 20:11:24 -04:00
trop[bot]
4d280ed483 docs: fix app 'ready' event arguments (#26174)
Co-authored-by: Milan Burda <milan.burda@gmail.com>
2020-10-26 20:38:42 -07:00
David Sanders
bb69770267 chore: bump @electron/docs-parser version (#26155) 2020-10-26 11:50:00 -07:00
David Sanders
d4112d38de chore: prefer empty() check for readability (#26157) 2020-10-26 11:48:12 -07:00
273 changed files with 6306 additions and 1637 deletions

View File

@@ -107,6 +107,7 @@ env-release-build: &env-release-build
STRIP_BINARIES: true
GENERATE_SYMBOLS: true
CHECK_DIST_MANIFEST: '1'
IS_RELEASE: true
env-headless-testing: &env-headless-testing
DISPLAY: ':99.0'
@@ -256,23 +257,34 @@ step-gclient-sync: &step-gclient-sync
"$CIRCLE_REPOSITORY_URL"
ELECTRON_USE_THREE_WAY_MERGE_FOR_PATCHES=1 gclient sync --with_branch_heads --with_tags
# Re-export all the patches to check if there were changes.
python src/electron/script/export_all_patches.py src/electron/patches/config.json
cd src/electron
git update-index --refresh || true
if ! git diff-index --quiet HEAD --; then
# There are changes to the patches. Make a git commit with the updated patches
git add patches
GIT_COMMITTER_NAME="Electron Bot" GIT_COMMITTER_EMAIL="anonymous@electronjs.org" git commit -m "update patches" --author="Electron Bot <anonymous@electronjs.org>"
# Export it
mkdir -p ../../patches
git format-patch -1 --stdout --keep-subject --no-stat --full-index > ../../patches/update-patches.patch
echo
echo "======================================================================"
echo "There were changes to the patches when applying."
echo "Check the CI artifacts for a patch you can apply to fix it."
echo "======================================================================"
exit 1
if [ "$IS_RELEASE" != "true" ]; then
# Re-export all the patches to check if there were changes.
python src/electron/script/export_all_patches.py src/electron/patches/config.json
cd src/electron
git update-index --refresh || true
if ! git diff-index --quiet HEAD --; then
# There are changes to the patches. Make a git commit with the updated patches
git add patches
GIT_COMMITTER_NAME="Electron Bot" GIT_COMMITTER_EMAIL="electron@github.com" git commit -m "update patches" --author="Electron Bot <electron@github.com>"
# Export it
mkdir -p ../../patches
git format-patch -1 --stdout --keep-subject --no-stat --full-index > ../../patches/update-patches.patch
if (node ./script/push-patch.js 2> /dev/null > /dev/null); then
echo
echo "======================================================================"
echo "Changes to the patches when applying, we have auto-pushed the diff to the current branch"
echo "A new CI job will kick off shortly"
echo "======================================================================"
exit 1
else
echo
echo "======================================================================"
echo "There were changes to the patches when applying."
echo "Check the CI artifacts for a patch you can apply to fix it."
echo "======================================================================"
exit 1
fi
fi
fi
fi
@@ -299,10 +311,10 @@ step-setup-goma-for-build: &step-setup-goma-for-build
name: Setup Goma
command: |
echo 'export USE_GOMA=true' >> $BASH_ENV
if [ "`uname`" == "Linux" ]; then
echo 'export NUMBER_OF_NINJA_PROCESSES=300' >> $BASH_ENV
else
echo 'export NUMBER_OF_NINJA_PROCESSES=25' >> $BASH_ENV
echo 'export NUMBER_OF_NINJA_PROCESSES=300' >> $BASH_ENV
if [ "`uname`" == "Darwin" ]; then
echo 'ulimit -n 10000' >> $BASH_ENV
echo 'sudo launchctl limit maxfiles 65536 200000' >> $BASH_ENV
fi
if [ ! -z "$RAW_GOMA_AUTH" ]; then
echo $RAW_GOMA_AUTH > ~/.goma_oauth2_config
@@ -311,7 +323,7 @@ step-setup-goma-for-build: &step-setup-goma-for-build
cd build-tools
npm install
mkdir third_party
node -e "require('./src/utils/goma.js').downloadAndPrepare()"
node -e "require('./src/utils/goma.js').downloadAndPrepare({ gomaOneForAll: true })"
node -e "require('./src/utils/goma.js').ensure()"
echo 'export GN_GOMA_FILE='`node -e "console.log(require('./src/utils/goma.js').gnFilePath)"` >> $BASH_ENV
echo 'export LOCAL_GOMA_DIR='`node -e "console.log(require('./src/utils/goma.js').dir)"` >> $BASH_ENV
@@ -572,6 +584,9 @@ step-electron-dist-build: &step-electron-dist-build
if [ x"$MAS_BUILD" == x"true" ]; then
target_os=mac_mas
fi
if [ "$TARGET_ARCH" == "arm64" ]; then
target_cpu=arm64
fi
elif [ "`uname`" == "Linux" ]; then
target_os=linux
if [ x"$TARGET_ARCH" == x ]; then
@@ -659,10 +674,10 @@ step-electron-publish: &step-electron-publish
cd src/electron
if [ "$UPLOAD_TO_S3" == "1" ]; then
echo 'Uploading Electron release distribution to S3'
script/release/uploaders/upload.py --upload_to_s3
script/release/uploaders/upload.py --verbose --upload_to_s3
else
echo 'Uploading Electron release distribution to Github releases'
script/release/uploaders/upload.py
script/release/uploaders/upload.py --verbose
fi
step-persist-data-for-tests: &step-persist-data-for-tests
@@ -915,6 +930,8 @@ step-ninja-summary: &step-ninja-summary
run:
name: Print ninja summary
command: |
set +e
set +o pipefail
python depot_tools/post_build_ninja_summary.py -C src/out/Default
step-ninja-report: &step-ninja-report

View File

@@ -325,7 +325,6 @@ source_set("electron_lib") {
"//base/allocator:buildflags",
"//chrome/app:command_ids",
"//chrome/app/resources:platform_locale_settings",
"//chrome/services/printing/public/mojom",
"//components/certificate_transparency",
"//components/language/core/browser",
"//components/net_log",
@@ -372,6 +371,7 @@ source_set("electron_lib") {
"//third_party/libyuv",
"//third_party/webrtc_overrides:webrtc_component",
"//third_party/widevine/cdm:headers",
"//third_party/zlib/google:zip",
"//ui/base/idle",
"//ui/events:dom_keycode_converter",
"//ui/gl",
@@ -620,7 +620,10 @@ source_set("electron_lib") {
"shell/renderer/printing/print_render_frame_helper_delegate.cc",
"shell/renderer/printing/print_render_frame_helper_delegate.h",
]
deps += [ "//components/printing/common:mojo_interfaces" ]
deps += [
"//chrome/services/printing/public/mojom",
"//components/printing/common:mojo_interfaces",
]
}
if (enable_electron_extensions) {
@@ -658,6 +661,14 @@ source_set("electron_lib") {
"shell/browser/electron_pdf_web_contents_helper_client.h",
]
}
if (is_win && enable_win_dark_mode_window_ui) {
sources += [
"shell/browser/win/dark_mode.cc",
"shell/browser/win/dark_mode.h",
]
libs += [ "uxtheme.lib" ]
}
}
electron_paks("packed_resources") {
@@ -683,10 +694,10 @@ if (is_mac) {
action("fake_v8_context_snapshot_generator") {
script = "build/fake_v8_context_snapshot_generator.py"
args = [
rebase_path("$root_out_dir/v8_context_snapshot.bin"),
rebase_path("$root_out_dir/fake/v8_context_snapshot.bin"),
rebase_path("$root_out_dir/$v8_context_snapshot_filename"),
rebase_path("$root_out_dir/fake/$v8_context_snapshot_filename"),
]
outputs = [ "$root_out_dir/fake/v8_context_snapshot.bin" ]
outputs = [ "$root_out_dir/fake/$v8_context_snapshot_filename" ]
}
bundle_data("electron_framework_resources") {
@@ -700,10 +711,10 @@ if (is_mac) {
public_deps += [ "//v8" ]
if (use_v8_context_snapshot) {
if (use_prebuilt_v8_context_snapshot) {
sources += [ "$root_out_dir/fake/v8_context_snapshot.bin" ]
sources += [ "$root_out_dir/fake/$v8_context_snapshot_filename" ]
public_deps += [ ":fake_v8_context_snapshot_generator" ]
} else {
sources += [ "$root_out_dir/v8_context_snapshot.bin" ]
sources += [ "$root_out_dir/$v8_context_snapshot_filename" ]
public_deps += [ "//tools/v8_context_snapshot" ]
}
} else {

2
DEPS
View File

@@ -14,7 +14,7 @@ gclient_gn_args = [
vars = {
'chromium_version':
'87.0.4280.27',
'87.0.4280.141',
'node_version':
'v12.18.3',
'nan_version':

View File

@@ -1 +1 @@
11.0.0-beta.17
11.2.0

View File

@@ -101,6 +101,11 @@ build_script:
} else {
# update external binaries
python src/electron/script/update-external-binaries.py
# update angle
cd src\third_party\angle
git remote set-url origin https://chromium.googlesource.com/angle/angle.git
git fetch
cd ..\..\..
}
} else {
# file does not exist, gclient sync, then zip
@@ -138,7 +143,7 @@ build_script:
cd build-tools
npm install
mkdir third_party
node -e "require('./src/utils/goma.js').downloadAndPrepare()"
node -e "require('./src/utils/goma.js').downloadAndPrepare({ gomaOneForAll: true })"
$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 ..
@@ -224,10 +229,10 @@ deploy_script:
if (Test-Path Env:\ELECTRON_RELEASE) {
if (Test-Path Env:\UPLOAD_TO_S3) {
Write-Output "Uploading Electron release distribution to s3"
& python script\release\uploaders\upload.py --upload_to_s3
& python script\release\uploaders\upload.py --verbose --upload_to_s3
} else {
Write-Output "Uploading Electron release distribution to github releases"
& python script\release\uploaders\upload.py
& python script\release\uploaders\upload.py --verbose
}
} elseif (Test-Path Env:\TEST_WOA) {
node script/release/ci-release-build.js --job=electron-woa-testing --ci=VSTS --armTest --appveyorJobId=$env:APPVEYOR_JOB_ID $env:APPVEYOR_REPO_BRANCH

View File

@@ -21,6 +21,7 @@ buildflag_header("buildflags") {
"ENABLE_ELECTRON_EXTENSIONS=$enable_electron_extensions",
"ENABLE_BUILTIN_SPELLCHECKER=$enable_builtin_spellchecker",
"ENABLE_PICTURE_IN_PICTURE=$enable_picture_in_picture",
"ENABLE_WIN_DARK_MODE_WINDOW_UI=$enable_win_dark_mode_window_ui",
"OVERRIDE_LOCATION_PROVIDER=$enable_fake_location_provider",
]
}

View File

@@ -36,4 +36,7 @@ declare_args() {
# Enable Spellchecker support
enable_builtin_spellchecker = true
# Undocumented Windows dark mode API
enable_win_dark_mode_window_ui = false
}

View File

@@ -277,13 +277,15 @@ static_library("chrome") {
}
}
sources += [ "//chrome/browser/hang_monitor/hang_crash_dump.h" ]
if (is_mac) {
sources += [ "//chrome/browser/hang_monitor/hang_crash_dump_mac.cc" ]
} else if (is_win) {
sources += [ "//chrome/browser/hang_monitor/hang_crash_dump_win.cc" ]
} else {
sources += [ "//chrome/browser/hang_monitor/hang_crash_dump.cc" ]
if (!is_mas_build) {
sources += [ "//chrome/browser/hang_monitor/hang_crash_dump.h" ]
if (is_mac) {
sources += [ "//chrome/browser/hang_monitor/hang_crash_dump_mac.cc" ]
} else if (is_win) {
sources += [ "//chrome/browser/hang_monitor/hang_crash_dump_win.cc" ]
} else {
sources += [ "//chrome/browser/hang_monitor/hang_crash_dump.cc" ]
}
}
}

View File

@@ -826,10 +826,9 @@ ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessWithTimeout(
to_send.append(current_dir.value());
const std::vector<std::string>& argv = electron::ElectronCommandLine::argv();
for (std::vector<std::string>::const_iterator it = argv.begin();
it != argv.end(); ++it) {
for (const auto& arg : argv) {
to_send.push_back(kTokenDelimiter);
to_send.append(*it);
to_send.append(arg);
}
// Send the message

View File

@@ -122,8 +122,7 @@ void GlobalMenuBarRegistrarX11::OnNameOwnerChanged(GObject* /* ignored */,
GParamSpec* /* ignored */) {
// If the name owner changed, we need to reregister all the live x11::Window
// with the system.
for (std::set<x11::Window>::const_iterator it = live_windows_.begin();
it != live_windows_.end(); ++it) {
RegisterXWindow(*it);
for (const auto& window : live_windows_) {
RegisterXWindow(window);
}
}

View File

@@ -32,7 +32,8 @@ In most cases, you should do everything in the `ready` event handler.
Returns:
* `launchInfo` unknown _macOS_
* `event` Event
* `launchInfo` Record<string, any> _macOS_
Emitted once, when Electron has finished initializing. On macOS, `launchInfo`
holds the `userInfo` of the `NSUserNotification` that was used to open the
@@ -1340,7 +1341,7 @@ systems Application folder. Use in combination with `app.moveToApplicationsFolde
### `app.moveToApplicationsFolder([options])` _macOS_
* `options` Object (optional)
* `conflictHandler` Function<Boolean> (optional) - A handler for potential conflict in move failure.
* `conflictHandler` Function\<Boolean> (optional) - A handler for potential conflict in move failure.
* `conflictType` String - The type of move conflict encountered by the handler; can be `exists` or `existsAndRunning`, where `exists` means that an app of the same name is present in the Applications directory and `existsAndRunning` means both that it exists and that it's presently running.
Returns `Boolean` - Whether the move was successful. Please note that if
@@ -1484,3 +1485,12 @@ which native modules you can use in the renderer process. For more information
on the direction Electron is going with renderer process restarts and usage of
native modules in the renderer process please check out this
[Tracking Issue](https://github.com/electron/electron/issues/18397).
### `app.runningUnderRosettaTranslation` _macOS_ _Readonly_
A `Boolean` which when `true` indicates that the app is currently running
under the [Rosetta Translator Environment](https://en.wikipedia.org/wiki/Rosetta_(software)).
You can use this property to prompt users to download the arm64 version of
your application when they are running the x64 version under Rosetta
incorrectly.

View File

@@ -541,6 +541,12 @@ Note that this is only emitted when the window is being resized manually. Resizi
Emitted after the window has been resized.
#### Event: 'resized' _macOS_ _Windows_
Emitted once when the window has finished being resized.
This is usually emitted when the window has been resized manually. On macOS, resizing the window with `setBounds`/`setSize` and setting the `animate` parameter to `true` will also emit this event once resizing has finished.
#### Event: 'will-move' _macOS_ _Windows_
Returns:
@@ -556,12 +562,12 @@ Note that this is only emitted when the window is being resized manually. Resizi
Emitted when the window is being moved to a new position.
__Note__: On macOS this event is an alias of `moved`.
#### Event: 'moved' _macOS_
#### Event: 'moved' _macOS_ _Windows_
Emitted once when the window is moved to a new position.
__Note__: On macOS this event is an alias of `move`.
#### Event: 'enter-full-screen'
Emitted when the window enters a full-screen state.
@@ -1043,7 +1049,7 @@ 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_ _Linux_
#### `win.setAspectRatio(aspectRatio[, extraSize])`
* `aspectRatio` Float - The aspect ratio to maintain for some portion of the
content view.
@@ -1064,6 +1070,9 @@ the player itself we would call this function with arguments of 16/9 and
are within the content view--only that they exist. Sum any extra width and
height areas you have within the overall content view.
The aspect ratio is not respected when window is resized programmingly with
APIs like `win.setSize`.
#### `win.setBackgroundColor(backgroundColor)`
* `backgroundColor` String - Window's background color as a hexadecimal value,

View File

@@ -16,7 +16,7 @@ const { app, contentTracing } = require('electron')
app.whenReady().then(() => {
(async () => {
await contentTracing.startRecording({
include_categories: ['*']
included_categories: ['*']
})
console.log('Tracing started')
await new Promise(resolve => setTimeout(resolve, 5000))

View File

@@ -114,3 +114,9 @@ The following methods of `chrome.management` are supported:
- `chrome.management.getPermissionWarningsByManifest`
- `chrome.management.onEnabled`
- `chrome.management.onDisabled`
### `chrome.webRequest`
All features of this API are supported.
> **NOTE:** Electron's [`webRequest`](web-request.md) module takes precedence over `chrome.webRequest` if there are conflicting handlers.

View File

@@ -9,7 +9,7 @@ with the operating system so that you can customize the operations for various
shortcuts.
**Note:** The shortcut is global; it will work even if the app does
not have the keyboard focus. You should not use this module until the `ready`
not have the keyboard focus. This module cannot be used before the `ready`
event of the app module is emitted.
```javascript

View File

@@ -91,7 +91,7 @@ Removes listeners of the specified `channel`.
### `ipcMain.handle(channel, listener)`
* `channel` String
* `listener` Function<Promise<void> | any>
* `listener` Function<Promise\<void> | any>
* `event` IpcMainInvokeEvent
* `...args` any[]
@@ -123,7 +123,7 @@ WebContents is the source of the invoke request.
### `ipcMain.handleOnce(channel, listener)`
* `channel` String
* `listener` Function<Promise<void> | any>
* `listener` Function<Promise\<void> | any>
* `event` IpcMainInvokeEvent
* `...args` any[]

View File

@@ -349,6 +349,7 @@ win.webContents.session.setCertificateVerifyProc((request, callback) => {
* `handler` Function | null
* `webContents` [WebContents](web-contents.md) - WebContents requesting the permission. Please note that if the request comes from a subframe you should use `requestingUrl` to check the request origin.
* `permission` String - The type of requested permission.
* `clipboard-read` - Request access to read from the clipboard.
* `media` - Request access to media devices such as camera, microphone and speakers.
* `mediaKeySystem` - Request access to DRM protected content.
* `geolocation` - Request access to user's current location.
@@ -384,7 +385,7 @@ session.fromPartition('some-partition').setPermissionRequestHandler((webContents
#### `ses.setPermissionCheckHandler(handler)`
* `handler` Function<Boolean> | null
* `handler` Function\<Boolean> | null
* `webContents` [WebContents](web-contents.md) - WebContents checking the permission. Please note that if the request comes from a subframe you should use `requestingUrl` to check the request origin.
* `permission` String - Enum of 'media'.
* `requestingOrigin` String - The origin URL of the permission check

View File

@@ -1,5 +1,6 @@
# IpcMainEvent Object extends `Event`
* `processId` Integer - The internal ID of the renderer process that sent this message
* `frameId` Integer - The ID of the renderer frame that sent this message
* `returnValue` any - Set this to the value to be returned in a synchronous message
* `sender` WebContents - Returns the `webContents` that sent the message

View File

@@ -1,4 +1,5 @@
# IpcMainInvokeEvent Object extends `Event`
* `processId` Integer - The internal ID of the renderer process that sent this message
* `frameId` Integer - The ID of the renderer frame that sent this message
* `sender` WebContents - Returns the `webContents` that sent the message

View File

@@ -42,7 +42,8 @@ returns `null`.
* `id` Integer
Returns `WebContents` - A WebContents instance with the given ID.
Returns `WebContents` | undefined - A WebContents instance with the given ID, or
`undefined` if there is no WebContents associated with the given ID.
## Class: WebContents
@@ -1324,9 +1325,9 @@ Returns [`PrinterInfo[]`](structures/printer-info.md)
* `pagesPerSheet` Number (optional) - The number of pages to print per page sheet.
* `collate` Boolean (optional) - Whether the web page should be collated.
* `copies` Number (optional) - The number of copies of the web page to print.
* `pageRanges` Record<string, number> (optional) - The page range to print.
* `from` Number - the start page.
* `to` Number - the end page.
* `pageRanges` Object[] (optional) - The page range to print. On macOS, only one range is honored.
* `from` Number - Index of the first page to print (0-based).
* `to` Number - Index of the last page to print (inclusive) (0-based).
* `duplexMode` String (optional) - Set the duplex mode of the printed web page. Can be `simplex`, `shortEdge`, or `longEdge`.
* `dpi` Record<string, number> (optional)
* `horizontal` Number (optional) - The horizontal dpi.
@@ -1352,10 +1353,10 @@ Example usage:
const options = {
silent: true,
deviceName: 'My-Printer',
pageRanges: {
pageRanges: [{
from: 0,
to: 1
}
}]
}
win.webContents.print(options, (success, errorType) => {
if (!success) console.log(errorType)
@@ -1373,8 +1374,8 @@ win.webContents.print(options, (success, errorType) => {
default margin, 1 for no margin, and 2 for minimum margin.
* `scaleFactor` Number (optional) - The scale factor of the web page. Can range from 0 to 100.
* `pageRanges` Record<string, number> (optional) - The page range to print.
* `from` Number - zero-based index of the first page to print.
* `to` Number - zero-based index of the last page to print (inclusive).
* `from` Number - Index of the first page to print (0-based).
* `to` Number - Index of the last page to print (inclusive) (0-based).
* `pageSize` String | Size (optional) - Specify page size of the generated PDF. Can be `A3`,
`A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height` and `width` in microns.
* `printBackground` Boolean (optional) - Whether to print CSS backgrounds.
@@ -1621,7 +1622,9 @@ app.whenReady().then(() => {
#### `contents.sendToFrame(frameId, channel, ...args)`
* `frameId` Integer
* `frameId` Integer | [number, number] - the ID of the frame to send to, or a
pair of `[processId, frameId]` if the frame is in a different process to the
main frame.
* `channel` String
* `...args` any[]
@@ -1795,7 +1798,7 @@ Returns `Boolean` - If *offscreen rendering* is enabled returns whether it is cu
* `fps` Integer
If *offscreen rendering* is enabled sets the frame rate to the specified number.
Only values between 1 and 60 are accepted.
Only values between 1 and 240 are accepted.
#### `contents.getFrameRate()`
@@ -1893,7 +1896,7 @@ The zoom factor is the zoom percent divided by 100, so 300% = 3.0.
#### `contents.frameRate`
An `Integer` property that sets the frame rate of the web contents to the specified number.
Only values between 1 and 60 are accepted.
Only values between 1 and 240 are accepted.
Only applicable if *offscreen rendering* is enabled.

View File

@@ -560,9 +560,9 @@ Stops any `findInPage` request for the `webview` with the provided `action`.
* `pagesPerSheet` Number (optional) - The number of pages to print per page sheet.
* `collate` Boolean (optional) - Whether the web page should be collated.
* `copies` Number (optional) - The number of copies of the web page to print.
* `pageRanges` Record<string, number> (optional) - The page range to print.
* `from` Number - zero-based index of the first page to print.
* `to` Number - zero-based index of the last page to print (inclusive).
* `pageRanges` Object[] (optional) - The page range to print.
* `from` Number - Index of the first page to print (0-based).
* `to` Number - Index of the last page to print (inclusive) (0-based).
* `duplexMode` String (optional) - Set the duplex mode of the printed web page. Can be `simplex`, `shortEdge`, or `longEdge`.
* `dpi` Record<string, number> (optional)
* `horizontal` Number (optional) - The horizontal dpi.
@@ -588,8 +588,8 @@ Prints `webview`'s web page. Same as `webContents.print([options])`.
and `width` in microns.
* `scaleFactor` Number (optional) - The scale factor of the web page. Can range from 0 to 100.
* `pageRanges` Record<string, number> (optional) - The page range to print.
* `from` Number - the first page to print.
* `to` Number - the last page to print (inclusive).
* `from` Number - Index of the first page to print (0-based).
* `to` Number - Index of the last page to print (inclusive) (0-based).
* `pageSize` String | Size (optional) - Specify page size of the generated PDF. Can be `A3`,
`A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height`
* `printBackground` Boolean (optional) - Whether to print CSS backgrounds.
@@ -968,4 +968,4 @@ Emitted when DevTools is closed.
Emitted when DevTools is focused / opened.
[runtime-enabled-features]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/runtime_enabled_features.json5?l=70
[chrome-webview]: https://developer.chrome.com/apps/tags/webview
[chrome-webview]: https://developer.chrome.com/docs/extensions/reference/webviewTag/

View File

@@ -195,6 +195,45 @@ you should plan to update your native modules to be context aware.
For more detailed information see [#18397](https://github.com/electron/electron/issues/18397).
### Deprecated: `BrowserWindow` extension APIs
The following extension APIs have been deprecated:
* `BrowserWindow.addExtension(path)`
* `BrowserWindow.addDevToolsExtension(path)`
* `BrowserWindow.removeExtension(name)`
* `BrowserWindow.removeDevToolsExtension(name)`
* `BrowserWindow.getExtensions()`
* `BrowserWindow.getDevToolsExtensions()`
Use the session APIs instead:
* `ses.loadExtension(path)`
* `ses.removeExtension(extension_id)`
* `ses.getAllExtensions()`
```js
// Deprecated in Electron 9
BrowserWindow.addExtension(path)
BrowserWindow.addDevToolsExtension(path)
// Replace with
session.defaultSession.loadExtension(path)
```
```js
// Deprecated in Electron 9
BrowserWindow.removeExtension(name)
BrowserWindow.removeDevToolsExtension(name)
// Replace with
session.defaultSession.removeExtension(extension_id)
```
```js
// Deprecated in Electron 9
BrowserWindow.getExtensions()
BrowserWindow.getDevToolsExtensions()
// Replace with
session.defaultSession.getAllExtensions()
```
### Removed: `<webview>.getWebContents()`
This API, which was deprecated in Electron 8.0, is now removed.
@@ -338,6 +377,52 @@ 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).
### Deprecated events in `systemPreferences`
The following `systemPreferences` events have been deprecated:
* `inverted-color-scheme-changed`
* `high-contrast-color-scheme-changed`
Use the new `updated` event on the `nativeTheme` module instead.
```js
// Deprecated
systemPreferences.on('inverted-color-scheme-changed', () => { /* ... */ })
systemPreferences.on('high-contrast-color-scheme-changed', () => { /* ... */ })
// Replace with
nativeTheme.on('updated', () => { /* ... */ })
```
### Deprecated: methods in `systemPreferences`
The following `systemPreferences` methods have been deprecated:
* `systemPreferences.isDarkMode()`
* `systemPreferences.isInvertedColorScheme()`
* `systemPreferences.isHighContrastColorScheme()`
Use the following `nativeTheme` properties instead:
* `nativeTheme.shouldUseDarkColors`
* `nativeTheme.shouldUseInvertedColorScheme`
* `nativeTheme.shouldUseHighContrastColors`
```js
// Deprecated
systemPreferences.isDarkMode()
// Replace with
nativeTheme.shouldUseDarkColors
// Deprecated
systemPreferences.isInvertedColorScheme()
// Replace with
nativeTheme.shouldUseInvertedColorScheme
// Deprecated
systemPreferences.isHighContrastColorScheme()
// Replace with
nativeTheme.shouldUseHighContrastColors
```
## Planned Breaking API Changes (7.0)
### Deprecated: Atom.io Node Headers URL

View File

@@ -177,12 +177,12 @@ $ gn gen out/Testing-x86 --args='... target_cpu = "x86"'
Not all combinations of source and target CPU/OS are supported by Chromium.
<table>
<tr><th>Host</th><th>Target</th><th>Status</th></tr>
<tr><td>Windows x64</td><td>Windows arm64</td><td>Experimental</td>
<tr><td>Windows x64</td><td>Windows x86</td><td>Automatically tested</td></tr>
<tr><td>Linux x64</td><td>Linux x86</td><td>Automatically tested</td></tr>
</table>
| Host | Target | Status |
|-------------|---------------|----------------------|
| Windows x64 | Windows arm64 | Experimental |
| Windows x64 | Windows x86 | Automatically tested |
| Linux x64 | Linux x86 | Automatically tested |
If you test other combinations and find them to work, please update this document :)

View File

@@ -43,8 +43,8 @@ SRV*c:\code\symbols\*https://msdl.microsoft.com/download/symbols;SRV*c:\code\sym
## Using the symbol server in Visual Studio
<img src='https://mdn.mozillademos.org/files/733/symbol-server-vc8express-menu.jpg'>
<img src='https://mdn.mozillademos.org/files/2497/2005_options.gif'>
![Tools -> Options](https://mdn.mozillademos.org/files/733/symbol-server-vc8express-menu.jpg)
![Symbols Settings](https://mdn.mozillademos.org/files/2497/2005_options.gif)
## Troubleshooting: Symbols will not load

View File

@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
<h1>Hello World!</h1>
<p>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</p>
<a href="#" id="drag">Drag me</a>
<script src="renderer.js"></script>
</body>
</html>

View File

@@ -0,0 +1,41 @@
const { app, BrowserWindow, ipcMain, nativeImage, NativeImage } = require('electron')
const fs = require('fs');
const http = require('http');
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
win.loadFile('index.html')
}
const iconName = 'iconForDragAndDrop.png';
const icon = fs.createWriteStream(`${process.cwd()}/${iconName}`);
http.get('http://img.icons8.com/ios/452/drag-and-drop.png', (response) => {
response.pipe(icon);
});
app.whenReady().then(createWindow)
ipcMain.on('ondragstart', (event, filePath) => {
event.sender.startDrag({
file: filePath,
icon: `${process.cwd()}/${iconName}`
})
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})

View File

@@ -0,0 +1,9 @@
const { ipcRenderer } = require('electron')
const fs = require('fs')
document.getElementById('drag').ondragstart = (event) => {
const fileName = 'drag-and-drop.md'
fs.writeFileSync(fileName, '# Test drag and drop');
event.preventDefault()
ipcRenderer.send('ondragstart', process.cwd() + `/${fileName}`)
}

View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
<h1>Hello World!</h1>
<p>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</p>
</body>
</html>

View File

@@ -0,0 +1,31 @@
const { app, BrowserWindow, globalShortcut } = require('electron')
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
win.loadFile('index.html')
}
app.whenReady().then(() => {
globalShortcut.register('Alt+CommandOrControl+I', () => {
console.log('Electron loves global shortcuts!')
})
}).then(createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})

View File

@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
<h1>Hello World!</h1>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</body>
</html>

View File

@@ -0,0 +1,13 @@
const { app, BrowserWindow } = require('electron')
app.whenReady().then(() => {
const win = new BrowserWindow({ width: 800, height: 600, webPreferences: { nodeIntegration: true } })
win.loadFile('index.html')
win.webContents.on('before-input-event', (event, input) => {
if (input.control && input.key.toLowerCase() === 'i') {
console.log('Pressed Control+I')
event.preventDefault()
}
})
})

View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
<h1>Hello World!</h1>
<p>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</p>
</body>
</html>

View File

@@ -0,0 +1,39 @@
const { app, BrowserWindow, Menu, MenuItem } = require('electron')
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
win.loadFile('index.html')
}
const menu = new Menu()
menu.append(new MenuItem({
label: 'Electron',
submenu: [{
role: 'help',
accelerator: process.platform === 'darwin' ? 'Alt+Cmd+I' : 'Alt+Shift+I',
click: () => { console.log('Electron rocks!') }
}]
}))
Menu.setApplicationMenu(menu)
app.whenReady().then(createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})

View File

@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
<link rel="stylesheet" type="text/css" href="./styles.css">
</head>
<body>
<h1>Hello World!</h1>
<p>Current theme source: <strong id="theme-source">System</strong></p>
<button id="toggle-dark-mode">Toggle Dark Mode</button>
<button id="reset-to-system">Reset to System Theme</button>
<script src="renderer.js"></script>
</body>
</body>
</html>

View File

@@ -0,0 +1,40 @@
const { app, BrowserWindow, ipcMain, nativeTheme } = require('electron')
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
win.loadFile('index.html')
ipcMain.handle('dark-mode:toggle', () => {
if (nativeTheme.shouldUseDarkColors) {
nativeTheme.themeSource = 'light'
} else {
nativeTheme.themeSource = 'dark'
}
return nativeTheme.shouldUseDarkColors
})
ipcMain.handle('dark-mode:system', () => {
nativeTheme.themeSouce = 'system'
})
}
app.whenReady().then(createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})

View File

@@ -0,0 +1,11 @@
const { ipcRenderer } = require('electron')
document.getElementById('toggle-dark-mode').addEventListener('click', async () => {
const isDarkMode = await ipcRenderer.invoke('dark-mode:toggle')
document.getElementById('theme-source').innerHTML = isDarkMode ? 'Dark' : 'Light'
})
document.getElementById('reset-to-system').addEventListener('click', async () => {
await ipcRenderer.invoke('dark-mode:system')
document.getElementById('theme-source').innerHTML = 'System'
})

View File

@@ -0,0 +1,7 @@
@media (prefers-color-scheme: dark) {
body { background: #333; color: white; }
}
@media (prefers-color-scheme: light) {
body { background: #ddd; color: black; }
}

View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
<h1>Hello World!</h1>
<p>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</p>
</body>
</html>

View File

@@ -0,0 +1,43 @@
const { app, BrowserWindow, Menu } = require('electron')
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
win.loadFile('index.html')
}
const dockMenu = Menu.buildFromTemplate([
{
label: 'New Window',
click () { console.log('New Window') }
}, {
label: 'New Window with Settings',
submenu: [
{ label: 'Basic' },
{ label: 'Pro' }
]
},
{ label: 'New Command...' }
])
app.whenReady().then(() => {
app.dock.setMenu(dockMenu)
}).then(createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})

View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
<h1>Hello World!</h1>
<p>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</p>
</body>
</html>

View File

@@ -0,0 +1,35 @@
const { app, BrowserWindow, Notification } = require('electron')
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
win.loadFile('index.html')
}
function showNotification () {
const notification = {
title: 'Basic Notification',
body: 'Notification from the Main process'
}
new Notification(notification).show()
}
app.whenReady().then(createWindow).then(showNotification)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})

View File

@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
<h1>Hello World!</h1>
<p>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</p>
<script src="renderer.js"></script>
</body>
</html>

View File

@@ -0,0 +1,27 @@
const { app, BrowserWindow } = require('electron')
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
win.loadFile('index.html')
}
app.whenReady().then(createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})

View File

@@ -0,0 +1,7 @@
const myNotification = new Notification('Title', {
body: 'Notification from the Renderer process'
})
myNotification.onclick = () => {
console.log('Notification clicked')
}

View File

@@ -0,0 +1,15 @@
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
<h1>Hello World!</h1>
<p>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</p>
</body>
</html>

View File

@@ -0,0 +1,28 @@
const { app, BrowserWindow } = require('electron')
const fs = require('fs')
app.disableHardwareAcceleration()
let win
app.whenReady().then(() => {
win = new BrowserWindow({ webPreferences: { offscreen: true } })
win.loadURL('https://github.com')
win.webContents.on('paint', (event, dirty, image) => {
fs.writeFileSync('ex.png', image.toPNG())
})
win.webContents.setFrameRate(60)
console.log(`The screenshot has been successfully saved to ${process.cwd()}/ex.png`)
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})

View File

@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
<h1>Hello World!</h1>
<p>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</p>
<script src="renderer.js"></script>
</body>
</html>

View File

@@ -0,0 +1,24 @@
const { app, BrowserWindow, ipcMain } = require('electron')
let onlineStatusWindow
app.whenReady().then(() => {
onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false, webPreferences: { nodeIntegration: true } })
onlineStatusWindow.loadURL(`file://${__dirname}/index.html`)
})
ipcMain.on('online-status-changed', (event, status) => {
console.log(status)
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})

View File

@@ -0,0 +1,7 @@
const { ipcRenderer } = require('electron')
const updateOnlineStatus = () => { ipcRenderer.send('online-status-changed', navigator.onLine ? 'online' : 'offline') }
window.addEventListener('online', updateOnlineStatus)
window.addEventListener('offline', updateOnlineStatus)
updateOnlineStatus()

View File

@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
<h1>Hello World!</h1>
<p>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</p>
<script src="renderer.js"></script>
</body>
</html>

View File

@@ -0,0 +1,20 @@
const { app, BrowserWindow } = require('electron')
let onlineStatusWindow
app.whenReady().then(() => {
onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false })
onlineStatusWindow.loadURL(`file://${__dirname}/index.html`)
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})

View File

@@ -0,0 +1,6 @@
const alertOnlineStatus = () => { window.alert(navigator.onLine ? 'online' : 'offline') }
window.addEventListener('online', alertOnlineStatus)
window.addEventListener('offline', alertOnlineStatus)
alertOnlineStatus()

View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
<h1>Hello World!</h1>
<p>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</p>
</body>
</html>

View File

@@ -0,0 +1,30 @@
const { app, BrowserWindow } = require('electron')
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
win.loadFile('index.html')
win.setProgressBar(0.5)
}
app.whenReady().then(createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})

View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
<h1>Hello World!</h1>
<p>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</p>
</body>
</html>

View File

@@ -0,0 +1,34 @@
const { app, BrowserWindow } = require('electron')
const fs = require('fs')
const path = require('path')
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
win.loadFile('index.html')
}
const fileName = 'recently-used.md'
fs.writeFile(fileName, 'Lorem Ipsum', () => {
app.addRecentDocument(path.join(process.cwd(), `${fileName}`))
})
app.whenReady().then(createWindow)
app.on('window-all-closed', () => {
app.clearRecentDocuments()
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})

View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
<h1>Hello World!</h1>
<p>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</p>
</body>
</html>

View File

@@ -0,0 +1,33 @@
const { app, BrowserWindow } = require('electron')
const os = require('os');
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
win.loadFile('index.html')
}
app.whenReady().then(() => {
const win = new BrowserWindow()
win.setRepresentedFilename(os.homedir())
win.setDocumentEdited(true)
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})

View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
<h1>Hello World!</h1>
<p>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</p>
</body>
</html>

View File

@@ -0,0 +1,27 @@
const { app, BrowserWindow } = require('electron')
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
win.loadFile('index.html')
}
app.whenReady().then(createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})

View File

@@ -9,7 +9,7 @@ Two modes of rendering can be used and only the dirty area is passed in the
`'paint'` event to be more efficient. The rendering can be stopped, continued
and the frame rate can be set. The specified frame rate is a top limit value,
when there is nothing happening on a webpage, no frames are generated. The
maximum frame rate is 60, because above that there is no benefit, only
maximum frame rate is 240, because above that there is no benefit, only
performance loss.
**Note:** An offscreen window is always created as a [Frameless Window](../api/frameless-window.md).

View File

@@ -363,8 +363,12 @@ filenames = {
"shell/browser/electron_web_ui_controller_factory.h",
"shell/browser/event_emitter_mixin.cc",
"shell/browser/event_emitter_mixin.h",
"shell/browser/extended_web_contents_observer.h",
"shell/browser/feature_list.cc",
"shell/browser/feature_list.h",
"shell/browser/file_select_helper.cc",
"shell/browser/file_select_helper.h",
"shell/browser/file_select_helper_mac.mm",
"shell/browser/font_defaults.cc",
"shell/browser/font_defaults.h",
"shell/browser/javascript_environment.cc",
@@ -441,6 +445,7 @@ filenames = {
"shell/browser/ui/devtools_manager_delegate.h",
"shell/browser/ui/devtools_ui.cc",
"shell/browser/ui/devtools_ui.h",
"shell/browser/ui/drag_util.cc",
"shell/browser/ui/drag_util.h",
"shell/browser/ui/electron_menu_model.cc",
"shell/browser/ui/electron_menu_model.h",

View File

@@ -612,9 +612,10 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
if (options.withFileTypes) {
const dirents = [];
for (const file of files) {
const stats = archive.stat(file);
const childPath = path.join(filePath, file);
const stats = archive.stat(childPath);
if (!stats) {
const error = createError(AsarError.NOT_FOUND, { asarPath, filePath: file });
const error = createError(AsarError.NOT_FOUND, { asarPath, filePath: childPath });
nextTick(callback!, [error]);
return;
}
@@ -654,9 +655,10 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
if (options && (options as any).withFileTypes) {
const dirents = [];
for (const file of files) {
const stats = archive.stat(file);
const childPath = path.join(filePath, file);
const stats = archive.stat(childPath);
if (!stats) {
throw createError(AsarError.NOT_FOUND, { asarPath, filePath: file });
throw createError(AsarError.NOT_FOUND, { asarPath, filePath: childPath });
}
if (stats.isFile) {
dirents.push(new fs.Dirent(file, fs.constants.UV_DIRENT_FILE));
@@ -686,7 +688,8 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
if (info.size === 0) return ['', false];
if (info.unpacked) {
const realPath = archive.copyFileOut(filePath);
return fs.readFileSync(realPath, { encoding: 'utf8' });
const str = fs.readFileSync(realPath, { encoding: 'utf8' });
return [str, str.length > 0];
}
logASARAccess(asarPath, filePath, info.offset);

View File

@@ -17,8 +17,12 @@ Object.setPrototypeOf(protocol, new Proxy({}, {
ownKeys () {
if (!app.isReady()) return [];
return Reflect.ownKeys(session.defaultSession!.protocol);
},
return Object.getOwnPropertyNames(Object.getPrototypeOf(session.defaultSession!.protocol));
has: (target, property: string) => {
if (!app.isReady()) return false;
return Reflect.has(session.defaultSession!.protocol, property);
},
getOwnPropertyDescriptor () {

View File

@@ -1,20 +1,47 @@
import { EventEmitter } from 'events';
const { createScreen } = process._linkedBinding('electron_common_screen');
let _screen: Electron.Screen;
const createScreenIfNeeded = () => {
if (_screen === undefined) {
_screen = createScreen();
}
};
// We can't call createScreen until after app.on('ready'), but this module
// exposes an instance created by createScreen. In order to avoid
// side-effecting and calling createScreen upon import of this module, instead
// we export a proxy which lazily calls createScreen on first access.
export default new Proxy({}, {
get: (target, prop) => {
if (_screen === undefined) {
_screen = createScreen();
get: (target, property: keyof Electron.Screen) => {
createScreenIfNeeded();
const value = _screen[property];
if (typeof value === 'function') {
return value.bind(_screen);
}
const v = (_screen as any)[prop];
if (typeof v === 'function') {
return v.bind(_screen);
}
return v;
return value;
},
set: (target, property: string, value: unknown) => {
createScreenIfNeeded();
return Reflect.set(_screen, property, value);
},
ownKeys: () => {
createScreenIfNeeded();
return Reflect.ownKeys(_screen);
},
has: (target, property: string) => {
createScreenIfNeeded();
return property in _screen;
},
getOwnPropertyDescriptor: (target, property: string) => {
createScreenIfNeeded();
return Reflect.getOwnPropertyDescriptor(_screen, property);
},
getPrototypeOf: () => {
// This is necessary as a result of weirdness with EventEmitterMixin
// and FunctionTemplate - we need to explicitly ensure it's returned
// in the prototype.
return EventEmitter.prototype;
}
});

View File

@@ -11,7 +11,7 @@ if ('getAppLevelAppearance' in systemPreferences) {
}
if ('getEffectiveAppearance' in systemPreferences) {
const nativeEAGetter = systemPreferences.getAppLevelAppearance;
const nativeEAGetter = systemPreferences.getEffectiveAppearance;
Object.defineProperty(systemPreferences, 'effectiveAppearance', {
get: () => nativeEAGetter.call(systemPreferences)
});

View File

@@ -161,29 +161,29 @@ WebContents.prototype._sendInternalToAll = function (channel, ...args) {
return this._send(internal, sendToAll, channel, args);
};
WebContents.prototype.sendToFrame = function (frameId, channel, ...args) {
WebContents.prototype.sendToFrame = function (frame, channel, ...args) {
if (typeof channel !== 'string') {
throw new Error('Missing required channel argument');
} else if (typeof frameId !== 'number') {
throw new Error('Missing required frameId argument');
} else if (!(typeof frame === 'number' || Array.isArray(frame))) {
throw new Error('Missing required frame argument (must be number or array)');
}
const internal = false;
const sendToAll = false;
return this._sendToFrame(internal, sendToAll, frameId, channel, args);
return this._sendToFrame(internal, sendToAll, frame, channel, args);
};
WebContents.prototype._sendToFrameInternal = function (frameId, channel, ...args) {
WebContents.prototype._sendToFrameInternal = function (frame, channel, ...args) {
if (typeof channel !== 'string') {
throw new Error('Missing required channel argument');
} else if (typeof frameId !== 'number') {
throw new Error('Missing required frameId argument');
} else if (!(typeof frame === 'number' || Array.isArray(frame))) {
throw new Error('Missing required frame argument (must be number or array)');
}
const internal = true;
const sendToAll = false;
return this._sendToFrame(internal, sendToAll, frameId, channel, args);
return this._sendToFrame(internal, sendToAll, frame, channel, args);
};
// Following methods are mapped to webFrame.
@@ -439,8 +439,9 @@ WebContents.prototype.loadFile = function (filePath, options = {}) {
};
const addReplyToEvent = (event: any) => {
const { processId, frameId } = event;
event.reply = (...args: any[]) => {
event.sender.sendToFrame(event.frameId, ...args);
event.sender.sendToFrame([processId, frameId], ...args);
};
};
@@ -485,6 +486,13 @@ WebContents.prototype._init = function () {
this.goToOffset = navigationController.goToOffset.bind(navigationController);
this.getActiveIndex = navigationController.getActiveIndex.bind(navigationController);
this.length = navigationController.length.bind(navigationController);
// Read off the ID at construction time, so that it's accessible even after
// the underlying C++ WebContents is destroyed.
const id = this.id;
Object.defineProperty(this, 'id', {
value: id,
writable: false
});
// Every remote callback from renderer process would add a listener to the
// render-view-deleted event, so ignore the listeners warning.

View File

@@ -48,6 +48,9 @@ export const getSourcesImpl = (event: Electron.IpcMainEvent | null, args: Electr
}
// Remove from currentlyRunning once we resolve or reject
currentlyRunning = currentlyRunning.filter(running => running.options !== options);
if (event) {
event.sender.removeListener('destroyed', stopRunning);
}
};
capturer._onerror = (error: string) => {
@@ -66,7 +69,7 @@ export const getSourcesImpl = (event: Electron.IpcMainEvent | null, args: Electr
// reference to emit and the capturer itself so that it never dispatches
// back to the renderer
if (event) {
event.sender.once('destroyed', () => stopRunning());
event.sender.once('destroyed', stopRunning);
}
});

View File

@@ -19,7 +19,7 @@ const FUNCTION_PROPERTIES = [
];
type RendererFunctionId = [string, number] // [contextId, funcId]
type FinalizerInfo = { id: RendererFunctionId, webContents: electron.WebContents, frameId: number };
type FinalizerInfo = { id: RendererFunctionId, webContents: electron.WebContents, frameId: [number, number] };
type WeakRef<T> = { deref(): T | undefined }
type CallIntoRenderer = (...args: any[]) => void
@@ -31,7 +31,7 @@ const finalizationRegistry = new (globalThis as any).FinalizationRegistry((fi: F
const ref = rendererFunctionCache.get(mapKey);
if (ref !== undefined && ref.deref() === undefined) {
rendererFunctionCache.delete(mapKey);
if (!fi.webContents.isDestroyed()) { fi.webContents.sendToFrame(fi.frameId, 'ELECTRON_RENDERER_RELEASE_CALLBACK', fi.id[0], fi.id[1]); }
if (!fi.webContents.isDestroyed()) { fi.webContents._sendToFrameInternal(fi.frameId, 'ELECTRON_RENDERER_RELEASE_CALLBACK', fi.id[0], fi.id[1]); }
}
});
@@ -43,7 +43,7 @@ function getCachedRendererFunction (id: RendererFunctionId): CallIntoRenderer |
if (deref !== undefined) return deref;
}
}
function setCachedRendererFunction (id: RendererFunctionId, wc: electron.WebContents, frameId: number, value: CallIntoRenderer) {
function setCachedRendererFunction (id: RendererFunctionId, wc: electron.WebContents, frameId: [number, number], value: CallIntoRenderer) {
// eslint-disable-next-line no-undef
const wr = new (globalThis as any).WeakRef(value) as WeakRef<CallIntoRenderer>;
const mapKey = id[0] + '~' + id[1];
@@ -218,7 +218,7 @@ const fakeConstructor = (constructor: Function, name: string) =>
});
// Convert array of meta data from renderer into array of real values.
const unwrapArgs = function (sender: electron.WebContents, frameId: number, contextId: string, args: any[]) {
const unwrapArgs = function (sender: electron.WebContents, frameId: [number, number], contextId: string, args: any[]) {
const metaToValue = function (meta: MetaTypeFromRenderer): any {
switch (meta.type) {
case 'nativeimage':
@@ -263,7 +263,7 @@ const unwrapArgs = function (sender: electron.WebContents, frameId: number, cont
const callIntoRenderer = function (this: any, ...args: any[]) {
let succeed = false;
if (!sender.isDestroyed()) {
succeed = (sender as any)._sendToFrameInternal(frameId, 'ELECTRON_RENDERER_CALLBACK', contextId, meta.id, valueToMeta(sender, contextId, args));
succeed = sender._sendToFrameInternal(frameId, 'ELECTRON_RENDERER_CALLBACK', contextId, meta.id, valueToMeta(sender, contextId, args));
}
if (!succeed) {
removeRemoteListenersAndLogWarning(this, callIntoRenderer);
@@ -421,7 +421,7 @@ handleRemoteCommand('ELECTRON_BROWSER_CURRENT_WEB_CONTENTS', function (event, co
});
handleRemoteCommand('ELECTRON_BROWSER_CONSTRUCTOR', function (event, contextId, id, args) {
args = unwrapArgs(event.sender, event.frameId, contextId, args);
args = unwrapArgs(event.sender, [event.processId, event.frameId], contextId, args);
const constructor = objectsRegistry.get(id);
if (constructor == null) {
@@ -432,7 +432,7 @@ handleRemoteCommand('ELECTRON_BROWSER_CONSTRUCTOR', function (event, contextId,
});
handleRemoteCommand('ELECTRON_BROWSER_FUNCTION_CALL', function (event, contextId, id, args) {
args = unwrapArgs(event.sender, event.frameId, contextId, args);
args = unwrapArgs(event.sender, [event.processId, event.frameId], contextId, args);
const func = objectsRegistry.get(id);
if (func == null) {
@@ -449,7 +449,7 @@ handleRemoteCommand('ELECTRON_BROWSER_FUNCTION_CALL', function (event, contextId
});
handleRemoteCommand('ELECTRON_BROWSER_MEMBER_CONSTRUCTOR', function (event, contextId, id, method, args) {
args = unwrapArgs(event.sender, event.frameId, contextId, args);
args = unwrapArgs(event.sender, [event.processId, event.frameId], contextId, args);
const object = objectsRegistry.get(id);
if (object == null) {
@@ -460,7 +460,7 @@ handleRemoteCommand('ELECTRON_BROWSER_MEMBER_CONSTRUCTOR', function (event, cont
});
handleRemoteCommand('ELECTRON_BROWSER_MEMBER_CALL', function (event, contextId, id, method, args) {
args = unwrapArgs(event.sender, event.frameId, contextId, args);
args = unwrapArgs(event.sender, [event.processId, event.frameId], contextId, args);
const object = objectsRegistry.get(id);
if (object == null) {
@@ -477,7 +477,7 @@ handleRemoteCommand('ELECTRON_BROWSER_MEMBER_CALL', function (event, contextId,
});
handleRemoteCommand('ELECTRON_BROWSER_MEMBER_SET', function (event, contextId, id, name, args) {
args = unwrapArgs(event.sender, event.frameId, contextId, args);
args = unwrapArgs(event.sender, [event.processId, event.frameId], contextId, args);
const obj = objectsRegistry.get(id);
if (obj == null) {

View File

@@ -38,7 +38,7 @@ const keysOfTypeNumber = ['top', 'left', ...Object.keys(keysOfTypeNumberCompileT
type CoercedValue = string | number | boolean;
function coerce (key: string, value: string): CoercedValue {
if (keysOfTypeNumber.includes(key)) {
return Number(value);
return parseInt(value, 10);
}
switch (value) {

View File

@@ -298,7 +298,7 @@ function metaToError (meta: { type: 'error', value: any, members: ObjectMember[]
}
function handleMessage (channel: string, handler: Function) {
ipcRendererInternal.on(channel, (event, passedContextId, id, ...args) => {
ipcRendererInternal.onMessageFromMain(channel, (event, passedContextId, id, ...args) => {
if (passedContextId === contextId) {
handler(id, ...args);
} else {

View File

@@ -1,119 +0,0 @@
import { webFrame } from 'electron';
import * as ipcRendererUtils from '@electron/internal/renderer/ipc-renderer-internal-utils';
const v8Util = process._linkedBinding('electron_common_v8_util');
const IsolatedWorldIDs = {
/**
* Start of extension isolated world IDs, as defined in
* electron_render_frame_observer.h
*/
ISOLATED_WORLD_EXTENSIONS: 1 << 20
};
let isolatedWorldIds = IsolatedWorldIDs.ISOLATED_WORLD_EXTENSIONS;
const extensionWorldId: {[key: string]: number | undefined} = {};
// https://cs.chromium.org/chromium/src/extensions/renderer/script_injection.cc?type=cs&sq=package:chromium&g=0&l=52
const getIsolatedWorldIdForInstance = () => {
// TODO(samuelmaddock): allocate and cleanup IDs
return isolatedWorldIds++;
};
const escapePattern = function (pattern: string) {
return pattern.replace(/[\\^$+?.()|[\]{}]/g, '\\$&');
};
// Check whether pattern matches.
// https://developer.chrome.com/extensions/match_patterns
const matchesPattern = function (pattern: string) {
if (pattern === '<all_urls>') return true;
const regexp = new RegExp(`^${pattern.split('*').map(escapePattern).join('.*')}$`);
const url = `${location.protocol}//${location.host}${location.pathname}`;
return url.match(regexp);
};
// Run the code with chrome API integrated.
const runContentScript = function (this: any, extensionId: string, url: string, code: string) {
// Assign unique world ID to each extension
const worldId = extensionWorldId[extensionId] ||
(extensionWorldId[extensionId] = getIsolatedWorldIdForInstance());
// store extension ID for content script to read in isolated world
v8Util.setHiddenValue(global, `extension-${worldId}`, extensionId);
webFrame.setIsolatedWorldInfo(worldId, {
name: `${extensionId} [${worldId}]`
// TODO(samuelmaddock): read `content_security_policy` from extension manifest
// csp: manifest.content_security_policy,
});
const sources = [{ code, url }];
return webFrame.executeJavaScriptInIsolatedWorld(worldId, sources);
};
const runAllContentScript = function (scripts: Array<Electron.InjectionBase>, extensionId: string) {
for (const { url, code } of scripts) {
runContentScript.call(window, extensionId, url, code);
}
};
const runStylesheet = function (this: any, url: string, code: string) {
webFrame.insertCSS(code);
};
const runAllStylesheet = function (css: Array<Electron.InjectionBase>) {
for (const { url, code } of css) {
runStylesheet.call(window, url, code);
}
};
// Run injected scripts.
// https://developer.chrome.com/extensions/content_scripts
const injectContentScript = function (extensionId: string, script: Electron.ContentScript) {
if (!process.isMainFrame && !script.allFrames) return;
if (!script.matches.some(matchesPattern)) return;
if (script.js) {
const fire = runAllContentScript.bind(window, script.js, extensionId);
if (script.runAt === 'document_start') {
process.once('document-start', fire);
} else if (script.runAt === 'document_end') {
process.once('document-end', fire);
} else {
document.addEventListener('DOMContentLoaded', fire);
}
}
if (script.css) {
const fire = runAllStylesheet.bind(window, script.css);
if (script.runAt === 'document_start') {
process.once('document-start', fire);
} else if (script.runAt === 'document_end') {
process.once('document-end', fire);
} else {
document.addEventListener('DOMContentLoaded', fire);
}
}
};
// Handle the request of chrome.tabs.executeJavaScript.
ipcRendererUtils.handle('CHROME_TABS_EXECUTE_SCRIPT', function (
event: Electron.Event,
extensionId: string,
url: string,
code: string
) {
return runContentScript.call(window, extensionId, url, code);
});
module.exports = (entries: Electron.ContentScriptEntry[]) => {
for (const entry of entries) {
if (entry.contentScripts) {
for (const script of entry.contentScripts) {
injectContentScript(entry.extensionId, script);
}
}
}
};

View File

@@ -1,20 +0,0 @@
export class Event {
private listeners: Function[] = []
addListener (callback: Function) {
this.listeners.push(callback);
}
removeListener (callback: Function) {
const index = this.listeners.indexOf(callback);
if (index !== -1) {
this.listeners.splice(index, 1);
}
}
emit (...args: any[]) {
for (const listener of this.listeners) {
listener(...args);
}
}
}

View File

@@ -1,60 +0,0 @@
// Implementation of chrome.i18n.getMessage
// https://developer.chrome.com/extensions/i18n#method-getMessage
//
// Does not implement predefined messages:
// https://developer.chrome.com/extensions/i18n#overview-predefined
import * as ipcRendererUtils from '@electron/internal/renderer/ipc-renderer-internal-utils';
interface Placeholder {
content: string;
example?: string;
}
const getMessages = (extensionId: number) => {
try {
const data = ipcRendererUtils.invokeSync<string>('CHROME_GET_MESSAGES', extensionId);
return JSON.parse(data) || {};
} catch {
return {};
}
};
const replaceNumberedSubstitutions = (message: string, substitutions: string[]) => {
return message.replace(/\$(\d+)/, (_, number) => {
const index = parseInt(number, 10) - 1;
return substitutions[index] || '';
});
};
const replacePlaceholders = (message: string, placeholders: Record<string, Placeholder>, substitutions: string[] | string) => {
if (typeof substitutions === 'string') substitutions = [substitutions];
if (!Array.isArray(substitutions)) substitutions = [];
if (placeholders) {
Object.keys(placeholders).forEach((name: string) => {
let { content } = placeholders[name];
const substitutionsArray = Array.isArray(substitutions) ? substitutions : [];
content = replaceNumberedSubstitutions(content, substitutionsArray);
message = message.replace(new RegExp(`\\$${name}\\$`, 'gi'), content);
});
}
return replaceNumberedSubstitutions(message, substitutions);
};
const getMessage = (extensionId: number, messageName: string, substitutions: string[]) => {
const messages = getMessages(extensionId);
if (Object.prototype.hasOwnProperty.call(messages, messageName)) {
const { message, placeholders } = messages[messageName];
return replacePlaceholders(message, placeholders, substitutions);
}
};
exports.setup = (extensionId: number) => {
return {
getMessage (messageName: string, substitutions: string[]) {
return getMessage(extensionId, messageName, substitutions);
}
};
};

View File

@@ -1,86 +0,0 @@
import { ipcRendererInternal } from '@electron/internal/renderer/ipc-renderer-internal';
const getStorage = (storageType: string, extensionId: number, callback: Function) => {
if (typeof callback !== 'function') throw new TypeError('No callback provided');
ipcRendererInternal.invoke<string>('CHROME_STORAGE_READ', storageType, extensionId)
.then(data => {
if (data !== null) {
callback(JSON.parse(data));
} else {
// Disabled due to false positive in StandardJS
// eslint-disable-next-line standard/no-callback-literal
callback({});
}
});
};
const setStorage = (storageType: string, extensionId: number, storage: Record<string, any>, callback: Function) => {
const json = JSON.stringify(storage);
ipcRendererInternal.invoke('CHROME_STORAGE_WRITE', storageType, extensionId, json)
.then(() => {
if (callback) callback();
});
};
const getStorageManager = (storageType: string, extensionId: number) => {
return {
get (keys: string[], callback: Function) {
getStorage(storageType, extensionId, (storage: Record<string, any>) => {
if (keys == null) return callback(storage);
let defaults: Record<string, any> = {};
switch (typeof keys) {
case 'string':
keys = [keys];
break;
case 'object':
if (!Array.isArray(keys)) {
defaults = keys;
keys = Object.keys(keys);
}
break;
}
// Disabled due to false positive in StandardJS
// eslint-disable-next-line standard/no-callback-literal
if (keys.length === 0) return callback({});
const items: Record<string, any> = {};
keys.forEach((key: string) => {
let value = storage[key];
if (value == null) value = defaults[key];
items[key] = value;
});
callback(items);
});
},
set (items: Record<string, any>, callback: Function) {
getStorage(storageType, extensionId, (storage: Record<string, any>) => {
Object.keys(items).forEach(name => { storage[name] = items[name]; });
setStorage(storageType, extensionId, storage, callback);
});
},
remove (keys: string[], callback: Function) {
getStorage(storageType, extensionId, (storage: Record<string, any>) => {
if (!Array.isArray(keys)) keys = [keys];
keys.forEach((key: string) => {
delete storage[key];
});
setStorage(storageType, extensionId, storage, callback);
});
},
clear (callback: Function) {
setStorage(storageType, extensionId, {}, callback);
}
};
};
export const setup = (extensionId: number) => ({
sync: getStorageManager('sync', extensionId),
local: getStorageManager('local', extensionId)
});

View File

@@ -1,19 +0,0 @@
import { Event } from '@electron/internal/renderer/extensions/event';
import { ipcRendererInternal } from '@electron/internal/renderer/ipc-renderer-internal';
class WebNavigation {
private onBeforeNavigate = new Event()
private onCompleted = new Event()
constructor () {
ipcRendererInternal.on('CHROME_WEBNAVIGATION_ONBEFORENAVIGATE', (event: Electron.IpcRendererEvent, details: any) => {
this.onBeforeNavigate.emit(details);
});
ipcRendererInternal.on('CHROME_WEBNAVIGATION_ONCOMPLETED', (event: Electron.IpcRendererEvent, details: any) => {
this.onCompleted.emit(details);
});
}
}
export const setup = () => new WebNavigation();

View File

@@ -3,7 +3,7 @@ import { ipcRendererInternal } from '@electron/internal/renderer/ipc-renderer-in
type IPCHandler = (event: Electron.IpcRendererEvent, ...args: any[]) => any
export const handle = function <T extends IPCHandler> (channel: string, handler: T) {
ipcRendererInternal.on(channel, async (event, requestId, ...args) => {
ipcRendererInternal.onMessageFromMain(channel, async (event, requestId, ...args) => {
const replyChannel = `${channel}_RESPONSE_${requestId}`;
try {
event.sender.send(replyChannel, null, await handler(event, ...args));

View File

@@ -29,4 +29,27 @@ ipcRendererInternal.invoke = async function<T> (channel: string, ...args: any[])
return result;
};
ipcRendererInternal.onMessageFromMain = function (channel: string, listener: (event: Electron.IpcRendererEvent, ...args: any[]) => void) {
return ipcRendererInternal.on(channel, (event, ...args) => {
if (event.senderId !== 0) {
console.error(`Message ${channel} sent by unexpected WebContents (${event.senderId})`);
return;
}
listener(event, ...args);
});
};
ipcRendererInternal.onceMessageFromMain = function (channel: string, listener: (event: Electron.IpcRendererEvent, ...args: any[]) => void) {
return ipcRendererInternal.on(channel, function wrapper (event, ...args) {
if (event.senderId !== 0) {
console.error(`Message ${channel} sent by unexpected WebContents (${event.senderId})`);
return;
}
ipcRendererInternal.removeListener(channel, wrapper);
listener(event, ...args);
});
};
export { ipcRendererInternal };

View File

@@ -179,7 +179,7 @@ const warnAboutInsecureCSP = function () {
console.warn('%cElectron Security Warning (Insecure Content-Security-Policy)',
'font-weight: bold;', warning);
});
}).catch(() => {});
};
/**

View File

@@ -27,6 +27,7 @@ const WEB_VIEW_EVENTS: Record<string, Array<string>> = {
'focus-change': ['focus', 'guestInstanceId'],
close: [],
crashed: [],
'render-process-gone': ['details'],
'plugin-crashed': ['name', 'version'],
destroyed: [],
'page-title-updated': ['title', 'explicitSet'],
@@ -66,18 +67,18 @@ const dispatchEvent = function (
};
export function registerEvents (webView: WebViewImpl, viewInstanceId: number) {
ipcRendererInternal.on(`ELECTRON_GUEST_VIEW_INTERNAL_DESTROY_GUEST-${viewInstanceId}`, function () {
ipcRendererInternal.onMessageFromMain(`ELECTRON_GUEST_VIEW_INTERNAL_DESTROY_GUEST-${viewInstanceId}`, function () {
webView.guestInstanceId = undefined;
webView.reset();
const domEvent = new Event('destroyed');
webView.dispatchEvent(domEvent);
});
ipcRendererInternal.on(`ELECTRON_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-${viewInstanceId}`, function (event, eventName, ...args) {
ipcRendererInternal.onMessageFromMain(`ELECTRON_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-${viewInstanceId}`, function (event, eventName, ...args) {
dispatchEvent(webView, eventName, eventName, ...args);
});
ipcRendererInternal.on(`ELECTRON_GUEST_VIEW_INTERNAL_IPC_MESSAGE-${viewInstanceId}`, function (event, channel, ...args) {
ipcRendererInternal.onMessageFromMain(`ELECTRON_GUEST_VIEW_INTERNAL_IPC_MESSAGE-${viewInstanceId}`, function (event, channel, ...args) {
const domEvent = new Event('ipc-message') as IpcMessageEvent;
domEvent.channel = channel;
domEvent.args = args;

View File

@@ -17,7 +17,7 @@ interface MutationHandler {
// Attribute objects.
// Default implementation of a WebView attribute.
class WebViewAttribute implements MutationHandler {
export class WebViewAttribute implements MutationHandler {
public value: any;
public ignoreMutation = false;
@@ -78,7 +78,7 @@ class BooleanAttribute extends WebViewAttribute {
}
// Attribute representing the state of the storage partition.
class PartitionAttribute extends WebViewAttribute {
export class PartitionAttribute extends WebViewAttribute {
public validPartitionId = true
constructor (public webViewImpl: WebViewImpl) {
@@ -102,7 +102,7 @@ class PartitionAttribute extends WebViewAttribute {
}
// Attribute that handles the location and navigation of the webview.
class SrcAttribute extends WebViewAttribute {
export class SrcAttribute extends WebViewAttribute {
public observer!: MutationObserver;
constructor (public webViewImpl: WebViewImpl) {
@@ -168,7 +168,7 @@ class SrcAttribute extends WebViewAttribute {
}
public parse () {
if (!this.webViewImpl.elementAttached || !this.webViewImpl.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_PARTITION].validPartitionId || !this.getValue()) {
if (!this.webViewImpl.elementAttached || !(this.webViewImpl.attributes.get(WEB_VIEW_CONSTANTS.ATTRIBUTE_PARTITION) as PartitionAttribute).validPartitionId || !this.getValue()) {
return;
}
if (this.webViewImpl.guestInstanceId == null) {
@@ -182,12 +182,12 @@ class SrcAttribute extends WebViewAttribute {
// Navigate to |this.src|.
const opts: Record<string, string> = {};
const httpreferrer = this.webViewImpl.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_HTTPREFERRER].getValue();
const httpreferrer = this.webViewImpl.attributes.get(WEB_VIEW_CONSTANTS.ATTRIBUTE_HTTPREFERRER)!.getValue();
if (httpreferrer) {
opts.httpReferrer = httpreferrer;
}
const useragent = this.webViewImpl.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_USERAGENT].getValue();
const useragent = this.webViewImpl.attributes.get(WEB_VIEW_CONSTANTS.ATTRIBUTE_USERAGENT)!.getValue();
if (useragent) {
opts.userAgent = useragent;
}
@@ -274,19 +274,18 @@ class EnableRemoteModuleAttribute extends WebViewAttribute {
// Sets up all of the webview attributes.
WebViewImpl.prototype.setupWebViewAttributes = function () {
this.attributes = {};
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_PARTITION] = new PartitionAttribute(this);
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_SRC] = new SrcAttribute(this);
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_HTTPREFERRER] = new HttpReferrerAttribute(this);
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_USERAGENT] = new UserAgentAttribute(this);
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_NODEINTEGRATION] = new BooleanAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_NODEINTEGRATION, this);
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_NODEINTEGRATIONINSUBFRAMES] = new BooleanAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_NODEINTEGRATIONINSUBFRAMES, this);
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_PLUGINS] = new BooleanAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_PLUGINS, this);
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_DISABLEWEBSECURITY] = new BooleanAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_DISABLEWEBSECURITY, this);
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_ALLOWPOPUPS] = new BooleanAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_ALLOWPOPUPS, this);
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_ENABLEREMOTEMODULE] = new EnableRemoteModuleAttribute(this);
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_PRELOAD] = new PreloadAttribute(this);
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_BLINKFEATURES] = new BlinkFeaturesAttribute(this);
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_DISABLEBLINKFEATURES] = new DisableBlinkFeaturesAttribute(this);
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_WEBPREFERENCES] = new WebPreferencesAttribute(this);
this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_PARTITION, new PartitionAttribute(this));
this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_SRC, new SrcAttribute(this));
this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_HTTPREFERRER, new HttpReferrerAttribute(this));
this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_USERAGENT, new UserAgentAttribute(this));
this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_NODEINTEGRATION, new BooleanAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_NODEINTEGRATION, this));
this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_NODEINTEGRATIONINSUBFRAMES, new BooleanAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_NODEINTEGRATIONINSUBFRAMES, this));
this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_PLUGINS, new BooleanAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_PLUGINS, this));
this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_DISABLEWEBSECURITY, new BooleanAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_DISABLEWEBSECURITY, this));
this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_ALLOWPOPUPS, new BooleanAttribute(WEB_VIEW_CONSTANTS.ATTRIBUTE_ALLOWPOPUPS, this));
this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_ENABLEREMOTEMODULE, new EnableRemoteModuleAttribute(this));
this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_PRELOAD, new PreloadAttribute(this));
this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_BLINKFEATURES, new BlinkFeaturesAttribute(this));
this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_DISABLEBLINKFEATURES, new DisableBlinkFeaturesAttribute(this));
this.attributes.set(WEB_VIEW_CONSTANTS.ATTRIBUTE_WEBPREFERENCES, new WebPreferencesAttribute(this));
};

View File

@@ -16,9 +16,6 @@ export const enum WEB_VIEW_CONSTANTS {
ATTRIBUTE_DISABLEBLINKFEATURES = 'disableblinkfeatures',
ATTRIBUTE_WEBPREFERENCES = 'webpreferences',
// Internal attribute.
ATTRIBUTE_INTERNALINSTANCEID = 'internalinstanceid',
// Error messages.
ERROR_MSG_ALREADY_NAVIGATED = 'The object has already navigated, so its partition cannot be changed.',
ERROR_MSG_CANNOT_INJECT_SCRIPT = '<webview> = ' + 'Script cannot be injected into content until the page has loaded.',

View File

@@ -10,6 +10,7 @@
import { WEB_VIEW_CONSTANTS } from '@electron/internal/renderer/web-view/web-view-constants';
import { WebViewImpl as IWebViewImpl, webViewImplModule } from '@electron/internal/renderer/web-view/web-view-impl';
import type { SrcAttribute } from '@electron/internal/renderer/web-view/web-view-attributes';
// Return a WebViewElement class that is defined in this context.
const defineWebViewElement = (v8Util: NodeJS.V8UtilBinding, webViewImpl: typeof webViewImplModule) => {
@@ -49,7 +50,7 @@ const defineWebViewElement = (v8Util: NodeJS.V8UtilBinding, webViewImpl: typeof
if (!internal.elementAttached) {
guestViewInternal.registerEvents(internal, internal.viewInstanceId);
internal.elementAttached = true;
internal.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_SRC].parse();
(internal.attributes.get(WEB_VIEW_CONSTANTS.ATTRIBUTE_SRC) as SrcAttribute).parse();
}
}

View File

@@ -5,6 +5,7 @@ import * as ipcRendererUtils from '@electron/internal/renderer/ipc-renderer-inte
import * as guestViewInternal from '@electron/internal/renderer/web-view/guest-view-internal';
import { WEB_VIEW_CONSTANTS } from '@electron/internal/renderer/web-view/web-view-constants';
import { syncMethods, asyncMethods, properties } from '@electron/internal/common/web-view-methods';
import type { WebViewAttribute, PartitionAttribute } from '@electron/internal/renderer/web-view/web-view-attributes';
import { deserialize } from '@electron/internal/common/type-utils';
const { webFrame } = electron;
@@ -33,7 +34,7 @@ export class WebViewImpl {
public internalElement: HTMLIFrameElement
// Replaced in web-view-attributes
public attributes: Record<string, any> = {}
public attributes = new Map<string, WebViewAttribute>();
public setupWebViewAttributes (): void {}
constructor (public webviewNode: HTMLElement) {
@@ -76,7 +77,7 @@ export class WebViewImpl {
}
this.beforeFirstNavigation = true;
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_PARTITION].validPartitionId = true;
(this.attributes.get(WEB_VIEW_CONSTANTS.ATTRIBUTE_PARTITION) as PartitionAttribute).validPartitionId = true;
// Since attachment swaps a local frame for a remote frame, we need our
// internal iframe element to be local again before we can reattach.
@@ -95,12 +96,12 @@ export class WebViewImpl {
// attribute, if necessary. See BrowserPlugin::UpdateDOMAttribute for more
// details.
handleWebviewAttributeMutation (attributeName: string, oldValue: any, newValue: any) {
if (!this.attributes[attributeName] || this.attributes[attributeName].ignoreMutation) {
if (!this.attributes.has(attributeName) || this.attributes.get(attributeName)!.ignoreMutation) {
return;
}
// Let the changed attribute handle its own mutation
this.attributes[attributeName].handleMutation(oldValue, newValue);
this.attributes.get(attributeName)!.handleMutation(oldValue, newValue);
}
onElementResize () {
@@ -149,7 +150,7 @@ export class WebViewImpl {
// Touching the src attribute triggers a navigation. To avoid
// triggering a page reload on every guest-initiated navigation,
// we do not handle this mutation.
this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_SRC].setValueIgnoreMutation(newValue);
this.attributes.get(WEB_VIEW_CONSTANTS.ATTRIBUTE_SRC)!.setValueIgnoreMutation(newValue);
}
}
@@ -163,7 +164,7 @@ export class WebViewImpl {
}
onAttach (storagePartitionId: number) {
return this.attributes[WEB_VIEW_CONSTANTS.ATTRIBUTE_PARTITION].setValue(storagePartitionId);
return this.attributes.get(WEB_VIEW_CONSTANTS.ATTRIBUTE_PARTITION)!.setValue(storagePartitionId);
}
buildParams () {
@@ -172,10 +173,8 @@ export class WebViewImpl {
userAgentOverride: this.userAgentOverride
};
for (const attributeName in this.attributes) {
if (Object.prototype.hasOwnProperty.call(this.attributes, attributeName)) {
params[attributeName] = this.attributes[attributeName].getValue();
}
for (const [attributeName, attribute] of this.attributes) {
params[attributeName] = attribute.getValue();
}
return params;

View File

@@ -181,7 +181,7 @@ class BrowserWindowProxy {
this.guestId = guestId;
this._location = new LocationProxy(guestId);
ipcRendererInternal.once(`ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_CLOSED_${guestId}`, () => {
ipcRendererInternal.onceMessageFromMain(`ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_CLOSED_${guestId}`, () => {
removeProxy(guestId);
this.closed = true;
});
@@ -281,7 +281,7 @@ export const windowSetup = (
if (contextIsolationEnabled) internalContextBridge.overrideGlobalValueFromIsolatedWorld(['prompt'], window.prompt);
if (!usesNativeWindowOpen || openerId != null) {
ipcRendererInternal.on('ELECTRON_GUEST_WINDOW_POSTMESSAGE', function (
ipcRendererInternal.onMessageFromMain('ELECTRON_GUEST_WINDOW_POSTMESSAGE', function (
_event, sourceId: number, message: any, sourceOrigin: string
) {
// Manually dispatch event instead of using postMessage because we also need to
@@ -336,7 +336,7 @@ export const windowSetup = (
let cachedVisibilityState = isHiddenPage ? 'hidden' : 'visible';
// Subscribe to visibilityState changes.
ipcRendererInternal.on('ELECTRON_GUEST_INSTANCE_VISIBILITY_CHANGE', function (_event, visibilityState: VisibilityState) {
ipcRendererInternal.onMessageFromMain('ELECTRON_GUEST_INSTANCE_VISIBILITY_CHANGE', function (_event, visibilityState: VisibilityState) {
if (cachedVisibilityState !== visibilityState) {
cachedVisibilityState = visibilityState;
document.dispatchEvent(new Event('visibilitychange'));

View File

@@ -1,11 +1,12 @@
{
"name": "electron",
"version": "11.0.0-beta.17",
"version": "11.2.0",
"repository": "https://github.com/electron/electron",
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
"devDependencies": {
"@electron/docs-parser": "^0.9.2",
"@electron/docs-parser": "^0.10.0",
"@electron/typescript-definitions": "^8.7.5",
"@octokit/auth-app": "^2.10.0",
"@octokit/rest": "^18.0.3",
"@primer/octicons": "^10.0.0",
"@types/basic-auth": "^1.1.3",

View File

@@ -15,6 +15,7 @@ webview_cross_drag.patch
gin_enable_disable_v8_platform.patch
blink-worker-enable-csp-in-file-scheme.patch
disable-redraw-lock.patch
enable_reset_aspect_ratio.patch
v8_context_snapshot_generator.patch
boringssl_build_gn.patch
pepper_plugin_support.patch
@@ -100,3 +101,10 @@ worker_feat_add_hook_to_notify_script_ready.patch
cherry-pick-2f5b8357dca2.patch
fix_use_electron_generated_resources.patch
chore_expose_v8_initialization_isolate_callbacks.patch
crashpad-initialize-logging.patch
fix_properly_honor_printing_page_ranges.patch
cherry-pick-8f5a08079948.patch
cherry-pick-275865e8c237.patch
use_public_apis_to_determine_if_a_font_is_a_system_font_in_mas_build.patch
cherry-pick-47e21abe349a.patch
fix_setparentacessibile_crash_win.patch

View File

@@ -23,10 +23,10 @@ index f63b17435218d0d67bba044da67c1c80015fc996..d0fe24182f2cb48a1333054ce44b6a7f
int32_t world_id) {}
virtual void DidClearWindowObject() {}
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index e811aec4853c1ba0dacdcad758a5bc834643d7e3..5eb2dcde4d2033015677681ceeba7da9b9fe32df 100644
index 72a3bd4837f37bb1bab1f5ca48e90c41a297337f..23ff9cc13aaa97d395983dceb2a27158b2d679a5 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -5034,6 +5034,12 @@ void RenderFrameImpl::DidCreateScriptContext(v8::Local<v8::Context> context,
@@ -5036,6 +5036,12 @@ void RenderFrameImpl::DidCreateScriptContext(v8::Local<v8::Context> context,
observer.DidCreateScriptContext(context, world_id);
}

View File

@@ -9,10 +9,10 @@ potentially prevent a window from being created.
TODO(loc): this patch is currently broken.
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index 497033d3d5257daffe4aca2ebdd1fd71513db73f..7412bf8f9a9e07975917514e7f4c13253112138a 100644
index 8aa3723aa317ccd1591196a4929582b61c0d3b5f..b820655013e58a55698450f703dd7230f1d1d250 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -4945,6 +4945,7 @@ void RenderFrameHostImpl::CreateNewWindow(
@@ -4959,6 +4959,7 @@ void RenderFrameHostImpl::CreateNewWindow(
last_committed_origin_, params->window_container_type,
params->target_url, params->referrer.To<Referrer>(),
params->frame_name, params->disposition, *params->features,
@@ -21,10 +21,10 @@ index 497033d3d5257daffe4aca2ebdd1fd71513db73f..7412bf8f9a9e07975917514e7f4c1325
&no_javascript_access);
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index a39f43b61afc70296470a9ed616d7e8a423780aa..b113c265dcf5b8e3c7533085f1b8409fa13bcfa0 100644
index 26bd3968521cc2713d6350a0fa9265124c7efb00..5234e86d8f10533c4f8c6992a328d521c1850cea 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -3703,9 +3703,9 @@ RenderFrameHostDelegate* WebContentsImpl::CreateNewWindow(
@@ -3712,9 +3712,9 @@ RenderFrameHostDelegate* WebContentsImpl::CreateNewWindow(
}
if (delegate_) {
@@ -66,7 +66,7 @@ index da3aceed75b10087a86bcb8427c241fe647cdcfe..cafd45df059293bc1cf31e1d7b798e67
bool opener_suppressed,
bool* no_javascript_access) {
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
index 27b7e117b531bb370ea948e56b33d1a07eef11c6..9953cc472c04c2dc6ae0f70b64ea2b8d6ac86a05 100644
index 811bc7be6b174e0695beac6ee604ca19e9402739..3b93afa004fb4d56ade2ab16147b42f26e90e3db 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -153,6 +153,7 @@ class NetworkService;
@@ -77,7 +77,7 @@ index 27b7e117b531bb370ea948e56b33d1a07eef11c6..9953cc472c04c2dc6ae0f70b64ea2b8d
} // namespace network
namespace sandbox {
@@ -868,6 +869,8 @@ class CONTENT_EXPORT ContentBrowserClient {
@@ -876,6 +877,8 @@ class CONTENT_EXPORT ContentBrowserClient {
const std::string& frame_name,
WindowOpenDisposition disposition,
const blink::mojom::WindowFeatures& features,

View File

@@ -0,0 +1,413 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Robinson <mrobinson@igalia.com>
Date: Tue, 20 Oct 2020 09:00:52 +0000
Subject: Mac: Target a11y actions on certain containers to focused or
activedescendant children
When an action is triggered on a container with selectable children and
that container has a focused or activedescendant child, retarget the
action to that child. This fixes an issue where when the VoiceOver
cursor is on a tree with a focused child, triggered context menus would
use the tree as the target element.
menu on a tree instead of a focused child.
Bug: 1114892
Change-Id: Ibe580beed93aeaac54d1dabaee28443b290fd0e2
AX-Relnotes: Fix an issue where VoiceOver would trigger a context
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2466281
Commit-Queue: Martin Robinson <mrobinson@igalia.com>
Reviewed-by: Scott Violet <sky@chromium.org>
Reviewed-by: Dominic Mazzoni <dmazzoni@chromium.org>
Reviewed-by: Nektarios Paisios <nektar@chromium.org>
Cr-Commit-Position: refs/heads/master@{#818831}
diff --git a/content/browser/accessibility/browser_accessibility_cocoa.h b/content/browser/accessibility/browser_accessibility_cocoa.h
index 770c0cb6a4dad8cbf35900311a23a8296407d81d..0ffc8d768299cc5e7f37878fb656c12b028fead9 100644
--- a/content/browser/accessibility/browser_accessibility_cocoa.h
+++ b/content/browser/accessibility/browser_accessibility_cocoa.h
@@ -117,6 +117,14 @@ id AXTextMarkerRangeFrom(id anchor_textmarker, id focus_textmarker);
- (bool)findRowIndex:(BrowserAccessibilityCocoa*)toFind
withCurrentIndex:(int*)currentIndex;
+// Choose the appropriate accessibility object to receive an action depending
+// on the characteristics of this accessibility node.
+- (content::BrowserAccessibility*)actionTarget;
+
+// Return the active descendant for this accessibility object or null if there
+// is no active descendant defined or in the case of an error.
+- (content::BrowserAccessibility*)activeDescendant;
+
// Internally-used property.
@property(nonatomic, readonly) NSPoint origin;
diff --git a/content/browser/accessibility/browser_accessibility_cocoa.mm b/content/browser/accessibility/browser_accessibility_cocoa.mm
index 17aa494d6473866721a8cc5f4c5c646af9307d93..71f927cd35a27dd5f656907dc177fbfe7577d3f0 100644
--- a/content/browser/accessibility/browser_accessibility_cocoa.mm
+++ b/content/browser/accessibility/browser_accessibility_cocoa.mm
@@ -1744,14 +1744,7 @@ - (id)owns {
// supported with VoiceOver.
//
- int activeDescendantId;
- if (!_owner->GetIntAttribute(ax::mojom::IntAttribute::kActivedescendantId,
- &activeDescendantId))
- return nil;
-
- BrowserAccessibilityManager* manager = _owner->manager();
- BrowserAccessibility* activeDescendant =
- manager->GetFromID(activeDescendantId);
+ BrowserAccessibility* activeDescendant = [self activeDescendant];
if (!activeDescendant)
return nil;
@@ -3729,16 +3722,18 @@ - (void)accessibilityPerformAction:(NSString*)action {
return;
// TODO(dmazzoni): Support more actions.
- BrowserAccessibilityManager* manager = _owner->manager();
+ BrowserAccessibility* actionTarget = [self actionTarget];
+ BrowserAccessibilityManager* manager = actionTarget->manager();
if ([action isEqualToString:NSAccessibilityPressAction]) {
- manager->DoDefaultAction(*_owner);
- if (_owner->GetData().GetRestriction() != ax::mojom::Restriction::kNone ||
+ manager->DoDefaultAction(*actionTarget);
+ if (actionTarget->GetData().GetRestriction() !=
+ ax::mojom::Restriction::kNone ||
![self isCheckable])
return;
// Hack: preemptively set the checked state to what it should become,
// otherwise VoiceOver will very likely report the old, incorrect state to
// the user as it requests the value too quickly.
- ui::AXNode* node = _owner->node();
+ ui::AXNode* node = actionTarget->node();
if (!node)
return;
AXNodeData data(node->TakeData()); // Temporarily take data.
@@ -3756,13 +3751,13 @@ - (void)accessibilityPerformAction:(NSString*)action {
}
node->SetData(data); // Set the data back in the node.
} else if ([action isEqualToString:NSAccessibilityShowMenuAction]) {
- manager->ShowContextMenu(*_owner);
+ manager->ShowContextMenu(*actionTarget);
} else if ([action isEqualToString:NSAccessibilityScrollToVisibleAction]) {
- manager->ScrollToMakeVisible(*_owner, gfx::Rect());
+ manager->ScrollToMakeVisible(*actionTarget, gfx::Rect());
} else if ([action isEqualToString:NSAccessibilityIncrementAction]) {
- manager->Increment(*_owner);
+ manager->Increment(*actionTarget);
} else if ([action isEqualToString:NSAccessibilityDecrementAction]) {
- manager->Decrement(*_owner);
+ manager->Decrement(*actionTarget);
}
}
@@ -3871,4 +3866,32 @@ - (BOOL)accessibilityNotifiesWhenDestroyed {
return YES;
}
+// Choose the appropriate accessibility object to receive an action depending
+// on the characteristics of this accessibility node.
+- (BrowserAccessibility*)actionTarget {
+ // When an action is triggered on a container with selectable children and
+ // one of those children is an active descendant or focused, retarget the
+ // action to that child. See https://crbug.com/1114892.
+ if (!ui::IsContainerWithSelectableChildren(_owner->node()->data().role))
+ return _owner;
+
+ if (BrowserAccessibility* activeDescendant = [self activeDescendant])
+ return activeDescendant;
+
+ BrowserAccessibility* focused = _owner->manager()->GetFocus();
+ if (focused && focused->IsDescendantOf(_owner))
+ return focused;
+
+ return _owner;
+}
+
+// Return the active descendant for this accessibility object or null if there
+// is no active descendant defined or in the case of an error.
+- (BrowserAccessibility*)activeDescendant {
+ int activeDescendantId;
+ if (!_owner->GetIntAttribute(ax::mojom::IntAttribute::kActivedescendantId,
+ &activeDescendantId))
+ return nullptr;
+ return _owner->manager()->GetFromID(activeDescendantId);
+}
@end
diff --git a/content/browser/accessibility/browser_accessibility_cocoa_browsertest.mm b/content/browser/accessibility/browser_accessibility_cocoa_browsertest.mm
index 17801b9774813df79e4b944cb0a73535eb4c07c2..6eb2c484ddc479d9cfa566df0b103782264d3af8 100644
--- a/content/browser/accessibility/browser_accessibility_cocoa_browsertest.mm
+++ b/content/browser/accessibility/browser_accessibility_cocoa_browsertest.mm
@@ -44,6 +44,35 @@
return web_contents->GetRootBrowserAccessibilityManager();
}
+ // Trigger a context menu for the provided element without showing it. Returns
+ // the coordinates where the context menu was invoked (calculated based on
+ // the provided element). These coordinates are relative to the RenderView
+ // origin.
+ gfx::Point TriggerContextMenuAndGetMenuLocation(
+ NSAccessibilityElement* element,
+ ContextMenuFilter* filter) {
+ // accessibilityPerformAction is deprecated, but it's still used internally
+ // by AppKit.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+ [element accessibilityPerformAction:NSAccessibilityShowMenuAction];
+ filter->Wait();
+
+ UntrustworthyContextMenuParams context_menu_params = filter->get_params();
+ return gfx::Point(context_menu_params.x, context_menu_params.y);
+#pragma clang diagnostic pop
+ }
+
+ void FocusAccessibilityElementAndWaitForFocusChange(
+ NSAccessibilityElement* element) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+ [element accessibilitySetValue:@(1)
+ forAttribute:NSAccessibilityFocusedAttribute];
+#pragma clang diagnostic pop
+ WaitForAccessibilityFocusChange();
+ }
+
private:
BrowserAccessibility* FindNodeInSubtree(BrowserAccessibility& node,
ax::mojom::Role role) {
@@ -466,4 +495,165 @@ GURL url(R"HTML(data:text/html,
EXPECT_NSEQ(@"AXRow", [row_nodes[1] role]);
EXPECT_NSEQ(@"row2", [row_nodes[1] descriptionForAccessibility]);
}
+
+IN_PROC_BROWSER_TEST_F(BrowserAccessibilityCocoaBrowserTest,
+ TestTreeContextMenuEvent) {
+ AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+ ui::kAXModeComplete,
+ ax::mojom::Event::kLoadComplete);
+
+ GURL url(R"HTML(data:text/html,
+ <div alt="tree" role="tree">
+ <div tabindex="1" role="treeitem">1</div>
+ <div tabindex="2" role="treeitem">2</div>
+ </div>)HTML");
+
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+ waiter.WaitForNotification();
+
+ BrowserAccessibility* tree = FindNode(ax::mojom::Role::kTree);
+ base::scoped_nsobject<BrowserAccessibilityCocoa> cocoa_tree(
+ [ToBrowserAccessibilityCocoa(tree) retain]);
+
+ NSArray* tree_children = [cocoa_tree children];
+ EXPECT_NSEQ(@"AXRow", [tree_children[0] role]);
+ EXPECT_NSEQ(@"AXRow", [tree_children[1] role]);
+
+ content::RenderProcessHost* render_process_host =
+ shell()->web_contents()->GetMainFrame()->GetProcess();
+ auto menu_filter = base::MakeRefCounted<ContextMenuFilter>(
+ ContextMenuFilter::ShowBehavior::kPreventShow);
+ render_process_host->AddFilter(menu_filter.get());
+
+ gfx::Point tree_point =
+ TriggerContextMenuAndGetMenuLocation(cocoa_tree, menu_filter.get());
+
+ menu_filter->Reset();
+ gfx::Point item_1_point =
+ TriggerContextMenuAndGetMenuLocation(tree_children[1], menu_filter.get());
+ ASSERT_NE(tree_point, item_1_point);
+
+ // Now focus the second child and trigger a context menu on the tree.
+ EXPECT_TRUE(
+ content::ExecuteScript(shell()->web_contents(),
+ "document.body.children[0].children[1].focus();"));
+ WaitForAccessibilityFocusChange();
+
+ // Triggering a context menu on the tree should now trigger the menu
+ // on the focused child.
+ menu_filter->Reset();
+ gfx::Point new_point =
+ TriggerContextMenuAndGetMenuLocation(cocoa_tree, menu_filter.get());
+ ASSERT_EQ(new_point, item_1_point);
+}
+
+IN_PROC_BROWSER_TEST_F(BrowserAccessibilityCocoaBrowserTest,
+ TestEventRetargetingFocus) {
+ AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+ ui::kAXModeComplete,
+ ax::mojom::Event::kLoadComplete);
+
+ GURL url(R"HTML(data:text/html,
+ <div role="tree">
+ <div tabindex="1" role="treeitem">1</div>
+ <div tabindex="2" role="treeitem">2</div>
+ </div>
+ <div role="treegrid">
+ <div tabindex="1" role="treeitem">1</div>
+ <div tabindex="2" role="treeitem">2</div>
+ </div>
+ <div role="tablist">
+ <div tabindex="1" role="tab">1</div>
+ <div tabindex="2" role="tab">2</div>
+ </div>
+ <div role="table">
+ <div tabindex="1" role="row">1</div>
+ <div tabindex="2" role="row">2</div>
+ </div>
+ <div role="banner">
+ <div tabindex="1" role="link">1</div>
+ <div tabindex="2" role="link">2</div>
+ </div>)HTML");
+
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+ waiter.WaitForNotification();
+
+ std::pair<ax::mojom::Role, bool> tests[] = {
+ std::make_pair(ax::mojom::Role::kTree, true),
+ std::make_pair(ax::mojom::Role::kTreeGrid, true),
+ std::make_pair(ax::mojom::Role::kTabList, true),
+ std::make_pair(ax::mojom::Role::kTable, false),
+ std::make_pair(ax::mojom::Role::kBanner, false),
+ };
+
+ for (auto& test : tests) {
+ base::scoped_nsobject<BrowserAccessibilityCocoa> parent(
+ [ToBrowserAccessibilityCocoa(FindNode(test.first)) retain]);
+ BrowserAccessibilityCocoa* child = [parent children][1];
+
+ EXPECT_NE(nullptr, parent.get());
+ EXPECT_EQ([child owner], [child actionTarget]);
+ EXPECT_EQ([parent owner], [parent actionTarget]);
+
+ FocusAccessibilityElementAndWaitForFocusChange(child);
+ ASSERT_EQ(test.second, [parent actionTarget] == [child owner]);
+ }
+}
+
+IN_PROC_BROWSER_TEST_F(BrowserAccessibilityCocoaBrowserTest,
+ TestEventRetargetingActiveDescendant) {
+ AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+ ui::kAXModeComplete,
+ ax::mojom::Event::kLoadComplete);
+
+ GURL url(R"HTML(data:text/html,
+ <div role="tree" aria-activedescendant="tree-child">
+ <div tabindex="1" role="treeitem">1</div>
+ <div id="tree-child" tabindex="2" role="treeitem">2</div>
+ </div>
+ <div role="treegrid" aria-activedescendant="treegrid-child">
+ <div tabindex="1" role="treeitem">1</div>
+ <div id="treegrid-child" tabindex="2" role="treeitem">2</div>
+ </div>
+ <div role="tablist" aria-activedescendant="tablist-child">
+ <div tabindex="1" role="tab">1</div>
+ <div id="tablist-child" tabindex="2" role="tab">2</div>
+ </div>
+ <div role="table" aria-activedescendant="table-child">
+ <div tabindex="1" role="row">1</div>
+ <div id="table-child" tabindex="2" role="row">2</div>
+ </div>
+ <div role="banner" aria-activedescendant="banner-child">
+ <div tabindex="1" role="link">1</div>
+ <div id="banner-child" tabindex="2" role="link">2</div>
+ </div>)HTML");
+
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+ waiter.WaitForNotification();
+
+ std::pair<ax::mojom::Role, bool> tests[] = {
+ std::make_pair(ax::mojom::Role::kTree, true),
+ std::make_pair(ax::mojom::Role::kTreeGrid, true),
+ std::make_pair(ax::mojom::Role::kTabList, true),
+ std::make_pair(ax::mojom::Role::kTable, false),
+ std::make_pair(ax::mojom::Role::kBanner, false),
+ };
+
+ for (auto& test : tests) {
+ base::scoped_nsobject<BrowserAccessibilityCocoa> parent(
+ [ToBrowserAccessibilityCocoa(FindNode(test.first)) retain]);
+ BrowserAccessibilityCocoa* first_child = [parent children][0];
+ BrowserAccessibilityCocoa* second_child = [parent children][1];
+
+ EXPECT_NE(nullptr, parent.get());
+ EXPECT_EQ([second_child owner], [second_child actionTarget]);
+ EXPECT_EQ(test.second, [second_child owner] == [parent actionTarget]);
+
+ // aria-activedescendant should take priority of focus for determining
+ // if an object is the action target.
+ FocusAccessibilityElementAndWaitForFocusChange(first_child);
+ EXPECT_EQ(test.second, [second_child owner] == [parent actionTarget]);
+ }
+}
+
} // namespace content
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc
index 47161f98b2fcdacece578cde50141860d2ab0a40..a8f988b8465c420224979d805baf454483e49134 100644
--- a/content/public/test/browser_test_utils.cc
+++ b/content/public/test/browser_test_utils.cc
@@ -3220,10 +3220,11 @@ void VerifyStaleContentOnFrameEviction(
#endif // defined(USE_AURA)
-ContextMenuFilter::ContextMenuFilter()
+ContextMenuFilter::ContextMenuFilter(ShowBehavior behavior)
: BrowserMessageFilter(FrameMsgStart),
run_loop_(std::make_unique<base::RunLoop>()),
- quit_closure_(run_loop_->QuitClosure()) {}
+ quit_closure_(run_loop_->QuitClosure()),
+ show_behavior_(behavior) {}
bool ContextMenuFilter::OnMessageReceived(const IPC::Message& message) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -3234,6 +3235,9 @@ bool ContextMenuFilter::OnMessageReceived(const IPC::Message& message) {
GetUIThreadTaskRunner({})->PostTask(
FROM_HERE,
base::BindOnce(&ContextMenuFilter::OnContextMenu, this, menu_params));
+ // Returning true here blocks the default action for this message, which
+ // means that the menu will not be shown.
+ return show_behavior_ == ShowBehavior::kPreventShow;
}
return false;
}
@@ -3244,6 +3248,12 @@ void ContextMenuFilter::Wait() {
run_loop_ = nullptr;
}
+void ContextMenuFilter::Reset() {
+ ASSERT_EQ(run_loop_, nullptr);
+ run_loop_ = std::make_unique<base::RunLoop>();
+ quit_closure_ = run_loop_->QuitClosure();
+}
+
ContextMenuFilter::~ContextMenuFilter() = default;
void ContextMenuFilter::OnContextMenu(
diff --git a/content/public/test/browser_test_utils.h b/content/public/test/browser_test_utils.h
index f68d423999ff711b46b7fe9d718163158e1d5223..3568bcceee9867db634306d36e3281d32450ea0a 100644
--- a/content/public/test/browser_test_utils.h
+++ b/content/public/test/browser_test_utils.h
@@ -1688,10 +1688,15 @@ void VerifyStaleContentOnFrameEviction(
// sent by the renderer.
class ContextMenuFilter : public content::BrowserMessageFilter {
public:
- ContextMenuFilter();
+ // Whether or not the ContextMenu should be prevented from performing
+ // its default action, preventing the context menu from showing.
+ enum ShowBehavior { kShow, kPreventShow };
+
+ explicit ContextMenuFilter(ShowBehavior behavior = ShowBehavior::kShow);
bool OnMessageReceived(const IPC::Message& message) override;
void Wait();
+ void Reset();
content::UntrustworthyContextMenuParams get_params() { return last_params_; }
@@ -1703,6 +1708,7 @@ class ContextMenuFilter : public content::BrowserMessageFilter {
std::unique_ptr<base::RunLoop> run_loop_;
base::OnceClosure quit_closure_;
content::UntrustworthyContextMenuParams last_params_;
+ const ShowBehavior show_behavior_;
DISALLOW_COPY_AND_ASSIGN(ContextMenuFilter);
};

View File

@@ -0,0 +1,723 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Robinson <mrobinson@igalia.com>
Date: Thu, 19 Nov 2020 21:28:45 +0000
Subject: Improve AXTextStateChangeType in
NSAccessibilitySelectedTextChangedNotification
When setting the AXTextStateChangeType key in the user info data
structure for the notification, use AXTextStateChangeTypeSelectionMove
when we detect a focus change. This causes VoiceOver to properly
announce the label and type of form entries when their contents are
selected due to focus changes.
type are now announced.
Bug: 1127421
Change-Id: I42d66ad60fbcba7c8c34396fdbc3f6e0c739d1a2
AX-Relnotes: When focus changes moves to form inputs, the input label and
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2512913
Commit-Queue: Martin Robinson <mrobinson@igalia.com>
Reviewed-by: Nektarios Paisios <nektar@chromium.org>
Cr-Commit-Position: refs/heads/master@{#829380}
diff --git a/content/browser/accessibility/accessibility_event_recorder_mac.mm b/content/browser/accessibility/accessibility_event_recorder_mac.mm
index fcb93bab1c94f792dc9868e895a0e562d1fd8449..1e415ee8f849b67c098e49572c9d4e890ed44d04 100644
--- a/content/browser/accessibility/accessibility_event_recorder_mac.mm
+++ b/content/browser/accessibility/accessibility_event_recorder_mac.mm
@@ -6,6 +6,7 @@
#import <Cocoa/Cocoa.h>
+#include <algorithm>
#include <string>
#include "base/logging.h"
@@ -15,6 +16,7 @@
#include "base/strings/sys_string_conversions.h"
#include "content/browser/accessibility/accessibility_tools_utils_mac.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
+#include "ui/accessibility/platform/ax_private_webkit_constants_mac.h"
namespace content {
@@ -28,7 +30,11 @@
~AccessibilityEventRecorderMac() override;
// Callback executed every time we receive an event notification.
- void EventReceived(AXUIElementRef element, CFStringRef notification);
+ void EventReceived(AXUIElementRef element,
+ CFStringRef notification,
+ CFDictionaryRef user_info);
+ static std::string SerializeTextSelectionChangedProperties(
+ CFDictionaryRef user_info);
private:
// Add one notification to the list of notifications monitored by our
@@ -54,10 +60,11 @@
static void EventReceivedThunk(AXObserverRef observer_ref,
AXUIElementRef element,
CFStringRef notification,
+ CFDictionaryRef user_info,
void* refcon) {
AccessibilityEventRecorderMac* this_ptr =
static_cast<AccessibilityEventRecorderMac*>(refcon);
- this_ptr->EventReceived(element, notification);
+ this_ptr->EventReceived(element, notification, user_info);
}
// static
@@ -95,8 +102,9 @@ static void EventReceivedThunk(AXObserverRef observer_ref,
base::ProcessId pid,
AXUIElementRef node)
: AccessibilityEventRecorder(manager), observer_run_loop_source_(NULL) {
- if (kAXErrorSuccess != AXObserverCreate(pid, EventReceivedThunk,
- observer_ref_.InitializeInto())) {
+ if (kAXErrorSuccess !=
+ AXObserverCreateWithInfoCallback(pid, EventReceivedThunk,
+ observer_ref_.InitializeInto())) {
LOG(FATAL) << "Failed to create AXObserverRef";
}
@@ -157,7 +165,8 @@ static void EventReceivedThunk(AXObserverRef observer_ref,
}
void AccessibilityEventRecorderMac::EventReceived(AXUIElementRef element,
- CFStringRef notification) {
+ CFStringRef notification,
+ CFDictionaryRef user_info) {
std::string notification_str = base::SysCFStringRefToUTF8(notification);
std::string role = GetAXAttributeValue(element, NSAccessibilityRoleAttribute);
if (role.empty())
@@ -180,7 +189,49 @@ static void EventReceivedThunk(AXObserverRef observer_ref,
if (!value.empty())
log += base::StringPrintf(" AXValue=\"%s\"", value.c_str());
+ if (notification_str ==
+ base::SysNSStringToUTF8(NSAccessibilitySelectedTextChangedNotification))
+ log += " " + SerializeTextSelectionChangedProperties(user_info);
+
OnEvent(log);
}
+std::string
+AccessibilityEventRecorderMac::SerializeTextSelectionChangedProperties(
+ CFDictionaryRef user_info) {
+ std::vector<std::string> serialized_info;
+ CFDictionaryApplyFunction(
+ user_info,
+ [](const void* raw_key, const void* raw_value, void* context) {
+ auto* key = static_cast<NSString*>(raw_key);
+ auto* value = static_cast<NSObject*>(raw_value);
+ auto* serialized_info = static_cast<std::vector<std::string>*>(context);
+ std::string value_string;
+ if ([key isEqual:ui::NSAccessibilityTextStateChangeTypeKey]) {
+ value_string = ToString(static_cast<ui::AXTextStateChangeType>(
+ [static_cast<NSNumber*>(value) intValue]));
+ } else if ([key isEqual:ui::NSAccessibilityTextSelectionDirection]) {
+ value_string = ToString(static_cast<ui::AXTextSelectionDirection>(
+ [static_cast<NSNumber*>(value) intValue]));
+ } else if ([key isEqual:ui::NSAccessibilityTextSelectionGranularity]) {
+ value_string = ToString(static_cast<ui::AXTextSelectionGranularity>(
+ [static_cast<NSNumber*>(value) intValue]));
+ } else if ([key isEqual:ui::NSAccessibilityTextEditType]) {
+ value_string = ToString(static_cast<ui::AXTextEditType>(
+ [static_cast<NSNumber*>(value) intValue]));
+ } else {
+ return;
+ }
+ serialized_info->push_back(base::SysNSStringToUTF8(key) + "=" +
+ value_string);
+ },
+ &serialized_info);
+
+ // Always sort the info so that we don't depend on CFDictionary for
+ // consistent output ordering.
+ std::sort(serialized_info.begin(), serialized_info.end());
+
+ return base::JoinString(serialized_info, " ");
+}
+
} // namespace content
diff --git a/content/browser/accessibility/browser_accessibility_manager_mac.h b/content/browser/accessibility/browser_accessibility_manager_mac.h
index b4043f56341e72bcf75ef71c56cb8cf9fc442579..925bfe1ea191ab846805fdbff1b0314e779b1c9e 100644
--- a/content/browser/accessibility/browser_accessibility_manager_mac.h
+++ b/content/browser/accessibility/browser_accessibility_manager_mac.h
@@ -54,7 +54,8 @@ class CONTENT_EXPORT BrowserAccessibilityManagerMac
const std::vector<Change>& changes) override;
// Returns an autoreleased object.
- NSDictionary* GetUserInfoForSelectedTextChangedNotification();
+ NSDictionary* GetUserInfoForSelectedTextChangedNotification(
+ bool focus_changed);
// Returns an autoreleased object.
NSDictionary* GetUserInfoForValueChangedNotification(
diff --git a/content/browser/accessibility/browser_accessibility_manager_mac.mm b/content/browser/accessibility/browser_accessibility_manager_mac.mm
index 68b8ccd88fb4ad6e4793a54869d5424f2a860d8a..4232959e30ab758bff58aa8e4457b6cdd3c7745b 100644
--- a/content/browser/accessibility/browser_accessibility_manager_mac.mm
+++ b/content/browser/accessibility/browser_accessibility_manager_mac.mm
@@ -19,91 +19,13 @@
#include "content/public/browser/web_contents.h"
#include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
#include "ui/accessibility/ax_role_properties.h"
+#include "ui/accessibility/platform/ax_private_webkit_constants_mac.h"
namespace {
// Use same value as in Safari's WebKit.
const int kLiveRegionChangeIntervalMS = 20;
-// Declare undocumented accessibility constants and enums only present in
-// WebKit.
-
-enum AXTextStateChangeType {
- AXTextStateChangeTypeUnknown,
- AXTextStateChangeTypeEdit,
- AXTextStateChangeTypeSelectionMove,
- AXTextStateChangeTypeSelectionExtend
-};
-
-enum AXTextSelectionDirection {
- AXTextSelectionDirectionUnknown,
- AXTextSelectionDirectionBeginning,
- AXTextSelectionDirectionEnd,
- AXTextSelectionDirectionPrevious,
- AXTextSelectionDirectionNext,
- AXTextSelectionDirectionDiscontiguous
-};
-
-enum AXTextSelectionGranularity {
- AXTextSelectionGranularityUnknown,
- AXTextSelectionGranularityCharacter,
- AXTextSelectionGranularityWord,
- AXTextSelectionGranularityLine,
- AXTextSelectionGranularitySentence,
- AXTextSelectionGranularityParagraph,
- AXTextSelectionGranularityPage,
- AXTextSelectionGranularityDocument,
- AXTextSelectionGranularityAll
-};
-
-enum AXTextEditType {
- AXTextEditTypeUnknown,
- AXTextEditTypeDelete,
- AXTextEditTypeInsert,
- AXTextEditTypeTyping,
- AXTextEditTypeDictation,
- AXTextEditTypeCut,
- AXTextEditTypePaste,
- AXTextEditTypeAttributesChange
-};
-
-// Native mac notifications fired.
-NSString* const NSAccessibilityAutocorrectionOccurredNotification =
- @"AXAutocorrectionOccurred";
-NSString* const NSAccessibilityLoadCompleteNotification = @"AXLoadComplete";
-NSString* const NSAccessibilityInvalidStatusChangedNotification =
- @"AXInvalidStatusChanged";
-NSString* const NSAccessibilityLiveRegionCreatedNotification =
- @"AXLiveRegionCreated";
-NSString* const NSAccessibilityLiveRegionChangedNotification =
- @"AXLiveRegionChanged";
-NSString* const NSAccessibilityExpandedChanged = @"AXExpandedChanged";
-NSString* const NSAccessibilityMenuItemSelectedNotification =
- @"AXMenuItemSelected";
-
-// The following native mac notifications are not fired:
-// AXLayoutComplete: Voiceover does not use this, it is considered too spammy.
-
-// Attributes used for NSAccessibilitySelectedTextChangedNotification and
-// NSAccessibilityValueChangedNotification.
-NSString* const NSAccessibilityTextStateChangeTypeKey =
- @"AXTextStateChangeType";
-NSString* const NSAccessibilityTextStateSyncKey = @"AXTextStateSync";
-NSString* const NSAccessibilityTextSelectionDirection =
- @"AXTextSelectionDirection";
-NSString* const NSAccessibilityTextSelectionGranularity =
- @"AXTextSelectionGranularity";
-NSString* const NSAccessibilityTextSelectionChangedFocus =
- @"AXTextSelectionChangedFocus";
-NSString* const NSAccessibilityTextChangeElement = @"AXTextChangeElement";
-NSString* const NSAccessibilityTextEditType = @"AXTextEditType";
-NSString* const NSAccessibilityTextChangeValue = @"AXTextChangeValue";
-NSString* const NSAccessibilityChangeValueStartMarker =
- @"AXTextChangeValueStartMarker";
-NSString* const NSAccessibilityTextChangeValueLength =
- @"AXTextChangeValueLength";
-NSString* const NSAccessibilityTextChangeValues = @"AXTextChangeValues";
-
} // namespace
namespace content {
@@ -164,7 +86,7 @@
NSString* mac_notification = nullptr;
switch (event_type) {
case ax::mojom::Event::kAutocorrectionOccured:
- mac_notification = NSAccessibilityAutocorrectionOccurredNotification;
+ mac_notification = ui::NSAccessibilityAutocorrectionOccurredNotification;
break;
default:
return;
@@ -203,6 +125,8 @@ void PostAnnouncementNotification(NSString* announcement) {
auto native_node = ToBrowserAccessibilityCocoa(node);
DCHECK(native_node);
+ bool focus_changed = GetFocus() != GetLastFocusedNode();
+
// Refer to |AXObjectCache::postPlatformNotification| in WebKit source code.
NSString* mac_notification = nullptr;
switch (event_type) {
@@ -232,7 +156,7 @@ void PostAnnouncementNotification(NSString* announcement) {
// |NSAccessibilityLoadCompleteNotification| should only be fired on the
// top document and when the document is not Chrome's new tab page.
if (IsRootTree() && !IsChromeNewTabPage()) {
- mac_notification = NSAccessibilityLoadCompleteNotification;
+ mac_notification = ui::NSAccessibilityLoadCompleteNotification;
} else {
// Voiceover moves focus to the web content when it receives an
// AXLoadComplete event. On Chrome's new tab page, focus should stay
@@ -242,7 +166,7 @@ void PostAnnouncementNotification(NSString* announcement) {
}
break;
case ui::AXEventGenerator::Event::INVALID_STATUS_CHANGED:
- mac_notification = NSAccessibilityInvalidStatusChangedNotification;
+ mac_notification = ui::NSAccessibilityInvalidStatusChangedNotification;
break;
case ui::AXEventGenerator::Event::SELECTED_CHILDREN_CHANGED:
if (ui::IsTableLike(node->GetRole())) {
@@ -289,7 +213,7 @@ void PostAnnouncementNotification(NSString* announcement) {
// API has been present on versions of OS X since 10.7 but doesn't
// appear to be needed by Voiceover before version 10.11.
NSDictionary* user_info =
- GetUserInfoForSelectedTextChangedNotification();
+ GetUserInfoForSelectedTextChangedNotification(focus_changed);
BrowserAccessibilityManager* root_manager = GetRootManager();
if (!root_manager)
@@ -342,11 +266,11 @@ void PostAnnouncementNotification(NSString* announcement) {
}
break;
case ui::AXEventGenerator::Event::LIVE_REGION_CREATED:
- mac_notification = NSAccessibilityLiveRegionCreatedNotification;
+ mac_notification = ui::NSAccessibilityLiveRegionCreatedNotification;
break;
case ui::AXEventGenerator::Event::ALERT:
NSAccessibilityPostNotification(
- native_node, NSAccessibilityLiveRegionCreatedNotification);
+ native_node, ui::NSAccessibilityLiveRegionCreatedNotification);
// Voiceover requires a live region changed notification to actually
// announce the live region.
FireGeneratedEvent(ui::AXEventGenerator::Event::LIVE_REGION_CHANGED,
@@ -359,7 +283,7 @@ void PostAnnouncementNotification(NSString* announcement) {
if (never_suppress_or_delay_events_for_testing_) {
NSAccessibilityPostNotification(
- native_node, NSAccessibilityLiveRegionChangedNotification);
+ native_node, ui::NSAccessibilityLiveRegionChangedNotification);
return;
}
@@ -383,7 +307,7 @@ void PostAnnouncementNotification(NSString* announcement) {
[](base::scoped_nsobject<BrowserAccessibilityCocoa> node) {
if (node && [node instanceActive]) {
NSAccessibilityPostNotification(
- node, NSAccessibilityLiveRegionChangedNotification);
+ node, ui::NSAccessibilityLiveRegionChangedNotification);
}
},
std::move(retained_node)),
@@ -398,7 +322,7 @@ void PostAnnouncementNotification(NSString* announcement) {
node->GetRole() == ax::mojom::Role::kTreeItem) {
mac_notification = NSAccessibilityRowExpandedNotification;
} else {
- mac_notification = NSAccessibilityExpandedChanged;
+ mac_notification = ui::NSAccessibilityExpandedChanged;
}
break;
case ui::AXEventGenerator::Event::COLLAPSED:
@@ -406,11 +330,11 @@ void PostAnnouncementNotification(NSString* announcement) {
node->GetRole() == ax::mojom::Role::kTreeItem) {
mac_notification = NSAccessibilityRowCollapsedNotification;
} else {
- mac_notification = NSAccessibilityExpandedChanged;
+ mac_notification = ui::NSAccessibilityExpandedChanged;
}
break;
case ui::AXEventGenerator::Event::MENU_ITEM_SELECTED:
- mac_notification = NSAccessibilityMenuItemSelectedNotification;
+ mac_notification = ui::NSAccessibilityMenuItemSelectedNotification;
break;
case ui::AXEventGenerator::Event::ACCESS_KEY_CHANGED:
case ui::AXEventGenerator::Event::ATK_TEXT_OBJECT_ATTRIBUTE_CHANGED:
@@ -514,18 +438,32 @@ void PostAnnouncementNotification(NSString* announcement) {
}
}
-NSDictionary* BrowserAccessibilityManagerMac::
- GetUserInfoForSelectedTextChangedNotification() {
+NSDictionary*
+BrowserAccessibilityManagerMac::GetUserInfoForSelectedTextChangedNotification(
+ bool focus_changed) {
NSMutableDictionary* user_info =
[[[NSMutableDictionary alloc] init] autorelease];
- [user_info setObject:@YES forKey:NSAccessibilityTextStateSyncKey];
- [user_info setObject:@(AXTextStateChangeTypeUnknown)
- forKey:NSAccessibilityTextStateChangeTypeKey];
- [user_info setObject:@(AXTextSelectionDirectionUnknown)
- forKey:NSAccessibilityTextSelectionDirection];
- [user_info setObject:@(AXTextSelectionGranularityUnknown)
- forKey:NSAccessibilityTextSelectionGranularity];
- [user_info setObject:@YES forKey:NSAccessibilityTextSelectionChangedFocus];
+ [user_info setObject:@YES forKey:ui::NSAccessibilityTextStateSyncKey];
+ [user_info setObject:@(ui::AXTextSelectionDirectionUnknown)
+ forKey:ui::NSAccessibilityTextSelectionDirection];
+ [user_info setObject:@(ui::AXTextSelectionGranularityUnknown)
+ forKey:ui::NSAccessibilityTextSelectionGranularity];
+ [user_info setObject:@YES
+ forKey:ui::NSAccessibilityTextSelectionChangedFocus];
+
+ // Try to detect when the text selection changes due to a focus change.
+ // This is necessary so that VoiceOver also anounces information about the
+ // element that contains this selection.
+ // TODO(mrobinson): Determine definitively what the type of this text
+ // selection change is. This requires passing this information here from
+ // blink.
+ if (focus_changed) {
+ [user_info setObject:@(ui::AXTextStateChangeTypeSelectionMove)
+ forKey:ui::NSAccessibilityTextStateChangeTypeKey];
+ } else {
+ [user_info setObject:@(ui::AXTextStateChangeTypeUnknown)
+ forKey:ui::NSAccessibilityTextStateChangeTypeKey];
+ }
int32_t focus_id = ax_tree()->GetUnignoredSelection().focus_object_id;
BrowserAccessibility* focus_object = GetFromID(focus_id);
@@ -534,7 +472,7 @@ void PostAnnouncementNotification(NSString* announcement) {
auto native_focus_object = ToBrowserAccessibilityCocoa(focus_object);
if (native_focus_object && [native_focus_object instanceActive]) {
[user_info setObject:native_focus_object
- forKey:NSAccessibilityTextChangeElement];
+ forKey:ui::NSAccessibilityTextChangeElement];
#ifndef MAS_BUILD
id selected_text = [native_focus_object selectedTextMarkerRange];
@@ -565,38 +503,39 @@ void PostAnnouncementNotification(NSString* announcement) {
if (!deleted_text.empty()) {
NSMutableDictionary* change =
[NSMutableDictionary dictionaryWithDictionary:@{
- NSAccessibilityTextEditType : @(AXTextEditTypeDelete),
- NSAccessibilityTextChangeValueLength : @(deleted_text.length()),
- NSAccessibilityTextChangeValue :
+ ui::NSAccessibilityTextEditType : @(ui::AXTextEditTypeDelete),
+ ui::NSAccessibilityTextChangeValueLength : @(deleted_text.length()),
+ ui::NSAccessibilityTextChangeValue :
base::SysUTF16ToNSString(deleted_text)
}];
if (edit_text_marker) {
- change[NSAccessibilityChangeValueStartMarker] = edit_text_marker;
+ change[ui::NSAccessibilityChangeValueStartMarker] = edit_text_marker;
}
[changes addObject:change];
}
if (!inserted_text.empty()) {
// TODO(nektar): Figure out if this is a paste, insertion or typing.
// Changes to Blink would be required. A heuristic is currently used.
- auto edit_type = inserted_text.length() > 1 ? @(AXTextEditTypeInsert)
- : @(AXTextEditTypeTyping);
+ auto edit_type = inserted_text.length() > 1 ? @(ui::AXTextEditTypeInsert)
+ : @(ui::AXTextEditTypeTyping);
NSMutableDictionary* change =
[NSMutableDictionary dictionaryWithDictionary:@{
- NSAccessibilityTextEditType : edit_type,
- NSAccessibilityTextChangeValueLength : @(inserted_text.length()),
- NSAccessibilityTextChangeValue :
+ ui::NSAccessibilityTextEditType : edit_type,
+ ui::NSAccessibilityTextChangeValueLength : @(inserted_text.length()),
+ ui::NSAccessibilityTextChangeValue :
base::SysUTF16ToNSString(inserted_text)
}];
if (edit_text_marker) {
- change[NSAccessibilityChangeValueStartMarker] = edit_text_marker;
+ change[ui::NSAccessibilityChangeValueStartMarker] = edit_text_marker;
}
[changes addObject:change];
}
return @{
- NSAccessibilityTextStateChangeTypeKey : @(AXTextStateChangeTypeEdit),
- NSAccessibilityTextChangeValues : changes,
- NSAccessibilityTextChangeElement : native_node
+ ui::
+ NSAccessibilityTextStateChangeTypeKey : @(ui::AXTextStateChangeTypeEdit),
+ ui::NSAccessibilityTextChangeValues : changes,
+ ui::NSAccessibilityTextChangeElement : native_node
};
}
diff --git a/content/test/data/accessibility/event/aria-combo-box-focus-expected-mac.txt b/content/test/data/accessibility/event/aria-combo-box-focus-expected-mac.txt
index ad5e2bf2c8029185c51eecc94cac1dbe7608c99e..67e07a89f77f7c61a57eb51cecea211df5227341 100644
--- a/content/test/data/accessibility/event/aria-combo-box-focus-expected-mac.txt
+++ b/content/test/data/accessibility/event/aria-combo-box-focus-expected-mac.txt
@@ -1,3 +1,3 @@
AXFocusedUIElementChanged on AXStaticText AXValue="Apple not selected"
-AXSelectedTextChanged on AXStaticText AXValue="Apple not selected"
-AXSelectedTextChanged on AXWebArea
\ No newline at end of file
+AXSelectedTextChanged on AXStaticText AXValue="Apple not selected" AXTextSelectionDirection=AXTextSelectionDirectionUnknown AXTextSelectionGranularity=AXTextSelectionGranularityUnknown AXTextStateChangeType=AXTextStateChangeTypeSelectionMove
+AXSelectedTextChanged on AXWebArea AXTextSelectionDirection=AXTextSelectionDirectionUnknown AXTextSelectionGranularity=AXTextSelectionGranularityUnknown AXTextStateChangeType=AXTextStateChangeTypeSelectionMove
diff --git a/content/test/data/accessibility/event/caret-browsing-disabled-expected-mac.txt b/content/test/data/accessibility/event/caret-browsing-disabled-expected-mac.txt
index ec0b74d984ade9928705242f9b0682a743e20fb2..87447c5a4b14efde5b64b1d340a3fa2fb6574b80 100644
--- a/content/test/data/accessibility/event/caret-browsing-disabled-expected-mac.txt
+++ b/content/test/data/accessibility/event/caret-browsing-disabled-expected-mac.txt
@@ -1,5 +1,5 @@
-AXSelectedTextChanged on AXWebArea
-AXSelectedTextChanged on AXWebArea
+AXSelectedTextChanged on AXWebArea AXTextSelectionDirection=AXTextSelectionDirectionUnknown AXTextSelectionGranularity=AXTextSelectionGranularityUnknown AXTextStateChangeType=AXTextStateChangeTypeUnknown
+AXSelectedTextChanged on AXWebArea AXTextSelectionDirection=AXTextSelectionDirectionUnknown AXTextSelectionGranularity=AXTextSelectionGranularityUnknown AXTextStateChangeType=AXTextStateChangeTypeUnknown
=== Start Continuation ===
-AXSelectedTextChanged on AXWebArea
-AXSelectedTextChanged on AXWebArea
+AXSelectedTextChanged on AXWebArea AXTextSelectionDirection=AXTextSelectionDirectionUnknown AXTextSelectionGranularity=AXTextSelectionGranularityUnknown AXTextStateChangeType=AXTextStateChangeTypeUnknown
+AXSelectedTextChanged on AXWebArea AXTextSelectionDirection=AXTextSelectionDirectionUnknown AXTextSelectionGranularity=AXTextSelectionGranularityUnknown AXTextStateChangeType=AXTextStateChangeTypeUnknown
diff --git a/content/test/data/accessibility/event/caret-browsing-enabled-expected-mac.txt b/content/test/data/accessibility/event/caret-browsing-enabled-expected-mac.txt
index ec0b74d984ade9928705242f9b0682a743e20fb2..87447c5a4b14efde5b64b1d340a3fa2fb6574b80 100644
--- a/content/test/data/accessibility/event/caret-browsing-enabled-expected-mac.txt
+++ b/content/test/data/accessibility/event/caret-browsing-enabled-expected-mac.txt
@@ -1,5 +1,5 @@
-AXSelectedTextChanged on AXWebArea
-AXSelectedTextChanged on AXWebArea
+AXSelectedTextChanged on AXWebArea AXTextSelectionDirection=AXTextSelectionDirectionUnknown AXTextSelectionGranularity=AXTextSelectionGranularityUnknown AXTextStateChangeType=AXTextStateChangeTypeUnknown
+AXSelectedTextChanged on AXWebArea AXTextSelectionDirection=AXTextSelectionDirectionUnknown AXTextSelectionGranularity=AXTextSelectionGranularityUnknown AXTextStateChangeType=AXTextStateChangeTypeUnknown
=== Start Continuation ===
-AXSelectedTextChanged on AXWebArea
-AXSelectedTextChanged on AXWebArea
+AXSelectedTextChanged on AXWebArea AXTextSelectionDirection=AXTextSelectionDirectionUnknown AXTextSelectionGranularity=AXTextSelectionGranularityUnknown AXTextStateChangeType=AXTextStateChangeTypeUnknown
+AXSelectedTextChanged on AXWebArea AXTextSelectionDirection=AXTextSelectionDirectionUnknown AXTextSelectionGranularity=AXTextSelectionGranularityUnknown AXTextStateChangeType=AXTextStateChangeTypeUnknown
diff --git a/content/test/data/accessibility/event/text-selection-changed-expected-mac.txt b/content/test/data/accessibility/event/text-selection-changed-expected-mac.txt
new file mode 100644
index 0000000000000000000000000000000000000000..9213c873393d595bba8796cdb0e2325d3ee37ee9
--- /dev/null
+++ b/content/test/data/accessibility/event/text-selection-changed-expected-mac.txt
@@ -0,0 +1,10 @@
+AXSelectedTextChanged on AXWebArea AXTextSelectionDirection=AXTextSelectionDirectionUnknown AXTextSelectionGranularity=AXTextSelectionGranularityUnknown AXTextStateChangeType=AXTextStateChangeTypeUnknown
+AXSelectedTextChanged on AXWebArea AXTextSelectionDirection=AXTextSelectionDirectionUnknown AXTextSelectionGranularity=AXTextSelectionGranularityUnknown AXTextStateChangeType=AXTextStateChangeTypeUnknown
+=== Start Continuation ===
+AXFocusedUIElementChanged on AXTextField AXDescription="input" AXValue="input"
+AXSelectedTextChanged on AXTextField AXDescription="input" AXValue="input" AXTextSelectionDirection=AXTextSelectionDirectionUnknown AXTextSelectionGranularity=AXTextSelectionGranularityUnknown AXTextStateChangeType=AXTextStateChangeTypeSelectionMove
+AXSelectedTextChanged on AXWebArea AXTextSelectionDirection=AXTextSelectionDirectionUnknown AXTextSelectionGranularity=AXTextSelectionGranularityUnknown AXTextStateChangeType=AXTextStateChangeTypeSelectionMove
+=== Start Continuation ===
+AXFocusedUIElementChanged on AXTextArea AXDescription="textarea"
+AXSelectedTextChanged on AXTextArea AXDescription="textarea" AXTextSelectionDirection=AXTextSelectionDirectionUnknown AXTextSelectionGranularity=AXTextSelectionGranularityUnknown AXTextStateChangeType=AXTextStateChangeTypeSelectionMove
+AXSelectedTextChanged on AXWebArea AXTextSelectionDirection=AXTextSelectionDirectionUnknown AXTextSelectionGranularity=AXTextSelectionGranularityUnknown AXTextStateChangeType=AXTextStateChangeTypeSelectionMove
diff --git a/ui/accessibility/platform/BUILD.gn b/ui/accessibility/platform/BUILD.gn
index 2f015b939bb6835f2ff817ce6c960157eaf32342..eafddade0f7fa8ab8d008bf4888fc9ecef85463d 100644
--- a/ui/accessibility/platform/BUILD.gn
+++ b/ui/accessibility/platform/BUILD.gn
@@ -110,6 +110,8 @@ source_set("platform") {
"ax_event_intent_mac.mm",
"ax_platform_node_mac.h",
"ax_platform_node_mac.mm",
+ "ax_private_webkit_constants_mac.h",
+ "ax_private_webkit_constants_mac.mm",
]
frameworks = [
diff --git a/ui/accessibility/platform/ax_private_webkit_constants_mac.h b/ui/accessibility/platform/ax_private_webkit_constants_mac.h
new file mode 100644
index 0000000000000000000000000000000000000000..5f1776a3aeac89b70d6d852b8e5209a1208271ae
--- /dev/null
+++ b/ui/accessibility/platform/ax_private_webkit_constants_mac.h
@@ -0,0 +1,96 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_ACCESSIBILITY_PLATFORM_AX_PRIVATE_WEBKIT_CONSTANTS_MAC_H_
+#define UI_ACCESSIBILITY_PLATFORM_AX_PRIVATE_WEBKIT_CONSTANTS_MAC_H_
+
+#import <Cocoa/Cocoa.h>
+#include "ui/accessibility/ax_export.h"
+
+namespace ui {
+
+enum AXTextStateChangeType {
+ AXTextStateChangeTypeUnknown,
+ AXTextStateChangeTypeEdit,
+ AXTextStateChangeTypeSelectionMove,
+ AXTextStateChangeTypeSelectionExtend
+};
+
+enum AXTextSelectionDirection {
+ AXTextSelectionDirectionUnknown,
+ AXTextSelectionDirectionBeginning,
+ AXTextSelectionDirectionEnd,
+ AXTextSelectionDirectionPrevious,
+ AXTextSelectionDirectionNext,
+ AXTextSelectionDirectionDiscontiguous
+};
+
+enum AXTextSelectionGranularity {
+ AXTextSelectionGranularityUnknown,
+ AXTextSelectionGranularityCharacter,
+ AXTextSelectionGranularityWord,
+ AXTextSelectionGranularityLine,
+ AXTextSelectionGranularitySentence,
+ AXTextSelectionGranularityParagraph,
+ AXTextSelectionGranularityPage,
+ AXTextSelectionGranularityDocument,
+ AXTextSelectionGranularityAll
+};
+
+enum AXTextEditType {
+ AXTextEditTypeUnknown,
+ AXTextEditTypeDelete,
+ AXTextEditTypeInsert,
+ AXTextEditTypeTyping,
+ AXTextEditTypeDictation,
+ AXTextEditTypeCut,
+ AXTextEditTypePaste,
+ AXTextEditTypeAttributesChange
+};
+
+// Native mac notifications fired.
+NSString* const NSAccessibilityAutocorrectionOccurredNotification =
+ @"AXAutocorrectionOccurred";
+NSString* const NSAccessibilityLoadCompleteNotification = @"AXLoadComplete";
+NSString* const NSAccessibilityInvalidStatusChangedNotification =
+ @"AXInvalidStatusChanged";
+NSString* const NSAccessibilityLiveRegionCreatedNotification =
+ @"AXLiveRegionCreated";
+NSString* const NSAccessibilityLiveRegionChangedNotification =
+ @"AXLiveRegionChanged";
+NSString* const NSAccessibilityExpandedChanged = @"AXExpandedChanged";
+NSString* const NSAccessibilityMenuItemSelectedNotification =
+ @"AXMenuItemSelected";
+
+// The following native mac notifications are not fired:
+// AXLayoutComplete: Voiceover does not use this, it is considered too spammy.
+
+// Attributes used for NSAccessibilitySelectedTextChangedNotification and
+// NSAccessibilityValueChangedNotification.
+NSString* const NSAccessibilityTextStateChangeTypeKey =
+ @"AXTextStateChangeType";
+NSString* const NSAccessibilityTextStateSyncKey = @"AXTextStateSync";
+NSString* const NSAccessibilityTextSelectionDirection =
+ @"AXTextSelectionDirection";
+NSString* const NSAccessibilityTextSelectionGranularity =
+ @"AXTextSelectionGranularity";
+NSString* const NSAccessibilityTextSelectionChangedFocus =
+ @"AXTextSelectionChangedFocus";
+NSString* const NSAccessibilityTextChangeElement = @"AXTextChangeElement";
+NSString* const NSAccessibilityTextEditType = @"AXTextEditType";
+NSString* const NSAccessibilityTextChangeValue = @"AXTextChangeValue";
+NSString* const NSAccessibilityChangeValueStartMarker =
+ @"AXTextChangeValueStartMarker";
+NSString* const NSAccessibilityTextChangeValueLength =
+ @"AXTextChangeValueLength";
+NSString* const NSAccessibilityTextChangeValues = @"AXTextChangeValues";
+
+AX_EXPORT const char* ToString(AXTextStateChangeType);
+AX_EXPORT const char* ToString(AXTextSelectionDirection);
+AX_EXPORT const char* ToString(AXTextSelectionGranularity);
+AX_EXPORT const char* ToString(AXTextEditType);
+
+} // namespace ui
+
+#endif // UI_ACCESSIBILITY_PLATFORM_AX_PRIVATE_WEBKIT_CONSTANTS_MAC_H_
diff --git a/ui/accessibility/platform/ax_private_webkit_constants_mac.mm b/ui/accessibility/platform/ax_private_webkit_constants_mac.mm
new file mode 100644
index 0000000000000000000000000000000000000000..7de31a487dd6e0e6a4af2f4fa62e463f41a0d96a
--- /dev/null
+++ b/ui/accessibility/platform/ax_private_webkit_constants_mac.mm
@@ -0,0 +1,91 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/accessibility/platform/ax_private_webkit_constants_mac.h"
+
+namespace ui {
+
+const char* ToString(AXTextStateChangeType type) {
+ switch (type) {
+ case AXTextStateChangeTypeUnknown:
+ return "AXTextStateChangeTypeUnknown";
+ case AXTextStateChangeTypeEdit:
+ return "AXTextStateChangeTypeEdit";
+ case AXTextStateChangeTypeSelectionMove:
+ return "AXTextStateChangeTypeSelectionMove";
+ case AXTextStateChangeTypeSelectionExtend:
+ return "AXTextStateChangeTypeSelectionExtend";
+ }
+
+ return "";
+}
+
+const char* ToString(AXTextSelectionDirection direction) {
+ switch (direction) {
+ case AXTextSelectionDirectionUnknown:
+ return "AXTextSelectionDirectionUnknown";
+ case AXTextSelectionDirectionBeginning:
+ return "AXTextSelectionDirectionBeginning";
+ case AXTextSelectionDirectionEnd:
+ return "AXTextSelectionDirectionEnd";
+ case AXTextSelectionDirectionPrevious:
+ return "AXTextSelectionDirectionPrevious";
+ case AXTextSelectionDirectionNext:
+ return "AXTextSelectionDirectionNext";
+ case AXTextSelectionDirectionDiscontiguous:
+ return "AXTextSelectionDirectionDiscontiguous";
+ }
+
+ return "";
+}
+
+const char* ToString(AXTextSelectionGranularity granularity) {
+ switch (granularity) {
+ case AXTextSelectionGranularityUnknown:
+ return "AXTextSelectionGranularityUnknown";
+ case AXTextSelectionGranularityCharacter:
+ return "AXTextSelectionGranularityCharacter";
+ case AXTextSelectionGranularityWord:
+ return "AXTextSelectionGranularityWord";
+ case AXTextSelectionGranularityLine:
+ return "AXTextSelectionGranularityLine";
+ case AXTextSelectionGranularitySentence:
+ return "AXTextSelectionGranularitySentence";
+ case AXTextSelectionGranularityParagraph:
+ return "AXTextSelectionGranularityParagraph";
+ case AXTextSelectionGranularityPage:
+ return "AXTextSelectionGranularityPage";
+ case AXTextSelectionGranularityDocument:
+ return "AXTextSelectionGranularityDocument";
+ case AXTextSelectionGranularityAll:
+ return "AXTextSelectionGranularityAll";
+ }
+
+ return "";
+}
+
+const char* ToString(AXTextEditType type) {
+ switch (type) {
+ case AXTextEditTypeUnknown:
+ return "AXTextEditTypeUnknown";
+ case AXTextEditTypeDelete:
+ return "AXTextEditTypeDelete";
+ case AXTextEditTypeInsert:
+ return "AXTextEditTypeInsert";
+ case AXTextEditTypeTyping:
+ return "AXTextEditTypeTyping";
+ case AXTextEditTypeDictation:
+ return "AXTextEditTypeDictation";
+ case AXTextEditTypeCut:
+ return "AXTextEditTypeCut";
+ case AXTextEditTypePaste:
+ return "AXTextEditTypePaste";
+ case AXTextEditTypeAttributesChange:
+ return "AXTextEditTypeAttributesChange";
+ }
+
+ return "";
+}
+
+} // namespace ui

View File

@@ -0,0 +1,115 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Robinson <mrobinson@igalia.com>
Date: Mon, 26 Oct 2020 23:12:55 +0000
Subject: Expose a11y popup menu type via the name "AXPopupValue" on Mac
This value was exposed via the name "AXHasPopupValue", while WebKit
exposes this value via "AXPopupValue." Fix the attribute name, which in
turn fixes an issue with how popup buttons are announced in VoiceOver.
Bug: 1129678
Change-Id: Iede26b2fd6ddb9d7717fcb47fd1dd1cce5b74075
AX-Relnotes: Fix an issue with the announcement of popup buttons in VoiceOver.
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2489985
Commit-Queue: Aaron Leventhal <aleventhal@chromium.org>
Reviewed-by: Aaron Leventhal <aleventhal@chromium.org>
Cr-Commit-Position: refs/heads/master@{#820964}
diff --git a/content/browser/accessibility/browser_accessibility_cocoa.mm b/content/browser/accessibility/browser_accessibility_cocoa.mm
index 3abd9933ab325bda6cb486a41fd6c8b246aa8e71..17aa494d6473866721a8cc5f4c5c646af9307d93 100644
--- a/content/browser/accessibility/browser_accessibility_cocoa.mm
+++ b/content/browser/accessibility/browser_accessibility_cocoa.mm
@@ -92,7 +92,7 @@
@"AXFocusableAncestor";
NSString* const NSAccessibilityGrabbedAttribute = @"AXGrabbed";
NSString* const NSAccessibilityHasPopupAttribute = @"AXHasPopup";
-NSString* const NSAccessibilityHasPopupValueAttribute = @"AXHasPopupValue";
+NSString* const NSAccessibilityPopupValueAttribute = @"AXPopupValue";
NSString* const NSAccessibilityHighestEditableAncestorAttribute =
@"AXHighestEditableAncestor";
NSString* const NSAccessibilityInvalidAttribute = @"AXInvalid";
@@ -836,7 +836,7 @@ + (void)initialize {
{NSAccessibilityGrabbedAttribute, @"grabbed"},
{NSAccessibilityHeaderAttribute, @"header"},
{NSAccessibilityHasPopupAttribute, @"hasPopup"},
- {NSAccessibilityHasPopupValueAttribute, @"hasPopupValue"},
+ {NSAccessibilityPopupValueAttribute, @"popupValue"},
{NSAccessibilityHelpAttribute, @"help"},
{NSAccessibilityHighestEditableAncestorAttribute,
@"highestEditableAncestor"},
@@ -1411,7 +1411,7 @@ - (NSNumber*)hasPopup {
return @(_owner->HasIntAttribute(ax::mojom::IntAttribute::kHasPopup));
}
-- (NSString*)hasPopupValue {
+- (NSString*)popupValue {
if (![self instanceActive])
return nil;
int hasPopup = _owner->GetIntAttribute(ax::mojom::IntAttribute::kHasPopup);
@@ -3586,7 +3586,7 @@ - (NSArray*)accessibilityAttributeNames {
if (_owner->HasIntAttribute(ax::mojom::IntAttribute::kHasPopup)) {
[ret addObjectsFromArray:@[
- NSAccessibilityHasPopupAttribute, NSAccessibilityHasPopupValueAttribute
+ NSAccessibilityHasPopupAttribute, NSAccessibilityPopupValueAttribute
]];
}
diff --git a/content/test/data/accessibility/aria/aria-haspopup-expected-mac.txt b/content/test/data/accessibility/aria/aria-haspopup-expected-mac.txt
index e988b9fe7d061fa3aa6930ababa4f32c095bd8a3..de0f31f2065490d6085027e2800706a3926bcf5b 100644
--- a/content/test/data/accessibility/aria/aria-haspopup-expected-mac.txt
+++ b/content/test/data/accessibility/aria/aria-haspopup-expected-mac.txt
@@ -1,10 +1,10 @@
AXWebArea
-++AXPopUpButton AXHasPopup=1 AXHasPopupValue='menu'
+++AXPopUpButton AXHasPopup=1 AXPopupValue='menu'
++AXPopUpButton
-++AXPopUpButton AXHasPopup=1 AXHasPopupValue='menu'
-++AXPopUpButton AXHasPopup=1 AXHasPopupValue='listbox'
-++AXPopUpButton AXHasPopup=1 AXHasPopupValue='grid'
-++AXPopUpButton AXHasPopup=1 AXHasPopupValue='dialog'
-++AXPopUpButton AXHasPopup=1 AXHasPopupValue='menu'
-++AXPopUpButton AXHasPopup=1 AXHasPopupValue='listbox'
-++AXPopUpButton AXHasPopup=1 AXHasPopupValue='listbox'
+++AXPopUpButton AXHasPopup=1 AXPopupValue='menu'
+++AXPopUpButton AXHasPopup=1 AXPopupValue='listbox'
+++AXPopUpButton AXHasPopup=1 AXPopupValue='grid'
+++AXPopUpButton AXHasPopup=1 AXPopupValue='dialog'
+++AXPopUpButton AXHasPopup=1 AXPopupValue='menu'
+++AXPopUpButton AXHasPopup=1 AXPopupValue='listbox'
+++AXPopUpButton AXHasPopup=1 AXPopupValue='listbox'
diff --git a/content/test/data/accessibility/aria/aria-haspopup.html b/content/test/data/accessibility/aria/aria-haspopup.html
index 026397c4e9ad805f5facfc499cc986cd0763aef3..7d982745e89b8346bf71eee90110fe6a96648629 100644
--- a/content/test/data/accessibility/aria/aria-haspopup.html
+++ b/content/test/data/accessibility/aria/aria-haspopup.html
@@ -3,7 +3,7 @@
@MAC-ALLOW:AXShowMenu*
@MAC-ALLOW:AXPress*
@MAC-ALLOW:AXHasPopup
-@MAC-ALLOW:AXHasPopupValue
+@MAC-ALLOW:AXPopupValue
@WIN-ALLOW:EXPANDED*
@WIN-ALLOW:HASPOPUP*
@WIN-ALLOW:haspopup*
diff --git a/content/test/data/accessibility/html/input-suggestions-source-element-expected-mac.txt b/content/test/data/accessibility/html/input-suggestions-source-element-expected-mac.txt
index 4b0bde650deed34edead37ffabd3eda2d7a82b49..38ca751991f564f9a24ba131652014f161d4b996 100644
--- a/content/test/data/accessibility/html/input-suggestions-source-element-expected-mac.txt
+++ b/content/test/data/accessibility/html/input-suggestions-source-element-expected-mac.txt
@@ -1,3 +1,3 @@
AXWebArea AXRoleDescription='HTML content'
++AXGroup AXRoleDescription='group'
-++++AXComboBox AXAutocompleteValue='list' AXHasPopup=1 AXHasPopupValue='listbox' AXRoleDescription='combo box'
+++++AXComboBox AXAutocompleteValue='list' AXHasPopup=1 AXPopupValue='listbox' AXRoleDescription='combo box'
diff --git a/content/test/data/accessibility/html/input-suggestions-source-element.html b/content/test/data/accessibility/html/input-suggestions-source-element.html
index 039ac5855e1122b34dad0c1fae42f798791b7890..d024f17de3d3b04029c532e616140e20afa87549 100644
--- a/content/test/data/accessibility/html/input-suggestions-source-element.html
+++ b/content/test/data/accessibility/html/input-suggestions-source-element.html
@@ -1,7 +1,7 @@
<!--
@MAC-ALLOW:AXRoleDescription
@MAC-ALLOW:AXHasPopup
-@MAC-ALLOW:AXHasPopupValue
+@MAC-ALLOW:AXPopupValue
@WIN-ALLOW:haspopup*
@AURALINUX-ALLOW:haspopup*
@AURALINUX-ALLOW:supports-autocompletion

View File

@@ -7,10 +7,10 @@ spellchecker uses a few IDS_ resources. We need to load these from
Electrons grit header instead of Chromes
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 7e37891fc3d551d36d5949ed5865bd6cf4800215..9ea8f5d90f23b7255ef17f505f2b746f2f098e26 100644
index 62ddc2d8548bcac4d55bbc7283426c426fecf254..b0eb803cd132390d492b82600d8629e2c43cc72e 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -5955,6 +5955,7 @@ static_library("browser") {
@@ -5960,6 +5960,7 @@ static_library("browser") {
deps += [
"//components/spellcheck/browser",
"//components/spellcheck/common",

View File

@@ -75,10 +75,10 @@ index aaa9ad1d58d7f584cbf391e0cb0a61a0d25d5c69..5b02834b5ecaf4bcb7e051d9ee98cd5e
// Used by WebView to sample crashes without generating the unwanted dumps. If
// the returned value is less than 100, crash dumping will be sampled to that
diff --git a/components/crash/core/app/crashpad_mac.mm b/components/crash/core/app/crashpad_mac.mm
index aa7c3302f2e3fc7129381b355ed4fa1bc386f8cb..d7dd05118f3c90f5ab570f59685c43bd180885e5 100644
index eb675321436a53e82432144d43f258bed6e938e2..ae2032a12eac7c789d790e53857d11ba3e03d510 100644
--- a/components/crash/core/app/crashpad_mac.mm
+++ b/components/crash/core/app/crashpad_mac.mm
@@ -71,6 +71,8 @@
@@ -77,6 +77,8 @@
} // @autoreleasepool
return process_annotations;
}();
@@ -87,7 +87,7 @@ index aa7c3302f2e3fc7129381b355ed4fa1bc386f8cb..d7dd05118f3c90f5ab570f59685c43bd
return annotations;
}
@@ -141,6 +143,13 @@ void DumpProcessWithoutCrashing(task_t task_port) {
@@ -147,6 +149,13 @@ void DumpProcessWithoutCrashing(task_t task_port) {
std::vector<std::string> arguments;

View File

@@ -0,0 +1,146 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Joshua Peraza <jperaza@chromium.org>
Date: Wed, 21 Oct 2020 11:10:25 -0700
Subject: Initialize logging for crashpad
Although logging to files is not yet supported by mini_chromium, it is
the default behavior for OS_WIN in chromium. This change should
cause crashpad to log via OutputDebugString() on Windows, instead of
debug.log files. Future work (crbug.com/crashpad/26) should arrange for
logs to be uploaded with reports, embedded in associated minidumps or as
file attachments.
Bug: chromium:711159
Change-Id: I0f9004f7de94dd29d555cc7d23c48a63da6b4bba
Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/2425108
Reviewed-by: Mark Mentovai <mark@chromium.org>
diff --git a/base/logging.cc b/base/logging.cc
index b5cf2c4933d0cbb89f2f1b410c5c249a0b8647f0..698dca03914934b294457d05d89722a27cdebb56 100644
--- a/base/logging.cc
+++ b/base/logging.cc
@@ -369,21 +369,23 @@ bool BaseInitLoggingImpl(const LoggingSettings& settings) {
g_log_format = settings.log_format;
#endif
- base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
- // Don't bother initializing |g_vlog_info| unless we use one of the
- // vlog switches.
- if (command_line->HasSwitch(switches::kV) ||
- command_line->HasSwitch(switches::kVModule)) {
- // NOTE: If |g_vlog_info| has already been initialized, it might be in use
- // by another thread. Don't delete the old VLogInfo, just create a second
- // one. We keep track of both to avoid memory leak warnings.
- CHECK(!g_vlog_info_prev);
- g_vlog_info_prev = g_vlog_info;
-
- g_vlog_info =
- new VlogInfo(command_line->GetSwitchValueASCII(switches::kV),
- command_line->GetSwitchValueASCII(switches::kVModule),
- &g_min_log_level);
+ if (base::CommandLine::InitializedForCurrentProcess()) {
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+ // Don't bother initializing |g_vlog_info| unless we use one of the
+ // vlog switches.
+ if (command_line->HasSwitch(switches::kV) ||
+ command_line->HasSwitch(switches::kVModule)) {
+ // NOTE: If |g_vlog_info| has already been initialized, it might be in use
+ // by another thread. Don't delete the old VLogInfo, just create a second
+ // one. We keep track of both to avoid memory leak warnings.
+ CHECK(!g_vlog_info_prev);
+ g_vlog_info_prev = g_vlog_info;
+
+ g_vlog_info =
+ new VlogInfo(command_line->GetSwitchValueASCII(switches::kV),
+ command_line->GetSwitchValueASCII(switches::kVModule),
+ &g_min_log_level);
+ }
}
g_logging_destination = settings.logging_dest;
@@ -394,7 +396,10 @@ bool BaseInitLoggingImpl(const LoggingSettings& settings) {
config.min_severity = FX_LOG_INFO;
config.console_fd = -1;
config.log_service_channel = ZX_HANDLE_INVALID;
- std::string log_tag = command_line->GetProgram().BaseName().AsUTF8Unsafe();
+ std::string log_tag = base::CommandLine::ForCurrentProcess()
+ ->GetProgram()
+ .BaseName()
+ .AsUTF8Unsafe();
const char* log_tag_data = log_tag.data();
config.tags = &log_tag_data;
config.num_tags = 1;
diff --git a/third_party/crashpad/crashpad/DEPS b/third_party/crashpad/crashpad/DEPS
index 83995e0cdea91522c272415330c57af764d23163..7e83327aac2582e81a38720086a52832de58a37a 100644
--- a/third_party/crashpad/crashpad/DEPS
+++ b/third_party/crashpad/crashpad/DEPS
@@ -42,7 +42,7 @@ deps = {
'7bde79cc274d06451bf65ae82c012a5d3e476b5a',
'crashpad/third_party/mini_chromium/mini_chromium':
Var('chromium_git') + '/chromium/mini_chromium@' +
- '76a9bb7475f6217eaf108789246379d3972b4e6a',
+ '5fc64bfbf1c000161445c586de45e40464ff2314',
'crashpad/third_party/libfuzzer/src':
Var('chromium_git') + '/chromium/llvm-project/compiler-rt/lib/fuzzer.git@' +
'fda403cf93ecb8792cb1d061564d89a6553ca020',
diff --git a/third_party/crashpad/crashpad/handler/handler_main.cc b/third_party/crashpad/crashpad/handler/handler_main.cc
index 33649291e253a7a9bd281b892bab415ff1950b6a..a3ba9bb17e221e8330b09eae572d116bd29e4ba4 100644
--- a/third_party/crashpad/crashpad/handler/handler_main.cc
+++ b/third_party/crashpad/crashpad/handler/handler_main.cc
@@ -504,16 +504,26 @@ class ScopedStoppable {
DISALLOW_COPY_AND_ASSIGN(ScopedStoppable);
};
+void InitCrashpadLogging() {
+ logging::LoggingSettings settings;
+#if defined(OS_CHROMEOS)
+ settings.logging_dest = logging::LOG_TO_FILE;
+ settings.log_file_path = "/var/log/chrome/chrome";
+#elif defined(OS_WIN)
+ settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
+#else
+ settings.logging_dest =
+ logging::LOG_TO_SYSTEM_DEBUG_LOG | logging::LOG_TO_STDERR;
+#endif
+ logging::InitLogging(settings);
+}
+
} // namespace
int HandlerMain(int argc,
char* argv[],
const UserStreamDataSources* user_stream_sources) {
-#if defined(OS_CHROMEOS)
- if (freopen("/var/log/chrome/chrome", "a", stderr) == nullptr) {
- PLOG(ERROR) << "Failed to redirect stderr to /var/log/chrome/chrome";
- }
-#endif
+ InitCrashpadLogging();
InstallCrashHandler();
CallMetricsRecordNormalExit metrics_record_normal_exit;
diff --git a/third_party/crashpad/crashpad/test/gtest_main.cc b/third_party/crashpad/crashpad/test/gtest_main.cc
index 67cfa0d72d7eb469775201f3a9df906f27c302a9..c67b8e24bb940935d5da88428ed3058a135f5a57 100644
--- a/third_party/crashpad/crashpad/test/gtest_main.cc
+++ b/third_party/crashpad/crashpad/test/gtest_main.cc
@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include "base/logging.h"
#include "build/build_config.h"
#include "gtest/gtest.h"
#include "test/main_arguments.h"
@@ -99,6 +100,12 @@ int main(int argc, char* argv[]) {
#endif // CRASHPAD_IS_IN_CHROMIUM
+ // base::TestSuite initializes logging when using Chromium's test launcher.
+ logging::LoggingSettings settings;
+ settings.logging_dest =
+ logging::LOG_TO_STDERR | logging::LOG_TO_SYSTEM_DEBUG_LOG;
+ logging::InitLogging(settings);
+
#if defined(CRASHPAD_TEST_LAUNCHER_GOOGLEMOCK)
testing::InitGoogleMock(&argc, argv);
#elif defined(CRASHPAD_TEST_LAUNCHER_GOOGLETEST)

View File

@@ -17,10 +17,10 @@ only one or two specific checks fail. Then it's better to simply comment out the
failing checks and allow the rest of the target to have them enabled.
diff --git a/content/browser/renderer_host/navigation_controller_impl.cc b/content/browser/renderer_host/navigation_controller_impl.cc
index 18f5da7bc5953282e72933fffd7e37bbf77bfb31..b164f15fa7506caf82f0f5f450d90dbbd88a116e 100644
index 29fed88f36ecaf0c022d2a5a2f3ed7db66e2c96c..e1aadf680851d23cc2ce6023b20f496ee97c22da 100644
--- a/content/browser/renderer_host/navigation_controller_impl.cc
+++ b/content/browser/renderer_host/navigation_controller_impl.cc
@@ -1275,8 +1275,10 @@ NavigationType NavigationControllerImpl::ClassifyNavigation(
@@ -1276,8 +1276,10 @@ NavigationType NavigationControllerImpl::ClassifyNavigation(
return NAVIGATION_TYPE_NEW_SUBFRAME;
}
@@ -33,7 +33,7 @@ index 18f5da7bc5953282e72933fffd7e37bbf77bfb31..b164f15fa7506caf82f0f5f450d90dbb
if (rfh->GetParent()) {
// All manual subframes would be did_create_new_entry and handled above, so
@@ -1551,7 +1553,10 @@ void NavigationControllerImpl::RendererDidNavigateToNewPage(
@@ -1552,7 +1554,10 @@ void NavigationControllerImpl::RendererDidNavigateToNewPage(
new_entry->GetFavicon() = GetLastCommittedEntry()->GetFavicon();
}
@@ -46,10 +46,10 @@ index 18f5da7bc5953282e72933fffd7e37bbf77bfb31..b164f15fa7506caf82f0f5f450d90dbb
// navigation. Now we know that the renderer has updated its state accordingly
// and it is safe to also clear the browser side history.
diff --git a/ui/base/clipboard/clipboard_win.cc b/ui/base/clipboard/clipboard_win.cc
index 8d0e981720bb4a0ec4c42f389275fd375c1b1e43..9473f4f7819667d7cc4bfa514955b4e65d69c1c9 100644
index 260858079f2f511cb6eb513c37eec8a0d38b55a0..39f2cef515c4a1724aeb6f3660730221f251e51e 100644
--- a/ui/base/clipboard/clipboard_win.cc
+++ b/ui/base/clipboard/clipboard_win.cc
@@ -850,10 +850,10 @@ SkBitmap ClipboardWin::ReadImageInternal(ClipboardBuffer buffer) const {
@@ -817,10 +817,10 @@ SkBitmap ClipboardWin::ReadImageInternal(ClipboardBuffer buffer) const {
void ClipboardWin::WriteToClipboard(ClipboardFormatType format, HANDLE handle) {
UINT cf_format = format.ToFormatEtc().cfFormat;

View File

@@ -35,10 +35,10 @@ index bb7ff971823db702991a3167b5b0ac1b3dd4a6c9..e5afad68300bdd6ac109b3c9b94d3c20
// If we are likely to software composite the resource, we use sRGB because
diff --git a/cc/trees/layer_tree_settings.h b/cc/trees/layer_tree_settings.h
index 64fe3c1c3f60758c25f9bc88daedf35633508aa7..a2e9ebb3dc31b4e8665376ffb1f805c6093bce5c 100644
index e5a58655788be3bd1c86e238e34bbadf8012bc48..2a2de85e89a8a0f803b7c987620a259b26281d8d 100644
--- a/cc/trees/layer_tree_settings.h
+++ b/cc/trees/layer_tree_settings.h
@@ -98,6 +98,8 @@ class CC_EXPORT LayerTreeSettings {
@@ -99,6 +99,8 @@ class CC_EXPORT LayerTreeSettings {
bool use_rgba_4444 = false;
bool unpremultiply_and_dither_low_bit_depth_tiles = false;
@@ -229,7 +229,7 @@ index e5179c0e4971bc593860b1e5b606fec651e6756b..fc7c09d19c60d498885d3e4f1a4a4ac9
+
+#undef PATCH_CS
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc
index de4eadaf7be8be95fc0ad454d66c8ec397cfc20a..d4c451ea992490befb34b3690a98d968bb50b899 100644
index d7439d851d6c027a20bf09a258603939b5c19f1e..72162a468f63543c508a3d34e357be1dfcdeba51 100644
--- a/content/browser/gpu/gpu_process_host.cc
+++ b/content/browser/gpu/gpu_process_host.cc
@@ -221,6 +221,7 @@ GpuTerminationStatus ConvertToGpuTerminationStatus(
@@ -327,7 +327,7 @@ index 95e818f1406eb1a73a746b73a608137ab5c6e894..6e1d3b3b1add4eda90560856b6915d46
// is what the renderer uses if its not threaded.
settings.enable_checker_imaging =
diff --git a/ui/gfx/mac/io_surface.cc b/ui/gfx/mac/io_surface.cc
index 3e80dc40c83bd4eb96f9029643c4a0856253494e..8e19a78f106daf4185ee69970832ea1237d3d03b 100644
index ec83bd814a0d5d6802b349d08b22013a0d99e015..043e769e7db9773de2054dcc66f13f062823f58f 100644
--- a/ui/gfx/mac/io_surface.cc
+++ b/ui/gfx/mac/io_surface.cc
@@ -18,6 +18,7 @@
@@ -353,7 +353,7 @@ index 3e80dc40c83bd4eb96f9029643c4a0856253494e..8e19a78f106daf4185ee69970832ea12
// Allow but ignore invalid color spaces.
if (!color_space.IsValid())
return true;
@@ -265,6 +274,15 @@ IOSurfaceRef CreateIOSurface(const gfx::Size& size,
@@ -286,6 +295,15 @@ IOSurfaceRef CreateIOSurface(const gfx::Size& size,
DCHECK_EQ(kIOReturnSuccess, r);
}

View File

@@ -6,10 +6,10 @@ Subject: disable_hidden.patch
Electron uses this to disable background throttling for hidden windows.
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index 529a5b71b9987be21bfb1494b420ef88bbd17f7a..19d7421e1de9680a8b1364f010e19cc95ef7325a 100644
index 1ff402be7362bd1dd64f3ffb88081f6cfac328d8..aa00ff974485d3093f05b0cdaeb6c8ed865015e3 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -692,6 +692,9 @@ void RenderWidgetHostImpl::WasHidden() {
@@ -693,6 +693,9 @@ void RenderWidgetHostImpl::WasHidden() {
if (is_hidden_)
return;
@@ -20,7 +20,7 @@ index 529a5b71b9987be21bfb1494b420ef88bbd17f7a..19d7421e1de9680a8b1364f010e19cc9
blink::mojom::PointerLockResult::kWrongDocument);
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h
index 9d7d10136a683620d6fb67246aae51df982930d0..c119dd8916fe2fbde97ce91cce6f788fc62f3534 100644
index 9f02961f7ef63d672b918439bb84121ea22e2931..66fd1cbec90c1ecc1f0f1a9722367a58d66c64fd 100644
--- a/content/browser/renderer_host/render_widget_host_impl.h
+++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -173,6 +173,9 @@ class CONTENT_EXPORT RenderWidgetHostImpl

View File

@@ -0,0 +1,38 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Cheng Zhao <zcbenz@gmail.com>
Date: Thu, 4 Oct 2018 14:57:02 -0700
Subject: feat: enable setting aspect ratio to 0
Make SetAspectRatio accept 0 as valid input, which would reset to null.
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
index 3b132d4d7618e11b851b315e82fa67442c852fb3..af2c2f2bbc1f52f4455fb973ab2fc0d0dd013ca5 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
@@ -484,7 +484,7 @@ void DesktopWindowTreeHostWin::SetOpacity(float opacity) {
}
void DesktopWindowTreeHostWin::SetAspectRatio(const gfx::SizeF& aspect_ratio) {
- DCHECK(!aspect_ratio.IsEmpty());
+ DCHECK_NE(aspect_ratio.height(), 0);
message_handler_->SetAspectRatio(aspect_ratio.width() /
aspect_ratio.height());
}
diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc
index 42eeb16a3d59de7e37eb858a982cc3534ab7cc51..ce3672e4d5cee51651bc6f8c294b27f0a9e01682 100644
--- a/ui/views/win/hwnd_message_handler.cc
+++ b/ui/views/win/hwnd_message_handler.cc
@@ -920,8 +920,11 @@ void HWNDMessageHandler::SetFullscreen(bool fullscreen) {
}
void HWNDMessageHandler::SetAspectRatio(float aspect_ratio) {
- // If the aspect ratio is not in the valid range, do nothing.
- DCHECK_GT(aspect_ratio, 0.0f);
+ // If the aspect ratio is 0, reset it to null.
+ if (aspect_ratio == 0.0f) {
+ aspect_ratio_.reset();
+ return;
+ }
aspect_ratio_ = aspect_ratio;

View File

@@ -62,7 +62,7 @@ index e2ca7dd198390ebc923facd690904faeb8300e62..f2f53775abb0ba2954cbb3ec431d84c3
};
diff --git a/ui/native_theme/native_theme_win.cc b/ui/native_theme/native_theme_win.cc
index eaf817b4b5400fa4d2b6af7c86ac69aabf030a38..0f702be38f8e015c4e61677db5cf566259650dc6 100644
index fd075a6f8a1357e7456a97d37af339848635a102..54fa642f614acd221ceaeee0938506e6fea41b1a 100644
--- a/ui/native_theme/native_theme_win.cc
+++ b/ui/native_theme/native_theme_win.cc
@@ -737,6 +737,8 @@ bool NativeThemeWin::ShouldUseDarkColors() const {

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