[Attachment Support] Expose file name and content type of WKAttachment
authorwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 9 Jan 2018 02:05:48 +0000 (02:05 +0000)
committerwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 9 Jan 2018 02:05:48 +0000 (02:05 +0000)
https://bugs.webkit.org/show_bug.cgi?id=181390
<rdar://problem/36336837>

Reviewed by Tim Horton.

Source/WebCore:

Add new structs in AttachmentTypes.h and refactor HTMLAttachmentElement::requestData to requestInfo. See below
for more details. Augmented existing API tests in WKAttachmentTests.

* html/AttachmentTypes.h:

Add a struct to represent a snapshot of information about an attachment element.

* html/HTMLAttachmentElement.cpp:
(WebCore::HTMLAttachmentElement::requestInfo):
(WebCore::HTMLAttachmentElement::requestData): Deleted.
* html/HTMLAttachmentElement.h:

Change requestData to requestInfo. Instead of fetching and delivering data via callback, requestInfo returns an
AttachmentInfo.

* rendering/RenderThemeIOS.mm:
(WebCore::RenderAttachmentInfo::addLine):
(WebCore::RenderAttachmentInfo::buildWrappedLines):
(WebCore::RenderAttachmentInfo::buildSingleLine):
(WebCore::RenderAttachmentInfo::RenderAttachmentInfo):
(WebCore::RenderThemeIOS::attachmentBaseline const):
(WebCore::paintAttachmentIcon):
(WebCore::paintAttachmentText):
(WebCore::paintAttachmentProgress):
(WebCore::attachmentBorderPath):
(WebCore::RenderThemeIOS::paintAttachment):
(WebCore::AttachmentInfo::addLine): Deleted.
(WebCore::AttachmentInfo::buildWrappedLines): Deleted.
(WebCore::AttachmentInfo::buildSingleLine): Deleted.
(WebCore::AttachmentInfo::AttachmentInfo): Deleted.

Rename AttachmentInfo to RenderAttachmentInfo to resolve a name conflict with the new AttachmentInfo struct.

Source/WebKit:

Add support for -[_WKAttachment requestInfo:], which fetches a snapshot of the attachment's state. This API is
meant to be a replacement for -requestData: that provides additional metadata about the attachment.

* Scripts/webkit/messages.py:
(headers_for_type):
* Shared/WebCoreArgumentCoders.cpp:
(IPC::ArgumentCoder<AttachmentInfo>::encode):
(IPC::ArgumentCoder<AttachmentInfo>::decode):
* Shared/WebCoreArgumentCoders.h:

Add IPC support for AttachmentInfo. Note that instead of using (encode|decode)SharedBuffer, we send and receive
data references to the shared buffer.

* UIProcess/API/APIAttachment.cpp:
(API::Attachment::requestInfo):
(API::Attachment::requestData): Deleted.
* UIProcess/API/APIAttachment.h:

Change requestData to requestInfo.

* UIProcess/API/Cocoa/_WKAttachment.h:
* UIProcess/API/Cocoa/_WKAttachment.mm:
(-[_WKAttachmentInfo initWithInfo:]):
(-[_WKAttachmentInfo data]):
(-[_WKAttachmentInfo name]):
(-[_WKAttachmentInfo filePath]):
(-[_WKAttachmentInfo contentType]):
(-[_WKAttachment requestInfo:]):
(-[_WKAttachment requestData:]):

Implement -requestInfo: by calling into APIAttachment, and reimplement -requestData: in terms of -requestInfo:.

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::attachmentInfoCallback):
(WebKit::WebPageProxy::requestAttachmentInfo):
(WebKit::WebPageProxy::sharedBufferCallback): Deleted.
(WebKit::WebPageProxy::requestAttachmentData): Deleted.
* UIProcess/WebPageProxy.h:
* UIProcess/WebPageProxy.messages.in:

Rename the SharedBufferCallback IPC message to AttachmentInfoCallback, and make it conditional on
ATTACHMENT_ELEMENT. Rename requestAttachmentData to requestAttachmentInfo.

* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::requestAttachmentInfo):
(WebKit::WebPage::invokeSharedBufferCallback): Deleted.
(WebKit::WebPage::requestAttachmentData): Deleted.

Rename requestAttachmentData to requestAttachmentInfo and adopt HTMLAttachmentElement::requestInfo.

* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:

Tools:

Adjusts some existing tests in WKAttachmentTests to exercise -requestInfo:.

* TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm:
(-[_WKAttachment synchronouslyRequestInfo:]):
(-[_WKAttachment synchronouslyRequestData:]):

Reimplement this in terms of -synchronouslyRequestInfo:.

(-[_WKAttachment expectRequestedDataToBe:]):
(TestWebKitAPI::TEST):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@226604 268f45cc-cd09-0410-ab3c-d52691b4dbfc

21 files changed:
Source/WebCore/ChangeLog
Source/WebCore/html/AttachmentTypes.h
Source/WebCore/html/HTMLAttachmentElement.cpp
Source/WebCore/html/HTMLAttachmentElement.h
Source/WebCore/rendering/RenderThemeIOS.mm
Source/WebKit/ChangeLog
Source/WebKit/Scripts/webkit/messages.py
Source/WebKit/Shared/WebCoreArgumentCoders.cpp
Source/WebKit/Shared/WebCoreArgumentCoders.h
Source/WebKit/UIProcess/API/APIAttachment.cpp
Source/WebKit/UIProcess/API/APIAttachment.h
Source/WebKit/UIProcess/API/Cocoa/_WKAttachment.h
Source/WebKit/UIProcess/API/Cocoa/_WKAttachment.mm
Source/WebKit/UIProcess/WebPageProxy.cpp
Source/WebKit/UIProcess/WebPageProxy.h
Source/WebKit/UIProcess/WebPageProxy.messages.in
Source/WebKit/WebProcess/WebPage/WebPage.cpp
Source/WebKit/WebProcess/WebPage/WebPage.h
Source/WebKit/WebProcess/WebPage/WebPage.messages.in
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm

