[Attachment Support] Implement WKWebView SPI for inserting attachment elements
authorwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 31 Oct 2017 19:29:12 +0000 (19:29 +0000)
committerwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 31 Oct 2017 19:29:12 +0000 (19:29 +0000)
https://bugs.webkit.org/show_bug.cgi?id=179013
<rdar://problem/35249668>

Reviewed by Tim Horton.

Source/WebCore:

Adds Editor helper methods to insert an attachment element at the current selection.

Test: WKAttachmentTests.AttachmentElementInsertion

* editing/Editor.cpp:
(WebCore::Editor::insertAttachment):
(WebCore::Editor::insertAttachmentFromFile):
* editing/Editor.h:

Add two new helpers for inserting attachment elements, either from a filename or a data blob. This is a wrapper
around Editor::replaceSelectionWithFragment.

* html/HTMLAttachmentElement.cpp:
(WebCore::HTMLAttachmentElement::HTMLAttachmentElement):
(WebCore::HTMLAttachmentElement::create):
* html/HTMLAttachmentElement.h:

Add a unique identifier string to HTMLAttachmentElement. This unique identifier allows the UI process to
reference and indirectly manipulate attachment elements.

Source/WebCore/PAL:

Add a PAL library function to convert a file size to a human-readable string. On Cocoa platforms, this is a
wrapper around NSLocalizedFileSizeDescription; otherwise, we fall back to a naive platform-agnostic
implementation in FileSizeFormatter.cpp.

* PAL.xcodeproj/project.pbxproj:
* pal/CMakeLists.txt:
* pal/FileSizeFormatter.cpp: Added.
(fileSizeDescription):
* pal/FileSizeFormatter.h: Added.
* pal/cocoa/FileSizeFormatterCocoa.mm: Added.
(fileSizeDescription):
* pal/spi/cocoa/NSFileSizeFormatterSPI.h: Added.

Source/WebKit:

Adds native SPI to insert attachment elements given a filename, an optional MIME type, and a data blob. See
change-by-change comments below for more detail. Covered by a new API test.

* PlatformMac.cmake:
* Shared/API/APIObject.h:
* Shared/API/Cocoa/WebKitPrivate.h:
* UIProcess/API/APIAttachment.cpp: Copied from Source/WebKit/Shared/API/Cocoa/WebKitPrivate.h.
(API::Attachment::create):
(API::Attachment::Attachment):
(API::Attachment::~Attachment):

Introduce API::Attachment, which represents a platform-agnostic Attachment.

* UIProcess/API/APIAttachment.h: Copied from Source/WebKit/Shared/API/Cocoa/WebKitPrivate.h.
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _insertAttachmentWithFilename:contentType:data:options:completion:]):

Adds support for inserting a new attachment element. Calls out to WebPageProxy to insert the attachment from the
given data blob, and creates a new API-object-backed _WKAttachment.

(-[WKWebView _executeEditCommand:argument:completion:]):

Support passing in a nil completion block.

* UIProcess/API/Cocoa/WKWebViewInternal.h:
* UIProcess/API/Cocoa/WKWebViewPrivate.h:
* UIProcess/API/Cocoa/_WKAttachment.h: Copied from Source/WebKit/Shared/API/Cocoa/WebKitPrivate.h.
* UIProcess/API/Cocoa/_WKAttachment.mm: Copied from Source/WebCore/html/HTMLAttachmentElement.h.

Introduces _WKAttachment, an Objective C wrapper around the API::Attachment.

(-[_WKAttachment _apiObject]):
(-[_WKAttachment isEqual:]):
(-[_WKAttachment uniqueIdentifier]):
(-[_WKAttachment hash]):

Add _WKAttachment, a WebKit SPI object that wraps an attachment element unique identifier. Also, allow
_WKAttachment to be used as a hashable NSDictionary key.

(-[_WKAttachment description]):
* UIProcess/API/Cocoa/_WKAttachmentInternal.h: Copied from Source/WebKit/Shared/API/Cocoa/WebKitPrivate.h.
(API::wrapper):
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::insertAttachment):

Implement IPC support for inserting an attachment.

* UIProcess/WebPageProxy.h:
* WebKit.xcodeproj/project.pbxproj:
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::insertAttachment):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:

Tools:

Adds a new API test suite to exercise attachment element insertion and manipulation.

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm: Added.
(webViewForTestingAttachments):
(testHTMLData):
(testImageData):
(-[TestWKWebView synchronouslyInsertAttachmentWithFilename:contentType:data:options:]):
(-[TestWKWebView valueOfAttribute:forQuerySelector:]):
(TestWebKitAPI::TEST):

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

34 files changed:
Source/WebCore/ChangeLog
Source/WebCore/PAL/ChangeLog
Source/WebCore/PAL/PAL.xcodeproj/project.pbxproj
Source/WebCore/PAL/pal/CMakeLists.txt
Source/WebCore/PAL/pal/FileSizeFormatter.cpp [new file with mode: 0644]
Source/WebCore/PAL/pal/FileSizeFormatter.h [new file with mode: 0644]
Source/WebCore/PAL/pal/cocoa/FileSizeFormatterCocoa.mm [new file with mode: 0644]
Source/WebCore/PAL/pal/spi/cocoa/NSFileSizeFormatterSPI.h [new file with mode: 0644]
Source/WebCore/editing/Editor.cpp
Source/WebCore/editing/Editor.h
Source/WebCore/html/HTMLAttachmentElement.cpp
Source/WebCore/html/HTMLAttachmentElement.h
Source/WebKit/ChangeLog
Source/WebKit/Platform/cocoa/SharedMemoryCocoa.cpp
Source/WebKit/PlatformMac.cmake
Source/WebKit/Shared/API/APIObject.h
Source/WebKit/Shared/API/Cocoa/WebKitPrivate.h
Source/WebKit/UIProcess/API/APIAttachment.cpp [new file with mode: 0644]
Source/WebKit/UIProcess/API/APIAttachment.h [new file with mode: 0644]
Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm
Source/WebKit/UIProcess/API/Cocoa/WKWebViewInternal.h
Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h
Source/WebKit/UIProcess/API/Cocoa/_WKAttachment.h [new file with mode: 0644]
Source/WebKit/UIProcess/API/Cocoa/_WKAttachment.mm [new file with mode: 0644]
Source/WebKit/UIProcess/API/Cocoa/_WKAttachmentInternal.h [new file with mode: 0644]
Source/WebKit/UIProcess/WebPageProxy.cpp
Source/WebKit/UIProcess/WebPageProxy.h
Source/WebKit/WebKit.xcodeproj/project.pbxproj
Source/WebKit/WebProcess/WebPage/WebPage.cpp
Source/WebKit/WebProcess/WebPage/WebPage.h
Source/WebKit/WebProcess/WebPage/WebPage.messages.in
Tools/ChangeLog
Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm [new file with mode: 0644]

index 57e9f6d..7e4d0d5 100644 (file)
@@ -1,3 +1,31 @@
+2017-10-31  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        [Attachment Support] Implement WKWebView SPI for inserting attachment elements
+        https://bugs.webkit.org/show_bug.cgi?id=179013
+        <rdar://problem/35249668>
+
+        Reviewed by Tim Horton.
+
+        Adds Editor helper methods to insert an attachment element at the current selection.
+
+        Test: WKAttachmentTests.AttachmentElementInsertion
+
+        * editing/Editor.cpp:
+        (WebCore::Editor::insertAttachment):
+        (WebCore::Editor::insertAttachmentFromFile):
+        * editing/Editor.h:
+
+        Add two new helpers for inserting attachment elements, either from a filename or a data blob. This is a wrapper
+        around Editor::replaceSelectionWithFragment.
+
+        * html/HTMLAttachmentElement.cpp:
+        (WebCore::HTMLAttachmentElement::HTMLAttachmentElement):
+        (WebCore::HTMLAttachmentElement::create):
+        * html/HTMLAttachmentElement.h:
+
+        Add a unique identifier string to HTMLAttachmentElement. This unique identifier allows the UI process to
+        reference and indirectly manipulate attachment elements.
+
 2017-10-31  Alex Christensen  <achristensen@webkit.org>
 
         Fix custom header field setting with reloads and asynchronous navigation action policy decisions
