Title: [224593] trunk
Revision
224593
Author
wenson_hs...@apple.com
Date
2017-11-08 13:10:00 -0800 (Wed, 08 Nov 2017)

Log Message

[Attachment Support] Implement delegate hooks for attachment element insertion and removal
https://bugs.webkit.org/show_bug.cgi?id=179016
<rdar://problem/35250890>

Reviewed by Tim Horton.

Source/WebCore:

Relanding this patch with a tweaked API test. WKAttachmentTests.AttachmentUpdatesWhenChangingFontStyles, in its
original form, hit a debug assertion and exposed an existing bug related to EditingStyles and text decoration.
After some investigation, this debug assertion is unrelated to the attachment logic introduced here; see
<https://bugs.webkit.org/show_bug.cgi?id=179431> for additional analysis, and several proposed fixes.

* editing/Editor.cpp:
(WebCore::Editor::respondToChangedSelection):
(WebCore::Editor::editorUIUpdateTimerFired):
(WebCore::Editor::scheduleEditorUIUpdate):
(WebCore::Editor::didInsertAttachmentElement):
(WebCore::Editor::didRemoveAttachmentElement):
(WebCore::Editor::notifyClientOfAttachmentUpdates):
(WebCore::Editor::insertAttachmentFromFile):
* editing/Editor.h:
* html/HTMLAttachmentElement.cpp:
(WebCore::HTMLAttachmentElement::HTMLAttachmentElement):
(WebCore::HTMLAttachmentElement::insertedIntoAncestor):
(WebCore::HTMLAttachmentElement::removedFromAncestor):
(WebCore::HTMLAttachmentElement::uniqueIdentifier const):
(WebCore::HTMLAttachmentElement::setUniqueIdentifier):
* html/HTMLAttachmentElement.h:
* html/HTMLAttributeNames.in:
* page/EditorClient.h:
(WebCore::EditorClient::didInsertAttachment):
(WebCore::EditorClient::didRemoveAttachment):

Source/WebKit:

See WebCore/ChangeLog for more details.

* UIProcess/API/Cocoa/WKUIDelegatePrivate.h:
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _didInsertAttachment:]):
(-[WKWebView _didRemoveAttachment:]):
* UIProcess/API/Cocoa/WKWebViewInternal.h:
* UIProcess/Cocoa/PageClientImplCocoa.h:
* UIProcess/Cocoa/PageClientImplCocoa.mm:
(WebKit::PageClientImplCocoa::didInsertAttachment):
(WebKit::PageClientImplCocoa::didRemoveAttachment):
* UIProcess/PageClient.h:
(WebKit::PageClient::didInsertAttachment):
(WebKit::PageClient::didRemoveAttachment):
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::didInsertAttachment):
(WebKit::WebPageProxy::didRemoveAttachment):
* UIProcess/WebPageProxy.h:
* UIProcess/WebPageProxy.messages.in:
* WebProcess/WebCoreSupport/WebEditorClient.cpp:
(WebKit::WebEditorClient::didInsertAttachment):
(WebKit::WebEditorClient::didRemoveAttachment):
* WebProcess/WebCoreSupport/WebEditorClient.h:

Tools:

See WebCore/ChangeLog for more details.

* TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm:
(-[AttachmentUpdateObserver init]):
(-[AttachmentUpdateObserver inserted]):
(-[AttachmentUpdateObserver removed]):
(-[AttachmentUpdateObserver _webView:didInsertAttachment:]):
(-[AttachmentUpdateObserver _webView:didRemoveAttachment:]):
(TestWebKitAPI::ObserveAttachmentUpdatesForScope::ObserveAttachmentUpdatesForScope):
(TestWebKitAPI::ObserveAttachmentUpdatesForScope::~ObserveAttachmentUpdatesForScope):
(TestWebKitAPI::ObserveAttachmentUpdatesForScope::observer const):
(TestWebKitAPI::ObserveAttachmentUpdatesForScope::expectAttachmentUpdates):
(-[TestWKWebView _synchronouslyExecuteEditCommand:argument:]):
(-[TestWKWebView expectUpdatesAfterCommand:withArgument:expectedRemovals:expectedInsertions:]):
(TestWebKitAPI::TEST):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (224592 => 224593)


--- trunk/Source/WebCore/ChangeLog	2017-11-08 20:42:15 UTC (rev 224592)
+++ trunk/Source/WebCore/ChangeLog	2017-11-08 21:10:00 UTC (rev 224593)
@@ -1,3 +1,37 @@
+2017-11-08  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [Attachment Support] Implement delegate hooks for attachment element insertion and removal
+        https://bugs.webkit.org/show_bug.cgi?id=179016
+        <rdar://problem/35250890>
+
+        Reviewed by Tim Horton.
+
+        Relanding this patch with a tweaked API test. WKAttachmentTests.AttachmentUpdatesWhenChangingFontStyles, in its
+        original form, hit a debug assertion and exposed an existing bug related to EditingStyles and text decoration.
+        After some investigation, this debug assertion is unrelated to the attachment logic introduced here; see
+        <https://bugs.webkit.org/show_bug.cgi?id=179431> for additional analysis, and several proposed fixes.
+
+        * editing/Editor.cpp:
+        (WebCore::Editor::respondToChangedSelection):
+        (WebCore::Editor::editorUIUpdateTimerFired):
+        (WebCore::Editor::scheduleEditorUIUpdate):
+        (WebCore::Editor::didInsertAttachmentElement):
+        (WebCore::Editor::didRemoveAttachmentElement):
+        (WebCore::Editor::notifyClientOfAttachmentUpdates):
+        (WebCore::Editor::insertAttachmentFromFile):
+        * editing/Editor.h:
+        * html/HTMLAttachmentElement.cpp:
+        (WebCore::HTMLAttachmentElement::HTMLAttachmentElement):
+        (WebCore::HTMLAttachmentElement::insertedIntoAncestor):
+        (WebCore::HTMLAttachmentElement::removedFromAncestor):
+        (WebCore::HTMLAttachmentElement::uniqueIdentifier const):
+        (WebCore::HTMLAttachmentElement::setUniqueIdentifier):
+        * html/HTMLAttachmentElement.h:
+        * html/HTMLAttributeNames.in:
+        * page/EditorClient.h:
+        (WebCore::EditorClient::didInsertAttachment):
+        (WebCore::EditorClient::didRemoveAttachment):
+
 2017-11-08  Chris Dumez  <cdu...@apple.com>
 
         Simplify ServiceWorkerContainer::jobResolvedWithRegistration()

