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//
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@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
54static 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