Title: [258474] trunk/Source/WebKit
Revision
258474
Author
[email protected]
Date
2020-03-14 15:17:04 -0700 (Sat, 14 Mar 2020)

Log Message

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.

Modified Paths

Diff

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()
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to