Modified: trunk/Source/WebCore/editing/Editor.cpp (224592 => 224593)


--- trunk/Source/WebCore/editing/Editor.cpp	2017-11-08 20:42:15 UTC (rev 224592)
+++ trunk/Source/WebCore/editing/Editor.cpp	2017-11-08 21:10:00 UTC (rev 224593)
@@ -3428,7 +3428,7 @@
     m_editorUIUpdateTimerShouldCheckSpellingAndGrammar = options & FrameSelection::CloseTyping
         && !(options & FrameSelection::SpellCorrectionTriggered);
     m_editorUIUpdateTimerWasTriggeredByDictation = options & FrameSelection::DictationTriggered;
-    m_editorUIUpdateTimer.startOneShot(0_s);
+    scheduleEditorUIUpdate();
 }
 
 #if ENABLE(TELEPHONE_NUMBER_DETECTION) && !PLATFORM(IOS)
@@ -3601,6 +3601,10 @@
         m_alternativeTextController->respondToChangedSelection(oldSelection);
 
     m_oldSelectionForEditorUIUpdate = m_frame.selection().selection();
+
+#if ENABLE(ATTACHMENT_ELEMENT)
+    notifyClientOfAttachmentUpdates();
+#endif
 }
 
 static Node* findFirstMarkable(Node* node)
@@ -3733,8 +3737,48 @@
     return TextIterator::subrange(*contextRange, result.location, result.length);
 }
 
+void Editor::scheduleEditorUIUpdate()
+{
+    m_editorUIUpdateTimer.startOneShot(0_s);
+}
+
 #if ENABLE(ATTACHMENT_ELEMENT)
 
