mirror of
https://github.com/electron/electron.git
synced 2026-02-26 03:01:17 -05:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
763729c9ef | ||
|
|
bc7b2a3589 | ||
|
|
13908747ab | ||
|
|
0ebe40354e | ||
|
|
e16d9f99e6 | ||
|
|
682b27f606 | ||
|
|
0b94b5b86f |
@@ -257,6 +257,10 @@ step-depot-tools-get: &step-depot-tools-get
|
||||
name: Get depot tools
|
||||
command: |
|
||||
git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
cd depot_tools
|
||||
git fetch --depth 1 origin f76550541c751f956ef9287f2695a6c8a74bf709
|
||||
git checkout f76550541c751f956ef9287f2695a6c8a74bf709
|
||||
cd ..
|
||||
if [ "`uname`" == "Darwin" ]; then
|
||||
# remove ninjalog_uploader_wrapper.py from autoninja since we don't use it and it causes problems
|
||||
sed -i '' '/ninjalog_uploader_wrapper.py/d' ./depot_tools/autoninja
|
||||
|
||||
@@ -92,6 +92,11 @@ for:
|
||||
Remove-Item -Recurse -Force $pwd\build-tools
|
||||
}
|
||||
- git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
- ps: |
|
||||
cd depot_tools
|
||||
git fetch --depth 1 origin f76550541c751f956ef9287f2695a6c8a74bf709
|
||||
git checkout f76550541c751f956ef9287f2695a6c8a74bf709
|
||||
cd ..
|
||||
- ps: New-Item -Name depot_tools\.disable_auto_update -ItemType File
|
||||
- depot_tools\bootstrap\win_tools.bat
|
||||
- ps: $env:PATH="$pwd\depot_tools;$env:PATH"
|
||||
|
||||
@@ -90,6 +90,11 @@ for:
|
||||
Remove-Item -Recurse -Force $pwd\build-tools
|
||||
}
|
||||
- git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
- ps: |
|
||||
cd depot_tools
|
||||
git fetch --depth 1 origin f76550541c751f956ef9287f2695a6c8a74bf709
|
||||
git checkout f76550541c751f956ef9287f2695a6c8a74bf709
|
||||
cd ..
|
||||
- ps: New-Item -Name depot_tools\.disable_auto_update -ItemType File
|
||||
- depot_tools\bootstrap\win_tools.bat
|
||||
- ps: $env:PATH="$pwd\depot_tools;$env:PATH"
|
||||
|
||||
@@ -123,32 +123,19 @@ support via Electron's support for the [Chrome DevTools Protocol][] (CDP).
|
||||
|
||||
### Install dependencies
|
||||
|
||||
You can install Playwright through your preferred Node.js package manager. The Playwright team
|
||||
recommends using the `PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD` environment variable to avoid
|
||||
unnecessary browser downloads when testing an Electron app.
|
||||
|
||||
```sh npm2yarn
|
||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm install --save-dev playwright
|
||||
```
|
||||
|
||||
Playwright also comes with its own test runner, Playwright Test, which is built for end-to-end
|
||||
testing. You can also install it as a dev dependency in your project:
|
||||
You can install Playwright through your preferred Node.js package manager. It comes with its
|
||||
own [test runner][playwright-intro], which is built for end-to-end testing:
|
||||
|
||||
```sh npm2yarn
|
||||
npm install --save-dev @playwright/test
|
||||
```
|
||||
|
||||
:::caution Dependencies
|
||||
This tutorial was written `playwright@1.16.3` and `@playwright/test@1.16.3`. Check out
|
||||
This tutorial was written with `@playwright/test@1.41.1`. Check out
|
||||
[Playwright's releases][playwright-releases] page to learn about
|
||||
changes that might affect the code below.
|
||||
:::
|
||||
|
||||
:::info Using third-party test runners
|
||||
If you're interested in using an alternative test runner (e.g. Jest or Mocha), check out
|
||||
Playwright's [Third-Party Test Runner][playwright-test-runners] guide.
|
||||
:::
|
||||
|
||||
### Write your tests
|
||||
|
||||
Playwright launches your app in development mode through the `_electron.launch` API.
|
||||
@@ -156,8 +143,7 @@ To point this API to your Electron app, you can pass the path to your main proce
|
||||
entry point (here, it is `main.js`).
|
||||
|
||||
```js {5} @ts-nocheck
|
||||
const { _electron: electron } = require('playwright')
|
||||
const { test } = require('@playwright/test')
|
||||
const { test, _electron: electron } = require('@playwright/test')
|
||||
|
||||
test('launch app', async () => {
|
||||
const electronApp = await electron.launch({ args: ['main.js'] })
|
||||
@@ -169,9 +155,8 @@ test('launch app', async () => {
|
||||
After that, you will access to an instance of Playwright's `ElectronApp` class. This
|
||||
is a powerful class that has access to main process modules for example:
|
||||
|
||||
```js {6-11} @ts-nocheck
|
||||
const { _electron: electron } = require('playwright')
|
||||
const { test } = require('@playwright/test')
|
||||
```js {5-10} @ts-nocheck
|
||||
const { test, _electron: electron } = require('@playwright/test')
|
||||
|
||||
test('get isPackaged', async () => {
|
||||
const electronApp = await electron.launch({ args: ['main.js'] })
|
||||
@@ -190,8 +175,7 @@ It can also create individual [Page][playwright-page] objects from Electron Brow
|
||||
For example, to grab the first BrowserWindow and save a screenshot:
|
||||
|
||||
```js {6-7} @ts-nocheck
|
||||
const { _electron: electron } = require('playwright')
|
||||
const { test } = require('@playwright/test')
|
||||
const { test, _electron: electron } = require('@playwright/test')
|
||||
|
||||
test('save screenshot', async () => {
|
||||
const electronApp = await electron.launch({ args: ['main.js'] })
|
||||
@@ -202,12 +186,11 @@ test('save screenshot', async () => {
|
||||
})
|
||||
```
|
||||
|
||||
Putting all this together using the PlayWright Test runner, let's create a `example.spec.js`
|
||||
Putting all this together using the Playwright test-runner, let's create a `example.spec.js`
|
||||
test file with a single test and assertion:
|
||||
|
||||
```js title='example.spec.js' @ts-nocheck
|
||||
const { _electron: electron } = require('playwright')
|
||||
const { test, expect } = require('@playwright/test')
|
||||
const { test, expect, _electron: electron } = require('@playwright/test')
|
||||
|
||||
test('example test', async () => {
|
||||
const electronApp = await electron.launch({ args: ['.'] })
|
||||
@@ -243,6 +226,7 @@ Running 1 test using 1 worker
|
||||
:::info
|
||||
Playwright Test will automatically run any files matching the `.*(test|spec)\.(js|ts|mjs)` regex.
|
||||
You can customize this match in the [Playwright Test configuration options][playwright-test-config].
|
||||
It also works with TypeScript out of the box.
|
||||
:::
|
||||
|
||||
:::tip Further reading
|
||||
@@ -400,10 +384,10 @@ test.after.always('cleanup', async t => {
|
||||
|
||||
[chrome-driver]: https://sites.google.com/chromium.org/driver/
|
||||
[Puppeteer]: https://github.com/puppeteer/puppeteer
|
||||
[playwright-intro]: https://playwright.dev/docs/intro
|
||||
[playwright-electron]: https://playwright.dev/docs/api/class-electron/
|
||||
[playwright-electronapplication]: https://playwright.dev/docs/api/class-electronapplication
|
||||
[playwright-page]: https://playwright.dev/docs/api/class-page
|
||||
[playwright-releases]: https://github.com/microsoft/playwright/releases
|
||||
[playwright-releases]: https://playwright.dev/docs/release-notes
|
||||
[playwright-test-config]: https://playwright.dev/docs/api/class-testconfig#test-config-test-match
|
||||
[playwright-test-runners]: https://playwright.dev/docs/test-runners/
|
||||
[Chrome DevTools Protocol]: https://chromedevtools.github.io/devtools-protocol/
|
||||
|
||||
@@ -643,7 +643,6 @@ filenames = {
|
||||
"shell/common/node_includes.h",
|
||||
"shell/common/node_util.cc",
|
||||
"shell/common/node_util.h",
|
||||
"shell/common/node_util_mac.mm",
|
||||
"shell/common/options_switches.cc",
|
||||
"shell/common/options_switches.h",
|
||||
"shell/common/platform_util.cc",
|
||||
|
||||
@@ -156,3 +156,11 @@ cherry-pick-5b2fddadaa12.patch
|
||||
cherry-pick-50a1bddfca85.patch
|
||||
reland_mojom_ts_generator_handle_empty_module_path_identically_to.patch
|
||||
cherry-pick-c1cda70a433a.patch
|
||||
cherry-pick-cc07a95bc309.patch
|
||||
safely_crash_on_dangling_profile.patch
|
||||
cherry-pick-ee0b8769f428.patch
|
||||
cherry-pick-1f8bec968902.patch
|
||||
cherry-pick-4a98f9e304be.patch
|
||||
fix_racy_iterator_use_in_node_addconnection.patch
|
||||
fix_a_crash_when_a_bmp_image_contains_an_unnecessary_eof_code.patch
|
||||
m120_ipcz_fix_a_few_weak_asserts.patch
|
||||
|
||||
125
patches/chromium/cherry-pick-1f8bec968902.patch
Normal file
125
patches/chromium/cherry-pick-1f8bec968902.patch
Normal file
@@ -0,0 +1,125 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tsuyoshi Horo <horo@chromium.org>
|
||||
Date: Wed, 24 Jan 2024 02:04:24 +0000
|
||||
Subject: Fix UAF in SourceStreamToDataPipe
|
||||
|
||||
SourceStreamToDataPipe::ReadMore() is passing a callback with
|
||||
Unretained(this) to net::SourceStream::Read(). But this callback may be
|
||||
called even after the SourceStream is destructed. This is causing UAF
|
||||
issue (crbug.com/1511085).
|
||||
|
||||
To solve this problem, this CL changes ReadMore() method to pass a
|
||||
callback with a weak ptr of this.
|
||||
|
||||
(cherry picked from commit 6e36a69da1b73f9aea9c54bfbe6c5b9cb2c672a5)
|
||||
|
||||
Bug: 1511085
|
||||
Change-Id: Idd4e34ff300ff5db2de1de7b303841c7db3a964a
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5179746
|
||||
Reviewed-by: Adam Rice <ricea@chromium.org>
|
||||
Commit-Queue: Tsuyoshi Horo <horo@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1244526}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5231558
|
||||
Reviewed-by: Kenichi Ishibashi <bashi@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/6099@{#1860}
|
||||
Cr-Branched-From: e6ee4500f7d6549a9ac1354f8d056da49ef406be-refs/heads/main@{#1217362}
|
||||
|
||||
diff --git a/services/network/public/cpp/source_stream_to_data_pipe.cc b/services/network/public/cpp/source_stream_to_data_pipe.cc
|
||||
index bfd85b1a00b216b52ae816ca29cb66ddabe20b6d..07afd58a40f92485ded07c535092a891c5140c7b 100644
|
||||
--- a/services/network/public/cpp/source_stream_to_data_pipe.cc
|
||||
+++ b/services/network/public/cpp/source_stream_to_data_pipe.cc
|
||||
@@ -55,9 +55,9 @@ void SourceStreamToDataPipe::ReadMore() {
|
||||
|
||||
scoped_refptr<net::IOBuffer> buffer(
|
||||
new network::NetToMojoIOBuffer(pending_write_.get()));
|
||||
- int result = source_->Read(
|
||||
- buffer.get(), base::checked_cast<int>(num_bytes),
|
||||
- base::BindOnce(&SourceStreamToDataPipe::DidRead, base::Unretained(this)));
|
||||
+ int result = source_->Read(buffer.get(), base::checked_cast<int>(num_bytes),
|
||||
+ base::BindOnce(&SourceStreamToDataPipe::DidRead,
|
||||
+ weak_factory_.GetWeakPtr()));
|
||||
|
||||
if (result != net::ERR_IO_PENDING)
|
||||
DidRead(result);
|
||||
diff --git a/services/network/public/cpp/source_stream_to_data_pipe_unittest.cc b/services/network/public/cpp/source_stream_to_data_pipe_unittest.cc
|
||||
index 7061418c5141d936f04b1193c98e66efc5e72ac5..54159df39afa7cf6e2faa51da185dc034b923209 100644
|
||||
--- a/services/network/public/cpp/source_stream_to_data_pipe_unittest.cc
|
||||
+++ b/services/network/public/cpp/source_stream_to_data_pipe_unittest.cc
|
||||
@@ -6,7 +6,9 @@
|
||||
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
+#include "base/test/bind.h"
|
||||
#include "base/test/task_environment.h"
|
||||
+#include "net/base/net_errors.h"
|
||||
#include "net/filter/mock_source_stream.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
#include "third_party/abseil-cpp/absl/types/optional.h"
|
||||
@@ -42,6 +44,33 @@ struct SourceStreamToDataPipeTestParam {
|
||||
const ReadResultType read_result_type;
|
||||
};
|
||||
|
||||
+class DummyPendingSourceStream : public net::SourceStream {
|
||||
+ public:
|
||||
+ DummyPendingSourceStream() : net::SourceStream(SourceStream::TYPE_NONE) {}
|
||||
+ ~DummyPendingSourceStream() override = default;
|
||||
+
|
||||
+ DummyPendingSourceStream(const DummyPendingSourceStream&) = delete;
|
||||
+ DummyPendingSourceStream& operator=(const DummyPendingSourceStream&) = delete;
|
||||
+
|
||||
+ // SourceStream implementation
|
||||
+ int Read(net::IOBuffer* dest_buffer,
|
||||
+ int buffer_size,
|
||||
+ net::CompletionOnceCallback callback) override {
|
||||
+ callback_ = std::move(callback);
|
||||
+ return net::ERR_IO_PENDING;
|
||||
+ }
|
||||
+ std::string Description() const override { return ""; }
|
||||
+ bool MayHaveMoreBytes() const override { return true; }
|
||||
+
|
||||
+ net::CompletionOnceCallback TakeCompletionCallback() {
|
||||
+ CHECK(callback_);
|
||||
+ return std::move(callback_);
|
||||
+ }
|
||||
+
|
||||
+ private:
|
||||
+ net::CompletionOnceCallback callback_;
|
||||
+};
|
||||
+
|
||||
} // namespace
|
||||
|
||||
class SourceStreamToDataPipeTest
|
||||
@@ -212,4 +241,33 @@ TEST_P(SourceStreamToDataPipeTest, MayHaveMoreBytes) {
|
||||
EXPECT_EQ(ReadPipe(&output), net::OK);
|
||||
EXPECT_EQ(output, message);
|
||||
}
|
||||
+
|
||||
+TEST(SourceStreamToDataPipeCallbackTest, CompletionCallbackAfterDestructed) {
|
||||
+ base::test::TaskEnvironment task_environment;
|
||||
+
|
||||
+ std::unique_ptr<DummyPendingSourceStream> source =
|
||||
+ std::make_unique<DummyPendingSourceStream>();
|
||||
+ DummyPendingSourceStream* source_ptr = source.get();
|
||||
+ const MojoCreateDataPipeOptions data_pipe_options{
|
||||
+ sizeof(MojoCreateDataPipeOptions), MOJO_CREATE_DATA_PIPE_FLAG_NONE, 1, 1};
|
||||
+ mojo::ScopedDataPipeProducerHandle producer_end;
|
||||
+ mojo::ScopedDataPipeConsumerHandle consumer_end;
|
||||
+ CHECK_EQ(MOJO_RESULT_OK, mojo::CreateDataPipe(&data_pipe_options,
|
||||
+ producer_end, consumer_end));
|
||||
+
|
||||
+ std::unique_ptr<SourceStreamToDataPipe> adapter =
|
||||
+ std::make_unique<SourceStreamToDataPipe>(std::move(source),
|
||||
+ std::move(producer_end));
|
||||
+ bool callback_called = false;
|
||||
+ adapter->Start(
|
||||
+ base::BindLambdaForTesting([&](int result) { callback_called = true; }));
|
||||
+ net::CompletionOnceCallback callback = source_ptr->TakeCompletionCallback();
|
||||
+ adapter.reset();
|
||||
+
|
||||
+ // Test that calling `callback` after deleting `adapter` must not cause UAF
|
||||
+ // (crbug.com/1511085).
|
||||
+ std::move(callback).Run(net::ERR_FAILED);
|
||||
+ EXPECT_FALSE(callback_called);
|
||||
+}
|
||||
+
|
||||
} // namespace network
|
||||
67
patches/chromium/cherry-pick-4a98f9e304be.patch
Normal file
67
patches/chromium/cherry-pick-4a98f9e304be.patch
Normal file
@@ -0,0 +1,67 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Peter=20Bostr=C3=B6m?= <pbos@chromium.org>
|
||||
Date: Fri, 26 Jan 2024 19:37:57 +0000
|
||||
Subject: Speculatively fix race in mojo ShutDownOnIOThread
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This acquires `write_lock_` before resetting handles used by WriteNoLock
|
||||
(which is called under the same lock in another thread). We also set
|
||||
`reject_writes_` to prevent future write attempts after shutdown. That
|
||||
seems strictly more correct.
|
||||
|
||||
We also acquire `fds_to_close_lock_` before clearing the FDs.
|
||||
|
||||
I was unable to repro locally as content_browsertests just times out
|
||||
in my local setup without reporting anything interesting. This seems
|
||||
strictly more correct though.
|
||||
|
||||
(cherry picked from commit 9755d9d81e4a8cb5b4f76b23b761457479dbb06b)
|
||||
|
||||
Bug: 1519980
|
||||
Change-Id: I96279936ca908ecb98eddd381df20d61597cba43
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5226127
|
||||
Auto-Submit: Peter Boström <pbos@chromium.org>
|
||||
Reviewed-by: Ken Rockot <rockot@google.com>
|
||||
Commit-Queue: Ken Rockot <rockot@google.com>
|
||||
Commit-Queue: Peter Boström <pbos@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1250580}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5239564
|
||||
Cr-Commit-Position: refs/branch-heads/6099@{#1883}
|
||||
Cr-Branched-From: e6ee4500f7d6549a9ac1354f8d056da49ef406be-refs/heads/main@{#1217362}
|
||||
|
||||
diff --git a/mojo/core/channel_posix.cc b/mojo/core/channel_posix.cc
|
||||
index 0a3596382d0e9a40c72bfb4ead6f0338a61253d6..eae6b0768463679b5043514dc5745da52b80ae10 100644
|
||||
--- a/mojo/core/channel_posix.cc
|
||||
+++ b/mojo/core/channel_posix.cc
|
||||
@@ -246,16 +246,21 @@ void ChannelPosix::WaitForWriteOnIOThreadNoLock() {
|
||||
void ChannelPosix::ShutDownOnIOThread() {
|
||||
base::CurrentThread::Get()->RemoveDestructionObserver(this);
|
||||
|
||||
- read_watcher_.reset();
|
||||
- write_watcher_.reset();
|
||||
- if (leak_handle_) {
|
||||
- std::ignore = socket_.release();
|
||||
- } else {
|
||||
- socket_.reset();
|
||||
- }
|
||||
+ {
|
||||
+ base::AutoLock lock(write_lock_);
|
||||
+ reject_writes_ = true;
|
||||
+ read_watcher_.reset();
|
||||
+ write_watcher_.reset();
|
||||
+ if (leak_handle_) {
|
||||
+ std::ignore = socket_.release();
|
||||
+ } else {
|
||||
+ socket_.reset();
|
||||
+ }
|
||||
#if BUILDFLAG(IS_IOS)
|
||||
- fds_to_close_.clear();
|
||||
+ base::AutoLock fd_lock(fds_to_close_lock_);
|
||||
+ fds_to_close_.clear();
|
||||
#endif
|
||||
+ }
|
||||
|
||||
// May destroy the |this| if it was the last reference.
|
||||
self_ = nullptr;
|
||||
150
patches/chromium/cherry-pick-cc07a95bc309.patch
Normal file
150
patches/chromium/cherry-pick-cc07a95bc309.patch
Normal file
@@ -0,0 +1,150 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Hongchan Choi <hongchan@chromium.org>
|
||||
Date: Fri, 19 Jan 2024 19:17:18 +0000
|
||||
Subject: Update rendering state of automatic pull nodes before graph rendering
|
||||
|
||||
In rare cases, the rendering fan out count of automatic pull node
|
||||
does not match the main thread fan out count after recreating
|
||||
a platform destination followed by disconnection.
|
||||
|
||||
This CL forces the update of the rendering state of automatic
|
||||
pull nodes before graph rendering to make sure that fan out counts
|
||||
are synchronized before executing the audio processing function call.
|
||||
|
||||
NOTE: This change makes 2 WPTs fail. The follow-up work is planned
|
||||
to address them once this patch is merged.
|
||||
|
||||
(cherry picked from commit f4bffa09b46c21147431179e1e6dd2b27bc35fbc)
|
||||
|
||||
Bug: 1505080
|
||||
Test: Locally confirmed that ASAN doesn't crash on all repro cases.
|
||||
Change-Id: I6768cd8bc64525ea9d56a19b9c58439e9cdab9a8
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5131958
|
||||
Reviewed-by: Michael Wilson <mjwilson@chromium.org>
|
||||
Commit-Queue: Hongchan Choi <hongchan@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1246718}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5214669
|
||||
Auto-Submit: Hongchan Choi <hongchan@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/6099@{#1833}
|
||||
Cr-Branched-From: e6ee4500f7d6549a9ac1354f8d056da49ef406be-refs/heads/main@{#1217362}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/webaudio/analyser_handler.cc b/third_party/blink/renderer/modules/webaudio/analyser_handler.cc
|
||||
index a3ef095cdeba50edc14b278cfc802a306e2719e8..3c885957ed5ef5f88de7c40c33160461391843fe 100644
|
||||
--- a/third_party/blink/renderer/modules/webaudio/analyser_handler.cc
|
||||
+++ b/third_party/blink/renderer/modules/webaudio/analyser_handler.cc
|
||||
@@ -39,9 +39,14 @@ AnalyserHandler::~AnalyserHandler() {
|
||||
}
|
||||
|
||||
void AnalyserHandler::Process(uint32_t frames_to_process) {
|
||||
- AudioBus* output_bus = Output(0).Bus();
|
||||
+ DCHECK(Context()->IsAudioThread());
|
||||
|
||||
- if (!IsInitialized()) {
|
||||
+ // It's possible that output is not connected. Assign nullptr to indicate
|
||||
+ // such case.
|
||||
+ AudioBus* output_bus = Output(0).RenderingFanOutCount() > 0
|
||||
+ ? Output(0).Bus() : nullptr;
|
||||
+
|
||||
+ if (!IsInitialized() && output_bus) {
|
||||
output_bus->Zero();
|
||||
return;
|
||||
}
|
||||
@@ -53,6 +58,11 @@ void AnalyserHandler::Process(uint32_t frames_to_process) {
|
||||
// Analyser reflects the current input.
|
||||
analyser_.WriteInput(input_bus.get(), frames_to_process);
|
||||
|
||||
+ // Subsequent steps require `output_bus` to be valid.
|
||||
+ if (!output_bus) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
if (!Input(0).IsConnected()) {
|
||||
// No inputs, so clear the output, and propagate the silence hint.
|
||||
output_bus->Zero();
|
||||
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_handler.cc b/third_party/blink/renderer/modules/webaudio/audio_worklet_handler.cc
|
||||
index 0bf86b7d659533e0acd9cd0c902c6dd68b51e1e6..903e8172d7c381da2e2cb8e9962ea601c76b375a 100644
|
||||
--- a/third_party/blink/renderer/modules/webaudio/audio_worklet_handler.cc
|
||||
+++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_handler.cc
|
||||
@@ -119,12 +119,14 @@ void AudioWorkletHandler::Process(uint32_t frames_to_process) {
|
||||
return;
|
||||
}
|
||||
|
||||
- // If the input is not connected, inform the processor with nullptr.
|
||||
+ // If the input or the output is not connected, inform the processor with
|
||||
+ // nullptr.
|
||||
for (unsigned i = 0; i < NumberOfInputs(); ++i) {
|
||||
inputs_[i] = Input(i).IsConnected() ? Input(i).Bus() : nullptr;
|
||||
}
|
||||
for (unsigned i = 0; i < NumberOfOutputs(); ++i) {
|
||||
- outputs_[i] = WrapRefCounted(Output(i).Bus());
|
||||
+ outputs_[i] = Output(i).RenderingFanOutCount() > 0
|
||||
+ ? WrapRefCounted(Output(i).Bus()) : nullptr;
|
||||
}
|
||||
|
||||
for (const auto& param_name : param_value_map_.Keys()) {
|
||||
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_processor.cc b/third_party/blink/renderer/modules/webaudio/audio_worklet_processor.cc
|
||||
index 181dfa92723843d5ce9ae3e7399215870ac1dc80..c3c53d7a7099d67a6bb76df55a6c71965ca3bf02 100644
|
||||
--- a/third_party/blink/renderer/modules/webaudio/audio_worklet_processor.cc
|
||||
+++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_processor.cc
|
||||
@@ -376,6 +376,12 @@ void AudioWorkletProcessor::CopyArrayBuffersToPort(
|
||||
|
||||
for (uint32_t bus_index = 0; bus_index < audio_port.size(); ++bus_index) {
|
||||
const scoped_refptr<AudioBus>& audio_bus = audio_port[bus_index];
|
||||
+
|
||||
+ // nullptr indicates the output bus is not connected. Do not proceed.
|
||||
+ if (!audio_bus) {
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
for (uint32_t channel_index = 0;
|
||||
channel_index < audio_bus->NumberOfChannels(); ++channel_index) {
|
||||
auto backing_store = array_buffers[bus_index][channel_index]
|
||||
diff --git a/third_party/blink/renderer/modules/webaudio/deferred_task_handler.cc b/third_party/blink/renderer/modules/webaudio/deferred_task_handler.cc
|
||||
index fa1de8f37b9be681f7ac447bc3e3859e8909216d..4730383dafa957c2e84c009387d15d6fe479e5ba 100644
|
||||
--- a/third_party/blink/renderer/modules/webaudio/deferred_task_handler.cc
|
||||
+++ b/third_party/blink/renderer/modules/webaudio/deferred_task_handler.cc
|
||||
@@ -172,6 +172,16 @@ void DeferredTaskHandler::UpdateAutomaticPullNodes() {
|
||||
base::AutoTryLock try_locker(automatic_pull_handlers_lock_);
|
||||
if (try_locker.is_acquired()) {
|
||||
rendering_automatic_pull_handlers_.assign(automatic_pull_handlers_);
|
||||
+
|
||||
+ // In rare cases, it is possible for automatic pull nodes' output bus
|
||||
+ // to become stale. Make sure update their rendering output counts.
|
||||
+ // crbug.com/1505080.
|
||||
+ for (auto& handler : rendering_automatic_pull_handlers_) {
|
||||
+ for (unsigned i = 0; i < handler->NumberOfOutputs(); ++i) {
|
||||
+ handler->Output(i).UpdateRenderingState();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
automatic_pull_handlers_need_updating_ = false;
|
||||
}
|
||||
}
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audioworklet-interface/audioworkletprocessor-process-frozen-array.https.html b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audioworklet-interface/audioworkletprocessor-process-frozen-array.https.html
|
||||
index 33627204a6f538eba77bd8346952404814e4affa..ce0cfa40b691d859d372c9e6da7ff54fe64bbbe1 100644
|
||||
--- a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audioworklet-interface/audioworkletprocessor-process-frozen-array.https.html
|
||||
+++ b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audioworklet-interface/audioworkletprocessor-process-frozen-array.https.html
|
||||
@@ -43,7 +43,10 @@
|
||||
if (actual.done)
|
||||
task.done();
|
||||
};
|
||||
- sourceNode.connect(workletNode);
|
||||
+ // To have valid ArrayBuffers for both input and output, we need
|
||||
+ // both connections.
|
||||
+ // See: https://github.com/WebAudio/web-audio-api/issues/2566
|
||||
+ sourceNode.connect(workletNode).connect(context.destination);
|
||||
sourceNode.start();
|
||||
});
|
||||
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audioworklet-interface/process-parameters.https-expected.txt b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audioworklet-interface/process-parameters.https-expected.txt
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..fbac76d9b865bfdec552bf280e4a19ae1743ef4a
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audioworklet-interface/process-parameters.https-expected.txt
|
||||
@@ -0,0 +1,6 @@
|
||||
+This is a testharness.js-based test.
|
||||
+[PASS] 3 inputs; 0 outputs
|
||||
+[FAIL] 0 inputs; 3 outputs
|
||||
+ assert_equals: outputs[0].length expected 1 but got 0
|
||||
+Harness: the test ran to completion.
|
||||
+
|
||||
72
patches/chromium/cherry-pick-ee0b8769f428.patch
Normal file
72
patches/chromium/cherry-pick-ee0b8769f428.patch
Normal file
@@ -0,0 +1,72 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Guido Urdaneta <guidou@chromium.org>
|
||||
Date: Wed, 24 Jan 2024 18:40:01 +0000
|
||||
Subject: Exit early from RTCPeerConnectionHandler
|
||||
|
||||
For certain operations that require a live client
|
||||
(i.e., RTCPeerConnection, which is garbage collected),
|
||||
PeerConnectionHandler keeps a pointer to the client on the stack
|
||||
to prevent garbage collection.
|
||||
|
||||
In some cases, the client may have already been garbage collected
|
||||
(the client is null). In that case, there is no point in doing the
|
||||
operation and it should exit early to avoid UAF/crashes.
|
||||
|
||||
This CL adds early exit to the cases that do not already have it.
|
||||
|
||||
(cherry picked from commit 8755f76bec326c654370de6dd68eea693df74ede)
|
||||
|
||||
Bug: 1514777
|
||||
Change-Id: I27e9541cfaa74d978799c03e2832a0980f9e5710
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5210359
|
||||
Reviewed-by: Tomas Gunnarsson <tommi@chromium.org>
|
||||
Commit-Queue: Guido Urdaneta <guidou@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1248826}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5233883
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Auto-Submit: Guido Urdaneta <guidou@chromium.org>
|
||||
Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/6099@{#1867}
|
||||
Cr-Branched-From: e6ee4500f7d6549a9ac1354f8d056da49ef406be-refs/heads/main@{#1217362}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
|
||||
index 76fa93800543ff134859c8fc0c0fa63123cf9772..9e5ce0572cfd1d2dd729e5f560b021aba05653f3 100644
|
||||
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
|
||||
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
|
||||
@@ -1057,15 +1057,19 @@ bool RTCPeerConnectionHandler::Initialize(
|
||||
WebLocalFrame* frame,
|
||||
ExceptionState& exception_state) {
|
||||
DCHECK(task_runner_->RunsTasksInCurrentSequence());
|
||||
- DCHECK(frame);
|
||||
DCHECK(dependency_factory_);
|
||||
- frame_ = frame;
|
||||
|
||||
CHECK(!initialize_called_);
|
||||
initialize_called_ = true;
|
||||
|
||||
// Prevent garbage collection of client_ during processing.
|
||||
auto* client_on_stack = client_;
|
||||
+ if (!client_on_stack) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ DCHECK(frame);
|
||||
+ frame_ = frame;
|
||||
peer_connection_tracker_ = PeerConnectionTracker::From(*frame);
|
||||
|
||||
configuration_ = server_configuration;
|
||||
@@ -2312,10 +2316,13 @@ void RTCPeerConnectionHandler::OnIceCandidate(const String& sdp,
|
||||
int sdp_mline_index,
|
||||
int component,
|
||||
int address_family) {
|
||||
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
|
||||
// In order to ensure that the RTCPeerConnection is not garbage collected
|
||||
// from under the function, we keep a pointer to it on the stack.
|
||||
auto* client_on_stack = client_;
|
||||
- DCHECK(task_runner_->RunsTasksInCurrentSequence());
|
||||
+ if (!client_on_stack) {
|
||||
+ return;
|
||||
+ }
|
||||
TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceCandidateImpl");
|
||||
// This line can cause garbage collection.
|
||||
auto* platform_candidate = MakeGarbageCollected<RTCIceCandidatePlatform>(
|
||||
@@ -0,0 +1,108 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: John Stiles <johnstiles@google.com>
|
||||
Date: Thu, 1 Feb 2024 20:40:55 +0000
|
||||
Subject: Fix a crash when a BMP image contains an unnecessary EOF code.
|
||||
|
||||
Previously, this would try to perform color correction on a row
|
||||
one past the end of the image data.
|
||||
|
||||
(cherry picked from commit 4bdd8d61bebbba9fab77fa86a8f66b305995199b)
|
||||
|
||||
Bug: 1521893
|
||||
Change-Id: I425437005b9ef400138556705616095857d2cf0d
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5241305
|
||||
Auto-Submit: John Stiles <johnstiles@google.com>
|
||||
Commit-Queue: John Stiles <johnstiles@google.com>
|
||||
Reviewed-by: Peter Kasting <pkasting@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1253633}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5259699
|
||||
Commit-Queue: Peter Kasting <pkasting@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/6099@{#1915}
|
||||
Cr-Branched-From: e6ee4500f7d6549a9ac1354f8d056da49ef406be-refs/heads/main@{#1217362}
|
||||
|
||||
diff --git a/third_party/blink/renderer/platform/blink_platform_unittests_bundle_data.filelist b/third_party/blink/renderer/platform/blink_platform_unittests_bundle_data.filelist
|
||||
index 74f34d801d7ad00a0b63731030fe32d9ed4e6595..48febaa9f2ea301d3928864d43ccb40f4f83d5c6 100644
|
||||
--- a/third_party/blink/renderer/platform/blink_platform_unittests_bundle_data.filelist
|
||||
+++ b/third_party/blink/renderer/platform/blink_platform_unittests_bundle_data.filelist
|
||||
@@ -385,6 +385,7 @@
|
||||
../../web_tests/images/resources/truncated.webp
|
||||
../../web_tests/images/resources/truncated2.webp
|
||||
../../web_tests/images/resources/twitter_favicon.ico
|
||||
+../../web_tests/images/resources/unnecessary-eof.bmp
|
||||
../../web_tests/images/resources/webp-animated-icc-xmp.webp
|
||||
../../web_tests/images/resources/webp-animated-large.webp
|
||||
../../web_tests/images/resources/webp-animated-no-blend.webp
|
||||
diff --git a/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_decoder_test.cc b/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_decoder_test.cc
|
||||
index a6e7353cd24ff4ec94f4ec068eaa94fa225f6537..287adb4410bfa91777f0def18e2cdf1bbbef1c25 100644
|
||||
--- a/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_decoder_test.cc
|
||||
+++ b/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_decoder_test.cc
|
||||
@@ -98,6 +98,19 @@ TEST(BMPImageDecoderTest, crbug752898) {
|
||||
decoder->DecodeFrameBufferAtIndex(0);
|
||||
}
|
||||
|
||||
+// Verify that decoding an image with an unnecessary EOF marker does not crash.
|
||||
+TEST(BMPImageDecoderTest, allowEOFWhenPastEndOfImage) {
|
||||
+ static constexpr char kBmpFile[] = "/images/resources/unnecessary-eof.bmp";
|
||||
+ scoped_refptr<SharedBuffer> data = ReadFile(kBmpFile);
|
||||
+ ASSERT_TRUE(data.get());
|
||||
+
|
||||
+ std::unique_ptr<ImageDecoder> decoder = CreateBMPDecoder();
|
||||
+ decoder->SetData(data.get(), true);
|
||||
+ ImageFrame* frame = decoder->DecodeFrameBufferAtIndex(0);
|
||||
+ EXPECT_EQ(ImageFrame::kFrameComplete, frame->GetStatus());
|
||||
+ EXPECT_FALSE(decoder->Failed());
|
||||
+}
|
||||
+
|
||||
class BMPImageDecoderCorpusTest : public ImageDecoderBaseTest {
|
||||
public:
|
||||
BMPImageDecoderCorpusTest() : ImageDecoderBaseTest("bmp") {}
|
||||
diff --git a/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.cc b/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.cc
|
||||
index 063e5385d7f66c8fb31941fe29dfe8dd5bcfb2e1..b40c8aa5c1fe514c933daa7ac5dc9791b73bf7e2 100644
|
||||
--- a/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.cc
|
||||
+++ b/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.cc
|
||||
@@ -827,8 +827,10 @@ BMPImageReader::ProcessingResult BMPImageReader::ProcessRLEData() {
|
||||
// the image.
|
||||
const uint8_t count = ReadUint8(0);
|
||||
const uint8_t code = ReadUint8(1);
|
||||
- if ((count || (code != 1)) && PastEndOfImage(0))
|
||||
+ const bool is_past_end_of_image = PastEndOfImage(0);
|
||||
+ if ((count || (code != 1)) && is_past_end_of_image) {
|
||||
return kFailure;
|
||||
+ }
|
||||
|
||||
// Decode.
|
||||
if (!count) {
|
||||
@@ -849,7 +851,9 @@ BMPImageReader::ProcessingResult BMPImageReader::ProcessRLEData() {
|
||||
(is_top_down_ ? (coord_.y() < (parent_->Size().height() - 1))
|
||||
: (coord_.y() > 0)))
|
||||
buffer_->SetHasAlpha(true);
|
||||
- ColorCorrectCurrentRow();
|
||||
+ if (!is_past_end_of_image) {
|
||||
+ ColorCorrectCurrentRow();
|
||||
+ }
|
||||
// There's no need to move |coord_| here to trigger the caller
|
||||
// to call SetPixelsChanged(). If the only thing that's changed
|
||||
// is the alpha state, that will be properly written into the
|
||||
@@ -1061,6 +1065,13 @@ void BMPImageReader::ColorCorrectCurrentRow() {
|
||||
const ColorProfileTransform* const transform = parent_->ColorTransform();
|
||||
if (!transform)
|
||||
return;
|
||||
+ int decoder_width = parent_->Size().width();
|
||||
+ // Enforce 0 ≤ current row < bitmap height.
|
||||
+ CHECK_GE(coord_.y(), 0);
|
||||
+ CHECK_LT(coord_.y(), buffer_->Bitmap().height());
|
||||
+ // Enforce decoder width == bitmap width exactly. (The bitmap rowbytes might
|
||||
+ // add a bit of padding, but we are only converting one row at a time.)
|
||||
+ CHECK_EQ(decoder_width, buffer_->Bitmap().width());
|
||||
ImageFrame::PixelData* const row = buffer_->GetAddr(0, coord_.y());
|
||||
const skcms_PixelFormat fmt = XformColorFormat();
|
||||
const skcms_AlphaFormat alpha =
|
||||
@@ -1069,7 +1080,7 @@ void BMPImageReader::ColorCorrectCurrentRow() {
|
||||
: skcms_AlphaFormat_Unpremul;
|
||||
const bool success =
|
||||
skcms_Transform(row, fmt, alpha, transform->SrcProfile(), row, fmt, alpha,
|
||||
- transform->DstProfile(), parent_->Size().width());
|
||||
+ transform->DstProfile(), decoder_width);
|
||||
DCHECK(success);
|
||||
buffer_->SetPixelsChanged(true);
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Peter=20Bostr=C3=B6m?= <pbos@chromium.org>
|
||||
Date: Thu, 1 Feb 2024 21:24:43 +0000
|
||||
Subject: Fix racy iterator use in Node::AddConnection
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Before this fix an iterator to `connections_` which requires a lock
|
||||
would be dereferenced outside an unlock operation because the `it` taken
|
||||
from the map isn't understood as guarded by the same lock.
|
||||
|
||||
This takes a Ref<NodeLink> before unlocking which'll keep the link
|
||||
reference alive even if `connections_` is concurrently modified and the
|
||||
entry removed (or replaced).
|
||||
|
||||
(cherry picked from commit 1f2cbf5833d7f00d3fcbfd1f3ef0c1aff10c04cd)
|
||||
|
||||
Bug: 1523704
|
||||
Change-Id: I6f6fe4e34ec2c8268d4e7f33965a13e3b10f9f92
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5254025
|
||||
Commit-Queue: Peter Boström <pbos@chromium.org>
|
||||
Reviewed-by: Ken Rockot <rockot@google.com>
|
||||
Commit-Queue: Ken Rockot <rockot@google.com>
|
||||
Auto-Submit: Peter Boström <pbos@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1254709}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5260163
|
||||
Cr-Commit-Position: refs/branch-heads/6099@{#1916}
|
||||
Cr-Branched-From: e6ee4500f7d6549a9ac1354f8d056da49ef406be-refs/heads/main@{#1217362}
|
||||
|
||||
diff --git a/third_party/ipcz/src/ipcz/node.cc b/third_party/ipcz/src/ipcz/node.cc
|
||||
index 695fda10a65d26239f68c36e10420b9e4955c0d7..d7a9c0a01a4bc1fd74182748756c9bb5c694688b 100644
|
||||
--- a/third_party/ipcz/src/ipcz/node.cc
|
||||
+++ b/third_party/ipcz/src/ipcz/node.cc
|
||||
@@ -170,9 +170,10 @@ bool Node::AddConnection(const NodeName& remote_node_name,
|
||||
// handling an incoming NodeConnector message, we can err on the side of
|
||||
// caution (i.e. less re-entrancy in event handlers) by treating every
|
||||
// case like an API call.
|
||||
+ const Ref<NodeLink> link = it->second.link;
|
||||
mutex_.Unlock();
|
||||
const OperationContext context{OperationContext::kAPICall};
|
||||
- DropConnection(context, *it->second.link);
|
||||
+ DropConnection(context, *link);
|
||||
mutex_.Lock();
|
||||
}
|
||||
|
||||
87
patches/chromium/m120_ipcz_fix_a_few_weak_asserts.patch
Normal file
87
patches/chromium/m120_ipcz_fix_a_few_weak_asserts.patch
Normal file
@@ -0,0 +1,87 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Rockot <rockot@google.com>
|
||||
Date: Tue, 30 Jan 2024 21:36:01 +0000
|
||||
Subject: ipcz: Fix a few weak asserts
|
||||
|
||||
DriverMemory cloning should not weakly assert success, as it can fail in
|
||||
real production scenarios. Now Clone() will return an invalid
|
||||
DriverMemory object if it fails to duplicate the internal handle.
|
||||
Existing callers of Clone() are already durable to an invalid output, so
|
||||
this change results in graceful failures instead of undefined behavior.
|
||||
|
||||
This also replaces some weak asserts in DriverTransport creation with
|
||||
hardening asserts. We may want to fail more gracefully if these end
|
||||
up crashing a lot, but it seems unlikely.
|
||||
|
||||
(cherry picked from commit 4bd18c5a3a7a935716bbed197fba6d45a1122894)
|
||||
|
||||
Fixed: 1521571
|
||||
Change-Id: Id764b33ead8bbba58e61b3270920c839479eaa4a
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5240312
|
||||
Commit-Queue: Ken Rockot <rockot@google.com>
|
||||
Reviewed-by: Alex Gough <ajgo@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1252882}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5250958
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Auto-Submit: Ken Rockot <rockot@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/6099@{#1905}
|
||||
Cr-Branched-From: e6ee4500f7d6549a9ac1354f8d056da49ef406be-refs/heads/main@{#1217362}
|
||||
|
||||
diff --git a/third_party/ipcz/src/ipcz/driver_memory.cc b/third_party/ipcz/src/ipcz/driver_memory.cc
|
||||
index f8761985b78409fdb5420456661b0d227030cc8f..3bdc3aaf52d166a7691b5f28ebc86cc47600f7cc 100644
|
||||
--- a/third_party/ipcz/src/ipcz/driver_memory.cc
|
||||
+++ b/third_party/ipcz/src/ipcz/driver_memory.cc
|
||||
@@ -30,10 +30,11 @@ DriverMemory::DriverMemory(const IpczDriver& driver, size_t num_bytes)
|
||||
: size_(num_bytes) {
|
||||
ABSL_ASSERT(num_bytes > 0);
|
||||
IpczDriverHandle handle;
|
||||
- IpczResult result =
|
||||
+ const IpczResult result =
|
||||
driver.AllocateSharedMemory(num_bytes, IPCZ_NO_FLAGS, nullptr, &handle);
|
||||
- ABSL_ASSERT(result == IPCZ_RESULT_OK);
|
||||
- memory_ = DriverObject(driver, handle);
|
||||
+ if (result == IPCZ_RESULT_OK) {
|
||||
+ memory_ = DriverObject(driver, handle);
|
||||
+ }
|
||||
}
|
||||
|
||||
DriverMemory::DriverMemory(DriverMemory&& other) = default;
|
||||
@@ -43,12 +44,14 @@ DriverMemory& DriverMemory::operator=(DriverMemory&& other) = default;
|
||||
DriverMemory::~DriverMemory() = default;
|
||||
|
||||
DriverMemory DriverMemory::Clone() {
|
||||
- ABSL_ASSERT(is_valid());
|
||||
+ ABSL_HARDENING_ASSERT(is_valid());
|
||||
|
||||
IpczDriverHandle handle;
|
||||
- IpczResult result = memory_.driver()->DuplicateSharedMemory(
|
||||
+ const IpczResult result = memory_.driver()->DuplicateSharedMemory(
|
||||
memory_.handle(), 0, nullptr, &handle);
|
||||
- ABSL_ASSERT(result == IPCZ_RESULT_OK);
|
||||
+ if (result != IPCZ_RESULT_OK) {
|
||||
+ return DriverMemory();
|
||||
+ }
|
||||
|
||||
return DriverMemory(DriverObject(*memory_.driver(), handle));
|
||||
}
|
||||
diff --git a/third_party/ipcz/src/ipcz/driver_transport.cc b/third_party/ipcz/src/ipcz/driver_transport.cc
|
||||
index 096f1b3bed3cfbe0074b074edba21bcfceacd897..dbeb69a0a881a82c9360118a017942ec6eb920f8 100644
|
||||
--- a/third_party/ipcz/src/ipcz/driver_transport.cc
|
||||
+++ b/third_party/ipcz/src/ipcz/driver_transport.cc
|
||||
@@ -68,14 +68,14 @@ DriverTransport::Pair DriverTransport::CreatePair(
|
||||
IpczDriverHandle target_transport0 = IPCZ_INVALID_DRIVER_HANDLE;
|
||||
IpczDriverHandle target_transport1 = IPCZ_INVALID_DRIVER_HANDLE;
|
||||
if (transport0) {
|
||||
- ABSL_ASSERT(transport1);
|
||||
+ ABSL_HARDENING_ASSERT(transport1);
|
||||
target_transport0 = transport0->driver_object().handle();
|
||||
target_transport1 = transport1->driver_object().handle();
|
||||
}
|
||||
IpczResult result = driver.CreateTransports(
|
||||
target_transport0, target_transport1, IPCZ_NO_FLAGS, nullptr,
|
||||
&new_transport0, &new_transport1);
|
||||
- ABSL_ASSERT(result == IPCZ_RESULT_OK);
|
||||
+ ABSL_HARDENING_ASSERT(result == IPCZ_RESULT_OK);
|
||||
auto first =
|
||||
MakeRefCounted<DriverTransport>(DriverObject(driver, new_transport0));
|
||||
auto second =
|
||||
55
patches/chromium/safely_crash_on_dangling_profile.patch
Normal file
55
patches/chromium/safely_crash_on_dangling_profile.patch
Normal file
@@ -0,0 +1,55 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Bo Liu <boliu@chromium.org>
|
||||
Date: Mon, 4 Dec 2023 15:01:22 +0000
|
||||
Subject: Safely crash on dangling profile
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Bug: 1407197
|
||||
Change-Id: Idcafd8f0ba2f980d06338e573489a3456e3823c1
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5080603
|
||||
Reviewed-by: Łukasz Anforowicz <lukasza@chromium.org>
|
||||
Commit-Queue: Bo Liu <boliu@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1232704}
|
||||
|
||||
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
|
||||
index 23f68b9f9c108fd74bcba15289c1a2082a53c486..4675791781d2452732cfe4ddc93bfdf3f6f8bb03 100644
|
||||
--- a/content/browser/web_contents/web_contents_impl.cc
|
||||
+++ b/content/browser/web_contents/web_contents_impl.cc
|
||||
@@ -222,6 +222,11 @@ BASE_FEATURE(kBackNavigationPredictionMetrics,
|
||||
"BackNavigationPredictionMetrics",
|
||||
base::FEATURE_ENABLED_BY_DEFAULT);
|
||||
|
||||
+// Kill switch for crash immediately on dangling BrowserContext.
|
||||
+BASE_FEATURE(kCrashOnDanglingBrowserContext,
|
||||
+ "CrashOnDanglingBrowserContext",
|
||||
+ base::FEATURE_ENABLED_BY_DEFAULT);
|
||||
+
|
||||
using LifecycleState = RenderFrameHost::LifecycleState;
|
||||
using LifecycleStateImpl = RenderFrameHostImpl::LifecycleStateImpl;
|
||||
|
||||
@@ -940,11 +945,18 @@ class WebContentsOfBrowserContext : public base::SupportsUserData::Data {
|
||||
env, web_contents_with_dangling_ptr_to_browser_context);
|
||||
#endif // BUILDFLAG(IS_ANDROID)
|
||||
|
||||
- NOTREACHED()
|
||||
- << "BrowserContext is getting destroyed without first closing all "
|
||||
- << "WebContents (for more info see https://crbug.com/1376879#c44); "
|
||||
- << "creator = " << creator;
|
||||
- base::debug::DumpWithoutCrashing();
|
||||
+ if (base::FeatureList::IsEnabled(kCrashOnDanglingBrowserContext)) {
|
||||
+ LOG(FATAL)
|
||||
+ << "BrowserContext is getting destroyed without first closing all "
|
||||
+ << "WebContents (for more info see https://crbug.com/1376879#c44); "
|
||||
+ << "creator = " << creator;
|
||||
+ } else {
|
||||
+ NOTREACHED()
|
||||
+ << "BrowserContext is getting destroyed without first closing all "
|
||||
+ << "WebContents (for more info see https://crbug.com/1376879#c44); "
|
||||
+ << "creator = " << creator;
|
||||
+ base::debug::DumpWithoutCrashing();
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,3 +5,4 @@ pipewire_capturer_increase_buffer_size_to_avoid_buffer_overflow.patch
|
||||
prevent_sdp_munging_of_duplicate_ssrcs.patch
|
||||
fix_check_pipewire_init_before_creating_generic_capturer.patch
|
||||
pipewire_capturer_make_restore_tokens_re-usable_more_than_one_time.patch
|
||||
tighten_som_dchecks_to_checks_in_vp9_packetization.patch
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Erik=20Spr=C3=A5ng?= <sprang@webrtc.org>
|
||||
Date: Fri, 19 Jan 2024 16:59:01 +0100
|
||||
Subject: Tighten som DCHECKs to CHECKs in VP9 packetization.
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
(cherry picked from commit 6a992129fb0dede4a8fbdaf5de43abaf43c20299)
|
||||
|
||||
No-Try: True
|
||||
Bug: chromium:1518991, chromium:1518994
|
||||
Change-Id: I47f68ba6aaf4874fd952332bf213e3a1e0389268
|
||||
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/335241
|
||||
Auto-Submit: Erik Språng <sprang@webrtc.org>
|
||||
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
|
||||
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#41580}
|
||||
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/338640
|
||||
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
|
||||
Commit-Queue: Erik Språng <sprang@webrtc.org>
|
||||
Cr-Commit-Position: refs/branch-heads/6167@{#6}
|
||||
Cr-Branched-From: ece5cb83715dea85617114b6d4e981fdee2623ba-refs/heads/main@{#41315}
|
||||
|
||||
diff --git a/modules/rtp_rtcp/source/rtp_format_vp9.cc b/modules/rtp_rtcp/source/rtp_format_vp9.cc
|
||||
index 15e059e85c8968c8ed72efa6b17ac998b5597f45..9ad4aa97c34aabe761739045662adc6374e3dc69 100644
|
||||
--- a/modules/rtp_rtcp/source/rtp_format_vp9.cc
|
||||
+++ b/modules/rtp_rtcp/source/rtp_format_vp9.cc
|
||||
@@ -94,8 +94,8 @@ size_t RefIndicesLength(const RTPVideoHeaderVP9& hdr) {
|
||||
if (!hdr.inter_pic_predicted || !hdr.flexible_mode)
|
||||
return 0;
|
||||
|
||||
- RTC_DCHECK_GT(hdr.num_ref_pics, 0U);
|
||||
- RTC_DCHECK_LE(hdr.num_ref_pics, kMaxVp9RefPics);
|
||||
+ RTC_CHECK_GT(hdr.num_ref_pics, 0U);
|
||||
+ RTC_CHECK_LE(hdr.num_ref_pics, kMaxVp9RefPics);
|
||||
return hdr.num_ref_pics;
|
||||
}
|
||||
|
||||
@@ -123,9 +123,9 @@ size_t SsDataLength(const RTPVideoHeaderVP9& hdr) {
|
||||
if (!hdr.ss_data_available)
|
||||
return 0;
|
||||
|
||||
- RTC_DCHECK_GT(hdr.num_spatial_layers, 0U);
|
||||
- RTC_DCHECK_LE(hdr.num_spatial_layers, kMaxVp9NumberOfSpatialLayers);
|
||||
- RTC_DCHECK_LE(hdr.gof.num_frames_in_gof, kMaxVp9FramesInGof);
|
||||
+ RTC_CHECK_GT(hdr.num_spatial_layers, 0U);
|
||||
+ RTC_CHECK_LE(hdr.num_spatial_layers, kMaxVp9NumberOfSpatialLayers);
|
||||
+ RTC_CHECK_LE(hdr.gof.num_frames_in_gof, kMaxVp9FramesInGof);
|
||||
size_t length = 1; // V
|
||||
if (hdr.spatial_layer_resolution_present) {
|
||||
length += 4 * hdr.num_spatial_layers; // Y
|
||||
@@ -136,7 +136,7 @@ size_t SsDataLength(const RTPVideoHeaderVP9& hdr) {
|
||||
// N_G
|
||||
length += hdr.gof.num_frames_in_gof; // T, U, R
|
||||
for (size_t i = 0; i < hdr.gof.num_frames_in_gof; ++i) {
|
||||
- RTC_DCHECK_LE(hdr.gof.num_ref_pics[i], kMaxVp9RefPics);
|
||||
+ RTC_CHECK_LE(hdr.gof.num_ref_pics[i], kMaxVp9RefPics);
|
||||
length += hdr.gof.num_ref_pics[i]; // R times
|
||||
}
|
||||
return length;
|
||||
@@ -248,9 +248,9 @@ bool WriteRefIndices(const RTPVideoHeaderVP9& vp9,
|
||||
// +-+-+-+-+-+-+-+-+ -| -|
|
||||
//
|
||||
bool WriteSsData(const RTPVideoHeaderVP9& vp9, rtc::BitBufferWriter* writer) {
|
||||
- RTC_DCHECK_GT(vp9.num_spatial_layers, 0U);
|
||||
- RTC_DCHECK_LE(vp9.num_spatial_layers, kMaxVp9NumberOfSpatialLayers);
|
||||
- RTC_DCHECK_LE(vp9.gof.num_frames_in_gof, kMaxVp9FramesInGof);
|
||||
+ RTC_CHECK_GT(vp9.num_spatial_layers, 0U);
|
||||
+ RTC_CHECK_LE(vp9.num_spatial_layers, kMaxVp9NumberOfSpatialLayers);
|
||||
+ RTC_CHECK_LE(vp9.gof.num_frames_in_gof, kMaxVp9FramesInGof);
|
||||
bool g_bit = vp9.gof.num_frames_in_gof > 0;
|
||||
|
||||
RETURN_FALSE_ON_ERROR(writer->WriteBits(vp9.num_spatial_layers - 1, 3));
|
||||
@@ -288,6 +288,8 @@ bool WriteSsData(const RTPVideoHeaderVP9& vp9, rtc::BitBufferWriter* writer) {
|
||||
// current API to invoke SVC is not flexible enough.
|
||||
RTPVideoHeaderVP9 RemoveInactiveSpatialLayers(
|
||||
const RTPVideoHeaderVP9& original_header) {
|
||||
+ RTC_CHECK_LE(original_header.num_spatial_layers,
|
||||
+ kMaxVp9NumberOfSpatialLayers);
|
||||
RTPVideoHeaderVP9 hdr(original_header);
|
||||
if (original_header.first_active_layer == 0)
|
||||
return hdr;
|
||||
@@ -314,7 +316,7 @@ RtpPacketizerVp9::RtpPacketizerVp9(rtc::ArrayView<const uint8_t> payload,
|
||||
header_size_(PayloadDescriptorLengthMinusSsData(hdr_)),
|
||||
first_packet_extra_header_size_(SsDataLength(hdr_)),
|
||||
remaining_payload_(payload) {
|
||||
- RTC_DCHECK_EQ(hdr_.first_active_layer, 0);
|
||||
+ RTC_CHECK_EQ(hdr_.first_active_layer, 0);
|
||||
|
||||
limits.max_payload_len -= header_size_;
|
||||
limits.first_packet_reduction_len += first_packet_extra_header_size_;
|
||||
@@ -357,8 +359,8 @@ bool RtpPacketizerVp9::NextPacket(RtpPacketToSend* packet) {
|
||||
|
||||
// Ensure end_of_picture is always set on top spatial layer when it is not
|
||||
// dropped.
|
||||
- RTC_DCHECK(hdr_.spatial_idx < hdr_.num_spatial_layers - 1 ||
|
||||
- hdr_.end_of_picture);
|
||||
+ RTC_CHECK(hdr_.spatial_idx < hdr_.num_spatial_layers - 1 ||
|
||||
+ hdr_.end_of_picture);
|
||||
|
||||
packet->SetMarker(layer_end && hdr_.end_of_picture);
|
||||
return true;
|
||||
@@ -82,6 +82,23 @@ void ExitIfContainsDisallowedFlags(const std::vector<std::string>& argv) {
|
||||
}
|
||||
}
|
||||
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
// A list of node envs that may be used to inject scripts.
|
||||
const char* kHijackableEnvs[] = {"NODE_OPTIONS", "NODE_REPL_EXTERNAL_MODULE"};
|
||||
|
||||
// Return true if there is any env in kHijackableEnvs.
|
||||
bool UnsetHijackableEnvs(base::Environment* env) {
|
||||
bool has = false;
|
||||
for (const char* name : kHijackableEnvs) {
|
||||
if (env->HasVar(name)) {
|
||||
env->UnSetVar(name);
|
||||
has = true;
|
||||
}
|
||||
}
|
||||
return has;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if IS_MAS_BUILD()
|
||||
void SetCrashKeyStub(const std::string& key, const std::string& value) {}
|
||||
void ClearCrashKeyStub(const std::string& key) {}
|
||||
@@ -123,8 +140,8 @@ int NodeMain(int argc, char* argv[]) {
|
||||
// NODE_OPTIONS: "--require 'bad.js'"}})
|
||||
// To prevent Electron apps from being used to work around macOS security
|
||||
// restrictions, when the parent process is not part of the app bundle, all
|
||||
// environment variables starting with NODE_ will be removed.
|
||||
if (util::UnsetAllNodeEnvs()) {
|
||||
// environment variables that may be used to inject scripts are removed.
|
||||
if (UnsetHijackableEnvs(os_env.get())) {
|
||||
LOG(ERROR) << "Node.js environment variables are disabled because this "
|
||||
"process is invoked by other apps.";
|
||||
}
|
||||
|
||||
@@ -28,12 +28,6 @@ v8::MaybeLocal<v8::Value> CompileAndCall(
|
||||
std::vector<v8::Local<v8::Value>>* arguments,
|
||||
node::Environment* optional_env);
|
||||
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
// Unset all environment variables that start with NODE_. Return false if there
|
||||
// is no node env at all.
|
||||
bool UnsetAllNodeEnvs();
|
||||
#endif
|
||||
|
||||
} // namespace electron::util
|
||||
|
||||
#endif // ELECTRON_SHELL_COMMON_NODE_UTIL_H_
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
// Copyright (c) 2023 Microsoft, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "shell/common/node_util.h"
|
||||
|
||||
#include <Foundation/Foundation.h>
|
||||
|
||||
namespace electron::util {
|
||||
|
||||
bool UnsetAllNodeEnvs() {
|
||||
bool has_unset = false;
|
||||
for (NSString* env in NSProcessInfo.processInfo.environment) {
|
||||
if (![env hasPrefix:@"NODE_"])
|
||||
continue;
|
||||
const char* name = [[env componentsSeparatedByString:@"="][0] UTF8String];
|
||||
unsetenv(name);
|
||||
has_unset = true;
|
||||
}
|
||||
return has_unset;
|
||||
}
|
||||
|
||||
} // namespace electron::util
|
||||
@@ -5,7 +5,6 @@ import * as Busboy from 'busboy';
|
||||
import * as path from 'path';
|
||||
import { ifdescribe, ifit, defer, startRemoteControlApp, repeatedly, listen } from './lib/spec-helpers';
|
||||
import { app } from 'electron/main';
|
||||
import { crashReporter } from 'electron/common';
|
||||
import { EventEmitter } from 'events';
|
||||
import * as fs from 'fs';
|
||||
import * as uuid from 'uuid';
|
||||
@@ -583,16 +582,20 @@ ifdescribe(!isLinuxOnArm && !process.mas && !process.env.DISABLE_CRASH_REPORTER_
|
||||
});
|
||||
|
||||
describe('start() option validation', () => {
|
||||
it('requires that the submitURL option be specified', () => {
|
||||
expect(() => {
|
||||
it('requires that the submitURL option be specified', async () => {
|
||||
const { remotely } = await startRemoteControlApp();
|
||||
await expect(remotely(() => {
|
||||
const { crashReporter } = require('electron');
|
||||
crashReporter.start({} as any);
|
||||
}).to.throw('submitURL must be specified when uploadToServer is true');
|
||||
})).to.be.rejectedWith('submitURL must be specified when uploadToServer is true');
|
||||
});
|
||||
|
||||
it('allows the submitURL option to be omitted when uploadToServer is false', () => {
|
||||
expect(() => {
|
||||
it('allows the submitURL option to be omitted when uploadToServer is false', async () => {
|
||||
const { remotely } = await startRemoteControlApp();
|
||||
await expect(remotely(() => {
|
||||
const { crashReporter } = require('electron');
|
||||
crashReporter.start({ uploadToServer: false } as any);
|
||||
}).not.to.throw();
|
||||
})).to.be.fulfilled();
|
||||
});
|
||||
|
||||
it('can be called twice', async () => {
|
||||
|
||||
@@ -9,6 +9,7 @@ import { setImmediate } from 'timers/promises';
|
||||
|
||||
const fixturesPath = path.resolve(__dirname, 'fixtures', 'api', 'utility-process');
|
||||
const isWindowsOnArm = process.platform === 'win32' && process.arch === 'arm64';
|
||||
const isWindows32Bit = process.platform === 'win32' && process.arch === 'ia32';
|
||||
|
||||
describe('utilityProcess module', () => {
|
||||
describe('UtilityProcess constructor', () => {
|
||||
@@ -57,14 +58,14 @@ describe('utilityProcess module', () => {
|
||||
expect(code).to.equal(0);
|
||||
});
|
||||
|
||||
it('emits \'exit\' when child process crashes', async () => {
|
||||
ifit(!isWindows32Bit)('emits \'exit\' when child process crashes', async () => {
|
||||
const child = utilityProcess.fork(path.join(fixturesPath, 'crash.js'));
|
||||
// Do not check for exit code in this case,
|
||||
// SIGSEGV code can be 139 or 11 across our different CI pipeline.
|
||||
await once(child, 'exit');
|
||||
});
|
||||
|
||||
it('emits \'exit\' corresponding to the child process', async () => {
|
||||
ifit(!isWindows32Bit)('emits \'exit\' corresponding to the child process', async () => {
|
||||
const child1 = utilityProcess.fork(path.join(fixturesPath, 'endless.js'));
|
||||
await once(child1, 'spawn');
|
||||
const child2 = utilityProcess.fork(path.join(fixturesPath, 'crash.js'));
|
||||
@@ -88,7 +89,7 @@ describe('utilityProcess module', () => {
|
||||
});
|
||||
|
||||
describe('app \'child-process-gone\' event', () => {
|
||||
it('with default serviceName', async () => {
|
||||
ifit(!isWindows32Bit)('with default serviceName', async () => {
|
||||
utilityProcess.fork(path.join(fixturesPath, 'crash.js'));
|
||||
const [, details] = await once(app, 'child-process-gone') as [any, Electron.Details];
|
||||
expect(details.type).to.equal('Utility');
|
||||
@@ -97,7 +98,7 @@ describe('utilityProcess module', () => {
|
||||
expect(details.reason).to.be.oneOf(['crashed', 'abnormal-exit']);
|
||||
});
|
||||
|
||||
it('with custom serviceName', async () => {
|
||||
ifit(!isWindows32Bit)('with custom serviceName', async () => {
|
||||
utilityProcess.fork(path.join(fixturesPath, 'crash.js'), [], { serviceName: 'Hello World!' });
|
||||
const [, details] = await once(app, 'child-process-gone') as [any, Electron.Details];
|
||||
expect(details.type).to.equal('Utility');
|
||||
|
||||
@@ -29,13 +29,19 @@ export const closeWindow = async (
|
||||
await ensureWindowIsClosed(window);
|
||||
|
||||
if (assertNotWindows) {
|
||||
const windows = BrowserWindow.getAllWindows();
|
||||
try {
|
||||
expect(windows).to.have.lengthOf(0);
|
||||
} finally {
|
||||
for (const win of windows) {
|
||||
await ensureWindowIsClosed(win);
|
||||
}
|
||||
let windows = BrowserWindow.getAllWindows();
|
||||
if (windows.length > 0) {
|
||||
setTimeout(async () => {
|
||||
// Wait until next tick to assert that all windows have been closed.
|
||||
windows = BrowserWindow.getAllWindows();
|
||||
try {
|
||||
expect(windows).to.have.lengthOf(0);
|
||||
} finally {
|
||||
for (const win of windows) {
|
||||
await ensureWindowIsClosed(win);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -929,16 +929,23 @@ describe('node feature', () => {
|
||||
});
|
||||
|
||||
it('performs microtask checkpoint correctly', (done) => {
|
||||
let timer : NodeJS.Timeout;
|
||||
const listener = () => {
|
||||
done(new Error('catch block is delayed to next tick'));
|
||||
};
|
||||
|
||||
const f3 = async () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
timer = setTimeout(listener);
|
||||
reject(new Error('oops'));
|
||||
});
|
||||
};
|
||||
|
||||
process.once('unhandledRejection', () => done('catch block is delayed to next tick'));
|
||||
|
||||
setTimeout(() => {
|
||||
f3().catch(() => done());
|
||||
f3().catch(() => {
|
||||
clearTimeout(timer);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user