2 * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #import "WebNSPasteboardExtras.h"
31 #import "DOMElementInternal.h"
32 #import "WebArchive.h"
33 #import "WebFrameInternal.h"
34 #import "WebHTMLViewInternal.h"
35 #import "WebNSURLExtras.h"
36 #import "WebResourcePrivate.h"
37 #import "WebURLsWithTitles.h"
38 #import "WebViewPrivate.h"
39 #import <WebCore/Element.h>
40 #import <WebCore/Image.h>
41 #import <WebCore/MIMETypeRegistry.h>
42 #import <WebCore/RenderImage.h>
43 #import <WebKit/DOMExtensions.h>
44 #import <WebKit/DOMPrivate.h>
45 #import <WebKitSystemInterface.h>
46 #import <wtf/Assertions.h>
47 #import <wtf/RetainPtr.h>
48 #import <wtf/StdLibExtras.h>
50 using namespace WebCore;
52 NSString *WebURLPboardType = @"public.url";
53 NSString *WebURLNamePboardType = @"public.url-name";
55 @implementation NSPasteboard (WebExtras)
57 + (NSArray *)_web_writableTypesForURL
59 DEFINE_STATIC_LOCAL(RetainPtr<NSArray>, types, ([[NSArray alloc] initWithObjects:
60 WebURLsWithTitlesPboardType,
69 static inline NSArray *_createWritableTypesForImageWithoutArchive()
71 NSMutableArray *types = [[NSMutableArray alloc] initWithObjects:NSTIFFPboardType, nil];
72 [types addObjectsFromArray:[NSPasteboard _web_writableTypesForURL]];
76 static NSArray *_writableTypesForImageWithoutArchive (void)
78 DEFINE_STATIC_LOCAL(RetainPtr<NSArray>, types, (_createWritableTypesForImageWithoutArchive()));
82 static inline NSArray *_createWritableTypesForImageWithArchive()
84 NSMutableArray *types = [_writableTypesForImageWithoutArchive() mutableCopy];
85 [types addObject:NSRTFDPboardType];
86 [types addObject:WebArchivePboardType];
90 static NSArray *_writableTypesForImageWithArchive (void)
92 DEFINE_STATIC_LOCAL(RetainPtr<NSArray>, types, (_createWritableTypesForImageWithArchive()));
96 + (NSArray *)_web_writableTypesForImageIncludingArchive:(BOOL)hasArchive
99 ? _writableTypesForImageWithArchive()
100 : _writableTypesForImageWithoutArchive();
103 + (NSArray *)_web_dragTypesForURL
105 return [NSArray arrayWithObjects:
106 WebURLsWithTitlesPboardType,
109 WebURLNamePboardType,
111 NSFilenamesPboardType,
115 - (NSURL *)_web_bestURL
117 NSArray *types = [self types];
119 if ([types containsObject:NSURLPboardType]) {
120 NSURL *URLFromPasteboard = [NSURL URLFromPasteboard:self];
121 NSString *scheme = [URLFromPasteboard scheme];
122 if ([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"]) {
123 return [URLFromPasteboard _webkit_canonicalize];
127 if ([types containsObject:NSStringPboardType]) {
128 NSString *URLString = [self stringForType:NSStringPboardType];
129 if ([URLString _webkit_looksLikeAbsoluteURL]) {
130 NSURL *URL = [[NSURL _web_URLWithUserTypedString:URLString] _webkit_canonicalize];
137 if ([types containsObject:NSFilenamesPboardType]) {
138 NSArray *files = [self propertyListForType:NSFilenamesPboardType];
139 // FIXME: Maybe it makes more sense to allow multiple files and only use the first one?
140 if ([files count] == 1) {
141 NSString *file = [files objectAtIndex:0];
142 // FIXME: We are filtering out directories because that's what the original code used to
143 // do. Without this check, if the URL points to a local directory, Safari will open the
144 // parent directory of the directory in Finder. This check should go away as soon as
147 if ([[NSFileManager defaultManager] fileExistsAtPath:file isDirectory:&isDirectory] && isDirectory)
149 return [[NSURL fileURLWithPath:file] _webkit_canonicalize];
156 - (void)_web_writeURL:(NSURL *)URL andTitle:(NSString *)title types:(NSArray *)types
160 if ([title length] == 0) {
161 title = [[URL path] lastPathComponent];
162 if ([title length] == 0)
163 title = [URL _web_userVisibleString];
166 if ([types containsObject:NSURLPboardType])
167 [URL writeToPasteboard:self];
168 if ([types containsObject:WebURLPboardType])
169 [self setString:[URL _web_originalDataAsString] forType:WebURLPboardType];
170 if ([types containsObject:WebURLNamePboardType])
171 [self setString:title forType:WebURLNamePboardType];
172 if ([types containsObject:NSStringPboardType])
173 [self setString:[URL _web_userVisibleString] forType:NSStringPboardType];
174 if ([types containsObject:WebURLsWithTitlesPboardType])
175 [WebURLsWithTitles writeURLs:[NSArray arrayWithObject:URL] andTitles:[NSArray arrayWithObject:title] toPasteboard:self];
178 + (int)_web_setFindPasteboardString:(NSString *)string withOwner:(id)owner
180 NSPasteboard *findPasteboard = [NSPasteboard pasteboardWithName:NSFindPboard];
181 [findPasteboard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:owner];
182 [findPasteboard setString:string forType:NSStringPboardType];
183 return [findPasteboard changeCount];
186 - (void)_web_writeFileWrapperAsRTFDAttachment:(NSFileWrapper *)wrapper
188 NSTextAttachment *attachment = [[NSTextAttachment alloc] initWithFileWrapper:wrapper];
190 NSAttributedString *string = [NSAttributedString attributedStringWithAttachment:attachment];
191 [attachment release];
193 NSData *RTFDData = [string RTFDFromRange:NSMakeRange(0, [string length]) documentAttributes:nil];
194 [self setData:RTFDData forType:NSRTFDPboardType];
198 - (void)_web_writePromisedRTFDFromArchive:(WebArchive*)archive containsImage:(BOOL)containsImage
201 // This image data is either the only subresource of an archive (HTML image case)
202 // or the main resource (standalone image case).
203 NSArray *subresources = [archive subresources];
204 WebResource *resource = [archive mainResource];
205 if (containsImage && [subresources count] > 0
206 && MIMETypeRegistry::isSupportedImageResourceMIMEType([[subresources objectAtIndex:0] MIMEType]))
207 resource = (WebResource *)[subresources objectAtIndex:0];
208 ASSERT(resource != nil);
210 ASSERT(!containsImage || MIMETypeRegistry::isSupportedImageResourceMIMEType([resource MIMEType]));
211 if (!containsImage || MIMETypeRegistry::isSupportedImageResourceMIMEType([resource MIMEType]))
212 [self _web_writeFileWrapperAsRTFDAttachment:[resource _fileWrapperRepresentation]];
216 static CachedImage* imageFromElement(DOMElement *domElement)
218 Element* element = core(domElement);
222 RenderObject* renderer = element->renderer();
223 RenderImage* imageRenderer = toRenderImage(renderer);
224 if (!imageRenderer->cachedImage() || imageRenderer->cachedImage()->errorOccurred())
226 return imageRenderer->cachedImage();
229 - (void)_web_writeImage:(NSImage *)image
230 element:(DOMElement *)element
232 title:(NSString *)title
233 archive:(WebArchive *)archive
234 types:(NSArray *)types
235 source:(WebHTMLView *)source
237 ASSERT(image || element);
240 [self _web_writeURL:URL andTitle:title types:types];
242 if ([types containsObject:NSTIFFPboardType]) {
244 [self setData:[image TIFFRepresentation] forType:NSTIFFPboardType];
245 else if (source && element)
246 [source setPromisedDragTIFFDataSource:imageFromElement(element)];
248 [self setData:[element _imageTIFFRepresentation] forType:NSTIFFPboardType];
252 if ([types containsObject:WebArchivePboardType])
253 [self setData:[archive data] forType:WebArchivePboardType];
255 // We should not have declared types that we aren't going to write (4031826).
256 ASSERT(![types containsObject:NSRTFDPboardType]);
257 ASSERT(![types containsObject:WebArchivePboardType]);
261 - (id)_web_declareAndWriteDragImageForElement:(DOMElement *)element
263 title:(NSString *)title
264 archive:(WebArchive *)archive
265 source:(WebHTMLView *)source
267 ASSERT(self == [NSPasteboard pasteboardWithName:NSDragPboard]);
269 NSString *extension = @"";
270 if (RenderObject* renderer = core(element)->renderer()) {
271 if (renderer->isImage()) {
272 if (CachedImage* image = toRenderImage(renderer)->cachedImage()) {
273 extension = image->image()->filenameExtension();
274 if (![extension length])
280 NSMutableArray *types = [[NSMutableArray alloc] initWithObjects:NSFilesPromisePboardType, nil];
281 [types addObjectsFromArray:[NSPasteboard _web_writableTypesForImageIncludingArchive:(archive != nil)]];
282 [self declareTypes:types owner:source];
283 [self _web_writeImage:nil element:element URL:URL title:title archive:archive types:types source:source];
286 NSArray *extensions = [[NSArray alloc] initWithObjects:extension, nil];
287 [self setPropertyList:extensions forType:NSFilesPromisePboardType];
288 [extensions release];