index 852ad53..f95c7de 100644 (file)
@@ -1,3 +1,24 @@
+2017-10-31  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        [Attachment Support] Implement WKWebView SPI for inserting attachment elements
+        https://bugs.webkit.org/show_bug.cgi?id=179013
+        <rdar://problem/35249668>
+
+        Reviewed by Tim Horton.
+
+        Add a PAL library function to convert a file size to a human-readable string. On Cocoa platforms, this is a
+        wrapper around NSLocalizedFileSizeDescription; otherwise, we fall back to a naive platform-agnostic
+        implementation in FileSizeFormatter.cpp.
+
+        * PAL.xcodeproj/project.pbxproj:
+        * pal/CMakeLists.txt:
+        * pal/FileSizeFormatter.cpp: Added.
+        (fileSizeDescription):
+        * pal/FileSizeFormatter.h: Added.
+        * pal/cocoa/FileSizeFormatterCocoa.mm: Added.
+        (fileSizeDescription):
+        * pal/spi/cocoa/NSFileSizeFormatterSPI.h: Added.
+
 2017-10-27  Keith Miller  <keith_miller@apple.com>
 
         Move iOS specific sources to unified sources
index f51adb0..37f15e9 100644 (file)
                A3AB6E651F3D217F009C14B1 /* SystemSleepListenerMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = A3AB6E631F3D217F009C14B1 /* SystemSleepListenerMac.mm */; };
                A3C66CDC1F462D6A009E6EE9 /* SessionID.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A3C66CDA1F462D6A009E6EE9 /* SessionID.cpp */; };
                A3C66CDD1F462D6A009E6EE9 /* SessionID.h in Headers */ = {isa = PBXBuildFile; fileRef = A3C66CDB1F462D6A009E6EE9 /* SessionID.h */; };
+               F442915E1FA52473002CC93E /* NSFileSizeFormatterSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = F442915D1FA52473002CC93E /* NSFileSizeFormatterSPI.h */; };
+               F44291601FA5261E002CC93E /* FileSizeFormatter.h in Headers */ = {isa = PBXBuildFile; fileRef = F442915F1FA5261E002CC93E /* FileSizeFormatter.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               F44291641FA52670002CC93E /* FileSizeFormatter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F44291621FA52670002CC93E /* FileSizeFormatter.cpp */; };
+               F44291681FA52705002CC93E /* FileSizeFormatterCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = F44291661FA52705002CC93E /* FileSizeFormatterCocoa.mm */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
                A3C66CDA1F462D6A009E6EE9 /* SessionID.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SessionID.cpp; sourceTree = "<group>"; };
                A3C66CDB1F462D6A009E6EE9 /* SessionID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SessionID.h; sourceTree = "<group>"; };
                C2147A4A1EFD0AA600056FA5 /* CopyPALHeaders.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = CopyPALHeaders.xcconfig; sourceTree = "<group>"; };
+               F442915D1FA52473002CC93E /* NSFileSizeFormatterSPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NSFileSizeFormatterSPI.h; sourceTree = "<group>"; };
+               F442915F1FA5261E002CC93E /* FileSizeFormatter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FileSizeFormatter.h; sourceTree = "<group>"; };
+               F44291621FA52670002CC93E /* FileSizeFormatter.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FileSizeFormatter.cpp; sourceTree = "<group>"; };
+               F44291661FA52705002CC93E /* FileSizeFormatterCocoa.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FileSizeFormatterCocoa.mm; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
                                0C2DA1311F3BEB4900DBC317 /* NSColorSPI.h */,
                                0C2DA1321F3BEB4900DBC317 /* NSExtensionSPI.h */,
                                0C2DA1331F3BEB4900DBC317 /* NSFileManagerSPI.h */,
+                               F442915D1FA52473002CC93E /* NSFileSizeFormatterSPI.h */,
                                0C2DA1341F3BEB4900DBC317 /* NSStringSPI.h */,
                                0C2DA1351F3BEB4900DBC317 /* NSTouchBarSPI.h */,
                                0C2DA1361F3BEB4900DBC317 /* NSURLConnectionSPI.h */,
                                A3788E9F1F05B7CE00679425 /* system */,
                                A30D411D1F0DD0AC00B71954 /* text */,
                                0C2D9E721EEF5AF600DBC317 /* ExportMacros.h */,