+void Editor::didInsertAttachmentElement(HTMLAttachmentElement& attachment)
+{
+    auto identifier = attachment.uniqueIdentifier();
+    if (identifier.isEmpty())
+        return;
+
+    if (!m_removedAttachmentIdentifiers.take(identifier))
+        m_insertedAttachmentIdentifiers.add(identifier);
+    scheduleEditorUIUpdate();
+}
+
+void Editor::didRemoveAttachmentElement(HTMLAttachmentElement& attachment)
+{
+    auto identifier = attachment.uniqueIdentifier();
+    if (identifier.isEmpty())
+        return;
+
+    if (!m_insertedAttachmentIdentifiers.take(identifier))
+        m_removedAttachmentIdentifiers.add(identifier);
+    scheduleEditorUIUpdate();
+}
+
+void Editor::notifyClientOfAttachmentUpdates()
+{
+    if (auto* editorClient = client()) {
+        for (auto& identifier : m_removedAttachmentIdentifiers)
+            editorClient->didRemoveAttachment(identifier);
+        for (auto& identifier : m_insertedAttachmentIdentifiers)
+            editorClient->didInsertAttachment(identifier);
+    }
+
+    m_removedAttachmentIdentifiers.clear();
+    m_insertedAttachmentIdentifiers.clear();
+}
+
 void Editor::insertAttachment(const String& identifier, const String& filename, const String& filepath, std::optional<String> contentType)
 {
     if (!contentType)
@@ -3751,7 +3795,7 @@
 
 void Editor::insertAttachmentFromFile(const String& identifier, const String& filename, const String& contentType, Ref<File>&& file)
 {
-    auto attachment = HTMLAttachmentElement::create(HTMLNames::attachmentTag, document(), identifier);
+    auto attachment = HTMLAttachmentElement::create(HTMLNames::attachmentTag, document());
     attachment->setAttribute(HTMLNames::titleAttr, filename);
     attachment->setAttribute(HTMLNames::subtitleAttr, fileSizeDescription(file->size()));
     attachment->setAttribute(HTMLNames::typeAttr, contentType);

Modified: trunk/Source/WebCore/editing/Editor.h (224592 => 224593)


--- trunk/Source/WebCore/editing/Editor.h	2017-11-08 20:42:15 UTC (rev 224592)
+++ trunk/Source/WebCore/editing/Editor.h	2017-11-08 21:10:00 UTC (rev 224593)
@@ -503,6 +503,8 @@
 #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);
+    void didInsertAttachmentElement(HTMLAttachmentElement&);
+    void didRemoveAttachmentElement(HTMLAttachmentElement&);
 #endif
 
 private:
@@ -550,6 +552,12 @@
     static RefPtr<SharedBuffer> dataInRTFFormat(NSAttributedString *);
 #endif
 
+    void scheduleEditorUIUpdate();
+
+#if ENABLE(ATTACHMENT_ELEMENT)
+    void notifyClientOfAttachmentUpdates();
+#endif
+
     void postTextStateChangeNotificationForCut(const String&, const VisibleSelection&);
 
     Frame& m_frame;
@@ -569,6 +577,11 @@
     EditorParagraphSeparator m_defaultParagraphSeparator { EditorParagraphSeparatorIsDiv };
     bool m_overwriteModeEnabled { false };
 
+#if ENABLE(ATTACHMENT_ELEMENT)
+    HashSet<String> m_insertedAttachmentIdentifiers;
+    HashSet<String> m_removedAttachmentIdentifiers;
+#endif
+
     VisibleSelection m_oldSelectionForEditorUIUpdate;
     Timer m_editorUIUpdateTimer;
     bool m_editorUIUpdateTimerShouldCheckSpellingAndGrammar { false };

Modified: trunk/Source/WebCore/html/HTMLAttachmentElement.cpp (224592 => 224593)


--- trunk/Source/WebCore/html/HTMLAttachmentElement.cpp	2017-11-08 20:42:15 UTC (rev 224592)
+++ trunk/Source/WebCore/html/HTMLAttachmentElement.cpp	2017-11-08 21:10:00 UTC (rev 224593)
@@ -33,24 +33,17 @@
 #include "Frame.h"
 #include "HTMLNames.h"
 #include "RenderAttachment.h"
-#include <wtf/UUID.h>
 
 namespace WebCore {
 
 using namespace HTMLNames;
 
-HTMLAttachmentElement::HTMLAttachmentElement(const QualifiedName& tagName, Document& document, const String& identifier)
+HTMLAttachmentElement::HTMLAttachmentElement(const QualifiedName& tagName, Document& document)
     : HTMLElement(tagName, document)
-    , m_uniqueIdentifier(identifier)
 {
     ASSERT(hasTagName(attachmentTag));
 }
 
-HTMLAttachmentElement::HTMLAttachmentElement(const QualifiedName& tagName, Document& document)
-    : HTMLAttachmentElement(tagName, document, createCanonicalUUIDString())
-{
-}
-
 HTMLAttachmentElement::~HTMLAttachmentElement() = default;
 
 Ref<HTMLAttachmentElement> HTMLAttachmentElement::create(const QualifiedName& tagName, Document& document)
@@ -58,11 +51,6 @@
     return adoptRef(*new HTMLAttachmentElement(tagName, document));
 }
 
-Ref<HTMLAttachmentElement> HTMLAttachmentElement::create(const QualifiedName& tagName, Document& document, const String& identifier)
-{
-    return adoptRef(*new HTMLAttachmentElement(tagName, document, identifier));
-}
-
 RenderPtr<RenderElement> HTMLAttachmentElement::createElementRenderer(RenderStyle&& style, const RenderTreePosition&)
 {
     return createRenderer<RenderAttachment>(*this, WTFMove(style));
@@ -81,6 +69,25 @@
         renderer->invalidate();
 }
 
+Node::InsertedIntoAncestorResult HTMLAttachmentElement::insertedIntoAncestor(InsertionType type, ContainerNode& ancestor)
+{
+    auto result = HTMLElement::insertedIntoAncestor(type, ancestor);
+    if (auto* frame = document().frame()) {
+        if (type.connectedToDocument)
+            frame->editor().didInsertAttachmentElement(*this);
+    }
+    return result;
+}
+
+void HTMLAttachmentElement::removedFromAncestor(RemovalType type, ContainerNode& ancestor)
+{
+    HTMLElement::removedFromAncestor(type, ancestor);
+    if (auto* frame = document().frame()) {
+        if (type.disconnectedFromDocument)
+            frame->editor().didRemoveAttachmentElement(*this);
+    }
+}
+
 void HTMLAttachmentElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
 {
     if (name == progressAttr || name == subtitleAttr || name == titleAttr || name == typeAttr) {
@@ -91,6 +98,16 @@
     HTMLElement::parseAttribute(name, value);
 }
 
+String HTMLAttachmentElement::uniqueIdentifier() const
+{
+    return attributeWithoutSynchronization(HTMLNames::webkitattachmentidAttr);
+}
+
+void HTMLAttachmentElement::setUniqueIdentifier(const String& identifier)
+{
+    setAttributeWithoutSynchronization(HTMLNames::webkitattachmentidAttr, identifier);
+}
+
 String HTMLAttachmentElement::attachmentTitle() const
 {
     auto& title = attributeWithoutSynchronization(titleAttr);

Modified: trunk/Source/WebCore/html/HTMLAttachmentElement.h (224592 => 224593)


--- trunk/Source/WebCore/html/HTMLAttachmentElement.h	2017-11-08 20:42:15 UTC (rev 224592)
+++ trunk/Source/WebCore/html/HTMLAttachmentElement.h	2017-11-08 21:10:00 UTC (rev 224593)
@@ -37,14 +37,16 @@
 class HTMLAttachmentElement final : public HTMLElement {
 public:
     static Ref<HTMLAttachmentElement> create(const QualifiedName&, Document&);
-    static Ref<HTMLAttachmentElement> create(const QualifiedName&, Document&, const String& identifier);
 
     WEBCORE_EXPORT File* file() const;
     void setFile(File*);
 
-    WEBCORE_EXPORT String uniqueIdentifier() const { return m_uniqueIdentifier; }
-    void setUniqueIdentifier(const String& identifier) { m_uniqueIdentifier = identifier; }
+    WEBCORE_EXPORT String uniqueIdentifier() const;
+    void setUniqueIdentifier(const String&);
 
+    InsertedIntoAncestorResult insertedIntoAncestor(InsertionType, ContainerNode&) final;
+    void removedFromAncestor(RemovalType, ContainerNode&) final;
+
     WEBCORE_EXPORT String attachmentTitle() const;
     String attachmentType() const;
 
@@ -52,7 +54,6 @@
 
 private:
     HTMLAttachmentElement(const QualifiedName&, Document&);
-    HTMLAttachmentElement(const QualifiedName&, Document&, const String& identifier);
     virtual ~HTMLAttachmentElement();
 
     RenderPtr<RenderElement> createElementRenderer(RenderStyle&&, const RenderTreePosition&) final;
@@ -68,7 +69,6 @@
     void parseAttribute(const QualifiedName&, const AtomicString&) final;
     
     RefPtr<File> m_file;
-    String m_uniqueIdentifier;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/html/HTMLAttributeNames.in (224592 => 224593)


--- trunk/Source/WebCore/html/HTMLAttributeNames.in	2017-11-08 20:42:15 UTC (rev 224592)
+++ trunk/Source/WebCore/html/HTMLAttributeNames.in	2017-11-08 21:10:00 UTC (rev 224593)
@@ -381,6 +381,7 @@
 vlink
 vspace
 webkitallowfullscreen
+webkitattachmentid
 webkitattachmentpath
 webkitdirectory
 width

Modified: trunk/Source/WebCore/page/EditorClient.h (224592 => 224593)


--- trunk/Source/WebCore/page/EditorClient.h	2017-11-08 20:42:15 UTC (rev 224592)
+++ trunk/Source/WebCore/page/EditorClient.h	2017-11-08 21:10:00 UTC (rev 224593)
@@ -72,6 +72,11 @@
     virtual void didApplyStyle() = 0;
     virtual bool shouldMoveRangeAfterDelete(Range*, Range*) = 0;
 
+#if ENABLE(ATTACHMENT_ELEMENT)
+    virtual void didInsertAttachment(const String&) { }
+    virtual void didRemoveAttachment(const String&) { }
+#endif
+
     virtual void didBeginEditing() = 0;
     virtual void respondToChangedContents() = 0;
     virtual void respondToChangedSelection(Frame*) = 0;

Modified: trunk/Source/WebKit/ChangeLog (224592 => 224593)


--- trunk/Source/WebKit/ChangeLog	2017-11-08 20:42:15 UTC (rev 224592)
+++ trunk/Source/WebKit/ChangeLog	2017-11-08 21:10:00 UTC (rev 224593)
@@ -1,3 +1,35 @@
+2017-11-08  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [Attachment Support] Implement delegate hooks for attachment element insertion and removal
+        https://bugs.webkit.org/show_bug.cgi?id=179016
+        <rdar://problem/35250890>
+
+        Reviewed by Tim Horton.
+
+        See WebCore/ChangeLog for more details.
+
+        * UIProcess/API/Cocoa/WKUIDelegatePrivate.h:
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView _didInsertAttachment:]):
+        (-[WKWebView _didRemoveAttachment:]):
+        * UIProcess/API/Cocoa/WKWebViewInternal.h:
+        * UIProcess/Cocoa/PageClientImplCocoa.h:
+        * UIProcess/Cocoa/PageClientImplCocoa.mm:
+        (WebKit::PageClientImplCocoa::didInsertAttachment):
+        (WebKit::PageClientImplCocoa::didRemoveAttachment):
+        * UIProcess/PageClient.h:
+        (WebKit::PageClient::didInsertAttachment):
+        (WebKit::PageClient::didRemoveAttachment):
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::didInsertAttachment):
+        (WebKit::WebPageProxy::didRemoveAttachment):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebPageProxy.messages.in:
+        * WebProcess/WebCoreSupport/WebEditorClient.cpp:
+        (WebKit::WebEditorClient::didInsertAttachment):
+        (WebKit::WebEditorClient::didRemoveAttachment):
+        * WebProcess/WebCoreSupport/WebEditorClient.h:
+
 2017-11-08  Carlos Garcia Campos  <cgar...@igalia.com>
 
         REGRESSION(r223773): [GTK] WebKitWebInspector bring-to-front signal is emitted right after open-window

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegatePrivate.h (224592 => 224593)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegatePrivate.h	2017-11-08 20:42:15 UTC (rev 224592)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegatePrivate.h	2017-11-08 21:10:00 UTC (rev 224593)
@@ -110,6 +110,9 @@
 - (void)_webView:(WKWebView *)webView runBeforeUnloadConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler WK_API_AVAILABLE(macosx(10.13), ios(11.0));
 - (void)_webView:(WKWebView *)webView editorStateDidChange:(NSDictionary *)editorState WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
 
+- (void)_webView:(WKWebView *)webView didRemoveAttachment:(_WKAttachment *)attachment WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
+- (void)_webView:(WKWebView *)webView didInsertAttachment:(_WKAttachment *)attachment WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
+
 #if TARGET_OS_IPHONE
 - (BOOL)_webView:(WKWebView *)webView shouldIncludeAppLinkActionsForElement:(_WKActivatedElementInfo *)element WK_API_AVAILABLE(ios(9.0));
 - (NSArray *)_webView:(WKWebView *)webView actionsForElement:(_WKActivatedElementInfo *)element defaultActions:(NSArray<_WKElementAction *> *)defaultActions;

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm (224592 => 224593)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm	2017-11-08 20:42:15 UTC (rev 224592)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm	2017-11-08 21:10:00 UTC (rev 224593)
@@ -1197,6 +1197,24 @@
         [uiDelegate _webView:self editorStateDidChange:dictionaryRepresentationForEditorState(_page->editorState())];
 }
 
+#if ENABLE(ATTACHMENT_ELEMENT)
+
+- (void)_didInsertAttachment:(NSString *)identifier
+{
+    id <WKUIDelegatePrivate> uiDelegate = (id <WKUIDelegatePrivate>)self.UIDelegate;
+    if ([uiDelegate respondsToSelector:@selector(_webView:didInsertAttachment:)])
+        [uiDelegate _webView:self didInsertAttachment:[wrapper(API::Attachment::create(identifier, *_page).leakRef()) autorelease]];
+}
+
+- (void)_didRemoveAttachment:(NSString *)identifier
+{
+    id <WKUIDelegatePrivate> uiDelegate = (id <WKUIDelegatePrivate>)self.UIDelegate;
+    if ([uiDelegate respondsToSelector:@selector(_webView:didRemoveAttachment:)])
+        [uiDelegate _webView:self didRemoveAttachment:[wrapper(API::Attachment::create(identifier, *_page).leakRef()) autorelease]];
+}
+
+#endif // ENABLE(ATTACHMENT_ELEMENT)
+
 #pragma mark iOS-specific methods
 
 #if PLATFORM(IOS)

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewInternal.h (224592 => 224593)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewInternal.h	2017-11-08 20:42:15 UTC (rev 224592)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewInternal.h	2017-11-08 21:10:00 UTC (rev 224593)
@@ -148,6 +148,11 @@
 @property (nonatomic, readonly) UIEdgeInsets _computedUnobscuredSafeAreaInset;
 #endif
 
+#if ENABLE(ATTACHMENT_ELEMENT)
+- (void)_didRemoveAttachment:(NSString *)identifier;
+- (void)_didInsertAttachment:(NSString *)identifier;
+#endif
+
 - (WKPageRef)_pageForTesting;
 - (WebKit::WebPageProxy*)_page;
 

Modified: trunk/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.h (224592 => 224593)


--- trunk/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.h	2017-11-08 20:42:15 UTC (rev 224592)
+++ trunk/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.h	2017-11-08 21:10:00 UTC (rev 224593)
@@ -37,6 +37,12 @@
         : m_webView(webView) { }
     void isPlayingAudioWillChange() final;
     void isPlayingAudioDidChange() final;
+
+#if ENABLE(ATTACHMENT_ELEMENT)
+    void didInsertAttachment(const String& identifier) final;
+    void didRemoveAttachment(const String& identifier) final;
+#endif
+
 protected:
     WKWebView *m_webView;
 };

