Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: 8f4821e1ffd59699e422945d202686753d57ea37
      
https://github.com/WebKit/WebKit/commit/8f4821e1ffd59699e422945d202686753d57ea37
  Author: Abrar Rahman Protyasha <[email protected]>
  Date:   2026-02-25 (Wed, 25 Feb 2026)

  Changed paths:
    M Source/WebCore/loader/NetscapePlugInStreamLoader.cpp
    M Source/WebKit/WebProcess/Plugins/PluginView.cpp

  Log Message:
  -----------
  pdf/pdf-plugin-printing.html is flakily crashing, ASSERTION FAILED: 
m_plugInStreamLoaders.contains(&loader)
https://bugs.webkit.org/show_bug.cgi?id=308583
rdar://171111801

Reviewed by Wenson Hsieh.

When PDFPluginBase::tryRunScriptsInPDFDocument() triggers window.print(),
WebChromeClient::print() sends a sync PrintFrame message to the UI process.
The UI process responds with BeginPrintingDuringDOMPrintOperation, which is
dispatched re-entrantly during waitForSyncReply. This re-entrant message
triggers layout via updateLayout(), which can destroy the PluginView through
WidgetHierarchyUpdatesSuspensionScope::moveWidgets().

When the PluginView is destroyed, its stream is cancelled, which calls
NetscapePlugInStreamLoader::notifyDone() to remove the loader from
DocumentLoader::m_plugInStreamLoaders. But when the re-entrant unwind
completes and control returns to Stream::didFinishLoading (still on the
stack), it calls notifyDone() again, hitting the assertion that the loader
is still in m_plugInStreamLoaders. It also dereferences m_pluginView, which
is a WeakPtr that has been nulled by the PluginView's destruction.

In this patch, we fix both issues:

1. In NetscapePlugInStreamLoader::notifyDone(), reset m_isInitialized
   before removing from m_plugInStreamLoaders, so a next call is a no-op.

2. In PluginView::Stream::didFail() and didFinishLoading(), hold on to
   the PluginView object in a local RefPtr and clear out m_pluginView.
   This serves two purposes: nulling m_pluginView early ensures that if
   the callback triggers re-entrant destruction of the Stream, the
   ASSERT(!m_pluginView) in ~Stream() holds; and capturing the result
   into a RefPtr keeps the PluginView alive across the callback, so the
   cleanup afterward operates on a valid object.

* Source/WebCore/loader/NetscapePlugInStreamLoader.cpp:
(WebCore::NetscapePlugInStreamLoader::notifyDone):
* Source/WebKit/WebProcess/Plugins/PluginView.cpp:
(WebKit::PluginView::Stream::didFail):
(WebKit::PluginView::Stream::didFinishLoading):

Canonical link: https://commits.webkit.org/308242@main



To unsubscribe from these emails, change your notification settings at 
https://github.com/WebKit/WebKit/settings/notifications

Reply via email to