index 312baa8..5defe23 100644 (file)
@@ -1,3 +1,44 @@
+2018-01-08  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        [Attachment Support] Expose file name and content type of WKAttachment
+        https://bugs.webkit.org/show_bug.cgi?id=181390
+        <rdar://problem/36336837>
+
+        Reviewed by Tim Horton.
+
+        Add new structs in AttachmentTypes.h and refactor HTMLAttachmentElement::requestData to requestInfo. See below
+        for more details. Augmented existing API tests in WKAttachmentTests.
+
+        * html/AttachmentTypes.h:
+
+        Add a struct to represent a snapshot of information about an attachment element.
+
+        * html/HTMLAttachmentElement.cpp:
+        (WebCore::HTMLAttachmentElement::requestInfo):
+        (WebCore::HTMLAttachmentElement::requestData): Deleted.
+        * html/HTMLAttachmentElement.h:
+
+        Change requestData to requestInfo. Instead of fetching and delivering data via callback, requestInfo returns an
+        AttachmentInfo.
+
+        * rendering/RenderThemeIOS.mm:
+        (WebCore::RenderAttachmentInfo::addLine):
+        (WebCore::RenderAttachmentInfo::buildWrappedLines):
+        (WebCore::RenderAttachmentInfo::buildSingleLine):
+        (WebCore::RenderAttachmentInfo::RenderAttachmentInfo):
+        (WebCore::RenderThemeIOS::attachmentBaseline const):
+        (WebCore::paintAttachmentIcon):
+        (WebCore::paintAttachmentText):
+        (WebCore::paintAttachmentProgress):
+        (WebCore::attachmentBorderPath):
+        (WebCore::RenderThemeIOS::paintAttachment):
+        (WebCore::AttachmentInfo::addLine): Deleted.
+        (WebCore::AttachmentInfo::buildWrappedLines): Deleted.
+        (WebCore::AttachmentInfo::buildSingleLine): Deleted.
+        (WebCore::AttachmentInfo::AttachmentInfo): Deleted.
+
+        Rename AttachmentInfo to RenderAttachmentInfo to resolve a name conflict with the new AttachmentInfo struct.
+
 2018-01-08  Saam Barati  <sbarati@apple.com>
 
         Speculative build fix after r226600. We only use clflush on x86 and the `asm volatile` syntax is not available in the Windows build.
index 565de91..88c1817 100644 (file)
 #if ENABLE(ATTACHMENT_ELEMENT)
 
 #include <wtf/Optional.h>
+#include <wtf/text/WTFString.h>
 
 namespace WebCore {
 
+class SharedBuffer;
+
 enum class AttachmentDisplayMode {
     Auto,
     InPlace,
@@ -58,6 +61,13 @@ template<class Decoder> inline std::optional<AttachmentDisplayOptions> Attachmen
     return {{ mode }};
 }
 
+struct AttachmentInfo {
+    String contentType;
+    String name;
+    String filePath;
+    RefPtr<SharedBuffer> data;
+};
+
 } // namespace WebCore
 
 #endif // ENABLE(ATTACHMENT_ELEMENT)
index d3708fa..a52bd14 100644 (file)
@@ -296,12 +296,16 @@ void HTMLAttachmentElement::populateShadowRootIfNecessary()
     }
 }
 
-void HTMLAttachmentElement::requestData(Function<void(RefPtr<SharedBuffer>&&)>&& callback)
+void HTMLAttachmentElement::requestInfo(Function<void(const AttachmentInfo&)>&& callback)
 {
-    if (m_file)
-        m_attachmentReaders.append(AttachmentDataReader::create(*this, WTFMove(callback)));
-    else
-        callback(nullptr);
+    if (!m_file) {
+        callback({ });
+        return;
+    }
+
+    m_attachmentReaders.append(AttachmentDataReader::create(*this, [protectedFile = makeRef(*m_file), callback = WTFMove(callback)] (RefPtr<SharedBuffer>&& data) {
+        callback({ protectedFile->type(), protectedFile->name(), protectedFile->path(), WTFMove(data) });
+    }));
 }
 
 void HTMLAttachmentElement::destroyReader(AttachmentDataReader& finishedReader)
index b3223fa..e811bf8 100644 (file)
@@ -64,7 +64,7 @@ public:
 
     RenderAttachment* attachmentRenderer() const;
 
-    WEBCORE_EXPORT void requestData(Function<void(RefPtr<SharedBuffer>&&)>&& callback);
+    WEBCORE_EXPORT void requestInfo(Function<void(const AttachmentInfo&)>&& callback);
     void destroyReader(AttachmentDataReader&);
 
 private:
