Browse Source

chore: cherry-pick 2 changes from Release-0-M121 (#41107)

* chore: [26-x-y] cherry-pick 2 changes from Release-0-M121

* cc07a95bc309 from chromium

* test: fixup assertNotWindows (#41045)

* chore: fixup assertNotWindows

* remove logging

(cherry picked from commit 3dafb318a864b76fbe6412e00965af867da05b25)

* chore: cleanup global reject handler leaking into tests (#40689)

(cherry picked from commit 3a510a26d0ecea026f8f142ae69307064cd59b6d)

---------

Co-authored-by: John Kleinschmidt <[email protected]>
Co-authored-by: Robo <[email protected]>
Pedro Pontes 1 year ago
parent
commit
0ebe40354e

+ 2 - 0
patches/chromium/.patches

@@ -156,3 +156,5 @@ 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

+ 150 - 0
patches/chromium/cherry-pick-cc07a95bc309.patch

@@ -0,0 +1,150 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Hongchan Choi <[email protected]>
+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 <[email protected]>
+Commit-Queue: Hongchan Choi <[email protected]>
+Cr-Original-Commit-Position: refs/heads/main@{#1246718}
+Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5214669
+Auto-Submit: Hongchan Choi <[email protected]>
+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.
++

+ 55 - 0
patches/chromium/safely_crash_on_dangling_profile.patch

@@ -0,0 +1,55 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Bo Liu <[email protected]>
+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 <[email protected]>
+Commit-Queue: Bo Liu <[email protected]>
+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();
++      }
+     }
+   }
+ 

+ 13 - 7
spec/lib/window-helpers.ts

@@ -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);
+          }
+        }
+      });
     }
   }
 };

+ 10 - 3
spec/node-spec.ts

@@ -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();
+      });
     });
   });
 });