NEW 199793
WKWebView PDF viewer doesn't respect selection and callout preferences
https://bugs.webkit.org/show_bug.cgi?id=199793
Summary WKWebView PDF viewer doesn't respect selection and callout preferences
Josip
Reported 2019-07-15 01:17:12 PDT
I am trying to disable Copy callout on `WKWebView` for all document types. Try 1 (JavaScript): WebKit built in PDF viewer doesn't respect selection and callout preferences set on `WKWebView`. Executing this JS `document.documentElement.style.webkitUserSelect='none';` in web view that contains PDF doesn't do anything it seems. This works well for any other document type as far as I can tell. Try 2 (responder chain) Subclassing `WKWebView` and overriding `canPerformAction` doesn't help either. It seems that this is being called for some actions but not Copy. My guess is that some object deeper in hierarchy (maybe `PDFHostViewController`?) overrides this method and allows Copy action. All I can think of is to play with private view hierarchies and swizzle this method to hook in behaviour that I need. Are there any other workarounds? Since PDF preview is transparent for `WKWebView` users I feel both of these approaches should work out of the box? I am seeing the same behaviour on macOS and iOS.
Attachments
Josip
Comment 1 2019-07-15 03:47:51 PDT
I disassembled `PDFHostViewController` and it seems that assumption was correct: ``` /* @class PDFHostViewController */ -(bool)canPerformAction:(void *)arg2 withSender:(void *)arg3 { rax = (@selector(selectAll:) == arg2 ? 0x1 : 0x0) | (@selector(copy:) == arg2 ? 0x1 : 0x0); return rax; } ``` `PDFHostViewController` explicitly enables selectAll and copy actions.
Josip
Comment 2 2019-07-15 03:51:07 PDT
I am not familiar with specifics of WebKit view hierarchy. Would it be possible to override this method in some of WebKit views and forward to superclass somehow?
Josip
Comment 3 2019-07-15 08:55:10 PDT
For reference: I managed to workaround this by: ``` if let cls = NSClassFromString("PDFHostViewController") { let selector1 = #selector(canPerformAction(_:withSender:)) let selector2 = #selector(canPerformAction2(_:withSender:)) if let original = class_getInstanceMethod(cls, selector1), let replacement = class_getInstanceMethod(MyObject.self, selector2) { let replacemementImp = revert ? original : replacement let imp = method_getImplementation(replacemementImp) method_setImplementation(original, imp) } } ```
Radar WebKit Bug Importer
Comment 4 2019-07-15 16:15:57 PDT
Note You need to log in before you can comment on or make changes to this bug.