Skip to content

Commit 51c2745

Browse files
[iOS DnD] Allow the injected bundle to add client data when writing an image to the pasteboard
https://bugs.webkit.org/show_bug.cgi?id=173238 <rdar://problem/31943370> Reviewed by Ryosuke Niwa and Tim Horton. Source/WebCore: Add clientTypes and clientData to PasteboardImage, and call out to the injected bundle using getClientPasteboardDataForRange when writing a PasteboardImage. When generating item providers for dragging in the UI process in PlatformPasteboard, add any available client data as representations to the initialization list used to set the WebItemProviderPasteboard. Test: DataInteraction.InjectedBundleImageElementData * editing/ios/EditorIOS.mm: (WebCore::Editor::writeImageToPasteboard): * platform/Pasteboard.h: * platform/ios/PlatformPasteboardIOS.mm: (WebCore::PlatformPasteboard::writeObjectRepresentations): Source/WebKit2: Send PasteboardImage.clientTypes and PasteboardImage.clientData over IPC. * Shared/WebCoreArgumentCoders.cpp: (IPC::encodeClientTypesAndData): (IPC::decodeClientTypesAndData): Factor out common logic used to encode and decode client types and data into static helpers. (IPC::ArgumentCoder<PasteboardWebContent>::encode): (IPC::ArgumentCoder<PasteboardWebContent>::decode): (IPC::ArgumentCoder<PasteboardImage>::encode): (IPC::ArgumentCoder<PasteboardImage>::decode): Tools: Add a new unit test to verify that data inserted by the injected bundle when beginning a drag on an image element is plumbed across to the UI delegate. Also refactors injected bundle unit tests to use the new version of adjustedDataInteractionItemProvidersForItemProvider: that takes representing objects and additional data. * TestWebKitAPI/Tests/ios/DataInteractionTests.mm: (TestWebKitAPI::TEST): * TestWebKitAPI/ios/DataInteractionSimulator.h: * TestWebKitAPI/ios/DataInteractionSimulator.mm: (-[DataInteractionSimulator _webView:adjustedDataInteractionItemProvidersForItemProvider:representingObjects:additionalData:]): (-[DataInteractionSimulator _webView:adjustedDataInteractionItemProviders:]): Deleted. git-svn-id: http://svn.webkit.org/repository/webkit/trunk@218128 268f45cc-cd09-0410-ab3c-d52691b4dbfc
1 parent 5515b7a commit 51c2745

File tree

10 files changed

+137
-28
lines changed

10 files changed

+137
-28
lines changed

Source/WebCore/ChangeLog

+21
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,24 @@
1+
2017-06-12 Wenson Hsieh <[email protected]>
2+
3+
[iOS DnD] Allow the injected bundle to add client data when writing an image to the pasteboard
4+
https://bugs.webkit.org/show_bug.cgi?id=173238
5+
<rdar://problem/31943370>
6+
7+
Reviewed by Ryosuke Niwa and Tim Horton.
8+
9+
Add clientTypes and clientData to PasteboardImage, and call out to the injected bundle using
10+
getClientPasteboardDataForRange when writing a PasteboardImage. When generating item providers for dragging in
11+
the UI process in PlatformPasteboard, add any available client data as representations to the initialization
12+
list used to set the WebItemProviderPasteboard.
13+
14+
Test: DataInteraction.InjectedBundleImageElementData
15+
16+
* editing/ios/EditorIOS.mm:
17+
(WebCore::Editor::writeImageToPasteboard):
18+
* platform/Pasteboard.h:
19+
* platform/ios/PlatformPasteboardIOS.mm:
20+
(WebCore::PlatformPasteboard::writeObjectRepresentations):
21+
122
2017-06-12 Sam Weinig <[email protected]>
223

324
[WebIDL] Re-implement GetOwnPropertySlot[ByIndex] generation to more closely follow WebIDL

Source/WebCore/editing/ios/EditorIOS.mm

