Skip to content
Permalink
Browse files
Mail: dragged in attachments are shown as rich icons in compose but a…
…re received as generic icons

https://bugs.webkit.org/show_bug.cgi?id=240679
<rdar://93513798>

Reviewed by Wenson Hsieh.

Render the thumbnail for iWork files when the file wrapper is set for
attachments that are not added via the pasteboard.

Confirmed this also fixes the issue for Notes.

* Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm:
(testiWorkAttachmentFileURL):
(testiWorkAttachmentData):
(-[AttachmentUIDelegate _webView:didInsertAttachment:withSource:]):
(TestWebKitAPI::TEST):
* Source/WebKit/UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::updateAttachmentAttributes):
* Source/WebCore/rendering/RenderThemeMac.mm:
(WebCore::shouldDrawIcon):
(WebCore::paintAttachmentIcon):
There's a small delay while we wait for the file wrapper for the
attachment to be set so we can retrieve the thumbnail. In order to avoid a
flicker from the generic icon to the thumbnail, we should avoid painting
iWork file icons until the thumbnail is retrieved.

Canonical link: https://commits.webkit.org/250772@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@294515 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
kcheney1 committed May 20, 2022
1 parent 7d2e6e3 commit c89b516338ce3154e62ab01adc8d490972edda3d
Showing 3 changed files with 71 additions and 10 deletions.
@@ -2661,6 +2661,18 @@ static void paintAttachmentIconBackground(const RenderAttachment& attachment, Gr
}
}

static bool shouldDrawIcon(const String& title)
{
// The thumbnail will be painted by the client.
NSString *cocoaTitle = title;
if (auto fileExtension = cocoaTitle.pathExtension; fileExtension.length) {
return ![fileExtension isEqualToString:@"key"]
&& ![fileExtension isEqualToString:@"pages"]
&& ![fileExtension isEqualToString:@"numbers"];
}
return true;
}

static void paintAttachmentIcon(const RenderAttachment& attachment, GraphicsContext& context, AttachmentLayout& layout)
{
if (auto thumbnailIcon = attachment.attachmentElement().thumbnail()) {
@@ -2681,6 +2693,9 @@ static void paintAttachmentIcon(const RenderAttachment& attachment, GraphicsCont
if (!image)
return;

if (!shouldDrawIcon(attachment.attachmentElement().attachmentTitleForDisplay()))
return;

LocalCurrentGraphicsContext localCurrentGC(context);

[image drawInRect:layout.iconRect fromRect:NSMakeRect(0, 0, [image size].width, [image size].height) operation:NSCompositingOperationSourceOver fraction:1.0f];
@@ -10327,6 +10327,10 @@ void WebPageProxy::insertAttachment(Ref<API::Attachment>&& attachment, Completio

void WebPageProxy::updateAttachmentAttributes(const API::Attachment& attachment, CompletionHandler<void()>&& callback)
{
#if HAVE(QUICKLOOK_THUMBNAILING)
requestThumbnailWithFileWrapper(attachment.fileWrapper(), attachment.identifier());
#endif

sendWithAsyncReply(Messages::WebPage::UpdateAttachmentAttributes(attachment.identifier(), attachment.fileSizeForDisplay(), attachment.contentType(), attachment.fileName(), IPC::SharedBufferCopy(attachment.enclosingImageData())), WTFMove(callback));
}

@@ -146,6 +146,29 @@ - (void)_webView:(WKWebView *)webView didInvalidateDataForAttachment:(_WKAttachm

@end

static NSURL *testiWorkAttachmentFileURL()
{
return [[NSBundle mainBundle] URLForResource:@"test" withExtension:@"pages" subdirectory:@"TestWebKitAPI.resources"];
}

static NSData *testiWorkAttachmentData()
{
return [NSData dataWithContentsOfURL:testiWorkAttachmentFileURL()];
}

@interface AttachmentUIDelegate : NSObject<WKUIDelegatePrivate>
@end

@implementation AttachmentUIDelegate

- (void)_webView:(WKWebView *)webView didInsertAttachment:(_WKAttachment *)wkAttachment withSource:(NSString *)source
{
auto fileWrapper = adoptNS([[NSFileWrapper alloc] initWithURL:testiWorkAttachmentFileURL() options:0 error:NULL]);
[wkAttachment setFileWrapper:fileWrapper.get() contentType:nil completion:nil];
}

@end

namespace TestWebKitAPI {

class ObserveAttachmentUpdatesForScope {
@@ -243,16 +266,6 @@ @interface TestWKWebView (AttachmentTesting)
return [@"<a href='#'>This is some HTML data</a>" dataUsingEncoding:NSUTF8StringEncoding];
}

static NSURL *testiWorkAttachmentFileURL()
{
return [[NSBundle mainBundle] URLForResource:@"test" withExtension:@"pages" subdirectory:@"TestWebKitAPI.resources"];
}

static NSData *testiWorkAttachmentData()
{
return [NSData dataWithContentsOfURL:testiWorkAttachmentFileURL()];
}

static NSURL *testImageFileURL()
{
return [[NSBundle mainBundle] URLForResource:@"icon" withExtension:@"png" subdirectory:@"TestWebKitAPI.resources"];
@@ -1651,6 +1664,7 @@ static void _generateBestRepresentationForRequest(id, SEL)

TEST(WKAttachmentTests, CutAndPasteAttachmentBetweenWebViews)
{
triedToLoadThumbnail = false;
auto webView = webViewForTestingAttachments();
[webView synchronouslyInsertAttachmentWithFilename:@"test.pages" contentType:nil data:testiWorkAttachmentData()];
[webView selectAll:nil];
@@ -1671,6 +1685,34 @@ static void _generateBestRepresentationForRequest(id, SEL)
Util::run(&triedToLoadThumbnail);
}

TEST(WKAttachmentTests, iWorkAttachmentWithoutPasteboardActionLoadsThumbnail)
{
triedToLoadThumbnail = false;
InstanceMethodSwizzler quickLookSwizzler {
getQLThumbnailGeneratorClass(),
@selector(generateBestRepresentationForRequest:completionHandler:),
reinterpret_cast<IMP>(_generateBestRepresentationForRequest)
};

auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
configuration.get()._attachmentElementEnabled = YES;
WKPreferencesSetCustomPasteboardDataEnabled((__bridge WKPreferencesRef)[configuration preferences], YES);

auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 500, 500) configuration:configuration.get()]);

auto uiDelegate = adoptNS([[AttachmentUIDelegate alloc] init]);
webView.get().UIDelegate = uiDelegate.get();

static NSString *htmlWithEmbeddedAttachment = @"<meta name='viewport' content='width=device-width, initial-scale=1'>"
"<script>focus = () => document.body.focus()</script>"
"<body onload=focus() contenteditable>"
"<attachment src='test.pages' title='test.pages'></attachment></body>";

[webView synchronouslyLoadHTMLString:htmlWithEmbeddedAttachment];

Util::run(&triedToLoadThumbnail);
}

TEST(WKAttachmentTests, AttachmentIdentifierOfClonedAttachment)
{
auto webView = webViewForTestingAttachments();

0 comments on commit c89b516

Please sign in to comment.