+                               F44291621FA52670002CC93E /* FileSizeFormatter.cpp */,
+                               F442915F1FA5261E002CC93E /* FileSizeFormatter.h */,
                                A39DE74D1F7C443C007BCB00 /* HysteresisActivity.h */,
                                0708AC321F4C874A001F788F /* Logger.h */,
                                07377ADB1F5777D70027F16D /* LoggerHelper.h */,
                1C4876DE1F8D831300CCEEBD /* cocoa */ = {
                        isa = PBXGroup;
                        children = (
+                               F44291661FA52705002CC93E /* FileSizeFormatterCocoa.mm */,
                                1C4876DF1F8D837500CCEEBD /* LoggingCocoa.mm */,
                        );
                        path = cocoa;
                                0C5AF91A1F43A4C7002EAC02 /* DataDetectorsUISPI.h in Headers */,
                                A1175B571F6B470500C4B9F0 /* DefaultSearchProvider.h in Headers */,
                                0C2D9E731EEF5AF600DBC317 /* ExportMacros.h in Headers */,
+                               F44291601FA5261E002CC93E /* FileSizeFormatter.h in Headers */,
                                A10265871F56746100B4C844 /* FoundationSPI.h in Headers */,
                                0C5AF91B1F43A4C7002EAC02 /* GraphicsServicesSPI.h in Headers */,
                                A102658E1F567E9D00B4C844 /* HIServicesSPI.h in Headers */,
                                0C77858F1F45130F00F4EBB6 /* NSEventSPI.h in Headers */,
                                0C2DA14E1F3BEB4900DBC317 /* NSExtensionSPI.h in Headers */,
                                0C2DA14F1F3BEB4900DBC317 /* NSFileManagerSPI.h in Headers */,
+                               F442915E1FA52473002CC93E /* NSFileSizeFormatterSPI.h in Headers */,
                                0C7785901F45130F00F4EBB6 /* NSFontSPI.h in Headers */,
                                A10826FE1F58A433004772AC /* NSGraphicsSPI.h in Headers */,
                                0C7785911F45130F00F4EBB6 /* NSImmediateActionGestureRecognizerSPI.h in Headers */,
                                0CF99CA81F738437007EE793 /* CoreMediaSoftLink.cpp in Sources */,
                                1C09D0561E31C46500725F18 /* CryptoDigestCommonCrypto.cpp in Sources */,
                                A1175B581F6B470500C4B9F0 /* DefaultSearchProvider.cpp in Sources */,
+                               F44291641FA52670002CC93E /* FileSizeFormatter.cpp in Sources */,
+                               F44291681FA52705002CC93E /* FileSizeFormatterCocoa.mm in Sources */,
                                A30D41221F0DD0EA00B71954 /* KillRing.cpp in Sources */,
                                A30D41251F0DD12D00B71954 /* KillRingMac.mm in Sources */,
                                1C4876D81F8D7F4E00CCEEBD /* Logging.cpp in Sources */,
index a69db1c..544fff1 100644 (file)
@@ -1,4 +1,5 @@
 set(PAL_SOURCES
+    FileSizeFormatter.cpp
     Logging.cpp
     SessionID.cpp
 
diff --git a/Source/WebCore/PAL/pal/FileSizeFormatter.cpp b/Source/WebCore/PAL/pal/FileSizeFormatter.cpp
new file mode 100644 (file)
index 0000000..6af6512
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "FileSizeFormatter.h"
+
+#if !PLATFORM(COCOA)
+
+String fileSizeDescription(uint64_t size)
+{
+    // FIXME: These strings should be localized, but that would require bringing LocalizedStrings into PAL.
+    // See <https://bugs.webkit.org/show_bug.cgi?id=179019> for more details.
+    if (size < 1000)
+        return String::format("%tu bytes", size);
+    if (size < 1000000)
+        return String::format("%.1f KB", size / 1000.);
+    if (size < 1000000000)
+        return String::format("%.1f MB", size / 1000000.);
+    return String::format("%.1f GB", size / 1000000000.);
+}
+
+#endif
diff --git a/Source/WebCore/PAL/pal/FileSizeFormatter.h b/Source/WebCore/PAL/pal/FileSizeFormatter.h
new file mode 100644 (file)
index 0000000..2aea127
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <wtf/text/WTFString.h>
+
+PAL_EXPORT String fileSizeDescription(uint64_t);
diff --git a/Source/WebCore/PAL/pal/cocoa/FileSizeFormatterCocoa.mm b/Source/WebCore/PAL/pal/cocoa/FileSizeFormatterCocoa.mm
new file mode 100644 (file)
index 0000000..47095ba
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "FileSizeFormatter.h"
+
+#import "NSFileSizeFormatterSPI.h"
+
+String fileSizeDescription(uint64_t size)
+{
+    return NSLocalizedFileSizeDescription(size, 0, 0);
+}
diff --git a/Source/WebCore/PAL/pal/spi/cocoa/NSFileSizeFormatterSPI.h b/Source/WebCore/PAL/pal/spi/cocoa/NSFileSizeFormatterSPI.h
new file mode 100644 (file)
index 0000000..95576fd
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if USE(APPLE_INTERNAL_SDK)
+
+#import <Foundation/NSFileSizeFormatter.h>
+
+#else
+
+typedef uint64_t NSFileSizeFormatterOptions;
+extern "C" NSString *NSLocalizedFileSizeDescription(uint64_t size, uint64_t maximumDisplayedValue, NSFileSizeFormatterOptions);
+
+#endif
index 22116a0..2644dbd 100644 (file)
 #include "EditorClient.h"
 #include "EventHandler.h"
 #include "EventNames.h"
+#include "File.h"
 #include "FocusController.h"
 #include "Frame.h"
 #include "FrameLoader.h"
 #include "FrameTree.h"
 #include "FrameView.h"
 #include "GraphicsContext.h"
+#include "HTMLAttachmentElement.h"
 #include "HTMLCollection.h"
 #include "HTMLFormControlElement.h"
 #include "HTMLFrameOwnerElement.h"
 #include "UserTypingGestureIndicator.h"
 #include "VisibleUnits.h"
 #include "markup.h"
+#include <pal/FileSizeFormatter.h>
 #include <pal/system/Sound.h>
 #include <pal/text/KillRing.h>
 #include <wtf/unicode/CharacterNames.h>
@@ -3728,6 +3731,39 @@ RefPtr<Range> Editor::rangeForTextCheckingResult(const TextCheckingResult& resul
     return TextIterator::subrange(*contextRange, result.location, result.length);
 }
 
+#if ENABLE(ATTACHMENT_ELEMENT)
+
+void Editor::insertAttachment(const String& identifier, const String& filename, const String& filepath, std::optional<String> contentType)
+{
+    if (!contentType)
+        contentType = File::contentTypeForFile(filename);
+    insertAttachmentFromFile(identifier, filename, *contentType, File::create(filepath));
+}
+
+void Editor::insertAttachment(const String& identifier, const String& filename, Ref<SharedBuffer>&& data, std::optional<String> contentType)
+{
+    if (!contentType)
+        contentType = File::contentTypeForFile(filename);
+    insertAttachmentFromFile(identifier, filename, *contentType, File::create(Blob::create(data, *contentType), filename));
+}
+
+void Editor::insertAttachmentFromFile(const String& identifier, const String& filename, const String& contentType, Ref<File>&& file)
+{
+    auto attachment = HTMLAttachmentElement::create(HTMLNames::attachmentTag, document(), identifier);
+    attachment->setAttribute(HTMLNames::titleAttr, filename);
+    attachment->setAttribute(HTMLNames::subtitleAttr, fileSizeDescription(file->size()));
+    attachment->setAttribute(HTMLNames::typeAttr, contentType);
+    attachment->setUniqueIdentifier(identifier);
+    attachment->setFile(file.ptr());
+
+    auto fragmentToInsert = document().createDocumentFragment();
+    fragmentToInsert->appendChild(attachment.get());
+
+    replaceSelectionWithFragment(fragmentToInsert.get(), false, false, true);
+}
+
+#endif // ENABLE(ATTACHMENT_ELEMENT)
+
 void Editor::handleAcceptedCandidate(TextCheckingResult acceptedCandidate)
 {
     const VisibleSelection& selection = m_frame.selection().selection();
index b1e82fe..2ba89b6 100644 (file)
@@ -63,7 +63,9 @@ class EditCommand;
 class EditCommandComposition;
 class EditorClient;
 class EditorInternalCommand;
+class File;
 class Frame;
+class HTMLAttachmentElement;
 class HTMLElement;
 class HitTestResult;
 class KeyboardEvent;
@@ -498,9 +500,18 @@ public:
     void setIsGettingDictionaryPopupInfo(bool b) { m_isGettingDictionaryPopupInfo = b; }
     bool isGettingDictionaryPopupInfo() const { return m_isGettingDictionaryPopupInfo; }
 
+#if ENABLE(ATTACHMENT_ELEMENT)
+    WEBCORE_EXPORT void insertAttachment(const String& identifier, const String& filename, const String& filepath, std::optional<String> contentType = std::nullopt);
+    WEBCORE_EXPORT void insertAttachment(const String& identifier, const String& filename, Ref<SharedBuffer>&& data, std::optional<String> contentType = std::nullopt);
+#endif
+
 private:
     Document& document() const;
 
+#if ENABLE(ATTACHMENT_ELEMENT)
+    void insertAttachmentFromFile(const String& identifier, const String& filename, const String& contentType, Ref<File>&&);
+#endif
+
     bool canDeleteRange(Range*) const;
     bool canSmartReplaceWithPasteboard(Pasteboard&);
     void pasteAsPlainTextWithPasteboard(Pasteboard&);
index a6ed961..3bff0c7 100644 (file)
 
 #if ENABLE(ATTACHMENT_ELEMENT)
 
+#include "Editor.h"
 #include "File.h"
+#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)
+HTMLAttachmentElement::HTMLAttachmentElement(const QualifiedName& tagName, Document& document, const String& identifier)
     : 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)
@@ -49,6 +58,11 @@ Ref<HTMLAttachmentElement> HTMLAttachmentElement::create(const QualifiedName& ta
     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));
index 9ac6b6a..3a44a5f 100644 (file)
@@ -37,10 +37,14 @@ class RenderAttachment;
 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 attachmentTitle() const;
     String attachmentType() const;
 
@@ -48,6 +52,7 @@ public:
 
 private:
     HTMLAttachmentElement(const QualifiedName&, Document&);
+    HTMLAttachmentElement(const QualifiedName&, Document&, const String& identifier);
     virtual ~HTMLAttachmentElement();
 
     RenderPtr<RenderElement> createElementRenderer(RenderStyle&&, const RenderTreePosition&) final;
@@ -63,6 +68,7 @@ private:
     void parseAttribute(const QualifiedName&, const AtomicString&) final;
     
     RefPtr<File> m_file;
+    String m_uniqueIdentifier;
 };
 
 } // namespace WebCore
