Changeset 220865 in webkit
- Timestamp:
- Aug 17, 2017 11:34:15 AM (7 years ago)
- Location:
- trunk
- Files:
-
- 17 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r220863 r220865 1 2017-08-17 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 [iOS] Respect type fidelities when copying image elements to the pasteboard 4 https://bugs.webkit.org/show_bug.cgi?id=175638 5 <rdar://problem/26556043> 6 7 Reviewed by Ryosuke Niwa. 8 9 Ensures that we respect type fidelities when copying on iOS, by unifying pasteboard writing codepaths across 10 dragging and copying. When dragging and copying, we now generate and set UIItemProviders on the UIPasteboard. 11 12 Tests: ActionSheetTests.CopyImageElementWithHREF 13 ActionSheetTests.CopyImageElementWithoutHREF 14 15 * platform/PlatformPasteboard.h: 16 17 Remove all variants of the writeObjectRepresentations helper method. Now that both paths for writing to the 18 pasteboard are unified, it's no longer useful to separate out item-provider-based pasteboard logic. 19 20 * platform/ios/AbstractPasteboard.h: 21 * platform/ios/PlatformPasteboardIOS.mm: 22 23 Replaces -setItemsUsingRegistrationInfoLists: with -setRegistrationInfoLists:. Rather than have a helper that 24 both sets up item providers and item registration lists, split this functionality out into two setters. This is 25 because UIPasteboard does not need to know about the registration info lists used to set up the item providers 26 in the first place, but internal drag-and-drop clients require this information immediately when starting a drag 27 in order to construct custom drag previews. 28 29 (WebCore::richTextRepresentationsForPasteboardWebContent): 30 (WebCore::registerItemToPasteboard): 31 32 Add a new helper to register item providers to the pasteboard, given an WebItemProviderRegistrationInfoList. 33 34 (WebCore::PlatformPasteboard::write): 35 (WebCore::PlatformPasteboard::writeObjectRepresentations): Deleted. 36 37 Refactors PlatformPasteboard::write to always generate and set item providers, unless we're building for an SDK 38 prior to iOS 11. For images, strings and URLs, we can simply transition to using the new item-provider-based 39 codepaths used for drag and drop. For web content, we add two additional UTIs that were present when copying, 40 but not when dragging: flat RTFD and a string constant used to indicate to UIKit that the pasteboard contains 41 rich text. 42 43 * platform/ios/WebItemProviderPasteboard.h: 44 * platform/ios/WebItemProviderPasteboard.mm: 45 (-[WebItemProviderRegistrationInfoList init]): 46 (-[WebItemProviderRegistrationInfoList addData:forType:]): 47 (-[WebItemProviderRegistrationInfoList addRepresentingObject:]): 48 (-[WebItemProviderRegistrationInfoList numberOfItems]): 49 (-[WebItemProviderRegistrationInfoList itemAtIndex:]): 50 (-[WebItemProviderRegistrationInfoList itemProvider]): 51 (-[WebItemProviderRegistrationInfoList description]): 52 53 Make some small tweaks in WebItemProviderPasteboard (and related classes): 54 1. Transition to preferredPresentationSize from estimatedDisplayedSize, which is now deprecated. 55 2. Remove calls to -initWithItemProviderData:typeIdentifier:error:, which is deprecated. 56 3. Rename _items to _representations to better reflect the role of WebItemProviderRegistrationInfo. 57 4. Implement -description for WebItemProviderRegistrationInfoList for debugging purposes. 58 59 (-[WebItemProviderPasteboard valuesForPasteboardType:inItemSet:]): 60 (-[WebItemProviderPasteboard setRegistrationInfoLists:]): 61 (-[WebItemProviderPasteboard setItemsUsingRegistrationInfoLists:]): Deleted. 62 1 63 2017-08-17 Youenn Fablet <youenn@apple.com> 2 64 -
trunk/Source/WebCore/PAL/ChangeLog
r220857 r220865 1 2017-08-17 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 [iOS] Respect type fidelities when copying image elements to the pasteboard 4 https://bugs.webkit.org/show_bug.cgi?id=175638 5 <rdar://problem/26556043> 6 7 Reviewed by Ryosuke Niwa. 8 9 Replace -estimatedDisplayedSize with its non-deprecated counterpart, -preferredPresentationSize. 10 11 * pal/spi/ios/UIKitSPI.h: 12 1 13 2017-08-17 Don Olmstead <don.olmstead@sony.com> 2 14 -
trunk/Source/WebCore/PAL/pal/spi/ios/UIKitSPI.h
r220809 r220865 96 96 97 97 @interface UIItemProvider : NSItemProvider 98 @property (nonatomic) CGSize estimatedDisplayedSize;98 @property (nonatomic) CGSize preferredPresentationSize; 99 99 @end 100 100 -
trunk/Source/WebCore/platform/PlatformPasteboard.h
r219129 r220865 99 99 private: 100 100 #if PLATFORM(IOS) 101 WEBCORE_EXPORT void writeObjectRepresentations(const PasteboardWebContent&);102 WEBCORE_EXPORT void writeObjectRepresentations(const PasteboardImage&);103 WEBCORE_EXPORT void writeObjectRepresentations(const String& pasteboardType, const String& text);104 WEBCORE_EXPORT void writeObjectRepresentations(const PasteboardURL&);105 101 bool allowReadingURLAtIndex(const URL&, int index) const; 106 102 #endif -
trunk/Source/WebCore/platform/ios/AbstractPasteboard.h
r219129 r220865 30 30 NS_ASSUME_NONNULL_BEGIN 31 31 32 #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000 33 @class WebItemProviderRegistrationInfoList; 34 #endif 35 32 36 @protocol AbstractPasteboard <NSObject> 33 37 @required … … 45 49 46 50 @optional 47 - (void)setItemsUsingRegistrationInfoLists:(NSArray *)itemLists; 51 #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000 52 - (void)setRegistrationInfoLists:(NSArray <WebItemProviderRegistrationInfoList *> *)info; 53 #endif 48 54 - (void)setItems:(NSArray<NSDictionary *> *)items; 49 55 - (NSArray<NSString *> *)pasteboardTypesByFidelityForItemAtIndex:(NSUInteger)index; -
trunk/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm
r220814 r220865 174 174 } 175 175 176 static NSString *webIOSPastePboardType = @"iOS rich content paste pasteboard type"; 177 178 #if __IPHONE_OS_VERSION_MAX_ALLOWED < 110000 179 176 180 static RetainPtr<NSDictionary> richTextRepresentationsForPasteboardWebContent(const PasteboardWebContent& content) 177 181 { … … 185 189 [representations setValue:(NSData *)content.dataInWebArchiveFormat->createNSData().get() forKey:WebArchivePboardType]; 186 190 // Flag for UIKit to know that this copy contains rich content. This will trigger a two-step paste. 187 NSString *webIOSPastePboardType = @"iOS rich content paste pasteboard type";188 191 [representations setValue:webIOSPastePboardType forKey:webIOSPastePboardType]; 189 192 } … … 197 200 } 198 201 202 #else 203 204 static void registerItemToPasteboard(WebItemProviderRegistrationInfoList *representationsToRegister, id <AbstractPasteboard> pasteboard) 205 { 206 UIItemProvider *itemProvider = [representationsToRegister itemProvider]; 207 if (!itemProvider) { 208 [pasteboard setItemProviders:@[ ]]; 209 return; 210 } 211 212 [pasteboard setItemProviders:@[ itemProvider ]]; 213 if ([pasteboard respondsToSelector:@selector(setRegistrationInfoLists:)]) 214 [pasteboard setRegistrationInfoLists:@[ representationsToRegister ]]; 215 } 216 217 #endif 218 199 219 #if ENABLE(DATA_INTERACTION) 200 220 … … 231 251 #endif 232 252 233 void PlatformPasteboard::writeObjectRepresentations(const PasteboardWebContent& content)234 {235 #if ENABLE(DATA_INTERACTION)236 RetainPtr<WebItemProviderRegistrationInfoList> itemsToRegister = adoptNS([[WebItemProviderRegistrationInfoList alloc] init]);237 238 ASSERT(content.clientTypes.size() == content.clientData.size());239 for (size_t i = 0, size = content.clientTypes.size(); i < size; ++i)240 [itemsToRegister addData:content.clientData[i]->createNSData().get() forType:content.clientTypes[i]];241 242 if (content.dataInWebArchiveFormat)243 [itemsToRegister addData:content.dataInWebArchiveFormat->createNSData().get() forType:WebArchivePboardType];244 245 if (content.dataInAttributedStringFormat) {246 NSAttributedString *attributedString = [NSKeyedUnarchiver unarchiveObjectWithData:content.dataInAttributedStringFormat->createNSData().get()];247 if (attributedString)248 [itemsToRegister addRepresentingObject:attributedString];249 }250 251 if (content.dataInRTFFormat)252 [itemsToRegister addData:content.dataInRTFFormat->createNSData().get() forType:(NSString *)kUTTypeRTF];253 254 if (!content.dataInStringFormat.isEmpty())255 addRepresentationsForPlainText(itemsToRegister.get(), content.dataInStringFormat);256 257 [m_pasteboard setItemsUsingRegistrationInfoLists:@[ itemsToRegister.get() ]];258 #else259 UNUSED_PARAM(content);260 #endif261 }262 263 253 void PlatformPasteboard::write(const PasteboardWebContent& content) 264 254 { 265 if ([m_pasteboard respondsToSelector:@selector(setItemsUsingRegistrationInfoLists:)]) { 266 writeObjectRepresentations(content); 267 return; 268 } 269 255 #if __IPHONE_OS_VERSION_MAX_ALLOWED < 110000 270 256 RetainPtr<NSMutableDictionary> representations = adoptNS([[NSMutableDictionary alloc] init]); 271 257 [representations addEntriesFromDictionary:richTextRepresentationsForPasteboardWebContent(content).autorelease()]; … … 281 267 ASSERT([m_pasteboard isKindOfClass:getUIPasteboardClass()]); 282 268 [(UIPasteboard *)m_pasteboard setItems:@[representations.get()]]; 283 } 284 285 void PlatformPasteboard::writeObjectRepresentations(const PasteboardImage& pasteboardImage) 286 { 287 #if ENABLE(DATA_INTERACTION) 288 RetainPtr<WebItemProviderRegistrationInfoList> itemsToRegister = adoptNS([[WebItemProviderRegistrationInfoList alloc] init]); 289 290 auto& types = pasteboardImage.clientTypes; 291 auto& data = pasteboardImage.clientData; 292 ASSERT(types.size() == data.size()); 293 for (size_t i = 0, size = types.size(); i < size; ++i) 294 [itemsToRegister addData:data[i]->createNSData().get() forType:types[i]]; 295 296 if (pasteboardImage.resourceData && !pasteboardImage.resourceMIMEType.isEmpty()) { 297 auto utiOrMIMEType = pasteboardImage.resourceMIMEType; 298 if (!isDeclaredUTI(utiOrMIMEType)) 299 utiOrMIMEType = UTIFromMIMEType(utiOrMIMEType); 300 301 auto imageData = pasteboardImage.resourceData->createNSData(); 302 [itemsToRegister addData:imageData.get() forType:(NSString *)utiOrMIMEType]; 303 [itemsToRegister setEstimatedDisplayedSize:pasteboardImage.imageSize]; 304 [itemsToRegister setSuggestedName:pasteboardImage.suggestedName]; 305 } 306 307 if (!pasteboardImage.url.url.isEmpty()) { 308 NSURL *nsURL = pasteboardImage.url.url; 309 if (nsURL) 310 [itemsToRegister addRepresentingObject:nsURL]; 311 } 312 313 [m_pasteboard setItemsUsingRegistrationInfoLists:@[ itemsToRegister.get() ]]; 314 #else 315 UNUSED_PARAM(pasteboardImage); 269 #else 270 auto representationsToRegister = adoptNS([[WebItemProviderRegistrationInfoList alloc] init]); 271 272 [representationsToRegister addData:[webIOSPastePboardType dataUsingEncoding:NSUTF8StringEncoding] forType:webIOSPastePboardType]; 273 274 ASSERT(content.clientTypes.size() == content.clientData.size()); 275 for (size_t i = 0, size = content.clientTypes.size(); i < size; ++i) 276 [representationsToRegister addData:content.clientData[i]->createNSData().get() forType:content.clientTypes[i]]; 277 278 if (content.dataInWebArchiveFormat) 279 [representationsToRegister addData:content.dataInWebArchiveFormat->createNSData().get() forType:WebArchivePboardType]; 280 281 if (content.dataInAttributedStringFormat) { 282 NSAttributedString *attributedString = [NSKeyedUnarchiver unarchiveObjectWithData:content.dataInAttributedStringFormat->createNSData().get()]; 283 if (attributedString) 284 [representationsToRegister addRepresentingObject:attributedString]; 285 } 286 287 if (content.dataInRTFDFormat) 288 [representationsToRegister addData:content.dataInRTFDFormat->createNSData().get() forType:(NSString *)kUTTypeFlatRTFD]; 289 290 if (content.dataInRTFFormat) 291 [representationsToRegister addData:content.dataInRTFFormat->createNSData().get() forType:(NSString *)kUTTypeRTF]; 292 293 if (!content.dataInStringFormat.isEmpty()) 294 addRepresentationsForPlainText(representationsToRegister.get(), content.dataInStringFormat); 295 296 registerItemToPasteboard(representationsToRegister.get(), m_pasteboard.get()); 316 297 #endif 317 298 } … … 319 300 void PlatformPasteboard::write(const PasteboardImage& pasteboardImage) 320 301 { 321 if ([m_pasteboard respondsToSelector:@selector(setItemsUsingRegistrationInfoLists:)]) { 322 writeObjectRepresentations(pasteboardImage); 323 return; 324 } 325 302 #if __IPHONE_OS_VERSION_MAX_ALLOWED < 110000 326 303 RetainPtr<NSMutableDictionary> representations = adoptNS([[NSMutableDictionary alloc] init]); 327 304 if (!pasteboardImage.resourceMIMEType.isNull()) { … … 334 311 ASSERT([m_pasteboard isKindOfClass:getUIPasteboardClass()]); 335 312 [(UIPasteboard *)m_pasteboard setItems:@[representations.get()]]; 336 } 337 338 void PlatformPasteboard::writeObjectRepresentations(const String& pasteboardType, const String& text) 339 { 340 #if ENABLE(DATA_INTERACTION) 341 RetainPtr<WebItemProviderRegistrationInfoList> itemsToRegister = adoptNS([[WebItemProviderRegistrationInfoList alloc] init]); 342 343 NSString *pasteboardTypeAsNSString = pasteboardType; 344 if (!text.isEmpty() && pasteboardTypeAsNSString.length) { 345 if (UTTypeConformsTo((__bridge CFStringRef)pasteboardTypeAsNSString, kUTTypeURL) || UTTypeConformsTo((__bridge CFStringRef)pasteboardTypeAsNSString, kUTTypeText)) 346 addRepresentationsForPlainText(itemsToRegister.get(), text); 347 } 348 349 [m_pasteboard setItemsUsingRegistrationInfoLists:@[ itemsToRegister.get() ]]; 350 #else 351 UNUSED_PARAM(pasteboardType); 352 UNUSED_PARAM(text); 313 #else 314 auto representationsToRegister = adoptNS([[WebItemProviderRegistrationInfoList alloc] init]); 315 316 auto& types = pasteboardImage.clientTypes; 317 auto& data = pasteboardImage.clientData; 318 ASSERT(types.size() == data.size()); 319 for (size_t i = 0, size = types.size(); i < size; ++i) 320 [representationsToRegister addData:data[i]->createNSData().get() forType:types[i]]; 321 322 if (pasteboardImage.resourceData && !pasteboardImage.resourceMIMEType.isEmpty()) { 323 auto utiOrMIMEType = pasteboardImage.resourceMIMEType; 324 if (!isDeclaredUTI(utiOrMIMEType)) 325 utiOrMIMEType = UTIFromMIMEType(utiOrMIMEType); 326 327 auto imageData = pasteboardImage.resourceData->createNSData(); 328 [representationsToRegister addData:imageData.get() forType:(NSString *)utiOrMIMEType]; 329 [representationsToRegister setPreferredPresentationSize:pasteboardImage.imageSize]; 330 [representationsToRegister setSuggestedName:pasteboardImage.suggestedName]; 331 } 332 333 // FIXME: When writing a PasteboardImage, we currently always place the image data at a higer fidelity than the 334 // associated image URL. However, in the case of an image enclosed by an anchor, we might want to consider the 335 // the URL (i.e. the anchor's href attribute) to be a higher fidelity representation. 336 if (!pasteboardImage.url.url.isEmpty()) { 337 if (NSURL *nsURL = pasteboardImage.url.url) 338 [representationsToRegister addRepresentingObject:nsURL]; 339 } 340 341 registerItemToPasteboard(representationsToRegister.get(), m_pasteboard.get()); 353 342 #endif 354 343 } … … 356 345 void PlatformPasteboard::write(const String& pasteboardType, const String& text) 357 346 { 358 if ([m_pasteboard respondsToSelector:@selector(setItemsUsingRegistrationInfoLists:)]) { 359 writeObjectRepresentations(pasteboardType, text); 360 return; 361 } 362 347 #if __IPHONE_OS_VERSION_MAX_ALLOWED < 110000 363 348 RetainPtr<NSDictionary> representations = adoptNS([[NSMutableDictionary alloc] init]); 364 349 … … 379 364 ASSERT([m_pasteboard isKindOfClass:getUIPasteboardClass()]); 380 365 [(UIPasteboard *)m_pasteboard setItems:@[representations.get()]]; 381 } 382 383 void PlatformPasteboard::writeObjectRepresentations(const PasteboardURL& url) 384 { 385 #if ENABLE(DATA_INTERACTION) 386 RetainPtr<WebItemProviderRegistrationInfoList> itemsToRegister = adoptNS([[WebItemProviderRegistrationInfoList alloc] init]); 366 #else 367 auto representationsToRegister = adoptNS([[WebItemProviderRegistrationInfoList alloc] init]); 368 369 NSString *pasteboardTypeAsNSString = pasteboardType; 370 if (!text.isEmpty() && pasteboardTypeAsNSString.length) { 371 auto pasteboardTypeAsCFString = (CFStringRef)pasteboardTypeAsNSString; 372 if (UTTypeConformsTo(pasteboardTypeAsCFString, kUTTypeURL) || UTTypeConformsTo(pasteboardTypeAsCFString, kUTTypeText)) 373 addRepresentationsForPlainText(representationsToRegister.get(), text); 374 else 375 [representationsToRegister addData:[pasteboardTypeAsNSString dataUsingEncoding:NSUTF8StringEncoding] forType:pasteboardType]; 376 } 377 378 registerItemToPasteboard(representationsToRegister.get(), m_pasteboard.get()); 379 #endif 380 } 381 382 void PlatformPasteboard::write(const PasteboardURL& url) 383 { 384 #if __IPHONE_OS_VERSION_MAX_ALLOWED < 110000 385 write(kUTTypeURL, url.url.string()); 386 #else 387 auto representationsToRegister = adoptNS([[WebItemProviderRegistrationInfoList alloc] init]); 387 388 388 389 if (NSURL *nsURL = url.url) { 389 [itemsToRegister addRepresentingObject:nsURL];390 390 if (!url.title.isEmpty()) 391 391 nsURL._title = url.title; 392 } 393 394 [m_pasteboard setItemsUsingRegistrationInfoLists:@[ itemsToRegister.get() ]]; 395 #else 396 UNUSED_PARAM(url); 397 #endif 398 } 399 400 void PlatformPasteboard::write(const PasteboardURL& url) 401 { 402 if ([m_pasteboard respondsToSelector:@selector(setItemsUsingRegistrationInfoLists:)]) { 403 writeObjectRepresentations(url); 404 return; 405 } 406 407 write(kUTTypeURL, url.url.string()); 392 [representationsToRegister addRepresentingObject:nsURL]; 393 } 394 395 registerItemToPasteboard(representationsToRegister.get(), m_pasteboard.get()); 396 #endif 408 397 } 409 398 -
trunk/Source/WebCore/platform/ios/WebItemProviderPasteboard.h
r220124 r220865 61 61 - (void)addData:(NSData *)data forType:(NSString *)typeIdentifier; 62 62 63 @property (nonatomic) CGSize estimatedDisplayedSize;63 @property (nonatomic) CGSize preferredPresentationSize; 64 64 @property (nonatomic, copy) NSString *suggestedName; 65 @property (nonatomic, readonly, nullable) UIItemProvider *itemProvider; 65 66 66 67 - (NSUInteger)numberOfItems; -
trunk/Source/WebCore/platform/ios/WebItemProviderPasteboard.mm
r220809 r220865 29 29 #if ENABLE(DATA_INTERACTION) 30 30 31 #import <Foundation/NSItemProvider.h> 31 32 #import <Foundation/NSProgress.h> 32 33 #import <MobileCoreServices/MobileCoreServices.h> 34 #import <UIKit/NSItemProvider+UIKitAdditions.h> 33 35 #import <UIKit/UIColor.h> 34 36 #import <UIKit/UIImage.h> … … 46 48 SOFT_LINK_CLASS(UIKit, UIItemProvider) 47 49 48 // FIXME: Remove once +objectWithItemProviderData:typeIdentifier:error: is available in the public SDK.49 @interface NSObject (Foundation_NSItemProvider_Staging)50 + (id <NSItemProviderReading>)objectWithItemProviderData:(NSData *)data typeIdentifier:(NSString *)typeIdentifier error:(NSError **)outError;51 - (id <NSItemProviderReading>)initWithItemProviderData:(NSData *)data typeIdentifier:(NSString *)typeIdentifier error:(NSError **)outError;52 @end53 54 50 using namespace WebCore; 55 51 … … 101 97 @interface WebItemProviderRegistrationInfoList () 102 98 { 103 RetainPtr<NSMutableArray> _ items;99 RetainPtr<NSMutableArray> _representations; 104 100 } 105 101 @end … … 110 106 { 111 107 if (self = [super init]) { 112 _ items = adoptNS([[NSMutableArray alloc] init]);113 _ estimatedDisplayedSize = CGSizeZero;108 _representations = adoptNS([[NSMutableArray alloc] init]); 109 _preferredPresentationSize = CGSizeZero; 114 110 } 115 111 … … 125 121 - (void)addData:(NSData *)data forType:(NSString *)typeIdentifier 126 122 { 127 [_ items addObject:[[[WebItemProviderRegistrationInfo alloc] initWithRepresentingObject:nil typeIdentifier:typeIdentifier data:data] autorelease]];123 [_representations addObject:[[[WebItemProviderRegistrationInfo alloc] initWithRepresentingObject:nil typeIdentifier:typeIdentifier data:data] autorelease]]; 128 124 } 129 125 … … 131 127 { 132 128 ASSERT([object conformsToProtocol:@protocol(UIItemProviderWriting)]); 133 [_ items addObject:[[[WebItemProviderRegistrationInfo alloc] initWithRepresentingObject:object typeIdentifier:nil data:nil] autorelease]];129 [_representations addObject:[[[WebItemProviderRegistrationInfo alloc] initWithRepresentingObject:object typeIdentifier:nil data:nil] autorelease]]; 134 130 } 135 131 136 132 - (NSUInteger)numberOfItems 137 133 { 138 return [_ items count];134 return [_representations count]; 139 135 } 140 136 … … 144 140 return nil; 145 141 146 return [_ items objectAtIndex:index];142 return [_representations objectAtIndex:index]; 147 143 } 148 144 … … 151 147 for (NSUInteger index = 0; index < self.numberOfItems; ++index) 152 148 block([self itemAtIndex:index], index); 149 } 150 151 - (UIItemProvider *)itemProvider 152 { 153 if (!self.numberOfItems) 154 return nil; 155 156 auto itemProvider = adoptNS([allocUIItemProviderInstance() init]); 157 for (WebItemProviderRegistrationInfo *representation in _representations.get()) { 158 if (representation.representingObject) { 159 [itemProvider registerObject:representation.representingObject visibility:UIItemProviderRepresentationOptionsVisibilityAll]; 160 continue; 161 } 162 163 if (!representation.typeIdentifier.length || !representation.data.length) 164 continue; 165 166 RetainPtr<NSData> itemData = representation.data; 167 [itemProvider registerDataRepresentationForTypeIdentifier:representation.typeIdentifier visibility:UIItemProviderRepresentationOptionsVisibilityAll loadHandler:[itemData] (ItemProviderDataLoadCompletionHandler completionHandler) -> NSProgress * { 168 completionHandler(itemData.get(), nil); 169 return nil; 170 }]; 171 } 172 [itemProvider setPreferredPresentationSize:self.preferredPresentationSize]; 173 [itemProvider setSuggestedName:self.suggestedName]; 174 return itemProvider.autorelease(); 175 } 176 177 - (NSString *)description 178 { 179 __block NSMutableString *description = [NSMutableString string]; 180 [description appendFormat:@"<%@: %p", [self class], self]; 181 [self enumerateItems:^(WebItemProviderRegistrationInfo *item, NSUInteger index) { 182 if (index) 183 [description appendString:@","]; 184 185 if (item.representingObject) 186 [description appendFormat:@" (%@: %p)", [item.representingObject class], item.representingObject]; 187 else 188 [description appendFormat:@" ('%@' => %tu bytes)", item.typeIdentifier, item.data.length]; 189 }]; 190 [description appendString:@">"]; 191 return description; 153 192 } 154 193 … … 252 291 } 253 292 254 - (void)setItemsUsingRegistrationInfoLists:(NSArray<WebItemProviderRegistrationInfoList *> *)itemLists255 {256 NSMutableArray *providers = [NSMutableArray array];257 for (WebItemProviderRegistrationInfoList *itemList in itemLists) {258 if (!itemList.numberOfItems)259 continue;260 261 auto itemProvider = adoptNS([allocUIItemProviderInstance() init]);262 [itemList enumerateItems:[itemProvider] (WebItemProviderRegistrationInfo *item, NSUInteger) {263 if (item.representingObject) {264 [itemProvider registerObject:item.representingObject visibility:UIItemProviderRepresentationOptionsVisibilityAll];265 return;266 }267 268 if (!item.typeIdentifier.length || !item.data.length)269 return;270 271 RetainPtr<NSData> itemData = item.data;272 [itemProvider registerDataRepresentationForTypeIdentifier:item.typeIdentifier visibility:UIItemProviderRepresentationOptionsVisibilityAll loadHandler:[itemData] (ItemProviderDataLoadCompletionHandler completionHandler) -> NSProgress * {273 completionHandler(itemData.get(), nil);274 return nil;275 }];276 }];277 #pragma clang diagnostic push278 #pragma clang diagnostic ignored "-Wdeprecated-declarations"279 [itemProvider setEstimatedDisplayedSize:itemList.estimatedDisplayedSize];280 #pragma clang diagnostic pop281 [itemProvider setSuggestedName:itemList.suggestedName];282 [providers addObject:itemProvider.get()];283 }284 285 self.itemProviders = providers;286 _registrationInfoLists = itemLists;287 }288 289 293 - (NSData *)_preLoadedDataConformingToType:(NSString *)typeIdentifier forItemProviderAtIndex:(NSUInteger)index 290 294 { … … 365 369 return; 366 370 367 if ([readableClass respondsToSelector:@selector(objectWithItemProviderData:typeIdentifier:error:)]) { 368 if (id <NSItemProviderReading> readObject = [readableClass objectWithItemProviderData:preloadedData typeIdentifier:(NSString *)typeIdentifierToLoad error:nil]) 369 [values addObject:readObject]; 370 } else { 371 if (auto readObject = adoptNS([[readableClass alloc] initWithItemProviderData:preloadedData typeIdentifier:(NSString *)typeIdentifierToLoad error:nil])) 372 [values addObject:readObject.get()]; 373 } 371 if (id <NSItemProviderReading> readObject = [readableClass objectWithItemProviderData:preloadedData typeIdentifier:(NSString *)typeIdentifierToLoad error:nil]) 372 [values addObject:readObject]; 374 373 }]; 375 374 … … 547 546 } 548 547 548 - (void)setRegistrationInfoLists:(NSArray <WebItemProviderRegistrationInfoList *> *)infoLists 549 { 550 _registrationInfoLists = infoLists; 551 } 552 549 553 @end 550 554 -
trunk/Source/WebKit/ChangeLog
r220860 r220865 1 2017-08-17 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 [iOS] Respect type fidelities when copying image elements to the pasteboard 4 https://bugs.webkit.org/show_bug.cgi?id=175638 5 <rdar://problem/26556043> 6 7 Reviewed by Ryosuke Niwa. 8 9 Currently, we treat the case when copying an image enclosed by a link by only writing a URL to the pasteboard. 10 This patch tweaks logic in WebPage::performActionOnElement to write both an image and a link to the pasteboard 11 if the hit-tested image element is enclosed by an anchor. 12 13 * Platform/spi/ios/UIKitSPI.h: 14 * WebProcess/WebPage/ios/WebPageIOS.mm: 15 (WebKit::containingLinkElement): 16 17 Tweak this helper to be more restrictive when finding an enclosing 'link' -- only return an element if isLink() 18 is true, and it is an HTMLAnchorElement. Currently, the isLink() also matches HTMLLinkElements, but this isn't 19 the intention here. 20 21 (WebKit::WebPage::performActionOnElement): 22 1 23 2017-08-17 Jacobo Aragunde Pérez <jaragunde@igalia.com> 2 24 -
trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h
r220435 r220865 877 877 878 878 @interface UIItemProvider : NSItemProvider 879 @property (nonatomic) CGSize estimatedDisplayedSize;879 @property (nonatomic) CGSize preferredPresentationSize; 880 880 @end 881 881 -
trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm
r220503 r220865 2411 2411 } 2412 2412 2413 static Element* containingLinkElement(Element* element)2413 static HTMLAnchorElement* containingLinkElement(Element* element) 2414 2414 { 2415 2415 for (auto& currentElement : elementLineage(element)) { 2416 if (currentElement.isLink() )2417 return ¤tElement;2416 if (currentElement.isLink() && is<HTMLAnchorElement>(currentElement)) 2417 return downcast<HTMLAnchorElement>(¤tElement); 2418 2418 } 2419 2419 return nullptr; … … 2628 2628 if (static_cast<SheetAction>(action) == SheetAction::Copy) { 2629 2629 if (is<RenderImage>(*element.renderer())) { 2630 Element* linkElement = containingLinkElement(&element); 2631 if (!linkElement) 2632 m_interactionNode->document().frame()->editor().writeImageToPasteboard(*Pasteboard::createForCopyAndPaste(), element, URL(), String()); 2633 else 2634 m_interactionNode->document().frame()->editor().copyURL(linkElement->document().completeURL(stripLeadingAndTrailingHTMLSpaces(linkElement->attributeWithoutSynchronization(HTMLNames::hrefAttr))), linkElement->textContent()); 2630 URL url; 2631 String title; 2632 if (auto* linkElement = containingLinkElement(&element)) { 2633 url = linkElement->href(); 2634 title = linkElement->attributeWithoutSynchronization(HTMLNames::titleAttr); 2635 if (!title.length()) 2636 title = linkElement->textContent(); 2637 title = stripLeadingAndTrailingHTMLSpaces(title); 2638 } 2639 m_interactionNode->document().frame()->editor().writeImageToPasteboard(*Pasteboard::createForCopyAndPaste(), element, url, title); 2635 2640 } else if (element.isLink()) { 2636 2641 m_interactionNode->document().frame()->editor().copyURL(element.document().completeURL(stripLeadingAndTrailingHTMLSpaces(element.attributeWithoutSynchronization(HTMLNames::hrefAttr))), element.textContent()); -
trunk/Tools/ChangeLog
r220864 r220865 1 2017-08-17 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 [iOS] Respect type fidelities when copying image elements to the pasteboard 4 https://bugs.webkit.org/show_bug.cgi?id=175638 5 <rdar://problem/26556043> 6 7 Reviewed by Ryosuke Niwa. 8 9 Add API tests that simulate copying an image element using the action sheet, and verifying that the pasteboard 10 contains UTIs in order of fidelity (image type before URL). Also pulls out UIKit SPI (UIApplicationInitialize) 11 used in UIPasteboardTests and ActionSheetTests into a common UIKitSPI header. 12 13 * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: 14 * TestWebKitAPI/Tests/ios/ActionSheetTests.mm: 15 (-[ActionSheetObserver _webView:actionsForElement:defaultActions:]): 16 (TestWebKitAPI::TEST): 17 (TestWebKitAPI::presentActionSheetAndChooseAction): 18 (-[ActionSheetObserver waitForActionSheetAfterBlock:]): Deleted. 19 * TestWebKitAPI/Tests/ios/DataInteractionTests.mm: 20 (checkEstimatedSize): 21 (checkSuggestedNameAndEstimatedSize): 22 23 Replace -estimatedDisplayedSize with its non-deprecated counterpart, -preferredPresentationSize. 24 25 * TestWebKitAPI/Tests/ios/UIPasteboardTests.mm: 26 (TestWebKitAPI::TEST): 27 * TestWebKitAPI/ios/DataInteractionSimulator.h: 28 * TestWebKitAPI/ios/UIKitSPI.h: Added. 29 1 30 2017-08-17 Jonathan Bedard <jbedard@apple.com> 2 31 -
trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
r220722 r220865 1692 1692 F47D30ED1ED28A6C000482E1 /* gif-and-file-input.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "gif-and-file-input.html"; sourceTree = "<group>"; }; 1693 1693 F4856CA21E6498A8009D7EE7 /* attachment-element.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "attachment-element.html"; sourceTree = "<group>"; }; 1694 F493247C1F44DF8D006F4336 /* UIKitSPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UIKitSPI.h; sourceTree = "<group>"; }; 1694 1695 F4A32EC31F05F3780047C544 /* dragstart-change-selection-offscreen.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "dragstart-change-selection-offscreen.html"; sourceTree = "<group>"; }; 1695 1696 F4A32ECA1F0642F40047C544 /* contenteditable-in-iframe.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "contenteditable-in-iframe.html"; sourceTree = "<group>"; }; … … 1982 1983 F4D4F3B41E4E2BCB00BB2767 /* DataInteractionSimulator.mm */, 1983 1984 2E7765CC16C4D80A00BA2BB1 /* mainIOS.mm */, 1985 F493247C1F44DF8D006F4336 /* UIKitSPI.h */, 1984 1986 ); 1985 1987 path = ios; -
trunk/Tools/TestWebKitAPI/Tests/ios/ActionSheetTests.mm
r219541 r220865 31 31 #import "PlatformUtilities.h" 32 32 #import "TestWKWebView.h" 33 #import "UIKitSPI.h" 34 #import <MobileCoreServices/MobileCoreServices.h> 33 35 #import <WebKit/WKUIDelegatePrivate.h> 34 36 #import <WebKit/WKWebViewPrivate.h> 37 #import <WebKit/_WKActivatedElementInfo.h> 38 #import <WebKit/_WKElementAction.h> 39 #import <wtf/BlockPtr.h> 35 40 #import <wtf/RetainPtr.h> 36 41 #import <wtf/SoftLinking.h> 37 42 38 43 @interface ActionSheetObserver : NSObject<WKUIDelegatePrivate> 39 @property (nonatomic) B OOL presentedActionSheet;44 @property (nonatomic) BlockPtr<NSArray *(_WKActivatedElementInfo *, NSArray *)> presentationHandler; 40 45 @end 41 46 42 47 @implementation ActionSheetObserver 43 48 44 - ( BOOL)waitForActionSheetAfterBlock:(dispatch_block_t)block49 - (NSArray *)_webView:(WKWebView *)webView actionsForElement:(_WKActivatedElementInfo *)element defaultActions:(NSArray<_WKElementAction *> *)defaultActions 45 50 { 46 _presentedActionSheet = NO; 47 block(); 48 while ([[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantPast]]) { 49 if (_presentedActionSheet) 50 break; 51 } 52 return _presentedActionSheet; 53 } 54 55 - (NSArray *)_webView:(ActionSheetObserver *)webView actionsForElement:(_WKActivatedElementInfo *)element defaultActions:(NSArray<_WKElementAction *> *)defaultActions 56 { 57 _presentedActionSheet = YES; 58 return defaultActions; 51 return _presentationHandler ? _presentationHandler(element, defaultActions) : defaultActions; 59 52 } 60 53 … … 88 81 89 82 EXPECT_WK_STREQ("Hello world", [webView stringByEvaluatingJavaScript:@"getSelection().toString()"]); 90 [observer waitForActionSheetAfterBlock:^() { 91 [webView _simulateLongPressActionAtLocation:CGPointMake(200, 200)]; 83 84 __block bool done = false; 85 [observer setPresentationHandler:^(_WKActivatedElementInfo *element, NSArray *actions) { 86 done = true; 87 return actions; 92 88 }]; 89 [webView _simulateLongPressActionAtLocation:CGPointMake(200, 200)]; 90 TestWebKitAPI::Util::run(&done); 91 93 92 EXPECT_WK_STREQ("Hello world", [webView stringByEvaluatingJavaScript:@"getSelection().toString()"]); 94 93 } 94 95 #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000 96 97 static void presentActionSheetAndChooseAction(WKWebView *webView, ActionSheetObserver *observer, CGPoint location, _WKElementActionType actionType) 98 { 99 __block RetainPtr<_WKElementAction> copyAction; 100 __block RetainPtr<_WKActivatedElementInfo> copyElement; 101 __block bool done = false; 102 [observer setPresentationHandler:^(_WKActivatedElementInfo *element, NSArray *actions) { 103 copyElement = element; 104 for (_WKElementAction *action in actions) { 105 if (action.type == actionType) 106 copyAction = action; 107 } 108 done = true; 109 return @[ copyAction.get() ]; 110 }]; 111 [webView _simulateLongPressActionAtLocation:location]; 112 TestWebKitAPI::Util::run(&done); 113 114 EXPECT_TRUE(!!copyAction); 115 EXPECT_TRUE(!!copyElement); 116 [copyAction runActionWithElementInfo:copyElement.get()]; 117 } 118 119 TEST(ActionSheetTests, CopyImageElementWithHREF) 120 { 121 UIApplicationInitialize(); 122 [UIPasteboard generalPasteboard].items = @[ ]; 123 124 auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); 125 auto observer = adoptNS([[ActionSheetObserver alloc] init]); 126 [webView setUIDelegate:observer.get()]; 127 [webView synchronouslyLoadTestPageNamed:@"image-in-link-and-input"]; 128 129 presentActionSheetAndChooseAction(webView.get(), observer.get(), CGPointMake(100, 50), _WKElementActionTypeCopy); 130 131 __block bool done = false; 132 [webView _doAfterNextPresentationUpdate:^() { 133 NSArray <NSString *> *pasteboardTypes = [[UIPasteboard generalPasteboard] pasteboardTypes]; 134 EXPECT_EQ(2UL, pasteboardTypes.count); 135 EXPECT_WK_STREQ((NSString *)kUTTypePNG, pasteboardTypes.firstObject); 136 EXPECT_WK_STREQ((NSString *)kUTTypeURL, pasteboardTypes.lastObject); 137 NSArray <NSItemProvider *> *itemProviders = [[UIPasteboard generalPasteboard] itemProviders]; 138 EXPECT_EQ(1UL, itemProviders.count); 139 NSItemProvider *itemProvider = itemProviders.firstObject; 140 EXPECT_EQ(2UL, itemProvider.registeredTypeIdentifiers.count); 141 EXPECT_WK_STREQ((NSString *)kUTTypePNG, itemProvider.registeredTypeIdentifiers.firstObject); 142 EXPECT_WK_STREQ((NSString *)kUTTypeURL, itemProvider.registeredTypeIdentifiers.lastObject); 143 done = true; 144 }]; 145 TestWebKitAPI::Util::run(&done); 146 } 147 148 TEST(ActionSheetTests, CopyImageElementWithoutHREF) 149 { 150 UIApplicationInitialize(); 151 [UIPasteboard generalPasteboard].items = @[ ]; 152 153 auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); 154 auto observer = adoptNS([[ActionSheetObserver alloc] init]); 155 [webView setUIDelegate:observer.get()]; 156 [webView synchronouslyLoadTestPageNamed:@"image-and-contenteditable"]; 157 158 presentActionSheetAndChooseAction(webView.get(), observer.get(), CGPointMake(100, 100), _WKElementActionTypeCopy); 159 160 __block bool done = false; 161 [webView _doAfterNextPresentationUpdate:^() { 162 NSArray <NSString *> *pasteboardTypes = [[UIPasteboard generalPasteboard] pasteboardTypes]; 163 EXPECT_EQ(1UL, pasteboardTypes.count); 164 EXPECT_WK_STREQ((NSString *)kUTTypePNG, pasteboardTypes.firstObject); 165 NSArray <NSItemProvider *> *itemProviders = [[UIPasteboard generalPasteboard] itemProviders]; 166 EXPECT_EQ(1UL, itemProviders.count); 167 NSItemProvider *itemProvider = itemProviders.firstObject; 168 EXPECT_EQ(1UL, itemProvider.registeredTypeIdentifiers.count); 169 EXPECT_WK_STREQ((NSString *)kUTTypePNG, itemProvider.registeredTypeIdentifiers.firstObject); 170 done = true; 171 }]; 172 TestWebKitAPI::Util::run(&done); 173 } 174 175 #endif // __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000 95 176 96 177 } // namespace TestWebKitAPI -
trunk/Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm
r220051 r220865 33 33 #import "WKWebViewConfigurationExtras.h" 34 34 #import <MobileCoreServices/MobileCoreServices.h> 35 #import <UIKit/NSItemProvider+UIKitAdditions.h> 35 36 #import <WebKit/WKPreferencesPrivate.h> 36 37 #import <WebKit/WKProcessPoolPrivate.h> … … 132 133 { 133 134 UIItemProvider *sourceItemProvider = [simulator sourceItemProviders].firstObject; 134 EXPECT_EQ(estimatedSize.width, sourceItemProvider. estimatedDisplayedSize.width);135 EXPECT_EQ(estimatedSize.height, sourceItemProvider. estimatedDisplayedSize.height);135 EXPECT_EQ(estimatedSize.width, sourceItemProvider.preferredPresentationSize.width); 136 EXPECT_EQ(estimatedSize.height, sourceItemProvider.preferredPresentationSize.height); 136 137 } 137 138 … … 140 141 UIItemProvider *sourceItemProvider = [simulator sourceItemProviders].firstObject; 141 142 EXPECT_WK_STREQ(suggestedName.UTF8String, sourceItemProvider.suggestedName.UTF8String); 142 EXPECT_EQ(estimatedSize.width, sourceItemProvider. estimatedDisplayedSize.width);143 EXPECT_EQ(estimatedSize.height, sourceItemProvider. estimatedDisplayedSize.height);143 EXPECT_EQ(estimatedSize.width, sourceItemProvider.preferredPresentationSize.width); 144 EXPECT_EQ(estimatedSize.height, sourceItemProvider.preferredPresentationSize.height); 144 145 } 145 146 -
trunk/Tools/TestWebKitAPI/Tests/ios/UIPasteboardTests.mm
r219191 r220865 30 30 #import "PlatformUtilities.h" 31 31 #import "TestWKWebView.h" 32 #import "UIKitSPI.h" 32 33 #import <MobileCoreServices/MobileCoreServices.h> 33 34 #import <UIKit/UIPasteboard.h> … … 35 36 #import <WebKit/WKWebViewPrivate.h> 36 37 #import <wtf/SoftLinking.h> 37 38 SOFT_LINK_FRAMEWORK(UIKit)39 SOFT_LINK(UIKit, UIApplicationInitialize, void, (void), ())40 38 41 39 namespace TestWebKitAPI { … … 70 68 71 69 auto utf8Result = adoptNS([[NSString alloc] initWithData:dataForPasteboardType(kUTTypeUTF8PlainText) encoding:NSUTF8StringEncoding]); 72 auto utf16Result = adoptNS([[NSString alloc] initWithData:dataForPasteboardType(kUTTypeUTF16PlainText) encoding:NSUTF16StringEncoding]);73 70 EXPECT_WK_STREQ("Hello world", [utf8Result UTF8String]); 74 EXPECT_WK_STREQ("Hello world", [utf16Result UTF8String]);75 71 } 76 72 … … 82 78 83 79 auto utf8Result = adoptNS([[NSString alloc] initWithData:dataForPasteboardType(kUTTypeUTF8PlainText) encoding:NSUTF8StringEncoding]); 84 auto utf16Result = adoptNS([[NSString alloc] initWithData:dataForPasteboardType(kUTTypeUTF16PlainText) encoding:NSUTF16StringEncoding]);85 80 EXPECT_WK_STREQ("Hello world", [utf8Result UTF8String]); 86 EXPECT_WK_STREQ("Hello world", [utf16Result UTF8String]);87 81 } 88 82 -
trunk/Tools/TestWebKitAPI/ios/DataInteractionSimulator.h
r219537 r220865 40 40 @interface NSURL () 41 41 @property (nonatomic, copy, setter=_setTitle:) NSString *_title; 42 @end43 44 @interface UIItemProvider : NSItemProvider45 @property (nonatomic) CGSize estimatedDisplayedSize;46 42 @end 47 43 -
trunk/Tools/TestWebKitAPI/ios/UIKitSPI.h
r220864 r220865 24 24 */ 25 25 26 #i mport <Foundation/Foundation.h>26 #if PLATFORM(IOS) 27 27 28 #if TARGET_OS_IPHONE28 #if USE(APPLE_INTERNAL_SDK) 29 29 30 NS_ASSUME_NONNULL_BEGIN 30 #import <UIKit/UIApplication_Private.h> 31 31 32 @protocol AbstractPasteboard <NSObject> 33 @required 32 #else 34 33 35 @property (readonly, nonatomic) NSInteger numberOfItems; 34 WTF_EXTERN_C_BEGIN 36 35 37 #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000 38 @property (nonatomic, copy, nullable) NSArray<__kindof NSItemProvider *> *itemProviders; 36 void UIApplicationInitialize(void); 37 38 WTF_EXTERN_C_END 39 39 40 #endif 40 41 41 - (NSArray<NSString *> *)pasteboardTypes; 42 - (NSArray *)dataForPasteboardType:(NSString *)pasteboardType inItemSet:(NSIndexSet *)itemSet; 43 - (NSArray *)valuesForPasteboardType:(NSString *)pasteboardType inItemSet:(NSIndexSet *)itemSet; 44 - (NSInteger)changeCount; 45 46 @optional 47 - (void)setItemsUsingRegistrationInfoLists:(NSArray *)itemLists; 48 - (void)setItems:(NSArray<NSDictionary *> *)items; 49 - (NSArray<NSString *> *)pasteboardTypesByFidelityForItemAtIndex:(NSUInteger)index; 50 @property (readonly, nonatomic) NSInteger numberOfFiles; 51 @property (readonly, nonatomic) NSArray<NSURL *> *fileURLsForDataInteraction; 52 - (void)updateSupportedTypeIdentifiers:(NSArray<NSString *> *)types; 53 54 @end 55 56 NS_ASSUME_NONNULL_END 57 58 #endif // TARGET_OS_IPHONE 42 #endif // PLATFORM(IOS)
Note: See TracChangeset
for help on using the changeset viewer.