1 /* 2 * Copyright (C) 2005, 2006, 2007 Apple, Inc. All rights reserved. 3 * (C) 2007 Graham Dennis (graham.dennis (at) gmail.com) 4 * (C) 2007 Eric Seidel <eric (at) webkit.org> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 16 * its contributors may be used to endorse or promote products derived 17 * from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 // 32 // This file comes from WebKit: 33 // WebKit/Tools/DumpRenderTree/mac/DumpRenderTreePasteboard.m 34 // It is copied here since that location is the best for pulling into Chromium 35 // and has a few includes commented out. darin (at) chromium.org suggests in the 36 // future we see if there is a better place for it to live so it could be 37 // shared. 38 // 39 40 // #import "DumpRenderTreeMac.h" 41 #import "DumpRenderTreePasteboard.h" 42 43 // #import <WebKit/WebTypesInternal.h> 44 45 @interface LocalPasteboard : NSPasteboard 46 { 47 NSMutableArray *typesArray; 48 NSMutableSet *typesSet; 49 NSMutableDictionary *dataByType; 50 NSInteger changeCount; 51 } 52 @end 53 54 static NSMutableDictionary *localPasteboards; 55 56 @implementation DumpRenderTreePasteboard 57 58 // Return a local pasteboard so we don't disturb the real pasteboards when running tests. 59 + (NSPasteboard *)_pasteboardWithName:(NSString *)name 60 { 61 static int number = 0; 62 if (!name) 63 name = [NSString stringWithFormat:@"LocalPasteboard%d", ++number]; 64 if (!localPasteboards) 65 localPasteboards = [[NSMutableDictionary alloc] init]; 66 LocalPasteboard *pasteboard = [localPasteboards objectForKey:name]; 67 if (pasteboard) 68 return pasteboard; 69 pasteboard = [[LocalPasteboard alloc] init]; 70 [localPasteboards setObject:pasteboard forKey:name]; 71 [pasteboard release]; 72 return pasteboard; 73 } 74 75 + (void)releaseLocalPasteboards 76 { 77 [localPasteboards release]; 78 localPasteboards = nil; 79 } 80 81 // Convenience method for JS so that it doesn't have to try and create a NSArray on the objc side instead 82 // of the usual WebScriptObject that is passed around 83 - (NSInteger)declareType:(NSString *)type owner:(id)newOwner 84 { 85 return [self declareTypes:[NSArray arrayWithObject:type] owner:newOwner]; 86 } 87 88 @end 89 90 @implementation LocalPasteboard 91 92 + (id)alloc 93 { 94 return NSAllocateObject(self, 0, 0); 95 } 96 97 - (id)init 98 { 99 typesArray = [[NSMutableArray alloc] init]; 100 typesSet = [[NSMutableSet alloc] init]; 101 dataByType = [[NSMutableDictionary alloc] init]; 102 return self; 103 } 104 105 - (void)dealloc 106 { 107 [typesArray release]; 108 [typesSet release]; 109 [dataByType release]; 110 [super dealloc]; 111 } 112 113 - (NSString *)name 114 { 115 return nil; 116 } 117 118 - (void)releaseGlobally 119 { 120 } 121 122 - (NSInteger)declareTypes:(NSArray *)newTypes owner:(id)newOwner 123 { 124 [typesArray removeAllObjects]; 125 [typesSet removeAllObjects]; 126 [dataByType removeAllObjects]; 127 return [self addTypes:newTypes owner:newOwner]; 128 } 129 130 - (NSInteger)addTypes:(NSArray *)newTypes owner:(id)newOwner 131 { 132 unsigned count = [newTypes count]; 133 unsigned i; 134 for (i = 0; i < count; ++i) { 135 NSString *type = [newTypes objectAtIndex:i]; 136 NSString *setType = [typesSet member:type]; 137 if (!setType) { 138 setType = [type copy]; 139 [typesArray addObject:setType]; 140 [typesSet addObject:setType]; 141 [setType release]; 142 } 143 if (newOwner && [newOwner respondsToSelector:@selector(pasteboard:provideDataForType:)]) 144 [newOwner pasteboard:self provideDataForType:setType]; 145 } 146 return ++changeCount; 147 } 148 149 - (NSInteger)changeCount 150 { 151 return changeCount; 152 } 153 154 - (NSArray *)types 155 { 156 return typesArray; 157 } 158 159 - (NSString *)availableTypeFromArray:(NSArray *)types 160 { 161 unsigned count = [types count]; 162 unsigned i; 163 for (i = 0; i < count; ++i) { 164 NSString *type = [types objectAtIndex:i]; 165 NSString *setType = [typesSet member:type]; 166 if (setType) 167 return setType; 168 } 169 return nil; 170 } 171 172 - (BOOL)setData:(NSData *)data forType:(NSString *)dataType 173 { 174 if (data == nil) 175 data = [NSData data]; 176 if (![typesSet containsObject:dataType]) 177 return NO; 178 [dataByType setObject:data forKey:dataType]; 179 ++changeCount; 180 return YES; 181 } 182 183 - (NSData *)dataForType:(NSString *)dataType 184 { 185 return [dataByType objectForKey:dataType]; 186 } 187 188 - (BOOL)setPropertyList:(id)propertyList forType:(NSString *)dataType 189 { 190 CFDataRef data = NULL; 191 if (propertyList) 192 data = CFPropertyListCreateXMLData(NULL, propertyList); 193 BOOL result = [self setData:(NSData *)data forType:dataType]; 194 if (data) 195 CFRelease(data); 196 return result; 197 } 198 199 - (BOOL)setString:(NSString *)string forType:(NSString *)dataType 200 { 201 CFDataRef data = NULL; 202 if (string) { 203 if ([string length] == 0) 204 data = CFDataCreate(NULL, NULL, 0); 205 else 206 data = CFStringCreateExternalRepresentation(NULL, (CFStringRef)string, kCFStringEncodingUTF8, 0); 207 } 208 BOOL result = [self setData:(NSData *)data forType:dataType]; 209 if (data) 210 CFRelease(data); 211 return result; 212 } 213 214 @end 215