index 80b14f4..56231fe 100644 (file)
@@ -1,3 +1,65 @@
+2017-10-31  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        [Attachment Support] Implement WKWebView SPI for inserting attachment elements
+        https://bugs.webkit.org/show_bug.cgi?id=179013
+        <rdar://problem/35249668>
+
+        Reviewed by Tim Horton.
+
+        Adds native SPI to insert attachment elements given a filename, an optional MIME type, and a data blob. See
+        change-by-change comments below for more detail. Covered by a new API test.
+
+        * PlatformMac.cmake:
+        * Shared/API/APIObject.h:
+        * Shared/API/Cocoa/WebKitPrivate.h:
+        * UIProcess/API/APIAttachment.cpp: Copied from Source/WebKit/Shared/API/Cocoa/WebKitPrivate.h.
+        (API::Attachment::create):
+        (API::Attachment::Attachment):
+        (API::Attachment::~Attachment):
+
+        Introduce API::Attachment, which represents a platform-agnostic Attachment.
+
+        * UIProcess/API/APIAttachment.h: Copied from Source/WebKit/Shared/API/Cocoa/WebKitPrivate.h.
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView _insertAttachmentWithFilename:contentType:data:options:completion:]):
+
+        Adds support for inserting a new attachment element. Calls out to WebPageProxy to insert the attachment from the
+        given data blob, and creates a new API-object-backed _WKAttachment.
+
+        (-[WKWebView _executeEditCommand:argument:completion:]):
+
+        Support passing in a nil completion block.
+
+        * UIProcess/API/Cocoa/WKWebViewInternal.h:
+        * UIProcess/API/Cocoa/WKWebViewPrivate.h:
+        * UIProcess/API/Cocoa/_WKAttachment.h: Copied from Source/WebKit/Shared/API/Cocoa/WebKitPrivate.h.
+        * UIProcess/API/Cocoa/_WKAttachment.mm: Copied from Source/WebCore/html/HTMLAttachmentElement.h.
+
+        Introduces _WKAttachment, an Objective C wrapper around the API::Attachment.
+
+        (-[_WKAttachment _apiObject]):
+        (-[_WKAttachment isEqual:]):
+        (-[_WKAttachment uniqueIdentifier]):
+        (-[_WKAttachment hash]):
+
+        Add _WKAttachment, a WebKit SPI object that wraps an attachment element unique identifier. Also, allow
+        _WKAttachment to be used as a hashable NSDictionary key.
+
+        (-[_WKAttachment description]):
+        * UIProcess/API/Cocoa/_WKAttachmentInternal.h: Copied from Source/WebKit/Shared/API/Cocoa/WebKitPrivate.h.
+        (API::wrapper):
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::insertAttachment):
+
+        Implement IPC support for inserting an attachment.
+
+        * UIProcess/WebPageProxy.h:
+        * WebKit.xcodeproj/project.pbxproj:
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::insertAttachment):
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+
 2017-10-31  Alex Christensen  <achristensen@webkit.org>
 
         Fix custom header field setting with reloads and asynchronous navigation action policy decisions
index aea7985..554015e 100644 (file)
@@ -31,6 +31,7 @@
 #include "Logging.h"
 #include "MachPort.h"
 #include <WebCore/MachSendRight.h>
+#include <WebCore/SharedBuffer.h>
 #include <mach/mach_error.h>
 #include <mach/mach_port.h>
 #include <mach/vm_map.h>
index 0e6f669..789f384 100644 (file)
@@ -222,6 +222,7 @@ list(APPEND WebKit_SOURCES
     UIProcess/API/Cocoa/WKWebsiteDataStore.mm
     UIProcess/API/Cocoa/WKWindowFeatures.mm
     UIProcess/API/Cocoa/_WKActivatedElementInfo.mm
+    UIProcess/API/Cocoa/_WKAttachment.mm
     UIProcess/API/Cocoa/_WKAutomationSession.mm
     UIProcess/API/Cocoa/_WKAutomationSessionConfiguration.mm
     UIProcess/API/Cocoa/_WKContextMenuElementInfo.mm
index 962864f..f6f99fa 100644 (file)
@@ -97,6 +97,7 @@ public:
         
         // UIProcess types
         ApplicationCacheManager,
+        Attachment,
         AutomationSession,
         BackForwardList,
         BackForwardListItem,
index 4a35809..18bf0c5 100644 (file)
@@ -30,6 +30,7 @@
 #import <WebKit/WKWebViewConfigurationPrivate.h>
 #import <WebKit/WKWebViewPrivate.h>
 #import <WebKit/_WKActivatedElementInfo.h>
+#import <WebKit/_WKAttachment.h>
 #import <WebKit/_WKElementAction.h>
 #import <WebKit/_WKFocusedElementInfo.h>
 #import <WebKit/_WKFormInputSession.h>
diff --git a/Source/WebKit/UIProcess/API/APIAttachment.cpp b/Source/WebKit/UIProcess/API/APIAttachment.cpp
new file mode 100644 (file)
index 0000000..91ec0b7
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "APIAttachment.h"
+
+#include <wtf/text/WTFString.h>
+
+namespace API {
+
+Ref<Attachment> Attachment::create(const WTF::String& identifier, WebKit::WebPageProxy& webPage)
+{
+    return adoptRef(*new Attachment(identifier, webPage));
+}
+
+Attachment::Attachment(const WTF::String& identifier, WebKit::WebPageProxy& webPage)
+    : m_identifier(identifier)
+    , m_webPage(webPage.createWeakPtr())
+{
+}
+
+Attachment::~Attachment()
+{
+}
+
+}
diff --git a/Source/WebKit/UIProcess/API/APIAttachment.h b/Source/WebKit/UIProcess/API/APIAttachment.h
new file mode 100644 (file)
index 0000000..245590e
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "APIObject.h"
+#include <WebKit/WKBase.h>
+#include <WebKit/WebPageProxy.h>
+#include <wtf/WeakPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebKit {
+class WebPageProxy;
+}
+
+namespace API {
+
+class Attachment final : public ObjectImpl<Object::Type::Attachment> {
+public:
+    static Ref<Attachment> create(const WTF::String& identifier, WebKit::WebPageProxy&);
+    virtual ~Attachment();
+
+    const WTF::String& identifier() const { return m_identifier; }
+
+private:
+    explicit Attachment(const WTF::String& identifier, WebKit::WebPageProxy&);
+
+    WTF::String m_identifier;
+    WeakPtr<WebKit::WebPageProxy> m_webPage;
+};
+
+} // namespace API
index 1468131..5e36e2e 100644 (file)
@@ -99,6 +99,7 @@
 #import <WebCore/SQLiteDatabaseTracker.h>
 #import <WebCore/SchemeRegistry.h>
 #import <WebCore/Settings.h>
