Title: [238538] trunk
Revision
238538
Author
[email protected]
Date
2018-11-26 17:37:22 -0800 (Mon, 26 Nov 2018)

Log Message

Insert <attachment> elements under editable images to make their backing data accessible
https://bugs.webkit.org/show_bug.cgi?id=191844
<rdar://problem/30900149>

Reviewed by Simon Fraser.

Source/WebCore:

Test: editing/images/editable-image-creates-attachment.html

* html/HTMLImageElement.cpp:
(WebCore::HTMLImageElement::parseAttribute):
(WebCore::HTMLImageElement::insertedIntoAncestor):
(WebCore::HTMLImageElement::removedFromAncestor):
When the x-apple-editable-image attribute changes, or the element is
moved into or out of a document, call updateEditableImage.

(WebCore::HTMLImageElement::editableImageViewID const):
Adopt EditableImageReference.

(WebCore::HTMLImageElement::updateEditableImage):
When the image element moves into a document, the setting is on, and
the appropriate attribute is applied, add an <attachment> into the
shadow DOM, and inform the UI process both of the editable image's
creation and that it should be associated with the new attachment.

Use an EditableImageReference to extend the lifetime of the
corresponding editable image in the UI process, and to communicate
the attachment association.

If the element was cloned from another editable image element, use the
EditableImageReference and attachmentID from the original; the embedded
view will be re-parented under this element's layer, and the attachment
will be cloned (with a new ID) by editing code if the element is parented.

(WebCore::HTMLImageElement::attachmentIdentifier const):
(WebCore::HTMLImageElement::copyNonAttributePropertiesFromElement):
Store the aforementioned bits of information when cloned so that we can
reconstitute the appropriate attachment data and embedded view.

* html/HTMLImageElement.h:
* page/ChromeClient.h:

* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* page/EditableImageReference.cpp: Added.
(WebCore::EditableImageReference::EditableImageReference):
(WebCore::EditableImageReference::~EditableImageReference):
(WebCore::EditableImageReference::associateWithAttachment):
* page/EditableImageReference.h: Added.
(WebCore::EditableImageReference::create):
(WebCore::EditableImageReference::embeddedViewID const):
Add EditableImageReference, which manages the lifetime of the UI-side
EditableImage and helps clients communicate about it. It is refcounted
so that cloned <img> elements can potentially borrow the UI-side state
(in the case where they end up getting parented).

* page/NavigatorBase.cpp:
Fix an unrelated unified build failure that I exposed.

Source/WebKit:

* DerivedSources.make:
* SourcesCocoa.txt:
* UIProcess/API/APIAttachment.h:
fileWrapper() is no longer a trivial getter; it can now construct
the file wrapper from a file wrapper generator if necessary.

Add setFileWrapperGenerator() and invalidateGeneratedFileWrapper().

Make m_fileWrapper mutable so it can be adjusted inside its own getter.

* UIProcess/API/Cocoa/APIAttachmentCocoa.mm:
(API::Attachment::fileWrapper const):
If we have a fileWrapperGenerator and don't have a cached file wrapper,
create one before returning it.

(API::Attachment::invalidateGeneratedFileWrapper):
Invalidate the currently-cached file wrapper. The next time a client
requests the file wrapper it will be regenerated.

(API::Attachment::fileName const):
(API::Attachment::fileSizeForDisplay const):
(API::Attachment::enclosingImageData const):
(API::Attachment::isEmpty const):
(API::Attachment::createSerializedRepresentation const):
Make use of fileWrapper() instead of m_fileWrapper directly, to ensure
that it is created lazily if necessary.

(API::Attachment::setFileWrapperGenerator):
* UIProcess/RemoteLayerTree/ios/RemoteLayerTreeHostIOS.mm:
(WebKit::RemoteLayerTreeHost::createEmbeddedView):
* UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.h:
* UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.mm:
(-[WKEmbeddedView initWithEmbeddedViewID:]):
Defer to EditableImageController for creating WKDrawingViews for
editable images. This is done primarily so we don't have to pollute
Remote Layer Tree and DrawingArea interfaces with editable-image-specific messages.

* UIProcess/WebPageProxy.cpp:
(WebKit::m_editableImageController):
(WebKit::m_resetRecentCrashCountTimer): Deleted.
* UIProcess/WebPageProxy.h:
(WebKit::WebPageProxy::editableImageController):
Keep an EditableImageController on the WebPageProxy.

* UIProcess/ios/EditableImageController.h: Added.
* UIProcess/ios/EditableImageController.messages.in: Added.
* UIProcess/ios/EditableImageController.mm: Added.
(WebKit::EditableImageController::EditableImageController):
(WebKit::EditableImageController::~EditableImageController):
(WebKit::EditableImageController::ensureEditableImage):
(WebKit::EditableImageController::editableImage):
(WebKit::EditableImageController::didCreateEditableImage):
(WebKit::EditableImageController::didDestroyEditableImage):
(WebKit::EditableImageController::associateWithAttachment):
(WebKit::EditableImageController::invalidateAttachmentForEditableImage):
Add EditableImageController, which keeps track of EditableImages.
It can be messaged directly to create or destroy the UI-side state
of an editable image, and also to associate a WKDrawingView with
a particular attachment.

* UIProcess/ios/WKDrawingView.h:
* UIProcess/ios/WKDrawingView.mm:
(-[WKDrawingView initWithEmbeddedViewID:webPageProxy:]):
Store the WebPageProxy (weakly) so that we can get to the EditableImageController.

(-[WKDrawingView layoutSubviews]):
(-[WKDrawingView PNGRepresentation]):
Synchronously render the PKCanvasView to PNG.

(-[WKDrawingView drawingDidChange:]):
If the drawing changes, inform the APIAttachment that it needs
to discard its NSFileWrapper; a new one will be generated lazily.

(-[WKDrawingView init]): Deleted.
* WebKit.xcodeproj/project.pbxproj:
* WebProcess/WebCoreSupport/WebChromeClient.h:
* WebProcess/WebCoreSupport/ios/WebChromeClientIOS.mm:
(WebKit::WebChromeClient::associateEditableImageWithAttachment):
(WebKit::WebChromeClient::didCreateEditableImage):
(WebKit::WebChromeClient::didDestroyEditableImage):

Tools:

* DumpRenderTree/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::attachmentInfo):
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.cpp:
(WTR::UIScriptController::attachmentInfo):
* TestRunnerShared/UIScriptContext/UIScriptController.h:
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptController::attachmentInfo):
Add a UIScriptController mechanism to retrieve information about
a given attachment.

LayoutTests:

* editing/images/editable-image-creates-attachment-expected.txt: Added.
* editing/images/editable-image-creates-attachment.html: Added.
* resources/ui-helper.js:
(window.UIHelper.attachmentInfo):
(window.UIHelper):

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (238537 => 238538)


--- trunk/LayoutTests/ChangeLog	2018-11-27 01:15:08 UTC (rev 238537)
+++ trunk/LayoutTests/ChangeLog	2018-11-27 01:37:22 UTC (rev 238538)
@@ -1,3 +1,17 @@
+2018-11-26  Tim Horton  <[email protected]>
+
+        Insert <attachment> elements under editable images to make their backing data accessible
+        https://bugs.webkit.org/show_bug.cgi?id=191844
+        <rdar://problem/30900149>
+
+        Reviewed by Simon Fraser.
+
+        * editing/images/editable-image-creates-attachment-expected.txt: Added.
+        * editing/images/editable-image-creates-attachment.html: Added.
+        * resources/ui-helper.js:
+        (window.UIHelper.attachmentInfo):
+        (window.UIHelper):
+
 2018-11-26  Daniel Bates  <[email protected]>
 
         REGRESSION (r237738): Command Down Arrow doesn't scroll to the end of a page anymore

Added: trunk/LayoutTests/editing/images/editable-image-creates-attachment-expected.txt (0 => 238538)


--- trunk/LayoutTests/editing/images/editable-image-creates-attachment-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/editing/images/editable-image-creates-attachment-expected.txt	2018-11-27 01:37:22 UTC (rev 238538)
@@ -0,0 +1,3 @@
+Has attachment inside editable image: true.
+Attachment type after drawing on editable image: image/png.
+

Added: trunk/LayoutTests/editing/images/editable-image-creates-attachment.html (0 => 238538)


--- trunk/LayoutTests/editing/images/editable-image-creates-attachment.html	                        (rev 0)
+++ trunk/LayoutTests/editing/images/editable-image-creates-attachment.html	2018-11-27 01:37:22 UTC (rev 238538)
@@ -0,0 +1,24 @@
+<!DOCTYPE html><!-- webkit-test-runner [ enableEditableImages=true enableAttachmentElement=true ] -->
+<head>
+<script src=""
+<script>
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+}
+
+addEventListener("load", async () => {
+    const attachmentIdentifier = HTMLAttachmentElement.getAttachmentIdentifier(document.querySelector("img"));
+    const hasAttachment = !!attachmentIdentifier.length;
+    await UIHelper.drawSquareInEditableImage();
+    const attachmentInfo = (await UIHelper.attachmentInfo(attachmentIdentifier));
+    const attachmentType = attachmentInfo.contentType;
+    document.getElementById("log").innerHTML = `Has attachment inside editable image: ${hasAttachment}.<br/>Attachment type after drawing on editable image: ${attachmentType}.`;
+    testRunner.notifyDone();
+});
+</script>
+</head>
+<body>
+<div id="log"></div>
+<img x-apple-editable-image width="300" height="300">
+</body>

