Changeset 226085 in webkit
- Timestamp:
- Dec 18, 2017 4:19:17 PM (6 years ago)
- Location:
- trunk
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r226084 r226085 1 2017-12-18 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 [Attachment Support] Insert images as inline attachments when pasting and dropping 4 https://bugs.webkit.org/show_bug.cgi?id=180853 5 <rdar://problem/35756268> 6 7 Reviewed by Tim Horton. 8 9 Adds support for transforming dropped and pasted web content fragments prior to insertion, such that inline 10 elements (so far, only images) are replaced with attachment elements that have an inline representation. See 11 below comments for more detail. 12 13 Tests: WKAttachmentTests.InsertPastedImageAsAttachment 14 WKAttachmentTests.InsertPastedAttributedStringContainingImage 15 WKAttachmentTestsMac.InsertPastedFileURLsAsAttachments 16 WKAttachmentTestsIOS.InsertDroppedImageAsAttachment 17 WKAttachmentTestsIOS.InsertDroppedAttributedStringContainingAttachment 18 19 * editing/WebContentReader.h: 20 * editing/cocoa/EditorCocoa.mm: 21 (WebCore::Editor::replaceSelectionWithAttributedString): 22 23 Add a new helper to replace elements in a DOM fragment with inline attachment elements instead, using the given 24 Blobs. So far, we only replace image elements with these attachments, by mapping the source of each image to a 25 Blob, and constructing a replacement attachment backed by a File constructed from the image's corresponding 26 Blob. However, this mechanism can be generalized in the future to handle transformations from arbitrary elements 27 to attachment elements capable of representing the same elements using inline display mode. 28 29 This function is a noop if the attachment elements are disabled via runtime-enabled features. 30 31 * editing/cocoa/WebContentReaderCocoa.mm: 32 (WebCore::replaceRichContentWithAttachmentsIfNecessary): 33 (WebCore::createFragmentAndAddResources): 34 (WebCore::sanitizeMarkupWithArchive): 35 36 Add out-params to both of these helper functions that capture the map of blob URLs to Blobs being used to 37 replace subresource URLs in the pasted/dropped DOM fragment. 38 39 (WebCore::WebContentReader::readWebArchive): 40 (WebCore::WebContentMarkupReader::readWebArchive): 41 (WebCore::createFragmentFromAttributedString): 42 (WebCore::WebContentReader::readRTFD): 43 (WebCore::WebContentMarkupReader::readRTFD): 44 (WebCore::WebContentReader::readRTF): 45 (WebCore::WebContentMarkupReader::readRTF): 46 (WebCore::WebContentReader::readImage): 47 48 In these places where we swap out subresource URLs for blob URLs, collect a map of blob URL => Blob, and use it 49 to replace images in the DOM with attachments (if needed, and possible). 50 51 * editing/mac/WebContentReaderMac.mm: 52 (WebCore::WebContentReader::readFilenames): 53 54 Augment existing logic to generate attachment elements when pasting or dropping file URLs, so that the generated 55 attachment elements also have titles, subtitles, and content type information. 56 57 * html/HTMLAttachmentElement.cpp: 58 (WebCore::HTMLAttachmentElement::setFile): 59 60 Add an optional second param, UpdateDisplayAttributes. If UpdateDisplayAttributes::Yes is passed in, then we set 61 the elements's attributes that are displayed in the attachment representation (title, subtitle, and type) using 62 the given File. 63 64 (WebCore::HTMLAttachmentElement::updateFileWithData): 65 (WebCore::HTMLAttachmentElement::populateShadowRootIfNecessary): 66 67 Make a small tweak to correctly handle the case where an attachment with a content type that is a UTI is being 68 displayed inline. Content type can either be a UTI or a MIME type, but the code to construct the shadow tree of 69 an attachment element only handles MIME types. 70 71 * html/HTMLAttachmentElement.h: 72 1 73 2017-12-18 Youenn Fablet <youenn@apple.com> 2 74 -
trunk/Source/WebCore/editing/WebContentReader.h
r223678 r226085 33 33 34 34 class ArchiveResource; 35 class Blob; 35 36 36 37 class FrameWebContentReader : public PasteboardWebContentReader { … … 106 107 }; 107 108 108 RefPtr<DocumentFragment> createFragmentAndAddResources(Frame&, NSAttributedString*); 109 void replaceRichContentWithAttachmentsIfNecessary(DocumentFragment&, HashMap<AtomicString, RefPtr<Blob>>&& urlToBlobMap); 110 RefPtr<DocumentFragment> createFragmentAndAddResources(Frame&, NSAttributedString*, HashMap<AtomicString, RefPtr<Blob>>& urlToBlobMap); 109 111 #endif 110 112 -
trunk/Source/WebCore/editing/cocoa/EditorCocoa.mm
r225264 r226085 223 223 224 224 if (m_frame.selection().selection().isContentRichlyEditable()) { 225 RefPtr<DocumentFragment> fragment = createFragmentAndAddResources(m_frame, attributedString); 226 if (fragment && shouldInsertFragment(*fragment, selectedRange().get(), EditorInsertAction::Pasted)) 227 pasteAsFragment(fragment.releaseNonNull(), false, false, mailBlockquoteHandling); 225 HashMap<AtomicString, RefPtr<Blob>> urlToBlobMap; 226 if (auto fragment = createFragmentAndAddResources(m_frame, attributedString, urlToBlobMap)) { 227 replaceRichContentWithAttachmentsIfNecessary(*fragment, WTFMove(urlToBlobMap)); 228 if (shouldInsertFragment(*fragment, selectedRange().get(), EditorInsertAction::Pasted)) 229 pasteAsFragment(fragment.releaseNonNull(), false, false, mailBlockquoteHandling); 230 } 228 231 } else { 229 232 String text = attributedString.string; -
trunk/Source/WebCore/editing/cocoa/WebContentReaderCocoa.mm
r225675 r226085 35 35 #import "DocumentFragment.h" 36 36 #import "DocumentLoader.h" 37 #import "File.h" 37 38 #import "Frame.h" 38 39 #import "FrameLoader.h" 39 40 #import "FrameLoaderClient.h" 41 #import "HTMLAttachmentElement.h" 40 42 #import "HTMLBodyElement.h" 41 43 #import "HTMLIFrameElement.h" … … 45 47 #import "Page.h" 46 48 #import "PublicURLManager.h" 49 #import "RuntimeEnabledFeatures.h" 47 50 #import "Settings.h" 48 51 #import "SocketProvider.h" … … 53 56 #import <pal/spi/cocoa/NSAttributedStringSPI.h> 54 57 #import <wtf/SoftLinking.h> 58 #import <wtf/UUID.h> 55 59 56 60 #if (PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000) || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300) … … 69 73 70 74 namespace WebCore { 75 76 #if ENABLE(ATTACHMENT_ELEMENT) 77 78 void replaceRichContentWithAttachmentsIfNecessary(DocumentFragment& fragment, HashMap<AtomicString, RefPtr<Blob>>&& urlToBlobMap) 79 { 80 if (!RuntimeEnabledFeatures::sharedFeatures().attachmentElementEnabled() || urlToBlobMap.isEmpty()) 81 return; 82 83 Vector<Ref<Element>> elementsToRemove; 84 Vector<std::pair<Ref<File>, Ref<Element>>> filesForElementsToReplace; 85 for (auto& image : descendantsOfType<HTMLImageElement>(fragment)) { 86 auto url = image.attributeWithoutSynchronization(HTMLNames::srcAttr); 87 88 if (url.isEmpty()) { 89 elementsToRemove.append(image); 90 continue; 91 } 92 93 auto blob = urlToBlobMap.get(url); 94 if (!blob) { 95 elementsToRemove.append(image); 96 continue; 97 } 98 99 auto title = image.attributeWithoutSynchronization(HTMLNames::titleAttr); 100 if (title.isEmpty()) 101 title = AtomicString("media"); 102 103 filesForElementsToReplace.append({ File::create(*blob, title), image }); 104 } 105 106 for (auto& fileAndElement : filesForElementsToReplace) { 107 auto& file = fileAndElement.first; 108 auto& elementToReplace = fileAndElement.second; 109 auto parent = makeRefPtr(elementToReplace->parentNode()); 110 if (!parent) 111 continue; 112 113 auto attachment = HTMLAttachmentElement::create(HTMLNames::attachmentTag, fragment.document()); 114 attachment->setUniqueIdentifier(createCanonicalUUIDString()); 115 attachment->setFile(WTFMove(file), HTMLAttachmentElement::UpdateDisplayAttributes::Yes); 116 attachment->updateDisplayMode(AttachmentDisplayMode::InPlace); 117 parent->replaceChild(attachment, elementToReplace); 118 } 119 120 for (auto& elementToRemove : elementsToRemove) 121 elementToRemove->remove(); 122 } 123 124 #else 125 126 void replaceRichContentWithAttachmentsIfNecessary(DocumentFragment&, HashMap<AtomicString, RefPtr<Blob>>&&) 127 { 128 } 129 130 #endif 71 131 72 132 #if (PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000) || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300) … … 160 220 }; 161 221 162 RefPtr<DocumentFragment> createFragmentAndAddResources(Frame& frame, NSAttributedString *string )222 RefPtr<DocumentFragment> createFragmentAndAddResources(Frame& frame, NSAttributedString *string, HashMap<AtomicString, RefPtr<Blob>>& urlToBlobMap) 163 223 { 164 224 if (!frame.page() || !frame.document()) … … 179 239 String blobURL = DOMURL::createObjectURL(document, blob); 180 240 blobURLMap.set(subresource->url().string(), blobURL); 241 urlToBlobMap.set(blobURL, WTFMove(blob)); 181 242 } 182 243 replaceSubresourceURLs(*fragmentAndResources.fragment, WTFMove(blobURLMap)); … … 208 269 } 209 270 210 static String sanitizeMarkupWithArchive(Document& destinationDocument, MarkupAndArchive& markupAndArchive, const std::function<bool(const String)>& canShowMIMETypeAsHTML )271 static String sanitizeMarkupWithArchive(Document& destinationDocument, MarkupAndArchive& markupAndArchive, const std::function<bool(const String)>& canShowMIMETypeAsHTML, HashMap<AtomicString, RefPtr<Blob>>& urlToBlobMap) 211 272 { 212 273 auto page = createPageForSanitizingWebContent(); … … 220 281 String blobURL = DOMURL::createObjectURL(destinationDocument, blob); 221 282 blobURLMap.set(subresource->url().string(), blobURL); 283 urlToBlobMap.set(blobURL, WTFMove(blob)); 222 284 } 223 285 … … 235 297 MarkupAndArchive subframeContent = { String::fromUTF8(subframeMainResource->data().data(), subframeMainResource->data().size()), 236 298 subframeMainResource.releaseNonNull(), subframeArchive.copyRef() }; 237 auto subframeMarkup = sanitizeMarkupWithArchive(destinationDocument, subframeContent, canShowMIMETypeAsHTML );299 auto subframeMarkup = sanitizeMarkupWithArchive(destinationDocument, subframeContent, canShowMIMETypeAsHTML, urlToBlobMap); 238 300 239 301 CString utf8 = subframeMarkup.utf8(); … … 245 307 String subframeBlobURL = DOMURL::createObjectURL(destinationDocument, blob); 246 308 blobURLMap.set(subframeURL.string(), subframeBlobURL); 309 urlToBlobMap.set(subframeBlobURL, WTFMove(blob)); 247 310 } 248 311 … … 275 338 } 276 339 340 HashMap<AtomicString, RefPtr<Blob>> urlToBlobMap; 277 341 String sanitizedMarkup = sanitizeMarkupWithArchive(*frame.document(), *result, [&] (const String& type) { 278 342 return frame.loader().client().canShowMIMETypeAsHTML(type); 279 } );343 }, urlToBlobMap); 280 344 fragment = createFragmentFromMarkup(*frame.document(), sanitizedMarkup, blankURL(), DisallowScriptingAndPluginContent); 281 345 346 if (!fragment) 347 return false; 348 349 replaceRichContentWithAttachmentsIfNecessary(*fragment, WTFMove(urlToBlobMap)); 282 350 return true; 283 351 } … … 299 367 } 300 368 369 HashMap<AtomicString, RefPtr<Blob>> urlToBlobMap; 301 370 markup = sanitizeMarkupWithArchive(*frame.document(), *result, [&] (const String& type) { 302 371 return frame.loader().client().canShowMIMETypeAsHTML(type); 303 } );372 }, urlToBlobMap); 304 373 305 374 return true; … … 349 418 } 350 419 420 static RefPtr<DocumentFragment> createFragmentFromAttributedString(Frame& frame, NSAttributedString *string) 421 { 422 HashMap<AtomicString, RefPtr<Blob>> urlToBlobMap; 423 auto fragment = createFragmentAndAddResources(frame, string, urlToBlobMap); 424 if (!fragment) 425 return nullptr; 426 427 replaceRichContentWithAttachmentsIfNecessary(*fragment, WTFMove(urlToBlobMap)); 428 return fragment; 429 } 430 351 431 bool WebContentReader::readRTFD(SharedBuffer& buffer) 352 432 { … … 354 434 return false; 355 435 356 auto fragment = createFragmentAndAddResources(frame, adoptNS([[NSAttributedString alloc] initWithRTFD:buffer.createNSData().get() documentAttributes:nullptr]).get()); 436 auto string = adoptNS([[NSAttributedString alloc] initWithRTFD:buffer.createNSData().get() documentAttributes:nullptr]); 437 auto fragment = createFragmentFromAttributedString(frame, string.get()); 357 438 if (!fragment) 358 439 return false; … … 366 447 if (!frame.document()) 367 448 return false; 368 auto fragment = createFragmentAndAddResources(frame, adoptNS([[NSAttributedString alloc] initWithRTFD:buffer.createNSData().get() documentAttributes:nullptr]).get()); 449 auto string = adoptNS([[NSAttributedString alloc] initWithRTFD:buffer.createNSData().get() documentAttributes:nullptr]); 450 auto fragment = createFragmentFromAttributedString(frame, string.get()); 451 if (!fragment) 452 return false; 453 369 454 markup = createMarkup(*fragment); 370 455 return true; … … 376 461 return false; 377 462 378 auto fragment = createFragmentAndAddResources(frame, adoptNS([[NSAttributedString alloc] initWithRTF:buffer.createNSData().get() documentAttributes:nullptr]).get()); 463 auto string = adoptNS([[NSAttributedString alloc] initWithRTF:buffer.createNSData().get() documentAttributes:nullptr]); 464 auto fragment = createFragmentFromAttributedString(frame, string.get()); 379 465 if (!fragment) 380 466 return false; … … 388 474 if (!frame.document()) 389 475 return false; 390 auto fragment = createFragmentAndAddResources(frame, adoptNS([[NSAttributedString alloc] initWithRTF:buffer.createNSData().get() documentAttributes:nullptr]).get()); 476 auto string = adoptNS([[NSAttributedString alloc] initWithRTF:buffer.createNSData().get() documentAttributes:nullptr]); 477 auto fragment = createFragmentFromAttributedString(frame, string.get()); 391 478 if (!fragment) 392 479 return false; … … 413 500 String blobURL = DOMURL::createObjectURL(document, blob); 414 501 addFragment(createFragmentForImageAndURL(document, blobURL)); 415 return true; 416 } 417 418 } 502 503 if (!fragment) 504 return false; 505 506 replaceRichContentWithAttachmentsIfNecessary(*fragment, {{ blobURL, WTFMove(blob) }}); 507 return true; 508 } 509 510 } -
trunk/Source/WebCore/editing/mac/WebContentReaderMac.mm
r224755 r226085 48 48 #import "WebCoreNSURLExtras.h" 49 49 #import "markup.h" 50 #import <wtf/UUID.h> 50 51 51 52 namespace WebCore { … … 66 67 if (RuntimeEnabledFeatures::sharedFeatures().attachmentElementEnabled()) { 67 68 auto attachment = HTMLAttachmentElement::create(HTMLNames::attachmentTag, document); 68 attachment->setFile(File::create([[NSURL fileURLWithPath:text] path])); 69 attachment->setUniqueIdentifier(createCanonicalUUIDString()); 70 attachment->setFile(File::create([NSURL fileURLWithPath:text].path), HTMLAttachmentElement::UpdateDisplayAttributes::Yes); 69 71 fragment->appendChild(attachment); 70 72 continue; -
trunk/Source/WebCore/html/HTMLAttachmentElement.cpp
r225422 r226085 46 46 #include <pal/FileSizeFormatter.h> 47 47 48 #if PLATFORM(COCOA) 49 #include "UTIUtilities.h" 50 #endif 51 48 52 namespace WebCore { 49 53 … … 113 117 } 114 118 115 void HTMLAttachmentElement::setFile(RefPtr<File>&& file )119 void HTMLAttachmentElement::setFile(RefPtr<File>&& file, UpdateDisplayAttributes updateAttributes) 116 120 { 117 121 m_file = WTFMove(file); 118 122 119 123 setAttributeWithoutSynchronization(HTMLNames::webkitattachmentbloburlAttr, m_file ? m_file->url() : emptyString()); 124 125 if (updateAttributes == UpdateDisplayAttributes::Yes) { 126 if (m_file) { 127 setAttributeWithoutSynchronization(HTMLNames::titleAttr, m_file->name()); 128 setAttributeWithoutSynchronization(HTMLNames::subtitleAttr, fileSizeDescription(m_file->size())); 129 setAttributeWithoutSynchronization(HTMLNames::typeAttr, m_file->type()); 130 } else { 131 removeAttribute(HTMLNames::titleAttr); 132 removeAttribute(HTMLNames::subtitleAttr); 133 removeAttribute(HTMLNames::typeAttr); 134 } 135 } 120 136 121 137 if (auto* renderAttachment = attachmentRenderer()) … … 224 240 auto contentType = newContentType ? *newContentType : File::contentTypeForFile(filename); 225 241 auto file = File::create(Blob::create(WTFMove(data), contentType), filename); 226 227 setAttributeWithoutSynchronization(titleAttr, filename); 228 setAttributeWithoutSynchronization(subtitleAttr, fileSizeDescription(file->size())); 229 setAttributeWithoutSynchronization(typeAttr, contentType); 230 setFile(WTFMove(file)); 242 setFile(WTFMove(file), UpdateDisplayAttributes::Yes); 231 243 } 232 244 … … 267 279 void HTMLAttachmentElement::populateShadowRootIfNecessary() 268 280 { 281 if (!m_file) 282 return; 283 269 284 auto mimeType = attachmentType(); 270 if (!m_file || mimeType.isEmpty()) 285 286 #if PLATFORM(COCOA) 287 if (isDeclaredUTI(mimeType)) 288 mimeType = MIMETypeFromUTI(mimeType); 289 #endif 290 291 if (mimeType.isEmpty()) 271 292 return; 272 293 -
trunk/Source/WebCore/html/HTMLAttachmentElement.h
r225422 r226085 46 46 WEBCORE_EXPORT URL blobURL() const; 47 47 WEBCORE_EXPORT File* file() const; 48 void setFile(RefPtr<File>&&); 48 49 enum class UpdateDisplayAttributes { No, Yes }; 50 void setFile(RefPtr<File>&&, UpdateDisplayAttributes = UpdateDisplayAttributes::No); 49 51 50 52 WEBCORE_EXPORT String uniqueIdentifier() const; -
trunk/Tools/ChangeLog
r226062 r226085 1 2017-12-18 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 [Attachment Support] Insert images as inline attachments when pasting and dropping 4 https://bugs.webkit.org/show_bug.cgi?id=180853 5 <rdar://problem/35756268> 6 7 Reviewed by Tim Horton. 8 9 Adds new WKAttachment API tests and test support. See comments below for more detail. 10 11 * TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm: 12 13 Tweak the editing test page markup, such that document.body.innerHTML doesn't additionally contain the contents 14 of the script tag. 15 16 (webViewForTestingAttachments): 17 (testImageFileURL): 18 (testImageData): 19 (testPDFFileURL): 20 (testPDFData): 21 (platformCopyRichTextWithAttachment): 22 (platformCopyPNG): 23 (platformImageWithData): 24 25 Add some platform helper functions, which some of the platform-agnostic tests below use to resolve differences 26 between iOS and macOS when writing to the pasteboard and creating an image from data. 27 28 (TestWebKitAPI::TEST): 29 30 Add new API tests to exercise drag and drop/copy and paste of rich content (namely, images and files) on iOS and 31 macOS. iOS attachment tests use DataInteractionSimulator to simulate UIKit drag and drop coordination. On macOS, 32 handling of dropped content is much closer to handling of pasted content (they use the same codepaths to read 33 from the platform pasteboard), so exercising paste codepaths on Mac is sufficient. 34 35 * TestWebKitAPI/ios/DataInteractionSimulator.h: 36 * TestWebKitAPI/ios/DataInteractionSimulator.mm: 37 (-[DataInteractionSimulator _resetSimulatedState]): 38 (-[DataInteractionSimulator insertedAttachments]): 39 (-[DataInteractionSimulator removedAttachments]): 40 41 Teach the iOS drag and drop simulator to keep track of attachment elements that are inserted during a drop. We 42 also keep track of removed attachments here too, though no default drop handling scenario should trigger 43 attachment removal, so we simply use this to check that no _WKAttachments were removed during a drop. 44 45 (-[DataInteractionSimulator _webView:didInsertAttachment:]): 46 (-[DataInteractionSimulator _webView:didRemoveAttachment:]): 47 1 48 2017-12-18 Fujii Hironori <Hironori.Fujii@sony.com> 2 49 -
trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm
r225422 r226085 26 26 #import "config.h" 27 27 28 #import "DataInteractionSimulator.h" 28 29 #import "PlatformUtilities.h" 29 30 #import "TestWKWebView.h" 31 #import <WebKit/WKPreferencesRefPrivate.h> 30 32 #import <WebKit/WKWebViewPrivate.h> 31 33 #import <WebKit/WebKit.h> 32 34 #import <WebKit/WebKitPrivate.h> 33 35 #import <wtf/RetainPtr.h> 36 37 #if PLATFORM(IOS) 38 #import <MobileCoreServices/MobileCoreServices.h> 39 #endif 34 40 35 41 #if WK_API_ENABLED … … 123 129 auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]); 124 130 [configuration _setAttachmentElementEnabled:YES]; 131 WKPreferencesSetCustomPasteboardDataEnabled((WKPreferencesRef)[configuration preferences], YES); 125 132 126 133 auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500) configuration:configuration.get()]); 127 [webView synchronouslyLoadHTMLString:@"< body contenteditable></body><script>document.body.focus();</script>"];134 [webView synchronouslyLoadHTMLString:@"<script>focus = () => document.body.focus()</script><body onload=focus() contenteditable></body>"]; 128 135 129 136 return webView; … … 135 142 } 136 143 144 static NSURL *testImageFileURL() 145 { 146 return [[NSBundle mainBundle] URLForResource:@"icon" withExtension:@"png" subdirectory:@"TestWebKitAPI.resources"]; 147 } 148 137 149 static NSData *testImageData() 138 150 { 139 NSURL *url = [[NSBundle mainBundle] URLForResource:@"icon" withExtension:@"png" subdirectory:@"TestWebKitAPI.resources"]; 140 return [NSData dataWithContentsOfURL:url]; 151 return [NSData dataWithContentsOfURL:testImageFileURL()]; 141 152 } 142 153 … … 147 158 } 148 159 160 static NSURL *testPDFFileURL() 161 { 162 return [[NSBundle mainBundle] URLForResource:@"test" withExtension:@"pdf" subdirectory:@"TestWebKitAPI.resources"]; 163 } 164 149 165 static NSData *testPDFData() 150 166 { 151 NSURL *url = [[NSBundle mainBundle] URLForResource:@"test" withExtension:@"pdf" subdirectory:@"TestWebKitAPI.resources"]; 152 return [NSData dataWithContentsOfURL:url]; 167 return [NSData dataWithContentsOfURL:testPDFFileURL()]; 153 168 } 154 169 … … 292 307 @end 293 308 309 #pragma mark - Platform testing helper functions 310 311 void platformCopyRichTextWithImage() 312 { 313 auto richText = adoptNS([[NSMutableAttributedString alloc] init]); 314 auto image = adoptNS([[NSTextAttachment alloc] initWithData:testImageData() ofType:(NSString *)kUTTypePNG]); 315 316 [richText appendAttributedString:[[[NSAttributedString alloc] initWithString:@"Lorem ipsum "] autorelease]]; 317 [richText appendAttributedString:[NSAttributedString attributedStringWithAttachment:image.get()]]; 318 [richText appendAttributedString:[[[NSAttributedString alloc] initWithString:@" dolor sit amet."] autorelease]]; 319 320 #if PLATFORM(MAC) 321 NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; 322 [pasteboard clearContents]; 323 [pasteboard writeObjects:@[ richText.get() ]]; 324 #elif PLATFORM(IOS) 325 auto item = adoptNS([[NSItemProvider alloc] init]); 326 [item registerObject:richText.get() visibility:NSItemProviderRepresentationVisibilityAll]; 327 [UIPasteboard generalPasteboard].itemProviders = @[ item.get() ]; 328 #endif 329 } 330 331 typedef void(^ItemProviderDataLoadHandler)(NSData *, NSError *); 332 333 void platformCopyPNG() 334 { 335 #if PLATFORM(MAC) 336 NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; 337 [pasteboard declareTypes:@[NSPasteboardTypePNG] owner:nil]; 338 [pasteboard setData:testImageData() forType:NSPasteboardTypePNG]; 339 #elif PLATFORM(IOS) 340 UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; 341 auto item = adoptNS([[UIItemProvider alloc] init]); 342 [item setPreferredPresentationStyle:UIPreferredPresentationStyleAttachment]; 343 [item registerDataRepresentationForTypeIdentifier:(NSString *)kUTTypePNG visibility:NSItemProviderRepresentationVisibilityAll loadHandler:[] (ItemProviderDataLoadHandler completionHandler) -> NSProgress * { 344 completionHandler(testImageData(), nil); 345 return nil; 346 }]; 347 pasteboard.itemProviders = @[ item.get() ]; 348 #endif 349 } 350 351 #if PLATFORM(MAC) 352 typedef NSImage PlatformImage; 353 #else 354 typedef UIImage PlatformImage; 355 #endif 356 357 PlatformImage *platformImageWithData(NSData *data) 358 { 359 #if PLATFORM(MAC) 360 return [[[NSImage alloc] initWithData:data] autorelease]; 361 #else 362 return [UIImage imageWithData:data]; 363 #endif 364 } 365 294 366 namespace TestWebKitAPI { 367 368 #pragma mark - Platform-agnostic tests 295 369 296 370 TEST(WKAttachmentTests, AttachmentElementInsertion) … … 676 750 } 677 751 752 TEST(WKAttachmentTests, InsertPastedImageAsAttachment) 753 { 754 platformCopyPNG(); 755 756 RetainPtr<_WKAttachment> attachment; 757 auto webView = webViewForTestingAttachments(); 758 { 759 ObserveAttachmentUpdatesForScope observer(webView.get()); 760 [webView _synchronouslyExecuteEditCommand:@"Paste" argument:nil]; 761 EXPECT_EQ(1U, observer.observer().inserted.count); 762 attachment = observer.observer().inserted[0]; 763 } 764 765 auto size = platformImageWithData([attachment synchronouslyRequestData:nil]).size; 766 EXPECT_EQ(215., size.width); 767 EXPECT_EQ(174., size.height); 768 769 { 770 ObserveAttachmentUpdatesForScope observer(webView.get()); 771 [webView _synchronouslyExecuteEditCommand:@"SelectAll" argument:nil]; 772 [webView _synchronouslyExecuteEditCommand:@"DeleteBackward" argument:nil]; 773 observer.expectAttachmentUpdates(@[attachment.get()], @[]); 774 } 775 } 776 777 TEST(WKAttachmentTests, InsertPastedAttributedStringContainingImage) 778 { 779 platformCopyRichTextWithImage(); 780 781 RetainPtr<_WKAttachment> attachment; 782 auto webView = webViewForTestingAttachments(); 783 { 784 ObserveAttachmentUpdatesForScope observer(webView.get()); 785 [webView _synchronouslyExecuteEditCommand:@"Paste" argument:nil]; 786 EXPECT_EQ(0U, observer.observer().removed.count); 787 EXPECT_EQ(1U, observer.observer().inserted.count); 788 attachment = observer.observer().inserted[0]; 789 } 790 791 [attachment expectRequestedDataToBe:testImageData()]; 792 EXPECT_WK_STREQ("Lorem ipsum dolor sit amet.", [webView stringByEvaluatingJavaScript:@"document.body.textContent"]); 793 EXPECT_WK_STREQ("image/png", [webView valueOfAttribute:@"type" forQuerySelector:@"attachment"]); 794 795 { 796 ObserveAttachmentUpdatesForScope observer(webView.get()); 797 [webView _synchronouslyExecuteEditCommand:@"SelectAll" argument:nil]; 798 [webView _synchronouslyExecuteEditCommand:@"DeleteBackward" argument:nil]; 799 observer.expectAttachmentUpdates(@[attachment.get()], @[]); 800 } 801 } 802 803 #pragma mark - Platform-specific tests 804 805 #if PLATFORM(MAC) 806 807 TEST(WKAttachmentTestsMac, InsertPastedFileURLsAsAttachments) 808 { 809 NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; 810 [pasteboard clearContents]; 811 [pasteboard declareTypes:@[NSFilenamesPboardType] owner:nil]; 812 [pasteboard setPropertyList:@[testPDFFileURL().path, testImageFileURL().path] forType:NSFilenamesPboardType]; 813 814 RetainPtr<NSArray<_WKAttachment *>> insertedAttachments; 815 auto webView = webViewForTestingAttachments(); 816 { 817 ObserveAttachmentUpdatesForScope observer(webView.get()); 818 [webView _synchronouslyExecuteEditCommand:@"Paste" argument:nil]; 819 insertedAttachments = [observer.observer() inserted]; 820 EXPECT_EQ(2U, [insertedAttachments count]); 821 } 822 823 NSArray<NSData *> *expectedAttachmentData = @[ testPDFData(), testImageData() ]; 824 EXPECT_TRUE([expectedAttachmentData containsObject:[[insertedAttachments firstObject] synchronouslyRequestData:nil]]); 825 EXPECT_TRUE([expectedAttachmentData containsObject:[[insertedAttachments lastObject] synchronouslyRequestData:nil]]); 826 EXPECT_WK_STREQ("application/pdf", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[0].getAttribute('type')"]); 827 EXPECT_WK_STREQ("test.pdf", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[0].getAttribute('title')"]); 828 EXPECT_WK_STREQ("image/png", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[1].getAttribute('type')"]); 829 EXPECT_WK_STREQ("icon.png", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[1].getAttribute('title')"]); 830 831 { 832 ObserveAttachmentUpdatesForScope observer(webView.get()); 833 [webView _synchronouslyExecuteEditCommand:@"SelectAll" argument:nil]; 834 [webView _synchronouslyExecuteEditCommand:@"DeleteBackward" argument:nil]; 835 NSArray<_WKAttachment *> *removedAttachments = [observer.observer() removed]; 836 EXPECT_EQ(2U, removedAttachments.count); 837 EXPECT_TRUE([removedAttachments containsObject:[insertedAttachments firstObject]]); 838 EXPECT_TRUE([removedAttachments.lastObject isEqual:[insertedAttachments lastObject]]); 839 } 840 } 841 842 #endif // PLATFORM(MAC) 843 844 #if PLATFORM(IOS) 845 846 TEST(WKAttachmentTestsIOS, InsertDroppedImageAsAttachment) 847 { 848 auto webView = webViewForTestingAttachments(); 849 auto draggingSimulator = adoptNS([[DataInteractionSimulator alloc] initWithWebView:webView.get()]); 850 auto item = adoptNS([[NSItemProvider alloc] init]); 851 [item setPreferredPresentationStyle:UIPreferredPresentationStyleAttachment]; 852 [item registerDataRepresentationForTypeIdentifier:(NSString *)kUTTypePNG visibility:NSItemProviderRepresentationVisibilityAll loadHandler:[] (ItemProviderDataLoadHandler completionHandler) -> NSProgress * { 853 completionHandler(testImageData(), nil); 854 return nil; 855 }]; 856 [draggingSimulator setExternalItemProviders:@[ item.get() ]]; 857 [draggingSimulator runFrom:CGPointZero to:CGPointMake(50, 50)]; 858 859 EXPECT_EQ(1U, [draggingSimulator insertedAttachments].count); 860 EXPECT_EQ(0U, [draggingSimulator removedAttachments].count); 861 auto attachment = retainPtr([draggingSimulator insertedAttachments].firstObject); 862 [attachment expectRequestedDataToBe:testImageData()]; 863 EXPECT_WK_STREQ("public.png", [webView valueOfAttribute:@"type" forQuerySelector:@"attachment"]); 864 865 { 866 ObserveAttachmentUpdatesForScope observer(webView.get()); 867 [webView _synchronouslyExecuteEditCommand:@"SelectAll" argument:nil]; 868 [webView _synchronouslyExecuteEditCommand:@"DeleteBackward" argument:nil]; 869 observer.expectAttachmentUpdates(@[attachment.get()], @[]); 870 } 871 } 872 873 TEST(WKAttachmentTestsIOS, InsertDroppedAttributedStringContainingAttachment) 874 { 875 auto webView = webViewForTestingAttachments(); 876 auto draggingSimulator = adoptNS([[DataInteractionSimulator alloc] initWithWebView:webView.get()]); 877 auto image = adoptNS([[NSTextAttachment alloc] initWithData:testImageData() ofType:(NSString *)kUTTypePNG]); 878 auto item = adoptNS([[NSItemProvider alloc] init]); 879 [item registerObject:[NSAttributedString attributedStringWithAttachment:image.get()] visibility:NSItemProviderRepresentationVisibilityAll]; 880 881 [draggingSimulator setExternalItemProviders:@[ item.get() ]]; 882 [draggingSimulator runFrom:CGPointZero to:CGPointMake(50, 50)]; 883 884 EXPECT_EQ(1U, [draggingSimulator insertedAttachments].count); 885 EXPECT_EQ(0U, [draggingSimulator removedAttachments].count); 886 auto attachment = retainPtr([draggingSimulator insertedAttachments].firstObject); 887 888 auto size = platformImageWithData([attachment synchronouslyRequestData:nil]).size; 889 EXPECT_EQ(215., size.width); 890 EXPECT_EQ(174., size.height); 891 EXPECT_WK_STREQ("image/png", [webView valueOfAttribute:@"type" forQuerySelector:@"attachment"]); 892 893 { 894 ObserveAttachmentUpdatesForScope observer(webView.get()); 895 [webView _synchronouslyExecuteEditCommand:@"SelectAll" argument:nil]; 896 [webView _synchronouslyExecuteEditCommand:@"DeleteBackward" argument:nil]; 897 observer.expectAttachmentUpdates(@[attachment.get()], @[]); 898 } 899 } 900 901 #endif // PLATFORM(IOS) 902 678 903 } // namespace TestWebKitAPI 679 904 -
trunk/Tools/TestWebKitAPI/ios/DataInteractionSimulator.h
r221907 r226085 139 139 RetainPtr<NSMutableArray<UITargetedDragPreview *>> _liftPreviews; 140 140 141 RetainPtr<NSMutableArray<_WKAttachment *>> _insertedAttachments; 142 RetainPtr<NSMutableArray<_WKAttachment *>> _removedAttachments; 143 141 144 bool _isDoneWaitingForInputSession; 142 145 BOOL _shouldPerformOperation; … … 169 172 @property (nonatomic, readonly) NSArray<UITargetedDragPreview *> *liftPreviews; 170 173 174 @property (nonatomic, readonly) NSArray<_WKAttachment *> *insertedAttachments; 175 @property (nonatomic, readonly) NSArray<_WKAttachment *> *removedAttachments; 176 171 177 @end 172 178 -
trunk/Tools/TestWebKitAPI/ios/DataInteractionSimulator.mm
r224517 r226085 318 318 _isDoneWithCurrentRun = false; 319 319 _observedEventNames = adoptNS([[NSMutableArray alloc] init]); 320 _insertedAttachments = adoptNS([[NSMutableArray alloc] init]); 321 _removedAttachments = adoptNS([[NSMutableArray alloc] init]); 320 322 _finalSelectionRects = @[ ]; 321 323 _dragSession = nil; … … 577 579 } 578 580 581 - (NSArray<_WKAttachment *> *)insertedAttachments 582 { 583 return _insertedAttachments.get(); 584 } 585 586 - (NSArray<_WKAttachment *> *)removedAttachments 587 { 588 return _removedAttachments.get(); 589 } 590 579 591 #pragma mark - WKUIDelegatePrivate 580 592 … … 618 630 } 619 631 632 - (void)_webView:(WKWebView *)webView didInsertAttachment:(_WKAttachment *)attachment 633 { 634 [_insertedAttachments addObject:attachment]; 635 } 636 637 - (void)_webView:(WKWebView *)webView didRemoveAttachment:(_WKAttachment *)attachment 638 { 639 [_removedAttachments addObject:attachment]; 640 } 641 620 642 #pragma mark - _WKInputDelegate 621 643
Note: See TracChangeset
for help on using the changeset viewer.