+#import <WebCore/SharedBuffer.h>
 #import <WebCore/ValidationBubble.h>
 #import <WebCore/ViewportArguments.h>
 #import <WebCore/WritingMode.h>
 #import <wtf/Optional.h>
 #import <wtf/RetainPtr.h>
 #import <wtf/SetForScope.h>
+#import <wtf/UUID.h>
 #import <wtf/spi/darwin/dyldSPI.h>
 #import <wtf/text/TextStream.h>
 
@@ -4168,6 +4170,23 @@ static int32_t activeOrientation(WKWebView *webView)
     _page->close();
 }
 
+- (_WKAttachment *)_insertAttachmentWithFilename:(NSString *)filename contentType:(NSString *)contentType data:(NSData *)data options:(_WKAttachmentDisplayOptions *)options completion:(void(^)(BOOL success))completionHandler
+{
+#if ENABLE(ATTACHMENT_ELEMENT)
+    auto identifier = createCanonicalUUIDString();
+
+    auto buffer = WebCore::SharedBuffer::create(data);
+    _page->insertAttachment(identifier, filename, contentType.length ? std::optional<String> { contentType } : std::nullopt, buffer.get(), [capturedHandler = makeBlockPtr(completionHandler), capturedBuffer = buffer.copyRef()] (WebKit::CallbackBase::Error error) {
+        if (capturedHandler)
+            capturedHandler(error == WebKit::CallbackBase::Error::None);
+    });
+
+    return [wrapper(API::Attachment::create(identifier, *_page).leakRef()) autorelease];
+#else
+    return nil;
+#endif
+}
+
 - (void)_evaluateJavaScriptWithoutUserGesture:(NSString *)javaScriptString completionHandler:(void (^)(id, NSError *))completionHandler
 {
     [self _evaluateJavaScript:javaScriptString forceUserGesture:NO completionHandler:completionHandler];
@@ -6033,7 +6052,8 @@ static WebCore::UserInterfaceLayoutDirection toUserInterfaceLayoutDirection(UISe
 - (void)_executeEditCommand:(NSString *)command argument:(NSString *)argument completion:(void (^)(BOOL))completion
 {
     _page->executeEditCommand(command, argument, [capturedCompletionBlock = makeBlockPtr(completion)](WebKit::CallbackBase::Error error) {
-        capturedCompletionBlock(error == WebKit::CallbackBase::Error::None);
+        if (capturedCompletionBlock)
+            capturedCompletionBlock(error == WebKit::CallbackBase::Error::None);
     });
 }
 
index d2d6eb8..12ea6f5 100644 (file)
@@ -29,6 +29,7 @@
 
 #import "SameDocumentNavigationType.h"
 #import "WKWebViewConfiguration.h"
+#import "_WKAttachmentInternal.h"
 #import <wtf/RefPtr.h>
 #import <wtf/RetainPtr.h>
 
index 5ed2b2c..c9fd540 100644 (file)
@@ -28,6 +28,7 @@
 #if WK_API_ENABLED
 
 #import <WebKit/_WKActivatedElementInfo.h>
+#import <WebKit/_WKAttachment.h>
 #import <WebKit/_WKFindOptions.h>
 #import <WebKit/_WKLayoutMode.h>
 #import <WebKit/_WKOverlayScrollbarStyle.h>
@@ -177,6 +178,8 @@ typedef NS_OPTIONS(NSInteger, _WKRectEdge) {
 
 @property (nonatomic, setter=_setBackgroundExtendsBeyondPage:) BOOL _backgroundExtendsBeyondPage WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(8.0));
 
+- (_WKAttachment *)_insertAttachmentWithFilename:(NSString *)filename contentType:(NSString *)contentType data:(NSData *)data options:(_WKAttachmentDisplayOptions *)options completion:(void(^)(BOOL success))completionHandler WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
+
 #if TARGET_OS_IPHONE
 // DERECATED: The setters of the three following function are deprecated, please use overrideLayoutParameters.
 // Define the smallest size a page take with a regular viewport.
diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKAttachment.h b/Source/WebKit/UIProcess/API/Cocoa/_WKAttachment.h
new file mode 100644 (file)
index 0000000..9403239
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#import <WebKit/WKFoundation.h>
+
+#if WK_API_ENABLED
+
+typedef NS_ENUM(NSInteger, _WKAttachmentDisplayMode) {
+    _WKAttachmentDisplayModeAuto = 1,
+    _WKAttachmentDisplayModeInPlace,
+    _WKAttachmentDisplayModeAsIcon
+} WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
+
+WK_CLASS_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA))
+@interface _WKAttachmentDisplayOptions : NSObject
+@property (nonatomic) _WKAttachmentDisplayMode mode;
+@property (nonatomic) BOOL expandsImageToMaximumWidth;
+@end
+
+WK_CLASS_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA))
+@interface _WKAttachment : NSObject
+@end
+
+#endif
diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKAttachment.mm b/Source/WebKit/UIProcess/API/Cocoa/_WKAttachment.mm
new file mode 100644 (file)
index 0000000..d1b146f
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "_WKAttachment.h"
+
+#if WK_API_ENABLED
+
+#import "APIAttachment.h"
+#import "_WKAttachmentInternal.h"
+
+using namespace WebKit;
+
+@implementation _WKAttachmentDisplayOptions : NSObject
+
+- (instancetype)init
+{
+    if (self = [super init]) {
+        _mode = _WKAttachmentDisplayModeAuto;
+        _expandsImageToMaximumWidth = NO;
+    }
+    return self;
+}
+
+@end
+
+@implementation _WKAttachment
+
+- (API::Object&)_apiObject
+{
+    return *_attachment;
+}
+
+- (BOOL)isEqual:(id)object
+{
+    return [object isKindOfClass:[_WKAttachment class]] && [self.uniqueIdentifier isEqual:[(_WKAttachment *)object uniqueIdentifier]];
+}
+
+- (NSString *)uniqueIdentifier
+{
+    return _attachment->identifier();
+}
+
+- (NSUInteger)hash
+{
+    return [self.uniqueIdentifier hash];
+}
+
+- (NSString *)description
+{
+    return [NSString stringWithFormat:@"<%@ id='%@'>", [self class], self.uniqueIdentifier];
+}
+
+@end
+
+#endif // WK_API_ENABLED
diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKAttachmentInternal.h b/Source/WebKit/UIProcess/API/Cocoa/_WKAttachmentInternal.h
new file mode 100644 (file)
index 0000000..a983057
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#import "APIAttachment.h"
+#import "_WKAttachment.h"
+
+namespace API {
+
+inline _WKAttachment *wrapper(API::Attachment& attachment)
+{
+    ASSERT([attachment.wrapper() isKindOfClass:[_WKAttachment class]]);
+    return (_WKAttachment *)attachment.wrapper();
+}
+
+}
+
+@interface _WKAttachment () <WKObject> {
+@package
+    API::ObjectStorage<API::Attachment> _attachment;
+}
+@end
index dcbb528..eef13b3 100644 (file)
@@ -7105,4 +7105,14 @@ void WebPageProxy::requestStorageAccess(String&& subFrameHost, String&& topFrame
     });
 }
 
+#if ENABLE(ATTACHMENT_ELEMENT)
+
+void WebPageProxy::insertAttachment(const String& identifier, const String& filename, std::optional<String> contentType, SharedBuffer& data, Function<void(CallbackBase::Error)>&& callback)
+{
+    auto callbackID = m_callbacks.put(WTFMove(callback), m_process->throttler().backgroundActivityToken());
+    m_process->send(Messages::WebPage::InsertAttachment(identifier, filename, contentType, IPC::SharedBufferDataReference { &data }, callbackID), m_pageID);
+}
+
+#endif // ENABLE(ATTACHMENT_ELEMENT)
+
 } // namespace WebKit
