<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[287547] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/287547">287547</a></dd>
<dt>Author</dt> <dd>wenson_hsieh@apple.com</dd>
<dt>Date</dt> <dd>2022-01-03 10:27:07 -0800 (Mon, 03 Jan 2022)</dd>
</dl>

<h3>Log Message</h3>
<pre>Undownloaded iCloud Photos are inserted as broken images when attachment element is enabled
https://bugs.webkit.org/show_bug.cgi?id=234803
rdar://82318259

Reviewed by Darin Adler.

Source/WebCore:

Currently, when inserting file paths via paste or drop that correspond to undownloaded files in iCloud Drive,
we show a generic empty file as the file preview, with "Zero Bytes" as the attachment subtitle when the
attachment element is enabled (i.e., Mail compose when using WebKit2). Even worse, for undownloaded image files,
we'll attempt to insert them as broken images.

Mail handles this scenario by detecting that we've dropped an undownloaded attachment, downloads the attachment,
and eventually updates the attachment element with the downloaded data. In the meantime, however, it's not ideal
for WebKit to represent the attachment that is still being downloaded as a broken image or empty file.

To address this, make a slight adjustment to detect that the file we're inserting is not locally available and
render it as an attachment element with progress="0". The client is then expected to update this progress as the
download is taking place, and update the attachment data once it's complete.

Test: WKAttachmentTestsMac.InsertNonExistentImageFileAsAttachment

* editing/cocoa/WebContentReaderCocoa.mm:
(WebCore::attachmentForFilePath):

Tools:

Add a new API test to exercise the change. See WebCore/ChangeLog for more information.

* TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm:
(nonexistentFilePath):
(TestWebKitAPI::TEST):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreeditingcocoaWebContentReaderCocoamm">trunk/Source/WebCore/editing/cocoa/WebContentReaderCocoa.mm</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsWebKitCocoaWKAttachmentTestsmm">trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (287546 => 287547)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog   2022-01-03 17:46:10 UTC (rev 287546)
+++ trunk/Source/WebCore/ChangeLog      2022-01-03 18:27:07 UTC (rev 287547)
</span><span class="lines">@@ -1,3 +1,29 @@
</span><ins>+2022-01-03  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        Undownloaded iCloud Photos are inserted as broken images when attachment element is enabled
+        https://bugs.webkit.org/show_bug.cgi?id=234803
+        rdar://82318259
+
+        Reviewed by Darin Adler.
+
+        Currently, when inserting file paths via paste or drop that correspond to undownloaded files in iCloud Drive,
+        we show a generic empty file as the file preview, with "Zero Bytes" as the attachment subtitle when the
+        attachment element is enabled (i.e., Mail compose when using WebKit2). Even worse, for undownloaded image files,
+        we'll attempt to insert them as broken images.
+
+        Mail handles this scenario by detecting that we've dropped an undownloaded attachment, downloads the attachment,
+        and eventually updates the attachment element with the downloaded data. In the meantime, however, it's not ideal
+        for WebKit to represent the attachment that is still being downloaded as a broken image or empty file.
+
+        To address this, make a slight adjustment to detect that the file we're inserting is not locally available and
+        render it as an attachment element with progress="0". The client is then expected to update this progress as the
+        download is taking place, and update the attachment data once it's complete.
+
+        Test: WKAttachmentTestsMac.InsertNonExistentImageFileAsAttachment
+
+        * editing/cocoa/WebContentReaderCocoa.mm:
+        (WebCore::attachmentForFilePath):
+
</ins><span class="cx"> 2022-01-03  Antti Koivisto  <antti@apple.com>
</span><span class="cx"> 
</span><span class="cx">         PseudoClassChangeInvalidation should allow multiple pseudo classes as argument
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingcocoaWebContentReaderCocoamm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/cocoa/WebContentReaderCocoa.mm (287546 => 287547)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/cocoa/WebContentReaderCocoa.mm      2022-01-03 17:46:10 UTC (rev 287546)
+++ trunk/Source/WebCore/editing/cocoa/WebContentReaderCocoa.mm 2022-01-03 18:27:07 UTC (rev 287547)
</span><span class="lines">@@ -711,7 +711,8 @@
</span><span class="cx">         return attachment;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    bool isDirectory = FileSystem::fileTypeFollowingSymlinks(path) == FileSystem::FileType::Directory;
</del><ins>+    auto fileType = FileSystem::fileTypeFollowingSymlinks(path);
+    bool isDirectory = fileType == FileSystem::FileType::Directory;
</ins><span class="cx">     String contentType = typeForAttachmentElement(explicitContentType);
</span><span class="cx">     if (contentType.isEmpty()) {
</span><span class="cx"> ALLOW_DEPRECATED_DECLARATIONS_BEGIN
</span><span class="lines">@@ -726,12 +727,14 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     std::optional<uint64_t> fileSizeForDisplay;
</span><del>-    if (!isDirectory)
</del><ins>+    if (fileType && !isDirectory)
</ins><span class="cx">         fileSizeForDisplay = FileSystem::fileSize(path).value_or(0);
</span><span class="cx"> 
</span><span class="cx">     frame.editor().registerAttachmentIdentifier(attachment->ensureUniqueIdentifier(), contentType, path);
</span><span class="cx"> 
</span><del>-    if (contentTypeIsSuitableForInlineImageRepresentation(contentType)) {
</del><ins>+    if (!fileType)
+        attachment->setAttributeWithoutSynchronization(HTMLNames::progressAttr, AtomString::number(0));
+    else if (contentTypeIsSuitableForInlineImageRepresentation(contentType)) {
</ins><span class="cx">         auto image = HTMLImageElement::create(document);
</span><span class="cx">         image->setAttributeWithoutSynchronization(HTMLNames::srcAttr, DOMURL::createObjectURL(document, File::create(document.ptr(), path)));
</span><span class="cx">         image->setAttachmentElement(WTFMove(attachment));
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (287546 => 287547)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog    2022-01-03 17:46:10 UTC (rev 287546)
+++ trunk/Tools/ChangeLog       2022-01-03 18:27:07 UTC (rev 287547)
</span><span class="lines">@@ -1,3 +1,17 @@
</span><ins>+2022-01-03  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        Undownloaded iCloud Photos are inserted as broken images when attachment element is enabled
+        https://bugs.webkit.org/show_bug.cgi?id=234803
+        rdar://82318259
+
+        Reviewed by Darin Adler.
+
+        Add a new API test to exercise the change. See WebCore/ChangeLog for more information.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm:
+        (nonexistentFilePath):
+        (TestWebKitAPI::TEST):
+
</ins><span class="cx"> 2022-01-03  Martin Robinson  <mrobinson@webkit.org>
</span><span class="cx"> 
</span><span class="cx">         A manual test was imported with the WPT css-transforms test suite
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebKitCocoaWKAttachmentTestsmm"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm (287546 => 287547)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm 2022-01-03 17:46:10 UTC (rev 287546)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm    2022-01-03 18:27:07 UTC (rev 287547)
</span><span class="lines">@@ -511,8 +511,14 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-#endif
</del><ins>+static NSString *nonexistentFilePath(NSString *extension)
+{
+    auto nonexistentFileName = [NSString stringWithFormat:@"%@.%@", NSUUID.UUID.UUIDString, extension];
+    return [NSTemporaryDirectory() stringByAppendingPathComponent:nonexistentFileName];
+}
</ins><span class="cx"> 
</span><ins>+#endif // PLATFORM(MAC)
+
</ins><span class="cx"> #if PLATFORM(IOS_FAMILY)
</span><span class="cx"> 
</span><span class="cx"> typedef void(^ItemProviderDataLoadHandler)(NSData *, NSError *);
</span><span class="lines">@@ -1672,6 +1678,32 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+TEST(WKAttachmentTestsMac, InsertNonExistentImageFileAsAttachment)
+{
+    NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
+    [pasteboard clearContents];
+    [pasteboard declareTypes:@[NSFilenamesPboardType] owner:nil];
+
+    RetainPtr filePath = nonexistentFilePath(@"jpg");
+    [pasteboard setPropertyList:@[filePath.get()] forType:NSFilenamesPboardType];
+
+    RetainPtr<NSArray<_WKAttachment *>> insertedAttachments;
+    auto webView = webViewForTestingAttachments();
+    {
+        ObserveAttachmentUpdatesForScope observer(webView.get());
+        [webView _synchronouslyExecuteEditCommand:@"Paste" argument:nil];
+        insertedAttachments = [observer.observer() inserted];
+        EXPECT_EQ(1U, [insertedAttachments count]);
+    }
+
+    [webView expectElementCount:1 querySelector:@"ATTACHMENT"];
+    [webView expectElementCount:0 querySelector:@"IMG"];
+    EXPECT_WK_STREQ("0", [webView stringByEvaluatingJavaScript:@"document.querySelector('attachment').getAttribute('progress')"]);
+    EXPECT_WK_STREQ([filePath lastPathComponent], [webView stringByEvaluatingJavaScript:@"document.querySelector('attachment').getAttribute('title')"]);
+    EXPECT_WK_STREQ("image/jpeg", [webView stringByEvaluatingJavaScript:@"document.querySelector('attachment').getAttribute('type')"]);
+    EXPECT_FALSE([[webView objectByEvaluatingJavaScript:@"document.querySelector('attachment').hasAttribute('subtitle')"] boolValue]);
+}
+
</ins><span class="cx"> TEST(WKAttachmentTestsMac, InsertDroppedFilePromisesAsAttachments)
</span><span class="cx"> {
</span><span class="cx">     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
</span></span></pre>
</div>
</div>

</body>
</html>