Skip to content

Commit

Permalink
[UnifiedPDF] Handle PDF annotations actions that reset form fields.
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=269122
rdar://problem/122680796

Reviewed by Tim Horton.

A certain type of PDF annotation action can reset various fields on a
form. PDFKit represents this type of action as a PDFKitActionResetForm.

Basically what we will do is check to see if an annotation has an action
associated with it and will handle it if it does. This first patch
supports the reset form action and will check to see if the action is
of that type when handling it. If it is, we will call into the
appropriate PDFKit SPI which will do the actual work for us.

Also, the PDF specification says that an action is composed of a type,
which specifies the type of action that it is, and a list of subsequent
actions that are supposed to be performed. So we need to handle this
scenario also by:
1.) Performing the action
2.) Store the subsequent actions on a stack in reverse order (so that
the first action is at the top of the stack).
We keep handling the action at the top of the stack until it is empty.

* Source/WebKit/Platform/spi/Cocoa/PDFKitSPI.h:
* Source/WebKit/Shared/Cocoa/PDFKitSoftLink.h:
* Source/WebKit/Shared/Cocoa/PDFKitSoftLink.mm:
* Source/WebKit/WebProcess/Plugins/PDF/UnifiedPDF/UnifiedPDFPlugin.h:
* Source/WebKit/WebProcess/Plugins/PDF/UnifiedPDF/UnifiedPDFPlugin.mm:
(WebKit::UnifiedPDFPlugin::handleMouseEvent):
(WebKit::UnifiedPDFPlugin::handlePDFActionForAnnotation):

Canonical link: https://commits.webkit.org/274546@main
  • Loading branch information
sammygill committed Feb 13, 2024
1 parent 245919a commit 5d64ca8
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 0 deletions.
9 changes: 9 additions & 0 deletions Source/WebKit/Platform/spi/Cocoa/PDFKitSPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,15 @@
#import <PDFKit/PDFHostViewController.h>
#endif // PLATFORM(IOS_FAMILY)

#import <PDFKit/PDFDocumentPriv.h>
#import <PDFKit/PDFSelectionPriv.h>
#if __has_include(<PDFKit/PDFActionPriv.h>)
#import <PDFKit/PDFActionPriv.h>
#else
@interface PDFAction(SPI)
- (NSArray *) nextActions;
@end
#endif // __has_include(PDFKIT/PDFActionPriv.h)

#endif // HAVE(PDFKIT)

Expand Down Expand Up @@ -97,6 +105,7 @@
@interface PDFDocument ()
-(instancetype)initWithProvider:(CGDataProviderRef)dataProvider;
-(void)preloadDataOfPagesInRange:(NSRange)range onQueue:(dispatch_queue_t)queue completion:(void (^)(NSIndexSet* loadedPageIndexes))completionBlock;
-(void)resetFormFields:(PDFActionResetForm *) action;
@property (readwrite, nonatomic) BOOL hasHighLatencyDataProvider;
@end
#endif // HAVE(INCREMENTAL_PDF_APIS)
Expand Down
1 change: 1 addition & 0 deletions Source/WebKit/Shared/Cocoa/PDFKitSoftLink.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
SOFT_LINK_FRAMEWORK_FOR_HEADER(WebKit, PDFKit)

ALLOW_DEPRECATED_DECLARATIONS_BEGIN
SOFT_LINK_CLASS_FOR_HEADER(WebKit, PDFActionResetForm)
SOFT_LINK_CLASS_FOR_HEADER(WebKit, PDFAnnotationButtonWidget)
SOFT_LINK_CLASS_FOR_HEADER(WebKit, PDFAnnotationChoiceWidget)
SOFT_LINK_CLASS_FOR_HEADER(WebKit, PDFAnnotationLink)
Expand Down
1 change: 1 addition & 0 deletions Source/WebKit/Shared/Cocoa/PDFKitSoftLink.mm
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
SOFT_LINK_FRAMEWORK_FOR_SOURCE(WebKit, PDFKit)

ALLOW_DEPRECATED_DECLARATIONS_BEGIN
SOFT_LINK_CLASS_FOR_SOURCE(WebKit, PDFKit, PDFActionResetForm)
SOFT_LINK_CLASS_FOR_SOURCE(WebKit, PDFKit, PDFAnnotationButtonWidget)
SOFT_LINK_CLASS_FOR_SOURCE(WebKit, PDFKit, PDFAnnotationChoiceWidget)
SOFT_LINK_CLASS_FOR_SOURCE(WebKit, PDFKit, PDFAnnotationLink)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <WebCore/GraphicsLayer.h>
#include <wtf/OptionSet.h>

OBJC_CLASS PDFAction;
OBJC_CLASS PDFDestination;
OBJC_CLASS WKPDFFormMutationObserver;

Expand Down Expand Up @@ -90,6 +91,7 @@ class UnifiedPDFPlugin final : public PDFPluginBase, public WebCore::GraphicsLay
void focusPreviousAnnotation() final;
#if PLATFORM(MAC)
RetainPtr<PDFAnnotation> nextTextAnnotation(AnnotationSearchDirection) const;
void handlePDFActionForAnnotation(PDFAnnotation *);
#endif

void attemptToUnlockPDF(const String& password) final;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1358,6 +1358,10 @@ static bool isContextMenuEvent(const WebMouseEvent& event)
if (annotationIsLinkWithDestination(trackedAnnotation.get()))
followLinkAnnotation(trackedAnnotation.get());

#if PLATFORM(MAC)
if (RetainPtr pdfAction = [trackedAnnotation action])
handlePDFActionForAnnotation(trackedAnnotation.get());
#endif
updateLayerHierarchy();
}

Expand Down Expand Up @@ -2045,6 +2049,41 @@ static IntRect computeMarqueeSelectionRect(const WebCore::IntPoint& point1, cons
#endif
}

#if PLATFORM(MAC)
void UnifiedPDFPlugin::handlePDFActionForAnnotation(PDFAnnotation *annotation)
{
if (!annotation)
return;
RetainPtr firstAction = [annotation action];
ASSERT(firstAction);
if (!firstAction)
return;

using PDFActionList = Vector<RetainPtr<PDFAction>>;
auto performPDFAction = [this](PDFAction *action) {
if (!action)
return;
if ([action isKindOfClass:getPDFActionResetFormClass()] && [m_pdfDocument respondsToSelector:@selector(resetFormFields:)])
[m_pdfDocument resetFormFields:static_cast<PDFActionResetForm *>(action)];
};

PDFActionList actionsForAnnotation;
actionsForAnnotation.append(firstAction);
while (!actionsForAnnotation.isEmpty()) {
RetainPtr currentAction = actionsForAnnotation.takeLast().get();
performPDFAction(currentAction.get());

if ([currentAction respondsToSelector:@selector(nextActions)]) {
RetainPtr reversedNextActions = [[currentAction nextActions] reverseObjectEnumerator];
while (RetainPtr nextAction = [reversedNextActions nextObject]) {
actionsForAnnotation.append(WTFMove(nextAction));
nextAction = [reversedNextActions nextObject];
}
}
}
}
#endif

void AnnotationTrackingState::startAnnotationTracking(RetainPtr<PDFAnnotation>&& annotation, WebEventType mouseEventType, WebMouseEventButton mouseEventButton)
{
ASSERT(!m_trackedAnnotation);
Expand Down

0 comments on commit 5d64ca8

Please sign in to comment.