<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[214865] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/214865">214865</a></dd>
<dt>Author</dt> <dd>wenson_hsieh@apple.com</dd>
<dt>Date</dt> <dd>2017-04-03 21:31:48 -0700 (Mon, 03 Apr 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>Data interaction should register type identifiers in order of priority
https://bugs.webkit.org/show_bug.cgi?id=170428
&lt;rdar://problem/30633296&gt;

Reviewed by Tim Horton.

Source/WebCore:

Currently, due to the shared logic for writing to a UIPasteboard (in the case of copy/paste) and the shared
UIItemProvider-based pasteboard wrapper (in the case of data interaction), we don't enforce any particular
ordering in which type identifiers are registered in the generated item provider. This is because
-[UIPasteboard setItems:] only takes an unordered mapping of type identifiers to objects.

To fix this, we introduce a separate way to set pasteboard data that first writes a list of object
representations in order of priority (which is dependent on the content being interacted with) and then register
individual type-data mappings at the end.

Augmented existing API tests in DataInteractionTests to check for the existence and priority of type identifiers
in the UIItemProviders created upon starting data interaction. Also adds a new unit test:
DataInteractionTests.TextAreaToInput.

* WebCore.xcodeproj/project.pbxproj:
* editing/cocoa/EditorCocoa.mm:
(WebCore::archivedDataForAttributedString):
(WebCore::Editor::writeSelectionToPasteboard):
(WebCore::Editor::writeSelection):
* platform/Pasteboard.h:
* platform/PasteboardWriterData.h:
* platform/PlatformPasteboard.h:
* platform/ios/AbstractPasteboard.h:
* platform/ios/AbstractPasteboard.mm: Copied from Source/WebCore/platform/ios/AbstractPasteboard.h.

Introduce WebPasteboardItemData, a wrapper around a list of objects representating the pasteboard data in order
of priority, and a dictionary containing additional NSData blobs that contain data useful for private clients.

(+[WebPasteboardItemData itemWithRepresentingObjects:additionalData:]):
(-[WebPasteboardItemData initWithRepresentingObjects:additionalData:]):
(-[WebPasteboardItemData representingObjects]):
(-[WebPasteboardItemData additionalData]):
* platform/ios/PlatformPasteboardIOS.mm:
(WebCore::richTextRepresentationsForPasteboardWebContent):
(WebCore::PlatformPasteboard::writeObjectRepresentations):
(WebCore::PlatformPasteboard::write):

Tweaked to check whether the pasteboard responds to -setItemsFromObjectRepresentations:. If so, uses the
PlatformPasteboard::writeObjectRepresentations codepath to write data to the pasteboard, respecting type
priority.

* platform/ios/WebItemProviderPasteboard.mm:
(-[WebItemProviderPasteboard pasteboardTypes]):
(-[WebItemProviderPasteboard setItemProviders:]):
(-[WebItemProviderPasteboard setItemsFromObjectRepresentations:]):

Replaces -setItems: with -setItemsFromObjectRepresentations:, which respects the priority of each object
representation of the data in the pasteboard.

(-[WebItemProviderPasteboard setItems:]): Deleted.

Source/WebKit2:

Serialize PasteboardWebContent.dataInAttributedStringFormat when sending over IPC. Refer to WebCore ChangeLog
for more details.

* Shared/WebCoreArgumentCoders.cpp:
(IPC::ArgumentCoder&lt;PasteboardWebContent&gt;::encode):
(IPC::ArgumentCoder&lt;PasteboardWebContent&gt;::decode):
* UIProcess/API/Cocoa/WKWebView.mm:

Tools:

Augments existing unit tests to check for the existence and priority of type identifiers in the UIItemProviders
created upon starting data interaction. Also fixes a race condition in one of the unit tests and adds a new unit
test for data interaction from a textarea to an input.

* TestWebKitAPI/Tests/ios/DataInteractionTests.mm:
(checkTypeIdentifierPrecedesOtherTypeIdentifier):
(TestWebKitAPI::TEST):
* TestWebKitAPI/ios/DataInteractionSimulator.h:
* TestWebKitAPI/ios/DataInteractionSimulator.mm:
(-[DataInteractionSimulator _advanceProgress]):
(-[DataInteractionSimulator sourceItemProviders]):
(-[DataInteractionSimulator _webView:showCustomSheetForElement:]):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebCoreeditingcocoaEditorCocoamm">trunk/Source/WebCore/editing/cocoa/EditorCocoa.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformPasteboardh">trunk/Source/WebCore/platform/Pasteboard.h</a></li>
<li><a href="#trunkSourceWebCoreplatformPasteboardWriterDatah">trunk/Source/WebCore/platform/PasteboardWriterData.h</a></li>
<li><a href="#trunkSourceWebCoreplatformPlatformPasteboardh">trunk/Source/WebCore/platform/PlatformPasteboard.h</a></li>
<li><a href="#trunkSourceWebCoreplatformiosAbstractPasteboardh">trunk/Source/WebCore/platform/ios/AbstractPasteboard.h</a></li>
<li><a href="#trunkSourceWebCoreplatformiosPlatformPasteboardIOSmm">trunk/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformiosWebItemProviderPasteboardmm">trunk/Source/WebCore/platform/ios/WebItemProviderPasteboard.mm</a></li>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2SharedWebCoreArgumentCoderscpp">trunk/Source/WebKit2/Shared/WebCoreArgumentCoders.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPICocoaWKWebViewmm">trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsiosDataInteractionTestsmm">trunk/Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm</a></li>
<li><a href="#trunkToolsTestWebKitAPIiosDataInteractionSimulatorh">trunk/Tools/TestWebKitAPI/ios/DataInteractionSimulator.h</a></li>
<li><a href="#trunkToolsTestWebKitAPIiosDataInteractionSimulatormm">trunk/Tools/TestWebKitAPI/ios/DataInteractionSimulator.mm</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreplatformiosAbstractPasteboardmm">trunk/Source/WebCore/platform/ios/AbstractPasteboard.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (214864 => 214865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2017-04-04 03:30:30 UTC (rev 214864)
+++ trunk/Source/WebCore/ChangeLog        2017-04-04 04:31:48 UTC (rev 214865)
</span><span class="lines">@@ -1,3 +1,61 @@
</span><ins>+2017-04-03  Wenson Hsieh  &lt;wenson_hsieh@apple.com&gt;
+
+        Data interaction should register type identifiers in order of priority
+        https://bugs.webkit.org/show_bug.cgi?id=170428
+        &lt;rdar://problem/30633296&gt;
+
+        Reviewed by Tim Horton.
+
+        Currently, due to the shared logic for writing to a UIPasteboard (in the case of copy/paste) and the shared
+        UIItemProvider-based pasteboard wrapper (in the case of data interaction), we don't enforce any particular
+        ordering in which type identifiers are registered in the generated item provider. This is because
+        -[UIPasteboard setItems:] only takes an unordered mapping of type identifiers to objects.
+
+        To fix this, we introduce a separate way to set pasteboard data that first writes a list of object
+        representations in order of priority (which is dependent on the content being interacted with) and then register
+        individual type-data mappings at the end.
+
+        Augmented existing API tests in DataInteractionTests to check for the existence and priority of type identifiers
+        in the UIItemProviders created upon starting data interaction. Also adds a new unit test:
+        DataInteractionTests.TextAreaToInput.
+
+        * WebCore.xcodeproj/project.pbxproj:
+        * editing/cocoa/EditorCocoa.mm:
+        (WebCore::archivedDataForAttributedString):
+        (WebCore::Editor::writeSelectionToPasteboard):
+        (WebCore::Editor::writeSelection):
+        * platform/Pasteboard.h:
+        * platform/PasteboardWriterData.h:
+        * platform/PlatformPasteboard.h:
+        * platform/ios/AbstractPasteboard.h:
+        * platform/ios/AbstractPasteboard.mm: Copied from Source/WebCore/platform/ios/AbstractPasteboard.h.
+
+        Introduce WebPasteboardItemData, a wrapper around a list of objects representating the pasteboard data in order
+        of priority, and a dictionary containing additional NSData blobs that contain data useful for private clients.
+
+        (+[WebPasteboardItemData itemWithRepresentingObjects:additionalData:]):
+        (-[WebPasteboardItemData initWithRepresentingObjects:additionalData:]):
+        (-[WebPasteboardItemData representingObjects]):
+        (-[WebPasteboardItemData additionalData]):
+        * platform/ios/PlatformPasteboardIOS.mm:
+        (WebCore::richTextRepresentationsForPasteboardWebContent):
+        (WebCore::PlatformPasteboard::writeObjectRepresentations):
+        (WebCore::PlatformPasteboard::write):
+
+        Tweaked to check whether the pasteboard responds to -setItemsFromObjectRepresentations:. If so, uses the
+        PlatformPasteboard::writeObjectRepresentations codepath to write data to the pasteboard, respecting type
+        priority.
+
+        * platform/ios/WebItemProviderPasteboard.mm:
+        (-[WebItemProviderPasteboard pasteboardTypes]):
+        (-[WebItemProviderPasteboard setItemProviders:]):
+        (-[WebItemProviderPasteboard setItemsFromObjectRepresentations:]):
+
+        Replaces -setItems: with -setItemsFromObjectRepresentations:, which respects the priority of each object
+        representation of the data in the pasteboard.
+
+        (-[WebItemProviderPasteboard setItems:]): Deleted.
+
</ins><span class="cx"> 2017-04-03  Javier Fernandez  &lt;jfernandez@igalia.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [css-align] Adapt place-content alignment shorthand to the new baseline syntax
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (214864 => 214865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2017-04-04 03:30:30 UTC (rev 214864)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2017-04-04 04:31:48 UTC (rev 214865)
</span><span class="lines">@@ -6830,6 +6830,7 @@
</span><span class="cx">                 F48223131E386E240066FC79 /* AbstractPasteboard.h in Headers */ = {isa = PBXBuildFile; fileRef = F48223121E386E240066FC79 /* AbstractPasteboard.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 F4BFB9851E1DDF9B00862C24 /* DumpEditingHistory.js in Copy Scripts */ = {isa = PBXBuildFile; fileRef = F48389831E1DDF2B0076B7EA /* DumpEditingHistory.js */; };
</span><span class="cx">                 F4BFB9861E1DDF9B00862C24 /* EditingHistoryUtil.js in Copy Scripts */ = {isa = PBXBuildFile; fileRef = F48389841E1DDF2B0076B7EA /* EditingHistoryUtil.js */; };
</span><ins>+                F4D831621E908C0700941174 /* AbstractPasteboard.mm in Sources */ = {isa = PBXBuildFile; fileRef = F4D831611E908C0700941174 /* AbstractPasteboard.mm */; };
</ins><span class="cx">                 F50664F7157F52DC00AC226F /* FormController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F50664F5157F52DC00AC226F /* FormController.cpp */; };
</span><span class="cx">                 F50664F8157F52DC00AC226F /* FormController.h in Headers */ = {isa = PBXBuildFile; fileRef = F50664F6157F52DC00AC226F /* FormController.h */; };
</span><span class="cx">                 F513A3EA15FF4841001526DB /* ValidationMessageClient.h in Headers */ = {isa = PBXBuildFile; fileRef = F513A3E915FF4841001526DB /* ValidationMessageClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -15332,6 +15333,7 @@
</span><span class="cx">                 F48223121E386E240066FC79 /* AbstractPasteboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AbstractPasteboard.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 F48389831E1DDF2B0076B7EA /* DumpEditingHistory.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = DumpEditingHistory.js; path = Scripts/DumpEditingHistory.js; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 F48389841E1DDF2B0076B7EA /* EditingHistoryUtil.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = EditingHistoryUtil.js; path = Scripts/EditingHistoryUtil.js; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                F4D831611E908C0700941174 /* AbstractPasteboard.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AbstractPasteboard.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 F50664F5157F52DC00AC226F /* FormController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FormController.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 F50664F6157F52DC00AC226F /* FormController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FormController.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 F513A3E915FF4841001526DB /* ValidationMessageClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ValidationMessageClient.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -20863,6 +20865,7 @@
</span><span class="cx">                         children = (
</span><span class="cx">                                 A148328B187F506800DA63A6 /* wak */,
</span><span class="cx">                                 F48223121E386E240066FC79 /* AbstractPasteboard.h */,
</span><ins>+                                F4D831611E908C0700941174 /* AbstractPasteboard.mm */,
</ins><span class="cx">                                 2655414B1489AA2B000DFC5D /* CursorIOS.cpp */,
</span><span class="cx">                                 A1ED778A1BE3293F00DC1791 /* Device.cpp */,
</span><span class="cx">                                 A1ED778B1BE3294000DC1791 /* Device.h */,
</span><span class="lines">@@ -31629,6 +31632,7 @@
</span><span class="cx">                                 A6148A7812E41E3B0044A784 /* JSHTMLKeygenElement.cpp in Sources */,
</span><span class="cx">                                 1AE2AB210A1CE63B00B42B25 /* JSHTMLLabelElement.cpp in Sources */,
</span><span class="cx">                                 1AE2AB230A1CE63B00B42B25 /* JSHTMLLegendElement.cpp in Sources */,
</span><ins>+                                F4D831621E908C0700941174 /* AbstractPasteboard.mm in Sources */,
</ins><span class="cx">                                 1AE2AB250A1CE63B00B42B25 /* JSHTMLLIElement.cpp in Sources */,
</span><span class="cx">                                 A80E7B100A19D606007FB8C5 /* JSHTMLLinkElement.cpp in Sources */,
</span><span class="cx">                                 1AE2AB270A1CE63B00B42B25 /* JSHTMLMapElement.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingcocoaEditorCocoamm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/cocoa/EditorCocoa.mm (214864 => 214865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/cocoa/EditorCocoa.mm        2017-04-04 03:30:30 UTC (rev 214864)
+++ trunk/Source/WebCore/editing/cocoa/EditorCocoa.mm        2017-04-04 04:31:48 UTC (rev 214865)
</span><span class="lines">@@ -152,6 +152,14 @@
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static RefPtr&lt;SharedBuffer&gt; archivedDataForAttributedString(NSAttributedString *attributedString)
+{
+    if (!attributedString.length)
+        return nullptr;
+
+    return SharedBuffer::wrapNSData([NSKeyedArchiver archivedDataWithRootObject:attributedString]);
+}
+
</ins><span class="cx"> void Editor::writeSelectionToPasteboard(Pasteboard&amp; pasteboard)
</span><span class="cx"> {
</span><span class="cx">     NSAttributedString *attributedString = attributedStringFromRange(*selectedRange());
</span><span class="lines">@@ -161,6 +169,7 @@
</span><span class="cx">     content.dataInWebArchiveFormat = selectionInWebArchiveFormat();
</span><span class="cx">     content.dataInRTFDFormat = attributedString.containsAttachments ? dataInRTFDFormat(attributedString) : nullptr;
</span><span class="cx">     content.dataInRTFFormat = dataInRTFFormat(attributedString);
</span><ins>+    content.dataInAttributedStringFormat = archivedDataForAttributedString(attributedString);
</ins><span class="cx">     // FIXME: Why don't we want this on iOS?
</span><span class="cx"> #if PLATFORM(MAC)
</span><span class="cx">     content.dataInHTMLFormat = selectionInHTMLFormat();
</span><span class="lines">@@ -180,6 +189,7 @@
</span><span class="cx">     webContent.dataInWebArchiveFormat = selectionInWebArchiveFormat();
</span><span class="cx">     webContent.dataInRTFDFormat = attributedString.containsAttachments ? dataInRTFDFormat(attributedString) : nullptr;
</span><span class="cx">     webContent.dataInRTFFormat = dataInRTFFormat(attributedString);
</span><ins>+    webContent.dataInAttributedStringFormat = archivedDataForAttributedString(attributedString);
</ins><span class="cx">     // FIXME: Why don't we want this on iOS?
</span><span class="cx"> #if PLATFORM(MAC)
</span><span class="cx">     webContent.dataInHTMLFormat = selectionInHTMLFormat();
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformPasteboardh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/Pasteboard.h (214864 => 214865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/Pasteboard.h        2017-04-04 03:30:30 UTC (rev 214864)
+++ trunk/Source/WebCore/platform/Pasteboard.h        2017-04-04 04:31:48 UTC (rev 214865)
</span><span class="lines">@@ -69,6 +69,7 @@
</span><span class="cx">     RefPtr&lt;SharedBuffer&gt; dataInWebArchiveFormat;
</span><span class="cx">     RefPtr&lt;SharedBuffer&gt; dataInRTFDFormat;
</span><span class="cx">     RefPtr&lt;SharedBuffer&gt; dataInRTFFormat;
</span><ins>+    RefPtr&lt;SharedBuffer&gt; dataInAttributedStringFormat;
</ins><span class="cx">     String dataInHTMLFormat;
</span><span class="cx">     String dataInStringFormat;
</span><span class="cx">     Vector&lt;String&gt; clientTypes;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformPasteboardWriterDatah"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/PasteboardWriterData.h (214864 => 214865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/PasteboardWriterData.h        2017-04-04 03:30:30 UTC (rev 214864)
+++ trunk/Source/WebCore/platform/PasteboardWriterData.h        2017-04-04 04:31:48 UTC (rev 214865)
</span><span class="lines">@@ -54,6 +54,7 @@
</span><span class="cx">         RefPtr&lt;SharedBuffer&gt; dataInWebArchiveFormat;
</span><span class="cx">         RefPtr&lt;SharedBuffer&gt; dataInRTFDFormat;
</span><span class="cx">         RefPtr&lt;SharedBuffer&gt; dataInRTFFormat;
</span><ins>+        RefPtr&lt;SharedBuffer&gt; dataInAttributedStringFormat;
</ins><span class="cx">         // FIXME: Why don't we want this on iOS?
</span><span class="cx"> #if PLATFORM(MAC)
</span><span class="cx">         String dataInHTMLFormat;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformPlatformPasteboardh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/PlatformPasteboard.h (214864 => 214865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/PlatformPasteboard.h        2017-04-04 03:30:30 UTC (rev 214864)
+++ trunk/Source/WebCore/platform/PlatformPasteboard.h        2017-04-04 04:31:48 UTC (rev 214865)
</span><span class="lines">@@ -88,6 +88,12 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> private:
</span><ins>+#if PLATFORM(IOS)
+    WEBCORE_EXPORT void writeObjectRepresentations(const PasteboardWebContent&amp;);
+    WEBCORE_EXPORT void writeObjectRepresentations(const PasteboardImage&amp;);
+    WEBCORE_EXPORT void writeObjectRepresentations(const String&amp; pasteboardType, const String&amp; text);
+#endif
+
</ins><span class="cx"> #if PLATFORM(MAC)
</span><span class="cx">     RetainPtr&lt;NSPasteboard&gt; m_pasteboard;
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformiosAbstractPasteboardh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/ios/AbstractPasteboard.h (214864 => 214865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/ios/AbstractPasteboard.h        2017-04-04 03:30:30 UTC (rev 214864)
+++ trunk/Source/WebCore/platform/ios/AbstractPasteboard.h        2017-04-04 04:31:48 UTC (rev 214865)
</span><span class="lines">@@ -25,6 +25,17 @@
</span><span class="cx"> 
</span><span class="cx"> #import &lt;Foundation/Foundation.h&gt;
</span><span class="cx"> 
</span><ins>+#if TARGET_OS_IPHONE
+
+WEBCORE_EXPORT @interface WebPasteboardItemData : NSObject
+
++ (instancetype)itemWithRepresentingObjects:(NSArray *)representingObjects additionalData:(NSDictionary *)additionalData;
+
+@property (nonatomic, readonly, strong) NSArray *representingObjects;
+@property (nonatomic, readonly, strong) NSDictionary *additionalData;
+
+@end
+
</ins><span class="cx"> @protocol AbstractPasteboard &lt;NSObject&gt;
</span><span class="cx"> @required
</span><span class="cx"> 
</span><span class="lines">@@ -31,9 +42,14 @@
</span><span class="cx"> @property (readonly, nonatomic) NSInteger numberOfItems;
</span><span class="cx"> 
</span><span class="cx"> - (NSArray&lt;NSString *&gt; *)pasteboardTypes;
</span><del>-- (void)setItems:(NSArray *)items;
</del><span class="cx"> - (NSArray *)dataForPasteboardType:(NSString *)pasteboardType inItemSet:(NSIndexSet *)itemSet;
</span><span class="cx"> - (NSArray *)valuesForPasteboardType:(NSString *)pasteboardType inItemSet:(NSIndexSet *)itemSet;
</span><span class="cx"> - (NSInteger)changeCount;
</span><span class="cx"> 
</span><ins>+@optional
+- (void)setItemsFromObjectRepresentations:(NSArray&lt;WebPasteboardItemData *&gt; *)itemData;
+- (void)setItems:(NSArray&lt;NSDictionary *&gt; *)items;
+
</ins><span class="cx"> @end
</span><ins>+
+#endif // TARGET_OS_IPHONE
</ins></span></pre></div>
<a id="trunkSourceWebCoreplatformiosAbstractPasteboardmmfromrev214864trunkSourceWebCoreplatformiosAbstractPasteboardh"></a>
<div class="copfile"><h4>Copied: trunk/Source/WebCore/platform/ios/AbstractPasteboard.mm (from rev 214864, trunk/Source/WebCore/platform/ios/AbstractPasteboard.h) (0 => 214865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/ios/AbstractPasteboard.mm                                (rev 0)
+++ trunk/Source/WebCore/platform/ios/AbstractPasteboard.mm        2017-04-04 04:31:48 UTC (rev 214865)
</span><span class="lines">@@ -0,0 +1,69 @@
</span><ins>+/*
+ * 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 &quot;config.h&quot;
+#include &quot;AbstractPasteboard.h&quot;
+
+#import &lt;wtf/RetainPtr.h&gt;
+
+#if PLATFORM(IOS)
+
+@interface WebPasteboardItemData ()
+{
+    RetainPtr&lt;NSArray&gt; _representingObjects;
+    RetainPtr&lt;NSDictionary&gt; _additionalData;
+}
+
+@end
+
+@implementation WebPasteboardItemData
+
++ (instancetype)itemWithRepresentingObjects:(NSArray *)representingObjects additionalData:(NSDictionary *)additionalData
+{
+    return [[[self alloc] initWithRepresentingObjects:representingObjects additionalData:additionalData] autorelease];
+}
+
+- (instancetype)initWithRepresentingObjects:(NSArray *)representingObjects additionalData:(NSDictionary *)additionalData
+{
+    if (self = [super init]) {
+        _representingObjects = representingObjects;
+        _additionalData = additionalData;
+    }
+    return self;
+}
+
+- (NSArray *)representingObjects
+{
+    return _representingObjects.get();
+}
+
+- (NSDictionary *)additionalData
+{
+    return _additionalData.get();
+}
+
+@end
+
+#endif // PLATFORM(IOS)
</ins></span></pre></div>
<a id="trunkSourceWebCoreplatformiosPlatformPasteboardIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm (214864 => 214865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm        2017-04-04 03:30:30 UTC (rev 214864)
+++ trunk/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm        2017-04-04 04:31:48 UTC (rev 214865)
</span><span class="lines">@@ -34,8 +34,10 @@
</span><span class="cx"> #import &quot;SoftLinking.h&quot;
</span><span class="cx"> #import &quot;WebItemProviderPasteboard.h&quot;
</span><span class="cx"> #import &lt;MobileCoreServices/MobileCoreServices.h&gt;
</span><ins>+#import &lt;UIKit/UIImage.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> SOFT_LINK_FRAMEWORK(UIKit)
</span><ins>+SOFT_LINK_CLASS(UIKit, UIImage)
</ins><span class="cx"> SOFT_LINK_CLASS(UIKit, UIPasteboard)
</span><span class="cx"> 
</span><span class="cx"> @interface UIPasteboard
</span><span class="lines">@@ -147,9 +149,9 @@
</span><span class="cx">     return String();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void PlatformPasteboard::write(const PasteboardWebContent&amp; content)
</del><ins>+static RetainPtr&lt;NSDictionary&gt; richTextRepresentationsForPasteboardWebContent(const PasteboardWebContent&amp; content)
</ins><span class="cx"> {
</span><del>-    RetainPtr&lt;NSDictionary&gt; representations = adoptNS([[NSMutableDictionary alloc] init]);
</del><ins>+    RetainPtr&lt;NSMutableDictionary&gt; representations = adoptNS([[NSMutableDictionary alloc] init]);
</ins><span class="cx"> 
</span><span class="cx">     ASSERT(content.clientTypes.size() == content.clientData.size());
</span><span class="cx">     for (size_t i = 0, size = content.clientTypes.size(); i &lt; size; ++i)
</span><span class="lines">@@ -158,7 +160,7 @@
</span><span class="cx">     if (content.dataInWebArchiveFormat) {
</span><span class="cx">         [representations setValue:(NSData *)content.dataInWebArchiveFormat-&gt;createNSData().get() forKey:WebArchivePboardType];
</span><span class="cx">         // Flag for UIKit to know that this copy contains rich content. This will trigger a two-step paste.
</span><del>-        NSString* webIOSPastePboardType = @&quot;iOS rich content paste pasteboard type&quot;;
</del><ins>+        NSString *webIOSPastePboardType = @&quot;iOS rich content paste pasteboard type&quot;;
</ins><span class="cx">         [representations setValue:webIOSPastePboardType forKey:webIOSPastePboardType];
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -167,13 +169,70 @@
</span><span class="cx">     if (content.dataInRTFFormat)
</span><span class="cx">         [representations setValue:content.dataInRTFFormat-&gt;createNSData().get() forKey:(NSString *)kUTTypeRTF];
</span><span class="cx"> 
</span><ins>+    return representations;
+}
+
+void PlatformPasteboard::writeObjectRepresentations(const PasteboardWebContent&amp; content)
+{
+    RetainPtr&lt;NSMutableArray&gt; objectRepresentations = adoptNS([[NSMutableArray alloc] init]);
+    RetainPtr&lt;NSDictionary&gt; additionalData = richTextRepresentationsForPasteboardWebContent(content);
+
+    if (content.dataInAttributedStringFormat) {
+        NSAttributedString *attributedString = [NSKeyedUnarchiver unarchiveObjectWithData:content.dataInAttributedStringFormat-&gt;createNSData().get()];
+        if (attributedString)
+            [objectRepresentations addObject:attributedString];
+    }
+
+    if (!content.dataInStringFormat.isEmpty())
+        [objectRepresentations addObject:(NSString *)content.dataInStringFormat];
+
+    [m_pasteboard setItemsFromObjectRepresentations:@[[WebPasteboardItemData itemWithRepresentingObjects:objectRepresentations.get() additionalData:additionalData.get()]]];
+}
+
+void PlatformPasteboard::write(const PasteboardWebContent&amp; content)
+{
+    if ([m_pasteboard respondsToSelector:@selector(setItemsFromObjectRepresentations:)]) {
+        writeObjectRepresentations(content);
+        return;
+    }
+
+    RetainPtr&lt;NSMutableDictionary&gt; representations = adoptNS([[NSMutableDictionary alloc] init]);
+    [representations addEntriesFromDictionary:richTextRepresentationsForPasteboardWebContent(content).autorelease()];
</ins><span class="cx">     [representations setValue:content.dataInStringFormat forKey:(NSString *)kUTTypeText];
</span><del>-    [representations setValue:[(NSString *)content.dataInStringFormat dataUsingEncoding:NSUTF8StringEncoding] forKey:(NSString *)kUTTypeUTF8PlainText];
</del><ins>+
</ins><span class="cx">     [m_pasteboard setItems:@[representations.get()]];
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void PlatformPasteboard::writeObjectRepresentations(const PasteboardImage&amp; pasteboardImage)
+{
+    RetainPtr&lt;NSMutableArray&gt; objectRepresentations = adoptNS([[NSMutableArray alloc] init]);
+    RetainPtr&lt;NSMutableDictionary&gt; additionalData = adoptNS([[NSMutableDictionary alloc] init]);
+
+    if (auto nativeImage = pasteboardImage.image-&gt;nativeImage()) {
+        UIImage *uiImage = (UIImage *)[getUIImageClass() imageWithCGImage:nativeImage.get()];
+        if (uiImage)
+            [objectRepresentations addObject:uiImage];
+    }
+
+    if (!pasteboardImage.url.url.isEmpty()) {
+        NSURL *nsURL = pasteboardImage.url.url;
+        if (nsURL)
+            [objectRepresentations addObject:nsURL];
+    }
+
+    if (!pasteboardImage.resourceMIMEType.isNull())
+        [additionalData setObject:pasteboardImage.resourceData-&gt;createNSData().get() forKey:pasteboardImage.resourceMIMEType];
+
+    [m_pasteboard setItemsFromObjectRepresentations:@[[WebPasteboardItemData itemWithRepresentingObjects:objectRepresentations.get() additionalData:additionalData.get()]]];
+}
+
</ins><span class="cx"> void PlatformPasteboard::write(const PasteboardImage&amp; pasteboardImage)
</span><span class="cx"> {
</span><ins>+    if ([m_pasteboard respondsToSelector:@selector(setItemsFromObjectRepresentations:)]) {
+        writeObjectRepresentations(pasteboardImage);
+        return;
+    }
+
</ins><span class="cx">     RetainPtr&lt;NSMutableDictionary&gt; representations = adoptNS([[NSMutableDictionary alloc] init]);
</span><span class="cx">     if (!pasteboardImage.resourceMIMEType.isNull()) {
</span><span class="cx">         [representations setObject:pasteboardImage.resourceData-&gt;createNSData().get() forKey:pasteboardImage.resourceMIMEType];
</span><span class="lines">@@ -182,8 +241,33 @@
</span><span class="cx">     [m_pasteboard setItems:@[representations.get()]];
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void PlatformPasteboard::writeObjectRepresentations(const String&amp; pasteboardType, const String&amp; text)
+{
+    RetainPtr&lt;NSMutableArray&gt; objectRepresentations = adoptNS([[NSMutableArray alloc] init]);
+    RetainPtr&lt;NSMutableDictionary&gt; additionalData = adoptNS([[NSMutableDictionary alloc] init]);
+
+    NSString *pasteboardTypeAsNSString = pasteboardType;
+    NSString *textAsNSString = text;
+    if (textAsNSString &amp;&amp; pasteboardTypeAsNSString.length) {
+        if (UTTypeConformsTo((__bridge CFStringRef)pasteboardTypeAsNSString, kUTTypeURL))
+            [objectRepresentations addObject:[[[NSURL alloc] initWithString:textAsNSString] autorelease]];
+
+        if (UTTypeConformsTo((__bridge CFStringRef)pasteboardTypeAsNSString, kUTTypeText))
+            [objectRepresentations addObject:textAsNSString];
+        else
+            [additionalData setObject:textAsNSString forKey:pasteboardTypeAsNSString];
+    }
+
+    [m_pasteboard setItemsFromObjectRepresentations:@[[WebPasteboardItemData itemWithRepresentingObjects:objectRepresentations.get() additionalData:additionalData.get()]]];
+}
+
</ins><span class="cx"> void PlatformPasteboard::write(const String&amp; pasteboardType, const String&amp; text)
</span><span class="cx"> {
</span><ins>+    if ([m_pasteboard respondsToSelector:@selector(setItemsFromObjectRepresentations:)]) {
+        writeObjectRepresentations(pasteboardType, text);
+        return;
+    }
+
</ins><span class="cx">     RetainPtr&lt;NSDictionary&gt; representations = adoptNS([[NSMutableDictionary alloc] init]);
</span><span class="cx"> 
</span><span class="cx">     if (pasteboardType == String(kUTTypeURL)) {
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformiosWebItemProviderPasteboardmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/ios/WebItemProviderPasteboard.mm (214864 => 214865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/ios/WebItemProviderPasteboard.mm        2017-04-04 03:30:30 UTC (rev 214864)
+++ trunk/Source/WebCore/platform/ios/WebItemProviderPasteboard.mm        2017-04-04 04:31:48 UTC (rev 214865)
</span><span class="lines">@@ -80,6 +80,7 @@
</span><span class="cx"> 
</span><span class="cx"> @implementation WebItemProviderPasteboard {
</span><span class="cx">     RetainPtr&lt;NSArray&gt; _itemProviders;
</span><ins>+    RetainPtr&lt;NSArray&gt; _cachedTypeIdentifiers;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> + (instancetype)sharedInstance
</span><span class="lines">@@ -104,10 +105,22 @@
</span><span class="cx"> 
</span><span class="cx"> - (NSArray&lt;NSString *&gt; *)pasteboardTypes
</span><span class="cx"> {
</span><ins>+    if (_cachedTypeIdentifiers)
+        return _cachedTypeIdentifiers.get();
+
</ins><span class="cx">     NSMutableSet&lt;NSString *&gt; *allTypes = [NSMutableSet set];
</span><del>-    for (UIItemProvider *provider in _itemProviders.get())
-        [allTypes addObjectsFromArray:provider.registeredTypeIdentifiers];
-    return allTypes.allObjects;
</del><ins>+    NSMutableArray&lt;NSString *&gt; *allTypesInOrder = [NSMutableArray array];
+    for (UIItemProvider *provider in _itemProviders.get()) {
+        for (NSString *typeIdentifier in provider.registeredTypeIdentifiers) {
+            if ([allTypes containsObject:typeIdentifier])
+                continue;
+
+            [allTypes addObject:typeIdentifier];
+            [allTypesInOrder addObject:typeIdentifier];
+        }
+    }
+    _cachedTypeIdentifiers = allTypesInOrder;
+    return _cachedTypeIdentifiers.get();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (NSArray&lt;UIItemProvider *&gt; *)itemProviders
</span><span class="lines">@@ -123,6 +136,7 @@
</span><span class="cx"> 
</span><span class="cx">     _itemProviders = itemProviders;
</span><span class="cx">     _changeCount++;
</span><ins>+    _cachedTypeIdentifiers = nil;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (NSInteger)numberOfItems
</span><span class="lines">@@ -130,40 +144,38 @@
</span><span class="cx">     return [_itemProviders count];
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-- (void)setItems:(NSArray *)items
</del><ins>+- (void)setItemsFromObjectRepresentations:(NSArray&lt;WebPasteboardItemData *&gt; *)itemData
</ins><span class="cx"> {
</span><span class="cx">     NSMutableArray *providers = [NSMutableArray array];
</span><del>-    for (NSDictionary *item in items) {
-        if (!item.count)
</del><ins>+    for (WebPasteboardItemData *data in itemData) {
+        if (!data.representingObjects.count &amp;&amp; !data.additionalData.count)
</ins><span class="cx">             continue;
</span><ins>+
</ins><span class="cx">         RetainPtr&lt;UIItemProvider&gt; itemProvider = adoptNS([[getUIItemProviderClass() alloc] init]);
</span><del>-        RetainPtr&lt;NSMutableDictionary&gt; itemRepresentationsCopy = adoptNS([item mutableCopy]);
-        // First, let the platform write all the default object types it can recognize, such as NSString and NSURL.
-        for (NSString *typeIdentifier in [itemRepresentationsCopy allKeys]) {
-            id representingObject = [itemRepresentationsCopy objectForKey:typeIdentifier];
</del><ins>+        // First, register all platform objects, prioritizing objects at the beginning of the array.
+        for (id representingObject in data.representingObjects) {
</ins><span class="cx">             if (![representingObject conformsToProtocol:@protocol(UIItemProviderWriting)])
</span><span class="cx">                 continue;
</span><span class="cx"> 
</span><del>-            id &lt;UIItemProviderWriting&gt; objectToWrite = (id &lt;UIItemProviderWriting&gt;)representingObject;
-            if (![objectToWrite.writableTypeIdentifiersForItemProvider containsObject:typeIdentifier])
</del><ins>+            [itemProvider registerObject:(id &lt;UIItemProviderWriting&gt;)representingObject options:nil];
+        }
+
+        // Next, register other custom data representations for type identifiers.
+        NSDictionary &lt;NSString *, NSData *&gt; *additionalData = data.additionalData;
+        for (NSString *typeIdentifier in additionalData) {
+            if (![additionalData[typeIdentifier] isKindOfClass:[NSData class]])
</ins><span class="cx">                 continue;
</span><span class="cx"> 
</span><del>-            [itemRepresentationsCopy removeObjectForKey:typeIdentifier];
-            [itemProvider registerObject:objectToWrite options:nil];
-        }
-
-        // Secondly, WebKit uses some custom type representations and/or type identifiers, so we need to write these as well.
-        for (NSString *typeIdentifier in itemRepresentationsCopy.get()) {
</del><span class="cx">             [itemProvider registerDataRepresentationForTypeIdentifier:typeIdentifier options:nil loadHandler:^NSProgress *(UIItemProviderDataLoadCompletionBlock completionBlock)
</span><span class="cx">             {
</span><del>-                completionBlock([itemRepresentationsCopy objectForKey:typeIdentifier], nil);
</del><ins>+                completionBlock(additionalData[typeIdentifier], nil);
</ins><span class="cx">                 return [NSProgress discreteProgressWithTotalUnitCount:100];
</span><span class="cx">             }];
</span><span class="cx">         }
</span><span class="cx">         [providers addObject:itemProvider.get()];
</span><span class="cx">     }
</span><del>-    _changeCount++;
-    _itemProviders = providers;
</del><ins>+
+    self.itemProviders = providers;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (NSArray *)dataForPasteboardType:(NSString *)pasteboardType inItemSet:(NSIndexSet *)itemSet
</span></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (214864 => 214865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2017-04-04 03:30:30 UTC (rev 214864)
+++ trunk/Source/WebKit2/ChangeLog        2017-04-04 04:31:48 UTC (rev 214865)
</span><span class="lines">@@ -1,3 +1,19 @@
</span><ins>+2017-04-03  Wenson Hsieh  &lt;wenson_hsieh@apple.com&gt;
+
+        Data interaction should register type identifiers in order of priority
+        https://bugs.webkit.org/show_bug.cgi?id=170428
+        &lt;rdar://problem/30633296&gt;
+
+        Reviewed by Tim Horton.
+
+        Serialize PasteboardWebContent.dataInAttributedStringFormat when sending over IPC. Refer to WebCore ChangeLog
+        for more details.
+
+        * Shared/WebCoreArgumentCoders.cpp:
+        (IPC::ArgumentCoder&lt;PasteboardWebContent&gt;::encode):
+        (IPC::ArgumentCoder&lt;PasteboardWebContent&gt;::decode):
+        * UIProcess/API/Cocoa/WKWebView.mm:
+
</ins><span class="cx"> 2017-04-03  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Remove no longer needed forward declarations
</span></span></pre></div>
<a id="trunkSourceWebKit2SharedWebCoreArgumentCoderscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Shared/WebCoreArgumentCoders.cpp (214864 => 214865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Shared/WebCoreArgumentCoders.cpp        2017-04-04 03:30:30 UTC (rev 214864)
+++ trunk/Source/WebKit2/Shared/WebCoreArgumentCoders.cpp        2017-04-04 04:31:48 UTC (rev 214865)
</span><span class="lines">@@ -1404,6 +1404,7 @@
</span><span class="cx">     encodeSharedBuffer(encoder, content.dataInWebArchiveFormat.get());
</span><span class="cx">     encodeSharedBuffer(encoder, content.dataInRTFDFormat.get());
</span><span class="cx">     encodeSharedBuffer(encoder, content.dataInRTFFormat.get());
</span><ins>+    encodeSharedBuffer(encoder, content.dataInAttributedStringFormat.get());
</ins><span class="cx"> 
</span><span class="cx">     encoder &lt;&lt; content.clientTypes;
</span><span class="cx">     encoder &lt;&lt; static_cast&lt;uint64_t&gt;(content.clientData.size());
</span><span class="lines">@@ -1423,6 +1424,8 @@
</span><span class="cx">         return false;
</span><span class="cx">     if (!decodeSharedBuffer(decoder, content.dataInRTFFormat))
</span><span class="cx">         return false;
</span><ins>+    if (!decodeSharedBuffer(decoder, content.dataInAttributedStringFormat))
+        return false;
</ins><span class="cx">     if (!decoder.decode(content.clientTypes))
</span><span class="cx">         return false;
</span><span class="cx">     uint64_t clientDataSize;
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPICocoaWKWebViewmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm (214864 => 214865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm        2017-04-04 03:30:30 UTC (rev 214864)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm        2017-04-04 04:31:48 UTC (rev 214865)
</span><span class="lines">@@ -5378,6 +5378,8 @@
</span><span class="cx">     WebKit::ViewSnapshotStore::singleton().setDisableSnapshotVolatilityForTesting(true);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if PLATFORM(IOS)
+
</ins><span class="cx"> - (void)_simulateDataInteractionEntered:(id)info
</span><span class="cx"> {
</span><span class="cx"> #if ENABLE(DATA_INTERACTION)
</span><span class="lines">@@ -5436,6 +5438,8 @@
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#endif // PLATFORM(IOS)
+
</ins><span class="cx"> @end
</span><span class="cx"> 
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (214864 => 214865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2017-04-04 03:30:30 UTC (rev 214864)
+++ trunk/Tools/ChangeLog        2017-04-04 04:31:48 UTC (rev 214865)
</span><span class="lines">@@ -1,3 +1,24 @@
</span><ins>+2017-04-03  Wenson Hsieh  &lt;wenson_hsieh@apple.com&gt;
+
+        Data interaction should register type identifiers in order of priority
+        https://bugs.webkit.org/show_bug.cgi?id=170428
+        &lt;rdar://problem/30633296&gt;
+
+        Reviewed by Tim Horton.
+
+        Augments existing unit tests to check for the existence and priority of type identifiers in the UIItemProviders
+        created upon starting data interaction. Also fixes a race condition in one of the unit tests and adds a new unit
+        test for data interaction from a textarea to an input.
+
+        * TestWebKitAPI/Tests/ios/DataInteractionTests.mm:
+        (checkTypeIdentifierPrecedesOtherTypeIdentifier):
+        (TestWebKitAPI::TEST):
+        * TestWebKitAPI/ios/DataInteractionSimulator.h:
+        * TestWebKitAPI/ios/DataInteractionSimulator.mm:
+        (-[DataInteractionSimulator _advanceProgress]):
+        (-[DataInteractionSimulator sourceItemProviders]):
+        (-[DataInteractionSimulator _webView:showCustomSheetForElement:]):
+
</ins><span class="cx"> 2017-04-03  Carlos Alberto Lopez Perez  &lt;clopez@igalia.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [GTK][JHBuild] Update mesa repository url for tarballs
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsiosDataInteractionTestsmm"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm (214864 => 214865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm        2017-04-04 03:30:30 UTC (rev 214864)
+++ trunk/Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm        2017-04-04 04:31:48 UTC (rev 214865)
</span><span class="lines">@@ -62,6 +62,14 @@
</span><span class="cx">     EXPECT_TRUE([expected isEqualToArray:observed]);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static void checkTypeIdentifierPrecedesOtherTypeIdentifier(DataInteractionSimulator *simulator, NSString *firstType, NSString *secondType)
+{
+    NSArray *registeredTypes = [simulator.sourceItemProviders.firstObject registeredTypeIdentifiers];
+    EXPECT_TRUE([registeredTypes containsObject:firstType]);
+    EXPECT_TRUE([registeredTypes containsObject:secondType]);
+    EXPECT_TRUE([registeredTypes indexOfObject:firstType] &lt; [registeredTypes indexOfObject:secondType]);
+}
+
</ins><span class="cx"> namespace TestWebKitAPI {
</span><span class="cx"> 
</span><span class="cx"> TEST(DataInteractionTests, ImageToContentEditable)
</span><span class="lines">@@ -79,6 +87,7 @@
</span><span class="cx">     EXPECT_TRUE([observedEventNames containsObject:DataInteractionOverEventName]);
</span><span class="cx">     EXPECT_TRUE([observedEventNames containsObject:DataInteractionPerformOperationEventName]);
</span><span class="cx">     checkSelectionRectsWithLogging(@[ makeCGRectValue(1, 201, 215, 174) ], [dataInteractionSimulator finalSelectionRects]);
</span><ins>+    checkTypeIdentifierPrecedesOtherTypeIdentifier(dataInteractionSimulator.get(), (NSString *)kUTTypePNG, (NSString *)kUTTypeFileURL);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> TEST(DataInteractionTests, ImageToTextarea)
</span><span class="lines">@@ -99,6 +108,7 @@
</span><span class="cx"> 
</span><span class="cx">     NSArray *expectedSelectionRects = [NSArray arrayWithObjects:makeCGRectValue(6, 203, 188, 14), makeCGRectValue(6, 217, 188, 14), makeCGRectValue(6, 231, 66, 14), nil];
</span><span class="cx">     checkSelectionRectsWithLogging(expectedSelectionRects, [dataInteractionSimulator finalSelectionRects]);
</span><ins>+    checkTypeIdentifierPrecedesOtherTypeIdentifier(dataInteractionSimulator.get(), (NSString *)kUTTypePNG, (NSString *)kUTTypeFileURL);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> TEST(DataInteractionTests, ContentEditableToContentEditable)
</span><span class="lines">@@ -117,6 +127,7 @@
</span><span class="cx">     EXPECT_TRUE([observedEventNames containsObject:DataInteractionOverEventName]);
</span><span class="cx">     EXPECT_TRUE([observedEventNames containsObject:DataInteractionPerformOperationEventName]);
</span><span class="cx">     checkSelectionRectsWithLogging(@[ makeCGRectValue(1, 201, 961, 227) ], [dataInteractionSimulator finalSelectionRects]);
</span><ins>+    checkTypeIdentifierPrecedesOtherTypeIdentifier(dataInteractionSimulator.get(), (NSString *)kUTTypeRTFD, (NSString *)kUTTypeUTF8PlainText);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> TEST(DataInteractionTests, ContentEditableToTextarea)
</span><span class="lines">@@ -135,8 +146,22 @@
</span><span class="cx">     EXPECT_TRUE([observedEventNames containsObject:DataInteractionOverEventName]);
</span><span class="cx">     EXPECT_TRUE([observedEventNames containsObject:DataInteractionPerformOperationEventName]);
</span><span class="cx">     checkSelectionRectsWithLogging(@[ makeCGRectValue(6, 203, 990, 232) ], [dataInteractionSimulator finalSelectionRects]);
</span><ins>+    checkTypeIdentifierPrecedesOtherTypeIdentifier(dataInteractionSimulator.get(), (NSString *)kUTTypeRTFD, (NSString *)kUTTypeUTF8PlainText);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+TEST(DataInteractionTests, TextAreaToInput)
+{
+    RetainPtr&lt;TestWKWebView&gt; webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
+    [webView synchronouslyLoadTestPageNamed:@&quot;textarea-to-input&quot;];
+
+    RetainPtr&lt;DataInteractionSimulator&gt; dataInteractionSimulator = adoptNS([[DataInteractionSimulator alloc] initWithWebView:webView.get()]);
+    [dataInteractionSimulator runFrom:CGPointMake(100, 50) to:CGPointMake(100, 300)];
+
+    EXPECT_EQ([webView stringByEvaluatingJavaScript:@&quot;source.value&quot;].length, 0UL);
+    EXPECT_WK_STREQ(&quot;Hello world&quot;, [webView editorValue].UTF8String);
+    checkSelectionRectsWithLogging(@[ makeCGRectValue(101, 241, 990, 232) ], [dataInteractionSimulator finalSelectionRects]);
+}
+
</ins><span class="cx"> TEST(DataInteractionTests, LinkToInput)
</span><span class="cx"> {
</span><span class="cx">     RetainPtr&lt;TestWKWebView&gt; webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
</span><span class="lines">@@ -152,6 +177,7 @@
</span><span class="cx">     EXPECT_TRUE([observedEventNames containsObject:DataInteractionOverEventName]);
</span><span class="cx">     EXPECT_TRUE([observedEventNames containsObject:DataInteractionPerformOperationEventName]);
</span><span class="cx">     checkSelectionRectsWithLogging(@[ makeCGRectValue(101, 273, 2057, 232) ], [dataInteractionSimulator finalSelectionRects]);
</span><ins>+    checkTypeIdentifierPrecedesOtherTypeIdentifier(dataInteractionSimulator.get(), (NSString *)kUTTypeURL, (NSString *)kUTTypeUTF8PlainText);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> TEST(DataInteractionTests, BackgroundImageLinkToInput)
</span><span class="lines">@@ -169,6 +195,7 @@
</span><span class="cx">     EXPECT_TRUE([observedEventNames containsObject:DataInteractionOverEventName]);
</span><span class="cx">     EXPECT_TRUE([observedEventNames containsObject:DataInteractionPerformOperationEventName]);
</span><span class="cx">     checkSelectionRectsWithLogging(@[ makeCGRectValue(101, 241, 2057, 232) ], [dataInteractionSimulator finalSelectionRects]);
</span><ins>+    checkTypeIdentifierPrecedesOtherTypeIdentifier(dataInteractionSimulator.get(), (NSString *)kUTTypeURL, (NSString *)kUTTypeUTF8PlainText);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> TEST(DataInteractionTests, CanPreventStart)
</span><span class="lines">@@ -298,6 +325,7 @@
</span><span class="cx">     RetainPtr&lt;DataInteractionSimulator&gt; dataInteractionSimulator = adoptNS([[DataInteractionSimulator alloc] initWithWebView:webView.get()]);
</span><span class="cx">     [dataInteractionSimulator runFrom:CGPointMake(200, 400) to:CGPointMake(200, 150)];
</span><span class="cx">     EXPECT_WK_STREQ(&quot;PASS&quot;, [webView stringByEvaluatingJavaScript:@&quot;target.textContent&quot;].UTF8String);
</span><ins>+    checkTypeIdentifierPrecedesOtherTypeIdentifier(dataInteractionSimulator.get(), (NSString *)kUTTypePNG, (NSString *)kUTTypeFileURL);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> TEST(DataInteractionTests, LinkWithEmptyHREF)
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPIiosDataInteractionSimulatorh"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/ios/DataInteractionSimulator.h (214864 => 214865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/ios/DataInteractionSimulator.h        2017-04-04 03:30:30 UTC (rev 214864)
+++ trunk/Tools/TestWebKitAPI/ios/DataInteractionSimulator.h        2017-04-04 04:31:48 UTC (rev 214865)
</span><span class="lines">@@ -55,6 +55,7 @@
</span><span class="cx">     RetainPtr&lt;MockDataOperationSession&gt; _dataOperationSession;
</span><span class="cx">     RetainPtr&lt;NSMutableArray&gt; _observedEventNames;
</span><span class="cx">     RetainPtr&lt;UIItemProvider&gt; _externalItemProvider;
</span><ins>+    RetainPtr&lt;NSArray *&gt; _sourceItemProviders;
</ins><span class="cx">     RetainPtr&lt;NSArray *&gt; _finalSelectionRects;
</span><span class="cx">     CGPoint _startLocation;
</span><span class="cx">     CGPoint _endLocation;
</span><span class="lines">@@ -71,6 +72,7 @@
</span><span class="cx"> @property (nonatomic) BlockPtr&lt;BOOL(_WKActivatedElementInfo *)&gt; showCustomActionSheetBlock;
</span><span class="cx"> @property (nonatomic) BlockPtr&lt;NSArray *(NSArray *)&gt; convertItemProvidersBlock;
</span><span class="cx"> @property (nonatomic, strong) UIItemProvider *externalItemProvider;
</span><ins>+@property (nonatomic, readonly) NSArray *sourceItemProviders;
</ins><span class="cx"> @property (nonatomic, readonly) NSArray *observedEventNames;
</span><span class="cx"> @property (nonatomic, readonly) NSArray *finalSelectionRects;
</span><span class="cx"> @property (nonatomic, readonly) DataInteractionPhase phase;
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPIiosDataInteractionSimulatormm"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/ios/DataInteractionSimulator.mm (214864 => 214865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/ios/DataInteractionSimulator.mm        2017-04-04 03:30:30 UTC (rev 214864)
+++ trunk/Tools/TestWebKitAPI/ios/DataInteractionSimulator.mm        2017-04-04 04:31:48 UTC (rev 214865)
</span><span class="lines">@@ -202,10 +202,14 @@
</span><span class="cx"> 
</span><span class="cx">         _dataOperationSession = adoptNS([[MockDataOperationSession alloc] initWithProvider:itemProviders.firstObject location:self._currentLocation window:[_webView window]]);
</span><span class="cx">         [_dataInteractionSession setItems:items];
</span><del>-        if (!self.showCustomActionSheetBlock) {
-            [_webView _simulateWillBeginDataInteractionWithSession:_dataInteractionSession.get()];
-            _phase = DataInteractionBegan;
</del><ins>+        _sourceItemProviders = itemProviders;
+        if (self.showCustomActionSheetBlock) {
+            // Defer progress until the custom action sheet is dismissed.
+            return;
</ins><span class="cx">         }
</span><ins>+
+        [_webView _simulateWillBeginDataInteractionWithSession:_dataInteractionSession.get()];
+        _phase = DataInteractionBegan;
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">     case DataInteractionBegan:
</span><span class="lines">@@ -235,6 +239,11 @@
</span><span class="cx">     [self performSelector:@selector(_advanceProgress) withObject:nil afterDelay:progressTimeStep];
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+- (NSArray *)sourceItemProviders
+{
+    return _sourceItemProviders.get();
+}
+
</ins><span class="cx"> - (UIItemProvider *)externalItemProvider
</span><span class="cx"> {
</span><span class="cx">     return _externalItemProvider.get();
</span><span class="lines">@@ -274,6 +283,7 @@
</span><span class="cx">         DataInteractionSimulator *weakSelf = strongSelf.get();
</span><span class="cx">         [weakSelf-&gt;_webView _simulateWillBeginDataInteractionWithSession:weakSelf-&gt;_dataInteractionSession.get()];
</span><span class="cx">         weakSelf-&gt;_phase = DataInteractionBegan;
</span><ins>+        [weakSelf _scheduleAdvanceProgress];
</ins><span class="cx">     });
</span><span class="cx"> 
</span><span class="cx">     return self.showCustomActionSheetBlock(element);
</span></span></pre>
</div>
</div>

</body>
</html>