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