index 8165257..1067eb9 100644 (file)
@@ -1211,6 +1211,10 @@ public:
 
     void requestStorageAccess(String&& subFrameHost, String&& topFrameHost, uint64_t webProcessContextId);
 
+#if ENABLE(ATTACHMENT_ELEMENT)
+    void insertAttachment(const String& identifier, const String& filename, std::optional<String> contentType, WebCore::SharedBuffer& data, Function<void(CallbackBase::Error)>&&);
+#endif
+
 private:
     WebPageProxy(PageClient&, WebProcessProxy&, uint64_t pageID, Ref<API::PageConfiguration>&&);
     void platformInitialize();
index 06f70db..7cd6e1c 100644 (file)
                2DFC7DBB1BCCC19500C1548C /* WebViewImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DFC7DB91BCCC19500C1548C /* WebViewImpl.h */; };
                2DFC7DBC1BCCC19500C1548C /* WebViewImpl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2DFC7DBA1BCCC19500C1548C /* WebViewImpl.mm */; };
                2DFF7B6F1DA4CFAF00814614 /* WKBackForwardListItemPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DFF7B6E1DA4CFAF00814614 /* WKBackForwardListItemPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               2E5C770E1FA7D429005932C3 /* APIAttachment.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E5C770C1FA7D429005932C3 /* APIAttachment.h */; };
+               2E5C770F1FA7D429005932C3 /* APIAttachment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2E5C770D1FA7D429005932C3 /* APIAttachment.cpp */; };
                2E7A944A1BBD97C300945547 /* _WKFocusedElementInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E7A94491BBD95C600945547 /* _WKFocusedElementInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
                31099973146C75A20029DEB9 /* WebNotificationClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 31099971146C759B0029DEB9 /* WebNotificationClient.cpp */; };
                310999C7146C9E3D0029DEB9 /* WebNotificationClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 31099968146C71F50029DEB9 /* WebNotificationClient.h */; };
                EDCA71B7128DDA8C00201B26 /* WKBundlePageOverlay.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A22F1001289FCD90085E74F /* WKBundlePageOverlay.cpp */; };
                F036978815F4BF0500C3A80E /* WebColorPicker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F036978715F4BF0500C3A80E /* WebColorPicker.cpp */; };
                F409BA181E6E64BC009DA28E /* WKDragDestinationAction.h in Headers */ = {isa = PBXBuildFile; fileRef = F409BA171E6E64B3009DA28E /* WKDragDestinationAction.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               F44291921FA591C9002CC93E /* _WKAttachment.h in Headers */ = {isa = PBXBuildFile; fileRef = F44291911FA59107002CC93E /* _WKAttachment.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               F44291941FA59311002CC93E /* _WKAttachment.mm in Sources */ = {isa = PBXBuildFile; fileRef = F44291931FA59311002CC93E /* _WKAttachment.mm */; };
+               F44291961FA5942A002CC93E /* _WKAttachmentInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = F44291951FA5942A002CC93E /* _WKAttachmentInternal.h */; };
                F44DFEB21E9E752F0038D196 /* WebIconUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = F44DFEB01E9E752F0038D196 /* WebIconUtilities.h */; };
                F44DFEB31E9E752F0038D196 /* WebIconUtilities.mm in Sources */ = {isa = PBXBuildFile; fileRef = F44DFEB11E9E752F0038D196 /* WebIconUtilities.mm */; };
                F496A4311F58A272004C1757 /* DragDropInteractionState.h in Headers */ = {isa = PBXBuildFile; fileRef = F496A42F1F58A272004C1757 /* DragDropInteractionState.h */; };
                2DFC7DB91BCCC19500C1548C /* WebViewImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewImpl.h; sourceTree = "<group>"; };
                2DFC7DBA1BCCC19500C1548C /* WebViewImpl.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebViewImpl.mm; sourceTree = "<group>"; };
                2DFF7B6E1DA4CFAF00814614 /* WKBackForwardListItemPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKBackForwardListItemPrivate.h; sourceTree = "<group>"; };
+               2E5C770C1FA7D429005932C3 /* APIAttachment.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = APIAttachment.h; sourceTree = "<group>"; };
+               2E5C770D1FA7D429005932C3 /* APIAttachment.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = APIAttachment.cpp; sourceTree = "<group>"; };
                2E7A94491BBD95C600945547 /* _WKFocusedElementInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = _WKFocusedElementInfo.h; sourceTree = "<group>"; };
                31099968146C71F50029DEB9 /* WebNotificationClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebNotificationClient.h; sourceTree = "<group>"; };
                31099971146C759B0029DEB9 /* WebNotificationClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebNotificationClient.cpp; sourceTree = "<group>"; };
                ECBFC1DB1E6A4D66000300C7 /* ExtraPublicSymbolsForTAPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ExtraPublicSymbolsForTAPI.h; sourceTree = "<group>"; };
                F036978715F4BF0500C3A80E /* WebColorPicker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebColorPicker.cpp; sourceTree = "<group>"; };
                F409BA171E6E64B3009DA28E /* WKDragDestinationAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKDragDestinationAction.h; sourceTree = "<group>"; };
+               F44291911FA59107002CC93E /* _WKAttachment.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = _WKAttachment.h; sourceTree = "<group>"; };
+               F44291931FA59311002CC93E /* _WKAttachment.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = _WKAttachment.mm; sourceTree = "<group>"; };
+               F44291951FA5942A002CC93E /* _WKAttachmentInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = _WKAttachmentInternal.h; sourceTree = "<group>"; };
                F44DFEB01E9E752F0038D196 /* WebIconUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebIconUtilities.h; path = ios/WebIconUtilities.h; sourceTree = "<group>"; };
                F44DFEB11E9E752F0038D196 /* WebIconUtilities.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = WebIconUtilities.mm; path = ios/WebIconUtilities.mm; sourceTree = "<group>"; };
                F496A42F1F58A272004C1757 /* DragDropInteractionState.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = DragDropInteractionState.h; path = ios/DragDropInteractionState.h; sourceTree = "<group>"; };
                                37A5E01218BBF937000A081E /* _WKActivatedElementInfo.h */,
                                37A5E01118BBF937000A081E /* _WKActivatedElementInfo.mm */,
                                379A873518BBFA4300588AF2 /* _WKActivatedElementInfoInternal.h */,
+                               F44291911FA59107002CC93E /* _WKAttachment.h */,
+                               F44291931FA59311002CC93E /* _WKAttachment.mm */,
+                               F44291951FA5942A002CC93E /* _WKAttachmentInternal.h */,
                                99E714C11C1249E600665B3A /* _WKAutomationDelegate.h */,
                                990D28A71C6404B000986977 /* _WKAutomationSession.h */,
                                990D28AD1C65190400986977 /* _WKAutomationSession.mm */,
                                37C4C08318149C2A003688B9 /* Cocoa */,
                                BC8A501311765F4500757573 /* cpp */,
                                BC111B47112F616900337BAB /* mac */,