Modified: trunk/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.mm (224592 => 224593)


--- trunk/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.mm	2017-11-08 20:42:15 UTC (rev 224592)
+++ trunk/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.mm	2017-11-08 21:10:00 UTC (rev 224593)
@@ -26,7 +26,7 @@
 #import "config.h"
 #import "PageClientImplCocoa.h"
 
-#import "WKWebViewPrivate.h"
+#import "WKWebViewInternal.h"
 
 namespace WebKit {
 
@@ -43,5 +43,27 @@
     [m_webView didChangeValueForKey:NSStringFromSelector(@selector(_isPlayingAudio))];
 #endif
 }
+
+#if ENABLE(ATTACHMENT_ELEMENT)
+
+void PageClientImplCocoa::didInsertAttachment(const String& identifier)
+{
+#if WK_API_ENABLED
+    [m_webView _didInsertAttachment:identifier];
+#else
+    UNUSED_PARAM(identifier);
+#endif
+}
+
+void PageClientImplCocoa::didRemoveAttachment(const String& identifier)
+{
+#if WK_API_ENABLED
+    [m_webView _didRemoveAttachment:identifier];
+#else
+    UNUSED_PARAM(identifier);
+#endif
+}
+
+#endif
     
 }

Modified: trunk/Source/WebKit/UIProcess/PageClient.h (224592 => 224593)