+5
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,11 @@ static void getImage(Element& imageElement, RefPtr<Image>& image, CachedImage*&
211211
pasteboardImage.resourceMIMEType = pasteboard.resourceMIMEType(cachedImage->response().mimeType());
212212
pasteboardImage.resourceData = cachedImage->resourceBuffer();
213213

214+
Position beforeImagePosition(&imageElement, Position::PositionIsBeforeAnchor);
215+
Position afterImagePosition(&imageElement, Position::PositionIsAfterAnchor);
216+
RefPtr<Range> imageRange = Range::create(imageElement.document(), beforeImagePosition, afterImagePosition);
217+
client()->getClientPasteboardDataForRange(imageRange.get(), pasteboardImage.clientTypes, pasteboardImage.clientData);
218+
214219
pasteboard.write(pasteboardImage);
215220
}
216221

Source/WebCore/platform/Pasteboard.h

+2
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ struct PasteboardImage {
110110
#if !(PLATFORM(GTK) || PLATFORM(WIN))
111111
RefPtr<SharedBuffer> resourceData;
112112
String resourceMIMEType;
113+
Vector<String> clientTypes;
114+
Vector<RefPtr<SharedBuffer>> clientData;
113115
#endif
114116
String suggestedName;
115117
};

Source/WebCore/platform/ios/PlatformPasteboardIOS.mm