+                               2E5C770D1FA7D429005932C3 /* APIAttachment.cpp */,
+                               2E5C770C1FA7D429005932C3 /* APIAttachment.h */,
                                99C81D5B1C20E817005C4C82 /* APIAutomationClient.h */,
                                990D28B31C6526D400986977 /* APIAutomationSessionClient.h */,
                                7C89D2B11A6B068C003A5FDE /* APIContentRuleList.cpp */,
                        files = (
                                37A5E01418BBF93F000A081E /* _WKActivatedElementInfo.h in Headers */,
                                379A873618BBFA4300588AF2 /* _WKActivatedElementInfoInternal.h in Headers */,
+                               F44291921FA591C9002CC93E /* _WKAttachment.h in Headers */,
+                               F44291961FA5942A002CC93E /* _WKAttachmentInternal.h in Headers */,
                                99E714C51C124A0400665B3A /* _WKAutomationDelegate.h in Headers */,
                                990D28AB1C6420C600986977 /* _WKAutomationSession.h in Headers */,
                                99788ACB1F421DDA00C08000 /* _WKAutomationSessionConfiguration.h in Headers */,
                                A182D5B51BE6BD250087A7CC /* AccessibilityIOS.h in Headers */,
                                A7D792D81767CCA300881CBE /* ActivityAssertion.h in Headers */,
                                BC64697011DBE603006455B0 /* APIArray.h in Headers */,
+                               2E5C770E1FA7D429005932C3 /* APIAttachment.h in Headers */,
                                99C81D5D1C21F38B005C4C82 /* APIAutomationClient.h in Headers */,
                                990D28C01C6553F100986977 /* APIAutomationSessionClient.h in Headers */,
                                1A3DD206125E5A2F004515E6 /* APIClient.h in Headers */,
                        buildActionMask = 2147483647;
                        files = (
                                37A5E01318BBF937000A081E /* _WKActivatedElementInfo.mm in Sources */,
+                               F44291941FA59311002CC93E /* _WKAttachment.mm in Sources */,
                                990D28B21C65209400986977 /* _WKAutomationSession.mm in Sources */,
                                99788ACC1F421DE200C08000 /* _WKAutomationSessionConfiguration.mm in Sources */,
                                1A5704F71BE01FF400874AF1 /* _WKContextMenuElementInfo.mm in Sources */,
                                A182D5B41BE6BD250087A7CC /* AccessibilityIOS.mm in Sources */,
                                A7D792D61767CB6E00881CBE /* ActivityAssertion.cpp in Sources */,
                                BC64696F11DBE603006455B0 /* APIArray.cpp in Sources */,
+                               2E5C770F1FA7D429005932C3 /* APIAttachment.cpp in Sources */,
                                7C89D2B31A6B068C003A5FDE /* APIContentRuleList.cpp in Sources */,
                                7C3A06A71AAB903E009D74BA /* APIContentRuleListStore.cpp in Sources */,
                                7CEFA9621AC0999300B910FD /* APIContentRuleListStoreCocoa.mm in Sources */,
index 91aa5ef..037bbfc 100644 (file)
 #include <WebCore/MIMETypeRegistry.h>
 #include <WebCore/MainFrame.h>
 #include <WebCore/MouseEvent.h>
+#include <WebCore/NotImplemented.h>
 #include <WebCore/Page.h>
 #include <WebCore/PageConfiguration.h>
 #include <WebCore/PlatformKeyboardEvent.h>
@@ -5764,4 +5765,15 @@ void WebPage::storageAccessResponse(bool wasGranted, uint64_t contextId)
     callback(wasGranted);
 }
 
+#if ENABLE(ATTACHMENT_ELEMENT)
+
+void WebPage::insertAttachment(const String& identifier, const String& filename, std::optional<String> contentType, const IPC::DataReference& data, CallbackID callbackID)
+{
+    auto& frame = m_page->focusController().focusedOrMainFrame();
+    frame.editor().insertAttachment(identifier, filename, SharedBuffer::create(data.data(), data.size()), contentType);
+    send(Messages::WebPageProxy::VoidCallback(callbackID));
+}
+
+#endif // ENABLE(ATTACHMENT_ELEMENT)
+
 } // namespace WebKit
index 73fde28..1d84d4d 100644 (file)
@@ -153,6 +153,7 @@ class MediaPlayerRequestInstallMissingPluginsCallback;
 }
 
 namespace WebKit {
+class DataReference;
 class DrawingArea;
 class DownloadID;
 class FindController;
@@ -998,6 +999,10 @@ public:
     void requestStorageAccess(String&& subFrameHost, String&& topFrameHost, WTF::Function<void (bool)>&& callback);
     void storageAccessResponse(bool wasGranted, uint64_t contextId);
 
+#if ENABLE(ATTACHMENT_ELEMENT)
+    void insertAttachment(const String& identifier, const String& filename, std::optional<String> contentType, const IPC::DataReference&, CallbackID);
+#endif
+
 private:
     WebPage(uint64_t pageID, WebPageCreationParameters&&);
 
index 461098b..1b28d1a 100644 (file)
@@ -484,4 +484,8 @@ messages -> WebPage LegacyReceiver {
     URLSchemeTaskDidComplete(uint64_t handlerIdentifier, uint64_t taskIdentifier, WebCore::ResourceError error)
 
     StorageAccessResponse(bool wasGranted, uint64_t contextId)
+
+#if ENABLE(ATTACHMENT_ELEMENT)
+    InsertAttachment(String identifier, String filename, std::optional<String> contentType, IPC::DataReference data, WebKit::CallbackID callbackID)
+#endif
 }
index 3bedf30..873d81a 100644 (file)
@@ -1,3 +1,22 @@
+2017-10-31  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        [Attachment Support] Implement WKWebView SPI for inserting attachment elements
+        https://bugs.webkit.org/show_bug.cgi?id=179013
+        <rdar://problem/35249668>
+
+        Reviewed by Tim Horton.
+
+        Adds a new API test suite to exercise attachment element insertion and manipulation.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm: Added.
+        (webViewForTestingAttachments):
+        (testHTMLData):
+        (testImageData):
+        (-[TestWKWebView synchronouslyInsertAttachmentWithFilename:contentType:data:options:]):
+        (-[TestWKWebView valueOfAttribute:forQuerySelector:]):
+        (TestWebKitAPI::TEST):
+
 2017-10-31  Alex Christensen  <achristensen@webkit.org>
 
         Fix custom header field setting with reloads and asynchronous navigation action policy decisions
index d3601aa..5a8fb53 100644 (file)
@@ -89,6 +89,7 @@
                2E1DFDF11D42E1E400714A00 /* large-video-seek-to-beginning-and-play-after-ending.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 2E1DFDF01D42E14400714A00 /* large-video-seek-to-beginning-and-play-after-ending.html */; };
                2E205BA41F527746005952DD /* AccessibilityTestsIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2E205BA31F527746005952DD /* AccessibilityTestsIOS.mm */; };
                2E54F40D1D7BC84200921ADF /* large-video-mutes-onplaying.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 2E54F40C1D7BC83900921ADF /* large-video-mutes-onplaying.html */; };
