Changeset 262047 in webkit
- Timestamp:
- May 21, 2020 9:42:47 PM (4 years ago)
- Location:
- trunk
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r262046 r262047 1 2020-05-21 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 DataTransfer.files contains multiple files when pasting a single image with multiple representations 4 https://bugs.webkit.org/show_bug.cgi?id=212245 5 <rdar://problem/60240436> 6 7 Reviewed by Tim Horton. 8 9 When pasting or dropping a single image that is backed by multiple representations in NSPasteboard (or 10 UIPasteboard), we currently report more than one `File` to the page via `DataTransfer.files`. This is because 11 `Pasteboard::read(PasteboardFileReader&)`, which is responsible for converting the contents of the pasteboard 12 into a list of files, currently iterates over every pasteboard type and adds each of them as a file. This is 13 wrong when an item has multiple type representations. 14 15 To differentiate the case where a single item has multiple representations from the case where it has multiple 16 pasteboard items, we use `allPasteboardItemInfo()` instead to grab a per-item list of types from the pasteboard 17 on Cocoa platforms, and only create at most 1 file per item using the highest fidelity type that contains data. 18 19 Test: PasteImage.PasteImageWithMultipleRepresentations 20 21 * platform/cocoa/PasteboardCocoa.mm: 22 (WebCore::Pasteboard::read): 23 1 24 2020-05-21 Simon Fraser <simon.fraser@apple.com> 2 25 -
trunk/Source/WebCore/platform/cocoa/PasteboardCocoa.mm
r260366 r262047 225 225 } 226 226 227 auto cocoaTypes = readTypesWithSecurityCheck(); 228 HashSet<const char*> existingMIMEs; 229 for (auto& cocoaType : cocoaTypes) { 230 auto imageType = cocoaTypeToImageType(cocoaType); 231 const char* mimeType = imageTypeToMIMEType(imageType); 232 if (!mimeType) 233 continue; 234 if (existingMIMEs.contains(mimeType)) 235 continue; 236 auto buffer = readBufferForTypeWithSecurityCheck(cocoaType); 237 #if PLATFORM(MAC) 238 if (buffer && imageType == ImageType::TIFF) 239 buffer = convertTIFFToPNG(buffer.releaseNonNull()); 240 #endif 241 if (!buffer) 242 continue; 243 existingMIMEs.add(mimeType); 244 reader.readBuffer(imageTypeToFakeFilename(imageType), mimeType, buffer.releaseNonNull()); 227 auto allInfo = allPasteboardItemInfo(); 228 if (!allInfo) 229 return; 230 231 for (size_t itemIndex = 0; itemIndex < allInfo->size(); ++itemIndex) { 232 auto& info = allInfo->at(itemIndex); 233 for (auto cocoaType : info.platformTypesByFidelity) { 234 auto imageType = cocoaTypeToImageType(cocoaType); 235 auto* mimeType = imageTypeToMIMEType(imageType); 236 if (!mimeType) 237 continue; 238 auto buffer = readBuffer(itemIndex, cocoaType); 239 #if PLATFORM(MAC) 240 if (buffer && imageType == ImageType::TIFF) 241 buffer = convertTIFFToPNG(buffer.releaseNonNull()); 242 #endif 243 if (buffer) { 244 reader.readBuffer(imageTypeToFakeFilename(imageType), mimeType, buffer.releaseNonNull()); 245 break; 246 } 247 } 245 248 } 246 249 } -
trunk/Tools/ChangeLog
r262040 r262047 1 2020-05-21 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 DataTransfer.files contains multiple files when pasting a single image with multiple representations 4 https://bugs.webkit.org/show_bug.cgi?id=212245 5 <rdar://problem/60240436> 6 7 Reviewed by Tim Horton. 8 9 * DumpRenderTree/mac/DumpRenderTreePasteboard.mm: 10 (-[LocalPasteboard _clearContentsWithoutUpdatingChangeCount]): 11 (-[LocalPasteboard _addTypesWithoutUpdatingChangeCount:owner:]): 12 (-[LocalPasteboard writeObjects:]): 13 (-[LocalPasteboard pasteboardItems]): 14 15 Adjust DumpRenderTree's LocalPasteboard so that it lazily populates the pasteboard when constructing 16 NSPasteboardItems. To do this, we need to make a few adjustments: 17 18 1. When reifying NSPasteboardItems from LocalPasteboard, ask the owner (WebHTMLView) to provide pasteboard 19 data for each pasteboard type that was promised by WebKit, but was not eagerly written to the pasteboard. 20 21 2. Cache pasteboard items that were created, so that we don't repeatedly ask WebHTMLView to provide 22 pasteboard data. WebHTMLView doesn't currently support this, and suffers from a bug where TIFF data may 23 only be provided once. This was fixed for WebKit2, but not for WebKit1. 24 25 3. Maintain a separate hash list of original pasteboard types (which may not be UTIs) that were handed to 26 LocalPasteboard by WebKit. We use these original types in step (1). 27 28 * TestWebKitAPI/Tests/WebKitCocoa/PasteImage.mm: 29 30 Add a new API test to verify that one file is exposed via the DataTranfer when the pasteboard contains a single 31 image with two image representations, but two files are exposed when the pasteboard contains two images, each 32 with a single representation. 33 34 (writeImageDataToPasteboard): 35 36 Overload this helper method with two additional variants: one that takes a dictionary of pasteboard types to 37 data, and another that takes an array of dictionaries, each representing a single item's types and data. 38 1 39 2020-05-21 Robin Morisset <rmorisset@apple.com> 2 40 -
trunk/Tools/DumpRenderTree/mac/DumpRenderTreePasteboard.mm
r259843 r262047 46 46 RetainPtr<id> _owner; 47 47 RetainPtr<NSString> _pasteboardName; 48 RetainPtr<NS MutableArray<NSPasteboardItem *>> _writtenPasteboardItems;48 RetainPtr<NSArray<NSPasteboardItem *>> _cachedPasteboardItems; 49 49 NSInteger _changeCount; 50 50 51 51 ListHashSet<RetainPtr<CFStringRef>, WTF::RetainPtrObjectHash<CFStringRef>> _types; 52 ListHashSet<RetainPtr<CFStringRef>, WTF::RetainPtrObjectHash<CFStringRef>> _originalTypes; 52 53 HashMap<RetainPtr<CFStringRef>, RetainPtr<CFDataRef>, WTF::RetainPtrObjectHash<CFStringRef>, WTF::RetainPtrObjectHashTraits<CFStringRef>> _data; 53 54 } … … 145 146 - (void)_clearContentsWithoutUpdatingChangeCount 146 147 { 147 _ writtenPasteboardItems = nil;148 _cachedPasteboardItems = nil; 148 149 _types.clear(); 150 _originalTypes.clear(); 149 151 _data.clear(); 150 152 } … … 169 171 _owner = newOwner; 170 172 171 for (NSString *type in newTypes) 173 for (NSString *type in newTypes) { 172 174 _types.add(toUTI(type)); 175 _originalTypes.add((__bridge CFStringRef)type); 176 } 173 177 } 174 178 … … 240 244 - (BOOL)writeObjects:(NSArray<id <NSPasteboardWriting>> *)objects 241 245 { 242 _writtenPasteboardItems = adoptNS([[NSMutableArray<NSPasteboardItem *> alloc] initWithCapacity:objects.count]);246 auto items = adoptNS([[NSMutableArray<NSPasteboardItem *> alloc] initWithCapacity:objects.count]); 243 247 for (id <NSPasteboardWriting> object in objects) { 244 248 ASSERT([object isKindOfClass:NSPasteboardItem.class]); 245 [ _writtenPasteboardItems addObject:(NSPasteboardItem *)object];249 [items addObject:(NSPasteboardItem *)object]; 246 250 for (NSString *type in [object writableTypesForPasteboard:self]) { 247 251 [self addTypes:@[ type ] owner:self]; … … 255 259 } 256 260 261 _cachedPasteboardItems = items.get(); 257 262 return YES; 258 263 } … … 260 265 - (NSArray<NSPasteboardItem *> *)pasteboardItems 261 266 { 262 if (_ writtenPasteboardItems)263 return _ writtenPasteboardItems.get();267 if (_cachedPasteboardItems) 268 return _cachedPasteboardItems.get(); 264 269 265 270 auto item = adoptNS([[NSPasteboardItem alloc] init]); 271 for (auto& type : _originalTypes) { 272 if (!_data.contains(toUTI((__bridge NSString *)type.get()))) 273 [_owner pasteboard:self provideDataForType:(__bridge NSString *)type.get()]; 274 } 275 266 276 for (const auto& typeAndData : _data) { 267 277 NSData *data = (__bridge NSData *)typeAndData.value.get(); … … 269 279 [item setData:data forType:[NSPasteboard _modernPasteboardType:type]]; 270 280 } 271 return @[ item.get() ]; 281 282 _cachedPasteboardItems = @[ item.get() ]; 283 return _cachedPasteboardItems.get(); 272 284 } 273 285 -
trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/PasteImage.mm
r260366 r262047 38 38 39 39 #if PLATFORM(MAC) 40 40 41 void writeImageDataToPasteboard(NSString *type, NSData *data) 41 42 { 42 [[NSPasteboard generalPasteboard] declareTypes:@[type] owner:nil]; 43 [[NSPasteboard generalPasteboard] setData:data forType:type]; 44 } 43 [NSPasteboard.generalPasteboard declareTypes:@[type] owner:nil]; 44 [NSPasteboard.generalPasteboard setData:data forType:type]; 45 } 46 47 void writeImageDataToPasteboard(NSDictionary <NSString *, NSData *> *typesAndData) 48 { 49 [NSPasteboard.generalPasteboard declareTypes:typesAndData.allKeys owner:nil]; 50 for (NSString *type in typesAndData) 51 [NSPasteboard.generalPasteboard setData:typesAndData[type] forType:type]; 52 } 53 54 void writeImageDataToPasteboard(NSArray<NSDictionary <NSString *, NSData *> *> *items) 55 { 56 [NSPasteboard.generalPasteboard clearContents]; 57 auto pasteboardItems = adoptNS([[NSMutableArray alloc] initWithCapacity:items.count]); 58 for (NSDictionary<NSString *, NSData *> *typesAndData in items) { 59 auto pasteboardItem = adoptNS([[NSPasteboardItem alloc] init]); 60 for (NSString *type in typesAndData) 61 [pasteboardItem setData:typesAndData[type] forType:type]; 62 [pasteboardItems addObject:pasteboardItem.get()]; 63 } 64 [NSPasteboard.generalPasteboard writeObjects:pasteboardItems.get()]; 65 } 66 45 67 #else 68 46 69 void writeImageDataToPasteboard(NSString *type, NSData *data) 47 70 { 48 [[UIPasteboard generalPasteboard] setItems:@[@{ type: data }]]; 49 } 71 UIPasteboard.generalPasteboard.items = @[ @{ type: data } ]; 72 } 73 74 void writeImageDataToPasteboard(NSDictionary <NSString *, NSData *> *typesAndData) 75 { 76 UIPasteboard.generalPasteboard.items = @[ typesAndData ]; 77 } 78 79 void writeImageDataToPasteboard(NSArray<NSDictionary <NSString *, NSData *> *> *items) 80 { 81 UIPasteboard.generalPasteboard.items = items; 82 } 83 50 84 #endif 51 85 … … 138 172 } 139 173 174 TEST(PasteImage, PasteImageWithMultipleRepresentations) 175 { 176 auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 400, 400)]); 177 [webView synchronouslyLoadTestPageNamed:@"paste-image"]; 178 179 auto pngData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"sunset-in-cupertino-200px" ofType:@"png" inDirectory:@"TestWebKitAPI.resources"]]; 180 auto jpegData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"sunset-in-cupertino-600px" ofType:@"jpg" inDirectory:@"TestWebKitAPI.resources"]]; 181 writeImageDataToPasteboard(@{ 182 (__bridge NSString *)kUTTypePNG : pngData, 183 (__bridge NSString *)kUTTypeJPEG : jpegData 184 }); 185 [webView paste:nil]; 186 187 EXPECT_WK_STREQ("1", [webView stringByEvaluatingJavaScript:@"dataTransfer.files.length"]); 188 189 writeImageDataToPasteboard(@[ 190 @{ (__bridge NSString *)kUTTypePNG : pngData }, 191 @{ (__bridge NSString *)kUTTypeJPEG : jpegData } 192 ]); 193 [webView paste:nil]; 194 195 EXPECT_WK_STREQ("2", [webView stringByEvaluatingJavaScript:@"dataTransfer.files.length"]); 196 } 197 140 198 TEST(PasteImage, RevealSelectionAfterPastingImage) 141 199 {
Note: See TracChangeset
for help on using the changeset viewer.