Modified: trunk/Source/WebKit/ChangeLog (257963 => 257964)
--- trunk/Source/WebKit/ChangeLog 2020-03-06 02:37:45 UTC (rev 257963)
+++ trunk/Source/WebKit/ChangeLog 2020-03-06 03:00:01 UTC (rev 257964)
@@ -1,3 +1,18 @@
+2020-03-05 Brady Eidson <beid...@apple.com>
+
+ Pre-fetch first page in new PDF loading model.
+ https://bugs.webkit.org/show_bug.cgi?id=208669
+
+ Reviewed by Alex Christensen.
+
+ Also add some logging.
+
+ * Platform/Logging.h:
+ * WebProcess/Plugins/PDF/PDFPlugin.mm:
+ (WebKit::dataProviderGetBytesAtPositionCallback):
+ (WebKit::dataProviderGetByteRangesCallback):
+ (WebKit::PDFPlugin::threadEntry):
+
2020-03-05 Alex Christensen <achristen...@webkit.org>
Add WKNavigationDelegatePrivate SPI to inform application of subframe navigations
Modified: trunk/Source/WebKit/Platform/Logging.h (257963 => 257964)
--- trunk/Source/WebKit/Platform/Logging.h 2020-03-06 02:37:45 UTC (rev 257963)
+++ trunk/Source/WebKit/Platform/Logging.h 2020-03-06 03:00:01 UTC (rev 257964)
@@ -71,6 +71,7 @@
M(NetworkCacheStorage) \
M(NetworkScheduling) \
M(NetworkSession) \
+ M(PDF) \
M(PerformanceLogging) \
M(Plugins) \
M(Printing) \
Modified: trunk/Source/WebKit/WebProcess/Plugins/PDF/PDFPlugin.mm (257963 => 257964)
--- trunk/Source/WebKit/WebProcess/Plugins/PDF/PDFPlugin.mm 2020-03-06 02:37:45 UTC (rev 257963)
+++ trunk/Source/WebKit/WebProcess/Plugins/PDF/PDFPlugin.mm 2020-03-06 03:00:01 UTC (rev 257964)
@@ -30,6 +30,7 @@
#import "ArgumentCoders.h"
#import "DataReference.h"
+#import "Logging.h"
#import "PDFAnnotationTextWidgetDetails.h"
#import "PDFContextMenu.h"
#import "PDFLayerControllerSPI.h"
@@ -88,10 +89,13 @@
#import <pal/spi/mac/NSMenuSPI.h>
#import <wtf/UUID.h>
#import <wtf/WTFSemaphore.h>
+#import <wtf/WorkQueue.h>
+#import <wtf/text/TextStream.h>
#if HAVE(INCREMENTAL_PDF_APIS)
@interface PDFDocument ()
--(instancetype) initWithProvider:(CGDataProviderRef)dataProvider;
+-(instancetype)initWithProvider:(CGDataProviderRef)dataProvider;
+-(void)preloadDataOfPagesInRange:(NSRange)range onQueue:(dispatch_queue_t)queue completion:(void (^)(NSIndexSet* loadedPageIndexes))completionBlock;
@end
#endif
@@ -622,6 +626,7 @@
static size_t dataProviderGetBytesAtPositionCallback(void* info, void* buffer, off_t position, size_t count)
{
ASSERT(!isMainThread());
+ LOG(PDF, "PDF data provider requesting %lu bytes at position %llu", count, position);
Ref<PDFPlugin> plugin = *((PDFPlugin*)info);
WTF::Semaphore dataSemaphore { 0 };
@@ -644,11 +649,23 @@
{
ASSERT(!isMainThread());
+#ifndef NDEBUG
+ TextStream stream;
+ stream << "PDF data provider requesting " << count << " byte ranges (";
+ for (size_t i = 0; i < count; ++i) {
+ stream << ranges[i].length << " at " << ranges[i].location;
+ if (i < count - 1)
+ stream << ", ";
+ }
+ stream << ")";
+ LOG(PDF, "%s", stream.release().utf8().data());
+#endif
+
Ref<PDFPlugin> plugin = *((PDFPlugin*)info);
WTF::Semaphore dataSemaphore { 0 };
Vector<RetainPtr<CFDataRef>> dataResults(count);
- // FIXME: Once we support range requests, make a single request for all ranges instead of <count> individual requests.
+ // FIXME: Once we support multi-range requests, make a single request for all ranges instead of <count> individual requests.
RunLoop::main().dispatch([plugin = WTFMove(plugin), &dataResults, ranges, count, &dataSemaphore] {
for (size_t i = 0; i < count; ++i) {
plugin->getResourceBytesAtPosition(ranges[i].length, ranges[i].location, [i, &dataResults, &dataSemaphore](const uint8_t* bytes, size_t bytesCount) {
@@ -690,11 +707,21 @@
CGDataProviderSetProperty(dataProvider.get(), kCGDataProviderHasHighLatency, kCFBooleanTrue);
m_backgroundThreadDocument = adoptNS([[pdfDocumentClass() alloc] initWithProvider:dataProvider.get()]);
+ WTF::Semaphore firstPageSemaphore { 0 };
+ auto firstPageQueue = WorkQueue::create("PDF first page work queue");
+
+ [m_backgroundThreadDocument preloadDataOfPagesInRange:NSMakeRange(0, 1) onQueue:firstPageQueue->dispatchQueue() completion:[&firstPageSemaphore, this] (NSIndexSet *) mutable {
+ callOnMainThread([this] {
+ adoptBackgroundThreadDocument();
+ });
+ firstPageSemaphore.signal();
+ }];
+
+ firstPageSemaphore.wait();
+
// The main thread dispatch below removes the last reference to the PDF thread.
// It must be the last code executed in this function.
- callOnMainThread([this, protectedPlugin = WTFMove(protectedPlugin)] {
- adoptBackgroundThreadDocument();
- });
+ callOnMainThread([protectedPlugin = WTFMove(protectedPlugin)] { });
}
void PDFPlugin::unconditionalCompleteOutstandingRangeRequests()