Compare commits

..

175 Commits

Author SHA1 Message Date
Electron Bot
f37c1ff644 Bump v9.4.0 2020-12-11 13:16:23 -08:00
Jeremy Rose
5c8e7e8b7f fix: restrict sendToFrame to same-process frames by default (#26928)
* fix: restrict sendToFrame to same-process frames by default (#26875)

* missed a conflict

* fix build

* fix build again
2020-12-11 13:01:49 -08:00
trop[bot]
36b1f8fcf8 fix: Upload all *.dll.pdb to symbol server (#26967)
Fixes #26961.

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

Co-authored-by: Biru Mohanathas <birunthan@mohanathas.com>
2020-12-11 12:54:11 -08:00
trop[bot]
e83bd9bbf0 fix: Avoid crashing in NativeViewHost::SetParentAccessible on Windows 10 (#26950)
* 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

* update patches

Co-authored-by: Biru Mohanathas <birunthan@mohanathas.com>
Co-authored-by: Jeremy Rose <jeremya@chromium.org>
Co-authored-by: Electron Bot <electron@github.com>
2020-12-11 12:51:05 -08:00
Jeremy Rose
c2136b6065 chore: cherry-pick 290fe9c6e245 from v8 (#26897) 2020-12-11 11:09:26 -08:00
Jeremy Rose
a57428553e chore: cherry-pick 3abc372c9c00 from chromium (#26895)
* chore: cherry-pick 3abc372c9c00 from chromium

* resolve conflict
2020-12-11 11:03:28 -08:00
Jeremy Rose
559c008e0d chore: cherry-pick d8d64b7cd244 from chromium (#26893)
* chore: cherry-pick d8d64b7cd244 from chromium

* update patches

Co-authored-by: Electron Bot <electron@github.com>
2020-12-10 14:57:43 -08:00
Pedro Pontes
2d41c02714 chore: cherry-pick ecdec1fb0f42 from chromium (#26867)
* chore: cherry-pick ecdec1fb0f42 from chromium

* update patches

Co-authored-by: Electron Bot <electron@github.com>
2020-12-10 10:41:20 -05:00
Pedro Pontes
662810f881 chore: cherry-pick bbc6ab5bb49c from chromium (#26861)
* chore: cherry-pick bbc6ab5bb49c from chromium

* update patches

Co-authored-by: Electron Bot <electron@github.com>
2020-12-10 09:45:54 +09:00
Robo
0065e3d12b fix: Propagate --disable-dev-shm-usage to child processes (#26806)
* fix: Propagate --disable-dev-shm-usage to child processes.

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

* update patches

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
Co-authored-by: Electron Bot <electron@github.com>
2020-12-09 09:55:52 -08:00
Pedro Pontes
2b69fbc4bd chore: cherry-pick 5ffbb7ed173a from chromium (#26856)
* chore: cherry-pick 5ffbb7ed173a from chromium

* update patches

Co-authored-by: Electron Bot <electron@github.com>
2020-12-08 20:31:22 -08:00
Milan Burda
72511cc9d2 fix: systemPreferences.effectiveAppearance returning systemPreferences.getAppLevelAppearance() (#26852) (#26881) 2020-12-08 08:21:42 -08:00
Pedro Pontes
84ce462803 chore: cherry-pick eec5025668f8 from chromium (#26859)
* chore: cherry-pick eec5025668f8 from chromium

* update patches

Co-authored-by: Electron Bot <electron@github.com>
2020-12-07 10:58:09 -05:00
Pedro Pontes
533b9716af chore: cherry-pick 8c346e3cd9 from chromium. (#26831) 2020-12-04 13:31:03 -08:00
trop[bot]
24a1234e28 build: use all-for-one goma (#26699) (#26800)
* Revert "Revert "build: use one-for-all goma (#26679)" (#26689)"

This reverts commit 38ab829ea6.

* build: ensure file descriptor limit is higher on macOS

Co-authored-by: Samuel Attard <sam@electronjs.org>
2020-12-02 10:58:37 -08:00
trop[bot]
b2e345857a docs: BrowserWindow extension APIs are deprecated in Electron 9 (#26784)
Co-authored-by: Milan Burda <milan.burda@gmail.com>
2020-12-01 21:33:02 -08:00
Shelley Vohr
63873140d9 fix: webContents interaction with draggable browserviews (#26745) 2020-12-01 16:03:26 -08:00
Shelley Vohr
738740fd7d fix: renderer crash on setImmediate (#26748) 2020-12-01 15:44:05 -06:00
Electron Bot
415c1f9e9b Bump v9.3.5 2020-11-23 12:46:32 -08:00
Milan Burda
07c4e24ebb fix: <webview> render-process-gone event dispatch (#26576)
Co-authored-by: Milan Burda <miburda@microsoft.com>
2020-11-18 17:56:32 -06:00
trop[bot]
b7b714a020 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:37 -08:00
trop[bot]
14d03d7b78 test: support for adding extra module paths (#26545)
Co-authored-by: David Sanders <dsanders11@ucsbalum.com>
2020-11-17 19:07:26 -08:00
Cheng Zhao
7bd4570ff4 fix: LC_ALL env should not be changed (#26508) 2020-11-18 11:13:33 +09:00
Milan Burda
a5c65aae37 fix: ensure that internal messages are sent from the main process (#26437) 2020-11-16 15:32:44 +09:00
Cheng Zhao
d28a7b15a2 fix: make draggable regions work when devtools is opened on macOS (#26506)
* fix: make draggable region work when devtools is open

* fix: update draggable regions when resizing
2020-11-16 11:11:18 +09:00
Pedro Pontes
ef674025b5 chore: cherry-pick c244270e23 from chromium. (#26477) 2020-11-13 11:30:03 -08:00
trop[bot]
7446006c24 build: upload dsym files for all mac releases (#26427)
Co-authored-by: John Kleinschmidt <jkleinsc@github.com>
2020-11-11 14:25:27 -05:00
Michaela Laurencin
24fbb73838 chore: synchronously destroy WebContents on event prevented (#26442) 2020-11-11 10:14:01 -05:00
Charles Kerr
16b8c06bbf chore: cherry-pick daad98ce from chromium (#26430)
Fixes #26419

The "IsOS/IsAtLeastOS/IsAtMostOS" functions are driven from the Darwin
version number, which is always accurate. Adjust the
SysInfo::OperatingSystemVersionNumbers() function to return accurate
version numbers (or the best we can deduce) so that all version
numbers returned by helper functions are accurate and consistent.

Bug: 1101439
Bug: 1108832
Change-Id: I2ca92478d76bf572cc55875cba443f4978482d10
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2315490
Reviewed-by: Mark Mentovai <mark@chromium.org>
Commit-Queue: Avi Drissman <avi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#791491}
2020-11-11 09:54:07 -05:00
Jeremy Rose
f729d7456f chore: cherry-pick 815b12dfb5ec from v8 (#26412) 2020-11-10 14:47:54 -08:00
Jeremy Rose
badae800c1 chore: cherry-pick 8c725f7b5bbf from v8 (#26409) 2020-11-10 14:23:40 -08:00
Jeremy Rose
d89aa3a36e chore: cherry-pick 2882e1afd982 from angle (#26406) 2020-11-10 13:49:12 -08:00
Jeremy Rose
5b53cfa56f chore: cherry-pick 146bd99e762b from v8 (#26400) 2020-11-10 13:48:58 -08:00
Jeremy Rose
56e906d073 chore: cherry-pick 8f24f935c903 from chromium (#26397) 2020-11-10 13:48:45 -08:00
Samuel Attard
d94a5ddc09 build: auto-push patch file changes (#26235) (#26434)
* 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:48:08 -08:00
trop[bot]
7feffc7c35 build: verbose is flag, no value (#26422)
Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2020-11-10 10:02:14 -08:00
trop[bot]
2800ddf930 chore: cleanup inline HTML in docs (#26393)
Co-authored-by: David Sanders <dsanders11@ucsbalum.com>
2020-11-10 10:47:42 -05:00
trop[bot]
fabe766816 fix: Initialize logging for crashpad (#26267)
* 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

* chore: update patches

* update patch list

Co-authored-by: deepak1556 <hop2deep@gmail.com>
2020-11-10 10:07:26 -05:00
trop[bot]
87e2950e2d build: fix usage of octokit/rest and make uploading better (#26387)
Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2020-11-09 13:52:52 -08:00
Electron Bot
979e59e871 Bump v9.3.4 2020-11-09 12:28:27 -08:00
Shelley Vohr
1384b76570 fix: draggable region edge calculation on resize (#26322)
* fix: draggable region edge calculation on resize

* Feedback from review
2020-11-04 11:17:24 +09:00
Shelley Vohr
1ba30ace9b build: only check patch diffs in testing builds (#26285)
* build: only check patch diffs in testing builds

* Fixup patch indices
2020-11-02 18:57:11 +09:00
Shelley Vohr
8326cea7e7 fix: draggable regions exclusively on BrowserViews (#26261) 2020-11-02 16:08:20 +09:00
David Sanders
e6b24a21e4 chore: change some for loops to range-based (#26264) 2020-10-29 20:51:59 -07:00
Jeremy Rose
a9b1f2fd0e chore: cherry-pick f440137cd96a from chromium (#26210) 2020-10-29 10:43:22 -07:00
trop[bot]
0563bcad49 fix: hover text only working when VO enabled (#26244)
* 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:20 -07:00
David Sanders
a64a3e8aa9 chore: use auto to avoid repeating type (#26256) 2020-10-29 08:50:32 -07:00
Cheng Zhao
f1ffcb56d9 fix: set app locale after user's script is loaded (#26242) 2020-10-28 20:23:03 -07:00
Jeremy Rose
f3af287d4a chore: cherry-pick 30261f9de11e from chromium (#26204) 2020-10-28 15:42:29 -07:00
Jeremy Rose
305d623570 chore: cherry-pick 6a4cd97d6691 from v8 (#26207) 2020-10-28 14:38:46 -07:00
Jeremy Rose
c8d7be4a09 chore: cherry-pick 88f263f401b4 from chromium (#26197) 2020-10-28 14:38:12 -07:00
Jeremy Rose
e3d1a3163f chore: cherry-pick 6aa1e71fbd09 from v8 (#26200) 2020-10-28 14:03:49 -07:00
Jeremy Rose
8261e580ae chore: cherry-pick 229fdaf8fc05 from chromium (#26194) 2020-10-28 14:02:49 -07:00
Jeremy Rose
d007efa5e8 chore: cherry-pick 1ed869ad4bb3 from chromium (#26191)
* chore: cherry-pick 1ed869ad4bb3 from chromium

* update patches

Co-authored-by: Electron Bot <anonymous@electronjs.org>
2020-10-28 16:07:38 -04:00
Charles Kerr
a1e9b973b1 perf: improve heap snapshot performance (#26228)
Fixes #24509.

cherry-pick 2e2dc98 from v8
2020-10-28 15:58:50 -04:00
Jeremy Rose
eca3138e10 chore: cherry-pick 9591642a0896 from pdfium (#26213)
* chore: cherry-pick 9591642a0896 from pdfium

* update patches

Co-authored-by: Electron Bot <anonymous@electronjs.org>
2020-10-28 15:21:42 -04:00
trop[bot]
8443cf143b docs: fix app 'ready' event arguments (#26175)
Co-authored-by: Milan Burda <milan.burda@gmail.com>
2020-10-26 20:37:59 -07:00
trop[bot]
b7584fa0e8 chore: prefer empty() check for readability (#26169)
Co-authored-by: David Sanders <dsanders11@ucsbalum.com>
2020-10-26 20:36:59 -07:00
Electron Bot
0b5f24002b Bump v9.3.3 2020-10-26 09:39:50 -07:00
Shelley Vohr
dcb5b8244e ci: cleanup up test app directories (#26121)
Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
2020-10-24 18:49:06 -05:00
trop[bot]
6785021927 fix: setSimpleFullScreen shows traffic light in frameless window (#26128)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-10-23 09:43:08 -07:00
trop[bot]
d073ab64fb fix: return early on promise rejection (#26112)
Co-authored-by: David Sanders <dsanders11@ucsbalum.com>
2020-10-22 14:45:33 -05:00
trop[bot]
205f9432ee chore: tweak branch detection in release notes. (#26108)
Co-authored-by: Charles Kerr <charles@charleskerr.com>
2020-10-22 14:43:15 -05:00
trop[bot]
b2fb8cd60e fix: release NSAlert properly (#26098)
Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2020-10-22 08:22:02 -07:00
Samuel Attard
ab504006e2 revert: reply notifs sometimes destroyed too early (#26083)
This reverts commit cbd91b1fba.
2020-10-21 15:58:43 -07:00
Andrey Belenko
e2ab29fb29 chore: cherry-pick b977dff8 from freetype (#26069)
Co-authored-by: Andrey Belenko <anbelen@microsoft.com>
2020-10-21 13:35:24 -07:00
Shelley Vohr
8837679de6 fix: Save As PDF from PDF Preview (#26067) 2020-10-20 18:59:43 -07:00
Shelley Vohr
ba167e6c86 fix: crash in printing on Windows (#26066) 2020-10-20 16:38:43 -04:00
trop[bot]
1bc5b7f350 perf: remove GC timer that fired once per minute. (#26053)
Co-authored-by: Charles Kerr <charles@charleskerr.com>
2020-10-19 20:19:28 -07:00
trop[bot]
9d72cda6c4 build: fix invocation of cpplint on Windows (#26042)
Co-authored-by: David Sanders <dsanders11@ucsbalum.com>
2020-10-19 14:19:38 -07:00
Shelley Vohr
6763cca16f fix: pass module resolution paths to wrapped function (#26035)
Co-authored-by: Matt Kane <m@mk.gg>
2020-10-19 12:07:16 -07:00
trop[bot]
599da9c728 fix: correct null pointer checks in autoresizing browser views (#26034)
* Correction null pointer checks

* fix: correct null pointer checks in autoresizing browser views

Co-authored-by: mlaurencin <mlaurencin@microsoft.com>
2020-10-19 12:05:35 -07:00
Shelley Vohr
16db2d7856 fix: disable PDF annotation button (#26004) 2020-10-16 16:02:40 -07:00
trop[bot]
04548770fb fix: maximized frameless window bleeding to other monitors (#25980)
Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2020-10-15 20:02:07 -07:00
trop[bot]
ca8cda068d docs: move breaking-changes-ns.md contents to breaking-changes.md (#25948)
Co-authored-by: Milan Burda <milan.burda@gmail.com>
2020-10-15 10:50:59 +09:00
Pedro Pontes
b4f7463215 chore: cherry-pick 8629cd7f8af3 from chromium (#25857)
* chore: cherry-pick 8629cd7f8af3 from chromium

* update patches

Co-authored-by: Electron Bot <anonymous@electronjs.org>
2020-10-15 10:07:16 +09:00
Pedro Pontes
1efe79b874 chore: backport ffed0925f2 from webrtc. (#25854) 2020-10-15 10:06:30 +09:00
Shelley Vohr
e58853af3d docs: rename launch-failure -> launch-failed to match C++ code (#25930) 2020-10-14 10:56:12 -05:00
Pedro Pontes
437701d0ef chore: cherry-pick 3b5f65c0aeca from chromium (#25859)
* chore: cherry-pick 3b5f65c0aeca from chromium

* update patches

Co-authored-by: Electron Bot <anonymous@electronjs.org>
2020-10-14 10:20:54 +09:00
Shelley Vohr
13f319eddf fix: uv loop polling when render process reuse enabled (#25924) 2020-10-14 10:18:03 +09:00
Pedro Pontes
88baf5507f chore: cherry-pick f06a6cb3a38e from chromium (#25911)
* chore: cherry-pick f06a6cb3a38e from chromium

* update patches

Co-authored-by: Electron Bot <anonymous@electronjs.org>
2020-10-13 10:20:43 -07:00
trop[bot]
2472f81647 fix: NativeImage.getScaleFactors returns correct scales (#25904)
* fix: NativeImage.getScaleFactors returns correct scales

* fix tests

Co-authored-by: Jeremy Rose <nornagon@nornagon.net>
2020-10-13 09:21:24 -07:00
Pedro Pontes
40f0c01e15 chore: cherry-pick b7ccc3f6cc from chromium (#25896)
* chore: cherry-pick b7ccc3f6cc from chromium

* update patches

Co-authored-by: Electron Bot <anonymous@electronjs.org>
2020-10-12 19:38:21 -07:00
Michaela Laurencin
5e6c03c5c5 fix: notifications successfully never timeout with included flag (#25862)
* Backport changes for notification timeout never to version 9

* fix: notifications successfully never timeout with included flag

Co-authored-by: mlaurencin <mlaurencin@microsoft.com>
2020-10-12 10:55:13 -07:00
Milan Burda
9d3aa08c75 chore: cherry-pick abc6ab85e704 from chromium (#25638)
Co-authored-by: Milan Burda <miburda@microsoft.com>
2020-10-10 22:12:16 +09:00
Milan Burda
a5a34868d5 chore: cherry-pick adc731d678c4 from chromium (#25641)
Co-authored-by: Milan Burda <miburda@microsoft.com>
Co-authored-by: Jeremy Rose <jeremya@chromium.org>
2020-10-10 10:13:50 +09:00
Milan Burda
c481324725 test: improve app 'session-created' event spec (#25815) 2020-10-09 20:54:05 +09:00
Milan Burda
ea7d9182a1 chore: cherry-pick 7e5c7b5964 from v8 (#25645)
Co-authored-by: Milan Burda <miburda@microsoft.com>
2020-10-09 20:05:44 +09:00
trop[bot]
143c6b3d39 ci: fixup doc only check on Windows (#25840)
Co-authored-by: John Kleinschmidt <jkleinsc@github.com>
2020-10-08 21:35:25 -04:00
Robert Borg
86372e642c fix: gdi printing in silent printing mode (#25724)
for windows print_text_with_gdi is set to the value of is_modifiable
but this code path is not taken for silent printing
2020-10-08 09:41:20 -07:00
Electron Bot
09677ab592 Bump v9.3.2 2020-10-05 09:18:53 -07:00
Milan Burda
2cd8848b97 chore: cherry-pick 52dceba66599 from chromium (#25656)
Co-authored-by: Milan Burda <miburda@microsoft.com>
2020-10-05 09:58:07 +09:00
trop[bot]
82151b4f0d fix: crash when application launched from UNUserNotificationCenter notification (#25739)
Co-authored-by: Milan Burda <milan.burda@gmail.com>
2020-10-02 13:57:41 -07:00
trop[bot]
37ece8b71a build: move to ACR for docker image storage (#25733)
Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2020-10-02 13:28:52 -07:00
Shelley Vohr
e4c2be03b2 fix: close window when leave fs crash (#25605) 2020-09-30 10:49:24 -04:00
Milan Burda
d1735ee2f3 chore: cherry-pick 814a27f8522b from chromium (#25643)
Co-authored-by: Milan Burda <miburda@microsoft.com>
2020-09-29 16:06:22 -07:00
trop[bot]
4c8eb34bab fix: submenu should be autoreleased (#25689)
Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2020-09-29 15:48:23 -04:00
Milan Burda
14ded68b75 chore: cherry-pick 0e61c69ebd47 from chromium (#25658)
Co-authored-by: Milan Burda <miburda@microsoft.com>
2020-09-28 10:04:13 -07:00
trop[bot]
220b356233 refactor: add a wrapper for wrangling uv handles. (#25663) 2020-09-27 18:52:01 -07:00
Michaela Laurencin
858d74bc36 fix: prevent destroyed view references from causing crashes (#25609) 2020-09-25 09:42:58 -07:00
trop[bot]
c32cb09a68 chore: improve renderer crash logging (#25620)
Co-authored-by: Milan Burda <milan.burda@gmail.com>
2020-09-24 12:55:54 -07:00
Shelley Vohr
194edd0270 fix: check printer list when no default printers (#25607) 2020-09-23 15:44:23 -07:00
trop[bot]
6c3c9b5a51 fix: unsubscribe from observers when window is closing (#25586)
Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2020-09-23 10:02:19 -04:00
Samuel Maddock
a43d4cacde fix(extensions): devtools now open for background pages (#25567) 2020-09-22 07:12:32 -07:00
trop[bot]
a7372e8f53 fix: app.importCertificate crash on Linux (#25538)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-09-19 15:24:14 -06:00
Milan Burda
3aa207c2dc build: fix build with enable_pdf_viewer=false (#25494) (#25521) 2020-09-17 20:23:53 -06:00
trop[bot]
f96153a4d1 fix: disable CORS when webSecurity is disabled (#25505)
Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2020-09-17 14:55:56 -06:00
Shelley Vohr
1aeba811cc chore: add V8 crash information to crashReporter (#24864) 2020-09-17 12:08:24 -06:00
trop[bot]
f6dced63b5 fix: ensure ready-to-show event is fired (#25490)
Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2020-09-17 09:42:24 +09:00
Jeremy Rose
489aafc1f9 fix: call node::Stop on exit (#25502) 2020-09-17 09:39:35 +09:00
trop[bot]
a6ed6480d8 fix: update node certdata to NSS 3.56 (#25364)
* fix: update node certdata to NSS 3.56

* Update .patches

Co-authored-by: Jeremy Rose <nornagon@nornagon.net>
Co-authored-by: Jeremy Rose <jeremya@chromium.org>
2020-09-15 21:52:36 -06:00
trop[bot]
81c1a6ed29 chore: log hint on renderer crash (#25473)
* chore: log hint on renderer crash

* Address feedback from review

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-09-15 14:01:31 -06:00
Electron Bot
fe3378db92 Bump v9.3.1 2020-09-14 13:10:19 -07:00
Samuel Attard
fe85a94035 fix: handle electron script errors better (#25331) (#25453)
Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
2020-09-14 11:21:23 -07:00
trop[bot]
48779feb91 fix: Ensure electron delay loads the same modules as chromium (#25437)
* Ensure electron delay loads the appropriate modules as chromium on windows

This change adds the same module delay load list that chromium uses for electron.  Some modules were already getting delay loaded from other build files in chromium but not the main list via //build/config/win:delayloads.  We do not include the list of delay loads in delayloads_not_for_child_dll as those have issues being loaded in sandboxes processes.  This will reduce the overall reference set impact of the electron processes.

* fix: Ensure win modules are properly delayloaded

* chore: fix linting

Co-authored-by: Chris Davis <chrisdavis@outlook.com>
Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2020-09-14 09:05:27 -06:00
Cheng Zhao
5e289cee04 chore: cherry-pick 1283160e334f 0dc563cbbca5 from chromium (#25391) 2020-09-14 15:28:53 +09:00
Cheng Zhao
5f4ccec09a chore: cherry-pick c1a7439efcc7 from chromium (#25390) 2020-09-14 11:03:20 +09:00
Cheng Zhao
20f58fddf1 chore: cherry-pick 5e61913985df from chromium (#25389) 2020-09-14 09:50:03 +09:00
Jeremy Rose
75f193a089 fix: memory leak in net.request (#25382) 2020-09-10 11:40:53 +09:00
trop[bot]
7de2539399 fix: bind fake mojo service for badging (#25371)
* fix: bind fake mojo service for badging

* Add a test

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-09-10 09:14:34 +09:00
Charles Kerr
a90397f348 chore: sync 9-x-y release notes script to master (#25305)
* adds the '(Also in N-x-y)' annotations
* handle sublists in release notes (#25279)
* has prepare-release.js catch thrown exceptions (#24923)
* syncs related tests
2020-09-08 20:18:51 +09:00
Eryk Rakowski
6e734570ac feat(extensions): add support for some chrome.management APIs (#25344)
* feat(extensions): add support for some chrome.management APIs (#25098)

* fix: initialize management policy

* fix(extensions): crash when using chrome.management

* test: add tests

* docs: add a note about chrome.management

* fix: lint errors

* fix: lint errors

* fix: remove favicon_service include

* fix: add missing management permission

* docs: more supported apis

* fix: extensions.md line endings

* feat(extensions): add support for some chrome.management APIs (#25098)

* fix: initialize management policy

* fix(extensions): crash when using chrome.management

* test: add tests

* docs: add a note about chrome.management

* fix: lint errors

* fix: lint errors

* fix: remove favicon_service include

* fix: add missing management permission

* docs: more supported apis

* fix: extensions.md line endings

* Update electron_extensions_api_client.cc
2020-09-08 20:12:57 +09:00
Robo
79c1c8d21f fix: avoid creating client_id file for empty DIR_CRASH_DUMPS (#25316) 2020-09-03 18:46:29 -07:00
Cheng Zhao
35b348a7d7 fix: multiple dock icons when calling dock.show/hide (#25301) 2020-09-03 13:06:39 -07:00
Jeremy Rose
213f2fc838 chore: cherry-pick f6cb89728f04 from chromium (#25289) 2020-09-03 11:02:01 -07:00
Electron Bot
fb03807cd2 Bump v9.3.0 2020-09-02 18:08:24 -07:00
Electron Bot
89523b2504 Revert "Bump v9.3.0"
This reverts commit 243dbda31c.
2020-09-02 16:06:01 -07:00
Electron Bot
243dbda31c Bump v9.3.0 2020-09-02 15:02:59 -07:00
Electron Bot
587157e933 Revert "Bump v9.3.0"
This reverts commit 15f9300a64.
2020-09-02 14:51:38 -07:00
Electron Bot
15f9300a64 Bump v9.3.0 2020-09-02 14:23:38 -07:00
Jeremy Rose
88898acfef chore: cherry-pick 72ee7c437c88 from chromium (#25242) 2020-09-02 14:00:58 -07:00
Jeremy Rose
8a69889048 chore: cherry-pick 9ad8c9610d0a from chromium (#25240) 2020-09-02 12:02:49 -07:00
Jeremy Rose
b032c415c1 chore: cherry-pick 0dc563cbbca5 from chromium (#25238) 2020-09-02 11:56:47 -07:00
Jeremy Rose
e8643c1144 chore: cherry-pick 138b748dd0a4 from chromium (#25231) 2020-09-02 11:52:56 -07:00
Jeremy Rose
f8af08c279 chore: cherry-pick 9d100199c92b from chromium (#25229) 2020-09-02 10:31:34 -07:00
Jeremy Rose
713ff4c471 chore: cherry-pick c4f3b713800f from swiftshader (#25265) 2020-09-02 09:48:19 -07:00
Jeremy Rose
99abcba062 chore: cherry-pick af5b008a9546 from angle (#25263) 2020-09-02 09:48:03 -07:00
Jeremy Rose
086086b4e5 chore: cherry-pick bee371eeaf66 from chromium (#25226)
* chore: cherry-pick bee371eeaf66 from chromium

* update patches

Co-authored-by: Electron Bot <anonymous@electronjs.org>
2020-09-02 10:00:49 +09:00
Jeremy Rose
6e7425164f chore: cherry-pick e50772b2a25e from skia (#25245) 2020-09-01 14:21:06 -07:00
Jeremy Rose
4a03aa5bd2 chore: cherry-pick 44bb4d7abee6 from angle (#25233) 2020-09-01 14:19:58 -07:00
Jeremy Rose
99b4fd1ce0 chore: cherry-pick 9746a4cde14a from chromium (#25225)
* chore: cherry-pick 9746a4cde14a from chromium

* update patches

Co-authored-by: Electron Bot <anonymous@electronjs.org>
2020-09-01 14:17:47 -07:00
Jeremy Rose
a60211333c chore: cherry-pick 6b9a07d9eb9b from chromium (#25223) 2020-09-01 14:17:13 -07:00
trop[bot]
732ce44e61 chore: force source code and markdown files to use LF line ending (#25177)
* chore: force source code and markdown files to use LF line ending

* chore: replace CRLF with LF

Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2020-09-01 12:48:07 +09:00
Robo
0f70d096fc fix: crash when using v8 cpu_profiler with wasm in the renderer (#25220)
* fix: crash when using v8 cpu_profiler with wasm in the renderer

* update patches

Co-authored-by: Electron Bot <anonymous@electronjs.org>
2020-08-31 13:15:11 -07:00
Robo
56cde790e1 fix: Avoid loading DRI via GBM when GpuMemoryBuffers are disabled (#25221) 2020-08-31 13:04:31 -07:00
Robo
7dc7b3627f fix: client area inset calculation when maximized for framless windows (#25052) (#25218)
* adopt per monitor scale factor

* fix: client area inset calculation when maximized

* address review feedback

* pass correct glass insets to GetDwmFrameInsetsInPixels

* remove unused code

* Windows 8 and 10 use the same DWM frame calculation

Co-authored-by: Cheng Zhao <zcbenz@gmail.com>

Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2020-08-31 11:22:25 -07:00
trop[bot]
123f4087ca docs: fix supported platforms of powerMonitor (#25215)
Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2020-08-31 10:15:14 -07:00
Shelley Vohr
b5720bb2b8 feat: reinvigorate visibleOnFullscreen option (#25126) 2020-08-28 11:41:43 -07:00
trop[bot]
84f05ee0a4 fix: do not reset process_id in URLLoaderFactoryParams (#25179)
Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2020-08-28 11:37:27 -07:00
trop[bot]
694e8d8e66 fix: save dialog extensions should be deterministic (#25194)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-08-28 10:34:33 -07:00
Milan Burda
1529bf7ce5 fix: register for connected standby changes (#25076) (#25165)
Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2020-08-28 10:17:00 +09:00
Markus Olsson
d688b77187 fix: make shell.moveItemToTrash return false on Windows when move is unsuccessful (#25169)
* test: add tests for shell.moveItemToTrash (#25113)

* fix: make shell.moveItemToTrash return false on Windows when move unsuccessful (#25124)

Co-authored-by: Jeremy Rose <jeremya@chromium.org>
2020-08-27 13:07:19 -07:00
trop[bot]
7651036bce feat: expose currencyCode on Product struct in IAP module (#25085)
Co-authored-by: Shur Singh <ssingh@evernote.com>
2020-08-27 11:46:49 -07:00
Shelley Vohr
294825837c fix: save normal window bounds when maximizing (#25133)
* fix: save normal window bounds when maximizing

* fix: prevent maximize being emitted twice

Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2020-08-25 22:08:26 -07:00
Samuel Attard
945defd47e refactor: wire will-navigate up to a navigation throttle instead of OpenURL (#25109)
* refactor: wire will-navigate up to a navigation throttle instead of OpenURL (#25065)

* refactor: wire will-navigate up to a navigation throttle instead of OpenURL

* spec: add test for x-site _top navigation

* chore: old code be old
2020-08-25 19:22:13 +09:00
trop[bot]
cbd91b1fba fix: reply notifs sometimes destroyed too early (#25101)
* fix: reply notifs sometimes destroyed too early

* Fix windows build

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-08-24 08:47:30 -07:00
Eryk Rakowski
1aebbe9538 fix(extensions): enable WebSQL in background pages (#25070)
* fix(extensions): enable WebSQL in background pages

* fix: remove trailing spaces
2020-08-21 10:40:05 -07:00
trop[bot]
508d2cb1f5 fix: calculate frame when setting window placement (#25045)
Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2020-08-20 08:46:12 -07:00
trop[bot]
f769da64ad fix: enable TLS renegotiation in node (#25041)
* fix: enable TLS renegotiation in node

* Update .patches

* update patches

Co-authored-by: Jeremy Rose <nornagon@nornagon.net>
Co-authored-by: Jeremy Rose <jeremya@chromium.org>
Co-authored-by: Electron Bot <anonymous@electronjs.org>
2020-08-19 19:35:47 -07:00
Jeremy Rose
e16decd6a1 chore: cherry-pick 70579363ce7b from chromium (#25024)
* chore: cherry-pick 70579363ce7b from chromium

* update patches

Co-authored-by: Electron Bot <anonymous@electronjs.org>
2020-08-19 12:38:54 -07:00
Electron Bot
03c7a54dc5 Bump v9.2.1 2020-08-18 10:36:50 -07:00
Robo
eefcbda641 fix: [a11y] Allow focus to move into an editable combobox's listbox (#25004) 2020-08-18 10:33:08 -07:00
Eryk Rakowski
ea118c3984 fix(extensions): bypass cors in requests made from background pages (#24915) 2020-08-18 16:42:21 +09:00
trop[bot]
b204da6603 build: upload windows breakpad symbols (#25007)
Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2020-08-17 22:27:28 -07:00
Daniel White
cf321a9b55 chore: cherry-pick fix from chromium issue 1113227 (#24997) 2020-08-17 21:58:19 -07:00
trop[bot]
358d6e1116 fix: pdf download not working (#24996)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-08-17 19:49:37 -07:00
Jeremy Rose
12934c911f fix: browser contexts live forever (#25002) 2020-08-17 19:49:17 -07:00
trop[bot]
e2c4e341cc fix: loading dedicated/shared worker scripts over custom protocol (#24750)
* fix: add patch to avoid crash in worker with nodeintegration enabled

[worker_global_scope.cc(111)] Check failed: url_.IsValid().

* update patches

* ProtocolRegistry does not exist yet

* use custom partition for sw tests

Co-authored-by: deepak1556 <hop2deep@gmail.com>
Co-authored-by: Electron Bot <anonymous@electronjs.org>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-08-17 14:41:57 -04:00
trop[bot]
79f6ba4b18 fix: use non-symbols in isURLInstance check (#24862) 2020-08-17 08:55:34 -07:00
Pedro Pontes
3e835c1247 chore: cherry-pick c7c412a36c from webrtc (#24887) 2020-08-10 21:07:09 -07:00
Pedro Pontes
91849fccbe chore: cherry-pick 26df3fdc25 from v8 (#24885) 2020-08-10 20:24:16 -07:00
trop[bot]
8dc38cb973 fix: send guid with linux crashes (#24898) 2020-08-10 13:45:24 -07:00
trop[bot]
f799b6eb37 build: ensure symbol files are named lowercase on disk so that boto can find them (#24858)
* build: ensure symbol files are named lowercase on disk so that boto can find them

* build: only do the lower case symbol copy on case sensitive file systems (#24876)

Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
Co-authored-by: Samuel Attard <sattard@slack-corp.com>
2020-08-07 13:51:49 -07:00
trop[bot]
7063ba73df fix: do not render inactive titlebar as active on Windows (#24873)
Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2020-08-06 20:46:59 -07:00
Jeremy Rose
f01bb5f43b fix: increase max crash key value length (#24854) 2020-08-06 08:02:46 -07:00
349 changed files with 15722 additions and 2373 deletions

View File

@@ -61,7 +61,7 @@ parameters:
# Build machines configs.
docker-image: &docker-image
docker:
- image: electronjs/build:d09fd95029bd8c1c73069888231b29688ef385ed
- image: electron.azurecr.io/build:4cec2c5ab66765caa724e37bae2bffb9b29722a5
machine-linux-medium: &machine-linux-medium
<<: *docker-image
@@ -90,6 +90,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'
@@ -228,23 +229,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
@@ -271,10 +283,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
@@ -283,7 +295,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
@@ -538,10 +550,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

10
.gitattributes vendored
View File

@@ -2,3 +2,13 @@
# files to be checked out with LF endings even if core.autocrlf is true.
*.patch text eol=lf
patches/**/.patches merge=union
# Source code and markdown files should always use LF as line ending.
*.cc text eol=lf
*.mm text eol=lf
*.h text eol=lf
*.js text eol=lf
*.ts text eol=lf
*.py text eol=lf
*.ps1 text eol=lf
*.md text eol=lf

View File

@@ -1115,20 +1115,17 @@ if (is_mac) {
"//components/crash/core/app:run_as_crashpad_handler",
]
ldflags = []
libs = [
"comctl32.lib",
"uiautomationcore.lib",
"wtsapi32.lib",
]
configs += [ "//build/config/win:windowed" ]
ldflags = [
# Windows 7 doesn't have these DLLs.
# TODO: are there other DLLs we need to list here to be win7
# compatible?
"/DELAYLOAD:api-ms-win-core-winrt-l1-1-0.dll",
"/DELAYLOAD:api-ms-win-core-winrt-string-l1-1-0.dll",
configs += [
"//build/config/win:windowed",
"//build/config/win:delayloads",
]
# This is to support renaming of electron.exe. node-gyp has hard-coded

View File

@@ -1 +1 @@
9.2.0
9.4.0

View File

@@ -53,7 +53,9 @@ build_script:
} else {
node script/yarn.js install --frozen-lockfile
if ($(node script/doc-only-change.js --prNumber=$env:APPVEYOR_PULL_REQUEST_NUMBER --prBranch=$env:APPVEYOR_REPO_BRANCH;$LASTEXITCODE -eq 0)) {
$result = node script/doc-only-change.js --prNumber=$env:APPVEYOR_PULL_REQUEST_NUMBER --prBranch=$env:APPVEYOR_REPO_BRANCH
Write-Output $result
if ($result.ExitCode -eq 0) {
Write-warning "Skipping build for doc only change"; Exit-AppveyorBuild
}
}
@@ -127,7 +129,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 ..
@@ -212,10 +214,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

@@ -10,10 +10,9 @@ config.output = {
filename: path.basename(outPath)
}
const { wrapInitWithProfilingTimeout } = config;
delete config.wrapInitWithProfilingTimeout;
const { wrapInitWithProfilingTimeout, wrapInitWithTryCatch, ...webpackConfig } = config;
webpack(config, (err, stats) => {
webpack(webpackConfig, (err, stats) => {
if (err) {
console.error(err)
process.exit(1)
@@ -21,9 +20,17 @@ webpack(config, (err, stats) => {
console.error(stats.toString('normal'))
process.exit(1)
} else {
let contents = fs.readFileSync(outPath, 'utf8');
if (wrapInitWithTryCatch) {
contents = `try {
${contents}
} catch (err) {
console.error('Electron ${webpackConfig.output.filename} script failed to run');
console.error(err);
}`;
}
if (wrapInitWithProfilingTimeout) {
const contents = fs.readFileSync(outPath, 'utf8');
const newContents = `function ___electron_webpack_init__() {
contents = `function ___electron_webpack_init__() {
${contents}
};
if ((globalThis.process || binding.process).argv.includes("--profile-electron-init")) {
@@ -31,8 +38,8 @@ if ((globalThis.process || binding.process).argv.includes("--profile-electron-in
} else {
___electron_webpack_init__();
}`;
fs.writeFileSync(outPath, newContents);
}
fs.writeFileSync(outPath, contents)
process.exit(0)
}
})

View File

@@ -86,7 +86,8 @@ module.exports = ({
loadElectronFromAlternateTarget,
targetDeletesNodeGlobals,
target,
wrapInitWithProfilingTimeout
wrapInitWithProfilingTimeout,
wrapInitWithTryCatch
}) => {
let entry = path.resolve(electronRoot, 'lib', target, 'init.ts')
if (!fs.existsSync(entry)) {
@@ -102,6 +103,7 @@ module.exports = ({
filename: `${target}.bundle.js`
},
wrapInitWithProfilingTimeout,
wrapInitWithTryCatch,
resolve: {
alias: {
'@electron/internal': path.resolve(electronRoot, 'lib'),

View File

@@ -1,4 +1,5 @@
module.exports = require('./webpack.config.base')({
target: 'isolated_renderer',
alwaysHasNode: false
alwaysHasNode: false,
wrapInitWithTryCatch: true
})

View File

@@ -2,5 +2,6 @@ module.exports = require('./webpack.config.base')({
target: 'renderer',
alwaysHasNode: true,
targetDeletesNodeGlobals: true,
wrapInitWithProfilingTimeout: true
wrapInitWithProfilingTimeout: true,
wrapInitWithTryCatch: true
})

View File

@@ -2,4 +2,5 @@ module.exports = require('./webpack.config.base')({
target: 'sandboxed_renderer',
alwaysHasNode: false,
wrapInitWithProfilingTimeout: true,
wrapInitWithTryCatch: true
})

View File

@@ -2,5 +2,6 @@ module.exports = require('./webpack.config.base')({
target: 'worker',
loadElectronFromAlternateTarget: 'renderer',
alwaysHasNode: true,
targetDeletesNodeGlobals: true
targetDeletesNodeGlobals: true,
wrapInitWithTryCatch: true
})

View File

@@ -36,6 +36,7 @@ net::NSSCertDatabase* GetNSSCertDatabaseForResourceContext(
// Linux has only a single persistent slot compared to ChromeOS's separate
// public and private slot.
// Redirect any slot usage to this persistent slot on Linux.
crypto::EnsureNSSInit();
g_nss_cert_database = new net::NSSCertDatabase(
crypto::ScopedPK11Slot(PK11_GetInternalKeySlot()) /* public slot */,
crypto::ScopedPK11Slot(PK11_GetInternalKeySlot()) /* private slot */);

View File

@@ -827,10 +827,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 xids with
// the system.
for (std::set<unsigned long>::const_iterator it = live_xids_.begin();
it != live_xids_.end(); ++it) {
RegisterXID(*it);
for (auto xid : live_xids_) {
RegisterXID(xid);
}
}

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
@@ -382,7 +383,7 @@ Returns:
* `killed` - Process was sent a SIGTERM or otherwise killed externally
* `crashed` - Process crashed
* `oom` - Process ran out of memory
* `launch-failure` - Process never successfully launched
* `launch-failed` - Process never successfully launched
* `integrity-failure` - Windows code integrity checks failed
Emitted when the renderer process unexpectedly dissapears. This is normally
@@ -1259,7 +1260,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

View File

@@ -1669,9 +1669,12 @@ Sets whether the menu bar should be visible. If the menu bar is auto-hide, users
Returns `Boolean` - Whether the menu bar is visible.
#### `win.setVisibleOnAllWorkspaces(visible)`
#### `win.setVisibleOnAllWorkspaces(visible[, options])`
* `visible` Boolean
* `options` Object (optional)
* `visibleOnFullScreen` Boolean (optional) _macOS_ - Sets whether
the window should be visible above fullscreen windows
Sets whether the window should be visible on all workspaces.

View File

@@ -157,10 +157,16 @@ parameters in a renderer process will not result in those parameters being sent
with crashes that occur in other renderer processes or in the main process.
**Note:** Parameters have limits on the length of the keys and values. Key
names must be no longer than 39 bytes, and values must be no longer than 127
names must be no longer than 39 bytes, and values must be no longer than 20320
bytes. Keys with names longer than the maximum will be silently ignored. Key
values longer than the maximum length will be truncated.
**Note:** On linux values that are longer than 127 bytes will be chunked into
multiple keys, each 127 bytes in length. E.g. `addExtraParameter('foo', 'a'.repeat(130))`
will result in two chunked keys `foo__1` and `foo__2`, the first will contain
the first 127 bytes and the second will contain the remaining 3 bytes. On
your crash reporting backend you should stitch together keys in this format.
### `crashReporter.removeExtraParameter(key)`
* `key` String - Parameter key, must be no longer than 39 bytes.

View File

@@ -28,6 +28,9 @@ session.loadExtension('path/to/unpacked/extension').then(({ id }) => {
Loaded extensions will not be automatically remembered across exits; if you do
not call `loadExtension` when the app runs, the extension will not be loaded.
Note that loading extensions is only supported in persistent sessions.
Attempting to load an extension into an in-memory session will throw an error.
See the [`session`](session.md) documentation for more information about
loading, unloading, and querying active extensions.
@@ -99,3 +102,15 @@ The following methods of `chrome.tabs` are supported:
> **Note:** In Chrome, passing `-1` as a tab ID signifies the "currently active
> tab". Since Electron has no such concept, passing `-1` as a tab ID is not
> supported and will raise an error.
### `chrome.management`
The following methods of `chrome.management` are supported:
- `chrome.management.getAll`
- `chrome.management.get`
- `chrome.management.getSelf`
- `chrome.management.getPermissionWarningsById`
- `chrome.management.getPermissionWarningsByManifest`
- `chrome.management.onEnabled`
- `chrome.management.onDisabled`

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

@@ -24,19 +24,19 @@ app.whenReady().then(() => {
The `powerMonitor` module emits the following events:
### Event: 'suspend' _Linux_ _Windows_
### Event: 'suspend' _macOS_ _Windows_
Emitted when the system is suspending.
### Event: 'resume' _Linux_ _Windows_
### Event: 'resume' _macOS_ _Windows_
Emitted when system is resuming.
### Event: 'on-ac' _Windows_
### Event: 'on-ac' _macOS_ _Windows_
Emitted when the system changes to AC power.
### Event: 'on-battery' _Windows_
### Event: 'on-battery' _macOS_ _Windows_
Emitted when system changes to battery power.

View File

@@ -376,7 +376,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

@@ -7,4 +7,5 @@
* `contentLengths` Number[] - The total size of the content, in bytes.
* `price` Number - The cost of the product in the local currency.
* `formattedPrice` String - The locale formatted price of the product.
* `currencyCode` String - 3 character code presenting a product's currency based on the ISO 4217 standard.
* `isDownloadable` Boolean - A Boolean value that indicates whether the App Store has downloadable content for this product. `true` if at least one file has been associated with the product.

View File

@@ -351,7 +351,7 @@ Returns:
* `killed` - Process was sent a SIGTERM or otherwise killed externally
* `crashed` - Process crashed
* `oom` - Process ran out of memory
* `launch-failure` - Process never successfully launched
* `launch-failed` - Process never successfully launched
* `integrity-failure` - Windows code integrity checks failed
Emitted when the renderer process unexpectedly dissapears. This is normally
@@ -1570,7 +1570,7 @@ app.whenReady().then(() => {
#### `contents.sendToFrame(frameId, channel, ...args)`
* `frameId` Integer
* `frameId` Integer | [number, number]
* `channel` String
* `...args` any[]

View File

@@ -1,61 +0,0 @@
# Breaking changes (NetworkService) (Draft)
This document describes changes to Electron APIs after migrating network code
to NetworkService API.
We don't currently have an estimate of when we will enable `NetworkService` by
default in Electron, but as Chromium is already removing non-`NetworkService`
code, we might switch before Electron 10.
The content of this document should be moved to `breaking-changes.md` once we have
determined when to enable `NetworkService` in Electron.
## Planned Breaking API Changes
### `protocol.unregisterProtocol`
### `protocol.uninterceptProtocol`
The APIs are now synchronous and the optional callback is no longer needed.
```javascript
// Deprecated
protocol.unregisterProtocol(scheme, () => { /* ... */ })
// Replace with
protocol.unregisterProtocol(scheme)
```
### `protocol.registerFileProtocol`
### `protocol.registerBufferProtocol`
### `protocol.registerStringProtocol`
### `protocol.registerHttpProtocol`
### `protocol.registerStreamProtocol`
### `protocol.interceptFileProtocol`
### `protocol.interceptStringProtocol`
### `protocol.interceptBufferProtocol`
### `protocol.interceptHttpProtocol`
### `protocol.interceptStreamProtocol`
The APIs are now synchronous and the optional callback is no longer needed.
```javascript
// Deprecated
protocol.registerFileProtocol(scheme, handler, () => { /* ... */ })
// Replace with
protocol.registerFileProtocol(scheme, handler)
```
The registered or intercepted protocol does not have effect on current page
until navigation happens.
### `protocol.isProtocolHandled`
This API is deprecated and users should use `protocol.isProtocolRegistered`
and `protocol.isProtocolIntercepted` instead.
```javascript
// Deprecated
protocol.isProtocolHandled(scheme).then(() => { /* ... */ })
// Replace with
const isRegistered = protocol.isProtocolRegistered(scheme)
const isIntercepted = protocol.isProtocolIntercepted(scheme)
```

View File

@@ -105,6 +105,54 @@ const w = new BrowserWindow({
We [recommend moving away from the remote
module](https://medium.com/@nornagon/electrons-remote-module-considered-harmful-70d69500f31).
### `protocol.unregisterProtocol`
### `protocol.uninterceptProtocol`
The APIs are now synchronous and the optional callback is no longer needed.
```javascript
// Deprecated
protocol.unregisterProtocol(scheme, () => { /* ... */ })
// Replace with
protocol.unregisterProtocol(scheme)
```
### `protocol.registerFileProtocol`
### `protocol.registerBufferProtocol`
### `protocol.registerStringProtocol`
### `protocol.registerHttpProtocol`
### `protocol.registerStreamProtocol`
### `protocol.interceptFileProtocol`
### `protocol.interceptStringProtocol`
### `protocol.interceptBufferProtocol`
### `protocol.interceptHttpProtocol`
### `protocol.interceptStreamProtocol`
The APIs are now synchronous and the optional callback is no longer needed.
```javascript
// Deprecated
protocol.registerFileProtocol(scheme, handler, () => { /* ... */ })
// Replace with
protocol.registerFileProtocol(scheme, handler)
```
The registered or intercepted protocol does not have effect on current page
until navigation happens.
### `protocol.isProtocolHandled`
This API is deprecated and users should use `protocol.isProtocolRegistered`
and `protocol.isProtocolIntercepted` instead.
```javascript
// Deprecated
protocol.isProtocolHandled(scheme).then(() => { /* ... */ })
// Replace with
const isRegistered = protocol.isProtocolRegistered(scheme)
const isIntercepted = protocol.isProtocolIntercepted(scheme)
```
## Planned Breaking API Changes (9.0)
### Default Changed: Loading non-context-aware native modules in the renderer process is disabled by default
@@ -119,6 +167,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.

View File

@@ -186,12 +186,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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,13 +1,13 @@
const { shell } = require('electron')
const os = require('os')
const exLinksBtn = document.getElementById('open-ex-links')
const fileManagerBtn = document.getElementById('open-file-manager')
fileManagerBtn.addEventListener('click', (event) => {
shell.showItemInFolder(os.homedir())
})
exLinksBtn.addEventListener('click', (event) => {
shell.openExternal('http://electron.atom.io')
const { shell } = require('electron')
const os = require('os')
const exLinksBtn = document.getElementById('open-ex-links')
const fileManagerBtn = document.getElementById('open-file-manager')
fileManagerBtn.addEventListener('click', (event) => {
shell.showItemInFolder(os.homedir())
})
exLinksBtn.addEventListener('click', (event) => {
shell.openExternal('http://electron.atom.io')
})

View File

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

View File

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

File diff suppressed because one or more lines are too long

View File

@@ -1,35 +1,35 @@
const { ipcRenderer, shell } = require('electron')
const trayBtn = document.getElementById('put-in-tray')
const links = document.querySelectorAll('a[href]')
let trayOn = false
trayBtn.addEventListener('click', function (event) {
if (trayOn) {
trayOn = false
document.getElementById('tray-countdown').innerHTML = ''
ipcRenderer.send('remove-tray')
} else {
trayOn = true
const message = 'Click demo again to remove.'
document.getElementById('tray-countdown').innerHTML = message
ipcRenderer.send('put-in-tray')
}
})
// Tray removed from context menu on icon
ipcRenderer.on('tray-removed', function () {
ipcRenderer.send('remove-tray')
trayOn = false
document.getElementById('tray-countdown').innerHTML = ''
})
Array.prototype.forEach.call(links, (link) => {
const url = link.getAttribute('href')
if (url.indexOf('http') === 0) {
link.addEventListener('click', (e) => {
e.preventDefault()
shell.openExternal(url)
})
}
const { ipcRenderer, shell } = require('electron')
const trayBtn = document.getElementById('put-in-tray')
const links = document.querySelectorAll('a[href]')
let trayOn = false
trayBtn.addEventListener('click', function (event) {
if (trayOn) {
trayOn = false
document.getElementById('tray-countdown').innerHTML = ''
ipcRenderer.send('remove-tray')
} else {
trayOn = true
const message = 'Click demo again to remove.'
document.getElementById('tray-countdown').innerHTML = message
ipcRenderer.send('put-in-tray')
}
})
// Tray removed from context menu on icon
ipcRenderer.on('tray-removed', function () {
ipcRenderer.send('remove-tray')
trayOn = false
document.getElementById('tray-countdown').innerHTML = ''
})
Array.prototype.forEach.call(links, (link) => {
const url = link.getAttribute('href')
if (url.indexOf('http') === 0) {
link.addEventListener('click', (e) => {
e.preventDefault()
shell.openExternal(url)
})
}
})

View File

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

View File

@@ -1,25 +1,25 @@
const { BrowserWindow } = require('electron').remote
const shell = require('electron').shell
const framelessWindowBtn = document.getElementById('frameless-window')
const links = document.querySelectorAll('a[href]')
framelessWindowBtn.addEventListener('click', (event) => {
const modalPath = 'https://electronjs.org'
let win = new BrowserWindow({ frame: false })
win.on('close', () => { win = null })
win.loadURL(modalPath)
win.show()
})
Array.prototype.forEach.call(links, (link) => {
const url = link.getAttribute('href')
if (url.indexOf('http') === 0) {
link.addEventListener('click', (e) => {
e.preventDefault()
shell.openExternal(url)
})
}
})
const { BrowserWindow } = require('electron').remote
const shell = require('electron').shell
const framelessWindowBtn = document.getElementById('frameless-window')
const links = document.querySelectorAll('a[href]')
framelessWindowBtn.addEventListener('click', (event) => {
const modalPath = 'https://electronjs.org'
let win = new BrowserWindow({ frame: false })
win.on('close', () => { win = null })
win.loadURL(modalPath)
win.show()
})
Array.prototype.forEach.call(links, (link) => {
const url = link.getAttribute('href')
if (url.indexOf('http') === 0) {
link.addEventListener('click', (e) => {
e.preventDefault()
shell.openExternal(url)
})
}
})

View File

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

View File

@@ -1,35 +1,35 @@
const { BrowserWindow } = require('electron').remote
const shell = require('electron').shell
const manageWindowBtn = document.getElementById('manage-window')
const links = document.querySelectorAll('a[href]')
let win
manageWindowBtn.addEventListener('click', (event) => {
const modalPath = 'https://electronjs.org'
win = new BrowserWindow({ width: 400, height: 275 })
win.on('resize', updateReply)
win.on('move', updateReply)
win.on('close', () => { win = null })
win.loadURL(modalPath)
win.show()
function updateReply () {
const manageWindowReply = document.getElementById('manage-window-reply')
const message = `Size: ${win.getSize()} Position: ${win.getPosition()}`
manageWindowReply.innerText = message
}
})
Array.prototype.forEach.call(links, (link) => {
const url = link.getAttribute('href')
if (url.indexOf('http') === 0) {
link.addEventListener('click', (e) => {
e.preventDefault()
shell.openExternal(url)
})
}
})
const { BrowserWindow } = require('electron').remote
const shell = require('electron').shell
const manageWindowBtn = document.getElementById('manage-window')
const links = document.querySelectorAll('a[href]')
let win
manageWindowBtn.addEventListener('click', (event) => {
const modalPath = 'https://electronjs.org'
win = new BrowserWindow({ width: 400, height: 275 })
win.on('resize', updateReply)
win.on('move', updateReply)
win.on('close', () => { win = null })
win.loadURL(modalPath)
win.show()
function updateReply () {
const manageWindowReply = document.getElementById('manage-window-reply')
const message = `Size: ${win.getSize()} Position: ${win.getPosition()}`
manageWindowReply.innerText = message
}
})
Array.prototype.forEach.call(links, (link) => {
const url = link.getAttribute('href')
if (url.indexOf('http') === 0) {
link.addEventListener('click', (e) => {
e.preventDefault()
shell.openExternal(url)
})
}
})

View File

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

View File

@@ -1,48 +1,48 @@
const { BrowserWindow } = require('electron').remote
const shell = require('electron').shell
const listenToWindowBtn = document.getElementById('listen-to-window')
const focusModalBtn = document.getElementById('focus-on-modal-window')
const links = document.querySelectorAll('a[href]')
let win
listenToWindowBtn.addEventListener('click', () => {
const modalPath = 'https://electronjs.org'
win = new BrowserWindow({ width: 600, height: 400 })
const hideFocusBtn = () => {
focusModalBtn.classList.add('disappear')
focusModalBtn.classList.remove('smooth-appear')
focusModalBtn.removeEventListener('click', clickHandler)
}
const showFocusBtn = (btn) => {
if (!win) return
focusModalBtn.classList.add('smooth-appear')
focusModalBtn.classList.remove('disappear')
focusModalBtn.addEventListener('click', clickHandler)
}
win.on('focus', hideFocusBtn)
win.on('blur', showFocusBtn)
win.on('close', () => {
hideFocusBtn()
win = null
})
win.loadURL(modalPath)
win.show()
const clickHandler = () => { win.focus() }
})
Array.prototype.forEach.call(links, (link) => {
const url = link.getAttribute('href')
if (url.indexOf('http') === 0) {
link.addEventListener('click', (e) => {
e.preventDefault()
shell.openExternal(url)
})
}
})
const { BrowserWindow } = require('electron').remote
const shell = require('electron').shell
const listenToWindowBtn = document.getElementById('listen-to-window')
const focusModalBtn = document.getElementById('focus-on-modal-window')
const links = document.querySelectorAll('a[href]')
let win
listenToWindowBtn.addEventListener('click', () => {
const modalPath = 'https://electronjs.org'
win = new BrowserWindow({ width: 600, height: 400 })
const hideFocusBtn = () => {
focusModalBtn.classList.add('disappear')
focusModalBtn.classList.remove('smooth-appear')
focusModalBtn.removeEventListener('click', clickHandler)
}
const showFocusBtn = (btn) => {
if (!win) return
focusModalBtn.classList.add('smooth-appear')
focusModalBtn.classList.remove('disappear')
focusModalBtn.addEventListener('click', clickHandler)
}
win.on('focus', hideFocusBtn)
win.on('blur', showFocusBtn)
win.on('close', () => {
hideFocusBtn()
win = null
})
win.loadURL(modalPath)
win.show()
const clickHandler = () => { win.focus() }
})
Array.prototype.forEach.call(links, (link) => {
const url = link.getAttribute('href')
if (url.indexOf('http') === 0) {
link.addEventListener('click', (e) => {
e.preventDefault()
shell.openExternal(url)
})
}
})

View File

@@ -178,6 +178,7 @@ filenames = {
"shell/browser/electron_speech_recognition_manager_delegate.h",
"shell/browser/electron_web_ui_controller_factory.cc",
"shell/browser/electron_web_ui_controller_factory.h",
"shell/browser/extended_web_contents_observer.h",
"shell/browser/feature_list.cc",
"shell/browser/feature_list.h",
"shell/browser/font_defaults.cc",
@@ -338,6 +339,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/drag_util_mac.mm",
"shell/browser/ui/drag_util_views.cc",
@@ -614,6 +616,8 @@ filenames = {
"shell/browser/extensions/api/resources_private/resources_private_api.h",
"shell/browser/extensions/api/runtime/electron_runtime_api_delegate.cc",
"shell/browser/extensions/api/runtime/electron_runtime_api_delegate.h",
"shell/browser/extensions/api/management/electron_management_api_delegate.cc",
"shell/browser/extensions/api/management/electron_management_api_delegate.h",
"shell/browser/extensions/api/tabs/tabs_api.cc",
"shell/browser/extensions/api/tabs/tabs_api.h",
"shell/browser/extensions/api/streams_private/streams_private_api.cc",

View File

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

View File

@@ -166,29 +166,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.
@@ -437,8 +437,9 @@ WebContents.prototype.loadFile = function (filePath, options = {}) {
};
const addReplyToEvent = (event) => {
const { processId, frameId } = event;
event.reply = (...args) => {
event.sender.sendToFrame(event.frameId, ...args);
event.sender.sendToFrame([processId, frameId], ...args);
};
};
@@ -459,6 +460,10 @@ const addReturnValueToEvent = (event) => {
});
};
const loggingEnabled = () => {
return process.env.ELECTRON_ENABLE_LOGGING || app.commandLine.hasSwitch('enable-logging');
};
// Add JavaScript wrappers for WebContents class.
WebContents.prototype._init = function () {
// The navigation controller.
@@ -527,8 +532,13 @@ WebContents.prototype._init = function () {
app.emit('renderer-process-crashed', event, this, ...args);
});
this.on('render-process-gone', (event, ...args) => {
app.emit('render-process-gone', event, this, ...args);
this.on('render-process-gone', (event, details) => {
app.emit('render-process-gone', event, this, details);
// Log out a hint to help users better debug renderer crashes.
if (loggingEnabled()) {
console.info(`Renderer process ${details.reason} - see https://www.electronjs.org/docs/tutorial/application-debugging for potential debugging information.`);
}
});
// The devtools requests the webContents to reload.

View File

@@ -275,7 +275,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':
@@ -329,7 +329,7 @@ const unwrapArgs = function (sender: electron.WebContents, frameId: number, cont
v8Util.setHiddenValue(callIntoRenderer, 'location', meta.location);
Object.defineProperty(callIntoRenderer, 'length', { value: meta.length });
v8Util.setRemoteCallbackFreer(callIntoRenderer, frameId, contextId, meta.id, sender);
v8Util.setRemoteCallbackFreer(callIntoRenderer, frameId[0], frameId[1], contextId, meta.id, sender);
rendererFunctions.set(objectId, callIntoRenderer);
return callIntoRenderer;
}
@@ -478,7 +478,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) {
@@ -489,7 +489,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) {
@@ -506,7 +506,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) {
@@ -517,7 +517,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) {
@@ -534,7 +534,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

@@ -33,10 +33,10 @@ Object.defineProperty(electronModule, 'exports', {
Module._cache['electron'] = electronModule;
const originalResolveFilename = Module._resolveFilename;
Module._resolveFilename = function (request: string, parent: NodeModule, isMain: boolean) {
Module._resolveFilename = function (request: string, parent: NodeModule, isMain: boolean, options?: { paths: Array<string>}) {
if (request === 'electron') {
return 'electron';
} else {
return originalResolveFilename(request, parent, isMain);
return originalResolveFilename(request, parent, isMain, options);
}
};

View File

@@ -279,7 +279,7 @@ function metaToError (meta) {
}
function handleMessage (channel, handler) {
ipcRendererInternal.on(channel, (event, passedContextId, id, ...args) => {
ipcRendererInternal.onMessageFromMain(channel, (event, passedContextId, id, ...args) => {
if (passedContextId === contextId) {
handler(id, ...args);
} else {

View File

@@ -73,7 +73,7 @@ export function injectTo (extensionId: string, context: any) {
const chrome = context.chrome = context.chrome || {};
ipcRendererInternal.on(`CHROME_RUNTIME_ONCONNECT_${extensionId}`, (
ipcRendererInternal.onMessageFromMain(`CHROME_RUNTIME_ONCONNECT_${extensionId}`, (
_event: Electron.Event, tabId: number, portId: number, connectInfo: { name: string }
) => {
chrome.runtime.onConnect.emit(new Port(tabId, portId, extensionId, connectInfo.name));
@@ -87,11 +87,11 @@ export function injectTo (extensionId: string, context: any) {
});
});
ipcRendererInternal.on('CHROME_TABS_ONCREATED', (_event: Electron.Event, tabId: number) => {
ipcRendererInternal.onMessageFromMain('CHROME_TABS_ONCREATED', (_event: Electron.Event, tabId: number) => {
chrome.tabs.onCreated.emit(new Tab(tabId));
});
ipcRendererInternal.on('CHROME_TABS_ONREMOVED', (_event: Electron.Event, tabId: number) => {
ipcRendererInternal.onMessageFromMain('CHROME_TABS_ONREMOVED', (_event: Electron.Event, tabId: number) => {
chrome.tabs.onRemoved.emit(tabId);
});

View File

@@ -6,11 +6,11 @@ class WebNavigation {
private onCompleted = new Event()
constructor () {
ipcRendererInternal.on('CHROME_WEBNAVIGATION_ONBEFORENAVIGATE', (event: Electron.IpcRendererEvent, details: any) => {
ipcRendererInternal.onMessageFromMain('CHROME_WEBNAVIGATION_ONBEFORENAVIGATE', (event: Electron.IpcRendererEvent, details: any) => {
this.onBeforeNavigate.emit(details);
});
ipcRendererInternal.on('CHROME_WEBNAVIGATION_ONCOMPLETED', (event: Electron.IpcRendererEvent, details: any) => {
ipcRendererInternal.onMessageFromMain('CHROME_WEBNAVIGATION_ONCOMPLETED', (event: Electron.IpcRendererEvent, details: any) => {
this.onCompleted.emit(details);
});
}

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 @@ if (!ipcRendererInternal.send) {
}
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);
});
};
}

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

@@ -180,7 +180,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;
});
@@ -280,7 +280,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
@@ -335,7 +335,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": "9.2.0",
"version": "9.4.0",
"repository": "https://github.com/electron/electron",
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
"devDependencies": {
"@electron/docs-parser": "^0.4.2",
"@electron/typescript-definitions": "^8.6.4",
"@octokit/auth-app": "^2.10.0",
"@octokit/rest": "^16.3.2",
"@primer/octicons": "^9.1.1",
"@types/basic-auth": "^1.1.2",

3
patches/angle/.patches Normal file
View File

@@ -0,0 +1,3 @@
fix_stale_validation_cache_on_buffer_deletion.patch
d3d11_fix_bug_with_static_vertex_attributes.patch
cherry-pick-2882e1afd982.patch

View File

@@ -0,0 +1,35 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jamie Madill <jmadill@chromium.org>
Date: Tue, 20 Oct 2020 09:45:23 -0400
Subject: Fix missing validation cache update on VAO binding.
Bug: chromium:1139398
Change-Id: I85a0d7a72bc2c97b07ebc5f86effd8e36aefd544
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2485581
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Commit-Queue: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp
index 3233d12dd233786b0988f299ace57d932e0d0fe6..0bdc3f6e5e8ebfcc6bbb2ff1bef57a1d50736368 100644
--- a/src/libANGLE/Context.cpp
+++ b/src/libANGLE/Context.cpp
@@ -8441,6 +8441,7 @@ void StateCache::onVertexArrayBindingChange(Context *context)
updateActiveAttribsMask(context);
updateVertexElementLimits(context);
updateBasicDrawStatesError();
+ updateBasicDrawElementsError();
}
void StateCache::onProgramExecutableChange(Context *context)
diff --git a/src/libANGLE/Context.h b/src/libANGLE/Context.h
index 06eeff3b94c937067e674fc127afdeab34e63f21..1e61266921bc7aafb26388b12d0aa1b914c4b5a9 100644
--- a/src/libANGLE/Context.h
+++ b/src/libANGLE/Context.h
@@ -203,6 +203,7 @@ class StateCache final : angle::NonCopyable
// 2. onVertexArrayBufferStateChange.
// 3. onBufferBindingChange.
// 4. onVertexArrayStateChange.
+ // 5. onVertexArrayBindingStateChange.
intptr_t getBasicDrawElementsError(const Context *context) const
{
if (mCachedBasicDrawElementsError != kInvalidPointer)

View File

@@ -0,0 +1,41 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jamie Madill <jmadill@chromium.org>
Date: Wed, 22 Jul 2020 13:58:50 -0400
Subject: D3D11: Fix bug with static vertex attributes.
In some specific cases after binding a zero size buffer we could end
up trying to use a buffer storage that was no longer valid. Fix this
by ensuring we don't flush dirty bits when we have an early exit due
to a zero size buffer.
Also adds a regression test.
Bug: chromium:1107433
Change-Id: I9db560e8dd3699abed2bb7fe6d91060148ba1817
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2314216
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp b/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp
index 5f834b5c8dbc63d3bcc374eca15a17ee442d77e3..b0e27c9f0c6c316fe347a44776a6926b093a81c4 100644
--- a/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp
@@ -250,8 +250,6 @@ angle::Result VertexArray11::updateDirtyAttribs(const gl::Context *context,
for (size_t dirtyAttribIndex : activeDirtyAttribs)
{
- mAttribsToTranslate.reset(dirtyAttribIndex);
-
auto *translatedAttrib = &mTranslatedAttribs[dirtyAttribIndex];
const auto &currentValue = glState.getVertexAttribCurrentValue(dirtyAttribIndex);
@@ -279,6 +277,9 @@ angle::Result VertexArray11::updateDirtyAttribs(const gl::Context *context,
UNREACHABLE();
break;
}
+
+ // Make sure we reset the dirty bit after the switch because STATIC can early exit.
+ mAttribsToTranslate.reset(dirtyAttribIndex);
}
return angle::Result::Continue;

View File

@@ -0,0 +1,39 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jamie Madill <jmadill@chromium.org>
Date: Tue, 14 Jul 2020 17:20:18 -0400
Subject: Fix stale validation cache on buffer deletion.
When we would delete the currently bound element array buffer we
would neglect to invalidate a specific validation cache variable.
This incorrectly would let us skip buffer size validation and lead
to internal invalid memory accesses.
Bug: chromium:1105202
Change-Id: I23ab28ccd3ac6b5d461cb8745b930f4d42d53b35
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2323644
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp
index d8bccaf1e920e261c45c777993b77b8c40a011ad..3233d12dd233786b0988f299ace57d932e0d0fe6 100644
--- a/src/libANGLE/Context.cpp
+++ b/src/libANGLE/Context.cpp
@@ -8468,6 +8468,7 @@ void StateCache::onVertexArrayStateChange(Context *context)
updateActiveAttribsMask(context);
updateVertexElementLimits(context);
updateBasicDrawStatesError();
+ updateBasicDrawElementsError();
}
void StateCache::onVertexArrayBufferStateChange(Context *context)
diff --git a/src/libANGLE/Context.h b/src/libANGLE/Context.h
index 201010f9f5555faa79cab480a34caf63bf5ffbf2..06eeff3b94c937067e674fc127afdeab34e63f21 100644
--- a/src/libANGLE/Context.h
+++ b/src/libANGLE/Context.h
@@ -202,6 +202,7 @@ class StateCache final : angle::NonCopyable
// 1. onActiveTransformFeedbackChange.
// 2. onVertexArrayBufferStateChange.
// 3. onBufferBindingChange.
+ // 4. onVertexArrayStateChange.
intptr_t getBasicDrawElementsError(const Context *context) const
{
if (mCachedBasicDrawElementsError != kInvalidPointer)

View File

@@ -81,7 +81,6 @@ feat_allow_disabling_blink_scheduler_throttling_per_renderview.patch
accessible_pane_view.patch
fixme_grit_conflicts.patch
fix_use_the_new_mediaplaypause_key_listener_for_internal_chrome.patch
use_electron_resources_in_pdf_util.patch
hack_plugin_response_interceptor_to_point_to_electron.patch
delay_lock_the_protocol_scheme_registry.patch
fix_route_mouse_event_navigations_through_the_web_contents_delegate.patch
@@ -117,3 +116,49 @@ backport_1074340.patch
backport_1016278.patch
backport_1042986.patch
a11y_axplatformnodebase_getindexinparent_returns_base_optional.patch
worker_feat_add_hook_to_notify_script_ready.patch
reconnect_p2p_socket_dispatcher_if_network_service_dies.patch
allow_focus_to_move_into_an_editable_combobox_s_listbox.patch
cherry-pick-70579363ce7b.patch
cherry-pick-138b748dd0a4.patch
cherry-pick-9d100199c92b.patch
cherry-pick-bee371eeaf66.patch
cherry-pick-9746a4cde14a.patch
avoid_loading_dri_via_gbm_when_gpumemorybuffers_are_disabled.patch
cherry-pick-72ee7c437c88.patch
cherry-pick-9ad8c9610d0a.patch
indexeddb_fix_crash_in_webidbgetdbnamescallbacksimpl.patch
indexeddb_reset_async_tasks_in_webidbgetdbnamescallbacksimpl.patch
reland_fix_uaf_in_selecttype.patch
cherry-pick-f6cb89728f04.patch
backport_1081874.patch
backport_1122684.patch
backport_1111737.patch
cherry-pick-0e61c69ebd47.patch
cherry-pick-814a27f8522b.patch
cherry-pick-adc731d678c4.patch
cherry-pick-52dceba66599.patch
cherry-pick-abc6ab85e704.patch
avoid_use-after-free.patch
cherry-pick-f06a6cb3a38e.patch
reland_add_more_checks_for_chrome_debugger_extensions.patch
cherry-pick-8629cd7f8af3.patch
fix_use_electron_generated_resources.patch
cherry-pick-f440137cd96a.patch
cherry-pick-30261f9de11e.patch
cherry-pick-88f263f401b4.patch
cherry-pick-229fdaf8fc05.patch
cherry-pick-1ed869ad4bb3.patch
cherry-pick-8f24f935c903.patch
crashpad-initialize-logging.patch
make_macos_os_version_numbers_consistent.patch
ignore_renderframehostimpl_detach_for_speculative_rfhs.patch
ui_check_that_unpremultiply_is_passed_a_32bpp_image.patch
cherry-pick-eec5025668f8.patch
cherry-pick-3abc372c9c00.patch
cherry-pick-d8d64b7cd244.patch
cherry-pick-5ffbb7ed173a.patch
propagate_disable-dev-shm-usage_to_child_processes.patch
cherry-pick-bbc6ab5bb49c.patch
cherry-pick-ecdec1fb0f42.patch
fix_setparentacessibile_crash_win.patch

View File

@@ -0,0 +1,115 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aaron Leventhal <aleventhal@chromium.org>
Date: Tue, 21 Jul 2020 19:41:11 +0000
Subject: Allow focus to move into an editable combobox's listbox
In bug 593646 (https://codereview.chromium.org/2024053003/) a rule was
added, apparently similar to a rule in WebKit, that prevents
aria-activedescendant on an editable combobox field from moving focus
into its listbox. However, removing this condition fixes an issue where
the first item is not read. It also improves the verbalization,
providing the user with the positional info, e.g. "2 of 5".
Removing this line also does not seem to break the example attached to
bug 593646.
Bug: 1082865
Change-Id: I4250fb152f4b06f3c57b300ebe7ef5549c58d624
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2303789
Reviewed-by: Dominic Mazzoni <dmazzoni@chromium.org>
Commit-Queue: Aaron Leventhal <aleventhal@chromium.org>
Cr-Commit-Position: refs/heads/master@{#790502}
diff --git a/content/browser/accessibility/browser_accessibility_manager_mac.mm b/content/browser/accessibility/browser_accessibility_manager_mac.mm
index 33324bbca5953f6f2f9d829e4c7b5d7daa3f49ea..a27cacfd303706ef3ee637107d2de0c8839bfa20 100644
--- a/content/browser/accessibility/browser_accessibility_manager_mac.mm
+++ b/content/browser/accessibility/browser_accessibility_manager_mac.mm
@@ -143,11 +143,6 @@ BrowserAccessibility* BrowserAccessibilityManagerMac::GetFocus() const {
if (!focus)
return nullptr;
- // For editable combo boxes, focus should stay on the combo box so the user
- // will not be taken out of the combo box while typing.
- if (focus->GetRole() == ax::mojom::Role::kTextFieldWithComboBox)
- return focus;
-
// Otherwise, follow the active descendant.
return GetActiveDescendant(focus);
}
diff --git a/content/test/data/accessibility/aria/aria-combobox-expected-mac.txt b/content/test/data/accessibility/aria/aria-combobox-expected-mac.txt
index d28f2235dedeedab23bf23db0475087c3d3ec73e..9dd9803232490edb95c80abcb2f084b8c42ceb7e 100644
--- a/content/test/data/accessibility/aria/aria-combobox-expected-mac.txt
+++ b/content/test/data/accessibility/aria/aria-combobox-expected-mac.txt
@@ -1,7 +1,7 @@
AXWebArea
++AXGroup
++++AXStaticText AXValue='State'
-++AXComboBox AXTitle='State' AXAutocompleteValue='list' AXFocused='1'
+++AXComboBox AXTitle='State' AXAutocompleteValue='list'
++AXList
++++AXStaticText AXValue='Alabama'
-++++AXStaticText AXValue='Alaska'
\ No newline at end of file
+++++AXStaticText AXFocused='1' AXValue='Alaska'
diff --git a/content/test/data/accessibility/event/aria-combo-box-collapse-expected-mac.txt b/content/test/data/accessibility/event/aria-combo-box-collapse-expected-mac.txt
index 97c3c417f30812abecdde273f130088df86bd4ae..93ef79e311977bb4277842fa5332f6097faba837 100644
--- a/content/test/data/accessibility/event/aria-combo-box-collapse-expected-mac.txt
+++ b/content/test/data/accessibility/event/aria-combo-box-collapse-expected-mac.txt
@@ -1,2 +1,3 @@
AXExpandedChanged on AXComboBox
-AXSelectedChildrenChanged on AXComboBox
+AXFocusedUIElementChanged on AXComboBox
+AXSelectedChildrenChanged on AXComboBox
\ No newline at end of file
diff --git a/content/test/data/accessibility/event/aria-combo-box-delay-add-list-expected-mac.txt b/content/test/data/accessibility/event/aria-combo-box-delay-add-list-expected-mac.txt
index 47ff72a2689baa23600ededfe38d79fd6b5bedcf..f7d4c30f49fe3f3f62132cddf59942181b8127b8 100644
--- a/content/test/data/accessibility/event/aria-combo-box-delay-add-list-expected-mac.txt
+++ b/content/test/data/accessibility/event/aria-combo-box-delay-add-list-expected-mac.txt
@@ -1 +1,2 @@
-AXSelectedChildrenChanged on AXComboBox
+AXFocusedUIElementChanged on AXStaticText AXValue="Apple"
+AXSelectedChildrenChanged on AXComboBox
\ No newline at end of file
diff --git a/content/test/data/accessibility/event/aria-combo-box-delay-show-list-expected-mac.txt b/content/test/data/accessibility/event/aria-combo-box-delay-show-list-expected-mac.txt
index 47ff72a2689baa23600ededfe38d79fd6b5bedcf..ab757bb0687ff49affcc67076eddd52e18b0eacc 100644
--- a/content/test/data/accessibility/event/aria-combo-box-delay-show-list-expected-mac.txt
+++ b/content/test/data/accessibility/event/aria-combo-box-delay-show-list-expected-mac.txt
@@ -1 +1,2 @@
+AXFocusedUIElementChanged on AXStaticText AXValue="Apple"
AXSelectedChildrenChanged on AXComboBox
diff --git a/content/test/data/accessibility/event/aria-combo-box-expand-expected-mac.txt b/content/test/data/accessibility/event/aria-combo-box-expand-expected-mac.txt
index 97cdb8b8b67d46e0a952d22765c823bd346aef3a..343feae3d79a48981cc1e27015ba2a93423eedc0 100644
--- a/content/test/data/accessibility/event/aria-combo-box-expand-expected-mac.txt
+++ b/content/test/data/accessibility/event/aria-combo-box-expand-expected-mac.txt
@@ -1,3 +1,4 @@
AXExpandedChanged on AXComboBox
+AXFocusedUIElementChanged on AXStaticText AXValue="Apple"
AXSelectedChildrenChanged on AXComboBox
-AXSelectedChildrenChanged on AXList
+AXSelectedChildrenChanged on AXList
\ No newline at end of file
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 2bfc70f5fecea2c2a5e7268cef641d6d0e7d4a47..ad5e2bf2c8029185c51eecc94cac1dbe7608c99e 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 AXComboBox
-AXSelectedTextChanged on AXComboBox
-AXSelectedTextChanged on AXWebArea
+AXFocusedUIElementChanged on AXStaticText AXValue="Apple not selected"
+AXSelectedTextChanged on AXStaticText AXValue="Apple not selected"
+AXSelectedTextChanged on AXWebArea
\ No newline at end of file
diff --git a/content/test/data/accessibility/event/aria-combo-box-next-expected-mac.txt b/content/test/data/accessibility/event/aria-combo-box-next-expected-mac.txt
index d5f21183c3d0a1c24cb6665194a93c3299dbfd56..9e7d0c0aaeb1c52dc1f1b3afed36f287851b89ff 100644
--- a/content/test/data/accessibility/event/aria-combo-box-next-expected-mac.txt
+++ b/content/test/data/accessibility/event/aria-combo-box-next-expected-mac.txt
@@ -1,5 +1,7 @@
+AXFocusedUIElementChanged on AXStaticText AXValue="Orange"
AXSelectedChildrenChanged on AXComboBox
AXSelectedChildrenChanged on AXList
=== Start Continuation ===
+AXFocusedUIElementChanged on AXStaticText AXValue="Banana"
AXSelectedChildrenChanged on AXComboBox
-AXSelectedChildrenChanged on AXList
+AXSelectedChildrenChanged on AXList
\ No newline at end of file

View File

@@ -0,0 +1,41 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Tom Anderson <thomasanderson@chromium.org>
Date: Thu, 21 May 2020 01:20:33 +0000
Subject: Avoid loading DRI via GBM when GpuMemoryBuffers are disabled
We haven't yet whitelisted the necessary dri files in the GPU sandbox,
which is leading to issues like 1077609 and 1077626. Since GMBs are
not yet supported, avoid loading GBM unless
--enable-native-gpu-memory-buffers is passed.
Bug: 1077609, 1077626, 1031269
Change-Id: Ic052d2e89330c6558da86a91b77637229808102f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2211120
Auto-Submit: Thomas Anderson <thomasanderson@chromium.org>
Reviewed-by: Kenneth Russell <kbr@chromium.org>
Commit-Queue: Thomas Anderson <thomasanderson@chromium.org>
Cr-Commit-Position: refs/heads/master@{#770878}
diff --git a/content/gpu/gpu_main.cc b/content/gpu/gpu_main.cc
index 9b22493abbd81c2f592e75fe32f7ab7efbb281d9..d650cef5e081da9cd00896db7d59f00635f13279 100644
--- a/content/gpu/gpu_main.cc
+++ b/content/gpu/gpu_main.cc
@@ -366,11 +366,13 @@ int GpuMain(const MainFunctionParams& parameters) {
#if defined(USE_X11)
// ui::GbmDevice() takes >50ms with amdgpu, so kick off
// GpuMemoryBufferSupportX11 creation on another thread now.
- base::PostTask(
- FROM_HERE, base::BindOnce([]() {
- SCOPED_UMA_HISTOGRAM_TIMER("Linux.X11.GbmSupportX11CreationTime");
- ui::GpuMemoryBufferSupportX11::GetInstance();
- }));
+ if (gpu_preferences.enable_native_gpu_memory_buffers) {
+ base::PostTask(
+ FROM_HERE, base::BindOnce([]() {
+ SCOPED_UMA_HISTOGRAM_TIMER("Linux.X11.GbmSupportX11CreationTime");
+ ui::GpuMemoryBufferSupportX11::GetInstance();
+ }));
+ }
#endif
if (client)

View File

@@ -0,0 +1,50 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Bruce Dawson <brucedawson@chromium.org>
Date: Thu, 17 Sep 2020 22:34:58 +0000
Subject: Avoid use-after-free
SetNotWaitingForResponse can trigger a message pump which can then free
the object which |this| points to. This use-after-free can be avoided by
not dereferencing |this| after the call, by ensuring that calling
SetNotWaitingForResponse is the last thing done.
(cherry picked from commit e1c5c8442210bccfbc2475c9bc75a9cf99bb259e)
Bug: 1125199
Change-Id: Ie1289c93112151978e6daaa1d24326770028c529
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2407065
Reviewed-by: Alex Moshchuk <alexmos@chromium.org>
Commit-Queue: Bruce Dawson <brucedawson@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#806839}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2416264
Reviewed-by: Bruce Dawson <brucedawson@chromium.org>
Cr-Commit-Position: refs/branch-heads/4240@{#816}
Cr-Branched-From: f297677702651916bbf65e59c0d4bbd4ce57d1ee-refs/heads/master@{#800218}
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 5b4f85cfadac54fa81a357ebece6f9b274066a29..d300755ec1402d7bd0fb9488a2829962b98853cb 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -3409,10 +3409,11 @@ void WebContentsImpl::SetNotWaitingForResponse() {
return;
waiting_for_response_ = false;
- if (delegate_)
- delegate_->LoadingStateChanged(this, is_load_to_different_document_);
for (auto& observer : observers_)
observer.DidReceiveResponse();
+
+ if (delegate_)
+ delegate_->LoadingStateChanged(this, is_load_to_different_document_);
}
void WebContentsImpl::SendScreenRects() {
@@ -4526,6 +4527,8 @@ void WebContentsImpl::ReadyToCommitNavigation(
: false);
}
+ // LoadingStateChanged must be called last in case it triggers deletion of
+ // |this| due to recursive message pumps.
SetNotWaitingForResponse();
}

View File

@@ -0,0 +1,549 @@
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: fix: data race on NodeChannel destruction
[1081874] [High] [CVE-2020-6575]: Double free on NodeChannel
Backport https://chromium.googlesource.com/chromium/src/+/5e61913985df0cc621bf72f7fa75e76759ffde15.
diff --git a/mojo/core/BUILD.gn b/mojo/core/BUILD.gn
index e6fcb96256f6fdb867a362588547a7829f28efe8..6282eed9158c691a9ca49d1ec9a57cedc4392741 100644
--- a/mojo/core/BUILD.gn
+++ b/mojo/core/BUILD.gn
@@ -18,6 +18,7 @@ component("embedder_internal") {
":test_sources",
"//mojo:*",
"//mojo/core/embedder",
+ "//mojo/core/test:test_support",
]
}
@@ -57,6 +58,7 @@ template("core_impl_source_set") {
"handle_table.h",
"invitation_dispatcher.h",
"message_pipe_dispatcher.h",
+ "node_channel.h",
"node_controller.h",
"options_validation.h",
"platform_handle_dispatcher.h",
@@ -86,7 +88,6 @@ template("core_impl_source_set") {
"invitation_dispatcher.cc",
"message_pipe_dispatcher.cc",
"node_channel.cc",
- "node_channel.h",
"node_controller.cc",
"platform_handle_dispatcher.cc",
"platform_handle_in_transit.cc",
@@ -289,6 +290,7 @@ source_set("test_sources") {
"handle_table_unittest.cc",
"message_pipe_unittest.cc",
"message_unittest.cc",
+ "node_channel_unittest.cc",
"options_validation_unittest.cc",
"platform_handle_dispatcher_unittest.cc",
"quota_unittest.cc",
@@ -387,6 +389,7 @@ fuzzer_test("mojo_core_node_channel_fuzzer") {
deps = [
":core_impl_for_fuzzers",
"//base",
+ "//mojo/core/test:test_support",
"//mojo/public/cpp/platform",
]
}
diff --git a/mojo/core/embedder/embedder.cc b/mojo/core/embedder/embedder.cc
index ec68e37d09888f672759f79961e3e6e4d18f0c5c..f70c73be4df529cce09cb503dfce28f2a04e7e1a 100644
--- a/mojo/core/embedder/embedder.cc
+++ b/mojo/core/embedder/embedder.cc
@@ -35,7 +35,7 @@ void SetDefaultProcessErrorCallback(ProcessErrorCallback callback) {
Core::Get()->SetDefaultProcessErrorCallback(std::move(callback));
}
-scoped_refptr<base::TaskRunner> GetIOTaskRunner() {
+scoped_refptr<base::SingleThreadTaskRunner> GetIOTaskRunner() {
return Core::Get()->GetNodeController()->io_task_runner();
}
diff --git a/mojo/core/embedder/embedder.h b/mojo/core/embedder/embedder.h
index 5d65400987728940a296ba2a84d40158f52d6d34..96dc44c0a78e0e6cb6e5aa511bd2fd4f1252cf16 100644
--- a/mojo/core/embedder/embedder.h
+++ b/mojo/core/embedder/embedder.h
@@ -13,7 +13,7 @@
#include "base/component_export.h"
#include "base/memory/ref_counted.h"
#include "base/process/process_handle.h"
-#include "base/task_runner.h"
+#include "base/single_thread_task_runner.h"
#include "build/build_config.h"
#include "mojo/core/embedder/configuration.h"
@@ -42,9 +42,10 @@ void SetDefaultProcessErrorCallback(ProcessErrorCallback callback);
// Initialialization/shutdown for interprocess communication (IPC) -------------
-// Retrieves the TaskRunner used for IPC I/O, as set by ScopedIPCSupport.
+// Retrieves the SequencedTaskRunner used for IPC I/O, as set by
+// ScopedIPCSupport.
COMPONENT_EXPORT(MOJO_CORE_EMBEDDER)
-scoped_refptr<base::TaskRunner> GetIOTaskRunner();
+scoped_refptr<base::SingleThreadTaskRunner> GetIOTaskRunner();
} // namespace core
} // namespace mojo
diff --git a/mojo/core/node_channel.cc b/mojo/core/node_channel.cc
index e898b044286e019b5e423b941502030ce3094582..061ea1026e95d1b1f80a762ce377aebdd97e1b42 100644
--- a/mojo/core/node_channel.cc
+++ b/mojo/core/node_channel.cc
@@ -228,7 +228,7 @@ void NodeChannel::NotifyBadMessage(const std::string& error) {
}
void NodeChannel::SetRemoteProcessHandle(ScopedProcessHandle process_handle) {
- DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
{
base::AutoLock lock(channel_lock_);
if (channel_)
@@ -253,7 +253,7 @@ ScopedProcessHandle NodeChannel::CloneRemoteProcessHandle() {
}
void NodeChannel::SetRemoteNodeName(const ports::NodeName& name) {
- DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
remote_node_name_ = name;
}
@@ -468,15 +468,15 @@ NodeChannel::NodeChannel(
Channel::HandlePolicy channel_handle_policy,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
const ProcessErrorCallback& process_error_callback)
- : delegate_(delegate),
- io_task_runner_(io_task_runner),
+ : base::RefCountedDeleteOnSequence<NodeChannel>(io_task_runner),
+ delegate_(delegate),
process_error_callback_(process_error_callback)
#if !defined(OS_NACL_SFI)
,
channel_(Channel::Create(this,
std::move(connection_params),
channel_handle_policy,
- io_task_runner_))
+ std::move(io_task_runner)))
#endif
{
}
@@ -499,15 +499,10 @@ void NodeChannel::CreateAndBindLocalBrokerHost(
void NodeChannel::OnChannelMessage(const void* payload,
size_t payload_size,
std::vector<PlatformHandle> handles) {
- DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
RequestContext request_context(RequestContext::Source::SYSTEM);
- // Ensure this NodeChannel stays alive through the extent of this method. The
- // delegate may have the only other reference to this object and it may choose
- // to drop it here in response to, e.g., a malformed message.
- scoped_refptr<NodeChannel> keepalive = this;
-
if (payload_size <= sizeof(Header)) {
delegate_->OnChannelError(remote_node_name_, this);
return;
@@ -739,7 +734,7 @@ void NodeChannel::OnChannelMessage(const void* payload,
}
void NodeChannel::OnChannelError(Channel::Error error) {
- DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
RequestContext request_context(RequestContext::Source::SYSTEM);
diff --git a/mojo/core/node_channel.h b/mojo/core/node_channel.h
index ea91f927049befa258884b13e7f7966c09518687..04501da0fb6cd36df1b332135282104dd442b41e 100644
--- a/mojo/core/node_channel.h
+++ b/mojo/core/node_channel.h
@@ -11,7 +11,7 @@
#include "base/callback.h"
#include "base/containers/queue.h"
#include "base/macros.h"
-#include "base/memory/ref_counted.h"
+#include "base/memory/ref_counted_delete_on_sequence.h"
#include "base/process/process_handle.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/lock.h"
@@ -21,13 +21,15 @@
#include "mojo/core/embedder/process_error_callback.h"
#include "mojo/core/ports/name.h"
#include "mojo/core/scoped_process_handle.h"
+#include "mojo/core/system_impl_export.h"
namespace mojo {
namespace core {
// Wraps a Channel to send and receive Node control messages.
-class NodeChannel : public base::RefCountedThreadSafe<NodeChannel>,
- public Channel::Delegate {
+class MOJO_SYSTEM_IMPL_EXPORT NodeChannel
+ : public base::RefCountedDeleteOnSequence<NodeChannel>,
+ public Channel::Delegate {
public:
class Delegate {
public:
@@ -92,8 +94,6 @@ class NodeChannel : public base::RefCountedThreadSafe<NodeChannel>,
void** data,
size_t* num_data_bytes);
- Channel* channel() const { return channel_.get(); }
-
// Start receiving messages.
void Start();
@@ -155,7 +155,8 @@ class NodeChannel : public base::RefCountedThreadSafe<NodeChannel>,
#endif
private:
- friend class base::RefCountedThreadSafe<NodeChannel>;
+ friend class base::RefCountedDeleteOnSequence<NodeChannel>;
+ friend class base::DeleteHelper<NodeChannel>;
using PendingMessageQueue = base::queue<Channel::MessagePtr>;
using PendingRelayMessageQueue =
@@ -181,13 +182,12 @@ class NodeChannel : public base::RefCountedThreadSafe<NodeChannel>,
void WriteChannelMessage(Channel::MessagePtr message);
Delegate* const delegate_;
- const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
const ProcessErrorCallback process_error_callback_;
base::Lock channel_lock_;
- scoped_refptr<Channel> channel_;
+ scoped_refptr<Channel> channel_ GUARDED_BY(channel_lock_);
- // Must only be accessed from |io_task_runner_|'s thread.
+ // Must only be accessed from the owning task runner's thread.
ports::NodeName remote_node_name_;
base::Lock remote_process_handle_lock_;
diff --git a/mojo/core/node_channel_fuzzer.cc b/mojo/core/node_channel_fuzzer.cc
index 99047c000dbe6be90f1d28b4b6817e608f9853a6..54fe757e0dec8aa138af96aa1a0afe596563c26c 100644
--- a/mojo/core/node_channel_fuzzer.cc
+++ b/mojo/core/node_channel_fuzzer.cc
@@ -14,6 +14,7 @@
#include "mojo/core/connection_params.h"
#include "mojo/core/entrypoints.h"
#include "mojo/core/node_channel.h" // nogncheck
+#include "mojo/core/test/mock_node_channel_delegate.h"
#include "mojo/public/cpp/platform/platform_channel.h"
#if defined(OS_WIN)
@@ -24,60 +25,6 @@ using mojo::core::Channel;
using mojo::core::ConnectionParams;
using mojo::core::ports::NodeName;
-// Implementation of NodeChannel::Delegate which does nothing. All of the
-// interesting NodeChannel control message message parsing is done by
-// NodeChannel by the time any of the delegate methods are invoked, so there's
-// no need for this to do any work.
-class FakeNodeChannelDelegate : public mojo::core::NodeChannel::Delegate {
- public:
- FakeNodeChannelDelegate() = default;
- ~FakeNodeChannelDelegate() override = default;
-
- void OnAcceptInvitee(const NodeName& from_node,
- const NodeName& inviter_name,
- const NodeName& token) override {}
- void OnAcceptInvitation(const NodeName& from_node,
- const NodeName& token,
- const NodeName& invitee_name) override {}
- void OnAddBrokerClient(const NodeName& from_node,
- const NodeName& client_name,
- base::ProcessHandle process_handle) override {}
- void OnBrokerClientAdded(const NodeName& from_node,
- const NodeName& client_name,
- mojo::PlatformHandle broker_channel) override {}
- void OnAcceptBrokerClient(const NodeName& from_node,
- const NodeName& broker_name,
- mojo::PlatformHandle broker_channel) override {}
- void OnEventMessage(const NodeName& from_node,
- Channel::MessagePtr message) override {}
- void OnRequestPortMerge(
- const NodeName& from_node,
- const mojo::core::ports::PortName& connector_port_name,
- const std::string& token) override {}
- void OnRequestIntroduction(const NodeName& from_node,
- const NodeName& name) override {}
- void OnIntroduce(const NodeName& from_node,
- const NodeName& name,
- mojo::PlatformHandle channel_handle) override {}
- void OnBroadcast(const NodeName& from_node,
- Channel::MessagePtr message) override {}
-#if defined(OS_WIN)
- void OnRelayEventMessage(const NodeName& from_node,
- base::ProcessHandle from_process,
- const NodeName& destination,
- Channel::MessagePtr message) override {}
- void OnEventMessageFromRelay(const NodeName& from_node,
- const NodeName& source_node,
- Channel::MessagePtr message) override {}
-#endif
- void OnAcceptPeer(const NodeName& from_node,
- const NodeName& token,
- const NodeName& peer_name,
- const mojo::core::ports::PortName& port_name) override {}
- void OnChannelError(const NodeName& node,
- mojo::core::NodeChannel* channel) override {}
-};
-
// A fake delegate for the sending Channel endpoint. The sending Channel is not
// being fuzzed and won't receive any interesting messages, so this doesn't need
// to do anything.
@@ -109,7 +56,7 @@ extern "C" int LLVMFuzzerTestOneInput(const unsigned char* data, size_t size) {
// used to carry messages between processes.
mojo::PlatformChannel channel;
- FakeNodeChannelDelegate receiver_delegate;
+ mojo::core::MockNodeChannelDelegate receiver_delegate;
auto receiver = mojo::core::NodeChannel::Create(
&receiver_delegate, ConnectionParams(channel.TakeLocalEndpoint()),
Channel::HandlePolicy::kRejectHandles,
diff --git a/mojo/core/node_channel_unittest.cc b/mojo/core/node_channel_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..13c46f13fea6342316534a7a843debbf7586108d
--- /dev/null
+++ b/mojo/core/node_channel_unittest.cc
@@ -0,0 +1,72 @@
+// 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 "mojo/core/node_channel.h"
+
+#include "base/bind_helpers.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/message_loop/message_pump_type.h"
+#include "base/test/task_environment.h"
+#include "base/threading/thread.h"
+#include "mojo/core/embedder/embedder.h"
+#include "mojo/core/test/mock_node_channel_delegate.h"
+#include "mojo/public/cpp/platform/platform_channel.h"
+#include "mojo/public/cpp/platform/platform_channel_endpoint.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace mojo {
+namespace core {
+namespace {
+
+using NodeChannelTest = testing::Test;
+using ports::NodeName;
+
+scoped_refptr<NodeChannel> CreateNodeChannel(NodeChannel::Delegate* delegate,
+ PlatformChannelEndpoint endpoint) {
+ return NodeChannel::Create(delegate, ConnectionParams(std::move(endpoint)),
+ Channel::HandlePolicy::kAcceptHandles,
+ GetIOTaskRunner(), base::NullCallback());
+}
+
+TEST_F(NodeChannelTest, DestructionIsSafe) {
+ // Regression test for https://crbug.com/1081874.
+ base::test::TaskEnvironment task_environment;
+
+ PlatformChannel channel;
+ MockNodeChannelDelegate local_delegate;
+ auto local_channel =
+ CreateNodeChannel(&local_delegate, channel.TakeLocalEndpoint());
+ local_channel->Start();
+ MockNodeChannelDelegate remote_delegate;
+ auto remote_channel =
+ CreateNodeChannel(&remote_delegate, channel.TakeRemoteEndpoint());
+ remote_channel->Start();
+
+ // Verify end-to-end operation
+ const NodeName kRemoteNodeName{123, 456};
+ const NodeName kToken{987, 654};
+ base::RunLoop loop;
+ EXPECT_CALL(local_delegate,
+ OnAcceptInvitee(ports::kInvalidNodeName, kRemoteNodeName, kToken))
+ .WillRepeatedly([&] { loop.Quit(); });
+ remote_channel->AcceptInvitee(kRemoteNodeName, kToken);
+ loop.Run();
+
+ // Now send another message to the local endpoint but tear it down
+ // immediately. This will race with the message being received on the IO
+ // thread, and although the corresponding delegate call may or may not
+ // dispatch as a result, the race should still be memory-safe.
+ remote_channel->AcceptInvitee(kRemoteNodeName, kToken);
+
+ base::RunLoop error_loop;
+ EXPECT_CALL(remote_delegate, OnChannelError).WillOnce([&] {
+ error_loop.Quit();
+ });
+ local_channel.reset();
+ error_loop.Run();
+}
+
+} // namespace
+} // namespace core
+} // namespace mojo
diff --git a/mojo/core/test/BUILD.gn b/mojo/core/test/BUILD.gn
index 1abadfc503d5176d2af1dcecfde153f17488546d..9429c61853059e10ca2430ad79ec8d9a39d90906 100644
--- a/mojo/core/test/BUILD.gn
+++ b/mojo/core/test/BUILD.gn
@@ -7,6 +7,8 @@ import("//third_party/protobuf/proto_library.gni")
static_library("test_support") {
testonly = true
sources = [
+ "mock_node_channel_delegate.cc",
+ "mock_node_channel_delegate.h",
"mojo_test_base.cc",
"mojo_test_base.h",
"test_utils.h",
@@ -27,8 +29,10 @@ static_library("test_support") {
public_deps = [
"//base",
"//base/test:test_support",
+ "//mojo/core:embedder_internal",
"//mojo/core/embedder",
"//mojo/public/cpp/system",
+ "//testing/gmock",
"//testing/gtest",
]
}
diff --git a/mojo/core/test/mock_node_channel_delegate.cc b/mojo/core/test/mock_node_channel_delegate.cc
new file mode 100644
index 0000000000000000000000000000000000000000..d257c3e1dc03857f91e94807328a0dc176f332f4
--- /dev/null
+++ b/mojo/core/test/mock_node_channel_delegate.cc
@@ -0,0 +1,15 @@
+// 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 "mojo/core/test/mock_node_channel_delegate.h"
+
+namespace mojo {
+namespace core {
+
+MockNodeChannelDelegate::MockNodeChannelDelegate() = default;
+
+MockNodeChannelDelegate::~MockNodeChannelDelegate() = default;
+
+} // namespace core
+} // namespace mojo
diff --git a/mojo/core/test/mock_node_channel_delegate.h b/mojo/core/test/mock_node_channel_delegate.h
new file mode 100644
index 0000000000000000000000000000000000000000..06ca96857b9472682d577a802c68a56a7af0aacd
--- /dev/null
+++ b/mojo/core/test/mock_node_channel_delegate.h
@@ -0,0 +1,114 @@
+// 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 MOJO_CORE_TEST_MOCK_NODE_CHANNEL_DELEGATE_H_
+#define MOJO_CORE_TEST_MOCK_NODE_CHANNEL_DELEGATE_H_
+
+#include "build/build_config.h"
+#include "mojo/core/node_channel.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace mojo {
+namespace core {
+
+// A NodeChannel Delegate implementation which can be used by NodeChannel unit
+// tests and fuzzers.
+class MockNodeChannelDelegate
+ : public testing::NiceMock<NodeChannel::Delegate> {
+ public:
+ using NodeName = ports::NodeName;
+ using PortName = ports::PortName;
+
+ MockNodeChannelDelegate();
+ MockNodeChannelDelegate(const MockNodeChannelDelegate&) = delete;
+ MockNodeChannelDelegate& operator=(const MockNodeChannelDelegate&) = delete;
+ ~MockNodeChannelDelegate() override;
+
+ // testing::NiceMock<NodeChannel::Delegate> implementation:
+ MOCK_METHOD(void,
+ OnAcceptInvitee,
+ (const NodeName& from_node,
+ const NodeName& inviter_name,
+ const NodeName& token),
+ (override));
+ MOCK_METHOD(void,
+ OnAcceptInvitation,
+ (const NodeName& from_node,
+ const NodeName& token,
+ const NodeName& invitee_name),
+ (override));
+ MOCK_METHOD(void,
+ OnAddBrokerClient,
+ (const NodeName& from_node,
+ const NodeName& client_name,
+ base::ProcessHandle process_handle),
+ (override));
+ MOCK_METHOD(void,
+ OnBrokerClientAdded,
+ (const NodeName& from_node,
+ const NodeName& client_name,
+ PlatformHandle broker_channel),
+ (override));
+ MOCK_METHOD(void,
+ OnAcceptBrokerClient,
+ (const NodeName& from_node,
+ const NodeName& broker_name,
+ PlatformHandle broker_channel),
+ (override));
+ MOCK_METHOD(void,
+ OnEventMessage,
+ (const NodeName& from_node, Channel::MessagePtr message),
+ (override));
+ MOCK_METHOD(void,
+ OnRequestPortMerge,
+ (const NodeName& from_node,
+ const PortName& connector_port_name,
+ const std::string& token),
+ (override));
+ MOCK_METHOD(void,
+ OnRequestIntroduction,
+ (const NodeName& from_node, const NodeName& name),
+ (override));
+ MOCK_METHOD(void,
+ OnIntroduce,
+ (const NodeName& from_node,
+ const NodeName& name,
+ PlatformHandle channel_handle),
+ (override));
+ MOCK_METHOD(void,
+ OnBroadcast,
+ (const NodeName& from_node, Channel::MessagePtr message),
+ (override));
+#if defined(OS_WIN)
+ MOCK_METHOD(void,
+ OnRelayEventMessage,
+ (const NodeName& from_node,
+ base::ProcessHandle from_process,
+ const NodeName& destination,
+ Channel::MessagePtr message),
+ (override));
+ MOCK_METHOD(void,
+ OnEventMessageFromRelay,
+ (const NodeName& from_node,
+ const NodeName& source_node,
+ Channel::MessagePtr message),
+ (override));
+#endif
+ MOCK_METHOD(void,
+ OnAcceptPeer,
+ (const NodeName& from_node,
+ const NodeName& token,
+ const NodeName& peer_name,
+ const PortName& port_name),
+ (override));
+ MOCK_METHOD(void,
+ OnChannelError,
+ (const NodeName& node, NodeChannel* channel),
+ (override));
+};
+
+} // namespace core
+} // namespace mojo
+
+#endif // MOJO_CORE_TEST_MOCK_NODE_CHANNEL_DELEGATE_H_

View File

@@ -0,0 +1,23 @@
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: fix: remove references to launched device before it is reset
[1111737] [High] [CVE-2020-6576]: Security: OffscreenCanvas - Use After Free in OffscreenCanvasRenderingContext2D::DrawTextInternal()
Backport https://chromium.googlesource.com/chromium/src/+/1283160e334f78c5eed4668d95e04f2ed2e2a4a3.
diff --git a/content/browser/renderer_host/media/video_capture_controller.cc b/content/browser/renderer_host/media/video_capture_controller.cc
index 8a3f1c3be3d804e3879a8a6aa5921bee99b0879e..85ed13b0008c58ba45cc28be36441234d928ed30 100644
--- a/content/browser/renderer_host/media/video_capture_controller.cc
+++ b/content/browser/renderer_host/media/video_capture_controller.cc
@@ -709,6 +709,10 @@ void VideoCaptureController::ReleaseDeviceAsync(base::OnceClosure done_cb) {
device_launcher_->AbortLaunch();
return;
}
+ // |buffer_contexts_| contain references to |launched_device_| as observers.
+ // Clear those observer references prior to resetting |launced_device_|.
+ for (auto& entry : buffer_contexts_)
+ entry.set_consumer_feedback_observer(nullptr);
launched_device_.reset();
}

View File

@@ -0,0 +1,149 @@
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: fix: elide headers in QuicHttp3Logger
[1122684] [High] [CVE-2020-15959]: Insufficient policy enforcement in networking.
Backport https://chromium.googlesource.com/chromium/src/+/c1a7439efcc7626c34d3e38503c974e4c215c489.
diff --git a/net/quic/quic_http3_logger.cc b/net/quic/quic_http3_logger.cc
index 8240046a419ed41fa340c106f45d6e9468ec7bf9..4cebe54bce4df8daaffe1a31f07ffe431a96bff6 100644
--- a/net/quic/quic_http3_logger.cc
+++ b/net/quic/quic_http3_logger.cc
@@ -9,10 +9,13 @@
#include <vector>
#include "base/metrics/histogram_macros.h"
+#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
+#include "net/http/http_log_util.h"
#include "net/log/net_log_capture_mode.h"
#include "net/log/net_log_event_type.h"
#include "net/log/net_log_values.h"
+#include "net/spdy/spdy_log_util.h"
namespace net {
@@ -64,20 +67,19 @@ base::Value NetLogThreeIntParams(base::StringPiece name1,
return dict;
}
-base::Value NetLogHeadersToDict(const quic::QuicHeaderList& headers) {
- base::Value dict(base::Value::Type::DICTIONARY);
- for (auto header : headers) {
- dict.SetStringKey(header.first, header.second);
- }
- return dict;
-}
-
-base::Value NetLogHeadersToDict(const spdy::SpdyHeaderBlock& headers) {
- base::Value dict(base::Value::Type::DICTIONARY);
- for (auto header : headers) {
- dict.SetStringKey(header.first, header.second);
+base::ListValue ElideQuicHeaderListForNetLog(
+ const quic::QuicHeaderList& headers,
+ NetLogCaptureMode capture_mode) {
+ base::ListValue headers_list;
+ for (const auto& header : headers) {
+ base::StringPiece key = header.first;
+ base::StringPiece value = header.second;
+ headers_list.Append(NetLogStringValue(
+ base::StrCat({key, ": ",
+ ElideHeaderValueForNetLog(capture_mode, key.as_string(),
+ value.as_string())})));
}
- return dict;
+ return headers_list;
}
} // namespace
@@ -235,11 +237,13 @@ void QuicHttp3Logger::OnHeadersDecoded(quic::QuicStreamId stream_id,
return;
}
net_log_.AddEvent(
- NetLogEventType::HTTP3_HEADERS_DECODED, [stream_id, &headers] {
+ NetLogEventType::HTTP3_HEADERS_DECODED,
+ [stream_id, &headers](NetLogCaptureMode capture_mode) {
base::Value dict(base::Value::Type::DICTIONARY);
dict.SetKey("stream_id",
NetLogNumberValue(static_cast<uint64_t>(stream_id)));
- dict.SetKey("headers", NetLogHeadersToDict(headers));
+ dict.SetKey("headers",
+ ElideQuicHeaderListForNetLog(headers, capture_mode));
return dict;
});
}
@@ -266,16 +270,18 @@ void QuicHttp3Logger::OnPushPromiseDecoded(quic::QuicStreamId stream_id,
if (!net_log_.IsCapturing()) {
return;
}
- net_log_.AddEvent(NetLogEventType::HTTP3_PUSH_PROMISE_DECODED, [stream_id,
- push_id,
- &headers] {
- base::Value dict(base::Value::Type::DICTIONARY);
- dict.SetKey("stream_id",
- NetLogNumberValue(static_cast<uint64_t>(stream_id)));
- dict.SetKey("push_id", NetLogNumberValue(static_cast<uint64_t>(push_id)));
- dict.SetKey("headers", NetLogHeadersToDict(headers));
- return dict;
- });
+ net_log_.AddEvent(
+ NetLogEventType::HTTP3_PUSH_PROMISE_DECODED,
+ [stream_id, push_id, &headers](NetLogCaptureMode capture_mode) {
+ base::Value dict(base::Value::Type::DICTIONARY);
+ dict.SetKey("stream_id",
+ NetLogNumberValue(static_cast<uint64_t>(stream_id)));
+ dict.SetKey("push_id",
+ NetLogNumberValue(static_cast<uint64_t>(push_id)));
+ dict.SetKey("headers",
+ ElideQuicHeaderListForNetLog(headers, capture_mode));
+ return dict;
+ });
}
void QuicHttp3Logger::OnUnknownFrameReceived(
@@ -344,11 +350,13 @@ void QuicHttp3Logger::OnHeadersFrameSent(
return;
}
net_log_.AddEvent(
- NetLogEventType::HTTP3_HEADERS_SENT, [stream_id, &header_block] {
+ NetLogEventType::HTTP3_HEADERS_SENT,
+ [stream_id, &header_block](NetLogCaptureMode capture_mode) {
base::Value dict(base::Value::Type::DICTIONARY);
dict.SetKey("stream_id",
NetLogNumberValue(static_cast<uint64_t>(stream_id)));
- dict.SetKey("headers", NetLogHeadersToDict(header_block));
+ dict.SetKey("headers",
+ ElideSpdyHeaderBlockForNetLog(header_block, capture_mode));
return dict;
});
}
@@ -360,16 +368,18 @@ void QuicHttp3Logger::OnPushPromiseFrameSent(
if (!net_log_.IsCapturing()) {
return;
}
- net_log_.AddEvent(NetLogEventType::HTTP3_PUSH_PROMISE_SENT, [stream_id,
- push_id,
- &header_block] {
- base::Value dict(base::Value::Type::DICTIONARY);
- dict.SetKey("stream_id",
- NetLogNumberValue(static_cast<uint64_t>(stream_id)));
- dict.SetKey("push_id", NetLogNumberValue(static_cast<uint64_t>(push_id)));
- dict.SetKey("headers", NetLogHeadersToDict(header_block));
- return dict;
- });
+ net_log_.AddEvent(
+ NetLogEventType::HTTP3_PUSH_PROMISE_SENT,
+ [stream_id, push_id, &header_block](NetLogCaptureMode capture_mode) {
+ base::Value dict(base::Value::Type::DICTIONARY);
+ dict.SetKey("stream_id",
+ NetLogNumberValue(static_cast<uint64_t>(stream_id)));
+ dict.SetKey("push_id",
+ NetLogNumberValue(static_cast<uint64_t>(push_id)));
+ dict.SetKey("headers",
+ ElideSpdyHeaderBlockForNetLog(header_block, capture_mode));
+ return dict;
+ });
}
} // namespace net

View File

@@ -0,0 +1,750 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ramin Halavati <rhalavati@chromium.org>
Date: Wed, 9 Sep 2020 05:10:19 +0000
Subject: Reland Run ObfuscatedFileUtilMemoryDelegate entirely on TaskRunner.
MemoryFileStreamWriter called some ObfuscatedFileUtilMemoryDelegate
functions through IO thread while other functions in OFUMD are called
on a threadpool sequence. This could result in races in updating
directory structure.
To fix the issue, MemoryFileStreamWriter and MemoryFileStreamReader are
updated to call all OFUMD on the default task runner of the file system
context.
This CL was landed in crrev.com/c/2308721 and reverted due to flakiness.
The flaky crashes are believed to be because the buffer passed to
MemoryFileStreamReader::Read and MemoryFileStreamWrite::Write are not
thread safe.
Patchset1 is a copy of the previous CL and the issue is fixed in the
next patchsets.
Bug: 1100136
Change-Id: I619b82c2f4d23a020e9ce7e5e6c16980907b501b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2398701
Reviewed-by: Marijn Kruisselbrink <mek@chromium.org>
Commit-Queue: Ramin Halavati <rhalavati@chromium.org>
Cr-Commit-Position: refs/heads/master@{#805198}
(cherry picked from commit 0e61c69ebd476e5b688f341f8d0bf69fe814c515)
diff --git a/storage/browser/file_system/file_stream_reader.h b/storage/browser/file_system/file_stream_reader.h
index b3cfc7f751be2e8654ba6d5e51849a4f35863d7a..d9ac296c94a4df765417d71b0c80b798ff7c888c 100644
--- a/storage/browser/file_system/file_stream_reader.h
+++ b/storage/browser/file_system/file_stream_reader.h
@@ -60,6 +60,7 @@ class FileStreamReader {
// ERR_UPLOAD_FILE_CHANGED error.
COMPONENT_EXPORT(STORAGE_BROWSER)
static std::unique_ptr<FileStreamReader> CreateForMemoryFile(
+ scoped_refptr<base::TaskRunner> task_runner,
base::WeakPtr<ObfuscatedFileUtilMemoryDelegate> memory_file_util,
const base::FilePath& file_path,
int64_t initial_offset,
diff --git a/storage/browser/file_system/file_stream_test_utils.cc b/storage/browser/file_system/file_stream_test_utils.cc
index 835a423c9c913ed46e8b68e7a9d3b323b3263695..e66dfc716aae031cc9c6e00d660753d4487cb60a 100644
--- a/storage/browser/file_system/file_stream_test_utils.cc
+++ b/storage/browser/file_system/file_stream_test_utils.cc
@@ -40,6 +40,14 @@ void ReadFromReader(FileStreamReader* reader,
}
}
+int64_t GetLengthFromReader(FileStreamReader* reader) {
+ EXPECT_NE(nullptr, reader);
+ net::TestInt64CompletionCallback callback;
+
+ int rv = reader->GetLength(callback.callback());
+ return callback.GetResult(rv);
+}
+
int WriteStringToWriter(FileStreamWriter* writer, const std::string& data) {
scoped_refptr<net::StringIOBuffer> buffer =
base::MakeRefCounted<net::StringIOBuffer>(data);
diff --git a/storage/browser/file_system/file_stream_test_utils.h b/storage/browser/file_system/file_stream_test_utils.h
index 5714f7a1e7a1f6e91628e9f958a1b13324d7ec8e..d6425f15af6309a0891a10ca54cc092b8c1180f1 100644
--- a/storage/browser/file_system/file_stream_test_utils.h
+++ b/storage/browser/file_system/file_stream_test_utils.h
@@ -20,8 +20,12 @@ void ReadFromReader(FileStreamReader* reader,
size_t size,
int* result);
-// Writes |data| to |writer|, an intialized FileStreamWriter. Returns net::OK if
-// successful, otherwise a net error.
+// Returns the length of the file if it could be successfully retrieved,
+// otherwise a net error.
+int64_t GetLengthFromReader(FileStreamReader* reader);
+
+// Writes |data| to |writer|, an initialized FileStreamWriter. Returns net::OK
+// if successful, otherwise a net error.
int WriteStringToWriter(FileStreamWriter* writer, const std::string& data);
} // namespace storage
diff --git a/storage/browser/file_system/file_stream_writer.h b/storage/browser/file_system/file_stream_writer.h
index 2ddbecc6587d94d16ad547e3b2249c103621ee7e..11ce21c64d9b0f43d761b45ae7a710be60f03316 100644
--- a/storage/browser/file_system/file_stream_writer.h
+++ b/storage/browser/file_system/file_stream_writer.h
@@ -48,10 +48,9 @@ class FileStreamWriter {
// Creates a writer for the existing memory file in the path |file_path|
// starting from |initial_offset|.
- // TODO(mek): Remove or use |open_or_create| field here, as it is not
- // currently used. https://crbug.com/1041048
COMPONENT_EXPORT(STORAGE_BROWSER)
static std::unique_ptr<FileStreamWriter> CreateForMemoryFile(
+ scoped_refptr<base::TaskRunner> task_runner,
base::WeakPtr<ObfuscatedFileUtilMemoryDelegate> memory_file_util,
const base::FilePath& file_path,
int64_t initial_offset);
diff --git a/storage/browser/file_system/file_system_file_stream_reader.cc b/storage/browser/file_system/file_system_file_stream_reader.cc
index 8a3b85166bf85fb9661953c37b2942eddd5a61e1..9d37b8075199fe5c93c058610bb1f9d99730b526 100644
--- a/storage/browser/file_system/file_system_file_stream_reader.cc
+++ b/storage/browser/file_system/file_system_file_stream_reader.cc
@@ -112,6 +112,7 @@ void FileSystemFileStreamReader::DidCreateSnapshot(
file_system_context_->sandbox_delegate()->memory_file_util_delegate();
}
file_reader_ = FileStreamReader::CreateForMemoryFile(
+ file_system_context_->default_file_task_runner(),
memory_file_util_delegate, platform_path, initial_offset_,
expected_modification_time_);
} else {
diff --git a/storage/browser/file_system/memory_file_stream_reader.cc b/storage/browser/file_system/memory_file_stream_reader.cc
index f5d895c6cc97e883024e854395a24f094c797ed4..0ca229bb8e8e853d96710fc5946e7a5d854c2180 100644
--- a/storage/browser/file_system/memory_file_stream_reader.cc
+++ b/storage/browser/file_system/memory_file_stream_reader.cc
@@ -8,68 +8,114 @@
#include <utility>
#include "base/memory/ptr_util.h"
+#include "base/task_runner_util.h"
+#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
namespace storage {
std::unique_ptr<FileStreamReader> FileStreamReader::CreateForMemoryFile(
+ scoped_refptr<base::TaskRunner> task_runner,
base::WeakPtr<ObfuscatedFileUtilMemoryDelegate> memory_file_util,
const base::FilePath& file_path,
int64_t initial_offset,
const base::Time& expected_modification_time) {
- return base::WrapUnique(
- new MemoryFileStreamReader(std::move(memory_file_util), file_path,
- initial_offset, expected_modification_time));
+ return base::WrapUnique(new MemoryFileStreamReader(
+ std::move(task_runner), std::move(memory_file_util), file_path,
+ initial_offset, expected_modification_time));
}
MemoryFileStreamReader::MemoryFileStreamReader(
+ scoped_refptr<base::TaskRunner> task_runner,
base::WeakPtr<ObfuscatedFileUtilMemoryDelegate> memory_file_util,
const base::FilePath& file_path,
int64_t initial_offset,
const base::Time& expected_modification_time)
: memory_file_util_(std::move(memory_file_util)),
+ task_runner_(std::move(task_runner)),
file_path_(file_path),
expected_modification_time_(expected_modification_time),
offset_(initial_offset) {
- DCHECK(memory_file_util_);
+ DCHECK(memory_file_util_.MaybeValid());
}
MemoryFileStreamReader::~MemoryFileStreamReader() = default;
int MemoryFileStreamReader::Read(net::IOBuffer* buf,
int buf_len,
- net::CompletionOnceCallback /*callback*/) {
- base::File::Info file_info;
- if (memory_file_util_->GetFileInfo(file_path_, &file_info) !=
- base::File::FILE_OK) {
- return net::ERR_FILE_NOT_FOUND;
- }
-
- if (!FileStreamReader::VerifySnapshotTime(expected_modification_time_,
- file_info)) {
- return net::ERR_UPLOAD_FILE_CHANGED;
- }
-
- int result = memory_file_util_->ReadFile(file_path_, offset_, buf, buf_len);
+ net::CompletionOnceCallback callback) {
+ task_runner_->PostTaskAndReplyWithResult(
+ FROM_HERE,
+ base::BindOnce(
+ [](base::WeakPtr<ObfuscatedFileUtilMemoryDelegate> util,
+ const base::FilePath& path, base::Time expected_modification_time,
+ int64_t offset, scoped_refptr<net::IOBuffer> buf,
+ int buf_len) -> int {
+ if (!util)
+ return net::ERR_FILE_NOT_FOUND;
+ base::File::Info file_info;
+ if (util->GetFileInfo(path, &file_info) != base::File::FILE_OK)
+ return net::ERR_FILE_NOT_FOUND;
+
+ if (!FileStreamReader::VerifySnapshotTime(
+ expected_modification_time, file_info)) {
+ return net::ERR_UPLOAD_FILE_CHANGED;
+ }
+
+ return util->ReadFile(path, offset, std::move(buf), buf_len);
+ },
+ memory_file_util_, file_path_, expected_modification_time_, offset_,
+ base::WrapRefCounted(buf), buf_len),
+ base::BindOnce(&MemoryFileStreamReader::OnReadCompleted,
+ weak_factory_.GetWeakPtr(), std::move(callback)));
+
+ return net::ERR_IO_PENDING;
+}
+
+void MemoryFileStreamReader::OnReadCompleted(
+ net::CompletionOnceCallback callback,
+ int result) {
if (result > 0)
offset_ += result;
- return result;
+
+ std::move(callback).Run(result);
}
int64_t MemoryFileStreamReader::GetLength(
- net::Int64CompletionOnceCallback /*callback*/) {
- base::File::Info file_info;
- if (memory_file_util_->GetFileInfo(file_path_, &file_info) !=
- base::File::FILE_OK) {
- return net::ERR_FILE_NOT_FOUND;
- }
-
- if (!FileStreamReader::VerifySnapshotTime(expected_modification_time_,
- file_info)) {
- return net::ERR_UPLOAD_FILE_CHANGED;
- }
-
- return file_info.size;
+ net::Int64CompletionOnceCallback callback) {
+ task_runner_->PostTaskAndReplyWithResult(
+ FROM_HERE,
+ base::BindOnce(
+ [](base::WeakPtr<ObfuscatedFileUtilMemoryDelegate> util,
+ const base::FilePath& path,
+ base::Time expected_modification_time) -> int64_t {
+ if (!util)
+ return net::ERR_FILE_NOT_FOUND;
+ base::File::Info file_info;
+ if (util->GetFileInfo(path, &file_info) != base::File::FILE_OK) {
+ return net::ERR_FILE_NOT_FOUND;
+ }
+
+ if (!FileStreamReader::VerifySnapshotTime(
+ expected_modification_time, file_info)) {
+ return net::ERR_UPLOAD_FILE_CHANGED;
+ }
+
+ return file_info.size;
+ },
+ memory_file_util_, file_path_, expected_modification_time_),
+ // |callback| is not directly used to make sure that it is not called if
+ // stream is deleted while this function is in flight.
+ base::BindOnce(&MemoryFileStreamReader::OnGetLengthCompleted,
+ weak_factory_.GetWeakPtr(), std::move(callback)));
+
+ return net::ERR_IO_PENDING;
+}
+
+void MemoryFileStreamReader::OnGetLengthCompleted(
+ net::Int64CompletionOnceCallback callback,
+ int64_t result) {
+ std::move(callback).Run(result);
}
} // namespace storage
diff --git a/storage/browser/file_system/memory_file_stream_reader.h b/storage/browser/file_system/memory_file_stream_reader.h
index 909db6b1178bc329af5e4694538045bba243310b..4f05d450522613e668549e59d58c36552650773e 100644
--- a/storage/browser/file_system/memory_file_stream_reader.h
+++ b/storage/browser/file_system/memory_file_stream_reader.h
@@ -32,17 +32,25 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) MemoryFileStreamReader
friend class FileStreamReader;
MemoryFileStreamReader(
+ scoped_refptr<base::TaskRunner> task_runner,
base::WeakPtr<ObfuscatedFileUtilMemoryDelegate> memory_file_util,
const base::FilePath& file_path,
int64_t initial_offset,
const base::Time& expected_modification_time);
+ void OnReadCompleted(net::CompletionOnceCallback callback, int result);
+ void OnGetLengthCompleted(net::Int64CompletionOnceCallback callback,
+ int64_t result);
+
base::WeakPtr<ObfuscatedFileUtilMemoryDelegate> memory_file_util_;
+ const scoped_refptr<base::TaskRunner> task_runner_;
const base::FilePath file_path_;
const base::Time expected_modification_time_;
int64_t offset_;
+ base::WeakPtrFactory<MemoryFileStreamReader> weak_factory_{this};
+
DISALLOW_COPY_AND_ASSIGN(MemoryFileStreamReader);
};
diff --git a/storage/browser/file_system/memory_file_stream_reader_unittest.cc b/storage/browser/file_system/memory_file_stream_reader_unittest.cc
index 7cbaf6e06f82e792a52d549f963a0044a0a5fbd5..99bcfcbeb7e5dcdced47be3df1820f518558a78b 100644
--- a/storage/browser/file_system/memory_file_stream_reader_unittest.cc
+++ b/storage/browser/file_system/memory_file_stream_reader_unittest.cc
@@ -17,6 +17,7 @@
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
+#include "base/test/task_environment.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "storage/browser/file_system/file_stream_reader.h"
@@ -62,9 +63,9 @@ class MemoryFileStreamReaderTest : public testing::Test {
const base::FilePath& path,
int64_t initial_offset,
const base::Time& expected_modification_time) {
- return FileStreamReader::CreateForMemoryFile(file_util_->GetWeakPtr(), path,
- initial_offset,
- expected_modification_time);
+ return FileStreamReader::CreateForMemoryFile(
+ base::ThreadTaskRunnerHandle::Get(), file_util_->GetWeakPtr(), path,
+ initial_offset, expected_modification_time);
}
void TouchTestFile(base::TimeDelta delta) {
@@ -83,6 +84,7 @@ class MemoryFileStreamReaderTest : public testing::Test {
}
private:
+ base::test::TaskEnvironment task_environment_;
base::ScopedTempDir file_system_directory_;
std::unique_ptr<ObfuscatedFileUtilMemoryDelegate> file_util_;
base::Time test_file_modification_time_;
@@ -113,14 +115,14 @@ TEST_F(MemoryFileStreamReaderTest, Empty) {
ASSERT_EQ(net::OK, result);
ASSERT_EQ(0U, data.size());
- int64_t length_result = reader->GetLength(base::DoNothing());
+ int64_t length_result = GetLengthFromReader(reader.get());
ASSERT_EQ(0, length_result);
}
TEST_F(MemoryFileStreamReaderTest, GetLengthNormal) {
std::unique_ptr<FileStreamReader> reader(
CreateFileReader(test_path(), 0, test_file_modification_time()));
- int64_t result = reader->GetLength(base::DoNothing());
+ int64_t result = GetLengthFromReader(reader.get());
ASSERT_EQ(kTestDataSize, result);
}
@@ -131,7 +133,7 @@ TEST_F(MemoryFileStreamReaderTest, GetLengthAfterModified) {
std::unique_ptr<FileStreamReader> reader(
CreateFileReader(test_path(), 0, test_file_modification_time()));
- int64_t result = reader->GetLength(base::DoNothing());
+ int64_t result = GetLengthFromReader(reader.get());
ASSERT_EQ(net::ERR_UPLOAD_FILE_CHANGED, result);
}
@@ -142,14 +144,14 @@ TEST_F(MemoryFileStreamReaderTest, GetLengthAfterModifiedWithNoExpectedTime) {
std::unique_ptr<FileStreamReader> reader(
CreateFileReader(test_path(), 0, base::Time()));
- int64_t result = reader->GetLength(base::DoNothing());
+ int64_t result = GetLengthFromReader(reader.get());
ASSERT_EQ(kTestDataSize, result);
}
TEST_F(MemoryFileStreamReaderTest, GetLengthWithOffset) {
std::unique_ptr<FileStreamReader> reader(
CreateFileReader(test_path(), 3, base::Time()));
- int64_t result = reader->GetLength(base::DoNothing());
+ int64_t result = GetLengthFromReader(reader.get());
// Initial offset does not affect the result of GetLength.
ASSERT_EQ(kTestDataSize, result);
}
diff --git a/storage/browser/file_system/memory_file_stream_writer.cc b/storage/browser/file_system/memory_file_stream_writer.cc
index 9c421145866cd4425f752e343abcfca6260178a2..b36c4b5e4bbb5d7280fba11ab73e8c4a4d39c088 100644
--- a/storage/browser/file_system/memory_file_stream_writer.cc
+++ b/storage/browser/file_system/memory_file_stream_writer.cc
@@ -8,43 +8,68 @@
#include <utility>
#include "base/memory/ptr_util.h"
+#include "base/task_runner_util.h"
+#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
namespace storage {
std::unique_ptr<FileStreamWriter> FileStreamWriter::CreateForMemoryFile(
+ scoped_refptr<base::TaskRunner> task_runner,
base::WeakPtr<ObfuscatedFileUtilMemoryDelegate> memory_file_util,
const base::FilePath& file_path,
int64_t initial_offset) {
return base::WrapUnique(new MemoryFileStreamWriter(
- std::move(memory_file_util), file_path, initial_offset));
+ std::move(task_runner), std::move(memory_file_util), file_path,
+ initial_offset));
}
MemoryFileStreamWriter::MemoryFileStreamWriter(
+ scoped_refptr<base::TaskRunner> task_runner,
base::WeakPtr<ObfuscatedFileUtilMemoryDelegate> memory_file_util,
const base::FilePath& file_path,
int64_t initial_offset)
: memory_file_util_(std::move(memory_file_util)),
+ task_runner_(std::move(task_runner)),
file_path_(file_path),
offset_(initial_offset) {
- DCHECK(memory_file_util_);
+ DCHECK(memory_file_util_.MaybeValid());
}
MemoryFileStreamWriter::~MemoryFileStreamWriter() = default;
int MemoryFileStreamWriter::Write(net::IOBuffer* buf,
int buf_len,
- net::CompletionOnceCallback /*callback*/) {
- base::File::Info file_info;
- if (memory_file_util_->GetFileInfo(file_path_, &file_info) !=
- base::File::FILE_OK) {
- return net::ERR_FILE_NOT_FOUND;
- }
-
- int result = memory_file_util_->WriteFile(file_path_, offset_, buf, buf_len);
+ net::CompletionOnceCallback callback) {
+ task_runner_->PostTaskAndReplyWithResult(
+ FROM_HERE,
+ base::BindOnce(
+ [](base::WeakPtr<ObfuscatedFileUtilMemoryDelegate> util,
+ const base::FilePath& path, int64_t offset,
+ scoped_refptr<net::IOBuffer> buf, int buf_len) -> int {
+ if (!util)
+ return net::ERR_FILE_NOT_FOUND;
+ base::File::Info file_info;
+ if (util->GetFileInfo(path, &file_info) != base::File::FILE_OK)
+ return net::ERR_FILE_NOT_FOUND;
+
+ return util->WriteFile(path, offset, std::move(buf), buf_len);
+ },
+ memory_file_util_, file_path_, offset_, base::WrapRefCounted(buf),
+ buf_len),
+ base::BindOnce(&MemoryFileStreamWriter::OnWriteCompleted,
+ weak_factory_.GetWeakPtr(), std::move(callback)));
+
+ return net::ERR_IO_PENDING;
+}
+
+void MemoryFileStreamWriter::OnWriteCompleted(
+ net::CompletionOnceCallback callback,
+ int result) {
if (result > 0)
offset_ += result;
- return result;
+
+ std::move(callback).Run(result);
}
int MemoryFileStreamWriter::Cancel(net::CompletionOnceCallback /*callback*/) {
diff --git a/storage/browser/file_system/memory_file_stream_writer.h b/storage/browser/file_system/memory_file_stream_writer.h
index fe1c9d17932e2c4398295bc0ed6359f86281be91..74f6213f0f80b619083779184d04a62c0f983835 100644
--- a/storage/browser/file_system/memory_file_stream_writer.h
+++ b/storage/browser/file_system/memory_file_stream_writer.h
@@ -30,15 +30,21 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) MemoryFileStreamWriter
private:
friend class FileStreamWriter;
MemoryFileStreamWriter(
+ scoped_refptr<base::TaskRunner> task_runner,
base::WeakPtr<ObfuscatedFileUtilMemoryDelegate> memory_file_util,
const base::FilePath& file_path,
int64_t initial_offset);
+ void OnWriteCompleted(net::CompletionOnceCallback callback, int result);
+
base::WeakPtr<ObfuscatedFileUtilMemoryDelegate> memory_file_util_;
+ const scoped_refptr<base::TaskRunner> task_runner_;
const base::FilePath file_path_;
int64_t offset_;
+ base::WeakPtrFactory<MemoryFileStreamWriter> weak_factory_{this};
+
DISALLOW_COPY_AND_ASSIGN(MemoryFileStreamWriter);
};
diff --git a/storage/browser/file_system/memory_file_stream_writer_unittest.cc b/storage/browser/file_system/memory_file_stream_writer_unittest.cc
index 7fcda3dfd5e533e8d501a5b56ae5b2abd9486f2f..44342a33c66f21eed35287a4bb9b94f82de21521 100644
--- a/storage/browser/file_system/memory_file_stream_writer_unittest.cc
+++ b/storage/browser/file_system/memory_file_stream_writer_unittest.cc
@@ -13,6 +13,7 @@
#include "base/bind_helpers.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
+#include "base/test/task_environment.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "storage/browser/file_system/file_stream_test_utils.h"
@@ -59,11 +60,13 @@ class MemoryFileStreamWriterTest : public testing::Test {
std::unique_ptr<FileStreamWriter> CreateWriter(const base::FilePath& path,
int64_t offset) {
- return FileStreamWriter::CreateForMemoryFile(file_util_->GetWeakPtr(), path,
- offset);
+ return FileStreamWriter::CreateForMemoryFile(
+ base::ThreadTaskRunnerHandle::Get(), file_util_->GetWeakPtr(), path,
+ offset);
}
private:
+ base::test::TaskEnvironment task_environment_;
base::ScopedTempDir file_system_directory_;
std::unique_ptr<ObfuscatedFileUtilMemoryDelegate> file_util_;
};
diff --git a/storage/browser/file_system/obfuscated_file_util_memory_delegate.cc b/storage/browser/file_system/obfuscated_file_util_memory_delegate.cc
index 5919d1f1c2c4c80fd73cfbb0586af0e505d43152..3a3d8563e3c91d3b9ca15a980a709a8fd96e8c6c 100644
--- a/storage/browser/file_system/obfuscated_file_util_memory_delegate.cc
+++ b/storage/browser/file_system/obfuscated_file_util_memory_delegate.cc
@@ -56,13 +56,17 @@ struct ObfuscatedFileUtilMemoryDelegate::DecomposedPath {
ObfuscatedFileUtilMemoryDelegate::ObfuscatedFileUtilMemoryDelegate(
const base::FilePath& file_system_directory)
: root_(std::make_unique<Entry>(Entry::kDirectory)) {
+ DETACH_FROM_SEQUENCE(sequence_checker_);
file_system_directory.GetComponents(&root_path_components_);
}
-ObfuscatedFileUtilMemoryDelegate::~ObfuscatedFileUtilMemoryDelegate() = default;
+ObfuscatedFileUtilMemoryDelegate::~ObfuscatedFileUtilMemoryDelegate() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
base::Optional<ObfuscatedFileUtilMemoryDelegate::DecomposedPath>
ObfuscatedFileUtilMemoryDelegate::ParsePath(const base::FilePath& path) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DecomposedPath dp;
path.GetComponents(&dp.components);
@@ -118,6 +122,7 @@ ObfuscatedFileUtilMemoryDelegate::ParsePath(const base::FilePath& path) {
bool ObfuscatedFileUtilMemoryDelegate::DirectoryExists(
const base::FilePath& path) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::Optional<DecomposedPath> dp = ParsePath(path);
return dp && dp->entry && dp->entry->type == Entry::kDirectory;
}
@@ -126,6 +131,7 @@ base::File::Error ObfuscatedFileUtilMemoryDelegate::CreateDirectory(
const base::FilePath& path,
bool exclusive,
bool recursive) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::Optional<DecomposedPath> dp = ParsePath(path);
if (!dp)
return base::File::FILE_ERROR_NOT_FOUND;
@@ -169,6 +175,7 @@ base::File::Error ObfuscatedFileUtilMemoryDelegate::CreateDirectory(
bool ObfuscatedFileUtilMemoryDelegate::DeleteFileOrDirectory(
const base::FilePath& path,
bool recursive) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::Optional<DecomposedPath> dp = ParsePath(path);
if (!dp)
return false;
@@ -185,11 +192,13 @@ bool ObfuscatedFileUtilMemoryDelegate::DeleteFileOrDirectory(
}
bool ObfuscatedFileUtilMemoryDelegate::IsLink(const base::FilePath& file_path) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// In-memory file system does not support links.
return false;
}
bool ObfuscatedFileUtilMemoryDelegate::PathExists(const base::FilePath& path) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::Optional<DecomposedPath> dp = ParsePath(path);
return dp && dp->entry;
}
@@ -197,6 +206,7 @@ bool ObfuscatedFileUtilMemoryDelegate::PathExists(const base::FilePath& path) {
base::File ObfuscatedFileUtilMemoryDelegate::CreateOrOpen(
const base::FilePath& path,
int file_flags) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// TODO:(https://crbug.com/936722): Once the output of this function is
// changed to base::File::Error, it can use CreateOrOpenInternal to perform
// the task and return the result.
@@ -206,6 +216,7 @@ base::File ObfuscatedFileUtilMemoryDelegate::CreateOrOpen(
void ObfuscatedFileUtilMemoryDelegate::CreateOrOpenInternal(
const DecomposedPath& dp,
int file_flags) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!dp.entry) {
dp.parent->directory_content.emplace(dp.components.back(), Entry::kFile);
return;
@@ -221,6 +232,7 @@ void ObfuscatedFileUtilMemoryDelegate::CreateOrOpenInternal(
base::File::Error ObfuscatedFileUtilMemoryDelegate::DeleteFile(
const base::FilePath& path) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::Optional<DecomposedPath> dp = ParsePath(path);
if (!dp || !dp->entry)
return base::File::FILE_ERROR_NOT_FOUND;
@@ -235,6 +247,7 @@ base::File::Error ObfuscatedFileUtilMemoryDelegate::DeleteFile(
base::File::Error ObfuscatedFileUtilMemoryDelegate::EnsureFileExists(
const base::FilePath& path,
bool* created) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::Optional<DecomposedPath> dp = ParsePath(path);
*created = false;
if (!dp || !dp->parent)
@@ -253,6 +266,7 @@ base::File::Error ObfuscatedFileUtilMemoryDelegate::EnsureFileExists(
base::File::Error ObfuscatedFileUtilMemoryDelegate::GetFileInfo(
const base::FilePath& path,
base::File::Info* file_info) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::Optional<DecomposedPath> dp = ParsePath(path);
if (!dp || !dp->entry)
return base::File::FILE_ERROR_NOT_FOUND;
@@ -272,6 +286,7 @@ base::File::Error ObfuscatedFileUtilMemoryDelegate::Touch(
const base::FilePath& path,
const base::Time& last_access_time,
const base::Time& last_modified_time) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::Optional<DecomposedPath> dp = ParsePath(path);
if (!dp || !dp->entry)
return base::File::FILE_ERROR_FAILED;
@@ -285,6 +300,7 @@ base::File::Error ObfuscatedFileUtilMemoryDelegate::Touch(
base::File::Error ObfuscatedFileUtilMemoryDelegate::Truncate(
const base::FilePath& path,
int64_t length) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::Optional<DecomposedPath> dp = ParsePath(path);
if (!dp || !dp->entry || dp->entry->type != Entry::kFile)
return base::File::FILE_ERROR_NOT_FOUND;
@@ -297,6 +313,7 @@ NativeFileUtil::CopyOrMoveMode
ObfuscatedFileUtilMemoryDelegate::CopyOrMoveModeForDestination(
const FileSystemURL& /*dest_url*/,
bool copy) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return copy ? NativeFileUtil::CopyOrMoveMode::COPY_SYNC
: NativeFileUtil::CopyOrMoveMode::MOVE;
}
@@ -306,6 +323,7 @@ base::File::Error ObfuscatedFileUtilMemoryDelegate::CopyOrMoveFile(
const base::FilePath& dest_path,
FileSystemOperation::CopyOrMoveOption option,
NativeFileUtil::CopyOrMoveMode mode) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::Optional<DecomposedPath> src_dp = ParsePath(src_path);
base::Optional<DecomposedPath> dest_dp = ParsePath(dest_path);
@@ -361,6 +379,7 @@ base::File::Error ObfuscatedFileUtilMemoryDelegate::CopyOrMoveFile(
bool ObfuscatedFileUtilMemoryDelegate::MoveDirectoryInternal(
const DecomposedPath& src_dp,
const DecomposedPath& dest_dp) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(src_dp.entry->type == Entry::kDirectory);
if (!dest_dp.entry) {
dest_dp.parent->directory_content.insert(
@@ -379,6 +398,7 @@ bool ObfuscatedFileUtilMemoryDelegate::CopyOrMoveFileInternal(
const DecomposedPath& src_dp,
const DecomposedPath& dest_dp,
bool move) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(src_dp.entry->type == Entry::kFile);
if (dest_dp.entry)
dest_dp.parent->directory_content.erase(dest_dp.components.back());
@@ -404,6 +424,7 @@ bool ObfuscatedFileUtilMemoryDelegate::CopyOrMoveFileInternal(
size_t ObfuscatedFileUtilMemoryDelegate::ComputeDirectorySize(
const base::FilePath& path) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::Optional<DecomposedPath> dp = ParsePath(path);
if (!dp || !dp->entry || dp->entry->type != Entry::kDirectory)
return 0;
@@ -427,8 +448,9 @@ size_t ObfuscatedFileUtilMemoryDelegate::ComputeDirectorySize(
int ObfuscatedFileUtilMemoryDelegate::ReadFile(const base::FilePath& path,
int64_t offset,
- net::IOBuffer* buf,
+ scoped_refptr<net::IOBuffer> buf,
int buf_len) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::Optional<DecomposedPath> dp = ParsePath(path);
if (!dp || dp->entry->type != Entry::kFile)
return net::ERR_FILE_NOT_FOUND;
@@ -445,13 +467,15 @@ int ObfuscatedFileUtilMemoryDelegate::ReadFile(const base::FilePath& path,
return buf_len;
}
-int ObfuscatedFileUtilMemoryDelegate::WriteFile(const base::FilePath& path,
- int64_t offset,
- net::IOBuffer* buf,
- int buf_len) {
+int ObfuscatedFileUtilMemoryDelegate::WriteFile(
+ const base::FilePath& path,
+ int64_t offset,
+ scoped_refptr<net::IOBuffer> buf,
+ int buf_len) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::Optional<DecomposedPath> dp = ParsePath(path);
- if (!dp || dp->entry->type != Entry::kFile)
+ if (!dp || !dp->entry || dp->entry->type != Entry::kFile)
return net::ERR_FILE_NOT_FOUND;
size_t offset_u = static_cast<size_t>(offset);
@@ -479,6 +503,7 @@ int ObfuscatedFileUtilMemoryDelegate::WriteFile(const base::FilePath& path,
base::File::Error ObfuscatedFileUtilMemoryDelegate::CreateFileForTesting(
const base::FilePath& path,
base::span<const char> content) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
bool created;
base::File::Error result = EnsureFileExists(path, &created);
if (result != base::File::FILE_OK)
@@ -498,6 +523,7 @@ base::File::Error ObfuscatedFileUtilMemoryDelegate::CopyInForeignFile(
const base::FilePath& dest_path,
FileSystemOperation::CopyOrMoveOption /* option */,
NativeFileUtil::CopyOrMoveMode /* mode */) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::Optional<DecomposedPath> dest_dp = ParsePath(dest_path);
if (!dest_dp || !dest_dp->parent)
diff --git a/storage/browser/file_system/obfuscated_file_util_memory_delegate.h b/storage/browser/file_system/obfuscated_file_util_memory_delegate.h
index 4dd25b48affa901251ec4ec54dc6221a60626d19..d1240511303860e67603543e5795c893ef0db482 100644
--- a/storage/browser/file_system/obfuscated_file_util_memory_delegate.h
+++ b/storage/browser/file_system/obfuscated_file_util_memory_delegate.h
@@ -88,7 +88,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) ObfuscatedFileUtilMemoryDelegate
// bytes are returned. Otherwise a net::Error value is returned.
int ReadFile(const base::FilePath& path,
int64_t offset,
- net::IOBuffer* buf,
+ scoped_refptr<net::IOBuffer> buf,
int buf_len);
// Writes |buf_len| bytes to the file at |path|, starting from |offset|.
@@ -96,7 +96,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) ObfuscatedFileUtilMemoryDelegate
// net::Error value is returned.
int WriteFile(const base::FilePath& path,
int64_t offset,
- net::IOBuffer* buf,
+ scoped_refptr<net::IOBuffer> buf,
int buf_len);
base::File::Error CreateFileForTesting(const base::FilePath& path,
@@ -126,6 +126,8 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) ObfuscatedFileUtilMemoryDelegate
const DecomposedPath& dest_dp,
bool move);
+ SEQUENCE_CHECKER(sequence_checker_);
+
// The root of the directory tree.
std::unique_ptr<Entry> root_;
diff --git a/storage/browser/file_system/sandbox_file_stream_writer.cc b/storage/browser/file_system/sandbox_file_stream_writer.cc
index 21495aee42684fcbe7c79fa5d26ad4f2006da875..d344e8ae71e254c2fc758e6a8f6b219d4b145805 100644
--- a/storage/browser/file_system/sandbox_file_stream_writer.cc
+++ b/storage/browser/file_system/sandbox_file_stream_writer.cc
@@ -155,6 +155,7 @@ void SandboxFileStreamWriter::DidCreateSnapshotFile(
file_system_context_->sandbox_delegate()->memory_file_util_delegate();
}
file_writer_ = FileStreamWriter::CreateForMemoryFile(
+ file_system_context_->default_file_task_runner(),
memory_file_util_delegate, platform_path, initial_offset_);
} else {

View File

@@ -0,0 +1,64 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alexander Cooper <alcooper@chromium.org>
Date: Tue, 4 Aug 2020 00:31:54 +0000
Subject: Update FocusChanged notifiers to operate on a copy
These focus changed calls ultimately trigger javascript events. These
events could potentially run code that would modify the list of items
that the FocusChanged notifiers are notifying, and thus invalidate their
in-use iterators.
Fix this by having these methods iterate over a copy instead of the
member list.
(cherry picked from commit d8f526f4e25c24ed29e60b46b3416bfabd5e8f11)
Fixed: 1107815
Change-Id: I03fa08eeadc60736f3a3fae079253dbd3ee26476
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2314158
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Reviewed-by: Klaus Weidner <klausw@chromium.org>
Commit-Queue: Daniel Cheng <dcheng@chromium.org>
Auto-Submit: Alexander Cooper <alcooper@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#791261}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2335893
Reviewed-by: Alexander Cooper <alcooper@chromium.org>
Commit-Queue: Alexander Cooper <alcooper@chromium.org>
Cr-Commit-Position: refs/branch-heads/4147@{#1015}
Cr-Branched-From: 16307825352720ae04d898f37efa5449ad68b606-refs/heads/master@{#768962}
diff --git a/third_party/blink/renderer/core/page/focus_controller.cc b/third_party/blink/renderer/core/page/focus_controller.cc
index 225ff4339c3a9b0bd79b3a188e28cf615e6ed97c..19215d532094c340dd146660b062aeb3293b7bc3 100644
--- a/third_party/blink/renderer/core/page/focus_controller.cc
+++ b/third_party/blink/renderer/core/page/focus_controller.cc
@@ -1335,7 +1335,12 @@ void FocusController::RegisterFocusChangedObserver(
}
void FocusController::NotifyFocusChangedObservers() const {
- for (const auto& it : focus_changed_observers_)
+ // Since this eventually dispatches an event to the page, the page could add
+ // new observer, which would invalidate our iterators; so iterate over a copy
+ // of the observer list.
+ HeapHashSet<WeakMember<FocusChangedObserver>> observers =
+ focus_changed_observers_;
+ for (const auto& it : observers)
it->FocusedFrameChanged();
}
diff --git a/third_party/blink/renderer/modules/xr/xr_system.cc b/third_party/blink/renderer/modules/xr/xr_system.cc
index a94164360dcfe0e0686e5d48e64ee8a4dc9ef125..8b22f66e7f0c9e905d9a6503abb557287c6e456b 100644
--- a/third_party/blink/renderer/modules/xr/xr_system.cc
+++ b/third_party/blink/renderer/modules/xr/xr_system.cc
@@ -682,7 +682,11 @@ XRSystem::XRSystem(LocalFrame& frame, int64_t ukm_source_id)
void XRSystem::FocusedFrameChanged() {
// Tell all sessions that focus changed.
- for (const auto& session : sessions_) {
+ // Since this eventually dispatches an event to the page, the page could
+ // create a new session which would invalidate our iterators; so iterate over
+ // a copy of the session map.
+ HeapHashSet<WeakMember<XRSession>> processing_sessions = sessions_;
+ for (const auto& session : processing_sessions) {
session->OnFocusChanged();
}

View File

@@ -0,0 +1,160 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Reilly Grant <reillyg@chromium.org>
Date: Wed, 7 Oct 2020 23:26:36 +0000
Subject: usb: Prevent parallel calls to UsbDevice::Open
This change adds a check to prevent a Mojo client from calling Open()
multiple times while the open is in progress.
Bug: 1135857
Change-Id: Ib467de9129673710b883d9e186c32c359f8592d8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2454846
Auto-Submit: Reilly Grant <reillyg@chromium.org>
Reviewed-by: Matt Reynolds <mattreynolds@chromium.org>
Commit-Queue: Reilly Grant <reillyg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#814940}
diff --git a/services/device/usb/mojo/device_impl.cc b/services/device/usb/mojo/device_impl.cc
index 6507b470afd2756878cd0990cfa7da2b9c730036..3dc07f879d70bc7755e59be1864a17f9a8e0ef10 100644
--- a/services/device/usb/mojo/device_impl.cc
+++ b/services/device/usb/mojo/device_impl.cc
@@ -160,6 +160,7 @@ void DeviceImpl::OnOpen(base::WeakPtr<DeviceImpl> self,
return;
}
+ self->opening_ = false;
self->device_handle_ = std::move(handle);
if (self->device_handle_ && self->client_)
self->client_->OnDeviceOpened();
@@ -175,16 +176,19 @@ void DeviceImpl::OnPermissionGrantedForOpen(OpenCallback callback,
device_->Open(base::BindOnce(
&DeviceImpl::OnOpen, weak_factory_.GetWeakPtr(), std::move(callback)));
} else {
+ opening_ = false;
std::move(callback).Run(mojom::UsbOpenDeviceError::ACCESS_DENIED);
}
}
void DeviceImpl::Open(OpenCallback callback) {
- if (device_handle_) {
+ if (opening_ || device_handle_) {
std::move(callback).Run(mojom::UsbOpenDeviceError::ALREADY_OPEN);
return;
}
+ opening_ = true;
+
if (!device_->permission_granted()) {
device_->RequestPermission(
base::BindOnce(&DeviceImpl::OnPermissionGrantedForOpen,
diff --git a/services/device/usb/mojo/device_impl.h b/services/device/usb/mojo/device_impl.h
index 60ccbcc2e1e3ed964341a7bb8581c142eb27cf40..ab0a3797ae0031708b42f9f1cbc5bddb6f42efac 100644
--- a/services/device/usb/mojo/device_impl.h
+++ b/services/device/usb/mojo/device_impl.h
@@ -104,7 +104,9 @@ class DeviceImpl : public mojom::UsbDevice, public device::UsbDevice::Observer {
ScopedObserver<device::UsbDevice, device::UsbDevice::Observer> observer_;
// The device handle. Will be null before the device is opened and after it
- // has been closed.
+ // has been closed. |opening_| is set to true while the asynchronous open is
+ // in progress.
+ bool opening_ = false;
scoped_refptr<UsbDeviceHandle> device_handle_;
mojo::SelfOwnedReceiverRef<mojom::UsbDevice> receiver_;
diff --git a/services/device/usb/mojo/device_impl_unittest.cc b/services/device/usb/mojo/device_impl_unittest.cc
index f0cd0eab4cf04d6f922c1748274d8f5f07a9452e..81045373bb3fa306b78f580f87424eacba36cd3d 100644
--- a/services/device/usb/mojo/device_impl_unittest.cc
+++ b/services/device/usb/mojo/device_impl_unittest.cc
@@ -22,6 +22,7 @@
#include "base/memory/ref_counted_memory.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
+#include "base/test/bind_test_util.h"
#include "base/test/task_environment.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "mojo/public/cpp/bindings/receiver.h"
@@ -265,7 +266,10 @@ class USBDeviceImplTest : public testing::Test {
void OpenMockHandle(UsbDevice::OpenCallback& callback) {
EXPECT_FALSE(is_device_open_);
is_device_open_ = true;
- std::move(callback).Run(mock_handle_);
+ // Simulate the asynchronous device opening process.
+ base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, base::BindOnce(std::move(callback), mock_handle_),
+ base::TimeDelta::FromMilliseconds(1));
}
void CloseMockHandle() {
@@ -515,17 +519,39 @@ TEST_F(USBDeviceImplTest, OpenFailure) {
GetMockDeviceProxy(device_client.CreateInterfacePtrAndBind());
EXPECT_CALL(mock_device(), OpenInternal(_))
- .WillOnce(Invoke([](UsbDevice::OpenCallback& callback) {
+ .WillOnce([](UsbDevice::OpenCallback& callback) {
std::move(callback).Run(nullptr);
- }));
+ });
EXPECT_CALL(device_client, OnDeviceOpened()).Times(0);
EXPECT_CALL(device_client, OnDeviceClosed()).Times(0);
- base::RunLoop loop;
- device->Open(base::BindOnce(&ExpectOpenAndThen,
- mojom::UsbOpenDeviceError::ACCESS_DENIED,
- loop.QuitClosure()));
- loop.Run();
+ {
+ base::RunLoop loop;
+ device->Open(
+ base::BindLambdaForTesting([&](mojom::UsbOpenDeviceError result) {
+ EXPECT_EQ(result, mojom::UsbOpenDeviceError::ACCESS_DENIED);
+ loop.Quit();
+ }));
+ loop.Run();
+ }
+
+ // A second attempt can succeed.
+ EXPECT_CALL(mock_device(), OpenInternal(_));
+ EXPECT_CALL(device_client, OnDeviceOpened());
+ EXPECT_CALL(device_client, OnDeviceClosed());
+
+ {
+ base::RunLoop loop;
+ device->Open(
+ base::BindLambdaForTesting([&](mojom::UsbOpenDeviceError result) {
+ EXPECT_EQ(result, mojom::UsbOpenDeviceError::OK);
+ loop.Quit();
+ }));
+ loop.Run();
+ }
+
+ device.reset();
+ base::RunLoop().RunUntilIdle();
}
TEST_F(USBDeviceImplTest, OpenDelayedFailure) {
@@ -549,6 +575,24 @@ TEST_F(USBDeviceImplTest, OpenDelayedFailure) {
std::move(saved_callback).Run(nullptr);
}
+TEST_F(USBDeviceImplTest, MultipleOpenNotAllowed) {
+ MockUsbDeviceClient device_client;
+ mojo::Remote<mojom::UsbDevice> device =
+ GetMockDeviceProxy(device_client.CreateInterfacePtrAndBind());
+
+ base::RunLoop loop;
+ device->Open(
+ base::BindLambdaForTesting([&](mojom::UsbOpenDeviceError result) {
+ EXPECT_EQ(result, mojom::UsbOpenDeviceError::OK);
+ }));
+ device->Open(
+ base::BindLambdaForTesting([&](mojom::UsbOpenDeviceError result) {
+ EXPECT_EQ(result, mojom::UsbOpenDeviceError::ALREADY_OPEN);
+ loop.Quit();
+ }));
+ loop.Run();
+}
+
TEST_F(USBDeviceImplTest, Close) {
MockUsbDeviceClient device_client;
mojo::Remote<mojom::UsbDevice> device =

View File

@@ -0,0 +1,64 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Guido Urdaneta <guidou@chromium.org>
Date: Wed, 14 Oct 2020 19:40:12 +0000
Subject: Validate input of MediaStreamDispatcherHost::OpenDevice()
This method forwards to MediaStreamManager::OpenDevice(), which
DCHECKs for the stream type to be device video or audio capture
(i.e., webcam or mic). However, MSDH admits other stream types,
which cause MSM::OpenDevice to hit this DCHECK.
This CL ensures that a message containing an incorrect stream type,
which could be sent by a malicious renderer, results in killing the
renderer process.
Bug: 1135018
Change-Id: I3884dde95d92c41f44966a8ab1dd7bdfd4b23b9b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2472397
Auto-Submit: Guido Urdaneta <guidou@chromium.org>
Commit-Queue: Guido Urdaneta <guidou@chromium.org>
Reviewed-by: Avi Drissman <avi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#817151}
diff --git a/content/browser/bad_message.h b/content/browser/bad_message.h
index 473a6a93edc4491e36ebc28b28e8a05b9fb64d62..3a2bcf0655dd02b95425c43caa3b8e5d896d7375 100644
--- a/content/browser/bad_message.h
+++ b/content/browser/bad_message.h
@@ -253,6 +253,7 @@ enum BadMessageReason {
RFH_BAD_DOCUMENT_POLICY_HEADER = 225,
RFMF_INVALID_PLUGIN_EMBEDDER_ORIGIN = 226,
RFH_INVALID_CALL_FROM_NOT_MAIN_FRAME = 227,
+ MSDH_INVALID_STREAM_TYPE = 234,
// Please add new elements here. The naming convention is abbreviated class
// name (e.g. RenderFrameHost becomes RFH) plus a unique description of the
diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host.cc b/content/browser/renderer_host/media/media_stream_dispatcher_host.cc
index 1a3b5b446bbff28e60278bfe5f29e13acc3c5306..488b6746a3545f687159dabfee4dd278c1eaea0e 100644
--- a/content/browser/renderer_host/media/media_stream_dispatcher_host.cc
+++ b/content/browser/renderer_host/media/media_stream_dispatcher_host.cc
@@ -196,6 +196,13 @@ void MediaStreamDispatcherHost::OpenDevice(int32_t page_request_id,
blink::mojom::MediaStreamType type,
OpenDeviceCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ // OpenDevice is only supported for microphone or webcam capture.
+ if (type != blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE &&
+ type != blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE) {
+ bad_message::ReceivedBadMessage(
+ render_process_id_, bad_message::MDDH_INVALID_DEVICE_TYPE_REQUEST);
+ return;
+ }
base::PostTaskAndReplyWithResult(
base::CreateSingleThreadTaskRunner({BrowserThread::UI}).get(), FROM_HERE,
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index d69575e355a2692531a9c76ccdb6bb69eae07da8..21dc7d1d1b07e246232d128cd6a7084915ca0c6c 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -5668,6 +5668,7 @@ Unknown properties are collapsed to zero. -->
<int value="225" label="RFH_BAD_DOCUMENT_POLICY_HEADER"/>
<int value="226" label="RFMF_INVALID_PLUGIN_EMBEDDER_ORIGIN"/>
<int value="227" label="RFH_INVALID_CALL_FROM_NOT_MAIN_FRAME"/>
+ <int value="234" label="MSDH_INVALID_STREAM_TYPE"/>
</enum>
<enum name="BadMessageReasonExtensions">

View File

@@ -0,0 +1,29 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lei Zhang <thestig@chromium.org>
Date: Thu, 1 Oct 2020 19:18:54 +0000
Subject: Check RF is alive In PrintRenderFrameHelper::PreviewPageRendered().
Do not take an accessibility snapshot if the RenderFrame is gone.
Bug: 1133983
Change-Id: I612cc72936a1dcedc5180c24eae067e47237b09b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2442375
Reviewed-by: Dominic Mazzoni <dmazzoni@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
Cr-Commit-Position: refs/heads/master@{#812851}
diff --git a/components/printing/renderer/print_render_frame_helper.cc b/components/printing/renderer/print_render_frame_helper.cc
index 9dd56e9df0d91ccd1d6789e3b3f261a533d373e8..340c31dc77d719dcf37f23770f16ca9e64536b03 100644
--- a/components/printing/renderer/print_render_frame_helper.cc
+++ b/components/printing/renderer/print_render_frame_helper.cc
@@ -2403,6 +2403,10 @@ bool PrintRenderFrameHelper::PreviewPageRendered(
DCHECK(print_preview_context_.IsModifiable());
#if BUILDFLAG(ENABLE_TAGGED_PDF)
+ // Make sure the RenderFrame is alive before taking the snapshot.
+ if (render_frame_gone_)
+ snapshotter_.reset();
+
// For tagged PDF exporting, send a snapshot of the accessibility tree
// along with page 0. The accessibility tree contains the content for
// all of the pages of the main frame.

View File

@@ -0,0 +1,61 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Xiaocheng Hu <xiaochengh@chromium.org>
Date: Tue, 3 Nov 2020 23:00:29 +0000
Subject: Apply markup sanitizer in CompositeEditCommand::MoveParagraphs()
CompositeEditCommand::MoveParagraphs() serailizes part of the DOM and
then re-parse it and insert it at some other place of the document. This
is essentially a copy-and-paste, and can be exploited in the same way
how copy-and-paste is exploited. So we should also sanitize markup in
the function.
(cherry picked from commit c529cbcc1bb0f72af944c30f03c2b3b435317bc7)
Bug: 1141350
Change-Id: I25c1dfc61c20b9134b23e057c5a3a0f56c190b5c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2500633
Commit-Queue: Yoshifumi Inoue <yosin@chromium.org>
Reviewed-by: Yoshifumi Inoue <yosin@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#821098}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2518088
Reviewed-by: Xiaocheng Hu <xiaochengh@chromium.org>
Commit-Queue: Xiaocheng Hu <xiaochengh@chromium.org>
Cr-Commit-Position: refs/branch-heads/4280@{#1099}
Cr-Branched-From: ea420fb963f9658c9969b6513c56b8f47efa1a2a-refs/heads/master@{#812852}
diff --git a/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc b/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc
index a665fe438041cce473b195a606378ee26500ebc4..2ba9c0cd368b3b907320ef2d6de550ae7598779e 100644
--- a/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc
@@ -1492,19 +1492,18 @@ void CompositeEditCommand::MoveParagraphs(
// FIXME: This is an inefficient way to preserve style on nodes in the
// paragraph to move. It shouldn't matter though, since moved paragraphs will
// usually be quite small.
- DocumentFragment* fragment =
- start_of_paragraph_to_move.DeepEquivalent() !=
- end_of_paragraph_to_move.DeepEquivalent()
- ? CreateFragmentFromMarkup(
- GetDocument(),
- CreateMarkup(start.ParentAnchoredEquivalent(),
- end.ParentAnchoredEquivalent(),
- CreateMarkupOptions::Builder()
- .SetShouldConvertBlocksToInlines(true)
- .SetConstrainingAncestor(constraining_ancestor)
- .Build()),
- "", kDisallowScriptingAndPluginContent)
- : nullptr;
+ DocumentFragment* fragment = nullptr;
+ if (start_of_paragraph_to_move.DeepEquivalent() !=
+ end_of_paragraph_to_move.DeepEquivalent()) {
+ const String paragraphs_markup = CreateMarkup(
+ start.ParentAnchoredEquivalent(), end.ParentAnchoredEquivalent(),
+ CreateMarkupOptions::Builder()
+ .SetShouldConvertBlocksToInlines(true)
+ .SetConstrainingAncestor(constraining_ancestor)
+ .Build());
+ fragment = CreateSanitizedFragmentFromMarkupWithContext(
+ GetDocument(), paragraphs_markup, 0, paragraphs_markup.length(), "");
+ }
// A non-empty paragraph's style is moved when we copy and move it. We don't
// move anything if we're given an empty paragraph, but an empty paragraph can

View File

@@ -0,0 +1,115 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Rahul Arakeri <arakeri@microsoft.com>
Date: Tue, 8 Sep 2020 20:36:24 +0000
Subject: Fix for UAF when referencing a deleted scrollbar layer.
This CL fixes an issue where autoscroll may be called on a scrollbar
layer that is deleted. When the pointer is pressed down, an autoscroll
task is scheduled to be executed after ~250ms. The task will execute if
the pointer remains held down. In LayerTreeImpl::UnregisterScrollbar,
DidUnregisterScrollbarLayer only gets called after both scrollbars are
removed. So if you go from 2 to 1 scrollbar while an autoscroll task is
queued, the autoscroll task won't get cancelled. At this point, the
ScrollbarController tries to access the deleted scrollbar and that
leads to an access violation. The fix here is to ensure that the call
to DidUnregisterScrollbarLayer happens for each scrollbar.
Bug: 1106612
Change-Id: I4f1d684830012db8fdd73258c9a9e5231807bcb6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2356809
Reviewed-by: Robert Flack <flackr@chromium.org>
Commit-Queue: Rahul Arakeri <arakeri@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#805057}
(cherry picked from commit 52dceba66599f0892fb649717fc462ff016d2fa2)
diff --git a/cc/input/scrollbar_controller.cc b/cc/input/scrollbar_controller.cc
index b4d2ef531e2f5ccee157babb67522c454c720c9e..be80b5e07f5330ac636946f32f6cf713e0bb77a5 100644
--- a/cc/input/scrollbar_controller.cc
+++ b/cc/input/scrollbar_controller.cc
@@ -433,9 +433,12 @@ void ScrollbarController::ResetState() {
captured_scrollbar_metadata_ = base::nullopt;
}
-void ScrollbarController::DidUnregisterScrollbar(ElementId element_id) {
+void ScrollbarController::DidUnregisterScrollbar(
+ ElementId element_id,
+ ScrollbarOrientation orientation) {
if (captured_scrollbar_metadata_.has_value() &&
- captured_scrollbar_metadata_->scroll_element_id == element_id)
+ captured_scrollbar_metadata_->scroll_element_id == element_id &&
+ captured_scrollbar_metadata_->orientation == orientation)
ResetState();
}
@@ -531,6 +534,7 @@ void ScrollbarController::StartAutoScrollAnimation(
// the same time.
DCHECK(!drag_state_.has_value());
DCHECK_NE(velocity, 0);
+ DCHECK(ScrollbarLayer());
// scroll_node is set up while handling GSB. If there's no node to scroll, we
// don't need to create any animation for it.
diff --git a/cc/input/scrollbar_controller.h b/cc/input/scrollbar_controller.h
index ab93bde692dfc48f3d2e2f95ca56c984e8d0eb88..c9faf8ca505776b1b2764225427e28008ae74c8e 100644
--- a/cc/input/scrollbar_controller.h
+++ b/cc/input/scrollbar_controller.h
@@ -135,7 +135,8 @@ class CC_EXPORT ScrollbarController {
const ScrollbarLayerImplBase* scrollbar,
ScrollbarPart pressed_scrollbar_part);
bool ScrollbarScrollIsActive() { return scrollbar_scroll_is_active_; }
- void DidUnregisterScrollbar(ElementId element_id);
+ void DidUnregisterScrollbar(ElementId element_id,
+ ScrollbarOrientation orientation);
ScrollbarLayerImplBase* ScrollbarLayer();
void WillBeginImplFrame();
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 688a0905c997c86b63bcc607033ec82a74741114..46821befb4f1720a93cb9e4b8e9d33bd45a6292a 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -5326,9 +5326,10 @@ void LayerTreeHostImpl::RegisterScrollbarAnimationController(
}
void LayerTreeHostImpl::DidUnregisterScrollbarLayer(
- ElementId scroll_element_id) {
+ ElementId scroll_element_id,
+ ScrollbarOrientation orientation) {
scrollbar_animation_controllers_.erase(scroll_element_id);
- scrollbar_controller_->DidUnregisterScrollbar(scroll_element_id);
+ scrollbar_controller_->DidUnregisterScrollbar(scroll_element_id, orientation);
}
ScrollbarAnimationController*
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index 2352d8e17c316542f2d65f6e1c6b075db9cf66bd..f2272d0c760f3301b0b64d81d6372758110798e9 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -464,7 +464,8 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandler,
void RegisterScrollbarAnimationController(ElementId scroll_element_id,
float initial_opacity);
- void DidUnregisterScrollbarLayer(ElementId scroll_element_id);
+ void DidUnregisterScrollbarLayer(ElementId scroll_element_id,
+ ScrollbarOrientation orientation);
ScrollbarAnimationController* ScrollbarAnimationControllerForElementId(
ElementId scroll_element_id) const;
void FlashAllScrollbars(bool did_scroll);
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index 45f7e5707a0ab5b983294964369d549e2981bf7d..2b6ea7532e954babe7150386209e958546b9bc40 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -1933,9 +1933,11 @@ void LayerTreeImpl::UnregisterScrollbar(
if (scrollbar_ids.horizontal == Layer::INVALID_ID &&
scrollbar_ids.vertical == Layer::INVALID_ID) {
element_id_to_scrollbar_layer_ids_.erase(scroll_element_id);
- if (IsActiveTree()) {
- host_impl_->DidUnregisterScrollbarLayer(scroll_element_id);
- }
+ }
+
+ if (IsActiveTree()) {
+ host_impl_->DidUnregisterScrollbarLayer(scroll_element_id,
+ scrollbar_layer->orientation());
}
}

View File

@@ -0,0 +1,37 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Darwin Huang <huangdarwin@chromium.org>
Date: Fri, 13 Nov 2020 10:07:05 +0000
Subject: Pepper: Ensure weak pointer is still valid before use (M86).
TBR=bbudge@chromium.org
(cherry picked from commit f24c213293752250db05e11c5e4b77adce002d38)
Bug: 1146675
Change-Id: I382dcb5c0b09a26e3c397ebef46947f626e2aef9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2527065
Reviewed-by: Bill Budge <bbudge@chromium.org>
Commit-Queue: Darwin Huang <huangdarwin@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#825558}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2536757
Reviewed-by: Darwin Huang <huangdarwin@chromium.org>
Cr-Commit-Position: refs/branch-heads/4240@{#1448}
Cr-Branched-From: f297677702651916bbf65e59c0d4bbd4ce57d1ee-refs/heads/master@{#800218}
diff --git a/content/browser/renderer_host/pepper/pepper_file_io_host.cc b/content/browser/renderer_host/pepper/pepper_file_io_host.cc
index bd68358ddb41529bf946d10d7eb66ff4b6d20519..ae42a62622724d4aee85a066f1931deea7f00037 100644
--- a/content/browser/renderer_host/pepper/pepper_file_io_host.cc
+++ b/content/browser/renderer_host/pepper/pepper_file_io_host.cc
@@ -248,7 +248,12 @@ void PepperFileIOHost::GotUIThreadStuffForInternalFileSystems(
return;
}
- DCHECK(file_system_host_.get());
+ if (!file_system_host_.get()) {
+ reply_context.params.set_result(PP_ERROR_FAILED);
+ SendOpenErrorReply(reply_context);
+ return;
+ }
+
DCHECK(file_system_host_->GetFileSystemOperationRunner());
file_system_host_->GetFileSystemOperationRunner()->OpenFile(

View File

@@ -0,0 +1,78 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Reilly Grant <reillyg@chromium.org>
Date: Wed, 22 Jul 2020 04:00:16 +0000
Subject: usb: Prevent iterator invalidation during Promise resolution
This change swaps sets of ScriptPromiseResolvers into local variables in
a number of places where it was possible for script to execute during
the call to Resolve() or Reject() and modify the set being iterated
over, thus invalidating the iterator.
(cherry picked from commit dbc6c3c3652680e287c60b3c6551622748543439)
Bug: 1106773
Change-Id: Id4eb0cd444a7dbb5de23038ec80f44fee649cfe4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2304538
Auto-Submit: Reilly Grant <reillyg@chromium.org>
Commit-Queue: James Hollyer <jameshollyer@chromium.org>
Reviewed-by: James Hollyer <jameshollyer@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#790217}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2310964
Reviewed-by: Reilly Grant <reillyg@chromium.org>
Commit-Queue: Reilly Grant <reillyg@chromium.org>
Cr-Commit-Position: refs/branch-heads/4183@{#842}
Cr-Branched-From: 740e9e8a40505392ba5c8e022a8024b3d018ca65-refs/heads/master@{#782793}
diff --git a/third_party/blink/renderer/modules/webusb/usb.cc b/third_party/blink/renderer/modules/webusb/usb.cc
index de66613d20851dee9a96a8fdcfaec30da9f05b53..e3dc44eb208946aac4a2f836365127ba88c08edd 100644
--- a/third_party/blink/renderer/modules/webusb/usb.cc
+++ b/third_party/blink/renderer/modules/webusb/usb.cc
@@ -254,15 +254,22 @@ void USB::OnDeviceRemoved(UsbDeviceInfoPtr device_info) {
void USB::OnServiceConnectionError() {
service_.reset();
client_receiver_.reset();
- for (ScriptPromiseResolver* resolver : get_devices_requests_)
+
+ // Move the set to a local variable to prevent script execution in Resolve()
+ // from invalidating the iterator used by the loop.
+ HeapHashSet<Member<ScriptPromiseResolver>> get_devices_requests;
+ get_devices_requests.swap(get_devices_requests_);
+ for (auto& resolver : get_devices_requests)
resolver->Resolve(HeapVector<Member<USBDevice>>(0));
- get_devices_requests_.clear();
- for (ScriptPromiseResolver* resolver : get_permission_requests_) {
+ // Move the set to a local variable to prevent script execution in Reject()
+ // from invalidating the iterator used by the loop.
+ HeapHashSet<Member<ScriptPromiseResolver>> get_permission_requests;
+ get_permission_requests.swap(get_permission_requests_);
+ for (auto& resolver : get_permission_requests) {
resolver->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kNotFoundError, kNoDeviceSelected));
}
- get_permission_requests_.clear();
}
void USB::AddedEventListener(const AtomicString& event_type,
diff --git a/third_party/blink/renderer/modules/webusb/usb_device.cc b/third_party/blink/renderer/modules/webusb/usb_device.cc
index 655212ee5dd6c27498b83b8eb5b9e13a14c38a40..17f52e86a134ceb137923b65d1686ce3cbf3bf85 100644
--- a/third_party/blink/renderer/modules/webusb/usb_device.cc
+++ b/third_party/blink/renderer/modules/webusb/usb_device.cc
@@ -1125,11 +1125,15 @@ void USBDevice::AsyncReset(ScriptPromiseResolver* resolver, bool success) {
void USBDevice::OnConnectionError() {
device_.reset();
opened_ = false;
- for (ScriptPromiseResolver* resolver : device_requests_) {
+
+ // Move the set to a local variable to prevent script execution in Reject()
+ // from invalidating the iterator used by the loop.
+ HeapHashSet<Member<ScriptPromiseResolver>> device_requests;
+ device_requests.swap(device_requests_);
+ for (auto& resolver : device_requests) {
resolver->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kNotFoundError, kDeviceDisconnected));
}
- device_requests_.clear();
}
bool USBDevice::MarkRequestComplete(ScriptPromiseResolver* resolver) {

View File

@@ -0,0 +1,83 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Hiroki Nakagawa <nhiroki@chromium.org>
Date: Fri, 7 Aug 2020 15:27:06 +0000
Subject: Worker: Fix a race condition on task runner handling
WebSharedWorkerImpl accesses WorkerScheduler from the main thread to
take a task runner, and then dispatches a connect event to
SharedWorkerGlobalScope using the task runner.
This causes a race condition if close() is called on the global scope
on the worker thread while the task runner is being taken on the main
thread: close() call disposes of WorkerScheduler, and accessing the
scheduler after that is not allowed. See the issue for details.
To fix this, this CL makes WebSharedWorkerImpl capture the task runner
between starting a worker thread (initializing WorkerScheduler) and
posting a task to evaluate worker scripts that may call close(). This
ensures that WebSharedWorkerImpl accesses WorkerScheduler before the
scheduler is disposed of.
(cherry picked from commit c7bbec3e595c4359e36e5472b7265c4b6d047f2c)
Bug: 1104046
Change-Id: I145cd39f706019c33220fcb01ed81f76963ffff0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2308550
Commit-Queue: Hiroki Nakagawa <nhiroki@chromium.org>
Reviewed-by: Kenichi Ishibashi <bashi@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#790284}
Tbr: bashi@chromium.org
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2342337
Reviewed-by: Hiroki Nakagawa <nhiroki@chromium.org>
Cr-Commit-Position: refs/branch-heads/4147@{#1050}
Cr-Branched-From: 16307825352720ae04d898f37efa5449ad68b606-refs/heads/master@{#768962}
diff --git a/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc b/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc
index 7582cdbd3a1ee5e8a58686715020f304319860d8..9942e60d41f4add60bf28388902e08bc1d071dc7 100644
--- a/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc
@@ -145,11 +145,8 @@ void WebSharedWorkerImpl::Connect(MessagePortChannel web_channel) {
DCHECK(IsMainThread());
if (asked_to_terminate_)
return;
- // The HTML spec requires to queue a connect event using the DOM manipulation
- // task source.
- // https://html.spec.whatwg.org/C/#shared-workers-and-the-sharedworker-interface
PostCrossThreadTask(
- *GetWorkerThread()->GetTaskRunner(TaskType::kDOMManipulation), FROM_HERE,
+ *task_runner_for_connect_event_, FROM_HERE,
CrossThreadBindOnce(&WebSharedWorkerImpl::ConnectTaskOnWorkerThread,
WTF::CrossThreadUnretained(this),
WTF::Passed(std::move(web_channel))));
@@ -269,6 +266,18 @@ void WebSharedWorkerImpl::StartWorkerContext(
GetWorkerThread()->Start(std::move(creation_params), thread_startup_data,
std::move(devtools_params));
+
+ // Capture the task runner for dispatching connect events. This is necessary
+ // for avoiding race condition with WorkerScheduler termination induced by
+ // close() call on SharedWorkerGlobalScope. See https://crbug.com/1104046 for
+ // details.
+ //
+ // The HTML spec requires to queue a connect event using the DOM manipulation
+ // task source.
+ // https://html.spec.whatwg.org/C/#shared-workers-and-the-sharedworker-interface
+ task_runner_for_connect_event_ =
+ GetWorkerThread()->GetTaskRunner(TaskType::kDOMManipulation);
+
switch (script_type) {
case mojom::ScriptType::kClassic:
GetWorkerThread()->FetchAndRunClassicScript(
diff --git a/third_party/blink/renderer/core/exported/web_shared_worker_impl.h b/third_party/blink/renderer/core/exported/web_shared_worker_impl.h
index 13006f67bd3e10b8d6c38e504d4bf235aa2f9022..98374fb9031e200a225e6e2982ff2d364fa007f5 100644
--- a/third_party/blink/renderer/core/exported/web_shared_worker_impl.h
+++ b/third_party/blink/renderer/core/exported/web_shared_worker_impl.h
@@ -114,6 +114,8 @@ class CORE_EXPORT WebSharedWorkerImpl final : public WebSharedWorker {
// |client_| owns |this|.
WebSharedWorkerClient* client_;
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_for_connect_event_;
+
bool asked_to_terminate_ = false;
base::WeakPtrFactory<WebSharedWorkerImpl> weak_ptr_factory_{this};

View File

@@ -0,0 +1,54 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Andrey Kosyakov <caseq@chromium.org>
Date: Fri, 28 Aug 2020 18:55:17 +0000
Subject: Delegate TargetHandler::Session permission checks to the root client
Bug: 1114636
Change-Id: Iba3865206d7e80b363ec69180ac05e20b56aade2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2380855
Reviewed-by: Dmitry Gozman <dgozman@chromium.org>
Reviewed-by: Devlin <rdevlin.cronin@chromium.org>
Commit-Queue: Andrey Kosyakov <caseq@chromium.org>
Cr-Commit-Position: refs/heads/master@{#802736}
(cherry picked from commit 814a27f8522b6ccddcce1a8f6a3b8fb37128ecf9)
diff --git a/content/browser/devtools/protocol/target_handler.cc b/content/browser/devtools/protocol/target_handler.cc
index 4614ecae2110e5577539cffba02fcab153af301f..bcd054f2dc388908cf92bae3ff0254422960dc12 100644
--- a/content/browser/devtools/protocol/target_handler.cc
+++ b/content/browser/devtools/protocol/target_handler.cc
@@ -436,7 +436,7 @@ class TargetHandler::Session : public DevToolsAgentHostClient {
// was introduced. Try a DCHECK instead and possibly remove the check.
if (!handler_->root_session_->HasChildSession(id_))
return;
- handler_->root_session_->GetClient()->DispatchProtocolMessage(
+ GetRootClient()->DispatchProtocolMessage(
handler_->root_session_->GetAgentHost(), message);
return;
}
@@ -454,6 +454,26 @@ class TargetHandler::Session : public DevToolsAgentHostClient {
Detach(true);
}
+ bool MayAttachToURL(const GURL& url, bool is_webui) override {
+ return GetRootClient()->MayAttachToURL(url, is_webui);
+ }
+
+ bool MayAttachToBrowser() override {
+ return GetRootClient()->MayAttachToBrowser();
+ }
+
+ bool MayReadLocalFiles() override {
+ return GetRootClient()->MayReadLocalFiles();
+ }
+
+ bool MayWriteLocalFiles() override {
+ return GetRootClient()->MayWriteLocalFiles();
+ }
+
+ content::DevToolsAgentHostClient* GetRootClient() {
+ return handler_->root_session_->GetClient();
+ }
+
TargetHandler* handler_;
scoped_refptr<DevToolsAgentHost> agent_host_;
std::string id_;

View File

@@ -0,0 +1,292 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Raymond Toy <rtoy@chromium.org>
Date: Tue, 29 Sep 2020 17:56:16 +0000
Subject: Add mutex for allowing the graph to be pulled
Basically add a mutex to protect access to
allow_pulling_audio_graph_. The main thread waits until it has the
lock before setting this. This prevents the main thread from deleting
things while the audio thread is pulling on the graph.
A try lock is used so as not to block the audio thread if it can't get
lock.
This is applied to both real time and offline contexts which required
moving the original real-time-only implementation to
audio_destination_node so we can use the same methods for the offline
context.
Tested the repro case from 1125635, and the issue does not reproduce.
We're assuming this will fix 1115901, but I've not been able to
reproduce that locally.
(cherry picked from commit 6785a406fd652f7a2f40933620ef4c979643c56b)
Bug: 1125635, 1115901
Change-Id: I1037d8c44225c6dcc8fe906c29a5a86740a15e1d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2410743
Reviewed-by: Hongchan Choi <hongchan@chromium.org>
Commit-Queue: Raymond Toy <rtoy@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#809393}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2436324
Reviewed-by: Raymond Toy <rtoy@chromium.org>
Cr-Commit-Position: refs/branch-heads/4240@{#1083}
Cr-Branched-From: f297677702651916bbf65e59c0d4bbd4ce57d1ee-refs/heads/master@{#800218}
diff --git a/third_party/blink/renderer/modules/webaudio/audio_destination_node.cc b/third_party/blink/renderer/modules/webaudio/audio_destination_node.cc
index c85f6d2e26f2e34b8633c29754028afbd8f2cbb9..9b1a5ec495f8f3614e8e77fdeaf9eaa159b3e3ae 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_destination_node.cc
+++ b/third_party/blink/renderer/modules/webaudio/audio_destination_node.cc
@@ -30,7 +30,8 @@
namespace blink {
AudioDestinationHandler::AudioDestinationHandler(AudioNode& node)
- : AudioHandler(kNodeTypeDestination, node, 0) {
+ : AudioHandler(kNodeTypeDestination, node, 0),
+ allow_pulling_audio_graph_(false) {
AddInput();
}
diff --git a/third_party/blink/renderer/modules/webaudio/audio_destination_node.h b/third_party/blink/renderer/modules/webaudio/audio_destination_node.h
index c35722c9296b6c98832444799124334d382225df..ce7bf61ef9ad18a5aa9669edb990542d2899acc2 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_destination_node.h
+++ b/third_party/blink/renderer/modules/webaudio/audio_destination_node.h
@@ -71,6 +71,53 @@ class AudioDestinationHandler : public AudioHandler {
return is_execution_context_destroyed_;
}
+ // Should only be called from
+ // RealtimeAudioDestinationHandler::StartPlatformDestination for a realtime
+ // context or OfflineAudioDestinationHandler::StartRendering for an offline
+ // context---basically wherever the context has started rendering.
+ // TODO(crbug.com/1128121): Consider removing this if possible
+ void EnablePullingAudioGraph() {
+ MutexLocker lock(allow_pulling_audio_graph_mutex_);
+ allow_pulling_audio_graph_.store(true, std::memory_order_release);
+ }
+
+ // Should only be called from
+ // RealtimeAudioDestinationHandler::StopPlatformDestination for a realtime
+ // context or from OfflineAudioDestinationHandler::Uninitialize for an offline
+ // context---basically whenever the context is being stopped.
+ // TODO(crbug.com/1128121): Consider removing this if possible
+ void DisablePullingAudioGraph() {
+ MutexLocker lock(allow_pulling_audio_graph_mutex_);
+ allow_pulling_audio_graph_.store(false, std::memory_order_release);
+ }
+
+ // TODO(crbug.com/1128121): Consider removing this if possible
+ bool IsPullingAudioGraphAllowed() const {
+ return allow_pulling_audio_graph_.load(std::memory_order_acquire);
+ }
+
+ // If true, the audio graph will be pulled to get new data. Otherwise, the
+ // graph is not pulled, even if the audio thread is still running and
+ // requesting data.
+ //
+ // For an AudioContext, this MUST be modified only in
+ // RealtimeAudioDestinationHandler::StartPlatformDestination (via
+ // AudioDestinationHandler::EnablePullingAudioGraph) or
+ // RealtimeAudioDestinationHandler::StopPlatformDestination (via
+ // AudioDestinationHandler::DisablePullingAudioGraph), including destroying
+ // the the realtime context.
+ //
+ // For an OfflineAudioContext, this MUST be modified only when the the context
+ // is started or it has stopped rendering, including destroying the offline
+ // context.
+
+ // TODO(crbug.com/1128121): Consider removing this if possible
+ std::atomic_bool allow_pulling_audio_graph_;
+
+ // Protects allow_pulling_audio_graph_ from race conditions. Must use try
+ // lock on the audio thread.
+ mutable Mutex allow_pulling_audio_graph_mutex_;
+
protected:
void AdvanceCurrentSampleFrame(size_t number_of_frames) {
current_sample_frame_.fetch_add(number_of_frames,
diff --git a/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.cc b/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.cc
index 2b0d87395cef31793273ef69f61eb540be897fcf..697a3e684e9bc582a93b20ac163ceb790dfb62cc 100644
--- a/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.cc
+++ b/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.cc
@@ -92,6 +92,7 @@ void OfflineAudioDestinationHandler::Uninitialize() {
render_thread_.reset();
+ DisablePullingAudioGraph();
AudioHandler::Uninitialize();
}
@@ -111,6 +112,7 @@ void OfflineAudioDestinationHandler::StartRendering() {
// Rendering was not started. Starting now.
if (!is_rendering_started_) {
is_rendering_started_ = true;
+ EnablePullingAudioGraph();
PostCrossThreadTask(
*render_thread_task_runner_, FROM_HERE,
CrossThreadBindOnce(
@@ -292,20 +294,34 @@ bool OfflineAudioDestinationHandler::RenderIfNotSuspended(
DCHECK_GE(NumberOfInputs(), 1u);
- // This will cause the node(s) connected to us to process, which in turn will
- // pull on their input(s), all the way backwards through the rendering graph.
- scoped_refptr<AudioBus> rendered_bus =
- Input(0).Pull(destination_bus, number_of_frames);
+ {
+ // The entire block that relies on |IsPullingAudioGraphAllowed| needs
+ // locking to prevent pulling audio graph being disallowed (i.e. a
+ // destruction started) in the middle of processing
+ MutexTryLocker try_locker(allow_pulling_audio_graph_mutex_);
+
+ if (IsPullingAudioGraphAllowed() && try_locker.Locked()) {
+ // This will cause the node(s) connected to us to process, which in turn
+ // will pull on their input(s), all the way backwards through the
+ // rendering graph.
+ scoped_refptr<AudioBus> rendered_bus =
+ Input(0).Pull(destination_bus, number_of_frames);
+
+ if (!rendered_bus) {
+ destination_bus->Zero();
+ } else if (rendered_bus != destination_bus) {
+ // in-place processing was not possible - so copy
+ destination_bus->CopyFrom(*rendered_bus);
+ }
- if (!rendered_bus) {
- destination_bus->Zero();
- } else if (rendered_bus != destination_bus) {
- // in-place processing was not possible - so copy
- destination_bus->CopyFrom(*rendered_bus);
+ } else {
+ // Not allowed to pull on the graph or couldn't get the lock.
+ destination_bus->Zero();
+ }
}
- // Process nodes which need a little extra help because they are not connected
- // to anything, but still need to process.
+ // Process nodes which need a little extra help because they are not
+ // connected to anything, but still need to process.
Context()->GetDeferredTaskHandler().ProcessAutomaticPullNodes(
number_of_frames);
diff --git a/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_node.cc b/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_node.cc
index 743cddb2d4bd7f04d8bdef7ce70241cbe2255430..dd183350f603d2c5997e89a62756a92c8ad566dc 100644
--- a/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_node.cc
+++ b/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_node.cc
@@ -52,8 +52,7 @@ RealtimeAudioDestinationHandler::RealtimeAudioDestinationHandler(
base::Optional<float> sample_rate)
: AudioDestinationHandler(node),
latency_hint_(latency_hint),
- sample_rate_(sample_rate),
- allow_pulling_audio_graph_(false) {
+ sample_rate_(sample_rate) {
// Node-specific default channel count and mixing rules.
channel_count_ = 2;
SetInternalChannelCountMode(kExplicit);
@@ -198,28 +197,38 @@ void RealtimeAudioDestinationHandler::Render(
// Only pull on the audio graph if we have not stopped the destination. It
// takes time for the destination to stop, but we want to stop pulling before
// the destination has actually stopped.
- if (IsPullingAudioGraphAllowed()) {
- // Renders the graph by pulling all the inputs to this node. This will in
- // turn pull on their inputs, all the way backwards through the graph.
- scoped_refptr<AudioBus> rendered_bus =
- Input(0).Pull(destination_bus, number_of_frames);
-
- DCHECK(rendered_bus);
- if (!rendered_bus) {
- // AudioNodeInput might be in the middle of destruction. Then the internal
- // summing bus will return as nullptr. Then zero out the output.
+ {
+ // The entire block that relies on |IsPullingAudioGraphAllowed| needs
+ // locking to prevent pulling audio graph being disallowed (i.e. a
+ // destruction started) in the middle of processing.
+ MutexTryLocker try_locker(allow_pulling_audio_graph_mutex_);
+
+ if (IsPullingAudioGraphAllowed() && try_locker.Locked()) {
+ // Renders the graph by pulling all the inputs to this node. This will in
+ // turn pull on their inputs, all the way backwards through the graph.
+ scoped_refptr<AudioBus> rendered_bus =
+ Input(0).Pull(destination_bus, number_of_frames);
+
+ DCHECK(rendered_bus);
+ if (!rendered_bus) {
+ // AudioNodeInput might be in the middle of destruction. Then the
+ // internal summing bus will return as nullptr. Then zero out the
+ // output.
+ destination_bus->Zero();
+ } else if (rendered_bus != destination_bus) {
+ // In-place processing was not possible. Copy the rendered result to the
+ // given |destination_bus| buffer.
+ destination_bus->CopyFrom(*rendered_bus);
+ }
+ } else {
+ // Not allowed to pull on the graph or couldn't get the lock.
destination_bus->Zero();
- } else if (rendered_bus != destination_bus) {
- // In-place processing was not possible. Copy the rendered result to the
- // given |destination_bus| buffer.
- destination_bus->CopyFrom(*rendered_bus);
}
- } else {
- destination_bus->Zero();
}
- // Processes "automatic" nodes that are not connected to anything. This can
- // be done after copying because it does not affect the rendered result.
+ // Processes "automatic" nodes that are not connected to anything. This
+ // can be done after copying because it does not affect the rendered
+ // result.
context->GetDeferredTaskHandler().ProcessAutomaticPullNodes(number_of_frames);
context->HandlePostRenderTasks();
diff --git a/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_node.h b/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_node.h
index 9c8653880c37a02c87b2e82558dd2940a1b9a425..89e33ec6a9eb2b60ad1c2d46dcb748415bf2be33 100644
--- a/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_node.h
+++ b/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_node.h
@@ -81,10 +81,6 @@ class RealtimeAudioDestinationHandler final : public AudioDestinationHandler,
// Returns a given frames-per-buffer size from audio infra.
int GetFramesPerBuffer() const;
- bool IsPullingAudioGraphAllowed() const {
- return allow_pulling_audio_graph_.load(std::memory_order_acquire);
- }
-
private:
explicit RealtimeAudioDestinationHandler(AudioNode&,
const WebAudioLatencyHint&,
@@ -94,32 +90,12 @@ class RealtimeAudioDestinationHandler final : public AudioDestinationHandler,
void StartPlatformDestination();
void StopPlatformDestination();
- // Should only be called from StartPlatformDestination.
- void EnablePullingAudioGraph() {
- allow_pulling_audio_graph_.store(true, std::memory_order_release);
- }
-
- // Should only be called from StopPlatformDestination.
- void DisablePullingAudioGraph() {
- allow_pulling_audio_graph_.store(false, std::memory_order_release);
- }
-
const WebAudioLatencyHint latency_hint_;
// Holds the audio device thread that runs the real time audio context.
scoped_refptr<AudioDestination> platform_destination_;
base::Optional<float> sample_rate_;
-
- // If true, the audio graph will be pulled to get new data. Otherwise, the
- // graph is not pulled, even if the audio thread is still running and
- // requesting data.
- //
- // Must be modified only in StartPlatformDestination (via
- // EnablePullingAudioGraph) or StopPlatformDestination (via
- // DisablePullingAudioGraph) . This is modified only by the main threda and
- // the audio thread only reads this.
- std::atomic_bool allow_pulling_audio_graph_;
};
// -----------------------------------------------------------------------------

View File

@@ -0,0 +1,265 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Will Cassella <cassew@google.com>
Date: Thu, 24 Sep 2020 22:54:27 +0000
Subject: Add callback to WebMediaPlayerImpl to notify when a redirect occurs
(cherry picked from commit 8b18bcfd9aa8096c4551ec34c0225b6017cd211e)
Bug: 1128657
Change-Id: I9548e1f3bfe5693871a56e23c3373f45147e52e0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2422091
Reviewed-by: Dale Curtis <dalecurtis@chromium.org>
Reviewed-by: Guido Urdaneta <guidou@chromium.org>
Commit-Queue: Guido Urdaneta <guidou@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#809217}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2425223
Commit-Queue: Will Cassella <cassew@google.com>
Cr-Commit-Position: refs/branch-heads/4240@{#993}
Cr-Branched-From: f297677702651916bbf65e59c0d4bbd4ce57d1ee-refs/heads/master@{#800218}
diff --git a/media/blink/multibuffer_data_source.cc b/media/blink/multibuffer_data_source.cc
index 0f6ae1fb8b4ff9f24ce3f407b7359e016fc6de5f..4ec77cf8a6b56002e601fb89eb0dee059f3ab31b 100644
--- a/media/blink/multibuffer_data_source.cc
+++ b/media/blink/multibuffer_data_source.cc
@@ -145,7 +145,7 @@ MultibufferDataSource::MultibufferDataSource(
DCHECK(url_data_.get());
url_data_->Use();
url_data_->OnRedirect(
- base::BindOnce(&MultibufferDataSource::OnRedirect, weak_ptr_));
+ base::BindOnce(&MultibufferDataSource::OnRedirected, weak_ptr_));
}
MultibufferDataSource::~MultibufferDataSource() {
@@ -219,10 +219,10 @@ void MultibufferDataSource::Initialize(InitializeCB init_cb) {
}
}
-void MultibufferDataSource::OnRedirect(
- const scoped_refptr<UrlData>& destination) {
- if (!destination) {
- // A failure occured.
+void MultibufferDataSource::OnRedirected(
+ const scoped_refptr<UrlData>& new_destination) {
+ if (!new_destination) {
+ // A failure occurred.
failed_ = true;
if (init_cb_) {
render_task_runner_->PostTask(
@@ -235,38 +235,39 @@ void MultibufferDataSource::OnRedirect(
StopLoader();
return;
}
- if (url_data_->url().GetOrigin() != destination->url().GetOrigin()) {
+ if (url_data_->url().GetOrigin() != new_destination->url().GetOrigin()) {
single_origin_ = false;
}
SetReader(nullptr);
- url_data_ = std::move(destination);
+ url_data_ = std::move(new_destination);
- if (url_data_) {
- url_data_->OnRedirect(
- base::BindOnce(&MultibufferDataSource::OnRedirect, weak_ptr_));
+ url_data_->OnRedirect(
+ base::BindOnce(&MultibufferDataSource::OnRedirected, weak_ptr_));
- if (init_cb_) {
- CreateResourceLoader(0, kPositionNotSpecified);
- if (reader_->Available()) {
- render_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&MultibufferDataSource::StartCallback, weak_ptr_));
- } else {
- reader_->Wait(1, base::BindOnce(&MultibufferDataSource::StartCallback,
- weak_ptr_));
- }
- } else if (read_op_) {
- CreateResourceLoader(read_op_->position(), kPositionNotSpecified);
- if (reader_->Available()) {
- render_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&MultibufferDataSource::ReadTask, weak_ptr_));
- } else {
- reader_->Wait(
- 1, base::BindOnce(&MultibufferDataSource::ReadTask, weak_ptr_));
- }
+ if (init_cb_) {
+ CreateResourceLoader(0, kPositionNotSpecified);
+ if (reader_->Available()) {
+ render_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&MultibufferDataSource::StartCallback, weak_ptr_));
+ } else {
+ reader_->Wait(
+ 1, base::BindOnce(&MultibufferDataSource::StartCallback, weak_ptr_));
+ }
+ } else if (read_op_) {
+ CreateResourceLoader(read_op_->position(), kPositionNotSpecified);
+ if (reader_->Available()) {
+ render_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&MultibufferDataSource::ReadTask, weak_ptr_));
+ } else {
+ reader_->Wait(
+ 1, base::BindOnce(&MultibufferDataSource::ReadTask, weak_ptr_));
}
}
+
+ if (redirect_cb_)
+ redirect_cb_.Run();
}
void MultibufferDataSource::SetPreload(Preload preload) {
@@ -287,6 +288,10 @@ bool MultibufferDataSource::IsCorsCrossOrigin() const {
return url_data_->is_cors_cross_origin();
}
+void MultibufferDataSource::OnRedirect(RedirectCB callback) {
+ redirect_cb_ = std::move(callback);
+}
+
bool MultibufferDataSource::HasAccessControl() const {
return url_data_->has_access_control();
}
diff --git a/media/blink/multibuffer_data_source.h b/media/blink/multibuffer_data_source.h
index 3da5a7bba5e7cc0f54998a81649f4dd9d78aa7be..da316964ff1543086865d7c85597f381ca8a3296 100644
--- a/media/blink/multibuffer_data_source.h
+++ b/media/blink/multibuffer_data_source.h
@@ -38,6 +38,7 @@ class MultiBufferReader;
class MEDIA_BLINK_EXPORT MultibufferDataSource : public DataSource {
public:
using DownloadingCB = base::RepeatingCallback<void(bool)>;
+ using RedirectCB = base::RepeatingCallback<void()>;
// Used to specify video preload states. They are "hints" to the browser about
// how aggressively the browser should load and buffer data.
@@ -82,6 +83,9 @@ class MEDIA_BLINK_EXPORT MultibufferDataSource : public DataSource {
// This must be called after the response arrives.
bool IsCorsCrossOrigin() const;
+ // Provides a callback to be run when the underlying url is redirected.
+ void OnRedirect(RedirectCB callback);
+
// Returns true if the response includes an Access-Control-Allow-Origin
// header (that is not "null").
bool HasAccessControl() const;
@@ -128,7 +132,7 @@ class MEDIA_BLINK_EXPORT MultibufferDataSource : public DataSource {
bool cancel_on_defer_for_testing() const { return cancel_on_defer_; }
protected:
- void OnRedirect(const scoped_refptr<UrlData>& destination);
+ void OnRedirected(const scoped_refptr<UrlData>& new_destination);
// A factory method to create a BufferedResourceLoader based on the read
// parameters.
@@ -243,6 +247,9 @@ class MEDIA_BLINK_EXPORT MultibufferDataSource : public DataSource {
// go between different origins.
bool single_origin_;
+ // Callback used when a redirect occurs.
+ RedirectCB redirect_cb_;
+
// Close the connection when we have enough data.
bool cancel_on_defer_;
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc
index bf58056d7826e2d56e927ceaf07cb14090cf5e9f..189c71a54e313acae735471d3c67f9895c4c2cf3 100644
--- a/media/blink/webmediaplayer_impl.cc
+++ b/media/blink/webmediaplayer_impl.cc
@@ -764,6 +764,8 @@ void WebMediaPlayerImpl::DoLoad(LoadType load_type,
base::BindRepeating(&WebMediaPlayerImpl::NotifyDownloading,
weak_this_));
data_source_.reset(mb_data_source_);
+ mb_data_source_->OnRedirect(base::BindRepeating(
+ &WebMediaPlayerImpl::OnDataSourceRedirected, weak_this_));
mb_data_source_->SetPreload(preload_);
mb_data_source_->SetIsClientAudioElement(client_->IsAudioElement());
mb_data_source_->Initialize(
@@ -2589,6 +2591,16 @@ void WebMediaPlayerImpl::DataSourceInitialized(bool success) {
StartPipeline();
}
+void WebMediaPlayerImpl::OnDataSourceRedirected() {
+ DVLOG(1) << __func__;
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ DCHECK(mb_data_source_);
+
+ if (WouldTaintOrigin()) {
+ audio_source_provider_->TaintOrigin();
+ }
+}
+
void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) {
DVLOG(1) << __func__ << "(" << is_downloading << ")";
if (!is_downloading && network_state_ == WebMediaPlayer::kNetworkStateLoading)
diff --git a/media/blink/webmediaplayer_impl.h b/media/blink/webmediaplayer_impl.h
index 69e853bb93eb53cdd20d40b7b01050ac2094cffc..72627e8a97781515065aeb564d829679cb4dfe41 100644
--- a/media/blink/webmediaplayer_impl.h
+++ b/media/blink/webmediaplayer_impl.h
@@ -379,6 +379,9 @@ class MEDIA_BLINK_EXPORT WebMediaPlayerImpl
// Called after asynchronous initialization of a data source completed.
void DataSourceInitialized(bool success);
+ // Called if the |MultiBufferDataSource| is redirected.
+ void OnDataSourceRedirected();
+
// Called when the data source is downloading or paused.
void NotifyDownloading(bool is_downloading);
diff --git a/third_party/blink/public/platform/webaudiosourceprovider_impl.h b/third_party/blink/public/platform/webaudiosourceprovider_impl.h
index 5383074dcbffbb77a102de6fb551628ff5b964b8..bbf2a0b3d28282587625d6a5cd0103f6a5378b54 100644
--- a/third_party/blink/public/platform/webaudiosourceprovider_impl.h
+++ b/third_party/blink/public/platform/webaudiosourceprovider_impl.h
@@ -75,6 +75,7 @@ class BLINK_PLATFORM_EXPORT WebAudioSourceProviderImpl
bool CurrentThreadIsRenderingThread() override;
void SwitchOutputDevice(const std::string& device_id,
media::OutputDeviceStatusCB callback) override;
+ void TaintOrigin();
// These methods allow a client to get a copy of the rendered audio.
void SetCopyAudioCallback(CopyAudioCB callback);
diff --git a/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl.cc b/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl.cc
index a38efb3e55b268d3a40e14dea8d66478015a3369..37ceac48d3d7f49ba49ad623cd5c7e632aa89279 100644
--- a/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl.cc
+++ b/third_party/blink/renderer/platform/media/webaudiosourceprovider_impl.cc
@@ -80,6 +80,10 @@ class WebAudioSourceProviderImpl::TeeFilter
const int num_rendered_frames = renderer_->Render(
delay, delay_timestamp, prior_frames_skipped, audio_bus);
+ // Zero out frames after rendering
+ if (origin_tainted_.IsSet())
+ audio_bus->Zero();
+
// Avoid taking the copy lock for the vast majority of cases.
if (copy_required_) {
base::AutoLock auto_lock(copy_lock_);
@@ -113,11 +117,18 @@ class WebAudioSourceProviderImpl::TeeFilter
copy_audio_bus_callback_ = std::move(callback);
}
+ void TaintOrigin() { origin_tainted_.Set(); }
+
private:
AudioRendererSink::RenderCallback* renderer_ = nullptr;
int channels_ = 0;
int sample_rate_ = 0;
+ // Indicates whether the audio source is tainted, and output should be muted.
+ // This can happen if the media element source is a cross-origin source which
+ // the page is not allowed to access due to CORS restrictions.
+ base::AtomicFlag origin_tainted_;
+
// The vast majority of the time we're operating in passthrough mode. So only
// acquire a lock to read |copy_audio_bus_callback_| when necessary.
std::atomic<bool> copy_required_;
@@ -317,6 +328,10 @@ void WebAudioSourceProviderImpl::SwitchOutputDevice(
sink_->SwitchOutputDevice(device_id, std::move(callback));
}
+void WebAudioSourceProviderImpl::TaintOrigin() {
+ tee_filter_->TaintOrigin();
+}
+
void WebAudioSourceProviderImpl::SetCopyAudioCallback(CopyAudioCB callback) {
DCHECK(!callback.is_null());
tee_filter_->SetCopyAudioCallback(std::move(callback));

View File

@@ -0,0 +1,40 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Thu, 5 Nov 2020 08:50:39 +0000
Subject: Prevent overflow of drag image on Windows.
(cherry picked from commit 236b1a349111fc945c741f85e1b1e2e04d9c42ff)
(cherry picked from commit 5f61af8f3af5efd0d915a51da6df822678d959b9)
Bug: 1144489
Change-Id: I130adffc1c69073295537aaff3ce7054260064fc
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2513345
Reviewed-by: Krishna Govind <govind@chromium.org>
Cr-Original-Original-Commit-Position: refs/branch-heads/4310@{#4}
Cr-Original-Original-Branched-From: 3e31ebb7467fdc4295f123385825b8c95ef13332-refs/heads/master@{#822916}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2513349
Reviewed-by: Adrian Taylor <adetaylor@chromium.org>
Commit-Queue: Krishna Govind <govind@chromium.org>
Cr-Original-Commit-Position: refs/branch-heads/4240@{#1373}
Cr-Original-Branched-From: f297677702651916bbf65e59c0d4bbd4ce57d1ee-refs/heads/master@{#800218}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2517728
Reviewed-by: Achuith Bhandarkar <achuith@chromium.org>
Commit-Queue: Victor-Gabriel Savu <vsavu@google.com>
Cr-Commit-Position: refs/branch-heads/4240_112@{#18}
Cr-Branched-From: 427c00d3874b6abcf4c4c2719768835fc3ef26d6-refs/branch-heads/4240@{#1291}
Cr-Branched-From: f297677702651916bbf65e59c0d4bbd4ce57d1ee-refs/heads/master@{#800218}
diff --git a/ui/base/dragdrop/os_exchange_data_provider_win.cc b/ui/base/dragdrop/os_exchange_data_provider_win.cc
index c5183eaab9986d668d7b109fef13205f54ff80fa..847920ada50bae2615c964fc82ea3dc696b86e8a 100644
--- a/ui/base/dragdrop/os_exchange_data_provider_win.cc
+++ b/ui/base/dragdrop/os_exchange_data_provider_win.cc
@@ -714,7 +714,7 @@ void OSExchangeDataProviderWin::SetDragImage(
int width = unpremul_bitmap.width();
int height = unpremul_bitmap.height();
size_t rowbytes = unpremul_bitmap.rowBytes();
- DCHECK_EQ(rowbytes, static_cast<size_t>(width) * 4u);
+ CHECK_EQ(rowbytes, static_cast<size_t>(width) * 4u);
void* bits;
HBITMAP hbitmap;

View File

@@ -0,0 +1,29 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Andres Calderon Jaramillo <andrescj@chromium.org>
Date: Mon, 20 Jul 2020 19:49:42 +0000
Subject: blink: Disable WebP YUV image decoding by default.
JPEG YUV image decoding is already disabled by default.
Bug: 1102054,1091347
Test: WebP images in bug 1091347 don't have artifacts on Linux
Change-Id: Icf7f9ef46da97ba80d4e3b4aac4196f789bdf6d5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2283409
Reviewed-by: Andres Calderon Jaramillo <andrescj@chromium.org>
Commit-Queue: Andres Calderon Jaramillo <andrescj@chromium.org>
Cr-Commit-Position: refs/branch-heads/4147@{#901}
Cr-Branched-From: 16307825352720ae04d898f37efa5449ad68b606-refs/heads/master@{#768962}
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc
index ad1c48f2d727f5fee33b2f5bd9d39682da2ba085..5f87b90e6cf3a3e3cb5f68e13fcbed06d039b18f 100644
--- a/third_party/blink/common/features.cc
+++ b/third_party/blink/common/features.cc
@@ -257,7 +257,7 @@ const base::Feature kDecodeJpeg420ImagesToYUV{
// Decodes lossy WebP images to YUV instead of RGBX and stores in this format
// in the image decode cache. See crbug.com/900264 for details on the feature.
const base::Feature kDecodeLossyWebPImagesToYUV{
- "DecodeLossyWebPImagesToYUV", base::FEATURE_ENABLED_BY_DEFAULT};
+ "DecodeLossyWebPImagesToYUV", base::FEATURE_DISABLED_BY_DEFAULT};
// Enables cache-aware WebFonts loading. See https://crbug.com/570205.
// The feature is disabled on Android for WebView API issue discussed at

View File

@@ -0,0 +1,42 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Guido Urdaneta <guidou@chromium.org>
Date: Tue, 4 Aug 2020 21:25:10 +0000
Subject: Use copy of source map in
MediaElementElementListener::UpdateSources()
Prior to this CL, this function iterated over a source map that could
be modified by a re-entrant call triggered by JS code.
(cherry picked from commit 292ac9aa5ba263f63f761e03b8214cae21e667c9)
Bug: 1105426
Change-Id: I47e49e4132cba98e12ee7c195720ac9ecc1f485b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2312703
Reviewed-by: Marina Ciocea <marinaciocea@chromium.org>
Commit-Queue: Guido Urdaneta <guidou@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#790894}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2332823
Reviewed-by: Guido Urdaneta <guidou@chromium.org>
Cr-Commit-Position: refs/branch-heads/4147@{#1026}
Cr-Branched-From: 16307825352720ae04d898f37efa5449ad68b606-refs/heads/master@{#768962}
diff --git a/third_party/blink/renderer/modules/mediacapturefromelement/html_media_element_capture.cc b/third_party/blink/renderer/modules/mediacapturefromelement/html_media_element_capture.cc
index 03ba68236c511ba2d2767af3c796b37a90dce476..80f36cb236adee50aefc505ff64f092cbc4e82b9 100644
--- a/third_party/blink/renderer/modules/mediacapturefromelement/html_media_element_capture.cc
+++ b/third_party/blink/renderer/modules/mediacapturefromelement/html_media_element_capture.cc
@@ -242,9 +242,14 @@ void MediaElementEventListener::UpdateSources(ExecutionContext* context) {
for (auto track : media_stream_->getTracks())
sources_.insert(track->Component()->Source());
+ // Handling of the ended event in JS triggered by DidStopMediaStreamSource()
+ // may cause a reentrant call to this function, which can modify |sources_|.
+ // Iterate over a copy of |sources_| to avoid invalidation of the iterator
+ // when a reentrant call occurs.
+ auto sources_copy = sources_;
if (!media_element_->currentSrc().IsEmpty() &&
!media_element_->IsMediaDataCorsSameOrigin()) {
- for (auto source : sources_)
+ for (auto source : sources_copy)
DidStopMediaStreamSource(source.Get());
}
}

View File

@@ -0,0 +1,160 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Yutaka Hirano <yhirano@chromium.org>
Date: Fri, 7 Aug 2020 09:06:23 +0000
Subject: Fix UAF in ScriptPromiseProperty caused by reentrant code
v8::Promise::Resolve can run user code synchronously, which caused a UAF
in ScriptPromiseProperty. Fix it.
Bug: 1108518
Change-Id: Ia9baec6eef0887323cd88ceb1d3fa0c14fdb77ef
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2325499
Reviewed-by: Yuki Shiino <yukishiino@chromium.org>
Commit-Queue: Yutaka Hirano <yhirano@chromium.org>
Cr-Commit-Position: refs/heads/master@{#792661}
(cherry picked from commit 6d18e924b9c426905434cc280d7b602b3a3379ed)
TBR=yhirano@chromium.org
Change-Id: I3b7bfd5e8d932fb59c292159a4526cf70b44c58b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2342489
Commit-Queue: Yutaka Hirano <yhirano@chromium.org>
Reviewed-by: Yutaka Hirano <yhirano@chromium.org>
Cr-Commit-Position: refs/branch-heads/4147@{#1049}
Cr-Branched-From: 16307825352720ae04d898f37efa5449ad68b606-refs/heads/master@{#768962}
diff --git a/third_party/blink/renderer/bindings/core/v8/script_promise_property.h b/third_party/blink/renderer/bindings/core/v8/script_promise_property.h
index 7c83ee35246486cf2a43227bf180904b2d9eb5f3..49ec9edc0d897e6f6e842a425cc2b0a4272702e2 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_promise_property.h
+++ b/third_party/blink/renderer/bindings/core/v8/script_promise_property.h
@@ -102,10 +102,11 @@ class ScriptPromiseProperty final
}
state_ = kResolved;
resolved_ = value;
- for (const Member<ScriptPromiseResolver>& resolver : resolvers_) {
+ HeapVector<Member<ScriptPromiseResolver>> resolvers;
+ resolvers.swap(resolvers_);
+ for (const Member<ScriptPromiseResolver>& resolver : resolvers) {
resolver->Resolve(resolved_);
}
- resolvers_.clear();
}
void ResolveWithUndefined() {
@@ -116,10 +117,11 @@ class ScriptPromiseProperty final
}
state_ = kResolved;
resolved_with_undefined_ = true;
- for (const Member<ScriptPromiseResolver>& resolver : resolvers_) {
+ HeapVector<Member<ScriptPromiseResolver>> resolvers;
+ resolvers.swap(resolvers_);
+ for (const Member<ScriptPromiseResolver>& resolver : resolvers) {
resolver->Resolve();
}
- resolvers_.clear();
}
template <typename PassRejectedType>
@@ -131,10 +133,11 @@ class ScriptPromiseProperty final
}
state_ = kRejected;
rejected_ = value;
- for (const Member<ScriptPromiseResolver>& resolver : resolvers_) {
+ HeapVector<Member<ScriptPromiseResolver>> resolvers;
+ resolvers.swap(resolvers_);
+ for (const Member<ScriptPromiseResolver>& resolver : resolvers) {
resolver->Reject(rejected_);
}
- resolvers_.clear();
}
// Resets this property by unregistering the Promise property from the
diff --git a/third_party/blink/renderer/bindings/core/v8/script_promise_property_test.cc b/third_party/blink/renderer/bindings/core/v8/script_promise_property_test.cc
index c2dd607686e4ef76885036b4a678103c3869241e..95b6b1b83638b30918032fc4f76fec56a781c492 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_promise_property_test.cc
+++ b/third_party/blink/renderer/bindings/core/v8/script_promise_property_test.cc
@@ -96,6 +96,35 @@ class GarbageCollectedHolder final : public GarbageCollectedScriptWrappable {
Member<Property> property_;
};
+class ScriptPromisePropertyResetter : public ScriptFunction {
+ public:
+ using Property =
+ ScriptPromiseProperty<Member<GarbageCollectedScriptWrappable>,
+ Member<GarbageCollectedScriptWrappable>>;
+ static v8::Local<v8::Function> CreateFunction(ScriptState* script_state,
+ Property* property) {
+ auto* self = MakeGarbageCollected<ScriptPromisePropertyResetter>(
+ script_state, property);
+ return self->BindToV8Function();
+ }
+
+ ScriptPromisePropertyResetter(ScriptState* script_state, Property* property)
+ : ScriptFunction(script_state), property_(property) {}
+
+ void Trace(Visitor* visitor) override {
+ visitor->Trace(property_);
+ ScriptFunction::Trace(visitor);
+ }
+
+ private:
+ ScriptValue Call(ScriptValue arg) override {
+ property_->Reset();
+ return ScriptValue();
+ }
+
+ const Member<Property> property_;
+};
+
class ScriptPromisePropertyTestBase {
public:
ScriptPromisePropertyTestBase()
@@ -520,6 +549,48 @@ TEST_F(ScriptPromisePropertyGarbageCollectedTest, MarkAsHandled) {
}
}
+TEST_F(ScriptPromisePropertyGarbageCollectedTest, SyncResolve) {
+ // Call getters to create resolvers in the property.
+ GetProperty()->Promise(DOMWrapperWorld::MainWorld());
+ GetProperty()->Promise(OtherWorld());
+
+ auto* resolution =
+ MakeGarbageCollected<GarbageCollectedScriptWrappable>("hi");
+ v8::HandleScope handle_scope(GetIsolate());
+ v8::Local<v8::Object> main_v8_resolution;
+ v8::Local<v8::Object> other_v8_resolution;
+ {
+ ScriptState::Scope scope(MainScriptState());
+ main_v8_resolution = ToV8(resolution, MainScriptState()).As<v8::Object>();
+ v8::PropertyDescriptor descriptor(
+ ScriptPromisePropertyResetter::CreateFunction(MainScriptState(),
+ GetProperty()),
+ v8::Undefined(GetIsolate()));
+ ASSERT_EQ(
+ v8::Just(true),
+ main_v8_resolution->DefineProperty(
+ MainScriptState()->GetContext(),
+ v8::String::NewFromUtf8Literal(GetIsolate(), "then"), descriptor));
+ }
+ {
+ ScriptState::Scope scope(OtherScriptState());
+ other_v8_resolution = ToV8(resolution, OtherScriptState()).As<v8::Object>();
+ v8::PropertyDescriptor descriptor(
+ ScriptPromisePropertyResetter::CreateFunction(OtherScriptState(),
+ GetProperty()),
+ v8::Undefined(GetIsolate()));
+ ASSERT_EQ(
+ v8::Just(true),
+ other_v8_resolution->DefineProperty(
+ OtherScriptState()->GetContext(),
+ v8::String::NewFromUtf8Literal(GetIsolate(), "then"), descriptor));
+ }
+
+ // This shouldn't crash.
+ GetProperty()->Resolve(resolution);
+ EXPECT_EQ(GetProperty()->GetState(), Property::State::kPending);
+}
+
TEST_F(ScriptPromisePropertyNonScriptWrappableResolutionTargetTest,
ResolveWithUndefined) {
Test(ToV8UndefinedGenerator(), "undefined", __FILE__, __LINE__);

View File

@@ -0,0 +1,99 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Guido Urdaneta <guidou@chromium.org>
Date: Mon, 31 Aug 2020 09:01:16 +0000
Subject: Do not produce frames if media player is tainted
This prevents potential cross-origin mid-stream redirects from
braking the cross-origin restrictions.
Bug: 1111149
Change-Id: I18d05a5836b9a390dec50e10c43d3d2b9ec5915a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2377811
Commit-Queue: Guido Urdaneta <guidou@chromium.org>
Reviewed-by: Dan Sanders <sandersd@chromium.org>
Cr-Commit-Position: refs/heads/master@{#803036}
(cherry picked from commit abc6ab85e704f599fa366344f9c5ce35585f3217)
diff --git a/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source.cc b/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source.cc
index 900d4534bc2c3f54d53cf4db3b2c3b6eb675b83a..a712281d52726c156035b00b3408f0f6baa18a5f 100644
--- a/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source.cc
+++ b/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source.cc
@@ -116,8 +116,10 @@ void HtmlVideoElementCapturerSource::sendNewFrame() {
TRACE_EVENT0("media", "HtmlVideoElementCapturerSource::sendNewFrame");
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- if (!web_media_player_ || new_frame_callback_.is_null())
+ if (!web_media_player_ || new_frame_callback_.is_null() ||
+ web_media_player_->WouldTaintOrigin()) {
return;
+ }
const base::TimeTicks current_time = base::TimeTicks::Now();
if (start_capture_time_.is_null())
diff --git a/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source_unittest.cc b/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source_unittest.cc
index 4d24f214880bfad608dbd151ed4fe00bb22c1aad..6e9960f4bbf60eb72097406ef4e835dcba6fba78 100644
--- a/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source_unittest.cc
+++ b/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source_unittest.cc
@@ -71,7 +71,7 @@ class MockWebMediaPlayer : public WebMediaPlayer {
WebString GetErrorMessage() const override { return WebString(); }
bool DidLoadingProgress() override { return true; }
- bool WouldTaintOrigin() const override { return false; }
+ bool WouldTaintOrigin() const override { return would_taint_origin_; }
double MediaTimeForTimeValue(double timeValue) const override { return 0.0; }
unsigned DecodedFrameCount() const override { return 0; }
unsigned DroppedFrameCount() const override { return 0; }
@@ -79,6 +79,8 @@ class MockWebMediaPlayer : public WebMediaPlayer {
uint64_t AudioDecodedByteCount() const override { return 0; }
uint64_t VideoDecodedByteCount() const override { return 0; }
+ void SetWouldTaintOrigin(bool taint) { would_taint_origin_ = taint; }
+
void Paint(cc::PaintCanvas* canvas,
const WebRect& rect,
cc::PaintFlags&,
@@ -98,6 +100,7 @@ class MockWebMediaPlayer : public WebMediaPlayer {
bool is_video_opaque_ = true;
gfx::Size size_ = gfx::Size(16, 10);
+ bool would_taint_origin_ = false;
base::WeakPtrFactory<MockWebMediaPlayer> weak_factory_{this};
};
@@ -326,4 +329,36 @@ TEST_F(HTMLVideoElementCapturerSourceTest, SizeChange) {
Mock::VerifyAndClearExpectations(this);
}
+// Checks that the usual sequence of GetPreferredFormats() ->
+// StartCapture() -> StopCapture() works as expected and let it capture two
+// frames, that are tested for format vs the expected source opacity.
+TEST_F(HTMLVideoElementCapturerSourceTest, TaintedPlayerDoesNotDeliverFrames) {
+ InSequence s;
+ media::VideoCaptureFormats formats =
+ html_video_capturer_->GetPreferredFormats();
+ ASSERT_EQ(1u, formats.size());
+ EXPECT_EQ(web_media_player_->NaturalSize(), formats[0].frame_size);
+ web_media_player_->SetWouldTaintOrigin(true);
+
+ media::VideoCaptureParams params;
+ params.requested_format = formats[0];
+
+ EXPECT_CALL(*this, DoOnRunning(true)).Times(1);
+
+ // No frames should be delivered.
+ EXPECT_CALL(*this, DoOnDeliverFrame(_, _)).Times(0);
+ html_video_capturer_->StartCapture(
+ params,
+ WTF::BindRepeating(&HTMLVideoElementCapturerSourceTest::OnDeliverFrame,
+ base::Unretained(this)),
+ WTF::BindRepeating(&HTMLVideoElementCapturerSourceTest::OnRunning,
+ base::Unretained(this)));
+
+ // Wait for frames to be potentially sent in a follow-up task.
+ base::RunLoop().RunUntilIdle();
+
+ html_video_capturer_->StopCapture();
+ Mock::VerifyAndClearExpectations(this);
+}
+
} // namespace blink

View File

@@ -0,0 +1,82 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Reilly Grant <reillyg@chromium.org>
Date: Tue, 8 Sep 2020 19:29:40 +0000
Subject: serial: Check that port is open before reading or writing
This change adds checks to the platform-specific implementations
of Read() and Write() to make sure that the file descriptor is
valid before. This makes the assumptions validated by later DCHECK
correct.
This cannot be done in the platform-independent layer because test
code depends on being able to call some SerialIoHandler methods
without an actual file descriptor.
Bug: 1121836
Change-Id: If182404cf10a2f3b445b9c80b75fed5df6b5ab4b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2393001
Reviewed-by: James Hollyer <jameshollyer@chromium.org>
Commit-Queue: Reilly Grant <reillyg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#805016}
(cherry picked from commit adc731d678c4c795e7c4c74133a624310e7bc9ae)
diff --git a/services/device/serial/serial_io_handler_posix.cc b/services/device/serial/serial_io_handler_posix.cc
index 452d81538fd34ceb8f4267b8ceee0f39588d2528..7f2a2c421b3f5a890652bac470c945ef4534728c 100644
--- a/services/device/serial/serial_io_handler_posix.cc
+++ b/services/device/serial/serial_io_handler_posix.cc
@@ -126,7 +126,11 @@ scoped_refptr<SerialIoHandler> SerialIoHandler::Create(
void SerialIoHandlerPosix::ReadImpl() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(pending_read_buffer());
- DCHECK(file().IsValid());
+
+ if (!file().IsValid()) {
+ QueueReadCompleted(0, mojom::SerialReceiveError::DISCONNECTED);
+ return;
+ }
// Try to read immediately. This is needed because on some platforms
// (e.g., OSX) there may not be a notification from the message loop
@@ -138,7 +142,11 @@ void SerialIoHandlerPosix::ReadImpl() {
void SerialIoHandlerPosix::WriteImpl() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(pending_write_buffer());
- DCHECK(file().IsValid());
+
+ if (!file().IsValid()) {
+ QueueWriteCompleted(0, mojom::SerialSendError::DISCONNECTED);
+ return;
+ }
EnsureWatchingWrites();
}
diff --git a/services/device/serial/serial_io_handler_win.cc b/services/device/serial/serial_io_handler_win.cc
index 1501ce9081c3dc5a2b2fd2cfd681aea98ed16efe..5696ab995dc999fc0357230fb930652fa13a4c92 100644
--- a/services/device/serial/serial_io_handler_win.cc
+++ b/services/device/serial/serial_io_handler_win.cc
@@ -266,7 +266,11 @@ bool SerialIoHandlerWin::PostOpen() {
void SerialIoHandlerWin::ReadImpl() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(pending_read_buffer());
- DCHECK(file().IsValid());
+
+ if (!file().IsValid()) {
+ QueueReadCompleted(0, mojom::SerialReceiveError::DISCONNECTED);
+ return;
+ }
if (!SetCommMask(file().GetPlatformFile(), EV_RXCHAR)) {
VPLOG(1) << "Failed to set serial event flags";
@@ -285,7 +289,11 @@ void SerialIoHandlerWin::ReadImpl() {
void SerialIoHandlerWin::WriteImpl() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(pending_write_buffer());
- DCHECK(file().IsValid());
+
+ if (!file().IsValid()) {
+ QueueWriteCompleted(0, mojom::SerialSendError::DISCONNECTED);
+ return;
+ }
BOOL ok = ::WriteFile(file().GetPlatformFile(), pending_write_buffer(),
pending_write_buffer_len(), NULL,

View File

@@ -0,0 +1,187 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Adam Rice <ricea@chromium.org>
Date: Wed, 2 Dec 2020 20:26:52 +0000
Subject: Add ports 5060 and 5061 to the restricted list
Some NAT devices examine traffic on port 5060 to look for a valid SIP
message. If they find one, they will forward a port back to the origin
host. A carefully crafted HTTP request can trick these NAT devices into
forwarding an arbitrary port. See https://samy.pl/slipstream for more
details on the attack and sample code.
Block port 5060 for HTTP. Out of an abundance of caution, and to match
the Fetch standard (https://github.com/whatwg/fetch/pull/1109), also
block port 5061 (SIP over TLS).
Also reduce the whitespace before protocol description comments. This
was insisted on by clang-format and is not worth fighting.
BUG=1145680
(cherry picked from commit 90d1302aec437166b383eabc08af741bf24f7ea8)
(cherry picked from commit dbb0452e69a49e803e0e4cbb6921d5ccad338716)
Change-Id: I3a556fbbb4dc6099caa4418addaf1e89bf254ae3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2519174
Reviewed-by: Matt Menke <mmenke@chromium.org>
Commit-Queue: Adam Rice <ricea@chromium.org>
Cr-Original-Original-Commit-Position: refs/heads/master@{#824254}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2525474
Reviewed-by: Adam Rice <ricea@chromium.org>
Cr-Original-Commit-Position: refs/branch-heads/4280@{#1247}
Cr-Original-Branched-From: ea420fb963f9658c9969b6513c56b8f47efa1a2a-refs/heads/master@{#812852}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2560585
Reviewed-by: Achuith Bhandarkar <achuith@chromium.org>
Reviewed-by: Victor-Gabriel Savu <vsavu@google.com>
Commit-Queue: Artem Sumaneev <asumaneev@google.com>
Cr-Commit-Position: refs/branch-heads/4240@{#1474}
Cr-Branched-From: f297677702651916bbf65e59c0d4bbd4ce57d1ee-refs/heads/master@{#800218}
diff --git a/net/base/port_util.cc b/net/base/port_util.cc
index 63a7c35c39eb965d8a752bd262c115a8263733f9..41deaaded2f251d6153c01203b68cc6bdc06554f 100644
--- a/net/base/port_util.cc
+++ b/net/base/port_util.cc
@@ -20,73 +20,75 @@ namespace {
// The general list of blocked ports. Will be blocked unless a specific
// protocol overrides it. (Ex: ftp can use ports 20 and 21)
const int kRestrictedPorts[] = {
- 1, // tcpmux
- 7, // echo
- 9, // discard
- 11, // systat
- 13, // daytime
- 15, // netstat
- 17, // qotd
- 19, // chargen
- 20, // ftp data
- 21, // ftp access
- 22, // ssh
- 23, // telnet
- 25, // smtp
- 37, // time
- 42, // name
- 43, // nicname
- 53, // domain
- 77, // priv-rjs
- 79, // finger
- 87, // ttylink
- 95, // supdup
- 101, // hostriame
- 102, // iso-tsap
- 103, // gppitnp
- 104, // acr-nema
- 109, // pop2
- 110, // pop3
- 111, // sunrpc
- 113, // auth
- 115, // sftp
- 117, // uucp-path
- 119, // nntp
- 123, // NTP
- 135, // loc-srv /epmap
- 139, // netbios
- 143, // imap2
- 179, // BGP
- 389, // ldap
- 427, // SLP (Also used by Apple Filing Protocol)
- 465, // smtp+ssl
- 512, // print / exec
- 513, // login
- 514, // shell
- 515, // printer
- 526, // tempo
- 530, // courier
- 531, // chat
- 532, // netnews
- 540, // uucp
- 548, // AFP (Apple Filing Protocol)
- 556, // remotefs
- 563, // nntp+ssl
- 587, // smtp (rfc6409)
- 601, // syslog-conn (rfc3195)
- 636, // ldap+ssl
- 993, // ldap+ssl
- 995, // pop3+ssl
- 2049, // nfs
- 3659, // apple-sasl / PasswordServer
- 4045, // lockd
- 6000, // X11
- 6665, // Alternate IRC [Apple addition]
- 6666, // Alternate IRC [Apple addition]
- 6667, // Standard IRC [Apple addition]
- 6668, // Alternate IRC [Apple addition]
- 6669, // Alternate IRC [Apple addition]
- 6697, // IRC + TLS
+ 1, // tcpmux
+ 7, // echo
+ 9, // discard
+ 11, // systat
+ 13, // daytime
+ 15, // netstat
+ 17, // qotd
+ 19, // chargen
+ 20, // ftp data
+ 21, // ftp access
+ 22, // ssh
+ 23, // telnet
+ 25, // smtp
+ 37, // time
+ 42, // name
+ 43, // nicname
+ 53, // domain
+ 77, // priv-rjs
+ 79, // finger
+ 87, // ttylink
+ 95, // supdup
+ 101, // hostriame
+ 102, // iso-tsap
+ 103, // gppitnp
+ 104, // acr-nema
+ 109, // pop2
+ 110, // pop3
+ 111, // sunrpc
+ 113, // auth
+ 115, // sftp
+ 117, // uucp-path
+ 119, // nntp
+ 123, // NTP
+ 135, // loc-srv /epmap
+ 139, // netbios
+ 143, // imap2
+ 179, // BGP
+ 389, // ldap
+ 427, // SLP (Also used by Apple Filing Protocol)
+ 465, // smtp+ssl
+ 512, // print / exec
+ 513, // login
+ 514, // shell
+ 515, // printer
+ 526, // tempo
+ 530, // courier
+ 531, // chat
+ 532, // netnews
+ 540, // uucp
+ 548, // AFP (Apple Filing Protocol)
+ 556, // remotefs
+ 563, // nntp+ssl
+ 587, // smtp (rfc6409)
+ 601, // syslog-conn (rfc3195)
+ 636, // ldap+ssl
+ 993, // ldap+ssl
+ 995, // pop3+ssl
+ 2049, // nfs
+ 3659, // apple-sasl / PasswordServer
+ 4045, // lockd
+ 5060, // sip
+ 5061, // sips
+ 6000, // X11
+ 6665, // Alternate IRC [Apple addition]
+ 6666, // Alternate IRC [Apple addition]
+ 6667, // Standard IRC [Apple addition]
+ 6668, // Alternate IRC [Apple addition]
+ 6669, // Alternate IRC [Apple addition]
+ 6697, // IRC + TLS
};
// FTP overrides the following restricted port.

View File

@@ -0,0 +1,112 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Hongchan Choi <hongchan@chromium.org>
Date: Tue, 4 Aug 2020 16:13:40 +0000
Subject: Use SupportWeakPtr in OfflineAudioDestinationHandler
OfflineAudioDestinationHandler's render thread notifies the
main thread when the rendering state changes. In this process,
the associated audio context can be deleted when a posted task
is performed sometime later in the task runner's queue.
By using WeakPtr, the task runner will not perform a scheduled task
in the queue when the target object is no longer valid.
(cherry picked from commit 4f309b864587890acaefa9da5d580abb21ff9ca0)
Bug: 1095584
Test: Locally confirmed that the repro case does not crash after 30 min.
Change-Id: Ic1814b97f8d9a8d1027ef04f475112874cfa8137
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2285473
Reviewed-by: Robert Sesek <rsesek@chromium.org>
Reviewed-by: Raymond Toy <rtoy@chromium.org>
Commit-Queue: Hongchan Choi <hongchan@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#786381}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2335487
Reviewed-by: Hongchan Choi <hongchan@chromium.org>
Cr-Commit-Position: refs/branch-heads/4147@{#1019}
Cr-Branched-From: 16307825352720ae04d898f37efa5449ad68b606-refs/heads/master@{#768962}
diff --git a/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.cc b/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.cc
index ec610b99c6758bc66cda07bd344f29825c8376a3..2b0d87395cef31793273ef69f61eb540be897fcf 100644
--- a/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.cc
+++ b/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.cc
@@ -51,17 +51,14 @@ OfflineAudioDestinationHandler::OfflineAudioDestinationHandler(
frames_to_process_(frames_to_process),
is_rendering_started_(false),
number_of_channels_(number_of_channels),
- sample_rate_(sample_rate) {
- channel_count_ = number_of_channels;
+ sample_rate_(sample_rate),
+ main_thread_task_runner_(Context()->GetExecutionContext()->GetTaskRunner(
+ TaskType::kInternalMedia)) {
+ DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
+ channel_count_ = number_of_channels;
SetInternalChannelCountMode(kExplicit);
SetInternalChannelInterpretation(AudioBus::kSpeakers);
-
- if (Context()->GetExecutionContext()) {
- main_thread_task_runner_ = Context()->GetExecutionContext()->GetTaskRunner(
- TaskType::kMiscPlatformAPI);
- DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
- }
}
scoped_refptr<OfflineAudioDestinationHandler>
@@ -218,7 +215,7 @@ void OfflineAudioDestinationHandler::SuspendOfflineRendering() {
PostCrossThreadTask(
*main_thread_task_runner_, FROM_HERE,
CrossThreadBindOnce(&OfflineAudioDestinationHandler::NotifySuspend,
- WrapRefCounted(this),
+ GetWeakPtr(),
Context()->CurrentSampleFrame()));
}
@@ -229,7 +226,7 @@ void OfflineAudioDestinationHandler::FinishOfflineRendering() {
PostCrossThreadTask(
*main_thread_task_runner_, FROM_HERE,
CrossThreadBindOnce(&OfflineAudioDestinationHandler::NotifyComplete,
- WrapRefCounted(this)));
+ GetWeakPtr()));
}
void OfflineAudioDestinationHandler::NotifySuspend(size_t frame) {
diff --git a/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.h b/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.h
index e4d2d8bfcd5d90d233ca8c761f07e8f518f83018..07d80e4cff535ee7230ea14d96c292bacaa7c19e 100644
--- a/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.h
+++ b/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.h
@@ -28,6 +28,7 @@
#include <memory>
#include "base/memory/scoped_refptr.h"
+#include "base/memory/weak_ptr.h"
#include "third_party/blink/renderer/modules/webaudio/audio_buffer.h"
#include "third_party/blink/renderer/modules/webaudio/audio_destination_node.h"
#include "third_party/blink/renderer/modules/webaudio/offline_audio_context.h"
@@ -124,6 +125,17 @@ class OfflineAudioDestinationHandler final : public AudioDestinationHandler {
// from AudioWorkletThread will be used until the rendering is finished.
void PrepareTaskRunnerForRendering();
+ // For cross-thread posting, this object uses two different targets.
+ // 1. rendering thread -> main thread: WeakPtr
+ // When the main thread starts deleting this object, a task posted with
+ // a WeakPtr from the rendering thread will be cancelled.
+ // 2. main thread -> rendering thread: scoped_refptr
+ // |render_thread_| is owned by this object, so it is safe to target with
+ // WrapRefCounted() instead of GetWeakPtr().
+ base::WeakPtr<OfflineAudioDestinationHandler> GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+ }
+
// This AudioHandler renders into this SharedAudioBuffer.
std::unique_ptr<SharedAudioBuffer> shared_render_target_;
// Temporary AudioBus for each render quantum.
@@ -148,6 +160,8 @@ class OfflineAudioDestinationHandler final : public AudioDestinationHandler {
scoped_refptr<base::SingleThreadTaskRunner> render_thread_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
+
+ base::WeakPtrFactory<OfflineAudioDestinationHandler> weak_factory_{this};
};
class OfflineAudioDestinationNode final : public AudioDestinationNode {

View File

@@ -0,0 +1,132 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Xianzhu Wang <wangxianzhu@chromium.org>
Date: Mon, 16 Nov 2020 17:26:33 +0000
Subject: Ensure change type for OverflowControlsClip is returned
This at least ensures that we will update the paint properites for the
composited overflow control layers in pre-CompositeAfterPaint to avoid
stale properties on the layers.
The test doesn't actually reproduce the bug because any test simpler
than the bug case couldn't reproduce the bug as the update would be
triggered in other code paths (any style change, layout change, etc.).
Anyway this CL does fix the bug case.
TBR=wangxianzhu@chromium.org
(cherry picked from commit c20bb9897ef6d26a46391a4dc1658c5d33e0c100)
(cherry picked from commit cfb81e677a508871f56d8bec958d0b585298ae0c)
Bug: 1137603
Change-Id: I5cca970bcf8cda6085527f79a97f269c4e3e9986
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2500264
Reviewed-by: Stefan Zager <szager@chromium.org>
Commit-Queue: Xianzhu Wang <wangxianzhu@chromium.org>
Cr-Original-Original-Commit-Position: refs/heads/master@{#820986}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2536910
Reviewed-by: Xianzhu Wang <wangxianzhu@chromium.org>
Cr-Original-Commit-Position: refs/branch-heads/4240@{#1446}
Cr-Original-Branched-From: f297677702651916bbf65e59c0d4bbd4ce57d1ee-refs/heads/master@{#800218}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2540592
Reviewed-by: Victor-Gabriel Savu <vsavu@google.com>
Commit-Queue: Jana Grill <janagrill@chromium.org>
Cr-Commit-Position: refs/branch-heads/4240_112@{#26}
Cr-Branched-From: 427c00d3874b6abcf4c4c2719768835fc3ef26d6-refs/branch-heads/4240@{#1291}
Cr-Branched-From: f297677702651916bbf65e59c0d4bbd4ce57d1ee-refs/heads/master@{#800218}
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater_test.cc b/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater_test.cc
index b7946eb567463938066b54ecd54ca710f649380e..f7ff1d68e36840c8647b863943f8c9134233c8ee 100644
--- a/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater_test.cc
+++ b/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater_test.cc
@@ -174,4 +174,56 @@ TEST_F(CompositingLayerPropertyUpdaterTest,
}
}
+TEST_F(CompositingLayerPropertyUpdaterTest, OverflowControlsClip) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ ::-webkit-scrollbar { width: 20px; }
+ #container {
+ width: 5px;
+ height: 100px;
+ }
+ #target {
+ overflow: scroll;
+ will-change: transform;
+ width: 100%;
+ height: 100%;
+ }
+ </style>
+ <div id="container">
+ <div id="target"></div>
+ </div>
+ )HTML");
+
+ // Initially the vertical scrollbar overflows the narrow border box.
+ auto* container = GetDocument().getElementById("container");
+ auto* target = ToLayoutBox(GetLayoutObjectByElementId("target"));
+ auto* scrollbar_layer =
+ target->GetScrollableArea()->GraphicsLayerForVerticalScrollbar();
+ auto target_state = target->FirstFragment().LocalBorderBoxProperties();
+ auto scrollbar_state = target_state;
+ auto* overflow_controls_clip =
+ target->FirstFragment().PaintProperties()->OverflowControlsClip();
+ ASSERT_TRUE(overflow_controls_clip);
+ scrollbar_state.SetClip(*overflow_controls_clip);
+ EXPECT_EQ(scrollbar_state, scrollbar_layer->GetPropertyTreeState());
+
+ // Widen target to make the vertical scrollbar contained by the border box.
+ container->setAttribute(html_names::kStyleAttr, "width: 100px");
+ UpdateAllLifecyclePhasesForTest();
+ LOG(ERROR) << target->Size();
+ EXPECT_FALSE(
+ target->FirstFragment().PaintProperties()->OverflowControlsClip());
+ EXPECT_EQ(target_state, scrollbar_layer->GetPropertyTreeState());
+
+ // Narrow down target back.
+ container->removeAttribute(html_names::kStyleAttr);
+ UpdateAllLifecyclePhasesForTest();
+ scrollbar_state = target_state;
+ overflow_controls_clip =
+ target->FirstFragment().PaintProperties()->OverflowControlsClip();
+ ASSERT_TRUE(overflow_controls_clip);
+ scrollbar_state.SetClip(*overflow_controls_clip);
+ EXPECT_EQ(scrollbar_state, scrollbar_layer->GetPropertyTreeState());
+}
+
} // namespace blink
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
index 6810fb3e4f7ba1c994812c3fa983009792e00cc4..7d391839432a7d11102db78ef84b6369357eb77f 100644
--- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
+++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -1525,21 +1525,21 @@ void FragmentPaintPropertyTreeBuilder::UpdateOverflowControlsClip() {
if (NeedsOverflowControlsClip()) {
// Clip overflow controls to the border box rect. Not wrapped with
- // OnUpdateClip() because this clip doesn't affect descendants.
+ // OnUpdateClip() because this clip doesn't affect descendants. Wrap with
+ // OnUpdate() to let PrePaintTreeWalk see the change. This may cause
+ // unnecessary subtree update, but is not a big deal because it is rare.
const auto& clip_rect = PhysicalRect(context_.current.paint_offset,
ToLayoutBox(object_).Size());
- properties_->UpdateOverflowControlsClip(
+ OnUpdate(properties_->UpdateOverflowControlsClip(
*context_.current.clip,
ClipPaintPropertyNode::State(context_.current.transform,
FloatRoundedRect(FloatRect(clip_rect)),
- ToSnappedClipRect(clip_rect)));
+ ToSnappedClipRect(clip_rect))));
} else {
- properties_->ClearOverflowControlsClip();
+ OnClear(properties_->ClearOverflowControlsClip());
}
- // No need to set force_subtree_update_reasons and clip_changed because
- // OverflowControlsClip applies to overflow controls only, not descendants.
- // We also don't walk into custom scrollbars in PrePaintTreeWalk and
+ // We don't walk into custom scrollbars in PrePaintTreeWalk because
// LayoutObjects under custom scrollbars don't support paint properties.
}

View File

@@ -0,0 +1,70 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Etienne Bergeron <etienneb@chromium.org>
Date: Fri, 13 Nov 2020 17:40:59 +0000
Subject: Fix text eliding for single-codepoint text with BiDi
This CL is fixing a corner case where RenderText::Elide(...) may
produce a text with more codepoints than the original one. This is
an issue since the breaklists are not resized and the overflow
will lead the render_text code to perfoarm an out-of-bound memory
access by deferencing breaks_.end() while rendering the text. This
is causing chrome to crash.
See crbug/1142020 for details.
The bug was happening when:
1) The text to elide was a single codepoint
2) The width of the glyph of the codepoint is larger than the width
of the ellipsis glyph
3) Eliding is set to ELIDING_TAIL
4) The display_rect width will trigger eliding
(smaller than codepoint width, but larger than ellipsis width)
5) The render text is set to RTL
A possible solution is to adjust the breaklist but this required
larger refactoring and cannot be a minimal patch to be merge on
other channels.
TBR=msw@chromium.org
(cherry picked from commit e54920751871321474e0b953329c8aedcc8702c3)
Bug: 1142020
Change-Id: I9854651175562ec5f0d0bf7083a8da99fede0e29
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2522892
Commit-Queue: Etienne Bergeron <etienneb@chromium.org>
Reviewed-by: Michael Wasserman <msw@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#824878}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2537931
Reviewed-by: Etienne Bergeron <etienneb@chromium.org>
Cr-Commit-Position: refs/branch-heads/4240@{#1450}
Cr-Branched-From: f297677702651916bbf65e59c0d4bbd4ce57d1ee-refs/heads/master@{#800218}
diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc
index 7d5fb0c4d6e609d99533a10f26cf5ef195b4c18a..5a32f3f0987f7c4f94ba471876e9a0ff4ff91751 100644
--- a/ui/gfx/render_text.cc
+++ b/ui/gfx/render_text.cc
@@ -2067,8 +2067,10 @@ base::string16 RenderText::Elide(const base::string16& text,
}
// Append the ellipsis and the optional directional marker characters.
+ // Do not append the BiDi marker if the only codepoint in the text is
+ // an ellipsis.
new_text.append(ellipsis);
- if (trailing_text_direction != text_direction) {
+ if (new_text.size() != 1 && trailing_text_direction != text_direction) {
if (trailing_text_direction == base::i18n::LEFT_TO_RIGHT)
new_text += base::i18n::kLeftToRightMark;
else
diff --git a/ui/gfx/render_text_unittest.cc b/ui/gfx/render_text_unittest.cc
index 6796016d97a6c167a31482e353e4faac652ce2a4..80b9d756a52f8df2a4420ffd3c275d529ef95bfb 100644
--- a/ui/gfx/render_text_unittest.cc
+++ b/ui/gfx/render_text_unittest.cc
@@ -1851,7 +1851,7 @@ const ElideTextCase kElideTailTextCases[] = {
{"ltr_0", L"abc", L""},
{"rtl_3", L"\u05d0\u05d1\u05d2", L"\u05d0\u05d1\u05d2"},
{"rtl_2", L"\u05d0\u05d1\u05d2", L"\u05d0\u2026"},
- {"rtl_1", L"\u05d0\u05d1\u05d2", L"\u2026\x200E"},
+ {"rtl_1", L"\u05d0\u05d1\u05d2", L"\u2026"},
{"rtl_0", L"\u05d0\u05d1\u05d2", L""},
{"ltr_rtl_5", L"abc\u05d0\u05d1\u05d2", L"abc\u05d0\u2026\x200F"},
{"ltr_rtl_4", L"abc\u05d0\u05d1\u05d2", L"abc\u2026"},

View File

@@ -0,0 +1,77 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Bill Budge <bbudge@chromium.org>
Date: Fri, 13 Nov 2020 09:02:09 +0000
Subject: Merged: [wasm][code cache] Match response to cached raw resource
- Verifies that the retrieved resource has the same response time, and
that the source matches (i.e. both are from service worker, or both
are not).
Bug: chromium:1146673
(cherry picked from commit a8b46244ecaa1647ee2d70304878c0365ee04087)
Change-Id: I6243ec9017b2405687056aa6ea199c67b1c16063
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2526802
Reviewed-by: Yutaka Hirano <yhirano@chromium.org>
Reviewed-by: Andreas Haas <ahaas@chromium.org>
Commit-Queue: Bill Budge <bbudge@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#826277}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2537531
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Commit-Queue: Andreas Haas <ahaas@chromium.org>
Auto-Submit: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/branch-heads/4240@{#1447}
Cr-Branched-From: f297677702651916bbf65e59c0d4bbd4ce57d1ee-refs/heads/master@{#800218}
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc b/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc
index 6023c25e49ae6459cae350a3aae9b03c43da738a..978fb874469ad6e2a0ce2f70737c4a5c5b16aee3 100644
--- a/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc
+++ b/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc
@@ -210,7 +210,8 @@ class ExceptionToAbortStreamingScope {
};
RawResource* GetRawResource(ScriptState* script_state,
- const String& url_string) {
+ const String& url_string,
+ Response* response) {
ExecutionContext* execution_context = ExecutionContext::From(script_state);
if (!execution_context)
return nullptr;
@@ -224,6 +225,18 @@ RawResource* GetRawResource(ScriptState* script_state,
if (!resource)
return nullptr;
+ // Make sure the resource matches the |response|. To check that, we make sure
+ // the response times match, and the response sources match.
+ const ResourceResponse& resource_response = resource->GetResponse();
+ const FetchResponseData* fetch_response_data =
+ response->GetResponse()->InternalResponse();
+ if (resource_response.ResponseTime() != fetch_response_data->ResponseTime())
+ return nullptr;
+ bool from_service_worker = fetch_response_data->ResponseSource() ==
+ network::mojom::FetchResponseSource::kUnspecified;
+ if (resource_response.WasFetchedViaServiceWorker() != from_service_worker)
+ return nullptr;
+
// Wasm modules should be fetched as raw resources.
DCHECK_EQ(ResourceType::kRaw, resource->GetType());
return ToRawResource(resource);
@@ -354,13 +367,12 @@ void StreamFromResponseCallback(
String url = response->url();
const std::string& url_utf8 = url.Utf8();
streaming->SetUrl(url_utf8.c_str(), url_utf8.size());
- RawResource* raw_resource = GetRawResource(script_state, url);
- if (raw_resource) {
- SingleCachedMetadataHandler* cache_handler =
- raw_resource->ScriptCacheHandler();
+ RawResource* resource = GetRawResource(script_state, url, response);
+ if (resource) {
+ SingleCachedMetadataHandler* cache_handler = resource->ScriptCacheHandler();
if (cache_handler) {
auto client = std::make_shared<WasmStreamingClient>(
- url, raw_resource->GetResponse().ResponseTime());
+ url, resource->GetResponse().ResponseTime());
streaming->SetClient(client);
scoped_refptr<CachedMetadata> cached_module =
cache_handler->GetCachedMetadata(kWasmModuleTag);

View File

@@ -0,0 +1,206 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: John Rummell <jrummell@chromium.org>
Date: Wed, 16 Sep 2020 00:43:28 +0000
Subject: (merge) Check for context destroyed in MediaKeys
Don't allow calls to proceed once the associated content has been
destroyed.
(cherry picked from commit 1257ea7e0601a4a2a2a86bcc4a428573813f6cd7)
Bug: 1121414
Test: example in the bug no longer crashes
Change-Id: I3bdeb86f2020f684958b624fcc30438babfb5004
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2378889
Reviewed-by: Kentaro Hara <haraken@chromium.org>
Reviewed-by: Xiaohan Wang <xhwang@chromium.org>
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Commit-Queue: John Rummell <jrummell@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#805561}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2412559
Reviewed-by: John Rummell <jrummell@chromium.org>
Cr-Commit-Position: refs/branch-heads/4183@{#1836}
Cr-Branched-From: 740e9e8a40505392ba5c8e022a8024b3d018ca65-refs/heads/master@{#782793}
diff --git a/third_party/blink/renderer/modules/encryptedmedia/media_keys.cc b/third_party/blink/renderer/modules/encryptedmedia/media_keys.cc
index 82a2c622ebe5bd70f99c5effd730c063e7b63ab3..2d3b0a526d9cbcec248019826bdc4b40ec8f6f7f 100644
--- a/third_party/blink/renderer/modules/encryptedmedia/media_keys.cc
+++ b/third_party/blink/renderer/modules/encryptedmedia/media_keys.cc
@@ -228,6 +228,13 @@ MediaKeySession* MediaKeys::createSession(ScriptState* script_state,
DVLOG(MEDIA_KEYS_LOG_LEVEL)
<< __func__ << "(" << this << ") " << session_type_string;
+ // If the context for MediaKeys has been destroyed, fail.
+ if (!GetExecutionContext()) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
+ "The context provided is invalid.");
+ return nullptr;
+ }
+
// [RuntimeEnabled] does not work with enum values. So we have to check it
// here. See https://crbug.com/871867 for details.
if (!RuntimeEnabledFeatures::
@@ -274,6 +281,13 @@ ScriptPromise MediaKeys::setServerCertificate(
ScriptState* script_state,
const DOMArrayPiece& server_certificate,
ExceptionState& exception_state) {
+ // If the context for MediaKeys has been destroyed, fail.
+ if (!GetExecutionContext()) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
+ "The context provided is invalid.");
+ return ScriptPromise();
+ }
+
// From https://w3c.github.io/encrypted-media/#setServerCertificate
// The setServerCertificate(serverCertificate) method provides a server
// certificate to be used to encrypt messages to the license server.
@@ -317,6 +331,15 @@ void MediaKeys::SetServerCertificateTask(
ContentDecryptionModuleResult* result) {
DVLOG(MEDIA_KEYS_LOG_LEVEL) << __func__ << "(" << this << ")";
+ // If the context has been destroyed, don't proceed. Try to have the promise
+ // be rejected.
+ if (!GetExecutionContext()) {
+ result->CompleteWithError(
+ kWebContentDecryptionModuleExceptionInvalidStateError, 0,
+ "The context provided is invalid.");
+ return;
+ }
+
// 5.1 Let cdm be the cdm during the initialization of this object.
WebContentDecryptionModule* cdm = ContentDecryptionModule();
@@ -333,7 +356,15 @@ void MediaKeys::SetServerCertificateTask(
ScriptPromise MediaKeys::getStatusForPolicy(
ScriptState* script_state,
- const MediaKeysPolicy* media_keys_policy) {
+ const MediaKeysPolicy* media_keys_policy,
+ ExceptionState& exception_state) {
+ // If the context for MediaKeys has been destroyed, fail.
+ if (!GetExecutionContext()) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
+ "The context provided is invalid.");
+ return ScriptPromise();
+ }
+
// TODO(xhwang): Pass MediaKeysPolicy classes all the way to Chromium when
// we have more than one policy to check.
String min_hdcp_version = media_keys_policy->minHdcpVersion();
@@ -358,6 +389,15 @@ void MediaKeys::GetStatusForPolicyTask(const String& min_hdcp_version,
ContentDecryptionModuleResult* result) {
DVLOG(MEDIA_KEYS_LOG_LEVEL) << __func__ << ": " << min_hdcp_version;
+ // If the context has been destroyed, don't proceed. Try to have the promise
+ // be rejected.
+ if (!GetExecutionContext()) {
+ result->CompleteWithError(
+ kWebContentDecryptionModuleExceptionInvalidStateError, 0,
+ "The context provided is invalid.");
+ return;
+ }
+
WebContentDecryptionModule* cdm = ContentDecryptionModule();
cdm->GetStatusForPolicy(min_hdcp_version, result->Result());
}
diff --git a/third_party/blink/renderer/modules/encryptedmedia/media_keys.h b/third_party/blink/renderer/modules/encryptedmedia/media_keys.h
index ba2d0093ba83ca0c391f0edf03bf44502723e4cb..d24ad3d6e39f65d84200d3b198a59aca4c1c3c1f 100644
--- a/third_party/blink/renderer/modules/encryptedmedia/media_keys.h
+++ b/third_party/blink/renderer/modules/encryptedmedia/media_keys.h
@@ -71,9 +71,11 @@ class MediaKeys : public ScriptWrappable,
ScriptPromise setServerCertificate(ScriptState*,
const DOMArrayPiece& server_certificate,
- ExceptionState& exception_state);
+ ExceptionState&);
- ScriptPromise getStatusForPolicy(ScriptState*, const MediaKeysPolicy*);
+ ScriptPromise getStatusForPolicy(ScriptState*,
+ const MediaKeysPolicy*,
+ ExceptionState&);
// Indicates that the provided HTMLMediaElement wants to use this object.
// Returns true if no other HTMLMediaElement currently references this
diff --git a/third_party/blink/renderer/modules/encryptedmedia/media_keys_get_status_for_policy.cc b/third_party/blink/renderer/modules/encryptedmedia/media_keys_get_status_for_policy.cc
index 0b12f4d3a03158b3d3e83845612416a6ef67a3f5..c6e7ff4a754c3edfc258bb3ecdf652a38febfa77 100644
--- a/third_party/blink/renderer/modules/encryptedmedia/media_keys_get_status_for_policy.cc
+++ b/third_party/blink/renderer/modules/encryptedmedia/media_keys_get_status_for_policy.cc
@@ -14,10 +14,12 @@ namespace blink {
ScriptPromise MediaKeysGetStatusForPolicy::getStatusForPolicy(
ScriptState* script_state,
MediaKeys& media_keys,
- const MediaKeysPolicy* media_keys_policy) {
+ const MediaKeysPolicy* media_keys_policy,
+ ExceptionState& exception_state) {
DVLOG(1) << __func__;
- return media_keys.getStatusForPolicy(script_state, media_keys_policy);
+ return media_keys.getStatusForPolicy(script_state, media_keys_policy,
+ exception_state);
}
} // namespace blink
diff --git a/third_party/blink/renderer/modules/encryptedmedia/media_keys_get_status_for_policy.h b/third_party/blink/renderer/modules/encryptedmedia/media_keys_get_status_for_policy.h
index 246e7a5aac85c37cbbafab5b9fb6f2f4726ffbf2..62317f6c03724d2a6294a4516ef680fb89581481 100644
--- a/third_party/blink/renderer/modules/encryptedmedia/media_keys_get_status_for_policy.h
+++ b/third_party/blink/renderer/modules/encryptedmedia/media_keys_get_status_for_policy.h
@@ -20,7 +20,8 @@ class MediaKeysGetStatusForPolicy {
public:
static ScriptPromise getStatusForPolicy(ScriptState*,
MediaKeys&,
- const MediaKeysPolicy*);
+ const MediaKeysPolicy*,
+ ExceptionState&);
};
} // namespace blink
diff --git a/third_party/blink/renderer/modules/encryptedmedia/media_keys_get_status_for_policy.idl b/third_party/blink/renderer/modules/encryptedmedia/media_keys_get_status_for_policy.idl
index 15a6ca073ec19700a778f963a2697c4cf5c1f99d..671ba323111b6450288b55d9be95dbd216540b54 100644
--- a/third_party/blink/renderer/modules/encryptedmedia/media_keys_get_status_for_policy.idl
+++ b/third_party/blink/renderer/modules/encryptedmedia/media_keys_get_status_for_policy.idl
@@ -8,5 +8,5 @@
ImplementedAs=MediaKeysGetStatusForPolicy,
SecureContext
] partial interface MediaKeys {
- [Measure, CallWith=ScriptState] Promise<MediaKeyStatus> getStatusForPolicy(MediaKeysPolicy policy);
+ [Measure, CallWith=ScriptState, RaisesException] Promise<MediaKeyStatus> getStatusForPolicy(MediaKeysPolicy policy);
};
diff --git a/third_party/blink/web_tests/media/encrypted-media/encrypted-media-context-destroyed.html b/third_party/blink/web_tests/media/encrypted-media/encrypted-media-context-destroyed.html
new file mode 100644
index 0000000000000000000000000000000000000000..2d54624b0fa76b59a4341ed41a876654d135bc0e
--- /dev/null
+++ b/third_party/blink/web_tests/media/encrypted-media/encrypted-media-context-destroyed.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Test context destruction.</title>
+ <script src="encrypted-media-utils.js"></script>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <script>
+ function allociframe() {
+ iframe = document.createElement('iframe');
+ iframe.height = 50;
+ iframe.width = 50;
+ document.body.appendChild(iframe);
+ return iframe;
+ }
+
+ async_test(async function(test)
+ {
+ iframe = allociframe();
+ keySystemAccess = await iframe.contentWindow.navigator.requestMediaKeySystemAccess('org.w3.clearkey', getSimpleConfiguration());
+ keys = await keySystemAccess.createMediaKeys();
+ document.body.removeChild(iframe);
+ keys.getStatusForPolicy({minHdcpVersion : '1.0'}).then(function(result) {
+ assert_unreached('getStatusforPolicy() should fail');
+ }, function(error) {
+ test.done();
+ });
+ }, 'Test context destruction.');
+ </script>
+ </body>
+</html>

View File

@@ -0,0 +1,155 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Stephen Chenney <schenney@chromium.org>
Date: Wed, 14 Oct 2020 02:52:47 +0000
Subject: Implement WebGL image-orientation
M-86 merge.
When creating textures for WebGL, always orient images
with EXIF orientation data.
This change also corrects the transposed size reported by
ImageBitmap. And it removes superfluous arguments from
CopyImageData.
(cherry picked from commit f373458c504c2d115c42f31b29ff5c19674acbbc)
Bug: 1100470, 1125337
Change-Id: I79aa798327a3582939aa574723926b3325c80e7c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2459400
Reviewed-by: Kenneth Russell <kbr@chromium.org>
Commit-Queue: Stephen Chenney <schenney@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#815359}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2469776
Reviewed-by: Stephen Chenney <schenney@chromium.org>
Cr-Commit-Position: refs/branch-heads/4240@{#1237}
Cr-Branched-From: f297677702651916bbf65e59c0d4bbd4ce57d1ee-refs/heads/master@{#800218}
diff --git a/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc b/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
index 234ae964ad1ac8df7fd369ff8b62a9917757517d..f0bf8d0f5c2d74d942dfbfd194753dd03e3de758 100644
--- a/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
+++ b/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
@@ -195,14 +195,16 @@ SkImageInfo GetSkImageInfo(const scoped_refptr<Image>& input) {
// This function results in a readback due to using SkImage::readPixels().
// Returns transparent black pixels if the input SkImageInfo.bounds() does
-// not intersect with the input image boundaries.
+// not intersect with the input image boundaries. When apply_orientation
+// is true this method will orient the data according to the source's EXIF
+// information.
Vector<uint8_t> CopyImageData(const scoped_refptr<StaticBitmapImage>& input,
const SkImageInfo& info,
- const unsigned x = 0,
- const unsigned y = 0) {
+ bool apply_orientation = true) {
if (info.isEmpty())
return {};
- sk_sp<SkImage> sk_image = input->PaintImageForCurrentFrame().GetSkImage();
+ PaintImage paint_image = input->PaintImageForCurrentFrame();
+ sk_sp<SkImage> sk_image = paint_image.GetSkImage();
if (sk_image->bounds().isEmpty())
return {};
@@ -211,16 +213,30 @@ Vector<uint8_t> CopyImageData(const scoped_refptr<StaticBitmapImage>& input,
Vector<uint8_t> dst_buffer(byte_length);
bool read_pixels_successful =
- sk_image->readPixels(info, dst_buffer.data(), info.minRowBytes(), x, y);
+ sk_image->readPixels(info, dst_buffer.data(), info.minRowBytes(), 0, 0);
DCHECK(read_pixels_successful);
if (!read_pixels_successful)
return {};
+
+ // Orient the data, and re-read the pixels.
+ if (apply_orientation && !input->HasDefaultOrientation()) {
+ paint_image = Image::ResizeAndOrientImage(
+ paint_image, input->CurrentFrameOrientation(), FloatSize(1, 1), 1,
+ kInterpolationNone);
+ sk_image = paint_image.GetSkImage();
+ read_pixels_successful = sk_image->readPixels(info, dst_buffer.data(),
+ info.minRowBytes(), 0, 0);
+ DCHECK(read_pixels_successful);
+ if (!read_pixels_successful)
+ return {};
+ }
+
return dst_buffer;
}
Vector<uint8_t> CopyImageData(const scoped_refptr<StaticBitmapImage>& input) {
SkImageInfo info = GetSkImageInfo(input);
- return CopyImageData(std::move(input), info);
+ return CopyImageData(std::move(input), info, false);
}
static inline bool ShouldAvoidPremul(
@@ -1055,12 +1071,13 @@ Vector<uint8_t> ImageBitmap::CopyBitmapData(AlphaDisposition alpha_op,
auto color_type = info.colorType();
if (color_type == kN32_SkColorType && u8_color_type == kRGBAColorType)
color_type = kRGBA_8888_SkColorType;
+ // Note that width() and height() here apply EXIF orientation
info =
SkImageInfo::Make(width(), height(), color_type,
(alpha_op == kPremultiplyAlpha) ? kPremul_SkAlphaType
: kUnpremul_SkAlphaType,
info.refColorSpace());
- return CopyImageData(image_, info);
+ return CopyImageData(image_, info, true);
}
Vector<uint8_t> ImageBitmap::CopyBitmapData() {
@@ -1090,7 +1107,7 @@ IntSize ImageBitmap::Size() const {
return IntSize();
DCHECK_GT(image_->width(), 0);
DCHECK_GT(image_->height(), 0);
- return IntSize(image_->width(), image_->height());
+ return image_->SizeRespectingOrientation();
}
ScriptPromise ImageBitmap::CreateImageBitmap(ScriptState* script_state,
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
index 39d00937e8a17183c22dcfc99692aed9a8638ac6..fe5d33eca1ae6564a2528c60e880e619d1f59b62 100644
--- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
+++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
@@ -5212,10 +5212,12 @@ void WebGLRenderingContextBase::TexImageHelperHTMLImageElement(
return;
scoped_refptr<Image> image_for_render = image->CachedImage()->GetImage();
- if (IsA<SVGImage>(image_for_render.get())) {
- if (canvas()) {
+ bool have_svg_image = IsA<SVGImage>(image_for_render.get());
+ if (have_svg_image || !image_for_render->HasDefaultOrientation()) {
+ if (have_svg_image && canvas()) {
UseCounter::Count(canvas()->GetDocument(), WebFeature::kSVGInWebGL);
}
+ // DrawImageIntoBuffer always respects orientation
image_for_render =
DrawImageIntoBuffer(std::move(image_for_render), image->width(),
image->height(), func_name);
@@ -5751,6 +5753,7 @@ void WebGLRenderingContextBase::TexImageHelperImageBitmap(
level, internalformat, width, height, depth, 0, format,
type, xoffset, yoffset, zoffset))
return;
+
scoped_refptr<StaticBitmapImage> image = bitmap->BitmapImage();
DCHECK(image);
@@ -5777,9 +5780,16 @@ void WebGLRenderingContextBase::TexImageHelperImageBitmap(
return;
}
+ // Apply orientation if necessary
+ PaintImage paint_image = bitmap->BitmapImage()->PaintImageForCurrentFrame();
+ if (!image->HasDefaultOrientation()) {
+ paint_image = Image::ResizeAndOrientImage(
+ paint_image, image->CurrentFrameOrientation(), FloatSize(1, 1), 1,
+ kInterpolationNone);
+ }
+
// TODO(kbr): refactor this away to use TexImageImpl on image.
- sk_sp<SkImage> sk_image =
- bitmap->BitmapImage()->PaintImageForCurrentFrame().GetSkImage();
+ sk_sp<SkImage> sk_image = paint_image.GetSkImage();
if (!sk_image) {
SynthesizeGLError(GL_OUT_OF_MEMORY, func_name,
"ImageBitmap unexpectedly empty");

View File

@@ -0,0 +1,284 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lei Zhang <thestig@chromium.org>
Date: Tue, 28 Jul 2020 22:47:48 +0000
Subject: M85: Correctly retrieve the plugin when printing.
The logic in PrintRenderFrameHelper to retrieve a plugin is out of sync
with the logic in WebLocalFrameImpl::PrintBegin(). If
PrintRenderFrameHelper thinks it is printing a webpage, while
WebLocalFrameImpl thinks it is printing a plugin, bad things happen.
Fix this by adding WebLocalFrame::GetPluginToPrint(), to expose the
plugin finding logic in WebLocalFrameImpl. With GetPluginToPrint()
available, PrintRenderFrameHelper can delete its own GetPlugin() helper,
and switch the GetPlugin() callers to use GetPluginToPrint() instead.
Once synchronized, some use cases for printing Flash now work correctly.
(cherry picked from commit f8d7d428b1549ff1f87e3d34c5ca0b53d6ce4e84)
Tbr: japhet@chromium.org
Bug: 1098860
Change-Id: I9500db9ed2d6da0f87dad84c197f738d3a1e3c84
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2317168
Reviewed-by: Nate Chapin <japhet@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#791564}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2324664
Reviewed-by: Lei Zhang <thestig@chromium.org>
Cr-Commit-Position: refs/branch-heads/4183@{#1009}
Cr-Branched-From: 740e9e8a40505392ba5c8e022a8024b3d018ca65-refs/heads/master@{#782793}
diff --git a/components/printing/renderer/print_render_frame_helper.cc b/components/printing/renderer/print_render_frame_helper.cc
index 8456ec0c453345e5cab96728e501d341053d8cf2..9dd56e9df0d91ccd1d6789e3b3f261a533d373e8 100644
--- a/components/printing/renderer/print_render_frame_helper.cc
+++ b/components/printing/renderer/print_render_frame_helper.cc
@@ -61,8 +61,6 @@
#include "third_party/blink/public/web/web_local_frame_client.h"
#include "third_party/blink/public/web/web_navigation_control.h"
#include "third_party/blink/public/web/web_plugin.h"
-#include "third_party/blink/public/web/web_plugin_container.h"
-#include "third_party/blink/public/web/web_plugin_document.h"
#include "third_party/blink/public/web/web_print_params.h"
#include "third_party/blink/public/web/web_print_preset_options.h"
#include "third_party/blink/public/web/web_script_source.h"
@@ -343,28 +341,14 @@ void ComputeWebKitPrintParamsInDesiredDpi(
webkit_print_params->pages_per_sheet = print_params.pages_per_sheet;
}
-blink::WebPlugin* GetPlugin(const blink::WebLocalFrame* frame) {
- return frame->GetDocument().IsPluginDocument()
- ? frame->GetDocument().To<blink::WebPluginDocument>().Plugin()
- : nullptr;
-}
-
-bool IsPrintingNodeOrPdfFrame(const blink::WebLocalFrame* frame,
+bool IsPrintingNodeOrPdfFrame(blink::WebLocalFrame* frame,
const blink::WebNode& node) {
- if (!node.IsNull())
- return true;
- blink::WebPlugin* plugin = GetPlugin(frame);
+ blink::WebPlugin* plugin = frame->GetPluginToPrint(node);
return plugin && plugin->SupportsPaginatedPrint();
}
bool IsPrintingPdf(blink::WebLocalFrame* frame, const blink::WebNode& node) {
- blink::WebPlugin* plugin;
- if (node.IsNull()) {
- plugin = GetPlugin(frame);
- } else {
- blink::WebPluginContainer* plugin_container = node.PluginContainer();
- plugin = plugin_container ? plugin_container->Plugin() : nullptr;
- }
+ blink::WebPlugin* plugin = frame->GetPluginToPrint(node);
return plugin && plugin->IsPdfPlugin();
}
@@ -2337,7 +2321,7 @@ void PrintRenderFrameHelper::RequestPrintPreview(PrintPreviewRequestType type) {
// 2. PrintHostMsg_ShowScriptedPrintPreview shows preview once the
// document has been loaded.
is_scripted_preview_delayed_ = true;
- if (is_loading_ && GetPlugin(print_preview_context_.source_frame())) {
+ if (is_loading_ && print_preview_context_.IsPlugin()) {
// Wait for DidStopLoading. Plugins may not know the correct
// |is_modifiable| value until they are fully loaded, which occurs when
// DidStopLoading() is called. Defer showing the preview until then.
@@ -2364,7 +2348,7 @@ void PrintRenderFrameHelper::RequestPrintPreview(PrintPreviewRequestType type) {
// Wait for DidStopLoading. Continuing with this function while
// |is_loading_| is true will cause print preview to hang when try to
// print a PDF document.
- if (is_loading_ && GetPlugin(print_preview_context_.source_frame())) {
+ if (is_loading_ && print_preview_context_.IsPlugin()) {
on_stop_loading_closure_ =
base::BindOnce(&PrintRenderFrameHelper::RequestPrintPreview,
weak_ptr_factory_.GetWeakPtr(), type);
@@ -2375,12 +2359,12 @@ void PrintRenderFrameHelper::RequestPrintPreview(PrintPreviewRequestType type) {
}
case PRINT_PREVIEW_USER_INITIATED_SELECTION: {
DCHECK(has_selection);
- DCHECK(!GetPlugin(print_preview_context_.source_frame()));
+ DCHECK(!print_preview_context_.IsPlugin());
params.selection_only = has_selection;
break;
}
case PRINT_PREVIEW_USER_INITIATED_CONTEXT_NODE: {
- if (is_loading_ && GetPlugin(print_preview_context_.source_frame())) {
+ if (is_loading_ && print_preview_context_.IsPlugin()) {
on_stop_loading_closure_ =
base::BindOnce(&PrintRenderFrameHelper::RequestPrintPreview,
weak_ptr_factory_.GetWeakPtr(), type);
@@ -2465,8 +2449,7 @@ void PrintRenderFrameHelper::PrintPreviewContext::InitWithFrame(
state_ = INITIALIZED;
source_frame_.Reset(web_frame);
source_node_.Reset();
- CalculateIsModifiable();
- CalculateIsPdf();
+ CalculatePluginAttributes();
}
void PrintRenderFrameHelper::PrintPreviewContext::InitWithNode(
@@ -2477,8 +2460,7 @@ void PrintRenderFrameHelper::PrintPreviewContext::InitWithNode(
state_ = INITIALIZED;
source_frame_.Reset(web_node.GetDocument().GetFrame());
source_node_ = web_node;
- CalculateIsModifiable();
- CalculateIsPdf();
+ CalculatePluginAttributes();
}
void PrintRenderFrameHelper::PrintPreviewContext::OnPrintPreview() {
@@ -2621,6 +2603,11 @@ bool PrintRenderFrameHelper::PrintPreviewContext::IsForArc() const {
return is_for_arc_;
}
+bool PrintRenderFrameHelper::PrintPreviewContext::IsPlugin() const {
+ DCHECK(state_ != UNINITIALIZED);
+ return is_plugin_;
+}
+
bool PrintRenderFrameHelper::PrintPreviewContext::IsModifiable() const {
DCHECK(state_ != UNINITIALIZED);
return is_modifiable_;
@@ -2713,11 +2700,9 @@ void PrintRenderFrameHelper::PrintPreviewContext::ClearContext() {
error_ = PREVIEW_ERROR_NONE;
}
-void PrintRenderFrameHelper::PrintPreviewContext::CalculateIsModifiable() {
+void PrintRenderFrameHelper::PrintPreviewContext::CalculatePluginAttributes() {
+ is_plugin_ = !!source_frame()->GetPluginToPrint(source_node_);
is_modifiable_ = !IsPrintingNodeOrPdfFrame(source_frame(), source_node_);
-}
-
-void PrintRenderFrameHelper::PrintPreviewContext::CalculateIsPdf() {
is_pdf_ = IsPrintingPdf(source_frame(), source_node_);
}
diff --git a/components/printing/renderer/print_render_frame_helper.h b/components/printing/renderer/print_render_frame_helper.h
index 81df566a5908f1b35b9da5c2aad35ea7dec1dc3b..30cb90cab8a971b1b4eb11bb89e05b09853b7721 100644
--- a/components/printing/renderer/print_render_frame_helper.h
+++ b/components/printing/renderer/print_render_frame_helper.h
@@ -503,6 +503,7 @@ class PrintRenderFrameHelper
int GetNextPageNumber();
bool IsRendering() const;
bool IsForArc() const;
+ bool IsPlugin() const;
bool IsModifiable() const;
bool IsPdf() const;
bool HasSelection();
@@ -543,9 +544,7 @@ class PrintRenderFrameHelper
// Reset some of the internal rendering context.
void ClearContext();
- void CalculateIsModifiable();
-
- void CalculateIsPdf();
+ void CalculatePluginAttributes();
// Specifies what to render for print preview.
FrameReference source_frame_;
@@ -565,6 +564,9 @@ class PrintRenderFrameHelper
// List of page indices that need to be rendered.
std::vector<int> pages_to_render_;
+ // True, if the document source is a plugin.
+ bool is_plugin_ = false;
+
// True, if the document source is modifiable. e.g. HTML and not PDF.
bool is_modifiable_ = true;
diff --git a/third_party/blink/public/web/web_local_frame.h b/third_party/blink/public/web/web_local_frame.h
index c5d9cd52989c0d776ac12a5c0b88782d2c40b213..ecb810fecebd4ecb8c93630490cfb8ad5fe856c6 100644
--- a/third_party/blink/public/web/web_local_frame.h
+++ b/third_party/blink/public/web/web_local_frame.h
@@ -59,6 +59,7 @@ class WebLocalFrameClient;
class WebFrameWidget;
class WebInputMethodController;
class WebPerformance;
+class WebPlugin;
class WebRange;
class WebSecurityOrigin;
class WebScriptExecutionCallback;
@@ -655,13 +656,16 @@ class WebLocalFrame : public WebFrame {
// This function should be called before pairs of PrintBegin() and PrintEnd().
virtual void DispatchBeforePrintEvent() = 0;
+ // Get the plugin to print, if any. The |constrain_to_node| parameter is the
+ // same as the one for PrintBegin() below.
+ virtual WebPlugin* GetPluginToPrint(const WebNode& constrain_to_node) = 0;
+
// Reformats the WebFrame for printing. WebPrintParams specifies the printable
// content size, paper size, printable area size, printer DPI and print
- // scaling option. If constrainToNode node is specified, then only the given
+ // scaling option. If |constrain_to_node| is specified, then only the given
// node is printed (for now only plugins are supported), instead of the entire
// frame.
- // Returns the number of pages that can be printed at the given
- // page size.
+ // Returns the number of pages that can be printed at the given page size.
virtual int PrintBegin(const WebPrintParams&,
const WebNode& constrain_to_node = WebNode()) = 0;
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
index 9cb4f3d02fccd6f1098c9b8080f1057642aead5f..52e57b11169ec19c2f890545560a5784af071029 100644
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
@@ -1537,19 +1537,29 @@ void WebLocalFrameImpl::DispatchPrintEventRecursively(
}
}
-int WebLocalFrameImpl::PrintBegin(const WebPrintParams& print_params,
- const WebNode& constrain_to_node) {
- WebPluginContainerImpl* plugin_container = nullptr;
+WebPluginContainerImpl* WebLocalFrameImpl::GetPluginToPrintHelper(
+ const WebNode& constrain_to_node) {
if (constrain_to_node.IsNull()) {
// If this is a plugin document, check if the plugin supports its own
// printing. If it does, we will delegate all printing to that.
- plugin_container = GetFrame()->GetWebPluginContainer();
- } else {
- // We only support printing plugin nodes for now.
- plugin_container =
- To<WebPluginContainerImpl>(constrain_to_node.PluginContainer());
+ return GetFrame()->GetWebPluginContainer();
}
+ // We only support printing plugin nodes for now.
+ return To<WebPluginContainerImpl>(constrain_to_node.PluginContainer());
+}
+
+WebPlugin* WebLocalFrameImpl::GetPluginToPrint(
+ const WebNode& constrain_to_node) {
+ WebPluginContainerImpl* plugin_container =
+ GetPluginToPrintHelper(constrain_to_node);
+ return plugin_container ? plugin_container->Plugin() : nullptr;
+}
+
+int WebLocalFrameImpl::PrintBegin(const WebPrintParams& print_params,
+ const WebNode& constrain_to_node) {
+ WebPluginContainerImpl* plugin_container =
+ GetPluginToPrintHelper(constrain_to_node);
if (plugin_container && plugin_container->SupportsPaginatedPrint()) {
print_context_ = MakeGarbageCollected<ChromePluginPrintContext>(
GetFrame(), plugin_container, print_params);
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.h b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
index d7582f9c2f733d4beeb294df34dcbf09ce3970ce..f93ce60b7dd67c49feadc7679f2dc40dab0fb47e 100644
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.h
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
@@ -279,6 +279,7 @@ class CORE_EXPORT WebLocalFrameImpl final
bool HasVisibleContent() const override;
WebRect VisibleContentRect() const override;
void DispatchBeforePrintEvent() override;
+ WebPlugin* GetPluginToPrint(const WebNode& constrain_to_node) override;
int PrintBegin(const WebPrintParams&,
const WebNode& constrain_to_node) override;
float GetPrintPageShrink(int page) override;
@@ -470,6 +471,9 @@ class CORE_EXPORT WebLocalFrameImpl final
// A helper for DispatchBeforePrintEvent() and DispatchAfterPrintEvent().
void DispatchPrintEventRecursively(const AtomicString& event_type);
+ WebPluginContainerImpl* GetPluginToPrintHelper(
+ const WebNode& constrain_to_node);
+
Node* ContextMenuNodeInner() const;
WebLocalFrameClient* client_;

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