1/* 2 * Copyright (C) 2005, 2006, 2007 Apple, Inc. All rights reserved. 3 * (C) 2007 Graham Dennis (graham.dennis@gmail.com) 4 * (C) 2007 Eric Seidel <eric@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#import "config.h" 32#import "DumpRenderTreeMac.h" 33#import "DumpRenderTreePasteboard.h" 34 35#import <WebKit/WebTypesInternal.h> 36 37@interface LocalPasteboard : NSPasteboard 38{ 39 NSMutableArray *typesArray; 40 NSMutableSet *typesSet; 41 NSMutableDictionary *dataByType; 42 NSInteger changeCount; 43} 44@end 45 46static NSMutableDictionary *localPasteboards; 47 48@implementation DumpRenderTreePasteboard 49 50// Return a local pasteboard so we don't disturb the real pasteboards when running tests. 51+ (NSPasteboard *)_pasteboardWithName:(NSString *)name 52{ 53 static int number = 0; 54 if (!name) 55 name = [NSString stringWithFormat:@"LocalPasteboard%d", ++number]; 56 if (!localPasteboards) 57 localPasteboards = [[NSMutableDictionary alloc] init]; 58 LocalPasteboard *pasteboard = [localPasteboards objectForKey:name]; 59 if (pasteboard) 60 return pasteboard; 61 pasteboard = [[LocalPasteboard alloc] init]; 62 [localPasteboards setObject:pasteboard forKey:name]; 63 [pasteboard release]; 64 return pasteboard; 65} 66 67+ (void)releaseLocalPasteboards 68{ 69 [localPasteboards release]; 70 localPasteboards = nil; 71} 72 73// Convenience method for JS so that it doesn't have to try and create a NSArray on the objc side instead 74// of the usual WebScriptObject that is passed around 75- (NSInteger)declareType:(NSString *)type owner:(id)newOwner 76{ 77 return [self declareTypes:[NSArray arrayWithObject:type] owner:newOwner]; 78} 79 80@end 81 82@implementation LocalPasteboard 83 84+ (id)alloc 85{ 86 return NSAllocateObject(self, 0, 0); 87} 88 89- (id)init 90{ 91 typesArray = [[NSMutableArray alloc] init]; 92 typesSet = [[NSMutableSet alloc] init]; 93 dataByType = [[NSMutableDictionary alloc] init]; 94 return self; 95} 96 97- (void)dealloc 98{ 99 [typesArray release]; 100 [typesSet release]; 101 [dataByType release]; 102 [super dealloc]; 103} 104 105- (NSString *)name 106{ 107 return nil; 108} 109 110- (void)releaseGlobally 111{ 112} 113 114- (NSInteger)declareTypes:(NSArray *)newTypes owner:(id)newOwner 115{ 116 [typesArray removeAllObjects]; 117 [typesSet removeAllObjects]; 118 [dataByType removeAllObjects]; 119 return [self addTypes:newTypes owner:newOwner]; 120} 121 122- (NSInteger)addTypes:(NSArray *)newTypes owner:(id)newOwner 123{ 124 unsigned count = [newTypes count]; 125 unsigned i; 126 for (i = 0; i < count; ++i) { 127 NSString *type = [newTypes objectAtIndex:i]; 128 NSString *setType = [typesSet member:type]; 129 if (!setType) { 130 setType = [type copy]; 131 [typesArray addObject:setType]; 132 [typesSet addObject:setType]; 133 [setType release]; 134 } 135 if (newOwner && [newOwner respondsToSelector:@selector(pasteboard:provideDataForType:)]) 136 [newOwner pasteboard:self provideDataForType:setType]; 137 } 138 return ++changeCount; 139} 140 141- (NSInteger)changeCount 142{ 143 return changeCount; 144} 145 146- (NSArray *)types 147{ 148 return typesArray; 149} 150 151- (NSString *)availableTypeFromArray:(NSArray *)types 152{ 153 unsigned count = [types count]; 154 unsigned i; 155 for (i = 0; i < count; ++i) { 156 NSString *type = [types objectAtIndex:i]; 157 NSString *setType = [typesSet member:type]; 158 if (setType) 159 return setType; 160 } 161 return nil; 162} 163 164- (BOOL)setData:(NSData *)data forType:(NSString *)dataType 165{ 166 if (data == nil) 167 data = [NSData data]; 168 if (![typesSet containsObject:dataType]) 169 return NO; 170 [dataByType setObject:data forKey:dataType]; 171 ++changeCount; 172 return YES; 173} 174 175- (NSData *)dataForType:(NSString *)dataType 176{ 177 return [dataByType objectForKey:dataType]; 178} 179 180- (BOOL)setPropertyList:(id)propertyList forType:(NSString *)dataType 181{ 182 CFDataRef data = NULL; 183 if (propertyList) 184 data = CFPropertyListCreateXMLData(NULL, propertyList); 185 BOOL result = [self setData:(NSData *)data forType:dataType]; 186 if (data) 187 CFRelease(data); 188 return result; 189} 190 191- (BOOL)setString:(NSString *)string forType:(NSString *)dataType 192{ 193 CFDataRef data = NULL; 194 if (string) { 195 if ([string length] == 0) 196 data = CFDataCreate(NULL, NULL, 0); 197 else 198 data = CFStringCreateExternalRepresentation(NULL, (CFStringRef)string, kCFStringEncodingUTF8, 0); 199 } 200 BOOL result = [self setData:(NSData *)data forType:dataType]; 201 if (data) 202 CFRelease(data); 203 return result; 204} 205 206@end 207