--- trunk/Source/WebKit/UIProcess/PageClient.h	2017-11-08 20:42:15 UTC (rev 224592)
+++ trunk/Source/WebKit/UIProcess/PageClient.h	2017-11-08 21:10:00 UTC (rev 224593)
@@ -384,6 +384,11 @@
     virtual void didChangeDataInteractionCaretRect(const WebCore::IntRect& previousCaretRect, const WebCore::IntRect& caretRect) = 0;
 #endif
 
+#if ENABLE(ATTACHMENT_ELEMENT)
+    virtual void didInsertAttachment(const String& identifier) { }
+    virtual void didRemoveAttachment(const String& identifier) { }
+#endif
+
 #if PLATFORM(GTK) || PLATFORM(WPE)
     virtual JSGlobalContextRef _javascript_GlobalContext() { return nullptr; }
 #endif

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (224592 => 224593)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2017-11-08 20:42:15 UTC (rev 224592)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2017-11-08 21:10:00 UTC (rev 224593)
@@ -7113,6 +7113,16 @@
     m_process->send(Messages::WebPage::InsertAttachment(identifier, filename, contentType, IPC::SharedBufferDataReference { &data }, callbackID), m_pageID);
 }
 
+void WebPageProxy::didInsertAttachment(const String& identifier)
+{
+    m_pageClient.didInsertAttachment(identifier);
+}
+
+void WebPageProxy::didRemoveAttachment(const String& identifier)
+{
+    m_pageClient.didRemoveAttachment(identifier);
+}
+
 #endif // ENABLE(ATTACHMENT_ELEMENT)
 
 } // namespace WebKit

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (224592 => 224593)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.h	2017-11-08 20:42:15 UTC (rev 224592)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h	2017-11-08 21:10:00 UTC (rev 224593)
@@ -1637,6 +1637,11 @@
 
     void stopAllURLSchemeTasks();
 
+#if ENABLE(ATTACHMENT_ELEMENT)
+    void didInsertAttachment(const String& identifier);
+    void didRemoveAttachment(const String& identifier);
+#endif
+
     PageClient& m_pageClient;
     Ref<API::PageConfiguration> m_configuration;
 

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in (224592 => 224593)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in	2017-11-08 20:42:15 UTC (rev 224592)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in	2017-11-08 21:10:00 UTC (rev 224593)
@@ -498,4 +498,9 @@
     StopURLSchemeTask(uint64_t handlerIdentifier, uint64_t taskIdentifier)
 
     RequestStorageAccess(String subFrameHost, String topFrameHost, uint64_t contextID)
+
+#if ENABLE(ATTACHMENT_ELEMENT)
+    DidInsertAttachment(String identifier)
+    DidRemoveAttachment(String identifier)
+#endif
 }

Modified: trunk/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.cpp (224592 => 224593)