Modified: trunk/LayoutTests/resources/ui-helper.js (238537 => 238538)


--- trunk/LayoutTests/resources/ui-helper.js	2018-11-27 01:15:08 UTC (rev 238537)
+++ trunk/LayoutTests/resources/ui-helper.js	2018-11-27 01:37:22 UTC (rev 238538)
@@ -454,4 +454,18 @@
             })()`, numberAsString => resolve(parseInt(numberAsString, 10)))
         });
     }
+
+    static attachmentInfo(attachmentIdentifier)
+    {
+        if (!this.isWebKit2())
+            return Promise.resolve();
+
+        return new Promise(resolve => {
+            testRunner.runUIScript(`(() => {
+                uiController.uiScriptComplete(JSON.stringify(uiController.attachmentInfo('${attachmentIdentifier}')));
+            })()`, jsonString => {
+                resolve(JSON.parse(jsonString));
+            })
+        });
+    }
 }

Modified: trunk/Source/WebCore/ChangeLog (238537 => 238538)


--- trunk/Source/WebCore/ChangeLog	2018-11-27 01:15:08 UTC (rev 238537)
+++ trunk/Source/WebCore/ChangeLog	2018-11-27 01:37:22 UTC (rev 238538)
@@ -1,3 +1,63 @@
+2018-11-26  Tim Horton  <[email protected]>
+
+        Insert <attachment> elements under editable images to make their backing data accessible
+        https://bugs.webkit.org/show_bug.cgi?id=191844
+        <rdar://problem/30900149>
+
+        Reviewed by Simon Fraser.
+
+        Test: editing/images/editable-image-creates-attachment.html
+
+        * html/HTMLImageElement.cpp:
+        (WebCore::HTMLImageElement::parseAttribute):
+        (WebCore::HTMLImageElement::insertedIntoAncestor):
+        (WebCore::HTMLImageElement::removedFromAncestor):
+        When the x-apple-editable-image attribute changes, or the element is
+        moved into or out of a document, call updateEditableImage.
+
+        (WebCore::HTMLImageElement::editableImageViewID const):
+        Adopt EditableImageReference.
+
+        (WebCore::HTMLImageElement::updateEditableImage):
+        When the image element moves into a document, the setting is on, and
+        the appropriate attribute is applied, add an <attachment> into the
+        shadow DOM, and inform the UI process both of the editable image's
+        creation and that it should be associated with the new attachment.
+
+        Use an EditableImageReference to extend the lifetime of the
+        corresponding editable image in the UI process, and to communicate
+        the attachment association.
+
+        If the element was cloned from another editable image element, use the
+        EditableImageReference and attachmentID from the original; the embedded
+        view will be re-parented under this element's layer, and the attachment
+        will be cloned (with a new ID) by editing code if the element is parented.
+
+        (WebCore::HTMLImageElement::attachmentIdentifier const):
+        (WebCore::HTMLImageElement::copyNonAttributePropertiesFromElement):
+        Store the aforementioned bits of information when cloned so that we can
+        reconstitute the appropriate attachment data and embedded view.
+
+        * html/HTMLImageElement.h:
+        * page/ChromeClient.h:
+
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * page/EditableImageReference.cpp: Added.
+        (WebCore::EditableImageReference::EditableImageReference):
+        (WebCore::EditableImageReference::~EditableImageReference):
+        (WebCore::EditableImageReference::associateWithAttachment):
+        * page/EditableImageReference.h: Added.
+        (WebCore::EditableImageReference::create):
+        (WebCore::EditableImageReference::embeddedViewID const):
+        Add EditableImageReference, which manages the lifetime of the UI-side
+        EditableImage and helps clients communicate about it. It is refcounted
+        so that cloned <img> elements can potentially borrow the UI-side state
+        (in the case where they end up getting parented).
+
+        * page/NavigatorBase.cpp:
+        Fix an unrelated unified build failure that I exposed.
+
 2018-11-26  Jer Noble  <[email protected]>
 
         Adopt -setOverrideRouteSharingPolicy:routingContextUID: SPI

Modified: trunk/Source/WebCore/Sources.txt (238537 => 238538)


--- trunk/Source/WebCore/Sources.txt	2018-11-27 01:15:08 UTC (rev 238537)
+++ trunk/Source/WebCore/Sources.txt	2018-11-27 01:37:22 UTC (rev 238538)
@@ -1419,6 +1419,7 @@
 page/DiagnosticLoggingKeys.cpp
 page/DisabledAdaptations.cpp
 page/DragController.cpp
+page/EditableImageReference.cpp
 page/EventHandler.cpp
 page/EventSource.cpp
 page/FocusController.cpp

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (238537 => 238538)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2018-11-27 01:15:08 UTC (rev 238537)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2018-11-27 01:37:22 UTC (rev 238538)
@@ -733,6 +733,7 @@
 		2D29ECC6192ECC8300984B78 /* DisplayRefreshMonitorClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D29ECC2192ECC8300984B78 /* DisplayRefreshMonitorClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		2D29ECC8192ECC8300984B78 /* DisplayRefreshMonitorManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D29ECC4192ECC8300984B78 /* DisplayRefreshMonitorManager.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		2D29ECCA192F1F1D00984B78 /* DisplayRefreshMonitorIOS.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D29ECC9192F1F1D00984B78 /* DisplayRefreshMonitorIOS.h */; };
+		2D2E34AC21A4E192004598B5 /* EditableImageReference.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D2E34A921A4E191004598B5 /* EditableImageReference.h */; };
 		2D3A0E3613A7D76100E85AF0 /* SVGParsingError.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D3A0E3513A7D76100E85AF0 /* SVGParsingError.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		2D3EF4481917915C00034184 /* WebActionDisablingCALayerDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D3EF4441917915C00034184 /* WebActionDisablingCALayerDelegate.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		2D3EF44A1917915C00034184 /* WebCoreCALayerExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D3EF4461917915C00034184 /* WebCoreCALayerExtras.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -6612,6 +6613,8 @@
 		2D29ECC3192ECC8300984B78 /* DisplayRefreshMonitorManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DisplayRefreshMonitorManager.cpp; sourceTree = "<group>"; };
 		2D29ECC4192ECC8300984B78 /* DisplayRefreshMonitorManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DisplayRefreshMonitorManager.h; sourceTree = "<group>"; };
 		2D29ECC9192F1F1D00984B78 /* DisplayRefreshMonitorIOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DisplayRefreshMonitorIOS.h; sourceTree = "<group>"; };
+		2D2E34A921A4E191004598B5 /* EditableImageReference.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EditableImageReference.h; sourceTree = "<group>"; };
+		2D2E34AB21A4E192004598B5 /* EditableImageReference.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EditableImageReference.cpp; sourceTree = "<group>"; };
 		2D2FC0541460CD6F00263633 /* CrossfadeGeneratedImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CrossfadeGeneratedImage.cpp; sourceTree = "<group>"; };
 		2D2FC0551460CD6F00263633 /* CrossfadeGeneratedImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CrossfadeGeneratedImage.h; sourceTree = "<group>"; };
 		2D2FC0561460CD6F00263633 /* GradientImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GradientImage.cpp; sourceTree = "<group>"; };
@@ -19988,6 +19991,8 @@
 				A7CA595C0B27BD9E00FA021D /* DragController.cpp */,
 				A7CA595B0B27BD9E00FA021D /* DragController.h */,
 				81F65FF513788FAA00FF6F2D /* DragState.h */,
+				2D2E34AB21A4E192004598B5 /* EditableImageReference.cpp */,
+				2D2E34A921A4E191004598B5 /* EditableImageReference.h */,
 				1AF326770D78B9440068F0C4 /* EditorClient.h */,
 				93C09A800B064F00005ABD4D /* EventHandler.cpp */,
 				93C09A520B064DB3005ABD4D /* EventHandler.h */,
@@ -28643,6 +28648,7 @@
 				FD6ED2C8136B8E66003CF072 /* DynamicsCompressor.h in Headers */,
 				FD537357137B653B00008DCE /* DynamicsCompressorKernel.h in Headers */,
 				FD6ED2C4136B8E42003CF072 /* DynamicsCompressorNode.h in Headers */,
+				2D2E34AC21A4E192004598B5 /* EditableImageReference.h in Headers */,
 				93309DE2099E64920056E581 /* EditAction.h in Headers */,
 				93309DE4099E64920056E581 /* EditCommand.h in Headers */,
 				93309DE8099E64920056E581 /* Editing.h in Headers */,

Modified: trunk/Source/WebCore/html/HTMLImageElement.cpp (238537 => 238538)


--- trunk/Source/WebCore/html/HTMLImageElement.cpp	2018-11-27 01:15:08 UTC (rev 238537)
+++ trunk/Source/WebCore/html/HTMLImageElement.cpp	2018-11-27 01:37:22 UTC (rev 238538)
@@ -26,6 +26,10 @@
 #include "CSSPropertyNames.h"
 #include "CSSValueKeywords.h"
 #include "CachedImage.h"
+#include "Chrome.h"
+#include "ChromeClient.h"
+#include "EditableImageReference.h"
+#include "Editor.h"
 #include "ElementIterator.h"
 #include "FrameView.h"
 #include "HTMLAnchorElement.h"
@@ -238,7 +242,9 @@
         m_experimentalImageMenuEnabled = !value.isNull();
         updateImageControls();
 #endif
-    } else {
+    } else if (name == x_apple_editable_imageAttr)
+        updateEditableImage(isConnected() ? IsConnectedToDocument::Yes : IsConnectedToDocument::No);
+    else {
         if (name == nameAttr) {
             bool willHaveName = !value.isNull();
             if (m_hadNameBeforeAttributeChanged != willHaveName && isConnected() && !isInShadowTree() && is<HTMLDocument>(document())) {
@@ -326,6 +332,10 @@
         if (m_form)
             m_form->registerImgElement(this);
     }
+
+    if (insertionType.connectedToDocument)
+        updateEditableImage(IsConnectedToDocument::Yes);
+
     // Insert needs to complete first, before we start updating the loader. Loader dispatches events which could result
     // in callbacks back to this node.
     Node::InsertedIntoAncestorResult insertNotificationRequest = HTMLElement::insertedIntoAncestor(insertionType, parentOfInsertedTree);
@@ -357,10 +367,62 @@
     if (is<HTMLPictureElement>(parentNode()))
         setPictureElement(nullptr);
 
+    if (removalType.disconnectedFromDocument)
+        updateEditableImage(IsConnectedToDocument::No);
+
     m_form = nullptr;
     HTMLElement::removedFromAncestor(removalType, oldParentOfRemovedTree);
 }
 
+GraphicsLayer::EmbeddedViewID HTMLImageElement::editableImageViewID() const
+{
+    if (!m_editableImage)
+        return 0;
+    return m_editableImage->embeddedViewID();
+}
+
+void HTMLImageElement::updateEditableImage(IsConnectedToDocument connected)
+{
+    if (!document().settings().editableImagesEnabled())
+        return;
+
+    auto* page = document().page();
+    if (!page)
+        return;
+
+    bool hasEditableAttribute = hasAttributeWithoutSynchronization(x_apple_editable_imageAttr);
+    bool isCurrentlyEditable = !!m_editableImage;
+    bool shouldBeEditable = (connected == IsConnectedToDocument::Yes) && hasEditableAttribute;
+
+#if ENABLE(ATTACHMENT_ELEMENT)
+    // Create the inner attachment for editable images, or non-editable
+    // images that were cloned from editable image sources.
+    if (!attachmentElement() && (shouldBeEditable || !m_pendingClonedAttachmentID.isEmpty())) {
+        auto attachment = HTMLAttachmentElement::create(HTMLNames::attachmentTag, document());
+        if (!m_pendingClonedAttachmentID.isEmpty())
+            attachment->setUniqueIdentifier(WTFMove(m_pendingClonedAttachmentID));
+        else
+            attachment->ensureUniqueIdentifier();
+        setAttachmentElement(WTFMove(attachment));
+    }
+#endif
+
+    if (shouldBeEditable == isCurrentlyEditable)
+        return;
+
+    if (!hasEditableAttribute) {
+        m_editableImage = nullptr;
+        return;
+    }
+
+    if (!m_editableImage)
+        m_editableImage = EditableImageReference::create(document());
+
+#if ENABLE(ATTACHMENT_ELEMENT)
+    m_editableImage->associateWithAttachment(attachmentElement()->uniqueIdentifier());
+#endif
+}
+
 HTMLPictureElement* HTMLImageElement::pictureElement() const
 {
     if (!gPictureOwnerMap || !gPictureOwnerMap->contains(this))
@@ -633,6 +695,9 @@
 
 const String& HTMLImageElement::attachmentIdentifier() const
 {
+    if (!m_pendingClonedAttachmentID.isEmpty())
+        return m_pendingClonedAttachmentID;
+
     if (auto attachment = attachmentElement())
         return attachment->uniqueIdentifier();
 
@@ -737,11 +802,14 @@
 }
 #endif
 
-GraphicsLayer::EmbeddedViewID HTMLImageElement::editableImageViewID() const
+void HTMLImageElement::copyNonAttributePropertiesFromElement(const Element& source)
 {
-    if (!m_editableImageViewID)
-        m_editableImageViewID = GraphicsLayer::nextEmbeddedViewID();
-    return m_editableImageViewID;
+    auto& sourceImage = static_cast<const HTMLImageElement&>(source);
+#if ENABLE(ATTACHMENT_ELEMENT)
+    m_pendingClonedAttachmentID = !sourceImage.m_pendingClonedAttachmentID.isEmpty() ? sourceImage.m_pendingClonedAttachmentID : sourceImage.attachmentIdentifier();
+#endif
+    m_editableImage = sourceImage.m_editableImage;
+    Element::copyNonAttributePropertiesFromElement(source);
 }
 
 }

Modified: trunk/Source/WebCore/html/HTMLImageElement.h (238537 => 238538)


--- trunk/Source/WebCore/html/HTMLImageElement.h	2018-11-27 01:15:08 UTC (rev 238537)
+++ trunk/Source/WebCore/html/HTMLImageElement.h	2018-11-27 01:37:22 UTC (rev 238538)
@@ -32,6 +32,7 @@
 
 namespace WebCore {
 
+class EditableImageReference;
 class HTMLAttachmentElement;
 class HTMLFormElement;
 class HTMLMapElement;
@@ -152,6 +153,11 @@
 
     ImageCandidate bestFitSourceFromPictureElement();
 
+    enum class IsConnectedToDocument : bool { No, Yes };
+    void updateEditableImage(IsConnectedToDocument);
+
+    void copyNonAttributePropertiesFromElement(const Element&) final;
+
 #if ENABLE(SERVICE_CONTROLS)
     void updateImageControls();
     void tryCreateImageControls();
@@ -172,7 +178,10 @@
     bool m_experimentalImageMenuEnabled;
     bool m_hadNameBeforeAttributeChanged { false }; // FIXME: We only need this because parseAttribute() can't see the old value.
 
-    mutable GraphicsLayer::EmbeddedViewID m_editableImageViewID { 0 };
+    RefPtr<EditableImageReference> m_editableImage;
+#if ENABLE(ATTACHMENT_ELEMENT)
+    String m_pendingClonedAttachmentID;
+#endif
 
     friend class HTMLPictureElement;
 };

Modified: trunk/Source/WebCore/page/ChromeClient.h (238537 => 238538)


--- trunk/Source/WebCore/page/ChromeClient.h	2018-11-27 01:15:08 UTC (rev 238537)
+++ trunk/Source/WebCore/page/ChromeClient.h	2018-11-27 01:37:22 UTC (rev 238538)
@@ -30,6 +30,7 @@
 #include "FocusDirection.h"
 #include "FrameLoader.h"
 #include "GraphicsContext.h"
+#include "GraphicsLayer.h"
 #include "HTMLMediaElementEnums.h"
 #include "HostWindow.h"
 #include "Icon.h"
@@ -489,6 +490,10 @@
 
     virtual String signedPublicKeyAndChallengeString(unsigned, const String&, const URL&) const { return emptyString(); }
 
+    virtual void associateEditableImageWithAttachment(GraphicsLayer::EmbeddedViewID, const String&) { }
+    virtual void didCreateEditableImage(GraphicsLayer::EmbeddedViewID) { }
+    virtual void didDestroyEditableImage(GraphicsLayer::EmbeddedViewID) { }
+
 protected:
     virtual ~ChromeClient() = default;
 };

Added: trunk/Source/WebCore/page/EditableImageReference.cpp (0 => 238538)


--- trunk/Source/WebCore/page/EditableImageReference.cpp	                        (rev 0)
+++ trunk/Source/WebCore/page/EditableImageReference.cpp	2018-11-27 01:37:22 UTC (rev 238538)
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2018 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * HOLDER OR 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.
+ */
+
+#include "config.h"
+#include "EditableImageReference.h"
+
+#include "Chrome.h"
+#include "ChromeClient.h"
+
+namespace WebCore {
+
+EditableImageReference::EditableImageReference(Document& document)
+    : m_document(makeWeakPtr(document))
+    , m_embeddedViewID(GraphicsLayer::nextEmbeddedViewID())
+{
+    if (auto* page = document.page())
+        page->chrome().client().didCreateEditableImage(m_embeddedViewID);
+}
+
+EditableImageReference::~EditableImageReference()
+{
+    if (!m_document)
+        return;
+    if (auto* page = m_document->page())
+        page->chrome().client().didDestroyEditableImage(m_embeddedViewID);
+}
+
+void EditableImageReference::associateWithAttachment(const String& attachmentID)
+{
+    if (!m_document)
+        return;
+    if (auto* page = m_document->page())
+        page->chrome().client().associateEditableImageWithAttachment(m_embeddedViewID, attachmentID);
+}
+
+
+} // namespace WebCore

Added: trunk/Source/WebCore/page/EditableImageReference.h (0 => 238538)


--- trunk/Source/WebCore/page/EditableImageReference.h	                        (rev 0)
+++ trunk/Source/WebCore/page/EditableImageReference.h	2018-11-27 01:37:22 UTC (rev 238538)
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2018 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * HOLDER OR 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
+
+#include "GraphicsLayer.h"
+#include <wtf/RefCounted.h>
+#include <wtf/WeakPtr.h>
+
+namespace WebCore {
+
+class Document;
+
+class EditableImageReference : public RefCounted<EditableImageReference> {
+public:
+    static Ref<EditableImageReference> create(Document& document)
+    {
+        return adoptRef(*new EditableImageReference(document));
+    }
+
+    ~EditableImageReference();
+
+    GraphicsLayer::EmbeddedViewID embeddedViewID() const { return m_embeddedViewID; }
+
+    void associateWithAttachment(const String& attachmentID);
+
+private:
+    explicit EditableImageReference(Document&);
+
+    WeakPtr<Document> m_document;
+    GraphicsLayer::EmbeddedViewID m_embeddedViewID;
+};
+
+} // namespace WebCore

Modified: trunk/Source/WebCore/page/NavigatorBase.cpp (238537 => 238538)


--- trunk/Source/WebCore/page/NavigatorBase.cpp	2018-11-27 01:15:08 UTC (rev 238537)
+++ trunk/Source/WebCore/page/NavigatorBase.cpp	2018-11-27 01:37:22 UTC (rev 238538)
@@ -27,6 +27,7 @@
 #include "config.h"
 #include "NavigatorBase.h"
 
+#include "Document.h"
 #include "ServiceWorkerContainer.h"
 #include <mutex>
 #include <wtf/Language.h>

Modified: trunk/Source/WebKit/ChangeLog (238537 => 238538)


--- trunk/Source/WebKit/ChangeLog	2018-11-27 01:15:08 UTC (rev 238537)
+++ trunk/Source/WebKit/ChangeLog	2018-11-27 01:37:22 UTC (rev 238538)
@@ -1,3 +1,92 @@
+2018-11-26  Tim Horton  <[email protected]>
+
+        Insert <attachment> elements under editable images to make their backing data accessible
+        https://bugs.webkit.org/show_bug.cgi?id=191844
+        <rdar://problem/30900149>
+
+        Reviewed by Simon Fraser.
+
+        * DerivedSources.make:
+        * SourcesCocoa.txt:
+        * UIProcess/API/APIAttachment.h:
+        fileWrapper() is no longer a trivial getter; it can now construct
+        the file wrapper from a file wrapper generator if necessary.
+
+        Add setFileWrapperGenerator() and invalidateGeneratedFileWrapper().
+
+        Make m_fileWrapper mutable so it can be adjusted inside its own getter.
+
+        * UIProcess/API/Cocoa/APIAttachmentCocoa.mm:
+        (API::Attachment::fileWrapper const):
+        If we have a fileWrapperGenerator and don't have a cached file wrapper,
+        create one before returning it.
+
+        (API::Attachment::invalidateGeneratedFileWrapper):
+        Invalidate the currently-cached file wrapper. The next time a client
+        requests the file wrapper it will be regenerated.
+
+        (API::Attachment::fileName const):
+        (API::Attachment::fileSizeForDisplay const):
+        (API::Attachment::enclosingImageData const):
+        (API::Attachment::isEmpty const):
+        (API::Attachment::createSerializedRepresentation const):
+        Make use of fileWrapper() instead of m_fileWrapper directly, to ensure
+        that it is created lazily if necessary.
+
+        (API::Attachment::setFileWrapperGenerator):
+        * UIProcess/RemoteLayerTree/ios/RemoteLayerTreeHostIOS.mm:
+        (WebKit::RemoteLayerTreeHost::createEmbeddedView):
+        * UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.h:
+        * UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.mm:
+        (-[WKEmbeddedView initWithEmbeddedViewID:]):
+        Defer to EditableImageController for creating WKDrawingViews for
+        editable images. This is done primarily so we don't have to pollute
+        Remote Layer Tree and DrawingArea interfaces with editable-image-specific messages.
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::m_editableImageController):
+        (WebKit::m_resetRecentCrashCountTimer): Deleted.
+        * UIProcess/WebPageProxy.h:
+        (WebKit::WebPageProxy::editableImageController):
+        Keep an EditableImageController on the WebPageProxy.
+
+        * UIProcess/ios/EditableImageController.h: Added.
+        * UIProcess/ios/EditableImageController.messages.in: Added.
+        * UIProcess/ios/EditableImageController.mm: Added.
+        (WebKit::EditableImageController::EditableImageController):
+        (WebKit::EditableImageController::~EditableImageController):
+        (WebKit::EditableImageController::ensureEditableImage):
+        (WebKit::EditableImageController::editableImage):
+        (WebKit::EditableImageController::didCreateEditableImage):
+        (WebKit::EditableImageController::didDestroyEditableImage):
+        (WebKit::EditableImageController::associateWithAttachment):
+        (WebKit::EditableImageController::invalidateAttachmentForEditableImage):
+        Add EditableImageController, which keeps track of EditableImages.
+        It can be messaged directly to create or destroy the UI-side state
+        of an editable image, and also to associate a WKDrawingView with
+        a particular attachment.
+
+        * UIProcess/ios/WKDrawingView.h:
+        * UIProcess/ios/WKDrawingView.mm:
+        (-[WKDrawingView initWithEmbeddedViewID:webPageProxy:]):
+        Store the WebPageProxy (weakly) so that we can get to the EditableImageController.
+
+        (-[WKDrawingView layoutSubviews]):
+        (-[WKDrawingView PNGRepresentation]):
+        Synchronously render the PKCanvasView to PNG.
+
+        (-[WKDrawingView drawingDidChange:]):
+        If the drawing changes, inform the APIAttachment that it needs
+        to discard its NSFileWrapper; a new one will be generated lazily.
+
+        (-[WKDrawingView init]): Deleted.
+        * WebKit.xcodeproj/project.pbxproj:
+        * WebProcess/WebCoreSupport/WebChromeClient.h:
+        * WebProcess/WebCoreSupport/ios/WebChromeClientIOS.mm:
+        (WebKit::WebChromeClient::associateEditableImageWithAttachment):
+        (WebKit::WebChromeClient::didCreateEditableImage):
+        (WebKit::WebChromeClient::didDestroyEditableImage):
+
 2018-11-26  Jer Noble  <[email protected]>
 
         Adopt -setOverrideRouteSharingPolicy:routingContextUID: SPI

Modified: trunk/Source/WebKit/DerivedSources.make (238537 => 238538)


--- trunk/Source/WebKit/DerivedSources.make	2018-11-27 01:15:08 UTC (rev 238537)
+++ trunk/Source/WebKit/DerivedSources.make	2018-11-27 01:37:22 UTC (rev 238538)
@@ -104,6 +104,7 @@
     DownloadProxy \
     DrawingArea \
     DrawingAreaProxy \
+    EditableImageController \
     EventDispatcher \
     LegacyCustomProtocolManager \
     LegacyCustomProtocolManagerProxy \

Modified: trunk/Source/WebKit/SourcesCocoa.txt (238537 => 238538)


--- trunk/Source/WebKit/SourcesCocoa.txt	2018-11-27 01:15:08 UTC (rev 238537)
+++ trunk/Source/WebKit/SourcesCocoa.txt	2018-11-27 01:37:22 UTC (rev 238538)
@@ -368,6 +368,7 @@
 UIProcess/ios/fullscreen/WKFullScreenWindowControllerIOS.mm
 
 UIProcess/ios/DragDropInteractionState.mm
+UIProcess/ios/EditableImageController.mm
 UIProcess/ios/InputViewUpdateDeferrer.mm
 UIProcess/ios/PageClientImplIOS.mm
 UIProcess/ios/ProcessAssertionIOS.mm
@@ -556,3 +557,7 @@
 WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDisplayRefreshMonitor.mm
 WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.mm @no-unify
 WebProcess/WebPage/RemoteLayerTree/RemoteScrollingCoordinator.mm
+
+// Derived Sources
+
+EditableImageControllerMessageReceiver.cpp

Modified: trunk/Source/WebKit/UIProcess/API/APIAttachment.h (238537 => 238538)


--- trunk/Source/WebKit/UIProcess/API/APIAttachment.h	2018-11-27 01:15:08 UTC (rev 238537)
+++ trunk/Source/WebKit/UIProcess/API/APIAttachment.h	2018-11-27 01:37:22 UTC (rev 238538)
@@ -60,9 +60,11 @@
     bool isValid() const { return !!m_webPage; }
 
 #if PLATFORM(COCOA)
-    NSFileWrapper *fileWrapper() const { return m_fileWrapper.get(); }
+    NSFileWrapper *fileWrapper() const;
     void setFileWrapper(NSFileWrapper *fileWrapper) { m_fileWrapper = fileWrapper; }
     void setFileWrapperAndUpdateContentType(NSFileWrapper *, NSString *contentType);
+    void setFileWrapperGenerator(Function<RetainPtr<NSFileWrapper>(void)>&&);
+    void invalidateGeneratedFileWrapper();
     WTF::String utiType() const;
 #endif
     WTF::String mimeType() const;
@@ -92,7 +94,8 @@
     explicit Attachment(const WTF::String& identifier, WebKit::WebPageProxy&);
 
 #if PLATFORM(COCOA)
-    RetainPtr<NSFileWrapper> m_fileWrapper;
+    mutable RetainPtr<NSFileWrapper> m_fileWrapper;
+    Function<RetainPtr<NSFileWrapper>(void)> m_fileWrapperGenerator;
 #endif
     WTF::String m_identifier;
     WTF::String m_filePath;

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/APIAttachmentCocoa.mm (238537 => 238538)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/APIAttachmentCocoa.mm	2018-11-27 01:15:08 UTC (rev 238537)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/APIAttachmentCocoa.mm	2018-11-27 01:37:22 UTC (rev 238538)
@@ -53,6 +53,19 @@
     return UTTypeIsDeclared((__bridge CFStringRef)type) || UTTypeIsDynamic((__bridge CFStringRef)type);
 }
 
+NSFileWrapper *Attachment::fileWrapper() const
+{
+    if (m_fileWrapperGenerator && !m_fileWrapper)
+        m_fileWrapper = m_fileWrapperGenerator();
+    return m_fileWrapper.get();
+}
+
+void Attachment::invalidateGeneratedFileWrapper()
+{
+    ASSERT(m_fileWrapperGenerator);
+    m_fileWrapper = nil;
+}
+
 WTF::String Attachment::mimeType() const
 {
     NSString *contentType = m_contentType.isEmpty() ? mimeTypeInferredFromFileExtension(*this) : m_contentType;
@@ -73,10 +86,12 @@
 
 WTF::String Attachment::fileName() const
 {
-    if ([m_fileWrapper filename].length)
-        return [m_fileWrapper filename];
+    auto fileWrapper = this->fileWrapper();
 
-    return [m_fileWrapper preferredFilename];
+    if ([fileWrapper filename].length)
+        return [fileWrapper filename];
+
+    return [fileWrapper preferredFilename];
 }
 
 void Attachment::setFileWrapperAndUpdateContentType(NSFileWrapper *fileWrapper, NSString *contentType)
@@ -98,15 +113,17 @@
 
 std::optional<uint64_t> Attachment::fileSizeForDisplay() const
 {
-    if (![m_fileWrapper isRegularFile]) {
+    auto fileWrapper = this->fileWrapper();
+
+    if (![fileWrapper isRegularFile]) {
         // FIXME: We should display a size estimate for directory-type file wrappers.
         return std::nullopt;
     }
 
-    if (auto fileSize = [[m_fileWrapper fileAttributes][NSFileSize] unsignedLongLongValue])
+    if (auto fileSize = [[fileWrapper fileAttributes][NSFileSize] unsignedLongLongValue])
         return fileSize;
 
-    return [m_fileWrapper regularFileContents].length;
+    return [fileWrapper regularFileContents].length;
 }
 
 RefPtr<WebCore::SharedBuffer> Attachment::enclosingImageData() const
@@ -114,10 +131,12 @@
     if (!m_hasEnclosingImage)
         return nullptr;
 
-    if (![m_fileWrapper isRegularFile])
+    auto fileWrapper = this->fileWrapper();
+
+    if (![fileWrapper isRegularFile])
         return nullptr;
 
-    NSData *data = "" regularFileContents];
+    NSData *data = "" regularFileContents];
     if (!data)
         return nullptr;
 
@@ -126,18 +145,20 @@
 
 bool Attachment::isEmpty() const
 {
-    return !m_fileWrapper;
+    return !m_fileWrapper && !m_fileWrapperGenerator;
 }
 
 RefPtr<WebCore::SharedBuffer> Attachment::createSerializedRepresentation() const
 {
-    if (!m_fileWrapper || !m_webPage)
+    auto fileWrapper = this->fileWrapper();
+
+    if (!fileWrapper || !m_webPage)
         return nullptr;
 
 #if CAN_SECURELY_ARCHIVE_FILE_WRAPPER
-    NSData *serializedData = securelyArchivedDataWithRootObject(m_fileWrapper.get());
+    NSData *serializedData = securelyArchivedDataWithRootObject(fileWrapper);
 #else
-    NSData *serializedData = insecurelyArchivedDataWithRootObject(m_fileWrapper.get());
+    NSData *serializedData = insecurelyArchivedDataWithRootObject(fileWrapper);
 #endif
 
     if (!serializedData)
@@ -168,4 +189,10 @@
     m_webPage->updateAttachmentAttributes(*this, [] (auto) { });
 }
 
+void Attachment::setFileWrapperGenerator(Function<RetainPtr<NSFileWrapper>(void)>&& fileWrapperGenerator)
+{
+    m_fileWrapperGenerator = WTFMove(fileWrapperGenerator);
+    m_fileWrapper = nil;
+}
+
 } // namespace API

Modified: trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteLayerTreeHostIOS.mm (238537 => 238538)


--- trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteLayerTreeHostIOS.mm	2018-11-27 01:15:08 UTC (rev 238537)
+++ trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteLayerTreeHostIOS.mm	2018-11-27 01:37:22 UTC (rev 238538)
@@ -28,6 +28,7 @@
 
 #if PLATFORM(IOS_FAMILY)
 
+#import "EditableImageController.h"
 #import "RemoteLayerTreeDrawingAreaProxy.h"
 #import "RemoteLayerTreeViews.h"
 #import "UIKitSPI.h"
@@ -123,28 +124,24 @@
 
 RetainPtr<WKEmbeddedView> RemoteLayerTreeHost::createEmbeddedView(const RemoteLayerTreeTransaction::LayerCreationProperties& properties)
 {
-    Class embeddedViewClass = nil;
-    switch (properties.type) {
-    case PlatformCALayer::LayerTypeEditableImageLayer:
+    if (m_isDebugLayerTreeHost)
+        return adoptNS([[UIView alloc] init]);
+
+    auto result = m_embeddedViews.ensure(properties.embeddedViewID, [&]() -> RetainPtr<UIView *> {
+        switch (properties.type) {
 #if HAVE(PENCILKIT)
-        embeddedViewClass = [WKDrawingView class];
+        case PlatformCALayer::LayerTypeEditableImageLayer: {
+            auto editableImage = m_drawingArea->page().editableImageController().editableImage(properties.embeddedViewID);
+            return editableImage ? editableImage->drawingView : nil;
+        }
 #endif
-        break;
-    default:
-        break;
-    }
-
-    if (!embeddedViewClass || m_isDebugLayerTreeHost)
-        return adoptNS([[UIView alloc] init]);
-
-    auto result = m_embeddedViews.ensure(properties.embeddedViewID, [&] {
-        return adoptNS([[embeddedViewClass alloc] init]);
+        default:
+            return adoptNS([[UIView alloc] init]);
+        }
     });
     auto view = result.iterator->value;
     if (!result.isNewEntry)
-        m_layerToEmbeddedViewMap.remove([view layerID]);
-    [view setLayerID:properties.layerID];
-    m_embeddedViews.set(properties.embeddedViewID, view);
+        m_layerToEmbeddedViewMap.remove(RemoteLayerTreeNode::layerID([view layer]));
     m_layerToEmbeddedViewMap.set(properties.layerID, properties.embeddedViewID);
     return view;
 }

Modified: trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.h (238537 => 238538)


--- trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.h	2018-11-27 01:15:08 UTC (rev 238537)
+++ trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.h	2018-11-27 01:37:22 UTC (rev 238538)
@@ -30,6 +30,10 @@
 #import "UIKitSPI.h"
 #import <WebCore/GraphicsLayer.h>
 
+namespace WebKit {
+class WebPageProxy;
+}
+
 @protocol WKNativelyInteractible <NSObject>
 @end
 
@@ -62,9 +66,10 @@
 
 @interface WKEmbeddedView : UIView
 
-@property (nonatomic, assign) WebCore::GraphicsLayer::EmbeddedViewID embeddedViewID;
-@property (nonatomic, assign) WebCore::GraphicsLayer::PlatformLayerID layerID;
+- (instancetype)initWithEmbeddedViewID:(WebCore::GraphicsLayer::EmbeddedViewID)embeddedViewID;
 
+@property (nonatomic, readonly, assign) WebCore::GraphicsLayer::EmbeddedViewID embeddedViewID;
+
 @end
 
 #endif // PLATFORM(IOS_FAMILY)

Modified: trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.mm (238537 => 238538)


--- trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.mm	2018-11-27 01:15:08 UTC (rev 238537)
+++ trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.mm	2018-11-27 01:37:22 UTC (rev 238538)
@@ -202,6 +202,18 @@
 @end
 
 @implementation WKEmbeddedView
+
+- (instancetype)initWithEmbeddedViewID:(WebCore::GraphicsLayer::EmbeddedViewID)embeddedViewID
+{
+    self = [super init];
+    if (!self)
+        return nil;
+
+    _embeddedViewID = embeddedViewID;
+
+    return self;
+}
+
 @end
 
 #endif // PLATFORM(IOS_FAMILY)

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (238537 => 238538)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2018-11-27 01:15:08 UTC (rev 238537)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2018-11-27 01:37:22 UTC (rev 238538)
@@ -233,6 +233,10 @@
 #include "SecKeyProxyStore.h"
 #endif
 
+#if HAVE(PENCILKIT)
+#include "EditableImageController.h"
+#endif
+
 // This controls what strategy we use for mouse wheel coalescing.
 #define MERGE_WHEEL_EVENTS 1
 
@@ -436,6 +440,9 @@
     , m_inspectorDebuggable(std::make_unique<WebPageDebuggable>(*this))
 #endif
     , m_resetRecentCrashCountTimer(RunLoop::main(), this, &WebPageProxy::resetRecentCrashCount)
+#if HAVE(PENCILKIT)
+    , m_editableImageController(std::make_unique<EditableImageController>(*this))
+#endif
 {
     m_webProcessLifetimeTracker.addObserver(m_visitedLinkStore);
     m_webProcessLifetimeTracker.addObserver(m_websiteDataStore);

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (238537 => 238538)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.h	2018-11-27 01:15:08 UTC (rev 238537)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h	2018-11-27 01:37:22 UTC (rev 238538)
@@ -217,6 +217,7 @@
 
 namespace WebKit {
 class DrawingAreaProxy;
+class EditableImageController;
 class NativeWebGestureEvent;
 class NativeWebKeyboardEvent;
 class NativeWebMouseEvent;
@@ -1368,6 +1369,7 @@
     void insertAttachment(Ref<API::Attachment>&&, Function<void(CallbackBase::Error)>&&);
     void updateAttachmentAttributes(const API::Attachment&, Function<void(CallbackBase::Error)>&&);
     void serializedAttachmentDataForIdentifiers(const Vector<String>&, Vector<WebCore::SerializedAttachmentData>&);
+    void registerAttachmentIdentifier(const String&);
 #endif
 
 #if ENABLE(APPLICATION_MANIFEST)
@@ -1389,6 +1391,10 @@
 
     void updateCurrentModifierState();
 
+#if HAVE(PENCILKIT)
+    EditableImageController& editableImageController() { return *m_editableImageController; }
+#endif
+
 private:
     WebPageProxy(PageClient&, WebProcessProxy&, uint64_t pageID, Ref<API::PageConfiguration>&&);
     void platformInitialize();
@@ -1853,7 +1859,6 @@
     void registerAttachmentIdentifierFromData(const String&, const String& contentType, const String& preferredFileName, const IPC::DataReference&);
     void registerAttachmentIdentifierFromFilePath(const String&, const String& contentType, const String& filePath);
     void registerAttachmentsFromSerializedData(Vector<WebCore::SerializedAttachmentData>&&);
-    void registerAttachmentIdentifier(const String&);
     void cloneAttachmentData(const String& fromIdentifier, const String& toIdentifier);
 
     void platformRegisterAttachment(Ref<API::Attachment>&&, const String& preferredFileName, const IPC::DataReference&);
@@ -2280,6 +2285,10 @@
     unsigned m_recentCrashCount { 0 };
 
     bool m_needsFontAttributes { false };
+
+#if HAVE(PENCILKIT)
+    std::unique_ptr<EditableImageController> m_editableImageController;
+#endif
 };
 
 } // namespace WebKit

Copied: trunk/Source/WebKit/UIProcess/ios/EditableImageController.h (from rev 238535, trunk/Source/WebKit/UIProcess/ios/WKDrawingView.mm) (0 => 238538)


--- trunk/Source/WebKit/UIProcess/ios/EditableImageController.h	                        (rev 0)
+++ trunk/Source/WebKit/UIProcess/ios/EditableImageController.h	2018-11-27 01:37:22 UTC (rev 238538)
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2018 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 HAVE(PENCILKIT)
+
+#include "MessageReceiver.h"
+#include <WebCore/GraphicsLayer.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/WeakObjCPtr.h>
+#include <wtf/WeakPtr.h>
+#include <wtf/text/WTFString.h>
+
+OBJC_CLASS WKDrawingView;
+
+namespace WebKit {
+
+class WebPageProxy;
+
+struct EditableImage {
+    RetainPtr<WKDrawingView> drawingView;
+    String attachmentID;
+};
+
+class EditableImageController : private IPC::MessageReceiver {
+    WTF_MAKE_NONCOPYABLE(EditableImageController);
+public:
+    explicit EditableImageController(WebPageProxy&);
+    ~EditableImageController();
+
+    // IPC::MessageReceiver.
+    void didReceiveMessage(IPC::Connection&, IPC::Decoder&) override;
+
+    EditableImage* editableImage(WebCore::GraphicsLayer::EmbeddedViewID);
+    EditableImage& ensureEditableImage(WebCore::GraphicsLayer::EmbeddedViewID);
+
+    void invalidateAttachmentForEditableImage(WebCore::GraphicsLayer::EmbeddedViewID);
+
+private:
+    void didCreateEditableImage(WebCore::GraphicsLayer::EmbeddedViewID);
+    void didDestroyEditableImage(WebCore::GraphicsLayer::EmbeddedViewID);
+
+    void associateWithAttachment(WebCore::GraphicsLayer::EmbeddedViewID, const String& attachmentID);
+
+    WeakPtr<WebPageProxy> m_webPageProxy;
+
+    HashMap<WebCore::GraphicsLayer::EmbeddedViewID, std::unique_ptr<EditableImage>> m_editableImages;
+};
+
+} // namespace WebKit
+
+#endif // HAVE(PENCILKIT)

Added: trunk/Source/WebKit/UIProcess/ios/EditableImageController.messages.in (0 => 238538)


--- trunk/Source/WebKit/UIProcess/ios/EditableImageController.messages.in	                        (rev 0)
+++ trunk/Source/WebKit/UIProcess/ios/EditableImageController.messages.in	2018-11-27 01:37:22 UTC (rev 238538)
@@ -0,0 +1,31 @@
+# Copyright (C) 2018 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.
+
+#if HAVE(PENCILKIT)
+
+messages -> EditableImageController {
+    DidCreateEditableImage(uint64_t editableImageID)
+    DidDestroyEditableImage(uint64_t editableImageID)
+    AssociateWithAttachment(uint64_t editableImageID, String attachmentID)
+}
+
+#endif

Added: trunk/Source/WebKit/UIProcess/ios/EditableImageController.mm (0 => 238538)


--- trunk/Source/WebKit/UIProcess/ios/EditableImageController.mm	                        (rev 0)
+++ trunk/Source/WebKit/UIProcess/ios/EditableImageController.mm	2018-11-27 01:37:22 UTC (rev 238538)
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#import "config.h"
+#import "EditableImageController.h"
+
+#if HAVE(PENCILKIT)
+
+#import "APIAttachment.h"
+#import "EditableImageControllerMessages.h"
+#import "PencilKitSPI.h"
+#import "WKDrawingView.h"
+#import "WebPageProxy.h"
+#import "WebProcessProxy.h"
+#import <WebCore/GraphicsLayer.h>
+#import <wtf/RetainPtr.h>
+
+namespace WebKit {
+
+EditableImageController::EditableImageController(WebPageProxy& webPageProxy)
+    : m_webPageProxy(makeWeakPtr(webPageProxy))
+{
+    if (auto* webPageProxy = m_webPageProxy.get())
+        webPageProxy->process().addMessageReceiver(Messages::EditableImageController::messageReceiverName(), webPageProxy->pageID(), *this);
+}
+
+EditableImageController::~EditableImageController()
+{
+    if (auto* webPageProxy = m_webPageProxy.get())
+        webPageProxy->process().removeMessageReceiver(Messages::EditableImageController::messageReceiverName(), webPageProxy->pageID());
+}
+
+EditableImage& EditableImageController::ensureEditableImage(WebCore::GraphicsLayer::EmbeddedViewID embeddedViewID)
+{
+    auto result = m_editableImages.ensure(embeddedViewID, [&] {
+        std::unique_ptr<EditableImage> image = std::make_unique<EditableImage>();
+        image->drawingView = adoptNS([[WKDrawingView alloc] initWithEmbeddedViewID:embeddedViewID webPageProxy:*m_webPageProxy]);
+        return image;
+    });
+    return *result.iterator->value;
+}
+
+EditableImage* EditableImageController::editableImage(WebCore::GraphicsLayer::EmbeddedViewID embeddedViewID)
+{
+    auto drawingViewIter = m_editableImages.find(embeddedViewID);
+    if (drawingViewIter == m_editableImages.end())
+        return nil;
+    return drawingViewIter->value.get();
+}
+
+void EditableImageController::didCreateEditableImage(WebCore::GraphicsLayer::EmbeddedViewID embeddedViewID)
+{
+    ensureEditableImage(embeddedViewID);
+}
+
+void EditableImageController::didDestroyEditableImage(WebCore::GraphicsLayer::EmbeddedViewID embeddedViewID)
+{
+    m_editableImages.remove(embeddedViewID);
+}
+
+void EditableImageController::associateWithAttachment(WebCore::GraphicsLayer::EmbeddedViewID embeddedViewID, const String& attachmentID)
+{
+    if (!m_webPageProxy)
+        return;
+    auto& page = *m_webPageProxy;
+
+    page.registerAttachmentIdentifier(attachmentID);
+    auto& attachment = *page.attachmentForIdentifier(attachmentID);
+
+    auto& editableImage = ensureEditableImage(embeddedViewID);
+    WeakObjCPtr<WKDrawingView> drawingView = editableImage.drawingView.get();
+    editableImage.attachmentID = attachmentID;
+    attachment.setFileWrapperGenerator([drawingView]() -> RetainPtr<NSFileWrapper> {
+        if (!drawingView)
+            return nil;
+        RetainPtr<NSFileWrapper> fileWrapper = adoptNS([[NSFileWrapper alloc] initRegularFileWithContents:[drawingView PNGRepresentation]]);
+        [fileWrapper setPreferredFilename:@"drawing.png"];
+        return fileWrapper;
+    });
+    attachment.setContentType("public.png");
+}
+
+void EditableImageController::invalidateAttachmentForEditableImage(WebCore::GraphicsLayer::EmbeddedViewID embeddedViewID)
+{
+    if (!m_webPageProxy)
+        return;
+    auto& page = *m_webPageProxy;
+
+    auto editableImage = this->editableImage(embeddedViewID);
+    if (!editableImage)
+        return;
+
+    auto attachment = page.attachmentForIdentifier(editableImage->attachmentID);
+    if (!attachment)
+        return;
+
+    attachment->invalidateGeneratedFileWrapper();
+}
+
+} // namespace WebKit
+
+#endif // HAVE(PENCILKIT)

Modified: trunk/Source/WebKit/UIProcess/ios/WKDrawingView.h (238537 => 238538)


--- trunk/Source/WebKit/UIProcess/ios/WKDrawingView.h	2018-11-27 01:15:08 UTC (rev 238537)
+++ trunk/Source/WebKit/UIProcess/ios/WKDrawingView.h	2018-11-27 01:37:22 UTC (rev 238538)
@@ -30,6 +30,10 @@
 
 @interface WKDrawingView : WKEmbeddedView <WKNativelyInteractible>
 
+- (instancetype)initWithEmbeddedViewID:(WebCore::GraphicsLayer::EmbeddedViewID)embeddedViewID webPageProxy:(WebKit::WebPageProxy&)webPageProxy;
+
+- (NSData *)PNGRepresentation;
+
 @end
 
 

Modified: trunk/Source/WebKit/UIProcess/ios/WKDrawingView.mm (238537 => 238538)


--- trunk/Source/WebKit/UIProcess/ios/WKDrawingView.mm	2018-11-27 01:15:08 UTC (rev 238537)
+++ trunk/Source/WebKit/UIProcess/ios/WKDrawingView.mm	2018-11-27 01:37:22 UTC (rev 238538)
@@ -28,27 +28,41 @@
 
 #if HAVE(PENCILKIT)
 
+#import "EditableImageController.h"
 #import "PencilKitSPI.h"
+#import <wtf/OSObjectPtr.h>
 #import <wtf/RetainPtr.h>
 
 SOFT_LINK_PRIVATE_FRAMEWORK(PencilKit);
 SOFT_LINK_CLASS(PencilKit, PKCanvasView);
+SOFT_LINK_CLASS(PencilKit, PKImageRenderer);
 
+@interface WKDrawingView () <PKCanvasViewDelegate>
+@end
+
 @implementation WKDrawingView {
     RetainPtr<PKCanvasView> _pencilView;
+
+    OSObjectPtr<dispatch_queue_t> _renderQueue;
+    RetainPtr<PKImageRenderer> _renderer;
+
+    WeakPtr<WebKit::WebPageProxy> _webPageProxy;
 }
 
-- (id)init
+- (instancetype)initWithEmbeddedViewID:(WebCore::GraphicsLayer::EmbeddedViewID)embeddedViewID webPageProxy:(WebKit::WebPageProxy&)webPageProxy
 {
-    self = [super init];
+    self = [super initWithEmbeddedViewID:embeddedViewID];
     if (!self)
         return nil;
 
+    _webPageProxy = makeWeakPtr(webPageProxy);
+
     _pencilView = adoptNS([allocPKCanvasViewInstance() initWithFrame:CGRectZero]);
 
     [_pencilView setFingerDrawingEnabled:NO];
     [_pencilView setUserInteractionEnabled:YES];
     [_pencilView setOpaque:NO];
+    [_pencilView setDrawingDelegate:self];
 
     [self addSubview:_pencilView.get()];
 
@@ -57,9 +71,45 @@
 
 - (void)layoutSubviews
 {
-    [_pencilView setFrame:self.bounds];
+    if (!CGRectEqualToRect([_pencilView frame], self.bounds)) {
+        [_pencilView setFrame:self.bounds];
+
+        // The renderer is instantiated for a particular size output; if
+        // the size changes, we need to re-create the renderer.
+        _renderer = nil;
+    }
 }
 
+- (NSData *)PNGRepresentation
+{
+    if (!_renderQueue)
+        _renderQueue = adoptOSObject(dispatch_queue_create("com.apple.WebKit.WKDrawingView.Rendering", DISPATCH_QUEUE_SERIAL));
+
+    if (!_renderer)
+        _renderer = adoptNS([allocPKImageRendererInstance() initWithSize:self.bounds.size scale:self.window.screen.scale renderQueue:_renderQueue.get()]);
+
+    __block RetainPtr<UIImage> resultImage;
+    [_renderer renderDrawing:[_pencilView drawing] completion:^(UIImage *image) {
+        resultImage = image;
+    }];
+
+    // FIXME: Ideally we would not synchronously wait for this rendering,
+    // but NSFileWrapper requires data synchronously, and our clients expect
+    // an NSFileWrapper to be available synchronously.
+    dispatch_sync(_renderQueue.get(), ^{ });
+
+    return UIImagePNGRepresentation(resultImage.get());
+}
+
+- (void)drawingDidChange:(PKCanvasView *)canvasView
+{
+    if (!_webPageProxy)
+        return;
+    auto& page = *_webPageProxy;
+
+    page.editableImageController().invalidateAttachmentForEditableImage(self.embeddedViewID);
+}
+
 @end
 
 #endif // HAVE(PENCILKIT)

Modified: trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj (238537 => 238538)


--- trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj	2018-11-27 01:15:08 UTC (rev 238537)
+++ trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj	2018-11-27 01:37:22 UTC (rev 238538)
@@ -604,6 +604,7 @@
 		2D54C319212F3B330049C174 /* UnifiedSource62-mm.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D54C305212F3B330049C174 /* UnifiedSource62-mm.mm */; };
 		2D54C31A212F3B330049C174 /* UnifiedSource61-mm.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D54C306212F3B330049C174 /* UnifiedSource61-mm.mm */; };
 		2D54C31B212F4DA60049C174 /* ProcessLauncher.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AE117F511DBB30900981615 /* ProcessLauncher.cpp */; };
+		2D5875BF219B53150070B9AA /* EditableImageController.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D5875BD219B53150070B9AA /* EditableImageController.h */; };
 		2D5C9D0619C81D8F00B3C5C1 /* WebPageOverlay.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D5C9D0419C81D8F00B3C5C1 /* WebPageOverlay.h */; };
 		2D6AB541192B1C4A003A9FD1 /* WKPDFPageNumberIndicator.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D6AB53F192B1C4A003A9FD1 /* WKPDFPageNumberIndicator.h */; };
 		2D6B371B18A967AD0042AE80 /* _WKThumbnailView.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D6B371918A967AD0042AE80 /* _WKThumbnailView.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -2537,6 +2538,9 @@
 		2D54C304212F3B330049C174 /* UnifiedSource71-mm.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "UnifiedSource71-mm.mm"; path = "DerivedSources/WebKit2/unified-sources/UnifiedSource71-mm.mm"; sourceTree = BUILT_PRODUCTS_DIR; };
 		2D54C305212F3B330049C174 /* UnifiedSource62-mm.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "UnifiedSource62-mm.mm"; path = "DerivedSources/WebKit2/unified-sources/UnifiedSource62-mm.mm"; sourceTree = BUILT_PRODUCTS_DIR; };
 		2D54C306212F3B330049C174 /* UnifiedSource61-mm.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "UnifiedSource61-mm.mm"; path = "DerivedSources/WebKit2/unified-sources/UnifiedSource61-mm.mm"; sourceTree = BUILT_PRODUCTS_DIR; };
+		2D5875BB219B28A50070B9AA /* EditableImageController.messages.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = EditableImageController.messages.in; path = ios/EditableImageController.messages.in; sourceTree = "<group>"; };
+		2D5875BD219B53150070B9AA /* EditableImageController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = EditableImageController.h; path = ios/EditableImageController.h; sourceTree = "<group>"; };
+		2D5875BE219B53150070B9AA /* EditableImageController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = EditableImageController.mm; path = ios/EditableImageController.mm; sourceTree = "<group>"; };
 		2D5C9D0319C81D8F00B3C5C1 /* WebPageOverlay.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebPageOverlay.cpp; sourceTree = "<group>"; };
 		2D5C9D0419C81D8F00B3C5C1 /* WebPageOverlay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebPageOverlay.h; sourceTree = "<group>"; };
 		2D6AB53F192B1C4A003A9FD1 /* WKPDFPageNumberIndicator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WKPDFPageNumberIndicator.h; path = ios/WKPDFPageNumberIndicator.h; sourceTree = "<group>"; };
@@ -5789,6 +5793,9 @@
 				1AD4C1901B39F33200ABC28E /* ApplicationStateTracker.mm */,
 				F496A42F1F58A272004C1757 /* DragDropInteractionState.h */,
 				F496A4301F58A272004C1757 /* DragDropInteractionState.mm */,
+				2D5875BD219B53150070B9AA /* EditableImageController.h */,
+				2D5875BB219B28A50070B9AA /* EditableImageController.messages.in */,
+				2D5875BE219B53150070B9AA /* EditableImageController.mm */,
 				2DD45ADC1E5F8972006C355F /* InputViewUpdateDeferrer.h */,
 				2DD45ADD1E5F8972006C355F /* InputViewUpdateDeferrer.mm */,
 				0F0C365D18C110A500F607D7 /* LayerRepresentation.mm */,
@@ -8990,6 +8997,7 @@
 				BC2652171182608100243E12 /* DrawingAreaProxy.h in Headers */,
 				1A64230912DD09EB00CAAE2C /* DrawingAreaProxyMessages.h in Headers */,
 				2DA6731A20C754B1003CB401 /* DynamicViewportSizeUpdate.h in Headers */,
+				2D5875BF219B53150070B9AA /* EditableImageController.h in Headers */,
 				E105FE5418D7B9DE008F57A8 /* EditingRange.h in Headers */,
 				1AA41AB512C02EC4002BE67B /* EditorState.h in Headers */,
 				BC032DA810F437D10058C15A /* Encoder.h in Headers */,

Modified: trunk/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h (238537 => 238538)


--- trunk/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h	2018-11-27 01:15:08 UTC (rev 238537)
+++ trunk/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h	2018-11-27 01:37:22 UTC (rev 238538)
@@ -178,6 +178,10 @@
     void showPlaybackTargetPicker(bool hasVideo, WebCore::RouteSharingPolicy, const String&) final;
 
     Seconds eventThrottlingDelay() final;
+
+    void associateEditableImageWithAttachment(WebCore::GraphicsLayer::EmbeddedViewID, const String& attachmentID) final;
+    void didCreateEditableImage(WebCore::GraphicsLayer::EmbeddedViewID) final;
+    void didDestroyEditableImage(WebCore::GraphicsLayer::EmbeddedViewID) final;
 #endif
 
 #if ENABLE(ORIENTATION_EVENTS)

Modified: trunk/Source/WebKit/WebProcess/WebCoreSupport/ios/WebChromeClientIOS.mm (238537 => 238538)


--- trunk/Source/WebKit/WebProcess/WebCoreSupport/ios/WebChromeClientIOS.mm	2018-11-27 01:15:08 UTC (rev 238537)
+++ trunk/Source/WebKit/WebProcess/WebCoreSupport/ios/WebChromeClientIOS.mm	2018-11-27 01:37:22 UTC (rev 238538)
@@ -29,6 +29,7 @@
 #if PLATFORM(IOS_FAMILY)
 
 #import "DrawingArea.h"
+#import "EditableImageControllerMessages.h"
 #import "UIKitSPI.h"
 #import "WebCoreArgumentCoders.h"
 #import "WebFrame.h"
@@ -159,6 +160,34 @@
     return Icon::createIconForImage(iconForFile([NSURL fileURLWithPath:filenames[0] isDirectory:NO]).CGImage);
 }
 
+void WebChromeClient::associateEditableImageWithAttachment(GraphicsLayer::EmbeddedViewID embeddedViewID, const String& attachmentID)
+{
+#if HAVE(PENCILKIT)
+    m_page.send(Messages::EditableImageController::AssociateWithAttachment(embeddedViewID, attachmentID));
+#else
+    UNUSED_PARAM(embeddedViewID);
+    UNUSED_PARAM(attachmentID);
+#endif
+}
+
+void WebChromeClient::didCreateEditableImage(GraphicsLayer::EmbeddedViewID embeddedViewID)
+{
+#if HAVE(PENCILKIT)
+    m_page.send(Messages::EditableImageController::DidCreateEditableImage(embeddedViewID));
+#else
+    UNUSED_PARAM(embeddedViewID);
+#endif
+}
+
+void WebChromeClient::didDestroyEditableImage(GraphicsLayer::EmbeddedViewID embeddedViewID)
+{
+#if HAVE(PENCILKIT)
+    m_page.send(Messages::EditableImageController::DidDestroyEditableImage(embeddedViewID));
+#else
+    UNUSED_PARAM(embeddedViewID);
+#endif
+}
+
 } // namespace WebKit
 
 #endif // PLATFORM(IOS_FAMILY)

Modified: trunk/Tools/ChangeLog (238537 => 238538)


--- trunk/Tools/ChangeLog	2018-11-27 01:15:08 UTC (rev 238537)
+++ trunk/Tools/ChangeLog	2018-11-27 01:37:22 UTC (rev 238538)
@@ -1,3 +1,22 @@
+2018-11-26  Tim Horton  <[email protected]>
+
+        Insert <attachment> elements under editable images to make their backing data accessible
+        https://bugs.webkit.org/show_bug.cgi?id=191844
+        <rdar://problem/30900149>
+
+        Reviewed by Simon Fraser.
+
+        * DumpRenderTree/ios/UIScriptControllerIOS.mm:
+        (WTR::UIScriptController::attachmentInfo):
+        * TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
+        * TestRunnerShared/UIScriptContext/UIScriptController.cpp:
+        (WTR::UIScriptController::attachmentInfo):
+        * TestRunnerShared/UIScriptContext/UIScriptController.h:
+        * WebKitTestRunner/ios/UIScriptControllerIOS.mm:
+        (WTR::UIScriptController::attachmentInfo):
+        Add a UIScriptController mechanism to retrieve information about
+        a given attachment.
+
 2018-11-26  Aakash Jain  <[email protected]>
 
         [ews-app] Add support to communicate with Buildbot

Modified: trunk/Tools/DumpRenderTree/ios/UIScriptControllerIOS.mm (238537 => 238538)


--- trunk/Tools/DumpRenderTree/ios/UIScriptControllerIOS.mm	2018-11-27 01:15:08 UTC (rev 238537)
+++ trunk/Tools/DumpRenderTree/ios/UIScriptControllerIOS.mm	2018-11-27 01:37:22 UTC (rev 238538)
@@ -427,6 +427,11 @@
     doAsyncTask(callback);
 }
 
+JSObjectRef UIScriptController::attachmentInfo(JSStringRef)
+{
+    return nullptr;
 }
 
+}
+
 #endif // PLATFORM(IOS_FAMILY)

Modified: trunk/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl (238537 => 238538)


--- trunk/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl	2018-11-27 01:15:08 UTC (rev 238537)
+++ trunk/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl	2018-11-27 01:37:22 UTC (rev 238538)
@@ -286,4 +286,6 @@
 
     void drawSquareInEditableImage();
     readonly attribute long numberOfStrokesInEditableImage;
+
+    object attachmentInfo(DOMString attachmentIdentifier);
 };

Modified: trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.cpp (238537 => 238538)


--- trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.cpp	2018-11-27 01:15:08 UTC (rev 238537)
+++ trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.cpp	2018-11-27 01:37:22 UTC (rev 238538)
@@ -501,6 +501,11 @@
     return 0;
 }
 
+JSObjectRef UIScriptController::attachmentInfo(JSStringRef)
+{
+    return nullptr;
+}
+
 #endif
 
 #if !PLATFORM(COCOA)

Modified: trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h (238537 => 238538)


--- trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h	2018-11-27 01:15:08 UTC (rev 238537)
+++ trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h	2018-11-27 01:37:22 UTC (rev 238538)
@@ -200,6 +200,8 @@
     void drawSquareInEditableImage();
     long numberOfStrokesInEditableImage();
 
+    JSObjectRef attachmentInfo(JSStringRef attachmentIdentifier);
+
 private:
     UIScriptController(UIScriptContext&);
     

Modified: trunk/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm (238537 => 238538)


--- trunk/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm	2018-11-27 01:15:08 UTC (rev 238537)
+++ trunk/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm	2018-11-27 01:37:22 UTC (rev 238538)
@@ -931,6 +931,25 @@
     doAsyncTask(callback);
 }
 
+JSObjectRef UIScriptController::attachmentInfo(JSStringRef jsAttachmentIdentifier)
+{
+    TestRunnerWKWebView *webView = TestController::singleton().mainWebView()->platformView();
+
+    auto attachmentIdentifier = toWTFString(toWK(jsAttachmentIdentifier));
+    _WKAttachment *attachment = [webView _attachmentForIdentifier:attachmentIdentifier];
+    _WKAttachmentInfo *attachmentInfo = attachment.info;
+
+    NSDictionary *attachmentInfoDictionary = @{
+        @"id": attachmentIdentifier,
+        @"name": attachmentInfo.name,
+        @"contentType": attachmentInfo.contentType,
+        @"filePath": attachmentInfo.filePath,
+        @"size": @(attachmentInfo.data.length),
+    };
+
+    return JSValueToObject(m_context->jsContext(), [JSValue valueWithObject:attachmentInfoDictionary inContext:[JSContext contextWithJSGlobalContextRef:m_context->jsContext()]].JSValueRef, nullptr);
 }
 
+}
+
 #endif // PLATFORM(IOS_FAMILY)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to