index d2e641e..f099c28 100644 (file)
@@ -1485,8 +1485,8 @@ static UIColor *attachmentTitleColor() { return [getUIColorClass() systemGrayCol
 static RetainPtr<CTFontRef> attachmentSubtitleFont() { return attachmentTitleFont(); }
 static UIColor *attachmentSubtitleColor() { return [getUIColorClass() systemGrayColor]; }
 
-struct AttachmentInfo {
-    explicit AttachmentInfo(const RenderAttachment&);
+struct RenderAttachmentInfo {
+    explicit RenderAttachmentInfo(const RenderAttachment&);
 
     FloatRect iconRect;
     FloatRect attachmentRect;
@@ -1514,7 +1514,7 @@ private:
     void addLine(CTLineRef);
 };
 
-void AttachmentInfo::addLine(CTLineRef line)
+void RenderAttachmentInfo::addLine(CTLineRef line)
 {
     CGRect lineBounds = CTLineGetBoundsWithOptions(line, kCTLineBoundsExcludeTypographicLeading);
     CGFloat trailingWhitespaceWidth = CTLineGetTrailingWhitespaceWidth(line);
@@ -1529,7 +1529,7 @@ void AttachmentInfo::addLine(CTLineRef line)
     lines.append(labelLine);
 }
 
-void AttachmentInfo::buildWrappedLines(const String& text, CTFontRef font, UIColor *color, unsigned maximumLineCount)
+void RenderAttachmentInfo::buildWrappedLines(const String& text, CTFontRef font, UIColor *color, unsigned maximumLineCount)
 {
     if (text.isEmpty())
         return;
@@ -1578,7 +1578,7 @@ void AttachmentInfo::buildWrappedLines(const String& text, CTFontRef font, UICol
     addLine(truncatedLine.get());
 }
 
-void AttachmentInfo::buildSingleLine(const String& text, CTFontRef font, UIColor *color)
+void RenderAttachmentInfo::buildSingleLine(const String& text, CTFontRef font, UIColor *color)
 {
     if (text.isEmpty())
         return;
@@ -1653,7 +1653,7 @@ static RetainPtr<UIImage> iconForAttachment(const RenderAttachment& attachment,
     return result;
 }
 
-AttachmentInfo::AttachmentInfo(const RenderAttachment& attachment)
+RenderAttachmentInfo::RenderAttachmentInfo(const RenderAttachment& attachment)
 {
     attachmentRect = FloatRect(0, 0, attachment.width().toFloat(), attachment.height().toFloat());
 
@@ -1703,11 +1703,11 @@ LayoutSize RenderThemeIOS::attachmentIntrinsicSize(const RenderAttachment&) cons
 
 int RenderThemeIOS::attachmentBaseline(const RenderAttachment& attachment) const
 {
-    AttachmentInfo info(attachment);
+    RenderAttachmentInfo info(attachment);
     return info.baseline;
 }
 
-static void paintAttachmentIcon(GraphicsContext& context, AttachmentInfo& info)
+static void paintAttachmentIcon(GraphicsContext& context, RenderAttachmentInfo& info)
 {
     if (!info.icon)
         return;
@@ -1719,7 +1719,7 @@ static void paintAttachmentIcon(GraphicsContext& context, AttachmentInfo& info)
     context.drawImage(*iconImage, info.iconRect);
 }
 
-static void paintAttachmentText(GraphicsContext& context, AttachmentInfo& info)
+static void paintAttachmentText(GraphicsContext& context, RenderAttachmentInfo& info)
 {
     for (const auto& line : info.lines) {
         GraphicsContextStateSaver saver(context);
@@ -1732,7 +1732,7 @@ static void paintAttachmentText(GraphicsContext& context, AttachmentInfo& info)
     }
 }
 
-static void paintAttachmentProgress(GraphicsContext& context, AttachmentInfo& info)
+static void paintAttachmentProgress(GraphicsContext& context, RenderAttachmentInfo& info)
 {
     GraphicsContextStateSaver saver(context);
 
@@ -1751,7 +1751,7 @@ static void paintAttachmentProgress(GraphicsContext& context, AttachmentInfo& in
     context.fillPath(progressPath);
 }
 
-static Path attachmentBorderPath(AttachmentInfo& info)
+static Path attachmentBorderPath(RenderAttachmentInfo& info)
 {
     Path borderPath;
     borderPath.addRoundedRect(info.attachmentRect, FloatSize(attachmentBorderRadius, attachmentBorderRadius));
@@ -1772,7 +1772,7 @@ bool RenderThemeIOS::paintAttachment(const RenderObject& renderer, const PaintIn
 
     const RenderAttachment& attachment = downcast<RenderAttachment>(renderer);
 
-    AttachmentInfo info(attachment);
+    RenderAttachmentInfo info(attachment);
 
     GraphicsContext& context = paintInfo.context();
     GraphicsContextStateSaver saver(context);
index 088fb71..27cb3e9 100644 (file)
@@ -1,3 +1,64 @@
+2018-01-08  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        [Attachment Support] Expose file name and content type of WKAttachment
+        https://bugs.webkit.org/show_bug.cgi?id=181390
+        <rdar://problem/36336837>
+
+        Reviewed by Tim Horton.
+
+        Add support for -[_WKAttachment requestInfo:], which fetches a snapshot of the attachment's state. This API is
+        meant to be a replacement for -requestData: that provides additional metadata about the attachment.
+
+        * Scripts/webkit/messages.py:
+        (headers_for_type):
+        * Shared/WebCoreArgumentCoders.cpp:
+        (IPC::ArgumentCoder<AttachmentInfo>::encode):
+        (IPC::ArgumentCoder<AttachmentInfo>::decode):
+        * Shared/WebCoreArgumentCoders.h:
+
+        Add IPC support for AttachmentInfo. Note that instead of using (encode|decode)SharedBuffer, we send and receive
+        data references to the shared buffer.
+
+        * UIProcess/API/APIAttachment.cpp:
+        (API::Attachment::requestInfo):
+        (API::Attachment::requestData): Deleted.
+        * UIProcess/API/APIAttachment.h:
+
+        Change requestData to requestInfo.
+
+        * UIProcess/API/Cocoa/_WKAttachment.h:
+        * UIProcess/API/Cocoa/_WKAttachment.mm:
+        (-[_WKAttachmentInfo initWithInfo:]):
+        (-[_WKAttachmentInfo data]):
+        (-[_WKAttachmentInfo name]):
+        (-[_WKAttachmentInfo filePath]):
+        (-[_WKAttachmentInfo contentType]):
+        (-[_WKAttachment requestInfo:]):
+        (-[_WKAttachment requestData:]):
+
+        Implement -requestInfo: by calling into APIAttachment, and reimplement -requestData: in terms of -requestInfo:.
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::attachmentInfoCallback):
+        (WebKit::WebPageProxy::requestAttachmentInfo):
+        (WebKit::WebPageProxy::sharedBufferCallback): Deleted.
+        (WebKit::WebPageProxy::requestAttachmentData): Deleted.
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebPageProxy.messages.in:
+
+        Rename the SharedBufferCallback IPC message to AttachmentInfoCallback, and make it conditional on
+        ATTACHMENT_ELEMENT. Rename requestAttachmentData to requestAttachmentInfo.
+
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::requestAttachmentInfo):
+        (WebKit::WebPage::invokeSharedBufferCallback): Deleted.
+        (WebKit::WebPage::requestAttachmentData): Deleted.
+
+        Rename requestAttachmentData to requestAttachmentInfo and adopt HTMLAttachmentElement::requestInfo.
+
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+
 2018-01-08  Alex Christensen  <achristensen@webkit.org>
 
         Pass around Vector<Ref<WebContextMenuItem>> instead of WKArrayRef or Vector<WebContextMenuItemData>
index 706df56..a8bcc97 100644 (file)
@@ -368,6 +368,7 @@ def headers_for_type(type):
         'String': ['<wtf/text/WTFString.h>'],
         'PAL::SessionID': ['<pal/SessionID.h>'],
         'WebCore::AttachmentDisplayOptions': ['<WebCore/AttachmentTypes.h>'],
+        'WebCore::AttachmentInfo': ['<WebCore/AttachmentTypes.h>'],
         'WebCore::AutoplayEventFlags': ['<WebCore/AutoplayEvent.h>'],
         'WebCore::ExceptionDetails': ['<WebCore/JSDOMExceptionHandling.h>'],
         'WebCore::FileChooserSettings': ['<WebCore/FileChooser.h>'],
index 81c4e0f..f8e357b 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "DataReference.h"
 #include "ShareableBitmap.h"
+#include <WebCore/AttachmentTypes.h>
 #include <WebCore/AuthenticationChallenge.h>
 #include <WebCore/BlobPart.h>
 #include <WebCore/CacheQueryOptions.h>
@@ -2771,4 +2772,43 @@ bool ArgumentCoder<PromisedBlobInfo>::decode(Decoder& decoder, PromisedBlobInfo&
     return true;
 }
 
+#if ENABLE(ATTACHMENT_ELEMENT)
+
+void ArgumentCoder<AttachmentInfo>::encode(Encoder& encoder, const AttachmentInfo& info)
+{
+    bool dataIsNull = !info.data;
+    encoder << info.contentType << info.name << info.filePath << dataIsNull;
+    if (!dataIsNull) {
+        SharedBufferDataReference dataReference { info.data.get() };
+        encoder << static_cast<DataReference&>(dataReference);
+    }
+}
+
+bool ArgumentCoder<AttachmentInfo>::decode(Decoder& decoder, AttachmentInfo& info)
+{
+    if (!decoder.decode(info.contentType))
+        return false;
+
+    if (!decoder.decode(info.name))
+        return false;
+
+    if (!decoder.decode(info.filePath))
+        return false;
+
+    bool dataIsNull = true;
+    if (!decoder.decode(dataIsNull))
+        return false;
+
+    if (!dataIsNull) {
+        DataReference dataReference;
+        if (!decoder.decode(dataReference))
+            return false;
+        info.data = SharedBuffer::create(dataReference.data(), dataReference.size());
+    }
+
+    return true;
+}
+
+#endif // ENABLE(ATTACHMENT_ELEMENT)
+
 } // namespace IPC
index f53ded2..4a0d940 100644 (file)
@@ -89,6 +89,7 @@ class TransformationMatrix;
 class UserStyleSheet;
 class URL;
 
+struct AttachmentInfo;
 struct CacheQueryOptions;
 struct CompositionUnderline;
 struct DictationAlternative;
@@ -689,6 +690,15 @@ template<> struct ArgumentCoder<WebCore::PromisedBlobInfo> {
     static bool decode(Decoder&, WebCore::PromisedBlobInfo&);
 };
 
+#if ENABLE(ATTACHMENT_ELEMENT)
+
+template<> struct ArgumentCoder<WebCore::AttachmentInfo> {
+    static void encode(Encoder&, const WebCore::AttachmentInfo&);
+    static bool decode(Decoder&, WebCore::AttachmentInfo&);
+};
+
+#endif
+
 } // namespace IPC
 
 namespace WTF {
index 85a8a3e..04e0717 100644 (file)
@@ -48,12 +48,12 @@ Attachment::~Attachment()
 {
 }
 
-void Attachment::requestData(Function<void(RefPtr<WebCore::SharedBuffer>, WebKit::CallbackBase::Error)>&& callback)
+void Attachment::requestInfo(Function<void(const WebCore::AttachmentInfo&, WebKit::CallbackBase::Error)>&& callback)
 {
     if (m_webPage)
-        m_webPage->requestAttachmentData(m_identifier, WTFMove(callback));
+        m_webPage->requestAttachmentInfo(m_identifier, WTFMove(callback));
     else
-        callback(nullptr, WebKit::CallbackBase::Error::OwnerWasInvalidated);
+        callback({ }, WebKit::CallbackBase::Error::OwnerWasInvalidated);
 }
 
 void Attachment::setDisplayOptions(WebCore::AttachmentDisplayOptions options, Function<void(WebKit::CallbackBase::Error)>&& callback)
index d26f2ef..261d143 100644 (file)
@@ -35,6 +35,7 @@
 namespace WebCore {
 class SharedBuffer;
 struct AttachmentDisplayOptions;
+struct AttachmentInfo;
 }
 
 namespace WebKit {
@@ -49,7 +50,7 @@ public:
     virtual ~Attachment();
 
     const WTF::String& identifier() const { return m_identifier; }
-    void requestData(Function<void(RefPtr<WebCore::SharedBuffer>, WebKit::CallbackBase::Error)>&&);
+    void requestInfo(Function<void(const WebCore::AttachmentInfo&, WebKit::CallbackBase::Error)>&&);
     void setDisplayOptions(WebCore::AttachmentDisplayOptions, Function<void(WebKit::CallbackBase::Error)>&&);
     void setDataAndContentType(WebCore::SharedBuffer&, const WTF::String& newContentType, const WTF::String& newFilename, Function<void(WebKit::CallbackBase::Error)>&&);
 
index 210ca0e..d25b52a 100644 (file)
@@ -43,10 +43,20 @@ WK_CLASS_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA))
 @end
 
 WK_CLASS_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA))
+@interface _WKAttachmentInfo : NSObject
+@property (nonatomic, readonly) NSString *contentType;
+@property (nonatomic, readonly) NSString *name;
+@property (nonatomic, readonly) NSString *filePath;
+@property (nonatomic, readonly, nullable) NSData *data;
+@end
+
+WK_CLASS_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA))
 @interface _WKAttachment : NSObject
+- (void)requestInfo:(void(^)(_WKAttachmentInfo * _Nullable, NSError * _Nullable))completionHandler;
 - (void)requestData:(void(^)(NSData * _Nullable, NSError * _Nullable))completionHandler;
 - (void)setDisplayOptions:(_WKAttachmentDisplayOptions *)options completion:(void(^ _Nullable)(NSError * _Nullable))completionHandler;
 - (void)setData:(NSData *)data newContentType:(nullable NSString *)newContentType newFilename:(nullable NSString *)newFilename completion:(void(^ _Nullable)(NSError * _Nullable))completionHandler;
+@property (nonatomic, readonly) NSString *uniqueIdentifier;
 @end
 
 NS_ASSUME_NONNULL_END
index 939cc87..baeb313 100644 (file)
@@ -69,6 +69,48 @@ using namespace WebKit;
 
 @end
 
+@implementation _WKAttachmentInfo {
+    RetainPtr<NSData> _data;
+    RetainPtr<NSString> _name;
+    RetainPtr<NSString> _filePath;
+    RetainPtr<NSString> _contentType;
+}
+
+- (instancetype)initWithInfo:(const WebCore::AttachmentInfo&)info
+{
+    if (!(self = [super init]))
+        return nil;
+
+    _data = info.data ? info.data->createNSData() : nil;
+    _contentType = adoptNS([(NSString *)info.contentType ?: @"" copy]);
+    _name = adoptNS([(NSString *)info.name ?: @"" copy]);
+    _filePath = adoptNS([(NSString *)info.filePath ?: @"" copy]);
+
+    return self;
+}
+
+- (NSData *)data
+{
+    return _data.get();
+}
+
+- (NSString *)name
+{
+    return _name.get();
+}
+
+- (NSString *)filePath
+{
+    return _filePath.get();
+}
+
+- (NSString *)contentType
+{
+    return _contentType.get();
+}
+
+@end
+
 @implementation _WKAttachment
 
 - (API::Object&)_apiObject
@@ -81,19 +123,29 @@ using namespace WebKit;
     return [object isKindOfClass:[_WKAttachment class]] && [self.uniqueIdentifier isEqual:[(_WKAttachment *)object uniqueIdentifier]];
 }
 