+               2E5C77071FA70136005932C3 /* WKAttachmentTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2E5C77061FA70136005932C3 /* WKAttachmentTests.mm */; };
                2E691AEA1D78B53600129407 /* large-videos-paused-video-hides-controls.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 2E691AE81D78B52B00129407 /* large-videos-paused-video-hides-controls.html */; };
                2E691AEB1D78B53600129407 /* large-videos-playing-video-keeps-controls.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 2E691AE91D78B52B00129407 /* large-videos-playing-video-keeps-controls.html */; };
                2E691AED1D78B91000129407 /* large-videos-playing-muted-video-hides-controls.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 2E691AEC1D78B90200129407 /* large-videos-playing-muted-video-hides-controls.html */; };
                2E1DFDF01D42E14400714A00 /* large-video-seek-to-beginning-and-play-after-ending.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "large-video-seek-to-beginning-and-play-after-ending.html"; sourceTree = "<group>"; };
                2E205BA31F527746005952DD /* AccessibilityTestsIOS.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = AccessibilityTestsIOS.mm; sourceTree = "<group>"; };
                2E54F40C1D7BC83900921ADF /* large-video-mutes-onplaying.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "large-video-mutes-onplaying.html"; sourceTree = "<group>"; };
+               2E5C77061FA70136005932C3 /* WKAttachmentTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = WKAttachmentTests.mm; sourceTree = "<group>"; };
                2E691AE81D78B52B00129407 /* large-videos-paused-video-hides-controls.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "large-videos-paused-video-hides-controls.html"; sourceTree = "<group>"; };
                2E691AE91D78B52B00129407 /* large-videos-playing-video-keeps-controls.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "large-videos-playing-video-keeps-controls.html"; sourceTree = "<group>"; };
                2E691AEC1D78B90200129407 /* large-videos-playing-muted-video-hides-controls.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "large-videos-playing-muted-video-hides-controls.html"; sourceTree = "<group>"; };
                                51714EB61CF8C7A4004723C4 /* WebProcessKillIDBCleanup.mm */,
                                5120C83C1E6750790025B250 /* WebsiteDataStoreCustomPaths.mm */,
                                5C9E56841DF9143D00C9EE33 /* WebsitePolicies.mm */,
+                               2E5C77061FA70136005932C3 /* WKAttachmentTests.mm */,
                                1F83571A1D3FFB0E00E3967B /* WKBackForwardList.mm */,
                                5CE354D81E70D9C300BEFE3B /* WKContentExtensionStore.mm */,
                                2D838B1E1EEF3A5B009B980E /* WKContentViewEditingActions.mm */,
                BC9096411255616000083756 /* WebKit */ = {
                        isa = PBXGroup;
                        children = (
-                               07E499901F9E56A1002F1EF3 /* GetUserMediaReprompt.mm */,
                                0F139E741A423A4600F590F5 /* cocoa */,
                                C0C5D3BB14598B6F00A802A6 /* mac */,
                                BC90977B125571AE00083756 /* Resources */,
                                F660AA0C15A5F061003A1243 /* GetInjectedBundleInitializationUserDataCallback.cpp */,
                                F660AA0F15A5F624003A1243 /* GetInjectedBundleInitializationUserDataCallback_Bundle.cpp */,
                                07CE1CF21F06A7E000BF89F5 /* GetUserMediaNavigation.mm */,
+                               07E499901F9E56A1002F1EF3 /* GetUserMediaReprompt.mm */,
                                4BFDFFA8131477770061F24B /* HitTestResultNodeHandle.cpp */,
                                4BFDFFA61314776C0061F24B /* HitTestResultNodeHandle_Bundle.cpp */,
                                BC575AAC126E83B9006F0F12 /* InjectedBundleBasic.cpp */,
                                46397B951DC2C850009A78AE /* DOMNode.mm in Sources */,
                                7CCE7EBC1A411A7E00447C4C /* DOMNodeFromJSObject.mm in Sources */,
                                7CCE7EBD1A411A7E00447C4C /* DOMRangeOfString.mm in Sources */,
-                               07E499911F9E56DF002F1EF3 /* GetUserMediaReprompt.mm in Sources */,
                                7CCE7EEC1A411AE600447C4C /* DOMWindowExtensionBasic.cpp in Sources */,
                                7CCE7EED1A411AE600447C4C /* DOMWindowExtensionNoCache.cpp in Sources */,
                                7CCE7F231A411AF600447C4C /* Download.mm in Sources */,
                                7CCE7EF91A411AE600447C4C /* GetInjectedBundleInitializationUserDataCallback.cpp in Sources */,
                                7CCE7EE21A411A9A00447C4C /* GetPIDAfterAbortedProcessLaunch.cpp in Sources */,
                                07CE1CF31F06A7E000BF89F5 /* GetUserMediaNavigation.mm in Sources */,
+                               07E499911F9E56DF002F1EF3 /* GetUserMediaReprompt.mm in Sources */,
                                316BDBAC1E7207F100DE0D5A /* GPUBuffer.mm in Sources */,
                                315231CA1EB3B3C700A22A16 /* GPUCommandQueue.mm in Sources */,
                                3162AE9C1E6F2FF5000E4DBC /* GPUDevice.mm in Sources */,
                                7CCE7F1C1A411AE600447C4C /* WillSendSubmitEvent.cpp in Sources */,
                                7CCE7ED81A411A7E00447C4C /* WillSendSubmitEvent.mm in Sources */,
                                7CCE7ED91A411A7E00447C4C /* WindowlessWebViewWithMedia.mm in Sources */,
+                               2E5C77071FA70136005932C3 /* WKAttachmentTests.mm in Sources */,
                                1F83571B1D3FFB2300E3967B /* WKBackForwardList.mm in Sources */,
                                7CCE7F2E1A411B1000447C4C /* WKBrowsingContextGroupTest.mm in Sources */,
                                7CCE7F2F1A411B1000447C4C /* WKBrowsingContextLoadDelegateTest.mm in Sources */,
diff --git a/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm b/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm
new file mode 100644 (file)
index 0000000..2ec23f4
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+
+#import "PlatformUtilities.h"
+#import "TestWKWebView.h"
+#import <WebKit/WebKit.h>
+#import <WebKit/WebKitPrivate.h>
+#import <wtf/RetainPtr.h>
+
+#if WK_API_ENABLED
+
+static RetainPtr<TestWKWebView> webViewForTestingAttachments()
+{
+    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    [configuration _setAttachmentElementEnabled:YES];
+
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500) configuration:configuration.get()]);
+    [webView synchronouslyLoadHTMLString:@"<body contenteditable></body><script>document.body.focus();</script>"];
+
+    return webView;
+}
+
+static NSData *testHTMLData()
+{
+    return [@"<a href='#'>This is some HTML data</a>" dataUsingEncoding:NSUTF8StringEncoding];
+}
+
+static NSData *testImageData()
+{
+    NSURL *url = [[NSBundle mainBundle] URLForResource:@"icon" withExtension:@"png" subdirectory:@"TestWebKitAPI.resources"];
+    return [NSData dataWithContentsOfURL:url];
+}
+
+@implementation TestWKWebView (AttachmentTesting)
+
+- (_WKAttachment *)synchronouslyInsertAttachmentWithFilename:(NSString *)filename contentType:(NSString *)contentType data:(NSData *)data options:(_WKAttachmentDisplayOptions *)options
+{
+    __block bool done = false;
+    RetainPtr<_WKAttachment> attachment = [self _insertAttachmentWithFilename:filename contentType:contentType data:data options:options completion:^(BOOL) {
+        done = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+    return attachment.autorelease();
+}
+
+- (NSString *)valueOfAttribute:(NSString *)attributeName forQuerySelector:(NSString *)querySelector
+{
+    return [self stringByEvaluatingJavaScript:[NSString stringWithFormat:@"document.querySelector('%@').getAttribute('%@')", querySelector, attributeName]];
+}
+
+@end
+
+namespace TestWebKitAPI {
+
+TEST(WKAttachmentTests, AttachmentElementInsertion)
+{
+    auto webView = webViewForTestingAttachments();
+
+    // 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"]);
+
+    // 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"]);
+}
+
+} // namespace TestWebKitAPI
+
+#endif // WK_API_ENABLED