Changeset 252450 in webkit
- Timestamp:
- Nov 13, 2019, 10:39:08 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 6 added
- 11 edited
-
LayoutTests/ChangeLog (modified) (1 diff)
-
LayoutTests/editing/async-clipboard/clipboard-change-data-while-writing-expected.txt (added)
-
LayoutTests/editing/async-clipboard/clipboard-change-data-while-writing.html (added)
-
LayoutTests/editing/async-clipboard/clipboard-write-basic-expected.txt (added)
-
LayoutTests/editing/async-clipboard/clipboard-write-basic.html (added)
-
LayoutTests/editing/async-clipboard/clipboard-write-items-twice-expected.txt (added)
-
LayoutTests/editing/async-clipboard/clipboard-write-items-twice.html (added)
-
LayoutTests/editing/async-clipboard/resources/async-clipboard-helpers.js (modified) (1 diff)
-
LayoutTests/platform/win/TestExpectations (modified) (1 diff)
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/Modules/async-clipboard/Clipboard.cpp (modified) (4 diffs)
-
Source/WebCore/Modules/async-clipboard/Clipboard.h (modified) (3 diffs)
-
Source/WebCore/platform/ios/PlatformPasteboardIOS.mm (modified) (1 diff)
-
Source/WebCore/platform/mac/PlatformPasteboardMac.mm (modified) (1 diff)
-
Tools/ChangeLog (modified) (1 diff)
-
Tools/DumpRenderTree/mac/DumpRenderTreePasteboard.mm (modified) (5 diffs)
-
Tools/WebKitTestRunner/mac/WebKitTestRunnerPasteboard.mm (modified) (12 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r252444 r252450 1 2019-11-13 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 [Clipboard API] Add support for Clipboard.write() 4 https://bugs.webkit.org/show_bug.cgi?id=204078 5 <rdar://problem/57087756> 6 7 Reviewed by Ryosuke Niwa. 8 9 Adds several new layout tests to exercise the write method on Clipboard. 10 11 * editing/async-clipboard/clipboard-change-data-while-writing-expected.txt: Added. 12 * editing/async-clipboard/clipboard-change-data-while-writing.html: Added. 13 14 Verify that if the platform pasteboard contents change while the page attempts to write to the clipboard, we 15 will reject the promise for writing. 16 17 * editing/async-clipboard/clipboard-write-basic-expected.txt: Added. 18 * editing/async-clipboard/clipboard-write-basic.html: Added. 19 20 Verify that writing multiple ClipboardItems to the clipboard using write() works. Among these items, one of them 21 contains no types, and another only contains types that resolve to empty strings. The page should be able to 22 read all four items back using Clipboard.read(). 23 24 * editing/async-clipboard/clipboard-write-items-twice-expected.txt: Added. 25 * editing/async-clipboard/clipboard-write-items-twice.html: Added. 26 27 Verify that attempting to write a clipboard item that resolves on a long delay, and then attempting to write 28 another item that resolves on a short delay before the previous clipboard item has finished writing does not 29 cause the latter call to Clipboard.write() to fail. Additionally, the clipboard should contain the contents of 30 the second set of clipboard items, rather than the first. 31 32 * editing/async-clipboard/resources/async-clipboard-helpers.js: 33 (async.checkClipboardItemString): 34 35 Add a helper method to read a string for the given type, out of the given clipboard item, and compare it against 36 an expected result. 37 1 38 2019-11-13 Said Abou-Hallawa <sabouhallawa@apple.com> 2 39 -
trunk/LayoutTests/editing/async-clipboard/resources/async-clipboard-helpers.js
r251377 r252450 85 85 }); 86 86 } 87 88 async function checkClipboardItemString(item, type, expectedString) 89 { 90 const observedString = await loadText(await item.getType(type)); 91 if (observedString === expectedString) 92 testPassed(`getType("${type}") resolved to "${expectedString}"`); 93 else 94 testFailed(`getType("${type}") resolved to "${observedString}; expected "${expectedString}"`); 95 } -
trunk/LayoutTests/platform/win/TestExpectations
r252441 r252450 1191 1191 webkit.org/b/203100 editing/async-clipboard/clipboard-item-get-type-basic.html [ Skip ] 1192 1192 webkit.org/b/203100 editing/async-clipboard/clipboard-get-type-with-old-items.html [ Skip ] 1193 webkit.org/b/203100 editing/async-clipboard/clipboard-change-data-while-writing.html [ Skip ] 1194 webkit.org/b/203100 editing/async-clipboard/clipboard-write-basic.html [ Skip ] 1195 webkit.org/b/203100 editing/async-clipboard/clipboard-write-items-twice.html [ Skip ] 1193 1196 1194 1197 webkit.org/b/140783 [ Release ] editing/pasteboard/copy-standalone-image.html [ Failure ImageOnlyFailure ] -
trunk/Source/WebCore/ChangeLog
r252444 r252450 1 2019-11-13 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 [Clipboard API] Add support for Clipboard.write() 4 https://bugs.webkit.org/show_bug.cgi?id=204078 5 <rdar://problem/57087756> 6 7 Reviewed by Ryosuke Niwa. 8 9 This patch adds support for the write() method on Clipboard, forgoing sanitization for now (this will be added 10 in the next patch). See below for more details. 11 12 Tests: editing/async-clipboard/clipboard-change-data-while-writing.html 13 editing/async-clipboard/clipboard-write-basic.html 14 editing/async-clipboard/clipboard-write-items-twice.html 15 16 * Modules/async-clipboard/Clipboard.cpp: 17 (WebCore::Clipboard::~Clipboard): 18 (WebCore::shouldProceedWithClipboardWrite): 19 (WebCore::Clipboard::write): 20 21 Implement this method by creating a new ItemWriter and loading data from all the ClipboardItems that are being 22 written. If the previous writer is still in progress, make sure that we invalidate it first (rejecting the 23 promise) before proceeding. 24 25 (WebCore::Clipboard::didResolveOrReject): 26 (WebCore::Clipboard::ItemWriter::ItemWriter): 27 (WebCore::Clipboard::ItemWriter::write): 28 (WebCore::Clipboard::ItemWriter::invalidate): 29 (WebCore::Clipboard::ItemWriter::setData): 30 (WebCore::Clipboard::ItemWriter::didSetAllData): 31 (WebCore::Clipboard::ItemWriter::reject): 32 33 Introduce a private helper class to collect clipboard data for writing from a list of ClipboardItems, and 34 resolve or reject the given promise when finished. 35 36 * Modules/async-clipboard/Clipboard.h: 37 * platform/ios/PlatformPasteboardIOS.mm: 38 (WebCore::createItemProviderRegistrationList): 39 40 Fix a stray bug where the empty string could not be read back as plain text or URLs from the platform pasteboard 41 on iOS. This is exercised by the new layout test clipboard-write-basic.html. 42 43 * platform/mac/PlatformPasteboardMac.mm: 44 (WebCore::PlatformPasteboard::write): 45 46 Address another issue where we would sometimes try and declare the empty string as a pasteboard type when 47 writing to the platform pasteboard. While benign in a real NSPasteboard, there's no reason to include it in this 48 list of declared pasteboard types. 49 1 50 2019-11-13 Said Abou-Hallawa <sabouhallawa@apple.com> 2 51 -
trunk/Source/WebCore/Modules/async-clipboard/Clipboard.cpp
r251436 r252450 34 34 #include "Navigator.h" 35 35 #include "Pasteboard.h" 36 #include "Settings.h" 36 37 #include "SharedBuffer.h" 38 #include "UserGestureIndicator.h" 37 39 #include "WebContentReader.h" 40 #include <wtf/CompletionHandler.h> 38 41 #include <wtf/IsoMallocInlines.h> 39 42 … … 52 55 } 53 56 54 Clipboard::~Clipboard() = default; 57 Clipboard::~Clipboard() 58 { 59 if (auto writer = WTFMove(m_activeItemWriter)) 60 writer->invalidate(); 61 } 55 62 56 63 Navigator* Clipboard::navigator() … … 180 187 } 181 188 189 static bool shouldProceedWithClipboardWrite(const Frame& frame) 190 { 191 auto& settings = frame.settings(); 192 if (settings.javaScriptCanAccessClipboard()) 193 return true; 194 195 switch (settings.clipboardAccessPolicy()) { 196 case ClipboardAccessPolicy::Allow: 197 return true; 198 case ClipboardAccessPolicy::RequiresUserGesture: 199 return UserGestureIndicator::processingUserGesture(); 200 case ClipboardAccessPolicy::Deny: 201 return false; 202 } 203 204 ASSERT_NOT_REACHED(); 205 return false; 206 } 207 182 208 void Clipboard::write(const Vector<RefPtr<ClipboardItem>>& items, Ref<DeferredPromise>&& promise) 183 209 { 184 UNUSED_PARAM(items); 185 promise->reject(NotSupportedError); 210 auto frame = makeRefPtr(this->frame()); 211 if (!frame || !shouldProceedWithClipboardWrite(*frame)) { 212 promise->reject(NotAllowedError); 213 return; 214 } 215 216 if (auto existingWriter = std::exchange(m_activeItemWriter, ItemWriter::create(*this, WTFMove(promise)))) 217 existingWriter->invalidate(); 218 219 m_activeItemWriter->write(items); 220 } 221 222 void Clipboard::didResolveOrReject(Clipboard::ItemWriter& writer) 223 { 224 if (m_activeItemWriter == &writer) 225 m_activeItemWriter = nullptr; 186 226 } 187 227 … … 198 238 } 199 239 200 } 240 Clipboard::ItemWriter::ItemWriter(Clipboard& clipboard, Ref<DeferredPromise>&& promise) 241 : m_clipboard(makeWeakPtr(clipboard)) 242 , m_promise(WTFMove(promise)) 243 , m_pasteboard(Pasteboard::createForCopyAndPaste()) 244 { 245 } 246 247 Clipboard::ItemWriter::~ItemWriter() = default; 248 249 void Clipboard::ItemWriter::write(const Vector<RefPtr<ClipboardItem>>& items) 250 { 251 ASSERT(m_promise); 252 ASSERT(m_clipboard); 253 #if PLATFORM(COCOA) 254 m_changeCountAtStart = m_pasteboard->changeCount(); 255 #endif 256 m_dataToWrite.fill(WTF::nullopt, items.size()); 257 m_pendingItemCount = items.size(); 258 for (size_t index = 0; index < items.size(); ++index) { 259 items[index]->collectDataForWriting(*m_clipboard, [this, protectedThis = makeRef(*this), index] (auto data) { 260 protectedThis->setData(WTFMove(data), index); 261 if (!--m_pendingItemCount) 262 didSetAllData(); 263 }); 264 } 265 if (items.isEmpty()) 266 didSetAllData(); 267 } 268 269 void Clipboard::ItemWriter::invalidate() 270 { 271 if (m_promise) 272 reject(); 273 } 274 275 void Clipboard::ItemWriter::setData(Optional<PasteboardCustomData>&& data, size_t index) 276 { 277 if (index >= m_dataToWrite.size()) { 278 ASSERT_NOT_REACHED(); 279 return; 280 } 281 282 m_dataToWrite[index] = WTFMove(data); 283 } 284 285 void Clipboard::ItemWriter::didSetAllData() 286 { 287 if (!m_promise) 288 return; 289 290 #if PLATFORM(COCOA) 291 auto newChangeCount = m_pasteboard->changeCount(); 292 if (m_changeCountAtStart != newChangeCount) { 293 // FIXME: Instead of checking the changeCount here, send it over to the client (e.g. the UI process 294 // in WebKit2) and perform it there. 295 reject(); 296 return; 297 } 298 #endif // PLATFORM(COCOA) 299 auto dataToWrite = std::exchange(m_dataToWrite, { }); 300 Vector<PasteboardCustomData> customData; 301 customData.reserveInitialCapacity(dataToWrite.size()); 302 for (auto data : dataToWrite) { 303 if (!data) { 304 reject(); 305 return; 306 } 307 customData.append(*data); 308 } 309 310 m_pasteboard->writeCustomData(WTFMove(customData)); 311 m_promise->resolve(); 312 m_promise = nullptr; 313 314 if (auto clipboard = std::exchange(m_clipboard, nullptr)) 315 clipboard->didResolveOrReject(*this); 316 } 317 318 void Clipboard::ItemWriter::reject() 319 { 320 if (auto promise = std::exchange(m_promise, nullptr)) 321 promise->reject(NotAllowedError); 322 323 if (auto clipboard = std::exchange(m_clipboard, nullptr)) 324 clipboard->didResolveOrReject(*this); 325 } 326 327 } -
trunk/Source/WebCore/Modules/async-clipboard/Clipboard.h
r251421 r252450 28 28 #include "EventTarget.h" 29 29 #include <wtf/IsoMalloc.h> 30 #include <wtf/Optional.h> 30 31 #include <wtf/Vector.h> 31 32 #include <wtf/WeakPtr.h> … … 38 39 class Navigator; 39 40 class Pasteboard; 41 class PasteboardCustomData; 40 42 41 43 class Clipboard final : public RefCounted<Clipboard>, public EventTargetWithInlineData, public CanMakeWeakPtr<Clipboard> { … … 76 78 Pasteboard& activePasteboard(); 77 79 80 class ItemWriter : public RefCounted<ItemWriter> { 81 public: 82 static Ref<ItemWriter> create(Clipboard& clipboard, Ref<DeferredPromise>&& promise) 83 { 84 return adoptRef(*new ItemWriter(clipboard, WTFMove(promise))); 85 } 86 87 ~ItemWriter(); 88 89 void write(const Vector<RefPtr<ClipboardItem>>&); 90 void invalidate(); 91 92 private: 93 ItemWriter(Clipboard&, Ref<DeferredPromise>&&); 94 95 void setData(Optional<PasteboardCustomData>&&, size_t index); 96 void didSetAllData(); 97 void reject(); 98 99 WeakPtr<Clipboard> m_clipboard; 100 Vector<Optional<PasteboardCustomData>> m_dataToWrite; 101 RefPtr<DeferredPromise> m_promise; 102 unsigned m_pendingItemCount; 103 std::unique_ptr<Pasteboard> m_pasteboard; 104 #if PLATFORM(COCOA) 105 int64_t m_changeCountAtStart { 0 }; 106 #endif 107 }; 108 109 void didResolveOrReject(ItemWriter&); 110 78 111 Optional<Session> m_activeSession; 79 112 WeakPtr<Navigator> m_navigator; 113 Vector<Optional<PasteboardCustomData>> m_dataToWrite; 114 RefPtr<ItemWriter> m_activeItemWriter; 80 115 }; 81 116 -
trunk/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm
r251421 r252450 600 600 601 601 data.forEachPlatformString([&] (auto& type, auto& value) { 602 if (!value) 603 return; 604 602 605 NSString *stringValue = value; 603 if (!stringValue.length)604 return;605 606 606 auto cocoaType = PlatformPasteboard::platformPasteboardTypeForSafeTypeForDOMToReadAndWrite(type).createCFString(); 607 607 if (UTTypeConformsTo(cocoaType.get(), kUTTypeURL)) -
trunk/Source/WebCore/platform/mac/PlatformPasteboardMac.mm
r251421 r252450 227 227 NSMutableArray *types = [NSMutableArray array]; 228 228 data.forEachType([&] (auto& type) { 229 [types addObject:platformPasteboardTypeForSafeTypeForDOMToReadAndWrite(type)]; 229 NSString *platformType = platformPasteboardTypeForSafeTypeForDOMToReadAndWrite(type); 230 if (platformType.length) 231 [types addObject:platformType]; 230 232 }); 231 233 -
trunk/Tools/ChangeLog
r252449 r252450 1 2019-11-13 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 [Clipboard API] Add support for Clipboard.write() 4 https://bugs.webkit.org/show_bug.cgi?id=204078 5 <rdar://problem/57087756> 6 7 Reviewed by Ryosuke Niwa. 8 9 Make the LocalPasteboard in WebKitTestRunner compatible with calls to -writeObjects: with a list of pasteboard 10 items. Currently, attempts to -writeObjects: result in a crash, since NSPasteboard code will attempt to 11 communicate with pasted and fail. We fix this by implementing -writeObjects: and storing the array of 12 NSPasteboardItems in LocalPasteboard, the same way we do in DumpRenderTree's LocalPasteboard implementation. 13 14 * DumpRenderTree/mac/DumpRenderTreePasteboard.mm: 15 (-[LocalPasteboard declareTypes:owner:]): 16 (-[LocalPasteboard _clearContentsWithoutUpdatingChangeCount]): 17 18 Factor out logic to clear the pasteboard's content into a separate helper, and clear out the list of saved 19 pasteboard items here as well. 20 21 (-[LocalPasteboard clearContents]): 22 23 Implement -clearContents in DumpRenderTree's LocalPasteboard, so that we can test Clipboard.write() in WebKit1. 24 25 (-[LocalPasteboard writeObjects:]): 26 27 Also make it so that we save any NSPasteboardItems we write to the local pasteboard, so that we can return them 28 later in -pasteboardItems. 29 30 (-[LocalPasteboard pasteboardItems]): 31 * WebKitTestRunner/mac/WebKitTestRunnerPasteboard.mm: 32 (-[LocalPasteboard initWithName:]): 33 34 Clean up this code a bit by replacing manual reference counting for `typesArray` and its neighboring data 35 structures with `RetainPtr`. Additionally, underscore-prefix the instance variables on LocalPasteboard to match 36 most of the other Objective-C objects in WebKit. 37 38 (-[LocalPasteboard name]): 39 (-[LocalPasteboard _clearContentsWithoutUpdatingChangeCount]): 40 41 Clear out the NSPasteboardItem list here too. 42 43 (-[LocalPasteboard clearContents]): 44 (-[LocalPasteboard declareTypes:owner:]): 45 (-[LocalPasteboard addTypes:owner:]): 46 (-[LocalPasteboard _addTypesWithoutUpdatingChangeCount:owner:]): 47 (-[LocalPasteboard changeCount]): 48 (-[LocalPasteboard types]): 49 (-[LocalPasteboard availableTypeFromArray:]): 50 (-[LocalPasteboard setData:forType:]): 51 (-[LocalPasteboard dataForType:]): 52 (-[LocalPasteboard pasteboardItems]): 53 (-[LocalPasteboard writeObjects:]): 54 55 Implement this by porting over the implementation that currently exists in DumpRenderTree. Like in 56 DumpRenderTree, we want to also save the NSPasteboardItem array we're given here, so that we can return it in 57 -pasteboardItems. 58 59 (-[LocalPasteboard dealloc]): Deleted. 60 1 61 2019-11-13 Megan Gardner <megan_gardner@apple.com> 2 62 -
trunk/Tools/DumpRenderTree/mac/DumpRenderTreePasteboard.mm
r251377 r252450 46 46 RetainPtr<id> _owner; 47 47 RetainPtr<NSString> _pasteboardName; 48 RetainPtr<NSMutableArray<NSPasteboardItem *>> _writtenPasteboardItems; 48 49 NSInteger _changeCount; 49 50 … … 121 122 - (NSInteger)declareTypes:(NSArray *)newTypes owner:(id)newOwner 122 123 { 123 _types.clear(); 124 _data.clear(); 124 [self _clearContentsWithoutUpdatingChangeCount]; 125 125 126 126 [self _addTypesWithoutUpdatingChangeCount:newTypes owner:newOwner]; … … 141 141 142 142 return adoptCF(UTTypeCreatePreferredIdentifierForTag(kUTTagClassNSPboardType, (__bridge CFStringRef)type, nullptr)); 143 } 144 145 - (void)_clearContentsWithoutUpdatingChangeCount 146 { 147 _writtenPasteboardItems = nil; 148 _types.clear(); 149 _data.clear(); 150 } 151 152 - (NSInteger)clearContents 153 { 154 [self _clearContentsWithoutUpdatingChangeCount]; 155 return ++_changeCount; 143 156 } 144 157 … … 227 240 - (BOOL)writeObjects:(NSArray<id <NSPasteboardWriting>> *)objects 228 241 { 242 _writtenPasteboardItems = adoptNS([[NSMutableArray<NSPasteboardItem *> alloc] initWithCapacity:objects.count]); 229 243 for (id <NSPasteboardWriting> object in objects) { 244 ASSERT([object isKindOfClass:NSPasteboardItem.class]); 245 [_writtenPasteboardItems addObject:(NSPasteboardItem *)object]; 230 246 for (NSString *type in [object writableTypesForPasteboard:self]) { 231 ASSERT(UTTypeIsDeclared((__bridge CFStringRef)type) || UTTypeIsDynamic((__bridge CFStringRef)type));232 233 247 [self addTypes:@[ type ] owner:self]; 234 248 … … 246 260 - (NSArray<NSPasteboardItem *> *)pasteboardItems 247 261 { 262 if (_writtenPasteboardItems) 263 return _writtenPasteboardItems.get(); 264 248 265 auto item = adoptNS([[NSPasteboardItem alloc] init]); 249 266 for (const auto& typeAndData : _data) { -
trunk/Tools/WebKitTestRunner/mac/WebKitTestRunnerPasteboard.mm
r251377 r252450 35 35 @interface LocalPasteboard : NSPasteboard 36 36 { 37 NSMutableArray *typesArray; 38 NSMutableSet *typesSet; 39 NSMutableDictionary *dataByType; 40 NSInteger changeCount; 41 NSString *pasteboardName; 37 RetainPtr<NSMutableArray> _typesArray; 38 RetainPtr<NSMutableSet> _typesSet; 39 RetainPtr<NSMutableArray<NSPasteboardItem *>> _writtenPasteboardItems; 40 RetainPtr<NSMutableDictionary> _dataByType; 41 NSInteger _changeCount; 42 RetainPtr<NSString> _pasteboardName; 42 43 } 43 44 … … 100 101 if (!self) 101 102 return nil; 102 typesArray = [[NSMutableArray alloc] init];103 typesSet = [[NSMutableSet alloc] init];104 dataByType = [[NSMutableDictionary alloc] init];105 pasteboardName = [name copy];103 _typesArray = adoptNS([[NSMutableArray alloc] init]); 104 _typesSet = adoptNS([[NSMutableSet alloc] init]); 105 _dataByType = adoptNS([[NSMutableDictionary alloc] init]); 106 _pasteboardName = adoptNS([name copy]); 106 107 return self; 107 108 } 108 109 109 - (void)dealloc110 {111 [typesArray release];112 [typesSet release];113 [dataByType release];114 [pasteboardName release];115 [super dealloc];116 }117 118 110 - (NSString *)name 119 111 { 120 return pasteboardName;112 return _pasteboardName.get(); 121 113 } 122 114 … … 127 119 - (void)_clearContentsWithoutUpdatingChangeCount 128 120 { 129 [typesArray removeAllObjects]; 130 [typesSet removeAllObjects]; 131 [dataByType removeAllObjects]; 121 _writtenPasteboardItems = nil; 122 [_typesArray removeAllObjects]; 123 [_typesSet removeAllObjects]; 124 [_dataByType removeAllObjects]; 132 125 } 133 126 … … 135 128 { 136 129 [self _clearContentsWithoutUpdatingChangeCount]; 137 return ++ changeCount;130 return ++_changeCount; 138 131 } 139 132 … … 142 135 [self _clearContentsWithoutUpdatingChangeCount]; 143 136 [self _addTypesWithoutUpdatingChangeCount:newTypes owner:newOwner]; 144 return ++ changeCount;137 return ++_changeCount; 145 138 } 146 139 … … 150 143 // FIXME: Ideally, we would keep track of the current owner and only bump the change 151 144 // count if the new owner is different. 152 return ++ changeCount;145 return ++_changeCount; 153 146 } 154 147 … … 159 152 for (i = 0; i < count; ++i) { 160 153 NSString *type = [newTypes objectAtIndex:i]; 161 NSString *setType = [ typesSet member:type];154 NSString *setType = [_typesSet member:type]; 162 155 if (!setType) { 163 156 setType = [type copy]; 164 [ typesArray addObject:setType];165 [ typesSet addObject:setType];157 [_typesArray addObject:setType]; 158 [_typesSet addObject:setType]; 166 159 [setType release]; 167 160 } … … 173 166 - (NSInteger)changeCount 174 167 { 175 return changeCount;168 return _changeCount; 176 169 } 177 170 178 171 - (NSArray *)types 179 172 { 180 return typesArray;173 return _typesArray.get(); 181 174 } 182 175 … … 184 177 { 185 178 for (NSString *type in types) { 186 if (NSString *setType = [ typesSet member:type])179 if (NSString *setType = [_typesSet member:type]) 187 180 return setType; 188 181 } … … 192 185 - (BOOL)setData:(NSData *)data forType:(NSString *)dataType 193 186 { 194 if (![ typesSet containsObject:dataType])187 if (![_typesSet containsObject:dataType]) 195 188 return NO; 196 189 if (!data) 197 190 data = [NSData data]; 198 [ dataByType setObject:data forKey:dataType];199 ++ changeCount;191 [_dataByType setObject:data forKey:dataType]; 192 ++_changeCount; 200 193 return YES; 201 194 } … … 203 196 - (NSData *)dataForType:(NSString *)dataType 204 197 { 205 return [ dataByType objectForKey:dataType];198 return [_dataByType objectForKey:dataType]; 206 199 } 207 200 … … 221 214 - (NSArray<NSPasteboardItem *> *)pasteboardItems 222 215 { 216 if (_writtenPasteboardItems) 217 return _writtenPasteboardItems.get(); 218 223 219 auto item = adoptNS([[NSPasteboardItem alloc] init]); 224 for (NSString *type in dataByType) 225 [item setData:dataByType[type] forType:[NSPasteboard _modernPasteboardType:type]]; 220 for (NSString *type in _typesArray.get()) { 221 NSPasteboardType modernPasteboardType = [NSPasteboard _modernPasteboardType:type]; 222 if (NSData *dataForType = [_dataByType objectForKey:type] ?: [_dataByType objectForKey:modernPasteboardType]) 223 [item setData:dataForType forType:modernPasteboardType]; 224 } 226 225 return @[ item.get() ]; 227 226 } 228 227 228 - (BOOL)writeObjects:(NSArray<id <NSPasteboardWriting>> *)objects 229 { 230 _writtenPasteboardItems = adoptNS([[NSMutableArray<NSPasteboardItem *> alloc] initWithCapacity:objects.count]); 231 for (id <NSPasteboardWriting> object in objects) { 232 ASSERT([object isKindOfClass:NSPasteboardItem.class]); 233 [_writtenPasteboardItems addObject:(NSPasteboardItem *)object]; 234 NSArray<NSPasteboardType> *writableTypes = [object writableTypesForPasteboard:self]; 235 for (NSString *type in writableTypes) { 236 [self addTypes:@[type] owner:self]; 237 238 id propertyList = [object pasteboardPropertyListForType:type]; 239 if ([propertyList isKindOfClass:NSData.class]) 240 [self setData:propertyList forType:type]; 241 else 242 ASSERT_NOT_REACHED(); 243 } 244 } 245 246 return YES; 247 } 248 229 249 @end
Note:
See TracChangeset
for help on using the changeset viewer.