-- (void)requestData:(void(^)(NSData *, NSError *))completionHandler
+- (void)requestInfo:(void(^)(_WKAttachmentInfo *, NSError *))completionHandler
 {
-    _attachment->requestData([ capturedBlock = makeBlockPtr(completionHandler) ] (RefPtr<WebCore::SharedBuffer> buffer, CallbackBase::Error error) {
+    _attachment->requestInfo([capturedBlock = makeBlockPtr(completionHandler)] (const WebCore::AttachmentInfo& info, CallbackBase::Error error) {
         if (!capturedBlock)
             return;
 
-        if (buffer && error == CallbackBase::Error::None)
-            capturedBlock(buffer->createNSData().autorelease(), nil);
-        else
-            capturedBlock(nil, [NSError errorWithDomain:WKErrorDomain code:1 userInfo:nil]);
+        if (error != CallbackBase::Error::None) {
+            capturedBlock(nil, [NSError errorWithDomain:WKErrorDomain code:WKErrorWebViewInvalidated userInfo:nil]);
+            return;
+        }
+
+        auto attachmentInfo = adoptNS([[_WKAttachmentInfo alloc] initWithInfo:info]);
+        capturedBlock(attachmentInfo.get(), nil);
     });
 }
 
+- (void)requestData:(void(^)(NSData *, NSError *))completionHandler
+{
+    [self requestInfo:[protectedBlock = makeBlockPtr(completionHandler)] (_WKAttachmentInfo *info, NSError *error) {
+        protectedBlock(info.data, error);
+    }];
+}
+
 - (void)setDisplayOptions:(_WKAttachmentDisplayOptions *)options completion:(void(^)(NSError *))completionHandler
 {
     auto coreOptions = options ? options.coreDisplayOptions : WebCore::AttachmentDisplayOptions { };
index e10a2eb..584a600 100644 (file)
@@ -5206,23 +5206,22 @@ void WebPageProxy::voidCallback(CallbackID callbackID)
     callback->performCallback();
 }
 
-void WebPageProxy::sharedBufferCallback(const IPC::DataReference& dataReference, bool isNull, CallbackID callbackID)
+#if ENABLE(ATTACHMENT_ELEMENT)
+
+void WebPageProxy::attachmentInfoCallback(const WebCore::AttachmentInfo& info, CallbackID callbackID)
 {
-    auto callback = m_callbacks.take<SharedBufferCallback>(callbackID);
+    auto callback = m_callbacks.take<AttachmentInfoCallback>(callbackID);
     if (!callback) {
         ASSERT_NOT_REACHED();
         return;
     }
 
-    if (isNull) {
-        ASSERT(dataReference.isEmpty());
-        callback->performCallbackWithReturnValue(nullptr);
-        return;
-    }
-
-    callback->performCallbackWithReturnValue(SharedBuffer::create(dataReference.data(), dataReference.size()));
+    MESSAGE_CHECK_URL(info.filePath);
+    callback->performCallbackWithReturnValue(info);
 }
 
+#endif
+
 void WebPageProxy::dataCallback(const IPC::DataReference& dataReference, CallbackID callbackID)
 {
     auto callback = m_callbacks.take<DataCallback>(callbackID);
@@ -7237,15 +7236,15 @@ void WebPageProxy::insertAttachment(const String& identifier, const AttachmentDi
     m_process->send(Messages::WebPage::InsertAttachment(identifier, options, filename, contentType, IPC::SharedBufferDataReference { &data }, callbackID), m_pageID);
 }
 
-void WebPageProxy::requestAttachmentData(const String& identifier, Function<void(RefPtr<SharedBuffer>, CallbackBase::Error)>&& callback)
+void WebPageProxy::requestAttachmentInfo(const String& identifier, Function<void(const AttachmentInfo&, CallbackBase::Error)>&& callback)
 {
     if (!isValid()) {
-        callback(nullptr, CallbackBase::Error::OwnerWasInvalidated);
+        callback({ }, CallbackBase::Error::OwnerWasInvalidated);
         return;
     }
 
     auto callbackID = m_callbacks.put(WTFMove(callback), m_process->throttler().backgroundActivityToken());
-    m_process->send(Messages::WebPage::RequestAttachmentData(identifier, callbackID), m_pageID);
+    m_process->send(Messages::WebPage::RequestAttachmentInfo(identifier, callbackID), m_pageID);
 }
 
 void WebPageProxy::setAttachmentDisplayOptions(const String& identifier, AttachmentDisplayOptions options, Function<void(CallbackBase::Error)>&& callback)
index f80fdcd..d88e59b 100644 (file)
@@ -183,6 +183,7 @@ using FloatBoxExtent = RectEdges<float>;
 #if ENABLE(ATTACHMENT_ELEMENT)
 namespace WebCore {
 struct AttachmentDisplayOptions;
+struct AttachmentInfo;
 }
 #endif
 
@@ -247,7 +248,10 @@ typedef GenericCallback<uint64_t> UnsignedCallback;
 typedef GenericCallback<EditingRange> EditingRangeCallback;
 typedef GenericCallback<const String&> StringCallback;
 typedef GenericCallback<API::SerializedScriptValue*, bool, const WebCore::ExceptionDetails&> ScriptValueCallback;
-typedef GenericCallback<RefPtr<WebCore::SharedBuffer>> SharedBufferCallback;
+
+#if ENABLE(ATTACHMENT_ELEMENT)
+typedef GenericCallback<const WebCore::AttachmentInfo&> AttachmentInfoCallback;
+#endif
 
 #if PLATFORM(GTK)
 typedef GenericCallback<API::Error*> PrintFinishedCallback;
@@ -1254,9 +1258,10 @@ public:
 
 #if ENABLE(ATTACHMENT_ELEMENT)
     void insertAttachment(const String& identifier, const WebCore::AttachmentDisplayOptions&, const String& filename, std::optional<String> contentType, WebCore::SharedBuffer& data, Function<void(CallbackBase::Error)>&&);
-    void requestAttachmentData(const String& identifier, Function<void(RefPtr<WebCore::SharedBuffer>, CallbackBase::Error)>&&);
+    void requestAttachmentInfo(const String& identifier, Function<void(const WebCore::AttachmentInfo&, CallbackBase::Error)>&&);
     void setAttachmentDisplayOptions(const String& identifier, WebCore::AttachmentDisplayOptions, Function<void(CallbackBase::Error)>&&);
     void setAttachmentDataAndContentType(const String& identifier, WebCore::SharedBuffer& data, std::optional<String>&& newContentType, std::optional<String>&& newFilename, Function<void(CallbackBase::Error)>&&);
+    void attachmentInfoCallback(const WebCore::AttachmentInfo&, CallbackID);
 #endif
 
 #if ENABLE(APPLICATION_MANIFEST)
@@ -1517,7 +1522,6 @@ private:
 
     void voidCallback(CallbackID);
     void dataCallback(const IPC::DataReference&, CallbackID);
-    void sharedBufferCallback(const IPC::DataReference&, bool isNull, CallbackID);
     void imageCallback(const ShareableBitmap::Handle&, CallbackID);
     void stringCallback(const String&, CallbackID);
     void invalidateStringCallback(CallbackID);
index 1d8d43a..653bb1c 100644 (file)
@@ -157,7 +157,6 @@ messages -> WebPageProxy {
     # Callback messages
     VoidCallback(WebKit::CallbackID callbackID)
     DataCallback(IPC::DataReference resultData, WebKit::CallbackID callbackID)
-    SharedBufferCallback(IPC::DataReference resultData, bool isNull, WebKit::CallbackID callbackID);
     ImageCallback(WebKit::ShareableBitmap::Handle bitmapHandle, WebKit::CallbackID callbackID)
     StringCallback(String resultString, WebKit::CallbackID callbackID)
     InvalidateStringCallback(WebKit::CallbackID callbackID)
@@ -167,6 +166,9 @@ messages -> WebPageProxy {
     EditingRangeCallback(struct WebKit::EditingRange range, WebKit::CallbackID callbackID)
     UnsignedCallback(uint64_t result, WebKit::CallbackID callbackID)
     RectForCharacterRangeCallback(WebCore::IntRect rect, struct WebKit::EditingRange actualRange, WebKit::CallbackID callbackID)
+#if ENABLE(ATTACHMENT_ELEMENT)
+    AttachmentInfoCallback(struct WebCore::AttachmentInfo info, WebKit::CallbackID callbackID);
+#endif
 #if ENABLE(APPLICATION_MANIFEST)
     ApplicationManifestCallback(std::optional<WebCore::ApplicationManifest> manifest, WebKit::CallbackID callbackID)
 #endif
index cb8c05c..d9429f3 100644 (file)
@@ -5856,14 +5856,6 @@ void WebPage::storageAccessResponse(bool wasGranted, uint64_t contextId)
 }
 #endif
 
-void WebPage::invokeSharedBufferCallback(RefPtr<SharedBuffer>&& buffer, CallbackID callbackID)
-{
-    if (buffer)
-        send(Messages::WebPageProxy::SharedBufferCallback(IPC::SharedBufferDataReference { buffer.get() }, false, callbackID));
-    else
-        send(Messages::WebPageProxy::SharedBufferCallback({ }, true, callbackID));
-}
-
 #if ENABLE(ATTACHMENT_ELEMENT)
 
 void WebPage::insertAttachment(const String& identifier, const AttachmentDisplayOptions& options, const String& filename, std::optional<String> contentType, const IPC::DataReference& data, CallbackID callbackID)
@@ -5873,19 +5865,16 @@ void WebPage::insertAttachment(const String& identifier, const AttachmentDisplay
     send(Messages::WebPageProxy::VoidCallback(callbackID));
 }
 
-void WebPage::requestAttachmentData(const String& identifier, CallbackID callbackID)
+void WebPage::requestAttachmentInfo(const String& identifier, CallbackID callbackID)
 {
     auto attachment = attachmentElementWithIdentifier(identifier);
     if (!attachment) {
-        invokeSharedBufferCallback({ }, callbackID);
+        send(Messages::WebPageProxy::AttachmentInfoCallback({ }, callbackID));
         return;
     }
 
-    attachment->requestData([callbackID, protectedThis = makeRef(*this), protectedAttachment = WTFMove(attachment)] (RefPtr<SharedBuffer>&& buffer) {
-        if (buffer)
-            protectedThis->invokeSharedBufferCallback(WTFMove(buffer), callbackID);
-        else
-            protectedThis->invokeSharedBufferCallback({ }, callbackID);
+    attachment->requestInfo([callbackID, protectedThis = makeRef(*this), protectedAttachment = WTFMove(attachment)] (const AttachmentInfo& info) {
+        protectedThis->send(Messages::WebPageProxy::AttachmentInfoCallback(info, callbackID));
     });
 }
 
index 1353e1f..9073b5e 100644 (file)
@@ -1043,7 +1043,7 @@ public:
 
 #if ENABLE(ATTACHMENT_ELEMENT)
     void insertAttachment(const String& identifier, const WebCore::AttachmentDisplayOptions&, const String& filename, std::optional<String> contentType, const IPC::DataReference&, CallbackID);
-    void requestAttachmentData(const String& identifier, CallbackID);
+    void requestAttachmentInfo(const String& identifier, CallbackID);
     void setAttachmentDisplayOptions(const String& identifier, const WebCore::AttachmentDisplayOptions&, CallbackID);
     void setAttachmentDataAndContentType(const String& identifier, const IPC::DataReference&, std::optional<String> newContentType, std::optional<String> newFilename, CallbackID);
 #endif
@@ -1166,8 +1166,6 @@ private:
     void restoreSession(const Vector<BackForwardListItemState>&);
     void didRemoveBackForwardItem(uint64_t);
 
-    void invokeSharedBufferCallback(RefPtr<WebCore::SharedBuffer>&&, CallbackID);
-
 #if ENABLE(REMOTE_INSPECTOR)
     void setAllowsRemoteInspection(bool);
     void setRemoteInspectionNameOverride(const String&);
index 4e43bc7..f253e42 100644 (file)
@@ -494,7 +494,7 @@ messages -> WebPage LegacyReceiver {
 
 #if ENABLE(ATTACHMENT_ELEMENT)
     InsertAttachment(String identifier, struct WebCore::AttachmentDisplayOptions options, String filename, std::optional<String> contentType, IPC::DataReference data, WebKit::CallbackID callbackID)
-    RequestAttachmentData(String identifier, WebKit::CallbackID callbackID)
+    RequestAttachmentInfo(String identifier, WebKit::CallbackID callbackID)
     SetAttachmentDisplayOptions(String identifier, struct WebCore::AttachmentDisplayOptions options, WebKit::CallbackID callbackID)
     SetAttachmentDataAndContentType(String identifier, IPC::DataReference data, std::optional<String> newContentType, std::optional<String> newFilename, WebKit::CallbackID callbackID)
 #endif
index d2c68ba..a5e9192 100644 (file)
@@ -1,5 +1,24 @@
 2018-01-08  Wenson Hsieh  <wenson_hsieh@apple.com>
 
+        [Attachment Support] Expose file name and content type of WKAttachment
+        https://bugs.webkit.org/show_bug.cgi?id=181390
+        <rdar://problem/36336837>
+
+        Reviewed by Tim Horton.
+
+        Adjusts some existing tests in WKAttachmentTests to exercise -requestInfo:.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm:
+        (-[_WKAttachment synchronouslyRequestInfo:]):
+        (-[_WKAttachment synchronouslyRequestData:]):
+
+        Reimplement this in terms of -synchronouslyRequestInfo:.
+
+        (-[_WKAttachment expectRequestedDataToBe:]):
+        (TestWebKitAPI::TEST):
+
+2018-01-08  Wenson Hsieh  <wenson_hsieh@apple.com>
+
         Copying, pasting, and then deleting an attachment element breaks attachment data requests
         https://bugs.webkit.org/show_bug.cgi?id=181365
         <rdar://problem/36340647>
index 6b0f055..8dd3866 100644 (file)
@@ -271,13 +271,13 @@ static _WKAttachmentDisplayOptions *displayOptionsWithMode(_WKAttachmentDisplayM
         *error = resultError.autorelease();
 }
 
-- (NSData *)synchronouslyRequestData:(NSError **)error
+- (_WKAttachmentInfo *)synchronouslyRequestInfo:(NSError **)error
 {
-    __block RetainPtr<NSData> result;
+    __block RetainPtr<_WKAttachmentInfo> result;
     __block RetainPtr<NSError> resultError;
     __block bool done = false;
-    [self requestData:^(NSData *data, NSError *error) {
-        result = data;
+    [self requestInfo:^(_WKAttachmentInfo *info, NSError *error) {
+        result = info;
         resultError = error;
         done = true;
     }];
@@ -290,6 +290,11 @@ static _WKAttachmentDisplayOptions *displayOptionsWithMode(_WKAttachmentDisplayM
     return result.autorelease();
 }
 
+- (NSData *)synchronouslyRequestData:(NSError **)error
+{
+    return [self synchronouslyRequestInfo:error].data;
+}
+
 - (void)synchronouslySetData:(NSData *)data newContentType:(NSString *)newContentType newFilename:(NSString *)newFilename error:(NSError **)error
 {
     __block RetainPtr<NSError> resultError;
@@ -307,13 +312,14 @@ static _WKAttachmentDisplayOptions *displayOptionsWithMode(_WKAttachmentDisplayM
 
 - (void)expectRequestedDataToBe:(NSData *)expectedData
 {
-    NSError *dataRequestError = nil;
-    NSData *observedData = [self synchronouslyRequestData:&dataRequestError];
-    BOOL observedDataIsEqualToExpectedData = [observedData isEqualToData:expectedData] || observedData == expectedData;
+    NSError *requestError = nil;
+    _WKAttachmentInfo *info = [self synchronouslyRequestInfo:&requestError];
+
+    BOOL observedDataIsEqualToExpectedData = [info.data isEqualToData:expectedData] || info.data == expectedData;
     EXPECT_TRUE(observedDataIsEqualToExpectedData);
     if (!observedDataIsEqualToExpectedData) {
-        NSLog(@"Expected data: %@ but observed: %@ for %@", [expectedData shortDescription], [observedData shortDescription], self);
-        NSLog(@"Observed error: %@ while reading data for %@", dataRequestError, self);
+        NSLog(@"Expected data: %@ but observed: %@ for %@", [expectedData shortDescription], [info.data shortDescription], self);
+        NSLog(@"Observed error: %@ while reading data for %@", requestError, self);
     }
 }
 
@@ -430,7 +436,11 @@ TEST(WKAttachmentTests, AttachmentElementInsertion)
         observer.expectAttachmentUpdates(@[ ], @[ firstAttachment.get() ]);
     }
 
-    [firstAttachment expectRequestedDataToBe:testHTMLData()];
+    _WKAttachmentInfo *info = [firstAttachment synchronouslyRequestInfo:nil];
+    EXPECT_TRUE([info.data isEqualToData:testHTMLData()]);
+    EXPECT_TRUE([info.contentType isEqualToString:@"text/html"]);
+    EXPECT_TRUE([info.name isEqualToString:@"foo"]);
+    EXPECT_EQ(info.filePath.length, 0U);
 
     {
         ObserveAttachmentUpdatesForScope scope(webView.get());
@@ -465,7 +475,12 @@ TEST(WKAttachmentTests, AttachmentUpdatesWhenInsertingAndDeletingNewline)
     [webView expectUpdatesAfterCommand:@"InsertParagraph" withArgument:nil expectedRemovals:@[] expectedInsertions:@[]];
 
     [webView expectUpdatesAfterCommand:@"DeleteBackward" withArgument:nil expectedRemovals:@[] expectedInsertions:@[]];
-    [attachment expectRequestedDataToBe:testHTMLData()];
+
+    _WKAttachmentInfo *info = [attachment synchronouslyRequestInfo:nil];
+    EXPECT_TRUE([info.data isEqualToData:testHTMLData()]);
+    EXPECT_TRUE([info.contentType isEqualToString:@"text/plain"]);
+    EXPECT_TRUE([info.name isEqualToString:@"foo.txt"]);
+    EXPECT_EQ(info.filePath.length, 0U);
 
     [webView expectUpdatesAfterCommand:@"DeleteForward" withArgument:nil expectedRemovals:@[attachment.get()] expectedInsertions:@[]];
     [attachment expectRequestedDataToBe:nil];
@@ -623,13 +638,13 @@ TEST(WKAttachmentTests, MultipleSimultaneousAttachmentDataRequests)
     __block RetainPtr<NSData> dataForFirstRequest;
     __block RetainPtr<NSData> dataForSecondRequest;
     __block bool done = false;
-    [attachment requestData:^(NSData *data, NSError *error) {
+    [attachment requestInfo:^(_WKAttachmentInfo *info, NSError *error) {
         EXPECT_TRUE(!error);
-        dataForFirstRequest = data;
+        dataForFirstRequest = info.data;
     }];
-    [attachment requestData:^(NSData *data, NSError *error) {
+    [attachment requestInfo:^(_WKAttachmentInfo *info, NSError *error) {
         EXPECT_TRUE(!error);
-        dataForSecondRequest = data;
+        dataForSecondRequest = info.data;
         done = true;
     }];
 
@@ -1023,6 +1038,11 @@ TEST(WKAttachmentTestsMac, InsertPastedFileURLsAsAttachments)
     EXPECT_WK_STREQ("image/png", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[1].getAttribute('type')"]);
     EXPECT_WK_STREQ("icon.png", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[1].getAttribute('title')"]);
 
+    for (_WKAttachment *attachment in insertedAttachments.get()) {
+        _WKAttachmentInfo *info = [attachment synchronouslyRequestInfo:nil];
+        EXPECT_GT(info.filePath.length, 0U);
+    }
+
     {
         ObserveAttachmentUpdatesForScope observer(webView.get());
         [webView _synchronouslyExecuteEditCommand:@"SelectAll" argument:nil];