+6
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,12 @@ static void addRepresentationsForPlainText(WebItemProviderRegistrationInfoList *
266266
#if ENABLE(DATA_INTERACTION)
267267
RetainPtr<WebItemProviderRegistrationInfoList> itemsToRegister = adoptNS([[WebItemProviderRegistrationInfoList alloc] init]);
268268

269+
auto& types = pasteboardImage.clientTypes;
270+
auto& data = pasteboardImage.clientData;
271+
ASSERT(types.size() == data.size());
272+
for (size_t i = 0, size = types.size(); i < size; ++i)
273+
[itemsToRegister addData:data[i]->createNSData().get() forType:types[i]];
274+
269275
if (auto image = pasteboardImage.image) {
270276
NSString *mimeType = pasteboardImage.resourceMIMEType;
271277
if (UTTypeIsDeclared((CFStringRef)mimeType)) {

Source/WebKit2/ChangeLog

+21
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,24 @@
1+
2017-06-12 Wenson Hsieh <[email protected]>
2+
3+
[iOS DnD] Allow the injected bundle to add client data when writing an image to the pasteboard
4+
https://bugs.webkit.org/show_bug.cgi?id=173238
5+
<rdar://problem/31943370>
6+
7+
Reviewed by Ryosuke Niwa and Tim Horton.
8+
9+
Send PasteboardImage.clientTypes and PasteboardImage.clientData over IPC.
10+
11+
* Shared/WebCoreArgumentCoders.cpp:
12+
(IPC::encodeClientTypesAndData):
13+
(IPC::decodeClientTypesAndData):
14+
15+
Factor out common logic used to encode and decode client types and data into static helpers.
16+
17+
(IPC::ArgumentCoder<PasteboardWebContent>::encode):
18+
(IPC::ArgumentCoder<PasteboardWebContent>::decode):
19+
(IPC::ArgumentCoder<PasteboardImage>::encode):
20+
(IPC::ArgumentCoder<PasteboardImage>::decode):
21+
122
2017-06-12 Wenson Hsieh <[email protected]>
223

324
[iOS DnD] Introduce hooks to override targeted drag previews when lifting and cancelling

Source/WebKit2/Shared/WebCoreArgumentCoders.cpp

+32-12
Original file line numberDiff line numberDiff line change
@@ -1426,6 +1426,33 @@ bool ArgumentCoder<PasteboardURL>::decode(Decoder& decoder, PasteboardURL& conte
14261426
return true;
14271427
}
14281428

1429+
static void encodeClientTypesAndData(Encoder& encoder, const Vector<String>& types, const Vector<RefPtr<SharedBuffer>>& data)
1430+
{
1431+
ASSERT(types.size() == data.size());
1432+
encoder << types;
1433+
encoder << static_cast<uint64_t>(data.size());
1434+
for (size_t i = 0, size = types.size(); i < size; ++i)
1435+
encodeSharedBuffer(encoder, data[i].get());
1436+
}
1437+
1438+
static bool decodeClientTypesAndData(Decoder& decoder, Vector<String>& types, Vector<RefPtr<SharedBuffer>>& data)
1439+
{
1440+
if (!decoder.decode(types))
1441+
return false;
1442+
1443+
uint64_t clientDataSize;
1444+
if (!decoder.decode(clientDataSize))
1445+
return false;
1446+
1447+
if (clientDataSize)
1448+
data.resize(clientDataSize);
1449+
1450+
for (size_t i = 0; i < clientDataSize; i++)
1451+
decodeSharedBuffer(decoder, data[i]);
1452+
1453+
return true;
1454+
}
1455+
14291456
void ArgumentCoder<PasteboardWebContent>::encode(Encoder& encoder, const PasteboardWebContent& content)
14301457
{
14311458
encoder << content.canSmartCopyOrDelete;
@@ -1436,10 +1463,7 @@ void ArgumentCoder<PasteboardWebContent>::encode(Encoder& encoder, const Pastebo
14361463
encodeSharedBuffer(encoder, content.dataInRTFFormat.get());
14371464
encodeSharedBuffer(encoder, content.dataInAttributedStringFormat.get());
14381465

1439-
encoder << content.clientTypes;
1440-
encoder << static_cast<uint64_t>(content.clientData.size());
1441-
for (size_t i = 0; i < content.clientData.size(); i++)
1442-
encodeSharedBuffer(encoder, content.clientData[i].get());
1466+
encodeClientTypesAndData(encoder, content.clientTypes, content.clientData);
14431467
}
14441468

14451469
bool ArgumentCoder<PasteboardWebContent>::decode(Decoder& decoder, PasteboardWebContent& content)
@@ -1456,15 +1480,8 @@ bool ArgumentCoder<PasteboardWebContent>::decode(Decoder& decoder, PasteboardWeb
14561480
return false;
14571481
if (!decodeSharedBuffer(decoder, content.dataInAttributedStringFormat))
14581482
return false;
1459-
if (!decoder.decode(content.clientTypes))
1483+
if (!decodeClientTypesAndData(decoder, content.clientTypes, content.clientData))
14601484
return false;
1461-
uint64_t clientDataSize;
1462-
if (!decoder.decode(clientDataSize))
1463-
return false;
1464-
if (clientDataSize)
1465-
content.clientData.resize(clientDataSize);
1466-
for (size_t i = 0; i < clientDataSize; i++)
1467-
decodeSharedBuffer(decoder, content.clientData[i]);
14681485
return true;
14691486
}
14701487

@@ -1477,6 +1494,7 @@ void ArgumentCoder<PasteboardImage>::encode(Encoder& encoder, const PasteboardIm
14771494
encoder << pasteboardImage.suggestedName;
14781495
if (pasteboardImage.resourceData)
14791496
encodeSharedBuffer(encoder, pasteboardImage.resourceData.get());
1497+
encodeClientTypesAndData(encoder, pasteboardImage.clientTypes, pasteboardImage.clientData);
14801498
}
14811499

14821500
bool ArgumentCoder<PasteboardImage>::decode(Decoder& decoder, PasteboardImage& pasteboardImage)
@@ -1493,6 +1511,8 @@ bool ArgumentCoder<PasteboardImage>::decode(Decoder& decoder, PasteboardImage& p
14931511
return false;
14941512
if (!decodeSharedBuffer(decoder, pasteboardImage.resourceData))
14951513
return false;
1514+
if (!decodeClientTypesAndData(decoder, pasteboardImage.clientTypes, pasteboardImage.clientData))
1515+
return false;
14961516
return true;
14971517
}
14981518

Tools/ChangeLog

+19
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,22 @@
1+
2017-06-12 Wenson Hsieh <[email protected]>
2+
3+
[iOS DnD] Allow the injected bundle to add client data when writing an image to the pasteboard
4+
https://bugs.webkit.org/show_bug.cgi?id=173238
5+
<rdar://problem/31943370>
6+
7+
Reviewed by Ryosuke Niwa and Tim Horton.
8+
9+
Add a new unit test to verify that data inserted by the injected bundle when beginning a drag on an image
10+
element is plumbed across to the UI delegate. Also refactors injected bundle unit tests to use the new version
11+
of adjustedDataInteractionItemProvidersForItemProvider: that takes representing objects and additional data.
12+
13+
* TestWebKitAPI/Tests/ios/DataInteractionTests.mm:
14+
(TestWebKitAPI::TEST):
15+
* TestWebKitAPI/ios/DataInteractionSimulator.h:
16+
* TestWebKitAPI/ios/DataInteractionSimulator.mm:
17+
(-[DataInteractionSimulator _webView:adjustedDataInteractionItemProvidersForItemProvider:representingObjects:additionalData:]):
18+
(-[DataInteractionSimulator _webView:adjustedDataInteractionItemProviders:]): Deleted.
19+
120
2017-06-12 Wenson Hsieh <[email protected]>
221

322
WebItemProviderPasteboard should call its completion block immediately after a synchronous load

Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm

+28-13
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545
typedef void (^FileLoadCompletionBlock)(NSURL *, BOOL, NSError *);
4646
typedef void (^DataLoadCompletionBlock)(NSData *, NSError *);
4747

48+
static NSString *InjectedBundlePasteboardDataType = @"org.webkit.data";
49+
4850
static UIImage *testIconImage()
4951
{
5052
return [UIImage imageNamed:@"TestWebKitAPI.resources/icon.png"];
@@ -759,26 +761,39 @@ static void checkSuggestedNameAndEstimatedSize(DataInteractionSimulator *simulat
759761
EXPECT_WK_STREQ("Hello world", [webView stringByEvaluatingJavaScript:@"editor.textContent"].UTF8String);
760762
}
761763

762-
TEST(DataInteractionTests, AttachmentElementItemProviders)
764+
TEST(DataInteractionTests, InjectedBundleImageElementData)
765+
{
766+
WKWebViewConfiguration *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"BundleEditingDelegatePlugIn"];
767+
[configuration _setAttachmentElementEnabled:YES];
768+
auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500) configuration:configuration]);
769+
[webView synchronouslyLoadTestPageNamed:@"image-and-contenteditable"];
770+
771+
__block RetainPtr<NSString> injectedString;
772+
auto dataInteractionSimulator = adoptNS([[DataInteractionSimulator alloc] initWithWebView:webView.get()]);
773+
[dataInteractionSimulator setConvertItemProvidersBlock:^NSArray *(UIItemProvider *itemProvider, NSArray *, NSDictionary *data)
774+
{
775+
injectedString = adoptNS([[NSString alloc] initWithData:data[InjectedBundlePasteboardDataType] encoding:NSUTF8StringEncoding]);
776+
return @[ itemProvider ];
777+
}];
778+
779+
[dataInteractionSimulator runFrom:CGPointMake(100, 50) to:CGPointMake(100, 250)];
780+
781+
EXPECT_WK_STREQ("hello", [injectedString UTF8String]);
782+
}
783+
784+
TEST(DataInteractionTests, InjectedBundleAttachmentElementData)
763785
{
764-
RetainPtr<WKWebViewConfiguration> configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"BundleEditingDelegatePlugIn"];
786+
WKWebViewConfiguration *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"BundleEditingDelegatePlugIn"];
765787
[configuration _setAttachmentElementEnabled:YES];
766-
auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500) configuration:configuration.get()]);
788+
auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500) configuration:configuration]);
767789
[webView synchronouslyLoadTestPageNamed:@"attachment-element"];
768790

