Diff
Modified: trunk/Source/WebCore/ChangeLog (225310 => 225311)
--- trunk/Source/WebCore/ChangeLog 2017-11-30 01:50:14 UTC (rev 225310)
+++ trunk/Source/WebCore/ChangeLog 2017-11-30 02:23:44 UTC (rev 225311)
@@ -1,3 +1,76 @@
+2017-11-29 Wenson Hsieh <wenson_hs...@apple.com>
+
+ [Attachment Support] Implement SPI for clients to make an attachment element display in-place
+ https://bugs.webkit.org/show_bug.cgi?id=180153
+ <rdar://problem/35735252>
+
+ Reviewed by Tim Horton.
+
+ Adds SPI support for inserting attachments using in-place display style, and updating display options for
+ existing attachments. See comments below for more detail.
+
+ Tests: WKAttachmentTests.InPlaceImageAttachmentToggleDisplayMode
+ WKAttachmentTests.InPlaceImageAttachmentParagraphInsertion
+ WKAttachmentTests.InPlaceVideoAttachmentInsertionWithinList
+ WKAttachmentTests.InPlacePDFAttachmentCutAndPaste
+
+ * WebCore.xcodeproj/project.pbxproj:
+ * editing/Editor.cpp:
+ (WebCore::Editor::insertAttachment):
+ (WebCore::Editor::insertAttachmentFromFile):
+
+ Update display options for the attachment before inserting into the document.
+
+ * editing/Editor.h:
+ * html/AttachmentTypes.h: Added.
+
+ Add a new header to define the new attachment display types. This lets us avoid importing HTMLAttachmentElement.h
+ and instead just import AttachmentTypes.h in some places in WebKit that only deal with plumbing
+ AttachmentDisplayOptions to the web process.
+
+ (WebCore::AttachmentDisplayOptions::encode const):
+ (WebCore::AttachmentDisplayOptions::decode):
+
+ Support serializing and deserializing attachment display options.
+
+ * html/HTMLAttachmentElement.cpp:
+ (WebCore::HTMLAttachmentElement::setFile):
+
+ Regenerate the shadow root if needed when setting the file.
+
+ (WebCore::HTMLAttachmentElement::updateDisplayMode):
+
+ Introduce a new method to update the display mode of an attachment element. This builds up the shadow root of
+ the attachment if it is displayed in-place.
+
+ (WebCore::HTMLAttachmentElement::ensureInnerImage):
+ (WebCore::HTMLAttachmentElement::ensureInnerVideo):
+
+ Helpers to insert image and video elements into the shadow root if needed, and return the image or video element.
+
+ (WebCore::HTMLAttachmentElement::innerImage const):
+ (WebCore::HTMLAttachmentElement::innerVideo const):
+
+ Helpers to retrieve existing image and video elements in the shadow root.
+
+ (WebCore::HTMLAttachmentElement::populateShadowRootIfNecessary):
+
+ Appends and configures the attachment element's shadow root for inline display, initializing an image or video
+ element or neither, depending on the attachment type.
+
+ * html/HTMLAttachmentElement.h:
+
+ Introduce an AttachmentDisplayOptions struct which mirrors _WKAttachmentDisplayOptions in the WebKit layer. For
+ now, this only contains a display mode enum.
+
+ * platform/audio/ios/AudioSessionIOS.mm:
+
+ Avoid this AVAudioSession assertion when targeting iOS simulator. AVAudioSession always throws this error when
+ setting an audio session category in the simulator, even in a basic test app, since AVFoundation doesn't support
+ audio sessions in the simulator.
+
+ (WebCore::AudioSession::setCategory):
+
2017-11-29 Simon Fraser <simon.fra...@apple.com>
Missing layer content when animating elements on-screen
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (225310 => 225311)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2017-11-30 01:50:14 UTC (rev 225310)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2017-11-30 02:23:44 UTC (rev 225311)
@@ -4613,6 +4613,7 @@
F3ABFE0C130E9DA000E7F7D1 /* InstrumentingAgents.h in Headers */ = {isa = PBXBuildFile; fileRef = F3ABFE0B130E9DA000E7F7D1 /* InstrumentingAgents.h */; };
F3D461491161D53200CA0D09 /* JSErrorHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = F3D461471161D53200CA0D09 /* JSErrorHandler.h */; };
F433E9031DBBDBA200EF0D14 /* StaticPasteboard.h in Headers */ = {isa = PBXBuildFile; fileRef = F433E9021DBBDBA200EF0D14 /* StaticPasteboard.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ F43759B41FCF48FA00100706 /* AttachmentTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = F43759B31FCF48FA00100706 /* AttachmentTypes.h */; settings = {ATTRIBUTES = (Private, ); }; };
F44EBBD91DB5D21400277334 /* StaticRange.h in Headers */ = {isa = PBXBuildFile; fileRef = F44EBBD81DB5D21400277334 /* StaticRange.h */; settings = {ATTRIBUTES = (Private, ); }; };
F45C231E1995B73B00A6E2E3 /* AxisScrollSnapOffsets.h in Headers */ = {isa = PBXBuildFile; fileRef = F45C231C1995B73B00A6E2E3 /* AxisScrollSnapOffsets.h */; settings = {ATTRIBUTES = (Private, ); }; };
F46729281E0DE68500ACC3D8 /* ScrollSnapOffsetsInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = F46729251E0DE5AB00ACC3D8 /* ScrollSnapOffsetsInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -13963,6 +13964,7 @@
F3D461471161D53200CA0D09 /* JSErrorHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSErrorHandler.h; sourceTree = "<group>"; };
F433E9021DBBDBA200EF0D14 /* StaticPasteboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StaticPasteboard.h; sourceTree = "<group>"; };
F433E9041DBBDBC200EF0D14 /* StaticPasteboard.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = StaticPasteboard.cpp; sourceTree = "<group>"; };
+ F43759B31FCF48FA00100706 /* AttachmentTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AttachmentTypes.h; sourceTree = "<group>"; };
F44EBBD61DB5D1B600277334 /* StaticRange.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = StaticRange.idl; sourceTree = "<group>"; };
F44EBBD81DB5D21400277334 /* StaticRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StaticRange.h; sourceTree = "<group>"; };
F44EBBDA1DB5DD9D00277334 /* StaticRange.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StaticRange.cpp; sourceTree = "<group>"; };
@@ -19453,6 +19455,7 @@
97C1F5511228558800EDE616 /* parser */,
4150F9ED12B6E0990008C860 /* shadow */,
B1AD4E7713A12A7200846B27 /* track */,
+ F43759B31FCF48FA00100706 /* AttachmentTypes.h */,
A5F6E16C132ED46E008EDAE3 /* Autocapitalize.cpp */,
A501920C132EBF2E008BFE55 /* Autocapitalize.h */,
A5A7AA42132F0ECC00D3A3C2 /* AutocapitalizeTypes.h */,
@@ -26053,6 +26056,7 @@
FD5686CA13AC180200B69C68 /* AsyncAudioDecoder.h in Headers */,
E1CDE9221501916900862CC5 /* AsyncFileStream.h in Headers */,
0FFD4D6118651FA300512F6E /* AsyncScrollingCoordinator.h in Headers */,
+ F43759B41FCF48FA00100706 /* AttachmentTypes.h in Headers */,
A8C4A80D09D563270003AC8D /* Attr.h in Headers */,
A8C4A80B09D563270003AC8D /* Attribute.h in Headers */,
E4A814DA1C70E10D00BF85AC /* AttributeChangeInvalidation.h in Headers */,
Modified: trunk/Source/WebCore/editing/Editor.cpp (225310 => 225311)
--- trunk/Source/WebCore/editing/Editor.cpp 2017-11-30 01:50:14 UTC (rev 225310)
+++ trunk/Source/WebCore/editing/Editor.cpp 2017-11-30 02:23:44 UTC (rev 225311)
@@ -3791,21 +3791,21 @@
m_insertedAttachmentIdentifiers.clear();
}
-void Editor::insertAttachment(const String& identifier, const String& filename, const String& filepath, std::optional<String> contentType)
+void Editor::insertAttachment(const String& identifier, const AttachmentDisplayOptions& options, const String& filename, const String& filepath, std::optional<String> contentType)
{
if (!contentType)
contentType = File::contentTypeForFile(filename);
- insertAttachmentFromFile(identifier, filename, *contentType, File::create(filepath));
+ insertAttachmentFromFile(identifier, options, filename, *contentType, File::create(filepath));
}
-void Editor::insertAttachment(const String& identifier, const String& filename, Ref<SharedBuffer>&& data, std::optional<String> contentType)
+void Editor::insertAttachment(const String& identifier, const AttachmentDisplayOptions& options, const String& filename, Ref<SharedBuffer>&& data, std::optional<String> contentType)
{
if (!contentType)
contentType = File::contentTypeForFile(filename);
- insertAttachmentFromFile(identifier, filename, *contentType, File::create(Blob::create(data, *contentType), filename));
+ insertAttachmentFromFile(identifier, options, filename, *contentType, File::create(Blob::create(data, *contentType), filename));
}
-void Editor::insertAttachmentFromFile(const String& identifier, const String& filename, const String& contentType, Ref<File>&& file)
+void Editor::insertAttachmentFromFile(const String& identifier, const AttachmentDisplayOptions& options, const String& filename, const String& contentType, Ref<File>&& file)
{
auto attachment = HTMLAttachmentElement::create(HTMLNames::attachmentTag, document());
attachment->setAttribute(HTMLNames::titleAttr, filename);
@@ -3813,6 +3813,7 @@
attachment->setAttribute(HTMLNames::typeAttr, contentType);
attachment->setUniqueIdentifier(identifier);
attachment->setFile(WTFMove(file));
+ attachment->updateDisplayMode(options.mode);
auto fragmentToInsert = document().createDocumentFragment();
fragmentToInsert->appendChild(attachment.get());
Modified: trunk/Source/WebCore/editing/Editor.h (225310 => 225311)
--- trunk/Source/WebCore/editing/Editor.h 2017-11-30 01:50:14 UTC (rev 225310)
+++ trunk/Source/WebCore/editing/Editor.h 2017-11-30 02:23:44 UTC (rev 225311)
@@ -67,7 +67,6 @@
class EditorInternalCommand;
class File;
class Frame;
-class HTMLAttachmentElement;
class HTMLElement;
class HitTestResult;
class KeyboardEvent;
@@ -96,6 +95,11 @@
IgnoreBlockquote,
};
+#if ENABLE(ATTACHMENT_ELEMENT)
+class HTMLAttachmentElement;
+struct AttachmentDisplayOptions;
+#endif
+
enum TemporarySelectionOption : uint8_t {
// By default, no additional options are enabled.
TemporarySelectionOptionDefault = 0,
@@ -503,8 +507,8 @@
bool isGettingDictionaryPopupInfo() const { return m_isGettingDictionaryPopupInfo; }
#if ENABLE(ATTACHMENT_ELEMENT)
- WEBCORE_EXPORT void insertAttachment(const String& identifier, const String& filename, const String& filepath, std::optional<String> contentType = std::nullopt);
- WEBCORE_EXPORT void insertAttachment(const String& identifier, const String& filename, Ref<SharedBuffer>&& data, std::optional<String> contentType = std::nullopt);
+ WEBCORE_EXPORT void insertAttachment(const String& identifier, const AttachmentDisplayOptions&, const String& filename, const String& filepath, std::optional<String> contentType = std::nullopt);
+ WEBCORE_EXPORT void insertAttachment(const String& identifier, const AttachmentDisplayOptions&, const String& filename, Ref<SharedBuffer>&& data, std::optional<String> contentType = std::nullopt);
void didInsertAttachmentElement(HTMLAttachmentElement&);
void didRemoveAttachmentElement(HTMLAttachmentElement&);
#endif
@@ -524,7 +528,7 @@
Document& document() const;
#if ENABLE(ATTACHMENT_ELEMENT)
- void insertAttachmentFromFile(const String& identifier, const String& filename, const String& contentType, Ref<File>&&);
+ void insertAttachmentFromFile(const String& identifier, const AttachmentDisplayOptions&, const String& filename, const String& contentType, Ref<File>&&);
#endif
bool canDeleteRange(Range*) const;
Copied: trunk/Source/WebCore/html/AttachmentTypes.h (from rev 225310, trunk/Source/WebKit/UIProcess/API/APIAttachment.h) (0 => 225311)
--- trunk/Source/WebCore/html/AttachmentTypes.h (rev 0)
+++ trunk/Source/WebCore/html/AttachmentTypes.h 2017-11-30 02:23:44 UTC (rev 225311)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(ATTACHMENT_ELEMENT)
+
+namespace WebCore {
+
+enum class AttachmentDisplayMode {
+ Auto,
+ InPlace,
+ AsIcon
+};
+
+struct AttachmentDisplayOptions {
+ AttachmentDisplayMode mode { AttachmentDisplayMode::Auto };
+
+ template<class Encoder> void encode(Encoder&) const;
+ template<class Decoder> static std::optional<AttachmentDisplayOptions> decode(Decoder&);
+};
+
+template<class Encoder> inline void AttachmentDisplayOptions::encode(Encoder& encoder) const
+{
+ encoder.encodeEnum(mode);
+}
+
+template<class Decoder> inline std::optional<AttachmentDisplayOptions> AttachmentDisplayOptions::decode(Decoder& decoder)
+{
+ AttachmentDisplayMode mode;
+ if (!decoder.decodeEnum(mode))
+ return std::nullopt;
+
+ return {{ mode }};
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(ATTACHMENT_ELEMENT)
Modified: trunk/Source/WebCore/html/HTMLAttachmentElement.cpp (225310 => 225311)
--- trunk/Source/WebCore/html/HTMLAttachmentElement.cpp 2017-11-30 01:50:14 UTC (rev 225310)
+++ trunk/Source/WebCore/html/HTMLAttachmentElement.cpp 2017-11-30 02:23:44 UTC (rev 225311)
@@ -28,14 +28,20 @@
#if ENABLE(ATTACHMENT_ELEMENT)
+#include "DOMURL.h"
+#include "Document.h"
#include "Editor.h"
#include "File.h"
#include "FileReaderLoader.h"
#include "FileReaderLoaderClient.h"
#include "Frame.h"
+#include "HTMLImageElement.h"
#include "HTMLNames.h"
+#include "HTMLVideoElement.h"
+#include "MIMETypeRegistry.h"
#include "RenderAttachment.h"
#include "RenderBlockFlow.h"
+#include "ShadowRoot.h"
#include "SharedBuffer.h"
namespace WebCore {
@@ -113,6 +119,12 @@
if (auto* renderAttachment = attachmentRenderer())
renderAttachment->invalidate();
+
+ if (auto image = innerImage())
+ image->setAttributeWithoutSynchronization(srcAttr, emptyString());
+ if (auto video = innerVideo())
+ video->setAttributeWithoutSynchronization(srcAttr, emptyString());
+ populateShadowRootIfNecessary();
}
RenderAttachment* HTMLAttachmentElement::attachmentRenderer() const
@@ -174,6 +186,82 @@
return attributeWithoutSynchronization(webkitattachmentpathAttr);
}
+void HTMLAttachmentElement::updateDisplayMode(AttachmentDisplayMode mode)
+{
+ mode = mode == AttachmentDisplayMode::Auto ? defaultDisplayMode() : mode;
+
+ switch (mode) {
+ case AttachmentDisplayMode::InPlace:
+ populateShadowRootIfNecessary();
+ setInlineStyleProperty(CSSPropertyWebkitAppearance, CSSValueNone, true);
+ setInlineStyleProperty(CSSPropertyDisplay, CSSValueInlineBlock, true);
+ break;
+ case AttachmentDisplayMode::AsIcon:
+ removeInlineStyleProperty(CSSPropertyWebkitAppearance);
+ removeInlineStyleProperty(CSSPropertyDisplay);
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+
+ invalidateStyleAndRenderersForSubtree();
+}
+
+Ref<HTMLImageElement> HTMLAttachmentElement::ensureInnerImage()
+{
+ if (auto image = innerImage())
+ return *image;
+
+ auto image = HTMLImageElement::create(document());
+ ensureUserAgentShadowRoot().appendChild(image);
+ return image;
+}
+
+Ref<HTMLVideoElement> HTMLAttachmentElement::ensureInnerVideo()
+{
+ if (auto video = innerVideo())
+ return *video;
+
+ auto video = HTMLVideoElement::create(document());
+ ensureUserAgentShadowRoot().appendChild(video);
+ return video;
+}
+
+RefPtr<HTMLImageElement> HTMLAttachmentElement::innerImage() const
+{
+ if (auto root = userAgentShadowRoot())
+ return childrenOfType<HTMLImageElement>(*root).first();
+ return nullptr;
+}
+
+RefPtr<HTMLVideoElement> HTMLAttachmentElement::innerVideo() const
+{
+ if (auto root = userAgentShadowRoot())
+ return childrenOfType<HTMLVideoElement>(*root).first();
+ return nullptr;
+}
+
+void HTMLAttachmentElement::populateShadowRootIfNecessary()
+{
+ auto mimeType = attachmentType();
+ if (!m_file || mimeType.isEmpty())
+ return;
+
+ if (MIMETypeRegistry::isSupportedImageMIMEType(mimeType) || MIMETypeRegistry::isPDFMIMEType(mimeType)) {
+ auto image = ensureInnerImage();
+ if (image->attributeWithoutSynchronization(srcAttr).isEmpty())
+ image->setAttributeWithoutSynchronization(srcAttr, DOMURL::createObjectURL(document(), *m_file));
+
+ } else if (MIMETypeRegistry::isSupportedMediaMIMEType(mimeType)) {
+ auto video = ensureInnerVideo();
+ if (video->attributeWithoutSynchronization(srcAttr).isEmpty()) {
+ video->setAttributeWithoutSynchronization(srcAttr, DOMURL::createObjectURL(document(), *m_file));
+ video->setAttributeWithoutSynchronization(controlsAttr, emptyString());
+ }
+ }
+}
+
void HTMLAttachmentElement::requestData(Function<void(RefPtr<SharedBuffer>&&)>&& callback)
{
if (m_file)
Modified: trunk/Source/WebCore/html/HTMLAttachmentElement.h (225310 => 225311)
--- trunk/Source/WebCore/html/HTMLAttachmentElement.h 2017-11-30 01:50:14 UTC (rev 225310)
+++ trunk/Source/WebCore/html/HTMLAttachmentElement.h 2017-11-30 02:23:44 UTC (rev 225311)
@@ -27,6 +27,7 @@
#if ENABLE(ATTACHMENT_ELEMENT)
+#include "AttachmentTypes.h"
#include "HTMLElement.h"
namespace WebCore {
@@ -33,6 +34,8 @@
class AttachmentDataReader;
class File;
+class HTMLImageElement;
+class HTMLVideoElement;
class RenderAttachment;
class SharedBuffer;
@@ -47,6 +50,8 @@
WEBCORE_EXPORT String uniqueIdentifier() const;
void setUniqueIdentifier(const String&);
+ WEBCORE_EXPORT void updateDisplayMode(AttachmentDisplayMode);
+
InsertedIntoAncestorResult insertedIntoAncestor(InsertionType, ContainerNode&) final;
void removedFromAncestor(RemovalType, ContainerNode&) final;
@@ -64,7 +69,21 @@
virtual ~HTMLAttachmentElement();
RenderPtr<RenderElement> createElementRenderer(RenderStyle&&, const RenderTreePosition&) final;
+ Ref<HTMLImageElement> ensureInnerImage();
+ Ref<HTMLVideoElement> ensureInnerVideo();
+ RefPtr<HTMLImageElement> innerImage() const;
+ RefPtr<HTMLVideoElement> innerVideo() const;
+ void populateShadowRootIfNecessary();
+
+ AttachmentDisplayMode defaultDisplayMode() const
+ {
+ // FIXME: For now, all attachment elements automatically display using a file icon.
+ // In a followup patch, we'll change the default behavior to use in-place presentation
+ // for certain image MIME types.
+ return AttachmentDisplayMode::AsIcon;
+ }
+
bool shouldSelectOnMouseDown() final {
#if PLATFORM(IOS)
return false;
Modified: trunk/Source/WebCore/platform/audio/ios/AudioSessionIOS.mm (225310 => 225311)
--- trunk/Source/WebCore/platform/audio/ios/AudioSessionIOS.mm 2017-11-30 01:50:14 UTC (rev 225310)
+++ trunk/Source/WebCore/platform/audio/ios/AudioSessionIOS.mm 2017-11-30 02:23:44 UTC (rev 225311)
@@ -141,7 +141,9 @@
NSError *error = nil;
[[AVAudioSession sharedInstance] setCategory:categoryString mode:categoryMode options:options error:&error];
+#if !PLATFORM(IOS_SIMULATOR)
ASSERT(!error);
+#endif
}
AudioSession::CategoryType AudioSession::category() const
Modified: trunk/Source/WebKit/ChangeLog (225310 => 225311)
--- trunk/Source/WebKit/ChangeLog 2017-11-30 01:50:14 UTC (rev 225310)
+++ trunk/Source/WebKit/ChangeLog 2017-11-30 02:23:44 UTC (rev 225311)
@@ -1,3 +1,49 @@
+2017-11-29 Wenson Hsieh <wenson_hs...@apple.com>
+
+ [Attachment Support] Implement SPI for clients to make an attachment element display in-place
+ https://bugs.webkit.org/show_bug.cgi?id=180153
+ <rdar://problem/35735252>
+
+ Reviewed by Tim Horton.
+
+ Add new WebKit SPI, -[_WKAttachment setDisplayOptions:completion:], and add plumbing for attachment display
+ options to the web content process. Changes covered by 4 new API tests.
+
+ * Scripts/webkit/messages.py:
+ (headers_for_type):
+ * UIProcess/API/APIAttachment.cpp:
+ (API::Attachment::setDisplayOptions):
+ * UIProcess/API/APIAttachment.h:
+ * UIProcess/API/Cocoa/WKWebView.mm:
+ (-[WKWebView _insertAttachmentWithFilename:contentType:data:options:completion:]):
+
+ Respect given display options when inserting a new attachment.
+
+ * UIProcess/API/Cocoa/_WKAttachment.h:
+ * UIProcess/API/Cocoa/_WKAttachment.mm:
+ (-[_WKAttachmentDisplayOptions coreDisplayOptions]):
+
+ Introduce a helper to convert from the Cocoa _WKAttachmentDisplayOptions object to platform-agnostic
+ AttachmentDisplayOptions.
+
+ (-[_WKAttachment setDisplayOptions:completion:]):
+ (WebKit::if): Deleted.
+ * UIProcess/API/Cocoa/_WKAttachmentInternal.h:
+ * UIProcess/WebPageProxy.cpp:
+ (WebKit::WebPageProxy::insertAttachment):
+ (WebKit::WebPageProxy::setAttachmentDisplayOptions):
+ * UIProcess/WebPageProxy.h:
+ * WebProcess/WebPage/WebPage.cpp:
+ (WebKit::WebPage::insertAttachment):
+ (WebKit::WebPage::requestAttachmentData):
+ (WebKit::WebPage::setAttachmentDisplayOptions):
+ (WebKit::WebPage::attachmentElementWithIdentifier const):
+
+ Pull common logic to retrieve an attachment element matching a given identifier out into a helper.
+
+ * WebProcess/WebPage/WebPage.h:
+ * WebProcess/WebPage/WebPage.messages.in:
+
2017-11-29 Brent Fulgham <bfulg...@apple.com>
Part 2: Adopt updated NSKeyed[Un]Archiver API when available
Modified: trunk/Source/WebKit/Scripts/webkit/messages.py (225310 => 225311)
--- trunk/Source/WebKit/Scripts/webkit/messages.py 2017-11-30 01:50:14 UTC (rev 225310)
+++ trunk/Source/WebKit/Scripts/webkit/messages.py 2017-11-30 02:23:44 UTC (rev 225311)
@@ -361,6 +361,7 @@
special_cases = {
'String': ['<wtf/text/WTFString.h>'],
'PAL::SessionID': ['<pal/SessionID.h>'],
+ 'WebCore::AttachmentDisplayOptions': ['<WebCore/AttachmentTypes.h>'],
'WebCore::AutoplayEventFlags': ['<WebCore/AutoplayEvent.h>'],
'WebCore::ExceptionDetails': ['<WebCore/JSDOMExceptionHandling.h>'],
'WebCore::FileChooserSettings': ['<WebCore/FileChooser.h>'],
Modified: trunk/Source/WebKit/UIProcess/API/APIAttachment.cpp (225310 => 225311)
--- trunk/Source/WebKit/UIProcess/API/APIAttachment.cpp 2017-11-30 01:50:14 UTC (rev 225310)
+++ trunk/Source/WebKit/UIProcess/API/APIAttachment.cpp 2017-11-30 02:23:44 UTC (rev 225311)
@@ -26,6 +26,7 @@
#include "config.h"
#include "APIAttachment.h"
+#include <WebCore/AttachmentTypes.h>
#include <WebCore/SharedBuffer.h>
#include <wtf/BlockPtr.h>
#include <wtf/text/WTFString.h>
@@ -55,4 +56,12 @@
callback(nullptr, WebKit::CallbackBase::Error::OwnerWasInvalidated);
}
+void Attachment::setDisplayOptions(WebCore::AttachmentDisplayOptions options, Function<void(WebKit::CallbackBase::Error)>&& callback)
+{
+ if (m_webPage)
+ m_webPage->setAttachmentDisplayOptions(m_identifier, options, WTFMove(callback));
+ else
+ callback(WebKit::CallbackBase::Error::OwnerWasInvalidated);
}
+
+}
Modified: trunk/Source/WebKit/UIProcess/API/APIAttachment.h (225310 => 225311)
--- trunk/Source/WebKit/UIProcess/API/APIAttachment.h 2017-11-30 01:50:14 UTC (rev 225310)
+++ trunk/Source/WebKit/UIProcess/API/APIAttachment.h 2017-11-30 02:23:44 UTC (rev 225311)
@@ -34,6 +34,7 @@
namespace WebCore {
class SharedBuffer;
+struct AttachmentDisplayOptions;
}
namespace WebKit {
@@ -49,6 +50,7 @@
const WTF::String& identifier() const { return m_identifier; }
void requestData(Function<void(RefPtr<WebCore::SharedBuffer>, WebKit::CallbackBase::Error)>&&);
+ void setDisplayOptions(WebCore::AttachmentDisplayOptions, Function<void(WebKit::CallbackBase::Error)>&&);
private:
explicit Attachment(const WTF::String& identifier, WebKit::WebPageProxy&);
Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm (225310 => 225311)
--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm 2017-11-30 01:50:14 UTC (rev 225310)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm 2017-11-30 02:23:44 UTC (rev 225311)
@@ -90,6 +90,7 @@
#import "_WKSessionStateInternal.h"
#import "_WKVisitedLinkStoreInternal.h"
#import "_WKWebsitePoliciesInternal.h"
+#import <WebCore/AttachmentTypes.h>
#import <WebCore/GraphicsContextCG.h>
#import <WebCore/IOSurface.h>
#import <WebCore/JSDOMBinding.h>
@@ -4193,8 +4194,9 @@
#if ENABLE(ATTACHMENT_ELEMENT)
auto identifier = createCanonicalUUIDString();
+ auto coreOptions = options ? options.coreDisplayOptions : WebCore::AttachmentDisplayOptions { };
auto buffer = WebCore::SharedBuffer::create(data);
- _page->insertAttachment(identifier, filename, contentType.length ? std::optional<String> { contentType } : std::nullopt, buffer.get(), [capturedHandler = makeBlockPtr(completionHandler), capturedBuffer = buffer.copyRef()] (WebKit::CallbackBase::Error error) {
+ _page->insertAttachment(identifier, coreOptions, filename, contentType.length ? std::optional<String> { contentType } : std::nullopt, buffer.get(), [capturedHandler = makeBlockPtr(completionHandler), capturedBuffer = buffer.copyRef()] (WebKit::CallbackBase::Error error) {
if (capturedHandler)
capturedHandler(error == WebKit::CallbackBase::Error::None);
});
Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/_WKAttachment.h (225310 => 225311)
--- trunk/Source/WebKit/UIProcess/API/Cocoa/_WKAttachment.h 2017-11-30 01:50:14 UTC (rev 225310)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/_WKAttachment.h 2017-11-30 02:23:44 UTC (rev 225311)
@@ -38,12 +38,12 @@
WK_CLASS_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA))
@interface _WKAttachmentDisplayOptions : NSObject
@property (nonatomic) _WKAttachmentDisplayMode mode;
-@property (nonatomic) BOOL expandsImageToMaximumWidth;
@end
WK_CLASS_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA))
@interface _WKAttachment : NSObject
- (void)requestData:(void(^)(NSData *, NSError *))completionHandler;
+- (void)setDisplayOptions:(_WKAttachmentDisplayOptions *)options completion:(void(^)(NSError *))completionHandler;
@end
#endif
Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/_WKAttachment.mm (225310 => 225311)
--- trunk/Source/WebKit/UIProcess/API/Cocoa/_WKAttachment.mm 2017-11-30 01:50:14 UTC (rev 225310)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/_WKAttachment.mm 2017-11-30 02:23:44 UTC (rev 225311)
@@ -31,6 +31,7 @@
#import "APIAttachment.h"
#import "WKErrorPrivate.h"
#import "_WKAttachmentInternal.h"
+#import <WebCore/AttachmentTypes.h>
#import <WebCore/SharedBuffer.h>
#import <wtf/BlockPtr.h>
@@ -40,13 +41,32 @@
- (instancetype)init
{
- if (self = [super init]) {
+ if (self = [super init])
_mode = _WKAttachmentDisplayModeAuto;
- _expandsImageToMaximumWidth = NO;
- }
+
return self;
}
+- (WebCore::AttachmentDisplayOptions)coreDisplayOptions
+{
+ WebCore::AttachmentDisplayMode mode;
+ switch (self.mode) {
+ case _WKAttachmentDisplayModeAuto:
+ mode = WebCore::AttachmentDisplayMode::Auto;
+ break;
+ case _WKAttachmentDisplayModeAsIcon:
+ mode = WebCore::AttachmentDisplayMode::AsIcon;
+ break;
+ case _WKAttachmentDisplayModeInPlace:
+ mode = WebCore::AttachmentDisplayMode::InPlace;
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ mode = WebCore::AttachmentDisplayMode::Auto;
+ }
+ return { mode };
+}
+
@end
@implementation _WKAttachment
@@ -74,6 +94,20 @@
});
}
+- (void)setDisplayOptions:(_WKAttachmentDisplayOptions *)options completion:(void(^)(NSError *))completionHandler
+{
+ auto coreOptions = options ? options.coreDisplayOptions : WebCore::AttachmentDisplayOptions { };
+ _attachment->setDisplayOptions(coreOptions, [capturedBlock = makeBlockPtr(completionHandler)] (CallbackBase::Error error) {
+ if (!capturedBlock)
+ return;
+
+ if (error == CallbackBase::Error::None)
+ capturedBlock(nil);
+ else
+ capturedBlock([NSError errorWithDomain:WKErrorDomain code:1 userInfo:nil]);
+ });
+}
+
- (NSString *)uniqueIdentifier
{
return _attachment->identifier();
Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/_WKAttachmentInternal.h (225310 => 225311)
--- trunk/Source/WebKit/UIProcess/API/Cocoa/_WKAttachmentInternal.h 2017-11-30 01:50:14 UTC (rev 225310)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/_WKAttachmentInternal.h 2017-11-30 02:23:44 UTC (rev 225311)
@@ -38,6 +38,10 @@
}
+@interface _WKAttachmentDisplayOptions ()
+@property (nonatomic, readonly) WebCore::AttachmentDisplayOptions coreDisplayOptions;
+@end
+
@interface _WKAttachment () <WKObject> {
@package
API::ObjectStorage<API::Attachment> _attachment;
Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (225310 => 225311)
--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp 2017-11-30 01:50:14 UTC (rev 225310)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp 2017-11-30 02:23:44 UTC (rev 225311)
@@ -28,6 +28,7 @@
#include "WebPageProxy.h"
#include "APIArray.h"
+#include "APIAttachment.h"
#include "APIContextMenuClient.h"
#include "APIFindClient.h"
#include "APIFindMatchesClient.h"
@@ -113,6 +114,7 @@
#include "WebURLSchemeHandler.h"
#include "WebUserContentControllerProxy.h"
#include "WebsiteDataStore.h"
+#include <WebCore/AttachmentTypes.h>
#include <WebCore/BitmapImage.h>
#include <WebCore/DiagnosticLoggingClient.h>
#include <WebCore/DiagnosticLoggingKeys.h>
@@ -7147,7 +7149,7 @@
#if ENABLE(ATTACHMENT_ELEMENT)
-void WebPageProxy::insertAttachment(const String& identifier, const String& filename, std::optional<String> contentType, SharedBuffer& data, Function<void(CallbackBase::Error)>&& callback)
+void WebPageProxy::insertAttachment(const String& identifier, const AttachmentDisplayOptions& options, const String& filename, std::optional<String> contentType, SharedBuffer& data, Function<void(CallbackBase::Error)>&& callback)
{
if (!isValid()) {
callback(CallbackBase::Error::OwnerWasInvalidated);
@@ -7155,7 +7157,7 @@
}
auto callbackID = m_callbacks.put(WTFMove(callback), m_process->throttler().backgroundActivityToken());
- m_process->send(Messages::WebPage::InsertAttachment(identifier, filename, contentType, IPC::SharedBufferDataReference { &data }, callbackID), m_pageID);
+ 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)
@@ -7169,6 +7171,17 @@
m_process->send(Messages::WebPage::RequestAttachmentData(identifier, callbackID), m_pageID);
}
+void WebPageProxy::setAttachmentDisplayOptions(const String& identifier, AttachmentDisplayOptions options, Function<void(CallbackBase::Error)>&& callback)
+{
+ if (!isValid()) {
+ callback(CallbackBase::Error::OwnerWasInvalidated);
+ return;
+ }
+
+ auto callbackID = m_callbacks.put(WTFMove(callback), m_process->throttler().backgroundActivityToken());
+ m_process->send(Messages::WebPage::SetAttachmentDisplayOptions(identifier, options, callbackID), m_pageID);
+}
+
void WebPageProxy::didInsertAttachment(const String& identifier)
{
m_pageClient.didInsertAttachment(identifier);
Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (225310 => 225311)
--- trunk/Source/WebKit/UIProcess/WebPageProxy.h 2017-11-30 01:50:14 UTC (rev 225310)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h 2017-11-30 02:23:44 UTC (rev 225311)
@@ -176,6 +176,12 @@
using FloatBoxExtent = RectEdges<float>;
}
+#if ENABLE(ATTACHMENT_ELEMENT)
+namespace WebCore {
+struct AttachmentDisplayOptions;
+}
+#endif
+
#if PLATFORM(GTK)
typedef GtkWidget* PlatformWidget;
#endif
@@ -1216,8 +1222,9 @@
void requestStorageAccess(String&& subFrameHost, String&& topFrameHost, uint64_t webProcessContextId);
#if ENABLE(ATTACHMENT_ELEMENT)
- void insertAttachment(const String& identifier, const String& filename, std::optional<String> contentType, WebCore::SharedBuffer& data, Function<void(CallbackBase::Error)>&&);
+ 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 setAttachmentDisplayOptions(const String& identifier, WebCore::AttachmentDisplayOptions, Function<void(CallbackBase::Error)>&&);
#endif
private:
Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (225310 => 225311)
--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp 2017-11-30 01:50:14 UTC (rev 225310)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp 2017-11-30 02:23:44 UTC (rev 225311)
@@ -5767,23 +5767,16 @@
#if ENABLE(ATTACHMENT_ELEMENT)
-void WebPage::insertAttachment(const String& identifier, const String& filename, std::optional<String> contentType, const IPC::DataReference& data, CallbackID callbackID)
+void WebPage::insertAttachment(const String& identifier, const AttachmentDisplayOptions& options, const String& filename, std::optional<String> contentType, const IPC::DataReference& data, CallbackID callbackID)
{
auto& frame = m_page->focusController().focusedOrMainFrame();
- frame.editor().insertAttachment(identifier, filename, SharedBuffer::create(data.data(), data.size()), contentType);
+ frame.editor().insertAttachment(identifier, options, filename, SharedBuffer::create(data.data(), data.size()), contentType);
send(Messages::WebPageProxy::VoidCallback(callbackID));
}
void WebPage::requestAttachmentData(const String& identifier, CallbackID callbackID)
{
- // FIXME: We don't currently handle attachment data requests for attachment elements in subframes.
- auto* frame = mainFrame();
- if (!frame || !frame->document()) {
- invokeSharedBufferCallback({ }, callbackID);
- return;
- }
-
- auto attachment = frame->document()->attachmentForIdentifier(identifier);
+ auto attachment = attachmentElementWithIdentifier(identifier);
if (!attachment) {
invokeSharedBufferCallback({ }, callbackID);
return;
@@ -5797,6 +5790,25 @@
});
}
+void WebPage::setAttachmentDisplayOptions(const String& identifier, const AttachmentDisplayOptions& options, CallbackID callbackID)
+{
+ if (auto attachment = attachmentElementWithIdentifier(identifier)) {
+ attachment->document().updateLayout();
+ attachment->updateDisplayMode(options.mode);
+ }
+ send(Messages::WebPageProxy::VoidCallback(callbackID));
+}
+
+RefPtr<HTMLAttachmentElement> WebPage::attachmentElementWithIdentifier(const String& identifier) const
+{
+ // FIXME: Handle attachment elements in subframes too as well.
+ auto* frame = mainFrame();
+ if (!frame || !frame->document())
+ return nullptr;
+
+ return frame->document()->attachmentForIdentifier(identifier);
+}
+
#endif // ENABLE(ATTACHMENT_ELEMENT)
} // namespace WebKit
Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.h (225310 => 225311)
--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.h 2017-11-30 01:50:14 UTC (rev 225310)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.h 2017-11-30 02:23:44 UTC (rev 225311)
@@ -152,6 +152,10 @@
enum class TextIndicatorPresentationTransition : uint8_t;
+#if ENABLE(ATTACHMENT_ELEMENT)
+class HTMLAttachmentElement;
+struct AttachmentDisplayOptions;
+#endif
}
namespace WebKit {
@@ -1011,8 +1015,9 @@
void storageAccessResponse(bool wasGranted, uint64_t contextId);
#if ENABLE(ATTACHMENT_ELEMENT)
- void insertAttachment(const String& identifier, const String& filename, std::optional<String> contentType, const IPC::DataReference&, CallbackID);
+ 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 setAttachmentDisplayOptions(const String& identifier, const WebCore::AttachmentDisplayOptions&, CallbackID);
#endif
private:
@@ -1327,6 +1332,10 @@
RetainPtr<CFDataRef> pdfSnapshotAtSize(const WebCore::IntRect&, const WebCore::IntSize& bitmapSize, SnapshotOptions);
#endif
+#if ENABLE(ATTACHMENT_ELEMENT)
+ RefPtr<WebCore::HTMLAttachmentElement> attachmentElementWithIdentifier(const String& identifier) const;
+#endif
+
uint64_t m_pageID;
std::unique_ptr<WebCore::Page> m_page;
Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in (225310 => 225311)
--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in 2017-11-30 01:50:14 UTC (rev 225310)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in 2017-11-30 02:23:44 UTC (rev 225311)
@@ -486,7 +486,8 @@
StorageAccessResponse(bool wasGranted, uint64_t contextId)
#if ENABLE(ATTACHMENT_ELEMENT)
- InsertAttachment(String identifier, String filename, std::optional<String> contentType, IPC::DataReference data, WebKit::CallbackID callbackID)
+ 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)
+ SetAttachmentDisplayOptions(String identifier, struct WebCore::AttachmentDisplayOptions options, WebKit::CallbackID callbackID)
#endif
}
Modified: trunk/Tools/ChangeLog (225310 => 225311)
--- trunk/Tools/ChangeLog 2017-11-30 01:50:14 UTC (rev 225310)
+++ trunk/Tools/ChangeLog 2017-11-30 02:23:44 UTC (rev 225311)
@@ -1,3 +1,24 @@
+2017-11-29 Wenson Hsieh <wenson_hs...@apple.com>
+
+ [Attachment Support] Implement SPI for clients to make an attachment element display in-place
+ https://bugs.webkit.org/show_bug.cgi?id=180153
+ <rdar://problem/35735252>
+
+ Reviewed by Tim Horton.
+
+ Adds new API tests to cover inserting in-place attachments and updating the display mode of existing attachments,
+ as well as performing a few editing operations (paragraph insertion, cut/paste, list insertion) on attachment
+ elements.
+
+ * TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm:
+ (platformAttachmentIconElementSize):
+ (testVideoData):
+ (testPDFData):
+ (displayOptionsWithMode):
+ (-[TestWKWebView waitForAttachmentElementSizeToBecome:]):
+ (-[_WKAttachment synchronouslySetDisplayOptions:error:]):
+ (TestWebKitAPI::TEST):
+
2017-11-29 Simon Fraser <simon.fra...@apple.com>
API test fix after r225288.
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm (225310 => 225311)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm 2017-11-30 01:50:14 UTC (rev 225310)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm 2017-11-30 02:23:44 UTC (rev 225311)
@@ -27,6 +27,7 @@
#import "PlatformUtilities.h"
#import "TestWKWebView.h"
+#import <WebKit/WKWebViewPrivate.h>
#import <WebKit/WebKit.h>
#import <WebKit/WebKitPrivate.h>
#import <wtf/RetainPtr.h>
@@ -33,6 +34,15 @@
#if WK_API_ENABLED
+CGSize platformAttachmentIconElementSize()
+{
+#if PLATFORM(IOS)
+ return CGSizeMake(160, 119);
+#else
+ return CGSizeMake(61, 89);
+#endif
+}
+
@interface AttachmentUpdateObserver : NSObject <WKUIDelegatePrivate>
@property (nonatomic, readonly) NSArray *inserted;
@property (nonatomic, readonly) NSArray *removed;
@@ -139,6 +149,25 @@
return [NSData dataWithContentsOfURL:url];
}
+static NSData *testVideoData()
+{
+ NSURL *url = "" mainBundle] URLForResource:@"test" withExtension:@"mp4" subdirectory:@"TestWebKitAPI.resources"];
+ return [NSData dataWithContentsOfURL:url];
+}
+
+static NSData *testPDFData()
+{
+ NSURL *url = "" mainBundle] URLForResource:@"test" withExtension:@"pdf" subdirectory:@"TestWebKitAPI.resources"];
+ return [NSData dataWithContentsOfURL:url];
+}
+
+static _WKAttachmentDisplayOptions *displayOptionsWithMode(_WKAttachmentDisplayMode mode)
+{
+ _WKAttachmentDisplayOptions *options = [[[_WKAttachmentDisplayOptions alloc] init] autorelease];
+ options.mode = mode;
+ return options;
+}
+
@implementation TestWKWebView (AttachmentTesting)
- (BOOL)_synchronouslyExecuteEditCommand:(NSString *)command argument:(NSString *)argument
@@ -163,6 +192,22 @@
return attachment.autorelease();
}
+- (void)waitForAttachmentElementSizeToBecome:(CGSize)expectedSize
+{
+ while ([[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantPast]]) {
+ __block bool doneEvaluatingScript = false;
+ __block BOOL sizeIsEqual = NO;
+ [self evaluateJavaScript:@"r = document.querySelector('attachment').getBoundingClientRect(); [r.width, r.height]" completionHandler:^(NSArray<NSNumber *> *sizeResult, NSError *) {
+ CGSize observedSize { sizeResult.firstObject.floatValue, sizeResult.lastObject.floatValue };
+ sizeIsEqual = CGSizeEqualToSize(expectedSize, observedSize);
+ doneEvaluatingScript = true;
+ }];
+ TestWebKitAPI::Util::run(&doneEvaluatingScript);
+ if (sizeIsEqual)
+ break;
+ }
+}
+
- (NSString *)valueOfAttribute:(NSString *)attributeName forQuerySelector:(NSString *)querySelector
{
return [self stringByEvaluatingJavaScript:[NSString stringWithFormat:@"document.querySelector('%@').getAttribute('%@')", querySelector, attributeName]];
@@ -188,6 +233,21 @@
@implementation _WKAttachment (AttachmentTesting)
+- (void)synchronouslySetDisplayOptions:(_WKAttachmentDisplayOptions *)options error:(NSError **)error
+{
+ __block RetainPtr<NSError> resultError;
+ __block bool done = false;
+ [self setDisplayOptions:options completion:^(NSError *error) {
+ resultError = retainPtr(error);
+ done = true;
+ }];
+
+ TestWebKitAPI::Util::run(&done);
+
+ if (error)
+ *error = resultError.autorelease();
+}
+
- (NSData *)synchronouslyRequestData:(NSError **)error
{
__block RetainPtr<NSData> result;
@@ -432,6 +492,92 @@
EXPECT_TRUE([dataForSecondRequest isEqualToData:htmlData.get()]);
}
+TEST(WKAttachmentTests, InPlaceImageAttachmentToggleDisplayMode)
+{
+ auto webView = webViewForTestingAttachments();
+ RetainPtr<NSData> imageData = testImageData();
+ RetainPtr<_WKAttachment> attachment;
+ {
+ ObserveAttachmentUpdatesForScope observer(webView.get());
+ attachment = retainPtr([webView synchronouslyInsertAttachmentWithFilename:@"icon.png" contentType:@"image/png" data:imageData.get() options:displayOptionsWithMode(_WKAttachmentDisplayModeInPlace)]);
+ observer.expectAttachmentUpdates(@[], @[attachment.get()]);
+ [attachment expectRequestedDataToBe:imageData.get()];
+ [webView waitForAttachmentElementSizeToBecome:CGSizeMake(215, 174)];
+ }
+
+ [attachment synchronouslySetDisplayOptions:displayOptionsWithMode(_WKAttachmentDisplayModeAsIcon) error:nil];
+ [attachment expectRequestedDataToBe:imageData.get()];
+ [webView waitForAttachmentElementSizeToBecome:platformAttachmentIconElementSize()];
+
+ [attachment synchronouslySetDisplayOptions:displayOptionsWithMode(_WKAttachmentDisplayModeInPlace) error:nil];
+ [attachment expectRequestedDataToBe:imageData.get()];
+ [webView waitForAttachmentElementSizeToBecome:CGSizeMake(215, 174)];
+}
+
+TEST(WKAttachmentTests, InPlaceImageAttachmentParagraphInsertion)
+{
+ auto webView = webViewForTestingAttachments();
+ RetainPtr<NSData> imageData = testImageData();
+ RetainPtr<_WKAttachment> attachment;
+ {
+ ObserveAttachmentUpdatesForScope observer(webView.get());
+ attachment = retainPtr([webView synchronouslyInsertAttachmentWithFilename:@"icon.png" contentType:@"image/png" data:imageData.get() options:displayOptionsWithMode(_WKAttachmentDisplayModeInPlace)]);
+ observer.expectAttachmentUpdates(@[], @[attachment.get()]);
+ }
+ [webView expectUpdatesAfterCommand:@"InsertParagraph" withArgument:nil expectedRemovals:@[] expectedInsertions:@[]];
+ [webView expectUpdatesAfterCommand:@"DeleteBackward" withArgument:nil expectedRemovals:@[] expectedInsertions:@[]];
+ [webView stringByEvaluatingJavaScript:@"getSelection().collapse(document.body)"];
+ [webView expectUpdatesAfterCommand:@"InsertParagraph" withArgument:nil expectedRemovals:@[] expectedInsertions:@[]];
+ [webView expectUpdatesAfterCommand:@"DeleteBackward" withArgument:nil expectedRemovals:@[] expectedInsertions:@[]];
+
+ [attachment expectRequestedDataToBe:imageData.get()];
+ [webView waitForAttachmentElementSizeToBecome:CGSizeMake(215, 174)];
+
+ [webView expectUpdatesAfterCommand:@"DeleteForward" withArgument:nil expectedRemovals:@[attachment.get()] expectedInsertions:@[]];
+}
+
+TEST(WKAttachmentTests, InPlaceVideoAttachmentInsertionWithinList)
+{
+ auto webView = webViewForTestingAttachments();
+ RetainPtr<NSData> videoData = testVideoData();
+ RetainPtr<_WKAttachment> attachment;
+
+ [webView _synchronouslyExecuteEditCommand:@"InsertOrderedList" argument:nil];
+ {
+ ObserveAttachmentUpdatesForScope observer(webView.get());
+ attachment = retainPtr([webView synchronouslyInsertAttachmentWithFilename:@"test.mp4" contentType:@"video/mp4" data:videoData.get() options:displayOptionsWithMode(_WKAttachmentDisplayModeInPlace)]);
+ observer.expectAttachmentUpdates(@[], @[attachment.get()]);
+ }
+ [webView waitForAttachmentElementSizeToBecome:CGSizeMake(320, 240)];
+
+ [webView expectUpdatesAfterCommand:@"DeleteBackward" withArgument:nil expectedRemovals:@[attachment.get()] expectedInsertions:@[]];
+ [webView expectUpdatesAfterCommand:@"Undo" withArgument:nil expectedRemovals:@[] expectedInsertions:@[attachment.get()]];
+ [webView expectUpdatesAfterCommand:@"InsertOrderedList" withArgument:nil expectedRemovals:@[] expectedInsertions:@[]];
+
+ [webView waitForAttachmentElementSizeToBecome:CGSizeMake(320, 240)];
+ [attachment expectRequestedDataToBe:videoData.get()];
+}
+
+TEST(WKAttachmentTests, InPlacePDFAttachmentCutAndPaste)
+{
+ auto webView = webViewForTestingAttachments();
+ RetainPtr<NSData> pdfData = testPDFData();
+ RetainPtr<_WKAttachment> attachment;
+ {
+ ObserveAttachmentUpdatesForScope observer(webView.get());
+ attachment = retainPtr([webView synchronouslyInsertAttachmentWithFilename:@"test.pdf" contentType:@"application/pdf" data:pdfData.get() options:displayOptionsWithMode(_WKAttachmentDisplayModeInPlace)]);
+ observer.expectAttachmentUpdates(@[], @[attachment.get()]);
+ [webView waitForAttachmentElementSizeToBecome:CGSizeMake(130, 29)];
+ }
+
+ [webView _synchronouslyExecuteEditCommand:@"SelectAll" argument:nil];
+ [webView expectUpdatesAfterCommand:@"Cut" withArgument:nil expectedRemovals:@[attachment.get()] expectedInsertions:@[]];
+
+ [webView expectUpdatesAfterCommand:@"Paste" withArgument:nil expectedRemovals:@[] expectedInsertions:@[attachment.get()]];
+ [webView waitForAttachmentElementSizeToBecome:CGSizeMake(130, 29)];
+ [attachment expectRequestedDataToBe:pdfData.get()];
+}
+
} // namespace TestWebKitAPI
#endif // WK_API_ENABLED