[Cocoa] More tweaks and refactoring to prepare for ARC
[WebKit.git] / Tools / WebKitTestRunner / mac / WebKitTestRunnerPasteboard.mm
1 /*
2  * Copyright (C) 2005-2018 Apple, Inc.  All rights reserved.
3  * Copyright (C) 2007 Graham Dennis (graham.dennis@gmail.com)
4  * Copyright (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  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
19  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
25  * THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include "config.h"
29 #include "WebKitTestRunnerPasteboard.h"
30
31 #include <objc/runtime.h>
32
33 @interface LocalPasteboard : NSPasteboard
34 {
35     NSMutableArray *typesArray;
36     NSMutableSet *typesSet;
37     NSMutableDictionary *dataByType;
38     NSInteger changeCount;
39     NSString *pasteboardName;
40 }
41
42 -(id)initWithName:(NSString *)name;
43 @end
44
45 static NSMutableDictionary *localPasteboards;
46
47 @implementation WebKitTestRunnerPasteboard
48
49 // Return a local pasteboard so we don't disturb the real pasteboards when running tests.
50 + (NSPasteboard *)_pasteboardWithName:(NSString *)name
51 {
52     static int number = 0;
53     if (!name)
54         name = [NSString stringWithFormat:@"LocalPasteboard%d", ++number];
55     if (!localPasteboards)
56         localPasteboards = [[NSMutableDictionary alloc] init];
57     LocalPasteboard *pasteboard = [localPasteboards objectForKey:name];
58     if (pasteboard)
59         return pasteboard;
60     pasteboard = [[LocalPasteboard alloc] initWithName:name];
61     [localPasteboards setObject:pasteboard forKey:name];
62     [pasteboard release];
63     return pasteboard;
64 }
65
66 // This method crashes when called on LocalPasteboard.
67 // This happens during dragging, so overriding it may become unnecessary once we use mock dragging, like DumpRenderTree does.
68 - (void)_updateTypeCacheIfNeeded
69 {
70 }
71
72 + (void)releaseLocalPasteboards
73 {
74     [localPasteboards release];
75     localPasteboards = nil;
76 }
77
78 // Convenience method for JS so that it doesn't have to try and create a NSArray on the objc side instead
79 // of the usual WebScriptObject that is passed around
80 - (NSInteger)declareType:(NSString *)type owner:(id)newOwner
81 {
82     return [self declareTypes:[NSArray arrayWithObject:type] owner:newOwner];
83 }
84
85 @end
86
87 @implementation LocalPasteboard
88
89 + (id)alloc
90 {
91     // Need to skip over [NSPasteboard alloc], which won't allocate a new object.
92     return class_createInstance(self, 0);
93 }
94
95 - (id)initWithName:(NSString *)name
96 {
97     self = [super init];
98     if (!self)
99         return nil;
100     typesArray = [[NSMutableArray alloc] init];
101     typesSet = [[NSMutableSet alloc] init];
102     dataByType = [[NSMutableDictionary alloc] init];
103     pasteboardName = [name copy];
104     return self;
105 }
106
107 - (void)dealloc
108 {
109     [typesArray release];
110     [typesSet release];
111     [dataByType release];
112     [pasteboardName release];
113     [super dealloc];
114 }
115
116 - (NSString *)name
117 {
118     return pasteboardName;
119 }
120
121 - (void)releaseGlobally
122 {
123 }
124
125 - (NSInteger)declareTypes:(NSArray *)newTypes owner:(id)newOwner
126 {
127     [typesArray removeAllObjects];
128     [typesSet removeAllObjects];
129     [dataByType removeAllObjects];
130     return [self addTypes:newTypes owner:newOwner];
131 }
132
133 - (NSInteger)addTypes:(NSArray *)newTypes owner:(id)newOwner
134 {
135     unsigned count = [newTypes count];
136     unsigned i;
137     for (i = 0; i < count; ++i) {
138         NSString *type = [newTypes objectAtIndex:i];
139         NSString *setType = [typesSet member:type];
140         if (!setType) {
141             setType = [type copy];
142             [typesArray addObject:setType];
143             [typesSet addObject:setType];
144             [setType release];
145         }
146         if (newOwner && [newOwner respondsToSelector:@selector(pasteboard:provideDataForType:)])
147             [newOwner pasteboard:self provideDataForType:setType];
148     }
149     return ++changeCount;
150 }
151
152 - (NSInteger)changeCount
153 {
154     return changeCount;
155 }
156
157 - (NSArray *)types
158 {
159     return typesArray;
160 }
161
162 - (NSString *)availableTypeFromArray:(NSArray *)types
163 {
164     for (NSString *type in types) {
165         if (NSString *setType = [typesSet member:type])
166             return setType;
167     }
168     return nil;
169 }
170
171 - (BOOL)setData:(NSData *)data forType:(NSString *)dataType
172 {
173     if (![typesSet containsObject:dataType])
174         return NO;
175     if (!data)
176         data = [NSData data];
177     [dataByType setObject:data forKey:dataType];
178     ++changeCount;
179     return YES;
180 }
181
182 - (NSData *)dataForType:(NSString *)dataType
183 {
184     return [dataByType objectForKey:dataType];
185 }
186
187 - (BOOL)setPropertyList:(id)propertyList forType:(NSString *)dataType
188 {
189     NSData *data = nil;
190     if (propertyList)
191         data = [NSPropertyListSerialization dataWithPropertyList:propertyList format:NSPropertyListXMLFormat_v1_0 options:0 error:nullptr];
192     return [self setData:data forType:dataType];
193 }
194
195 - (BOOL)setString:(NSString *)string forType:(NSString *)dataType
196 {
197     return [self setData:[string dataUsingEncoding:NSUTF8StringEncoding] forType:dataType];
198 }
199
200 @end