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