769-
NSString *injectedTypeIdentifier = @"org.webkit.data";
770791
__block RetainPtr<NSString> injectedString;
771792
auto dataInteractionSimulator = adoptNS([[DataInteractionSimulator alloc] initWithWebView:webView.get()]);
772-
[dataInteractionSimulator setConvertItemProvidersBlock:^NSArray *(NSArray *originalItemProviders)
793+
[dataInteractionSimulator setConvertItemProvidersBlock:^NSArray *(UIItemProvider *itemProvider, NSArray *, NSDictionary *data)
773794
{
774-
for (UIItemProvider *provider in originalItemProviders) {
775-
NSData *injectedData = [provider copyDataRepresentationForTypeIdentifier:injectedTypeIdentifier error:nil];
776-
if (!injectedData.length)
777-
continue;
778-
injectedString = adoptNS([[NSString alloc] initWithData:injectedData encoding:NSUTF8StringEncoding]);
779-
break;
780-
}
781-
return originalItemProviders;
795+
injectedString = adoptNS([[NSString alloc] initWithData:data[InjectedBundlePasteboardDataType] encoding:NSUTF8StringEncoding]);
796+
return @[ itemProvider ];
782797
}];
783798

784799
[dataInteractionSimulator runFrom:CGPointMake(50, 50) to:CGPointMake(50, 400)];

Tools/TestWebKitAPI/ios/DataInteractionSimulator.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ typedef NS_ENUM(NSInteger, DataInteractionPhase) {
7575
@property (nonatomic) BOOL allowsFocusToStartInputSession;
7676
@property (nonatomic) BOOL shouldEnsureUIApplication;
7777
@property (nonatomic) BlockPtr<BOOL(_WKActivatedElementInfo *)> showCustomActionSheetBlock;
78-
@property (nonatomic) BlockPtr<NSArray *(NSArray *)> convertItemProvidersBlock;
78+
@property (nonatomic) BlockPtr<NSArray *(UIItemProvider *, NSArray *, NSDictionary *)> convertItemProvidersBlock;
7979
@property (nonatomic, strong) NSArray *externalItemProviders;
8080
@property (nonatomic) BlockPtr<NSUInteger(NSUInteger, id)> overrideDataInteractionOperationBlock;
8181
@property (nonatomic) BlockPtr<void(BOOL, NSArray *)> dataInteractionOperationCompletionBlock;

Tools/TestWebKitAPI/ios/DataInteractionSimulator.mm

+2-2
Original file line numberDiff line numberDiff line change
@@ -305,9 +305,9 @@ - (NSUInteger)_webView:(WKWebView *)webView willUpdateDataInteractionOperationTo
305305
return self.overrideDataInteractionOperationBlock ? self.overrideDataInteractionOperationBlock(operation, session) : operation;
306306
}
307307

308-
- (NSArray<UIItemProvider *>*)_webView:(WKWebView *)webView adjustedDataInteractionItemProviders:(NSArray<UIItemProvider *>*)originalItemProviders
308+
- (NSArray *)_webView:(WKWebView *)webView adjustedDataInteractionItemProvidersForItemProvider:(UIItemProvider *)itemProvider representingObjects:(NSArray *)representingObjects additionalData:(NSDictionary *)additionalData
309309
{
310-
return self.convertItemProvidersBlock ? self.convertItemProvidersBlock(originalItemProviders) : originalItemProviders;
310+
return self.convertItemProvidersBlock ? self.convertItemProvidersBlock(itemProvider, representingObjects, additionalData) : @[ itemProvider ];
311311
}
312312

313313
- (BOOL)_webView:(WKWebView *)webView showCustomSheetForElement:(_WKActivatedElementInfo *)element

0 commit comments

Comments
 (0)