Modified: trunk/Source/WebKit/ChangeLog (258473 => 258474)
--- trunk/Source/WebKit/ChangeLog 2020-03-14 22:04:00 UTC (rev 258473)
+++ trunk/Source/WebKit/ChangeLog 2020-03-14 22:17:04 UTC (rev 258474)
@@ -1,3 +1,31 @@
+2020-03-14 Brady Eidson <[email protected]>
+
+ Gather PDF scripts to run on a background thread.
+ https://bugs.webkit.org/show_bug.cgi?id=209063
+
+ Reviewed by Geoff Garen.
+
+ In incremental loading mode, gathering document scripts will sometimes require PDFKit/CG
+ to lock and wait on data loads from our data provider.
+
+ So if we gather them on the main thread, we will hang the main thread and therefore deadlock
+ with our data provider thread/queue.
+
+ So let's gather those scripts on a background thread!
+
+ * WebProcess/Plugins/PDF/PDFPlugin.h:
+ * WebProcess/Plugins/PDF/PDFPlugin.mm:
+ (WebKit::PDFPlugin::threadEntry):
+ (WebKit::PDFPlugin::ByteRangeRequest::completeWithAccumulatedData):
+ (WebKit::PDFPlugin::documentDataDidFinishLoading):
+ (WebKit::PDFPlugin::installPDFDocument):
+ (WebKit::PDFPlugin::streamDidFinishLoading):
+ (WebKit::PDFPlugin::manualStreamDidFinishLoading):
+ (WebKit::PDFPlugin::tryRunScriptsInPDFDocument): Only actually gathers scripts to execute if there
+ is a m_pdfDocument and the entire document data finished loading.
+ (WebKit::PDFPlugin::pdfDocumentDidLoad): Deleted.
+ (WebKit::PDFPlugin::runScriptsInPDFDocument): Deleted.
+
2020-03-13 Alex Christensen <[email protected]>
WKWebView._negotiatedLegacyTLS should be correct after back/forward navigations
Modified: trunk/Source/WebKit/WebProcess/Plugins/PDF/PDFPlugin.h (258473 => 258474)
--- trunk/Source/WebKit/WebProcess/Plugins/PDF/PDFPlugin.h 2020-03-14 22:04:00 UTC (rev 258473)
+++ trunk/Source/WebKit/WebProcess/Plugins/PDF/PDFPlugin.h 2020-03-14 22:17:04 UTC (rev 258474)
@@ -247,11 +247,11 @@
void updateScrollbars();
Ref<WebCore::Scrollbar> createScrollbar(WebCore::ScrollbarOrientation);
void destroyScrollbar(WebCore::ScrollbarOrientation);
- void pdfDocumentDidLoad();
+ void documentDataDidFinishLoading();
void installPDFDocument();
void addArchiveResource();
void calculateSizes();
- void runScriptsInPDFDocument();
+ void tryRunScriptsInPDFDocument();
NSEvent *nsEventForWebMouseEvent(const WebMouseEvent&);
WebCore::IntPoint convertFromPluginToPDFView(const WebCore::IntPoint&) const;
Modified: trunk/Source/WebKit/WebProcess/Plugins/PDF/PDFPlugin.mm (258473 => 258474)
--- trunk/Source/WebKit/WebProcess/Plugins/PDF/PDFPlugin.mm 2020-03-14 22:04:00 UTC (rev 258473)
+++ trunk/Source/WebKit/WebProcess/Plugins/PDF/PDFPlugin.mm 2020-03-14 22:17:04 UTC (rev 258474)
@@ -806,7 +806,7 @@
firstPageSemaphore.wait();
#if !LOG_DISABLED
- pdfLog("Fininished preloading first page");
+ pdfLog("Finished preloading first page");
#endif
// The main thread dispatch below removes the last reference to the PDF thread.
@@ -923,7 +923,7 @@
#endif
m_completionHandler(m_accumulatedData.data(), m_accumulatedData.size());
-
+
if (m_streamLoader)
plugin.forgetLoader(*m_streamLoader);
@@ -1407,7 +1407,7 @@
m_data = PDFDocumentImage::convertPostScriptDataToPDF(WTFMove(m_data));
}
-void PDFPlugin::pdfDocumentDidLoad()
+void PDFPlugin::documentDataDidFinishLoading()
{
addArchiveResource();
@@ -1426,6 +1426,8 @@
m_pdfDocument = adoptNS([[pdfDocumentClass() alloc] initWithData:rawData()]);
installPDFDocument();
}
+
+ tryRunScriptsInPDFDocument();
}
void PDFPlugin::installPDFDocument()
@@ -1446,7 +1448,7 @@
calculateSizes();
updateScrollbars();
- runScriptsInPDFDocument();
+ tryRunScriptsInPDFDocument();
if ([m_pdfDocument isLocked])
createPasswordEntryForm();
@@ -1494,7 +1496,7 @@
ASSERT_UNUSED(streamID, streamID == pdfDocumentRequestID);
convertPostScriptDataIfNeeded();
- pdfDocumentDidLoad();
+ documentDataDidFinishLoading();
}
void PDFPlugin::streamDidFail(uint64_t streamID, bool wasCancelled)
@@ -1544,7 +1546,7 @@
void PDFPlugin::manualStreamDidFinishLoading()
{
convertPostScriptDataIfNeeded();
- pdfDocumentDidLoad();
+ documentDataDidFinishLoading();
}
void PDFPlugin::manualStreamDidFail(bool)
@@ -1556,19 +1558,43 @@
#endif
}
-void PDFPlugin::runScriptsInPDFDocument()
+void PDFPlugin::tryRunScriptsInPDFDocument()
{
- Vector<RetainPtr<CFStringRef>> scripts;
- getAllScriptsInPDFDocument([m_pdfDocument documentRef], scripts);
+ ASSERT(isMainThread());
- if (scripts.isEmpty())
+ if (!m_pdfDocument || !m_documentFinishedLoading)
return;
- JSGlobalContextRef ctx = JSGlobalContextCreate(0);
- JSObjectRef jsPDFDoc = makeJSPDFDoc(ctx);
- for (auto& script : scripts)
- JSEvaluateScript(ctx, OpaqueJSString::tryCreate(script.get()).get(), jsPDFDoc, nullptr, 0, nullptr);
- JSGlobalContextRelease(ctx);
+ auto completionHandler = [this, protectedThis = makeRef(*this)] (Vector<RetainPtr<CFStringRef>>&& scripts) mutable {
+ if (scripts.isEmpty())
+ return;
+
+ JSGlobalContextRef ctx = JSGlobalContextCreate(nullptr);
+ JSObjectRef jsPDFDoc = makeJSPDFDoc(ctx);
+ for (auto& script : scripts)
+ JSEvaluateScript(ctx, OpaqueJSString::tryCreate(script.get()).get(), jsPDFDoc, nullptr, 1, nullptr);
+ JSGlobalContextRelease(ctx);
+ };
+
+#if HAVE(INCREMENTAL_PDF_APIS)
+ auto scriptUtilityQueue = WorkQueue::create("PDF script utility");
+ auto& rawQueue = scriptUtilityQueue.get();
+ RetainPtr<CGPDFDocumentRef> document = [m_pdfDocument documentRef];
+ rawQueue.dispatch([scriptUtilityQueue = WTFMove(scriptUtilityQueue), completionHandler = WTFMove(completionHandler), document = WTFMove(document)] () mutable {
+ ASSERT(!isMainThread());
+
+ Vector<RetainPtr<CFStringRef>> scripts;
+ getAllScriptsInPDFDocument(document.get(), scripts);
+
+ callOnMainThread([completionHandler = WTFMove(completionHandler), scripts = WTFMove(scripts)] () mutable {
+ completionHandler(WTFMove(scripts));
+ });
+ });
+#else
+ Vector<RetainPtr<CFStringRef>> scripts;
+ getAllScriptsInPDFDocument([m_pdfDocument documentRef], scripts);
+ completionHandler(WTFMove(scripts));
+#endif
}
void PDFPlugin::createPasswordEntryForm()