--- trunk/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.cpp	2017-11-08 20:42:15 UTC (rev 224592)
+++ trunk/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.cpp	2017-11-08 21:10:00 UTC (rev 224593)
@@ -157,6 +157,20 @@
     return result;
 }
 
+#if ENABLE(ATTACHMENT_ELEMENT)
+
+void WebEditorClient::didInsertAttachment(const String& identifier)
+{
+    m_page->send(Messages::WebPageProxy::DidInsertAttachment(identifier));
+}
+
+void WebEditorClient::didRemoveAttachment(const String& identifier)
+{
+    m_page->send(Messages::WebPageProxy::DidRemoveAttachment(identifier));
+}
+
+#endif
+
 void WebEditorClient::didApplyStyle()
 {
     m_page->didApplyStyle();

Modified: trunk/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.h (224592 => 224593)


--- trunk/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.h	2017-11-08 20:42:15 UTC (rev 224592)
+++ trunk/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.h	2017-11-08 21:10:00 UTC (rev 224593)
@@ -59,6 +59,11 @@
     void didApplyStyle() final;
     bool shouldMoveRangeAfterDelete(WebCore::Range*, WebCore::Range*) final;
 
+#if ENABLE(ATTACHMENT_ELEMENT)
+    void didInsertAttachment(const String& identifier) final;
+    void didRemoveAttachment(const String& identifier) final;
+#endif
+
     void didBeginEditing() final;
     void respondToChangedContents() final;
     void respondToChangedSelection(WebCore::Frame*) final;

Modified: trunk/Tools/ChangeLog (224592 => 224593)


--- trunk/Tools/ChangeLog	2017-11-08 20:42:15 UTC (rev 224592)
+++ trunk/Tools/ChangeLog	2017-11-08 21:10:00 UTC (rev 224593)
@@ -1,3 +1,27 @@
+2017-11-08  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [Attachment Support] Implement delegate hooks for attachment element insertion and removal
+        https://bugs.webkit.org/show_bug.cgi?id=179016
+        <rdar://problem/35250890>
+
+        Reviewed by Tim Horton.
+
+        See WebCore/ChangeLog for more details.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm:
+        (-[AttachmentUpdateObserver init]):
+        (-[AttachmentUpdateObserver inserted]):
+        (-[AttachmentUpdateObserver removed]):
+        (-[AttachmentUpdateObserver _webView:didInsertAttachment:]):
+        (-[AttachmentUpdateObserver _webView:didRemoveAttachment:]):
+        (TestWebKitAPI::ObserveAttachmentUpdatesForScope::ObserveAttachmentUpdatesForScope):
+        (TestWebKitAPI::ObserveAttachmentUpdatesForScope::~ObserveAttachmentUpdatesForScope):
+        (TestWebKitAPI::ObserveAttachmentUpdatesForScope::observer const):
+        (TestWebKitAPI::ObserveAttachmentUpdatesForScope::expectAttachmentUpdates):
+        (-[TestWKWebView _synchronouslyExecuteEditCommand:argument:]):
+        (-[TestWKWebView expectUpdatesAfterCommand:withArgument:expectedRemovals:expectedInsertions:]):
+        (TestWebKitAPI::TEST):
+
 2017-11-08  Carlos Garcia Campos  <cgar...@igalia.com>
 
         Web Inspector: use JSON::{Array,Object,Value} instead of Inspector{Array,Object,Value}

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm (224592 => 224593)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm	2017-11-08 20:42:15 UTC (rev 224592)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm	2017-11-08 21:10:00 UTC (rev 224593)
@@ -33,6 +33,90 @@
 
 #if WK_API_ENABLED
 
+@interface AttachmentUpdateObserver : NSObject <WKUIDelegatePrivate>
+@property (nonatomic, readonly) NSArray *inserted;
+@property (nonatomic, readonly) NSArray *removed;
+@end
+
+@implementation AttachmentUpdateObserver {
+    RetainPtr<NSMutableArray<_WKAttachment *>> _inserted;
+    RetainPtr<NSMutableArray<_WKAttachment *>> _removed;
+}
+
+- (instancetype)init
+{
+    if (self = [super init]) {
+        _inserted = adoptNS([[NSMutableArray alloc] init]);
+        _removed = adoptNS([[NSMutableArray alloc] init]);
+    }
+    return self;
+}
+
+- (NSArray<_WKAttachment *> *)inserted
+{
+    return _inserted.get();
+}
+
+- (NSArray<_WKAttachment *> *)removed
+{
+    return _removed.get();
+}
+
+- (void)_webView:(WKWebView *)webView didInsertAttachment:(_WKAttachment *)attachment
+{
+    [_inserted addObject:attachment];
+}
+
+- (void)_webView:(WKWebView *)webView didRemoveAttachment:(_WKAttachment *)attachment
+{
+    [_removed addObject:attachment];
+}
+
+@end
+
+namespace TestWebKitAPI {
+
+class ObserveAttachmentUpdatesForScope {
+public:
+    ObserveAttachmentUpdatesForScope(TestWKWebView *webView)
+        : m_webView(webView)
+    {
+        m_previousDelegate = retainPtr(webView.UIDelegate);
+        m_observer = adoptNS([[AttachmentUpdateObserver alloc] init]);
+        webView.UIDelegate = m_observer.get();
+    }
+
+    ~ObserveAttachmentUpdatesForScope()
+    {
+        [m_webView setUIDelegate:m_previousDelegate.get()];
+    }
+
+    AttachmentUpdateObserver *observer() const { return m_observer.get(); }
+
+    void expectAttachmentUpdates(NSArray<_WKAttachment *> *removed, NSArray<_WKAttachment *> *inserted)
+    {
+        BOOL removedAttachmentsMatch = [observer().removed isEqual:removed];
+        if (!removedAttachmentsMatch)
+            NSLog(@"Expected removed attachments: %@ to match %@.", observer().removed, removed);
+        EXPECT_TRUE(removedAttachmentsMatch);
+
+        BOOL insertedAttachmentsMatch = [observer().inserted isEqual:inserted];
+        if (!insertedAttachmentsMatch)
+            NSLog(@"Expected inserted attachments: %@ to match %@.", observer().inserted, inserted);
+        EXPECT_TRUE(insertedAttachmentsMatch);
+    }
+
+private:
+    RetainPtr<AttachmentUpdateObserver> m_observer;
+    RetainPtr<TestWKWebView> m_webView;
+    RetainPtr<id> m_previousDelegate;
+};
+
+}
+
+@interface TestWKWebView (AttachmentTesting)
+@end
+
 static RetainPtr<TestWKWebView> webViewForTestingAttachments()
 {
     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
@@ -57,6 +141,18 @@
 
 @implementation TestWKWebView (AttachmentTesting)
 
+- (BOOL)_synchronouslyExecuteEditCommand:(NSString *)command argument:(NSString *)argument
+{
+    __block bool done = false;
+    __block bool success;
+    [self _executeEditCommand:command argument:argument completion:^(BOOL completionSuccess) {
+        done = true;
+        success = completionSuccess;
+    }];
+    TestWebKitAPI::Util::run(&done);
+    return success;
+}
+
 - (_WKAttachment *)synchronouslyInsertAttachmentWithFilename:(NSString *)filename contentType:(NSString *)contentType data:(NSData *)data options:(_WKAttachmentDisplayOptions *)options
 {
     __block bool done = false;
@@ -72,6 +168,13 @@
     return [self stringByEvaluatingJavaScript:[NSString stringWithFormat:@"document.querySelector('%@').getAttribute('%@')", querySelector, attributeName]];
 }
 
+- (void)expectUpdatesAfterCommand:(NSString *)command withArgument:(NSString *)argument expectedRemovals:(NSArray<_WKAttachment *> *)removed expectedInsertions:(NSArray<_WKAttachment *> *)inserted
+{
+    TestWebKitAPI::ObserveAttachmentUpdatesForScope observer(self);
+    EXPECT_TRUE([self _synchronouslyExecuteEditCommand:command argument:argument]);
+    observer.expectAttachmentUpdates(removed, inserted);
+}
+
 @end
 
 namespace TestWebKitAPI {
@@ -79,21 +182,115 @@
 TEST(WKAttachmentTests, AttachmentElementInsertion)
 {
     auto webView = webViewForTestingAttachments();
+    RetainPtr<_WKAttachment> firstAttachment;
+    RetainPtr<_WKAttachment> secondAttachment;
+    {
+        ObserveAttachmentUpdatesForScope observer(webView.get());
+        // Use the given content type for the attachment element's type.
+        firstAttachment = retainPtr([webView synchronouslyInsertAttachmentWithFilename:@"foo" contentType:@"text/html" data:testHTMLData() options:nil]);
+        EXPECT_WK_STREQ(@"foo", [webView valueOfAttribute:@"title" forQuerySelector:@"attachment"]);
+        EXPECT_WK_STREQ(@"text/html", [webView valueOfAttribute:@"type" forQuerySelector:@"attachment"]);
+        EXPECT_WK_STREQ(@"38 bytes", [webView valueOfAttribute:@"subtitle" forQuerySelector:@"attachment"]);
+        observer.expectAttachmentUpdates(@[ ], @[ firstAttachment.get() ]);
+    }
+    {
+        ObserveAttachmentUpdatesForScope scope(webView.get());
+        // Since no content type is explicitly specified, compute it from the file extension.
+        [webView _executeEditCommand:@"DeleteBackward" argument:nil completion:nil];
+        secondAttachment = retainPtr([webView synchronouslyInsertAttachmentWithFilename:@"bar.png" contentType:nil data:testImageData() options:nil]);
+        EXPECT_WK_STREQ(@"bar.png", [webView valueOfAttribute:@"title" forQuerySelector:@"attachment"]);
+        EXPECT_WK_STREQ(@"image/png", [webView valueOfAttribute:@"type" forQuerySelector:@"attachment"]);
+        EXPECT_WK_STREQ(@"37 KB", [webView valueOfAttribute:@"subtitle" forQuerySelector:@"attachment"]);
+        scope.expectAttachmentUpdates(@[ firstAttachment.get() ], @[ secondAttachment.get() ]);
+    }
+}
 
-    // Use the given content type for the attachment element's type.
-    [webView synchronouslyInsertAttachmentWithFilename:@"foo" contentType:@"text/html" data:testHTMLData() options:nil];
-    EXPECT_WK_STREQ(@"foo", [webView valueOfAttribute:@"title" forQuerySelector:@"attachment"]);
-    EXPECT_WK_STREQ(@"text/html", [webView valueOfAttribute:@"type" forQuerySelector:@"attachment"]);
-    EXPECT_WK_STREQ(@"38 bytes", [webView valueOfAttribute:@"subtitle" forQuerySelector:@"attachment"]);
+TEST(WKAttachmentTests, AttachmentUpdatesWhenInsertingAndDeletingNewline)
+{
+    auto webView = webViewForTestingAttachments();
+    RetainPtr<_WKAttachment> attachment;
+    {
+        ObserveAttachmentUpdatesForScope observer(webView.get());
+        attachment = retainPtr([webView synchronouslyInsertAttachmentWithFilename:@"foo.txt" contentType:@"text/plain" data:testHTMLData() options:nil]);
+        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:@"DeleteForward" withArgument:nil expectedRemovals:@[attachment.get()] expectedInsertions:@[]];
+}
 
-    // Since no content type is explicitly specified, compute it from the file extension.
-    [webView _executeEditCommand:@"DeleteBackward" argument:nil completion:nil];
-    [webView synchronouslyInsertAttachmentWithFilename:@"bar.png" contentType:nil data:testImageData() options:nil];
-    EXPECT_WK_STREQ(@"bar.png", [webView valueOfAttribute:@"title" forQuerySelector:@"attachment"]);
-    EXPECT_WK_STREQ(@"image/png", [webView valueOfAttribute:@"type" forQuerySelector:@"attachment"]);
-    EXPECT_WK_STREQ(@"37 KB", [webView valueOfAttribute:@"subtitle" forQuerySelector:@"attachment"]);
+TEST(WKAttachmentTests, AttachmentUpdatesWhenUndoingAndRedoing)
+{
+    auto webView = webViewForTestingAttachments();
+    RetainPtr<_WKAttachment> attachment;
+    {
+        ObserveAttachmentUpdatesForScope observer(webView.get());
+        attachment = retainPtr([webView synchronouslyInsertAttachmentWithFilename:@"foo.txt" contentType:@"text/plain" data:testHTMLData() options:nil]);
+        observer.expectAttachmentUpdates(@[ ], @[attachment.get()]);
+    }
+    [webView expectUpdatesAfterCommand:@"Undo" withArgument:nil expectedRemovals:@[attachment.get()] expectedInsertions:@[]];
+    [webView expectUpdatesAfterCommand:@"Redo" withArgument:nil expectedRemovals:@[] expectedInsertions:@[attachment.get()]];
+    [webView expectUpdatesAfterCommand:@"DeleteBackward" withArgument:nil expectedRemovals:@[attachment.get()] expectedInsertions:@[]];
+    [webView expectUpdatesAfterCommand:@"Undo" withArgument:nil expectedRemovals:@[] expectedInsertions:@[attachment.get()]];
+    [webView expectUpdatesAfterCommand:@"Redo" withArgument:nil expectedRemovals:@[attachment.get()] expectedInsertions:@[]];
 }
 
+TEST(WKAttachmentTests, AttachmentUpdatesWhenChangingFontStyles)
+{
+    auto webView = webViewForTestingAttachments();
+    RetainPtr<_WKAttachment> attachment;
+    [webView _synchronouslyExecuteEditCommand:@"InsertText" argument:@"Hello"];
+    {
+        ObserveAttachmentUpdatesForScope observer(webView.get());
+        attachment = retainPtr([webView synchronouslyInsertAttachmentWithFilename:@"foo.txt" contentType:@"text/plain" data:testHTMLData() options:nil]);
+        observer.expectAttachmentUpdates(@[ ], @[attachment.get()]);
+    }
+    [webView expectUpdatesAfterCommand:@"InsertText" withArgument:@"World" expectedRemovals:@[] expectedInsertions:@[]];
+    [webView _synchronouslyExecuteEditCommand:@"SelectAll" argument:nil];
+    [webView expectUpdatesAfterCommand:@"ToggleBold" withArgument:nil expectedRemovals:@[] expectedInsertions:@[]];
+    [webView expectUpdatesAfterCommand:@"ToggleItalic" withArgument:nil expectedRemovals:@[] expectedInsertions:@[]];
+    // FIXME: Additionally test underlining after <https://bugs.webkit.org/show_bug.cgi?id=179431> is addressed.
+
+    // Inserting text should delete the current selection, removing the attachment in the process.
+    [webView expectUpdatesAfterCommand:@"InsertText" withArgument:@"foo" expectedRemovals:@[attachment.get()] expectedInsertions:@[]];
+}
+
+TEST(WKAttachmentTests, AttachmentUpdatesWhenInsertingLists)
+{
+    auto webView = webViewForTestingAttachments();
+    RetainPtr<_WKAttachment> attachment;
+    {
+        ObserveAttachmentUpdatesForScope observer(webView.get());
+        attachment = retainPtr([webView synchronouslyInsertAttachmentWithFilename:@"foo.txt" contentType:@"text/plain" data:testHTMLData() options:nil]);
+        observer.expectAttachmentUpdates(@[ ], @[attachment.get()]);
+    }
+    [webView expectUpdatesAfterCommand:@"InsertOrderedList" withArgument:nil expectedRemovals:@[] expectedInsertions:@[]];
+    // This edit command behaves more like a "toggle", and will actually break us out of the list we just inserted.
+    [webView expectUpdatesAfterCommand:@"InsertOrderedList" withArgument:nil expectedRemovals:@[] expectedInsertions:@[]];
+    [webView expectUpdatesAfterCommand:@"InsertUnorderedList" withArgument:nil expectedRemovals:@[] expectedInsertions:@[]];
+    [webView expectUpdatesAfterCommand:@"InsertUnorderedList" withArgument:nil expectedRemovals:@[] expectedInsertions:@[]];
+}
+
+TEST(WKAttachmentTests, AttachmentUpdatesWhenInsertingRichMarkup)
+{
+    auto webView = webViewForTestingAttachments();
+    RetainPtr<_WKAttachment> attachment;
+    {
+        ObserveAttachmentUpdatesForScope observer(webView.get());
+        [webView _synchronouslyExecuteEditCommand:@"InsertHTML" argument:@"<div><strong><attachment title='a' webkitattachmentid='a06fec41-9aa0-4c2c-ba3a-0149b54aad99'></attachment></strong></div>"];
+        attachment = observer.observer().inserted[0];
+        observer.expectAttachmentUpdates(@[ ], @[attachment.get()]);
+    }
+    {
+        ObserveAttachmentUpdatesForScope observer(webView.get());
+        [webView stringByEvaluatingJavaScript:@"document.querySelector('attachment').remove()"];
+        [webView waitForNextPresentationUpdate];
+        observer.expectAttachmentUpdates(@[attachment.get()], @[ ]);
+    }
+}
+
 } // namespace TestWebKitAPI
 
 #endif // WK_API_ENABLED
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to