Changeset 259760 in webkit
- Timestamp:
- Apr 8, 2020, 3:15:16 PM (6 years ago)
- Location:
- trunk/Source/WebKit
- Files:
-
- 3 edited
-
ChangeLog (modified) (1 diff)
-
WebProcess/Plugins/PDF/PDFPlugin.h (modified) (1 diff)
-
WebProcess/Plugins/PDF/PDFPlugin.mm (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebKit/ChangeLog
r259758 r259760 1 2020-04-08 Brady Eidson <beidson@apple.com> 2 3 Fix handling non-linearized PDFs when incremental PDF loading is enabled. 4 <rdar://problem/60619506> and https://bugs.webkit.org/show_bug.cgi?id=210208 5 6 Reviewed by Tim Horton (and I think Geoff Garen, probably. It's confusing.) 7 8 When we try to load a non-linearized PDF with PDFKit, it makes an outlandishly large range request 9 to try to verify the PDF file size. 10 11 That's covered by <rdar://problem/61473378> 12 13 Meanwhile we need to detect that and fallback to non-incremental PDF loading. 14 15 * WebProcess/Plugins/PDF/PDFPlugin.h: 16 * WebProcess/Plugins/PDF/PDFPlugin.mm: 17 (WebKit::PDFPlugin::receivedInvalidRangeRequest): 18 (WebKit::dataProviderGetBytesAtPositionCallback): 19 (WebKit::PDFPlugin::threadEntry): 20 (WebKit::PDFPlugin::installPDFDocument): 21 1 22 2020-04-08 Per Arne Vollan <pvollan@apple.com> 2 23 -
trunk/Source/WebKit/WebProcess/Plugins/PDF/PDFPlugin.h
r259597 r259760 136 136 void getResourceBytesAtPosition(size_t count, off_t position, CompletionHandler<void(const uint8_t*, size_t count)>&&); 137 137 size_t getResourceBytesAtPositionMainThread(void* buffer, off_t position, size_t count); 138 void receivedNonLinearizedPDFSentinel(); 139 bool incrementalPDFLoadingEnabled() const { return m_incrementalPDFLoadingEnabled; } 138 140 #ifndef NDEBUG 139 141 void pdfLog(const String& event); -
trunk/Source/WebKit/WebProcess/Plugins/PDF/PDFPlugin.mm
r259597 r259760 91 91 #import <pal/spi/mac/NSMenuSPI.h> 92 92 #import <wtf/HexNumber.h> 93 #import <wtf/Scope.h> 93 94 #import <wtf/UUID.h> 94 95 #import <wtf/WTFSemaphore.h> … … 137 138 static const int defaultScrollMagnitudeThresholdForPageFlip = 20; 138 139 140 // <rdar://problem/61473378> - PDFKit asks for a "way too large" range when the PDF it is loading 141 // incrementally turns out to be non-linearized. 142 // We'll assume any size over 4gb is PDFKit noticing non-linearized data. 143 static const uint32_t nonLinearizedPDFSentinel = std::numeric_limits<uint32_t>::max(); 144 139 145 @interface WKPDFPluginAccessibilityObject : NSObject { 140 146 PDFLayerController *_pdfLayerController; … … 694 700 #endif // !LOG_DISABLED 695 701 702 void PDFPlugin::receivedNonLinearizedPDFSentinel() 703 { 704 m_incrementalPDFLoadingEnabled = false; 705 706 if (!isMainThread()) { 707 #if !LOG_DISABLED 708 pdfLog("Disabling incremental PDF loading on background thread"); 709 #endif 710 callOnMainThread([this, protectedThis = makeRef(*this)] { 711 receivedNonLinearizedPDFSentinel(); 712 }); 713 return; 714 } 715 716 #if !LOG_DISABLED 717 pdfLog(makeString("Cancelling all ", m_streamLoaderMap.size(), " range request loaders")); 718 #endif 719 720 for (auto iterator = m_streamLoaderMap.begin(); iterator != m_streamLoaderMap.end(); iterator = m_streamLoaderMap.begin()) { 721 m_outstandingByteRangeRequests.remove(iterator->value); 722 cancelAndForgetLoader(*iterator->key); 723 } 724 725 if (!m_documentFinishedLoading || m_pdfDocument) 726 return; 727 728 m_pdfDocument = adoptNS([[pdfDocumentClass() alloc] initWithData:rawData()]); 729 installPDFDocument(); 730 tryRunScriptsInPDFDocument(); 731 } 732 696 733 static size_t dataProviderGetBytesAtPositionCallback(void* info, void* buffer, off_t position, size_t count) 697 734 { 735 Ref<PDFPlugin> plugin = *((PDFPlugin*)info); 736 698 737 if (isMainThread()) { 699 738 #if !LOG_DISABLED 700 ((PDFPlugin*)info)->pdfLog(makeString("Handling request for ", count, " bytes at position ", position, " synchronously on the main thread"));739 plugin->pdfLog(makeString("Handling request for ", count, " bytes at position ", position, " synchronously on the main thread")); 701 740 #endif 702 return ((PDFPlugin*)info)->getResourceBytesAtPositionMainThread(buffer, position, count); 703 } 741 return plugin->getResourceBytesAtPositionMainThread(buffer, position, count); 742 } 743 744 // It's possible we previously encountered an invalid range and therefore disabled incremental loading, 745 // but PDFDocument is still trying to read data using a different strategy. 746 // Always ignore such requests. 747 if (!plugin->incrementalPDFLoadingEnabled()) 748 return 0; 704 749 705 750 #if !LOG_DISABLED 706 Ref<PDFPlugin> debugPluginRef = *((PDFPlugin*)info);751 auto debugPluginRef = plugin.copyRef(); 707 752 debugPluginRef->incrementThreadsWaitingOnCallback(); 708 753 debugPluginRef->pdfLog(makeString("PDF data provider requesting ", count, " bytes at position ", position)); 709 754 #endif 710 755 711 Ref<PDFPlugin> plugin = *((PDFPlugin*)info); 756 if (position > nonLinearizedPDFSentinel) { 757 #if !LOG_DISABLED 758 plugin->pdfLog(makeString("Received invalid range request for ", count, " bytes at position ", position, ". PDF is probably not linearized. Falling back to non-incremental loading.")); 759 #endif 760 plugin->receivedNonLinearizedPDFSentinel(); 761 return 0; 762 } 763 712 764 WTF::Semaphore dataSemaphore { 0 }; 713 765 size_t bytesProvided = 0; … … 803 855 }; 804 856 857 auto scopeExit = makeScopeExit([protectedPlugin = WTFMove(protectedPlugin)] () mutable { 858 // Keep the PDFPlugin alive until the end of this function and the end 859 // of the last main thread task submitted by this function. 860 callOnMainThread([protectedPlugin = WTFMove(protectedPlugin)] { }); 861 }); 862 805 863 // Balanced by a deref inside of the dataProviderReleaseInfoCallback 806 864 ref(); … … 810 868 m_backgroundThreadDocument = adoptNS([[pdfDocumentClass() alloc] initWithProvider:dataProvider.get()]); 811 869 870 if (!m_incrementalPDFLoadingEnabled) { 871 m_backgroundThreadDocument = nil; 872 return; 873 } 874 812 875 WTF::Semaphore firstPageSemaphore { 0 }; 813 876 auto firstPageQueue = WorkQueue::create("PDF first page work queue"); 814 877 815 878 [m_backgroundThreadDocument preloadDataOfPagesInRange:NSMakeRange(0, 1) onQueue:firstPageQueue->dispatchQueue() completion:[&firstPageSemaphore, this] (NSIndexSet *) mutable { 816 callOnMainThread([this] { 817 adoptBackgroundThreadDocument(); 818 }); 879 if (m_incrementalPDFLoadingEnabled) { 880 callOnMainThread([this] { 881 adoptBackgroundThreadDocument(); 882 }); 883 } else 884 m_backgroundThreadDocument = nil; 885 819 886 firstPageSemaphore.signal(); 820 887 }]; … … 825 892 pdfLog("Finished preloading first page"); 826 893 #endif 827 828 // The main thread dispatch below removes the last reference to the PDF thread.829 // It must be the last code executed in this function.830 callOnMainThread([protectedPlugin = WTFMove(protectedPlugin)] { });831 894 } 832 895 … … 1470 1533 ASSERT(m_pdfDocument); 1471 1534 ASSERT(isMainThread()); 1535 LOG(IncrementalPDF, "Installing PDF document"); 1472 1536 1473 1537 #if HAVE(INCREMENTAL_PDF_APIS)
Note:
See TracChangeset
for help on using the changeset viewer.