Changeset 226396 in webkit
- Timestamp:
- Jan 3, 2018, 11:44:55 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 33 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r226395 r226396 1 2018-01-03 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 [Attachment Support] Create attachment elements when dropping files on iOS 4 https://bugs.webkit.org/show_bug.cgi?id=181192 5 <rdar://problem/36280945> 6 7 Reviewed by Tim Horton. 8 9 Implements support for dropping data as attachment elements on iOS. See comments below for more detail. 10 11 Tests: WKAttachmentTests.InsertDroppedRichAndPlainTextFilesAsAttachments 12 WKAttachmentTests.InsertDroppedZipArchiveAsAttachment 13 WKAttachmentTests.InsertDroppedItemProvidersInOrder 14 15 * WebCore.xcodeproj/project.pbxproj: 16 * editing/WebContentReader.cpp: 17 (WebCore::WebContentReader::ensureFragment): 18 19 Add a new helper to create the WebContentReader's fragment, if it hasn't already been created. 20 21 * editing/WebContentReader.h: 22 * editing/cocoa/WebContentReaderCocoa.mm: 23 (WebCore::WebContentReader::readFilePaths): 24 25 Rename readFilenames to readFilePaths (which better reflects its parameters, which are file paths). Also, move 26 the implementation of readFilePaths to shared iOS/macOS code in WebContentReaderCocoa, and remove the stub 27 implementation on iOS. 28 29 There's a bit of code here that I kept macOS-only which deals with inserting file paths as plain text in 30 editable areas, but it's unclear to me why and if WebKit clients currently find this useful, so I left a FIXME 31 to investigate removing this altogether. Code for handling this plain text insertion of file paths on Mac was 32 introduced in r67403. 33 34 * editing/ios/WebContentReaderIOS.mm: 35 (WebCore::WebContentReader::readFilenames): Deleted. 36 * editing/mac/WebContentReaderMac.mm: 37 (WebCore::WebContentReader::readFilenames): Deleted. 38 * page/mac/DragControllerMac.mm: 39 (WebCore::DragController::updateSupportedTypeIdentifiersForDragHandlingMethod const): 40 41 Teach DragController to accept all types conforming to "public.item" and "public.content" on iOS, only when 42 attachment elements are enabled. This allows us to load content from item providers that we otherwise would not 43 have loaded, since we now have the ability to fall back to attachment element insertion if the type is not have 44 a default representation using standard web content. 45 46 * platform/Pasteboard.h: 47 * platform/PasteboardItemInfo.h: Added. 48 (WebCore::PasteboardItemInfo::encode const): 49 (WebCore::PasteboardItemInfo::decode): 50 51 Add PasteboardItemInfo, a struct that describes an item on the pasteboard. Also, implement encoding and decoding 52 support for PasteboardItemInfo. So far, the item info only describes file information about the pasteboard item, 53 and flags indicating whether the item prefers attachment or inline presentation. 54 55 * platform/PasteboardStrategy.h: 56 57 Replace getFilenamesForDataInteraction with informationForItemAtIndex. Instead of returning all of the file 58 paths associated with any item on the pasteboard, fetch a PasteboardItemInfo at a given item index, which 59 includes information about the file path as well as some other metadata we'll need when deciding how to read 60 pasteboard contents as a document fragment. 61 62 * platform/PlatformPasteboard.h: 63 * platform/cocoa/PasteboardCocoa.mm: 64 (WebCore::Pasteboard::read): 65 * platform/ios/AbstractPasteboard.h: 66 * platform/ios/PasteboardIOS.mm: 67 (WebCore::Pasteboard::read): 68 (WebCore::Pasteboard::readRespectingUTIFidelities): 69 70 Teach the iOS Pasteboard to read web content using attachment elements, if enabled. There are two scenarios in 71 which we would want to insert an attachment element: 72 (1) The item provider uses a preferred presentation style of attachment, in which case we bail out of trying to 73 handle the drop using the default mechanisms, and simply insert it as an attachment. We need this to deal 74 with the case where we drop text or HTML files from the Files app, so that we don't try and insert the 75 contents of the text or HTML as inline web content. 76 (2) The item provider doesn't have a preferred attachment presentation style, but there's nothing WebKit would 77 otherwise do with the dropped content, so insert an attachment element as a fallback. Examples where this is 78 relevant are dropping a PDF or ZIP archive without attachment presentation style explicitly set. 79 We first check if we fall into case (1). If so, we can bail early by inserting an attachment; otherwise, we 80 proceed normally and see if we can read the contents of the drop as web content. If, at the end of default drop 81 handling, we don't still have a way to represent the dropped content, enter case (2). 82 83 (WebCore::Pasteboard::readFilePaths): 84 (WebCore::Pasteboard::readFilenames): Deleted. 85 86 Rename readFilenames to readFilePaths, and reimplement it using informationForItemAtIndex. 87 88 * platform/ios/PlatformPasteboardIOS.mm: 89 (WebCore::pasteboardItemPresentationStyle): 90 (WebCore::PlatformPasteboard::informationForItemAtIndex): 91 (WebCore::PlatformPasteboard::filenamesForDataInteraction): Deleted. 92 93 Implement informationForItemAtIndex and remove filenamesForDataInteraction. As before, we ask the pasteboard 94 (i.e. WebItemProviderPasteboard) for information about dropped file URLs. This time, we limit this to a single 95 file, so we don't end up creating multiple attachment elements for each representation of a single item 96 provider. See below for -preferredFileUploadURLAtIndex:fileType: for more detail. 97 98 * platform/ios/WebItemProviderPasteboard.h: 99 * platform/ios/WebItemProviderPasteboard.mm: 100 (-[WebItemProviderLoadResult initWithItemProvider:typesToLoad:]): 101 (-[WebItemProviderLoadResult canBeRepresentedAsFileUpload]): 102 103 Remove this synthesized instance variable and instead just check the item provider's preferredPresentationStyle. 104 105 (-[WebItemProviderLoadResult description]): 106 107 Add a verbose -description to the load result object. Useful for debugging what was content was loaded from an 108 item provider on drop. 109 110 (-[WebItemProviderPasteboard preferredFileUploadURLAtIndex:fileType:]): 111 112 Return the highest fidelity loaded type identifier for a given item. 113 114 (-[WebItemProviderPasteboard allDroppedFileURLs]): 115 (-[WebItemProviderPasteboard typeIdentifiersToLoadForRegisteredTypeIdentfiers:]): 116 117 Prefer flat RTFD to RTFD. In the case where attachments are enabled and we're accepting all types of content 118 using attachment elements as a fallback representation, if the source writes attributed strings to the 119 pasteboard with com.apple.rtfd at a higher fidelity than com.apple.flat-rtfd, we'll end up loading only 120 com.apple.rtfd and dropping the text as an attachment element because we cannot convert the dropped content to 121 markup. Instead, if flat RTFD is present in the item provider, always prefer that over RTFD so that dropping as 122 regular web content isn't overridden when attachment elements are enabled. 123 124 (-[WebItemProviderPasteboard doAfterLoadingProvidedContentIntoFileURLs:synchronousTimeout:]): 125 (-[WebItemProviderPasteboard droppedFileURLs]): Deleted. 126 * platform/mac/DragDataMac.mm: 127 (WebCore::DragData::containsCompatibleContent const): 128 129 DragData::containsCompatibleContent should be true when attachment elements are enabled, and there are files we 130 can drop as attachment elements. 131 132 * platform/mac/PasteboardMac.mm: 133 (WebCore::Pasteboard::read): 134 (WebCore::Pasteboard::readFilePaths): 135 (WebCore::Pasteboard::readFilenames): Deleted. 136 1 137 2018-01-03 Ting-Wei Lan <lantw44@gmail.com> 2 138 -
trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj
r226348 r226396 4654 4654 F48223111E3869B80066FC79 /* WebItemProviderPasteboard.h in Headers */ = {isa = PBXBuildFile; fileRef = F482230F1E3869B80066FC79 /* WebItemProviderPasteboard.h */; settings = {ATTRIBUTES = (Private, ); }; }; 4655 4655 F48223131E386E240066FC79 /* AbstractPasteboard.h in Headers */ = {isa = PBXBuildFile; fileRef = F48223121E386E240066FC79 /* AbstractPasteboard.h */; settings = {ATTRIBUTES = (Private, ); }; }; 4656 F49786881FF45FA500E060AB /* PasteboardItemInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = F49786871FF45FA500E060AB /* PasteboardItemInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; 4656 4657 F4BFB9851E1DDF9B00862C24 /* DumpEditingHistory.js in Copy Scripts */ = {isa = PBXBuildFile; fileRef = F48389831E1DDF2B0076B7EA /* DumpEditingHistory.js */; }; 4657 4658 F4BFB9861E1DDF9B00862C24 /* EditingHistoryUtil.js in Copy Scripts */ = {isa = PBXBuildFile; fileRef = F48389841E1DDF2B0076B7EA /* EditingHistoryUtil.js */; }; … … 14087 14088 F48389831E1DDF2B0076B7EA /* DumpEditingHistory.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = DumpEditingHistory.js; path = Scripts/DumpEditingHistory.js; sourceTree = "<group>"; }; 14088 14089 F48389841E1DDF2B0076B7EA /* EditingHistoryUtil.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = EditingHistoryUtil.js; path = Scripts/EditingHistoryUtil.js; sourceTree = "<group>"; }; 14090 F49786871FF45FA500E060AB /* PasteboardItemInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PasteboardItemInfo.h; sourceTree = "<group>"; }; 14089 14091 F50664F5157F52DC00AC226F /* FormController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FormController.cpp; sourceTree = "<group>"; }; 14090 14092 F50664F6157F52DC00AC226F /* FormController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FormController.h; sourceTree = "<group>"; }; … … 23692 23694 2EE02A1E1F7324280006AF72 /* Pasteboard.cpp */, 23693 23695 4B2708C50AF19EE40065127F /* Pasteboard.h */, 23696 F49786871FF45FA500E060AB /* PasteboardItemInfo.h */, 23694 23697 C5F765B414E1D414006C899B /* PasteboardStrategy.h */, 23695 23698 1AF5E4D21E56735A004A1F01 /* PasteboardWriterData.cpp */, … … 28691 28694 F55B3DCA1251F12D003EF269 /* PasswordInputType.h in Headers */, 28692 28695 4B2708C70AF19EE40065127F /* Pasteboard.h in Headers */, 28696 F49786881FF45FA500E060AB /* PasteboardItemInfo.h in Headers */, 28693 28697 C598905714E9C28000E8D18B /* PasteboardStrategy.h in Headers */, 28694 28698 1AF5E4E31E5779B1004A1F01 /* PasteboardWriter.h in Headers */, -
trunk/Source/WebCore/editing/WebContentReader.cpp
r223678 r226396 32 32 namespace WebCore { 33 33 34 DocumentFragment& WebContentReader::ensureFragment() 35 { 36 ASSERT(frame.document()); 37 if (!fragment) 38 fragment = frame.document()->createDocumentFragment(); 39 return *fragment; 40 } 41 34 42 void WebContentReader::addFragment(Ref<DocumentFragment>&& newFragment) 35 43 { -
trunk/Source/WebCore/editing/WebContentReader.h
r226213 r226396 64 64 } 65 65 66 DocumentFragment& ensureFragment(); 66 67 void addFragment(Ref<DocumentFragment>&&); 67 68 … … 69 70 #if PLATFORM(COCOA) 70 71 bool readWebArchive(SharedBuffer&) override; 71 bool readFile names(const Vector<String>&) override;72 bool readFilePaths(const Vector<String>&) override; 72 73 bool readHTML(const String&) override; 73 74 bool readRTFD(SharedBuffer&) override; … … 91 92 #if PLATFORM(COCOA) 92 93 bool readWebArchive(SharedBuffer&) override; 93 bool readFile names(const Vector<String>&) override { return false; }94 bool readFilePaths(const Vector<String>&) override { return false; } 94 95 bool readHTML(const String&) override; 95 96 bool readRTFD(SharedBuffer&) override; -
trunk/Source/WebCore/editing/cocoa/WebContentReaderCocoa.mm
r226340 r226396 597 597 } 598 598 599 } 599 bool WebContentReader::readFilePaths(const Vector<String>& paths) 600 { 601 if (paths.isEmpty() || !frame.document()) 602 return false; 603 604 auto& document = *frame.document(); 605 bool readAnyFilePath = false; 606 for (auto& path : paths) { 607 #if ENABLE(ATTACHMENT_ELEMENT) 608 if (RuntimeEnabledFeatures::sharedFeatures().attachmentElementEnabled()) { 609 auto attachment = HTMLAttachmentElement::create(HTMLNames::attachmentTag, document); 610 attachment->setUniqueIdentifier(createCanonicalUUIDString()); 611 attachment->setFile(File::create(path), HTMLAttachmentElement::UpdateDisplayAttributes::Yes); 612 ensureFragment().appendChild(attachment); 613 readAnyFilePath = true; 614 continue; 615 } 616 #endif 617 #if PLATFORM(MAC) 618 // FIXME: Does (and should) any macOS client depend on inserting file paths as plain text in web content? 619 // If not, we should just remove this. 620 auto paragraph = createDefaultParagraphElement(document); 621 paragraph->appendChild(document.createTextNode(userVisibleString([NSURL fileURLWithPath:path]))); 622 ensureFragment().appendChild(paragraph); 623 readAnyFilePath = true; 624 #endif 625 } 626 return readAnyFilePath; 627 } 628 629 } -
trunk/Source/WebCore/editing/ios/WebContentReaderIOS.mm
r223020 r226396 48 48 namespace WebCore { 49 49 50 bool WebContentReader::readFilenames(const Vector<String>&)51 {52 return false;53 }54 55 50 bool WebContentReader::readURL(const URL& url, const String& title) 56 51 { -
trunk/Source/WebCore/editing/mac/WebContentReaderMac.mm
r226085 r226396 39 39 #import "FrameLoaderClient.h" 40 40 #import "HTMLAnchorElement.h" 41 #import "HTMLAttachmentElement.h"42 41 #import "HTMLNames.h" 43 42 #import "LegacyWebArchive.h" 44 #import "MIMETypeRegistry.h"45 #import "RuntimeEnabledFeatures.h"46 43 #import "Settings.h" 47 44 #import "Text.h" 48 45 #import "WebCoreNSURLExtras.h" 49 46 #import "markup.h" 50 #import <wtf/UUID.h>51 47 52 48 namespace WebCore { 53 54 bool WebContentReader::readFilenames(const Vector<String>& paths)55 {56 if (paths.isEmpty())57 return false;58 59 if (!frame.document())60 return false;61 Document& document = *frame.document();62 63 fragment = document.createDocumentFragment();64 65 for (auto& text : paths) {66 #if ENABLE(ATTACHMENT_ELEMENT)67 if (RuntimeEnabledFeatures::sharedFeatures().attachmentElementEnabled()) {68 auto attachment = HTMLAttachmentElement::create(HTMLNames::attachmentTag, document);69 attachment->setUniqueIdentifier(createCanonicalUUIDString());70 attachment->setFile(File::create([NSURL fileURLWithPath:text].path), HTMLAttachmentElement::UpdateDisplayAttributes::Yes);71 fragment->appendChild(attachment);72 continue;73 }74 #else75 auto paragraph = createDefaultParagraphElement(document);76 paragraph->appendChild(document.createTextNode(userVisibleString([NSURL fileURLWithPath:text])));77 fragment->appendChild(paragraph);78 #endif79 }80 81 return true;82 }83 49 84 50 bool WebContentReader::readURL(const URL& url, const String& title) -
trunk/Source/WebCore/page/mac/DragControllerMac.mm
r226312 r226396 46 46 #import "PlatformStrategies.h" 47 47 #import "Range.h" 48 #import "RuntimeEnabledFeatures.h" 48 49 49 50 #if ENABLE(DATA_INTERACTION) … … 126 127 break; 127 128 case DragHandlingMethod::EditRichText: 128 for (NSString *type in Pasteboard::supportedWebContentPasteboardTypes()) 129 supportedTypes.append(type); 129 if (RuntimeEnabledFeatures::sharedFeatures().attachmentElementEnabled()) { 130 supportedTypes.append(WebArchivePboardType); 131 supportedTypes.append(kUTTypeContent); 132 supportedTypes.append(kUTTypeItem); 133 } else { 134 for (NSString *type in Pasteboard::supportedWebContentPasteboardTypes()) 135 supportedTypes.append(type); 136 } 130 137 break; 131 138 default: -
trunk/Source/WebCore/platform/Pasteboard.h
r223728 r226396 27 27 28 28 #include "DragImage.h" 29 #include "PasteboardItemInfo.h" 29 30 #include "URL.h" 30 31 #include <wtf/HashMap.h> … … 135 136 #if PLATFORM(COCOA) 136 137 virtual bool readWebArchive(SharedBuffer&) = 0; 137 virtual bool readFile names(const Vector<String>&) = 0;138 virtual bool readFilePaths(const Vector<String>&) = 0; 138 139 virtual bool readHTML(const String&) = 0; 139 140 virtual bool readRTFD(SharedBuffer&) = 0; … … 291 292 292 293 #if PLATFORM(COCOA) 293 Vector<String> readFile names();294 Vector<String> readFilePaths(); 294 295 String readPlatformValueAsString(const String& domType, long changeCount, const String& pasteboardName); 295 296 static void addHTMLClipboardTypesForCocoaType(ListHashSet<String>& resultTypes, const String& cocoaType); -
trunk/Source/WebCore/platform/PasteboardStrategy.h
r223195 r226396 36 36 class URL; 37 37 struct PasteboardImage; 38 struct PasteboardItemInfo; 38 39 struct PasteboardURL; 39 40 struct PasteboardWebContent; … … 51 52 virtual RefPtr<SharedBuffer> readBufferFromPasteboard(int index, const String& pasteboardType, const String& pasteboardName) = 0; 52 53 virtual URL readURLFromPasteboard(int index, const String& pasteboardType, const String& pasteboardName, String& title) = 0; 53 virtual void getFilenamesForDataInteraction(Vector<String>& filenames, const String& pasteboardName) = 0;54 virtual PasteboardItemInfo informationForItemAtIndex(int index, const String& pasteboardName) = 0; 54 55 virtual void updateSupportedTypeIdentifiers(const Vector<String>& identifiers, const String& pasteboardName) = 0; 55 56 virtual void getTypesByFidelityForItemAtIndex(Vector<String>& types, uint64_t index, const String& pasteboardName) = 0; -
trunk/Source/WebCore/platform/PlatformPasteboard.h
r223340 r226396 52 52 struct PasteboardCustomData; 53 53 struct PasteboardImage; 54 struct PasteboardItemInfo; 54 55 struct PasteboardURL; 55 56 struct PasteboardWebContent; … … 60 61 #if PLATFORM(IOS) || PLATFORM(WPE) 61 62 WEBCORE_EXPORT PlatformPasteboard(); 62 WEBCORE_EXPORT Vector<String> filenamesForDataInteraction();63 WEBCORE_EXPORT PasteboardItemInfo informationForItemAtIndex(int index); 63 64 WEBCORE_EXPORT void getTypesByFidelityForItemAtIndex(Vector<String>& types, int index); 64 65 WEBCORE_EXPORT void updateSupportedTypeIdentifiers(const Vector<String>& types); -
trunk/Source/WebCore/platform/cocoa/PasteboardCocoa.mm
r226277 r226396 192 192 void Pasteboard::read(PasteboardFileReader& reader) 193 193 { 194 auto filenames = readFile names();194 auto filenames = readFilePaths(); 195 195 if (!filenames.isEmpty()) { 196 196 for (auto& filename : filenames) -
trunk/Source/WebCore/platform/ios/AbstractPasteboard.h
r222595 r226396 57 57 - (NSArray<NSString *> *)pasteboardTypesByFidelityForItemAtIndex:(NSUInteger)index; 58 58 @property (readonly, nonatomic) NSInteger numberOfFiles; 59 @property (readonly, nonatomic) NSArray<NSURL *> *droppedFileURLs; 59 @property (readonly, nonatomic) NSArray<NSURL *> *allDroppedFileURLs; 60 - (nullable NSURL *)preferredFileUploadURLAtIndex:(NSUInteger)index fileType:(NSString *_Nullable *_Nullable)outFileType; 60 61 - (void)updateSupportedTypeIdentifiers:(NSArray<NSString *> *)types; 61 62 -
trunk/Source/WebCore/platform/ios/PasteboardIOS.mm
r223678 r226396 32 32 #import "PlatformPasteboard.h" 33 33 #import "PlatformStrategies.h" 34 #import "RuntimeEnabledFeatures.h" 34 35 #import "SharedBuffer.h" 35 36 #import "URL.h" … … 245 246 for (int i = 0; i < numberOfItems; i++) { 246 247 for (int typeIndex = 0; typeIndex < numberOfTypes; typeIndex++) { 247 auto result = readPasteboardWebContentDataForType(reader, strategy, [types objectAtIndex:typeIndex], i); 248 auto itemResult = readPasteboardWebContentDataForType(reader, strategy, [types objectAtIndex:typeIndex], i); 249 if (itemResult == ReaderResult::PasteboardWasChangedExternally) 250 return; 251 if (itemResult == ReaderResult::ReadType) 252 break; 253 } 254 } 255 } 256 257 bool Pasteboard::respectsUTIFidelities() const 258 { 259 // For now, data interaction is the only feature that uses item-provider-based pasteboard representations. 260 // In the future, we may need to consult the client layer to determine whether or not the pasteboard supports 261 // item types ranked by fidelity. 262 return m_pasteboardName == "data interaction pasteboard"; 263 } 264 265 void Pasteboard::readRespectingUTIFidelities(PasteboardWebContentReader& reader) 266 { 267 ASSERT(respectsUTIFidelities()); 268 auto& strategy = *platformStrategies()->pasteboardStrategy(); 269 for (NSUInteger index = 0, numberOfItems = strategy.getPasteboardItemsCount(m_pasteboardName); index < numberOfItems; ++index) { 270 #if ENABLE(ATTACHMENT_ELEMENT) 271 auto info = strategy.informationForItemAtIndex(index, m_pasteboardName); 272 bool canReadAttachment = RuntimeEnabledFeatures::sharedFeatures().attachmentElementEnabled() && !info.pathForFileUpload.isEmpty(); 273 if (canReadAttachment && info.preferredPresentationStyle == PasteboardItemPresentationStyle::Attachment) { 274 reader.readFilePaths({ info.pathForFileUpload }); 275 continue; 276 } 277 #endif 278 // Try to read data from each type identifier that this pasteboard item supports, and WebKit also recognizes. Type identifiers are 279 // read in order of fidelity, as specified by each pasteboard item. 280 Vector<String> typesForItemInOrderOfFidelity; 281 strategy.getTypesByFidelityForItemAtIndex(typesForItemInOrderOfFidelity, index, m_pasteboardName); 282 ReaderResult result = ReaderResult::DidNotReadType; 283 for (auto& type : typesForItemInOrderOfFidelity) { 284 result = readPasteboardWebContentDataForType(reader, strategy, type, index); 248 285 if (result == ReaderResult::PasteboardWasChangedExternally) 249 286 return; … … 251 288 break; 252 289 } 253 } 254 } 255 256 bool Pasteboard::respectsUTIFidelities() const 257 { 258 // For now, data interaction is the only feature that uses item-provider-based pasteboard representations. 259 // In the future, we may need to consult the client layer to determine whether or not the pasteboard supports 260 // item types ranked by fidelity. 261 return m_pasteboardName == "data interaction pasteboard"; 262 } 263 264 void Pasteboard::readRespectingUTIFidelities(PasteboardWebContentReader& reader) 265 { 266 ASSERT(respectsUTIFidelities()); 267 auto& strategy = *platformStrategies()->pasteboardStrategy(); 268 for (NSUInteger index = 0, numberOfItems = strategy.getPasteboardItemsCount(m_pasteboardName); index < numberOfItems; ++index) { 269 // Try to read data from each type identifier that this pasteboard item supports, and WebKit also recognizes. Type identifiers are 270 // read in order of fidelity, as specified by each pasteboard item. 271 Vector<String> typesForItemInOrderOfFidelity; 272 strategy.getTypesByFidelityForItemAtIndex(typesForItemInOrderOfFidelity, index, m_pasteboardName); 273 for (auto& type : typesForItemInOrderOfFidelity) { 274 auto result = readPasteboardWebContentDataForType(reader, strategy, type, index); 275 if (result == ReaderResult::PasteboardWasChangedExternally) 276 return; 277 if (result == ReaderResult::ReadType) 278 break; 279 } 290 #if ENABLE(ATTACHMENT_ELEMENT) 291 if (canReadAttachment && result == ReaderResult::DidNotReadType) 292 reader.readFilePaths({ info.pathForFileUpload }); 293 #endif 280 294 } 281 295 } … … 406 420 } 407 421 408 Vector<String> Pasteboard::readFilenames() 409 { 410 Vector<String> filenames; 411 // Currently, data interaction is the only case on iOS where the pasteboard may contain relevant filenames. 412 platformStrategies()->pasteboardStrategy()->getFilenamesForDataInteraction(filenames, m_pasteboardName); 413 return filenames; 414 } 415 416 } 422 Vector<String> Pasteboard::readFilePaths() 423 { 424 Vector<String> filePaths; 425 auto& strategy = *platformStrategies()->pasteboardStrategy(); 426 for (NSUInteger index = 0, numberOfItems = strategy.getPasteboardItemsCount(m_pasteboardName); index < numberOfItems; ++index) { 427 // Currently, drag and drop is the only case on iOS where the "pasteboard" may contain file paths. 428 auto filePath = strategy.informationForItemAtIndex(index, m_pasteboardName).pathForFileUpload; 429 if (!filePath.isEmpty()) 430 filePaths.append(WTFMove(filePath)); 431 } 432 return filePaths; 433 } 434 435 } -
trunk/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm
r226248 r226396 103 103 } 104 104 105 Vector<String> PlatformPasteboard::filenamesForDataInteraction() 106 { 107 if (![m_pasteboard respondsToSelector:@selector(droppedFileURLs)]) 105 #if PASTEBOARD_SUPPORTS_ITEM_PROVIDERS 106 107 static PasteboardItemPresentationStyle pasteboardItemPresentationStyle(UIPreferredPresentationStyle style) 108 { 109 switch (style) { 110 case UIPreferredPresentationStyleUnspecified: 111 return PasteboardItemPresentationStyle::Unspecified; 112 case UIPreferredPresentationStyleInline: 113 return PasteboardItemPresentationStyle::Inline; 114 case UIPreferredPresentationStyleAttachment: 115 return PasteboardItemPresentationStyle::Attachment; 116 default: 117 ASSERT_NOT_REACHED(); 118 return PasteboardItemPresentationStyle::Unspecified; 119 } 120 } 121 122 PasteboardItemInfo PlatformPasteboard::informationForItemAtIndex(int index) 123 { 124 if (index >= [m_pasteboard numberOfItems]) 108 125 return { }; 109 126 110 Vector<String> filenames; 111 for (NSURL *fileURL in [m_pasteboard droppedFileURLs]) 112 filenames.append(fileURL.path); 113 114 return filenames; 115 } 127 PasteboardItemInfo info; 128 if ([m_pasteboard respondsToSelector:@selector(preferredFileUploadURLAtIndex:fileType:)]) { 129 NSString *fileType = nil; 130 info.pathForFileUpload = [m_pasteboard preferredFileUploadURLAtIndex:index fileType:&fileType].path; 131 info.contentTypeForFileUpload = fileType; 132 } 133 134 NSItemProvider *itemProvider = [[m_pasteboard itemProviders] objectAtIndex:index]; 135 info.preferredPresentationStyle = pasteboardItemPresentationStyle(itemProvider.preferredPresentationStyle); 136 return info; 137 } 138 139 #else 140 141 PasteboardItemInfo PlatformPasteboard::informationForItemAtIndex(int) 142 { 143 return { }; 144 } 145 146 #endif 116 147 117 148 static bool pasteboardMayContainFilePaths(id<AbstractPasteboard> pasteboard) -
trunk/Source/WebCore/platform/ios/WebItemProviderPasteboard.h
r222595 r226396 91 91 92 92 // This will only be non-empty when an operation is being performed. 93 @property (readonly, nonatomic) NSArray<NSURL *> *droppedFileURLs; 93 @property (readonly, nonatomic) NSArray<NSURL *> *allDroppedFileURLs; 94 95 // The preferred file URL corresponds to the highest fidelity non-private UTI that was loaded. 96 - (nullable NSURL *)preferredFileUploadURLAtIndex:(NSUInteger)index fileType:(NSString *_Nullable *_Nullable)outFileType; 94 97 95 98 @property (readonly, nonatomic) BOOL hasPendingOperation; -
trunk/Source/WebCore/platform/ios/WebItemProviderPasteboard.mm
r224371 r226396 244 244 _itemProvider = itemProvider; 245 245 _typesToLoad = typesToLoad; 246 _canBeRepresentedAsFileUpload = itemProvider.preferredPresentationStyle != UIPreferredPresentationStyleInline;247 246 248 247 return self; 249 248 } 250 249 250 - (BOOL)canBeRepresentedAsFileUpload 251 { 252 return [_itemProvider preferredPresentationStyle] != UIPreferredPresentationStyleInline; 253 } 254 251 255 - (NSArray<NSString *> *)typesToLoad 252 256 { … … 277 281 { 278 282 return _itemProvider.get(); 283 } 284 285 - (NSString *)description 286 { 287 __block NSMutableString *description = [NSMutableString string]; 288 [description appendFormat:@"<%@: %p typesToLoad: [ ", [self class], self]; 289 [_typesToLoad enumerateObjectsUsingBlock:^(NSString *type, NSUInteger index, BOOL *) { 290 [description appendString:type]; 291 if (index + 1 < [_typesToLoad count]) 292 [description appendString:@", "]; 293 }]; 294 [description appendFormat:@" ] fileURLs: { "]; 295 __block NSUInteger index = 0; 296 [_fileURLs enumerateKeysAndObjectsUsingBlock:^(NSString *type, NSURL *url, BOOL *) { 297 [description appendFormat:@"%@ => \"%@\"", type, url.path]; 298 if (++index < [_fileURLs count]) 299 [description appendString:@", "]; 300 }]; 301 [description appendFormat:@" }>"]; 302 return description; 279 303 } 280 304 … … 471 495 } 472 496 473 - (NSArray<NSURL *> *)droppedFileURLs 497 - (NSURL *)preferredFileUploadURLAtIndex:(NSUInteger)index fileType:(NSString **)outFileType 498 { 499 if (outFileType) 500 *outFileType = nil; 501 502 if (index >= _loadResults.size()) 503 return nil; 504 505 auto result = _loadResults[index]; 506 if (![result canBeRepresentedAsFileUpload]) 507 return nil; 508 509 NSItemProvider *itemProvider = [result itemProvider]; 510 for (NSString *registeredTypeIdentifier in itemProvider.registeredTypeIdentifiers) { 511 // Search for the highest fidelity non-private type identifier we loaded from the item provider. 512 if (!UTTypeIsDeclared((CFStringRef)registeredTypeIdentifier) && !UTTypeIsDynamic((CFStringRef)registeredTypeIdentifier)) 513 continue; 514 515 for (NSString *loadedTypeIdentifier in [result loadedTypeIdentifiers]) { 516 if (!UTTypeConformsTo((CFStringRef)registeredTypeIdentifier, (CFStringRef)loadedTypeIdentifier)) 517 continue; 518 519 if (outFileType) 520 *outFileType = loadedTypeIdentifier; 521 return [result fileURLForType:loadedTypeIdentifier]; 522 } 523 } 524 525 return nil; 526 } 527 528 - (NSArray<NSURL *> *)allDroppedFileURLs 474 529 { 475 530 NSMutableArray<NSURL *> *fileURLs = [NSMutableArray array]; … … 540 595 NSString *highestFidelityContentType = nil; 541 596 597 BOOL containsFlatRTFD = [registeredTypeIdentifiers containsObject:(NSString *)kUTTypeFlatRTFD]; 542 598 // First, we want to either load the highest fidelity supported type or the highest fidelity generic content type. 543 599 for (NSString *registeredTypeIdentifier in registeredTypeIdentifiers) { 600 if (containsFlatRTFD && [registeredTypeIdentifier isEqualToString:(NSString *)kUTTypeRTFD]) { 601 // In the case where attachments are enabled and we're accepting all types of content using attachment 602 // elements as a fallback representation, if the source writes attributed strings to the pasteboard with 603 // com.apple.rtfd at a higher fidelity than com.apple.flat-rtfd, we'll end up loading only com.apple.rtfd 604 // and dropping the text as an attachment element because we cannot convert the dropped content to markup. 605 // Instead, if flat RTFD is present in the item provider, always prefer that over RTFD so that dropping as 606 // regular web content isn't overridden by enabling attachment elements. 607 continue; 608 } 609 544 610 if (typeConformsToTypes(registeredTypeIdentifier, _supportedTypeIdentifiers.get())) { 545 611 [typesToLoad addObject:registeredTypeIdentifier]; … … 627 693 } 628 694 629 completionBlock([retainedSelf droppedFileURLs]);695 completionBlock([retainedSelf allDroppedFileURLs]); 630 696 }; 631 697 -
trunk/Source/WebCore/platform/mac/DragDataMac.mm
r226277 r226396 35 35 #import "PlatformPasteboard.h" 36 36 #import "PlatformStrategies.h" 37 #import "RuntimeEnabledFeatures.h" 37 38 #import "WebCoreNSURLExtras.h" 38 39 … … 220 221 if (purpose == DraggingPurpose::ForFileUpload) 221 222 return containsFiles(); 223 224 if (purpose == DraggingPurpose::ForEditing && RuntimeEnabledFeatures::sharedFeatures().attachmentElementEnabled() && containsFiles()) 225 return true; 222 226 223 227 Vector<String> types; -
trunk/Source/WebCore/platform/mac/PasteboardMac.mm
r226277 r226396 351 351 Vector<String> paths; 352 352 strategy.getPathnamesForType(paths, legacyFilenamesPasteboardType(), m_pasteboardName); 353 if (m_changeCount != changeCount() || reader.readFile names(paths))353 if (m_changeCount != changeCount() || reader.readFilePaths(paths)) 354 354 return; 355 355 } … … 555 555 } 556 556 557 Vector<String> Pasteboard::readFile names()557 Vector<String> Pasteboard::readFilePaths() 558 558 { 559 559 // FIXME: Seems silly to convert paths to URLs and then back to paths. Does that do anything helpful? -
trunk/Source/WebKit/ChangeLog
r226395 r226396 1 2018-01-03 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 [Attachment Support] Create attachment elements when dropping files on iOS 4 https://bugs.webkit.org/show_bug.cgi?id=181192 5 <rdar://problem/36280945> 6 7 Reviewed by Tim Horton. 8 9 Make some minor adjustments for changes to the pasteboard in WebCore. See WebCore/ChangeLog for more detail. 10 Teaches WebPasteboardProxy et. al. to plumb PasteboardItemInfo from the UI process to the web process via the 11 new `InformationForItemAtIndex` codepath. 12 13 * UIProcess/Cocoa/WebPasteboardProxyCocoa.mm: 14 (WebKit::WebPasteboardProxy::informationForItemAtIndex): 15 (WebKit::WebPasteboardProxy::getFilenamesForDataInteraction): Deleted. 16 * UIProcess/WebPasteboardProxy.h: 17 * UIProcess/WebPasteboardProxy.messages.in: 18 * WebProcess/WebCoreSupport/WebPlatformStrategies.cpp: 19 (WebKit::WebPlatformStrategies::informationForItemAtIndex): 20 (WebKit::WebPlatformStrategies::getFilenamesForDataInteraction): Deleted. 21 * WebProcess/WebCoreSupport/WebPlatformStrategies.h: 22 1 23 2018-01-03 Ting-Wei Lan <lantw44@gmail.com> 2 24 -
trunk/Source/WebKit/UIProcess/Cocoa/WebPasteboardProxyCocoa.mm
r223195 r226396 30 30 #import "WebProcessProxy.h" 31 31 #import <WebCore/Color.h> 32 #import <WebCore/PasteboardItemInfo.h> 32 33 #import <WebCore/PlatformPasteboard.h> 33 34 #import <WebCore/SharedBuffer.h> … … 226 227 } 227 228 228 void WebPasteboardProxy:: getFilenamesForDataInteraction(const String& pasteboardName, Vector<String>& filenames)229 { 230 filenames = PlatformPasteboard(pasteboardName).filenamesForDataInteraction();229 void WebPasteboardProxy::informationForItemAtIndex(int index, const String& pasteboardName, PasteboardItemInfo& info) 230 { 231 info = PlatformPasteboard(pasteboardName).informationForItemAtIndex(index); 231 232 } 232 233 -
trunk/Source/WebKit/UIProcess/WebPasteboardProxy.h
r223195 r226396 36 36 struct PasteboardCustomData; 37 37 struct PasteboardImage; 38 struct PasteboardItemInfo; 38 39 struct PasteboardURL; 39 40 struct PasteboardWebContent; … … 78 79 void readBufferFromPasteboard(uint64_t index, const String& pasteboardType, const String& pasteboardName, SharedMemory::Handle&, uint64_t& size); 79 80 void getPasteboardItemsCount(const String& pasteboardName, uint64_t& itemsCount); 80 void getFilenamesForDataInteraction(const String& pasteboardName, Vector<String>& filenames);81 void informationForItemAtIndex(int index, const String& pasteboardName, WebCore::PasteboardItemInfo& filename); 81 82 void updateSupportedTypeIdentifiers(const Vector<String>& identifiers, const String& pasteboardName); 82 83 #endif -
trunk/Source/WebKit/UIProcess/WebPasteboardProxy.messages.in
r223195 r226396 31 31 ReadBufferFromPasteboard(uint64_t index, String pasteboardType, String pasteboardName) -> (WebKit::SharedMemory::Handle handle, uint64_t size) 32 32 GetPasteboardItemsCount(String pasteboardName) -> (uint64_t itemsCount) 33 GetFilenamesForDataInteraction(String pasteboardName) -> (Vector<String> filenames)33 InformationForItemAtIndex(uint64_t index, String pasteboardName) -> (struct WebCore::PasteboardItemInfo info) 34 34 UpdateSupportedTypeIdentifiers(Vector<String> identifiers, String pasteboardName) 35 35 GetPasteboardTypesByFidelityForItemAtIndex(uint64_t index, String pasteboardName) -> (Vector<String> types) -
trunk/Source/WebKit/WebProcess/WebCoreSupport/WebPlatformStrategies.cpp
r225934 r226396 56 56 #include <WebCore/Page.h> 57 57 #include <WebCore/PageGroup.h> 58 #include <WebCore/PasteboardItemInfo.h> 58 59 #include <WebCore/PlatformCookieJar.h> 59 60 #include <WebCore/PlatformPasteboard.h> … … 323 324 } 324 325 325 void WebPlatformStrategies::getFilenamesForDataInteraction(Vector<String>& filenames, const String& pasteboardName) 326 { 327 WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::GetFilenamesForDataInteraction(pasteboardName), Messages::WebPasteboardProxy::GetFilenamesForDataInteraction::Reply(filenames), 0); 326 PasteboardItemInfo WebPlatformStrategies::informationForItemAtIndex(int index, const String& pasteboardName) 327 { 328 PasteboardItemInfo info; 329 WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::InformationForItemAtIndex(index, pasteboardName), Messages::WebPasteboardProxy::InformationForItemAtIndex::Reply(info), 0); 330 return info; 328 331 } 329 332 -
trunk/Source/WebKit/WebProcess/WebCoreSupport/WebPlatformStrategies.h
r225934 r226396 66 66 RefPtr<WebCore::SharedBuffer> readBufferFromPasteboard(int index, const String& pasteboardType, const String& pasteboardName) override; 67 67 WebCore::URL readURLFromPasteboard(int index, const String& pasteboardType, const String& pasteboardName, String& title) override; 68 void getFilenamesForDataInteraction(Vector<String>& filenames, const String& pasteboardName) override;68 WebCore::PasteboardItemInfo informationForItemAtIndex(int index, const String& pasteboardName) override; 69 69 void updateSupportedTypeIdentifiers(const Vector<String>& identifiers, const String& pasteboardName) override; 70 70 void getTypesByFidelityForItemAtIndex(Vector<String>& types, uint64_t index, const String& pasteboardName) override; -
trunk/Source/WebKitLegacy/mac/ChangeLog
r226393 r226396 1 2018-01-03 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 [Attachment Support] Create attachment elements when dropping files on iOS 4 https://bugs.webkit.org/show_bug.cgi?id=181192 5 <rdar://problem/36280945> 6 7 Reviewed by Tim Horton. 8 9 Make some minor adjustments for changes to the pasteboard in WebCore. See WebCore/ChangeLog for more detail. 10 11 * WebCoreSupport/WebPlatformStrategies.h: 12 * WebCoreSupport/WebPlatformStrategies.mm: 13 (WebPlatformStrategies::informationForItemAtIndex): 14 (WebPlatformStrategies::getFilenamesForDataInteraction): Deleted. 15 1 16 2018-01-03 Wenson Hsieh <wenson_hsieh@apple.com> 2 17 -
trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebPlatformStrategies.h
r225934 r226396 67 67 RefPtr<WebCore::SharedBuffer> readBufferFromPasteboard(int index, const String& pasteboardType, const String& pasteboardName) override; 68 68 WebCore::URL readURLFromPasteboard(int index, const String& pasteboardType, const String& pasteboardName, String& title) override; 69 void getFilenamesForDataInteraction(Vector<String>& filenames, const String& pasteboardName) override;69 WebCore::PasteboardItemInfo informationForItemAtIndex(int index, const String& pasteboardName) override; 70 70 void updateSupportedTypeIdentifiers(const Vector<String>& identifiers, const String& pasteboardName) override; 71 71 void getTypesByFidelityForItemAtIndex(Vector<String>& types, uint64_t index, const String& pasteboardName) override; -
trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebPlatformStrategies.mm
r225934 r226396 33 33 #import <WebCore/MainFrame.h> 34 34 #import <WebCore/NetworkStorageSession.h> 35 #import <WebCore/PasteboardItemInfo.h> 35 36 #import <WebCore/PlatformCookieJar.h> 36 37 #import <WebCore/PlatformPasteboard.h> … … 240 241 } 241 242 242 void WebPlatformStrategies::getFilenamesForDataInteraction(Vector<String>& filenames, const String& pasteboardName)243 { 244 filenames = PlatformPasteboard(pasteboardName).filenamesForDataInteraction();243 WebCore::PasteboardItemInfo WebPlatformStrategies::informationForItemAtIndex(int index, const String& pasteboardName) 244 { 245 return PlatformPasteboard(pasteboardName).informationForItemAtIndex(index); 245 246 } 246 247 #endif // PLATFORM(IOS) -
trunk/Tools/ChangeLog
r226395 r226396 1 2018-01-03 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 [Attachment Support] Create attachment elements when dropping files on iOS 4 https://bugs.webkit.org/show_bug.cgi?id=181192 5 <rdar://problem/36280945> 6 7 Reviewed by Tim Horton. 8 9 Adds 3 new API tests to exercise different use cases of dropping content as attachment elements when the runtime 10 switch is enabled. See below for more details. 11 12 * TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm: 13 (-[NSItemProvider registerData:type:]): 14 (platformCopyPNG): 15 (TestWebKitAPI::TEST): 16 * TestWebKitAPI/Tests/ios/DataInteractionTests.mm: 17 18 Fix some currently failing iOS drag and drop tests. In this case, there's no reason RTFD should appear in the 19 source item provider when dragging rich text *without* attachments, so this should have been a check for just 20 kUTTypeRTF instead. 21 22 (TestWebKitAPI::TEST): 23 24 Tests a few cases of inserting attachment elements via drop: 25 1. We should distinguish between drops containing rich/plain text files from just dropping rich/plain text. 26 Instead of inserting the contents as inline web content, this should generate attachment elements. 27 2. Test the fallback mechanism for inserting attachment elements. If the preferred presentation style is not 28 explicitly set, but there's nothing WebKit would otherwise do with the dropped content, then we should fall 29 back to inserting the content as an attachment. 30 3. Test that if multiple attachments and inline item providers are present, WebKit will respect the order in 31 which they were inserted by the source (as opposed to, for instance, putting all of the attachments in front 32 or at the end). 33 34 * TestWebKitAPI/cocoa/TestWKWebView.h: 35 * TestWebKitAPI/cocoa/TestWKWebView.mm: 36 (-[TestWKWebView objectByEvaluatingJavaScript:]): 37 38 Add a helper method to return an object that represents the result of evaluating some given script, and rewrite 39 -stringByEvaluatingJavaScript to just turn around and call this. 40 41 (-[TestWKWebView stringByEvaluatingJavaScript:]): 42 1 43 2018-01-03 Ting-Wei Lan <lantw44@gmail.com> 2 44 -
trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm
r226342 r226396 322 322 #pragma mark - Platform testing helper functions 323 323 324 #if PLATFORM(IOS) 325 326 typedef void(^ItemProviderDataLoadHandler)(NSData *, NSError *); 327 328 @implementation NSItemProvider (AttachmentTesting) 329 330 - (void)registerData:(NSData *)data type:(NSString *)type 331 { 332 [self registerDataRepresentationForTypeIdentifier:type visibility:NSItemProviderRepresentationVisibilityAll loadHandler:[protectedData = retainPtr(data)] (ItemProviderDataLoadHandler completionHandler) -> NSProgress * { 333 completionHandler(protectedData.get(), nil); 334 return nil; 335 }]; 336 } 337 338 @end 339 340 #endif // PLATFORM(IOS) 341 324 342 void platformCopyRichTextWithMultipleAttachments() 325 343 { … … 364 382 } 365 383 366 typedef void(^ItemProviderDataLoadHandler)(NSData *, NSError *);367 368 384 void platformCopyPNG() 369 385 { … … 376 392 auto item = adoptNS([[UIItemProvider alloc] init]); 377 393 [item setPreferredPresentationStyle:UIPreferredPresentationStyleAttachment]; 378 [item registerDataRepresentationForTypeIdentifier:(NSString *)kUTTypePNG visibility:NSItemProviderRepresentationVisibilityAll loadHandler:[] (ItemProviderDataLoadHandler completionHandler) -> NSProgress * { 379 completionHandler(testImageData(), nil); 380 return nil; 381 }]; 394 [item registerData:testImageData() type:(NSString *)kUTTypePNG]; 382 395 pasteboard.itemProviders = @[ item.get() ]; 383 396 #endif … … 961 974 auto draggingSimulator = adoptNS([[DataInteractionSimulator alloc] initWithWebView:webView.get()]); 962 975 auto item = adoptNS([[NSItemProvider alloc] init]); 963 [item setPreferredPresentationStyle:UIPreferredPresentationStyleAttachment]; 964 [item registerDataRepresentationForTypeIdentifier:(NSString *)kUTTypePNG visibility:NSItemProviderRepresentationVisibilityAll loadHandler:[] (ItemProviderDataLoadHandler completionHandler) -> NSProgress * { 965 completionHandler(testImageData(), nil); 966 return nil; 967 }]; 976 [item registerData:testImageData() type:(NSString *)kUTTypePNG]; 968 977 [draggingSimulator setExternalItemProviders:@[ item.get() ]]; 969 978 [draggingSimulator runFrom:CGPointZero to:CGPointMake(50, 50)]; … … 1011 1020 } 1012 1021 1022 TEST(WKAttachmentTestsIOS, InsertDroppedRichAndPlainTextFilesAsAttachments) 1023 { 1024 // Here, both rich text and plain text are content types that WebKit already understands how to insert in editable 1025 // areas in the absence of attachment elements. However, due to the explicitly set attachment presentation style 1026 // on the item providers, we should instead treat them as dropped files and insert attachment elements. 1027 // This exercises the scenario of dragging rich and plain text files from Files to Mail. 1028 auto richTextItem = adoptNS([[NSItemProvider alloc] init]); 1029 auto richText = adoptNS([[NSAttributedString alloc] initWithString:@"Hello world" attributes:@{ NSFontAttributeName: [UIFont boldSystemFontOfSize:12] }]); 1030 [richTextItem setPreferredPresentationStyle:UIPreferredPresentationStyleAttachment]; 1031 [richTextItem registerObject:richText.get() visibility:NSItemProviderRepresentationVisibilityAll]; 1032 [richTextItem setSuggestedName:@"hello.rtf"]; 1033 1034 auto plainTextItem = adoptNS([[NSItemProvider alloc] init]); 1035 [plainTextItem setPreferredPresentationStyle:UIPreferredPresentationStyleAttachment]; 1036 [plainTextItem registerObject:@"Hello world" visibility:NSItemProviderRepresentationVisibilityAll]; 1037 [plainTextItem setSuggestedName:@"world.txt"]; 1038 1039 auto webView = webViewForTestingAttachments(); 1040 auto draggingSimulator = adoptNS([[DataInteractionSimulator alloc] initWithWebView:webView.get()]); 1041 [draggingSimulator setExternalItemProviders:@[ richTextItem.get(), plainTextItem.get() ]]; 1042 [draggingSimulator runFrom:CGPointZero to:CGPointMake(50, 50)]; 1043 1044 EXPECT_EQ(2U, [draggingSimulator insertedAttachments].count); 1045 EXPECT_EQ(0U, [draggingSimulator removedAttachments].count); 1046 1047 for (_WKAttachment *attachment in [draggingSimulator insertedAttachments]) { 1048 NSError *error = nil; 1049 EXPECT_GT([attachment synchronouslyRequestData:&error].length, 0U); 1050 EXPECT_TRUE(!error); 1051 if (error) 1052 NSLog(@"Error: %@", error); 1053 } 1054 1055 EXPECT_EQ(2, [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment').length"].intValue); 1056 EXPECT_WK_STREQ("hello.rtf", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[0].getAttribute('title')"]); 1057 EXPECT_WK_STREQ("text/rtf", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[0].getAttribute('type')"]); 1058 EXPECT_WK_STREQ("world.txt", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[1].getAttribute('title')"]); 1059 EXPECT_WK_STREQ("text/plain", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[1].getAttribute('type')"]); 1060 } 1061 1062 TEST(WKAttachmentTestsIOS, InsertDroppedZipArchiveAsAttachment) 1063 { 1064 // Since WebKit doesn't have any default DOM representation for ZIP archives, we should fall back to inserting 1065 // attachment elements. This exercises the flow of dragging a ZIP file from an app that doesn't specify a preferred 1066 // presentation style (e.g. Notes) into Mail. 1067 auto item = adoptNS([[NSItemProvider alloc] init]); 1068 NSData *data = testZIPData(); 1069 [item registerData:data type:(NSString *)kUTTypeZipArchive]; 1070 [item setSuggestedName:@"archive.zip"]; 1071 1072 auto webView = webViewForTestingAttachments(); 1073 auto draggingSimulator = adoptNS([[DataInteractionSimulator alloc] initWithWebView:webView.get()]); 1074 [draggingSimulator setExternalItemProviders:@[ item.get() ]]; 1075 [draggingSimulator runFrom:CGPointZero to:CGPointMake(50, 50)]; 1076 1077 EXPECT_EQ(1U, [draggingSimulator insertedAttachments].count); 1078 EXPECT_EQ(0U, [draggingSimulator removedAttachments].count); 1079 [[draggingSimulator insertedAttachments].firstObject expectRequestedDataToBe:data]; 1080 EXPECT_EQ(1, [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment').length"].intValue); 1081 EXPECT_WK_STREQ("archive.zip", [webView valueOfAttribute:@"title" forQuerySelector:@"attachment"]); 1082 EXPECT_WK_STREQ("application/zip", [webView valueOfAttribute:@"type" forQuerySelector:@"attachment"]); 1083 } 1084 1085 TEST(WKAttachmentTestsIOS, InsertDroppedItemProvidersInOrder) 1086 { 1087 // Tests that item providers are inserted in the order they are specified. In this case, the two inserted attachments 1088 // should be separated by a link. 1089 auto firstAttachmentItem = adoptNS([[NSItemProvider alloc] init]); 1090 [firstAttachmentItem setPreferredPresentationStyle:UIPreferredPresentationStyleAttachment]; 1091 [firstAttachmentItem registerObject:@"FIRST" visibility:NSItemProviderRepresentationVisibilityAll]; 1092 [firstAttachmentItem setSuggestedName:@"first.txt"]; 1093 1094 auto inlineTextItem = adoptNS([[NSItemProvider alloc] init]); 1095 auto appleURL = retainPtr([NSURL URLWithString:@"https://www.apple.com/"]); 1096 [inlineTextItem registerObject:appleURL.get() visibility:NSItemProviderRepresentationVisibilityAll]; 1097 1098 auto secondAttachmentItem = adoptNS([[NSItemProvider alloc] init]); 1099 [secondAttachmentItem registerData:testPDFData() type:(NSString *)kUTTypePDF]; 1100 [secondAttachmentItem setSuggestedName:@"second.pdf"]; 1101 1102 auto webView = webViewForTestingAttachments(); 1103 auto draggingSimulator = adoptNS([[DataInteractionSimulator alloc] initWithWebView:webView.get()]); 1104 [draggingSimulator setExternalItemProviders:@[ firstAttachmentItem.get(), inlineTextItem.get(), secondAttachmentItem.get() ]]; 1105 [draggingSimulator runFrom:CGPointZero to:CGPointMake(50, 50)]; 1106 1107 EXPECT_EQ(2U, [draggingSimulator insertedAttachments].count); 1108 EXPECT_EQ(0U, [draggingSimulator removedAttachments].count); 1109 1110 for (_WKAttachment *attachment in [draggingSimulator insertedAttachments]) { 1111 NSError *error = nil; 1112 EXPECT_GT([attachment synchronouslyRequestData:&error].length, 0U); 1113 EXPECT_TRUE(!error); 1114 if (error) 1115 NSLog(@"Error: %@", error); 1116 } 1117 1118 NSArray *observedElementTags = (NSArray *)[webView objectByEvaluatingJavaScript:@"Array.from(document.body.children).map(e => e.tagName)"]; 1119 NSArray *expectedElementTags = @[ @"ATTACHMENT", @"A", @"ATTACHMENT" ]; 1120 EXPECT_TRUE([observedElementTags isEqualToArray:expectedElementTags]); 1121 if (![observedElementTags isEqualToArray:expectedElementTags]) 1122 NSLog(@"Observed elements: %@ did not match expectations: %@", observedElementTags, expectedElementTags); 1123 1124 EXPECT_WK_STREQ("first.txt", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[0].getAttribute('title')"]); 1125 EXPECT_WK_STREQ("text/plain", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[0].getAttribute('type')"]); 1126 EXPECT_WK_STREQ([appleURL absoluteString], [webView valueOfAttribute:@"href" forQuerySelector:@"a"]); 1127 EXPECT_WK_STREQ("second.pdf", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[1].getAttribute('title')"]); 1128 EXPECT_WK_STREQ("application/pdf", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[1].getAttribute('type')"]); 1129 } 1130 1013 1131 #endif // PLATFORM(IOS) 1014 1132 -
trunk/Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm
r223440 r226396 345 345 EXPECT_TRUE([observedEventNames containsObject:DataInteractionPerformOperationEventName]); 346 346 checkSelectionRectsWithLogging(@[ makeCGRectValue(1, 201, 961, 227) ], [dataInteractionSimulator finalSelectionRects]); 347 checkTypeIdentifierPrecedesOtherTypeIdentifier(dataInteractionSimulator.get(), (NSString *)kUTTypeRTF D, (NSString *)kUTTypeUTF8PlainText);347 checkTypeIdentifierPrecedesOtherTypeIdentifier(dataInteractionSimulator.get(), (NSString *)kUTTypeRTF, (NSString *)kUTTypeUTF8PlainText); 348 348 } 349 349 … … 365 365 EXPECT_TRUE([observedEventNames containsObject:DataInteractionPerformOperationEventName]); 366 366 checkSelectionRectsWithLogging(@[ makeCGRectValue(6, 203, 990, 232) ], [dataInteractionSimulator finalSelectionRects]); 367 checkTypeIdentifierPrecedesOtherTypeIdentifier(dataInteractionSimulator.get(), (NSString *)kUTTypeRTF D, (NSString *)kUTTypeUTF8PlainText);367 checkTypeIdentifierPrecedesOtherTypeIdentifier(dataInteractionSimulator.get(), (NSString *)kUTTypeRTF, (NSString *)kUTTypeUTF8PlainText); 368 368 } 369 369 -
trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.h
r222654 r226396 46 46 - (void)synchronouslyLoadHTMLString:(NSString *)html; 47 47 - (void)synchronouslyLoadTestPageNamed:(NSString *)pageName; 48 - (id)objectByEvaluatingJavaScript:(NSString *)script; 48 49 - (NSString *)stringByEvaluatingJavaScript:(NSString *)script; 49 50 - (void)waitForMessage:(NSString *)message; -
trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm
r222654 r226396 239 239 } 240 240 241 - (NSString *)stringByEvaluatingJavaScript:(NSString *)script 242 { 243 __block bool isWaitingForJavaScript = false; 244 __block NSString *evalResult = nil; 245 [self _evaluateJavaScriptWithoutUserGesture:script completionHandler:^(id result, NSError *error) 246 { 247 evalResult = [[NSString alloc] initWithFormat:@"%@", result]; 241 - (id)objectByEvaluatingJavaScript:(NSString *)script 242 { 243 bool isWaitingForJavaScript = false; 244 RetainPtr<id> evalResult; 245 [self _evaluateJavaScriptWithoutUserGesture:script completionHandler:[&] (id result, NSError *error) { 246 evalResult = result; 248 247 isWaitingForJavaScript = true; 249 248 EXPECT_TRUE(!error); … … 251 250 NSLog(@"Encountered error: %@ while evaluating script: %@", error, script); 252 251 }]; 253 254 252 TestWebKitAPI::Util::run(&isWaitingForJavaScript); 255 return [evalResult autorelease]; 253 return evalResult.autorelease(); 254 } 255 256 - (NSString *)stringByEvaluatingJavaScript:(NSString *)script 257 { 258 return [NSString stringWithFormat:@"%@", [self objectByEvaluatingJavaScript:script]]; 256 259 } 257 260
Note:
See TracChangeset
for help on using the changeset viewer.